feat: продолжение миграции V2 системы поставок товаров

- Добавлен feature flag USE_V2_GOODS_SYSTEM для переключения между V1 и V2
- Создан трансформер рецептур для конвертации V1 → V2 формата
- Интегрирована V2 мутация CREATE_SELLER_GOODS_SUPPLY в useSupplyCart
- Добавлен V2 запрос GET_MY_SELLER_GOODS_SUPPLIES в supplies-dashboard
- Исправлены связи counterpartyOf в goods-supply-v2 resolver
- Временно отключена валидация для не-MAIN_PRODUCT товаров в V2
- Создан новый компонент supplies-dashboard-v2 (в разработке)

Изменения являются частью поэтапной миграции с V1 на V2 систему поставок

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Veronika Smirnova
2025-09-01 19:21:13 +03:00
parent a5816518be
commit c344a177b5
6 changed files with 585 additions and 82 deletions

View File

@ -305,7 +305,7 @@ export const sellerGoodsMutations = {
const fulfillmentCenter = await prisma.organization.findUnique({
where: { id: fulfillmentCenterId },
include: {
counterpartiesAsCounterparty: {
counterpartyOf: {
where: { organizationId: user.organizationId! },
},
},
@ -315,7 +315,7 @@ export const sellerGoodsMutations = {
throw new GraphQLError('Фулфилмент-центр не найден или имеет неверный тип')
}
if (fulfillmentCenter.counterpartiesAsCounterparty.length === 0) {
if (fulfillmentCenter.counterpartyOf.length === 0) {
throw new GraphQLError('Нет партнерских отношений с данным фулфилмент-центром')
}
@ -323,7 +323,7 @@ export const sellerGoodsMutations = {
const supplier = await prisma.organization.findUnique({
where: { id: supplierId },
include: {
counterpartiesAsCounterparty: {
counterpartyOf: {
where: { organizationId: user.organizationId! },
},
},
@ -333,7 +333,7 @@ export const sellerGoodsMutations = {
throw new GraphQLError('Поставщик не найден или имеет неверный тип')
}
if (supplier.counterpartiesAsCounterparty.length === 0) {
if (supplier.counterpartyOf.length === 0) {
throw new GraphQLError('Нет партнерских отношений с данным поставщиком')
}
@ -345,8 +345,14 @@ export const sellerGoodsMutations = {
throw new GraphQLError('Должен быть хотя бы один основной товар')
}
// Проверяем все товары в рецептуре
// Проверяем только основные товары (MAIN_PRODUCT) в рецептуре
for (const item of recipeItems) {
// В V2 временно валидируем только основные товары
if (item.recipeType !== 'MAIN_PRODUCT') {
console.log(`⚠️ Пропускаем валидацию ${item.recipeType} товара ${item.productId} - не поддерживается в V2`)
continue
}
const product = await prisma.product.findUnique({
where: { id: item.productId },
})
@ -359,19 +365,17 @@ export const sellerGoodsMutations = {
throw new GraphQLError(`Товар ${product.name} не принадлежит выбранному поставщику`)
}
// Для основных товаров проверяем остатки
if (item.recipeType === 'MAIN_PRODUCT') {
const availableStock = (product.stock || product.quantity || 0) - (product.ordered || 0)
// Проверяем остатки основных товаров
const availableStock = (product.stock || product.quantity || 0) - (product.ordered || 0)
if (item.quantity > availableStock) {
throw new GraphQLError(
`Недостаточно остатков товара "${product.name}". ` +
`Доступно: ${availableStock} шт., запрашивается: ${item.quantity} шт.`,
)
}
totalCost += product.price.toNumber() * item.quantity
if (item.quantity > availableStock) {
throw new GraphQLError(
`Недостаточно остатков товара "${product.name}". ` +
`Доступно: ${availableStock} шт., запрашивается: ${item.quantity} шт.`,
)
}
totalCost += product.price.toNumber() * item.quantity
}
// 🚀 СОЗДАНИЕ ПОСТАВКИ В ТРАНЗАКЦИИ
@ -390,8 +394,14 @@ export const sellerGoodsMutations = {
},
})
// Создаем записи рецептуры
// Создаем записи рецептуры только для MAIN_PRODUCT
for (const item of recipeItems) {
// В V2 временно создаем только основные товары
if (item.recipeType !== 'MAIN_PRODUCT') {
console.log(`⚠️ Пропускаем создание записи для ${item.recipeType} товара ${item.productId}`)
continue
}
await tx.goodsSupplyRecipeItem.create({
data: {
supplyOrderId: newOrder.id,
@ -402,16 +412,14 @@ export const sellerGoodsMutations = {
})
// Резервируем основные товары у поставщика
if (item.recipeType === 'MAIN_PRODUCT') {
await tx.product.update({
where: { id: item.productId },
data: {
ordered: {
increment: item.quantity,
},
await tx.product.update({
where: { id: item.productId },
data: {
ordered: {
increment: item.quantity,
},
})
}
},
})
}
return newOrder