# ДОМЕН ПОСТАВЩИКОВ (WHOLESALE)

## 🎯 РОЛЬ В ЭКОСИСТЕМЕ SFERA

**Поставщик (Wholesale)** - оптовая организация, поставляющая товары и расходники для селлеров и фулфилмент-центров. Центральное звено в цепочке поставок системы.

### КЛЮЧЕВЫЕ ФУНКЦИИ:

- ✅ Поставка товаров для продажи селлерам
- ✅ Поставка расходников фулфилмент-центрам
- ✅ Управление каталогом товаров и услуг
- ✅ Обработка входящих заказов поставок
- ✅ Логистическая координация отгрузок

## 🏢 БИЗНЕС-МОДЕЛЬ ПОСТАВЩИКА

### 1. ЭКОНОМИЧЕСКАЯ МОДЕЛЬ

```typescript
enum WholesaleEconomics {
  REVENUE = {
    PRODUCT_SALES: 'Продажа товаров селлерам', // Основной доход
    CONSUMABLES_SALES: 'Продажа расходников ФФ', // Дополнительный доход
    BULK_DISCOUNTS: 'Оптовые скидки за объем', // Увеличение маржи
    LONG_TERM_CONTRACTS: 'Долгосрочные контракты', // Стабильный доход
  },

  COSTS = {
    PROCUREMENT: 'Закупка товаров у производителей', // Основные затраты
    WAREHOUSE_OPERATIONS: 'Складские операции', // Хранение и обработка
    LOGISTICS: 'Доставка к клиентам', // Транспортные расходы
    QUALITY_CONTROL: 'Контроль качества', // Проверка товаров
  },
}
```

### 2. ПАРТНЕРСКИЕ СВЯЗИ

```mermaid
graph TD
    A[WHOLESALE] --> B[SELLER - Основные клиенты]
    A --> C[FULFILLMENT - Клиенты расходников]
    A --> D[LOGIST - Логистические партнеры]

    B --> E[Заказывают товары для продажи]
    C --> F[Заказывают расходники для операций]
    D --> G[Доставляют товары к получателям]

    H[ПРОИЗВОДИТЕЛИ] --> A
    H --> I[Поставляют товары оптовикам]
```

## 📦 УПРАВЛЕНИЕ КАТАЛОГОМ ТОВАРОВ

### ТИПЫ ПОСТАВЛЯЕМОЙ ПРОДУКЦИИ:

```typescript
interface WholesaleProducts {
  // Товары для селлеров (для перепродажи)
  sellerGoods: {
    type: 'ProductType.PRODUCT'
    purpose: 'Товары для продажи на маркетплейсах'
    buyers: ['SELLER']
    storage: 'Временно у поставщика → фулфилмент → маркетплейс'
  }

  // Расходники для фулфилмента
  fulfillmentConsumables: {
    type: 'SupplyType.FULFILLMENT_CONSUMABLES'
    purpose: 'Материалы для операций ФФ'
    buyers: ['FULFILLMENT']
    storage: 'Склад фулфилмента'
  }

  // Расходники для селлеров (компоненты рецептур)
  sellerConsumables: {
    type: 'SupplyType.SELLER_CONSUMABLES'
    purpose: 'Компоненты рецептур продуктов селлера'
    buyers: ['SELLER']
    storage: 'Склад фулфилмента (под селлера)'
  }
}
```

### КАТАЛОГ И ПОИСК:

```typescript
// GraphQL запросы каталога поставщика
const wholesaleCatalog = {
  // Публичный каталог (для всех)
  allProducts: `
    query AllProducts($search: String, $category: String) {
      allProducts(search: $search, category: $category) {
        id, name, price, category
        organization { type } # Только от WHOLESALE
      }
    }
  `,

  // Товары конкретного поставщика
  organizationProducts: `
    query OrganizationProducts($organizationId: ID!, $search: String, $type: String) {
      organizationProducts(
        organizationId: $organizationId, 
        search: $search,
        type: $type
      ) {
        id, name, article, price, quantity
      }
    }
  `,
}
```

**Ограничения доступа:**

```typescript
// Из resolvers.ts - контроль доступа
const catalogAccess = {
  rule: 'Только товары поставщиков в публичном каталоге',

  filter: `
    organizations: {
      type: 'WHOLESALE' // Только товары поставщиков
    }
  `,

  validation: `
    if (currentUser.organization.type !== 'WHOLESALE') {
      throw new GraphQLError('Только поставщики могут управлять каталогом')
    }
  `,
}
```

## 🔄 WORKFLOW ПОСТАВОК ДЛЯ ПОСТАВЩИКОВ

