# ДОМЕН СЕЛЛЕРОВ (SELLER)

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

**Селлер** - продавец на маркетплейсах (WB, Ozon), который размещает товары на хранение и обработку в фулфилмент-центрах для последующей отправки покупателям.

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

- ✅ Продажи на маркетплейсах через API интеграции
- ✅ Создание поставок товаров в фулфилмент
- ✅ Управление рецептурами продуктов
- ✅ Заказ услуг фулфилмента
- ✅ Контроль остатков и продаж

## 🏢 БИЗНЕС-МОДЕЛЬ СЕЛЛЕРА

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

```typescript
enum SellerEconomics {
  REVENUE = "Продажи на маркетплейсах"      // Основной доход
  COSTS = {
    FULFILLMENT_SERVICES: "Услуги ФФ",       // Обработка, упаковка
    CONSUMABLES: "Расходники ФФ",            // Компоненты рецептур
    STORAGE: "Хранение товаров",             // Складские услуги
    MARKETPLACE_FEES: "Комиссии WB/Ozon",    // Комиссии площадок
    ADVERTISING: "Реклама товаров"           // Продвижение
  }
}
```

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

```mermaid
graph TD
    A[SELLER] --> B[FULFILLMENT - Основной партнер]
    A --> C[WHOLESALE - Поставщики товаров]
    A --> D[LOGIST - Доставка к ФФ]

    B --> E[Обрабатывает товары селлера]
    B --> F[Предоставляет услуги и расходники]
    C --> G[Поставляют товары для продажи]
    D --> H[Доставляют товары в ФФ]
```

## 📱 ИНТЕГРАЦИЯ С МАРКЕТПЛЕЙСАМИ

### API КЛЮЧИ И РЕГИСТРАЦИЯ:

```typescript
// Регистрация селлера с API ключами
interface SellerRegistration {
  phone: string // Обязательно
  wbApiKey?: string // Wildberries API (опционально)
  ozonApiKey?: string // Ozon API ключ (опционально)
  ozonClientId?: string // Ozon Client ID (опционально)
  referralCode?: string // Реферальный код (опционально)
}
```

**GraphQL мутация:**

```graphql
mutation RegisterSellerOrganization($input: SellerRegistrationInput!) {
  registerSellerOrganization(input: $input) {
    success
    message
    user {
      id
      phone
    }
    organization {
      id
      type
    }
  }
}
```

**Валидация в коде:**

```typescript
// Из resolvers.ts - проверка API ключей
const validation = {
  rule: '!wbApiKey && !ozonApiKey',
  error: 'Необходимо указать хотя бы один API ключ маркетплейса',

  wbValidation: 'marketplaceService.validateWildberriesApiKey(wbApiKey)',
  ozonValidation: 'marketplaceService.validateOzonApiKey(ozonApiKey, ozonClientId)',
}
```

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

```typescript
enum SupportedMarketplaces {
  WILDBERRIES = {
    integration: 'Полная интеграция API',
    features: [
      'Статистика продаж',
      'Реклама и кампании',
      'Остатки на складах',
      'Заявки на возврат',
      'Создание поставок',
    ],
  },

  OZON = {
    integration: 'Базовая интеграция API',
    features: ['Создание поставок', 'Получение остатков'],
  },
}
```

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

### SELLER_CONSUMABLES (Расходники селлера)

```typescript
interface SellerConsumables {
  purpose: 'Компоненты для рецептур продуктов селлера'
  owner: 'SELLER'
  storage: 'На складе фулфилмента'
  management: 'Селлер заказывает у поставщиков → размещает в ФФ'
  usage: 'Используются в рецептурах ProductRecipe'

  // Экономика:
  cost: 'Селлер покупает у поставщиков'
  billing: 'Плата за хранение фулфилменту'
}
```

**GraphQL операции:**

```graphql
# Расходники селлера (хранящиеся в ФФ)
query GetMySupplies {
  mySupplies {
    id
    name
    type # = SELLER_CONSUMABLES
    sellerOwnerId # = currentUser.organization.id
    currentStock
    price
  }
}
```

### PRODUCT RECIPES (Рецептуры товаров)

```typescript
interface ProductRecipe {
  services: Service[] // Услуги фулфилмента
  fulfillmentConsumables: Supply[] // Расходники ФФ (покупает у ФФ)
  sellerConsumables: Supply[] // Расходники селлера (свои)
  marketplaceCardId?: string // Связь с карточкой маркетплейса
}
```

**Экономические правила рецептур:**

- Селлер выбирает расходники ФФ → расход в кабинете селлера
- Доход в кабинете ФФ от продажи расходников селлеру
- Селлер использует свои расходники → списание со склада ФФ

## 🔄 WORKFLOW ПОСТАВОК ДЛЯ СЕЛЛЕРОВ

