# 🚚 АРХИТЕКТУРА СИСТЕМЫ ПОСТАВОК SFERA

## 🎯 ОБЗОР СИСТЕМЫ

Система поставок SFERA включает **5 типов поставок**, разделенных на две категории:

### 📦 **ПОСТАВКИ НА ФУЛФИЛМЕНТ (3 типа)**
1. **Товарные поставки** - товары селлера → склад ФФ
2. **Поставки расходников ФФ** - расходники ФФ → склад ФФ  
3. **Поставки расходников селлеров** - расходники селлера → склад ФФ (на хранение)

### 🛒 **ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ (2+ типов)**
4. **Поставки на Ozon** - готовые продукты со склада ФФ → Ozon
5. **Поставки на Wildberries** - готовые продукты со склада ФФ → Wildberries

---

## 📊 АРХИТЕКТУРА ДАННЫХ

### ✅ **ПРИНЦИП: ОТДЕЛЬНАЯ ТАБЛИЦА ДЛЯ КАЖДОГО ТИПА ПОСТАВКИ**

#### **Преимущества подхода:**
- 🎯 Четкое разделение ответственности
- 🔒 Упрощение системы безопасности
- 📈 Независимые схемы для разных процессов
- 🔧 Простота миграций и изменений
- 📝 Специфичные поля для каждого типа

### 🏗️ **СТРУКТУРА ТАБЛИЦ ПОСТАВОК НА ФУЛФИЛМЕНТ**

#### **1. GoodsSupplyOrder - Товарные поставки**
```typescript
interface GoodsSupplyOrder {
  // === БАЗОВЫЕ ПОЛЯ ===
  id: string
  status: SupplyOrderStatus
  createdAt: DateTime
  updatedAt: DateTime
  
  // === ДАННЫЕ СЕЛЛЕРА (создатель) ===
  sellerId: string                   // кто заказывает
  fulfillmentCenterId: string        // куда доставить
  requestedDeliveryDate: DateTime    // когда нужно
  
  // === ДАННЫЕ ПОСТАВЩИКА ===
  supplierId: string                 // кто поставляет
  supplierApprovedAt?: DateTime      // когда одобрил
  packagesCount?: number             // количество грузомест
  estimatedVolume?: number           // объем груза
  supplierContractId?: string        // номер договора
  
  // === ДАННЫЕ ЛОГИСТИКИ ===
  logisticsPartnerId?: string        // кто везет
  estimatedDeliveryDate?: DateTime   // план доставки
  routeId?: string                   // маршрут
  logisticsCost?: number             // стоимость доставки
  
  // === ДАННЫЕ ОТГРУЗКИ ===
  shippedAt?: DateTime               // факт отгрузки
  
  // === ДАННЫЕ ПРИЕМКИ ===
  receivedAt?: DateTime              // факт приемки
  receivedById?: string              // кто принял (сотрудник ФФ)
  actualQuantity?: number            // принято количество
  defectQuantity?: number            // брак
  
  // === УНИКАЛЬНЫЕ ПОЛЯ ДЛЯ ТОВАРОВ ===
  hasRecipes: boolean                // есть ли рецептуры
  totalServicesValue?: number        // стоимость услуг ФФ
  
  // === СВЯЗИ ===
  items: GoodsSupplyItem[]
}

interface GoodsSupplyItem {
  id: string
  supplyOrderId: string              // связь с поставкой
  productId: string                  // какой товар
  requestedQuantity: number          // запросили
  approvedQuantity?: number          // поставщик одобрил
  shippedQuantity?: number           // отгрузили
  receivedQuantity?: number          // приняли
  defectQuantity?: number            // брак
  unitPrice: number                  // цена за единицу
  totalPrice: number                 // общая стоимость
  
  // === РЕЦЕПТУРА (JSON) ===
  recipe?: {
    services: string[]                    // ID услуг ФФ
    fulfillmentConsumables: string[]      // ID расходников ФФ  
    sellerConsumables: string[]           // ID расходников селлера
    marketplaceCardId?: string            // карточка товара
  }
}
```

