Files
sfera-new/docs/business-processes/SUPPLY_SYSTEM_ARCHITECTURE.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

20 KiB
Raw Permalink Blame History

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

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

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

📦 ПОСТАВКИ НА ФУЛФИЛМЕНТ (3 типа)

  1. Товарные поставки - товары селлера → склад ФФ
  2. Поставки расходников ФФ - расходники ФФ → склад ФФ
  3. Поставки расходников селлеров - расходники селлера → склад ФФ (на хранение)

🛒 ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ (2+ типов)

  1. Поставки на Ozon - готовые продукты со склада ФФ → Ozon
  2. Поставки на Wildberries - готовые продукты со склада ФФ → Wildberries

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

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

Преимущества подхода:

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

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

1. GoodsSupplyOrder - Товарные поставки

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 - Поставки расходников ФФ

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 - Поставки расходников селлеров

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

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

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 АРХИТЕКТУРА

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

Поставки расходников ФФ:

# Queries
myFulfillmentConsumableSupplies: [FulfillmentConsumableSupplyOrder!]!
fulfillmentConsumableSupply(id: ID!): FulfillmentConsumableSupplyOrder

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

Поставки расходников селлеров:

# Queries
mySellerConsumableSupplies: [SellerConsumableSupplyOrder!]!
sellerConsumableSupply(id: ID!): SellerConsumableSupplyOrder

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

Товарные поставки:

# Queries
myGoodsSupplies: [GoodsSupplyOrder!]!
goodsSupply(id: ID!): GoodsSupplyOrder

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

Поставки на маркетплейсы (отдельная система):

# Queries
myOzonSupplies: [OzonSupplyOrder!]!
myWildberriesSupplies: [WildberriesSupplyOrder!]!

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

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

ПРИНЦИПЫ БЕЗОПАСНОЙ МИГРАЦИИ

  • 🛡️ Сохранение работоспособности существующей системы
  • 🔄 Система откатов на каждом этапе
  • 🧪 Тестирование каждого типа поставки отдельно
  • 📝 Модульная архитектура
  • Удаление старого кода ТОЛЬКО после одобрения пользователя

ЭТАП 1: FulfillmentConsumableSupplyOrder

1.1 Создание новой модели данных

// Новая таблица параллельно со старой
model FulfillmentConsumableSupplyOrder {
  // ... вся структура
}

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

1.2 GraphQL API

# Новые операции
createFulfillmentConsumableSupply()
myFulfillmentConsumableSupplies()

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

1.3 Интерфейс

  • Форма /fulfillment-supplies/create-consumables → новая мутация
  • Вкладка /fulfillment-supplies/ff-consumables → новый запрос

1.4 Тестирование

  • Создание поставки расходников ФФ
  • Отображение в интерфейсе
  • Безопасность доступа
  • Работа старой системы

ЭТАП 2: SellerConsumableSupplyOrder

  • Аналогично этапу 1
  • Тестирование + интеграция

ЭТАП 3: GoodsSupplyOrder

  • Аналогично этапу 1
  • Тестирование + интеграция

ЭТАП 4: Очистка (ТОЛЬКО после одобрения)

  • Миграция данных из старых таблиц
  • Удаление старого кода
  • Обновление документации

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

SupplyOrderStatus (для поставок НА фулфилмент)

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

MarketplaceSupplyStatus (для поставок НА маркетплейсы)

enum MarketplaceSupplyStatus {
  PLANNED                // Запланирована
  PREPARED              // Подготовлена к отгрузке
  SHIPPED_TO_MARKETPLACE // Отгружена на маркетплейс
  ACCEPTED_BY_MARKETPLACE // Принята маркетплейсом
  CANCELLED             // Отменена
}

📊 ИНТЕГРАЦИИ

Поставки НА фулфилмент:

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

Поставки НА маркетплейсы:

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

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

Коммерческие данные:

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

Операционные метрики:

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

ЗАКЛЮЧЕНИЕ

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

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

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