Files
sfera-new/docs/development/DATABASE_SCHEMA_V2.md
Veronika Smirnova 0e3ffc179c 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>
2025-08-25 07:52:46 +03:00

600 lines
33 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🗄️ СХЕМА БАЗЫ ДАННЫХ 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