#### **2. FulfillmentConsumableSupplyOrder - Поставки расходников ФФ**
```typescript
interface FulfillmentConsumableSupplyOrder {
  // === БАЗОВЫЕ ПОЛЯ ===
  id: string
  status: SupplyOrderStatus
  createdAt: DateTime
  updatedAt: DateTime
  
  // === ДАННЫЕ ФФ (создатель) ===
  fulfillmentCenterId: string        // кто заказывает
  requestedDeliveryDate: DateTime    // когда нужно
  
  // === ДАННЫЕ ПОСТАВЩИКА ===
  supplierId: string                 // кто поставляет
  supplierApprovedAt?: DateTime      // когда одобрил
  packagesCount?: number             // количество грузомест
  estimatedVolume?: number           // объем груза
  supplierContractId?: string        // номер договора
  
  // === ДАННЫЕ ЛОГИСТИКИ ===
  logisticsPartnerId?: string        // кто везет
  estimatedDeliveryDate?: DateTime   // план доставки
  routeId?: string                   // маршрут
  logisticsCost?: number             // стоимость доставки
  
  // === ДАННЫЕ ОТГРУЗКИ ===
  shippedAt?: DateTime               // факт отгрузки
  
  // === ДАННЫЕ ПРИЕМКИ ===
  receivedAt?: DateTime              // факт приемки
  receivedById?: string              // кто принял (сотрудник ФФ)
  actualQuantity?: number            // принято количество
  defectQuantity?: number            // брак
  
  // === УНИКАЛЬНЫЕ ПОЛЯ ДЛЯ РАСХОДНИКОВ ФФ ===
  resalePricePerUnit?: number        // цена продажи селлерам
  minStockLevel?: number             // складские лимиты
  
  // === СВЯЗИ ===
  items: FulfillmentConsumableSupplyItem[]
}

interface FulfillmentConsumableSupplyItem {
  id: string
  supplyOrderId: string              // связь с поставкой
  productId: string                  // какой расходник
  requestedQuantity: number          // запросили
  approvedQuantity?: number          // поставщик одобрил
  shippedQuantity?: number           // отгрузили
  receivedQuantity?: number          // приняли
  defectQuantity?: number            // брак
  unitPrice: number                  // цена за единицу от поставщика
  totalPrice: number                 // общая стоимость
}
```

#### **3. SellerConsumableSupplyOrder - Поставки расходников селлеров**
```typescript
interface SellerConsumableSupplyOrder {
  // === БАЗОВЫЕ ПОЛЯ ===
  id: string
  status: SupplyOrderStatus
  createdAt: DateTime
  updatedAt: DateTime
  
  // === ДАННЫЕ СЕЛЛЕРА (создатель) ===
  sellerId: string                   // кто заказывает
  fulfillmentCenterId: string        // где будет храниться
  requestedDeliveryDate: DateTime    // когда нужно
  
  // === ДАННЫЕ ПОСТАВЩИКА ===
  supplierId: string                 // кто поставляет
  supplierApprovedAt?: DateTime      // когда одобрил
  packagesCount?: number             // количество грузомест
  estimatedVolume?: number           // объем груза
  supplierContractId?: string        // номер договора
  
  // === ДАННЫЕ ЛОГИСТИКИ ===
  logisticsPartnerId?: string        // кто везет
  estimatedDeliveryDate?: DateTime   // план доставки
  routeId?: string                   // маршрут
  logisticsCost?: number             // стоимость доставки
  
  // === ДАННЫЕ ОТГРУЗКИ ===
  shippedAt?: DateTime               // факт отгрузки
  
  // === ДАННЫЕ ПРИЕМКИ ===
  receivedAt?: DateTime              // факт приемки ФФ
  receivedById?: string              // кто принял (сотрудник ФФ)
  actualQuantity?: number            // принято количество
  defectQuantity?: number            // брак
  
  // === УНИКАЛЬНЫЕ ПОЛЯ ДЛЯ РАСХОДНИКОВ СЕЛЛЕРОВ ===
  storageTermMonths?: number         // срок хранения
  accessRights: 'SELLER_ONLY' | 'SHARED_WITH_FF'  // кто может использовать
  storageCostPerMonth?: number       // стоимость хранения
  
  // === СВЯЗИ ===
  items: SellerConsumableSupplyItem[]
}

interface SellerConsumableSupplyItem {
  id: string
  supplyOrderId: string              // связь с поставкой
  productId: string                  // какой расходник селлера
  requestedQuantity: number          // запросили
  approvedQuantity?: number          // поставщик одобрил
  shippedQuantity?: number           // отгрузили
  receivedQuantity?: number          // приняли
  defectQuantity?: number            // брак
  unitPrice: number                  // цена за единицу
  totalPrice: number                 // общая стоимость
}
```