### РОЛЬ В 8-СТАТУСНОЙ СИСТЕМЕ:

#### 1. ОБРАБОТКА ВХОДЯЩИХ ЗАКАЗОВ:

```typescript
// Поставщик получает входящие заказы от селлеров/ФФ
interface IncomingSupplierOrders {
  role: 'Получатель заказов поставок'

  // Из кода resolvers.ts
  query: `
    const incomingSupplierOrders = await prisma.supplyOrder.count({
      where: {
        partnerId: currentUser.organization.id, // Мы - поставщик
        status: 'PENDING' // Ожидает подтверждения от поставщика
      }
    })
  `

  responsibilities: [
    'Проверить наличие товаров на складе',
    'Подтвердить возможность поставки',
    'Указать сроки готовности к отгрузке',
    'Отклонить заказ при невозможности выполнения',
  ]
}
```

#### 2. ПЕРЕХОДЫ СТАТУСОВ ПОД КОНТРОЛЕМ ПОСТАВЩИКА:

```typescript
const wholesaleStatusControl = {
  // Поставщик подтверждает заказ
  'PENDING → SUPPLIER_APPROVED': {
    action: 'approveSupplyOrder',
    validation: 'Проверка наличия товаров',
    nextStep: 'Ожидание подтверждения логистики',
  },

  // Поставщик отгружает товар
  'LOGISTICS_CONFIRMED → SHIPPED': {
    action: 'shipSupplyOrder',
    validation: 'Подготовка товаров к отгрузке',
    nextStep: 'Товар в пути к получателю',
  },

  // Поставщик может отменить на любом этапе
  'ANY_STATUS → CANCELLED': {
    action: 'cancelSupplyOrder',
    reasons: ['Нет товаров', 'Технические проблемы', 'Изменение планов'],
  },
}
```

### DASHBOARD СЧЕТЧИКИ:

```typescript
// Из pendingSuppliesCount - что видит поставщик
const wholesaleCounters = {
  // Основной счетчик для поставщиков
  incomingSupplierOrders: 'Входящие заказы требующие подтверждения',

  // Поставщик не видит:
  logisticsOrders: 0, // Это для логистики
  ourSupplyOrders: 0, // Это для инициаторов заказов
  sellerSupplyOrders: 0, // Это для фулфилмента

  // Приоритет для поставщика:
  pendingSupplyOrders: '= incomingSupplierOrders', // Главный показатель
}
```

## 🏭 СКЛАДСКИЕ И ЛОГИСТИЧЕСКИЕ ОПЕРАЦИИ

### 1. УПРАВЛЕНИЕ ЗАПАСАМИ:

```typescript
interface WholesaleInventory {
  // Товарные остатки
  inventory: {
    tracking: 'currentStock, minStock, usedStock'
    replenishment: 'Заказы у производителей'
    allocation: 'Резервирование под заказы'
  }

  // Планирование поставок
  planning: {
    leadTime: 'Срок подготовки товаров к отгрузке'
    batchSizes: 'Минимальные партии отгрузки'
    seasonality: 'Сезонные колебания спроса'
  }

  // Качество товаров
  qualityControl: {
    incoming: 'Контроль при приемке от производителей'
    storage: 'Контроль условий хранения'
    outgoing: 'Проверка перед отгрузкой клиентам'
  }
}
```

### 2. КООРДИНАЦИЯ С ЛОГИСТИКОЙ:

```typescript
interface WholesaleLogistics {
  // Подготовка к отгрузке
  preparation: {
    status: 'LOGISTICS_CONFIRMED'
    actions: ['Комплектование заказа', 'Упаковка товаров', 'Подготовка документов', 'Ожидание логистики']
  }

  // Передача логистике
  handover: {
    status: 'LOGISTICS_CONFIRMED → SHIPPED'
    process: 'Передача товаров логистической компании'
    documentation: 'Накладные, сертификаты, инструкции'
  }

  // Контроль доставки
  tracking: {
    responsibility: 'Отслеживание до момента доставки'
    issues: 'Решение проблем в процессе доставки'
    confirmation: 'Подтверждение получения клиентом'
  }
}
```

## 💼 УПРАВЛЕНИЕ КЛИЕНТСКИМИ ОТНОШЕНИЯМИ

### 1. СИСТЕМА ПАРТНЕРСТВА:

