feat: реализовать полную автосинхронизацию V2 системы расходников с nameForSeller и анализ миграции

-  Добавлено поле nameForSeller в FulfillmentConsumable для кастомизации названий
-  Добавлено поле inventoryId для связи между каталогом и складом
-  Реализована автосинхронизация FulfillmentConsumableInventory → FulfillmentConsumable
-  Обновлен UI с колонкой "Название для селлера" в /fulfillment/services/consumables
-  Исправлены GraphQL запросы (удалено поле description, добавлены новые поля)
-  Создан скрипт sync-inventory-to-catalog.ts для миграции существующих данных
-  Добавлена техническая документация архитектуры системы инвентаря
-  Создан отчет о статусе миграции 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-03 23:10:16 +03:00
parent 65fba5d911
commit cdeee82237
35 changed files with 7869 additions and 311 deletions

View File

@ -154,6 +154,11 @@ model Organization {
// === СВЯЗИ С ИНВЕНТАРЕМ ТОВАРОВ СЕЛЛЕРА V2 ===
sellerGoodsInventoryAsOwner SellerGoodsInventory[] @relation("SellerGoodsInventoryOwner")
sellerGoodsInventoryAsWarehouse SellerGoodsInventory[] @relation("SellerGoodsInventoryWarehouse")
// === СВЯЗИ С УСЛУГАМИ ФУЛФИЛМЕНТА V2 ===
fulfillmentServicesV2 FulfillmentService[] @relation("FulfillmentServicesV2")
fulfillmentConsumablesV2 FulfillmentConsumable[] @relation("FulfillmentConsumablesV2")
fulfillmentLogisticsV2 FulfillmentLogistics[] @relation("FulfillmentLogisticsV2")
@@index([referralCode])
@@index([referredById])
@ -1005,6 +1010,7 @@ model FulfillmentConsumableInventory {
// === СВЯЗИ ===
fulfillmentCenter Organization @relation("FFInventory", fields: [fulfillmentCenterId], references: [id])
product Product @relation("InventoryProducts", fields: [productId], references: [id])
catalogItems FulfillmentConsumable[] // обратная связь с каталогом
// === ИНДЕКСЫ ===
@@unique([fulfillmentCenterId, productId]) // один товар = одна запись на фулфилмент
@ -1059,6 +1065,81 @@ model SellerConsumableInventory {
@@map("seller_consumable_inventory")
}
// =============================================================================
// 🛠️ СИСТЕМА УСЛУГ ФУЛФИЛМЕНТА V2
// =============================================================================
// Услуги фулфилмента (упаковка, маркировка, хранение и т.д.)
model FulfillmentService {
id String @id @default(cuid())
fulfillmentId String // какой фулфилмент предоставляет услугу
name String // название услуги
description String? // описание услуги
price Decimal @db.Decimal(10, 2) // цена за единицу
unit String @default("шт") // единица измерения (шт, день, м2)
isActive Boolean @default(true)
imageUrl String? // изображение услуги
sortOrder Int @default(0) // порядок сортировки
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// === СВЯЗИ ===
fulfillment Organization @relation("FulfillmentServicesV2", fields: [fulfillmentId], references: [id])
@@index([fulfillmentId, isActive])
@@map("fulfillment_services_v2")
}
// Расходники фулфилмента (пленка, скотч, коробки и т.д.)
model FulfillmentConsumable {
id String @id @default(cuid())
fulfillmentId String // какой фулфилмент использует расходник
inventoryId String? // связь со складом (FulfillmentConsumableInventory)
name String // название расходника
nameForSeller String? // название для селлера (кастомное)
article String? // артикул
pricePerUnit Decimal @db.Decimal(10, 2) // цена за единицу
unit String @default("шт") // единица измерения
minStock Int @default(0) // минимальный остаток
currentStock Int @default(0) // текущий остаток на складе
isAvailable Boolean @default(true)
imageUrl String? // изображение
sortOrder Int @default(0) // порядок сортировки
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// === СВЯЗИ ===
fulfillment Organization @relation("FulfillmentConsumablesV2", fields: [fulfillmentId], references: [id])
inventory FulfillmentConsumableInventory? @relation(fields: [inventoryId], references: [id])
@@index([fulfillmentId, isAvailable])
@@map("fulfillment_consumables_v2")
}
// Логистика фулфилмента (маршруты доставки)
model FulfillmentLogistics {
id String @id @default(cuid())
fulfillmentId String // какой фулфилмент предоставляет логистику
fromLocation String // откуда (город/рынок)
toLocation String // куда (адрес фулфилмента)
fromAddress String? // полный адрес забора
toAddress String? // полный адрес доставки
priceUnder1m3 Decimal @db.Decimal(10, 2) // цена до 1м³
priceOver1m3 Decimal @db.Decimal(10, 2) // цена свыше 1м³
estimatedDays Int @default(1) // дней на доставку
description String? // описание маршрута
isActive Boolean @default(true)
sortOrder Int @default(0) // порядок сортировки
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// === СВЯЗИ ===
fulfillment Organization @relation("FulfillmentLogisticsV2", fields: [fulfillmentId], references: [id])
@@index([fulfillmentId, isActive])
@@map("fulfillment_logistics_v2")
}
// ===============================================
// 🛒 SELLER GOODS SUPPLY SYSTEM V2.0 - ТОВАРНЫЕ ПОСТАВКИ
// ===============================================