Оптимизирован резолвер статистики склада фулфилмента: улучшено форматирование кода, добавлены дополнительные логи для отслеживания изменений остатков и заказов. Исправлены условия выборки заказов, исключая заказы самого фулфилмента. Обновлены комментарии для лучшего понимания логики работы. Синхронизация остатков поставщика теперь включает обновление основных значений и логирование изменений.

This commit is contained in:
Veronika Smirnova
2025-08-01 14:08:40 +03:00
parent 80d33b46b8
commit 3f759e7454

View File

@ -1009,7 +1009,11 @@ export const resolvers = {
}, },
// Статистика склада фулфилмента с изменениями за сутки // Статистика склада фулфилмента с изменениями за сутки
fulfillmentWarehouseStats: async (_: unknown, __: unknown, context: Context) => { fulfillmentWarehouseStats: async (
_: unknown,
__: unknown,
context: Context
) => {
console.log("🔥 FULFILLMENT WAREHOUSE STATS RESOLVER CALLED"); console.log("🔥 FULFILLMENT WAREHOUSE STATS RESOLVER CALLED");
if (!context.user) { if (!context.user) {
throw new GraphQLError("Требуется авторизация", { throw new GraphQLError("Требуется авторизация", {
@ -1036,41 +1040,53 @@ export const resolvers = {
const oneDayAgo = new Date(); const oneDayAgo = new Date();
oneDayAgo.setDate(oneDayAgo.getDate() - 1); oneDayAgo.setDate(oneDayAgo.getDate() - 1);
console.log(`🏢 Organization ID: ${organizationId}, Date 24h ago: ${oneDayAgo.toISOString()}`); console.log(
`🏢 Organization ID: ${organizationId}, Date 24h ago: ${oneDayAgo.toISOString()}`
);
// Сначала проверим ВСЕ заказы поставок // Сначала проверим ВСЕ заказы поставок
const allSupplyOrders = await prisma.supplyOrder.findMany({ const allSupplyOrders = await prisma.supplyOrder.findMany({
where: { status: "DELIVERED" }, where: { status: "DELIVERED" },
include: { include: {
items: { items: {
include: { product: true } include: { product: true },
}, },
organization: { select: { id: true, name: true, type: true } } organization: { select: { id: true, name: true, type: true } },
} },
}); });
console.log(`📦 ALL DELIVERED ORDERS: ${allSupplyOrders.length}`); console.log(`📦 ALL DELIVERED ORDERS: ${allSupplyOrders.length}`);
allSupplyOrders.forEach(order => { allSupplyOrders.forEach((order) => {
console.log(` Order ${order.id}: org=${order.organizationId} (${order.organization?.name}), fulfillment=${order.fulfillmentCenterId}, items=${order.items.length}`); console.log(
` Order ${order.id}: org=${order.organizationId} (${order.organization?.name}), fulfillment=${order.fulfillmentCenterId}, items=${order.items.length}`
);
}); });
// Продукты (товары от селлеров) - заказы К нам, но исключаем расходники фулфилмента // Продукты (товары от селлеров) - заказы К нам, но исключаем расходники фулфилмента
const allDeliveredOrders = await prisma.supplyOrder.findMany({ const sellerDeliveredOrders = await prisma.supplyOrder.findMany({
where: { where: {
fulfillmentCenterId: organizationId, // Доставлено к нам (фулфилменту) fulfillmentCenterId: organizationId, // Доставлено к нам (фулфилменту)
status: "DELIVERED" organizationId: { not: organizationId }, // ИСПРАВЛЕНО: исключаем заказы самого фулфилмента
status: "DELIVERED",
}, },
include: { include: {
items: { items: {
include: { product: true } include: { product: true },
} },
} },
}); });
console.log(`🛒 ALL ORDERS TO FULFILLMENT: ${allDeliveredOrders.length}`); console.log(
`🛒 SELLER ORDERS TO FULFILLMENT: ${sellerDeliveredOrders.length}`
);
const productsCount = sellerDeliveredOrders.reduce((sum, order) => const productsCount = sellerDeliveredOrders.reduce(
sum + order.items.reduce((itemSum, item) => (sum, order) =>
itemSum + (item.product.type === "PRODUCT" ? item.quantity : 0), 0 sum +
), 0 order.items.reduce(
(itemSum, item) =>
itemSum + (item.product.type === "PRODUCT" ? item.quantity : 0),
0
),
0
); );
// Изменения товаров за сутки (от селлеров) // Изменения товаров за сутки (от селлеров)
const recentSellerDeliveredOrders = await prisma.supplyOrder.findMany({ const recentSellerDeliveredOrders = await prisma.supplyOrder.findMany({
@ -1078,19 +1094,24 @@ export const resolvers = {
fulfillmentCenterId: organizationId, // К нам fulfillmentCenterId: organizationId, // К нам
organizationId: { not: organizationId }, // От селлеров organizationId: { not: organizationId }, // От селлеров
status: "DELIVERED", status: "DELIVERED",
updatedAt: { gte: oneDayAgo } updatedAt: { gte: oneDayAgo },
}, },
include: { include: {
items: { items: {
include: { product: true } include: { product: true },
} },
} },
}); });
const productsChangeToday = recentSellerDeliveredOrders.reduce((sum, order) => const productsChangeToday = recentSellerDeliveredOrders.reduce(
sum + order.items.reduce((itemSum, item) => (sum, order) =>
itemSum + (item.product.type === "PRODUCT" ? item.quantity : 0), 0 sum +
), 0 order.items.reduce(
(itemSum, item) =>
itemSum + (item.product.type === "PRODUCT" ? item.quantity : 0),
0
),
0
); );
// Товары (готовые товары = все продукты, не расходники) // Товары (готовые товары = все продукты, не расходники)
@ -1105,70 +1126,123 @@ export const resolvers = {
const pvzReturnsCount = 0; // TODO: реальные данные о возвратах const pvzReturnsCount = 0; // TODO: реальные данные о возвратах
const pvzReturnsChangeToday = 0; const pvzReturnsChangeToday = 0;
// Расходники фулфилмента - заказы ОТ фулфилмента К поставщикам // Расходники фулфилмента - заказы ОТ фулфилмента К поставщикам, НО доставленные на склад фулфилмента
// Согласно правилам: фулфилмент заказывает расходники у поставщиков для своих операционных нужд
const fulfillmentSupplyOrders = await prisma.supplyOrder.findMany({ const fulfillmentSupplyOrders = await prisma.supplyOrder.findMany({
where: { where: {
organizationId: organizationId, // Заказчик = фулфилмент organizationId: organizationId, // Заказчик = фулфилмент
fulfillmentCenterId: null, // Не является доставкой к фулфилменту fulfillmentCenterId: organizationId, // ИСПРАВЛЕНО: доставлено НА склад фулфилмента
status: "DELIVERED"
},
include: {
items: {
include: { product: true }
}
}
});
console.log(`🏭 FULFILLMENT SUPPLY ORDERS: ${fulfillmentSupplyOrders.length}`);
const fulfillmentSuppliesCount = fulfillmentSupplyOrders.reduce(
(sum, order) => sum + order.items.reduce((itemSum, item) =>
itemSum + (item.product.type === "CONSUMABLE" ? item.quantity : 0), 0
), 0
);
console.log(`🔥 FULFILLMENT SUPPLIES DEBUG: organizationId=${organizationId}, totalOrders=${fulfillmentSupplyOrders.length}, totalCount=${fulfillmentSuppliesCount}`);
// Изменения расходников фулфилмента за сутки
const fulfillmentSuppliesReceivedToday = await prisma.supplyOrder.findMany({
where: {
organizationId: organizationId, // Заказчик = фулфилмент
fulfillmentCenterId: null, // Не доставка к фулфилменту
status: "DELIVERED", status: "DELIVERED",
updatedAt: { gte: oneDayAgo }
}, },
include: { include: {
items: { items: {
include: { product: true } include: { product: true },
} },
} },
}); });
const fulfillmentSuppliesChangeToday = fulfillmentSuppliesReceivedToday.reduce(
(sum, order) => sum + order.items.reduce((itemSum, item) => console.log(
itemSum + (item.product.type === "CONSUMABLE" ? item.quantity : 0), 0 `🏭 FULFILLMENT SUPPLY ORDERS: ${fulfillmentSupplyOrders.length}`
), 0
); );
console.log(`📊 FULFILLMENT SUPPLIES RECEIVED TODAY: ${fulfillmentSuppliesReceivedToday.length} orders, ${fulfillmentSuppliesChangeToday} items`); // Подсчитываем количество из таблицы Supply (актуальные остатки на складе фулфилмента)
const fulfillmentSuppliesFromWarehouse = await prisma.supply.findMany({
where: {
organizationId: organizationId, // Склад фулфилмента
},
});
const fulfillmentSuppliesCount = fulfillmentSuppliesFromWarehouse.reduce(
(sum, supply) => sum + (supply.currentStock || 0),
0
);
console.log(
`🔥 FULFILLMENT SUPPLIES DEBUG: organizationId=${organizationId}, ordersCount=${fulfillmentSupplyOrders.length}, warehouseCount=${fulfillmentSuppliesFromWarehouse.length}, totalStock=${fulfillmentSuppliesCount}`
);
console.log(
`📦 FULFILLMENT SUPPLIES BREAKDOWN:`,
fulfillmentSuppliesFromWarehouse.map((supply) => ({
name: supply.name,
currentStock: supply.currentStock,
supplier: supply.supplier,
}))
);
// Изменения расходников фулфилмента за сутки (ПРИБЫЛО)
// Ищем заказы фулфилмента, доставленные на его склад за последние сутки
const fulfillmentSuppliesReceivedToday =
await prisma.supplyOrder.findMany({
where: {
organizationId: organizationId, // Заказчик = фулфилмент
fulfillmentCenterId: organizationId, // ИСПРАВЛЕНО: доставлено НА склад фулфилмента
status: "DELIVERED",
updatedAt: { gte: oneDayAgo },
},
include: {
items: {
include: { product: true },
},
},
});
const fulfillmentSuppliesChangeToday =
fulfillmentSuppliesReceivedToday.reduce(
(sum, order) =>
sum +
order.items.reduce(
(itemSum, item) =>
itemSum +
(item.product.type === "CONSUMABLE" ? item.quantity : 0),
0
),
0
);
console.log(
`📊 FULFILLMENT SUPPLIES RECEIVED TODAY (ПРИБЫЛО): ${fulfillmentSuppliesReceivedToday.length} orders, ${fulfillmentSuppliesChangeToday} items`
);
// Расходники селлеров - получаем из заказов от селлеров (расходники = CONSUMABLE) // Расходники селлеров - получаем из заказов от селлеров (расходники = CONSUMABLE)
const sellerSuppliesCount = sellerDeliveredOrders.reduce((sum, order) => // Согласно правилам: селлеры заказывают расходники у поставщиков и доставляют на склад фулфилмента
sum + order.items.reduce((itemSum, item) => const sellerSuppliesCount = sellerDeliveredOrders.reduce(
itemSum + (item.product.type === "CONSUMABLE" ? item.quantity : 0), 0 (sum, order) =>
), 0 sum +
order.items.reduce(
(itemSum, item) =>
itemSum +
(item.product.type === "CONSUMABLE" ? item.quantity : 0),
0
),
0
); );
console.log(`💼 SELLER SUPPLIES DEBUG: totalCount=${sellerSuppliesCount} (from delivered orders)`); console.log(
`💼 SELLER SUPPLIES DEBUG: totalCount=${sellerSuppliesCount} (from delivered orders)`
);
// Изменения расходников селлеров за сутки - используем уже полученные данные // Изменения расходников селлеров за сутки - используем уже полученные данные
const sellerSuppliesChangeToday = recentSellerDeliveredOrders.reduce((sum, order) => const sellerSuppliesChangeToday = recentSellerDeliveredOrders.reduce(
sum + order.items.reduce((itemSum, item) => (sum, order) =>
itemSum + (item.product.type === "CONSUMABLE" ? item.quantity : 0), 0 sum +
), 0 order.items.reduce(
(itemSum, item) =>
itemSum +
(item.product.type === "CONSUMABLE" ? item.quantity : 0),
0
),
0
); );
console.log(`📊 SELLER SUPPLIES RECEIVED TODAY: ${recentSellerDeliveredOrders.length} orders, ${sellerSuppliesChangeToday} items`); console.log(
`📊 SELLER SUPPLIES RECEIVED TODAY: ${recentSellerDeliveredOrders.length} orders, ${sellerSuppliesChangeToday} items`
);
// Вычисляем процентные изменения // Вычисляем процентные изменения
const calculatePercentChange = (current: number, change: number): number => { const calculatePercentChange = (
current: number,
change: number
): number => {
if (current === 0) return change > 0 ? 100 : 0; if (current === 0) return change > 0 ? 100 : 0;
return (change / current) * 100; return (change / current) * 100;
}; };
@ -1177,36 +1251,54 @@ export const resolvers = {
products: { products: {
current: productsCount, current: productsCount,
change: productsChangeToday, change: productsChangeToday,
percentChange: calculatePercentChange(productsCount, productsChangeToday) percentChange: calculatePercentChange(
productsCount,
productsChangeToday
),
}, },
goods: { goods: {
current: goodsCount, current: goodsCount,
change: goodsChangeToday, change: goodsChangeToday,
percentChange: calculatePercentChange(goodsCount, goodsChangeToday) percentChange: calculatePercentChange(goodsCount, goodsChangeToday),
}, },
defects: { defects: {
current: defectsCount, current: defectsCount,
change: defectsChangeToday, change: defectsChangeToday,
percentChange: calculatePercentChange(defectsCount, defectsChangeToday) percentChange: calculatePercentChange(
defectsCount,
defectsChangeToday
),
}, },
pvzReturns: { pvzReturns: {
current: pvzReturnsCount, current: pvzReturnsCount,
change: pvzReturnsChangeToday, change: pvzReturnsChangeToday,
percentChange: calculatePercentChange(pvzReturnsCount, pvzReturnsChangeToday) percentChange: calculatePercentChange(
pvzReturnsCount,
pvzReturnsChangeToday
),
}, },
fulfillmentSupplies: { fulfillmentSupplies: {
current: fulfillmentSuppliesCount, current: fulfillmentSuppliesCount,
change: fulfillmentSuppliesChangeToday, change: fulfillmentSuppliesChangeToday,
percentChange: calculatePercentChange(fulfillmentSuppliesCount, fulfillmentSuppliesChangeToday) percentChange: calculatePercentChange(
fulfillmentSuppliesCount,
fulfillmentSuppliesChangeToday
),
}, },
sellerSupplies: { sellerSupplies: {
current: sellerSuppliesCount, current: sellerSuppliesCount,
change: sellerSuppliesChangeToday, change: sellerSuppliesChangeToday,
percentChange: calculatePercentChange(sellerSuppliesCount, sellerSuppliesChangeToday) percentChange: calculatePercentChange(
} sellerSuppliesCount,
sellerSuppliesChangeToday
),
},
}; };
console.log(`🏁 FINAL WAREHOUSE STATS RESULT:`, JSON.stringify(result, null, 2)); console.log(
`🏁 FINAL WAREHOUSE STATS RESULT:`,
JSON.stringify(result, null, 2)
);
return result; return result;
}, },
@ -4037,9 +4129,12 @@ export const resolvers = {
}); });
} }
console.log(`📦 Зарезервированы товары для заказа ${supplyOrder.id}:`, console.log(
args.input.items.map(item => `${item.productId}: +${item.quantity} шт.`).join(', ')); `📦 Зарезервированы товары для заказа ${supplyOrder.id}:`,
args.input.items
.map((item) => `${item.productId}: +${item.quantity} шт.`)
.join(", ")
);
// Создаем расходники на основе заказанных товаров // Создаем расходники на основе заказанных товаров
// Расходники создаются в организации получателя (фулфилмент-центре) // Расходники создаются в организации получателя (фулфилмент-центре)
@ -4482,7 +4577,8 @@ export const resolvers = {
} }
// Проверяем доступность товара // Проверяем доступность товара
const availableStock = (product.stock || product.quantity) - (product.ordered || 0); const availableStock =
(product.stock || product.quantity) - (product.ordered || 0);
if (availableStock < args.quantity) { if (availableStock < args.quantity) {
return { return {
success: false, success: false,
@ -4498,7 +4594,9 @@ export const resolvers = {
}, },
}); });
console.log(`📦 Зарезервировано ${args.quantity} единиц товара ${product.name}`); console.log(
`📦 Зарезервировано ${args.quantity} единиц товара ${product.name}`
);
return { return {
success: true, success: true,
@ -4551,7 +4649,9 @@ export const resolvers = {
}, },
}); });
console.log(`🔄 Освобожден резерв ${args.quantity} единиц товара ${product.name}`); console.log(
`🔄 Освобожден резерв ${args.quantity} единиц товара ${product.name}`
);
return { return {
success: true, success: true,
@ -4617,7 +4717,9 @@ export const resolvers = {
}, },
}); });
console.log(`🚚 Обновлен статус "в пути" для товара ${product.name}: ${args.operation}`); console.log(
`🚚 Обновлен статус "в пути" для товара ${product.name}: ${args.operation}`
);
return { return {
success: true, success: true,
@ -5729,7 +5831,9 @@ export const resolvers = {
}, },
context: Context context: Context
) => { ) => {
console.log(`[DEBUG] updateSupplyOrderStatus вызван для заказа ${args.id} со статусом ${args.status}`); console.log(
`[DEBUG] updateSupplyOrderStatus вызван для заказа ${args.id} со статусом ${args.status}`
);
if (!context.user) { if (!context.user) {
throw new GraphQLError("Требуется авторизация", { throw new GraphQLError("Требуется авторизация", {
extensions: { code: "UNAUTHENTICATED" }, extensions: { code: "UNAUTHENTICATED" },
@ -5795,10 +5899,13 @@ export const resolvers = {
// ОТКЛЮЧЕНО: Устаревшая логика для обновления расходников // ОТКЛЮЧЕНО: Устаревшая логика для обновления расходников
// Теперь используются специальные мутации для каждой роли // Теперь используются специальные мутации для каждой роли
const targetOrganizationId = existingOrder.fulfillmentCenterId || existingOrder.organizationId; const targetOrganizationId =
existingOrder.fulfillmentCenterId || existingOrder.organizationId;
if (args.status === "CONFIRMED") { if (args.status === "CONFIRMED") {
console.log(`[WARNING] Попытка использовать устаревший статус CONFIRMED для заказа ${args.id}`); console.log(
`[WARNING] Попытка использовать устаревший статус CONFIRMED для заказа ${args.id}`
);
// Не обновляем расходники для устаревших статусов // Не обновляем расходники для устаревших статусов
// await prisma.supply.updateMany({ // await prisma.supply.updateMany({
// where: { // where: {
@ -5823,12 +5930,12 @@ export const resolvers = {
organizationId: targetOrganizationId, organizationId: targetOrganizationId,
status: "confirmed", status: "confirmed",
name: { name: {
in: existingOrder.items.map(item => item.product.name) in: existingOrder.items.map((item) => item.product.name),
} },
}, },
data: { data: {
status: "in-transit" status: "in-transit",
} },
}); });
console.log("✅ Статусы расходников обновлены на 'in-transit'"); console.log("✅ Статусы расходников обновлены на 'in-transit'");
@ -5836,7 +5943,6 @@ export const resolvers = {
// Если статус изменился на DELIVERED, обновляем склад // Если статус изменился на DELIVERED, обновляем склад
if (args.status === "DELIVERED") { if (args.status === "DELIVERED") {
console.log("🚚 Обновляем склад организации:", { console.log("🚚 Обновляем склад организации:", {
targetOrganizationId, targetOrganizationId,
fulfillmentCenterId: existingOrder.fulfillmentCenterId, fulfillmentCenterId: existingOrder.fulfillmentCenterId,
@ -5848,21 +5954,34 @@ export const resolvers = {
})), })),
}); });
// 🔄 СИНХРОНИЗАЦИЯ: Обновляем товары поставщика (переводим из "в пути" в "продано") // 🔄 СИНХРОНИЗАЦИЯ: Обновляем товары поставщика (переводим из "в пути" в "продано" + обновляем основные остатки)
for (const item of existingOrder.items) { for (const item of existingOrder.items) {
const product = await prisma.product.findUnique({ const product = await prisma.product.findUnique({
where: { id: item.product.id }, where: { id: item.product.id },
}); });
if (product) { if (product) {
// Согласно правилам: Основные значения = Предыдущие остатки + Прибыло - Убыло
const currentStock = product.stock || product.quantity || 0;
const newStock = Math.max(currentStock - item.quantity, 0);
await prisma.product.update({ await prisma.product.update({
where: { id: item.product.id }, where: { id: item.product.id },
data: { data: {
inTransit: Math.max((product.inTransit || 0) - item.quantity, 0), // Обновляем основные остатки (УБЫЛО)
stock: newStock,
quantity: newStock, // Синхронизируем оба поля для совместимости
// Обновляем дополнительные значения
inTransit: Math.max(
(product.inTransit || 0) - item.quantity,
0
),
sold: (product.sold || 0) + item.quantity, sold: (product.sold || 0) + item.quantity,
}, },
}); });
console.log(`✅ Товар поставщика "${product.name}" обновлен: доставлено ${item.quantity} единиц`); console.log(
`✅ Товар поставщика "${product.name}" обновлен: доставлено ${item.quantity} единиц (остаток: ${currentStock} -> ${newStock})`
);
} }
} }
@ -5992,7 +6111,9 @@ export const resolvers = {
}; };
} }
console.log(`[DEBUG] Поставщик ${currentUser.organization.name} одобряет заказ ${args.id}`); console.log(
`[DEBUG] Поставщик ${currentUser.organization.name} одобряет заказ ${args.id}`
);
// 🔄 СИНХРОНИЗАЦИЯ ОСТАТКОВ: Резервируем товары у поставщика // 🔄 СИНХРОНИЗАЦИЯ ОСТАТКОВ: Резервируем товары у поставщика
const orderWithItems = await prisma.supplyOrder.findUnique({ const orderWithItems = await prisma.supplyOrder.findUnique({
@ -6014,7 +6135,8 @@ export const resolvers = {
}); });
if (product) { if (product) {
const availableStock = (product.stock || product.quantity) - (product.ordered || 0); const availableStock =
(product.stock || product.quantity) - (product.ordered || 0);
if (availableStock < item.quantity) { if (availableStock < item.quantity) {
return { return {
@ -6023,14 +6145,32 @@ export const resolvers = {
}; };
} }
// Согласно правилам: при одобрении заказа остаток должен уменьшиться
const currentStock = product.stock || product.quantity || 0;
const newStock = Math.max(currentStock - item.quantity, 0);
await prisma.product.update({ await prisma.product.update({
where: { id: item.product.id }, where: { id: item.product.id },
data: { data: {
// Уменьшаем основной остаток (товар зарезервирован для заказа)
stock: newStock,
quantity: newStock, // Синхронизируем оба поля для совместимости
// Увеличиваем количество заказанного (для отслеживания)
ordered: (product.ordered || 0) + item.quantity, ordered: (product.ordered || 0) + item.quantity,
}, },
}); });
console.log(`📦 Зарезервировано ${item.quantity} единиц товара "${product.name}"`); console.log(
`📦 Товар "${product.name}" зарезервирован: ${item.quantity} единиц`
);
console.log(
` 📊 Остаток: ${currentStock} -> ${newStock} (уменьшен на ${item.quantity})`
);
console.log(
` 📋 Заказано: ${product.ordered || 0} -> ${
(product.ordered || 0) + item.quantity
}`
);
} }
} }
} }
@ -6056,10 +6196,13 @@ export const resolvers = {
}, },
}); });
console.log(`[DEBUG] Заказ ${args.id} успешно обновлен до статуса: ${updatedOrder.status}`); console.log(
`[DEBUG] Заказ ${args.id} успешно обновлен до статуса: ${updatedOrder.status}`
);
return { return {
success: true, success: true,
message: "Заказ поставки одобрен поставщиком. Товары зарезервированы.", message:
"Заказ поставки одобрен поставщиком. Товары зарезервированы, остатки обновлены.",
order: updatedOrder, order: updatedOrder,
}; };
} catch (error) { } catch (error) {
@ -6129,20 +6272,44 @@ export const resolvers = {
}); });
// 📦 СНИМАЕМ РЕЗЕРВАЦИЮ ПРИ ОТКЛОНЕНИИ // 📦 СНИМАЕМ РЕЗЕРВАЦИЮ ПРИ ОТКЛОНЕНИИ
// Уменьшаем поле "ordered" для каждого отклоненного товара // Восстанавливаем остатки и убираем резервацию для каждого отклоненного товара
for (const item of updatedOrder.items) { for (const item of updatedOrder.items) {
await prisma.product.update({ const product = await prisma.product.findUnique({
where: { id: item.productId }, where: { id: item.productId },
data: {
ordered: {
decrement: item.quantity,
},
},
}); });
if (product) {
// Восстанавливаем основные остатки (на случай, если заказ был одобрен, а затем отклонен)
const currentStock = product.stock || product.quantity || 0;
const restoredStock = currentStock + item.quantity;
await prisma.product.update({
where: { id: item.productId },
data: {
// Восстанавливаем основной остаток
stock: restoredStock,
quantity: restoredStock,
// Уменьшаем количество заказанного
ordered: Math.max((product.ordered || 0) - item.quantity, 0),
},
});
console.log(
`🔄 Восстановлены остатки товара "${
product.name
}": ${currentStock} -> ${restoredStock}, ordered: ${
product.ordered
} -> ${Math.max((product.ordered || 0) - item.quantity, 0)}`
);
}
} }
console.log(`📦 Снята резервация при отклонении заказа ${updatedOrder.id}:`, console.log(
updatedOrder.items.map(item => `${item.productId}: -${item.quantity} шт.`).join(', ')); `📦 Снята резервация при отклонении заказа ${updatedOrder.id}:`,
updatedOrder.items
.map((item) => `${item.productId}: -${item.quantity} шт.`)
.join(", ")
);
return { return {
success: true, success: true,
@ -6223,7 +6390,9 @@ export const resolvers = {
}, },
}); });
console.log(`🚚 Товар "${product.name}" переведен в статус "в пути": ${item.quantity} единиц`); console.log(
`🚚 Товар "${product.name}" переведен в статус "в пути": ${item.quantity} единиц`
);
} }
} }
} }
@ -6251,7 +6420,8 @@ export const resolvers = {
return { return {
success: true, success: true,
message: "Заказ отправлен поставщиком. Товары переведены в статус 'в пути'.", message:
"Заказ отправлен поставщиком. Товары переведены в статус 'в пути'.",
order: updatedOrder, order: updatedOrder,
}; };
} catch (error) { } catch (error) {
@ -6295,7 +6465,8 @@ export const resolvers = {
if (!existingOrder) { if (!existingOrder) {
return { return {
success: false, success: false,
message: "Заказ не найден или недоступен для подтверждения логистикой", message:
"Заказ не найден или недоступен для подтверждения логистикой",
}; };
} }
@ -6472,7 +6643,54 @@ export const resolvers = {
}, },
}); });
// 🔄 СИНХРОНИЗАЦИЯ СКЛАДА ПОСТАВЩИКА: Обновляем остатки поставщика согласно правилам
console.log("🔄 Начинаем синхронизацию остатков поставщика...");
for (const item of existingOrder.items) {
const product = await prisma.product.findUnique({
where: { id: item.product.id },
});
if (product) {
// Согласно правилам: Основные значения = Предыдущие остатки + Прибыло - Убыло
const currentStock = product.stock || product.quantity || 0;
const newStock = Math.max(currentStock - item.quantity, 0);
await prisma.product.update({
where: { id: item.product.id },
data: {
// Обновляем основные остатки (УБЫЛО)
stock: newStock,
quantity: newStock, // Синхронизируем оба поля для совместимости
// Обновляем дополнительные значения
inTransit: Math.max(
(product.inTransit || 0) - item.quantity,
0
),
sold: (product.sold || 0) + item.quantity,
},
});
console.log(
`✅ Товар поставщика "${product.name}" обновлен: доставлено ${item.quantity} единиц`
);
console.log(
` 📊 Остатки: ${currentStock} -> ${newStock} (УБЫЛО: ${item.quantity})`
);
console.log(
` 🚚 В пути: ${product.inTransit || 0} -> ${Math.max(
(product.inTransit || 0) - item.quantity,
0
)}`
);
console.log(
` 💰 Продано: ${product.sold || 0} -> ${
(product.sold || 0) + item.quantity
}`
);
}
}
// Обновляем склад фулфилмента // Обновляем склад фулфилмента
console.log("📦 Обновляем склад фулфилмента...");
for (const item of existingOrder.items) { for (const item of existingOrder.items) {
const existingSupply = await prisma.supply.findFirst({ const existingSupply = await prisma.supply.findFirst({
where: { where: {
@ -6490,11 +6708,20 @@ export const resolvers = {
status: "in-stock", status: "in-stock",
}, },
}); });
console.log(
`📈 Обновлен существующий расходник фулфилмента "${
item.product.name
}": ${existingSupply.currentStock} -> ${
existingSupply.currentStock + item.quantity
}`
);
} else { } else {
await prisma.supply.create({ await prisma.supply.create({
data: { data: {
name: item.product.name, name: item.product.name,
description: item.product.description || `Расходники от ${updatedOrder.partner.name}`, description:
item.product.description ||
`Расходники от ${updatedOrder.partner.name}`,
price: item.price, price: item.price,
quantity: item.quantity, quantity: item.quantity,
currentStock: item.quantity, currentStock: item.quantity,
@ -6502,16 +6729,25 @@ export const resolvers = {
unit: "шт", unit: "шт",
category: item.product.category?.name || "Расходники", category: item.product.category?.name || "Расходники",
status: "in-stock", status: "in-stock",
supplier: updatedOrder.partner.name || updatedOrder.partner.fullName || "Поставщик", supplier:
updatedOrder.partner.name ||
updatedOrder.partner.fullName ||
"Поставщик",
organizationId: currentUser.organization.id, organizationId: currentUser.organization.id,
}, },
}); });
console.log(
` Создан новый расходник фулфилмента "${item.product.name}": ${item.quantity} единиц`
);
} }
} }
console.log("🎉 Синхронизация склада завершена успешно!");
return { return {
success: true, success: true,
message: "Заказ принят фулфилментом. Склад обновлен.", message:
"Заказ принят фулфилментом. Склад обновлен. Остатки поставщика синхронизированы.",
order: updatedOrder, order: updatedOrder,
}; };
} catch (error) { } catch (error) {