```typescript
interface WholesalePartnership {
  // Входящие заявки на партнерство
  incomingRequests: {
    from: ['SELLER', 'FULFILLMENT', 'LOGIST']
    evaluation: 'Оценка потенциального партнера'
    decision: 'ACCEPTED | REJECTED | CANCELLED'
  }

  // Исходящие заявки
  outgoingRequests: {
    to: ['FULFILLMENT', 'LOGIST'] // Поставщик редко ищет селлеров
    purpose: 'Расширение сети дистрибуции'
  }

  // Автоматическое партнерство
  autoPartnership: {
    trigger: 'autoCreateWarehouseEntry'
    process: 'Автоматическое создание складских записей при партнерстве'
  }
}
```

### 2. ЦЕНООБРАЗОВАНИЕ И УСЛОВИЯ:

```typescript
interface WholesalePricing {
  // Базовые цены
  basePrices: {
    setup: 'Установка цен в каталоге товаров'
    currency: 'RUB (российские рубли)'
    precision: 'Decimal(10,2) - точность до копеек'
  }

  // Скидочная система
  discounts: {
    volume: 'Скидки за объем заказа'
    frequency: 'Скидки постоянным клиентам'
    seasonal: 'Сезонные акции и распродажи'
    payment: 'Скидки за предоплату'
  }

  // Условия оплаты
  paymentTerms: {
    methods: ['Предоплата', 'Постоплата', 'Кредит']
    terms: '30/60/90 дней отсрочки'
    penalties: 'Штрафы за просрочку платежей'
  }
}
```

## 🔐 ПРАВА ДОСТУПА И БЕЗОПАСНОСТЬ

### ДОСТУП К ДАННЫМ:

```typescript
const wholesaleAccess = {
  // ✅ Полный доступ
  own: {
    products: 'Каталог товаров поставщика',
    incomingOrders: 'Входящие заказы поставок',
    inventory: 'Складские остатки',
    pricing: 'Управление ценами',
    partnerships: 'Партнерские отношения',
  },

  // ✅ Доступ на чтение (через партнерство)
  partners: {
    fulfillmentServices: 'Услуги партнеров-фулфилментов',
    logisticsRoutes: 'Маршруты партнеров-логистов',
    marketDemand: 'Спрос от партнеров-селлеров',
  },

  // ❌ Запрещенный доступ
  restricted: {
    sellerApiKeys: 'API ключи маркетплейсов',
    fulfillmentWarehouse: 'Внутренние операции ФФ',
    competitorData: 'Данные других поставщиков',
    endCustomerData: 'Данные конечных покупателей',
  },
}
```

### БИЗНЕС-ПРАВИЛА БЕЗОПАСНОСТИ:

```typescript
const wholesaleSecurity = {
  // Изоляция данных
  dataIsolation: {
    rule: 'Поставщик видит только свои товары и заказы',
    implementation: 'organizationId = currentUser.organization.id',
  },

  // Контроль заказов
  orderControl: {
    rule: 'Может управлять только заказами где он - поставщик',
    validation: 'partnerId = currentUser.organization.id',
  },

  // Ценовая информация
  pricingAccess: {
    rule: 'Только поставщик может изменять цены своих товаров',
    protection: 'Конкуренты не видят себестоимость и наценки',
  },
}
```

## 📱 DASHBOARD И ИНТЕРФЕЙСЫ

### ОСНОВНЫЕ РАЗДЕЛЫ КАБИНЕТА:

```typescript
interface WholesaleDashboard {
  sections: {
    orders: 'Обработка входящих заказов' // Основной раздел
    catalog: 'Управление каталогом товаров' // Товары и цены
    inventory: 'Управление запасами' // Остатки и поставки
    partners: 'Партнерские отношения' // Клиенты и поставщики
    logistics: 'Координация доставок' // Статусы отгрузок
    analytics: 'Аналитика продаж' // Отчеты и статистика
    finance: 'Финансовый учет' // Платежи и расчеты
  }
}
```

### СПЕЦИАЛИЗИРОВАННЫЕ КОМПОНЕНТЫ:

```typescript
const wholesaleComponents = [
  // Обработка заказов
  'supplier-orders-dashboard.tsx', // Главный dashboard
  'supplier-order-card.tsx', // Карточка заказа
  'supplier-order-stats.tsx', // Статистика заказов

  // Управление каталогом
  'wholesale-catalog-management.tsx', // Управление товарами
  'product-pricing-form.tsx', // Установка цен
  'inventory-tracking.tsx', // Отслеживание остатков

  // Партнерские отношения
  'partnership-requests.tsx', // Входящие/исходящие заявки
  'client-management.tsx', // Управление клиентами
  'wholesale-statistics.tsx', // Аналитика поставщика
]
```

### WORKFLOW ИНТЕРФЕЙСЫ:

```typescript
interface WholesaleWorkflowUI {
  // Обработка входящих заказов
  incomingOrdersInterface: {
    view: 'Список заказов со статусом PENDING'
    actions: ['Подтвердить', 'Отклонить', 'Запросить изменения']
    details: 'Детали заказа, клиент, товары, сроки'
  }

  // Подготовка к отгрузке
  fulfillmentInterface: {
    view: 'Заказы со статусом LOGISTICS_CONFIRMED'
    actions: ['Комплектация', 'Упаковка', 'Передача логистике']
    tracking: 'Статус подготовки и готовность к отгрузке'
  }

  // Отслеживание доставки
  trackingInterface: {
    view: 'Заказы со статусом SHIPPED'
    info: 'Информация о доставке, логистическая компания'
    updates: 'Обновления статуса от логистики'
  }
}
```

## ⚠️ КРИТИЧЕСКИЕ ПРАВИЛА ДОМЕНА

### 1. ОБЯЗАТЕЛЬНОЕ ПАРТНЕРСТВО

> Поставщик может продавать товары **ТОЛЬКО** своим партнерам (SELLER, FULFILLMENT)

### 2. КОНТРОЛЬ WORKFLOW

> Поставщик **ОБЯЗАН** подтвердить или отклонить входящие заказы в разумные сроки

### 3. КАЧЕСТВО ТОВАРОВ

> Поставщик **НЕСЕТ ОТВЕТСТВЕННОСТЬ** за качество товаров до момента передачи логистике

### 4. ЦЕНОВАЯ ПОЛИТИКА

> Цены в каталоге **ВИДНЫ ВСЕМ**, но управлять может только владелец товаров

### 5. СКЛАДСКОЙ УЧЕТ

> Поставщик **ДОЛЖЕН** поддерживать актуальную информацию об остатках товаров

### 6. СТАТУСЫ ЗАКАЗОВ

> Поставщик **НЕ МОЖЕТ** изменять статусы заказов напрямую, только через бизнес-процессы

## 💻 ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ КАБИНЕТА

### АРХИТЕКТУРА КОМПОНЕНТОВ:

```typescript
src/components/
├── warehouse/              # Компоненты склада поставщика
│   ├── warehouse-dashboard.tsx      # Главный dashboard склада
│   ├── product-card.tsx            # Карточка товара
│   ├── product-form.tsx            # Форма создания/редактирования товара
│   └── warehouse-statistics.tsx    # Статистика склада
├── supplier-orders/        # Компоненты обработки заказов
│   ├── supplier-orders-dashboard.tsx  # Главный dashboard заказов
│   ├── supplier-order-card.tsx       # Карточка заказа
│   ├── supplier-orders-tabs.tsx      # Табы по статусам заказов
│   ├── supplier-orders-search.tsx    # Поиск и фильтры
│   └── supplier-order-stats.tsx      # Статистика заказов
└── economics/              # Экономическая аналитика
    └── wholesale-economics-page.tsx  # Финансовая отчетность
```

### СТРАНИЦЫ (NEXT.JS ROUTES):

```typescript
src/app/
├── warehouse/
│   └── page.tsx           # /warehouse - управление складом
├── supplier-orders/
│   └── page.tsx           # /supplier-orders - обработка заказов
└── economics/
    └── page.tsx           # /economics - финансовая аналитика
```

## 🛠️ GRAPHQL API ПОСТАВЩИКОВ

### ОСНОВНЫЕ ЗАПРОСЫ:

```graphql
# Получение товаров поставщика
query GetMyProducts {
  myProducts {
    id
    name
    article
    price
    quantity
    organization {
      id
      name
      market # Физический рынок поставщика
    }
  }
}

# Получение заказов поставщика
query GetSupplierOrders {
  supplyOrders(where: { partnerId: $myOrgId }) {
    id
    status
    totalAmount
    organization {
      name
    } # Заказчик
  }
}

# Получение партнеров
query GetMyCounterparties {
  myCounterparties {
    id
    name
    type
    market
    fullName
    inn
  }
}
```

### МУТАЦИИ ОБРАБОТКИ ЗАКАЗОВ:

```graphql
# Одобрение заказа поставщиком
mutation SupplierApproveOrder($orderId: ID!) {
  supplierApproveOrder(id: $orderId) {
    success
    order {
      id
      status
      organization {
        id
        name
      }
    }
  }
}

# Отклонение заказа
mutation SupplierRejectOrder($orderId: ID!, $reason: String) {
  supplierRejectOrder(id: $orderId, reason: $reason) {
    success
    message
  }
}

# Отгрузка заказа
mutation SupplierShipOrder($orderId: ID!) {
  supplierShipOrder(id: $orderId) {
    success
    order {
      id
      status # SHIPPED -> IN_TRANSIT
      organization {
        id
        name
      }
    }
  }
}

# Создание товара
mutation CreateProduct($input: ProductInput!) {
  createProduct(input: $input) {
    success
    product {
      id
      article
      organization {
        id
        name
      }
    }
  }
}
```