### 🛒 **СТРУКТУРА ТАБЛИЦ ПОСТАВОК НА МАРКЕТПЛЕЙСЫ**

#### **4. OzonSupplyOrder - Поставки на Ozon**
```typescript
interface OzonSupplyOrder {
  // === БАЗОВЫЕ ПОЛЯ ===
  id: string
  status: MarketplaceSupplyStatus
  createdAt: DateTime
  updatedAt: DateTime
  
  // === СПЕЦИФИЧНЫЕ ПОЛЯ OZON ===
  ozonWarehouseId: string            // склад Ozon
  ozonSupplyId?: string              // ID поставки в системе Ozon
  // ... дополнительные поля для Ozon API
  
  // === СВЯЗИ ===
  items: OzonSupplyItem[]
}
```

#### **5. WildberriesSupplyOrder - Поставки на Wildberries**
```typescript
interface WildberriesSupplyOrder {
  // === БАЗОВЫЕ ПОЛЯ ===
  id: string
  status: MarketplaceSupplyStatus
  createdAt: DateTime
  updatedAt: DateTime
  
  // === СПЕЦИФИЧНЫЕ ПОЛЯ WB ===
  wbWarehouseId: string              // склад WB
  wbSupplyId?: string                // ID поставки в системе WB
  // ... дополнительные поля для WB API
  
  // === СВЯЗИ ===
  items: WildberriesSupplyItem[]
}
```

---

## 🔐 СИСТЕМА БЕЗОПАСНОСТИ

### 📋 **ПРАВИЛА ДОСТУПА К ПОСТАВКАМ РАСХОДНИКОВ ФФ**

**Кто видит и что:**
- ✅ **ФФ (создатель):** все детали + цены + остатки  
- ✅ **Поставщик:** товары, количества, НЕ цены продажи ФФ
- ✅ **Логистика:** маршруты, объемы, НЕ коммерческие данные
- ❌ **Селлеры:** вообще не видят

### 📋 **ПРАВИЛА ДОСТУПА К ПОСТАВКАМ РАСХОДНИКОВ СЕЛЛЕРОВ**

**Кто видит и что:**
- ✅ **Селлер (создатель):** все свои детали + свои цены
- ✅ **ФФ (хранитель):** факт хранения + количества, НЕ закупочные цены селлера
- ✅ **Поставщик:** товары, количества для селлера  
- ✅ **Логистика:** маршруты, объемы
- ❌ **Другие селлеры:** не видят чужие расходники

### 📋 **ПРАВИЛА ДОСТУПА К ТОВАРНЫМ ПОСТАВКАМ**

**Кто видит и что:**
- ✅ **Селлер (создатель):** все детали своих товаров + рецептуры
- ✅ **ФФ (получатель):** товары + рецептуры + услуги, НЕ закупочные цены селлера
- ✅ **Поставщик:** товары + количества, НЕ рецептуры и НЕ цены ФФ
- ✅ **Логистика:** маршруты + объемы, НЕ коммерческие данные
- ❌ **Другие селлеры:** не видят чужие поставки