### СОЗДАНИЕ ПОСТАВОК ТОВАРОВ:

```typescript
// Селлер создает поставку товаров для размещения в ФФ
interface SellerSupplyOrder {
  organizationId: string // ID селлера (инициатор)
  partnerId: string // ID поставщика (WHOLESALE)
  fulfillmentCenterId: string // ID фулфилмента (получатель)
  logisticsPartnerId?: string // ID логистики (опционально)

  // Селлер определяет:
  deliveryDate: DateTime // Желаемая дата доставки
  consumableType?: string // Тип расходников
  items: SupplyOrderItem[] // Товары с рецептурами
}
```

**Роль в 8-статусной системе:**

```typescript
const sellerWorkflowRoles = {
  asInitiator: {
    status: 'PENDING',
    action: 'Создание заказа поставки',
    rights: ['CANCEL_ORDER', 'VIEW_STATUS'],
  },

  asObserver: {
    statuses: ['SUPPLIER_APPROVED', 'LOGISTICS_CONFIRMED', 'SHIPPED'],
    action: 'Отслеживание прогресса',
    rights: ['VIEW_STATUS', 'CANCEL_ORDER'],
  },

  finalStatus: {
    status: 'DELIVERED',
    action: 'Товары доставлены в ФФ',
    result: 'Товары готовы к обработке и отправке',
  },
}
```

### СЧЕТЧИКИ ПОСТАВОК:

```typescript
// Из pendingSuppliesCount - что видит селлер
const sellerCounters = {
  // Селлер не видит входящих заказов (он всегда инициатор)
  incomingSupplierOrders: 0,
  logisticsOrders: 0,

  // Селлер видит свои заказы
  mySupplyOrders: 'Количество активных поставок селлера',

  // Логика подсчета:
  condition: 'organizationId = currentUser.organization.id',
}
```

## 📊 СТАТИСТИКА И АНАЛИТИКА

### КЕШИРОВАНИЕ ДАННЫХ ПРОДАЖ:

```typescript
interface SellerStatsCache {
  period: string // Период аналитики
  dateFrom: DateTime // Начало периода
  dateTo: DateTime // Конец периода

  // Данные по товарам
  productsData: JSON // Детализация по товарам
  productsTotalSales: Decimal // Общая сумма продаж
  productsTotalOrders: number // Количество заказов
  productsCount: number // Количество товаров

  // Данные по рекламе
  advertisingData: JSON // Статистика рекламных кампаний
  advertisingTotalCost: Decimal // Общие затраты на рекламу
  advertisingTotalViews: number // Показы
  advertisingTotalClicks: number // Клики

  expiresAt: DateTime // TTL кеша
}
```

**GraphQL запросы:**

```graphql
query GetSellerStatsCache($period: String!, $dateFrom: String, $dateTo: String) {
  getSellerStatsCache(period: $period, dateFrom: $dateFrom, dateTo: $dateTo) {
    productsData
    productsTotalSales
    advertisingTotalCost
    # ... остальные поля
  }
}
```

### WB WAREHOUSE CACHE (Остатки Wildberries):

```typescript
interface WBWarehouseCache {
  organizationId: string // ID селлера
  cacheDate: DateTime // Дата кеширования
  data: JSON // Полные данные склада WB

  // Агрегированные данные:
  totalProducts: number // Общее количество товаров
  totalStocks: number // Общие остатки
  totalReserved: number // Зарезервированные товары

  // TTL кеширования для производительности
}
```

## 🎛️ СОЗДАНИЕ ПОСТАВОК WB/OZON

### WILDBERRIES SUPPLY:

```typescript
interface WildberriesSupply {
  organizationId: string // ID селлера
  status: WildberriesSupplyStatus // DRAFT, CREATED, IN_PROGRESS, etc.
  deliveryDate?: DateTime // Дата доставки
  totalAmount: Decimal // Общая сумма
  totalItems: number // Количество товаров

  // Карточки товаров в поставке
  cards: WildberriesSupplyCard[]
}

interface WildberriesSupplyCard {
  nmId: string // Номенклатура WB
  vendorCode: string // Артикул продавца
  title: string // Название товара
  brand?: string // Бренд
  price: Decimal // Цена
  quantity: number // Количество

  // Рецептура (связь с фулфилментом):
  selectedServices: JSON // Выбранные услуги ФФ
  sellerName?: string // Продавец
  sellerPhone?: string // Контакт продавца
  deliveryDate?: DateTime // Дата доставки в ФФ
  mediaFiles: JSON // Медиафайлы товара
}
```

**GraphQL мутации:**

