feat(v2-inventory): мигрировать систему расходников на V2 архитектуру
Переход от старой таблицы Supply к новой FulfillmentConsumableInventory: - Обновлен mySupplies resolver для чтения из V2 таблицы с корректными остатками - Добавлена V2 мутация updateFulfillmentInventoryPrice для обновления цен - Исправлен counterpartySupplies для показа актуальных V2 цен в рецептурах - Frontend использует новую мутацию UPDATE_FULFILLMENT_INVENTORY_PRICE - Цены расходников корректно сохраняются и отображаются после перезагрузки - Селлеры видят правильные цены при создании поставок товаров 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -11,16 +11,14 @@ import { SmsService } from '@/services/sms-service'
|
||||
import { WildberriesService } from '@/services/wildberries-service'
|
||||
|
||||
import '@/lib/seed-init' // Автоматическая инициализация БД
|
||||
|
||||
// Импорт новых resolvers для системы поставок v2
|
||||
import { fulfillmentConsumableV2Queries, fulfillmentConsumableV2Mutations } from './resolvers/fulfillment-consumables-v2'
|
||||
|
||||
// 🔒 СИСТЕМА БЕЗОПАСНОСТИ - импорты
|
||||
import { fulfillmentInventoryV2Queries } from './resolvers/fulfillment-inventory-v2'
|
||||
import { CommercialDataAudit } from './security/commercial-data-audit'
|
||||
import { createSecurityContext } from './security/index'
|
||||
|
||||
// 🔒 HELPER: Создание безопасного контекста с организационными данными
|
||||
function createSecureContextWithOrgData(context: Context, currentUser: any) {
|
||||
function createSecureContextWithOrgData(context: Context, currentUser: { organization: { id: string; type: string } }) {
|
||||
return {
|
||||
...context,
|
||||
user: {
|
||||
@ -793,27 +791,30 @@ export const resolvers = {
|
||||
return [] // Только фулфилменты имеют расходники
|
||||
}
|
||||
|
||||
// Получаем ВСЕ расходники из таблицы supply для фулфилмента
|
||||
const allSupplies = await prisma.supply.findMany({
|
||||
where: { organizationId: currentUser.organization.id },
|
||||
include: { organization: true },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
// Получаем расходники из V2 инвентаря фулфилмента
|
||||
const inventoryItems = await prisma.fulfillmentConsumableInventory.findMany({
|
||||
where: { fulfillmentCenterId: currentUser.organization.id },
|
||||
include: {
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
orderBy: { lastSupplyDate: 'desc' },
|
||||
})
|
||||
|
||||
// Преобразуем старую структуру в новую согласно GraphQL схеме
|
||||
const transformedSupplies = allSupplies.map((supply) => ({
|
||||
id: supply.id,
|
||||
name: supply.name,
|
||||
description: supply.description,
|
||||
pricePerUnit: supply.price ? parseFloat(supply.price.toString()) : null, // Конвертируем Decimal в Number
|
||||
unit: supply.unit || 'шт', // Единица измерения
|
||||
imageUrl: supply.imageUrl,
|
||||
warehouseStock: supply.currentStock || 0, // Остаток на складе
|
||||
isAvailable: (supply.currentStock || 0) > 0, // Есть ли в наличии
|
||||
warehouseConsumableId: supply.id, // Связь со складом (пока используем тот же ID)
|
||||
createdAt: supply.createdAt,
|
||||
updatedAt: supply.updatedAt,
|
||||
organization: supply.organization,
|
||||
// Преобразуем V2 структуру в формат для services/supplies
|
||||
const transformedSupplies = inventoryItems.map((item) => ({
|
||||
id: item.id,
|
||||
name: item.product.name,
|
||||
description: item.product.description || '',
|
||||
pricePerUnit: item.resalePrice ? parseFloat(item.resalePrice.toString()) : null, // Цена перепродажи
|
||||
unit: 'шт', // TODO: добавить unit в Product модель
|
||||
imageUrl: item.product.mainImage,
|
||||
warehouseStock: item.currentStock, // Текущий остаток V2
|
||||
isAvailable: item.currentStock > 0, // Есть ли в наличии
|
||||
warehouseConsumableId: item.id, // ID из V2 инвентаря
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
organization: item.fulfillmentCenter,
|
||||
}))
|
||||
|
||||
console.warn('🔥 SUPPLIES RESOLVER - NEW FORMAT:', {
|
||||
@ -898,39 +899,68 @@ export const resolvers = {
|
||||
throw new GraphQLError('Доступ только для фулфилмент центров')
|
||||
}
|
||||
|
||||
// Получаем расходники фулфилмента из таблицы Supply
|
||||
const supplies = await prisma.supply.findMany({
|
||||
// Получаем расходники фулфилмента из V2 таблицы FulfillmentConsumableInventory
|
||||
const inventoryItems = await prisma.fulfillmentConsumableInventory.findMany({
|
||||
where: {
|
||||
organizationId: currentUser.organization.id,
|
||||
type: 'FULFILLMENT_CONSUMABLES', // Только расходники фулфилмента
|
||||
fulfillmentCenterId: currentUser.organization.id,
|
||||
},
|
||||
include: {
|
||||
organization: true,
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
orderBy: { createdAt: 'desc' },
|
||||
orderBy: { lastSupplyDate: 'desc' },
|
||||
})
|
||||
|
||||
// Логирование для отладки
|
||||
console.warn('🔥🔥🔥 FULFILLMENT SUPPLIES RESOLVER CALLED (NEW ARCHITECTURE) 🔥🔥🔥')
|
||||
console.warn('📊 Расходники фулфилмента из склада:', {
|
||||
console.warn('🔥🔥🔥 FULFILLMENT SUPPLIES RESOLVER CALLED (V2 ARCHITECTURE) 🔥🔥🔥')
|
||||
console.warn('📊 Расходники фулфилмента из V2 инвентаря:', {
|
||||
organizationId: currentUser.organization.id,
|
||||
organizationType: currentUser.organization.type,
|
||||
suppliesCount: supplies.length,
|
||||
supplies: supplies.map((s) => ({
|
||||
id: s.id,
|
||||
name: s.name,
|
||||
type: s.type,
|
||||
status: s.status,
|
||||
currentStock: s.currentStock,
|
||||
quantity: s.quantity,
|
||||
inventoryItemsCount: inventoryItems.length,
|
||||
inventoryItems: inventoryItems.map((item) => ({
|
||||
id: item.id,
|
||||
productName: item.product.name,
|
||||
currentStock: item.currentStock,
|
||||
totalReceived: item.totalReceived,
|
||||
totalShipped: item.totalShipped,
|
||||
})),
|
||||
})
|
||||
|
||||
// Преобразуем в формат для фронтенда
|
||||
return supplies.map((supply) => ({
|
||||
...supply,
|
||||
price: supply.price ? parseFloat(supply.price.toString()) : 0,
|
||||
shippedQuantity: 0, // Добавляем для совместимости
|
||||
// Преобразуем V2 инвентарь в V1 формат для совместимости с фронтом
|
||||
return inventoryItems.map((item) => ({
|
||||
// === ОСНОВНЫЕ ПОЛЯ ===
|
||||
id: item.id,
|
||||
name: item.product.name,
|
||||
article: item.product.article,
|
||||
description: item.product.description || '',
|
||||
category: item.product.category?.name || 'Расходники',
|
||||
unit: 'шт', // TODO: добавить в Product модель
|
||||
|
||||
// === СКЛАДСКИЕ ДАННЫЕ ===
|
||||
currentStock: item.currentStock,
|
||||
minStock: item.minStock,
|
||||
usedStock: item.totalShipped, // V2: всего отгружено = использовано
|
||||
quantity: item.totalReceived, // V2: всего получено = количество
|
||||
shippedQuantity: item.totalShipped, // Для совместимости
|
||||
|
||||
// === ЦЕНЫ ===
|
||||
price: parseFloat(item.averageCost.toString()),
|
||||
|
||||
// === СТАТУС ===
|
||||
status: item.currentStock > 0 ? 'in-stock' : 'out-of-stock',
|
||||
|
||||
// === ДАТЫ ===
|
||||
date: item.lastSupplyDate?.toISOString() || item.createdAt.toISOString(),
|
||||
createdAt: item.createdAt.toISOString(),
|
||||
updatedAt: item.updatedAt.toISOString(),
|
||||
|
||||
// === ПОСТАВЩИК ===
|
||||
supplier: 'Различные поставщики', // V2 инвентарь агрегирует данные от разных поставщиков
|
||||
|
||||
// === ДОПОЛНИТЕЛЬНО ===
|
||||
imageUrl: item.product.mainImage,
|
||||
type: 'FULFILLMENT_CONSUMABLES', // Для совместимости
|
||||
organizationId: item.fulfillmentCenterId,
|
||||
}))
|
||||
},
|
||||
|
||||
@ -970,28 +1000,15 @@ export const resolvers = {
|
||||
],
|
||||
},
|
||||
include: {
|
||||
partner: {
|
||||
include: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
include: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
fulfillmentCenter: {
|
||||
include: {
|
||||
users: true,
|
||||
},
|
||||
},
|
||||
partner: true,
|
||||
organization: true,
|
||||
fulfillmentCenter: true,
|
||||
logisticsPartner: true,
|
||||
items: {
|
||||
include: {
|
||||
product: {
|
||||
include: {
|
||||
category: true,
|
||||
organization: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -2093,11 +2110,41 @@ export const resolvers = {
|
||||
throw new GraphQLError('Расходники доступны только у фулфилмент центров')
|
||||
}
|
||||
|
||||
return await prisma.supply.findMany({
|
||||
where: { organizationId: args.organizationId },
|
||||
include: { organization: true },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
// Получаем расходники из V2 инвентаря фулфилмента с правильными ценами
|
||||
const inventoryItems = await prisma.fulfillmentConsumableInventory.findMany({
|
||||
where: {
|
||||
fulfillmentCenterId: args.organizationId,
|
||||
currentStock: { gt: 0 }, // Только те, что есть в наличии
|
||||
resalePrice: { not: null }, // Только те, у которых установлена цена
|
||||
},
|
||||
include: {
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
orderBy: { lastSupplyDate: 'desc' },
|
||||
})
|
||||
|
||||
console.warn('🔥 COUNTERPARTY SUPPLIES - V2 FORMAT:', {
|
||||
organizationId: args.organizationId,
|
||||
itemsCount: inventoryItems.length,
|
||||
itemsWithPrices: inventoryItems.filter(item => item.resalePrice).length,
|
||||
})
|
||||
|
||||
// Преобразуем V2 формат в формат старого Supply для обратной совместимости
|
||||
return inventoryItems.map((item) => ({
|
||||
id: item.id,
|
||||
name: item.product.name,
|
||||
description: item.product.description || '',
|
||||
price: item.resalePrice ? parseFloat(item.resalePrice.toString()) : 0, // Цена перепродажи из V2
|
||||
quantity: item.currentStock, // Текущий остаток
|
||||
unit: 'шт', // TODO: добавить unit в Product модель
|
||||
category: 'CONSUMABLE',
|
||||
status: 'AVAILABLE',
|
||||
imageUrl: item.product.mainImage,
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
organization: item.fulfillmentCenter,
|
||||
}))
|
||||
},
|
||||
|
||||
// Корзина пользователя
|
||||
@ -2799,6 +2846,9 @@ export const resolvers = {
|
||||
|
||||
// Новая система поставок v2
|
||||
...fulfillmentConsumableV2Queries,
|
||||
|
||||
// Новая система складских остатков V2 (заменяет старый myFulfillmentSupplies)
|
||||
...fulfillmentInventoryV2Queries,
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
@ -4760,47 +4810,54 @@ export const resolvers = {
|
||||
}
|
||||
|
||||
try {
|
||||
// Находим и обновляем расходник
|
||||
const existingSupply = await prisma.supply.findFirst({
|
||||
// Находим и обновляем расходник в V2 таблице FulfillmentConsumableInventory
|
||||
const existingInventoryItem = await prisma.fulfillmentConsumableInventory.findFirst({
|
||||
where: {
|
||||
id: args.id,
|
||||
organizationId: currentUser.organization.id,
|
||||
fulfillmentCenterId: currentUser.organization.id,
|
||||
},
|
||||
include: {
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (!existingSupply) {
|
||||
throw new GraphQLError('Расходник не найден')
|
||||
if (!existingInventoryItem) {
|
||||
throw new GraphQLError('Расходник не найден в инвентаре')
|
||||
}
|
||||
|
||||
const updatedSupply = await prisma.supply.update({
|
||||
const updatedInventoryItem = await prisma.fulfillmentConsumableInventory.update({
|
||||
where: { id: args.id },
|
||||
data: {
|
||||
pricePerUnit: args.input.pricePerUnit, // Обновляем цену продажи, НЕ цену закупки
|
||||
resalePrice: args.input.pricePerUnit, // Обновляем цену перепродажи в V2
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
include: { organization: true },
|
||||
include: {
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Преобразуем в новый формат для GraphQL
|
||||
// Преобразуем V2 данные в формат для GraphQL (аналогично mySupplies resolver)
|
||||
const transformedSupply = {
|
||||
id: updatedSupply.id,
|
||||
name: updatedSupply.name,
|
||||
description: updatedSupply.description,
|
||||
pricePerUnit: updatedSupply.price ? parseFloat(updatedSupply.price.toString()) : null, // Конвертируем Decimal в Number
|
||||
unit: updatedSupply.unit || 'шт',
|
||||
imageUrl: updatedSupply.imageUrl,
|
||||
warehouseStock: updatedSupply.currentStock || 0,
|
||||
isAvailable: (updatedSupply.currentStock || 0) > 0,
|
||||
warehouseConsumableId: updatedSupply.id,
|
||||
createdAt: updatedSupply.createdAt,
|
||||
updatedAt: updatedSupply.updatedAt,
|
||||
organization: updatedSupply.organization,
|
||||
id: updatedInventoryItem.id,
|
||||
name: updatedInventoryItem.product.name,
|
||||
description: updatedInventoryItem.product.description || '',
|
||||
pricePerUnit: updatedInventoryItem.resalePrice ? parseFloat(updatedInventoryItem.resalePrice.toString()) : null,
|
||||
unit: 'шт', // TODO: добавить unit в Product модель
|
||||
imageUrl: updatedInventoryItem.product.mainImage,
|
||||
warehouseStock: updatedInventoryItem.currentStock,
|
||||
isAvailable: updatedInventoryItem.currentStock > 0,
|
||||
warehouseConsumableId: updatedInventoryItem.id,
|
||||
createdAt: updatedInventoryItem.createdAt,
|
||||
updatedAt: updatedInventoryItem.updatedAt,
|
||||
organization: updatedInventoryItem.fulfillmentCenter,
|
||||
}
|
||||
|
||||
console.warn('🔥 SUPPLY PRICE UPDATED:', {
|
||||
console.warn('🔥 V2 SUPPLY PRICE UPDATED:', {
|
||||
id: transformedSupply.id,
|
||||
name: transformedSupply.name,
|
||||
oldPrice: existingSupply.price,
|
||||
oldPrice: existingInventoryItem.resalePrice,
|
||||
newPrice: transformedSupply.pricePerUnit,
|
||||
})
|
||||
|
||||
@ -4818,6 +4875,88 @@ export const resolvers = {
|
||||
}
|
||||
},
|
||||
|
||||
// V2 мутация для обновления цены в инвентаре фулфилмента
|
||||
updateFulfillmentInventoryPrice: async (
|
||||
_: unknown,
|
||||
args: {
|
||||
id: string
|
||||
input: {
|
||||
pricePerUnit?: number | null
|
||||
}
|
||||
},
|
||||
context: Context,
|
||||
) => {
|
||||
if (!context.user) {
|
||||
throw new GraphQLError('Требуется авторизация', {
|
||||
extensions: { code: 'UNAUTHENTICATED' },
|
||||
})
|
||||
}
|
||||
|
||||
const currentUser = await prisma.user.findUnique({
|
||||
where: { id: context.user.id },
|
||||
include: { organization: true },
|
||||
})
|
||||
|
||||
if (!currentUser?.organization) {
|
||||
throw new GraphQLError('У пользователя нет организации')
|
||||
}
|
||||
|
||||
if (currentUser.organization.type !== 'FULFILLMENT') {
|
||||
throw new GraphQLError('Обновление цен расходников доступно только для фулфилмент центров')
|
||||
}
|
||||
|
||||
try {
|
||||
const updatedInventoryItem = await prisma.fulfillmentConsumableInventory.update({
|
||||
where: {
|
||||
id: args.id,
|
||||
fulfillmentCenterId: currentUser.organization.id,
|
||||
},
|
||||
data: {
|
||||
resalePrice: args.input.pricePerUnit,
|
||||
updatedAt: new Date(),
|
||||
},
|
||||
include: {
|
||||
product: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
})
|
||||
|
||||
const transformedItem = {
|
||||
id: updatedInventoryItem.id,
|
||||
name: updatedInventoryItem.product.name,
|
||||
description: updatedInventoryItem.product.description || '',
|
||||
pricePerUnit: updatedInventoryItem.resalePrice ? parseFloat(updatedInventoryItem.resalePrice.toString()) : null,
|
||||
unit: 'шт',
|
||||
imageUrl: updatedInventoryItem.product.mainImage,
|
||||
warehouseStock: updatedInventoryItem.currentStock,
|
||||
isAvailable: updatedInventoryItem.currentStock > 0,
|
||||
warehouseConsumableId: updatedInventoryItem.id,
|
||||
createdAt: updatedInventoryItem.createdAt,
|
||||
updatedAt: updatedInventoryItem.updatedAt,
|
||||
organization: updatedInventoryItem.fulfillmentCenter,
|
||||
}
|
||||
|
||||
console.warn('🔥 V2 FULFILLMENT INVENTORY PRICE UPDATED:', {
|
||||
id: transformedItem.id,
|
||||
name: transformedItem.name,
|
||||
newPrice: transformedItem.pricePerUnit,
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Цена расходника успешно обновлена',
|
||||
item: transformedItem,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating fulfillment inventory price:', error)
|
||||
return {
|
||||
success: false,
|
||||
message: 'Ошибка при обновлении цены расходника',
|
||||
item: null,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Использовать расходники фулфилмента
|
||||
useFulfillmentSupplies: async (
|
||||
_: unknown,
|
||||
@ -8217,6 +8356,120 @@ export const resolvers = {
|
||||
}
|
||||
|
||||
try {
|
||||
// Сначала пытаемся найти селлерскую поставку
|
||||
const sellerSupply = await prisma.sellerConsumableSupplyOrder.findFirst({
|
||||
where: {
|
||||
id: args.id,
|
||||
fulfillmentCenterId: currentUser.organization.id,
|
||||
status: 'SHIPPED',
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
include: {
|
||||
product: {
|
||||
include: {
|
||||
category: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
seller: true, // Селлер-создатель заказа
|
||||
supplier: true, // Поставщик
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Если нашли селлерскую поставку, обрабатываем её
|
||||
if (sellerSupply) {
|
||||
// Обновляем статус селлерской поставки
|
||||
const updatedSellerOrder = await prisma.sellerConsumableSupplyOrder.update({
|
||||
where: { id: args.id },
|
||||
data: {
|
||||
status: 'DELIVERED',
|
||||
deliveredAt: new Date(),
|
||||
},
|
||||
include: {
|
||||
items: {
|
||||
include: {
|
||||
product: {
|
||||
include: {
|
||||
category: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
seller: true,
|
||||
supplier: true,
|
||||
fulfillmentCenter: true,
|
||||
},
|
||||
})
|
||||
|
||||
// Добавляем расходники в склад фулфилмента как SELLER_CONSUMABLES
|
||||
console.warn('📦 Обновляем склад фулфилмента для селлерской поставки...')
|
||||
for (const item of sellerSupply.items) {
|
||||
const existingSupply = await prisma.supply.findFirst({
|
||||
where: {
|
||||
organizationId: currentUser.organization.id,
|
||||
article: item.product.article,
|
||||
type: 'SELLER_CONSUMABLES',
|
||||
sellerOwnerId: sellerSupply.sellerId,
|
||||
},
|
||||
})
|
||||
|
||||
if (existingSupply) {
|
||||
await prisma.supply.update({
|
||||
where: { id: existingSupply.id },
|
||||
data: {
|
||||
currentStock: existingSupply.currentStock + item.requestedQuantity,
|
||||
status: 'in-stock',
|
||||
},
|
||||
})
|
||||
console.warn(
|
||||
`📈 Обновлен расходник селлера "${item.product.name}" (владелец: ${sellerSupply.seller.name}): ${existingSupply.currentStock} -> ${existingSupply.currentStock + item.requestedQuantity}`,
|
||||
)
|
||||
} else {
|
||||
await prisma.supply.create({
|
||||
data: {
|
||||
name: item.product.name,
|
||||
article: item.product.article,
|
||||
description: `Расходники селлера ${sellerSupply.seller.name || sellerSupply.seller.fullName}`,
|
||||
price: item.unitPrice,
|
||||
quantity: item.requestedQuantity,
|
||||
actualQuantity: item.requestedQuantity,
|
||||
currentStock: item.requestedQuantity,
|
||||
usedStock: 0,
|
||||
unit: 'шт',
|
||||
category: item.product.category?.name || 'Расходники',
|
||||
status: 'in-stock',
|
||||
supplier: sellerSupply.supplier?.name || sellerSupply.supplier?.fullName || 'Поставщик',
|
||||
type: 'SELLER_CONSUMABLES',
|
||||
sellerOwnerId: sellerSupply.sellerId,
|
||||
organizationId: currentUser.organization.id,
|
||||
},
|
||||
})
|
||||
console.warn(
|
||||
`➕ Создан новый расходник селлера "${item.product.name}" (владелец: ${sellerSupply.seller.name}): ${item.requestedQuantity} единиц`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Селлерская поставка принята фулфилментом. Расходники добавлены на склад.',
|
||||
order: {
|
||||
id: updatedSellerOrder.id,
|
||||
status: updatedSellerOrder.status,
|
||||
deliveryDate: updatedSellerOrder.requestedDeliveryDate,
|
||||
totalAmount: updatedSellerOrder.items.reduce((sum, item) => sum + (item.unitPrice * item.requestedQuantity), 0),
|
||||
totalItems: updatedSellerOrder.items.reduce((sum, item) => sum + item.requestedQuantity, 0),
|
||||
partner: updatedSellerOrder.supplier,
|
||||
organization: updatedSellerOrder.seller,
|
||||
fulfillmentCenter: updatedSellerOrder.fulfillmentCenter,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Если селлерской поставки нет, ищем старую поставку
|
||||
const existingOrder = await prisma.supplyOrder.findFirst({
|
||||
where: {
|
||||
id: args.id,
|
||||
@ -10239,7 +10492,7 @@ resolvers.Mutation = {
|
||||
},
|
||||
|
||||
// Добавляем v2 mutations через spread
|
||||
...fulfillmentConsumableV2Mutations
|
||||
...fulfillmentConsumableV2Mutations,
|
||||
}
|
||||
|
||||
/* // Резолвер для парсинга JSON рецептуры в SupplyOrderItem
|
||||
|
Reference in New Issue
Block a user