---

## 🌐 URL-СТРУКТУРА ИНТЕРФЕЙСОВ

### 📦 **ПОСТАВКИ НА ФУЛФИЛМЕНТ**
```
/fulfillment-supplies/goods?status=new          # Товар → Новые
/fulfillment-supplies/goods?status=receiving    # Товар → Приёмка  
/fulfillment-supplies/goods?status=accepted     # Товар → Принято
/fulfillment-supplies/ff-consumables            # Расходники фулфилмента
/fulfillment-supplies/seller-consumables        # Расходники селлеров
/fulfillment-supplies/create-consumables        # Создание поставки расходников ФФ
```

### 🛒 **ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ**
```
/marketplace-supplies/ozon                      # Поставки на Ozon
/marketplace-supplies/wildberries               # Поставки на Wildberries
/marketplace-supplies/create-ozon               # Создание поставки на Ozon
/marketplace-supplies/create-wildberries        # Создание поставки на WB
```

---

## ⚡ GRAPHQL API АРХИТЕКТУРА

### 🎯 **ПРИНЦИП: ОТДЕЛЬНЫЕ ОПЕРАЦИИ ДЛЯ КАЖДОГО ТИПА**

#### **Поставки расходников ФФ:**
```graphql
# Queries
myFulfillmentConsumableSupplies: [FulfillmentConsumableSupplyOrder!]!
fulfillmentConsumableSupply(id: ID!): FulfillmentConsumableSupplyOrder

# Mutations  
createFulfillmentConsumableSupply(input: CreateFulfillmentConsumableSupplyInput!): CreateSupplyResult!
updateFulfillmentConsumableSupply(id: ID!, input: UpdateFulfillmentConsumableSupplyInput!): UpdateSupplyResult!
```

#### **Поставки расходников селлеров:**
```graphql
# Queries
mySellerConsumableSupplies: [SellerConsumableSupplyOrder!]!
sellerConsumableSupply(id: ID!): SellerConsumableSupplyOrder

# Mutations
createSellerConsumableSupply(input: CreateSellerConsumableSupplyInput!): CreateSupplyResult!
updateSellerConsumableSupply(id: ID!, input: UpdateSellerConsumableSupplyInput!): UpdateSupplyResult!
```

#### **Товарные поставки:**
```graphql  
# Queries
myGoodsSupplies: [GoodsSupplyOrder!]!
goodsSupply(id: ID!): GoodsSupplyOrder

# Mutations
createGoodsSupply(input: CreateGoodsSupplyInput!): CreateSupplyResult!
updateGoodsSupply(id: ID!, input: UpdateGoodsSupplyInput!): UpdateSupplyResult!
```

#### **Поставки на маркетплейсы (отдельная система):**
```graphql
# Queries
myOzonSupplies: [OzonSupplyOrder!]!
myWildberriesSupplies: [WildberriesSupplyOrder!]!

# Mutations
createOzonSupply(input: CreateOzonSupplyInput!): CreateMarketplaceSupplyResult!
createWildberriesSupply(input: CreateWildberriesSupplyInput!): CreateMarketplaceSupplyResult!
```

---

## 🔄 ПЛАН ПОЭТАПНОЙ МИГРАЦИИ

### ✅ **ПРИНЦИПЫ БЕЗОПАСНОЙ МИГРАЦИИ**
- 🛡️ Сохранение работоспособности существующей системы
- 🔄 Система откатов на каждом этапе
- 🧪 Тестирование каждого типа поставки отдельно
- 📝 Модульная архитектура
- ❌ **Удаление старого кода ТОЛЬКО после одобрения пользователя**

### **ЭТАП 1: FulfillmentConsumableSupplyOrder**