```graphql
# Создание поставки WB
mutation CreateWildberriesSupply($input: CreateWildberriesSupplyInput!) {
  createWildberriesSupply(input: $input) {
    success
    supply {
      id
      status
      totalAmount
    }
  }
}

# Обновление поставки
mutation UpdateWildberriesSupply($id: ID!, $input: UpdateWildberriesSupplyInput!) {
  updateWildberriesSupply(id: $id, input: $input) {
    success
    supply {
      id
      status
    }
  }
}
```

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

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

```typescript
const sellerAccess = {
  // ✅ Полный доступ
  own: {
    supplies: 'SELLER_CONSUMABLES (свои расходники)',
    supplyOrders: 'Собственные заказы поставок',
    apiKeys: 'API ключи маркетплейсов',
    statistics: 'Статистика продаж',
    wildberriesSupplies: 'Поставки WB/Ozon',
  },

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

  // ❌ Запрещенный доступ
  restricted: {
    fulfillmentConsumables: 'Расходники фулфилмента',
    otherSellersData: 'Данные других селлеров',
    fulfillmentWarehouse: 'Внутренние операции ФФ',
    adminFunctions: 'Административные функции',
  },
}
```

### ИЗОЛЯЦИЯ ДАННЫХ:

```typescript
// Правило изоляции селлеров из resolvers.ts
const sellerIsolation = {
  rule: 'Селлер видит только свои данные',

  implementation: `
    // Проверка принадлежности к организации
    const hasAccess = organization.users.some(user => 
      user.id === context.user!.id
    )
    
    if (!hasAccess) {
      throw new GraphQLError('Нет доступа к этой организации')
    }
  `,

  // Фильтрация по владельцу
  dataFilter: 'organizationId = currentUser.organization.id',
}
```

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

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

```typescript
interface SellerDashboard {
  sections: {
    supplies: 'Создание поставок товаров' // Основной раздел
    mySupplies: 'Управление расходниками' // SELLER_CONSUMABLES
    marketplace: 'Интеграция WB/Ozon' // API, остатки, статистика
    orders: 'Отслеживание поставок' // Статусы workflow
    statistics: 'Аналитика продаж' // Кеш данных маркетплейсов
    services: 'Каталог услуг партнеров' // Поиск ФФ и услуг
  }
}
```

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

```typescript
const sellerComponents = [
  // Создание поставок
  'create-suppliers-supply-page.tsx', // Модульная архитектура
  'direct-supply-creation.tsx', // Модульная архитектура
  'create-supply-page.tsx', // Простая форма

  // Управление товарами
  'goods-supplies-table.tsx', // Таблица товаров
  'multilevel-supplies-table.tsx', // Многоуровневая структура
  'wb-product-cards.tsx', // Карточки товаров WB

  // Интеграция маркетплейсов
  'wildberries-supplies-tab.tsx', // Поставки WB
  'ozon-supplies-tab.tsx', // Поставки Ozon
  'marketplace-supplies-tab.tsx', // Общий интерфейс
]
```

### ПРОДВИНУТЫЕ ИНТЕРФЕЙСЫ:

```typescript
interface AdvancedSellerUI {
  // Создание рецептур продуктов
  recipeBuilder: {
    component: 'recipe-display.tsx'
    features: [
      'Выбор услуг фулфилмента',
      'Добавление расходников ФФ',
      'Использование собственных расходников',
      'Расчет себестоимости',
    ]
  }

  // Статистика и аналитика
  analytics: {
    charts: 'Графики продаж и трендов'
    advertising: 'ROI рекламных кампаний'
    warehouse: 'Остатки по складам WB/Ozon'
    forecasting: 'Прогнозирование потребности'
  }
}
```

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

### 1. ОБЯЗАТЕЛЬНАЯ ИНТЕГРАЦИЯ С МАРКЕТПЛЕЙСАМИ

> При регистрации селлер **ДОЛЖЕН** предоставить хотя бы один API ключ (WB или Ozon)

### 2. ПАРТНЕРСТВО С ФУЛФИЛМЕНТОМ

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

### 3. ИЗОЛЯЦИЯ ДАННЫХ

> Селлер имеет доступ **ТОЛЬКО** к собственным данным, кроме публичных каталогов партнеров

### 4. ЭКОНОМИЧЕСКАЯ МОДЕЛЬ РЕЦЕПТУР

> Использование расходников ФФ = **покупка услуги**, собственные расходники = **списание со склада**

### 5. WORKFLOW ОГРАНИЧЕНИЯ

> Селлер может **отменить** свою поставку на любом этапе, но **не может** управлять переходами статусов

### 6. БЕЗОПАСНОСТЬ API КЛЮЧЕЙ

> API ключи маркетплейсов хранятся **зашифрованно** и **не возвращаются** через GraphQL запросы

---

_Извлечено из анализа: GraphQL resolvers, marketplace integration, бизнес-правила_  
_Дата создания: 2025-08-21_  
_Основано на коде: src/graphql/resolvers.ts, marketplace services, seller workflows_
