
## Структурные изменения: ### 📁 Организация архивных файлов: - Перенос всех устаревших правил в legacy-rules/ - Создание структуры docs-and-reports/ для отчетов - Архивация backup файлов в legacy-rules/backups/ ### 🔧 Критические компоненты: - src/components/supplies/multilevel-supplies-table.tsx - многоуровневая таблица поставок - src/components/supplies/components/recipe-display.tsx - отображение рецептур - src/components/fulfillment-supplies/fulfillment-goods-orders-tab.tsx - вкладка товарных заказов ### 🎯 GraphQL обновления: - Обновление mutations.ts, queries.ts, resolvers.ts, typedefs.ts - Синхронизация с Prisma schema.prisma - Backup файлы для истории изменений ### 🛠️ Утилитарные скрипты: - 12 новых скриптов в scripts/ для анализа данных - Скрипты проверки фулфилмент-пользователей - Утилиты очистки и фиксации данных поставок ### 📊 Тестирование: - test-fulfillment-filtering.js - тестирование фильтрации фулфилмента - test-full-workflow.js - полный workflow тестирование ### 📝 Документация: - logistics-statistics-warehouse-rules.md - объединенные правила модулей - Обновление журналов модуляризации и разработки ### ✅ Исправления ESLint: - Исправлены критические ошибки в sidebar.tsx - Исправлены ошибки типизации в multilevel-supplies-table.tsx - Исправлены неиспользуемые переменные в goods-supplies-table.tsx - Заменены типы any на строгую типизацию - Исправлены console.log на console.warn ## Результат: - Завершена полная модуляризация системы - Организована архитектура legacy файлов - Добавлены критически важные компоненты таблиц - Создана полная инфраструктура тестирования - Исправлены все критические ESLint ошибки - Сохранены 103 незакоммиченных изменения 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
197 lines
8.6 KiB
JavaScript
197 lines
8.6 KiB
JavaScript
const { PrismaClient } = require('@prisma/client')
|
||
|
||
const prisma = new PrismaClient()
|
||
|
||
async function analyzeFulfillmentSupplies() {
|
||
try {
|
||
console.log('🔍 ГЛУБОКИЙ АНАЛИЗ РАСХОДНИКОВ ФУЛФИЛМЕНТА')
|
||
console.log('=' .repeat(60))
|
||
|
||
// Находим фулфилмент организацию пользователя с номером +7 (999) 999-99-99
|
||
const fulfillmentUser = await prisma.user.findFirst({
|
||
where: { phone: '79999999999' },
|
||
include: {
|
||
organization: {
|
||
include: {
|
||
_count: {
|
||
select: {
|
||
supplies: true,
|
||
supplyOrders: true,
|
||
fulfillmentSupplyOrders: true
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
})
|
||
|
||
if (!fulfillmentUser?.organization) {
|
||
console.log('❌ Фулфилмент пользователь или организация не найдены')
|
||
return
|
||
}
|
||
|
||
const org = fulfillmentUser.organization
|
||
console.log('🏢 ОРГАНИЗАЦИЯ:')
|
||
console.log(` ID: ${org.id}`)
|
||
console.log(` Название: ${org.name}`)
|
||
console.log(` Тип: ${org.type}`)
|
||
console.log(` Расходников на складе: ${org._count.supplies}`)
|
||
console.log(` Заказов поставок: ${org._count.supplyOrders}`)
|
||
console.log(` Входящих поставок: ${org._count.fulfillmentSupplyOrders}`)
|
||
console.log('')
|
||
|
||
// 1. АНАЛИЗ РАСХОДНИКОВ НА СКЛАДЕ
|
||
console.log('📦 1. РАСХОДНИКИ НА СКЛАДЕ:')
|
||
|
||
const allSupplies = await prisma.supply.findMany({
|
||
where: { organizationId: org.id },
|
||
orderBy: { createdAt: 'desc' }
|
||
})
|
||
|
||
console.log(` Всего записей Supply: ${allSupplies.length}`)
|
||
|
||
// Группируем по типам
|
||
const fulfillmentSupplies = allSupplies.filter(s => s.type === 'FULFILLMENT_CONSUMABLES')
|
||
const sellerSupplies = allSupplies.filter(s => s.type === 'SELLER_CONSUMABLES')
|
||
|
||
console.log(` 📊 Расходники фулфилмента: ${fulfillmentSupplies.length} записей`)
|
||
console.log(` 💼 Расходники селлеров: ${sellerSupplies.length} записей`)
|
||
console.log('')
|
||
|
||
// Детальный анализ расходников фулфилмента
|
||
if (fulfillmentSupplies.length > 0) {
|
||
console.log('🔍 ДЕТАЛИ РАСХОДНИКОВ ФУЛФИЛМЕНТА:')
|
||
fulfillmentSupplies.forEach((supply, index) => {
|
||
console.log(` ${index + 1}. "${supply.name}" (${supply.article})`)
|
||
console.log(` ID: ${supply.id}`)
|
||
console.log(` Количество: ${supply.quantity} шт`)
|
||
console.log(` Текущий остаток: ${supply.currentStock} шт`)
|
||
console.log(` Использовано: ${supply.usedStock} шт`)
|
||
console.log(` Статус: ${supply.status}`)
|
||
console.log(` Поставщик: ${supply.supplier}`)
|
||
console.log(` Дата: ${supply.date?.toISOString().split('T')[0]}`)
|
||
console.log(` Создано: ${supply.createdAt?.toISOString().split('T')[0]}`)
|
||
console.log('')
|
||
})
|
||
}
|
||
|
||
// 2. АНАЛИЗ ЗАКАЗОВ ПОСТАВОК
|
||
console.log('📋 2. ЗАКАЗЫ ПОСТАВОК (созданные фулфилментом):')
|
||
|
||
const createdOrders = await prisma.supplyOrder.findMany({
|
||
where: { organizationId: org.id },
|
||
include: {
|
||
partner: { select: { name: true, type: true } },
|
||
items: {
|
||
include: { product: { select: { name: true, article: true } } }
|
||
}
|
||
},
|
||
orderBy: { createdAt: 'desc' }
|
||
})
|
||
|
||
console.log(` Всего заказов: ${createdOrders.length}`)
|
||
|
||
createdOrders.forEach((order, index) => {
|
||
console.log(` ${index + 1}. Заказ ${order.id}`)
|
||
console.log(` Поставщик: ${order.partner.name} (${order.partner.type})`)
|
||
console.log(` Статус: ${order.status}`)
|
||
console.log(` Тип расходников: ${order.consumableType}`)
|
||
console.log(` Дата доставки: ${order.deliveryDate?.toISOString().split('T')[0]}`)
|
||
console.log(` Сумма: ${order.totalAmount} ₽`)
|
||
console.log(` Товаров: ${order.items.length}`)
|
||
order.items.forEach((item, itemIndex) => {
|
||
console.log(` ${itemIndex + 1}) ${item.product.name} (${item.product.article}) - ${item.quantity} шт`)
|
||
})
|
||
console.log('')
|
||
})
|
||
|
||
// 3. АНАЛИЗ ВХОДЯЩИХ ПОСТАВОК
|
||
console.log('📥 3. ВХОДЯЩИЕ ПОСТАВКИ (доставляемые на фулфилмент):')
|
||
|
||
const receivedOrders = await prisma.supplyOrder.findMany({
|
||
where: { fulfillmentCenterId: org.id },
|
||
include: {
|
||
organization: { select: { name: true, type: true } },
|
||
partner: { select: { name: true, type: true } },
|
||
items: {
|
||
include: { product: { select: { name: true, article: true } } }
|
||
}
|
||
},
|
||
orderBy: { createdAt: 'desc' }
|
||
})
|
||
|
||
console.log(` Всего входящих поставок: ${receivedOrders.length}`)
|
||
|
||
receivedOrders.forEach((order, index) => {
|
||
console.log(` ${index + 1}. Поставка ${order.id}`)
|
||
console.log(` Заказчик: ${order.organization.name} (${order.organization.type})`)
|
||
console.log(` Поставщик: ${order.partner.name} (${order.partner.type})`)
|
||
console.log(` Статус: ${order.status}`)
|
||
console.log(` Тип расходников: ${order.consumableType}`)
|
||
console.log(` Дата доставки: ${order.deliveryDate?.toISOString().split('T')[0]}`)
|
||
console.log(` Сумма: ${order.totalAmount} ₽`)
|
||
console.log(` Товаров: ${order.items.length}`)
|
||
order.items.forEach((item, itemIndex) => {
|
||
console.log(` ${itemIndex + 1}) ${item.product.name} (${item.product.article}) - ${item.quantity} шт`)
|
||
})
|
||
console.log('')
|
||
})
|
||
|
||
// 4. СВЕРКА ДАННЫХ
|
||
console.log('⚖️ 4. СВЕРКА ДАННЫХ:')
|
||
|
||
// Подсчитываем ожидаемое количество расходников из заказов
|
||
const totalFromOrders = createdOrders
|
||
.filter(order => order.status === 'DELIVERED' && order.consumableType === 'FULFILLMENT_CONSUMABLES')
|
||
.reduce((sum, order) => {
|
||
return sum + order.items.reduce((itemSum, item) => itemSum + item.quantity, 0)
|
||
}, 0)
|
||
|
||
const totalFromSupplies = fulfillmentSupplies.reduce((sum, supply) => sum + supply.currentStock, 0)
|
||
|
||
console.log(` 📊 Ожидаемое из доставленных заказов: ${totalFromOrders} шт`)
|
||
console.log(` 📦 Фактическое в Supply записях: ${totalFromSupplies} шт`)
|
||
console.log(` ${totalFromOrders === totalFromSupplies ? '✅' : '❌'} Соответствие: ${totalFromOrders === totalFromSupplies ? 'КОРРЕКТНО' : 'ОШИБКА'}`)
|
||
|
||
if (totalFromOrders !== totalFromSupplies) {
|
||
console.log(` 🔍 Разница: ${Math.abs(totalFromOrders - totalFromSupplies)} шт`)
|
||
}
|
||
|
||
// 5. АНАЛИЗ ПО АРТИКУЛАМ
|
||
console.log('')
|
||
console.log('🏷️ 5. АНАЛИЗ ПО АРТИКУЛАМ:')
|
||
|
||
const articleGroups = {}
|
||
fulfillmentSupplies.forEach(supply => {
|
||
if (!articleGroups[supply.article]) {
|
||
articleGroups[supply.article] = []
|
||
}
|
||
articleGroups[supply.article].push(supply)
|
||
})
|
||
|
||
console.log(` Уникальных артикулов: ${Object.keys(articleGroups).length}`)
|
||
|
||
Object.entries(articleGroups).forEach(([article, supplies]) => {
|
||
const totalStock = supplies.reduce((sum, s) => sum + s.currentStock, 0)
|
||
console.log(` 📋 ${article}: ${supplies.length} записей, ${totalStock} шт общий остаток`)
|
||
if (supplies.length > 1) {
|
||
console.log(` ⚠️ ДУБЛИРОВАНИЕ: ${supplies.length} записей для одного артикула!`)
|
||
supplies.forEach((supply, index) => {
|
||
console.log(` ${index + 1}) ID: ${supply.id}, остаток: ${supply.currentStock} шт`)
|
||
})
|
||
}
|
||
})
|
||
|
||
console.log('')
|
||
console.log('=' .repeat(60))
|
||
console.log('✅ АНАЛИЗ ЗАВЕРШЕН')
|
||
|
||
} catch (error) {
|
||
console.error('❌ ОШИБКА при анализе:', error)
|
||
console.error(' Детали:', error.message)
|
||
} finally {
|
||
await prisma.$disconnect()
|
||
}
|
||
}
|
||
|
||
analyzeFulfillmentSupplies() |