feat(fulfillment-supplies): миграция формы создания поставок расходников на v2 систему
- Обновлена форма создания поставок расходников фулфилмента для использования v2 GraphQL API - Заменена мутация CREATE_SUPPLY_ORDER на CREATE_FULFILLMENT_CONSUMABLE_SUPPLY - Обновлена структура input данных под новый формат v2 - Сделано поле логистики опциональным - Добавлено поле notes для комментариев к поставке - Обновлены refetchQueries на новые v2 запросы - Исправлены TypeScript ошибки в интерфейсах - Удалена дублирующая страница consumables-v2 - Сохранен оригинальный богатый UI интерфейс формы (819 строк) - Подтверждена работа с новой таблицей FulfillmentConsumableSupplyOrder Технические изменения: - src/components/fulfillment-supplies/create-fulfillment-consumables-supply-v2.tsx - основная форма - src/components/fulfillment-supplies/fulfillment-supplies-layout.tsx - обновлена навигация - Добавлены недостающие поля quantity и ordered в интерфейсы продуктов - Исправлены импорты и зависимости Результат: форма полностью интегрирована с v2 системой поставок, которая использует отдельные таблицы для каждого типа поставок согласно новой архитектуре. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
600
docs/development/DATABASE_SCHEMA_V2.md
Normal file
600
docs/development/DATABASE_SCHEMA_V2.md
Normal file
@ -0,0 +1,600 @@
|
||||
# 🗄️ СХЕМА БАЗЫ ДАННЫХ SFERA v2.0 - СИСТЕМА ПОСТАВОК
|
||||
|
||||
> **⚠️ ВАЖНО:** Этот документ описывает НОВЫЕ таблицы для системы поставок v2.0. Существующие таблицы остаются без изменений для обратной совместимости.
|
||||
|
||||
## 📦 НОВЫЕ ТАБЛИЦЫ ПОСТАВОК НА ФУЛФИЛМЕНТ
|
||||
|
||||
### 1️⃣ **FulfillmentConsumableSupplyOrder - Поставки расходников ФФ**
|
||||
|
||||
```prisma
|
||||
model FulfillmentConsumableSupplyOrder {
|
||||
// === БАЗОВЫЕ ПОЛЯ ===
|
||||
id String @id @default(cuid())
|
||||
status SupplyOrderStatusV2 @default(PENDING)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === ДАННЫЕ ФФ (создатель) ===
|
||||
fulfillmentCenterId String // кто заказывает (FK: Organization)
|
||||
requestedDeliveryDate DateTime // когда нужно
|
||||
resalePricePerUnit Decimal? @db.Decimal(10, 2) // цена продажи селлерам
|
||||
minStockLevel Int? // минимальный остаток
|
||||
notes String? // заметки ФФ
|
||||
|
||||
// === ДАННЫЕ ПОСТАВЩИКА ===
|
||||
supplierId String? // кто поставляет (FK: Organization)
|
||||
supplierApprovedAt DateTime? // когда одобрил
|
||||
packagesCount Int? // количество грузомест
|
||||
estimatedVolume Decimal? @db.Decimal(8, 3) // объем груза в м³
|
||||
supplierContractId String? // номер договора
|
||||
supplierNotes String? // заметки поставщика
|
||||
|
||||
// === ДАННЫЕ ЛОГИСТИКИ ===
|
||||
logisticsPartnerId String? // кто везет (FK: Organization)
|
||||
estimatedDeliveryDate DateTime? // план доставки
|
||||
routeId String? // маршрут (FK: LogisticsRoute)
|
||||
logisticsCost Decimal? @db.Decimal(10, 2) // стоимость доставки
|
||||
logisticsNotes String? // заметки логистики
|
||||
|
||||
// === ДАННЫЕ ОТГРУЗКИ ===
|
||||
shippedAt DateTime? // факт отгрузки
|
||||
trackingNumber String? // номер отслеживания
|
||||
|
||||
// === ДАННЫЕ ПРИЕМКИ ===
|
||||
receivedAt DateTime? // факт приемки
|
||||
receivedById String? // кто принял (FK: User)
|
||||
actualQuantity Int? // принято количество
|
||||
defectQuantity Int? // брак
|
||||
receiptNotes String? // заметки приемки
|
||||
|
||||
// === СВЯЗИ ===
|
||||
fulfillmentCenter Organization @relation("FFSupplyOrdersFulfillment", fields: [fulfillmentCenterId], references: [id])
|
||||
supplier Organization? @relation("FFSupplyOrdersSupplier", fields: [supplierId], references: [id])
|
||||
logisticsPartner Organization? @relation("FFSupplyOrdersLogistics", fields: [logisticsPartnerId], references: [id])
|
||||
receivedBy User? @relation("FFSupplyOrdersReceiver", fields: [receivedById], references: [id])
|
||||
items FulfillmentConsumableSupplyItem[]
|
||||
|
||||
@@map("fulfillment_consumable_supply_orders")
|
||||
}
|
||||
|
||||
model FulfillmentConsumableSupplyItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String // связь с поставкой
|
||||
productId String // какой расходник (FK: Product)
|
||||
|
||||
// === КОЛИЧЕСТВА ===
|
||||
requestedQuantity Int // запросили
|
||||
approvedQuantity Int? // поставщик одобрил
|
||||
shippedQuantity Int? // отгрузили
|
||||
receivedQuantity Int? // приняли
|
||||
defectQuantity Int? @default(0) // брак
|
||||
|
||||
// === ЦЕНЫ ===
|
||||
unitPrice Decimal @db.Decimal(10, 2) // цена за единицу от поставщика
|
||||
totalPrice Decimal @db.Decimal(12, 2) // общая стоимость
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === СВЯЗИ ===
|
||||
supplyOrder FulfillmentConsumableSupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation("FFSupplyItems", fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("fulfillment_consumable_supply_items")
|
||||
}
|
||||
```
|
||||
|
||||
### 2️⃣ **SellerConsumableSupplyOrder - Поставки расходников селлеров**
|
||||
|
||||
```prisma
|
||||
model SellerConsumableSupplyOrder {
|
||||
// === БАЗОВЫЕ ПОЛЯ ===
|
||||
id String @id @default(cuid())
|
||||
status SupplyOrderStatusV2 @default(PENDING)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === ДАННЫЕ СЕЛЛЕРА (создатель) ===
|
||||
sellerId String // кто заказывает (FK: Organization)
|
||||
fulfillmentCenterId String // где будет храниться (FK: Organization)
|
||||
requestedDeliveryDate DateTime // когда нужно
|
||||
notes String? // заметки селлера
|
||||
|
||||
// === ДАННЫЕ ПОСТАВЩИКА ===
|
||||
supplierId String? // кто поставляет (FK: Organization)
|
||||
supplierApprovedAt DateTime? // когда одобрил
|
||||
packagesCount Int? // количество грузомест
|
||||
estimatedVolume Decimal? @db.Decimal(8, 3) // объем груза в м³
|
||||
supplierContractId String? // номер договора
|
||||
supplierNotes String? // заметки поставщика
|
||||
|
||||
// === ДАННЫЕ ЛОГИСТИКИ ===
|
||||
logisticsPartnerId String? // кто везет (FK: Organization)
|
||||
estimatedDeliveryDate DateTime? // план доставки
|
||||
routeId String? // маршрут (FK: LogisticsRoute)
|
||||
logisticsCost Decimal? @db.Decimal(10, 2) // стоимость доставки
|
||||
logisticsNotes String? // заметки логистики
|
||||
|
||||
// === ДАННЫЕ ОТГРУЗКИ ===
|
||||
shippedAt DateTime? // факт отгрузки
|
||||
trackingNumber String? // номер отслеживания
|
||||
|
||||
// === ДАННЫЕ ПРИЕМКИ ===
|
||||
receivedAt DateTime? // факт приемки ФФ
|
||||
receivedById String? // кто принял (FK: User)
|
||||
actualQuantity Int? // принято количество
|
||||
defectQuantity Int? // брак
|
||||
receiptNotes String? // заметки приемки
|
||||
|
||||
// === УНИКАЛЬНЫЕ ПОЛЯ ДЛЯ РАСХОДНИКОВ СЕЛЛЕРОВ ===
|
||||
storageTermMonths Int? // срок хранения в месяцах
|
||||
accessRights SellerConsumableAccessRights @default(SELLER_ONLY)
|
||||
storageCostPerMonth Decimal? @db.Decimal(8, 2) // стоимость хранения за месяц
|
||||
|
||||
// === СВЯЗИ ===
|
||||
seller Organization @relation("SellerSupplyOrdersSeller", fields: [sellerId], references: [id])
|
||||
fulfillmentCenter Organization @relation("SellerSupplyOrdersFulfillment", fields: [fulfillmentCenterId], references: [id])
|
||||
supplier Organization? @relation("SellerSupplyOrdersSupplier", fields: [supplierId], references: [id])
|
||||
logisticsPartner Organization? @relation("SellerSupplyOrdersLogistics", fields: [logisticsPartnerId], references: [id])
|
||||
receivedBy User? @relation("SellerSupplyOrdersReceiver", fields: [receivedById], references: [id])
|
||||
items SellerConsumableSupplyItem[]
|
||||
|
||||
@@map("seller_consumable_supply_orders")
|
||||
}
|
||||
|
||||
model SellerConsumableSupplyItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String // связь с поставкой
|
||||
productId String // какой расходник селлера (FK: Product)
|
||||
|
||||
// === КОЛИЧЕСТВА ===
|
||||
requestedQuantity Int // запросили
|
||||
approvedQuantity Int? // поставщик одобрил
|
||||
shippedQuantity Int? // отгрузили
|
||||
receivedQuantity Int? // приняли
|
||||
defectQuantity Int? @default(0) // брак
|
||||
|
||||
// === ЦЕНЫ (видит только селлер) ===
|
||||
unitPrice Decimal @db.Decimal(10, 2) // цена за единицу от поставщика
|
||||
totalPrice Decimal @db.Decimal(12, 2) // общая стоимость
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === СВЯЗИ ===
|
||||
supplyOrder SellerConsumableSupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation("SellerSupplyItems", fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("seller_consumable_supply_items")
|
||||
}
|
||||
```
|
||||
|
||||
### 3️⃣ **GoodsSupplyOrder - Товарные поставки**
|
||||
|
||||
```prisma
|
||||
model GoodsSupplyOrder {
|
||||
// === БАЗОВЫЕ ПОЛЯ ===
|
||||
id String @id @default(cuid())
|
||||
status SupplyOrderStatusV2 @default(PENDING)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === ДАННЫЕ СЕЛЛЕРА (создатель) ===
|
||||
sellerId String // кто заказывает (FK: Organization)
|
||||
fulfillmentCenterId String // куда доставить (FK: Organization)
|
||||
requestedDeliveryDate DateTime // когда нужно
|
||||
notes String? // заметки селлера
|
||||
|
||||
// === ДАННЫЕ ПОСТАВЩИКА ===
|
||||
supplierId String? // кто поставляет (FK: Organization)
|
||||
supplierApprovedAt DateTime? // когда одобрил
|
||||
packagesCount Int? // количество грузомест
|
||||
estimatedVolume Decimal? @db.Decimal(8, 3) // объем груза в м³
|
||||
supplierContractId String? // номер договора
|
||||
supplierNotes String? // заметки поставщика
|
||||
|
||||
// === ДАННЫЕ ЛОГИСТИКИ ===
|
||||
logisticsPartnerId String? // кто везет (FK: Organization)
|
||||
estimatedDeliveryDate DateTime? // план доставки
|
||||
routeId String? // маршрут (FK: LogisticsRoute)
|
||||
logisticsCost Decimal? @db.Decimal(10, 2) // стоимость доставки
|
||||
logisticsNotes String? // заметки логистики
|
||||
|
||||
// === ДАННЫЕ ОТГРУЗКИ ===
|
||||
shippedAt DateTime? // факт отгрузки
|
||||
trackingNumber String? // номер отслеживания
|
||||
|
||||
// === ДАННЫЕ ПРИЕМКИ ===
|
||||
receivedAt DateTime? // факт приемки
|
||||
receivedById String? // кто принял (FK: User)
|
||||
actualQuantity Int? // принято количество
|
||||
defectQuantity Int? // брак
|
||||
receiptNotes String? // заметки приемки
|
||||
|
||||
// === УНИКАЛЬНЫЕ ПОЛЯ ДЛЯ ТОВАРОВ ===
|
||||
hasRecipes Boolean @default(false) // есть ли рецептуры
|
||||
totalServicesValue Decimal? @db.Decimal(12, 2) // общая стоимость услуг ФФ
|
||||
|
||||
// === СВЯЗИ ===
|
||||
seller Organization @relation("GoodsSupplyOrdersSeller", fields: [sellerId], references: [id])
|
||||
fulfillmentCenter Organization @relation("GoodsSupplyOrdersFulfillment", fields: [fulfillmentCenterId], references: [id])
|
||||
supplier Organization? @relation("GoodsSupplyOrdersSupplier", fields: [supplierId], references: [id])
|
||||
logisticsPartner Organization? @relation("GoodsSupplyOrdersLogistics", fields: [logisticsPartnerId], references: [id])
|
||||
receivedBy User? @relation("GoodsSupplyOrdersReceiver", fields: [receivedById], references: [id])
|
||||
items GoodsSupplyItem[]
|
||||
|
||||
@@map("goods_supply_orders")
|
||||
}
|
||||
|
||||
model GoodsSupplyItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String // связь с поставкой
|
||||
productId String // какой товар (FK: Product)
|
||||
|
||||
// === КОЛИЧЕСТВА ===
|
||||
requestedQuantity Int // запросили
|
||||
approvedQuantity Int? // поставщик одобрил
|
||||
shippedQuantity Int? // отгрузили
|
||||
receivedQuantity Int? // приняли
|
||||
defectQuantity Int? @default(0) // брак
|
||||
|
||||
// === ЦЕНЫ (видит только селлер) ===
|
||||
unitPrice Decimal @db.Decimal(10, 2) // цена за единицу от поставщика
|
||||
totalPrice Decimal @db.Decimal(12, 2) // общая стоимость
|
||||
|
||||
// === РЕЦЕПТУРА (JSON) ===
|
||||
recipe Json? // полная рецептура в JSON
|
||||
/*
|
||||
recipe structure:
|
||||
{
|
||||
services: string[] // ID услуг ФФ
|
||||
fulfillmentConsumables: string[] // ID расходников ФФ
|
||||
sellerConsumables: string[] // ID расходников селлера
|
||||
marketplaceCardId?: string // карточка товара
|
||||
}
|
||||
*/
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === СВЯЗИ ===
|
||||
supplyOrder GoodsSupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation("GoodsSupplyItems", fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("goods_supply_items")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛒 ТАБЛИЦЫ ПОСТАВОК НА МАРКЕТПЛЕЙСЫ
|
||||
|
||||
### 4️⃣ **OzonSupplyOrder - Поставки на Ozon**
|
||||
|
||||
```prisma
|
||||
model OzonSupplyOrder {
|
||||
// === БАЗОВЫЕ ПОЛЯ ===
|
||||
id String @id @default(cuid())
|
||||
status MarketplaceSupplyStatus @default(PLANNED)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === ДАННЫЕ ФФ (создатель) ===
|
||||
fulfillmentCenterId String // кто отгружает (FK: Organization)
|
||||
plannedShipmentDate DateTime // план отгрузки
|
||||
notes String? // заметки ФФ
|
||||
|
||||
// === СПЕЦИФИЧНЫЕ ПОЛЯ OZON ===
|
||||
ozonWarehouseId String // склад Ozon
|
||||
ozonSupplyId String? // ID поставки в системе Ozon
|
||||
ozonPostingNumber String? // номер отправления Ozon
|
||||
|
||||
// === ДАННЫЕ ОТГРУЗКИ ===
|
||||
preparedAt DateTime? // готово к отгрузке
|
||||
shippedAt DateTime? // отгружено
|
||||
trackingNumber String? // номер отслеживания
|
||||
|
||||
// === ДАННЫЕ ПРИЕМКИ МАРКЕТПЛЕЙСОМ ===
|
||||
acceptedAt DateTime? // принято Ozon
|
||||
acceptedQuantity Int? // принято количество
|
||||
rejectedQuantity Int? // отклонено
|
||||
rejectionReason String? // причина отклонения
|
||||
|
||||
// === СВЯЗИ ===
|
||||
fulfillmentCenter Organization @relation("OzonSupplyOrders", fields: [fulfillmentCenterId], references: [id])
|
||||
items OzonSupplyItem[]
|
||||
|
||||
@@map("ozon_supply_orders")
|
||||
}
|
||||
|
||||
model OzonSupplyItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String // связь с поставкой
|
||||
productId String // какой готовый продукт (FK: Product)
|
||||
|
||||
// === КОЛИЧЕСТВА ===
|
||||
plannedQuantity Int // планируется отгрузить
|
||||
preparedQuantity Int? // подготовлено
|
||||
shippedQuantity Int? // отгружено
|
||||
acceptedQuantity Int? // принято Ozon
|
||||
rejectedQuantity Int? @default(0) // отклонено
|
||||
|
||||
// === OZON СПЕЦИФИЧНЫЕ ПОЛЯ ===
|
||||
ozonProductId String? // ID товара в Ozon
|
||||
ozonSku String? // SKU в Ozon
|
||||
ozonBarcode String? // штрихкод
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === СВЯЗИ ===
|
||||
supplyOrder OzonSupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation("OzonSupplyItems", fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("ozon_supply_items")
|
||||
}
|
||||
```
|
||||
|
||||
### 5️⃣ **WildberriesSupplyOrder - Поставки на Wildberries**
|
||||
|
||||
```prisma
|
||||
model WildberriesSupplyOrder {
|
||||
// === БАЗОВЫЕ ПОЛЯ ===
|
||||
id String @id @default(cuid())
|
||||
status MarketplaceSupplyStatus @default(PLANNED)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === ДАННЫЕ ФФ (создатель) ===
|
||||
fulfillmentCenterId String // кто отгружает (FK: Organization)
|
||||
plannedShipmentDate DateTime // план отгрузки
|
||||
notes String? // заметки ФФ
|
||||
|
||||
// === СПЕЦИФИЧНЫЕ ПОЛЯ WILDBERRIES ===
|
||||
wbWarehouseId String // склад WB
|
||||
wbSupplyId String? // ID поставки в системе WB
|
||||
wbStickerId String? // ID стикера WB
|
||||
|
||||
// === ДАННЫЕ ОТГРУЗКИ ===
|
||||
preparedAt DateTime? // готово к отгрузке
|
||||
shippedAt DateTime? // отгружено
|
||||
trackingNumber String? // номер отслеживания
|
||||
|
||||
// === ДАННЫЕ ПРИЕМКИ МАРКЕТПЛЕЙСОМ ===
|
||||
acceptedAt DateTime? // принято WB
|
||||
acceptedQuantity Int? // принято количество
|
||||
rejectedQuantity Int? // отклонено
|
||||
rejectionReason String? // причина отклонения
|
||||
|
||||
// === СВЯЗИ ===
|
||||
fulfillmentCenter Organization @relation("WildberriesSupplyOrders", fields: [fulfillmentCenterId], references: [id])
|
||||
items WildberriesSupplyItem[]
|
||||
|
||||
@@map("wildberries_supply_orders")
|
||||
}
|
||||
|
||||
model WildberriesSupplyItem {
|
||||
id String @id @default(cuid())
|
||||
supplyOrderId String // связь с поставкой
|
||||
productId String // какой готовый продукт (FK: Product)
|
||||
|
||||
// === КОЛИЧЕСТВА ===
|
||||
plannedQuantity Int // планируется отгрузить
|
||||
preparedQuantity Int? // подготовлено
|
||||
shippedQuantity Int? // отгружено
|
||||
acceptedQuantity Int? // принято WB
|
||||
rejectedQuantity Int? @default(0) // отклонено
|
||||
|
||||
// === WB СПЕЦИФИЧНЫЕ ПОЛЯ ===
|
||||
wbNmId String? // Номенклатура WB
|
||||
wbSku String? // SKU в WB
|
||||
wbBarcode String? // штрихкод
|
||||
wbSize String? // размер для WB
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// === СВЯЗИ ===
|
||||
supplyOrder WildberriesSupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
|
||||
product Product @relation("WBSupplyItems", fields: [productId], references: [id])
|
||||
|
||||
@@unique([supplyOrderId, productId])
|
||||
@@map("wildberries_supply_items")
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 НОВЫЕ ENUMS
|
||||
|
||||
### **SupplyOrderStatusV2 - Статусы поставок НА фулфилмент**
|
||||
|
||||
```prisma
|
||||
enum SupplyOrderStatusV2 {
|
||||
PENDING // Ожидает одобрения поставщика
|
||||
SUPPLIER_APPROVED // Одобрено поставщиком
|
||||
LOGISTICS_CONFIRMED // Логистика подтверждена
|
||||
SHIPPED // Отгружено поставщиком
|
||||
IN_TRANSIT // В пути
|
||||
DELIVERED // Доставлено и принято
|
||||
CANCELLED // Отменено
|
||||
}
|
||||
```
|
||||
|
||||
### **MarketplaceSupplyStatus - Статусы поставок НА маркетплейсы**
|
||||
|
||||
```prisma
|
||||
enum MarketplaceSupplyStatus {
|
||||
PLANNED // Запланирована
|
||||
PREPARED // Подготовлена к отгрузке
|
||||
SHIPPED_TO_MARKETPLACE // Отгружена на маркетплейс
|
||||
ACCEPTED_BY_MARKETPLACE // Принята маркетплейсом
|
||||
CANCELLED // Отменена
|
||||
}
|
||||
```
|
||||
|
||||
### **SellerConsumableAccessRights - Права доступа к расходникам селлеров**
|
||||
|
||||
```prisma
|
||||
enum SellerConsumableAccessRights {
|
||||
SELLER_ONLY // Только селлер может использовать
|
||||
SHARED_WITH_FF // ФФ тоже может использовать (с разрешения)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 ОБНОВЛЕНИЯ СУЩЕСТВУЮЩИХ ТАБЛИЦ
|
||||
|
||||
### **Product - Добавление новых связей**
|
||||
|
||||
```prisma
|
||||
model Product {
|
||||
// ... существующие поля остаются без изменений
|
||||
|
||||
// === НОВЫЕ СВЯЗИ С ПОСТАВКАМИ V2 ===
|
||||
fulfillmentSupplyItems FulfillmentConsumableSupplyItem[] @relation("FFSupplyItems")
|
||||
sellerSupplyItems SellerConsumableSupplyItem[] @relation("SellerSupplyItems")
|
||||
goodsSupplyItems GoodsSupplyItem[] @relation("GoodsSupplyItems")
|
||||
ozonSupplyItems OzonSupplyItem[] @relation("OzonSupplyItems")
|
||||
wildberriesSupplyItems WildberriesSupplyItem[] @relation("WBSupplyItems")
|
||||
|
||||
// ... остальные поля остаются без изменений
|
||||
}
|
||||
```
|
||||
|
||||
### **Organization - Добавление новых связей**
|
||||
|
||||
```prisma
|
||||
model Organization {
|
||||
// ... существующие поля остаются без изменений
|
||||
|
||||
// === НОВЫЕ СВЯЗИ С ПОСТАВКАМИ V2 ===
|
||||
// Поставки расходников ФФ
|
||||
fulfillmentSupplyOrdersAsFulfillment FulfillmentConsumableSupplyOrder[] @relation("FFSupplyOrdersFulfillment")
|
||||
fulfillmentSupplyOrdersAsSupplier FulfillmentConsumableSupplyOrder[] @relation("FFSupplyOrdersSupplier")
|
||||
fulfillmentSupplyOrdersAsLogistics FulfillmentConsumableSupplyOrder[] @relation("FFSupplyOrdersLogistics")
|
||||
|
||||
// Поставки расходников селлеров
|
||||
sellerSupplyOrdersAsSeller SellerConsumableSupplyOrder[] @relation("SellerSupplyOrdersSeller")
|
||||
sellerSupplyOrdersAsFulfillment SellerConsumableSupplyOrder[] @relation("SellerSupplyOrdersFulfillment")
|
||||
sellerSupplyOrdersAsSupplier SellerConsumableSupplyOrder[] @relation("SellerSupplyOrdersSupplier")
|
||||
sellerSupplyOrdersAsLogistics SellerConsumableSupplyOrder[] @relation("SellerSupplyOrdersLogistics")
|
||||
|
||||
// Товарные поставки
|
||||
goodsSupplyOrdersAsSeller GoodsSupplyOrder[] @relation("GoodsSupplyOrdersSeller")
|
||||
goodsSupplyOrdersAsFulfillment GoodsSupplyOrder[] @relation("GoodsSupplyOrdersFulfillment")
|
||||
goodsSupplyOrdersAsSupplier GoodsSupplyOrder[] @relation("GoodsSupplyOrdersSupplier")
|
||||
goodsSupplyOrdersAsLogistics GoodsSupplyOrder[] @relation("GoodsSupplyOrdersLogistics")
|
||||
|
||||
// Поставки на маркетплейсы
|
||||
ozonSupplyOrders OzonSupplyOrder[] @relation("OzonSupplyOrders")
|
||||
wildberriesSupplyOrders WildberriesSupplyOrder[] @relation("WildberriesSupplyOrders")
|
||||
|
||||
// ... остальные поля остаются без изменений
|
||||
}
|
||||
```
|
||||
|
||||
### **User - Добавление новых связей**
|
||||
|
||||
```prisma
|
||||
model User {
|
||||
// ... существующие поля остаются без изменений
|
||||
|
||||
// === НОВЫЕ СВЯЗИ С ПРИЕМКОЙ ПОСТАВОК V2 ===
|
||||
fulfillmentSupplyOrdersReceived FulfillmentConsumableSupplyOrder[] @relation("FFSupplyOrdersReceiver")
|
||||
sellerSupplyOrdersReceived SellerConsumableSupplyOrder[] @relation("SellerSupplyOrdersReceiver")
|
||||
goodsSupplyOrdersReceived GoodsSupplyOrder[] @relation("GoodsSupplyOrdersReceiver")
|
||||
|
||||
// ... остальные поля остаются без изменений
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 ИНДЕКСЫ ДЛЯ ПРОИЗВОДИТЕЛЬНОСТИ
|
||||
|
||||
```prisma
|
||||
// Индексы для быстрого поиска поставок по статусу и организации
|
||||
@@index([fulfillmentCenterId, status])
|
||||
@@index([sellerId, status])
|
||||
@@index([supplierId, status])
|
||||
@@index([logisticsPartnerId, status])
|
||||
|
||||
// Индексы для поиска по датам
|
||||
@@index([createdAt])
|
||||
@@index([requestedDeliveryDate])
|
||||
@@index([estimatedDeliveryDate])
|
||||
|
||||
// Индексы для отслеживания
|
||||
@@index([trackingNumber])
|
||||
@@index([supplierContractId])
|
||||
|
||||
// Маркетплейс-специфичные индексы
|
||||
@@index([ozonSupplyId])
|
||||
@@index([ozonProductId])
|
||||
@@index([wbSupplyId])
|
||||
@@index([wbNmId])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 ПЛАН МИГРАЦИИ
|
||||
|
||||
### **Phase 1: Создание новых таблиц**
|
||||
```sql
|
||||
-- Создание таблиц параллельно с существующими
|
||||
CREATE TABLE fulfillment_consumable_supply_orders (...);
|
||||
CREATE TABLE fulfillment_consumable_supply_items (...);
|
||||
-- и т.д.
|
||||
```
|
||||
|
||||
### **Phase 2: Новые enum значения**
|
||||
```sql
|
||||
-- Добавление новых enum без затрагивания старых
|
||||
CREATE TYPE "SupplyOrderStatusV2" AS ENUM (...);
|
||||
CREATE TYPE "MarketplaceSupplyStatus" AS ENUM (...);
|
||||
```
|
||||
|
||||
### **Phase 3: Обновление связей (без удаления старых)**
|
||||
```sql
|
||||
-- Добавление новых foreign key связей
|
||||
ALTER TABLE "Product" ADD COLUMN ...;
|
||||
ALTER TABLE "Organization" ADD COLUMN ...;
|
||||
```
|
||||
|
||||
### **Phase 4: Данные миграции (только с одобрения)**
|
||||
```sql
|
||||
-- Миграция данных из старых таблиц в новые
|
||||
-- ТОЛЬКО после полного тестирования новой системы
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ ВАЖНЫЕ ПРИНЦИПЫ
|
||||
|
||||
### ✅ **ОБРАТНАЯ СОВМЕСТИМОСТЬ**
|
||||
- Все существующие таблицы остаются без изменений
|
||||
- Новые таблицы создаются параллельно
|
||||
- Старая система продолжает работать
|
||||
|
||||
### 🔒 **БЕЗОПАСНОСТЬ ДАННЫХ**
|
||||
- Каждый тип поставки изолирован в отдельной таблице
|
||||
- Связи защищены foreign key constraints
|
||||
- Каскадное удаление только для зависимых записей
|
||||
|
||||
### 📈 **МАСШТАБИРУЕМОСТЬ**
|
||||
- Легко добавлять новые типы поставок
|
||||
- Оптимизированные индексы для каждого use case
|
||||
- Независимые схемы для разных процессов
|
||||
|
||||
### 🛡️ **ЦЕЛОСТНОСТЬ ДАННЫХ**
|
||||
- Строгие ограничения на связи между таблицами
|
||||
- Валидация через enum значения
|
||||
- Уникальные индексы предотвращают дублирование
|
||||
|
||||
**Следующий шаг:** Создание Prisma миграций для FulfillmentConsumableSupplyOrder
|
Reference in New Issue
Block a user