#### **1.1 Создание новой модели данных**
```typescript
// Новая таблица параллельно со старой
model FulfillmentConsumableSupplyOrder {
  // ... вся структура
}

// Старая таблица остается для совместимости
model SupplyOrder {
  // ... существующая структура
}
```

#### **1.2 GraphQL API**
```graphql  
# Новые операции
createFulfillmentConsumableSupply()
myFulfillmentConsumableSupplies()

# Старые операции остаются работать
createSupplyOrder() # для других типов
mySupplyOrders()   # для других типов
```

#### **1.3 Интерфейс**
- Форма `/fulfillment-supplies/create-consumables` → новая мутация
- Вкладка `/fulfillment-supplies/ff-consumables` → новый запрос

#### **1.4 Тестирование**
- ✅ Создание поставки расходников ФФ
- ✅ Отображение в интерфейсе
- ✅ Безопасность доступа
- ✅ Работа старой системы

### **ЭТАП 2: SellerConsumableSupplyOrder**
- Аналогично этапу 1
- Тестирование + интеграция

### **ЭТАП 3: GoodsSupplyOrder**  
- Аналогично этапу 1
- Тестирование + интеграция

### **ЭТАП 4: Очистка (ТОЛЬКО после одобрения)**
- Миграция данных из старых таблиц
- Удаление старого кода
- Обновление документации

---

## 🎯 СТАТУСЫ ПОСТАВОК

### **SupplyOrderStatus (для поставок НА фулфилмент)**
```typescript
enum SupplyOrderStatus {
  PENDING                 // Создана, ждет одобрения поставщика
  SUPPLIER_APPROVED       // Одобрена поставщиком
  LOGISTICS_CONFIRMED     // Логистика подтверждена
  SHIPPED                 // Отгружена поставщиком
  IN_TRANSIT             // В пути
  DELIVERED              // Доставлена на склад ФФ
  CANCELLED              // Отменена
}
```

### **MarketplaceSupplyStatus (для поставок НА маркетплейсы)**
```typescript  
enum MarketplaceSupplyStatus {
  PLANNED                // Запланирована
  PREPARED              // Подготовлена к отгрузке
  SHIPPED_TO_MARKETPLACE // Отгружена на маркетплейс
  ACCEPTED_BY_MARKETPLACE // Принята маркетплейсом
  CANCELLED             // Отменена
}
```

---

## 📊 ИНТЕГРАЦИИ

### **Поставки НА фулфилмент:**
- 🏪 **DaData API** - валидация ИНН поставщиков
- 📱 **SMS Aero** - уведомления участникам
- ☁️ **AWS S3** - документы поставок
- 🚚 **Логистические партнеры** - трекинг доставки

### **Поставки НА маркетплейсы:**
- 🛒 **Ozon API** - создание поставок
- 🛍️ **Wildberries API** - создание поставок  
- 📦 **Трекинг системы** - статусы доставки
- 💰 **Биллинг системы** - расчет комиссий

---

## 🔍 МОНИТОРИНГ И АУДИТ

### **Коммерческие данные:**
- 📊 Логирование доступа к ценам
- 🔐 Аудит прав доступа по ролям  
- 📈 Метрики безопасности
- ⚠️ Алерты на подозрительную активность

### **Операционные метрики:**
- ⏱️ Время выполнения поставок
- 📦 Процент успешных доставок
- 🔄 SLA по статусам
- 📊 Аналитика по типам поставок

---

## ✅ ЗАКЛЮЧЕНИЕ

Новая архитектура системы поставок обеспечивает:

- 🎯 **Четкое разделение** типов поставок
- 🔒 **Надежную безопасность** коммерческих данных  
- 📈 **Масштабируемость** для новых маркетплейсов
- 🔧 **Простоту развития** каждого типа независимо
- 🛡️ **Безопасную миграцию** без потери данных

**Следующий шаг:** Поэтапная реализация начиная с `FulfillmentConsumableSupplyOrder`