### ПРАВИЛА ПАРТНЕРСТВА В API:

```typescript
// ✅ ПРАВИЛЬНО: Поставщики берутся ТОЛЬКО из партнеров
const suppliers = await useQuery(GET_MY_COUNTERPARTIES, {
  variables: { type: 'WHOLESALE' },
})

// ❌ НЕПРАВИЛЬНО: Прямой запрос поставщиков
const suppliers = await useQuery(GET_SUPPLY_SUPPLIERS)
```

## 🔐 ТЕХНИЧЕСКИЕ ПРАВИЛА БЕЗОПАСНОСТИ

### КОНТРОЛЬ ДОСТУПА НА УРОВНЕ КОМПОНЕНТОВ:

```typescript
// Проверка типа организации в UI
{user?.organization?.type === "WHOLESALE" && (
  <WarehouseDashboard />
)}

// Условный рендеринг функций поставщика
{user?.organization?.type === 'WHOLESALE' ? (
  <SupplierOrdersTabs />
) : (
  <AccessDenied />
)}
```

### ПРОВЕРКИ В GRAPHQL РЕЗОЛВЕРАХ:

```typescript
// Проверка что пользователь - поставщик
if (context.user.organization.type !== 'WHOLESALE') {
  throw new Error('Access denied: Wholesale access required')
}

// Проверка доступа к своим товарам
const product = await prisma.product.findFirst({
  where: {
    id: productId,
    organizationId: context.user.organizationId,
  },
})

// Фильтрация заказов для поставщика
let whereClause
if (currentUser.organization.type === 'WHOLESALE') {
  // Поставщик видит заказы, где он является поставщиком
  whereClause = { partnerId: currentUser.organization.id }
} else {
  // Остальные видят заказы, которые они создали
  whereClause = { organizationId: currentUser.organization.id }
}
```

### ОБЯЗАТЕЛЬНЫЕ ВАЛИДАЦИИ:

```typescript
const wholesaleValidations = {
  // Основные проверки
  organizationType: 'organization.type === "WHOLESALE"',
  accessControl: 'GraphQL resolver level validation',
  inventoryControl: 'Stock availability before order confirmation',

  // Запрещенные действия
  forbidden: [
    'Создание товаров с типами DEFECT или FINISHED_PRODUCT',
    'Изменение статусов заказов минуя workflow',
    'Показ данных других поставщиков',
    'Прямое изменение статусов без бизнес-процессов',
  ],
}
```

## 🚨 КРИТИЧЕСКИЕ ПРОБЛЕМЫ И РЕШЕНИЯ

### ВЫЯВЛЕННЫЕ ПРОБЛЕМЫ В WORKFLOW:

```typescript
// ❌ ПРОБЛЕМА: Отображается статус вместо только кнопок действий
// Поставщик видит "ожидает подтверждения" вместо чистых кнопок

// ❌ ПРОБЛЕМА: Нет валидации минимальных количеств заказа
// Отсутствует проверка доступности товаров у поставщика

// ❌ ПРОБЛЕМА: Нет уведомления поставщика о новом заказе
// Поставщик не знает о поступивших заказах в реальном времени

// 🔧 РЕШЕНИЕ: Исправленный код фильтрации заказов
const fixedOrderFiltering = `
  if (currentUser.organization.type === 'WHOLESALE') {
    whereClause = {
      partnerId: currentUser.organization.id, // Мы - поставщик
    }
  }
`
```

### ТРЕБОВАНИЯ К ИСПРАВЛЕНИЯМ:

```typescript
interface WholesaleFixes {
  ui: {
    orderButtons: 'Показывать только кнопки действий, скрывать статусы'
    realTimeNotifications: 'Уведомления о новых заказах'
    inventoryValidation: 'Проверка остатков перед подтверждением'
  }

  backend: {
    minOrderValidation: 'Валидация минимальных количеств'
    stockAvailability: 'Проверка доступности товаров'
    notificationSystem: 'Система уведомлений поставщиков'
  }
}
```

---

_Дополнено техническими деталями из: legacy-rules/wholesale-cabinet-rules.md, правила создания поставки товаров.md_  
_Дата обновления: 2025-08-22_  
_Основано на коде: src/components/supplier-orders/, src/graphql/resolvers.ts, supply order management_
