# 📦 V2 СИСТЕМА СЕЛЛЕРСКИХ РАСХОДНИКОВ > **Статус:** ✅ **РЕАЛИЗОВАНО И АКТИВНО** (август 2025) > **Версия:** 2.0 > **Заменяет:** V1 Supply система для селлерских расходников --- ## 🎯 ОБЗОР СИСТЕМЫ ### ПРИНЦИП РАБОТЫ V2: - **Специализированные модели** вместо универсальной Supply таблицы - **Автоматическое управление инвентарем** при смене статусов заказов - **Доменная изоляция** между типами организаций - **Совместимость фронтенда** через адаптированные резолверы ### КЛЮЧЕВЫЕ КОМПОНЕНТЫ: 1. **SellerConsumableInventory** - основная модель V2 2. **seller-inventory-v2.ts** - GraphQL резолверы 3. **inventory-management.ts** - бизнес-логика управления 4. **Автоматические триггеры** в seller-consumables.ts --- ## 🗃️ МОДЕЛЬ ДАННЫХ ### SellerConsumableInventory ```prisma model SellerConsumableInventory { id String @id @default(cuid()) sellerId String // Владелец расходников (селлер) fulfillmentCenterId String // Фулфилмент-центр где хранятся productId String // Товар-расходник // === СКЛАДСКИЕ ДАННЫЕ === currentStock Int @default(0) // Текущий остаток minStock Int @default(0) // Минимальный остаток maxStock Int? // Максимальный остаток reservedStock Int @default(0) // Зарезервировано totalReceived Int @default(0) // Всего получено totalUsed Int @default(0) // Всего использовано // === ФИНАНСОВЫЕ ДАННЫЕ === averageCost Decimal @default(0) // Средняя себестоимость usagePrice Decimal? // Цена использования // === ВРЕМЕННЫЕ МЕТКИ === lastSupplyDate DateTime? // Последняя поставка lastUsageDate DateTime? // Последнее использование // === МЕТАДАННЫЕ === notes String? // Заметки createdAt DateTime @default(now()) updatedAt DateTime @updatedAt // === СВЯЗИ === seller Organization @relation("SellerInventory") fulfillmentCenter Organization @relation("SellerInventoryWarehouse") product Product @relation("SellerInventoryProducts") @@unique([sellerId, fulfillmentCenterId, productId]) } ``` ### КЛЮЧЕВЫЕ ИНДЕКСЫ: - `[sellerId, currentStock]` - быстрый поиск по остаткам селлера - `[fulfillmentCenterId, sellerId]` - поиск по фулфилменту - `[currentStock, minStock]` - контроль минимальных остатков --- ## 🔄 БИЗНЕС-ПРОЦЕССЫ ### 1. СОЗДАНИЕ ЗАКАЗА СЕЛЛЕРОМ ```mermaid graph TD A[Селлер создает заказ] --> B[createSellerConsumableSupplyOrder] B --> C[Статус: PENDING] C --> D[Уведомление поставщику] ``` **Компоненты:** - `CreateConsumablesSupplyPage` - форма создания - `createSellerConsumableSupplyOrder` - мутация ### 2. ОБРАБОТКА ПОСТАВЩИКОМ ```mermaid graph TD A[PENDING] --> B[Поставщик одобряет] B --> C[SUPPLIER_APPROVED] C --> D[Автоматический переход в CONFIRMED] ``` ### 3. ДОСТАВКА И ПОПОЛНЕНИЕ ИНВЕНТАРЯ ```mermaid graph TD A[SHIPPED] --> B[Фулфилмент получает] B --> C[updateSellerSupplyStatus: DELIVERED] C --> D[🔄 АВТОМАТИЧЕСКИЙ ТРИГГЕР] D --> E[processSellerConsumableSupplyReceipt] E --> F[Обновление SellerConsumableInventory] F --> G[Пересчет averageCost] ``` **Автоматический триггер (seller-consumables.ts:547-554):** ```typescript if (status === 'DELIVERED') { const inventoryItems = updatedSupply.items.map(item => ({ productId: item.productId, receivedQuantity: item.quantity, unitPrice: parseFloat(item.price.toString()), })) await processSellerConsumableSupplyReceipt(args.id, inventoryItems) } ``` --- ## 🛠️ ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ ### GraphQL Резолверы (seller-inventory-v2.ts): #### mySellerConsumableInventory - **Доступ:** Только селлеры - **Назначение:** Получение собственного инвентаря - **Фильтрация:** По sellerId из контекста #### allSellerConsumableInventory - **Доступ:** Только фулфилмент-центры - **Назначение:** Управление всем инвентарем селлеров - **Фильтрация:** По fulfillmentCenterId из контекста ### Функции управления инвентарем (inventory-management.ts): #### processSellerConsumableSupplyReceipt ```typescript async function processSellerConsumableSupplyReceipt( supplyOrderId: string, inventoryItems: Array<{ productId: string receivedQuantity: number unitPrice: number }> ) ``` #### updateSellerInventory - **Автоматическое создание** записей инвентаря - **Пересчет средней стоимости** (FIFO принцип) - **Обновление статистики** (totalReceived, currentStock) --- ## 🔄 МИГРАЦИЯ V1 → V2 ### ЧТО УДАЛЕНО ИЗ V1: - ❌ Создание Supply записей в `updateSupplyOrderStatus` - ❌ Создание Supply записей в `fulfillmentReceiveOrder` - ❌ Создание Supply записей в `createSupplyOrder` - ❌ Дублирование данных между системами ### ЧТО СОХРАНЕНО: - ✅ GraphQL совместимость через формат Supply - ✅ Фронтенд работает без изменений - ✅ Существующие V1 Supply записи (архивные) ### АДАПТЕРЫ СОВМЕСТИМОСТИ: #### sellerSuppliesOnWarehouse (V1→V2) ```typescript // Преобразование SellerConsumableInventory → Supply формат const suppliesFormatted = sellerInventory.map((item) => ({ // V2 данные адаптируются в V1 формат id: item.id, name: item.product.name, currentStock: item.currentStock, type: 'SELLER_CONSUMABLES', sellerOwner: { id: item.seller.id, name: item.seller.name || 'Неизвестно', inn: item.seller.inn || 'НЕ_УКАЗАН' } })) ``` --- ## 🎨 ФРОНТЕНД ИНТЕГРАЦИЯ ### ФИЛЬТРАЦИЯ ПОСТАВОК: #### `/seller/supplies/goods/cards` - ТОЛЬКО товары ```typescript goodsSupplies={(mySuppliesData?.mySupplyOrders || []).filter((supply: any) => supply.consumableType !== 'SELLER_CONSUMABLES' // Исключаем расходники )} ``` #### `/seller/supplies/consumables` - ТОЛЬКО расходники ```typescript const sellerOrders = (data?.supplyOrders || []).filter((order: SupplyOrder) => { return order.organization.id === user?.organization?.id && order.consumableType === 'SELLER_CONSUMABLES' // Только расходники }) ``` ### КОМПОНЕНТЫ UI: - `SuppliesDashboard` - главный дашборд с фильтрацией - `AllSuppliesTab` - показывает товарные поставки - `SellerSupplyOrdersTab` - показывает поставки расходников --- ## 📊 ПРЕИМУЩЕСТВА V2 СИСТЕМЫ ### ПРОИЗВОДИТЕЛЬНОСТЬ: - ✅ **Специализированные запросы** вместо JOIN по всей Supply таблице - ✅ **Индексированный поиск** по sellerId и fulfillmentCenterId - ✅ **Кэширование** на уровне GraphQL ### ТОЧНОСТЬ ДАННЫХ: - ✅ **Автоматический расчет** средней себестоимости (FIFO) - ✅ **Раздельная статистика** поступлений и расходов - ✅ **Исключение дублирования** данных ### МАСШТАБИРУЕМОСТЬ: - ✅ **Доменная изоляция** - каждый тип организации имеет свои модели - ✅ **Независимые обновления** - изменения в одной системе не влияют на другие - ✅ **Простое добавление новых типов** расходников --- ## 🛡️ БЕЗОПАСНОСТЬ И КОНТРОЛЬ ### ДОСТУП К ДАННЫМ: - **Селлеры:** Видят только свой инвентарь (`mySellerConsumableInventory`) - **Фулфилмент:** Видит весь инвентарь селлеров на своем складе (`allSellerConsumableInventory`) - **Остальные:** Доступ запрещен ### АУДИТ ИЗМЕНЕНИЙ: - Все изменения логируются через console.warn - Временные метки lastSupplyDate/lastUsageDate - Полная история в totalReceived/totalUsed --- ## 🔧 КОМАНДЫ И ТЕСТИРОВАНИЕ ### ПОЛЕЗНЫЕ ЗАПРОСЫ: ```sql -- Проверка инвентаря селлера SELECT * FROM seller_consumable_inventory WHERE seller_id = 'SELLER_ID'; -- Статистика по фулфилменту SELECT seller_id, COUNT(*) as products_count, SUM(current_stock) as total_stock FROM seller_consumable_inventory WHERE fulfillment_center_id = 'FULFILLMENT_ID' GROUP BY seller_id; ``` ### ТЕСТИРОВАНИЕ: ```bash # Проверка V2 системы node -e "..." # См. примеры в коде # Тестирование GraphQL curl -X POST http://localhost:3001/api/graphql -d '{ "query": "query { mySellerConsumableInventory { id currentStock } }" }' ``` --- ## 🚀 СТАТУС ВНЕДРЕНИЯ ### ✅ ЗАВЕРШЕНО (август 2025): - [x] SellerConsumableInventory модель создана - [x] GraphQL резолверы реализованы - [x] Автоматическое пополнение работает - [x] V1 код удален полностью - [x] UI фильтрация исправлена - [x] Система протестирована ### 📋 READY FOR PRODUCTION: - Все тесты проходят - Сборка успешна - GraphQL эндпоинты работают - Фронтенд совместим - Нет breaking changes --- ## 📚 СВЯЗАННАЯ ДОКУМЕНТАЦИЯ - **SUPPLY_CHAIN_WORKFLOW_V2.md** - общий workflow V2 систем - **SELLER_DOMAIN.md** - домен селлеров - **FULFILLMENT_DOMAIN.md** - домен фулфилмента - **PRISMA_MODEL_RULES.md** - правила моделей данных - **COMPONENT_ARCHITECTURE.md** - архитектура компонентов --- **🏆 РЕЗУЛЬТАТ:** Полнофункциональная V2 система управления расходниками селлеров с автоматическим инвентарем, доменной изоляцией и совместимостью с существующим фронтендом.