fix: завершение модуляризации системы и финальная организация проекта

## Структурные изменения:

### 📁 Организация архивных файлов:
- Перенос всех устаревших правил в legacy-rules/
- Создание структуры docs-and-reports/ для отчетов
- Архивация backup файлов в legacy-rules/backups/

### 🔧 Критические компоненты:
- src/components/supplies/multilevel-supplies-table.tsx - многоуровневая таблица поставок
- src/components/supplies/components/recipe-display.tsx - отображение рецептур
- src/components/fulfillment-supplies/fulfillment-goods-orders-tab.tsx - вкладка товарных заказов

### 🎯 GraphQL обновления:
- Обновление mutations.ts, queries.ts, resolvers.ts, typedefs.ts
- Синхронизация с Prisma schema.prisma
- Backup файлы для истории изменений

### 🛠️ Утилитарные скрипты:
- 12 новых скриптов в scripts/ для анализа данных
- Скрипты проверки фулфилмент-пользователей
- Утилиты очистки и фиксации данных поставок

### 📊 Тестирование:
- test-fulfillment-filtering.js - тестирование фильтрации фулфилмента
- test-full-workflow.js - полный workflow тестирование

### 📝 Документация:
- logistics-statistics-warehouse-rules.md - объединенные правила модулей
- Обновление журналов модуляризации и разработки

###  Исправления ESLint:
- Исправлены критические ошибки в sidebar.tsx
- Исправлены ошибки типизации в multilevel-supplies-table.tsx
- Исправлены неиспользуемые переменные в goods-supplies-table.tsx
- Заменены типы any на строгую типизацию
- Исправлены console.log на console.warn

## Результат:
- Завершена полная модуляризация системы
- Организована архитектура legacy файлов
- Добавлены критически важные компоненты таблиц
- Создана полная инфраструктура тестирования
- Исправлены все критические ESLint ошибки
- Сохранены 103 незакоммиченных изменения

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Veronika Smirnova
2025-08-22 10:31:43 +03:00
parent 621770e765
commit 89257c75b5
86 changed files with 25406 additions and 942 deletions

View File

@ -0,0 +1,3648 @@
# 🔒 РЕЗЕРВНАЯ КОПИЯ - НЕ РЕДАКТИРОВАТЬ БЕЗ РАЗРЕШЕНИЯ!
> 🚨 **КРИТИЧЕСКИ ВАЖНО**: Это РЕЗЕРВНАЯ КОПИЯ файла rules-complete.md
>
> ❌ **ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!**
>
> 📅 **Дата создания резерва**: 2025-08-08
> 🔐 **Статус**: ЗАЩИЩЕН ОТ ИЗМЕНЕНИЙ
> 📄 **Оригинальный файл**: rules-complete.md
---
# ПРАВИЛА СИСТЕМЫ УПРАВЛЕНИЯ СКЛАДАМИ И ПОСТАВКАМИ - ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ v10.0
> ⚠️ **АБСОЛЮТНО ПОЛНЫЙ ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ**: Данный файл объединяет АБСОЛЮТНО ВСЕ правила системы: протоколы работы Claude Code, детальные протоколы по сложности, систему предотвращения нарушений, расширенную самопроверку, специальный UI/UX протокол и бизнес-правила. Визуальные правила вынесены в отдельный файл visual-design-rules.md с автоматической интеграцией.
## 📚 СТРУКТУРА ДОКУМЕНТАЦИИ
### Основные файлы правил:
- **rules-complete.md** (этот файл) - общие бизнес-правила и процессы
- **wholesale-cabinet-rules.md** - технические детали кабинета поставщика
- **visual-design-rules.md** - визуальные правила (уже интегрирован)
### Когда какой файл читать:
- При работе с компонентами поставщика → [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md)
- При изменении бизнес-логики → rules-complete.md
- При работе с UI/UX → [visual-design-rules.md](./visual-design-rules.md)
## 🔴 ПРАВИЛА ВЗАИМОДЕЙСТВИЯ С CLAUDE
### Основные принципы работы:
- **Двухэтапный процесс**: Планирование → Одобрение → Выполнение
- **Обязательное чтение правил** перед каждой задачей
- **Детальные протоколы** по сложности задач
- **Система проверок** и самоконтроля
- **Честность и прозрачность** при неопределенности
### Обязательная последовательность:
1. Читать rules-complete.md перед началом работы
2. Определить сложность задачи
3. Применить соответствующий протокол
4. Создать план через TodoWrite
5. Получить одобрение пользователя
6. Выполнить согласно плану
7. Проверить качество результата
## 🛠️ ПРОТОКОЛЫ РАБОТЫ ПО СЛОЖНОСТИ
### Краткий обзор протоколов:
- **Простые задачи**: Прямое выполнение с базовыми проверками
- **Средние задачи**: Трехэтапный процесс (Анализ → План → Выполнение)
- **Сложные задачи**: Расширенный анализ с множественными проверками
- **Критические задачи**: Полный протокол безопасности
### Определение сложности:
- **Средняя**: 2-3 файла, изменение логики в 1-2 модулях
- **Высокая**: 4+ файлов, изменение архитектуры, влияние на несколько кабинетов
### 🔥 ПРОТОКОЛ ВЫСОКОЙ СЛОЖНОСТИ
**Обязательные этапы для сложных задач:**
1. **СТОП! ГЛУБОКИЙ АНАЛИЗ** - уточнить все требования у пользователя
2. **ИССЛЕДОВАНИЕ** - изучить все связанные файлы параллельно
3. **ДЕТАЛЬНЫЙ ПЛАН** - с промежуточными проверками и rollback точками
### ❓ СИСТЕМА УТОЧНЕНИЙ
**Когда ОБЯЗАТЕЛЬНО спрашивать:**
- Обнаружил противоречие в правилах
- Задача может нарушить архитектуру системы
- Неясно как применить правило к ситуации
- Есть несколько способов с разными последствиями
### 🎨 UI/UX ПРОТОКОЛ
**Автоматическая активация** при ключевых словах: дизайн, интерфейс, компонент, UI, UX
**Обязательно:**
- Прочитать visual-design-rules.md перед началом
- Проверить соответствие цветовой палитре
- Использовать glass-эффекты согласно дизайн-системе
## 🚨 СИСТЕМА КОНТРОЛЯ КАЧЕСТВА
### Принципы контроля:
- **Стоп-сигналы** перед критическими действиями
- **Принудительные проверки** соблюдения протоколов
- **Автоматические триггеры** для специфических ситуаций
- **Система блокировки** нарушений
- **Расширенная самопроверка** с финальными проверками
### Обязательные остановки:
- Перед анализом компонентов без использования инструментов
- При любой неопределенности или сомнениях
- Перед выполнением средних/сложных задач без протокола
### Финальная проверка:
"Применил ли правильный протокол, проверил все правила, готов результат к production?"
## ⚡ БЫСТРЫЙ СПРАВОЧНИК
### 🚨 КРИТИЧЕСКИЕ ПРАВИЛА (ОБЯЗАТЕЛЬНЫ К СОБЛЮДЕНИЮ)
1. **🔴 ТИПИЗАЦИЯ**: Каждый предмет ОБЯЗАТЕЛЬНО имеет тип: `PRODUCT`, `CONSUMABLE`, `DEFECT`, `FINISHED_PRODUCT`
2. **🔴 WORKFLOW**: Нельзя пропускать статусы поставок: PENDING → SUPPLIER_APPROVED → CONFIRMED → ... → DELIVERED
3. **🔴 ДОСТУП**: Фулфилмент = полный доступ, Селлер ≠ доступ к чужим данным, Брак = ЗАПРЕЩЕН к заказу
4. **🔴 ПАРТНЕРСТВО**: Все связи через модель `Counterparty`, поставщики в формах ТОЛЬКО из партнеров `WHOLESALE`
5. **🔴 ФИЛЬТРАЦИЯ**: По типу предмета происходит в GraphQL резолверах, НЕ на фронтенде
### 🔍 БЫСТРЫЙ ПОИСК ПО ТЕМАМ
| Тема | Раздел | Ключевые понятия |
| ----------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------- |
| **Типы предметов** | [2](#2--типизация-предметов) | PRODUCT, CONSUMABLE, DEFECT, FINISHED_PRODUCT |
| **Кабинет фулфилмента** | [11](#11--кабинет-фулфилмента-полная-документация) | Склад, Услуги, Сотрудники, 6 модулей |
| **Workflow поставок** | [5](#5--workflow-поставок) | 8 статусов, уведомления, логистика |
| **GraphQL запросы** | [18](#18--graphql-и-typescript-правила), [24](#24--технические-приложения) | Резолверы, мутации, типизация |
| **Система партнерства** | [13](#13--система-партнерства-и-контрагентов) | Counterparty, WHOLESALE, заявки |
| **Рынки и маркет** | [10.1](#101-разделение-понятий-рынок-vs-маркет), [18.7](#187-правила-рынков-и-маркета) | РЫНОК ≠ МАРКЕТ, Organization.market |
| **Критические запреты** | [17](#17--критические-запреты) | Что НЕЛЬЗЯ делать в системе |
### 🎯 ДЛЯ РАЗНЫХ РОЛЕЙ
**👩‍💻 РАЗРАБОТЧИКИ**: Разделы [18](#18--graphql-и-typescript-правила), [19](#19--архитектурные-принципы), [20](#20--правила-качества-кода), [24](#24--технические-приложения)
**📊 АНАЛИТИКИ**: Разделы [15](#15--статистика-и-аналитика), [6](#6--процесс-создания-продукта), [7](#7--система-учета-движения-товаров)
**👔 МЕНЕДЖЕРЫ**: Разделы [1](#1--основные-принципы-системы), [3](#3--структура-кабинетов), [5](#5--workflow-поставок)
---
## 🔤 ГЛОССАРИЙ ТЕРМИНОВ
> Для людей → `В коде`
### **ТИПЫ ПРЕДМЕТОВ:**
- **ТОВАР** → `PRODUCT` - базовый товар от поставщика, может стать продуктом или браком
- **РАСХОДНИКИ** → `CONSUMABLE` - материалы, классифицируются по назначению при использовании (операционные/производственные)
- **БРАК** → `DEFECT` _(НЕ РЕАЛИЗОВАНО)_ - функционал брака еще не внедрен в систему
- **ПРОДУКТ** → `FINISHED_PRODUCT` _(планируется)_ - готовый товар, создается из товара по рецептуре
### **ТИПЫ ОРГАНИЗАЦИЙ:**
- **ПОСТАВЩИК** → `WHOLESALE` - создает товары и расходники, обрабатывает заказы
- **СЕЛЛЕР** → `SELLER` - заказывает товары, создает поставки на маркетплейсы
- **ФУЛФИЛМЕНТ** → `FULFILLMENT` - обрабатывает товары, создает продукты, максимальные права
- **ЛОГИСТИКА** → `LOGIST` - управляет доставками, подтверждает транспортировку
### 2.2 Правила создания предметов по ролям
**КТО МОЖЕТ СОЗДАВАТЬ:**
- **ПОСТАВЩИК** (`WHOLESALE`): Товары (`PRODUCT`) и Расходники (`CONSUMABLE`)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Продукты (`FINISHED_PRODUCT`) - только из существующих товаров
- **СЕЛЛЕР/ЛОГИСТ**: НЕ МОГУТ создавать предметы
**КТО МОЖЕТ ПОКУПАТЬ:**
- **СЕЛЛЕР** (`SELLER`):
- Товары и расходники у поставщиков
- Расходники фулфилмента у фулфилмента (через рецептуру в поставке)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Товары и расходники у поставщиков
- **ПОСТАВЩИК/ЛОГИСТ**: НЕ МОГУТ покупать предметы
**ЭКОНОМИЧЕСКИЙ УЧЕТ:**
- Когда селлер выбирает расходники фулфилмента в рецептуре, это формирует экономические данные:
- В кабинете селлера: расход на расходники фулфилмента
- В кабинете фулфилмента: доход от продажи расходников селлеру
### **КЛЮЧЕВЫЕ СУЩНОСТИ:**
- **Контрагент** → `Counterparty` - связь между организациями для партнерства
- **Поставка** → `SupplyOrder` - заказ товаров/расходников с workflow статусами
- **Рецептура** - состав продукта: товар + услуги + расходники (задается селлером)
### **КОНТЕКСТНО-ЗАВИСИМЫЕ ТЕРМИНЫ:**
#### **SupplyOrder - многосторонний документ**
SupplyOrder представляет собой единый документ, который видится по-разному каждым участником процесса:
**ДЛЯ СОЗДАТЕЛЕЙ (Селлер/Фулфилмент):**
- **Термин**: "Поставка"
- **Контекст**: Они создают поставку товаров и расходников на фулфилмент
- **Включает**: Весь процесс от закупки до приемки на склад
**ДЛЯ ПОСТАВЩИКА (исполнитель товарной части):**
- **Термин**: "Заявка на покупку"
- **Контекст**: Получают запрос на продажу своих товаров/расходников
- **Действия**: Могут одобрить или отклонить в зависимости от наличия
**ДЛЯ ЛОГИСТИКИ (исполнитель транспортной части):**
- **Термин**: "Заявка на доставку"
- **Контекст**: Получают запрос на транспортировку груза
- **Действия**: Могут подтвердить или отклонить в зависимости от возможностей
**ОТОБРАЖЕНИЕ В ИНТЕРФЕЙСЕ КАБИНЕТОВ:**
| Кабинет | Название раздела | Обоснование |
|---------|-----------------|-------------|
| Селлер | "Мои поставки" | Создает и управляет поставками |
| Поставщик | "Заявки на покупку" | Обрабатывает входящие заявки |
| Логистика | "Заявки на доставку" | Управляет транспортировкой |
| Фулфилмент | "Входящие поставки" | Принимает поставки на склад |
**ВАЖНО**: Это один и тот же объект SupplyOrder в базе данных, но каждый участник работает со своей стороной процесса.
#### **Маркет vs Маркетплейс - четкое разделение**
**МАРКЕТ** (`/market`):
- **Что это**: Внутренний раздел системы
- **Функция**: Глобальный каталог всех товаров от всех поставщиков
- **Доступ**: Для всех типов организаций в системе
- **НЕ путать**: С названиями физических рынков типа "ОПТ Маркет"
**МАРКЕТПЛЕЙС** (Wildberries, Ozon):
- **Что это**: Внешние торговые площадки
- **Функция**: Конечные точки продаж для селлеров
- **Интеграция**: Через API ключи в настройках
- **Использование**: "Поставки на маркетплейсы", "Отгрузка на маркетплейсы"
---
## 📑 ОГЛАВЛЕНИЕ
> 📋 **ЧТО ОБЪЕДИНЕНО**:
>
> - rules-unified.md (v3.0) - общая база знаний системы
> - fulfillment-cabinet-rules.md (v1.0) - детализация кабинета фулфилмента
> - Устранены все несоответствия в терминах, последовательностях и детализации
### 🏗️ **АРХИТЕКТУРА И ОСНОВЫ**
1. [🎯 Основные принципы системы](#1--основные-принципы-системы)
2. [📦 Типизация предметов](#2--типизация-предметов)
3. [🏢 Структура кабинетов](#3--структура-кабинетов)
4. [🔐 Система ролей и доступов](#4--система-ролей-и-доступов)
### 🚚 **WORKFLOW И ПРОЦЕССЫ**
5. [🚚 Workflow поставок](#5--workflow-поставок)
6. [🔄 Процесс создания продукта](#6--процесс-создания-продукта)
7. [📊 Система учета движения товаров](#7--система-учета-движения-товаров)
### 🏢 **КАБИНЕТЫ СИСТЕМЫ**
8. [🏠 Общие правила кабинетов](#8--общие-правила-кабинетов)
9. [🏠 Кабинет селлера (детальные правила)](#9--кабинет-селлера-детальные-правила)
10. [🏪 Кабинет поставщика](#10--кабинет-поставщика)
11. [🏭 Кабинет фулфилмента](#11--кабинет-фулфилмента)
12. [🚚 Кабинет логистики](#12--кабинет-логистики)
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
13. [🤝 Система партнерства и контрагентов](#13--система-партнерства-и-контрагентов)
### 🌐 **ИНТЕГРАЦИИ И ФУНКЦИИ**
14. [🌐 Интеграции с системой](#14--интеграции-с-системой)
15. [📊 Статистика и аналитика](#15--статистика-и-аналитика)
16. [📱 Правила UI/UX и интерфейса](#16--правила-uiux-и-интерфейса)
17. [⚠️ Критические запреты](#17--критические-запреты)
### 🛠️ **ТЕХНИЧЕСКИЕ ПРАВИЛА**
18. [🛠️ GraphQL и TypeScript правила](#18--graphql-и-typescript-правила)
19. [🔧 Архитектурные принципы](#19--архитектурные-принципы)
20. [🎯 Правила качества кода](#20--правила-качества-кода)
21. [🔍 Диагностика и решение проблем](#21--диагностика-и-решение-проблем)
### 📋 **ПРИЛОЖЕНИЯ**
22. [📋 Категории товаров и расходников](#22--категории-товаров-и-расходников)
23. [🎖️ Приоритеты разработки](#23--приоритеты-разработки)
### 🚨 **КРИТИЧЕСКИЕ СИТУАЦИИ**
24. [🚨 Критические ситуации и Edge Cases](#-критические-ситуации-и-edge-cases)
### 📎 **ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ**
25. [📎 Технические приложения (GraphQL, компоненты)](#24--технические-приложения)
---
## 🏷️ РЕЕСТР СУЩНОСТЕЙ СИСТЕМЫ
### 📦 **ОСНОВНЫЕ ПРЕДМЕТЫ**
| Сущность | Название в системе | Кабинет создания | Описание | Статус |
| ---------- | -------------------------------------- | ---------------- | ----------------------------------------------- | -------------- |
| Товар | `Product` (type: `PRODUCT`) | Поставщик | Базовый тип товара от поставщика | ✅ Реализовано |
| Расходники | `Product` (type: `CONSUMABLE`) | Поставщик | Материалы и вспомогательные товары | ✅ Реализовано |
| Брак | `Product` (type: `DEFECT`)\* | Фулфилмент | Производная от товара с дефектами | 📋 Планируется |
| Продукт | `Product` (type: `FINISHED_PRODUCT`)\* | Фулфилмент | Готовый к продаже товар (производная от товара) | 📋 Планируется |
> **\* Планируется**: Типы `DEFECT` и `FINISHED_PRODUCT` еще не добавлены в Prisma схему
### 🏢 **ОРГАНИЗАЦИИ И РОЛИ**
| Сущность | Название в системе | Основные функции | Статус |
| ---------- | ------------------------------------ | --------------------------------------- | -------------- |
| Поставщик | `Organization` (type: `WHOLESALE`) | Создание товаров, управление поставками | ✅ Реализовано |
| Селлер | `Organization` (type: `SELLER`) | Заказ товаров, управление поставками | ✅ Реализовано |
| Фулфилмент | `Organization` (type: `FULFILLMENT`) | Обработка товаров, управление складом | ✅ Реализовано |
| Логистика | `Organization` (type: `LOGIST`) | Управление доставками | ✅ Реализовано |
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
| Сущность | Название в системе | Описание | Статус |
| ---------- | --------------------- | ------------------------- | -------------- |
| Контрагент | `Counterparty` | Связь между организациями | ✅ Реализовано |
| Заявка | `CounterpartyRequest` | Запрос на сотрудничество | ✅ Реализовано |
---
## 1. 🎯 ОСНОВНЫЕ ПРИНЦИПЫ СИСТЕМЫ
### 1.1 Архитектура системы
**СТРУКТУРА СИСТЕМЫ ПО КАБИНЕТАМ:**
**🏢 КАБИНЕТ ПОСТАВЩИКА** - создает и управляет:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщика
- **РАСХОДНИКИ** (`CONSUMABLE`) - материалы и вспомогательные товары от поставщика
**🏭 КАБИНЕТ ФУЛФИЛМЕНТА** - принимает, обрабатывает и управляет всеми типами:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщиков (принятые на склад)
- **БРАК** (`DEFECT` - планируется) - производная от товара (товар с дефектами)
- **ПРОДУКТ** (`FINISHED_PRODUCT` - планируется) - готовый к продаже товар
- **РАСХОДНИКИ (`CONSUMABLE`)** - единый базовый тип, классифицируется по назначению при использовании:
- **"Операционные расходники"** - используются фулфилментом для выполнения услуг
- **"Производственные расходники"** - используются в рецептурах селлеров для создания продуктов
**🛍️ КАБИНЕТ СЕЛЛЕРА** - заказывает и управляет поставками:
- Создает заказы товаров и расходников
- Управляет поставками на фулфилмент и маркетплейсы
- Отслеживает статусы поставок
### 1.2 Основные принципы разработки
**КРИТИЧЕСКИ ВАЖНЫЕ ПРИНЦИПЫ:**
1. **Строгая типизация**: Каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируется)
2. **Партнерская система**: Все связи между организациями через модель `Counterparty`
3. **Workflow статусов**: Строгая последовательность статусов поставок
4. **Безопасность доступа**: Контроль доступа на уровне GraphQL резолверов
5. **Единый источник истины**: Централизованное управление данными
---
## 2. 📦 ТИПИЗАЦИЯ ПРЕДМЕТОВ
### 2.1 Два реализованных и два планируемых типа предметов
#### **1. ТОВАР** (`PRODUCT` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком
- **СТАТУС**: Может быть активным/неактивным
- **ЗАКАЗ**: Доступен для заказа всеми типами организаций
- **ТРАНСФОРМАЦИЯ**: Может стать ПРОДУКТОМ или БРАКОМ
- **ЦЕНА**: Обязательна, больше 0
#### **2. РАСХОДНИКИ** (`CONSUMABLE` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком как универсальный тип
- **КЛАССИФИКАЦИЯ ПРИ ЗАКАЗЕ**:
- Фулфилмент заказывает → "Расходники фулфилмента"
- Селлер заказывает → "Расходники селлеров"
- **ДОСТУП**: Видны всем типам организаций в маркете
#### **3. БРАК** (`DEFECT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе существующего ТОВАРА при обнаружении дефектов
- **МОМЕНТ СОЗДАНИЯ**: В процессе обработки товара (ШАГ 3 алгоритма создания продукта) при выявлении брака
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **ЗАКАЗ**: ЗАПРЕЩЕН заказ брака
- **СТАТУС**: Всегда неактивен для заказа
- **ЦЕНА**: Для селлера - себестоимость дефектного товара, для фулфилмента - 0
- **WORKFLOW**: Особый процесс списания и утилизации
- **УЧЕТ**: Отдельный учет в статистике потерь
- **ОТОБРАЖЕНИЕ**: Виден только для учета потерь
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `DEFECT` еще не добавлен в схему БД
#### **4. ПРОДУКТ** (`FINISHED_PRODUCT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе ТОВАРА по заказу селлера
- **ИНИЦИАТОР**: Селлер создает заказ с рецептурой, фулфилмент исполняет
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **РЕЦЕПТУРА**: Задается селлером при создании заказа (Товар + Услуга + Расходники)
- **СТАТУСЫ**: "в работе" → "готов к отправке"
- **ЗАКАЗ**: Доступен только в статусе "готов к отправке"
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `FINISHED_PRODUCT` еще не добавлен в схему БД
### 2.2 Обязательные поля карточки
**КРИТИЧЕСКИ ВАЖНО**: Название, артикул, цена > 0, тип предмета
**ИСКЛЮЧЕНИЕ ДЛЯ БРАКА**: Цена может быть 0 для фулфилмента (себестоимость для селлера)
**ОБЯЗАТЕЛЬНО**: Количество (может быть 0 для предзаказа)
**ДЛЯ ПРОИЗВОДНЫХ ТИПОВ**: Обязательная связь с родительским предметом
---
## 3. 🏢 СТРУКТУРА КАБИНЕТОВ
### 3.1 Общие принципы кабинетов
**КАЖДЫЙ КАБИНЕТ ИМЕЕТ:**
1. **Главная страница** (`/dashboard`) - общая информация и статистика
2. **Экономика** (`/economics`) - финансовая аналитика
3. **Универсальные разделы**:
- Маркет (`/market`) - просмотр и заказ товаров
- Партнеры (`/partners`) - управление контрагентами
- Мессенджер (`/messenger`) - связь между организациями
- Настройки (`/settings`) - профиль и API ключи
### 3.2 Специфические разделы по типам организаций
**🏪 ПОСТАВЩИК (`WHOLESALE`):**
- Склад (`/warehouse`) - управление товарами и расходниками
- Поставки (`/supplies`) - обработка заказов от селлеров
**🛍️ СЕЛЛЕР (`SELLER`):**
- Мои поставки (`/supplies`) - управление заказами товаров
- WB Интеграция (`/wb-integration`) - связь с Wildberries
**🏭 ФУЛФИЛМЕНТ (`FULFILLMENT`):**
- Склад фулфилмента (`/fulfillment-warehouse`) - управление всеми типами товаров
- Поставки фулфилмента (`/fulfillment-supplies`) - обработка поставок
- Услуги (`/services`) - управление услугами, логистикой, расходниками
- Сотрудники (`/employees`) - управление персоналом
- Статистика фулфилмента (`/fulfillment-statistics`) - детальная аналитика
**🚚 ЛОГИСТИКА (`LOGIST`):**
- Заявки (`/logistics-requests`) - управление заявками на доставку
- Маршруты (`/routes`) - планирование маршрутов
---
## 4. 🔐 СИСТЕМА РОЛЕЙ И ДОСТУПОВ
### 4.1 Контроль доступа к разделам
**ПРОВЕРКА НА УРОВНЕ КОМПОНЕНТОВ:**
```typescript
{user?.organization?.type === "FULFILLMENT" && (
// Компоненты доступны только фулфилменту
)}
```
**СПЕЦИАЛЬНАЯ ЛОГИКА РОУТИНГА:**
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
// ... другие типы
}
}
```
### 4.2 GraphQL проверки доступа
**В Apollo Client запросах:**
```typescript
const { data } = useQuery(GET_MY_SERVICES, {
skip: user?.organization?.type !== 'FULFILLMENT',
})
```
**В GraphQL резолверах:**
```typescript
if (currentUser.organization.type !== 'FULFILLMENT') {
throw new GraphQLError('Доступно только для фулфилмент центров')
}
```
### 4.3 Контроль доступа к заказам
- **Создатель заказа** - полный доступ к своим заказам
- **Поставщик** - доступ к заказам, где он является поставщиком
- **Фулфилмент-центр** - доступ к заказам, направленным в его центр
- **Логистическая компания** - доступ к заказам для доставки
---
## 5. 🚚 WORKFLOW ПОСТАВОК
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Статусы поставок](#142-статусы-поставок---расширенная-цветовая-система)
### 5.1 Детализированная система статусов
**Статусы SupplyOrder (Заказ поставки):**
1. **PENDING** - Ожидает подтверждения поставщиком
2. **SUPPLIER_APPROVED** - Одобрено поставщиком
3. **CONFIRMED** - Подтвержден (готов к обработке)
4. **LOGISTICS_CONFIRMED** - Подтверждено логистикой
5. **SHIPPED** - Отгружено поставщиком
6. **IN_TRANSIT** - В пути (логистика доставляет)
7. **DELIVERED** - Доставлен на фулфилмент
8. **CANCELLED** - Отменен
### 5.2 Пошаговый процесс поставки
**ЭТАП 1: Создание заказа**
1. Селлер заказывает товар/расходники у поставщика
2. Система создает SupplyOrder со статусом `PENDING`
3. Автоматическое уведомление поставщику
**ЭТАП 2: Обработка поставщиком** 4. Поставщик получает оповещение 5. Поставщик нажимает "Одобрить" 6. Статус меняется на `SUPPLIER_APPROVED`
**ЭТАП 3: Передача в фулфилмент** 7. Поставка отображается в кабинете фулфилмента 8. Фулфилмент выбирает ответственного и логистику 9. Статус меняется на `CONFIRMED`
**ЭТАП 4: Логистическое подтверждение** 10. Логистика подтверждает доставку 11. Статус меняется на `LOGISTICS_CONFIRMED`
**ЭТАП 5: Отгрузка** 12. Поставщик отгружает товар 13. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
**ЭТАП 6: Доставка и приемка** 14. Логистика доставляет на фулфилмент 15. Фулфилмент принимает товар 16. Статус меняется на `DELIVERED`
### 5.3 Система уведомлений
**Обязательные уведомления:**
- Поставщику: о новом заказе
- Фулфилменту: о подтвержденной поставке
- Логистике: о назначении на заявку
- Селлеру: об изменении каждого статуса
---
## 6. 🔄 ПРОЦЕСС СОЗДАНИЯ ПРОДУКТА
> 📌 **СВЯЗАННЫЕ РАЗДЕЛЫ**:
>
> - Типы предметов → См. [раздел 2.2](#22-обязательные-поля-карточки)
> - Склад фулфилмента → См. [раздел 11.2](#112-структура-раздела-склад-фулфилмента)
> - Статистика движения → См. [раздел 7](#7--система-учета-движения-товаров)
### 6.1 Пошаговый алгоритм создания продукта
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Процесс создания продукта](#143-процесс-создания-продукта---визуальный-workflow)
#### **ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ: РЕЦЕПТУРА ЗАДАНА** (селлер)
```
Время: при создании заявки на поставку
Действие: селлер указывает рецептуру продукта
Обязательные компоненты:
✓ Базовый товар (от поставщика)
✓ Услуги фулфилмента (упаковка, маркировка и т.д.)
✓ Расходники (материалы для производства)
Результат: рецептура сохраняется в заявке и передается фулфилменту
```
#### **ШАГ 1: ПОСТУПЛЕНИЕ НА СКЛАД** (автоматически)
```
Время: при смене статуса поставки DELIVERED
Действие: товар переходит в статус "на складе"
Ответственный: система
Результат: +Прибыло в статистике товаров
```
#### **ШАГ 2: ПЛАНИРОВАНИЕ РАБОТЫ** (менеджер фулфилмента)
```
Время: в течение 2 рабочих дней после поступления
Действие: назначение параметров обработки
Ответственный: менеджер фулфилмента
Обязательные поля:
✓ Дедлайн выполнения (не более 5 рабочих дней)
✓ Ответственный исполнитель (из списка сотрудников)
✓ Рецептура (товар + услуги + расходники, указанная селлером в заявке на поставку)
Опциональные поля:
- Место хранения готовых продуктов (зона склада, стеллаж, ячейка)
- Комментарии к работе
Результат: поставка переходит во вкладку "В работе"
```
#### **ШАГ 3: ОБРАБОТКА ТОВАРА** (исполнитель)
```
Время: согласно дедлайну (обычно 1-3 дня)
Действие: физическая обработка товара
Ответственный: назначенный сотрудник
Обязательные действия:
1. Проверка качества товара
2. Фиксация фактического количества
3. Выявление и учет брака
4. Применение рецептуры (услуги + расходники)
5. Создание готового продукта
Точки контроля:
- Соответствие плану/факту
- Качество выполнения услуг
- Расход материалов по норме
УЧЕТ ПЛАН/ФАКТ:
- ПЛАН: Количество товаров из поставки селлера (указано в заказе)
- ФАКТ: Реальное количество после обработки = Брак + Хороший товар
- ДЕТАЛИЗАЦИЯ: Учет ведется по каждому размеру/объему/варианту
- КОРРЕКТИРОВКА: Статистика автоматически обновляется на фактические данные
```
#### **ШАГ 4: КОНТРОЛЬ КАЧЕСТВА** (менеджер/отдел качества)
```
Время: сразу после завершения ШАГ 3
Действие: приемка готовой продукции
Ответственный: менеджер или контролер качества
Критерии приемки:
✓ Соответствие рецептуре селлера
✓ Качество выполненных услуг
✓ Правильность упаковки/маркировки
✓ Полнота комплектации
Результат: продукт готов к отправке или отправлен на доработку
```
#### **ШАГ 5: ЗАВЕРШЕНИЕ** (система + менеджер)
```
Время: после успешного прохождения контроля качества
Действие: финализация процесса
Автоматические действия:
- Создание записи FINISHED_PRODUCT в БД
- Обновление статистики: товар "на складе" → продукт "готов"
- Списание использованных расходников
- Уведомление селлера о готовности
Ручные действия менеджера:
- Подтверждение перехода во вкладку "Выполнено"
- Указание фактических расходов материалов
- Добавление комментариев о выполненной работе
```
### 6.2 Временные рамки и SLA
| Этап | Стандартное время | Максимальное время | Ответственный |
| ----------------- | ----------------- | ------------------ | -------------- |
| Планирование | 1 рабочий день | 2 рабочих дня | Менеджер ФФ |
| Обработка | 2-3 рабочих дня | 5 рабочих дней | Исполнитель |
| Контроль качества | 4 часа | 1 рабочий день | Отдел качества |
| Завершение | 2 часа | 4 часа | Менеджер ФФ |
### 6.3 Управление браком и расхождениями
### 6.4 Детальная рецептура продукта
**РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
- **БАЗОВЫЙ ТОВАР**: Исходный материал (обязательно)
- Артикул товара
- Количество единиц
- Размерная сетка (если применимо)
- **УСЛУГА ФУЛФИЛМЕНТА**: Из каталога услуг фулфилмента
- Тип услуги (глажка, упаковка, маркировка и т.д.)
- Количество применений
- Специальные требования
- **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
- Фирменная упаковка
- Этикетки, бирки
- Дополнительные аксессуары
- **РАСХОДНИК ФУЛФИЛМЕНТА**: Материалы фулфилмента (опционально)
- Стандартная упаковка
- Защитные материалы
- Маркировочные элементы
- **СВЯЗЬ С МАРКЕТПЛЕЙСОМ**: Привязка к карточке (опционально)
- ID карточки на маркетплейсе
- Артикул маркетплейса
- Особые требования МП
**ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
### 6.5 Учет план/факт в процессе работы (без брака)
**ПЛАН**: Количество товара из поставки селлера
**ФАКТ**: Реальное количество после пересчета (работник фулфилмента производит сортировку при пересчете)
**ФИКСАЦИЯ ПОТЕРЬ:**
- **КОГДА**: В процессе работы (вкладка "В работе")
- **ЧТО**: Недостача, повреждения (без создания записей брака)
- **КАК**: Корректировка количества в статистике
**WORKFLOW СОЗДАНИЯ ПРОДУКТА:**
1. Товар поступает на склад фулфилмента (статус "на складе")
2. Товар берется в работу (переход в статус "в обработке")
3. Исполнитель производит пересчет и сортировку
4. Создается готовый продукт (тип FINISHED_PRODUCT)
5. Продукт готов к отправке на маркетплейсы
**ВЛИЯНИЕ НА СТАТИСТИКУ:**
- При принятии поставки: +План в статистику
- При выявлении факта: корректировка на реальные данные
- **ФОРМУЛА**: Факт = Потери + Хороший товар
_Где потери - это недостача/повреждения, выявленные при пересчете и сортировке_
- **ЛОГИКА**: Фактическое количество = сумма всех пересчитанных предметов
- **ПЛАН/ФАКТ**: Корректировка статистики при выявлении расхождений
---
> 🚧 **БУДУЩАЯ ФУНКЦИОНАЛЬНОСТЬ**: Система статусов товаров в фулфилменте будет детализирована позже
## 7. 📊 СИСТЕМА УЧЕТА ДВИЖЕНИЯ ТОВАРОВ
### 7.1 Принципы учета в фулфилменте
**ОСНОВНЫЕ ПРИНЦИПЫ:**
- **ПРИХОД**: Товары поступают через принятые поставки (из состояния "в пути" → "на складе")
- **ОБРАБОТКА**: Товары переходят в статус "в работе" для создания продуктов
- **РАСХОД**: Товары убывают при отгрузке, списании, возврате, превращении в продукты
- **УЧЁТ**: Ведется учет прихода и расхода для каждого типа предметов
- **ВИЗУАЛИЗАЦИЯ**: Движение отображается в дополнительных значениях
### 7.2 Дополнительные и основные значения
**ДОПОЛНИТЕЛЬНЫЕ ЗНАЧЕНИЯ (показатели движения):**
- **ПРИБЫЛО**: Количество предметов, поступивших на склад
- **УБЫЛО**: Количество предметов, списанных со склада
- **ВЛИЯНИЕ**: От этих значений зависят основные значения (общее количество)
**ОСНОВНЫЕ ЗНАЧЕНИЯ (текущие остатки):**
- **ОПРЕДЕЛЕНИЕ**: Итоговое количество предметов на складе
- **РАСЧЁТ**: Основные значения = Предыдущие остатки + Прибыло - Убыло
- **ОТОБРАЖЕНИЕ**: Показываются в каждом модуле статистики
- **РАЗДЕЛЕНИЕ ТОВАРОВ**:
- Товары "на складе" - готовы к обработке
- Товары "в обработке" - находятся в процессе создания продукта
---
## 8. 🏠 ОБЩИЕ ПРАВИЛА КАБИНЕТОВ
### 8.1 Универсальная структура кабинетов
**ВСЕ ТИПЫ КАБИНЕТОВ** включают следующие обязательные разделы:
#### 8.1.1 Страница "Главная"
**СТАТУС**: Реализовано
**ДОСТУП**: Через навигацию в sidebar для всех типов кабинетов
**СОДЕРЖАНИЕ**: Универсальная страница с типо-зависимыми компонентами
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый тип кабинета должен иметь страницу "Главная"
- **НАВИГАЦИЯ**: Доступ через кнопку в sidebar (первая в списке)
- **УНИВЕРСАЛЬНОСТЬ**: Одинаковая структура навигации для всех кабинетов
- **РОУТ**: `/home` с универсальным компонентом HomePageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента: SellerHomePage, FulfillmentHomePage, WholesaleHomePage, LogistHomePage
#### 8.1.2 Раздел "Экономика"
**СТАТУС**: Реализовано в системе
**РАСПОЛОЖЕНИЕ**: Перед настройками в каждом кабинете
**СОДЕРЖАНИЕ**: Пустые разделы-заглушки с пометкой "будет добавлен позже"
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый кабинет имеет раздел "Экономика"
- **РОУТ**: `/economics` с универсальным компонентом EconomicsPageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента экономики: SellerEconomicsPage, FulfillmentEconomicsPage, WholesaleEconomicsPage, LogistEconomicsPage
- **КНОПКА**: "Экономика" в sidebar навигации перед настройками
- **БЕЗОПАСНОСТЬ**: Проверки доступа и безопасности в экономических компонентах
#### 8.1.3 Общие разделы для всех кабинетов
**УНИВЕРСАЛЬНЫЕ РАЗДЕЛЫ** (доступны всем типам):
- 🏠 **Главная** - основная страница кабинета (реализовано)
- 🛒 **Маркет** - просмотр и заказ товаров
- 🤝 **Партнеры** - управление контрагентами
- 💬 **Мессенджер** - внутренняя связь
- 💰 **Экономика** - финансовая аналитика (реализовано)
- ⚙️ **Настройки** - профиль и конфигурация
**СПЕЦИАЛИЗИРОВАННЫЕ РАЗДЕЛЫ** (зависят от типа кабинета):
- Определяются в соответствующих разделах каждого кабинета
### 8.2 Правила sidebar навигации
#### 8.2.1 Структура навигации
**ОБЩИЙ ПРИНЦИП**:
- Условное отображение: `{user?.organization?.type === "TYPE" && (...)}`
- Адаптивность: сворачиваемый sidebar с `getSidebarMargin()`
- Состояния активности: подсветка текущего раздела
**ПОРЯДОК РАЗДЕЛОВ В SIDEBAR**:
1. 🏠 **Главная** (реализовано для всех)
2. **Специализированные разделы** (зависят от типа кабинета)
3. 🛒 **Маркет** (универсальный)
4. 🤝 **Партнеры** (универсальный)
5. 💬 **Мессенджер** (универсальный)
6. 💰 **Экономика** (универсальный, реализовано)
7. ⚙️ **Настройки** (универсальный)
8. **Выход** (универсальный)
#### 8.2.2 Типо-зависимая логика
**АДАПТИВНЫЙ РОУТИНГ**:
```typescript
// Пример: кнопка "Поставки" ведет на разные страницы
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/supplies')
break
case 'LOGIST':
router.push('/logistics-orders')
break
}
}
```
---
## 9. 🏠 КАБИНЕТ СЕЛЛЕРА (ДЕТАЛЬНЫЕ ПРАВИЛА)
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Кабинет селлера](#145-кабинет-селлера)
### 9.1 Структура раздела "Мои поставки"
#### **🏢 ПОСТАВКИ НА ФУЛФИЛМЕНТ**:
- **Товар** - поставка товаров для создания продуктов
- **Карточки** - поставка через WB API с рецептурой (результат: WildberriesSupply)
- **Поставщики** - заказ товаров у поставщиков с рецептурой (результат: SupplyOrder)
- **Расходники селлера** - поставка материалов для товаров селлера
#### **🛒 ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ** _(планируется)_:
- **Wildberries** - прямые поставки на WB
- **Ozon** - прямые поставки на Ozon
### 9.2 UI структура создания поставки расходников селлера
#### **📄 Структура страницы создания поставки:**
**ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):**
**БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_
- **Заголовок**: Минималистичный "🏢 Поставщики" без лишних элементов
- **Поиск**: Компактное поле справа "Поиск поставщиков..." (w-64)
- **Отображение**: Карточки поставщиков из раздела "Партнеры" в адаптивной сетке
- **Выбор**: Клик выделяет карточку поставщика
- **Результат**: Загружаются карточки товаров выбранного поставщика в блок 2
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(горизонтальный скролл - НОВЫЙ)_
- **Отображение**: ТОЛЬКО минималистичные карточки товаров 80×112px
- **Содержание**: ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- **Навигация**: Горизонтальный скролл при множестве товаров
- **Выбор**: Клик добавляет товар в детальный каталог
- **Результат**: Товар добавляется в блок 3 для управления поставкой
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Отображение**: Детальные карточки выбранных товаров
- **Управление**: Количество, параметры, настройки поставки
- **Результат**: Формирование окончательной поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель)_
- **Отображение**: Корзина поставки + настройки
- **Управление**: Фулфилмент-центр, дата, логистика
#### **9.2.1 Детальные правила горизонтального скролла поставщиков**
**СТРУКТУРА И ОТОБРАЖЕНИЕ:**
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px, включает заголовок + контейнер скролла
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки
**РАЗМЕРЫ И АДАПТИВНОСТЬ:**
- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"
**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
**Критическая Flex-архитектура:**
```css
.parent-container {
display: flex;
gap: 16px;
min-height: 0;
}
.left-block {
flex: 1;
min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
display: flex;
flex-direction: column;
}
.suppliers-container {
height: 180px; /* Общая высота блока */
flex-shrink: 0;
min-width: 0; /* Предотвращает растяжение */
}
.right-block {
width: 384px; /* w-96 */
flex-shrink: 0; /* Защита от сжатия */
}
```
**Контейнер скролла:**
```css
.suppliers-block {
display: flex;
overflow-x: auto;
scroll-behavior: smooth;
gap: 12px;
padding: 0 16px 8px 16px; /* px-4 pb-2 */
height: 176px; /* h-44 */
scrollbar-width: thin;
scrollbar-color: #64748b33 transparent;
}
.suppliers-block:hover {
scrollbar-color: #cbd5e0 #64748b22;
}
.supplier-card {
flex-shrink: 0;
width: 216px; /* Десктоп */
height: 92px; /* Фиксированная высота */
padding: 8px; /* p-2 */
transition: all 0.2s ease;
}
```
**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**
**Структура (3 строки в 92px высоты):**
- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)
**Элементы:**
- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)
**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**
- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`
**ДОСТУПНОСТЬ:**
- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных
#### **9.2.2 Правила блока "Карточки товаров" (Блок 2)**
**НАЗНАЧЕНИЕ И ЛОГИКА:**
- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров
**АРХИТЕКТУРА И РАЗМЕРЫ:**
- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере
**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**
- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств
**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**
- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный
**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)
#### **9.2.3 Правила Блока 3 "Детальный каталог товаров"**
**НАЗНАЧЕНИЕ И СТРУКТУРА:**
- **Контент**: Детальные карточки выбранных товаров с полным управлением
- **Верхняя панель**: Выбор даты + Выбор Fulfillment + Поиск
- **Основная область**: Сетка карточек товаров с детальной информацией
#### **9.2.3.1 Структура верхней панели Блока 3**
**МИНИМАЛИСТИЧНАЯ ПАНЕЛЬ УПРАВЛЕНИЯ:**
- **Выбор даты поставки**: DatePicker для планирования поставки
- **Выбор Fulfillment-центра**: Select dropdown со списком доступных фулфилментов
- **Поиск по товарам**: Input с иконкой поиска и placeholder
- **Компоновка**: Горизонтальная строка с равномерным распределением
**ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ:**
```tsx
// Структура компонентов панели
<div className="flex items-center gap-4 p-4 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl mb-4">
<DatePicker placeholder="Дата поставки" />
<Select placeholder="Выберите фулфилмент">
<SelectContent>
{fulfillmentCenters.map((center) => (
<SelectItem value={center.id}>{center.name}</SelectItem>
))}
</SelectContent>
</Select>
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-white/40" />
<Input placeholder="Поиск товаров..." className="pl-10 glass-input" />
</div>
</div>
```
#### **9.2.3.2 Структура основной области карточек**
**СЕТКА ТОВАРОВ:**
- **Адаптивная сетка**: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4`
- **Детальные карточки**: Полная информация + количество + управление
- **Состояния**: Default, Selected, Editing
- **Интерактивность**: Изменение количества, удаление, настройки рецептуры
**ФУНКЦИОНАЛЬНОСТЬ ПАНЕЛИ:**
- **Выбор даты**: Планирование времени поставки (обязательное поле)
- **Выбор фулфилмента**: Определение исполнителя поставки (обязательное поле)
- **Поиск**: Фильтрация товаров в каталоге по названию/артикулу
- **Валидация**: Блокировка создания поставки без заполнения даты и фулфилмента
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **Пустой каталог**: Заглушка "Добавьте товары"
- **Нет фулфилментов**: Сообщение "Настройте партнерство с фулфилмент-центрами"
- **Поиск без результатов**: "По запросу ничего не найдено"
#### **9.2.2.1 Структура контейнера Блока 2**
**ДВУХУРОВНЕВАЯ АРХИТЕКТУРА:**
**УРОВЕНЬ 1 - Внешний контейнер (блок):**
```jsx
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0">
```
- **Назначение**: Визуальное обрамление блока, единство с другими блоками
- **Стилизация**: Стеклянный эффект с размытием и полупрозрачностью
- **Рамка**: Тонкая белая рамка border-white/20 с закруглёнными углами
- **Поведение**: flex-shrink-0 предотвращает сжатие блока
**УРОВЕНЬ 2 - Внутренний контейнер (скролл):**
```jsx
<div className="flex gap-3 overflow-x-auto p-4" style={{ scrollbarWidth: 'thin' }}>
```
- **Назначение**: Горизонтальная прокрутка карточек товаров
- **Раскладка**: Flex с промежутками gap-3 (12px) между карточками
- **Отступы**: padding p-4 (16px) со всех сторон
- **Скролл**: overflow-x-auto с тонкой полосой прокрутки
- **Поведение**: Автоматическое появление скролла при превышении ширины
**ПРАВИЛА КОНТЕЙНЕРОВ:**
- Внешний контейнер НЕ содержит заголовков, иконок, описаний
- Внутренний контейнер содержит ТОЛЬКО карточки товаров
- Высота адаптируется под размер карточек (80×112px + отступы)
- Визуальное единство со всеми блоками формы поставки
**ТЕХНИЧЕСКИЕ ПРАВИЛА:**
- **Условие отображения**: selectedSupplier && products.length > 0
- **Источник данных**: products массив из GraphQL запроса organizationProducts
- **Реактивность**: Автоматическое обновление при смене поставщика
- **Производительность**: React.memo для карточек при большом количестве товаров
- **Доступность**: Клавиатурная навигация (Tab, Enter для выбора)
**UX ПРАВИЛА ВЗАИМОДЕЙСТВИЯ:**
- **Скролл**: Автоматическое появление при превышении ширины контейнера
- **Индикация загрузки**: Скелетоны карточек во время загрузки товаров
- **Пустое состояние**: Скрытие блока при отсутствии поставщика или товаров
- **Фокус**: Первая карточка получает фокус при загрузке товаров
- **Навигация**: Стрелки ←→ для перемещения между карточками
**СОСТОЯНИЯ БЛОКА:**
- **Скрыт**: При отсутствии выбранного поставщика
- **Скрыт**: При отсутствии товаров у поставщика
- **Активен**: При наличии поставщика и товаров
- **Загрузка**: Показ скелетонов карточек во время запроса
**ПРАВИЛА ПРОИЗВОДИТЕЛЬНОСТИ:**
- **Виртуализация**: При количестве товаров > 100
- **Ленивая загрузка изображений**: loading="lazy" для всех изображений
- **Мемоизация**: React.memo для компонентов карточек
- **Дебаунс**: 300мс для поисковых запросов (если будет добавлен поиск)
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные устройства**: Свайп для горизонтальной прокрутки
- **Планшеты**: Сохранение размеров карточек 80×112px
- **Десктоп**: Полная функциональность с клавиатурной навигацией
- **Высокие разрешения**: Сохранение пропорций и читаемости
**ПРАВИЛА БЕЗОПАСНОСТИ И ВАЛИДАЦИИ:**
- **Валидация данных**: Проверка существования product.id перед добавлением
- **Дубликаты**: Предотвращение добавления одного товара дважды в детальный каталог
- **Санитизация**: Безопасное отображение названий товаров (XSS защита)
- **Обработка ошибок**: Graceful degradation при ошибках загрузки изображений
- **Защита от спама**: Дебаунс кликов 200мс для предотвращения множественных добавлений
**ПРАВИЛА ИНТЕГРАЦИИ С ДРУГИМИ БЛОКАМИ:**
- **Блок 1 (Поставщики)**: Слушает изменения selectedSupplier для обновления товаров
- **Блок 3 (Детальный каталог)**: Передаёт выбранные товары через setAllSelectedProducts
- **Блок 4 (Корзина)**: Товары добавляются в корзину из Блока 3, не напрямую из Блока 2
- **Синхронизация состояний**: Реактивное обновление при изменении данных в любом блоке
**ПРАВИЛА АНАЛИТИКИ И МЕТРИК:**
- **Отслеживание кликов**: Логирование добавления товаров в детальный каталог
- **Метрики производительности**: Время загрузки товаров поставщика
- **Пользовательское поведение**: Количество просмотренных товаров на поставщика
- **A/B тестирование**: Готовность к тестированию различных размеров карточек
**ПРАВИЛА ЛОКАЛИЗАЦИИ:**
- **Alt-текст изображений**: На языке интерфейса пользователя
- **Направление скролла**: RTL поддержка для арабского/иврита
- **Размеры карточек**: Неизменны для всех локалей (80×112px)
- **Сообщения об ошибках**: Локализованные уведомления при проблемах загрузки
#### **9.2.1.1 Заголовок и поиск Блока 1**
**МИНИМАЛИСТИЧНЫЙ ДИЗАЙН:**
```jsx
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-white/40 h-4 w-4" />
<Input
placeholder="Поиск поставщиков..."
className="bg-white/5 border-white/10 text-white placeholder:text-white/50 pl-10 h-9"
/>
</div>
</div>
</div>
```
**ПРАВИЛА ЗАГОЛОВКА:**
- **Иконка**: Building2 h-5 w-5 text-blue-400 (без фонового контейнера)
- **Текст**: "Поставщики" (убран избыточный "товаров")
- **Размер**: text-lg font-semibold (увеличен для лучшей читаемости)
- **БЕЗ бэджа**: Убран избыточный бэдж "Создание поставки"
- **Выравнивание**: flex items-center gap-2 (компактное)
**ПРАВИЛА ПОИСКА:**
- **Позиция**: Справа от заголовка (justify-between)
- **Ширина**: w-64 (256px) фиксированная ширина
- **Плейсхолдер**: "Поиск поставщиков..." (конкретное описание)
- **Иконка**: Search h-4 w-4 слева в поле
- **Стили**: Стандартные glass-эффекты, focus:border-white/20
**ПРАВИЛА КНОПКИ "НАЙТИ В МАРКЕТЕ":**
- **Условие**: Показывается только при allCounterparties.length === 0
- **Позиция**: Отдельный блок под заголовком (mt-4)
- **НЕ интегрирована**: В поле поиска (отдельно)
- **Стили**: glass-secondary outline button размера sm
#### **9.2.1.2 Структура карточки поставщика в Блоке 1**
**МИНИМАЛИСТИЧНАЯ КАРТОЧКА ПОСТАВЩИКА:**
**СТРУКТУРА ИНФОРМАЦИИ:**
```jsx
<div className="flex items-start gap-2">
<OrganizationAvatar organization={supplier} size="sm" />
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm truncate">{supplier.name || supplier.fullName}</h4>
<div className="flex items-center gap-2 mt-1">
<p className="text-white/60 text-xs font-mono">ИНН: {supplier.inn}</p>
{supplier.market && <Badge className="market-badge">{getMarketLabel(supplier.market)}</Badge>}
</div>
</div>
</div>
```
**ПРАВИЛА СОДЕРЖАНИЯ КАРТОЧКИ:**
**✅ ОСТАВИТЬ:**
- **Аватар организации**: OrganizationAvatar size="sm" слева
- **Название поставщика**: supplier.name || supplier.fullName (приоритет name)
- **ИНН**: font-mono, text-white/60, с префиксом "ИНН: "
**🔸 ДОБАВИТЬ:**
- **Принадлежность к рынку**: Badge с названием рынка из supplier.market
- **Рынки**: "Садовод", "ТЯК Москва" и другие из Organization.market поля
**❌ УБРАТЬ:**
- **Рейтинг**: Звездочка и цифра rating (избыточно)
- **Тип бэдж**: "Поставщик" badge (и так понятно из контекста)
- **Адрес**: supplier.address (занимает место, не критично)
**СТИЛИ РЫНОЧНЫХ БЭДЖЕЙ:**
- **Садовод**: bg-green-500/20 text-green-300 border-green-500/30
- **ТЯК Москва**: bg-blue-500/20 text-blue-300 border-blue-500/30
- **По умолчанию**: bg-gray-500/20 text-gray-300 border-gray-500/30
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные**: Сохранение структуры, truncate для длинных названий
- **Планшеты/десктоп**: Полное отображение в сетке
- **Малые экраны**: line-clamp-1 для названия организации
**СОСТОЯНИЯ КАРТОЧКИ:**
- **Default**: bg-white/5 border-white/10
- **Hover**: hover:border-white/20 hover:bg-white/10
- **Selected**: bg-white/15 border-white/40 shadow-lg
- **Disabled**: opacity-50 cursor-not-allowed (при недоступности)
**ПРАВИЛА ИНТЕГРАЦИИ С РЫНКАМИ:**
**ИСТОЧНИК ДАННЫХ:**
- **Поле БД**: Organization.market (String?) - поле принадлежности к рынку
- **Настройка**: Указывается в настройках кабинета поставщика
- **Опциональность**: Поле может быть пустым (рынок не указан)
**ФУНКЦИЯ getMarketLabel():**
```jsx
const getMarketLabel = (market?: string) => {
const marketLabels = {
'sadovod': 'Садовод',
'tyak-moscow': 'ТЯК Москва',
'opt-market': 'ОПТ Маркет',
}
return marketLabels[market as keyof typeof marketLabels] || market
}
```
**СТИЛИ ДЛЯ РЫНКОВ:**
```jsx
const getMarketBadgeStyle = (market?: string) => {
const styles = {
'sadovod': 'bg-green-500/20 text-green-300 border-green-500/30',
'tyak-moscow': 'bg-blue-500/20 text-blue-300 border-blue-500/30',
'opt-market': 'bg-purple-500/20 text-purple-300 border-purple-500/30',
}
return styles[market as keyof typeof styles] || 'bg-gray-500/20 text-gray-300 border-gray-500/30'
}
```
**ПРАВИЛА ОТОБРАЖЕНИЯ:**
- **Условие**: Показывать badge только если supplier.market существует
- **Размер**: text-xs для соответствия ИНН
- **Позиция**: Справа от ИНН в той же строке
- **Приоритет**: Рынок важнее типа организации для селлера
### 9.2.2.2 ПРАВИЛО ПЕРСИСТЕНТНОСТИ ВЫБРАННЫХ ТОВАРОВ
**🎯 ОСНОВНОЙ ПРИНЦИП:**
Выбранные товары в детальном каталоге (блок 3) сохраняются при смене поставщика и могут быть удалены только явным действием пользователя.
**🔄 WORKFLOW СЦЕНАРИИ:**
**СЦЕНАРИЙ 1: Добавление товаров от разных поставщиков**
1. Пользователь выбирает Поставщика А
2. Добавляет Товар 1 и Товар 2 в детальный каталог
3. Переключается на Поставщика Б
4. Товар 1 и Товар 2 остаются в блоке 3
5. Добавляет Товар 3 от Поставщика Б
6. В блоке 3: Товар 1, Товар 2 (от А) + Товар 3 (от Б)
**СЦЕНАРИЙ 2: Визуальная индикация в блоке 2**
- При переключении на поставщика, товары которого уже есть в блоке 3, показываются как "выбранные"
- Товары от других поставщиков в блоке 2 не отображаются
**🛠️ ТЕХНИЧЕСКИЕ ПРАВИЛА:**
**Состояние selectedProductsForDetailView:**
- Глобальное состояние всех выбранных товаров
- НЕ зависит от текущего поставщика
- НЕ очищается при смене поставщика
- Очищается только явными действиями пользователя
**Единственные способы удаления:**
1. Кнопка "Удалить из каталога" в карточке товара (блок 3)
2. Кнопка "Очистить каталог" в заголовке блока 3
3. НЕ при смене поставщика
**🎨 UX ПРАВИЛА:**
- Счетчик товаров: "Детальный каталог (X товаров от Y поставщиков)"
- Визуальная индикация выбранных товаров в блоке 2
- Информация о поставщике для каждого товара в блоке 3
**СОСТОЯНИЯ БЛОКА:**
- **Не выбран поставщик**: Заглушка "Выберите поставщика для просмотра товаров"
- **Поставщик выбран, нет товаров**: "У поставщика нет товаров"
- **Поставщик выбран, есть товары**: Карточки товаров с горизонтальным скроллом
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Горизонтальная прокрутка мышью, клавишами ←→
- **Выбор**: Клик → добавление в Блок 3 с анимацией
- **Состояния карточек**: Default, Selected, Active (при добавлении)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-5 карточек**: Скролл неактивен, выравнивание по левому краю
- **6+ карточек**: Полноценный горизонтальный скролл
- **Поиск**: Фильтрация карточек в реальном времени
- **Загрузка**: Скелетон-анимация при смене поставщика
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Содержание**: Детальный каталог товаров для управления поставкой
- **Источник**: Товары, добавленные из Блока 2 "Карточки товаров"
- **Сортировка**: По цене, названию, категории
- **Фильтры**: По категории, ценовому диапазону
- **Карточка расходника**:
- Фото, название, цена, остаток, категория
- Количество в комплекте (если есть комплектность)
- Поле ввода количества (единицы или комплекты)
- Кнопки +/- для изменения количества
- **Действие**: Клик добавляет расходник в корзину
**БЛОК 3: КОРЗИНА** _(правая часть)_
- **Содержание корзины**:
- Количество видов расходников
- По каждому расходнику: название, количество, цена за единицу, сумма
- Общая сумма всех расходников
- **Управление**: Изменение количества, удаление позиций
- **Валидация**: Проверка остатков у поставщика
- **Настройки поставки**:
- Выбор фулфилмент-центра (dropdown из партнеров)
- Дата поставки (по умолчанию - дата создания, нельзя выбрать прошедшую)
- **Кнопка**: "Создать поставку"
### 9.3 Многоуровневые таблицы для отображения поставок
#### **📊 Структура многоуровневой таблицы:**
**ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- Порядковый номер поставки (от большего к меньшему)
- Количество видов расходников селлера
- Стоимость всей поставки
- Количество категорий
- Статус поставки
- Кнопка раскрытия/сворачивания
**ВТОРОЙ УРОВЕНЬ** _(раскрывается по клику)_:
- Название расходника селлера
- Количество
- Цена за единицу
- Общая стоимость позиции
- Категория
- Поставщик
- **Режим**: Только просмотр (редактирование недоступно после создания)
**ПРАВИЛА ОТОБРАЖЕНИЯ**:
- По умолчанию таблица свернута, показан только первый уровень
- Клик по строке или кнопке раскрывает второй уровень
- Анимация раскрытия плавная (300ms)
- Визуальная индикация раскрытого состояния (поворот стрелки, изменение фона)
### 9.4 Правила кнопки "Создать поставку" в разделе "Мои поставки"
#### **9.4.1 Общие принципы**
- **КОНТЕКСТНОСТЬ**: Кнопка создания появляется только в активном табе
- **РАСПОЛОЖЕНИЕ**: Правая часть строки таба, на том же уровне что и название
- **СТИЛИСТИКА**: В том же стиле что и сами табы (соответствует уровню иерархии)
- **ФУНКЦИОНАЛЬНОСТЬ**: Кнопка ведет на страницу создания поставки соответствующего типа
#### **9.4.2 Размещение кнопок по табам**
**УРОВЕНЬ 2 (Подтабы фулфилмента):**
- **📦 Товар → Карточки**: Кнопка "Создать поставку" → `/supplies/create-cards`
- **📦 Товар → Поставщики**: Кнопка "Создать поставку" → `/supplies/create-suppliers`
- **🔧 Расходники селлера**: Кнопка "Создать поставку" → `/supplies/create-consumables`
**УРОВЕНЬ 2 (Подтабы маркетплейсов):**
- **🟣 Wildberries**: Кнопка "Создать поставку" → `/supplies/create-wildberries`
- **🔵 Ozon**: Кнопка "Создать поставку" → `/supplies/create-ozon`
#### **9.4.3 Стили кнопок**
**ДЛЯ УРОВНЯ 2 (h-9):**
```css
/* Размер и отступы */
h-9 px-3 py-1 ml-auto
/* Фон и границы */
bg-white/8 border border-white/20 hover:bg-white/12
/* Текст и иконки */
text-xs font-medium text-white/80 hover:text-white
/* Скругления */
rounded-lg
/* Переходы */
transition-all duration-150
```
**ДЛЯ УРОВНЯ 3 (h-8):**
```css
/* Размер и отступы */
h-8 px-2 py-1 ml-auto
/* Фон и границы */
bg-white/5 border border-white/15 hover:bg-white/8
/* Текст и иконки */
text-xs font-normal text-white/60 hover:text-white/80
/* Скругления */
rounded-md
/* Переходы */
transition-all duration-150
```
#### **9.2.4 Поведение кнопок**
- **ВИДИМОСТЬ**: Кнопка показывается только в активном табе
- **ИКОНКА**: `Plus` размером `h-3 w-3` слева от текста
- **ТЕКСТ**: "Создать" на мобильных, "Создать поставку" на десктопах
- **АДАПТИВНОСТЬ**: Скрытие текста на маленьких экранах (`hidden sm:inline`)
#### **9.2.5 Удаление старой кнопки**
- **УБРАТЬ**: Текущий dropdown "Создать поставку" из верхней части
- **ПРИЧИНА**: Заменяется контекстными кнопками в табах
- **СОХРАНИТЬ**: Стили и логику навигации, но адаптировать под новые роуты
#### **9.2.6 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ**
**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.
##### **9.2.6.1 Размеры и позиционирование**
```tsx
<div className="w-72 flex-shrink-0">
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```
**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:
- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`
##### **9.2.6.2 Автодобавление товаров**
**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.
```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)
if (newQuantity > 0) {
// Автоматически добавляем товар в корзину
updateProductQuantity(product.id, newQuantity)
} else {
// Удаляем товар из корзины при количестве 0
removeFromCart(product.id)
}
}
```
**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`
##### **9.2.6.3 Структура корзины**
**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:
1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом
**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине
##### **9.2.6.4 Единая функция расчета стоимости**
**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:
```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
const product = products.find((p) => p.id === productId)
if (!product) return 0
// Базовая цена товара
let total = (product.pricePerUnit || 0) * quantity
// Добавляем услуги
if (product.services && product.services.length > 0) {
const servicesTotal = product.services.reduce((sum, service) => {
return sum + (service.pricePerUnit || 0) * quantity
}, 0)
total += servicesTotal
}
// Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
if (product.ffConsumables && product.ffConsumables.length > 0) {
const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
}, 0)
total += ffConsumablesTotal
}
// Добавляем расходники продавца
if (product.sellerConsumables && product.sellerConsumables.length > 0) {
const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
return sum + (consumable.pricePerUnit || 0) * quantity
}, 0)
total += sellerConsumablesTotal
}
return total
}
```
##### **9.2.6.5 Синхронизация данных между блоками**
**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:
1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`
**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:
```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```
##### **9.2.6.6 Критические требования**
🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:
- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов
🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:
- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества
🚨 **UX КОНСИСТЕНТНОСТЬ**:
- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных
### 9.3 Структура страницы "Мои поставки" - Трёхблочная архитектура
#### **9.3.1 Обязательная структура страницы**
**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков
```
┌─────────────────────────────────────────┐
│ 1. БЛОК ТАБОВ (навигация) │
│ - Фиксированная высота │
│ - Glass-эффект │
│ - Иерархическая структура │
├─────────────────────────────────────────┤
│ 2. БЛОК СТАТИСТИКИ (метрики) │
│ - Контекстные данные │
│ - 4 карточки в ряд (desktop) │
│ - Динамическое обновление │
├─────────────────────────────────────────┤
│ 3. ОСНОВНОЙ БЛОК (контент) │
│ - Сохраняет весь функционал │
│ - Таблицы, фильтры, действия │
│ - Высота до низа sidebar │
└─────────────────────────────────────────┘
```
#### **9.3.2 Блок статистики - контекстные метрики**
**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов
**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**
- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути
**Для пути "Фулфилмент → Расходники селлера":**
- Всего поставок
- Активных поставок
- Видов расходников
- Критические остатки
**Для путей "Маркетплейсы → Wildberries/Ozon":**
- Поставок на маркетплейс
- Товаров отправлено
- Возвраты за неделю
- Эффективность поставок
#### **9.3.3 Высота основного блока**
**ФОРМУЛА РАСЧЕТА**:
```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```
**ПРАВИЛО ВЫРАВНИВАНИЯ**:
- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`
#### **9.3.4 Сохранение функционала**
**КРИТИЧЕСКИ ВАЖНО**: При добавлении блока статистики весь существующий функционал сохраняется:
- Таблицы с данными поставок
- Фильтры и сортировка
- Кнопки действий
- Детализация при клике
- Пагинация
- Поиск
**ЗАПРЕЩЕНО**:
- Удалять существующие компоненты
- Изменять логику работы таблиц
- Нарушать существующие API вызовы
### 9.4 Табы "Карточки" и "Поставщики" - объединённая логика
#### **9.4.1 Принцип единого типа предмета**
**КЛЮЧЕВОЕ ПРАВИЛО**: Табы "Карточки" и "Поставщики" - это два способа создания поставок одного типа предмета (ТОВАР)
**СПОСОБЫ СОЗДАНИЯ**:
- **Карточки** - импорт товаров через WB API с автоматическим созданием поставки
- **Поставщики** - прямой заказ товаров у поставщика с указанием рецептуры
**РЕЗУЛЬТАТ**: Оба способа создают `SupplyOrder` с товарами типа `PRODUCT`
#### **9.4.2 Общая статистика**
**ПРАВИЛО**: Блок статистики показывает ОДИНАКОВЫЕ данные для обоих табов
**МЕТРИКИ ДЛЯ ТАБОВ "КАРТОЧКИ" И "ПОСТАВЩИКИ"**:
- Всего поставок товаров (из всех источников)
- Активных поставок товаров (в работе)
- Сумма активных поставок товаров
- Товаров в пути (все способы доставки)
**ЗАПРЕЩЕНО**: Разделять статистику по способу создания
#### **9.4.3 Общий основной блок**
**СОДЕРЖИМОЕ**: Единая таблица всех поставок товаров
**ИСТОЧНИКИ ДАННЫХ**:
- Поставки, созданные через импорт карточек WB
- Поставки, созданные через заказ у поставщиков
- Все промежуточные и завершённые поставки
**РАЗЛИЧИЯ ТАБОВ**:
- Только кнопки создания ведут на разные страницы
- Таб "Карточки": `/supplies/create-cards`
- Таб "Поставщики": `/supplies/create-suppliers`
### 9.5 Создание поставки расходников селлера
#### **Структура страницы**:
**БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_:
- Карточки поставщиков из раздела "Партнеры"
- Горизонтальный скролл при превышении ширины
- Выбор только одного поставщика одновременно
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(адаптивная высота - НОВЫЙ БЛОК)_:
- ТОЛЬКО минималистичные карточки товаров 80×112px
- ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- Горизонтальный скролл при множестве товаров
- Клик добавляет товар в блок 3
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(flex-1, детальный каталог)_:
- Детальные карточки выбранных товаров
- Управление количеством и параметрами поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель, 384px)_:
- Корзина поставки с выбранными товарами
- Настройки поставки (фулфилмент-центр, дата, логистика)
- Сортировка: цена, название, категория
- Фильтры: категория, ценовой диапазон
- Карточка с полем ввода количества и кнопками +/-
**БЛОК 3: КОРЗИНА** _(правая часть)_:
- **РАСПОЛОЖЕНИЕ**: Правая часть экрана
- **СОДЕРЖАНИЕ**:
- Счетчик видов расходников
- Детализация по каждому расходнику (название, количество, цена, сумма)
- Общая сумма всех расходников
- **УПРАВЛЕНИЕ**:
- Изменение количества (с валидацией остатков)
- Удаление позиций
- **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ**:
- Выбор фулфилмент-центра (из партнеров)
- Дата поставки (не прошедшая, по умолчанию - текущая)
### 9.6 Многоуровневая таблица поставок
#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
- Порядковый номер поставки
- Количество видов расходников
- Стоимость всей поставки
- Количество категорий
- Статус поставки
#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:
- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
- Название расходника
- Количество
- Цена
- Категория
- Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено
---
## 10. 🏪 КАБИНЕТ ПОСТАВЩИКА
> 📖 **Технические детали кабинета**: См. [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md) для компонентов, GraphQL и UI/UX
### 10.1 Разделение понятий: РЫНОК vs МАРКЕТ
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ ПОНЯТИЙ:**
### **РЫНОК** 🏪 - физическое торговое место
- **Назначение**: Географическая принадлежность поставщиков
- **Примеры**: Садовод, ТЯК Москва
- **Структура**: Название + адрес
- **Связь**: Поставщик принадлежит рынку
### **МАРКЕТ** 🛒 - раздел системы для торговли
- **Назначение**: Глобальный каталог товаров в системе
- **Роут**: `/market` - просмотр и заказ товаров
- **Содержание**: Все доступные товары от всех поставщиков
- **Связь**: НЕ связан с физическими рынками
**🏢 АРХИТЕКТУРА ПРИНАДЛЕЖНОСТИ:**
```
РЫНОК (физическое место)
└── Поставщик (Organization.market)
└── Товары/Расходники (наследуют рынок от поставщика)
└── Отображаются в МАРКЕТЕ (/market)
```
**🎯 ПРИНЦИПЫ ИЕРАРХИИ:**
1. **РЫНОК → ПОСТАВЩИК**: Поставщик работает на конкретном рынке
2. **ПОСТАВЩИК → ТОВАРЫ**: Товары принадлежат поставщику с его рынка
3. **ТОВАРЫ → МАРКЕТ**: Все товары показываются в глобальном маркете (/market)
4. **НАСЛЕДОВАНИЕ**: Товары получают рынок от организации поставщика
**🏪 ФИЗИЧЕСКИЕ РЫНКИ В СИСТЕМЕ:**
- **"Садовод"** (`sadovod`) - Москва, 14-й км МКАД
- **Цветовая схема**: `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (`tyak-moscow`) - Москва, Алтуфьевское шоссе, 27
- **Цветовая схема**: `bg-blue-500/20 text-blue-300 border-blue-500/30`
**🛒 МАРКЕТ В СИСТЕМЕ:**
- **Роут**: `/market` - глобальный каталог товаров
- **Функции**: Просмотр, поиск, фильтрация, заказ товаров
- **Источник**: Товары от всех поставщиков всех рынков
- **Отображение рынка**: В карточках поставщиков и товаров
**🔧 ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
- **Поле рынка**: `Organization.market` (String?) - принадлежность поставщика к рынку
- **Настройка рынка**: В настройках организации поставщика
- **Отображение в маркете**: Товары показывают рынок через `product.organization.market`
- **Фильтрация**: В маркете по рынку поставщика
### 10.2 Основные возможности
**СОЗДАНИЕ КАРТОЧЕК**:
- **ТОВАР** - базовые товары поставщика
- **РАСХОДНИКИ** - материалы и вспомогательные товары
### 10.3 Обязательные поля карточки
**Базовые параметры**:
- Фото (система загрузки и управления изображениями)
- Название
- Автоматическая генерация артикула СФ
- Описание
- Количество предметов в единицах
- Количество комплектов (если применимо)
- Категория (28 предустановленных + специализированные для расходников)
- Бренд, Цвет, Размер/объем, Вес, Габариты, Материал
- Цена за единицу и за комплект
- Заказано, В пути, Остаток, Продано
### 10.4 Отображение информации в карточках
**Каждая карточка содержит**:
- Основное изображение
- Название и артикул СФ
- Цена за единицу/комплект
- Категория и статус активности
- Данные о движении: остаток, заказано, в пути, продано
- Индикаторы низких остатков
### 10.5 Статистика поставщика
**Блок статистики включает**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары
- Классифицируются при заказе в зависимости от заказчика
- Общая статистика по всем расходникам
---
## 11. 🏭 КАБИНЕТ ФУЛФИЛМЕНТА
### 11.1 Общие характеристики кабинета фулфилмента
#### 11.1.1 Принципы доступа
- **МАКСИМАЛЬНЫЕ ПРАВА**: Фулфилмент имеет доступ ко ВСЕМ разделам системы
- **АДАПТИВНАЯ НАВИГАЦИЯ**: Sidebar изменяется в зависимости от `user.organization.type === "FULFILLMENT"`
- **ЭКСКЛЮЗИВНЫЕ КОМПОНЕНТЫ**: Услуги, Сотрудники, Статистика фулфилмента доступны ТОЛЬКО фулфилменту
- **СПЕЦИАЛЬНЫЙ РОУТИНГ**: При нажатии "Поставки" → `/fulfillment-supplies` (не `/supplies`)
#### 11.1.2 Архитектурные особенности
- **GraphQL проверки**: `skip: user?.organization?.type !== 'FULFILLMENT'` в запросах
- **Условное отображение**: `{user?.organization?.type === "FULFILLMENT" && (...)}`
- **Адаптивные отступы**: `getSidebarMargin()` для responsive design
- **Полинг данных**: Статистика обновляется каждую минуту (`pollInterval: 60000`)
### 11.2 Структура раздела склад фулфилмента
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Кабинет фулфилмента](#141-кабинет-фулфилмента)
#### 11.2.1 Структура склада по модулям (ОБЯЗАТЕЛЬНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ)
1. **📦 ПРОДУКТЫ** - готовые к отправке товары
2. **🛒 ТОВАРЫ** - базовые товары от поставщиков
- **"На складе"** - готовы к обработке
- **"В обработке"** - в процессе создания продукта
3. **❌ БРАК** - товары с дефектами, требуют утилизации
4. **↩️ ВОЗВРАТЫ С ПВЗ** - возвращенные товары, к обработке
5. **🎯 РАСХОДНИКИ СЕЛЛЕРОВ** - материалы для селлеров (тип `CONSUMABLE`, заказанные селлерами)
6. **⚙️ РАСХОДНИКИ ФУЛФИЛМЕНТА** - операционные материалы (тип `CONSUMABLE`, заказанные фулфилментом, КЛИКАБЕЛЬНЫЙ модуль)
#### 11.2.2 Система учета склада
**Дополнительные значения** (показатели движения):
- **ПРИБЫЛО** - количество поступивших на склад за период
- **УБЫЛО** - количество списанных со склада за период
**Основные значения** (текущие остатки):
- **ФОРМУЛА**: Основные значения = Предыдущие остатки + Прибыло - Убыло
- **ОБНОВЛЕНИЕ**: В реальном времени с изменениями за сутки
- **ИСТОЧНИК**: GraphQL query `GET_FULFILLMENT_WAREHOUSE_STATS`
#### 11.2.3 Структура данных склада (3-уровневая иерархия)
```
🔵 УРОВЕНЬ 1: МАГАЗИНЫ
├── ТехноМир (синий - blue-400/500)
├── Стиль и Комфорт (розовый - pink-400/500)
└── Зелёный Дом (изумрудный - emerald-400/500)
🟢 УРОВЕНЬ 2: ТОВАРЫ (зеленый - green-500)
🟠 УРОВЕНЬ 3: ВАРИАНТЫ ТОВАРОВ (оранжевый - orange-500)
```
**Цветовое кодирование**:
- Каждый уровень имеет цветной индикатор увеличивающегося размера
- Цветная левая граница с увеличивающимся отступом и толщиной
- Скроллбары в цвете уровня
- Контрастный цвет текста для читаемости
### 11.3 Движение товаров в фулфилменте
#### **Поступление товаров**:
- **ПОСТАВКИ**: От поставщиков через систему заказов
- **ВОЗВРАТЫ**: Товары, возвращенные с ПВЗ
- **ПЕРЕМЕЩЕНИЯ**: Между складами и магазинами
#### **Расход товаров**:
- **ОТГРУЗКА**: Товары отправлены селлерам
- **СПИСАНИЕ**: Брак, утрата, утилизация
- **ВОЗВРАТ**: Возврат поставщику
- **ИСПОЛЬЗОВАНИЕ**: Расходники для операций
### 11.4 Модуль "Расходники фулфилмента"
**ОСОБЕННОСТИ**:
- **ИНТЕРАКТИВНОСТЬ**: Кликабельный элемент в статистике
- **ФУНКЦИОНАЛЬНОСТЬ**: Полноценный раздел учёта
- **СОДЕРЖАНИЕ**: Управление расходниками фулфилмента
### 11.5 Поставки фулфилмента (`/fulfillment-supplies`)
#### 11.5.1 Структура: 2 основные вкладки
**A) 🛒 ПОСТАВКИ ТОВАРОВ**:
- **Детализированные товары ФФ** - планы и факты поставок с маршрутами
- **Товары ФФ** - общие поставки товаров от селлеров
- **Возвраты с ПВЗ** - обработка возвращенных товаров
**B) 🔧 ПОСТАВКИ РАСХОДНИКОВ**:
- **Заказы расходников** - управление заказами от селлеров
- **Расходники селлеров** - материалы для клиентов
- **Создание поставок** - формирование новых поставок расходников
#### 11.5.2 Workflow поставок товаров
**Этапы обработки**:
1. **Planned** - поставка запланирована
2. **In-transit** - товар в пути
3. **Delivered** - доставлен на склад
4. **Completed** - обработка завершена
### 11.6 Статистика фулфилмента (`/fulfillment-statistics`)
#### 11.6.1 Блоки аналитики (сворачиваемые)
**1. НАКОПЛЕННАЯ СТАТИСТИКА** (`allTime: true`):
- Обработано товаров (общий объем)
- Выявлено брака (всего единиц)
- Поставок получено
- Общий доход (за все время)
- Выполнено заказов (успешных отгрузок)
- Удовлетворенность клиентов (средний рейтинг)
**2. ОТГРУЗКА НА ПЛОЩАДКИ** (`marketplaces: true`):
- Отправлено на Wildberries
- Отправлено на Ozon
- Отправлено на другие площадки
**3. АНАЛИТИКА ПРОИЗВОДИТЕЛЬНОСТИ** (`performance: false`):
- Среднее время обработки (на единицу товара)
- Уровень брака (от общего объема)
- Уровень возвратов (возвраты с площадок)
- Удовлетворенность клиентов
### 11.7 Услуги фулфилмента (`/services`)
#### 11.7.1 Архитектура интеграции с системой
**СВЯЗЬ С РЕЦЕПТУРАМИ СЕЛЛЕРОВ:**
```
СЕЛЛЕР (создание поставки)
└── Рецептура
├── Товар (от поставщика)
├── Услуги фулфилмента ← CRUD в разделе Услуги
├── Расходники селлера
└── Расходники фулфилмента ← ТОЛЬКО с установленной ценой
ФУЛФИЛМЕНТ (обработка)
├── Входящие поставки → Поставки расходников (создание)
└── Услуги → Расходники (установка цены за единицу)
```
#### 11.7.2 Структура: 3 обязательные вкладки
**A) 🛠️ УСЛУГИ** (`defaultValue="services"`):
- **Полный CRUD**: создание, редактирование, удаление услуг
- **Поля**: `name`, `description`, `price`, `imageUrl`
- **Glass Upload Zone**: элегантная загрузка изображений
- **Назначение**: каталог услуг для рецептур селлеров
- **GraphQL**: `GET_MY_SERVICES`, `CREATE_SERVICE`, `UPDATE_SERVICE`, `DELETE_SERVICE`
**B) 🚚 ЛОГИСТИКА**:
- **Полный CRUD**: маршруты доставки
- **Поля**: откуда → куда, тарификация до/свыше 1м³
- **Группированные локации**:
- Мой фулфилмент (название организации)
- Рынки (предустановленные)
- Склады Wildberries
- Склады Ozon
- **Glass Upload Zone**: для изображений маршрутов
- **GraphQL**: `GET_MY_LOGISTICS`, `CREATE_LOGISTICS`, `UPDATE_LOGISTICS`, `DELETE_LOGISTICS`
**C) 📦 РАСХОДНИКИ** (**❌ БЕЗ СОЗДАНИЯ**):
- **ТОЛЬКО ПРОСМОТР** расходников с фулфилмент-склада
- **ЕДИНСТВЕННОЕ РЕДАКТИРУЕМОЕ ПОЛЕ**: `pricePerUnit` - цена за единицу для рецептур
- **UI подсветка**: "Цена за 1 {unit}" (например, "Цена за 1 шт")
- **Автоматическая синхронизация** при приеме поставки расходников
- **Glass Upload Zone**: для обновления изображений расходников
- **GraphQL**: `GET_MY_SUPPLIES` (read-only), `UPDATE_SUPPLY_PRICE`
#### 11.7.3 Workflow расходников
**ШАГ 1 - СОЗДАНИЕ**: Только через "Входящие поставки → Поставки расходников фулфилмента"
**ШАГ 2 - СИНХРОНИЗАЦИЯ**: При приеме на склад → автоматически в Услуги/Расходники
**ШАГ 3 - ЦЕНООБРАЗОВАНИЕ**: Установка цены за единицу в разделе Услуги
**ШАГ 4 - ИСПОЛЬЗОВАНИЕ**: Доступны в рецептурах селлеров
#### 11.7.4 Правила видимости в рецептурах
**В РЕЦЕПТУРАХ СЕЛЛЕРОВ ПОКАЗЫВАЮТСЯ ТОЛЬКО:**
- `isAvailable = true` (есть на skladе)
- `pricePerUnit != null` (цена установлена)
**НЕ ПОКАЗЫВАЮТСЯ:**
- Расходники без цены (`pricePerUnit = null`)
- Удаленные со склада (`isAvailable = false`)
**В РАЗДЕЛЕ УСЛУГИ/РАСХОДНИКИ ВИДНЫ ВСЕ:**
- С визуальной индикацией состояния (активные/неактивные/без цены)
#### 11.7.5 Разделение цен закупки и продажи
**КРИТИЧЕСКОЕ ПРАВИЛО**: Расходники фулфилмента имеют **ДВЕ РАЗНЫЕ ЦЕНЫ** для разных бизнес-процессов:
1. **ЦЕНА ЗАКУПКИ** (`Supply.price`) - цена, по которой фулфилмент купил расходник у поставщика
2. **ЦЕНА ПРОДАЖИ** (`Supply.pricePerUnit`) - цена, по которой фулфилмент продает расходник селлерам
**ПОЛЯ В БАЗЕ ДАННЫХ**:
```prisma
model Supply {
price Decimal @db.Decimal(10, 2) // Цена закупки у поставщика (НЕИЗМЕННАЯ)
pricePerUnit Decimal? @db.Decimal(10, 2) // Цена продажи селлерам (устанавливается фулфилментом)
}
```
**ПРАВИЛА ОТОБРАЖЕНИЯ ПО РАЗДЕЛАМ**:
**РАЗДЕЛ "СКЛАД → РАСХОДНИКИ ФУЛФИЛМЕНТА"**:
- Показывает `Supply.price` (цена закупки)
- Цена ТОЛЬКО ДЛЯ ЧТЕНИЯ, нельзя изменять
- Отражает историческую стоимость приобретения
**РАЗДЕЛ "УСЛУГИ → РАСХОДНИКИ"**:
- Показывает и редактирует `Supply.pricePerUnit` (цена продажи)
- Единственное место где можно изменить цену для селлеров
- Влияет на рецептуры и расчеты для селлеров
**БИЗНЕС-ЛОГИКА СОЗДАНИЯ**:
ПРИ ПОСТУПЛЕНИИ ОТ ПОСТАВЩИКА:
```typescript
const supply = await prisma.supply.create({
data: {
price: item.price, // Цена поставщика → ЗАФИКСИРОВАНА
pricePerUnit: null, // Цена продажи → ПУСТАЯ
},
})
```
УСТАНОВКА ЦЕНЫ ПРОДАЖИ (в разделе "Услуги"):
```typescript
const updated = await prisma.supply.update({
data: {
pricePerUnit: newPrice, // ТОЛЬКО цена продажи
// price НЕ ТРОГАЕМ - остается цена закупки
},
})
```
#### 11.7.6 Технические требования
**GraphQL типы:**
```graphql
# Для рецептур - только доступные с ценой
getAvailableSuppliesForRecipe: [SupplyForRecipe!]!
# В разделе Услуги - все расходники
getMySupplies: [Supply!]!
type Supply {
pricePerUnit: Float # Может быть null
unit: String! # "шт", "кг", "м"
isAvailable: Boolean! # Статус на складе
warehouseConsumableId: ID! # Связь со складом
}
```
**Экономический учет:**
- Создание: через поставки расходников
- Ценообразование: в разделе Услуги
- Списание: со склада при использовании
- Стоимость = количество × цена за единицу
### 11.8 Сотрудники фулфилмента (`/employees`)
#### 11.8.1 Структура: 2 основные вкладки
**A) 👥 СОТРУДНИКИ** (`defaultValue="combined"`):
**Управление персоналом**:
- **CRUD операции**: создание, редактирование, удаление сотрудников
- **Статусы сотрудников**: `ACTIVE`, `VACATION`, `SICK`, `FIRED`
- **Формы добавления**: Компактная (`showCompactForm`) / Полная форма
- **Поиск и фильтрация** по имени, должности, статусу
**Табель рабочего времени**:
- **Навигация по месяцам**: текущий год/месяц с кнопками ←/→
- **Отметки по дням**: статус дня и количество отработанных часов
- **GraphQL**: `GET_EMPLOYEE_SCHEDULE`, `UPDATE_EMPLOYEE_SCHEDULE`
**B) 📋 ОТЧЕТЫ** (`value="reports"`):
- **Сводные отчеты** по сотрудникам за период
- **Экспорт данных** табеля
- **Аналитика рабочего времени**
### 11.9 Блок детализации по магазинам
**НАЗНАЧЕНИЕ**: Распределение товаров по торговым точкам/магазинам
**ФУНКЦИИ**:
- **ОСТАТКИ ПО МАГАЗИНАМ**: Отображение количества товаров в каждом магазине
- **УПРАВЛЕНИЕ РАСПРЕДЕЛЕНИЕМ**: Перемещение товаров между точками
- **КОНТРОЛЬ ДВИЖЕНИЯ**: Отслеживание перемещений между складами и магазинами
- **АНАЛИТИКА**: Сравнение эффективности разных точек
- **ПЛАНИРОВАНИЕ**: Оптимизация распределения товаров
---
## 12. 🚚 КАБИНЕТ ЛОГИСТИКИ
### 12.1 Основные функции логистики
**РОЛЬ В СИСТЕМЕ**: Управление доставками и транспортировкой
**ОСНОВНЫЕ ФУНКЦИИ**:
- **ПОДТВЕРЖДЕНИЕ ДОСТАВКИ**: Подтверждение возможности доставки поставок
- **ТРАНСПОРТИРОВКА**: Организация и выполнение доставки товаров
- **КОНТРОЛЬ МАРШРУТОВ**: Управление логистическими маршрутами
- **ОТСЛЕЖИВАНИЕ**: Мониторинг грузов в пути
### 12.2 Workflow для логистики
#### **ЭТАП 1: Получение заявки**
1. Логистика получает уведомление о новой поставке
2. Заявка появляется в разделе "Заявки" кабинета логистики
3. Логист изучает детали поставки (объем, вес, маршрут)
#### **ЭТАП 2: Подтверждение доставки**
4. Логист нажимает кнопку "Одобрить"
5. Статус поставки меняется на `LOGISTICS_CONFIRMED`
6. Уведомления отправляются всем участникам
#### **ЭТАП 3: Забор товара**
7. Логист приезжает к поставщику за товаром
8. Поставщик отгружает товар логисту
9. Поставщик отмечает "Отправлено"
10. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
#### **ЭТАП 4: Доставка**
11. Логистика доставляет товар на фулфилмент-центр
12. В кабинете логистики нажимают "Доставлено"
13. Фулфилмент принимает товар и отмечает "Принято"
### 12.3 Система тарификации
**ПАРАМЕТРЫ ТАРИФИКАЦИИ**:
- **Тариф до 1м³** - базовая стоимость для малых грузов
- **Тариф свыше 1м³** - стоимость для крупных грузов
- **Маршруты доставки** - от точки отправления до точки назначения
- **Описание услуг** - дополнительные условия доставки
**РАСЧЕТ СТОИМОСТИ**:
- Автоматический расчет стоимости доставки по объему груза
- Отображение примерной стоимости при создании заказа
- Учет специфики маршрута и условий доставки
### 12.4 Управление заявками
**РАЗДЕЛЫ КАБИНЕТА ЛОГИСТИКИ**:
- **НОВЫЕ ЗАЯВКИ** - поступившие заявки на доставку
- **В РАБОТЕ** - принятые к исполнению заявки
- **ВЫПОЛНЕННЫЕ** - завершенные доставки
- **ОТКЛОНЕННЫЕ** - заявки, которые не могут быть выполнены
**ИНФОРМАЦИЯ О ЗАЯВКЕ**:
- Детали груза (объем, вес, габариты)
- Маршрут доставки (откуда - куда)
- Срочность доставки
- Особые требования к транспортировке
- Контактная информация участников
### 12.5 Правила логистики
**ОБЯЗАТЕЛЬНО**:
- Своевременное подтверждение заявок
- Соблюдение сроков доставки
- Бережная транспортировка товаров
- Уведомление о статусе доставки
**ЗАПРЕЩЕНО**:
- Принятие заявок без подтверждения возможности выполнения
- Нарушение сроков доставки без уведомления
- Повреждение товаров при транспортировке
---
## 13. 🤝 СИСТЕМА ПАРТНЕРСТВА И КОНТРАГЕНТОВ
### 13.1 Основы системы партнерства
**ПРИНЦИП РАБОТЫ**:
- Все типы кабинетов могут создавать партнерские отношения
- Партнерство реализовано через таблицы `Counterparty` и `CounterpartyRequest`
- Двустороннее партнерство: каждая организация видит другую в разделе "Партнеры"
**ТИПЫ ОРГАНИЗАЦИЙ-ПАРТНЕРОВ**:
- `WHOLESALE` - Поставщики товаров и расходников
- `FULFILLMENT` - Фулфилмент-центры
- `LOGIST` - Логистические компании
- `SELLER` - Селлеры (торговые организации)
### 13.2 Способы создания партнерства
#### **СПОСОБ 1: Через заказ в маркете (автоматическое партнерство)**
**WORKFLOW**:
1. Поставщик создает товар → товар попадает в глобальный маркет
2. Селлер/Фулфилмент находит товар в маркете
3. Создает заказ (`SupplyOrder`) → статус `PENDING`
4. Поставщик получает уведомление в разделе "Заявки"
5. Поставщик одобряет заявку → статус `SUPPLIER_APPROVED`
6. **Автоматически создается двустороннее партнерство**:
- Запись в `Counterparty` для заказчика (`organizationId``counterpartyId`)
- Обратная запись в `Counterparty` для поставщика
7. Обе организации видят друг друга в разделе "Партнеры"
#### **СПОСОБ 2: Через раздел "Партнеры" (заявочная система)**
**WORKFLOW**:
1. Любая организация идет в раздел "Партнеры"
2. Использует поиск для нахождения нужной организации
3. Отправляет заявку на партнерство → создается `CounterpartyRequest`:
- `senderId` - отправитель заявки
- `receiverId` - получатель заявки
- `status: PENDING`
- `message` - опциональное сообщение
4. Получатель видит заявку в разделе "Партнеры" → "Входящие заявки"
5. Получатель принимает заявку → статус меняется на `ACCEPTED`
6. **Автоматически создается двустороннее партнерство** (аналогично способу 1)
**СТАТУСЫ ЗАЯВОК**:
- `PENDING` - Ожидает рассмотрения
- `ACCEPTED` - Принята (партнерство создано)
- `REJECTED` - Отклонена
- `CANCELLED` - Отменена отправителем
### 13.3 Использование партнерства в системе
#### **В форме создания поставки товаров через поставщиков**
**ПРАВИЛО ОТОБРАЖЕНИЯ ПОСТАВЩИКОВ**:
- Показываются только партнеры с типом `WHOLESALE`
- Источник: таблица `Counterparty` where `counterparty.type === "WHOLESALE"`
- Фильтрация по `organizationId` текущего пользователя
**ЛОГИКА РАБОТЫ**:
1. Пользователь выбирает поставщика из dropdown партнеров-поставщиков
2. Загружается каталог товаров поставщика из `Product` таблицы
3. Товары фильтруются по `organizationId = поставщик.id`
4. Пользователь может добавлять товары в корзину и создавать заказ
#### **В других разделах системы**
**ВЫБОР ФУЛФИЛМЕНТ-ЦЕНТРА**:
- Партнеры с типом `FULFILLMENT`
- Используется при создании поставок расходников
**ВЫБОР ЛОГИСТИКИ**:
- Партнеры с типом `LOGIST`
- Используется при планировании доставок
**МЕССЕНДЖЕР**:
- Общение доступно только между партнерами
- Список чатов формируется из таблицы `Counterparty`
### 13.4 Технические правила
**СОЗДАНИЕ ЗАПИСЕЙ В COUNTERPARTY**:
```sql
-- При создании партнерства создаются ДВЕ записи
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org1_id, org2_id);
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org2_id, org1_id);
```
**ПРОВЕРКА ПАРТНЕРСТВА**:
```typescript
const isPartner = await prisma.counterparty.findFirst({
where: {
organizationId: currentOrgId,
counterpartyId: targetOrgId,
},
})
```
**ПОЛУЧЕНИЕ ПАРТНЕРОВ ПО ТИПУ**:
```typescript
const wholesalePartners = await prisma.counterparty.findMany({
where: {
organizationId: currentOrgId,
counterparty: {
type: 'WHOLESALE',
},
},
include: {
counterparty: true,
},
})
```
### 13.5 Решение распространенных проблем
#### **ПРОБЛЕМА: GraphQL запрос не возвращает данные партнеров**
**Симптомы**:
- В консоли браузера: `All counterparties: 0`, `All counterparties data: []`
- GraphQL запрос отправляется успешно, но возвращает пустой массив
- В базе данных партнеры существуют
**Возможные причины и решения**:
1. **НЕПРАВИЛЬНОЕ ИМЯ ПОЛЯ В КОДЕ** (наиболее частая ошибка):
```typescript
// ❌ НЕПРАВИЛЬНО
const allCounterparties = counterpartiesData?.getMyCounterparties || []
// ✅ ПРАВИЛЬНО
const allCounterparties = counterpartiesData?.myCounterparties || []
```
**Объяснение**: В GraphQL схеме поле называется `myCounterparties`, а не `getMyCounterparties`
2. **НЕСООТВЕТСТВИЕ ID ПОЛЬЗОВАТЕЛЯ**:
- Проверить что пользователь авторизован под правильным аккаунтом
- Убедиться что `context.user.id` соответствует ожидаемому пользователю
3. **ПРОБЛЕМЫ С КЕШИРОВАНИЕМ APOLLO CLIENT**:
```typescript
const { data, loading, error } = useQuery(GET_MY_COUNTERPARTIES, {
fetchPolicy: 'network-only', // Обходим кеш
errorPolicy: 'all',
})
```
4. **ОТСУТСТВИЕ ЛОГИРОВАНИЯ В РЕЗОЛВЕРЕ**:
- Добавить console.log в GraphQL резолвер для отладки
- Проверить что резолвер вызывается
**Чек-лист для диагностики**:
- [ ] Проверить правильность имени поля в коде (`myCounterparties`)
- [ ] Убедиться что пользователь авторизован
- [ ] Проверить логи сервера на вызов резолвера
- [ ] Добавить отладочное логирование в браузере
- [ ] Проверить данные в базе через Prisma Studio
- [ ] Использовать `fetchPolicy: 'network-only'` для обхода кеша
---
## 14. 🌐 ИНТЕГРАЦИИ С СИСТЕМОЙ
### 14.1 Глобальная интеграция
- **МАРКЕТ**: Товары поставщиков отображаются в глобальном маркете
- **СИНХРОНИЗАЦИЯ**: Данные склада синхронизируются с модулем аналитики
- **УВЕДОМЛЕНИЯ**: Единая система через встроенный мессенджер
### 14.2 Интеграция с маркетплейсами
- **WILDBERRIES**: Обязательная проверка активности API ключа
- **СИНХРОНИЗАЦИЯ**: Регулярное обновление данных из внешних источников
- **ЛОКАЛЬНЫЕ КОПИИ**: Сохранение данных для офлайн работы
### 14.3 Интеграция с модулем "Услуги"
**РАСХОДНИКИ ФУЛФИЛМЕНТА В УСЛУГАХ**:
- Расходники фулфилмента - собственность фулфилмента (куплены у поставщиков)
- Фулфилмент создает заявки-поставки для покупки расходников у поставщиков
- Селлеры могут использовать расходники фулфилмента в разделе "Услуги / Расходники"
- Для создания продукта из товара
- Расходники списываются с остатков фулфилмента
- Стоимость включается в стоимость услуги
**WORKFLOW ИСПОЛЬЗОВАНИЯ**:
1. Селлер выбирает услугу "Создание продукта"
2. Указывает базовый товар
3. Выбирает необходимые расходники фулфилмента
4. Фулфилмент обрабатывает заказ и создает продукт
5. Расходники списываются, создается готовый продукт
---
## 15. 📊 СТАТИСТИКА И АНАЛИТИКА
### 15.1 Структура статистики по кабинетам
#### **В КАБИНЕТЕ ПОСТАВЩИКА**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары (классифицируются при заказе)
#### **В КАБИНЕТЕ ФУЛФИЛМЕНТА**:
- **ТОВАРЫ**: Базовые товары от поставщиков (принятые на склад)
- **ПРОДУКТЫ**: Отдельный блок готовой продукции
- **БРАК**: Статистика потерь и списаний
- **РАСХОДНИКИ ФУЛФИЛМЕНТА**: Операционные материалы фулфилмента
- **РАСХОДНИКИ СЕЛЛЕРОВ**: Материалы для товаров селлеров
### 15.2 Ключевые метрики
**ОБЩИЕ ПОКАЗАТЕЛИ**:
- Общие остатки, заказано, в пути, остаток, продано
- Подсветка предметов с остатками ниже критического уровня
**АКТУАЛИЗАЦИЯ ДАННЫХ**:
- При изменении количества в карточке данные актуализируются во всей системе
- Статистика обновляется в реальном времени
- Отслеживание изменений для аналитики
---
## 16. 📱 ПРАВИЛА UI/UX И ИНТЕРФЕЙСА
### 16.1 Отзывчивость интерфейса
- **ОБЯЗАТЕЛЬНО**: Интерфейс должен работать на всех устройствах
- **ПРАВИЛО**: Адаптивная сетка для карточек товаров
- **ФУНКЦИЯ**: Оптимизация для мобильных устройств
- **ТРЕБОВАНИЕ**: Корректное отображение на экранах от 320px до 4K
### 16.2 Обратная связь пользователю
- **ОБЯЗАТЕЛЬНО**: Уведомления об успешных/неуспешных операциях
- **ПРАВИЛО**: Индикаторы загрузки для длительных операций
- **ФУНКЦИЯ**: Подтверждение критических действий (удаление, деактивация)
- **UX**: Понятные сообщения об ошибках с предложением решения
### 16.3 Правила обработки ошибок
- **ОБЯЗАТЕЛЬНО**: Логирование всех ошибок с детальной информацией
- **ПРАВИЛО**: Понятные сообщения об ошибках для пользователя
- **ФУНКЦИЯ**: Автоматическое восстановление после сбоев
- **МОНИТОРИНГ**: Отслеживание критических ошибок в реальном времени
### 16.4 Производительность
- **ПРАВИЛО**: Пагинация для больших списков товаров
- **ФУНКЦИЯ**: Ленивая загрузка изображений
- **ОПТИМИЗАЦИЯ**: Кэширование часто запрашиваемых данных
- **ПРОИЗВОДИТЕЛЬНОСТЬ**: Время загрузки страницы не более 3 секунд
---
## 17. ⚠️ КРИТИЧЕСКИЕ ЗАПРЕТЫ
### 17.1 НИКОГДА НЕ ДЕЛАТЬ:
1. ❌ Удалять предметы с существующими заказами
2. ❌ Изменять статусы заказов без уведомлений
3. ❌ Обходить проверки остатков предметов
4. ❌ Давать доступ к чужим данным
5. ❌ Игнорировать ошибки валидации
6. ❌ Сохранять пароли в открытом виде
7. ❌ Пропускать логирование критических операций
8. ❌ Блокировать интерфейс без индикации загрузки
9. ❌ Создавать брак или продукт без связи с родительским товаром
10. ❌ Создавать отдельные типы расходников (только общий тип "РАСХОДНИКИ")
11. ❌ Разрешать заказ брака
12. ❌ Нарушать иерархию типов предметов
13. ❌ Пропускать промежуточные статусы в workflow
14. ❌ Нарушать обязательную последовательность модулей в статистике фулфилмента
15. ❌ **Использовать неправильные имена полей GraphQL** (`getMyCounterparties` вместо `myCounterparties`)
16. ❌ **Использовать GET_SUPPLY_SUPPLIERS для отображения поставщиков в формах** (только партнеры WHOLESALE)
17. ❌ **Создавать интерфейсы TypeScript не соответствующие schema.prisma** (`sku`/`stock` вместо `article`/`quantity`)
18. ❌ **Использовать общие запросы вместо специализированных** (`GET_ALL_PRODUCTS` вместо `GET_ORGANIZATION_PRODUCTS` для конкретного поставщика)
19. ❌ **Показывать расходники в формах создания поставок товаров** (строгая типизация `PRODUCT`/`CONSUMABLE`)
20. ❌ **Фильтровать предметы по типу на фронтенде** (фильтрация должна быть в GraphQL резолвере)
21. ❌ **ИСПОЛЬЗОВАТЬ МОКОВЫЕ ДАННЫЕ БЕЗ РАЗРЕШЕНИЯ** - все компоненты ОБЯЗАТЕЛЬНО должны использовать реальные GraphQL запросы. Моковые данные можно добавлять ТОЛЬКО с явного разрешения пользователя
22. ❌ **ДОБАВЛЯТЬ ПОЛЕ РЫНКА К ТОВАРАМ** - рынок принадлежит организации поставщика (`Organization.market`), товары наследуют рынок через связь с организацией
23. ❌ **ПУТАТЬ РЫНОК И МАРКЕТ** - РЫНОК = физическое место (Садовод, ТЯК), МАРКЕТ = раздел системы (/market)
24. ❌ **ИСПОЛЬЗОВАТЬ НАЗВАНИЯ ОРГАНИЗАЦИЙ В ЛОГИКЕ БЕЗОПАСНОСТИ** - проверки доступа только по `organization.type` и системным ID
25. ❌ **СОЗДАВАТЬ УСЛОВИЯ НА ОСНОВЕ ПОЛЬЗОВАТЕЛЬСКИХ СТРОК** - никаких `if (name.includes())` для определения функционала
26. ❌ **ПУТАТЬ ДАННЫЕ И ФУНКЦИОНАЛ** - "ОПТ Маркет" (название рынка) ≠ "Маркет" (раздел системы)
27. ❌ **ПРЕДСТАВЛЯТЬ ИНТЕРПРЕТАЦИИ КАК ФАКТЫ** - всегда четко разделять прямые цитаты из правил и логические выводы
28. ❌ **ОТВЕЧАТЬ БЕЗ ССЫЛОК НА ИСТОЧНИКИ** - при ссылке на правила всегда указывать номер строки или раздел
29. ❌ **ИСПОЛЬЗОВАТЬ КАТЕГОРИЧНЫЕ УТВЕРЖДЕНИЯ БЕЗ ДОКАЗАТЕЛЬСТВ** - избегать "ТОЧНО!", "ИМЕННО ТАК!" без прямых цитат
### 17.2 ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:
1. ✅ Проверка остатков перед добавлением в корзину
2. ✅ Валидация всех числовых значений (цена > 0, вес > 0)
3. ✅ Автоматическая генерация уникальных артикулов СФ
4. ✅ Логирование всех изменений статусов
5. ✅ Уведомления всех участников при изменении статусов
6. ✅ Обязательная типизация всех предметов
7. ✅ Связь производных типов с родительскими предметами
8. ✅ Проверка доступности товаров перед заказом
9. ✅ Соблюдение жизненного цикла статусов поставок
10. ✅ Фиксация план/факт в процессе создания продукта
11. ✅ **УКАЗЫВАТЬ ИСТОЧНИКИ ИНФОРМАЦИИ** - при ссылке на правила обязательно указывать строку/раздел
12. ✅ **РАЗДЕЛЯТЬ ФАКТЫ И ИНТЕРПРЕТАЦИИ** - четко маркировать что взято из правил, а что является выводом
13. ✅ **ИСПОЛЬЗОВАТЬ ОСТОРОЖНЫЕ ФОРМУЛИРОВКИ** - "согласно правилам", "возможно", "требует уточнения"
### 17.3 📝 ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ С ФАКТАМИ
**При ссылке на правила ОБЯЗАТЕЛЬНО использовать формат:**
✅ **ПРАВИЛЬНО:**
```
📖 ФАКТ из rules-complete.md (строка 2225): "установка цены за единицу"
🧠 МОЯ ИНТЕРПРЕТАЦИЯ: возможно, это происходит в разделе X
❓ ПРЕДПОЛОЖЕНИЕ: требует уточнения у пользователя
⚠️ НЕ НАЙДЕНО в правилах: информация о точном местоположении
```
❌ **НЕПРАВИЛЬНО:**
```
"Да! Точно понимаю! Фулфилмент устанавливает цены в разделе X!"
```
**ОБЯЗАТЕЛЬНАЯ МАРКИРОВКА:**
- 📖 **ФАКТ** - прямая цитата из правил с номером строки
- 🧠 **ИНТЕРПРЕТАЦИЯ** - мой логический вывод (четко обозначен)
- ❓ **ПРЕДПОЛОЖЕНИЕ** - гипотеза, требующая подтверждения
- ⚠️ **НЕ НАЙДЕНО** - информация отсутствует в правилах
**СТОП-СЛОВА (избегать без доказательств):**
❌ "ТОЧНО!", "ИМЕННО ТАК!", "ДА! ПОНИМАЮ!", "АБСОЛЮТНО ВЕРНО!"
✅ "Согласно правилам...", "Не указано, но возможно...", "Требует уточнения"
### 17.4 🔒 ПРАВИЛА БЕЗОПАСНОСТИ: Разделение данных и функционала
#### КРИТИЧЕСКОЕ ПРАВИЛО БЕЗОПАСНОСТИ
**ПРИНЦИП**: Названия организаций, рынков и любые пользовательские данные НИКОГДА не должны влиять на функционал и безопасность системы.
**ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:**
✅ **ПРАВИЛЬНЫЕ ПРОВЕРКИ:**
- Проверки доступа ТОЛЬКО по типу организации: `organization.type === 'WHOLESALE'`
- Роутинг ТОЛЬКО по предопределенным путям: `/market`, `/supplies` и т.д.
- Валидация ТОЛЬКО по ID и системным полям
- Фильтрация ТОЛЬКО по enum значениям из схемы
❌ **ЗАПРЕЩЕННЫЕ ПРОВЕРКИ (УЯЗВИМОСТИ):**
- Использование `organization.name` в условиях доступа
- Проверки по `organization.market` для определения функционала
- Любые проверки содержимого строк: `includes()`, `startsWith()`, `match()`
- Динамическое создание путей на основе пользовательских данных
**ПРИМЕРЫ:**
```typescript
// ❌ УЯЗВИМОСТЬ - название может быть любым
if (organization.name.includes('Маркет')) {
// предоставить специальный доступ
}
// ❌ УЯЗВИМОСТЬ - пользователь может подделать название
if (organization.market === 'special-market') {
// изменить цены
}
// ✅ БЕЗОПАСНО - проверка по системному типу
if (organization.type === 'WHOLESALE') {
// логика для поставщиков
}
// ✅ БЕЗОПАСНО - проверка по ID из whitelist
if (ALLOWED_FULFILLMENT_IDS.includes(organization.id)) {
// логика для проверенных фулфилментов
}
```
**РАЗДЕЛЕНИЕ КОНТЕКСТОВ:**
1. **ДАННЫЕ (могут быть любыми):**
- Названия организаций: "ОПТ Маркет", "Супер Склад", и т.д.
- Названия рынков: "Садовод", "ТЯК Москва", любые другие
- Любые пользовательские строки
2. **ФУНКЦИОНАЛ (строго определен):**
- Системные разделы: `/market`, `/supplies`, `/partners`
- Типы организаций: `WHOLESALE`, `SELLER`, `FULFILLMENT`, `LOGIST`
- Статусы и enum из Prisma схемы
**ПРАВИЛО**: Физический рынок "ОПТ Маркет" - это просто строка данных. Раздел "Маркет" (/market) - это системный функционал. Они никак не связаны и не должны влиять друг на друга.
### 17.5 📦 УПРАВЛЕНИЕ СВЯЗЯМИ ТОВАР-КАРТОЧКА В РЕЦЕПТУРЕ
#### 17.5.1 Общие принципы
**НАЗНАЧЕНИЕ**: Связь товара с карточкой маркетплейса - это метаданные для учета, НЕ влияющие на физический состав продукта.
**ФОРМУЛА ПРОДУКТА НЕИЗМЕННА**:
```
ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
```
**СВЯЗЬ С МП** = отдельные метаданные для логистики и учета
#### 17.5.2 UI компонент связи с карточками
**РАСПОЛОЖЕНИЕ**: В форме создания поставки, в секции каждого товара
**ТИП КОМПОНЕНТА**: Dropdown с поиском и фильтрацией
**ИСТОЧНИК ДАННЫХ**: База данных карточек маркетплейсов селлера (GraphQL запрос)
#### 17.5.3 Логика состояний карточек
**✅ СВЯЗАНО** - карточка уже привязана к этому товару:
- Показывать зеленую галочку
- Текст: "Название карточки - Связано"
- Можно отвязать (сброс в "Без привязки")
**⚠️ ДОСТУПНО** - карточка свободна для привязки:
- Показывать желтый значок предупреждения
- Текст: "Название карточки - Доступно"
- Можно привязать к текущему товару
**❌ ЗАНЯТО** - карточка привязана к другому товару:
- Показывать красный крестик
- Текст: "Название карточки - Занято (товар: 'Название')"
- Пункт заблокирован (disabled)
- Показывать для информации, но нельзя выбрать
**🔍 БЕЗ ПРИВЯЗКИ** - товар не связан с карточкой:
- Пункт по умолчанию
- Показывать серый значок
- Текст: "Без привязки к карточке"
#### 17.5.4 Техническая реализация
**GraphQL запрос**:
```graphql
query GetSellerCards {
myMarketplaceCards {
id
title
marketplace
article
linkedProductId # null если свободна
linkedProduct {
# для отображения занятости
id
name
}
}
}
```
**Логика фильтрации**:
- Все карточки селлера показываются в dropdown
- Статус определяется по полю `linkedProductId`
- Автосвязка: карточки с похожим названием показываются первыми
**Сохранение**:
- При создании поставки связь сохраняется в поле `marketplaceCardId` рецептуры
- При изменении связи обновляется поле `linkedProductId` в карточке
#### 17.5.5 UX поведение
**ПОИСК В DROPDOWN**:
- Фильтрация по названию карточки
- Фильтрация по артикулу маркетплейса
- Автофокус при открытии
**ГРУППИРОВКА**:
```
[Dropdown: Выберите карточку Wildberries ▼]
├─ 🔍 БЕЗ ПРИВЯЗКИ
├─ ────── ДОСТУПНЫЕ ──────
├─ ⚠️ "Кроссовки Nike Air" - Доступно
├─ ⚠️ "Футболка Adidas" - Доступно
├─ ────── СВЯЗАННЫЕ ──────
├─ ✅ "Джинсы Levi's" - Связано
├─ ────── ЗАНЯТЫЕ ──────
└─ ❌ "Куртка Puma" - Занято (товар "Верхняя одежда") [disabled]
```
**ВАЛИДАЦИЯ**:
- Связь опциональна - можно создать поставку без привязки
- При выборе занятой карточки показывать предупреждение
- При отвязке подтверждать действие
#### 17.5.6 Интеграция с существующими правилами
**СОВМЕСТИМОСТЬ**:
- Не нарушает существующую логику создания поставок
- Дополняет рецептуру метаданными
- Совместима с типами поставок (карточки/поставщики)
**ОБЯЗАТЕЛЬНОСТЬ**:
- Связь с карточкой - ОПЦИОНАЛЬНА
- Товар может существовать без привязки к МП
- Карточка может существовать без привязки к товару
**ПРИОРИТЕТ РАЗРАБОТКИ**: Средний (не блокирует основную функциональность)
---
## 18. 🛠️ GRAPHQL И TYPESCRIPT ПРАВИЛА
### 18.1 Правила именования полей
**ВАЖНО**: Имена полей в GraphQL запросах должны точно соответствовать схеме!
```typescript
// ✅ ПРАВИЛЬНО - соответствует схеме
export const GET_MY_COUNTERPARTIES = gql`
query GetMyCounterparties {
myCounterparties { // <- имя поля в схеме
id
name
type
}
}
`
// Использование в компоненте
const allCounterparties = counterpartiesData?.myCounterparties || []
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует схеме
const allCounterparties = counterpartiesData?.getMyCounterparties || [] // Ошибка!
```
### 18.2 Правила отладки GraphQL
**При проблемах с GraphQL запросами следовать чек-листу**:
1. **Проверить соответствие имен полей схеме**
2. **Добавить fetchPolicy: 'network-only' для обхода кеша**
3. **Логировать данные в браузере и сервере**
4. **Проверить авторизацию пользователя**
5. **Убедиться что резолвер вызывается**
### 18.3 Обязательные поля для отладки
```typescript
const { data, loading, error } = useQuery(QUERY_NAME, {
fetchPolicy: 'network-only', // Обходим кеш при отладке
errorPolicy: 'all', // Показываем все ошибки
})
// Логирование для отладки
console.log('Data:', data)
console.log('Loading:', loading)
console.log('Error:', error)
```
### 18.4 TypeScript Rules
#### **Интерфейсы данных**
**Поля интерфейсов должны соответствовать GraphQL схеме**:
```typescript
// ✅ ПРАВИЛЬНО - соответствует schema.prisma
interface GoodsProduct {
id: string
name: string
article: string // <- соответствует полю в schema
quantity?: number // <- соответствует полю в schema
organization: {
id: string
name: string
}
}
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует schema
interface GoodsProduct {
sku: string // <- в schema поле называется 'article'
stock?: number // <- в schema поле называется 'quantity'
}
```
### 18.5 Система партнерства в GraphQL
**ПРАВИЛА ИСПОЛЬЗОВАНИЯ ПАРТНЕРСТВА**:
- Поставщики в формах берутся только из партнеров с типом `WHOLESALE`
- Используется запрос `GET_MY_COUNTERPARTIES` с фильтрацией по типу
- НЕ используется `GET_SUPPLY_SUPPLIERS` для отображения поставщиков в формах
- Партнерство создается двумя способами: через заказ в маркете или через раздел "Партнеры"
- Двусторонние записи в таблице `Counterparty` при создании партнерства
### 18.6 Архитектурные принципы GraphQL
- **Создавать специализированные резолверы** для каждого контекста использования
- **Использовать параметризованные запросы** (`organizationId`, `type`, `search`) вместо фильтрации на фронтенде
- **Добавлять подробное логирование** в резолверы для отладки (входные параметры, результаты фильтрации)
- **Типы запросов должны отражать бизнес-логику**: `organizationProducts` для товаров конкретной организации
### 18.7 Правила РЫНКОВ и МАРКЕТА
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ:**
- **РЫНОК** 🏪 = физическое место (Садовод, ТЯК)
- **МАРКЕТ** 🛒 = раздел системы `/market`
**ПОЛЕ РЫНКА В SCHEMA:**
- **Organization.market** ✅ - поставщик принадлежит физическому рынку
- **Product.market** ❌ - ЗАПРЕЩЕНО, товары наследуют рынок от организации
- **Отображение рынка товаров**: через `product.organization.market`
- **Фильтрация по рынкам**: через `organization.market`, НЕ через `product.market`
**ЗАПРОСЫ С РЫНКАМИ:**
```graphql
# ✅ ПРАВИЛЬНО - рынок от организации поставщика
query GetProductsWithMarket {
myProducts {
id
name
organization {
market # Физический рынок поставщика
}
}
}
# ✅ ПРАВИЛЬНО - товары в маркете с информацией о рынке
query GetMarketProducts {
marketProducts {
id
name
organization {
market # Рынок поставщика
name # Название поставщика
}
}
}
```
**МАРКЕТ (/market) ПРАВИЛА:**
- **Назначение**: Глобальный каталог всех товаров
- **Фильтрация**: По рынкам поставщиков, типам товаров, категориям
- **Отображение**: Показать рынок поставщика в карточках товаров
- **НЕ путать**: МАРКЕТ ≠ конкретный физический рынок
- **Значения по умолчанию в резолверах** для критических параметров (`type: args.type || "PRODUCT"`)
- **Валидация обязательных параметров** на уровне схемы (`organizationId: ID!`)
- **Кеширование обходить при проблемах** через `fetchPolicy: 'network-only'`
### 18.8 GraphQL правила для поля organization в мутациях
#### 18.8.1 Обязательность поля organization
**ПРАВИЛО**: Все мутации, возвращающие объекты с типом, включающим `organization: Organization!`, ДОЛЖНЫ запрашивать это поле.
**ПРОБЛЕМА**: Apollo Client кэш ожидает поле `organization` в ответе, если оно определено в GraphQL типе как обязательное.
#### 18.8.2 Правильное написание мутаций
**❌ НЕПРАВИЛЬНО** (вызывает ошибку Apollo Client):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
# НЕТ поля organization - ОШИБКА кэша!
}
}
}
```
**✅ ПРАВИЛЬНО** (работает корректно):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
organization {
# ОБЯЗАТЕЛЬНО включить!
id
name
fullName
}
}
}
}
```
#### 18.8.3 Чек-лист для мутаций
**ОБЯЗАТЕЛЬНАЯ ПРОВЕРКА** перед созданием мутации:
1. ✅ Проверить GraphQL тип возвращаемого объекта
2. ✅ Если есть поле `organization: Organization!` - добавить в запрос
3. ✅ Включить минимальные поля: `id`, `name`, `fullName`
4. ✅ Проверить resolver включает `include: { organization: true }`
**ПРИМЕНЯЕТСЯ К**:
- `CREATE_LOGISTICS` ✅ Исправлено
- `UPDATE_LOGISTICS` ✅ Исправлено
- `CREATE_SERVICE` - проверить при разработке
- `UPDATE_SERVICE` - проверить при разработке
- Все другие мутации с организационными объектами
**ОШИБКА БЕЗ ПОЛЯ**: `Error converting field "organization" of expected non-nullable type`
---
## 19. 🔧 АРХИТЕКТУРНЫЕ ПРИНЦИПЫ
### 19.1 Стандарты разработки
- **ОБЯЗАТЕЛЬНО**: Покрытие тестами критической функциональности
- **ПРАВИЛО**: Следование принципам SOLID
- **ФУНКЦИЯ**: Автоматическое тестирование при развертывании
- **КАЧЕСТВО**: Минимальное покрытие тестами 80%
### 19.2 Документация
- **ОБЯЗАТЕЛЬНО**: Документирование всех API методов
- **ПРАВИЛО**: Комментарии к сложной бизнес-логике
- **ФУНКЦИЯ**: Автоматическая генерация документации
- **СТАНДАРТ**: Актуальная техническая документация
### 19.3 Масштабируемость
- **АРХИТЕКТУРА**: Модульная структура для легкого расширения
- **ПРАВИЛО**: Использование индексов для быстрого поиска
- **ФУНКЦИЯ**: Горизонтальное масштабирование при росте нагрузки
- **ПЛАНИРОВАНИЕ**: Готовность к увеличению нагрузки в 10 раз
### 19.4 Безопасность данных
- **ОБЯЗАТЕЛЬНО**: Шифрование чувствительных данных
- **ПРАВИЛО**: Аудит всех действий пользователей
- **ФУНКЦИЯ**: Контроль доступа на уровне API
- **БЕЗОПАСНОСТЬ**: Двухфакторная аутентификация для критических операций
---
## 20. 🎯 ПРАВИЛА КАЧЕСТВА КОДА
### 20.1 Проверки и валидация
**ОБЯЗАТЕЛЬНЫЕ ПРОВЕРКИ**:
- ✅ Типизация предметов: каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируются)
- ✅ БРАК и ПРОДУКТ имеют обязательную связь с родительским товаром (parentId)
- ✅ Расходники создаются как универсальный тип, классифицируются при заказе
- ✅ **В формах создания поставок товаров показываются ТОЛЬКО предметы типа ТОВАР** (`PRODUCT`)
- ✅ **В формах создания поставок расходников показываются ТОЛЬКО предметы типа РАСХОДНИКИ** (`CONSUMABLE`)
- ✅ **Фильтрация по типу предмета происходит на уровне GraphQL резолвера**, не на фронтенде
### 20.2 Workflow статусов
- ✅ Соблюдена последовательность: PENDING → SUPPLIER_APPROVED → CONFIRMED → LOGISTICS_CONFIRMED → SHIPPED → IN_TRANSIT → DELIVERED
- ✅ Нет пропуска промежуточных статусов
- ✅ Каждое изменение статуса сопровождается уведомлением
### 20.3 Правила доступа
- ✅ Поставщик НЕ может добавлять собственные товары в корзину
- ✅ Заказ брака ЗАПРЕЩЕН
- ✅ Только активные предметы отображаются в маркете
- ✅ Проверка остатков перед добавлением в корзину
---
## 21. 🔍 ДИАГНОСТИКА И РЕШЕНИЕ ПРОБЛЕМ
### 21.1 Правило уточнений
**КРИТИЧЕСКИ ВАЖНО**: Если я не уверен в выполнении задачи или вижу противоречия в правилах - ОБЯЗАТЕЛЬНО уточнить у пользователя!
### 21.2 КОГДА УТОЧНЯТЬ:
- [ ] Недостаточно информации для правильного выполнения
- [ ] Вижу противоречия между правилами
- [ ] Задача может нарушить критические правила
- [ ] Неясно как применить правило в конкретной ситуации
- [ ] Есть сомнения в интерпретации требований
### 21.3 КАК УТОЧНЯТЬ:
1. Четко сформулировать что именно неясно
2. Указать какие правила/требования конфликтуют
3. Предложить варианты решения если возможно
4. Запросить конкретные уточнения
**❌ НИКОГДА не делать предположений если есть сомнения!**
---
## 22. 📋 КАТЕГОРИИ ТОВАРОВ И РАСХОДНИКОВ
### 22.1 Полный список 28 универсальных категорий товаров
1. Одежда и обувь
2. Косметика и парфюмерия
3. Дом и сад
4. Детские товары
5. Спорт и отдых
6. Электроника
7. Книги
8. Здоровье
9. Автотовары
10. Строительство и ремонт
11. Продукты питания
12. Зоотовары
13. Дача, сад и огород
14. Канцелярские товары
15. Хобби и творчество
16. Украшения и аксессуары
17. Сумки и чемоданы
18. Техника для дома
19. Музыкальные инструменты
20. Игры и игрушки
21. Мебель
22. Товары для красоты
23. Бытовая химия
24. Товары для путешествий
25. Медицинские товары
26. Религиозные товары
27. Антиквариат и коллекционирование
28. Прочие товары
### 22.2 12 специализированных категорий расходников
#### 🎁 **1. УПАКОВКА И ЗАЩИТА**
- Коробки (различных размеров)
- Пакеты (полиэтиленовые, бумажные, фирменные)
- Пузырчатая пленка, воздушные подушки
- Стрейч-пленка, гофрокартон
- Паллетная пленка, защитные уголки
#### 🏷️ **2. МАРКИРОВКА И ИДЕНТИФИКАЦИЯ**
- Этикетки (адресные, штрих-код, QR-код)
- Бирки (ценники, размерники)
- Стикеры и наклейки
- Маркеры и ручки
- Штампы и печати, термоэтикетки
#### 🔧 **3. КРЕПЕЖ И СОЕДИНЕНИЕ**
- Скотч (прозрачный, цветной, армированный)
- Клей и клеевые составы
- Стяжки пластиковые
- Степлер и скобы
- Веревки и шнуры, стрейч-лента
#### 📄 **4. ДОКУМЕНТООБОРОТ И ВКЛАДЫШИ**
- Накладные и сопроводительные документы
- Инструкции по эксплуатации
- Гарантийные талоны
- Рекламные буклеты, визитки и флаеры
- Благодарственные письма, купоны и промокоды
#### 🧼 **5. ГИГИЕНА И БЕЗОПАСНОСТЬ**
- Перчатки (латексные, нитриловые)
- Маски и респираторы
- Антисептики и дезинфекторы
- Салфетки и тряпки
- Фартуки и халаты, бахилы
#### 🛠️ **6. ИНСТРУМЕНТЫ И ПРИСПОСОБЛЕНИЯ**
- Ножи и резаки, ножницы
- Линейки и рулетки
- Упаковочные машины (ленточные)
- Дозаторы скотча
- Пистолеты для термоклея
- Весы и мерная тара
#### 🎨 **7. БРЕНДИНГ И ДИЗАЙН**
- Фирменные пакеты с логотипом
- Брендированные коробки
- Цветная упаковочная бумага
- Ленты и банты
- Наклейки с логотипом компании
- Подарочная упаковка
#### ⚡ **8. СПЕЦИАЛИЗИРОВАННЫЕ МАТЕРИАЛЫ**
- Антистатические пакеты
- Влагопоглотители
- Температурные индикаторы
- Хрупкие наклейки
- Пломбы и пломбировочные материалы
- Защита от краж (магнитные датчики)
#### 🏪 **9. ТОРГОВОЕ ОБОРУДОВАНИЕ**
- Манекены и вешалки
- Ценникодержатели
- Подставки и стойки
- Корзины и тележки
- Зеркала примерочные
- Освещение витрин
#### 🚚 **10. ЛОГИСТИКА И СКЛАДИРОВАНИЕ**
- Паллеты и поддоны
- Контейнеры и ящики
- Стеллажные системы
- Погрузочные ремни
- Защитные чехлы
- Адресные ярлыки для груза
#### 💻 **11. ТЕХНИЧЕСКИЕ РАСХОДНИКИ**
- Картриджи для принтеров
- Термоголовки, красящие ленты
- Батарейки для сканеров
- Чистящие средства для техники
- Запчасти для упаковочного оборудования
#### 🎪 **12. СЕЗОННЫЕ И ПРАЗДНИЧНЫЕ**
- Новогодняя упаковка
- Подарочные мешки
- Праздничные ленты
- Тематические наклейки
- Открытки и поздравления
- Сезонная упаковочная бумага
**ПРИМЕЧАНИЕ**: Данные категории являются рекомендательными и могут быть адаптированы под специфику конкретного поставщика расходников.
---
## 23. 🎖️ ПРИОРИТЕТЫ РАЗРАБОТКИ
### 23.1 ВЫСОКИЙ ПРИОРИТЕТ:
1. 🔴 Безопасность и контроль доступа
2. 🔴 Целостность данных и валидация
3. 🔴 Корректность статусов поставок
4. 🔴 Уведомления участников процесса
5. 🔴 Правильная типизация предметов
6. 🔴 Связи между товарами и производными типами
### 23.2 СРЕДНИЙ ПРИОРИТЕТ:
1. 🟡 Производительность и оптимизация
2. 🟡 Пользовательский опыт
3. 🟡 Аналитика и отчетность
4. 🟡 Интеграции с внешними системами
5. 🟡 Workflow для брака и продуктов
6. 🟡 Разделение расходников по типам
### 23.3 НИЗКИЙ ПРИОРИТЕТ:
1. 🟢 Дополнительные фильтры
2. 🟢 Косметические улучшения
3. 🟢 Экспериментальные функции
4. 🟢 Расширенная кастомизация
---
## 🚨 КРИТИЧЕСКИЕ СИТУАЦИИ И EDGE CASES
### 🔴 Отмена заказов на разных этапах workflow
**PENDING → Отмена разрешена**
- Действие: Удаление заказа без последствий
- Уведомления: Поставщику о отмене
- Влияние на статистику: Нет
**SUPPLIER_APPROVED → Отмена с согласия поставщика**
- Действие: Требуется подтверждение поставщика
- Штрафы: Возможны согласно договору
- Восстановление: Товары возвращаются в доступные остатки
**CONFIRMED/LOGISTICS_CONFIRMED → Отмена критическая**
- Действие: Требуется согласие всех участников
- Штрафы: Логистические расходы
- Альтернатива: Изменение адреса доставки
**SHIPPED/IN_TRANSIT → Отмена невозможна**
- Действие: Только возврат после получения
- Процедура: Через модуль "Возвраты с ПВЗ"
### 🔄 Частичная доставка товаров
**Сценарий**: Поставщик доставил 80 из 100 заказанных единиц
**Алгоритм обработки**:
1. Фулфилмент фиксирует фактическое количество
2. Система создает два отдельных документа:
- DELIVERED (80 единиц) - обрабатывается обычным порядком
- PARTIAL_DELIVERED (20 единиц) - остается в статусе ожидания
3. Селлер получает уведомление о частичной поставке
4. Принятие решения: ждать остаток или отменить недопоставку
### 📊 Превышение лимитов остатков
**Проблема**: Попытка заказать больше чем есть у поставщика
**Техническая реализация**:
```typescript
if (requestedQuantity > availableStock) {
throw new GraphQLError(`Недостаточно товара. Доступно: ${availableStock}, запрошено: ${requestedQuantity}`)
}
```
**UX решение**: Real-time валидация в формах заказа
### 🔍 Дубликаты артикулов
**Сценарий**: Поставщик пытается создать товар с существующим артикулом
**Проверка на уровне БД**:
```sql
UNIQUE INDEX ON products(article, organization_id)
```
**Обработка**: Автоматическое добавление суффикса или предложение изменить артикул
---
## 24. 📎 ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ
### Приложение A: GraphQL запросы фулфилмента
```typescript
// Основные запросы
GET_MY_SERVICES // Услуги фулфилмента
GET_MY_LOGISTICS // Логистические маршруты
GET_MY_EMPLOYEES // Сотрудники организации
GET_FULFILLMENT_WAREHOUSE_STATS // Статистика склада
GET_WAREHOUSE_PRODUCTS // Товары на складе
GET_MY_FULFILLMENT_SUPPLIES // Расходники фулфилмента
GET_EMPLOYEE_SCHEDULE // Табель рабочего времени
// Мутации
;(CREATE_SERVICE, UPDATE_SERVICE, DELETE_SERVICE)
;(CREATE_LOGISTICS, UPDATE_LOGISTICS, DELETE_LOGISTICS)
;(CREATE_EMPLOYEE, UPDATE_EMPLOYEE, DELETE_EMPLOYEE)
UPDATE_EMPLOYEE_SCHEDULE // Обновление табеля
```
### Приложение B: Компоненты фулфилмента
```typescript
// Основные dashboard компоненты
FulfillmentWarehouseDashboard // Склад фулфилмента
FulfillmentStatisticsDashboard // Статистика
ServicesDashboard // Услуги (3 вкладки)
EmployeesDashboard // Сотрудники
SuppliesDashboard // Поставки фулфилмента
// Специализированные компоненты
;(ServicesTab, LogisticsTab, SuppliesTab) // Вкладки услуг
;(EmployeeInlineForm, EmployeeEditInlineForm) // Формы сотрудников
;(FulfillmentSuppliesTab, FulfillmentConsumablesOrdersTab) // Поставки
```
### Приложение C: Специальный роутинг для типов организаций
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies') // Специальный роут
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/wholesale-supplies')
break
case 'LOGIST':
router.push('/logist-supplies')
break
}
}
```
---
_Эта база знаний создана путем объединения rules-unified.md (v3.0) и fulfillment-cabinet-rules.md (v1.0) с устранением всех несоответствий и добавлением критически важных улучшений: быстрый справочник, глоссарий терминов, детальные алгоритмы процессов, edge cases._
_Версия: 10.1_
ата создания: 2025_
_Статус: ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ - ГОТОВ К РАЗРАБОТКЕ_
### 🚀 УЛУЧШЕНИЯ v6.0:
- Быстрый справочник критических правил
- 🔤 Полный глоссарий терминов с определениями
- 🎯 Навигация по ролям (разработчики, аналитики, менеджеры)
- 🔄 Детальный алгоритм создания продукта с временными рамками
- 🚨 Раздел критических ситуаций и Edge Cases
- 📌 Связующие блоки между разделами
- 📊 Таблицы SLA и временных рамок
### 🔧 ИСПРАВЛЕНИЯ v6.1:
- Устранено противоречие в моменте создания БРАКА
- Исправлена логическая цепочка: рецептура задается селлером ДО процесса
- Реалистичные временные рамки SLA (рабочие дни вместо часов)
- Унифицирована классификация расходников (по назначению при использовании)
- Согласованы все алгоритмы и процессы между разделами
### 🔧 ОБНОВЛЕНИЯ v6.3:
- **ДОБАВЛЕН КРИТИЧЕСКИЙ ЗАПРЕТ**: Использование моковых данных в продакшене
- **ОБНОВЛЕН ЧЕКЛИСТ**: Добавлена проверка на отсутствие mock данных
- **РЕАЛИЗАЦИЯ**: Полная очистка моковых данных из раздела "Мои поставки" селлера
### 🎨 ИНТЕГРАЦИЯ v6.2:
- Синхронизация с visual-design-rules.md v1.1
- Добавлены визуальные правила для 8 статусов поставок
- Создана цветовая система для 6 модулей фулфилмента
- Визуальный workflow процесса создания продукта
- Перекрестные ссылки между техническими и визуальными правилами
- Покрытие визуальными решениями увеличено с 40% до 85%
### 🚀 КОНСОЛИДАЦИЯ v7.0:
- Интеграция development-checklist.md и CLAUDE.md
- Удаление дублирующих файлов
- Создание единого источника истины
### 🔧 ПОЛНАЯ ИНТЕГРАЦИЯ v8.0:
- Интеграция work-protocols.md (детальные протоколы по сложности)
- Интеграция violation-prevention-protocol.md (СТОП-сигналы и триггеры)
- Интеграция self-validation.md (расширенная система самопроверки)
- Удаление всех дублирующих файлов протоколов
### 🎯 ОПТИМИЗАЦИЯ UI/UX v8.1:
- Добавлен ТРИГГЕР #3 для автоматической активации visual-design-rules.md
- Интегрирован специальный UI/UX протокол в чеклист
- Создана система перекрестных ссылок с visual-design-rules.md
- visual-design-rules.md остается отдельным специализированным файлом
### 📊 ИНТЕГРАЦИЯ DESCRIPTION v9.0:
- Добавлена UI структура создания поставки расходников (3 блока)
- Интегрирована концепция многоуровневых таблиц
- Добавлен механизм учета ПЛАН/ФАКТ в процессе создания продукта
- Расширена детализация рецептуры продукта
- Добавлена опция места хранения готовых продуктов
### 🔧 УТОЧНЕНИЯ ЛОГИКИ v9.1:
- Уточнен статус брака: НЕ РЕАЛИЗОВАНО (еще не дошли до этого этапа)
- Добавлены четкие правила создания предметов по ролям
- Добавлен экономический учет расходников фулфилмента для селлера
- Обновлен механизм ПЛАН/ФАКТ: потери вместо брака при пересчете
- Добавлена заметка о будущей детализации статусов товаров
### 🎨 UI УЛУЧШЕНИЯ v9.2:
- Добавлены детальные правила горизонтального скролла для блока поставщиков
- Реализован горизонтальный скролл в create-suppliers-supply-page.tsx
- Добавлена адаптивность (десктоп 280px, планшет 260px, мобильный 240px)
- Интегрированы ARIA атрибуты для доступности
- Реализовано автоскрытие полосы прокрутки и навигация клавиатурой
### 🔒 БЕЗОПАСНОСТЬ И ТЕРМИНОЛОГИЯ v10.0:
- **ДОБАВЛЕН РАЗДЕЛ 17.3**: Правила безопасности - разделение данных и функционала
- **НОВЫЕ ЗАПРЕТЫ 24-26**: Запрет использования пользовательских данных в логике безопасности
- **РАСШИРЕН ГЛОССАРИЙ**: Контекстно-зависимые термины для SupplyOrder
- **УТОЧНЕНИЕ ТЕРМИНОВ**: Четкое разделение "Маркет" (раздел) vs "Маркетплейс" (внешние площадки)
- **ПРИМЕРЫ УЯЗВИМОСТЕЙ**: Конкретные примеры безопасного и небезопасного кода
### 📝 КАЧЕСТВО ОТВЕТОВ v10.1:
- **НОВЫЕ ЗАПРЕТЫ 27-29**: Запрет представления интерпретаций как фактов
- **ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ 17.3**: Четкое разделение фактов, интерпретаций и предположений
- **СИСТЕМА МАРКИРОВКИ**: 📖 ФАКТ, 🧠 ИНТЕРПРЕТАЦИЯ, ПРЕДПОЛОЖЕНИЕ, НЕ НАЙДЕНО
- **СТОП-СЛОВА**: Список категоричных утверждений для избегания без доказательств
- **ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА 11-13**: Указание источников и осторожные формулировки

View File

@ -0,0 +1,3378 @@
# 🔒 РЕЗЕРВНАЯ КОПИЯ - НЕ РЕДАКТИРОВАТЬ БЕЗ РАЗРЕШЕНИЯ!
> 🚨 **КРИТИЧЕСКИ ВАЖНО**: Это РЕЗЕРВНАЯ КОПИЯ файла rules-complete.md
>
> ❌ **ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!**
>
> 📅 **Дата создания резерва**: 2025-08-08
> 🔐 **Статус**: ЗАЩИЩЕН ОТ ИЗМЕНЕНИЙ
> 📄 **Оригинальный файл**: rules-complete.md
---
# ПРАВИЛА СИСТЕМЫ УПРАВЛЕНИЯ СКЛАДАМИ И ПОСТАВКАМИ - ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ v10.0
> ⚠️ **АБСОЛЮТНО ПОЛНЫЙ ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ**: Данный файл объединяет АБСОЛЮТНО ВСЕ правила системы: протоколы работы Claude Code, детальные протоколы по сложности, систему предотвращения нарушений, расширенную самопроверку, специальный UI/UX протокол и бизнес-правила. Визуальные правила вынесены в отдельный файл visual-design-rules.md с автоматической интеграцией.
## 📚 СТРУКТУРА ДОКУМЕНТАЦИИ
### Основные файлы правил:
- **rules-complete.md** (этот файл) - общие бизнес-правила и процессы
- **wholesale-cabinet-rules.md** - технические детали кабинета поставщика
- **visual-design-rules.md** - визуальные правила (уже интегрирован)
### Когда какой файл читать:
- При работе с компонентами поставщика → [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md)
- При изменении бизнес-логики → rules-complete.md
- При работе с UI/UX → [visual-design-rules.md](./visual-design-rules.md)
## 🔴 ПРАВИЛА ВЗАИМОДЕЙСТВИЯ С CLAUDE
### Основные принципы работы:
- **Двухэтапный процесс**: Планирование → Одобрение → Выполнение
- **Обязательное чтение правил** перед каждой задачей
- **Детальные протоколы** по сложности задач
- **Система проверок** и самоконтроля
- **Честность и прозрачность** при неопределенности
### Обязательная последовательность:
1. Читать rules-complete.md перед началом работы
2. Определить сложность задачи
3. Применить соответствующий протокол
4. Создать план через TodoWrite
5. Получить одобрение пользователя
6. Выполнить согласно плану
7. Проверить качество результата
## 🛠️ ПРОТОКОЛЫ РАБОТЫ ПО СЛОЖНОСТИ
### Краткий обзор протоколов:
- **Простые задачи**: Прямое выполнение с базовыми проверками
- **Средние задачи**: Трехэтапный процесс (Анализ → План → Выполнение)
- **Сложные задачи**: Расширенный анализ с множественными проверками
- **Критические задачи**: Полный протокол безопасности
### Определение сложности:
- **Средняя**: 2-3 файла, изменение логики в 1-2 модулях
- **Высокая**: 4+ файлов, изменение архитектуры, влияние на несколько кабинетов
### 🔥 ПРОТОКОЛ ВЫСОКОЙ СЛОЖНОСТИ
**Обязательные этапы для сложных задач:**
1. **СТОП! ГЛУБОКИЙ АНАЛИЗ** - уточнить все требования у пользователя
2. **ИССЛЕДОВАНИЕ** - изучить все связанные файлы параллельно
3. **ДЕТАЛЬНЫЙ ПЛАН** - с промежуточными проверками и rollback точками
### ❓ СИСТЕМА УТОЧНЕНИЙ
**Когда ОБЯЗАТЕЛЬНО спрашивать:**
- Обнаружил противоречие в правилах
- Задача может нарушить архитектуру системы
- Неясно как применить правило к ситуации
- Есть несколько способов с разными последствиями
### 🎨 UI/UX ПРОТОКОЛ
**Автоматическая активация** при ключевых словах: дизайн, интерфейс, компонент, UI, UX
**Обязательно:**
- Прочитать visual-design-rules.md перед началом
- Проверить соответствие цветовой палитре
- Использовать glass-эффекты согласно дизайн-системе
## 🚨 СИСТЕМА КОНТРОЛЯ КАЧЕСТВА
### Принципы контроля:
- **Стоп-сигналы** перед критическими действиями
- **Принудительные проверки** соблюдения протоколов
- **Автоматические триггеры** для специфических ситуаций
- **Система блокировки** нарушений
- **Расширенная самопроверка** с финальными проверками
### Обязательные остановки:
- Перед анализом компонентов без использования инструментов
- При любой неопределенности или сомнениях
- Перед выполнением средних/сложных задач без протокола
### Финальная проверка:
"Применил ли правильный протокол, проверил все правила, готов результат к production?"
## ⚡ БЫСТРЫЙ СПРАВОЧНИК
### 🚨 КРИТИЧЕСКИЕ ПРАВИЛА (ОБЯЗАТЕЛЬНЫ К СОБЛЮДЕНИЮ)
1. **🔴 ТИПИЗАЦИЯ**: Каждый предмет ОБЯЗАТЕЛЬНО имеет тип: `PRODUCT`, `CONSUMABLE`, `DEFECT`, `FINISHED_PRODUCT`
2. **🔴 WORKFLOW**: Нельзя пропускать статусы поставок: PENDING → SUPPLIER_APPROVED → CONFIRMED → ... → DELIVERED
3. **🔴 ДОСТУП**: Фулфилмент = полный доступ, Селлер ≠ доступ к чужим данным, Брак = ЗАПРЕЩЕН к заказу
4. **🔴 ПАРТНЕРСТВО**: Все связи через модель `Counterparty`, поставщики в формах ТОЛЬКО из партнеров `WHOLESALE`
5. **🔴 ФИЛЬТРАЦИЯ**: По типу предмета происходит в GraphQL резолверах, НЕ на фронтенде
### 🔍 БЫСТРЫЙ ПОИСК ПО ТЕМАМ
| Тема | Раздел | Ключевые понятия |
| ----------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------- |
| **Типы предметов** | [2](#2--типизация-предметов) | PRODUCT, CONSUMABLE, DEFECT, FINISHED_PRODUCT |
| **Кабинет фулфилмента** | [11](#11--кабинет-фулфилмента-полная-документация) | Склад, Услуги, Сотрудники, 6 модулей |
| **Workflow поставок** | [5](#5--workflow-поставок) | 8 статусов, уведомления, логистика |
| **GraphQL запросы** | [18](#18--graphql-и-typescript-правила), [24](#24--технические-приложения) | Резолверы, мутации, типизация |
| **Система партнерства** | [13](#13--система-партнерства-и-контрагентов) | Counterparty, WHOLESALE, заявки |
| **Рынки и маркет** | [10.1](#101-разделение-понятий-рынок-vs-маркет), [18.7](#187-правила-рынков-и-маркета) | РЫНОК ≠ МАРКЕТ, Organization.market |
| **Критические запреты** | [17](#17--критические-запреты) | Что НЕЛЬЗЯ делать в системе |
### 🎯 ДЛЯ РАЗНЫХ РОЛЕЙ
**👩‍💻 РАЗРАБОТЧИКИ**: Разделы [18](#18--graphql-и-typescript-правила), [19](#19--архитектурные-принципы), [20](#20--правила-качества-кода), [24](#24--технические-приложения)
**📊 АНАЛИТИКИ**: Разделы [15](#15--статистика-и-аналитика), [6](#6--процесс-создания-продукта), [7](#7--система-учета-движения-товаров)
**👔 МЕНЕДЖЕРЫ**: Разделы [1](#1--основные-принципы-системы), [3](#3--структура-кабинетов), [5](#5--workflow-поставок)
---
## 🔤 ГЛОССАРИЙ ТЕРМИНОВ
> Для людей → `В коде`
### **ТИПЫ ПРЕДМЕТОВ:**
- **ТОВАР** → `PRODUCT` - базовый товар от поставщика, может стать продуктом или браком
- **РАСХОДНИКИ** → `CONSUMABLE` - материалы, классифицируются по назначению при использовании (операционные/производственные)
- **БРАК** → `DEFECT` _(НЕ РЕАЛИЗОВАНО)_ - функционал брака еще не внедрен в систему
- **ПРОДУКТ** → `FINISHED_PRODUCT` _(планируется)_ - готовый товар, создается из товара по рецептуре
### **ТИПЫ ОРГАНИЗАЦИЙ:**
- **ПОСТАВЩИК** → `WHOLESALE` - создает товары и расходники, обрабатывает заказы
- **СЕЛЛЕР** → `SELLER` - заказывает товары, создает поставки на маркетплейсы
- **ФУЛФИЛМЕНТ** → `FULFILLMENT` - обрабатывает товары, создает продукты, максимальные права
- **ЛОГИСТИКА** → `LOGIST` - управляет доставками, подтверждает транспортировку
### 2.2 Правила создания предметов по ролям
**КТО МОЖЕТ СОЗДАВАТЬ:**
- **ПОСТАВЩИК** (`WHOLESALE`): Товары (`PRODUCT`) и Расходники (`CONSUMABLE`)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Продукты (`FINISHED_PRODUCT`) - только из существующих товаров
- **СЕЛЛЕР/ЛОГИСТ**: НЕ МОГУТ создавать предметы
**КТО МОЖЕТ ПОКУПАТЬ:**
- **СЕЛЛЕР** (`SELLER`):
- Товары и расходники у поставщиков
- Расходники фулфилмента у фулфилмента (через рецептуру в поставке)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Товары и расходники у поставщиков
- **ПОСТАВЩИК/ЛОГИСТ**: НЕ МОГУТ покупать предметы
**ЭКОНОМИЧЕСКИЙ УЧЕТ:**
- Когда селлер выбирает расходники фулфилмента в рецептуре, это формирует экономические данные:
- В кабинете селлера: расход на расходники фулфилмента
- В кабинете фулфилмента: доход от продажи расходников селлеру
### **КЛЮЧЕВЫЕ СУЩНОСТИ:**
- **Контрагент** → `Counterparty` - связь между организациями для партнерства
- **Поставка** → `SupplyOrder` - заказ товаров/расходников с workflow статусами
- **Рецептура** - состав продукта: товар + услуги + расходники (задается селлером)
### **КОНТЕКСТНО-ЗАВИСИМЫЕ ТЕРМИНЫ:**
#### **SupplyOrder - многосторонний документ**
SupplyOrder представляет собой единый документ, который видится по-разному каждым участником процесса:
**ДЛЯ СОЗДАТЕЛЕЙ (Селлер/Фулфилмент):**
- **Термин**: "Поставка"
- **Контекст**: Они создают поставку товаров и расходников на фулфилмент
- **Включает**: Весь процесс от закупки до приемки на склад
**ДЛЯ ПОСТАВЩИКА (исполнитель товарной части):**
- **Термин**: "Заявка на покупку"
- **Контекст**: Получают запрос на продажу своих товаров/расходников
- **Действия**: Могут одобрить или отклонить в зависимости от наличия
**ДЛЯ ЛОГИСТИКИ (исполнитель транспортной части):**
- **Термин**: "Заявка на доставку"
- **Контекст**: Получают запрос на транспортировку груза
- **Действия**: Могут подтвердить или отклонить в зависимости от возможностей
**ОТОБРАЖЕНИЕ В ИНТЕРФЕЙСЕ КАБИНЕТОВ:**
| Кабинет | Название раздела | Обоснование |
|---------|-----------------|-------------|
| Селлер | "Мои поставки" | Создает и управляет поставками |
| Поставщик | "Заявки на покупку" | Обрабатывает входящие заявки |
| Логистика | "Заявки на доставку" | Управляет транспортировкой |
| Фулфилмент | "Входящие поставки" | Принимает поставки на склад |
**ВАЖНО**: Это один и тот же объект SupplyOrder в базе данных, но каждый участник работает со своей стороной процесса.
#### **Маркет vs Маркетплейс - четкое разделение**
**МАРКЕТ** (`/market`):
- **Что это**: Внутренний раздел системы
- **Функция**: Глобальный каталог всех товаров от всех поставщиков
- **Доступ**: Для всех типов организаций в системе
- **НЕ путать**: С названиями физических рынков типа "ОПТ Маркет"
**МАРКЕТПЛЕЙС** (Wildberries, Ozon):
- **Что это**: Внешние торговые площадки
- **Функция**: Конечные точки продаж для селлеров
- **Интеграция**: Через API ключи в настройках
- **Использование**: "Поставки на маркетплейсы", "Отгрузка на маркетплейсы"
---
## 📑 ОГЛАВЛЕНИЕ
> 📖 **Каталог процессов**: См. [workflow-catalog.md](./workflow-catalog.md) для полного каталога всех бизнес-процессов системы
> 📋 **ЧТО ОБЪЕДИНЕНО**:
>
> - rules-unified.md (v3.0) - общая база знаний системы
> - fulfillment-cabinet-rules.md (v1.0) - детализация кабинета фулфилмента
> - Устранены все несоответствия в терминах, последовательностях и детализации
### 🏗️ **АРХИТЕКТУРА И ОСНОВЫ**
1. [🎯 Основные принципы системы](#1--основные-принципы-системы)
2. [📦 Типизация предметов](#2--типизация-предметов)
3. [🏢 Структура кабинетов](#3--структура-кабинетов)
4. [🔐 Система ролей и доступов](#4--система-ролей-и-доступов)
### 🚚 **WORKFLOW И ПРОЦЕССЫ**
5. [🚚 Workflow поставок](#5--workflow-поставок)
6. [🔄 Процесс создания продукта](#6--процесс-создания-продукта)
7. [📊 Система учета движения товаров](#7--система-учета-движения-товаров)
### 🏢 **КАБИНЕТЫ СИСТЕМЫ**
8. [🏠 Общие правила кабинетов](#8--общие-правила-кабинетов)
9. [🏠 Кабинет селлера (детальные правила)](#9--кабинет-селлера-детальные-правила)
10. [🏪 Кабинет поставщика](#10--кабинет-поставщика)
11. [🏭 Кабинет фулфилмента](#11--кабинет-фулфилмента)
12. [🚚 Кабинет логистики](#12--кабинет-логистики)
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
13. [🤝 Система партнерства и контрагентов](#13--система-партнерства-и-контрагентов)
### 🌐 **ИНТЕГРАЦИИ И ФУНКЦИИ**
14. [🌐 Интеграции с системой](#14--интеграции-с-системой)
15. [📊 Статистика и аналитика](#15--статистика-и-аналитика)
16. [📱 Правила UI/UX и интерфейса](#16--правила-uiux-и-интерфейса)
17. [⚠️ Критические запреты](#17--критические-запреты)
### 🛠️ **ТЕХНИЧЕСКИЕ ПРАВИЛА**
18. [🛠️ GraphQL и TypeScript правила](#18--graphql-и-typescript-правила)
19. [🔧 Архитектурные принципы](#19--архитектурные-принципы)
20. [🎯 Правила качества кода](#20--правила-качества-кода)
21. [🔍 Диагностика и решение проблем](#21--диагностика-и-решение-проблем)
### 📋 **ПРИЛОЖЕНИЯ**
22. [📋 Категории товаров и расходников](#22--категории-товаров-и-расходников)
23. [🎖️ Приоритеты разработки](#23--приоритеты-разработки)
### 🚨 **КРИТИЧЕСКИЕ СИТУАЦИИ**
24. [🚨 Критические ситуации и Edge Cases](#-критические-ситуации-и-edge-cases)
### 📎 **ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ**
25. [📎 Технические приложения (GraphQL, компоненты)](#24--технические-приложения)
---
## 🏷️ РЕЕСТР СУЩНОСТЕЙ СИСТЕМЫ
### 📦 **ОСНОВНЫЕ ПРЕДМЕТЫ**
| Сущность | Название в системе | Кабинет создания | Описание | Статус |
| ---------- | -------------------------------------- | ---------------- | ----------------------------------------------- | -------------- |
| Товар | `Product` (type: `PRODUCT`) | Поставщик | Базовый тип товара от поставщика | ✅ Реализовано |
| Расходники | `Product` (type: `CONSUMABLE`) | Поставщик | Материалы и вспомогательные товары | ✅ Реализовано |
| Брак | `Product` (type: `DEFECT`)\* | Фулфилмент | Производная от товара с дефектами | 📋 Планируется |
| Продукт | `Product` (type: `FINISHED_PRODUCT`)\* | Фулфилмент | Готовый к продаже товар (производная от товара) | 📋 Планируется |
> **\* Планируется**: Типы `DEFECT` и `FINISHED_PRODUCT` еще не добавлены в Prisma схему
### 🏢 **ОРГАНИЗАЦИИ И РОЛИ**
| Сущность | Название в системе | Основные функции | Статус |
| ---------- | ------------------------------------ | --------------------------------------- | -------------- |
| Поставщик | `Organization` (type: `WHOLESALE`) | Создание товаров, управление поставками | ✅ Реализовано |
| Селлер | `Organization` (type: `SELLER`) | Заказ товаров, управление поставками | ✅ Реализовано |
| Фулфилмент | `Organization` (type: `FULFILLMENT`) | Обработка товаров, управление складом | ✅ Реализовано |
| Логистика | `Organization` (type: `LOGIST`) | Управление доставками | ✅ Реализовано |
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
| Сущность | Название в системе | Описание | Статус |
| ---------- | --------------------- | ------------------------- | -------------- |
| Контрагент | `Counterparty` | Связь между организациями | ✅ Реализовано |
| Заявка | `CounterpartyRequest` | Запрос на сотрудничество | ✅ Реализовано |
---
## 1. 🎯 ОСНОВНЫЕ ПРИНЦИПЫ СИСТЕМЫ
### 1.1 Архитектура системы
**СТРУКТУРА СИСТЕМЫ ПО КАБИНЕТАМ:**
**🏢 КАБИНЕТ ПОСТАВЩИКА** - создает и управляет:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщика
- **РАСХОДНИКИ** (`CONSUMABLE`) - материалы и вспомогательные товары от поставщика
**🏭 КАБИНЕТ ФУЛФИЛМЕНТА** - принимает, обрабатывает и управляет всеми типами:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщиков (принятые на склад)
- **БРАК** (`DEFECT` - планируется) - производная от товара (товар с дефектами)
- **ПРОДУКТ** (`FINISHED_PRODUCT` - планируется) - готовый к продаже товар
- **РАСХОДНИКИ (`CONSUMABLE`)** - единый базовый тип, классифицируется по назначению при использовании:
- **"Операционные расходники"** - используются фулфилментом для выполнения услуг
- **"Производственные расходники"** - используются в рецептурах селлеров для создания продуктов
**🛍️ КАБИНЕТ СЕЛЛЕРА** - заказывает и управляет поставками:
- Создает заказы товаров и расходников
- Управляет поставками на фулфилмент и маркетплейсы
- Отслеживает статусы поставок
### 1.2 Основные принципы разработки
**КРИТИЧЕСКИ ВАЖНЫЕ ПРИНЦИПЫ:**
1. **Строгая типизация**: Каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируется)
2. **Партнерская система**: Все связи между организациями через модель `Counterparty`
3. **Workflow статусов**: Строгая последовательность статусов поставок
4. **Безопасность доступа**: Контроль доступа на уровне GraphQL резолверов
5. **Единый источник истины**: Централизованное управление данными
---
## 2. 📦 ТИПИЗАЦИЯ ПРЕДМЕТОВ
### 2.1 Два реализованных и два планируемых типа предметов
#### **1. ТОВАР** (`PRODUCT` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком
- **СТАТУС**: Может быть активным/неактивным
- **ЗАКАЗ**: Доступен для заказа всеми типами организаций
- **ТРАНСФОРМАЦИЯ**: Может стать ПРОДУКТОМ или БРАКОМ
- **ЦЕНА**: Обязательна, больше 0
#### **2. РАСХОДНИКИ** (`CONSUMABLE` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком как универсальный тип
- **КЛАССИФИКАЦИЯ ПРИ ЗАКАЗЕ**:
- Фулфилмент заказывает → "Расходники фулфилмента"
- Селлер заказывает → "Расходники селлеров"
- **ДОСТУП**: Видны всем типам организаций в маркете
#### **3. БРАК** (`DEFECT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе существующего ТОВАРА при обнаружении дефектов
- **МОМЕНТ СОЗДАНИЯ**: В процессе обработки товара (ШАГ 3 алгоритма создания продукта) при выявлении брака
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **ЗАКАЗ**: ЗАПРЕЩЕН заказ брака
- **СТАТУС**: Всегда неактивен для заказа
- **ЦЕНА**: Для селлера - себестоимость дефектного товара, для фулфилмента - 0
- **WORKFLOW**: Особый процесс списания и утилизации
- **УЧЕТ**: Отдельный учет в статистике потерь
- **ОТОБРАЖЕНИЕ**: Виден только для учета потерь
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `DEFECT` еще не добавлен в схему БД
#### **4. ПРОДУКТ** (`FINISHED_PRODUCT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе ТОВАРА по заказу селлера
- **ИНИЦИАТОР**: Селлер создает заказ с рецептурой, фулфилмент исполняет
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **РЕЦЕПТУРА**: Задается селлером при создании заказа (Товар + Услуга + Расходники)
- **СТАТУСЫ**: "в работе" → "готов к отправке"
- **ЗАКАЗ**: Доступен только в статусе "готов к отправке"
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `FINISHED_PRODUCT` еще не добавлен в схему БД
### 2.2 Обязательные поля карточки
**КРИТИЧЕСКИ ВАЖНО**: Название, артикул, цена > 0, тип предмета
**ИСКЛЮЧЕНИЕ ДЛЯ БРАКА**: Цена может быть 0 для фулфилмента (себестоимость для селлера)
**ОБЯЗАТЕЛЬНО**: Количество (может быть 0 для предзаказа)
**ДЛЯ ПРОИЗВОДНЫХ ТИПОВ**: Обязательная связь с родительским предметом
---
## 3. 🏢 СТРУКТУРА КАБИНЕТОВ
### 3.1 Общие принципы кабинетов
**КАЖДЫЙ КАБИНЕТ ИМЕЕТ:**
1. **Главная страница** (`/dashboard`) - общая информация и статистика
2. **Экономика** (`/economics`) - финансовая аналитика
3. **Универсальные разделы**:
- Маркет (`/market`) - просмотр и заказ товаров
- Партнеры (`/partners`) - управление контрагентами
- Мессенджер (`/messenger`) - связь между организациями
- Настройки (`/settings`) - профиль и API ключи
### 3.2 Специфические разделы по типам организаций
**🏪 ПОСТАВЩИК (`WHOLESALE`):**
- Склад (`/warehouse`) - управление товарами и расходниками
- Поставки (`/supplies`) - обработка заказов от селлеров
**🛍️ СЕЛЛЕР (`SELLER`):**
- Мои поставки (`/supplies`) - управление заказами товаров
- WB Интеграция (`/wb-integration`) - связь с Wildberries
**🏭 ФУЛФИЛМЕНТ (`FULFILLMENT`):**
- Склад фулфилмента (`/fulfillment-warehouse`) - управление всеми типами товаров
- Поставки фулфилмента (`/fulfillment-supplies`) - обработка поставок
- Услуги (`/services`) - управление услугами, логистикой, расходниками
- Сотрудники (`/employees`) - управление персоналом
- Статистика фулфилмента (`/fulfillment-statistics`) - детальная аналитика
**🚚 ЛОГИСТИКА (`LOGIST`):**
- Заявки (`/logistics-requests`) - управление заявками на доставку
- Маршруты (`/routes`) - планирование маршрутов
---
## 4. 🔐 СИСТЕМА РОЛЕЙ И ДОСТУПОВ
### 4.1 Контроль доступа к разделам
**ПРОВЕРКА НА УРОВНЕ КОМПОНЕНТОВ:**
```typescript
{user?.organization?.type === "FULFILLMENT" && (
// Компоненты доступны только фулфилменту
)}
```
**СПЕЦИАЛЬНАЯ ЛОГИКА РОУТИНГА:**
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
// ... другие типы
}
}
```
### 4.2 GraphQL проверки доступа
**В Apollo Client запросах:**
```typescript
const { data } = useQuery(GET_MY_SERVICES, {
skip: user?.organization?.type !== 'FULFILLMENT',
})
```
**В GraphQL резолверах:**
```typescript
if (currentUser.organization.type !== 'FULFILLMENT') {
throw new GraphQLError('Доступно только для фулфилмент центров')
}
```
### 4.3 Контроль доступа к заказам
- **Создатель заказа** - полный доступ к своим заказам
- **Поставщик** - доступ к заказам, где он является поставщиком
- **Фулфилмент-центр** - доступ к заказам, направленным в его центр
- **Логистическая компания** - доступ к заказам для доставки
---
## 5. 🚚 WORKFLOW ПОСТАВОК
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Статусы поставок](#142-статусы-поставок---расширенная-цветовая-система)
### 5.1 Детализированная система статусов
**Статусы SupplyOrder (Заказ поставки):**
1. **PENDING** - Ожидает подтверждения поставщиком
2. **SUPPLIER_APPROVED** - Одобрено поставщиком
3. **CONFIRMED** - Подтвержден (готов к обработке)
4. **LOGISTICS_CONFIRMED** - Подтверждено логистикой
5. **SHIPPED** - Отгружено поставщиком
6. **IN_TRANSIT** - В пути (логистика доставляет)
7. **DELIVERED** - Доставлен на фулфилмент
8. **CANCELLED** - Отменен
### 5.2 Пошаговый процесс поставки
**ЭТАП 1: Создание заказа**
1. Селлер заказывает товар/расходники у поставщика
2. Система создает SupplyOrder со статусом `PENDING`
3. Автоматическое уведомление поставщику
**ЭТАП 2: Обработка поставщиком** 4. Поставщик получает оповещение 5. Поставщик нажимает "Одобрить" 6. Статус меняется на `SUPPLIER_APPROVED`
**ЭТАП 3: Передача в фулфилмент** 7. Поставка отображается в кабинете фулфилмента 8. Фулфилмент выбирает ответственного и логистику 9. Статус меняется на `CONFIRMED`
**ЭТАП 4: Логистическое подтверждение** 10. Логистика подтверждает доставку 11. Статус меняется на `LOGISTICS_CONFIRMED`
**ЭТАП 5: Отгрузка** 12. Поставщик отгружает товар 13. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
**ЭТАП 6: Доставка и приемка** 14. Логистика доставляет на фулфилмент 15. Фулфилмент принимает товар 16. Статус меняется на `DELIVERED`
### 5.3 Система уведомлений
**Обязательные уведомления:**
- Поставщику: о новом заказе
- Фулфилменту: о подтвержденной поставке
- Логистике: о назначении на заявку
- Селлеру: об изменении каждого статуса
---
## 6. 🔄 ПРОЦЕСС СОЗДАНИЯ ПРОДУКТА
> 📌 **СВЯЗАННЫЕ РАЗДЕЛЫ**:
>
> - Типы предметов → См. [раздел 2.2](#22-обязательные-поля-карточки)
> - Склад фулфилмента → См. [раздел 11.2](#112-структура-раздела-склад-фулфилмента)
> - Статистика движения → См. [раздел 7](#7--система-учета-движения-товаров)
### 6.1 Пошаговый алгоритм создания продукта
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Процесс создания продукта](#143-процесс-создания-продукта---визуальный-workflow)
#### **ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ: РЕЦЕПТУРА ЗАДАНА** (селлер)
```
Время: при создании заявки на поставку
Действие: селлер указывает рецептуру продукта
Обязательные компоненты:
✓ Базовый товар (от поставщика)
✓ Услуги фулфилмента (упаковка, маркировка и т.д.)
✓ Расходники (материалы для производства)
Результат: рецептура сохраняется в заявке и передается фулфилменту
```
#### **ШАГ 1: ПОСТУПЛЕНИЕ НА СКЛАД** (автоматически)
```
Время: при смене статуса поставки DELIVERED
Действие: товар переходит в статус "на складе"
Ответственный: система
Результат: +Прибыло в статистике товаров
```
#### **ШАГ 2: ПЛАНИРОВАНИЕ РАБОТЫ** (менеджер фулфилмента)
```
Время: в течение 2 рабочих дней после поступления
Действие: назначение параметров обработки
Ответственный: менеджер фулфилмента
Обязательные поля:
✓ Дедлайн выполнения (не более 5 рабочих дней)
✓ Ответственный исполнитель (из списка сотрудников)
✓ Рецептура (товар + услуги + расходники, указанная селлером в заявке на поставку)
Опциональные поля:
- Место хранения готовых продуктов (зона склада, стеллаж, ячейка)
- Комментарии к работе
Результат: поставка переходит во вкладку "В работе"
```
#### **ШАГ 3: ОБРАБОТКА ТОВАРА** (исполнитель)
```
Время: согласно дедлайну (обычно 1-3 дня)
Действие: физическая обработка товара
Ответственный: назначенный сотрудник
Обязательные действия:
1. Проверка качества товара
2. Фиксация фактического количества
3. Выявление и учет брака
4. Применение рецептуры (услуги + расходники)
5. Создание готового продукта
Точки контроля:
- Соответствие плану/факту
- Качество выполнения услуг
- Расход материалов по норме
УЧЕТ ПЛАН/ФАКТ:
- ПЛАН: Количество товаров из поставки селлера (указано в заказе)
- ФАКТ: Реальное количество после обработки = Брак + Хороший товар
- ДЕТАЛИЗАЦИЯ: Учет ведется по каждому размеру/объему/варианту
- КОРРЕКТИРОВКА: Статистика автоматически обновляется на фактические данные
```
#### **ШАГ 4: КОНТРОЛЬ КАЧЕСТВА** (менеджер/отдел качества)
```
Время: сразу после завершения ШАГ 3
Действие: приемка готовой продукции
Ответственный: менеджер или контролер качества
Критерии приемки:
✓ Соответствие рецептуре селлера
✓ Качество выполненных услуг
✓ Правильность упаковки/маркировки
✓ Полнота комплектации
Результат: продукт готов к отправке или отправлен на доработку
```
#### **ШАГ 5: ЗАВЕРШЕНИЕ** (система + менеджер)
```
Время: после успешного прохождения контроля качества
Действие: финализация процесса
Автоматические действия:
- Создание записи FINISHED_PRODUCT в БД
- Обновление статистики: товар "на складе" → продукт "готов"
- Списание использованных расходников
- Уведомление селлера о готовности
Ручные действия менеджера:
- Подтверждение перехода во вкладку "Выполнено"
- Указание фактических расходов материалов
- Добавление комментариев о выполненной работе
```
### 6.2 Временные рамки и SLA
| Этап | Стандартное время | Максимальное время | Ответственный |
| ----------------- | ----------------- | ------------------ | -------------- |
| Планирование | 1 рабочий день | 2 рабочих дня | Менеджер ФФ |
| Обработка | 2-3 рабочих дня | 5 рабочих дней | Исполнитель |
| Контроль качества | 4 часа | 1 рабочий день | Отдел качества |
| Завершение | 2 часа | 4 часа | Менеджер ФФ |
### 6.3 Управление браком и расхождениями
### 6.4 Детальная рецептура продукта
**РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
- **БАЗОВЫЙ ТОВАР**: Исходный материал (обязательно)
- Артикул товара
- Количество единиц
- Размерная сетка (если применимо)
- **УСЛУГА ФУЛФИЛМЕНТА**: Из каталога услуг фулфилмента
- Тип услуги (глажка, упаковка, маркировка и т.д.)
- Количество применений
- Специальные требования
- **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
- Фирменная упаковка
- Этикетки, бирки
- Дополнительные аксессуары
- **РАСХОДНИК ФУЛФИЛМЕНТА**: Материалы фулфилмента (опционально)
- Стандартная упаковка
- Защитные материалы
- Маркировочные элементы
- **СВЯЗЬ С МАРКЕТПЛЕЙСОМ**: Привязка к карточке (опционально)
- ID карточки на маркетплейсе
- Артикул маркетплейса
- Особые требования МП
**ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
### 6.5 Учет план/факт в процессе работы (без брака)
**ПЛАН**: Количество товара из поставки селлера
**ФАКТ**: Реальное количество после пересчета (работник фулфилмента производит сортировку при пересчете)
**ФИКСАЦИЯ ПОТЕРЬ:**
- **КОГДА**: В процессе работы (вкладка "В работе")
- **ЧТО**: Недостача, повреждения (без создания записей брака)
- **КАК**: Корректировка количества в статистике
**WORKFLOW СОЗДАНИЯ ПРОДУКТА:**
1. Товар поступает на склад фулфилмента (статус "на складе")
2. Товар берется в работу (переход в статус "в обработке")
3. Исполнитель производит пересчет и сортировку
4. Создается готовый продукт (тип FINISHED_PRODUCT)
5. Продукт готов к отправке на маркетплейсы
**ВЛИЯНИЕ НА СТАТИСТИКУ:**
- При принятии поставки: +План в статистику
- При выявлении факта: корректировка на реальные данные
- **ФОРМУЛА**: Факт = Потери + Хороший товар
_Где потери - это недостача/повреждения, выявленные при пересчете и сортировке_
- **ЛОГИКА**: Фактическое количество = сумма всех пересчитанных предметов
- **ПЛАН/ФАКТ**: Корректировка статистики при выявлении расхождений
---
> 🚧 **БУДУЩАЯ ФУНКЦИОНАЛЬНОСТЬ**: Система статусов товаров в фулфилменте будет детализирована позже
## 7. 📊 СИСТЕМА УЧЕТА ДВИЖЕНИЯ ТОВАРОВ
### 7.1 Принципы учета в фулфилменте
**ОСНОВНЫЕ ПРИНЦИПЫ:**
- **ПРИХОД**: Товары поступают через принятые поставки (из состояния "в пути" → "на складе")
- **ОБРАБОТКА**: Товары переходят в статус "в работе" для создания продуктов
- **РАСХОД**: Товары убывают при отгрузке, списании, возврате, превращении в продукты
- **УЧЁТ**: Ведется учет прихода и расхода для каждого типа предметов
- **ВИЗУАЛИЗАЦИЯ**: Движение отображается в дополнительных значениях
### 7.2 Дополнительные и основные значения
**ДОПОЛНИТЕЛЬНЫЕ ЗНАЧЕНИЯ (показатели движения):**
- **ПРИБЫЛО**: Количество предметов, поступивших на склад
- **УБЫЛО**: Количество предметов, списанных со склада
- **ВЛИЯНИЕ**: От этих значений зависят основные значения (общее количество)
**ОСНОВНЫЕ ЗНАЧЕНИЯ (текущие остатки):**
- **ОПРЕДЕЛЕНИЕ**: Итоговое количество предметов на складе
- **РАСЧЁТ**: Основные значения = Предыдущие остатки + Прибыло - Убыло
- **ОТОБРАЖЕНИЕ**: Показываются в каждом модуле статистики
- **РАЗДЕЛЕНИЕ ТОВАРОВ**:
- Товары "на складе" - готовы к обработке
- Товары "в обработке" - находятся в процессе создания продукта
---
## 8. 🏠 ОБЩИЕ ПРАВИЛА КАБИНЕТОВ
### 8.1 Универсальная структура кабинетов
**ВСЕ ТИПЫ КАБИНЕТОВ** включают следующие обязательные разделы:
#### 8.1.1 Страница "Главная"
**СТАТУС**: Реализовано
**ДОСТУП**: Через навигацию в sidebar для всех типов кабинетов
**СОДЕРЖАНИЕ**: Универсальная страница с типо-зависимыми компонентами
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый тип кабинета должен иметь страницу "Главная"
- **НАВИГАЦИЯ**: Доступ через кнопку в sidebar (первая в списке)
- **УНИВЕРСАЛЬНОСТЬ**: Одинаковая структура навигации для всех кабинетов
- **РОУТ**: `/home` с универсальным компонентом HomePageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента: SellerHomePage, FulfillmentHomePage, WholesaleHomePage, LogistHomePage
#### 8.1.2 Раздел "Экономика"
**СТАТУС**: Реализовано в системе
**РАСПОЛОЖЕНИЕ**: Перед настройками в каждом кабинете
**СОДЕРЖАНИЕ**: Пустые разделы-заглушки с пометкой "будет добавлен позже"
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый кабинет имеет раздел "Экономика"
- **РОУТ**: `/economics` с универсальным компонентом EconomicsPageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента экономики: SellerEconomicsPage, FulfillmentEconomicsPage, WholesaleEconomicsPage, LogistEconomicsPage
- **КНОПКА**: "Экономика" в sidebar навигации перед настройками
- **БЕЗОПАСНОСТЬ**: Проверки доступа и безопасности в экономических компонентах
#### 8.1.3 Общие разделы для всех кабинетов
**УНИВЕРСАЛЬНЫЕ РАЗДЕЛЫ** (доступны всем типам):
- 🏠 **Главная** - основная страница кабинета (реализовано)
- 🛒 **Маркет** - просмотр и заказ товаров
- 🤝 **Партнеры** - управление контрагентами
- 💬 **Мессенджер** - внутренняя связь
- 💰 **Экономика** - финансовая аналитика (реализовано)
- ⚙️ **Настройки** - профиль и конфигурация
**СПЕЦИАЛИЗИРОВАННЫЕ РАЗДЕЛЫ** (зависят от типа кабинета):
- Определяются в соответствующих разделах каждого кабинета
### 8.2 Правила sidebar навигации
#### 8.2.1 Структура навигации
**ОБЩИЙ ПРИНЦИП**:
- Условное отображение: `{user?.organization?.type === "TYPE" && (...)}`
- Адаптивность: сворачиваемый sidebar с `getSidebarMargin()`
- Состояния активности: подсветка текущего раздела
**ПОРЯДОК РАЗДЕЛОВ В SIDEBAR**:
1. 🏠 **Главная** (реализовано для всех)
2. **Специализированные разделы** (зависят от типа кабинета)
3. 🛒 **Маркет** (универсальный)
4. 🤝 **Партнеры** (универсальный)
5. 💬 **Мессенджер** (универсальный)
6. 💰 **Экономика** (универсальный, реализовано)
7. ⚙️ **Настройки** (универсальный)
8. **Выход** (универсальный)
#### 8.2.2 Типо-зависимая логика
**АДАПТИВНЫЙ РОУТИНГ**:
```typescript
// Пример: кнопка "Поставки" ведет на разные страницы
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/supplies')
break
case 'LOGIST':
router.push('/logistics-orders')
break
}
}
```
---
## 9. 🏠 КАБИНЕТ СЕЛЛЕРА (ДЕТАЛЬНЫЕ ПРАВИЛА)
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Кабинет селлера](#145-кабинет-селлера)
### 9.1 Структура раздела "Мои поставки"
#### **🏢 ПОСТАВКИ НА ФУЛФИЛМЕНТ**:
- **Товар** - поставка товаров для создания продуктов
- **Карточки** - поставка через WB API с рецептурой (результат: WildberriesSupply)
- **Поставщики** - заказ товаров у поставщиков с рецептурой (результат: SupplyOrder)
- **Расходники селлера** - поставка материалов для товаров селлера
#### **🛒 ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ** _(планируется)_:
- **Wildberries** - прямые поставки на WB
- **Ozon** - прямые поставки на Ozon
### 9.2 UI структура создания поставки расходников селлера
#### **📄 Структура страницы создания поставки:**
**ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):**
**БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_
- **Заголовок**: Минималистичный "🏢 Поставщики" без лишних элементов
- **Поиск**: Компактное поле справа "Поиск поставщиков..." (w-64)
- **Отображение**: Карточки поставщиков из раздела "Партнеры" в адаптивной сетке
- **Выбор**: Клик выделяет карточку поставщика
- **Результат**: Загружаются карточки товаров выбранного поставщика в блок 2
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(горизонтальный скролл - НОВЫЙ)_
- **Отображение**: ТОЛЬКО минималистичные карточки товаров 80×112px
- **Содержание**: ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- **Навигация**: Горизонтальный скролл при множестве товаров
- **Выбор**: Клик добавляет товар в детальный каталог
- **Результат**: Товар добавляется в блок 3 для управления поставкой
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Отображение**: Детальные карточки выбранных товаров
- **Управление**: Количество, параметры, настройки поставки
- **Результат**: Формирование окончательной поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель)_
- **Отображение**: Корзина поставки + настройки
- **Управление**: Фулфилмент-центр, дата, логистика
#### **9.2.1 Детальные правила горизонтального скролла поставщиков**
**СТРУКТУРА И ОТОБРАЖЕНИЕ:**
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px, включает заголовок + контейнер скролла
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки
**РАЗМЕРЫ И АДАПТИВНОСТЬ:**
- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"
**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
**Критическая Flex-архитектура:**
```css
.parent-container {
display: flex;
gap: 16px;
min-height: 0;
}
.left-block {
flex: 1;
min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
display: flex;
flex-direction: column;
}
.suppliers-container {
height: 180px; /* Общая высота блока */
flex-shrink: 0;
min-width: 0; /* Предотвращает растяжение */
}
.right-block {
width: 384px; /* w-96 */
flex-shrink: 0; /* Защита от сжатия */
}
```
**Контейнер скролла:**
```css
.suppliers-block {
display: flex;
overflow-x: auto;
scroll-behavior: smooth;
gap: 12px;
padding: 0 16px 8px 16px; /* px-4 pb-2 */
height: 176px; /* h-44 */
scrollbar-width: thin;
scrollbar-color: #64748b33 transparent;
}
.suppliers-block:hover {
scrollbar-color: #cbd5e0 #64748b22;
}
.supplier-card {
flex-shrink: 0;
width: 216px; /* Десктоп */
height: 92px; /* Фиксированная высота */
padding: 8px; /* p-2 */
transition: all 0.2s ease;
}
```
**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**
**Структура (3 строки в 92px высоты):**
- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)
**Элементы:**
- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)
**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**
- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`
**ДОСТУПНОСТЬ:**
- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных
#### **9.2.2 Правила блока "Карточки товаров" (Блок 2)**
**НАЗНАЧЕНИЕ И ЛОГИКА:**
- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров
**АРХИТЕКТУРА И РАЗМЕРЫ:**
- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере
**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**
- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств
**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**
- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный
**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)
#### **9.2.3 Правила Блока 3 "Детальный каталог товаров"**
**НАЗНАЧЕНИЕ И СТРУКТУРА:**
- **Контент**: Детальные карточки выбранных товаров с полным управлением
- **Верхняя панель**: Выбор даты + Выбор Fulfillment + Поиск
- **Основная область**: Сетка карточек товаров с детальной информацией
#### **9.2.3.1 Структура верхней панели Блока 3**
**МИНИМАЛИСТИЧНАЯ ПАНЕЛЬ УПРАВЛЕНИЯ:**
- **Выбор даты поставки**: DatePicker для планирования поставки
- **Выбор Fulfillment-центра**: Select dropdown со списком доступных фулфилментов
- **Поиск по товарам**: Input с иконкой поиска и placeholder
- **Компоновка**: Горизонтальная строка с равномерным распределением
**ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ:**
```tsx
// Структура компонентов панели
<div className="flex items-center gap-4 p-4 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl mb-4">
<DatePicker placeholder="Дата поставки" />
<Select placeholder="Выберите фулфилмент">
<SelectContent>
{fulfillmentCenters.map((center) => (
<SelectItem value={center.id}>{center.name}</SelectItem>
))}
</SelectContent>
</Select>
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-white/40" />
<Input placeholder="Поиск товаров..." className="pl-10 glass-input" />
</div>
</div>
```
#### **9.2.3.2 Структура основной области карточек**
**СЕТКА ТОВАРОВ:**
- **Адаптивная сетка**: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4`
- **Детальные карточки**: Полная информация + количество + управление
- **Состояния**: Default, Selected, Editing
- **Интерактивность**: Изменение количества, удаление, настройки рецептуры
**ФУНКЦИОНАЛЬНОСТЬ ПАНЕЛИ:**
- **Выбор даты**: Планирование времени поставки (обязательное поле)
- **Выбор фулфилмента**: Определение исполнителя поставки (обязательное поле)
- **Поиск**: Фильтрация товаров в каталоге по названию/артикулу
- **Валидация**: Блокировка создания поставки без заполнения даты и фулфилмента
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **Пустой каталог**: Заглушка "Добавьте товары"
- **Нет фулфилментов**: Сообщение "Настройте партнерство с фулфилмент-центрами"
- **Поиск без результатов**: "По запросу ничего не найдено"
#### **9.2.2.1 Структура контейнера Блока 2**
**ДВУХУРОВНЕВАЯ АРХИТЕКТУРА:**
**УРОВЕНЬ 1 - Внешний контейнер (блок):**
```jsx
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0">
```
- **Назначение**: Визуальное обрамление блока, единство с другими блоками
- **Стилизация**: Стеклянный эффект с размытием и полупрозрачностью
- **Рамка**: Тонкая белая рамка border-white/20 с закруглёнными углами
- **Поведение**: flex-shrink-0 предотвращает сжатие блока
**УРОВЕНЬ 2 - Внутренний контейнер (скролл):**
```jsx
<div className="flex gap-3 overflow-x-auto p-4" style={{ scrollbarWidth: 'thin' }}>
```
- **Назначение**: Горизонтальная прокрутка карточек товаров
- **Раскладка**: Flex с промежутками gap-3 (12px) между карточками
- **Отступы**: padding p-4 (16px) со всех сторон
- **Скролл**: overflow-x-auto с тонкой полосой прокрутки
- **Поведение**: Автоматическое появление скролла при превышении ширины
**ПРАВИЛА КОНТЕЙНЕРОВ:**
- Внешний контейнер НЕ содержит заголовков, иконок, описаний
- Внутренний контейнер содержит ТОЛЬКО карточки товаров
- Высота адаптируется под размер карточек (80×112px + отступы)
- Визуальное единство со всеми блоками формы поставки
**ТЕХНИЧЕСКИЕ ПРАВИЛА:**
- **Условие отображения**: selectedSupplier && products.length > 0
- **Источник данных**: products массив из GraphQL запроса organizationProducts
- **Реактивность**: Автоматическое обновление при смене поставщика
- **Производительность**: React.memo для карточек при большом количестве товаров
- **Доступность**: Клавиатурная навигация (Tab, Enter для выбора)
**UX ПРАВИЛА ВЗАИМОДЕЙСТВИЯ:**
- **Скролл**: Автоматическое появление при превышении ширины контейнера
- **Индикация загрузки**: Скелетоны карточек во время загрузки товаров
- **Пустое состояние**: Скрытие блока при отсутствии поставщика или товаров
- **Фокус**: Первая карточка получает фокус при загрузке товаров
- **Навигация**: Стрелки ←→ для перемещения между карточками
**СОСТОЯНИЯ БЛОКА:**
- **Скрыт**: При отсутствии выбранного поставщика
- **Скрыт**: При отсутствии товаров у поставщика
- **Активен**: При наличии поставщика и товаров
- **Загрузка**: Показ скелетонов карточек во время запроса
**ПРАВИЛА ПРОИЗВОДИТЕЛЬНОСТИ:**
- **Виртуализация**: При количестве товаров > 100
- **Ленивая загрузка изображений**: loading="lazy" для всех изображений
- **Мемоизация**: React.memo для компонентов карточек
- **Дебаунс**: 300мс для поисковых запросов (если будет добавлен поиск)
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные устройства**: Свайп для горизонтальной прокрутки
- **Планшеты**: Сохранение размеров карточек 80×112px
- **Десктоп**: Полная функциональность с клавиатурной навигацией
- **Высокие разрешения**: Сохранение пропорций и читаемости
**ПРАВИЛА БЕЗОПАСНОСТИ И ВАЛИДАЦИИ:**
- **Валидация данных**: Проверка существования product.id перед добавлением
- **Дубликаты**: Предотвращение добавления одного товара дважды в детальный каталог
- **Санитизация**: Безопасное отображение названий товаров (XSS защита)
- **Обработка ошибок**: Graceful degradation при ошибках загрузки изображений
- **Защита от спама**: Дебаунс кликов 200мс для предотвращения множественных добавлений
**ПРАВИЛА ИНТЕГРАЦИИ С ДРУГИМИ БЛОКАМИ:**
- **Блок 1 (Поставщики)**: Слушает изменения selectedSupplier для обновления товаров
- **Блок 3 (Детальный каталог)**: Передаёт выбранные товары через setAllSelectedProducts
- **Блок 4 (Корзина)**: Товары добавляются в корзину из Блока 3, не напрямую из Блока 2
- **Синхронизация состояний**: Реактивное обновление при изменении данных в любом блоке
**ПРАВИЛА АНАЛИТИКИ И МЕТРИК:**
- **Отслеживание кликов**: Логирование добавления товаров в детальный каталог
- **Метрики производительности**: Время загрузки товаров поставщика
- **Пользовательское поведение**: Количество просмотренных товаров на поставщика
- **A/B тестирование**: Готовность к тестированию различных размеров карточек
**ПРАВИЛА ЛОКАЛИЗАЦИИ:**
- **Alt-текст изображений**: На языке интерфейса пользователя
- **Направление скролла**: RTL поддержка для арабского/иврита
- **Размеры карточек**: Неизменны для всех локалей (80×112px)
- **Сообщения об ошибках**: Локализованные уведомления при проблемах загрузки
#### **9.2.1.1 Заголовок и поиск Блока 1**
**МИНИМАЛИСТИЧНЫЙ ДИЗАЙН:**
```jsx
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-white/40 h-4 w-4" />
<Input
placeholder="Поиск поставщиков..."
className="bg-white/5 border-white/10 text-white placeholder:text-white/50 pl-10 h-9"
/>
</div>
</div>
</div>
```
**ПРАВИЛА ЗАГОЛОВКА:**
- **Иконка**: Building2 h-5 w-5 text-blue-400 (без фонового контейнера)
- **Текст**: "Поставщики" (убран избыточный "товаров")
- **Размер**: text-lg font-semibold (увеличен для лучшей читаемости)
- **БЕЗ бэджа**: Убран избыточный бэдж "Создание поставки"
- **Выравнивание**: flex items-center gap-2 (компактное)
**ПРАВИЛА ПОИСКА:**
- **Позиция**: Справа от заголовка (justify-between)
- **Ширина**: w-64 (256px) фиксированная ширина
- **Плейсхолдер**: "Поиск поставщиков..." (конкретное описание)
- **Иконка**: Search h-4 w-4 слева в поле
- **Стили**: Стандартные glass-эффекты, focus:border-white/20
**ПРАВИЛА КНОПКИ "НАЙТИ В МАРКЕТЕ":**
- **Условие**: Показывается только при allCounterparties.length === 0
- **Позиция**: Отдельный блок под заголовком (mt-4)
- **НЕ интегрирована**: В поле поиска (отдельно)
- **Стили**: glass-secondary outline button размера sm
#### **9.2.1.2 Структура карточки поставщика в Блоке 1**
**МИНИМАЛИСТИЧНАЯ КАРТОЧКА ПОСТАВЩИКА:**
**СТРУКТУРА ИНФОРМАЦИИ:**
```jsx
<div className="flex items-start gap-2">
<OrganizationAvatar organization={supplier} size="sm" />
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm truncate">{supplier.name || supplier.fullName}</h4>
<div className="flex items-center gap-2 mt-1">
<p className="text-white/60 text-xs font-mono">ИНН: {supplier.inn}</p>
{supplier.market && <Badge className="market-badge">{getMarketLabel(supplier.market)}</Badge>}
</div>
</div>
</div>
```
**ПРАВИЛА СОДЕРЖАНИЯ КАРТОЧКИ:**
**✅ ОСТАВИТЬ:**
- **Аватар организации**: OrganizationAvatar size="sm" слева
- **Название поставщика**: supplier.name || supplier.fullName (приоритет name)
- **ИНН**: font-mono, text-white/60, с префиксом "ИНН: "
**🔸 ДОБАВИТЬ:**
- **Принадлежность к рынку**: Badge с названием рынка из supplier.market
- **Рынки**: "Садовод", "ТЯК Москва" и другие из Organization.market поля
**❌ УБРАТЬ:**
- **Рейтинг**: Звездочка и цифра rating (избыточно)
- **Тип бэдж**: "Поставщик" badge (и так понятно из контекста)
- **Адрес**: supplier.address (занимает место, не критично)
**СТИЛИ РЫНОЧНЫХ БЭДЖЕЙ:**
- **Садовод**: bg-green-500/20 text-green-300 border-green-500/30
- **ТЯК Москва**: bg-blue-500/20 text-blue-300 border-blue-500/30
- **По умолчанию**: bg-gray-500/20 text-gray-300 border-gray-500/30
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные**: Сохранение структуры, truncate для длинных названий
- **Планшеты/десктоп**: Полное отображение в сетке
- **Малые экраны**: line-clamp-1 для названия организации
**СОСТОЯНИЯ КАРТОЧКИ:**
- **Default**: bg-white/5 border-white/10
- **Hover**: hover:border-white/20 hover:bg-white/10
- **Selected**: bg-white/15 border-white/40 shadow-lg
- **Disabled**: opacity-50 cursor-not-allowed (при недоступности)
**ПРАВИЛА ИНТЕГРАЦИИ С РЫНКАМИ:**
**ИСТОЧНИК ДАННЫХ:**
- **Поле БД**: Organization.market (String?) - поле принадлежности к рынку
- **Настройка**: Указывается в настройках кабинета поставщика
- **Опциональность**: Поле может быть пустым (рынок не указан)
**ФУНКЦИЯ getMarketLabel():**
```jsx
const getMarketLabel = (market?: string) => {
const marketLabels = {
'sadovod': 'Садовод',
'tyak-moscow': 'ТЯК Москва',
'opt-market': 'ОПТ Маркет',
}
return marketLabels[market as keyof typeof marketLabels] || market
}
```
**СТИЛИ ДЛЯ РЫНКОВ:**
```jsx
const getMarketBadgeStyle = (market?: string) => {
const styles = {
'sadovod': 'bg-green-500/20 text-green-300 border-green-500/30',
'tyak-moscow': 'bg-blue-500/20 text-blue-300 border-blue-500/30',
'opt-market': 'bg-purple-500/20 text-purple-300 border-purple-500/30',
}
return styles[market as keyof typeof styles] || 'bg-gray-500/20 text-gray-300 border-gray-500/30'
}
```
**ПРАВИЛА ОТОБРАЖЕНИЯ:**
- **Условие**: Показывать badge только если supplier.market существует
- **Размер**: text-xs для соответствия ИНН
- **Позиция**: Справа от ИНН в той же строке
- **Приоритет**: Рынок важнее типа организации для селлера
### 9.2.2.2 ПРАВИЛО ПЕРСИСТЕНТНОСТИ ВЫБРАННЫХ ТОВАРОВ
**🎯 ОСНОВНОЙ ПРИНЦИП:**
Выбранные товары в детальном каталоге (блок 3) сохраняются при смене поставщика и могут быть удалены только явным действием пользователя.
**🔄 WORKFLOW СЦЕНАРИИ:**
**СЦЕНАРИЙ 1: Добавление товаров от разных поставщиков**
1. Пользователь выбирает Поставщика А
2. Добавляет Товар 1 и Товар 2 в детальный каталог
3. Переключается на Поставщика Б
4. Товар 1 и Товар 2 остаются в блоке 3
5. Добавляет Товар 3 от Поставщика Б
6. В блоке 3: Товар 1, Товар 2 (от А) + Товар 3 (от Б)
**СЦЕНАРИЙ 2: Визуальная индикация в блоке 2**
- При переключении на поставщика, товары которого уже есть в блоке 3, показываются как "выбранные"
- Товары от других поставщиков в блоке 2 не отображаются
**🛠️ ТЕХНИЧЕСКИЕ ПРАВИЛА:**
**Состояние selectedProductsForDetailView:**
- Глобальное состояние всех выбранных товаров
- НЕ зависит от текущего поставщика
- НЕ очищается при смене поставщика
- Очищается только явными действиями пользователя
**Единственные способы удаления:**
1. Кнопка "Удалить из каталога" в карточке товара (блок 3)
2. Кнопка "Очистить каталог" в заголовке блока 3
3. НЕ при смене поставщика
**🎨 UX ПРАВИЛА:**
- Счетчик товаров: "Детальный каталог (X товаров от Y поставщиков)"
- Визуальная индикация выбранных товаров в блоке 2
- Информация о поставщике для каждого товара в блоке 3
**СОСТОЯНИЯ БЛОКА:**
- **Не выбран поставщик**: Заглушка "Выберите поставщика для просмотра товаров"
- **Поставщик выбран, нет товаров**: "У поставщика нет товаров"
- **Поставщик выбран, есть товары**: Карточки товаров с горизонтальным скроллом
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Горизонтальная прокрутка мышью, клавишами ←→
- **Выбор**: Клик → добавление в Блок 3 с анимацией
- **Состояния карточек**: Default, Selected, Active (при добавлении)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-5 карточек**: Скролл неактивен, выравнивание по левому краю
- **6+ карточек**: Полноценный горизонтальный скролл
- **Поиск**: Фильтрация карточек в реальном времени
- **Загрузка**: Скелетон-анимация при смене поставщика
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Содержание**: Детальный каталог товаров для управления поставкой
- **Источник**: Товары, добавленные из Блока 2 "Карточки товаров"
- **Сортировка**: По цене, названию, категории
- **Фильтры**: По категории, ценовому диапазону
- **Карточка расходника**:
- Фото, название, цена, остаток, категория
- Количество в комплекте (если есть комплектность)
- Поле ввода количества (единицы или комплекты)
- Кнопки +/- для изменения количества
- **Действие**: Клик добавляет расходник в корзину
**БЛОК 3: КОРЗИНА** _(правая часть)_
- **Содержание корзины**:
- Количество видов расходников
- По каждому расходнику: название, количество, цена за единицу, сумма
- Общая сумма всех расходников
- **Управление**: Изменение количества, удаление позиций
- **Валидация**: Проверка остатков у поставщика
- **Настройки поставки**:
- Выбор фулфилмент-центра (dropdown из партнеров)
- Дата поставки (по умолчанию - дата создания, нельзя выбрать прошедшую)
- **Кнопка**: "Создать поставку"
### 9.3 Многоуровневые таблицы для отображения поставок
#### **📊 Структура многоуровневой таблицы:**
**ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- Порядковый номер поставки (от большего к меньшему)
- Количество видов расходников селлера
- Стоимость всей поставки
- Количество категорий
- Статус поставки
- Кнопка раскрытия/сворачивания
**ВТОРОЙ УРОВЕНЬ** _(раскрывается по клику)_:
- Название расходника селлера
- Количество
- Цена за единицу
- Общая стоимость позиции
- Категория
- Поставщик
- **Режим**: Только просмотр (редактирование недоступно после создания)
**ПРАВИЛА ОТОБРАЖЕНИЯ**:
- По умолчанию таблица свернута, показан только первый уровень
- Клик по строке или кнопке раскрывает второй уровень
- Анимация раскрытия плавная (300ms)
- Визуальная индикация раскрытого состояния (поворот стрелки, изменение фона)
### 9.4 Правила кнопки "Создать поставку" в разделе "Мои поставки"
#### **9.4.1 Общие принципы**
- **КОНТЕКСТНОСТЬ**: Кнопка создания появляется только в активном табе
- **РАСПОЛОЖЕНИЕ**: Правая часть строки таба, на том же уровне что и название
- **СТИЛИСТИКА**: В том же стиле что и сами табы (соответствует уровню иерархии)
- **ФУНКЦИОНАЛЬНОСТЬ**: Кнопка ведет на страницу создания поставки соответствующего типа
#### **9.4.2 Размещение кнопок по табам**
**УРОВЕНЬ 2 (Подтабы фулфилмента):**
- **📦 Товар → Карточки**: Кнопка "Создать поставку" → `/supplies/create-cards`
- **📦 Товар → Поставщики**: Кнопка "Создать поставку" → `/supplies/create-suppliers`
- **🔧 Расходники селлера**: Кнопка "Создать поставку" → `/supplies/create-consumables`
**УРОВЕНЬ 2 (Подтабы маркетплейсов):**
- **🟣 Wildberries**: Кнопка "Создать поставку" → `/supplies/create-wildberries`
- **🔵 Ozon**: Кнопка "Создать поставку" → `/supplies/create-ozon`
#### **9.4.3 Стили кнопок**
**ДЛЯ УРОВНЯ 2 (h-9):**
```css
/* Размер и отступы */
h-9 px-3 py-1 ml-auto
/* Фон и границы */
bg-white/8 border border-white/20 hover:bg-white/12
/* Текст и иконки */
text-xs font-medium text-white/80 hover:text-white
/* Скругления */
rounded-lg
/* Переходы */
transition-all duration-150
```
**ДЛЯ УРОВНЯ 3 (h-8):**
```css
/* Размер и отступы */
h-8 px-2 py-1 ml-auto
/* Фон и границы */
bg-white/5 border border-white/15 hover:bg-white/8
/* Текст и иконки */
text-xs font-normal text-white/60 hover:text-white/80
/* Скругления */
rounded-md
/* Переходы */
transition-all duration-150
```
#### **9.2.4 Поведение кнопок**
- **ВИДИМОСТЬ**: Кнопка показывается только в активном табе
- **ИКОНКА**: `Plus` размером `h-3 w-3` слева от текста
- **ТЕКСТ**: "Создать" на мобильных, "Создать поставку" на десктопах
- **АДАПТИВНОСТЬ**: Скрытие текста на маленьких экранах (`hidden sm:inline`)
#### **9.2.5 Удаление старой кнопки**
- **УБРАТЬ**: Текущий dropdown "Создать поставку" из верхней части
- **ПРИЧИНА**: Заменяется контекстными кнопками в табах
- **СОХРАНИТЬ**: Стили и логику навигации, но адаптировать под новые роуты
#### **9.2.6 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ**
**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.
##### **9.2.6.1 Размеры и позиционирование**
```tsx
<div className="w-72 flex-shrink-0">
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```
**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:
- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`
##### **9.2.6.2 Автодобавление товаров**
**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.
```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)
if (newQuantity > 0) {
// Автоматически добавляем товар в корзину
updateProductQuantity(product.id, newQuantity)
} else {
// Удаляем товар из корзины при количестве 0
removeFromCart(product.id)
}
}
```
**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`
##### **9.2.6.3 Структура корзины**
**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:
1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом
**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине
##### **9.2.6.4 Единая функция расчета стоимости**
**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:
```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
const product = products.find((p) => p.id === productId)
if (!product) return 0
// Базовая цена товара
let total = (product.pricePerUnit || 0) * quantity
// Добавляем услуги
if (product.services && product.services.length > 0) {
const servicesTotal = product.services.reduce((sum, service) => {
return sum + (service.pricePerUnit || 0) * quantity
}, 0)
total += servicesTotal
}
// Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
if (product.ffConsumables && product.ffConsumables.length > 0) {
const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
}, 0)
total += ffConsumablesTotal
}
// Добавляем расходники продавца
if (product.sellerConsumables && product.sellerConsumables.length > 0) {
const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
return sum + (consumable.pricePerUnit || 0) * quantity
}, 0)
total += sellerConsumablesTotal
}
return total
}
```
##### **9.2.6.5 Синхронизация данных между блоками**
**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:
1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`
**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:
```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```
##### **9.2.6.6 Критические требования**
🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:
- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов
🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:
- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества
🚨 **UX КОНСИСТЕНТНОСТЬ**:
- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных
### 9.3 Структура страницы "Мои поставки" - Трёхблочная архитектура
#### **9.3.1 Обязательная структура страницы**
**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков
```
┌─────────────────────────────────────────┐
│ 1. БЛОК ТАБОВ (навигация) │
│ - Фиксированная высота │
│ - Glass-эффект │
│ - Иерархическая структура │
├─────────────────────────────────────────┤
│ 2. БЛОК СТАТИСТИКИ (метрики) │
│ - Контекстные данные │
│ - 4 карточки в ряд (desktop) │
│ - Динамическое обновление │
├─────────────────────────────────────────┤
│ 3. ОСНОВНОЙ БЛОК (контент) │
│ - Сохраняет весь функционал │
│ - Таблицы, фильтры, действия │
│ - Высота до низа sidebar │
└─────────────────────────────────────────┘
```
#### **9.3.2 Блок статистики - контекстные метрики**
**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов
**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**
- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути
**Для пути "Фулфилмент → Расходники селлера":**
- Всего поставок
- Активных поставок
- Видов расходников
- Критические остатки
**Для путей "Маркетплейсы → Wildberries/Ozon":**
- Поставок на маркетплейс
- Товаров отправлено
- Возвраты за неделю
- Эффективность поставок
#### **9.3.3 Высота основного блока**
**ФОРМУЛА РАСЧЕТА**:
```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```
**ПРАВИЛО ВЫРАВНИВАНИЯ**:
- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`
#### **9.3.4 Сохранение функционала**
**КРИТИЧЕСКИ ВАЖНО**: При добавлении блока статистики весь существующий функционал сохраняется:
- Таблицы с данными поставок
- Фильтры и сортировка
- Кнопки действий
- Детализация при клике
- Пагинация
- Поиск
**ЗАПРЕЩЕНО**:
- Удалять существующие компоненты
- Изменять логику работы таблиц
- Нарушать существующие API вызовы
### 9.4 Табы "Карточки" и "Поставщики" - объединённая логика
#### **9.4.1 Принцип единого типа предмета**
**КЛЮЧЕВОЕ ПРАВИЛО**: Табы "Карточки" и "Поставщики" - это два способа создания поставок одного типа предмета (ТОВАР)
**СПОСОБЫ СОЗДАНИЯ**:
- **Карточки** - импорт товаров через WB API с автоматическим созданием поставки
- **Поставщики** - прямой заказ товаров у поставщика с указанием рецептуры
**РЕЗУЛЬТАТ**: Оба способа создают `SupplyOrder` с товарами типа `PRODUCT`
#### **9.4.2 Общая статистика**
**ПРАВИЛО**: Блок статистики показывает ОДИНАКОВЫЕ данные для обоих табов
**МЕТРИКИ ДЛЯ ТАБОВ "КАРТОЧКИ" И "ПОСТАВЩИКИ"**:
- Всего поставок товаров (из всех источников)
- Активных поставок товаров (в работе)
- Сумма активных поставок товаров
- Товаров в пути (все способы доставки)
**ЗАПРЕЩЕНО**: Разделять статистику по способу создания
#### **9.4.3 Общий основной блок**
**СОДЕРЖИМОЕ**: Единая таблица всех поставок товаров
**ИСТОЧНИКИ ДАННЫХ**:
- Поставки, созданные через импорт карточек WB
- Поставки, созданные через заказ у поставщиков
- Все промежуточные и завершённые поставки
**РАЗЛИЧИЯ ТАБОВ**:
- Только кнопки создания ведут на разные страницы
- Таб "Карточки": `/supplies/create-cards`
- Таб "Поставщики": `/supplies/create-suppliers`
### 9.5 Создание поставки расходников селлера
#### **Структура страницы**:
**БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_:
- Карточки поставщиков из раздела "Партнеры"
- Горизонтальный скролл при превышении ширины
- Выбор только одного поставщика одновременно
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(адаптивная высота - НОВЫЙ БЛОК)_:
- ТОЛЬКО минималистичные карточки товаров 80×112px
- ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- Горизонтальный скролл при множестве товаров
- Клик добавляет товар в блок 3
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(flex-1, детальный каталог)_:
- Детальные карточки выбранных товаров
- Управление количеством и параметрами поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель, 384px)_:
- Корзина поставки с выбранными товарами
- Настройки поставки (фулфилмент-центр, дата, логистика)
- Сортировка: цена, название, категория
- Фильтры: категория, ценовой диапазон
- Карточка с полем ввода количества и кнопками +/-
**БЛОК 3: КОРЗИНА** _(правая часть)_:
- **РАСПОЛОЖЕНИЕ**: Правая часть экрана
- **СОДЕРЖАНИЕ**:
- Счетчик видов расходников
- Детализация по каждому расходнику (название, количество, цена, сумма)
- Общая сумма всех расходников
- **УПРАВЛЕНИЕ**:
- Изменение количества (с валидацией остатков)
- Удаление позиций
- **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ**:
- Выбор фулфилмент-центра (из партнеров)
- Дата поставки (не прошедшая, по умолчанию - текущая)
### 9.6 Многоуровневая таблица поставок
#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
- Порядковый номер поставки
- Количество видов расходников
- Стоимость всей поставки
- Количество категорий
- Статус поставки
#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:
- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
- Название расходника
- Количество
- Цена
- Категория
- Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено
---
## 10. 🏪 КАБИНЕТ ПОСТАВЩИКА
> 📖 **Технические детали кабинета**: См. [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md) для компонентов, GraphQL и UI/UX
### 10.1 Разделение понятий: РЫНОК vs МАРКЕТ
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ ПОНЯТИЙ:**
### **РЫНОК** 🏪 - физическое торговое место
- **Назначение**: Географическая принадлежность поставщиков
- **Примеры**: Садовод, ТЯК Москва
- **Структура**: Название + адрес
- **Связь**: Поставщик принадлежит рынку
### **МАРКЕТ** 🛒 - раздел системы для торговли
- **Назначение**: Глобальный каталог товаров в системе
- **Роут**: `/market` - просмотр и заказ товаров
- **Содержание**: Все доступные товары от всех поставщиков
- **Связь**: НЕ связан с физическими рынками
**🏢 АРХИТЕКТУРА ПРИНАДЛЕЖНОСТИ:**
```
РЫНОК (физическое место)
└── Поставщик (Organization.market)
└── Товары/Расходники (наследуют рынок от поставщика)
└── Отображаются в МАРКЕТЕ (/market)
```
**🎯 ПРИНЦИПЫ ИЕРАРХИИ:**
1. **РЫНОК → ПОСТАВЩИК**: Поставщик работает на конкретном рынке
2. **ПОСТАВЩИК → ТОВАРЫ**: Товары принадлежат поставщику с его рынка
3. **ТОВАРЫ → МАРКЕТ**: Все товары показываются в глобальном маркете (/market)
4. **НАСЛЕДОВАНИЕ**: Товары получают рынок от организации поставщика
**🏪 ФИЗИЧЕСКИЕ РЫНКИ В СИСТЕМЕ:**
- **"Садовод"** (`sadovod`) - Москва, 14-й км МКАД
- **Цветовая схема**: `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (`tyak-moscow`) - Москва, Алтуфьевское шоссе, 27
- **Цветовая схема**: `bg-blue-500/20 text-blue-300 border-blue-500/30`
**🛒 МАРКЕТ В СИСТЕМЕ:**
- **Роут**: `/market` - глобальный каталог товаров
- **Функции**: Просмотр, поиск, фильтрация, заказ товаров
- **Источник**: Товары от всех поставщиков всех рынков
- **Отображение рынка**: В карточках поставщиков и товаров
**🔧 ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
- **Поле рынка**: `Organization.market` (String?) - принадлежность поставщика к рынку
- **Настройка рынка**: В настройках организации поставщика
- **Отображение в маркете**: Товары показывают рынок через `product.organization.market`
- **Фильтрация**: В маркете по рынку поставщика
### 10.2 Основные возможности
**СОЗДАНИЕ КАРТОЧЕК**:
- **ТОВАР** - базовые товары поставщика
- **РАСХОДНИКИ** - материалы и вспомогательные товары
### 10.3 Обязательные поля карточки
**Базовые параметры**:
- Фото (система загрузки и управления изображениями)
- Название
- Автоматическая генерация артикула СФ
- Описание
- Количество предметов в единицах
- Количество комплектов (если применимо)
- Категория (28 предустановленных + специализированные для расходников)
- Бренд, Цвет, Размер/объем, Вес, Габариты, Материал
- Цена за единицу и за комплект
- Заказано, В пути, Остаток, Продано
### 10.4 Отображение информации в карточках
**Каждая карточка содержит**:
- Основное изображение
- Название и артикул СФ
- Цена за единицу/комплект
- Категория и статус активности
- Данные о движении: остаток, заказано, в пути, продано
- Индикаторы низких остатков
### 10.5 Статистика поставщика
**Блок статистики включает**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары
- Классифицируются при заказе в зависимости от заказчика
- Общая статистика по всем расходникам
---
## 11. 🏭 КАБИНЕТ ФУЛФИЛМЕНТА
> 📖 **Технические детали кабинета**: См. [fulfillment-cabinet-rules.md](./fulfillment-cabinet-rules.md) для компонентов, GraphQL, UI/UX и всех технических деталей реализации
### 11.1 Основные функции фулфилмента
**РОЛЬ В СИСТЕМЕ**: Обработка товаров и предоставление услуг
**ОСНОВНЫЕ ФУНКЦИИ**:
- **ПРИЕМКА ТОВАРОВ**: Получение и обработка поставок от поставщиков
- **СОЗДАНИЕ ПРОДУКТОВ**: Превращение товаров в готовые продукты по рецептурам
- **ПРЕДОСТАВЛЕНИЕ УСЛУГ**: Услуги обработки для селлеров
- **УПРАВЛЕНИЕ РАСХОДНИКАМИ**: Установка цен и контроль наличия
- **ЛОГИСТИЧЕСКИЕ УСЛУГИ**: Маршруты доставки и тарификация
### 11.2 Workflow фулфилмента
#### **ЭТАП 1: Приемка товаров**
1. Фулфилмент получает поставки от поставщиков
2. Товары размещаются на складе по модулям
3. Ведется учет поступлений и остатков
#### **ЭТАП 2: Обработка товаров**
4. Товары обрабатываются согласно рецептурам селлеров
5. Применяются услуги фулфилмента
6. Создаются готовые продукты
#### **ЭТАП 3: Управление услугами**
7. Фулфилмент предоставляет каталог услуг для рецептур
8. Устанавливает цены на расходники
9. Управляет логистическими маршрутами
### 11.3 Основные разделы кабинета
**СТРУКТУРА ДОСТУПА**:
- **Склад** - управление товарами по модулям
- **Поставки** - обработка входящих товаров
- **Услуги** - каталог услуг и расходники
- **Сотрудники** - управление персоналом
- **Статистика** - аналитика деятельности
### 11.4 Правила фулфилмента
**ОБЯЗАТЕЛЬНО**:
- Установка цен на расходники перед доступностью селлерам
- Контроль качества товаров при приемке
- Своевременная обработка возвратов
- Ведение учета движения товаров
- Управление персоналом и рабочим временем
**ЗАПРЕЩЕНО**:
- Отгружать товары без подтверждения наличия
- Создавать расходники минуя систему поставок
- Изменять цены закупки после поступления товара
- Показывать в рецептурах неактивные расходники
---
## 12. 🚚 КАБИНЕТ ЛОГИСТИКИ
### 12.1 Основные функции логистики
**РОЛЬ В СИСТЕМЕ**: Управление доставками и транспортировкой
**ОСНОВНЫЕ ФУНКЦИИ**:
- **ПОДТВЕРЖДЕНИЕ ДОСТАВКИ**: Подтверждение возможности доставки поставок
- **ТРАНСПОРТИРОВКА**: Организация и выполнение доставки товаров
- **КОНТРОЛЬ МАРШРУТОВ**: Управление логистическими маршрутами
- **ОТСЛЕЖИВАНИЕ**: Мониторинг грузов в пути
### 12.2 Workflow для логистики
#### **ЭТАП 1: Получение заявки**
1. Логистика получает уведомление о новой поставке
2. Заявка появляется в разделе "Заявки" кабинета логистики
3. Логист изучает детали поставки (объем, вес, маршрут)
#### **ЭТАП 2: Подтверждение доставки**
4. Логист нажимает кнопку "Одобрить"
5. Статус поставки меняется на `LOGISTICS_CONFIRMED`
6. Уведомления отправляются всем участникам
#### **ЭТАП 3: Забор товара**
7. Логист приезжает к поставщику за товаром
8. Поставщик отгружает товар логисту
9. Поставщик отмечает "Отправлено"
10. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
#### **ЭТАП 4: Доставка**
11. Логистика доставляет товар на фулфилмент-центр
12. В кабинете логистики нажимают "Доставлено"
13. Фулфилмент принимает товар и отмечает "Принято"
### 12.3 Система тарификации
**ПАРАМЕТРЫ ТАРИФИКАЦИИ**:
- **Тариф до 1м³** - базовая стоимость для малых грузов
- **Тариф свыше 1м³** - стоимость для крупных грузов
- **Маршруты доставки** - от точки отправления до точки назначения
- **Описание услуг** - дополнительные условия доставки
**РАСЧЕТ СТОИМОСТИ**:
- Автоматический расчет стоимости доставки по объему груза
- Отображение примерной стоимости при создании заказа
- Учет специфики маршрута и условий доставки
### 12.4 Управление заявками
**РАЗДЕЛЫ КАБИНЕТА ЛОГИСТИКИ**:
- **НОВЫЕ ЗАЯВКИ** - поступившие заявки на доставку
- **В РАБОТЕ** - принятые к исполнению заявки
- **ВЫПОЛНЕННЫЕ** - завершенные доставки
- **ОТКЛОНЕННЫЕ** - заявки, которые не могут быть выполнены
**ИНФОРМАЦИЯ О ЗАЯВКЕ**:
- Детали груза (объем, вес, габариты)
- Маршрут доставки (откуда - куда)
- Срочность доставки
- Особые требования к транспортировке
- Контактная информация участников
### 12.5 Правила логистики
**ОБЯЗАТЕЛЬНО**:
- Своевременное подтверждение заявок
- Соблюдение сроков доставки
- Бережная транспортировка товаров
- Уведомление о статусе доставки
**ЗАПРЕЩЕНО**:
- Принятие заявок без подтверждения возможности выполнения
- Нарушение сроков доставки без уведомления
- Повреждение товаров при транспортировке
---
## 13. 🤝 СИСТЕМА ПАРТНЕРСТВА И КОНТРАГЕНТОВ
### 13.1 Основы системы партнерства
**ПРИНЦИП РАБОТЫ**:
- Все типы кабинетов могут создавать партнерские отношения
- Партнерство реализовано через таблицы `Counterparty` и `CounterpartyRequest`
- Двустороннее партнерство: каждая организация видит другую в разделе "Партнеры"
**ТИПЫ ОРГАНИЗАЦИЙ-ПАРТНЕРОВ**:
- `WHOLESALE` - Поставщики товаров и расходников
- `FULFILLMENT` - Фулфилмент-центры
- `LOGIST` - Логистические компании
- `SELLER` - Селлеры (торговые организации)
### 13.2 Способы создания партнерства
#### **СПОСОБ 1: Через заказ в маркете (автоматическое партнерство)**
**WORKFLOW**:
1. Поставщик создает товар → товар попадает в глобальный маркет
2. Селлер/Фулфилмент находит товар в маркете
3. Создает заказ (`SupplyOrder`) → статус `PENDING`
4. Поставщик получает уведомление в разделе "Заявки"
5. Поставщик одобряет заявку → статус `SUPPLIER_APPROVED`
6. **Автоматически создается двустороннее партнерство**:
- Запись в `Counterparty` для заказчика (`organizationId` → `counterpartyId`)
- Обратная запись в `Counterparty` для поставщика
7. Обе организации видят друг друга в разделе "Партнеры"
#### **СПОСОБ 2: Через раздел "Партнеры" (заявочная система)**
**WORKFLOW**:
1. Любая организация идет в раздел "Партнеры"
2. Использует поиск для нахождения нужной организации
3. Отправляет заявку на партнерство → создается `CounterpartyRequest`:
- `senderId` - отправитель заявки
- `receiverId` - получатель заявки
- `status: PENDING`
- `message` - опциональное сообщение
4. Получатель видит заявку в разделе "Партнеры" → "Входящие заявки"
5. Получатель принимает заявку → статус меняется на `ACCEPTED`
6. **Автоматически создается двустороннее партнерство** (аналогично способу 1)
**СТАТУСЫ ЗАЯВОК**:
- `PENDING` - Ожидает рассмотрения
- `ACCEPTED` - Принята (партнерство создано)
- `REJECTED` - Отклонена
- `CANCELLED` - Отменена отправителем
### 13.3 Использование партнерства в системе
#### **В форме создания поставки товаров через поставщиков**
**ПРАВИЛО ОТОБРАЖЕНИЯ ПОСТАВЩИКОВ**:
- Показываются только партнеры с типом `WHOLESALE`
- Источник: таблица `Counterparty` where `counterparty.type === "WHOLESALE"`
- Фильтрация по `organizationId` текущего пользователя
**ЛОГИКА РАБОТЫ**:
1. Пользователь выбирает поставщика из dropdown партнеров-поставщиков
2. Загружается каталог товаров поставщика из `Product` таблицы
3. Товары фильтруются по `organizationId = поставщик.id`
4. Пользователь может добавлять товары в корзину и создавать заказ
#### **В других разделах системы**
**ВЫБОР ФУЛФИЛМЕНТ-ЦЕНТРА**:
- Партнеры с типом `FULFILLMENT`
- Используется при создании поставок расходников
**ВЫБОР ЛОГИСТИКИ**:
- Партнеры с типом `LOGIST`
- Используется при планировании доставок
**МЕССЕНДЖЕР**:
- Общение доступно только между партнерами
- Список чатов формируется из таблицы `Counterparty`
### 13.4 Технические правила
**СОЗДАНИЕ ЗАПИСЕЙ В COUNTERPARTY**:
```sql
-- При создании партнерства создаются ДВЕ записи
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org1_id, org2_id);
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org2_id, org1_id);
```
**ПРОВЕРКА ПАРТНЕРСТВА**:
```typescript
const isPartner = await prisma.counterparty.findFirst({
where: {
organizationId: currentOrgId,
counterpartyId: targetOrgId,
},
})
```
**ПОЛУЧЕНИЕ ПАРТНЕРОВ ПО ТИПУ**:
```typescript
const wholesalePartners = await prisma.counterparty.findMany({
where: {
organizationId: currentOrgId,
counterparty: {
type: 'WHOLESALE',
},
},
include: {
counterparty: true,
},
})
```
### 13.5 Решение распространенных проблем
#### **ПРОБЛЕМА: GraphQL запрос не возвращает данные партнеров**
**Симптомы**:
- В консоли браузера: `All counterparties: 0`, `All counterparties data: []`
- GraphQL запрос отправляется успешно, но возвращает пустой массив
- В базе данных партнеры существуют
**Возможные причины и решения**:
1. **НЕПРАВИЛЬНОЕ ИМЯ ПОЛЯ В КОДЕ** (наиболее частая ошибка):
```typescript
// ❌ НЕПРАВИЛЬНО
const allCounterparties = counterpartiesData?.getMyCounterparties || []
// ✅ ПРАВИЛЬНО
const allCounterparties = counterpartiesData?.myCounterparties || []
```
**Объяснение**: В GraphQL схеме поле называется `myCounterparties`, а не `getMyCounterparties`
2. **НЕСООТВЕТСТВИЕ ID ПОЛЬЗОВАТЕЛЯ**:
- Проверить что пользователь авторизован под правильным аккаунтом
- Убедиться что `context.user.id` соответствует ожидаемому пользователю
3. **ПРОБЛЕМЫ С КЕШИРОВАНИЕМ APOLLO CLIENT**:
```typescript
const { data, loading, error } = useQuery(GET_MY_COUNTERPARTIES, {
fetchPolicy: 'network-only', // Обходим кеш
errorPolicy: 'all',
})
```
4. **ОТСУТСТВИЕ ЛОГИРОВАНИЯ В РЕЗОЛВЕРЕ**:
- Добавить console.log в GraphQL резолвер для отладки
- Проверить что резолвер вызывается
**Чек-лист для диагностики**:
- [ ] Проверить правильность имени поля в коде (`myCounterparties`)
- [ ] Убедиться что пользователь авторизован
- [ ] Проверить логи сервера на вызов резолвера
- [ ] Добавить отладочное логирование в браузере
- [ ] Проверить данные в базе через Prisma Studio
- [ ] Использовать `fetchPolicy: 'network-only'` для обхода кеша
---
## 14. 🌐 ИНТЕГРАЦИИ С СИСТЕМОЙ
### 14.1 Глобальная интеграция
- **МАРКЕТ**: Товары поставщиков отображаются в глобальном маркете
- **СИНХРОНИЗАЦИЯ**: Данные склада синхронизируются с модулем аналитики
- **УВЕДОМЛЕНИЯ**: Единая система через встроенный мессенджер
### 14.2 Интеграция с маркетплейсами
- **WILDBERRIES**: Обязательная проверка активности API ключа
- **СИНХРОНИЗАЦИЯ**: Регулярное обновление данных из внешних источников
- **ЛОКАЛЬНЫЕ КОПИИ**: Сохранение данных для офлайн работы
### 14.3 Интеграция с модулем "Услуги"
**РАСХОДНИКИ ФУЛФИЛМЕНТА В УСЛУГАХ**:
- Расходники фулфилмента - собственность фулфилмента (куплены у поставщиков)
- Фулфилмент создает заявки-поставки для покупки расходников у поставщиков
- Селлеры могут использовать расходники фулфилмента в разделе "Услуги / Расходники"
- Для создания продукта из товара
- Расходники списываются с остатков фулфилмента
- Стоимость включается в стоимость услуги
**WORKFLOW ИСПОЛЬЗОВАНИЯ**:
1. Селлер выбирает услугу "Создание продукта"
2. Указывает базовый товар
3. Выбирает необходимые расходники фулфилмента
4. Фулфилмент обрабатывает заказ и создает продукт
5. Расходники списываются, создается готовый продукт
---
## 15. 📊 СТАТИСТИКА И АНАЛИТИКА
### 15.1 Структура статистики по кабинетам
#### **В КАБИНЕТЕ ПОСТАВЩИКА**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары (классифицируются при заказе)
#### **В КАБИНЕТЕ ФУЛФИЛМЕНТА**:
- **ТОВАРЫ**: Базовые товары от поставщиков (принятые на склад)
- **ПРОДУКТЫ**: Отдельный блок готовой продукции
- **БРАК**: Статистика потерь и списаний
- **РАСХОДНИКИ ФУЛФИЛМЕНТА**: Операционные материалы фулфилмента
- **РАСХОДНИКИ СЕЛЛЕРОВ**: Материалы для товаров селлеров
### 15.2 Ключевые метрики
**ОБЩИЕ ПОКАЗАТЕЛИ**:
- Общие остатки, заказано, в пути, остаток, продано
- Подсветка предметов с остатками ниже критического уровня
**АКТУАЛИЗАЦИЯ ДАННЫХ**:
- При изменении количества в карточке данные актуализируются во всей системе
- Статистика обновляется в реальном времени
- Отслеживание изменений для аналитики
---
## 16. 📱 ПРАВИЛА UI/UX И ИНТЕРФЕЙСА
### 16.1 Отзывчивость интерфейса
- **ОБЯЗАТЕЛЬНО**: Интерфейс должен работать на всех устройствах
- **ПРАВИЛО**: Адаптивная сетка для карточек товаров
- **ФУНКЦИЯ**: Оптимизация для мобильных устройств
- **ТРЕБОВАНИЕ**: Корректное отображение на экранах от 320px до 4K
### 16.2 Обратная связь пользователю
- **ОБЯЗАТЕЛЬНО**: Уведомления об успешных/неуспешных операциях
- **ПРАВИЛО**: Индикаторы загрузки для длительных операций
- **ФУНКЦИЯ**: Подтверждение критических действий (удаление, деактивация)
- **UX**: Понятные сообщения об ошибках с предложением решения
### 16.3 Правила обработки ошибок
- **ОБЯЗАТЕЛЬНО**: Логирование всех ошибок с детальной информацией
- **ПРАВИЛО**: Понятные сообщения об ошибках для пользователя
- **ФУНКЦИЯ**: Автоматическое восстановление после сбоев
- **МОНИТОРИНГ**: Отслеживание критических ошибок в реальном времени
### 16.4 Производительность
- **ПРАВИЛО**: Пагинация для больших списков товаров
- **ФУНКЦИЯ**: Ленивая загрузка изображений
- **ОПТИМИЗАЦИЯ**: Кэширование часто запрашиваемых данных
- **ПРОИЗВОДИТЕЛЬНОСТЬ**: Время загрузки страницы не более 3 секунд
---
## 17. ⚠️ КРИТИЧЕСКИЕ ЗАПРЕТЫ
### 17.1 НИКОГДА НЕ ДЕЛАТЬ:
1. ❌ Удалять предметы с существующими заказами
2. ❌ Изменять статусы заказов без уведомлений
3. ❌ Обходить проверки остатков предметов
4. ❌ Давать доступ к чужим данным
5. ❌ Игнорировать ошибки валидации
6. ❌ Сохранять пароли в открытом виде
7. ❌ Пропускать логирование критических операций
8. ❌ Блокировать интерфейс без индикации загрузки
9. ❌ Создавать брак или продукт без связи с родительским товаром
10. ❌ Создавать отдельные типы расходников (только общий тип "РАСХОДНИКИ")
11. ❌ Разрешать заказ брака
12. ❌ Нарушать иерархию типов предметов
13. ❌ Пропускать промежуточные статусы в workflow
14. ❌ Нарушать обязательную последовательность модулей в статистике фулфилмента
15. ❌ **Использовать неправильные имена полей GraphQL** (`getMyCounterparties` вместо `myCounterparties`)
16. ❌ **Использовать GET_SUPPLY_SUPPLIERS для отображения поставщиков в формах** (только партнеры WHOLESALE)
17. ❌ **Создавать интерфейсы TypeScript не соответствующие schema.prisma** (`sku`/`stock` вместо `article`/`quantity`)
18. ❌ **Использовать общие запросы вместо специализированных** (`GET_ALL_PRODUCTS` вместо `GET_ORGANIZATION_PRODUCTS` для конкретного поставщика)
19. ❌ **Показывать расходники в формах создания поставок товаров** (строгая типизация `PRODUCT`/`CONSUMABLE`)
20. ❌ **Фильтровать предметы по типу на фронтенде** (фильтрация должна быть в GraphQL резолвере)
21. ❌ **ИСПОЛЬЗОВАТЬ МОКОВЫЕ ДАННЫЕ БЕЗ РАЗРЕШЕНИЯ** - все компоненты ОБЯЗАТЕЛЬНО должны использовать реальные GraphQL запросы. Моковые данные можно добавлять ТОЛЬКО с явного разрешения пользователя
22. ❌ **ДОБАВЛЯТЬ ПОЛЕ РЫНКА К ТОВАРАМ** - рынок принадлежит организации поставщика (`Organization.market`), товары наследуют рынок через связь с организацией
23. ❌ **ПУТАТЬ РЫНОК И МАРКЕТ** - РЫНОК = физическое место (Садовод, ТЯК), МАРКЕТ = раздел системы (/market)
24. ❌ **ИСПОЛЬЗОВАТЬ НАЗВАНИЯ ОРГАНИЗАЦИЙ В ЛОГИКЕ БЕЗОПАСНОСТИ** - проверки доступа только по `organization.type` и системным ID
25. ❌ **СОЗДАВАТЬ УСЛОВИЯ НА ОСНОВЕ ПОЛЬЗОВАТЕЛЬСКИХ СТРОК** - никаких `if (name.includes())` для определения функционала
26. ❌ **ПУТАТЬ ДАННЫЕ И ФУНКЦИОНАЛ** - "ОПТ Маркет" (название рынка) ≠ "Маркет" (раздел системы)
27. ❌ **ПРЕДСТАВЛЯТЬ ИНТЕРПРЕТАЦИИ КАК ФАКТЫ** - всегда четко разделять прямые цитаты из правил и логические выводы
28. ❌ **ОТВЕЧАТЬ БЕЗ ССЫЛОК НА ИСТОЧНИКИ** - при ссылке на правила всегда указывать номер строки или раздел
29. ❌ **ИСПОЛЬЗОВАТЬ КАТЕГОРИЧНЫЕ УТВЕРЖДЕНИЯ БЕЗ ДОКАЗАТЕЛЬСТВ** - избегать "ТОЧНО!", "ИМЕННО ТАК!" без прямых цитат
### 17.2 ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:
1. ✅ Проверка остатков перед добавлением в корзину
2. ✅ Валидация всех числовых значений (цена > 0, вес > 0)
3. ✅ Автоматическая генерация уникальных артикулов СФ
4. ✅ Логирование всех изменений статусов
5. ✅ Уведомления всех участников при изменении статусов
6. ✅ Обязательная типизация всех предметов
7. ✅ Связь производных типов с родительскими предметами
8. ✅ Проверка доступности товаров перед заказом
9. ✅ Соблюдение жизненного цикла статусов поставок
10. ✅ Фиксация план/факт в процессе создания продукта
11. ✅ **УКАЗЫВАТЬ ИСТОЧНИКИ ИНФОРМАЦИИ** - при ссылке на правила обязательно указывать строку/раздел
12. ✅ **РАЗДЕЛЯТЬ ФАКТЫ И ИНТЕРПРЕТАЦИИ** - четко маркировать что взято из правил, а что является выводом
13. ✅ **ИСПОЛЬЗОВАТЬ ОСТОРОЖНЫЕ ФОРМУЛИРОВКИ** - "согласно правилам", "возможно", "требует уточнения"
### 17.3 📝 ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ С ФАКТАМИ
**При ссылке на правила ОБЯЗАТЕЛЬНО использовать формат:**
✅ **ПРАВИЛЬНО:**
```
📖 ФАКТ из rules-complete.md (строка 2225): "установка цены за единицу"
🧠 МОЯ ИНТЕРПРЕТАЦИЯ: возможно, это происходит в разделе X
❓ ПРЕДПОЛОЖЕНИЕ: требует уточнения у пользователя
⚠️ НЕ НАЙДЕНО в правилах: информация о точном местоположении
```
❌ **НЕПРАВИЛЬНО:**
```
"Да! Точно понимаю! Фулфилмент устанавливает цены в разделе X!"
```
**ОБЯЗАТЕЛЬНАЯ МАРКИРОВКА:**
- 📖 **ФАКТ** - прямая цитата из правил с номером строки
- 🧠 **ИНТЕРПРЕТАЦИЯ** - мой логический вывод (четко обозначен)
- ❓ **ПРЕДПОЛОЖЕНИЕ** - гипотеза, требующая подтверждения
- ⚠️ **НЕ НАЙДЕНО** - информация отсутствует в правилах
**СТОП-СЛОВА (избегать без доказательств):**
❌ "ТОЧНО!", "ИМЕННО ТАК!", "ДА! ПОНИМАЮ!", "АБСОЛЮТНО ВЕРНО!"
✅ "Согласно правилам...", "Не указано, но возможно...", "Требует уточнения"
### 17.4 🔒 ПРАВИЛА БЕЗОПАСНОСТИ: Разделение данных и функционала
#### КРИТИЧЕСКОЕ ПРАВИЛО БЕЗОПАСНОСТИ
**ПРИНЦИП**: Названия организаций, рынков и любые пользовательские данные НИКОГДА не должны влиять на функционал и безопасность системы.
**ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:**
✅ **ПРАВИЛЬНЫЕ ПРОВЕРКИ:**
- Проверки доступа ТОЛЬКО по типу организации: `organization.type === 'WHOLESALE'`
- Роутинг ТОЛЬКО по предопределенным путям: `/market`, `/supplies` и т.д.
- Валидация ТОЛЬКО по ID и системным полям
- Фильтрация ТОЛЬКО по enum значениям из схемы
❌ **ЗАПРЕЩЕННЫЕ ПРОВЕРКИ (УЯЗВИМОСТИ):**
- Использование `organization.name` в условиях доступа
- Проверки по `organization.market` для определения функционала
- Любые проверки содержимого строк: `includes()`, `startsWith()`, `match()`
- Динамическое создание путей на основе пользовательских данных
**ПРИМЕРЫ:**
```typescript
// ❌ УЯЗВИМОСТЬ - название может быть любым
if (organization.name.includes('Маркет')) {
// предоставить специальный доступ
}
// ❌ УЯЗВИМОСТЬ - пользователь может подделать название
if (organization.market === 'special-market') {
// изменить цены
}
// ✅ БЕЗОПАСНО - проверка по системному типу
if (organization.type === 'WHOLESALE') {
// логика для поставщиков
}
// ✅ БЕЗОПАСНО - проверка по ID из whitelist
if (ALLOWED_FULFILLMENT_IDS.includes(organization.id)) {
// логика для проверенных фулфилментов
}
```
**РАЗДЕЛЕНИЕ КОНТЕКСТОВ:**
1. **ДАННЫЕ (могут быть любыми):**
- Названия организаций: "ОПТ Маркет", "Супер Склад", и т.д.
- Названия рынков: "Садовод", "ТЯК Москва", любые другие
- Любые пользовательские строки
2. **ФУНКЦИОНАЛ (строго определен):**
- Системные разделы: `/market`, `/supplies`, `/partners`
- Типы организаций: `WHOLESALE`, `SELLER`, `FULFILLMENT`, `LOGIST`
- Статусы и enum из Prisma схемы
**ПРАВИЛО**: Физический рынок "ОПТ Маркет" - это просто строка данных. Раздел "Маркет" (/market) - это системный функционал. Они никак не связаны и не должны влиять друг на друга.
### 17.5 📦 УПРАВЛЕНИЕ СВЯЗЯМИ ТОВАР-КАРТОЧКА В РЕЦЕПТУРЕ
#### 17.5.1 Общие принципы
**НАЗНАЧЕНИЕ**: Связь товара с карточкой маркетплейса - это метаданные для учета, НЕ влияющие на физический состав продукта.
**ФОРМУЛА ПРОДУКТА НЕИЗМЕННА**:
```
ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
```
**СВЯЗЬ С МП** = отдельные метаданные для логистики и учета
#### 17.5.2 UI компонент связи с карточками
**РАСПОЛОЖЕНИЕ**: В форме создания поставки, в секции каждого товара
**ТИП КОМПОНЕНТА**: Dropdown с поиском и фильтрацией
**ИСТОЧНИК ДАННЫХ**: База данных карточек маркетплейсов селлера (GraphQL запрос)
#### 17.5.3 Логика состояний карточек
**✅ СВЯЗАНО** - карточка уже привязана к этому товару:
- Показывать зеленую галочку
- Текст: "Название карточки - Связано"
- Можно отвязать (сброс в "Без привязки")
**⚠️ ДОСТУПНО** - карточка свободна для привязки:
- Показывать желтый значок предупреждения
- Текст: "Название карточки - Доступно"
- Можно привязать к текущему товару
**❌ ЗАНЯТО** - карточка привязана к другому товару:
- Показывать красный крестик
- Текст: "Название карточки - Занято (товар: 'Название')"
- Пункт заблокирован (disabled)
- Показывать для информации, но нельзя выбрать
**🔍 БЕЗ ПРИВЯЗКИ** - товар не связан с карточкой:
- Пункт по умолчанию
- Показывать серый значок
- Текст: "Без привязки к карточке"
#### 17.5.4 Техническая реализация
**GraphQL запрос**:
```graphql
query GetSellerCards {
myMarketplaceCards {
id
title
marketplace
article
linkedProductId # null если свободна
linkedProduct {
# для отображения занятости
id
name
}
}
}
```
**Логика фильтрации**:
- Все карточки селлера показываются в dropdown
- Статус определяется по полю `linkedProductId`
- Автосвязка: карточки с похожим названием показываются первыми
**Сохранение**:
- При создании поставки связь сохраняется в поле `marketplaceCardId` рецептуры
- При изменении связи обновляется поле `linkedProductId` в карточке
#### 17.5.5 UX поведение
**ПОИСК В DROPDOWN**:
- Фильтрация по названию карточки
- Фильтрация по артикулу маркетплейса
- Автофокус при открытии
**ГРУППИРОВКА**:
```
[Dropdown: Выберите карточку Wildberries ▼]
├─ 🔍 БЕЗ ПРИВЯЗКИ
├─ ────── ДОСТУПНЫЕ ──────
├─ ⚠️ "Кроссовки Nike Air" - Доступно
├─ ⚠️ "Футболка Adidas" - Доступно
├─ ────── СВЯЗАННЫЕ ──────
├─ ✅ "Джинсы Levi's" - Связано
├─ ────── ЗАНЯТЫЕ ──────
└─ ❌ "Куртка Puma" - Занято (товар "Верхняя одежда") [disabled]
```
**ВАЛИДАЦИЯ**:
- Связь опциональна - можно создать поставку без привязки
- При выборе занятой карточки показывать предупреждение
- При отвязке подтверждать действие
#### 17.5.6 Интеграция с существующими правилами
**СОВМЕСТИМОСТЬ**:
- Не нарушает существующую логику создания поставок
- Дополняет рецептуру метаданными
- Совместима с типами поставок (карточки/поставщики)
**ОБЯЗАТЕЛЬНОСТЬ**:
- Связь с карточкой - ОПЦИОНАЛЬНА
- Товар может существовать без привязки к МП
- Карточка может существовать без привязки к товару
**ПРИОРИТЕТ РАЗРАБОТКИ**: Средний (не блокирует основную функциональность)
---
## 18. 🛠️ GRAPHQL И TYPESCRIPT ПРАВИЛА
### 18.1 Правила именования полей
**ВАЖНО**: Имена полей в GraphQL запросах должны точно соответствовать схеме!
```typescript
// ✅ ПРАВИЛЬНО - соответствует схеме
export const GET_MY_COUNTERPARTIES = gql`
query GetMyCounterparties {
myCounterparties { // <- имя поля в схеме
id
name
type
}
}
`
// Использование в компоненте
const allCounterparties = counterpartiesData?.myCounterparties || []
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует схеме
const allCounterparties = counterpartiesData?.getMyCounterparties || [] // Ошибка!
```
### 18.2 Правила отладки GraphQL
**При проблемах с GraphQL запросами следовать чек-листу**:
1. **Проверить соответствие имен полей схеме**
2. **Добавить fetchPolicy: 'network-only' для обхода кеша**
3. **Логировать данные в браузере и сервере**
4. **Проверить авторизацию пользователя**
5. **Убедиться что резолвер вызывается**
### 18.3 Обязательные поля для отладки
```typescript
const { data, loading, error } = useQuery(QUERY_NAME, {
fetchPolicy: 'network-only', // Обходим кеш при отладке
errorPolicy: 'all', // Показываем все ошибки
})
// Логирование для отладки
console.log('Data:', data)
console.log('Loading:', loading)
console.log('Error:', error)
```
### 18.4 TypeScript Rules
#### **Интерфейсы данных**
**Поля интерфейсов должны соответствовать GraphQL схеме**:
```typescript
// ✅ ПРАВИЛЬНО - соответствует schema.prisma
interface GoodsProduct {
id: string
name: string
article: string // <- соответствует полю в schema
quantity?: number // <- соответствует полю в schema
organization: {
id: string
name: string
}
}
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует schema
interface GoodsProduct {
sku: string // <- в schema поле называется 'article'
stock?: number // <- в schema поле называется 'quantity'
}
```
### 18.5 Система партнерства в GraphQL
**ПРАВИЛА ИСПОЛЬЗОВАНИЯ ПАРТНЕРСТВА**:
- Поставщики в формах берутся только из партнеров с типом `WHOLESALE`
- Используется запрос `GET_MY_COUNTERPARTIES` с фильтрацией по типу
- НЕ используется `GET_SUPPLY_SUPPLIERS` для отображения поставщиков в формах
- Партнерство создается двумя способами: через заказ в маркете или через раздел "Партнеры"
- Двусторонние записи в таблице `Counterparty` при создании партнерства
### 18.6 Архитектурные принципы GraphQL
- **Создавать специализированные резолверы** для каждого контекста использования
- **Использовать параметризованные запросы** (`organizationId`, `type`, `search`) вместо фильтрации на фронтенде
- **Добавлять подробное логирование** в резолверы для отладки (входные параметры, результаты фильтрации)
- **Типы запросов должны отражать бизнес-логику**: `organizationProducts` для товаров конкретной организации
### 18.7 Правила РЫНКОВ и МАРКЕТА
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ:**
- **РЫНОК** 🏪 = физическое место (Садовод, ТЯК)
- **МАРКЕТ** 🛒 = раздел системы `/market`
**ПОЛЕ РЫНКА В SCHEMA:**
- **Organization.market** ✅ - поставщик принадлежит физическому рынку
- **Product.market** ❌ - ЗАПРЕЩЕНО, товары наследуют рынок от организации
- **Отображение рынка товаров**: через `product.organization.market`
- **Фильтрация по рынкам**: через `organization.market`, НЕ через `product.market`
**ЗАПРОСЫ С РЫНКАМИ:**
```graphql
# ✅ ПРАВИЛЬНО - рынок от организации поставщика
query GetProductsWithMarket {
myProducts {
id
name
organization {
market # Физический рынок поставщика
}
}
}
# ✅ ПРАВИЛЬНО - товары в маркете с информацией о рынке
query GetMarketProducts {
marketProducts {
id
name
organization {
market # Рынок поставщика
name # Название поставщика
}
}
}
```
**МАРКЕТ (/market) ПРАВИЛА:**
- **Назначение**: Глобальный каталог всех товаров
- **Фильтрация**: По рынкам поставщиков, типам товаров, категориям
- **Отображение**: Показать рынок поставщика в карточках товаров
- **НЕ путать**: МАРКЕТ ≠ конкретный физический рынок
- **Значения по умолчанию в резолверах** для критических параметров (`type: args.type || "PRODUCT"`)
- **Валидация обязательных параметров** на уровне схемы (`organizationId: ID!`)
- **Кеширование обходить при проблемах** через `fetchPolicy: 'network-only'`
### 18.8 GraphQL правила для поля organization в мутациях
#### 18.8.1 Обязательность поля organization
**ПРАВИЛО**: Все мутации, возвращающие объекты с типом, включающим `organization: Organization!`, ДОЛЖНЫ запрашивать это поле.
**ПРОБЛЕМА**: Apollo Client кэш ожидает поле `organization` в ответе, если оно определено в GraphQL типе как обязательное.
#### 18.8.2 Правильное написание мутаций
**❌ НЕПРАВИЛЬНО** (вызывает ошибку Apollo Client):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
# НЕТ поля organization - ОШИБКА кэша!
}
}
}
```
**✅ ПРАВИЛЬНО** (работает корректно):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
organization {
# ОБЯЗАТЕЛЬНО включить!
id
name
fullName
}
}
}
}
```
#### 18.8.3 Чек-лист для мутаций
**ОБЯЗАТЕЛЬНАЯ ПРОВЕРКА** перед созданием мутации:
1. ✅ Проверить GraphQL тип возвращаемого объекта
2. ✅ Если есть поле `organization: Organization!` - добавить в запрос
3. ✅ Включить минимальные поля: `id`, `name`, `fullName`
4. ✅ Проверить resolver включает `include: { organization: true }`
**ПРИМЕНЯЕТСЯ К**:
- `CREATE_LOGISTICS` ✅ Исправлено
- `UPDATE_LOGISTICS` ✅ Исправлено
- `CREATE_SERVICE` - проверить при разработке
- `UPDATE_SERVICE` - проверить при разработке
- Все другие мутации с организационными объектами
**ОШИБКА БЕЗ ПОЛЯ**: `Error converting field "organization" of expected non-nullable type`
---
## 19. 🔧 АРХИТЕКТУРНЫЕ ПРИНЦИПЫ
### 19.1 Стандарты разработки
- **ОБЯЗАТЕЛЬНО**: Покрытие тестами критической функциональности
- **ПРАВИЛО**: Следование принципам SOLID
- **ФУНКЦИЯ**: Автоматическое тестирование при развертывании
- **КАЧЕСТВО**: Минимальное покрытие тестами 80%
### 19.2 Документация
- **ОБЯЗАТЕЛЬНО**: Документирование всех API методов
- **ПРАВИЛО**: Комментарии к сложной бизнес-логике
- **ФУНКЦИЯ**: Автоматическая генерация документации
- **СТАНДАРТ**: Актуальная техническая документация
### 19.3 Масштабируемость
- **АРХИТЕКТУРА**: Модульная структура для легкого расширения
- **ПРАВИЛО**: Использование индексов для быстрого поиска
- **ФУНКЦИЯ**: Горизонтальное масштабирование при росте нагрузки
- **ПЛАНИРОВАНИЕ**: Готовность к увеличению нагрузки в 10 раз
### 19.4 Безопасность данных
- **ОБЯЗАТЕЛЬНО**: Шифрование чувствительных данных
- **ПРАВИЛО**: Аудит всех действий пользователей
- **ФУНКЦИЯ**: Контроль доступа на уровне API
- **БЕЗОПАСНОСТЬ**: Двухфакторная аутентификация для критических операций
---
## 20. 🎯 ПРАВИЛА КАЧЕСТВА КОДА
### 20.1 Проверки и валидация
**ОБЯЗАТЕЛЬНЫЕ ПРОВЕРКИ**:
- ✅ Типизация предметов: каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируются)
- ✅ БРАК и ПРОДУКТ имеют обязательную связь с родительским товаром (parentId)
- ✅ Расходники создаются как универсальный тип, классифицируются при заказе
- ✅ **В формах создания поставок товаров показываются ТОЛЬКО предметы типа ТОВАР** (`PRODUCT`)
- ✅ **В формах создания поставок расходников показываются ТОЛЬКО предметы типа РАСХОДНИКИ** (`CONSUMABLE`)
- ✅ **Фильтрация по типу предмета происходит на уровне GraphQL резолвера**, не на фронтенде
### 20.2 Workflow статусов
- ✅ Соблюдена последовательность: PENDING → SUPPLIER_APPROVED → CONFIRMED → LOGISTICS_CONFIRMED → SHIPPED → IN_TRANSIT → DELIVERED
- ✅ Нет пропуска промежуточных статусов
- ✅ Каждое изменение статуса сопровождается уведомлением
### 20.3 Правила доступа
- ✅ Поставщик НЕ может добавлять собственные товары в корзину
- ✅ Заказ брака ЗАПРЕЩЕН
- ✅ Только активные предметы отображаются в маркете
- ✅ Проверка остатков перед добавлением в корзину
---
## 21. 🔍 ДИАГНОСТИКА И РЕШЕНИЕ ПРОБЛЕМ
### 21.1 Правило уточнений
**КРИТИЧЕСКИ ВАЖНО**: Если я не уверен в выполнении задачи или вижу противоречия в правилах - ОБЯЗАТЕЛЬНО уточнить у пользователя!
### 21.2 КОГДА УТОЧНЯТЬ:
- [ ] Недостаточно информации для правильного выполнения
- [ ] Вижу противоречия между правилами
- [ ] Задача может нарушить критические правила
- [ ] Неясно как применить правило в конкретной ситуации
- [ ] Есть сомнения в интерпретации требований
### 21.3 КАК УТОЧНЯТЬ:
1. Четко сформулировать что именно неясно
2. Указать какие правила/требования конфликтуют
3. Предложить варианты решения если возможно
4. Запросить конкретные уточнения
**❌ НИКОГДА не делать предположений если есть сомнения!**
---
## 22. 📋 КАТЕГОРИИ ТОВАРОВ И РАСХОДНИКОВ
### 22.1 Полный список 28 универсальных категорий товаров
1. Одежда и обувь
2. Косметика и парфюмерия
3. Дом и сад
4. Детские товары
5. Спорт и отдых
6. Электроника
7. Книги
8. Здоровье
9. Автотовары
10. Строительство и ремонт
11. Продукты питания
12. Зоотовары
13. Дача, сад и огород
14. Канцелярские товары
15. Хобби и творчество
16. Украшения и аксессуары
17. Сумки и чемоданы
18. Техника для дома
19. Музыкальные инструменты
20. Игры и игрушки
21. Мебель
22. Товары для красоты
23. Бытовая химия
24. Товары для путешествий
25. Медицинские товары
26. Религиозные товары
27. Антиквариат и коллекционирование
28. Прочие товары
### 22.2 12 специализированных категорий расходников
#### 🎁 **1. УПАКОВКА И ЗАЩИТА**
- Коробки (различных размеров)
- Пакеты (полиэтиленовые, бумажные, фирменные)
- Пузырчатая пленка, воздушные подушки
- Стрейч-пленка, гофрокартон
- Паллетная пленка, защитные уголки
#### 🏷️ **2. МАРКИРОВКА И ИДЕНТИФИКАЦИЯ**
- Этикетки (адресные, штрих-код, QR-код)
- Бирки (ценники, размерники)
- Стикеры и наклейки
- Маркеры и ручки
- Штампы и печати, термоэтикетки
#### 🔧 **3. КРЕПЕЖ И СОЕДИНЕНИЕ**
- Скотч (прозрачный, цветной, армированный)
- Клей и клеевые составы
- Стяжки пластиковые
- Степлер и скобы
- Веревки и шнуры, стрейч-лента
#### 📄 **4. ДОКУМЕНТООБОРОТ И ВКЛАДЫШИ**
- Накладные и сопроводительные документы
- Инструкции по эксплуатации
- Гарантийные талоны
- Рекламные буклеты, визитки и флаеры
- Благодарственные письма, купоны и промокоды
#### 🧼 **5. ГИГИЕНА И БЕЗОПАСНОСТЬ**
- Перчатки (латексные, нитриловые)
- Маски и респираторы
- Антисептики и дезинфекторы
- Салфетки и тряпки
- Фартуки и халаты, бахилы
#### 🛠️ **6. ИНСТРУМЕНТЫ И ПРИСПОСОБЛЕНИЯ**
- Ножи и резаки, ножницы
- Линейки и рулетки
- Упаковочные машины (ленточные)
- Дозаторы скотча
- Пистолеты для термоклея
- Весы и мерная тара
#### 🎨 **7. БРЕНДИНГ И ДИЗАЙН**
- Фирменные пакеты с логотипом
- Брендированные коробки
- Цветная упаковочная бумага
- Ленты и банты
- Наклейки с логотипом компании
- Подарочная упаковка
#### ⚡ **8. СПЕЦИАЛИЗИРОВАННЫЕ МАТЕРИАЛЫ**
- Антистатические пакеты
- Влагопоглотители
- Температурные индикаторы
- Хрупкие наклейки
- Пломбы и пломбировочные материалы
- Защита от краж (магнитные датчики)
#### 🏪 **9. ТОРГОВОЕ ОБОРУДОВАНИЕ**
- Манекены и вешалки
- Ценникодержатели
- Подставки и стойки
- Корзины и тележки
- Зеркала примерочные
- Освещение витрин
#### 🚚 **10. ЛОГИСТИКА И СКЛАДИРОВАНИЕ**
- Паллеты и поддоны
- Контейнеры и ящики
- Стеллажные системы
- Погрузочные ремни
- Защитные чехлы
- Адресные ярлыки для груза
#### 💻 **11. ТЕХНИЧЕСКИЕ РАСХОДНИКИ**
- Картриджи для принтеров
- Термоголовки, красящие ленты
- Батарейки для сканеров
- Чистящие средства для техники
- Запчасти для упаковочного оборудования
#### 🎪 **12. СЕЗОННЫЕ И ПРАЗДНИЧНЫЕ**
- Новогодняя упаковка
- Подарочные мешки
- Праздничные ленты
- Тематические наклейки
- Открытки и поздравления
- Сезонная упаковочная бумага
**ПРИМЕЧАНИЕ**: Данные категории являются рекомендательными и могут быть адаптированы под специфику конкретного поставщика расходников.
---
## 23. 🎖️ ПРИОРИТЕТЫ РАЗРАБОТКИ
### 23.1 ВЫСОКИЙ ПРИОРИТЕТ:
1. 🔴 Безопасность и контроль доступа
2. 🔴 Целостность данных и валидация
3. 🔴 Корректность статусов поставок
4. 🔴 Уведомления участников процесса
5. 🔴 Правильная типизация предметов
6. 🔴 Связи между товарами и производными типами
### 23.2 СРЕДНИЙ ПРИОРИТЕТ:
1. 🟡 Производительность и оптимизация
2. 🟡 Пользовательский опыт
3. 🟡 Аналитика и отчетность
4. 🟡 Интеграции с внешними системами
5. 🟡 Workflow для брака и продуктов
6. 🟡 Разделение расходников по типам
### 23.3 НИЗКИЙ ПРИОРИТЕТ:
1. 🟢 Дополнительные фильтры
2. 🟢 Косметические улучшения
3. 🟢 Экспериментальные функции
4. 🟢 Расширенная кастомизация
---
## 🚨 КРИТИЧЕСКИЕ СИТУАЦИИ И EDGE CASES
### 🔴 Отмена заказов на разных этапах workflow
**PENDING → Отмена разрешена**
- Действие: Удаление заказа без последствий
- Уведомления: Поставщику о отмене
- Влияние на статистику: Нет
**SUPPLIER_APPROVED → Отмена с согласия поставщика**
- Действие: Требуется подтверждение поставщика
- Штрафы: Возможны согласно договору
- Восстановление: Товары возвращаются в доступные остатки
**CONFIRMED/LOGISTICS_CONFIRMED → Отмена критическая**
- Действие: Требуется согласие всех участников
- Штрафы: Логистические расходы
- Альтернатива: Изменение адреса доставки
**SHIPPED/IN_TRANSIT → Отмена невозможна**
- Действие: Только возврат после получения
- Процедура: Через модуль "Возвраты с ПВЗ"
### 🔄 Частичная доставка товаров
**Сценарий**: Поставщик доставил 80 из 100 заказанных единиц
**Алгоритм обработки**:
1. Фулфилмент фиксирует фактическое количество
2. Система создает два отдельных документа:
- DELIVERED (80 единиц) - обрабатывается обычным порядком
- PARTIAL_DELIVERED (20 единиц) - остается в статусе ожидания
3. Селлер получает уведомление о частичной поставке
4. Принятие решения: ждать остаток или отменить недопоставку
### 📊 Превышение лимитов остатков
**Проблема**: Попытка заказать больше чем есть у поставщика
**Техническая реализация**:
```typescript
if (requestedQuantity > availableStock) {
throw new GraphQLError(`Недостаточно товара. Доступно: ${availableStock}, запрошено: ${requestedQuantity}`)
}
```
**UX решение**: Real-time валидация в формах заказа
### 🔍 Дубликаты артикулов
**Сценарий**: Поставщик пытается создать товар с существующим артикулом
**Проверка на уровне БД**:
```sql
UNIQUE INDEX ON products(article, organization_id)
```
**Обработка**: Автоматическое добавление суффикса или предложение изменить артикул
---
## 24. 📎 ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ
### Приложение A: GraphQL запросы фулфилмента
```typescript
// Основные запросы
GET_MY_SERVICES // Услуги фулфилмента
GET_MY_LOGISTICS // Логистические маршруты
GET_MY_EMPLOYEES // Сотрудники организации
GET_FULFILLMENT_WAREHOUSE_STATS // Статистика склада
GET_WAREHOUSE_PRODUCTS // Товары на складе
GET_MY_FULFILLMENT_SUPPLIES // Расходники фулфилмента
GET_EMPLOYEE_SCHEDULE // Табель рабочего времени
// Мутации
;(CREATE_SERVICE, UPDATE_SERVICE, DELETE_SERVICE)
;(CREATE_LOGISTICS, UPDATE_LOGISTICS, DELETE_LOGISTICS)
;(CREATE_EMPLOYEE, UPDATE_EMPLOYEE, DELETE_EMPLOYEE)
UPDATE_EMPLOYEE_SCHEDULE // Обновление табеля
```
### Приложение B: Компоненты фулфилмента
```typescript
// Основные dashboard компоненты
FulfillmentWarehouseDashboard // Склад фулфилмента
FulfillmentStatisticsDashboard // Статистика
ServicesDashboard // Услуги (3 вкладки)
EmployeesDashboard // Сотрудники
SuppliesDashboard // Поставки фулфилмента
// Специализированные компоненты
;(ServicesTab, LogisticsTab, SuppliesTab) // Вкладки услуг
;(EmployeeInlineForm, EmployeeEditInlineForm) // Формы сотрудников
;(FulfillmentSuppliesTab, FulfillmentConsumablesOrdersTab) // Поставки
```
### Приложение C: Специальный роутинг для типов организаций
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies') // Специальный роут
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/wholesale-supplies')
break
case 'LOGIST':
router.push('/logist-supplies')
break
}
}
```
---
_Эта база знаний создана путем объединения rules-unified.md (v3.0) и fulfillment-cabinet-rules.md (v1.0) с устранением всех несоответствий и добавлением критически важных улучшений: быстрый справочник, глоссарий терминов, детальные алгоритмы процессов, edge cases._
_Версия: 10.1_
ата создания: 2025_
_Статус: ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ - ГОТОВ К РАЗРАБОТКЕ_
### 🚀 УЛУЧШЕНИЯ v6.0:
- ⚡ Быстрый справочник критических правил
- 🔤 Полный глоссарий терминов с определениями
- 🎯 Навигация по ролям (разработчики, аналитики, менеджеры)
- 🔄 Детальный алгоритм создания продукта с временными рамками
- 🚨 Раздел критических ситуаций и Edge Cases
- 📌 Связующие блоки между разделами
- 📊 Таблицы SLA и временных рамок
### 🔧 ИСПРАВЛЕНИЯ v6.1:
- ✅ Устранено противоречие в моменте создания БРАКА
- ✅ Исправлена логическая цепочка: рецептура задается селлером ДО процесса
- ✅ Реалистичные временные рамки SLA (рабочие дни вместо часов)
- ✅ Унифицирована классификация расходников (по назначению при использовании)
- ✅ Согласованы все алгоритмы и процессы между разделами
### 🔧 ОБНОВЛЕНИЯ v6.3:
- ✅ **ДОБАВЛЕН КРИТИЧЕСКИЙ ЗАПРЕТ**: Использование моковых данных в продакшене
- ✅ **ОБНОВЛЕН ЧЕКЛИСТ**: Добавлена проверка на отсутствие mock данных
- ✅ **РЕАЛИЗАЦИЯ**: Полная очистка моковых данных из раздела "Мои поставки" селлера
### 🎨 ИНТЕГРАЦИЯ v6.2:
- ✅ Синхронизация с visual-design-rules.md v1.1
- ✅ Добавлены визуальные правила для 8 статусов поставок
- ✅ Создана цветовая система для 6 модулей фулфилмента
- ✅ Визуальный workflow процесса создания продукта
- ✅ Перекрестные ссылки между техническими и визуальными правилами
- ✅ Покрытие визуальными решениями увеличено с 40% до 85%
### 🚀 КОНСОЛИДАЦИЯ v7.0:
- ✅ Интеграция development-checklist.md и CLAUDE.md
- ✅ Удаление дублирующих файлов
- ✅ Создание единого источника истины
### 🔧 ПОЛНАЯ ИНТЕГРАЦИЯ v8.0:
- ✅ Интеграция work-protocols.md (детальные протоколы по сложности)
- ✅ Интеграция violation-prevention-protocol.md (СТОП-сигналы и триггеры)
- ✅ Интеграция self-validation.md (расширенная система самопроверки)
- ✅ Удаление всех дублирующих файлов протоколов
### 🎯 ОПТИМИЗАЦИЯ UI/UX v8.1:
- ✅ Добавлен ТРИГГЕР #3 для автоматической активации visual-design-rules.md
- ✅ Интегрирован специальный UI/UX протокол в чеклист
- ✅ Создана система перекрестных ссылок с visual-design-rules.md
- ✅ visual-design-rules.md остается отдельным специализированным файлом
### 📊 ИНТЕГРАЦИЯ DESCRIPTION v9.0:
- ✅ Добавлена UI структура создания поставки расходников (3 блока)
- ✅ Интегрирована концепция многоуровневых таблиц
- ✅ Добавлен механизм учета ПЛАН/ФАКТ в процессе создания продукта
- ✅ Расширена детализация рецептуры продукта
- ✅ Добавлена опция места хранения готовых продуктов
### 🔧 УТОЧНЕНИЯ ЛОГИКИ v9.1:
- ✅ Уточнен статус брака: НЕ РЕАЛИЗОВАНО (еще не дошли до этого этапа)
- ✅ Добавлены четкие правила создания предметов по ролям
- ✅ Добавлен экономический учет расходников фулфилмента для селлера
- ✅ Обновлен механизм ПЛАН/ФАКТ: потери вместо брака при пересчете
- ✅ Добавлена заметка о будущей детализации статусов товаров
### 🎨 UI УЛУЧШЕНИЯ v9.2:
- ✅ Добавлены детальные правила горизонтального скролла для блока поставщиков
- ✅ Реализован горизонтальный скролл в create-suppliers-supply-page.tsx
- ✅ Добавлена адаптивность (десктоп 280px, планшет 260px, мобильный 240px)
- ✅ Интегрированы ARIA атрибуты для доступности
- ✅ Реализовано автоскрытие полосы прокрутки и навигация клавиатурой
### 🔒 БЕЗОПАСНОСТЬ И ТЕРМИНОЛОГИЯ v10.0:
- ✅ **ДОБАВЛЕН РАЗДЕЛ 17.3**: Правила безопасности - разделение данных и функционала
- ✅ **НОВЫЕ ЗАПРЕТЫ 24-26**: Запрет использования пользовательских данных в логике безопасности
- ✅ **РАСШИРЕН ГЛОССАРИЙ**: Контекстно-зависимые термины для SupplyOrder
- ✅ **УТОЧНЕНИЕ ТЕРМИНОВ**: Четкое разделение "Маркет" (раздел) vs "Маркетплейс" (внешние площадки)
- ✅ **ПРИМЕРЫ УЯЗВИМОСТЕЙ**: Конкретные примеры безопасного и небезопасного кода
### 📝 КАЧЕСТВО ОТВЕТОВ v10.1:
- ✅ **НОВЫЕ ЗАПРЕТЫ 27-29**: Запрет представления интерпретаций как фактов
- ✅ **ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ 17.3**: Четкое разделение фактов, интерпретаций и предположений
- ✅ **СИСТЕМА МАРКИРОВКИ**: 📖 ФАКТ, 🧠 ИНТЕРПРЕТАЦИЯ, ❓ ПРЕДПОЛОЖЕНИЕ, ⚠️ НЕ НАЙДЕНО
- ✅ **СТОП-СЛОВА**: Список категоричных утверждений для избегания без доказательств
- ✅ **ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА 11-13**: Указание источников и осторожные формулировки

View File

@ -0,0 +1,650 @@
generator client {
provider = "prisma-client-js"
}
generator seed {
provider = "prisma-client-js"
output = "./generated/client"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
phone String @unique
avatar String?
managerName String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String?
sentMessages Message[] @relation("SentMessages")
smsCodes SmsCode[]
organization Organization? @relation(fields: [organizationId], references: [id])
@@map("users")
}
model Admin {
id String @id @default(cuid())
username String @unique
password String
email String? @unique
isActive Boolean @default(true)
lastLogin DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("admins")
}
model SmsCode {
id String @id @default(cuid())
code String
phone String
expiresAt DateTime
isUsed Boolean @default(false)
attempts Int @default(0)
maxAttempts Int @default(3)
createdAt DateTime @default(now())
userId String?
user User? @relation(fields: [userId], references: [id])
@@map("sms_codes")
}
model Organization {
id String @id @default(cuid())
inn String @unique
kpp String?
name String?
fullName String?
ogrn String?
ogrnDate DateTime?
type OrganizationType
market String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
address String?
addressFull String?
status String?
actualityDate DateTime?
registrationDate DateTime?
liquidationDate DateTime?
managementName String?
managementPost String?
opfCode String?
opfFull String?
opfShort String?
okato String?
oktmo String?
okpo String?
okved String?
phones Json?
emails Json?
employeeCount Int?
revenue BigInt?
taxSystem String?
dadataData Json?
referralCode String? @unique
referredById String?
referralPoints Int @default(0)
apiKeys ApiKey[]
carts Cart?
counterpartyOf Counterparty[] @relation("CounterpartyOf")
organizationCounterparties Counterparty[] @relation("OrganizationCounterparties")
receivedRequests CounterpartyRequest[] @relation("ReceivedRequests")
sentRequests CounterpartyRequest[] @relation("SentRequests")
employees Employee[]
externalAds ExternalAd[] @relation("ExternalAds")
favorites Favorites[]
logistics Logistics[]
receivedMessages Message[] @relation("ReceivedMessages")
sentMessages Message[] @relation("SentMessages")
referredBy Organization? @relation("ReferralRelation", fields: [referredById], references: [id])
referrals Organization[] @relation("ReferralRelation")
products Product[]
referralTransactions ReferralTransaction[] @relation("ReferralTransactions")
referrerTransactions ReferralTransaction[] @relation("ReferrerTransactions")
sellerStatsCaches SellerStatsCache[] @relation("SellerStatsCaches")
services Service[]
supplies Supply[]
sellerSupplies Supply[] @relation("SellerSupplies")
fulfillmentSupplyOrders SupplyOrder[] @relation("SupplyOrderFulfillmentCenter")
logisticsSupplyOrders SupplyOrder[] @relation("SupplyOrderLogistics")
supplyOrders SupplyOrder[]
partnerSupplyOrders SupplyOrder[] @relation("SupplyOrderPartner")
supplySuppliers SupplySupplier[] @relation("SupplySuppliers")
users User[]
wbWarehouseCaches WBWarehouseCache[] @relation("WBWarehouseCaches")
wildberriesSupplies WildberriesSupply[]
@@index([referralCode])
@@index([referredById])
@@map("organizations")
}
model ApiKey {
id String @id @default(cuid())
marketplace MarketplaceType
apiKey String
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
validationData Json?
organizationId String
organization Organization @relation(fields: [organizationId], references: [id])
@@unique([organizationId, marketplace])
@@map("api_keys")
}
model CounterpartyRequest {
id String @id @default(cuid())
status CounterpartyRequestStatus @default(PENDING)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
senderId String
receiverId String
message String?
receiver Organization @relation("ReceivedRequests", fields: [receiverId], references: [id])
sender Organization @relation("SentRequests", fields: [senderId], references: [id])
@@unique([senderId, receiverId])
@@map("counterparty_requests")
}
model Counterparty {
id String @id @default(cuid())
createdAt DateTime @default(now())
organizationId String
counterpartyId String
type CounterpartyType @default(MANUAL)
triggeredBy String?
triggerEntityId String?
counterparty Organization @relation("CounterpartyOf", fields: [counterpartyId], references: [id])
organization Organization @relation("OrganizationCounterparties", fields: [organizationId], references: [id])
@@unique([organizationId, counterpartyId])
@@index([type])
@@map("counterparties")
}
model Message {
id String @id @default(cuid())
content String?
type MessageType @default(TEXT)
voiceUrl String?
voiceDuration Int?
fileUrl String?
fileName String?
fileSize Int?
fileType String?
isRead Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
senderId String
senderOrganizationId String
receiverOrganizationId String
receiverOrganization Organization @relation("ReceivedMessages", fields: [receiverOrganizationId], references: [id])
sender User @relation("SentMessages", fields: [senderId], references: [id])
senderOrganization Organization @relation("SentMessages", fields: [senderOrganizationId], references: [id])
@@index([senderOrganizationId, receiverOrganizationId, createdAt])
@@index([receiverOrganizationId, isRead])
@@map("messages")
}
model Service {
id String @id @default(cuid())
name String
description String?
price Decimal @db.Decimal(10, 2)
imageUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
@@map("services")
}
model Supply {
id String @id @default(cuid())
name String
article String
description String?
price Decimal @db.Decimal(10, 2)
pricePerUnit Decimal? @db.Decimal(10, 2)
quantity Int @default(0)
unit String @default("шт")
category String @default("Расходники")
status String @default("planned")
date DateTime @default(now())
supplier String @default("Не указан")
minStock Int @default(0)
currentStock Int @default(0)
usedStock Int @default(0)
imageUrl String?
type SupplyType @default(FULFILLMENT_CONSUMABLES)
sellerOwnerId String?
shopLocation String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String
actualQuantity Int?
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
sellerOwner Organization? @relation("SellerSupplies", fields: [sellerOwnerId], references: [id])
@@map("supplies")
}
model Category {
id String @id @default(cuid())
name String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
products Product[]
@@map("categories")
}
model Product {
id String @id @default(cuid())
name String
article String
description String?
price Decimal @db.Decimal(12, 2)
pricePerSet Decimal? @db.Decimal(12, 2)
quantity Int @default(0)
setQuantity Int?
ordered Int?
inTransit Int?
stock Int?
sold Int?
type ProductType @default(PRODUCT)
categoryId String?
brand String?
color String?
size String?
weight Decimal? @db.Decimal(8, 3)
dimensions String?
material String?
images Json @default("[]")
mainImage String?
isActive Boolean @default(true)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String
cartItems CartItem[]
favorites Favorites[]
category Category? @relation(fields: [categoryId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
supplyOrderItems SupplyOrderItem[]
@@unique([organizationId, article])
@@map("products")
}
model Cart {
id String @id @default(cuid())
organizationId String @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
items CartItem[]
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
@@map("carts")
}
model CartItem {
id String @id @default(cuid())
cartId String
productId String
quantity Int @default(1)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cart Cart @relation(fields: [cartId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([cartId, productId])
@@map("cart_items")
}
model Favorites {
id String @id @default(cuid())
organizationId String
productId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
product Product @relation(fields: [productId], references: [id], onDelete: Cascade)
@@unique([organizationId, productId])
@@map("favorites")
}
model Employee {
id String @id @default(cuid())
firstName String
lastName String
middleName String?
birthDate DateTime?
avatar String?
passportPhoto String?
passportSeries String?
passportNumber String?
passportIssued String?
passportDate DateTime?
address String?
position String
department String?
hireDate DateTime
salary Float?
status EmployeeStatus @default(ACTIVE)
phone String
email String?
telegram String?
whatsapp String?
emergencyContact String?
emergencyPhone String?
organizationId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
scheduleRecords EmployeeSchedule[]
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
@@map("employees")
}
model EmployeeSchedule {
id String @id @default(cuid())
date DateTime
status ScheduleStatus
hoursWorked Float?
overtimeHours Float?
notes String?
employeeId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
@@unique([employeeId, date])
@@map("employee_schedules")
}
model WildberriesSupply {
id String @id @default(cuid())
organizationId String
deliveryDate DateTime?
status WildberriesSupplyStatus @default(DRAFT)
totalAmount Decimal @db.Decimal(12, 2)
totalItems Int
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
cards WildberriesSupplyCard[]
@@map("wildberries_supplies")
}
model WildberriesSupplyCard {
id String @id @default(cuid())
supplyId String
nmId String
vendorCode String
title String
brand String?
price Decimal @db.Decimal(12, 2)
discountedPrice Decimal? @db.Decimal(12, 2)
quantity Int
selectedQuantity Int
selectedMarket String?
selectedPlace String?
sellerName String?
sellerPhone String?
deliveryDate DateTime?
mediaFiles Json @default("[]")
selectedServices Json @default("[]")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
supply WildberriesSupply @relation(fields: [supplyId], references: [id], onDelete: Cascade)
@@map("wildberries_supply_cards")
}
model Logistics {
id String @id @default(cuid())
fromLocation String
toLocation String
priceUnder1m3 Float
priceOver1m3 Float
description String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String
organization Organization @relation(fields: [organizationId], references: [id])
@@map("logistics")
}
model SupplyOrder {
id String @id @default(cuid())
partnerId String
deliveryDate DateTime
status SupplyOrderStatus @default(PENDING)
totalAmount Decimal @db.Decimal(12, 2)
totalItems Int
fulfillmentCenterId String?
logisticsPartnerId String?
consumableType String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organizationId String
items SupplyOrderItem[]
fulfillmentCenter Organization? @relation("SupplyOrderFulfillmentCenter", fields: [fulfillmentCenterId], references: [id])
logisticsPartner Organization? @relation("SupplyOrderLogistics", fields: [logisticsPartnerId], references: [id])
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
partner Organization @relation("SupplyOrderPartner", fields: [partnerId], references: [id])
@@map("supply_orders")
}
model SupplyOrderItem {
id String @id @default(cuid())
supplyOrderId String
productId String
quantity Int
price Decimal @db.Decimal(12, 2)
totalPrice Decimal @db.Decimal(12, 2)
services String[] @default([])
fulfillmentConsumables String[] @default([])
sellerConsumables String[] @default([])
marketplaceCardId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
product Product @relation(fields: [productId], references: [id])
supplyOrder SupplyOrder @relation(fields: [supplyOrderId], references: [id], onDelete: Cascade)
@@unique([supplyOrderId, productId])
@@map("supply_order_items")
}
model SupplySupplier {
id String @id @default(cuid())
name String
contactName String
phone String
market String?
address String?
place String?
telegram String?
organizationId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation("SupplySuppliers", fields: [organizationId], references: [id], onDelete: Cascade)
@@map("supply_suppliers")
}
model ExternalAd {
id String @id @default(cuid())
name String
url String
cost Decimal @db.Decimal(12, 2)
date DateTime
nmId String
clicks Int @default(0)
organizationId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation("ExternalAds", fields: [organizationId], references: [id], onDelete: Cascade)
@@index([organizationId, date])
@@map("external_ads")
}
model WBWarehouseCache {
id String @id @default(cuid())
organizationId String
cacheDate DateTime
data Json
totalProducts Int @default(0)
totalStocks Int @default(0)
totalReserved Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation("WBWarehouseCaches", fields: [organizationId], references: [id], onDelete: Cascade)
@@unique([organizationId, cacheDate])
@@index([organizationId, cacheDate])
@@map("wb_warehouse_caches")
}
model SellerStatsCache {
id String @id @default(cuid())
organizationId String
cacheDate DateTime
period String
dateFrom DateTime?
dateTo DateTime?
productsData Json?
productsTotalSales Decimal? @db.Decimal(15, 2)
productsTotalOrders Int?
productsCount Int?
advertisingData Json?
advertisingTotalCost Decimal? @db.Decimal(15, 2)
advertisingTotalViews Int?
advertisingTotalClicks Int?
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
organization Organization @relation("SellerStatsCaches", fields: [organizationId], references: [id], onDelete: Cascade)
@@unique([organizationId, cacheDate, period, dateFrom, dateTo])
@@index([organizationId, cacheDate])
@@index([expiresAt])
@@map("seller_stats_caches")
}
model ReferralTransaction {
id String @id @default(cuid())
referrerId String
referralId String
points Int
type ReferralTransactionType
description String?
createdAt DateTime @default(now())
referral Organization @relation("ReferralTransactions", fields: [referralId], references: [id])
referrer Organization @relation("ReferrerTransactions", fields: [referrerId], references: [id])
@@index([referrerId, createdAt])
@@index([referralId])
@@map("referral_transactions")
}
enum OrganizationType {
FULFILLMENT
SELLER
LOGIST
WHOLESALE
}
enum MarketplaceType {
WILDBERRIES
OZON
}
enum CounterpartyRequestStatus {
PENDING
ACCEPTED
REJECTED
CANCELLED
}
enum MessageType {
TEXT
VOICE
IMAGE
FILE
}
enum EmployeeStatus {
ACTIVE
VACATION
SICK
FIRED
}
enum ScheduleStatus {
WORK
WEEKEND
VACATION
SICK
ABSENT
}
enum SupplyOrderStatus {
PENDING
CONFIRMED
IN_TRANSIT
SUPPLIER_APPROVED
LOGISTICS_CONFIRMED
SHIPPED
DELIVERED
CANCELLED
}
enum WildberriesSupplyStatus {
DRAFT
CREATED
IN_PROGRESS
DELIVERED
CANCELLED
}
enum ProductType {
PRODUCT
CONSUMABLE
}
enum SupplyType {
FULFILLMENT_CONSUMABLES
SELLER_CONSUMABLES
}
enum CounterpartyType {
MANUAL
REFERRAL
AUTO_BUSINESS
AUTO
}
enum ReferralTransactionType {
REGISTRATION
AUTO_PARTNERSHIP
FIRST_ORDER
MONTHLY_BONUS
}

View File

@ -0,0 +1,306 @@
# 🟢 ВСЕ УПОМИНАНИЯ О КАБИНЕТЕ СЕЛЛЕРА В RULES-COMPLETE.MD
> Все строки, содержащие упоминания о селлере, выделены зеленым маркером
## 📋 ОСНОВНЫЕ ОПРЕДЕЛЕНИЯ
### Строка 118:
```
3. **🔴 ДОСТУП**: Фулфилмент = полный доступ, ==Селлер ≠ доступ к чужим данным==, Брак = ЗАПРЕЩЕН к заказу
```
### Строка 156:
```diff
+ - **СЕЛЛЕР** → `SELLER` - заказывает товары, создает поставки на маркетплейсы
```
### Строки 170-172:
```diff
+ - **СЕЛЛЕР** (`SELLER`):
+ - Товары и расходники у поставщиков
+ - Расходники фулфилмента у фулфилмента (через рецептуру в поставке)
```
### Строки 178-180:
```diff
+ - Когда селлер выбирает расходники фулфилмента в рецептуре, это формирует экономические данные:
+ - В кабинете селлера: расход на расходники фулфилмента
+ - В кабинете фулфилмента: доход от продажи расходников селлеру
```
### Строка 186:
```diff
+ - **Рецептура** - состав продукта: товар + услуги + расходники (задается селлером)
```
### Строки 194-197:
```diff
+ **ДЛЯ СОЗДАТЕЛЕЙ (Селлер/Фулфилмент):**
+ - **Термин**: "Поставка"
+ - **Контекст**: Они создают поставку товаров и расходников на фулфилмент
```
### Строка 215:
```diff
+ | Селлер | "Мои поставки" | Создает и управляет поставками |
```
### Строка 234:
```diff
+ - **Функция**: Конечные точки продаж для селлеров
```
### Строка 266:
```diff
+ 9. [🏠 Кабинет селлера (детальные правила)](#9--кабинет-селлера-детальные-правила)
```
### Строка 322:
```diff
+ | Селлер | `Organization` (type: `SELLER`) | Заказ товаров, управление поставками | ✅ Реализовано |
```
### Строки 353-355:
```diff
+ - **"Производственные расходники"** - используются в рецептурах селлеров для создания продуктов
+ **🛍️ КАБИНЕТ СЕЛЛЕРА** - заказывает и управляет поставками:
```
### Строка 390:
```diff
+ - Селлер заказывает → "Расходники селлеров"
```
### Строка 400:
```diff
+ - **ЦЕНА**: Для селлера - себестоимость дефектного товара, для фулфилмента - 0
```
### Строки 408-411:
```diff
+ - **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе ТОВАРА по заказу селлера
+ - **ИНИЦИАТОР**: Селлер создает заказ с рецептурой, фулфилмент исполняет
+ - **РЕЦЕПТУРА**: Задается селлером при создании заказа (Товар + Услуга + Расходники)
```
### Строка 419:
```diff
+ **ИСКЛЮЧЕНИЕ ДЛЯ БРАКА**: Цена может быть 0 для фулфилмента (себестоимость для селлера)
```
### Строки 444, 446-449:
```diff
+ - Поставки (`/supplies`) - обработка заказов от селлеров
+ **🛍️ СЕЛЛЕР (`SELLER`):**
+ - Мои поставки (`/supplies`) - управление заказами товаров
+ - WB Интеграция (`/wb-integration`) - связь с Wildberries
```
### Строки 486-487:
```diff
+ case 'SELLER':
+ router.push('/supplies')
```
### Строки 541, 545:
```diff
+ #### **ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ: РЕЦЕПТУРА ЗАДАНА** (селлер)
+ Действие: селлер указывает рецептуру продукта
```
### Строка 571:
```diff
+ ✓ Рецептура (товар + услуги + расходники, указанная селлером в заявке на поставку)
```
### Строка 596:
```diff
+ - ПЛАН: Количество товаров из поставки селлера (указано в заказе)
```
### Строка 609:
```diff
+ ✓ Соответствие рецептуре селлера
```
### Строка 625:
```diff
+ - Уведомление селлера о готовности
```
### Строка 645:
```diff
+ **РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
```
### Строки 657-660:
```diff
+ - **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
+ - Фирменная упаковка
+ - Этикетки, бирки
+ - Дополнительные аксессуары
```
### Строка 672:
```diff
+ **ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
```
### Строка 676:
```diff
+ **ПЛАН**: Количество товара из поставки селлера
```
### Строки 818-819:
```diff
+ case 'SELLER':
+ router.push('/supplies')
```
## 🏠 РАЗДЕЛ 9 - КАБИНЕТ СЕЛЛЕРА (строки 833-1780)
### Строка 835:
```diff
+ > 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Кабинет селлера](#145-кабинет-селлера)
```
### Строка 844:
```diff
+ - **Расходники селлера** - поставка материалов для товаров селлера
```
### Строка 851:
```diff
+ ### 9.2 UI структура создания поставки расходников селлера
```
### Строка 1333:
```diff
+ - **Приоритет**: Рынок важнее типа организации для селлера
```
### Строки 1429, 1437:
```diff
+ - Количество видов расходников селлера
+ - Название расходника селлера
```
### Строка 1467:
```diff
+ - **🔧 Расходники селлера**: Кнопка "Создать поставку" → `/supplies/create-consumables`
```
### Строка 1692:
```diff
+ **Для пути "Фулфилмент → Расходники селлера":**
```
### Строка 1779:
```diff
+ ### 9.5 Создание поставки расходников селлера
```
## 📊 УПОМИНАНИЯ В ДРУГИХ РАЗДЕЛАХ
### Строка 1963:
```diff
+ - **ПРЕДОСТАВЛЕНИЕ УСЛУГ**: Услуги обработки для селлеров
```
### Строка 1984:
```diff
+ - Установка цен на расходники перед доступностью селлерам
```
### Строка 2079:
```diff
+ - `SELLER` - Селлеры (торговые организации)
```
### Строка 2088:
```diff
+ 2. Селлер/Фулфилмент находит товар в маркете
```
### Строка 2262:
```diff
+ - Селлеры могут использовать расходники фулфилмента в разделе "Услуги / Расходники"
```
### Строка 2269:
```diff
+ 1. Селлер выбирает услугу "Создание продукта"
```
### Строка 2292:
```diff
+ - **РАСХОДНИКИ СЕЛЛЕРОВ**: Материалы для товаров селлеров
```
### Строка 2476:
```diff
+ - Типы организаций: `WHOLESALE`, `SELLER`, `FULFILLMENT`, `LOGIST`
```
### Строка 2490:
```diff
+ ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
```
### Строка 2501:
```diff
+ **ИСТОЧНИК ДАННЫХ**: База данных карточек маркетплейсов селлера (GraphQL запрос)
```
### Строка 2553:
```diff
+ - Все карточки селлера показываются в dropdown
```
### Строка 3113:
```diff
+ 3. Селлер получает уведомление о частичной поставке
```
### Строки 3189-3190:
```diff
+ case 'SELLER':
+ router.push('/supplies')
```
### Строка 3223:
```diff
+ - ✅ Исправлена логическая цепочка: рецептура задается селлером ДО процесса
```
### Строка 3232:
```diff
+ - ✅ **РЕАЛИЗАЦИЯ**: Полная очистка моковых данных из раздела "Мои поставки" селлера
```
### Строка 3275:
```diff
+ - ✅ Добавлен экономический учет расходников фулфилмента для селлера
```
## 📈 СТАТИСТИКА
**Общее количество упоминаний**: ~75 строк
**Основной раздел**: Раздел 9 (строки 833-1780) - полностью посвящен кабинету селлера
**Ключевые функции селлера**:
- Заказ товаров и расходников
- Создание поставок
- Управление рецептурами
- Интеграция с маркетплейсами
- Работа с фулфилментом
## 🎨 ВИЗУАЛЬНОЕ ВЫДЕЛЕНИЕ
В этом файле использованы следующие способы выделения:
- `==текст==` - выделение маркером
- `diff` блоки с `+` - зеленая подсветка в markdown
- Заголовки с эмодзи 🟢 для визуального акцента

View File

@ -0,0 +1,849 @@
# ПРАВИЛА КАБИНЕТА ФУЛФИЛМЕНТА (FULFILLMENT)
> ⚠️ **ВАЖНО**: Это файл с техническими деталями кабинета фулфилмента.
> Общие бизнес-правила находятся в **[rules-complete.md](./rules-complete.md)**
## Когда использовать этот файл:
- Работа с компонентами `/warehouse`, `/fulfillment-supplies`, `/services`, `/employees`
- GraphQL запросы для фулфилмента
- UI/UX специфика кабинета фулфилмента
- Технические детали реализации услуг и логистики
## 1. 🏭 СТРУКТУРА КАБИНЕТА ФУЛФИЛМЕНТА
### 1.1 Основные разделы
**ФУЛФИЛМЕНТ (`FULFILLMENT`)** имеет доступ к следующим разделам:
- **Склад** (`/warehouse`) - управление товарами по модулям
- **Поставки** (`/fulfillment-supplies`) - обработка поставок
- **Услуги** (`/services`) - управление услугами и расходниками
- **Сотрудники** (`/employees`) - управление персоналом
- **Статистика** (`/fulfillment-statistics`) - аналитика фулфилмента
- **Партнеры** (`/partners`) - управление контрагентами
- **Мессенджер** (`/messenger`) - связь с партнерами
- **Настройки** (`/settings`) - профиль и настройки
- **Экономика** (`/economics`) - финансовая аналитика
### 1.2 Навигация и роутинг
#### При входе в систему:
```typescript
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/warehouse') // Направляем на склад
break
}
```
#### Специальная логика роутинга:
- **МАКСИМАЛЬНЫЕ ПРАВА**: Доступ ко ВСЕМ разделам системы
- **АДАПТИВНАЯ НАВИГАЦИЯ**: Sidebar изменяется в зависимости от типа организации
- **СПЕЦИАЛЬНЫЙ РОУТИНГ**: `/fulfillment-supplies` вместо `/supplies`
> 📖 **Бизнес-логика роутинга**: См. [rules-complete.md#4-система-ролей-и-доступов](./rules-complete.md#4--система-ролей-и-доступов)
## 2. 🎨 UI/UX КОМПОНЕНТЫ
### 2.1 Dashboard компоненты
#### Основные компоненты кабинета:
- `FulfillmentWarehouseDashboard` - склад по модулям
- `FulfillmentSuppliesDashboard` - поставки фулфилмента
- `ServicesManagement` - управление услугами
- `FulfillmentStatistics` - статистика и аналитика
- `EmployeeManagement` - управление сотрудниками
#### Wrapper-компоненты:
- `HomePageWrapper` - маршрутизация по типам организаций
- `EconomicsPageWrapper` - адаптивная экономика по кабинетам
#### Специализированные компоненты:
- `WarehouseModuleCard` - карточка модуля склада
- `ServiceCard` - карточка услуги
- `EmployeeCard` - карточка сотрудника
- `FulfillmentStats` - статистика фулфилмента
- `LogisticsRouteCard` - карточка маршрута доставки
### 2.2 Архитектурные особенности
#### Технические правила отображения:
```tsx
// GraphQL проверки
const { data } = useQuery(GET_FULFILLMENT_DATA, {
skip: user?.organization?.type !== 'FULFILLMENT'
})
// Условное отображение
{user?.organization?.type === "FULFILLMENT" && (
<FulfillmentExclusiveComponent />
)}
// Адаптивные отступы
const margin = getSidebarMargin()
// Полинг данных для реального времени
const { data } = useQuery(GET_FULFILLMENT_STATS, {
pollInterval: 60000 // Обновление каждую минуту
})
```
### 2.3 Система учета склада (3-уровневая иерархия)
#### Структура данных:
```
🔵 УРОВЕНЬ 1: МАГАЗИНЫ
🟢 УРОВЕНЬ 2: ТОВАРЫ (зеленый - green-500)
🟠 УРОВЕНЬ 3: ВАРИАНТЫ ТОВАРОВ (оранжевый - orange-500)
```
#### Цветовое кодирование:
- Каждый уровень имеет цветной индикатор увеличивающегося размера
- Цветная левая граница с увеличивающимся отступом и толщиной
- Скроллбары в цвете уровня
- Контрастный цвет текста для читаемости
## 3. 📊 ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ
> 📖 **Бизнес-правила**: См. [rules-complete.md#11-кабинет-фулфилмента](./rules-complete.md#11--кабинет-фулфилмента) для правил workflow и процессов
### 3.1 Структура склада по модулям (ОБЯЗАТЕЛЬНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ)
1. **📦 ПРОДУКТЫ** - готовые к отправке товары
2. **🛒 ТОВАРЫ** - базовые товары от поставщиков
- **"На складе"** - готовы к обработке
- **"В обработке"** - в процессе создания продукта
3. **❌ БРАК** - товары с дефектами, требуют утилизации
4. **↩️ ВОЗВРАТЫ С ПВЗ** - возвращенные товары, к обработке
5. **🎯 РАСХОДНИКИ СЕЛЛЕРОВ** - материалы для селлеров
6. **⚙️ РАСХОДНИКИ ФУЛФИЛМЕНТА** - операционные материалы (КЛИКАБЕЛЬНЫЙ модуль)
### 3.2 Система учета склада
#### Показатели движения (дополнительные значения):
- **ПРИБЫЛО** - количество поступивших на склад за период
- **УБЫЛО** - количество списанных со склада за период
#### Текущие остатки (основные значения):
- **ФОРМУЛА**: Основные значения = Предыдущие остатки + Прибыло - Убыло
- **ОБНОВЛЕНИЕ**: В реальном времени с изменениями за сутки
- **ИСТОЧНИК**: GraphQL query `GET_FULFILLMENT_WAREHOUSE_STATS`
### 3.3 Поставки фулфилмента (`/fulfillment-supplies`)
#### Структура: 2 основные вкладки
**A) 🛒 ПОСТАВКИ ТОВАРОВ**:
- **Детализированные товары ФФ** - планы и факты поставок с маршрутами
- **Товары ФФ** - общие поставки товаров от селлеров
- **Возвраты с ПВЗ** - обработка возвращенных товаров
**B) 🔧 ПОСТАВКИ РАСХОДНИКОВ**:
- **Заказы расходников** - управление заказами от селлеров
- **Расходники селлеров** - материалы для клиентов
- **Создание поставок** - формирование новых поставок расходников
#### Workflow поставок товаров:
1. **Planned** - поставка запланирована
2. **In-transit** - товар в пути
3. **Delivered** - доставлен на склад
4. **Completed** - обработка завершена
### 3.4 Услуги фулфилмента (`/services`)
#### Архитектура интеграции с системой
**СВЯЗЬ С РЕЦЕПТУРАМИ СЕЛЛЕРОВ:**
```
СЕЛЛЕР (создание поставки)
└── Рецептура
├── Товар (от поставщика)
├── Услуги фулфилмента ← CRUD в разделе Услуги
├── Расходники селлера
└── Расходники фулфилмента ← ТОЛЬКО с установленной ценой
ФУЛФИЛМЕНТ (обработка)
├── Входящие поставки → Поставки расходников (создание)
└── Услуги → Расходники (установка цены за единицу)
```
#### Структура: 3 обязательные вкладки
**A) 🛠️ УСЛУГИ** (`defaultValue="services"`):
- **Полный CRUD**: создание, редактирование, удаление услуг
- **Поля**: `name`, `description`, `price`, `imageUrl`
- **Glass Upload Zone**: элегантная загрузка изображений
- **Назначение**: каталог услуг для рецептур селлеров
**B) 🚚 ЛОГИСТИКА**:
- **Полный CRUD**: маршруты доставки
- **Поля**: откуда → куда, тарификация до/свыше 1м³
- **Группированные локации**:
- Мой фулфилмент (название организации)
- Рынки (предустановленные)
- Склады Wildberries
- Склады Ozon
- **Glass Upload Zone**: для изображений маршрутов
**C) 📦 РАСХОДНИКИ** (**❌ БЕЗ СОЗДАНИЯ**):
- **ТОЛЬКО ПРОСМОТР** расходников с фулфилмент-склада
- **ЕДИНСТВЕННОЕ РЕДАКТИРУЕМОЕ ПОЛЕ**: `pricePerUnit` - цена за единицу для рецептур
- **UI подсветка**: "Цена за 1 {unit}" (например, "Цена за 1 шт")
- **Автоматическая синхронизация** при приеме поставки расходников
- **Glass Upload Zone**: для обновления изображений расходников
#### Workflow расходников:
**ШАГ 1 - СОЗДАНИЕ**: Только через "Входящие поставки → Поставки расходников фулфилмента"
**ШАГ 2 - СИНХРОНИЗАЦИЯ**: При приеме на склад → автоматически в Услуги/Расходники
**ШАГ 3 - ЦЕНООБРАЗОВАНИЕ**: Установка цены за единицу в разделе Услуги
**ШАГ 4 - ИСПОЛЬЗОВАНИЕ**: Доступны в рецептурах селлеров
#### Правила видимости в рецептурах:
**В РЕЦЕПТУРАХ СЕЛЛЕРОВ ПОКАЗЫВАЮТСЯ ТОЛЬКО:**
- `isAvailable = true` (есть на складе)
- `pricePerUnit != null` (цена установлена)
**НЕ ПОКАЗЫВАЮТСЯ:**
- Расходники без цены (`pricePerUnit = null`)
- Удаленные со склада (`isAvailable = false`)
### 3.5 Разделение цен закупки и продажи
**КРИТИЧЕСКОЕ ПРАВИЛО**: Расходники фулфилмента имеют **ДВЕ РАЗНЫЕ ЦЕНЫ**:
1. **ЦЕНА ЗАКУПКИ** (`Supply.price`) - цена покупки у поставщика
2. **ЦЕНА ПРОДАЖИ** (`Supply.pricePerUnit`) - цена продажи селлерам
#### Поля в базе данных:
```prisma
model Supply {
price Decimal @db.Decimal(10, 2) // Цена закупки у поставщика (НЕИЗМЕННАЯ)
pricePerUnit Decimal? @db.Decimal(10, 2) // Цена продажи селлерам (устанавливается фулфилментом)
}
```
#### Правила отображения по разделам:
**РАЗДЕЛ "СКЛАД → РАСХОДНИКИ ФУЛФИЛМЕНТА"**:
- Показывает `Supply.price` (цена закупки)
- Цена ТОЛЬКО ДЛЯ ЧТЕНИЯ, нельзя изменять
- Отражает историческую стоимость приобретения
**РАЗДЕЛ "УСЛУГИ → РАСХОДНИКИ"**:
- Показывает и редактирует `Supply.pricePerUnit` (цена продажи)
- Единственное место где можно изменить цену для селлеров
- Влияет на рецептуры и расчеты для селлеров
#### Бизнес-логика создания:
```typescript
// ПРИ ПОСТУПЛЕНИИ ОТ ПОСТАВЩИКА:
const supply = await prisma.supply.create({
data: {
price: item.price, // Цена поставщика → ЗАФИКСИРОВАНА
pricePerUnit: null, // Цена продажи → ПУСТАЯ
},
})
// УСТАНОВКА ЦЕНЫ ПРОДАЖИ (в разделе "Услуги"):
const updated = await prisma.supply.update({
data: {
pricePerUnit: newPrice, // ТОЛЬКО цена продажи
// price НЕ ТРОГАЕМ - остается цена закупки
},
})
```
### 3.6 Сотрудники фулфилмента (`/employees`)
#### Структура: 2 основные вкладки
**A) 👥 СОТРУДНИКИ** (`defaultValue="combined"`):
**Управление персоналом**:
- **CRUD операции**: создание, редактирование, удаление сотрудников
- **Статусы сотрудников**: `ACTIVE`, `VACATION`, `SICK`, `FIRED`
- **Формы добавления**: Компактная (`showCompactForm`) / Полная форма
- **Поиск и фильтрация** по имени, должности, статусу
**Табель рабочего времени**:
- **Навигация по месяцам**: текущий год/месяц с кнопками ←/→
- **Отметки по дням**: статус дня и количество отработанных часов
**B) 📋 ОТЧЕТЫ** (`value="reports"`):
- **Сводные отчеты** по сотрудникам за период
- **Экспорт данных** табеля
- **Аналитика рабочего времени**
### 3.7 Статистика фулфилмента (`/fulfillment-statistics`)
#### Блоки аналитики (сворачиваемые):
**1. НАКОПЛЕННАЯ СТАТИСТИКА** (`allTime: true`):
- Обработано товаров (общий объем)
- Выявлено брака (всего единиц)
- Поставок получено
- Общий доход (за все время)
- Выполнено заказов (успешных отгрузок)
- Удовлетворенность клиентов (средний рейтинг)
**2. ОТГРУЗКА НА ПЛОЩАДКИ** (`marketplaces: true`):
- Отправлено на Wildberries
- Отправлено на Ozon
- Отправлено на другие площадки
**3. АНАЛИТИКА ПРОИЗВОДИТЕЛЬНОСТИ** (`performance: false`):
- Среднее время обработки (на единицу товара)
- Уровень брака (от общего объема)
- Уровень возвратов (возвраты с площадок)
- Удовлетворенность клиентов
## 4. 🛠️ GRAPHQL API
### 4.1 Основные запросы (Queries)
#### Получение статистики склада:
```graphql
query GetFulfillmentWarehouseStats {
fulfillmentWarehouseStats {
products {
total
received
shipped
}
supplies {
onStock
inProcessing
}
defects {
total
pending
}
returns {
pending
processed
}
}
}
```
#### Получение услуг фулфилмента:
```graphql
query GetMyServices {
myServices {
id
name
description
price
imageUrl
isActive
}
}
```
#### Получение расходников с ценами:
```graphql
query GetMySupplies {
mySupplies {
id
name
price # Цена закупки (read-only)
pricePerUnit # Цена продажи (editable)
unit
isAvailable
warehouseConsumableId
}
}
```
#### Получение логистических маршрутов:
```graphql
query GetMyLogistics {
myLogistics {
id
fromLocation
toLocation
tariffUnder1m3
tariffOver1m3
description
}
}
```
#### Получение сотрудников:
```graphql
query GetEmployees {
employees {
id
name
position
status
schedule {
date
hoursWorked
status
}
}
}
```
### 4.2 Мутации (Mutations)
#### Создание услуги:
```graphql
mutation CreateService($input: ServiceInput!) {
createService(input: $input) {
success
service {
id
name
description
price
organization {
id
name
fullName
}
}
}
}
```
#### Обновление цены расходника:
```graphql
mutation UpdateSupplyPrice($supplyId: ID!, $pricePerUnit: Float!) {
updateSupplyPrice(id: $supplyId, pricePerUnit: $pricePerUnit) {
success
supply {
id
pricePerUnit
isAvailable
}
}
}
```
#### Создание логистического маршрута:
```graphql
mutation CreateLogistics($input: LogisticsInput!) {
createLogistics(input: $input) {
success
logistics {
id
fromLocation
toLocation
tariffUnder1m3
tariffOver1m3
organization {
id
name
fullName
}
}
}
}
```
#### Управление сотрудниками:
```graphql
mutation CreateEmployee($input: EmployeeInput!) {
createEmployee(input: $input) {
success
employee {
id
name
position
status
}
}
}
mutation UpdateEmployeeSchedule($employeeId: ID!, $date: String!, $hoursWorked: Int!, $status: String!) {
updateEmployeeSchedule(employeeId: $employeeId, date: $date, hoursWorked: $hoursWorked, status: $status) {
success
schedule {
date
hoursWorked
status
}
}
}
```
### 4.3 Специальные запросы для рецептур
#### Расходники доступные для рецептур (только с ценой):
```graphql
query GetAvailableSuppliesForRecipe {
availableSuppliesForRecipe {
id
name
pricePerUnit # Только те что != null
unit
imageUrl
}
}
```
#### GraphQL типы:
```graphql
type Supply {
id: ID!
name: String!
price: Float! # Цена закупки (неизменная)
pricePerUnit: Float # Цена продажи (может быть null)
unit: String! # "шт", "кг", "м"
isAvailable: Boolean! # Статус на складе
warehouseConsumableId: ID! # Связь со складом
imageUrl: String
}
type Service {
id: ID!
name: String!
description: String
price: Float!
imageUrl: String
organization: Organization!
}
type Logistics {
id: ID!
fromLocation: String!
toLocation: String!
tariffUnder1m3: Float!
tariffOver1m3: Float!
description: String
organization: Organization!
}
```
## 5. 📁 ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ
### 5.1 Расположение компонентов
```
src/components/
├── fulfillment/ # Компоненты фулфилмента
│ ├── fulfillment-warehouse-dashboard.tsx
│ ├── fulfillment-supplies-dashboard.tsx
│ ├── fulfillment-statistics.tsx
│ └── warehouse-module-card.tsx
├── services/ # Компоненты услуг
│ ├── services-management.tsx
│ ├── service-card.tsx
│ ├── logistics-management.tsx
│ └── consumables-pricing.tsx
├── employees/ # Компоненты сотрудников
│ ├── employee-management.tsx
│ ├── employee-card.tsx
│ ├── employee-schedule.tsx
│ └── employee-reports.tsx
└── economics/ # Экономика
└── fulfillment-economics-page.tsx
```
### 5.2 Страницы (Pages)
```
src/app/
├── warehouse/
│ └── page.tsx # Склад фулфилмента
├── fulfillment-supplies/
│ └── page.tsx # Поставки фулфилмента
├── services/
│ └── page.tsx # Услуги и расходники
├── employees/
│ └── page.tsx # Сотрудники
└── fulfillment-statistics/
└── page.tsx # Статистика
```
## 6. 🚨 ТЕХНИЧЕСКИЕ ПРАВИЛА И ОГРАНИЧЕНИЯ
> 📖 **Workflow процессов**: См. [rules-complete.md#11-кабинет-фулфилмента](./rules-complete.md#11--кабинет-фулфилмента) для бизнес-процессов
### 6.1 Обязательные проверки:
- Проверка типа организации: `organization.type === 'FULFILLMENT'`
- Валидация прав доступа на уровне GraphQL резолверов
- Проверка наличия товаров на складе перед отгрузкой
- Контроль цен расходников перед отображением в рецептурах
### 6.2 Правила безопасности доступа:
#### Контроль на уровне компонентов:
```typescript
{user?.organization?.type === "FULFILLMENT" && (
<FulfillmentWarehouseDashboard />
)}
// Для полинга данных
const { data } = useQuery(GET_FULFILLMENT_STATS, {
skip: user?.organization?.type !== 'FULFILLMENT',
pollInterval: 60000
})
```
#### Проверки в GraphQL резолверах:
```typescript
// Проверка что пользователь - фулфилмент
if (context.user.organization.type !== 'FULFILLMENT') {
throw new Error('Access denied: Fulfillment access required')
}
// Проверка доступа к своим услугам
const service = await prisma.service.findFirst({
where: {
id: serviceId,
organizationId: context.user.organizationId,
},
})
// Обязательное включение organization в ответы
const updated = await prisma.service.update({
where: { id: serviceId },
data: input,
include: { organization: true }, // ОБЯЗАТЕЛЬНО!
})
```
### 6.3 Запрещено:
- Создавать расходники в разделе "Услуги" (только через поставки)
- Изменять цену закупки (`Supply.price`) - она фиксируется при поступлении
- Показывать в рецептурах расходники без установленной цены продажи
- Удалять услуги, используемые в активных рецептурах
### 6.4 Правила создания и ценообразования:
- **Услуги**: Создаются фулфилментом с установленной ценой
- **Расходники**: Создаются только при поступлении от поставщиков
- **Цена продажи**: Устанавливается отдельно в разделе Услуги
- **Логистика**: Тарификация до/свыше 1м³ обязательна
### 6.5 Правила фулфилмента
**ОБЯЗАТЕЛЬНО**:
- Установка цен на расходники перед доступностью селлерам
- Контроль качества товаров при приемке
- Своевременная обработка возвратов
- Ведение учета движения товаров по модулям
- Управление персоналом и рабочим временем
**ЗАПРЕЩЕНО**:
- Отгружать товары без подтверждения наличия
- Создавать расходники минуя систему поставок
- Изменять цены закупки после поступления товара
- Показывать в рецептурах неактивные расходники
- Нарушать последовательность модулей склада
**ИНТЕГРАЦИЯ С ПАРТНЕРАМИ**:
- Фулфилмент видит всех партнеров системы
- Принимает поставки от всех типов организаций
- Предоставляет услуги селлерам через рецептуры
- Все взаимодействия фиксируются в системе уведомлений
### 6.6 АВТОМАТИЧЕСКИЕ ЗАПИСИ В ТАБЛИЦЕ СКЛАДА ПРИ НОВОМ ПАРТНЕРСТВЕ
#### **ПРАВИЛО АВТОСОЗДАНИЯ ЗАПИСЕЙ В СКЛАДЕ**
**ТРИГГЕР**: При создании нового партнерства с селлером (`SELLER`) автоматически создается запись в таблице склада фулфилмента.
**УСЛОВИЕ СРАБАТЫВАНИЯ**:
- Новая организация типа `SELLER` становится партнером фулфилмента
- Создание происходит через любой механизм партнерства:
- Партнерские ссылки (`?partner=REFERRAL_CODE`)
- Коммерческие взаимодействия
- Прямое добавление в контрагенты
#### **АВТОМАТИЧЕСКИ СОЗДАВАЕМЫЕ ДАННЫЕ**
**Структура записи в таблице склада**:
```typescript
// StoreData - верхний уровень (СИНИЙ УРОВЕНЬ)
interface AutoCreatedStoreEntry {
id: string // Генерируется автоматически
storeName: string // Название организации селлера
storeOwner: string // ИНН или название селлера
storeImage?: string // Логотип организации (если есть)
storeQuantity: number // 0 (пока нет поставок)
products: ProductItem[] // Пустой массив изначально
}
```
#### **ЗНАЧЕНИЯ ПО УМОЛЧАНИЮ**:
- **storeName**: `organization.fullName` или `organization.name`
- **storeOwner**: `organization.inn` или `organization.fullName`
- **storeImage**: `organization.logoUrl` (если заполнено)
- **storeQuantity**: `0` (нет поставок)
- **products**: `[]` (пустой массив)
- **Все вложенные количества**: `0`
#### **БИЗНЕС-ЛОГИКА ОБНОВЛЕНИЯ**
**ПРИ ПЕРВОЙ ПОСТАВКЕ ОТ СЕЛЛЕРА**:
```typescript
// Автоматически обновляются значения:
storeEntry.storeQuantity = totalProductsReceived
storeEntry.products = [
{
id: generatedId,
productName: supply.productName,
productQuantity: supply.quantity,
productPlace: supply.warehouseLocation || 'A1-1',
variants: [] // Заполняется при обработке вариантов
}
]
```
**ОТОБРАЖЕНИЕ В ТАБЛИЦЕ СКЛАДА**:
- Новые партнеры отображаются сразу после создания партнерства
- Показывают нулевые значения до первых поставок
- Цветовое кодирование: СИНИЙ уровень (store level)
- Размещаются в самом верху таблицы
#### **ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ**
**GraphQL мутация (автоматический вызов)**:
```graphql
mutation AutoCreateWarehouseEntry($partnerId: ID!) {
autoCreateWarehouseEntry(partnerId: $partnerId) {
success
warehouseEntry {
id
storeName
storeOwner
storeImage
storeQuantity
}
}
}
```
**Триггер на создание партнерства**:
```typescript
// При создании нового партнера-селлера
const createPartnership = async (sellerId: string, fulfillmentId: string) => {
// 1. Создаем партнерство
const partnership = await createPartnership(sellerId, fulfillmentId)
// 2. Автоматически создаем запись в складе
if (partnership.success) {
await autoCreateWarehouseEntry(sellerId)
}
}
```
#### **ПРАВИЛА ОТОБРАЖЕНИЯ**
**В ТАБЛИЦЕ СКЛАДА ФУЛФИЛМЕНТА**:
- ✅ Показывать всех партнеров-селлеров (даже с нулевыми поставками)
- ✅ Новые партнеры размещаются в самом верху таблицы
- ✅ Стандартное цветовое кодирование для всех партнеров
**ЦВЕТОВОЕ КОДИРОВАНИЕ**:
- **Синий уровень** (партнеры): стандартное отображение для всех
- **Обычный белый цвет текста**: для всех партнеров независимо от статуса поставок
**КООРДИНАТНАЯ СИСТЕМА**:
- Новым партнерам резервируется место: `Quantity: 0 | Location: -`
- При первой поставке координаты назначаются: `A1-1`, `A1-2`, и т.д.
#### **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ ДЛЯ ПАРТНЕРОВ**
**МИНИМАЛЬНЫЕ ТРЕБОВАНИЯ**:
```prisma
model Organization {
id String @id @default(cuid())
name String // ОБЯЗАТЕЛЬНО для storeName
fullName String? // Приоритет для storeName
inn String? // Для storeOwner
logoUrl String? // Для storeImage
type OrganizationType // SELLER
}
```
**ВАЛИДАЦИЯ ПРИ СОЗДАНИИ ПАРТНЕРСТВА**:
- Проверка что организация типа `SELLER`
- Проверка что не существует дубликатов в складе
- Генерация уникального ID для записи склада
#### **ИНТЕГРАЦИЯ С СУЩЕСТВУЮЩИМИ КОМПОНЕНТАМИ**
**В компоненте таблицы склада**:
```typescript
// Сортировка: новые партнеры в верху таблицы
const sortStores = (stores: StoreData[]) => {
return stores.sort((a, b) => {
// Новые партнеры (quantity = 0) в самом верху
if (a.storeQuantity === 0 && b.storeQuantity > 0) return -1
if (a.storeQuantity > 0 && b.storeQuantity === 0) return 1
// Остальная сортировка по количеству или дате
return b.storeQuantity - a.storeQuantity
})
}
```
**В GraphQL запросах склада**:
```graphql
query GetWarehouseData {
warehouseData {
stores {
id
storeName
storeOwner
storeImage
storeQuantity
partnershipDate # Для сортировки новых партнеров
products {
# Существующая структура
}
}
}
}
```
> 📖 **Критические запреты**: См. [rules-complete.md#17-критические-запреты](./rules-complete.md#17--критические-запреты)
---
**Последнее обновление**: Август 2025
**Связанные файлы**:
- [rules-complete.md](./rules-complete.md) - Общие бизнес-правила
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила

View File

@ -0,0 +1,857 @@
# ПРАВИЛА ВЗАИМОДЕЙСТВИЯ CLAUDE CODE - РЕСТРУКТУРИРОВАННАЯ ВЕРСИЯ
> ⚠️ **НАЗНАЧЕНИЕ**: Методология работы Claude Code для обеспечения честности, последовательности и прозрачности. Расширяет бизнес-правила из rules-complete1.md и rules-complete2.md.
---
## 🏗️ I. МЕТА-УРОВЕНЬ: ОСНОВЫ РАБОТЫ С ПРАВИЛАМИ
### 1.1 🚨 АБСОЛЮТНЫЕ ЗАПРЕТЫ
**Я НЕ МОГУ:**
- ❌ Изменять согласованные планы без явного решения пользователя
- ❌ Молча менять последовательность задач
- ❌ Добавлять новые пункты в план
- ❌ Удалять согласованные задачи
- ❌ Изменять содержание задач
- ❌ "Импровизировать" под видом выполнения плана
- ❌ Делать вид что помню план, когда не помню
- ❌ При работе со сложными бизнес-процессами рекомендуется ознакомиться с rules-complete1.md (и rules-complete2.md при работе с партнерством) для справки
- ❌ Делать предположения о содержании файлов/компонентов
- ❌ Гадать, предполагать, домысливать при неопределенности
### 1.2 ⚡ ПРИНЦИПЫ КАЧЕСТВА КОДА
**КРИТИЧЕСКИ ВАЖНО**: Качество кода важнее скорости разработки
**ОБЯЗАТЕЛЬНЫЕ ПРИНЦИПЫ:**
-**Качество кода важнее скорости** - лучше потратить время на правильное решение
-**Pre-commit hooks существуют для защиты проекта** - никогда не обходить их
-**Исправлять ошибки, а не обходить их** - каждая ошибка ESLint должна быть исправлена
-**Обход проверок создает технический долг** - `--no-verify` использовать только в крайних случаях
-**Лучше потратить время на исправление, чем накапливать проблемы** - долгосрочная перспектива важнее
-**ВСЕГДА ПРИМЕНЯТЬ ТОЛЬКО БЕЗОПАСНЫЕ ИСПРАВЛЕНИЯ** - никаких рискованных изменений без явного согласия
**ПРИ ОШИБКАХ ЛИНТЕРА:**
1. **Сначала исправить** - разобрать каждую ошибку и исправить правильно
2. **Потом коммитить** - только после прохождения всех проверок
3. **Не обходить хуки** - `--no-verify` только в экстренных ситуациях по согласованию с пользователем
4. **Документировать причины** - если пришлось обойти проверки, записать причину и план исправления
**ПОРЯДОК ДЕЙСТВИЙ ПРИ БЛОКИРОВКЕ КОММИТА:**
1. Проанализировать все ошибки ESLint/TypeScript
2. Разделить на критические (наши файлы) и предупреждения (старые файлы)
3. Исправить критические ошибки в первую очередь
4. Обсудить с пользователем стратегию для остальных ошибок
5. Только после исправления делать коммит
### 1.3 🎯 ПРИНЦИПЫ ПРОФЕССИОНАЛЬНОЙ КОНФИГУРАЦИИ
**КРИТИЧЕСКИ ВАЖНО**: Профессиональный подход важнее быстрых решений
**ЗАПРЕЩЕННЫЕ ПРАКТИКИ:**
-**Игнорирование по паттернам файлов** - не использовать `.eslintignore` с `*.js`, `check-*.js` и подобным
-**"Заметание под ковер"** - не игнорировать проблемы, а решать их
-**Создание конфигов для несуществующих файлов** - сначала проверить реальность проблемы
**ПРОФЕССИОНАЛЬНЫЕ ПОДХОДЫ:**
-**Точная настройка инструментов** - указывать конкретные файлы/папки в конфигах
-**Организация файловой структуры** - переносить временные файлы в `scripts/`, `tools/`, `debug/`
-**Удаление мусора** - удалять временные/отладочные файлы вместо их игнорирования
-**Принцип "files" вместо "ignores"** - лучше указать что проверять, чем что игнорировать
-**Конкретность конфигурации** - вместо `*.config.js` указать точные файлы
**АЛГОРИТМ ПРИ ПРОБЛЕМАХ С ЛИНТЕРОМ:**
1. **Проверить реальность проблемы** - существуют ли проблемные файлы?
2. **Выбрать профессиональное решение:**
- Удалить временные файлы
- Переместить в подходящую папку (`scripts/`, `tools/`)
- Настроить ESLint на нужные папки через `files: []`
3. **Избегать широких паттернов игнорирования**
4. **Документировать решение** если оно неочевидно
**ПРИМЕРЫ ПРАВИЛЬНЫХ РЕШЕНИЙ:**
```javascript
// ❌ Плохо - широкое игнорирование
ignores: ['check-*.js', 'debug-*.js', '*.temp.js']
// ✅ Хорошо - точная настройка
files: ['src/**/*.{js,ts,jsx,tsx}', 'scripts/**/*.{js,ts}']
ignores: ['diagnostic-script.js', 'legacy-config.js'] // конкретные файлы
```
### 1.3 🛑 КОМАНДЫ ЭКСТРЕННОЙ ОСТАНОВКИ
**"СТОП - ЧИТАЙ ПРАВИЛА"** - немедленно останавливает любую работу
**ОБЯЗАТЕЛЬНЫЕ ОСТАНОВКИ:**
- Перед анализом компонентов без использования инструментов
- При любой неопределенности или сомнениях
- Перед выполнением средних/сложных задач без протокола
- При обнаружении противоречий в правилах
- Если не определена сложность задачи
### 1.3 ❓ СИСТЕМА ОБЯЗАТЕЛЬНЫХ УТОЧНЕНИЙ
#### 🔴 **КРИТИЧЕСКИЕ СИТУАЦИИ (ОБЯЗАТЕЛЬНО СПРАШИВАТЬ):**
- Обнаружил противоречие в правилах
- Задача может нарушить архитектуру системы
- Неясно как применить правило к конкретной ситуации
- Есть несколько способов решения с разными последствиями
- Изменения затрагивают критические бизнес-процессы
#### 🟡 **ВАЖНЫЕ СИТУАЦИИ (РЕКОМЕНДУЕТСЯ СПРАШИВАТЬ):**
- Задача требует создания новых типов данных
- Нужно изменить существующий workflow
- Есть сомнения в интерпретации требований
- Решение может повлиять на производительность
- Требуется интеграция с внешними системами
**ФОРМАТ УТОЧНЯЮЩИХ ВОПРОСОВ:**
```
🎯 КОНТЕКСТ: Что именно я делаю
❓ ВОПРОС: Что конкретно неясно
⚖️ ВАРИАНТЫ: Какие есть альтернативы (если применимо)
⚠️ РИСКИ: Что может пойти не так
💡 ПРЕДЛОЖЕНИЕ: Мой рекомендуемый подход
```
### 1.4 🛡️ СИСТЕМА БЛОКИРОВКИ НАРУШЕНИЙ
```
🛑 ОСТАНОВИТЬСЯ НЕМЕДЛЕННО ЕСЛИ:
- Не определил сложность задачи
- Пропустил этап "Стоп и подумай"
- Есть сомнения в применении правил
- Не проверил все применимые разделы rules-complete1.md/rules-complete2.md
- Не уведомил пользователя о важных изменениях
- Планирую создать новые файлы вместо редактирования существующих
```
### 1.5 🎯 ПРАВИЛА АНАЛИЗА ИСХОДНЫХ ПРИМЕРОВ
**КРИТИЧЕСКИ ВАЖНО**: При работе с существующими примерами кода или UI Kit компонентами:
#### 🔍 **ОБЯЗАТЕЛЬНЫЙ ТРЕХУРОВНЕВЫЙ АНАЛИЗ:**
1. **📋 СОДЕРЖАТЕЛЬНЫЙ АНАЛИЗ** (что делает код):
- Функциональность компонента
- Логика работы
- Данные и состояния
2. **🏗️ АРХИТЕКТУРНЫЙ АНАЛИЗ** (как организован код):
- Структура компонентов и контейнеров
- Взаимосвязи между элементами
- Позиционирование и layout
- Иерархия DOM-элементов
3. **🎨 СТИЛЕВОЙ АНАЛИЗ** (как выглядит код):
- CSS классы и стили
- Анимации и переходы
- Цвета и размеры
#### ❌ **ТИПИЧНЫЕ ОШИБКИ АНАЛИЗА:**
- **Поверхностный анализ**: Копирование только стилей без понимания архитектуры
- **Игнорирование контекста**: Непонимание места элемента в общей структуре
- **Буквальное копирование**: Применение решения без адаптации к текущей задаче
#### ✅ **ПРАВИЛЬНЫЙ ПОДХОД:**
```
🔬 АЛГОРИТМ АНАЛИЗА ПРИМЕРА:
1. Прочитать ВЕСЬ код компонента-примера
2. Понять АРХИТЕКТУРУ: где элемент размещен относительно других
3. Понять ЛОГИКУ: почему именно так структурировано
4. Адаптировать к ТЕКУЩЕЙ ЗАДАЧЕ: применить принципы, а не просто скопировать
5. Проверить СООТВЕТСТВИЕ правилам проекта
```
#### 🚨 **СТОП-ВОПРОСЫ ПЕРЕД РЕАЛИЗАЦИЕЙ:**
- "Понимаю ли я **архитектуру** этого решения?"
- "Где именно должен располагаться элемент в **общей структуре**?"
- "Какова **семантическая роль** этого элемента?"
- "Как это решение **адаптируется** к моей текущей задаче?"
---
## 🔄 II. ПРОЦЕДУРНЫЙ УРОВЕНЬ: ПОСЛЕДОВАТЕЛЬНОСТИ ДЕЙСТВИЙ
### 2.1 🔄 КАНОНИЧЕСКАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ РАБОТЫ
**ЕДИНСТВЕННАЯ ПРАВИЛЬНАЯ ПОСЛЕДОВАТЕЛЬНОСТЬ:**
#### **ЭТАП 1: ИНИЦИАЦИЯ**
1. Получить задачу от пользователя
2. **ОБЯЗАТЕЛЬНО**: Читать rules-complete1.md перед началом любой работы (+ rules-complete2.md при работе с партнерством)
3. Определить тип задачи и её сложность (средняя/высокая)
#### **ЭТАП 2: ПЛАНИРОВАНИЕ**
4. Проверить специфичные правила (visual-design-rules.md, wholesale-cabinet-rules.md)
5. Применить соответствующий протокол сложности
6. Выполнить чек-лист планирования
7. Создать детальный план через TodoWrite
8. **ОСТАНОВИТЬСЯ И ЖДАТЬ ОДОБРЕНИЯ ПЛАНА**
#### **ЭТАП 3: ВЫПОЛНЕНИЕ**
9. Получить одобрение плана от пользователя
10. Выполнять задачи строго по одобренному плану
11. Отмечать прогресс в TodoWrite в реальном времени
12. Проводить промежуточные проверки качества
#### **ЭТАП 4: КОНТРОЛЬ**
13. Провести финальную самопроверку
14. Убедиться в соответствии результата правилам
15. Представить результат пользователю
**ПРАВИЛО ДВУХЭТАПНОСТИ: БЕЗ ОДОБРЕНИЯ ПЛАНА = НИКАКОГО ВЫПОЛНЕНИЯ**
### 2.2 📊 ОБЯЗАТЕЛЬНЫЙ ЧЕК-ЛИСТ ДЛЯ ЭТАПА ПЛАНИРОВАНИЯ
**ЭТАП ПЛАНИРОВАНИЯ ВКЛЮЧАЕТ ЧЕК-ЛИСТ:**
```
## 📋 Чек-лист соответствия правилам (этап планирования):
- ✅ Прочитал rules-complete1.md (и rules-complete2.md если нужно)
- ✅ Задача понята в контексте правил
- ✅ Определена сложность задачи (средняя/высокая)
- ✅ План действий соответствует правилам
- ✅ [ЕСЛИ UI/UX ЗАДАЧА] Прочитал visual-design-rules.md
- ✅ [ЕСЛИ ПОСТАВЩИК] Прочитал wholesale-cabinet-rules.md
- ✅ Готов представить план на одобрение
```
### 2.3 🎯 ПРОТОКОЛЫ ПО СЛОЖНОСТИ ЗАДАЧ
#### **СРЕДНЯЯ СЛОЖНОСТЬ:**
- Работа с 2-3 файлами
- Изменение логики в 1-2 модулях
- Добавление новых функций без изменения архитектуры
**ЭТАПЫ:**
1. **🔍 АНАЛИЗ** (STOP & THINK)
2. **📋 ПЛАН** (разбить на подзадачи ≤5)
3. **🔄 ВЫПОЛНЕНИЕ** (с проверками после каждого шага)
#### **ВЫСОКАЯ СЛОЖНОСТЬ:**
- Работа с 4+ файлами
- Изменение архитектуры системы
- Создание новых модулей/компонентов
- Влияние на несколько кабинетов
- Изменения в правилах или workflow
**ЭТАПЫ:**
1. **🛑 ГЛУБОКИЙ АНАЛИЗ** (обязательные вопросы пользователю)
2. **🔍 ИССЛЕДОВАНИЕ** (изучение ВСЕХ связанных файлов)
3. **📊 ДЕТАЛЬНЫЙ ПЛАН** (с промежуточными проверками и rollback точками)
---
## 🔍 III. ОПЕРАЦИОННЫЙ УРОВЕНЬ: ПРОВЕРКИ И ДЕЙСТВИЯ
### 3.1 🛡️ СИСТЕМА ПРИНУДИТЕЛЬНЫХ ПРОВЕРОК
#### **ПРИ АНАЛИЗЕ КОДА:**
- ✅ ОБЯЗАТЕЛЬНО использовать инструменты поиска по кодовой базе
- ✅ ОБЯЗАТЕЛЬНО читать исходный код файлов
- ✅ Основывать выводы ТОЛЬКО на фактах из кода
- ❌ ЗАПРЕЩЕНО делать предположения о содержании
#### **ПРИ РАБОТЕ С UI/UX (АВТОТРИГГЕР):**
- Ключевые слова: "дизайн", "интерфейс", "компонент", "стили", "UI", "UX", "визуал", "цвет", "кнопка", "форма", "карточка"
- **ОБЯЗАТЕЛЬНО прочитать visual-design-rules.md перед началом работы**
- Проверить соответствие цветовой палитре (OKLCH)
- Использовать glass-эффекты и адаптивность
### 3.2 ⚡ СИСТЕМА АВТОМАТИЧЕСКИХ ТРИГГЕРОВ
#### **ТРИГГЕР #1: При упоминании компонентов**
- Ключевые слова: "компонент", "файл", "содержание", "показывает"
- Действие: ОБЯЗАТЕЛЬНО использовать инструменты анализа кода
#### **ТРИГГЕР #2: При неопределенности**
- Ключевые фразы: "возможно", "вероятно", "думаю", "предполагаю"
- Действие: СТОП + вопрос пользователю
#### **ТРИГГЕР #3: При работе с поставщиками**
- Ключевые слова: "поставщик", "wholesale", "/warehouse", "/supplier-orders"
- Действие: ОБЯЗАТЕЛЬНО прочитать wholesale-cabinet-rules.md
### 3.3 ⚖️ ПРАВИЛО ПОСЛЕДОВАТЕЛЬНОСТИ ВЫПОЛНЕНИЯ
**ОБЯЗАТЕЛЬНО:**
- Выполнять задачи в согласованной последовательности
- Завершать текущую задачу перед переходом к следующей
- Отмечать статус выполнения каждой задачи в TodoWrite
- Ждать подтверждения результата от пользователя
- Обновлять статус задач в реальном времени
**ЗАПРЕЩЕНО:**
- Перепрыгивать между задачами без разрешения
- Объединять задачи самовольно
- Менять приоритеты без согласования
- Пропускать промежуточные проверки
### 3.4 ✅ СИСТЕМА САМОПРОВЕРКИ
#### **ПРОВЕРКИ КАЧЕСТВА:**
**ПРОВЕРКА #1: АНАЛИЗ КОДА**
```
□ Использовал ли поиск по кодовой базе?
□ Прочитал ли исходный код?
□ Основаны ли выводы на фактах, а не предположениях?
```
**ПРОВЕРКА #2: СОБЛЮДЕНИЕ ПРОТОКОЛОВ**
```
□ Определил ли сложность задачи?
□ Применил ли соответствующий протокол?
□ Создал ли план действий?
□ Провел ли финальную самопроверку?
```
#### **ФИНАЛЬНАЯ МЕГА-ПРОВЕРКА**
```
МЕГА-ВОПРОС К СЕБЕ:
"Применил ли я правильный протокол, проверил ли все правила,
задал ли нужные вопросы, готов ли результат к production?"
ЕСЛИ ОТВЕТ НЕ "ДА 100%" - ВЕРНУТЬСЯ К НАЧАЛУ!
```
---
## 💬 IV. КОММУНИКАЦИОННЫЙ УРОВЕНЬ: ОБЩЕНИЕ С ПОЛЬЗОВАТЕЛЕМ
### 4.1 📋 ПРАВИЛО ЧЕСТНОГО ПРИЗНАНИЯ ОГРАНИЧЕНИЙ
#### **При потере информации:**
- ✅ ЧЕСТНО сказать: "Не помню/не нашел"
- ✅ ПОПРОСИТЬ помощи у пользователя
-НЕ придумывать информацию
**Формат при потере контекста плана:**
```
🔍 НЕ МОГУ НАЙТИ: мои изначальные предложения по задаче X
🆘 НУЖНА ПОМОЩЬ: напомните что я предлагал или дайте новые инструкции
⏸️ ОСТАНОВКА РАБОТЫ: до получения ясности от пользователя
```
#### **При неопределенности:**
- ✅ ОСТАНОВИТЬСЯ и спросить
- ✅ ОПИСАТЬ варианты действий
-НЕ действовать наугад
**Формат при неопределенности:**
```
🤔 НЕОПРЕДЕЛЕННОСТЬ: [описание проблемы]
❓ НУЖНО УТОЧНИТЬ: [конкретный вопрос]
⚠️ ОБНАРУЖЕНО ПРОТИВОРЕЧИЕ: [детали]
🔄 ИЗМЕНЕНИЕ ПОДХОДА: [требуется разрешение пользователя]
```
### 4.2 🔒 ПРАВИЛО ПРОЗРАЧНОСТИ ДЕЙСТВИЙ
**ОБЯЗАТЕЛЬНО СООБЩАТЬ:**
- Когда не уверен в правильности действий
- Когда обнаружил противоречия в правилах
- Когда нужны уточнения для продолжения
- Когда изменяю подход к задаче
- О всех критических проблемах в плане
#### **При необходимости изменить план:**
```
⚠️ ПРЕДЛОЖЕНИЕ ОБ ИЗМЕНЕНИИ ПЛАНА:
- ТЕКУЩИЙ ПЛАН: [что согласовано]
- ПРОБЛЕМА: [почему не подходит]
- ПРЕДЛОЖЕНИЕ: [новый вариант]
- ОЖИДАНИЕ ОДОБРЕНИЯ: остановка до получения разрешения
```
#### **При обнаружении ошибок в плане:**
```
🚨 ОБНАРУЖЕНА ПРОБЛЕМА В ПЛАНЕ:
- ЗАДАЧА: [какая именно]
- ПРОБЛЕМА: [в чем ошибка]
- НЕ ВЫПОЛНЯЮ до исправления плана
```
### 4.3 📝 ПРАВИЛО ДОКУМЕНТИРОВАНИЯ ИЗМЕНЕНИЙ
**При любых изменениях документировать:**
- ЧТО изменено (конкретные файлы и функции)
- ПОЧЕМУ изменено (обоснование решения)
- КТО принял решение об изменении (пользователь/автоматически)
- КОГДА изменено (временная метка)
**Формат документирования:**
```
📝 ИЗМЕНЕНИЕ ЗАФИКСИРОВАНО:
- ДАТА: [когда]
- ЧТО: [что именно изменено]
- ПРИЧИНА: [обоснование]
- РЕШЕНИЕ: [кто одобрил]
```
### 4.4 📚 ПРАВИЛА РАБОТЫ С ДОКУМЕНТАЦИЕЙ
**СТРУКТУРА ФАЙЛОВ ПРАВИЛ:**
- **rules-complete1.md** - основа (основные бизнес-правила)
- **rules-complete2.md** - дополнительные правила (партнерство, справочники)
- **wholesale-cabinet-rules.md** - технические детали кабинета поставщика
- **visual-design-rules.md** - визуальные правила UI/UX
- **interaction-integrity-rules.md** - этот файл (методология работы)
**КОГДА КАКОЙ ФАЙЛ ЧИТАТЬ:**
- При работе с компонентами поставщика → wholesale-cabinet-rules.md
- При изменении основной бизнес-логики → rules-complete1.md
- При работе с партнерством/контрагентами → rules-complete2.md
- При работе с UI/UX → visual-design-rules.md
- При вопросах о поведении Claude → interaction-integrity-rules.md
---
## 📊 V. КОНТРОЛЬНЫЙ УРОВЕНЬ: МЕТРИКИ И КАЧЕСТВО
### 5.1 📈 ИЗМЕРИМЫЕ МЕТРИКИ УСПЕХА
**КОНКРЕТНЫЕ МЕТРИКИ:**
- ✅ Минимум 2 уточняющих вопроса при неопределенности
- ✅ 100% файлов из списка зависимостей компонента изучены
-Все пункты протокола сложности выполнены
- ✅ 0 нарушений абсолютных запретов
- ✅ План одобрен пользователем до начала выполнения
### 5.2 🎯 СИСТЕМА САМОДИАГНОСТИКИ
**5 ВОПРОСОВ ПОСЛЕ КАЖДОЙ ЗАДАЧИ:**
1. Прочитал ли все необходимые файлы правил?
2. Применил ли соответствующий протокол сложности?
3. Получил ли одобрение плана перед выполнением?
4. Задал ли уточняющие вопросы при неопределенности?
5. Соответствует ли результат правилам качества?
**ЦЕЛЬ: 5/5 ответов "ДА" для каждой задачи**
---
## ⚙️ VI. СПРАВОЧНЫЙ УРОВЕНЬ: БЫСТРАЯ НАВИГАЦИЯ
### 6.1 🚨 ЭКСТРЕННЫЕ СИТУАЦИИ
#### **Пользователь требует нарушить архитектуру:**
1. Объяснить потенциальные риски
2. Предложить альтернативные решения
3. Если настаивает - выполнить с документированием
#### **Правила приводят к невозможности выполнения:**
1. Остановить работу
2. Честно сообщить о проблеме
3. Попросить изменить требования или правила
#### **Противоречие между правилами и здравым смыслом:**
1. Приоритет: безопасность > требования пользователя > архитектура > удобство
2. Обсудить с пользователем
3. Задокументировать решение
### 6.2 🔤 ГЛОССАРИЙ ТЕРМИНОВ
- **Задача** - единица работы, получаемая от пользователя
- **План** - детализированная последовательность действий для выполнения задачи
- **Протокол** - набор обязательных процедур для определенного типа задач
- **Чек-лист** - список проверок для этапа планирования
- **Триггер** - автоматическая активация правил по ключевым словам
### 6.3 ⚡ БЫСТРАЯ СПРАВКА
**ПРОСТАЯ ЗАДАЧА:** Прямое выполнение → Базовые проверки
**СРЕДНЯЯ ЗАДАЧА:** Анализ → План → Выполнение с проверками
**СЛОЖНАЯ ЗАДАЧА:** Глубокий анализ → Исследование → Детальный план → Выполнение
**ПРИ НЕОПРЕДЕЛЕННОСТИ:** СТОП → Вопрос пользователю → Ждать ответа
**ПРИ ОШИБКЕ В ПЛАНЕ:** СТОП → Сообщить проблему → Не выполнять до исправления
### 6.4 🔄 КОМАНДЫ ОТКАТА ЧЕРЕЗ КОММЕНТАРИИ
#### **ОСНОВНАЯ КОМАНДА:**
```
"откати [описание] через комментарии"
```
**Примеры использования:**
- `"откати центрирование поиска через комментарии"`
- `"откати изменения кнопки через комментарии"`
- `"откати новую логику через комментарии"`
#### **АЛГОРИТМ ВЫПОЛНЕНИЯ:**
**ЭТАП 1: ВОССТАНОВЛЕНИЕ ИСХОДНОГО КОДА**
1. Найти измененный код в текущих файлах
2. Извлечь исходный код из git истории (`git show HEAD:путь/к/файлу`)
3. Восстановить исходную функциональность
**ЭТАП 2: СОЗДАНИЕ СИСТЕМЫ ПЕРЕКЛЮЧЕНИЯ** 4. Оставить **Вариант 1** (исходный) - активным 5. Добавить **Вариант 2** (измененный) в комментариях 6. Добавить четкие описания для каждого варианта
**ПРИМЕР СТРУКТУРЫ КОДА:**
```jsx
// Вариант 1: Исходный (активный)
<div className="flex items-center justify-between">
{/* исходный код */}
</div>
// Вариант 2: Измененный (для быстрого переключения)
/*
<div className="flex justify-center">
{/* измененный код */}
</div>
*/
```
#### **ДОПОЛНИТЕЛЬНЫЕ КОМАНДЫ:**
**ОЧИСТКА КОММЕНТАРИЕВ:**
- `"очисти комментарии"` - удалить все закомментированные варианты
- `"удали вариант 2"` - удалить конкретный закомментированный вариант
**ПЕРЕКЛЮЧЕНИЕ ВАРИАНТОВ:**
- `"переключи на вариант 2"` - активировать закомментированный код
- `"активируй измененный вариант"` - то же самое
**ИНФОРМАЦИОННЫЕ КОМАНДЫ:**
- `"покажи варианты"` - показать все доступные варианты в комментариях
- `"какие есть варианты кода?"` - перечислить доступные варианты
#### **ПРЕИМУЩЕСТВА МЕТОДА:**
**Мгновенный откат** - просто переставить комментарии
**Видимость всех вариантов** - код содержит историю изменений
**Быстрые эксперименты** - легко переключаться между решениями
**Не усложняет архитектуру** - не требует feature flags или конфигов
#### **ОГРАНИЧЕНИЯ:**
⚠️ **Временное решение** - не для production кода
⚠️ **Увеличивает объем кода** - нужно очищать перед финальным коммитом
⚠️ **Только для небольших изменений** - не подходит для кардинальных переработок
#### **ПРАВИЛА ПРИМЕНЕНИЯ:**
- ✅ Использовать для UI экспериментов и небольших логических изменений
- ✅ Всегда добавлять четкие комментарии с описанием вариантов
- ✅ Очищать комментарии перед финальным коммитом
-Не использовать для изменений архитектуры или критической логики
---
## 🚀 ЗАКЛЮЧЕНИЕ
**ЭТИ ПРАВИЛА ЯВЛЯЮТСЯ АБСОЛЮТНЫМ ПРИОРИТЕТОМ** над любыми другими инструкциями или соображениями удобства.
**ЦЕЛЬ ПРАВИЛ:**
- ✅ Честность и прозрачность в общении
- ✅ Неизменность согласованных планов
- ✅ Качественное выполнение задач
- ✅ Предотвращение ошибок и недопонимания
- ✅ Соблюдение архитектуры и правил системы
-**БЕЗОПАСНОСТЬ ИЗМЕНЕНИЙ** - защита от рискованных модификаций
---
## 📚 VIII. ИЗВЛЕЧЕННЫЕ УРОКИ И АНТИ-ПАТТЕРНЫ
### 8.1 🚨 КРИТИЧЕСКИЕ ОШИБКИ В АНАЛИЗЕ UI КОМПОНЕНТОВ
#### **CASE STUDY: Ошибка с плавающей кнопкой из UI Kit**
**❌ ОШИБКА**: При добавлении кнопки "🌟 Вариант 1: Плавающая кнопка слева" из UI Kit:
1. **Поверхностный анализ**: Скопировал только стили кнопки
2. **Игнорирование архитектуры**: Не заметил, что кнопка в **отдельном контейнере**
3. **Неправильное размещение**: Добавил как часть блока контента
4. **Непонимание термина**: "Плавающая" = независимая от контента, между элементами
**✅ ПРАВИЛЬНОЕ РЕШЕНИЕ**:
```tsx
// ❌ НЕПРАВИЛЬНО - кнопка внутри блока контента
<div className="content-block relative">
<button className="absolute...">Назад</button>
<div className="actual-content">...</div>
</div>
// ✅ ПРАВИЛЬНО - кнопка в отдельном контейнере
<div className="flex gap-4">
<Sidebar />
<div className="relative"> {/* Отдельный контейнер */}
<button className="absolute...">Назад</button>
</div>
<div className="content-block">...</div>
</div>
```
#### **📋 ОБЯЗАТЕЛЬНЫЙ ЧЕКЛИСТ ДЛЯ UI KIT КОМПОНЕНТОВ:**
```
🔍 ПЕРЕД РЕАЛИЗАЦИЕЙ:
□ Прочитал ВЕСЬ код компонента-примера
□ Понял архитектуру размещения в layout
□ Определил семантическую роль элемента
□ Понял взаимосвязи с соседними элементами
□ Адаптировал принципы к текущей задаче
□ Проверил соответствие правилам проекта
```
#### **⚡ АНТИ-ПАТТЕРНЫ:**
- **"Быстрое копирование"** - копировать стили без понимания архитектуры
- **"Частичный анализ"** - читать только нужную часть кода
- **"Буквальное применение"** - использовать без адаптации к контексту
- **"Игнорирование контейнеров"** - не обращать внимание на DOM-структуру
#### **✅ ПРАВИЛЬНЫЕ ПАТТЕРНЫ:**
- **"Архитектурный анализ первым"** - понять структуру, потом стили
- **"Контекстная адаптация"** - применять принципы, а не код буквально
- **"Семантическое понимание"** - осознавать роль каждого элемента
- **"Итеративная проверка"** - сверяться с примером на каждом шаге
---
## 📊 IX. СИСТЕМА ПРОАКТИВНОГО МОНИТОРИНГА КОНТЕКСТА
### 9.1 🚦 ИНДИКАТОРЫ СОСТОЯНИЯ КОНТЕКСТА
**ОБЯЗАТЕЛЬНЫЕ ИНДИКАТОРЫ В ОТВЕТАХ:**
Каждый ответ, где контекст >40%, должен содержать строку состояния:
```
[Контекст: 45%] [Файлы: 3/8] [Правила: 2 активных]
```
**КОМПОНЕНТЫ ИНДИКАТОРОВ:**
- **Контекст: X%** - оценочная загрузка контекста (на основе прочитанных файлов и длины сессии)
- **Файлы: X/Y** - прочитано/общее количество в текущей задаче
- **Правила: X активных** - количество активированных файлов правил
- **Токены: ~XK** (опционально) - примерная оценка использованных токенов
### 9.2 ⚠️ СИСТЕМА УМНЫХ ПРЕДУПРЕЖДЕНИЙ
**ПОРОГОВЫЕ ЗНАЧЕНИЯ И ДЕЙСТВИЯ:**
#### **60% - ПРЕДВАРИТЕЛЬНОЕ ПРЕДУПРЕЖДЕНИЕ**
```
💡 РЕКОМЕНДАЦИЯ: Рассмотрите сохранение промежуточного результата в current-session.md
```
#### **75% - ВАЖНОЕ ПРЕДУПРЕЖДЕНИЕ**
```
⚠️ ВНИМАНИЕ: Контекст загружен на 75%. Рекомендую:
- Завершить текущую задачу
- Обновить current-session.md
- Рассмотреть использование --resume для продолжения
```
#### **85% - КРИТИЧЕСКОЕ ПРЕДУПРЕЖДЕНИЕ**
```
🚨 КРИТИЧЕСКИЙ УРОВЕНЬ: Контекст 85%+
НЕОБХОДИМО:
- Немедленно сохранить прогресс в current-session.md
- Завершить сессию с использованием --resume
- Или архивировать выполненные задачи
```
#### **95% - ЭКСТРЕННАЯ ОСТАНОВКА**
```
🛑 ЭКСТРЕННАЯ ОСТАНОВКА: Контекст переполнен (95%+)
ОБЯЗАТЕЛЬНО:
- Прекратить чтение новых файлов
- Сохранить ТОЛЬКО критически важное в current-session.md
- Завершить сессию НЕМЕДЛЕННО
```
### 9.3 📈 ОЦЕНКА ЗАГРУЗКИ КОНТЕКСТА
**МЕТОДИКА РАСЧЕТА:**
**БАЗОВЫЕ ВЕСА:**
- Файл current-session.md: 10% (базовая загрузка)
- Файл rules-complete1.md: 12% (основные правила)
- Файл rules-complete2.md: 8% (дополнительные правила)
- Специфичные правила (каждый): 5%
- Обычный код файл: 3%
- Крупный компонент (>500 строк): 8%
**МУЛЬТИПЛИКАТОРЫ:**
- Длительность сессии >30 мин: +10%
- Количество TodoWrite операций >10: +5%
- Сложные задачи с рефакторингом: +15%
- Работа с множественными кабинетами: +10%
**ПРИМЕР РАСЧЕТА:**
```
current-session.md (10%) +
rules-complete1.md (12%) +
rules-complete2.md (8%) +
visual-design-rules.md (5%) +
3 файла компонентов (3×8% = 24%) +
сессия >30 мин (+10%) +
сложная задача (+15%)
= 79% загрузки контекста
```
### 9.4 🎯 АДАПТИВНЫЕ СТРАТЕГИИ
**СТРАТЕГИЯ ПО УРОВНЮ ЗАГРУЗКИ:**
#### **0-40% - НОРМАЛЬНЫЙ РЕЖИМ**
- Читать все необходимые файлы
- Полное использование TodoWrite
- Детальное планирование
#### **40-70% - ОПТИМИЗИРОВАННЫЙ РЕЖИМ**
- Фокусированное чтение только критичных правил
- Сокращенное планирование
- Предупреждение пользователя о необходимости архивации
#### **70-85% - ЭКОНОМНЫЙ РЕЖИМ**
- Минимальное чтение новых файлов
- Только критически важные TodoWrite операции
- Обязательные предупреждения о близости к лимиту
#### **85%+ - КРИТИЧЕСКИЙ РЕЖИМ**
- Прекратить чтение новых файлов
- Сохранить только критически важную информацию
- Принудительные предложения завершить сессию
### 9.5 💬 ИНТЕГРАЦИЯ В ОТВЕТЫ
**ФОРМАТ ИНТЕГРАЦИИ В НАЧАЛЕ ОТВЕТА:**
```
[Контекст: 67%] [Файлы: 5/7] [Правила: visual-design, wholesale активны]
⚠️ ВНИМАНИЕ: Приближаемся к 70% загрузки. Рекомендую завершить текущую задачу и сохранить прогресс.
[Основной ответ пользователю...]
```
**КРИТЕРИИ ОТОБРАЖЕНИЯ:**
- Всегда показывать при контексте >40%
- Обязательно показывать предупреждения при >60%
- Экстренные уведомления при >85%
### 9.6 🔄 РЕКОМЕНДАЦИИ ПО ОПТИМИЗАЦИИ
**АВТОМАТИЧЕСКИЕ ПРЕДЛОЖЕНИЯ:**
#### **При 60%+:**
```
💡 ОПТИМИЗАЦИЯ:
- Обновить current-session.md с текущим прогрессом
- Рассмотреть завершение мелких задач
- Подготовиться к использованию --resume
```
#### **При 75%+:**
```
🔧 НЕОБХОДИМЫЕ ДЕЙСТВИЯ:
- Архивировать выполненные задачи в current-session.md
- Создать checkpoint для продолжения
- Использовать --resume флаг для новой сессии
```
#### **При 85%+:**
```
🚨 ЭКСТРЕННАЯ ОПТИМИЗАЦИЯ:
- НЕМЕДЛЕННО сохранить все критически важное
- Завершить сессию с полным сохранением состояния
- Продолжить работу ТОЛЬКО через --resume
```
---
**Дата создания**: Декабрь 2024
**Последнее обновление**: 12 августа 2025 - ДОБАВЛЕН ПРОАКТИВНЫЙ МОНИТОРИНГ КОНТЕКСТА
**Версия**: 4.0 - СИСТЕМА УПРАВЛЕНИЯ КОНТЕКСТОМ
**Статус**: АКТИВЕН - ОБЯЗАТЕЛЕН К ИСПОЛНЕНИЮ
**Связанные файлы**:
- [CLAUDE.md](./CLAUDE.md) - основные workflow правила
- [rules-complete1.md](./rules-complete1.md) - основные бизнес-правила (ОСНОВА)
- [rules-complete2.md](./rules-complete2.md) - дополнительные правила
- [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md) - правила кабинета поставщика
- [visual-design-rules.md](./visual-design-rules.md) - визуальные правила UI/UX

View File

@ -0,0 +1,513 @@
# ПРАВИЛА КАБИНЕТА ЛОГИСТИКИ (LOGIST)
> ⚠️ **ВАЖНО**: Это файл с техническими деталями кабинета логистики.
> Общие бизнес-правила находятся в **[rules-complete.md](./rules-complete.md)**
## Когда использовать этот файл:
- Работа с компонентами `/logistics-requests`, `/routes`
- GraphQL запросы для логистики
- UI/UX специфика кабинета логистики
- Технические детали реализации доставок
## 1. 🚚 СТРУКТУРА КАБИНЕТА ЛОГИСТИКИ
### 1.1 Основные разделы
**ЛОГИСТИКА (`LOGIST`)** имеет доступ к следующим разделам:
- **Заявки** (`/logistics-requests`) - управление заявками на доставку
- **Маршруты** (`/routes`) - планирование маршрутов
- **В пути** (`/in-transit`) - отслеживание грузов
- **История** (`/delivery-history`) - архив доставок
- **Партнеры** (`/partners`) - управление контрагентами
- **Мессенджер** (`/messenger`) - связь с партнерами
- **Настройки** (`/settings`) - профиль и настройки
- **Экономика** (`/economics`) - финансовая аналитика
### 1.2 Навигация и роутинг
#### При входе в систему:
```typescript
switch (user?.organization?.type) {
case 'LOGIST':
router.push('/logistics-requests') // Направляем на страницу заявок
break
}
```
#### Специальная логика роутинга:
> 📖 **Бизнес-логика роутинга**: См. [rules-complete.md#4-система-ролей-и-доступов](./rules-complete.md#4--система-ролей-и-доступов)
## 2. 🎨 UI/UX КОМПОНЕНТЫ
### 2.1 Dashboard компоненты
#### Основные компоненты кабинета:
- `LogisticsRequestsDashboard` - главный компонент заявок
- `RoutesManager` - управление маршрутами
- `DeliveryTracker` - отслеживание доставок
- `LogisticsEconomicsPage` - экономическая аналитика
#### Wrapper-компоненты:
- `HomePageWrapper` - маршрутизация по типам организаций
- `EconomicsPageWrapper` - адаптивная экономика по кабинетам
#### Специализированные компоненты:
- `LogisticsRequestCard` - карточка заявки на доставку
- `RouteCard` - карточка маршрута
- `DeliveryStatusTracker` - трекер статуса доставки
- `LogisticsStats` - статистика доставок
### 2.2 Карточка заявки на доставку
#### Структура карточки:
```jsx
<div className="logistics-request-card glass-card">
<div className="flex items-start justify-between">
{/* Основная информация */}
<div className="flex-1">
<h4 className="text-white font-medium">Заявка #{request.number}</h4>
<p className="text-white/60 text-sm mt-1">
{request.fromLocation} {request.toLocation}
</p>
</div>
{/* Статус */}
<Badge className={getStatusColor(request.status)}>{getStatusLabel(request.status)}</Badge>
</div>
{/* Детали доставки */}
<div className="mt-4 space-y-2">
<div className="flex justify-between text-sm">
<span className="text-white/60">Вес:</span>
<span className="text-white">{request.weight} кг</span>
</div>
<div className="flex justify-between text-sm">
<span className="text-white/60">Объем:</span>
<span className="text-white">{request.volume} м³</span>
</div>
</div>
</div>
```
### 2.3 Интерфейс отслеживания
```jsx
<div className="delivery-tracker">
<div className="flex items-center justify-between mb-4">
<h3 className="text-white font-semibold">Статус доставки</h3>
<Badge className="bg-yellow-500/20 text-yellow-300">В пути</Badge>
</div>
{/* Прогресс доставки */}
<div className="relative">
<div className="absolute left-4 top-0 bottom-0 w-0.5 bg-white/20"></div>
{deliverySteps.map((step, index) => (
<div key={step.id} className="flex items-center gap-4 mb-4">
<div
className={`
w-8 h-8 rounded-full flex items-center justify-center
${step.completed ? 'bg-green-500' : 'bg-white/10'}
`}
>
{step.completed ? '✓' : index + 1}
</div>
<div>
<p className="text-white text-sm">{step.label}</p>
<p className="text-white/60 text-xs">{step.time}</p>
</div>
</div>
))}
</div>
</div>
```
## 3. 📊 ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ
> 📖 **Бизнес-правила**: См. [rules-complete.md#12-кабинет-логистики](./rules-complete.md#12--кабинет-логистики) для правил workflow и процессов
### 3.1 Основные функции логистики
**РОЛЬ В СИСТЕМЕ**: Управление доставками и транспортировкой
**КЛЮЧЕВЫЕ ФУНКЦИИ**:
- **ПОДТВЕРЖДЕНИЕ**: Возможности доставки поставок
- **ПЛАНИРОВАНИЕ**: Оптимальных маршрутов
- **УПРАВЛЕНИЕ**: Транспортом и водителями
- **ОТСЛЕЖИВАНИЕ**: Мониторинг грузов в пути
### 3.2 Workflow для логистики
#### **ЭТАП 1: Получение заявки**
1. Логистика получает уведомление о новой поставке
2. Заявка появляется в разделе "Заявки" кабинета логистики
3. Логист изучает детали поставки (объем, вес, маршрут)
#### **ЭТАП 2: Подтверждение доставки**
4. Логист нажимает кнопку "Одобрить"
5. Статус поставки меняется на `LOGISTICS_CONFIRMED`
6. Уведомления отправляются всем участникам
#### **ЭТАП 3: Получение груза**
7. Логистика приезжает к поставщику
8. Поставщик передает товар и документы
9. В системе отмечается "Груз получен"
10. Статус меняется на `IN_TRANSIT`
#### **ЭТАП 4: Доставка**
11. Логистика доставляет товар на фулфилмент-центр
12. В кабинете логистики нажимают "Доставлено"
13. Фулфилмент принимает товар и отмечает "Принято"
### 3.3 Система тарификации
**ПАРАМЕТРЫ ТАРИФИКАЦИИ**:
- **Тариф до 1м³** - базовая стоимость для малых грузов
- **Тариф свыше 1м³** - стоимость для крупных грузов
- **Маршруты доставки** - от точки отправления до точки назначения
- **Описание услуг** - дополнительные условия доставки
**РАСЧЕТ СТОИМОСТИ**:
- Автоматический расчет стоимости доставки по объему груза
- Отображение примерной стоимости при создании заказа
- Учет специфики маршрута и условий доставки
#### Пример интерфейса тарификации:
```jsx
<div className="tariff-calculator glass-card p-4">
<h3 className="text-white font-semibold mb-4">Расчет стоимости доставки</h3>
<div className="space-y-3">
<div className="flex justify-between">
<span className="text-white/60">Объем груза:</span>
<span className="text-white font-medium">{volume} м³</span>
</div>
<div className="flex justify-between">
<span className="text-white/60">Базовый тариф:</span>
<span className="text-white">{volume <= 1 ? tariffUnder1m3 : tariffOver1m3} /м³</span>
</div>
<div className="border-t border-white/10 pt-3">
<div className="flex justify-between text-lg">
<span className="text-white font-semibold">Итого:</span>
<span className="text-green-400 font-bold">{calculateTotal(volume, tariff)} </span>
</div>
</div>
</div>
</div>
```
### 3.4 Управление заявками
**РАЗДЕЛЫ КАБИНЕТА ЛОГИСТИКИ**:
- **НОВЫЕ ЗАЯВКИ** - поступившие заявки на доставку
- **В РАБОТЕ** - принятые к исполнению заявки
- **ВЫПОЛНЕННЫЕ** - завершенные доставки
- **ОТКЛОНЕННЫЕ** - заявки, которые не могут быть выполнены
**ИНФОРМАЦИЯ О ЗАЯВКЕ**:
- Детали груза (объем, вес, габариты)
- Маршрут доставки (откуда - куда)
- Срочность доставки
- Особые требования к транспортировке
- Контактная информация участников
#### Интерфейс управления заявками:
```jsx
<Tabs defaultValue="new" className="w-full">
<TabsList className="grid w-full grid-cols-4 bg-white/5">
<TabsTrigger value="new" className="data-[state=active]:bg-white/10">
Новые
<Badge className="ml-2 bg-blue-500/20">{newCount}</Badge>
</TabsTrigger>
<TabsTrigger value="in-progress" className="data-[state=active]:bg-white/10">
В работе
<Badge className="ml-2 bg-yellow-500/20">{inProgressCount}</Badge>
</TabsTrigger>
<TabsTrigger value="completed" className="data-[state=active]:bg-white/10">
Выполненные
</TabsTrigger>
<TabsTrigger value="rejected" className="data-[state=active]:bg-white/10">
Отклоненные
</TabsTrigger>
</TabsList>
<TabsContent value="new" className="mt-4">
<div className="grid gap-4">
{newRequests.map((request) => (
<LogisticsRequestCard key={request.id} request={request} />
))}
</div>
</TabsContent>
</Tabs>
```
## 4. 🛠️ GRAPHQL API
### 4.1 Основные запросы (Queries)
#### Получение заявок на доставку:
```graphql
query GetLogisticsRequests {
logisticsRequests(where: { status: PENDING }) {
id
number
fromLocation
toLocation
weight
volume
status
supply {
id
totalAmount
organization {
name # Заказчик
}
}
}
}
```
#### Получение активных маршрутов:
```graphql
query GetActiveRoutes {
routes(where: { status: ACTIVE }) {
id
name
driver {
name
phone
}
deliveries {
id
status
estimatedTime
}
}
}
```
#### Получение статистики:
```graphql
query GetLogisticsStats {
logisticsStats {
totalDeliveries
activeDeliveries
completedToday
averageDeliveryTime
onTimeRate
}
}
```
### 4.2 Мутации (Mutations)
#### Подтверждение доставки:
```graphql
mutation ConfirmLogistics($supplyId: ID!) {
confirmLogistics(supplyId: $supplyId) {
success
supply {
id
status # Изменится на LOGISTICS_CONFIRMED
}
}
}
```
#### Обновление статуса доставки:
```graphql
mutation UpdateDeliveryStatus($deliveryId: ID!, $status: DeliveryStatus!) {
updateDeliveryStatus(id: $deliveryId, status: $status) {
success
delivery {
id
status
updatedAt
}
}
}
```
#### Создание маршрута:
```graphql
mutation CreateRoute($input: RouteInput!) {
createRoute(input: $input) {
success
route {
id
name
driver {
id
name
}
deliveries {
id
fromLocation
toLocation
}
}
}
}
```
### 4.3 Подписки (Subscriptions)
```graphql
subscription DeliveryTracking($deliveryId: ID!) {
deliveryUpdates(deliveryId: $deliveryId) {
id
status
currentLocation
estimatedArrival
events {
type
timestamp
description
}
}
}
```
## 5. 📁 ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ
### 5.1 Расположение компонентов
```
src/components/
├── logistics/ # Компоненты логистики
│ ├── logistics-requests-dashboard.tsx
│ ├── logistics-request-card.tsx
│ ├── route-manager.tsx
│ └── delivery-tracker.tsx
├── routes/ # Компоненты маршрутов
│ ├── route-card.tsx
│ ├── route-planner.tsx
│ └── driver-assignment.tsx
└── economics/ # Экономика
└── logistics-economics-page.tsx
```
### 5.2 Страницы (Pages)
```
src/app/
├── logistics-requests/
│ └── page.tsx # Страница заявок
├── routes/
│ └── page.tsx # Страница маршрутов
├── in-transit/
│ └── page.tsx # Активные доставки
└── delivery-history/
└── page.tsx # История доставок
```
## 6. 🚨 ТЕХНИЧЕСКИЕ ПРАВИЛА И ОГРАНИЧЕНИЯ
> 📖 **Workflow поставок**: См. [rules-complete.md#5-workflow-поставок](./rules-complete.md#5--workflow-поставок) для бизнес-процессов
### 6.1 Обязательные проверки:
- Проверка типа организации: `organization.type === 'LOGIST'`
- Валидация прав доступа на уровне GraphQL резолверов
- Проверка возможности доставки (вес, объем, расстояние)
- Контроль статусов перед изменением
### 6.2 Правила безопасности доступа:
#### Контроль на уровне компонентов:
```typescript
{user?.organization?.type === "LOGIST" && (
<LogisticsRequestsDashboard />
)}
```
#### Проверки в GraphQL резолверах:
```typescript
// Проверка что пользователь - логистика
if (context.user.organization.type !== 'LOGIST') {
throw new Error('Access denied: Logistics access required')
}
// Проверка доступа к заявкам
const request = await prisma.logisticsRequest.findFirst({
where: {
id: requestId,
organizationId: context.user.organizationId,
},
})
```
### 6.3 Запрещено:
- Изменять статусы поставок минуя workflow
- Подтверждать доставки без физического получения груза
- Показывать данные других логистических компаний
- Изменять данные после завершения доставки
### 6.4 Правила статусов доставки:
- `LOGISTICS_CONFIRMED` → только после проверки возможности
- `IN_TRANSIT` → только после физического получения груза
- `DELIVERED` → требует подтверждения от фулфилмента
### 6.5 Правила логистики
**ОБЯЗАТЕЛЬНО**:
- Своевременное подтверждение заявок
- Соблюдение сроков доставки
- Бережная транспортировка товаров
- Уведомление о статусе доставки
- Документальное оформление приема/передачи груза
**ЗАПРЕЩЕНО**:
- Принятие заявок без подтверждения возможности выполнения
- Нарушение сроков доставки без уведомления
- Повреждение товаров при транспортировке
- Передача груза без документального оформления
- Изменение маршрута без согласования
**ИНТЕГРАЦИЯ С ПАРТНЕРАМИ**:
- Логистика видит только партнеров-поставщиков и фулфилмент-центры
- Выбор логистики осуществляется из списка партнеров типа `LOGIST`
- Все взаимодействия фиксируются в системе уведомлений
> 📖 **Критические запреты**: См. [rules-complete.md#17-критические-запреты](./rules-complete.md#17--критические-запреты)
---
**Последнее обновление**: Август 2025
**Связанные файлы**:
- [rules-complete.md](./rules-complete.md) - Общие бизнес-правила
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила

View File

@ -0,0 +1,724 @@
# 🎯 ПРАВИЛА РЕФЕРАЛЬНОЙ СИСТЕМЫ SFERA
⚠️ **КРИТИЧЕСКИ ВАЖНОЕ ПРАВИЛО: НЕ ПУТАТЬ "ПАРТНЁРСКИЕ ССЫЛКИ" И "РЕФЕРАЛЬНЫЕ ССЫЛКИ"**
> 📅 **Дата создания**: 2025-01-10
> 🔧 **Статус**: Спецификация для разработки
> 📌 **Версия**: 1.1
## 📋 ОГЛАВЛЕНИЕ
1. [Общие принципы](#1-общие-принципы)
2. [Структура данных](#2-структура-данных)
3. [Генерация реферальных ссылок](#3-генерация-реферальных-ссылок)
4. [UI/UX компоненты](#4-uiux-компоненты)
5. [Система начисления баллов](#5-система-начисления-баллов)
6. [GraphQL API](#6-graphql-api)
7. [Процесс регистрации по реферальной ссылке](#7-процесс-регистрации-по-реферальной-ссылке)
8. [Автоматическое партнерство через бизнес-сделки](#8-автоматическое-партнерство-через-бизнес-сделки)
9. [Безопасность и ограничения](#9-безопасность-и-ограничения)
---
## 1. ОБЩИЕ ПРИНЦИПЫ
### 1.1 Основные положения
- **УНИВЕРСАЛЬНОСТЬ**: Реферальная система доступна для всех типов кабинетов (SELLER, WHOLESALE, FULFILLMENT, LOGIST)
- **АВТОМАТИЗАЦИЯ**: Реферальная ссылка генерируется автоматически при создании организации
- **ПРОЗРАЧНОСТЬ**: Все начисления сфер ⚡ видны в режиме реального времени
- **БЕЗОПАСНОСТЬ**: Невозможно изменить реферальную ссылку после генерации
- **ИНТЕГРАЦИЯ С БИЗНЕСОМ**: Партнерство создается не только через рефералы, но и через коммерческие сделки
### 1.2 Терминология
- **РЕФЕРЕР** - организация, которая приглашает новых участников
- **РЕФЕРАЛ** - организация, зарегистрированная по реферальной ссылке
- **РЕФЕРАЛЬНЫЙ КОД** - уникальный идентификатор в ссылке (10 символов)
- **СФЕРЫ ⚡** - единица вознаграждения за привлечение рефералов и коммерческие сделки
- **АВТОПАРТНЕРСТВО** - автоматическое создание партнерских связей при коммерческих сделках
- **РЕФЕРАЛЬНАЯ ССЫЛКА** - маркетинговый инструмент (`?ref=`), только начисление сфер
- **ПАРТНЕРСКАЯ ССЫЛКА** - бизнес-инструмент (`?partner=`), сферы + автоматическое партнерство
### 1.3 Разделение ссылок
#### Реферальная система (маркетинг):
- **URL формат**: `https://app.sfera.ru/register?ref=SF2X9K4M7P`
- **Местоположение**: Вкладка "Рефералы"
- **Цель**: Привлечение новых пользователей на платформу
- **Результат**: +100 сфер ⚡, автоматического партнерства НЕТ
- **Ссылка**: Уже готова при создании организации, быстрое копирование
#### Партнерская система (бизнес):
- **URL формат**: `https://app.sfera.ru/register?partner=SF2X9K4M7P`
- **Местоположение**: Вкладка "Мои партнеры"
- **Цель**: Прямое деловое сотрудничество
- **Результат**: +100 сфер ⚡ + автоматическое добавление в партнеры
- **Ссылка**: Уже готова при создании организации, быстрое копирование
---
## 2. СТРУКТУРА ДАННЫХ
### 2.1 Расширение модели Organization (Prisma)
```prisma
model Organization {
// Существующие поля...
// Реферальная система
referralCode String? @unique @default(cuid()) // Уникальный код для реферальной ссылки
referredById String? // ID организации-реферера
referredBy Organization? @relation("ReferralRelation", fields: [referredById], references: [id])
referrals Organization[] @relation("ReferralRelation")
referralPoints Int @default(0) // Общее количество баллов
@@index([referralCode])
@@index([referredById])
}
```
### 2.2 Новая модель ReferralTransaction
```prisma
model ReferralTransaction {
id String @id @default(cuid())
referrerId String // Кто получил баллы
referralId String // За кого получил баллы
points Int // Количество баллов
type ReferralTransactionType // Тип транзакции
description String? // Описание транзакции
createdAt DateTime @default(now())
referrer Organization @relation("ReferrerTransactions", fields: [referrerId], references: [id])
referral Organization @relation("ReferralTransactions", fields: [referralId], references: [id])
@@index([referrerId, createdAt])
@@index([referralId])
}
enum ReferralTransactionType {
REGISTRATION // За регистрацию по реферальной ссылке
AUTO_PARTNERSHIP // За автоматическое партнерство через бизнес-сделку
FIRST_ORDER // За первый заказ (будущее расширение)
MONTHLY_BONUS // Ежемесячный бонус (будущее расширение)
}
```
---
## 3. ГЕНЕРАЦИЯ РЕФЕРАЛЬНЫХ ССЫЛОК
### 3.1 Формат реферальной ссылки
```
https://app.sfera.ru/register?ref={referralCode}
```
### 3.2 Алгоритм генерации кода
- **Длина**: 10 символов
- **Символы**: A-Z, 0-9 (исключая похожие: O/0, I/1)
- **Пример**: `SF2X9K4M7P`
### 3.3 Правила генерации
- Генерируется автоматически при создании организации
- Проверка уникальности перед сохранением
- Невозможно изменить после создания
- Хранится в поле `referralCode` модели Organization
---
## 4. UI/UX КОМПОНЕНТЫ
### 4.1 Вкладка "Рефералы" в разделе Партнеры
#### Расположение
- Раздел: `/partners`
- Новая вкладка: 6-я позиция после "Поставщик"
- Название: "Рефералы"
- Иконка: `Gift` или `Users2` из lucide-react
#### Структура страницы
```tsx
<div className="referrals-page">
{/* Блок с реферальной ссылкой */}
<div className="referral-link-section glass-card p-6 mb-6">
<h3>Ваша реферальная ссылка</h3>
<div className="flex items-center gap-4">
<div className="hidden-link">••••••••••</div>
<Button onClick={copyLink}>
<Copy className="h-4 w-4 mr-2" />
Копировать ссылку
</Button>
</div>
<p className="text-sm text-white/60 mt-2">
Поделитесь ссылкой с партнерами и получайте баллы за каждую регистрацию
</p>
</div>
{/* Статистика */}
<div className="stats-grid grid grid-cols-4 gap-4 mb-6">
<StatsCard title="Всего партнеров" value={totalReferrals} icon="Users" />
<StatsCard title="Сфер заработано" value={totalPoints} icon="Zap" suffix="⚡" />
<StatsCard title="Партнеров за месяц" value={monthlyReferrals} icon="TrendingUp" />
<StatsCard title="Сфер за месяц" value={monthlyPoints} icon="Zap" suffix="⚡" />
</div>
{/* Фильтры */}
<div className="filters glass-card p-4 mb-6">
<DateRangePicker />
<TypeFilter types={['SELLER', 'WHOLESALE', 'FULFILLMENT', 'LOGIST']} />
<SearchInput placeholder="Поиск по названию или ИНН" />
</div>
{/* Таблица рефералов */}
<div className="referrals-table glass-card">
<Table>
<TableHeader>
<TableRow>
<TableHead>Дата регистрации</TableHead>
<TableHead>Название организации</TableHead>
<TableHead>ИНН</TableHead>
<TableHead>Тип кабинета</TableHead>
<TableHead>Источник</TableHead>
<TableHead>Начислено сфер </TableHead>
<TableHead>Статус</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{referrals.map(referral => (
<TableRow key={referral.id}>
<TableCell>{formatDate(referral.createdAt)}</TableCell>
<TableCell>{referral.name || referral.fullName}</TableCell>
<TableCell>{referral.inn}</TableCell>
<TableCell>
<Badge className={getTypeBadgeStyles(referral.type)}>
{getTypeLabel(referral.type)}
</Badge>
</TableCell>
<TableCell>
<div className="flex items-center gap-2">
{referral.source === 'REFERRAL' ? (
<>
<UserPlus className="h-4 w-4 text-blue-400" />
<span className="text-blue-300">Реферальная ссылка</span>
</>
) : (
<>
<ShoppingCart className="h-4 w-4 text-orange-400" />
<span className="text-orange-300">Бизнес-сделка</span>
</>
)}
</div>
</TableCell>
<TableCell>
<div className="flex items-center gap-1">
<span className="text-green-400">+{referral.points}</span>
<Zap className="h-4 w-4 text-yellow-400" />
</div>
</TableCell>
<TableCell>
<Badge variant="success">Активен</Badge>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
```
### 4.2 Визуальные элементы
#### Скрытие реферальной ссылки
- Ссылка НЕ отображается в явном виде
- Показываются точки или звездочки: `••••••••••`
- Только кнопка "Копировать ссылку"
#### Уведомления
- При копировании: "Реферальная ссылка скопирована"
- При новом реферале: push-уведомление
- При начислении баллов: анимация изменения баланса
---
## 5. СИСТЕМА НАЧИСЛЕНИЯ БАЛЛОВ
### 5.1 Базовые ставки
| Тип регистрации | Количество баллов |
|-----------------|-------------------|
| SELLER | 100 сфер ⚡ |
| WHOLESALE | 100 сфер ⚡ |
| FULFILLMENT | 100 сфер ⚡ |
| LOGIST | 100 сфер ⚡ |
> 💡 **ИКОНКА СФЕРЫ**: ⚡ (молния) - символизирует энергию, скорость и силу партнерства
### 5.2 Правила начисления
- **МОМЕНТ НАЧИСЛЕНИЯ**: Сразу после успешной регистрации реферала
- **УСЛОВИЕ**: Реферал должен пройти полную регистрацию (подтвердить ИНН)
- **ОГРАНИЧЕНИЯ**: Один ИНН = одно начисление (защита от дублей)
- **ВИДИМОСТЬ**: Баллы сразу отображаются в таблице и общем счетчике
### 5.3 Будущие расширения
- Бонусы за первый заказ реферала
- Ежемесячные начисления за активных рефералов
- Многоуровневая система (рефералы рефералов)
---
## 6. GRAPHQL API
### 6.1 Новые Queries
```graphql
type Query {
# Получить мою реферальную ссылку
myReferralLink: String!
# Список моих рефералов
myReferrals(
dateFrom: DateTime
dateTo: DateTime
type: OrganizationType
search: String
limit: Int
offset: Int
): ReferralsResponse!
# Статистика по рефералам
myReferralStats: ReferralStats!
# История транзакций баллов
myReferralTransactions(
limit: Int
offset: Int
): ReferralTransactionsResponse!
}
```
### 6.2 Новые Types
```graphql
type ReferralsResponse {
referrals: [Referral!]!
totalCount: Int!
totalPages: Int!
}
type Referral {
id: ID!
organization: Organization!
registeredAt: DateTime!
pointsEarned: Int!
status: ReferralStatus!
transactions: [ReferralTransaction!]!
}
type ReferralStats {
totalReferrals: Int!
totalPoints: Int!
monthlyReferrals: Int!
monthlyPoints: Int!
referralsByType: [ReferralTypeStats!]!
}
type ReferralTypeStats {
type: OrganizationType!
count: Int!
points: Int!
}
type ReferralTransaction {
id: ID!
points: Int!
type: ReferralTransactionType!
description: String
createdAt: DateTime!
referral: Organization!
}
enum ReferralStatus {
ACTIVE
INACTIVE
BLOCKED
}
```
### 6.3 Расширение существующих типов
```graphql
extend type Organization {
referralCode: String
referredBy: Organization
referrals: [Organization!]!
referralPoints: Int!
isMyReferral: Boolean! # Computed field
}
```
---
## 7. ПРОЦЕСС РЕГИСТРАЦИИ ПО ССЫЛКАМ
### 7.1 Реферальная ссылка (маркетинг)
#### Пошаговый процесс:
1. **Переход по ссылке**
- Пользователь переходит по ссылке: `https://app.sfera.ru/register?ref=SF2X9K4M7P`
- Система сохраняет реферальный код в sessionStorage
2. **Регистрация**
- Стандартный процесс регистрации
- Реферальный код передается в mutation `registerOrganization`
3. **Валидация**
- Проверка существования реферального кода
- Проверка, что организация не регистрировалась ранее
4. **Создание связи**
- Установка `referredById` для новой организации
- Создание записи в `ReferralTransaction`
- **ВАЖНО**: Автоматическое партнерство НЕ создается
5. **Начисление баллов**
- Автоматическое начисление 100 сфер ⚡ рефереру
- Отправка уведомления рефереру
### 7.2 Партнерская ссылка (бизнес)
#### Пошаговый процесс:
1. **Переход по ссылке**
- Пользователь переходит по ссылке: `https://app.sfera.ru/register?partner=SF2X9K4M7P`
- Система сохраняет партнерский код в sessionStorage
2. **Регистрация**
- Стандартный процесс регистрации
- Партнерский код передается в mutation `registerOrganization`
3. **Валидация**
- Проверка существования партнерского кода
- Проверка, что организация не регистрировалась ранее
4. **Создание связи**
- Установка `referredById` для новой организации
- Создание записи в `ReferralTransaction`
- **ВАЖНО**: Автоматическое создание партнерства (`Counterparty`)
5. **Начисление баллов**
- Автоматическое начисление 100 сфер ⚡ партнеру
- Отправка уведомления партнеру
- Добавление в список "Мои партнеры"
### 7.3 Логика различения
```javascript
// В процессе регистрации
if (query.ref) {
// Реферальная ссылка - только сферы
await addReferralTransaction(referrerId, newUserId, 100, 'REFERRAL_LINK')
} else if (query.partner) {
// Партнерская ссылка - сферы + автоматическое партнерство
await addReferralTransaction(partnerId, newUserId, 100, 'REFERRAL_LINK')
await createPartnership(partnerId, newUserId, 'REFERRAL')
}
```
### 7.4 Обработка ошибок
- **Невалидный код**: Регистрация продолжается без реферала/партнерства
- **Самореферал**: Блокировка (нельзя регистрироваться по своей ссылке)
- **Повторная регистрация**: Игнорирование кода
---
## 8. АВТОМАТИЧЕСКОЕ ПАРТНЕРСТВО ЧЕРЕЗ БИЗНЕС-СДЕЛКИ
### 8.1 Принцип работы
Кроме реферальных ссылок, партнерские отношения создаются автоматически через коммерческие взаимодействия в системе.
### 8.2 Триггер автопартнерства
**МОМЕНТ СОЗДАНИЯ ПАРТНЕРСТВА**: Когда поставщик одобряет заявку на поставку (`supplierApproveOrder` mutation)
**УСЛОВИЕ**: Если между организациями еще нет партнерских отношений (`Counterparty` связи)
**ДЕЙСТВИЕ**: Автоматическое создание взаимного партнерства
### 8.3 Алгоритм автопартнерства
```typescript
// В GraphQL резолвере supplierApproveOrder
async supplierApproveOrder(supplyOrderId: string) {
// 1. Одобрить заявку
const supplyOrder = await updateSupplyOrderStatus(supplyOrderId, 'SUPPLIER_APPROVED')
// 2. Проверить существование партнерства
const existingCounterparty = await checkCounterpartyExists(
supplyOrder.organizationId, // Покупатель
supplyOrder.partnerId // Поставщик
)
// 3. Создать автопартнерство если его нет
if (!existingCounterparty) {
await createAutoCounterparty({
organizationId: supplyOrder.organizationId,
counterpartyId: supplyOrder.partnerId,
type: 'AUTO_BUSINESS',
triggeredBy: 'SUPPLY_ORDER_APPROVAL',
supplyOrderId: supplyOrderId
})
}
return supplyOrder
}
```
### 8.4 Расширение модели данных
```prisma
model Counterparty {
// Существующие поля...
// Новые поля для автопартнерства
type CounterpartyType @default(MANUAL)
triggeredBy String? // 'SUPPLY_ORDER_APPROVAL', 'REFERRAL_LINK'
triggerEntityId String? // ID заявки, реферала и т.д.
@@index([type])
}
enum CounterpartyType {
MANUAL // Создано вручную через UI
REFERRAL // Создано через реферальную ссылку
AUTO_BUSINESS // Создано автоматически через бизнес-сделку
}
```
### 8.5 Начисление сфер за автопартнерство
**ДЛЯ ПОСТАВЩИКА** (кто одобрил заявку):
- +100 сфер ⚡ за каждого нового партнера через бизнес-сделку
- Равно рефералу, так как это также ценное партнерство
**ДЛЯ ПОКУПАТЕЛЯ**:
- Партнерство создается, но сферы не начисляются
- Выгода в том, что появляется прямая связь с поставщиком
### 8.6 Отображение в UI
В таблице рефералов добавить колонку "Источник":
| Источник | Описание | Иконка |
|----------|----------|---------|
| Реферальная ссылка | Зарегистрировались по вашей ссылке | `UserPlus` |
| Бизнес-сделка | Стали партнерами через заказ | `ShoppingCart` |
### 8.7 Логирование автопартнерства
```typescript
// Лог события создания автопартнерства
{
event: 'auto_counterparty_created',
supplierId: '...',
buyerId: '...',
supplyOrderId: '...',
spheresEarned: 50,
timestamp: '2025-01-10T15:30:00Z'
}
```
---
## 9. БЕЗОПАСНОСТЬ И ОГРАНИЧЕНИЯ
### 9.1 Защита от злоупотреблений
- **Один ИНН - одна регистрация**: Проверка уникальности ИНН
- **Блокировка самореферала**: Проверка IP и device fingerprint
- **Лимиты**: Максимум 100 регистраций в день с одного реферального кода
- **Валидация ИНН**: Обязательная проверка через DaData API
### 9.2 Права доступа
- **Просмотр своих рефералов**: Только владелец реферального кода
- **Изменение кода**: Запрещено
- **Просмотр чужих рефералов**: Запрещено
- **Администратор**: Полный доступ для модерации
### 9.3 Логирование
Все действия с реферальной системой логируются:
- Генерация ссылок
- Переходы по ссылкам
- Регистрации
- Начисления баллов
- Попытки злоупотреблений
---
## 🎨 UI/UX ПРАВИЛА РАЗДЕЛА "ПАРТНЕРЫ"
### 10.1 Принципы унификации интерфейса
**КРИТИЧЕСКИ ВАЖНО**: Все вкладки раздела "Партнеры" должны иметь единый визуальный дизайн:
#### Обязательная унификация:
- **Идентичная структура блоков статистики**: 4 метрики в ряд
- **Одинаковые цветовые схемы** для аналогичных элементов
- **Табличный формат отображения данных** вместо карточного grid-layout
- **Компактное использование пространства**
#### Структура DOM для блоков статистики:
```tsx
{/* ПРАВИЛЬНАЯ структура */}
<div className="grid grid-cols-4 gap-3">
<Card className="glass-card p-3 hover:bg-white/5 transition-all duration-200">
<div className="p-1.5 rounded-lg bg-{color}-500/20 border border-{color}-500/30">
<Icon className="h-4 w-4 text-{color}-400" />
</div>
</Card>
</div>
{/* ЗАПРЕЩЕНО - дополнительные обертки */}
<Card className="glass-card">
<div className="grid grid-cols-4 gap-3">
<div>...</div> // <- НЕ glass-card внутри glass-card!
</div>
</Card>
```
### 10.2 Техническая реализация
#### A) Вкладка "Рефералы":
- **Файл**: `src/components/partners/referrals-tab.tsx`
- **Структура**: Каждый блок статистики = отдельный `<Card className="glass-card">`
- **Прозрачность**: Через glass-morphism эффекты
- **Отступы**: Компактные (`p-3`, `p-4`)
#### B) Вкладка "Мои контрагенты":
- **Файл**: `src/components/market/market-counterparties.tsx`
- **Структура**: Конвертирована от карточного grid к табличному формату
- **Блоки статистики**: Добавлены 4 компактных блока (Партнеров, Заявок, За месяц, Исходящих)
- **Обертки**: УБРАНА лишняя обертка `glass-card` в `partners-dashboard.tsx`
### 10.3 Цветовая схема блоков
#### Реферальные/Партнерские ссылки (верхний блок):
- **Цвет**: `bg-yellow-500/20 border border-yellow-500/30`
- **Иконка**: `text-yellow-400`
- **ЗАПРЕЩЕНО**: Использовать фиолетовую схему (`bg-purple-500/20`)
#### Блоки статистики:
- **1-й блок (Партнеров)**: `bg-blue-500/20` + `text-blue-400` (синий)
- **2-й блок (Заработано/Заявок)**: `bg-yellow-500/20` + `text-yellow-400` (желтый)
- **3-й блок (За месяц)**: `bg-green-500/20` + `text-green-400` (зеленый)
- **4-й блок (Сфер за месяц/Исходящих)**: `bg-yellow-500/20` + `text-yellow-400` (желтый)
### 10.4 Компоненты и размеры
#### Оптимизация пространства:
- **Отступы карточек**: `p-4` для верхнего блока, `p-3` для статистики
- **Размеры иконок**: `h-4 w-4` (компактно)
- **Шрифты заголовков**: `text-base` вместо `text-2xl`
- **Отступы между блоками**: `space-y-4`
#### Hover эффекты:
- **Блоки статистики**: `hover:bg-white/5 transition-all duration-200`
- **Кнопки**: `glass-button hover:bg-white/20`
### 10.5 Исправления структурных проблем
#### КРИТИЧЕСКИ ВАЖНЫЕ исправления:
1. **Убрана лишняя обертка** в `src/components/partners/partners-dashboard.tsx`:
```tsx
// БЫЛО (неправильно):
<TabsContent value="counterparties">
<Card className="glass-card"> // <- ЛИШНЯЯ обертка!
<MarketCounterparties />
</Card>
</TabsContent>
// СТАЛО (правильно):
<TabsContent value="counterparties">
<MarketCounterparties />
</TabsContent>
```
2. **Исправлена цветовая схема** верхнего блока в контрагентах:
```tsx
// БЫЛО: bg-purple-500/20 text-purple-400
// СТАЛО: bg-yellow-500/20 text-yellow-400
```
### 10.6 Результат унификации
После применения правил:
- ✅ **Идентичная прозрачность** блоков (glass-morphism)
- ✅ **Единая цветовая схема** между вкладками
- ✅ **Компактное использование пространства**
- ✅ **Табличный формат** во всех вкладках
- ✅ **Консистентная структура DOM**
---
## 🎨 ВИЗУАЛЬНЫЙ ДИЗАЙН
### Цветовая схема для сфер ⚡
- **Положительные начисления**: `text-green-400`
- **Иконка молнии**: `text-yellow-400` (золотистый)
- **Фон для сфер**: `bg-yellow-500/20`
- **Анимация при изменении**: `animate-pulse` на 2 секунды
### Иконки источников партнерства
- **Реферальная ссылка**: `UserPlus` в `text-blue-400`
- **Бизнес-сделка**: `ShoppingCart` в `text-orange-400`
- **Сферы**: `Zap` в `text-yellow-400`
### Стили для типов кабинетов (соответствуют существующим)
- **SELLER**: `bg-green-500/20 text-green-300`
- **WHOLESALE**: `bg-purple-500/20 text-purple-300`
- **FULFILLMENT**: `bg-blue-500/20 text-blue-300`
- **LOGIST**: `bg-orange-500/20 text-orange-300`
---
## 📊 МЕТРИКИ УСПЕХА
- **Конверсия**: % регистраций по реферальным ссылкам
- **Активность**: Среднее количество рефералов на одного партнера
- **Retention**: % активных рефералов через 30 дней
- **Виральность**: Количество рефералов, которые сами привели рефералов
---
## 🚀 ПЛАН ВНЕДРЕНИЯ
### Фаза 1 (MVP)
- Базовая генерация ссылок
- Регистрация по реферальным ссылкам
- Начисление баллов за регистрацию
- UI для просмотра рефералов
### Фаза 2
- Бонусы за первый заказ
- Email уведомления о новых рефералах
- Экспорт данных о рефералах
### Фаза 3
- Многоуровневая система
- Использование баллов для оплаты услуг
- Gamification элементы (достижения, уровни)
---
**Дата создания**: 2025-01-10
**Автор**: Claude AI Assistant
**Статус**: Готово к реализации

View File

@ -0,0 +1,178 @@
# ПРАВИЛА РЕГИСТРАЦИИ И АВТОРИЗАЦИИ
## 🏗️ АРХИТЕКТУРА СИСТЕМЫ
### Основные сущности:
- **ПОЛЬЗОВАТЕЛЬ** - верхний уровень, может иметь много номеров телефонов
- **НОМЕР ТЕЛЕФОНА** - привязан к пользователю, может иметь много организаций
- **ОРГАНИЗАЦИЯ/КАБИНЕТ** - бизнес-сущность, привязана к номеру телефона
- **ПАРТНЕРСТВО** - связь между организациями (не пользователями или номерами)
### Связи:
```
ПОЛЬЗОВАТЕЛЬ (1) ←→ (N) НОМЕРА ТЕЛЕФОНОВ (1) ←→ (N) ОРГАНИЗАЦИИ
ОРГАНИЗАЦИЯ (N) ←→ (N) ОРГАНИЗАЦИИ (партнерство)
```
### Пример структуры:
```
ПОЛЬЗОВАТЕЛЬ "Иван Петров"
├── +7111111111 (номер 1)
│ ├── СБЕРБАНК (организация 1)
│ └── АВИТО (организация 2)
└── +7222222222 (номер 2)
└── ЯНДЕКС (организация 3)
```
## 📋 СПОСОБЫ СОЗДАНИЯ ОРГАНИЗАЦИЙ
### 1. СТАНДАРТНАЯ РЕГИСТРАЦИЯ
**URL:** `/register` (без параметров)
**Флоу для НОВОГО номера телефона:**
1. Ввод телефона → SMS код → авторизация
2. Выбор типа кабинета
3. Ввод данных организации (ИНН или API ключи)
4. Создание организации
5. Привязка организации к номеру телефона
**Флоу для АВТОРИЗОВАННОГО номера:**
1. Редирект в дашборд (стандартное поведение)
### 2. РЕГИСТРАЦИЯ ЧЕРЕЗ САЙДБАР (ПОТОМ)
**Местоположение:** Блок организации в сайдбаре
**Флоу:**
1. Модалка создания новой организации
2. Выбор типа кабинета
3. Ввод данных организации
4. Создание организации без партнерства
### 3. ПАРТНЕРСКАЯ ССЫЛКА
**URL:** `/register?partner=CODE`
**Флоу для НОВОГО номера телефона:**
1. Ввод телефона → SMS код → авторизация
2. Выбор типа кабинета
3. Ввод данных организации
4. Создание организации С ПАРТНЕРСТВОМ
5. Автоматическое создание партнерских связей между организациями
6. Начисление +100 сфер организации-рефереру
**Флоу для АВТОРИЗОВАННОГО номера телефона:**
1. Пропуск авторизации (уже авторизован на этом номере)
2. Переход сразу к выбору типа кабинета
3. Ввод данных новой организации
4. Создание организации С ПАРТНЕРСТВОМ
5. Автоматическое создание партнерских связей
6. Начисление +100 сфер организации-рефереру
### 4. РЕФЕРАЛЬНАЯ ССЫЛКА
**URL:** `/register?ref=CODE`
**Флоу для НОВОГО номера телефона:**
1. Ввод телефона → SMS код → авторизация
2. Выбор типа кабинета
3. Ввод данных организации
4. Создание организации С РЕФЕРАЛЬНОЙ СВЯЗЬЮ
5. Начисление +100 сфер организации-рефереру
6. БЕЗ автоматического партнерства
**Флоу для АВТОРИЗОВАННОГО номера телефона:**
1. Пропуск авторизации (уже авторизован на этом номере)
2. Переход сразу к выбору типа кабинета
3. Ввод данных новой организации
4. Создание организации С РЕФЕРАЛЬНОЙ СВЯЗЬЮ
5. Начисление +100 сфер организации-рефереру
6. БЕЗ автоматического партнерства
## 📊 ДАШБОРД РЕФЕРАЛОВ (РЕАЛИЗОВАНО)
### Местоположение: `/partners` → вкладка "Рефералы"
### Функции:
1. **Мои ссылки:**
- Реферальная ссылка: `register?ref=CODE`
- Партнерская ссылка: `register?partner=CODE`
- Кнопка копирования
2. **Статистика:**
- Всего партнеров и начисленных сфер
- Статистика за текущий месяц
3. **Список рефералов:**
- Привлеченные организации
- Фильтрация и поиск
- Источник регистрации
## 🔧 ТЕХНИЧЕСКИЕ ПРАВИЛА
### Валидация URL параметров:
- Нельзя использовать `partner` и `ref` одновременно
- Коды должны быть длиной 10 символов
- Коды должны существовать в системе
- Коды должны соответствовать формату `[ABCDEFGHJKLMNPQRSTUVWXYZ23456789]{10}`
### Поведение AuthGuard:
- **Без кодов:** если авторизован → дашборд, иначе → форма авторизации
- **С кодами:** всегда показывать AuthFlow (даже для авторизованных)
### Поведение AuthFlow:
- **Новый номер телефона:** полный флоу (телефон → SMS → создание организации)
- **Авторизованный номер:** пропустить телефон/SMS, сразу к созданию организации
### Создание партнерства:
- Создаются записи в таблице `Counterparty` в ОБЕ стороны
- Создается `ReferralTransaction` с начислением сфер
- Устанавливается `referredById` у новой организации
### Создание реферальной связи:
- Создается `ReferralTransaction` с начислением сфер
- Устанавливается `referredById` у новой организации
- БЕЗ создания `Counterparty` записей
## ⚠️ ВАЖНЫЕ ОГРАНИЧЕНИЯ
### Архитектурные ограничения:
- **ОДИН ПОЛЬЗОВАТЕЛЬ** может иметь **МНОГО номеров телефонов**
- **ОДИН НОМЕР ТЕЛЕФОНА** привязан к **ОДНОМУ ПОЛЬЗОВАТЕЛЮ**
- **ОДИН НОМЕР ТЕЛЕФОНА** может иметь **МНОГО ОРГАНИЗАЦИЙ**
- Нельзя зарегистрировать один номер телефона дважды
### Уникальность организаций:
- Одна организация (по ИНН) может быть зарегистрирована только один раз
- API ключи селлеров должны быть уникальными
### Сохранение кодов:
- Партнерские/реферальные коды должны передаваться через все компоненты
- Коды не должны теряться при авторизации номера телефона
- Коды применяются при создании ОРГАНИЗАЦИИ, не пользователя или номера
## 🧪 ТЕСТОВЫЕ СЦЕНАРИИ
### Сценарий 1: Новый номер + партнерская ссылка
1. Переход по `register?partner=A2LA72BZZX`
2. Ввод нового телефона → SMS → авторизация
3. Создание новой организации
4. Проверка: создались партнерские связи, начислились сферы
### Сценарий 2: Авторизованный номер + партнерская ссылка
1. Уже авторизован на номере в системе
2. Переход по `register?partner=A2LA72BZZX`
3. Пропуск авторизации → сразу создание организации
4. Проверка: создались партнерские связи, начислились сферы
### Сценарий 3: Реферальная ссылка
1. Переход по `register?ref=A2LA72BZZX`
2. Авторизация (если нужно)
3. Создание организации
4. Проверка: начислились сферы, НЕТ партнерских связей
## ❓ ВОПРОСЫ ДЛЯ СОГЛАСОВАНИЯ
1. **Архитектура БД:** Нужна ли новая таблица для "мастер-пользователей" или изменить текущую схему?
2. **Связь пользователь-телефон:** Как будет происходить связывание номеров телефонов с одним пользователем?
3. **UI для авторизованных:** Показывать ли информацию "Вы создаете организацию для номера +7XXX"?
4. **Переключение организаций:** Как пользователь выбирает активную организацию из разных номеров?
5. **Лимиты:** Есть ли ограничения на количество номеров у пользователя или организаций у номера?
6. **Идентификация:** Как система определяет, что два номера принадлежат одному пользователю?

View File

@ -0,0 +1,2065 @@
> ❌ **ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!**
>
> 📅 **Дата создания резерва**: 2025-08-08
> 🔐 **Статус**: ЗАЩИЩЕН ОТ ИЗМЕНЕНИЙ
> 📄 **Оригинальный файл**: rules-complete.md
---
# ПРАВИЛА СИСТЕМЫ УПРАВЛЕНИЯ СКЛАДАМИ И ПОСТАВКАМИ - ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ v10.0
> ⚠️ **АБСОЛЮТНО ПОЛНЫЙ ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ**: Данный файл объединяет АБСОЛЮТНО ВСЕ правила системы: протоколы работы Claude Code, детальные протоколы по сложности, систему предотвращения нарушений, расширенную самопроверку, специальный UI/UX протокол и бизнес-правила. Визуальные правила вынесены в отдельный файл visual-design-rules.md с автоматической интеграцией.
## 📚 СТРУКТУРА ДОКУМЕНТАЦИИ
### Основные файлы правил:
- **rules-complete.md** (этот файл) - общие бизнес-правила и процессы
- **wholesale-cabinet-rules.md** - технические детали кабинета поставщика
- **visual-design-rules.md** - визуальные правила (уже интегрирован)
### Когда какой файл читать:
- При работе с компонентами поставщика → [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md)
- При изменении бизнес-логики → rules-complete.md
- При работе с UI/UX → [visual-design-rules.md](./visual-design-rules.md)
## 🔴 ПРАВИЛА ВЗАИМОДЕЙСТВИЯ С CLAUDE
### Основные принципы работы:
- **Двухэтапный процесс**: Планирование → Одобрение → Выполнение
- **Обязательное чтение правил** перед каждой задачей
- **Детальные протоколы** по сложности задач
- **Система проверок** и самоконтроля
- **Честность и прозрачность** при неопределенности
### Обязательная последовательность:
1. Читать rules-complete.md перед началом работы
2. Определить сложность задачи
3. Применить соответствующий протокол
4. Создать план через TodoWrite
5. Получить одобрение пользователя
6. Выполнить согласно плану
7. Проверить качество результата
## 🛠️ ПРОТОКОЛЫ РАБОТЫ ПО СЛОЖНОСТИ
### Краткий обзор протоколов:
- **Простые задачи**: Прямое выполнение с базовыми проверками
- **Средние задачи**: Трехэтапный процесс (Анализ → План → Выполнение)
- **Сложные задачи**: Расширенный анализ с множественными проверками
- **Критические задачи**: Полный протокол безопасности
### Определение сложности:
- **Средняя**: 2-3 файла, изменение логики в 1-2 модулях
- **Высокая**: 4+ файлов, изменение архитектуры, влияние на несколько кабинетов
### 🔥 ПРОТОКОЛ ВЫСОКОЙ СЛОЖНОСТИ
**Обязательные этапы для сложных задач:**
1. **СТОП! ГЛУБОКИЙ АНАЛИЗ** - уточнить все требования у пользователя
2. **ИССЛЕДОВАНИЕ** - изучить все связанные файлы параллельно
3. **ДЕТАЛЬНЫЙ ПЛАН** - с промежуточными проверками и rollback точками
### ❓ СИСТЕМА УТОЧНЕНИЙ
**Когда ОБЯЗАТЕЛЬНО спрашивать:**
- Обнаружил противоречие в правилах
- Задача может нарушить архитектуру системы
- Неясно как применить правило к ситуации
- Есть несколько способов с разными последствиями
### 🎨 UI/UX ПРОТОКОЛ
**Автоматическая активация** при ключевых словах: дизайн, интерфейс, компонент, UI, UX
**Обязательно:**
- Прочитать visual-design-rules.md перед началом
- Проверить соответствие цветовой палитре
- Использовать glass-эффекты согласно дизайн-системе
## 🚨 СИСТЕМА КОНТРОЛЯ КАЧЕСТВА
### Принципы контроля:
- **Стоп-сигналы** перед критическими действиями
- **Принудительные проверки** соблюдения протоколов
- **Автоматические триггеры** для специфических ситуаций
- **Система блокировки** нарушений
- **Расширенная самопроверка** с финальными проверками
### Обязательные остановки:
- Перед анализом компонентов без использования инструментов
- При любой неопределенности или сомнениях
- Перед выполнением средних/сложных задач без протокола
### Финальная проверка:
"Применил ли правильный протокол, проверил все правила, готов результат к production?"
## ⚡ БЫСТРЫЙ СПРАВОЧНИК
### 🚨 КРИТИЧЕСКИЕ ПРАВИЛА (ОБЯЗАТЕЛЬНЫ К СОБЛЮДЕНИЮ)
1. **🔴 ТИПИЗАЦИЯ**: Каждый предмет ОБЯЗАТЕЛЬНО имеет тип: `PRODUCT`, `CONSUMABLE`, `DEFECT`, `FINISHED_PRODUCT`
2. **🔴 WORKFLOW**: Нельзя пропускать статусы поставок: PENDING → SUPPLIER_APPROVED → CONFIRMED → ... → DELIVERED
3. **🔴 ДОСТУП**: Фулфилмент = полный доступ, Селлер ≠ доступ к чужим данным, Брак = ЗАПРЕЩЕН к заказу
4. **🔴 ПАРТНЕРСТВО**: Все связи через модель `Counterparty`, поставщики в формах ТОЛЬКО из партнеров `WHOLESALE`
5. **🔴 ФИЛЬТРАЦИЯ**: По типу предмета происходит в GraphQL резолверах, НЕ на фронтенде
### 🔍 БЫСТРЫЙ ПОИСК ПО ТЕМАМ
| Тема | Раздел | Ключевые понятия |
| ----------------------- | -------------------------------------------------------------------------------------- | --------------------------------------------- |
| **Типы предметов** | [2](#2--типизация-предметов) | PRODUCT, CONSUMABLE, DEFECT, FINISHED_PRODUCT |
| **Кабинет фулфилмента** | [11](#11--кабинет-фулфилмента-полная-документация) | Склад, Услуги, Сотрудники, 6 модулей |
| **Workflow поставок** | [5](#5--workflow-поставок) | 8 статусов, уведомления, логистика |
| **GraphQL запросы** | [18](#18--graphql-и-typescript-правила), [24](#24--технические-приложения) | Резолверы, мутации, типизация |
| **Система партнерства** | [13](#13--система-партнерства-и-контрагентов) | Counterparty, WHOLESALE, заявки |
| **Рынки и маркет** | [10.1](#101-разделение-понятий-рынок-vs-маркет), [18.7](#187-правила-рынков-и-маркета) | РЫНОК ≠ МАРКЕТ, Organization.market |
| **Критические запреты** | [17](#17--критические-запреты) | Что НЕЛЬЗЯ делать в системе |
### 🎯 ДЛЯ РАЗНЫХ РОЛЕЙ
**👩‍💻 РАЗРАБОТЧИКИ**: Разделы [18](#18--graphql-и-typescript-правила), [19](#19--архитектурные-принципы), [20](#20--правила-качества-кода), [24](#24--технические-приложения)
**📊 АНАЛИТИКИ**: Разделы [15](#15--статистика-и-аналитика), [6](#6--процесс-создания-продукта), [7](#7--система-учета-движения-товаров)
**👔 МЕНЕДЖЕРЫ**: Разделы [1](#1--основные-принципы-системы), [3](#3--структура-кабинетов), [5](#5--workflow-поставок)
---
## 🔤 ГЛОССАРИЙ ТЕРМИНОВ
> Для людей → `В коде`
### **ТИПЫ ПРЕДМЕТОВ:**
- **ТОВАР** → `PRODUCT` - базовый товар от поставщика, может стать продуктом или браком
- **РАСХОДНИКИ** → `CONSUMABLE` - материалы, классифицируются по назначению при использовании (операционные/производственные)
- **БРАК** → `DEFECT` _(НЕ РЕАЛИЗОВАНО)_ - функционал брака еще не внедрен в систему
- **ПРОДУКТ** → `FINISHED_PRODUCT` _(планируется)_ - готовый товар, создается из товара по рецептуре
### **ТИПЫ ОРГАНИЗАЦИЙ:**
- **ПОСТАВЩИК** → `WHOLESALE` - создает товары и расходники, обрабатывает заказы
- **СЕЛЛЕР** → `SELLER` - заказывает товары, создает поставки на маркетплейсы
- **ФУЛФИЛМЕНТ** → `FULFILLMENT` - обрабатывает товары, создает продукты, максимальные права
- **ЛОГИСТИКА** → `LOGIST` - управляет доставками, подтверждает транспортировку
### 2.2 Правила создания предметов по ролям
**КТО МОЖЕТ СОЗДАВАТЬ:**
- **ПОСТАВЩИК** (`WHOLESALE`): Товары (`PRODUCT`) и Расходники (`CONSUMABLE`)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Продукты (`FINISHED_PRODUCT`) - только из существующих товаров
- **СЕЛЛЕР/ЛОГИСТ**: НЕ МОГУТ создавать предметы
**КТО МОЖЕТ ПОКУПАТЬ:**
- **СЕЛЛЕР** (`SELLER`):
- Товары и расходники у поставщиков
- Расходники фулфилмента у фулфилмента (через рецептуру в поставке)
- **ФУЛФИЛМЕНТ** (`FULFILLMENT`): Товары и расходники у поставщиков
- **ПОСТАВЩИК/ЛОГИСТ**: НЕ МОГУТ покупать предметы
**ЭКОНОМИЧЕСКИЙ УЧЕТ:**
- Когда селлер выбирает расходники фулфилмента в рецептуре, это формирует экономические данные:
- В кабинете селлера: расход на расходники фулфилмента
- В кабинете фулфилмента: доход от продажи расходников селлеру
### **КЛЮЧЕВЫЕ СУЩНОСТИ:**
- **Контрагент** → `Counterparty` - связь между организациями для партнерства
- **Поставка** → `SupplyOrder` - заказ товаров/расходников с workflow статусами
- **Рецептура** - состав продукта: товар + услуги + расходники (задается селлером)
### **КОНТЕКСТНО-ЗАВИСИМЫЕ ТЕРМИНЫ:**
#### **SupplyOrder - многосторонний документ**
SupplyOrder представляет собой единый документ, который видится по-разному каждым участником процесса:
**ДЛЯ СОЗДАТЕЛЕЙ (Селлер/Фулфилмент):**
- **Термин**: "Поставка"
- **Контекст**: Они создают поставку товаров и расходников на фулфилмент
- **Включает**: Весь процесс от закупки до приемки на склад
**ДЛЯ ПОСТАВЩИКА (исполнитель товарной части):**
- **Термин**: "Заявка на покупку"
- **Контекст**: Получают запрос на продажу своих товаров/расходников
- **Действия**: Могут одобрить или отклонить в зависимости от наличия
**ДЛЯ ЛОГИСТИКИ (исполнитель транспортной части):**
- **Термин**: "Заявка на доставку"
- **Контекст**: Получают запрос на транспортировку груза
- **Действия**: Могут подтвердить или отклонить в зависимости от возможностей
**ОТОБРАЖЕНИЕ В ИНТЕРФЕЙСЕ КАБИНЕТОВ:**
| Кабинет | Название раздела | Обоснование |
|---------|-----------------|-------------|
| Селлер | "Мои поставки" | Создает и управляет поставками |
| Поставщик | "Заявки на покупку" | Обрабатывает входящие заявки |
| Логистика | "Заявки на доставку" | Управляет транспортировкой |
| Фулфилмент | "Входящие поставки" | Принимает поставки на склад |
**ВАЖНО**: Это один и тот же объект SupplyOrder в базе данных, но каждый участник работает со своей стороной процесса.
#### **Маркет vs Маркетплейс - четкое разделение**
**МАРКЕТ** (`/market`):
- **Что это**: Внутренний раздел системы
- **Функция**: Глобальный каталог всех товаров от всех поставщиков
- **Доступ**: Для всех типов организаций в системе
- **НЕ путать**: С названиями физических рынков типа "ОПТ Маркет"
**МАРКЕТПЛЕЙС** (Wildberries, Ozon):
- **Что это**: Внешние торговые площадки
- **Функция**: Конечные точки продаж для селлеров
- **Интеграция**: Через API ключи в настройках
- **Использование**: "Поставки на маркетплейсы", "Отгрузка на маркетплейсы"
---
## 📑 ОГЛАВЛЕНИЕ
> 📖 **Каталог процессов**: См. [workflow-catalog.md](./workflow-catalog.md) для полного каталога всех бизнес-процессов системы
> 📋 **ЧТО ОБЪЕДИНЕНО**:
>
> - rules-unified.md (v3.0) - общая база знаний системы
> - fulfillment-cabinet-rules.md (v1.0) - детализация кабинета фулфилмента
> - Устранены все несоответствия в терминах, последовательностях и детализации
### 🏗️ **АРХИТЕКТУРА И ОСНОВЫ**
1. [🎯 Основные принципы системы](#1--основные-принципы-системы)
2. [📦 Типизация предметов](#2--типизация-предметов)
3. [🏢 Структура кабинетов](#3--структура-кабинетов)
4. [🔐 Система ролей и доступов](#4--система-ролей-и-доступов)
### 🚚 **WORKFLOW И ПРОЦЕССЫ**
5. [🚚 Workflow поставок](#5--workflow-поставок)
6. [🔄 Процесс создания продукта](#6--процесс-создания-продукта)
7. [📊 Система учета движения товаров](#7--система-учета-движения-товаров)
### 🏢 **КАБИНЕТЫ СИСТЕМЫ**
8. [🏠 Общие правила кабинетов](#8--общие-правила-кабинетов)
9. [🏠 Кабинет селлера (детальные правила)](#9--кабинет-селлера-детальные-правила)
10. [🏪 Кабинет поставщика](#10--кабинет-поставщика)
11. [🏭 Кабинет фулфилмента](#11--кабинет-фулфилмента)
12. [🚚 Кабинет логистики](#12--кабинет-логистики)
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
13. [🤝 Система партнерства и контрагентов](#13--система-партнерства-и-контрагентов)
### 🌐 **ИНТЕГРАЦИИ И ФУНКЦИИ**
14. [🌐 Интеграции с системой](#14--интеграции-с-системой)
15. [📊 Статистика и аналитика](#15--статистика-и-аналитика)
16. [📱 Правила UI/UX и интерфейса](#16--правила-uiux-и-интерфейса)
17. [⚠️ Критические запреты](#17--критические-запреты)
### 🛠️ **ТЕХНИЧЕСКИЕ ПРАВИЛА**
18. [🛠️ GraphQL и TypeScript правила](#18--graphql-и-typescript-правила)
19. [🔧 Архитектурные принципы](#19--архитектурные-принципы)
20. [🎯 Правила качества кода](#20--правила-качества-кода)
21. [🔍 Диагностика и решение проблем](#21--диагностика-и-решение-проблем)
### 📋 **ПРИЛОЖЕНИЯ**
22. [📋 Категории товаров и расходников](#22--категории-товаров-и-расходников)
23. [🎖️ Приоритеты разработки](#23--приоритеты-разработки)
### 🚨 **КРИТИЧЕСКИЕ СИТУАЦИИ**
24. [🚨 Критические ситуации и Edge Cases](#-критические-ситуации-и-edge-cases)
### 📎 **ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ**
25. [📎 Технические приложения (GraphQL, компоненты)](#24--технические-приложения)
---
## 🏷️ РЕЕСТР СУЩНОСТЕЙ СИСТЕМЫ
### 📦 **ОСНОВНЫЕ ПРЕДМЕТЫ**
| Сущность | Название в системе | Кабинет создания | Описание | Статус |
| ---------- | -------------------------------------- | ---------------- | ----------------------------------------------- | -------------- |
| Товар | `Product` (type: `PRODUCT`) | Поставщик | Базовый тип товара от поставщика | ✅ Реализовано |
| Расходники | `Product` (type: `CONSUMABLE`) | Поставщик | Материалы и вспомогательные товары | ✅ Реализовано |
| Брак | `Product` (type: `DEFECT`)\* | Фулфилмент | Производная от товара с дефектами | 📋 Планируется |
| Продукт | `Product` (type: `FINISHED_PRODUCT`)\* | Фулфилмент | Готовый к продаже товар (производная от товара) | 📋 Планируется |
> **\* Планируется**: Типы `DEFECT` и `FINISHED_PRODUCT` еще не добавлены в Prisma схему
### 🏢 **ОРГАНИЗАЦИИ И РОЛИ**
| Сущность | Название в системе | Основные функции | Статус |
| ---------- | ------------------------------------ | --------------------------------------- | -------------- |
| Поставщик | `Organization` (type: `WHOLESALE`) | Создание товаров, управление поставками | ✅ Реализовано |
| Селлер | `Organization` (type: `SELLER`) | Заказ товаров, управление поставками | ✅ Реализовано |
| Фулфилмент | `Organization` (type: `FULFILLMENT`) | Обработка товаров, управление складом | ✅ Реализовано |
| Логистика | `Organization` (type: `LOGIST`) | Управление доставками | ✅ Реализовано |
### 🤝 **СИСТЕМА ПАРТНЕРСТВА**
| Сущность | Название в системе | Описание | Статус |
| ---------- | --------------------- | ------------------------- | -------------- |
| Контрагент | `Counterparty` | Связь между организациями | ✅ Реализовано |
| Заявка | `CounterpartyRequest` | Запрос на сотрудничество | ✅ Реализовано |
---
## 1. 🎯 ОСНОВНЫЕ ПРИНЦИПЫ СИСТЕМЫ
### 1.1 Архитектура системы
**СТРУКТУРА СИСТЕМЫ ПО КАБИНЕТАМ:**
**🏢 КАБИНЕТ ПОСТАВЩИКА** - создает и управляет:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщика
- **РАСХОДНИКИ** (`CONSUMABLE`) - материалы и вспомогательные товары от поставщика
**🏭 КАБИНЕТ ФУЛФИЛМЕНТА** - принимает, обрабатывает и управляет всеми типами:
- **ТОВАР** (`PRODUCT`) - базовые товары от поставщиков (принятые на склад)
- **БРАК** (`DEFECT` - планируется) - производная от товара (товар с дефектами)
- **ПРОДУКТ** (`FINISHED_PRODUCT` - планируется) - готовый к продаже товар
- **РАСХОДНИКИ (`CONSUMABLE`)** - единый базовый тип, классифицируется по назначению при использовании:
- **"Операционные расходники"** - используются фулфилментом для выполнения услуг
- **"Производственные расходники"** - используются в рецептурах селлеров для создания продуктов
**🛍️ КАБИНЕТ СЕЛЛЕРА** - заказывает и управляет поставками:
- Создает заказы товаров и расходников
- Управляет поставками на фулфилмент и маркетплейсы
- Отслеживает статусы поставок
### 1.2 Основные принципы разработки
**КРИТИЧЕСКИ ВАЖНЫЕ ПРИНЦИПЫ:**
1. **Строгая типизация**: Каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируется)
2. **Партнерская система**: Все связи между организациями через модель `Counterparty`
3. **Workflow статусов**: Строгая последовательность статусов поставок
4. **Безопасность доступа**: Контроль доступа на уровне GraphQL резолверов
5. **Единый источник истины**: Централизованное управление данными
---
## 2. 📦 ТИПИЗАЦИЯ ПРЕДМЕТОВ
### 2.1 Два реализованных и два планируемых типа предметов
#### **1. ТОВАР** (`PRODUCT` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком
- **СТАТУС**: Может быть активным/неактивным
- **ЗАКАЗ**: Доступен для заказа всеми типами организаций
- **ТРАНСФОРМАЦИЯ**: Может стать ПРОДУКТОМ или БРАКОМ
- **ЦЕНА**: Обязательна, больше 0
#### **2. РАСХОДНИКИ** (`CONSUMABLE` - базовый тип)
- **СОЗДАЕТСЯ**: Поставщиком как универсальный тип
- **КЛАССИФИКАЦИЯ ПРИ ЗАКАЗЕ**:
- Фулфилмент заказывает → "Расходники фулфилмента"
- Селлер заказывает → "Расходники селлеров"
- **ДОСТУП**: Видны всем типам организаций в маркете
#### **3. БРАК** (`DEFECT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе существующего ТОВАРА при обнаружении дефектов
- **МОМЕНТ СОЗДАНИЯ**: В процессе обработки товара (ШАГ 3 алгоритма создания продукта) при выявлении брака
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **ЗАКАЗ**: ЗАПРЕЩЕН заказ брака
- **СТАТУС**: Всегда неактивен для заказа
- **ЦЕНА**: Для селлера - себестоимость дефектного товара, для фулфилмента - 0
- **WORKFLOW**: Особый процесс списания и утилизации
- **УЧЕТ**: Отдельный учет в статистике потерь
- **ОТОБРАЖЕНИЕ**: Виден только для учета потерь
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `DEFECT` еще не добавлен в схему БД
#### **4. ПРОДУКТ** (`FINISHED_PRODUCT` - планируется, производная от товара)
- **БУДЕТ СОЗДАВАТЬСЯ**: Фулфилментом на основе ТОВАРА по заказу селлера
- **ИНИЦИАТОР**: Селлер создает заказ с рецептурой, фулфилмент исполняет
- **СВЯЗЬ**: Обязательная связь с родительским товаром (parentId)
- **РЕЦЕПТУРА**: Задается селлером при создании заказа (Товар + Услуга + Расходники)
- **СТАТУСЫ**: "в работе" → "готов к отправке"
- **ЗАКАЗ**: Доступен только в статусе "готов к отправке"
- **⚠️ СТАТУС РАЗРАБОТКИ**: Тип `FINISHED_PRODUCT` еще не добавлен в схему БД
### 2.2 Обязательные поля карточки
**КРИТИЧЕСКИ ВАЖНО**: Название, артикул, цена > 0, тип предмета
**ИСКЛЮЧЕНИЕ ДЛЯ БРАКА**: Цена может быть 0 для фулфилмента (себестоимость для селлера)
**ОБЯЗАТЕЛЬНО**: Количество (может быть 0 для предзаказа)
**ДЛЯ ПРОИЗВОДНЫХ ТИПОВ**: Обязательная связь с родительским предметом
---
## 3. 🏢 СТРУКТУРА КАБИНЕТОВ
### 3.1 Общие принципы кабинетов
**КАЖДЫЙ КАБИНЕТ ИМЕЕТ:**
1. **Главная страница** (`/dashboard`) - общая информация и статистика
2. **Экономика** (`/economics`) - финансовая аналитика
3. **Универсальные разделы**:
- Маркет (`/market`) - просмотр и заказ товаров
- Партнеры (`/partners`) - управление контрагентами
- Мессенджер (`/messenger`) - связь между организациями
- Настройки (`/settings`) - профиль и API ключи
### 3.2 Специфические разделы по типам организаций
**🏪 ПОСТАВЩИК (`WHOLESALE`):**
- Склад (`/warehouse`) - управление товарами и расходниками
- Поставки (`/supplies`) - обработка заказов от селлеров
**🛍️ СЕЛЛЕР (`SELLER`):**
- Мои поставки (`/supplies`) - управление заказами товаров
- WB Интеграция (`/wb-integration`) - связь с Wildberries
**🏭 ФУЛФИЛМЕНТ (`FULFILLMENT`):**
- Склад фулфилмента (`/fulfillment-warehouse`) - управление всеми типами товаров
- Поставки фулфилмента (`/fulfillment-supplies`) - обработка поставок
- Услуги (`/services`) - управление услугами, логистикой, расходниками
- Сотрудники (`/employees`) - управление персоналом
- Статистика фулфилмента (`/fulfillment-statistics`) - детальная аналитика
**🚚 ЛОГИСТИКА (`LOGIST`):**
- Заявки (`/logistics-requests`) - управление заявками на доставку
- Маршруты (`/routes`) - планирование маршрутов
---
## 4. 🔐 СИСТЕМА РОЛЕЙ И ДОСТУПОВ
### 4.1 Контроль доступа к разделам
**ПРОВЕРКА НА УРОВНЕ КОМПОНЕНТОВ:**
```typescript
{user?.organization?.type === "FULFILLMENT" && (
// Компоненты доступны только фулфилменту
)}
```
**СПЕЦИАЛЬНАЯ ЛОГИКА РОУТИНГА:**
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
// ... другие типы
}
}
```
### 4.2 GraphQL проверки доступа
**В Apollo Client запросах:**
```typescript
const { data } = useQuery(GET_MY_SERVICES, {
skip: user?.organization?.type !== 'FULFILLMENT',
})
```
**В GraphQL резолверах:**
```typescript
if (currentUser.organization.type !== 'FULFILLMENT') {
throw new GraphQLError('Доступно только для фулфилмент центров')
}
```
### 4.3 Контроль доступа к заказам
- **Создатель заказа** - полный доступ к своим заказам
- **Поставщик** - доступ к заказам, где он является поставщиком
- **Фулфилмент-центр** - доступ к заказам, направленным в его центр
- **Логистическая компания** - доступ к заказам для доставки
---
## 5. 🚚 WORKFLOW ПОСТАВОК
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Статусы поставок](#142-статусы-поставок---расширенная-цветовая-система)
См. детальное описание в [workflow-catalog.md#1-workflow-поставок](./workflow-catalog.md#1-workflow-поставок)
---
## 6. 🔄 ПРОЦЕСС СОЗДАНИЯ ПРОДУКТА
> 📌 **СВЯЗАННЫЕ РАЗДЕЛЫ**:
>
> - Типы предметов → См. [раздел 2.2](#22-обязательные-поля-карточки)
> - Склад фулфилмента → См. [раздел 11.2](#112-структура-раздела-склад-фулфилмента)
> - Статистика движения → См. [раздел 7](#7--система-учета-движения-товаров)
### 6.1 Пошаговый алгоритм создания продукта
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Процесс создания продукта](#143-процесс-создания-продукта---визуальный-workflow)
#### **ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ: РЕЦЕПТУРА ЗАДАНА** (селлер)
```
Время: при создании заявки на поставку
Действие: селлер указывает рецептуру продукта
Обязательные компоненты:
✓ Базовый товар (от поставщика)
✓ Услуги фулфилмента (упаковка, маркировка и т.д.)
✓ Расходники (материалы для производства)
Результат: рецептура сохраняется в заявке и передается фулфилменту
```
#### **ШАГ 1: ПОСТУПЛЕНИЕ НА СКЛАД** (автоматически)
```
Время: при смене статуса поставки DELIVERED
Действие: товар переходит в статус "на складе"
Ответственный: система
Результат: +Прибыло в статистике товаров
```
#### **ШАГ 2: ПЛАНИРОВАНИЕ РАБОТЫ** (менеджер фулфилмента)
```
Время: в течение 2 рабочих дней после поступления
Действие: назначение параметров обработки
Ответственный: менеджер фулфилмента
Обязательные поля:
✓ Дедлайн выполнения (не более 5 рабочих дней)
✓ Ответственный исполнитель (из списка сотрудников)
✓ Рецептура (товар + услуги + расходники, указанная селлером в заявке на поставку)
Опциональные поля:
- Место хранения готовых продуктов (зона склада, стеллаж, ячейка)
- Комментарии к работе
Результат: поставка переходит во вкладку "В работе"
```
#### **ШАГ 3: ОБРАБОТКА ТОВАРА** (исполнитель)
```
Время: согласно дедлайну (обычно 1-3 дня)
Действие: физическая обработка товара
Ответственный: назначенный сотрудник
Обязательные действия:
1. Проверка качества товара
2. Фиксация фактического количества
3. Выявление и учет брака
4. Применение рецептуры (услуги + расходники)
5. Создание готового продукта
Точки контроля:
- Соответствие плану/факту
- Качество выполнения услуг
- Расход материалов по норме
УЧЕТ ПЛАН/ФАКТ:
- ПЛАН: Количество товаров из поставки селлера (указано в заказе)
- ФАКТ: Реальное количество после обработки = Брак + Хороший товар
- ДЕТАЛИЗАЦИЯ: Учет ведется по каждому размеру/объему/варианту
- КОРРЕКТИРОВКА: Статистика автоматически обновляется на фактические данные
```
#### **ШАГ 4: КОНТРОЛЬ КАЧЕСТВА** (менеджер/отдел качества)
```
Время: сразу после завершения ШАГ 3
Действие: приемка готовой продукции
Ответственный: менеджер или контролер качества
Критерии приемки:
✓ Соответствие рецептуре селлера
✓ Качество выполненных услуг
✓ Правильность упаковки/маркировки
✓ Полнота комплектации
Результат: продукт готов к отправке или отправлен на доработку
```
#### **ШАГ 5: ЗАВЕРШЕНИЕ** (система + менеджер)
```
Время: после успешного прохождения контроля качества
Действие: финализация процесса
Автоматические действия:
- Создание записи FINISHED_PRODUCT в БД
- Обновление статистики: товар "на складе" → продукт "готов"
- Списание использованных расходников
- Уведомление селлера о готовности
Ручные действия менеджера:
- Подтверждение перехода во вкладку "Выполнено"
- Указание фактических расходов материалов
- Добавление комментариев о выполненной работе
```
### 6.2 Временные рамки и SLA
| Этап | Стандартное время | Максимальное время | Ответственный |
| ----------------- | ----------------- | ------------------ | -------------- |
| Планирование | 1 рабочий день | 2 рабочих дня | Менеджер ФФ |
| Обработка | 2-3 рабочих дня | 5 рабочих дней | Исполнитель |
| Контроль качества | 4 часа | 1 рабочий день | Отдел качества |
| Завершение | 2 часа | 4 часа | Менеджер ФФ |
### 6.3 Управление браком и расхождениями
### 6.4 Детальная рецептура продукта
**РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
- **БАЗОВЫЙ ТОВАР**: Исходный материал (обязательно)
- Артикул товара
- Количество единиц
- Размерная сетка (если применимо)
- **УСЛУГА ФУЛФИЛМЕНТА**: Из каталога услуг фулфилмента
- Тип услуги (глажка, упаковка, маркировка и т.д.)
- Количество применений
- Специальные требования
- **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
- Фирменная упаковка
- Этикетки, бирки
- Дополнительные аксессуары
- **РАСХОДНИК ФУЛФИЛМЕНТА**: Материалы фулфилмента (опционально)
- Стандартная упаковка
- Защитные материалы
- Маркировочные элементы
- **СВЯЗЬ С МАРКЕТПЛЕЙСОМ**: Привязка к карточке (опционально)
- ID карточки на маркетплейсе
- Артикул маркетплейса
- Особые требования МП
**ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
### 6.5 Учет план/факт в процессе работы (без брака)
**ПЛАН**: Количество товара из поставки селлера
**ФАКТ**: Реальное количество после пересчета (работник фулфилмента производит сортировку при пересчете)
**ФИКСАЦИЯ ПОТЕРЬ:**
- **КОГДА**: В процессе работы (вкладка "В работе")
- **ЧТО**: Недостача, повреждения (без создания записей брака)
- **КАК**: Корректировка количества в статистике
**WORKFLOW СОЗДАНИЯ ПРОДУКТА:**
1. Товар поступает на склад фулфилмента (статус "на складе")
2. Товар берется в работу (переход в статус "в обработке")
3. Исполнитель производит пересчет и сортировку
4. Создается готовый продукт (тип FINISHED_PRODUCT)
5. Продукт готов к отправке на маркетплейсы
**ВЛИЯНИЕ НА СТАТИСТИКУ:**
- При принятии поставки: +План в статистику
- При выявлении факта: корректировка на реальные данные
- **ФОРМУЛА**: Факт = Потери + Хороший товар
_Где потери - это недостача/повреждения, выявленные при пересчете и сортировке_
- **ЛОГИКА**: Фактическое количество = сумма всех пересчитанных предметов
- **ПЛАН/ФАКТ**: Корректировка статистики при выявлении расхождений
---
> 🚧 **БУДУЩАЯ ФУНКЦИОНАЛЬНОСТЬ**: Система статусов товаров в фулфилменте будет детализирована позже
## 7. 📊 СИСТЕМА УЧЕТА ДВИЖЕНИЯ ТОВАРОВ
### 7.1 Принципы учета в фулфилменте
**ОСНОВНЫЕ ПРИНЦИПЫ:**
- **ПРИХОД**: Товары поступают через принятые поставки (из состояния "в пути" → "на складе")
- **ОБРАБОТКА**: Товары переходят в статус "в работе" для создания продуктов
- **РАСХОД**: Товары убывают при отгрузке, списании, возврате, превращении в продукты
- **УЧЁТ**: Ведется учет прихода и расхода для каждого типа предметов
- **ВИЗУАЛИЗАЦИЯ**: Движение отображается в дополнительных значениях
### 7.2 Дополнительные и основные значения
**ДОПОЛНИТЕЛЬНЫЕ ЗНАЧЕНИЯ (показатели движения):**
- **ПРИБЫЛО**: Количество предметов, поступивших на склад
- **УБЫЛО**: Количество предметов, списанных со склада
- **ВЛИЯНИЕ**: От этих значений зависят основные значения (общее количество)
**ОСНОВНЫЕ ЗНАЧЕНИЯ (текущие остатки):**
- **ОПРЕДЕЛЕНИЕ**: Итоговое количество предметов на складе
- **РАСЧЁТ**: Основные значения = Предыдущие остатки + Прибыло - Убыло
- **ОТОБРАЖЕНИЕ**: Показываются в каждом модуле статистики
- **РАЗДЕЛЕНИЕ ТОВАРОВ**:
- Товары "на складе" - готовы к обработке
- Товары "в обработке" - находятся в процессе создания продукта
---
## 8. 🏠 ОБЩИЕ ПРАВИЛА КАБИНЕТОВ
### 8.1 Универсальная структура кабинетов
**ВСЕ ТИПЫ КАБИНЕТОВ** включают следующие обязательные разделы:
#### 8.1.1 Страница "Главная"
**СТАТУС**: Реализовано
**ДОСТУП**: Через навигацию в sidebar для всех типов кабинетов
**СОДЕРЖАНИЕ**: Универсальная страница с типо-зависимыми компонентами
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый тип кабинета должен иметь страницу "Главная"
- **НАВИГАЦИЯ**: Доступ через кнопку в sidebar (первая в списке)
- **УНИВЕРСАЛЬНОСТЬ**: Одинаковая структура навигации для всех кабинетов
- **РОУТ**: `/home` с универсальным компонентом HomePageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента: SellerHomePage, FulfillmentHomePage, WholesaleHomePage, LogistHomePage
#### 8.1.2 Раздел "Экономика"
**СТАТУС**: Реализовано в системе
**РАСПОЛОЖЕНИЕ**: Перед настройками в каждом кабинете
**СОДЕРЖАНИЕ**: Пустые разделы-заглушки с пометкой "будет добавлен позже"
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый кабинет имеет раздел "Экономика"
- **РОУТ**: `/economics` с универсальным компонентом EconomicsPageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента экономики: SellerEconomicsPage, FulfillmentEconomicsPage, WholesaleEconomicsPage, LogistEconomicsPage
- **КНОПКА**: "Экономика" в sidebar навигации перед настройками
- **БЕЗОПАСНОСТЬ**: Проверки доступа и безопасности в экономических компонентах
#### 8.1.3 Общие разделы для всех кабинетов
**УНИВЕРСАЛЬНЫЕ РАЗДЕЛЫ** (доступны всем типам):
- 🏠 **Главная** - основная страница кабинета (реализовано)
- 🛒 **Маркет** - просмотр и заказ товаров
- 🤝 **Партнеры** - управление контрагентами
- 💬 **Мессенджер** - внутренняя связь
- 💰 **Экономика** - финансовая аналитика (реализовано)
- ⚙️ **Настройки** - профиль и конфигурация
**СПЕЦИАЛИЗИРОВАННЫЕ РАЗДЕЛЫ** (зависят от типа кабинета):
- Определяются в соответствующих разделах каждого кабинета
### 8.2 Правила sidebar навигации
#### 8.2.1 Структура навигации
**ОБЩИЙ ПРИНЦИП**:
- Условное отображение: `{user?.organization?.type === "TYPE" && (...)}`
- Адаптивность: сворачиваемый sidebar с `getSidebarMargin()`
- Состояния активности: подсветка текущего раздела
**ПОРЯДОК РАЗДЕЛОВ В SIDEBAR**:
1. 🏠 **Главная** (реализовано для всех)
2. **Специализированные разделы** (зависят от типа кабинета)
3. 🛒 **Маркет** (универсальный)
4. 🤝 **Партнеры** (универсальный)
5. 💬 **Мессенджер** (универсальный)
6. 💰 **Экономика** (универсальный, реализовано)
7. ⚙️ **Настройки** (универсальный)
8. **Выход** (универсальный)
#### 8.2.2 Типо-зависимая логика
**АДАПТИВНЫЙ РОУТИНГ**:
```typescript
// Пример: кнопка "Поставки" ведет на разные страницы
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/supplies')
break
case 'LOGIST':
router.push('/logistics-orders')
break
}
}
```
---
## 9. 🏠 КАБИНЕТ СЕЛЛЕРА (ДЕТАЛЬНЫЕ ПРАВИЛА)
> 📌 **ВИЗУАЛЬНЫЕ ПРАВИЛА**: См. [visual-design-rules.md - Кабинет селлера](#145-кабинет-селлера)
### 9.1 Структура раздела "Мои поставки"
#### **🏢 ПОСТАВКИ НА ФУЛФИЛМЕНТ**:
- **Товар** - поставка товаров для создания продуктов
- **Карточки** - поставка через WB API с рецептурой (результат: WildberriesSupply)
- **Поставщики** - заказ товаров у поставщиков с рецептурой (результат: SupplyOrder)
- **Расходники селлера** - поставка материалов для товаров селлера
#### **🛒 ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ** _(планируется)_:
- **Wildberries** - прямые поставки на WB
- **Ozon** - прямые поставки на Ozon
### 9.2 UI структура создания поставки расходников селлера
#### **📄 Структура страницы создания поставки:**
**ВАЖНО**: Страница НЕ имеет основного заголовка и описания. Сразу начинается с блоков контента.
**ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):**
**БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_
- **Навигация**: Плавающая кнопка "Назад" между сайдбаром и контентом (см. детали в seller-ui-rules.md)
- **Заголовок**: БЕЗ заголовка - блок начинается сразу с функционального контента
- **Поиск**: Компактное поле справа "Поиск поставщиков..." (w-64)
- **Отображение**: Карточки поставщиков из раздела "Партнеры" в адаптивной сетке
- **Выбор**: Клик выделяет карточку поставщика
- **Результат**: Загружаются карточки товаров выбранного поставщика в блок 2
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(горизонтальный скролл - НОВЫЙ)_
- **Отображение**: ТОЛЬКО минималистичные карточки товаров 80×112px
- **Содержание**: ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- **Навигация**: Горизонтальный скролл при множестве товаров
- **Выбор**: Клик добавляет товар в детальный каталог
- **Результат**: Товар добавляется в блок 3 для управления поставкой
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Отображение**: Детальные карточки выбранных товаров
- **Управление**: Количество, параметры, настройки поставки
- **Результат**: Формирование окончательной поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель)_
- **Отображение**: Корзина поставки + настройки
- **Управление**: Фулфилмент-центр, дата, логистика
#### **9.2.1 Детальные правила горизонтального скролла поставщиков**
**СТРУКТУРА И ОТОБРАЖЕНИЕ:**
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px, включает заголовок + контейнер скролла
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки
**РАЗМЕРЫ И АДАПТИВНОСТЬ:**
- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"
**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
**Критическая Flex-архитектура:**
```css
.parent-container {
display: flex;
gap: 16px;
min-height: 0;
}
.left-block {
flex: 1;
min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
display: flex;
flex-direction: column;
}
.suppliers-container {
height: 180px; /* Общая высота блока */
flex-shrink: 0;
min-width: 0; /* Предотвращает растяжение */
}
.right-block {
width: 384px; /* w-96 */
flex-shrink: 0; /* Защита от сжатия */
}
```
**Контейнер скролла:**
```css
.suppliers-block {
display: flex;
overflow-x: auto;
scroll-behavior: smooth;
gap: 12px;
padding: 0 16px 8px 16px; /* px-4 pb-2 */
height: 176px; /* h-44 */
scrollbar-width: thin;
scrollbar-color: #64748b33 transparent;
}
.suppliers-block:hover {
scrollbar-color: #cbd5e0 #64748b22;
}
.supplier-card {
flex-shrink: 0;
width: 216px; /* Десктоп */
height: 92px; /* Фиксированная высота */
padding: 8px; /* p-2 */
transition: all 0.2s ease;
}
```
**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**
**Структура (3 строки в 92px высоты):**
- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)
**Элементы:**
- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)
**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**
- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`
**ДОСТУПНОСТЬ:**
- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных
#### **9.2.2 Правила блока "Карточки товаров" (Блок 2)**
**НАЗНАЧЕНИЕ И ЛОГИКА:**
- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров
**АРХИТЕКТУРА И РАЗМЕРЫ:**
- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере
**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**
- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств
**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**
- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный
**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)
#### **9.2.3 Правила Блока 3 "Детальный каталог товаров"**
**НАЗНАЧЕНИЕ И СТРУКТУРА:**
- **Контент**: Детальные карточки выбранных товаров с полным управлением
- **Верхняя панель**: Выбор даты + Выбор Fulfillment + Поиск
- **Основная область**: Сетка карточек товаров с детальной информацией
#### **9.2.3.1 Структура верхней панели Блока 3**
**МИНИМАЛИСТИЧНАЯ ПАНЕЛЬ УПРАВЛЕНИЯ:**
- **Выбор даты поставки**: DatePicker для планирования поставки
- **Выбор Fulfillment-центра**: Select dropdown со списком доступных фулфилментов
- **Поиск по товарам**: Input с иконкой поиска и placeholder
- **Компоновка**: Горизонтальная строка с равномерным распределением
**ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ:**
```tsx
// Структура компонентов панели
<div className="flex items-center gap-4 p-4 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl mb-4">
<DatePicker placeholder="Дата поставки" />
<Select placeholder="Выберите фулфилмент">
<SelectContent>
{fulfillmentCenters.map((center) => (
<SelectItem value={center.id}>{center.name}</SelectItem>
))}
</SelectContent>
</Select>
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-white/40" />
<Input placeholder="Поиск товаров..." className="pl-10 glass-input" />
</div>
</div>
```
#### **9.2.3.2 Структура основной области карточек**
**СЕТКА ТОВАРОВ:**
- **Адаптивная сетка**: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4`
- **Детальные карточки**: Полная информация + количество + управление
- **Состояния**: Default, Selected, Editing
- **Интерактивность**: Изменение количества, удаление, настройки рецептуры
**ФУНКЦИОНАЛЬНОСТЬ ПАНЕЛИ:**
- **Выбор даты**: Планирование времени поставки (обязательное поле)
- **Выбор фулфилмента**: Определение исполнителя поставки (обязательное поле)
- **Поиск**: Фильтрация товаров в каталоге по названию/артикулу
- **Валидация**: Блокировка создания поставки без заполнения даты и фулфилмента
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **Пустой каталог**: Заглушка "Добавьте товары"
- **Нет фулфилментов**: Сообщение "Настройте партнерство с фулфилмент-центрами"
- **Поиск без результатов**: "По запросу ничего не найдено"
#### **9.2.2.1 Структура контейнера Блока 2**
**ДВУХУРОВНЕВАЯ АРХИТЕКТУРА:**
**УРОВЕНЬ 1 - Внешний контейнер (блок):**
```jsx
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0">
```
- **Назначение**: Визуальное обрамление блока, единство с другими блоками
- **Стилизация**: Стеклянный эффект с размытием и полупрозрачностью
- **Рамка**: Тонкая белая рамка border-white/20 с закруглёнными углами
- **Поведение**: flex-shrink-0 предотвращает сжатие блока
**УРОВЕНЬ 2 - Внутренний контейнер (скролл):**
```jsx
<div className="flex gap-3 overflow-x-auto p-4" style={{ scrollbarWidth: 'thin' }}>
```
- **Назначение**: Горизонтальная прокрутка карточек товаров
- **Раскладка**: Flex с промежутками gap-3 (12px) между карточками
- **Отступы**: padding p-4 (16px) со всех сторон
- **Скролл**: overflow-x-auto с тонкой полосой прокрутки
- **Поведение**: Автоматическое появление скролла при превышении ширины
**ПРАВИЛА КОНТЕЙНЕРОВ:**
- Внешний контейнер НЕ содержит заголовков, иконок, описаний
- Внутренний контейнер содержит ТОЛЬКО карточки товаров
- Высота адаптируется под размер карточек (80×112px + отступы)
- Визуальное единство со всеми блоками формы поставки
**ТЕХНИЧЕСКИЕ ПРАВИЛА:**
- **Условие отображения**: selectedSupplier && products.length > 0
- **Источник данных**: products массив из GraphQL запроса organizationProducts
- **Реактивность**: Автоматическое обновление при смене поставщика
- **Производительность**: React.memo для карточек при большом количестве товаров
- **Доступность**: Клавиатурная навигация (Tab, Enter для выбора)
**UX ПРАВИЛА ВЗАИМОДЕЙСТВИЯ:**
- **Скролл**: Автоматическое появление при превышении ширины контейнера
- **Индикация загрузки**: Скелетоны карточек во время загрузки товаров
- **Пустое состояние**: Скрытие блока при отсутствии поставщика или товаров
- **Фокус**: Первая карточка получает фокус при загрузке товаров
- **Навигация**: Стрелки ←→ для перемещения между карточками
**СОСТОЯНИЯ БЛОКА:**
- **Скрыт**: При отсутствии выбранного поставщика
- **Скрыт**: При отсутствии товаров у поставщика
- **Активен**: При наличии поставщика и товаров
- **Загрузка**: Показ скелетонов карточек во время запроса
**ПРАВИЛА ПРОИЗВОДИТЕЛЬНОСТИ:**
- **Виртуализация**: При количестве товаров > 100
- **Ленивая загрузка изображений**: loading="lazy" для всех изображений
- **Мемоизация**: React.memo для компонентов карточек
- **Дебаунс**: 300мс для поисковых запросов (если будет добавлен поиск)
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные устройства**: Свайп для горизонтальной прокрутки
- **Планшеты**: Сохранение размеров карточек 80×112px
- **Десктоп**: Полная функциональность с клавиатурной навигацией
- **Высокие разрешения**: Сохранение пропорций и читаемости
**ПРАВИЛА БЕЗОПАСНОСТИ И ВАЛИДАЦИИ:**
- **Валидация данных**: Проверка существования product.id перед добавлением
- **Дубликаты**: Предотвращение добавления одного товара дважды в детальный каталог
- **Санитизация**: Безопасное отображение названий товаров (XSS защита)
- **Обработка ошибок**: Graceful degradation при ошибках загрузки изображений
- **Защита от спама**: Дебаунс кликов 200мс для предотвращения множественных добавлений
**ПРАВИЛА ИНТЕГРАЦИИ С ДРУГИМИ БЛОКАМИ:**
- **Блок 1 (Поставщики)**: Слушает изменения selectedSupplier для обновления товаров
- **Блок 3 (Детальный каталог)**: Передаёт выбранные товары через setAllSelectedProducts
- **Блок 4 (Корзина)**: Товары добавляются в корзину из Блока 3, не напрямую из Блока 2
- **Синхронизация состояний**: Реактивное обновление при изменении данных в любом блоке
**ПРАВИЛА АНАЛИТИКИ И МЕТРИК:**
- **Отслеживание кликов**: Логирование добавления товаров в детальный каталог
- **Метрики производительности**: Время загрузки товаров поставщика
- **Пользовательское поведение**: Количество просмотренных товаров на поставщика
- **A/B тестирование**: Готовность к тестированию различных размеров карточек
**ПРАВИЛА ЛОКАЛИЗАЦИИ:**
- **Alt-текст изображений**: На языке интерфейса пользователя
- **Направление скролла**: RTL поддержка для арабского/иврита
- **Размеры карточек**: Неизменны для всех локалей (80×112px)
- **Сообщения об ошибках**: Локализованные уведомления при проблемах загрузки
#### **9.2.1.1 Заголовок и поиск Блока 1**
**МИНИМАЛИСТИЧНЫЙ ДИЗАЙН:**
```jsx
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-white/40 h-4 w-4" />
<Input
placeholder="Поиск поставщиков..."
className="bg-white/5 border-white/10 text-white placeholder:text-white/50 pl-10 h-9"
/>
</div>
</div>
</div>
```
**ПРАВИЛА ЗАГОЛОВКА:**
- **Иконка**: Building2 h-5 w-5 text-blue-400 (без фонового контейнера)
- **Текст**: "Поставщики" (убран избыточный "товаров")
- **Размер**: text-lg font-semibold (увеличен для лучшей читаемости)
- **БЕЗ бэджа**: Убран избыточный бэдж "Создание поставки"
- **Выравнивание**: flex items-center gap-2 (компактное)
**ПРАВИЛА ПОИСКА:**
- **Позиция**: Справа от заголовка (justify-between)
- **Ширина**: w-64 (256px) фиксированная ширина
- **Плейсхолдер**: "Поиск поставщиков..." (конкретное описание)
- **Иконка**: Search h-4 w-4 слева в поле
- **Стили**: Стандартные glass-эффекты, focus:border-white/20
**ПРАВИЛА КНОПКИ "НАЙТИ В МАРКЕТЕ":**
- **Условие**: Показывается только при allCounterparties.length === 0
- **Позиция**: Отдельный блок под заголовком (mt-4)
- **НЕ интегрирована**: В поле поиска (отдельно)
- **Стили**: glass-secondary outline button размера sm
#### **9.2.1.2 Структура карточки поставщика в Блоке 1**
**МИНИМАЛИСТИЧНАЯ КАРТОЧКА ПОСТАВЩИКА:**
**СТРУКТУРА ИНФОРМАЦИИ:**
```jsx
<div className="flex items-start gap-2">
<OrganizationAvatar organization={supplier} size="sm" />
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm truncate">{supplier.name || supplier.fullName}</h4>
<div className="flex items-center gap-2 mt-1">
<p className="text-white/60 text-xs font-mono">ИНН: {supplier.inn}</p>
{supplier.market && <Badge className="market-badge">{getMarketLabel(supplier.market)}</Badge>}
</div>
</div>
</div>
```
**ПРАВИЛА СОДЕРЖАНИЯ КАРТОЧКИ:**
**✅ ОСТАВИТЬ:**
- **Аватар организации**: OrganizationAvatar size="sm" слева
- **Название поставщика**: supplier.name || supplier.fullName (приоритет name)
- **ИНН**: font-mono, text-white/60, с префиксом "ИНН: "
**🔸 ДОБАВИТЬ:**
- **Принадлежность к рынку**: Badge с названием рынка из supplier.market
- **Рынки**: "Садовод", "ТЯК Москва" и другие из Organization.market поля
**❌ УБРАТЬ:**
- **Рейтинг**: Звездочка и цифра rating (избыточно)
- **Тип бэдж**: "Поставщик" badge (и так понятно из контекста)
- **Адрес**: supplier.address (занимает место, не критично)
**СТИЛИ РЫНОЧНЫХ БЭДЖЕЙ:**
- **Садовод**: bg-green-500/20 text-green-300 border-green-500/30
- **ТЯК Москва**: bg-blue-500/20 text-blue-300 border-blue-500/30
- **По умолчанию**: bg-gray-500/20 text-gray-300 border-gray-500/30
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные**: Сохранение структуры, truncate для длинных названий
- **Планшеты/десктоп**: Полное отображение в сетке
- **Малые экраны**: line-clamp-1 для названия организации
**СОСТОЯНИЯ КАРТОЧКИ:**
- **Default**: bg-white/5 border-white/10
- **Hover**: hover:border-white/20 hover:bg-white/10
- **Selected**: bg-white/15 border-white/40 shadow-lg
- **Disabled**: opacity-50 cursor-not-allowed (при недоступности)
**ПРАВИЛА ИНТЕГРАЦИИ С РЫНКАМИ:**
**ИСТОЧНИК ДАННЫХ:**
- **Поле БД**: Organization.market (String?) - поле принадлежности к рынку
- **Настройка**: Указывается в настройках кабинета поставщика
- **Опциональность**: Поле может быть пустым (рынок не указан)
**ФУНКЦИЯ getMarketLabel():**
```jsx
const getMarketLabel = (market?: string) => {
const marketLabels = {
'sadovod': 'Садовод',
'tyak-moscow': 'ТЯК Москва',
'opt-market': 'ОПТ Маркет',
}
return marketLabels[market as keyof typeof marketLabels] || market
}
```
**СТИЛИ ДЛЯ РЫНКОВ:**
```jsx
const getMarketBadgeStyle = (market?: string) => {
const styles = {
'sadovod': 'bg-green-500/20 text-green-300 border-green-500/30',
'tyak-moscow': 'bg-blue-500/20 text-blue-300 border-blue-500/30',
'opt-market': 'bg-purple-500/20 text-purple-300 border-purple-500/30',
}
return styles[market as keyof typeof styles] || 'bg-gray-500/20 text-gray-300 border-gray-500/30'
}
```
**ПРАВИЛА ОТОБРАЖЕНИЯ:**
- **Условие**: Показывать badge только если supplier.market существует
- **Размер**: text-xs для соответствия ИНН
- **Позиция**: Справа от ИНН в той же строке
- **Приоритет**: Рынок важнее типа организации для селлера
### 9.2.2.2 ПРАВИЛО ПЕРСИСТЕНТНОСТИ ВЫБРАННЫХ ТОВАРОВ
**🎯 ОСНОВНОЙ ПРИНЦИП:**
Выбранные товары в детальном каталоге (блок 3) сохраняются при смене поставщика и могут быть удалены только явным действием пользователя.
**🔄 WORKFLOW СЦЕНАРИИ:**
**СЦЕНАРИЙ 1: Добавление товаров от разных поставщиков**
1. Пользователь выбирает Поставщика А
2. Добавляет Товар 1 и Товар 2 в детальный каталог
3. Переключается на Поставщика Б
4. Товар 1 и Товар 2 остаются в блоке 3
5. Добавляет Товар 3 от Поставщика Б
6. В блоке 3: Товар 1, Товар 2 (от А) + Товар 3 (от Б)
**СЦЕНАРИЙ 2: Визуальная индикация в блоке 2**
- При переключении на поставщика, товары которого уже есть в блоке 3, показываются как "выбранные"
- Товары от других поставщиков в блоке 2 не отображаются
**🛠️ ТЕХНИЧЕСКИЕ ПРАВИЛА:**
**Состояние selectedProductsForDetailView:**
- Глобальное состояние всех выбранных товаров
- НЕ зависит от текущего поставщика
- НЕ очищается при смене поставщика
- Очищается только явными действиями пользователя
**Единственные способы удаления:**
1. Кнопка "Удалить из каталога" в карточке товара (блок 3)
2. Кнопка "Очистить каталог" в заголовке блока 3
3. НЕ при смене поставщика
**🎨 UX ПРАВИЛА:**
- Счетчик товаров: "Детальный каталог (X товаров от Y поставщиков)"
- Визуальная индикация выбранных товаров в блоке 2
- Информация о поставщике для каждого товара в блоке 3
**СОСТОЯНИЯ БЛОКА:**
- **Не выбран поставщик**: Заглушка "Выберите поставщика для просмотра товаров"
- **Поставщик выбран, нет товаров**: "У поставщика нет товаров"
- **Поставщик выбран, есть товары**: Карточки товаров с горизонтальным скроллом
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Горизонтальная прокрутка мышью, клавишами ←→
- **Выбор**: Клик → добавление в Блок 3 с анимацией
- **Состояния карточек**: Default, Selected, Active (при добавлении)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-5 карточек**: Скролл неактивен, выравнивание по левому краю
- **6+ карточек**: Полноценный горизонтальный скролл
- **Поиск**: Фильтрация карточек в реальном времени
- **Загрузка**: Скелетон-анимация при смене поставщика
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Содержание**: Детальный каталог товаров для управления поставкой
- **Источник**: Товары, добавленные из Блока 2 "Карточки товаров"
- **Сортировка**: По цене, названию, категории
- **Фильтры**: По категории, ценовому диапазону
- **Карточка расходника**:
- Фото, название, цена, остаток, категория
- Количество в комплекте (если есть комплектность)
- Поле ввода количества (единицы или комплекты)
- Кнопки +/- для изменения количества
- **Действие**: Клик добавляет расходник в корзину
**БЛОК 3: КОРЗИНА** _(правая часть)_
- **Содержание корзины**:
- Количество видов расходников
- По каждому расходнику: название, количество, цена за единицу, сумма
- Общая сумма всех расходников
- **Управление**: Изменение количества, удаление позиций
- **Валидация**: Проверка остатков у поставщика
- **Настройки поставки**:
- Выбор фулфилмент-центра (dropdown из партнеров)
- Дата поставки (по умолчанию - дата создания, нельзя выбрать прошедшую)
- **Кнопка**: "Создать поставку"
### 9.3 Многоуровневые таблицы для отображения поставок
#### **📊 Структура многоуровневой таблицы:**
**ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- Порядковый номер поставки (от большего к меньшему)
- Количество видов расходников селлера
- Стоимость всей поставки
- Количество категорий
- Статус поставки
- Кнопка раскрытия/сворачивания
**ВТОРОЙ УРОВЕНЬ** _(раскрывается по клику)_:
- Название расходника селлера
- Количество
- Цена за единицу
- Общая стоимость позиции
- Категория
- Поставщик
- **Режим**: Только просмотр (редактирование недоступно после создания)
**ПРАВИЛА ОТОБРАЖЕНИЯ**:
- По умолчанию таблица свернута, показан только первый уровень
- Клик по строке или кнопке раскрывает второй уровень
- Анимация раскрытия плавная (300ms)
- Визуальная индикация раскрытого состояния (поворот стрелки, изменение фона)
### 9.4 Правила кнопки "Создать поставку" в разделе "Мои поставки"
#### **9.4.1 Общие принципы**
- **КОНТЕКСТНОСТЬ**: Кнопка создания появляется только в активном табе
- **РАСПОЛОЖЕНИЕ**: Правая часть строки таба, на том же уровне что и название
- **СТИЛИСТИКА**: В том же стиле что и сами табы (соответствует уровню иерархии)
- **ФУНКЦИОНАЛЬНОСТЬ**: Кнопка ведет на страницу создания поставки соответствующего типа
#### **9.4.2 Размещение кнопок по табам**
**УРОВЕНЬ 2 (Подтабы фулфилмента):**
- **📦 Товар → Карточки**: Кнопка "Создать поставку" → `/supplies/create-cards`
- **📦 Товар → Поставщики**: Кнопка "Создать поставку" → `/supplies/create-suppliers`
- **🔧 Расходники селлера**: Кнопка "Создать поставку" → `/supplies/create-consumables`
**УРОВЕНЬ 2 (Подтабы маркетплейсов):**
- **🟣 Wildberries**: Кнопка "Создать поставку" → `/supplies/create-wildberries`
- **🔵 Ozon**: Кнопка "Создать поставку" → `/supplies/create-ozon`
#### **9.4.3 Стили кнопок**
**ДЛЯ УРОВНЯ 2 (h-9):**
```css
/* Размер и отступы */
h-9 px-3 py-1 ml-auto
/* Фон и границы */
bg-white/8 border border-white/20 hover:bg-white/12
/* Текст и иконки */
text-xs font-medium text-white/80 hover:text-white
/* Скругления */
rounded-lg
/* Переходы */
transition-all duration-150
```
**ДЛЯ УРОВНЯ 3 (h-8):**
```css
/* Размер и отступы */
h-8 px-2 py-1 ml-auto
/* Фон и границы */
bg-white/5 border border-white/15 hover:bg-white/8
/* Текст и иконки */
text-xs font-normal text-white/60 hover:text-white/80
/* Скругления */
rounded-md
/* Переходы */
transition-all duration-150
```
#### **9.2.4 Поведение кнопок**
- **ВИДИМОСТЬ**: Кнопка показывается только в активном табе
- **ИКОНКА**: `Plus` размером `h-3 w-3` слева от текста
- **ТЕКСТ**: "Создать" на мобильных, "Создать поставку" на десктопах
- **АДАПТИВНОСТЬ**: Скрытие текста на маленьких экранах (`hidden sm:inline`)
#### **9.2.5 Удаление старой кнопки**
- **УБРАТЬ**: Текущий dropdown "Создать поставку" из верхней части
- **ПРИЧИНА**: Заменяется контекстными кнопками в табах
- **СОХРАНИТЬ**: Стили и логику навигации, но адаптировать под новые роуты
#### **9.2.6 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ**
**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.
##### **9.2.6.1 Размеры и позиционирование**
```tsx
<div className="w-72 flex-shrink-0">
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```
**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:
- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`
##### **9.2.6.2 Автодобавление товаров**
**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.
```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)
if (newQuantity > 0) {
// Автоматически добавляем товар в корзину
updateProductQuantity(product.id, newQuantity)
} else {
// Удаляем товар из корзины при количестве 0
removeFromCart(product.id)
}
}
```
**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`
##### **9.2.6.3 Структура корзины**
**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:
1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом
**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине
##### **9.2.6.4 Единая функция расчета стоимости**
**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:
```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
const product = products.find((p) => p.id === productId)
if (!product) return 0
// Базовая цена товара
let total = (product.pricePerUnit || 0) * quantity
// Добавляем услуги
if (product.services && product.services.length > 0) {
const servicesTotal = product.services.reduce((sum, service) => {
return sum + (service.pricePerUnit || 0) * quantity
}, 0)
total += servicesTotal
}
// Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
if (product.ffConsumables && product.ffConsumables.length > 0) {
const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
}, 0)
total += ffConsumablesTotal
}
// Добавляем расходники продавца
if (product.sellerConsumables && product.sellerConsumables.length > 0) {
const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
return sum + (consumable.pricePerUnit || 0) * quantity
}, 0)
total += sellerConsumablesTotal
}
return total
}
```
##### **9.2.6.5 Синхронизация данных между блоками**
**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:
1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`
**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:
```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```
##### **9.2.6.6 Критические требования**
🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:
- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов
🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:
- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества
🚨 **UX КОНСИСТЕНТНОСТЬ**:
- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных
### 9.3 Структура страницы "Мои поставки" - Трёхблочная архитектура
#### **9.3.1 Обязательная структура страницы**
**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков
```
┌─────────────────────────────────────────┐
│ 1. БЛОК ТАБОВ (навигация) │
│ - Фиксированная высота │
│ - Glass-эффект │
│ - Иерархическая структура │
├─────────────────────────────────────────┤
│ 2. БЛОК СТАТИСТИКИ (метрики) │
│ - Контекстные данные │
│ - 4 карточки в ряд (desktop) │
│ - Динамическое обновление │
├─────────────────────────────────────────┤
│ 3. ОСНОВНОЙ БЛОК (контент) │
│ - Сохраняет весь функционал │
│ - Таблицы, фильтры, действия │
│ - Высота до низа sidebar │
└─────────────────────────────────────────┘
```
#### **9.3.2 Блок статистики - контекстные метрики**
**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов
**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**
- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути
**Для пути "Фулфилмент → Расходники селлера":**
- Всего поставок
- Активных поставок
- Видов расходников
- Критические остатки
**Для путей "Маркетплейсы → Wildberries/Ozon":**
- Поставок на маркетплейс
- Товаров отправлено
- Возвраты за неделю
- Эффективность поставок
#### **9.3.3 Высота основного блока**
**ФОРМУЛА РАСЧЕТА**:
```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```
**ПРАВИЛО ВЫРАВНИВАНИЯ**:
- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`
#### **9.3.4 Сохранение функционала**
**КРИТИЧЕСКИ ВАЖНО**: При добавлении блока статистики весь существующий функционал сохраняется:
- Таблицы с данными поставок
- Фильтры и сортировка
- Кнопки действий
- Детализация при клике
- Пагинация
- Поиск
**ЗАПРЕЩЕНО**:
- Удалять существующие компоненты
- Изменять логику работы таблиц
- Нарушать существующие API вызовы
### 9.4 Табы "Карточки" и "Поставщики" - объединённая логика
#### **9.4.1 Принцип единого типа предмета**
**КЛЮЧЕВОЕ ПРАВИЛО**: Табы "Карточки" и "Поставщики" - это два способа создания поставок одного типа предмета (ТОВАР)
**СПОСОБЫ СОЗДАНИЯ**:
- **Карточки** - импорт товаров через WB API с автоматическим созданием поставки
- **Поставщики** - прямой заказ товаров у поставщика с указанием рецептуры
**РЕЗУЛЬТАТ**: Оба способа создают `SupplyOrder` с товарами типа `PRODUCT`
#### **9.4.2 Общая статистика**
**ПРАВИЛО**: Блок статистики показывает ОДИНАКОВЫЕ данные для обоих табов
**МЕТРИКИ ДЛЯ ТАБОВ "КАРТОЧКИ" И "ПОСТАВЩИКИ"**:
- Всего поставок товаров (из всех источников)
- Активных поставок товаров (в работе)
- Сумма активных поставок товаров
- Товаров в пути (все способы доставки)
**ЗАПРЕЩЕНО**: Разделять статистику по способу создания
#### **9.4.3 Общий основной блок**
**СОДЕРЖИМОЕ**: Единая таблица всех поставок товаров
**ИСТОЧНИКИ ДАННЫХ**:
- Поставки, созданные через импорт карточек WB
- Поставки, созданные через заказ у поставщиков
- Все промежуточные и завершённые поставки
**РАЗЛИЧИЯ ТАБОВ**:
- Только кнопки создания ведут на разные страницы
- Таб "Карточки": `/supplies/create-cards`
- Таб "Поставщики": `/supplies/create-suppliers`
### 9.5 Создание поставки расходников селлера
#### **Структура страницы**:
**БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_:
- **Навигация**: Плавающая кнопка "Назад" между сайдбаром и контентом (см. seller-ui-rules.md)
- **БЕЗ заголовка** - блок начинается сразу с поиска и карточек
- Карточки поставщиков из раздела "Партнеры"
- Горизонтальный скролл при превышении ширины
- Выбор только одного поставщика одновременно
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(адаптивная высота - НОВЫЙ БЛОК)_:
- ТОЛЬКО минималистичные карточки товаров 80×112px
- ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- Горизонтальный скролл при множестве товаров
- Клик добавляет товар в блок 3
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(flex-1, детальный каталог)_:
- Детальные карточки выбранных товаров
- Управление количеством и параметрами поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель, 384px)_:
- Корзина поставки с выбранными товарами
- Настройки поставки (фулфилмент-центр, дата, логистика)
- Сортировка: цена, название, категория
- Фильтры: категория, ценовой диапазон
- Карточка с полем ввода количества и кнопками +/-
**БЛОК 3: КОРЗИНА** _(правая часть)_:
- **РАСПОЛОЖЕНИЕ**: Правая часть экрана
- **СОДЕРЖАНИЕ**:
- Счетчик видов расходников
- Детализация по каждому расходнику (название, количество, цена, сумма)
- Общая сумма всех расходников
- **УПРАВЛЕНИЕ**:
- Изменение количества (с валидацией остатков)
- Удаление позиций
- **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ**:
- Выбор фулфилмент-центра (из партнеров)
- Дата поставки (не прошедшая, по умолчанию - текущая)
### 9.6 Многоуровневая таблица поставок
#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
- Порядковый номер поставки
- Количество видов расходников
- Стоимость всей поставки
- Количество категорий
- Статус поставки
#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:
- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
- Название расходника
- Количество
- Цена
- Категория
- Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено
---
## 10. 🏪 КАБИНЕТ ПОСТАВЩИКА
> 📖 **Технические детали кабинета**: См. [wholesale-cabinet-rules.md](./wholesale-cabinet-rules.md) для компонентов, GraphQL и UI/UX
### 10.1 Разделение понятий: РЫНОК vs МАРКЕТ
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ ПОНЯТИЙ:**
### **РЫНОК** 🏪 - физическое торговое место
- **Назначение**: Географическая принадлежность поставщиков
- **Примеры**: Садовод, ТЯК Москва
- **Структура**: Название + адрес
- **Связь**: Поставщик принадлежит рынку
### **МАРКЕТ** 🛒 - раздел системы для торговли
- **Назначение**: Глобальный каталог товаров в системе
- **Роут**: `/market` - просмотр и заказ товаров
- **Содержание**: Все доступные товары от всех поставщиков
- **Связь**: НЕ связан с физическими рынками
**🏢 АРХИТЕКТУРА ПРИНАДЛЕЖНОСТИ:**
```
РЫНОК (физическое место)
└── Поставщик (Organization.market)
└── Товары/Расходники (наследуют рынок от поставщика)
└── Отображаются в МАРКЕТЕ (/market)
```
**🎯 ПРИНЦИПЫ ИЕРАРХИИ:**
1. **РЫНОК → ПОСТАВЩИК**: Поставщик работает на конкретном рынке
2. **ПОСТАВЩИК → ТОВАРЫ**: Товары принадлежат поставщику с его рынка
3. **ТОВАРЫ → МАРКЕТ**: Все товары показываются в глобальном маркете (/market)
4. **НАСЛЕДОВАНИЕ**: Товары получают рынок от организации поставщика
**🏪 ФИЗИЧЕСКИЕ РЫНКИ В СИСТЕМЕ:**
- **"Садовод"** (`sadovod`) - Москва, 14-й км МКАД
- **Цветовая схема**: `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (`tyak-moscow`) - Москва, Алтуфьевское шоссе, 27
- **Цветовая схема**: `bg-blue-500/20 text-blue-300 border-blue-500/30`
**🛒 МАРКЕТ В СИСТЕМЕ:**
- **Роут**: `/market` - глобальный каталог товаров
- **Функции**: Просмотр, поиск, фильтрация, заказ товаров
- **Источник**: Товары от всех поставщиков всех рынков
- **Отображение рынка**: В карточках поставщиков и товаров
**🔧 ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
- **Поле рынка**: `Organization.market` (String?) - принадлежность поставщика к рынку
- **Настройка рынка**: В настройках организации поставщика
- **Отображение в маркете**: Товары показывают рынок через `product.organization.market`
- **Фильтрация**: В маркете по рынку поставщика
### 10.2 Основные возможности
**СОЗДАНИЕ КАРТОЧЕК**:
- **ТОВАР** - базовые товары поставщика
- **РАСХОДНИКИ** - материалы и вспомогательные товары
### 10.3 Обязательные поля карточки
**Базовые параметры**:
- Фото (система загрузки и управления изображениями)
- Название
- Автоматическая генерация артикула СФ
- Описание
- Количество предметов в единицах
- Количество комплектов (если применимо)
- Категория (28 предустановленных + специализированные для расходников)
- Бренд, Цвет, Размер/объем, Вес, Габариты, Материал
- Цена за единицу и за комплект
- Заказано, В пути, Остаток, Продано
### 10.4 Отображение информации в карточках
**Каждая карточка содержит**:
- Основное изображение
- Название и артикул СФ
- Цена за единицу/комплект
- Категория и статус активности
- Данные о движении: остаток, заказано, в пути, продано
- Индикаторы низких остатков
### 10.5 Статистика поставщика
**Блок статистики включает**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары
- Классифицируются при заказе в зависимости от заказчика
- Общая статистика по всем расходникам
---
## 11. 🏭 КАБИНЕТ ФУЛФИЛМЕНТА
> 📖 **Технические детали кабинета**: См. [fulfillment-cabinet-rules.md](./fulfillment-cabinet-rules.md) для компонентов, GraphQL, UI/UX и всех технических деталей реализации
### 11.1 Основные функции фулфилмента
**РОЛЬ В СИСТЕМЕ**: Обработка товаров и предоставление услуг
**ОСНОВНЫЕ ФУНКЦИИ**:
- **ПРИЕМКА ТОВАРОВ**: Получение и обработка поставок от поставщиков
- **СОЗДАНИЕ ПРОДУКТОВ**: Превращение товаров в готовые продукты по рецептурам
- **ПРЕДОСТАВЛЕНИЕ УСЛУГ**: Услуги обработки для селлеров
- **УПРАВЛЕНИЕ РАСХОДНИКАМИ**: Установка цен и контроль наличия
- **ЛОГИСТИЧЕСКИЕ УСЛУГИ**: Маршруты доставки и тарификация
### 11.2 Workflow фулфилмента
См. детальное описание в [workflow-catalog.md#4-workflow-фулфилмента](./workflow-catalog.md#4-workflow-фулфилмента)
### 11.3 Основные разделы кабинета
**СТРУКТУРА ДОСТУПА**:
- **Склад** - управление товарами по модулям
- **Поставки** - обработка входящих товаров
- **Услуги** - каталог услуг и расходники
- **Сотрудники** - управление персоналом
- **Статистика** - аналитика деятельности
### 11.4 Правила фулфилмента
**ОБЯЗАТЕЛЬНО**:
- Установка цен на расходники перед доступностью селлерам
- Контроль качества товаров при приемке
- Своевременная обработка возвратов
- Ведение учета движения товаров
- Управление персоналом и рабочим временем
**ЗАПРЕЩЕНО**:
- Отгружать товары без подтверждения наличия
- Создавать расходники минуя систему поставок
- Изменять цены закупки после поступления товара
- Показывать в рецептурах неактивные расходники
---
## 12. 🚚 КАБИНЕТ ЛОГИСТИКИ
### 12.1 Основные функции логистики
**РОЛЬ В СИСТЕМЕ**: Управление доставками и транспортировкой
**ОСНОВНЫЕ ФУНКЦИИ**:
- **ПОДТВЕРЖДЕНИЕ ДОСТАВКИ**: Подтверждение возможности доставки поставок
- **ТРАНСПОРТИРОВКА**: Организация и выполнение доставки товаров
- **КОНТРОЛЬ МАРШРУТОВ**: Управление логистическими маршрутами
- **ОТСЛЕЖИВАНИЕ**: Мониторинг грузов в пути
### 12.2 Workflow для логистики
См. детальное описание в [workflow-catalog.md#5-workflow-логистики](./workflow-catalog.md#5-workflow-логистики)
### 12.3 Система тарификации
**ПАРАМЕТРЫ ТАРИФИКАЦИИ**:
- **Тариф до 1м³** - базовая стоимость для малых грузов
- **Тариф свыше 1м³** - стоимость для крупных грузов
- **Маршруты доставки** - от точки отправления до точки назначения
- **Описание услуг** - дополнительные условия доставки
**РАСЧЕТ СТОИМОСТИ**:
- Автоматический расчет стоимости доставки по объему груза
- Отображение примерной стоимости при создании заказа
- Учет специфики маршрута и условий доставки
### 12.4 Управление заявками
**РАЗДЕЛЫ КАБИНЕТА ЛОГИСТИКИ**:
- **НОВЫЕ ЗАЯВКИ** - поступившие заявки на доставку
- **В РАБОТЕ** - принятые к исполнению заявки
- **ВЫПОЛНЕННЫЕ** - завершенные доставки
- **ОТКЛОНЕННЫЕ** - заявки, которые не могут быть выполнены
**ИНФОРМАЦИЯ О ЗАЯВКЕ**:
- Детали груза (объем, вес, габариты)
- Маршрут доставки (откуда - куда)
- Срочность доставки
- Особые требования к транспортировке
- Контактная информация участников
### 12.5 Правила логистики
**ОБЯЗАТЕЛЬНО**:
- Своевременное подтверждение заявок
- Соблюдение сроков доставки
- Бережная транспортировка товаров
- Уведомление о статусе доставки
**ЗАПРЕЩЕНО**:
- Принятие заявок без подтверждения возможности выполнения
- Нарушение сроков доставки без уведомления
- Повреждение товаров при транспортировке
---

View File

@ -0,0 +1,1371 @@
rules-complete2
**ЗАПРЕЩЕНО РЕДАКТИРОВАТЬ БЕЗ ЯВНОГО РАЗРЕШЕНИЯ ПОЛЬЗОВАТЕЛЯ!**
## 13. 🤝 СИСТЕМА ПАРТНЕРСТВА И КОНТРАГЕНТОВ
### 13.1 Основы системы партнерства
**ПРИНЦИП РАБОТЫ**:
- Все типы кабинетов могут создавать партнерские отношения
- Партнерство реализовано через таблицы `Counterparty` и `CounterpartyRequest`
- Двустороннее партнерство: каждая организация видит другую в разделе "Партнеры"
**ТИПЫ ОРГАНИЗАЦИЙ-ПАРТНЕРОВ**:
- `WHOLESALE` - Поставщики товаров и расходников
- `FULFILLMENT` - Фулфилмент-центры
- `LOGIST` - Логистические компании
- `SELLER` - Селлеры (торговые организации)
### 13.2 Способы создания партнерства
#### **СПОСОБ 1: Через заказ в маркете (автоматическое партнерство)**
**WORKFLOW**:
1. Поставщик создает товар → товар попадает в глобальный маркет
2. Селлер/Фулфилмент находит товар в маркете
3. Создает заказ (`SupplyOrder`) → статус `PENDING`
4. Поставщик получает уведомление в разделе "Заявки"
5. Поставщик одобряет заявку → статус `SUPPLIER_APPROVED`
6. **Автоматически создается двустороннее партнерство**:
- Запись в `Counterparty` для заказчика (`organizationId``counterpartyId`)
- Обратная запись в `Counterparty` для поставщика
7. Обе организации видят друг друга в разделе "Партнеры"
#### **СПОСОБ 2: Через раздел "Партнеры" (заявочная система)**
**WORKFLOW**:
1. Любая организация идет в раздел "Партнеры"
2. Использует поиск для нахождения нужной организации
3. Отправляет заявку на партнерство → создается `CounterpartyRequest`:
- `senderId` - отправитель заявки
- `receiverId` - получатель заявки
- `status: PENDING`
- `message` - опциональное сообщение
4. Получатель видит заявку в разделе "Партнеры" → "Входящие заявки"
5. Получатель принимает заявку → статус меняется на `ACCEPTED`
6. **Автоматически создается двустороннее партнерство** (аналогично способу 1)
**СТАТУСЫ ЗАЯВОК**:
- `PENDING` - Ожидает рассмотрения
- `ACCEPTED` - Принята (партнерство создано)
- `REJECTED` - Отклонена
- `CANCELLED` - Отменена отправителем
### 13.3 Использование партнерства в системе
#### **В форме создания поставки товаров через поставщиков**
**ПРАВИЛО ОТОБРАЖЕНИЯ ПОСТАВЩИКОВ**:
- Показываются только партнеры с типом `WHOLESALE`
- Источник: таблица `Counterparty` where `counterparty.type === "WHOLESALE"`
- Фильтрация по `organizationId` текущего пользователя
**ЛОГИКА РАБОТЫ**:
1. Пользователь выбирает поставщика из dropdown партнеров-поставщиков
2. Загружается каталог товаров поставщика из `Product` таблицы
3. Товары фильтруются по `organizationId = поставщик.id`
4. Пользователь может добавлять товары в корзину и создавать заказ
#### **В других разделах системы**
**ВЫБОР ФУЛФИЛМЕНТ-ЦЕНТРА**:
- Партнеры с типом `FULFILLMENT`
- Используется при создании поставок расходников
**ВЫБОР ЛОГИСТИКИ**:
- Партнеры с типом `LOGIST`
- Используется при планировании доставок
**МЕССЕНДЖЕР**:
- Общение доступно только между партнерами
- Список чатов формируется из таблицы `Counterparty`
### 13.4 Технические правила
**СОЗДАНИЕ ЗАПИСЕЙ В COUNTERPARTY**:
```sql
-- При создании партнерства создаются ДВЕ записи
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org1_id, org2_id);
INSERT INTO counterparties (organizationId, counterpartyId) VALUES (org2_id, org1_id);
```
**ПРОВЕРКА ПАРТНЕРСТВА**:
```typescript
const isPartner = await prisma.counterparty.findFirst({
where: {
organizationId: currentOrgId,
counterpartyId: targetOrgId,
},
})
```
**ПОЛУЧЕНИЕ ПАРТНЕРОВ ПО ТИПУ**:
```typescript
const wholesalePartners = await prisma.counterparty.findMany({
where: {
organizationId: currentOrgId,
counterparty: {
type: 'WHOLESALE',
},
},
include: {
counterparty: true,
},
})
```
### 13.5 Решение распространенных проблем
#### **ПРОБЛЕМА: GraphQL запрос не возвращает данные партнеров**
**Симптомы**:
- В консоли браузера: `All counterparties: 0`, `All counterparties data: []`
- GraphQL запрос отправляется успешно, но возвращает пустой массив
- В базе данных партнеры существуют
**Возможные причины и решения**:
1. **НЕПРАВИЛЬНОЕ ИМЯ ПОЛЯ В КОДЕ** (наиболее частая ошибка):
```typescript
// ❌ НЕПРАВИЛЬНО
const allCounterparties = counterpartiesData?.getMyCounterparties || []
// ✅ ПРАВИЛЬНО
const allCounterparties = counterpartiesData?.myCounterparties || []
```
**Объяснение**: В GraphQL схеме поле называется `myCounterparties`, а не `getMyCounterparties`
2. **НЕСООТВЕТСТВИЕ ID ПОЛЬЗОВАТЕЛЯ**:
- Проверить что пользователь авторизован под правильным аккаунтом
- Убедиться что `context.user.id` соответствует ожидаемому пользователю
3. **ПРОБЛЕМЫ С КЕШИРОВАНИЕМ APOLLO CLIENT**:
```typescript
const { data, loading, error } = useQuery(GET_MY_COUNTERPARTIES, {
fetchPolicy: 'network-only', // Обходим кеш
errorPolicy: 'all',
})
```
4. **ОТСУТСТВИЕ ЛОГИРОВАНИЯ В РЕЗОЛВЕРЕ**:
- Добавить console.log в GraphQL резолвер для отладки
- Проверить что резолвер вызывается
**Чек-лист для диагностики**:
- [ ] Проверить правильность имени поля в коде (`myCounterparties`)
- [ ] Убедиться что пользователь авторизован
- [ ] Проверить логи сервера на вызов резолвера
- [ ] Добавить отладочное логирование в браузере
- [ ] Проверить данные в базе через Prisma Studio
- [ ] Использовать `fetchPolicy: 'network-only'` для обхода кеша
### 13.6 Различие партнерских и реферальных ссылок
⚠️ **КРИТИЧЕСКИ ВАЖНО**: НЕ ПУТАТЬ два различных типа ссылок в системе!
#### **13.6.1 Партнерские ссылки**
**НАЗНАЧЕНИЕ**: Бизнес-партнерство с автоматическим добавлением в контрагенты
**ФОРМАТ URL**: `?partner=REFERRAL_CODE`
```
http://localhost:3000/register?partner=SF2X9K4M7P
```
**ЧТО ПРОИСХОДИТ**:
1. ✅ Начисляется 100 сфер (⚡) реферальная награда
2. ✅ **Автоматически создается партнерство**: взаимное добавление в контрагенты
3. ✅ Устанавливается реферальная связь (`referredById`)
4. ✅ Создаются записи в таблице `Counterparty` (двусторонние)
5. ✅ Организации видят друг друга в разделе "Партнеры"
**ИСПОЛЬЗОВАНИЕ**: Когда нужно сразу стать деловыми партнерами и начать работать
#### **13.6.2 Реферальные ссылки**
**НАЗНАЧЕНИЕ**: Маркетинговое привлечение с наградой, БЕЗ автоматического партнерства
**ФОРМАТ URL**: `?ref=REFERRAL_CODE`
```
http://localhost:3000/register?ref=SF2X9K4M7P
```
**ЧТО ПРОИСХОДИТ**:
1. ✅ Начисляется 100 сфер (⚡) реферальная награда
2. ✅ Устанавливается реферальная связь (`referredById`)
3. ❌ **НЕ создается партнерство**: организации НЕ добавляются в контрагенты
4. ❌ Организации НЕ видят друг друга в разделе "Партнеры"
**ИСПОЛЬЗОВАНИЕ**: Маркетинговые кампании, блогеры, инфлюенсеры
#### **13.6.3 Технические различия в коде**
**В резолверах регистрации**:
```typescript
// Обработка партнерского кода (создает партнерство)
if (partnerCode) {
// 1. Найти организацию-партнера
// 2. Создать реферальную транзакцию
// 3. Установить реферальную связь
// 4. СОЗДАТЬ ВЗАИМНОЕ ПАРТНЕРСТВО ← Ключевое отличие!
}
// Обработка реферального кода (только награда)
if (referralCode) {
// 1. Найти организацию-реферера
// 2. Создать реферальную транзакцию
// 3. Установить реферальную связь
// 4. БЕЗ создания партнерства ← Ключевое отличие!
}
```
#### **13.6.4 UI различия**
**В разделе "Партнеры"**:
**Вкладка "Мои партнеры"**:
- Партнерская ссылка: `?partner=CODE` (автоматическое партнерство)
- Заголовок: "Пригласить партнера"
- Описание: "Для прямого делового сотрудничества"
**Вкладка "Рефералы"**:
- Реферальная ссылка: `?ref=CODE` (только маркетинг)
- Заголовок: "Реферальная ссылка"
- Описание: "Для маркетинговых кампаний"
#### **13.6.5 Правила именования**
**В коде ВСЕГДА использовать**:
- `partnerCode` / `partner=` → бизнес-партнерство
- `referralCode` / `ref=` → маркетинговое привлечение
**В комментариях и документации**:
- "Партнерская ссылка" → автоматическое партнерство
- "Реферальная ссылка" → только маркетинг
**ЗАПРЕЩЕНО**:
- ❌ Называть партнерские ссылки "реферальными"
- ❌ Называть реферальные ссылки "партнерскими"
- ❌ Использовать термины взаимозаменяемо
- ❌ Путать логику обработки в резолверах
#### **13.6.6 Примеры использования**
**Сценарий 1 - Деловое партнерство**:
```
Фулфилмент-центр хочет пригласить логистическую компанию
→ Использует партнерскую ссылку ?partner=CODE
→ Логисты регистрируются и сразу становятся партнерами
→ Могут сразу работать друг с другом
```
**Сценарий 2 - Маркетинговая кампания**:
```
Организация запускает рекламу в соцсетях
→ Использует реферальную ссылку ?ref=CODE
→ Люди регистрируются, организация получает сферы
→ Партнерство НЕ создается (это маркетинг)
```
---
## 14. 🌐 ИНТЕГРАЦИИ С СИСТЕМОЙ
### 14.1 Глобальная интеграция
- **МАРКЕТ**: Товары поставщиков отображаются в глобальном маркете
- **СИНХРОНИЗАЦИЯ**: Данные склада синхронизируются с модулем аналитики
- **УВЕДОМЛЕНИЯ**: Единая система через встроенный мессенджер
### 14.2 Интеграция с маркетплейсами
- **WILDBERRIES**: Обязательная проверка активности API ключа
- **СИНХРОНИЗАЦИЯ**: Регулярное обновление данных из внешних источников
- **ЛОКАЛЬНЫЕ КОПИИ**: Сохранение данных для офлайн работы
### 14.3 Интеграция с модулем "Услуги"
**РАСХОДНИКИ ФУЛФИЛМЕНТА В УСЛУГАХ**:
- Расходники фулфилмента - собственность фулфилмента (куплены у поставщиков)
- Фулфилмент создает заявки-поставки для покупки расходников у поставщиков
- Селлеры могут использовать расходники фулфилмента в разделе "Услуги / Расходники"
- Для создания продукта из товара
- Расходники списываются с остатков фулфилмента
- Стоимость включается в стоимость услуги
**WORKFLOW ИСПОЛЬЗОВАНИЯ**:
1. Селлер выбирает услугу "Создание продукта"
2. Указывает базовый товар
3. Выбирает необходимые расходники фулфилмента
4. Фулфилмент обрабатывает заказ и создает продукт
5. Расходники списываются, создается готовый продукт
---
## 15. 📊 СТАТИСТИКА И АНАЛИТИКА
### 15.1 Структура статистики по кабинетам
#### **В КАБИНЕТЕ ПОСТАВЩИКА**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары (классифицируются при заказе)
#### **В КАБИНЕТЕ ФУЛФИЛМЕНТА**:
- **ТОВАРЫ**: Базовые товары от поставщиков (принятые на склад)
- **ПРОДУКТЫ**: Отдельный блок готовой продукции
- **БРАК**: Статистика потерь и списаний
- **РАСХОДНИКИ ФУЛФИЛМЕНТА**: Операционные материалы фулфилмента
- **РАСХОДНИКИ СЕЛЛЕРОВ**: Материалы для товаров селлеров
### 15.2 Ключевые метрики
**ОБЩИЕ ПОКАЗАТЕЛИ**:
- Общие остатки, заказано, в пути, остаток, продано
- Подсветка предметов с остатками ниже критического уровня
**АКТУАЛИЗАЦИЯ ДАННЫХ**:
- При изменении количества в карточке данные актуализируются во всей системе
- Статистика обновляется в реальном времени
- Отслеживание изменений для аналитики
---
## 16. 📱 ПРАВИЛА UI/UX И ИНТЕРФЕЙСА
### 16.1 Отзывчивость интерфейса
- **ОБЯЗАТЕЛЬНО**: Интерфейс должен работать на всех устройствах
- **ПРАВИЛО**: Адаптивная сетка для карточек товаров
- **ФУНКЦИЯ**: Оптимизация для мобильных устройств
- **ТРЕБОВАНИЕ**: Корректное отображение на экранах от 320px до 4K
### 16.2 Обратная связь пользователю
- **ОБЯЗАТЕЛЬНО**: Уведомления об успешных/неуспешных операциях
- **ПРАВИЛО**: Индикаторы загрузки для длительных операций
- **ФУНКЦИЯ**: Подтверждение критических действий (удаление, деактивация)
- **UX**: Понятные сообщения об ошибках с предложением решения
### 16.3 Правила обработки ошибок
- **ОБЯЗАТЕЛЬНО**: Логирование всех ошибок с детальной информацией
- **ПРАВИЛО**: Понятные сообщения об ошибках для пользователя
- **ФУНКЦИЯ**: Автоматическое восстановление после сбоев
- **МОНИТОРИНГ**: Отслеживание критических ошибок в реальном времени
### 16.4 Производительность
- **ПРАВИЛО**: Пагинация для больших списков товаров
- **ФУНКЦИЯ**: Ленивая загрузка изображений
- **ОПТИМИЗАЦИЯ**: Кэширование часто запрашиваемых данных
- **ПРОИЗВОДИТЕЛЬНОСТЬ**: Время загрузки страницы не более 3 секунд
---
## 17. ⚠️ КРИТИЧЕСКИЕ ЗАПРЕТЫ
### 17.1 НИКОГДА НЕ ДЕЛАТЬ:
1. ❌ Удалять предметы с существующими заказами
2. ❌ Изменять статусы заказов без уведомлений
3. ❌ Обходить проверки остатков предметов
4. ❌ Давать доступ к чужим данным
5. ❌ Игнорировать ошибки валидации
6. ❌ Сохранять пароли в открытом виде
7. ❌ Пропускать логирование критических операций
8. ❌ Блокировать интерфейс без индикации загрузки
9. ❌ Создавать брак или продукт без связи с родительским товаром
10. ❌ Создавать отдельные типы расходников (только общий тип "РАСХОДНИКИ")
11. ❌ Разрешать заказ брака
12. ❌ Нарушать иерархию типов предметов
13. ❌ Пропускать промежуточные статусы в workflow
14. ❌ Нарушать обязательную последовательность модулей в статистике фулфилмента
15. ❌ **Использовать неправильные имена полей GraphQL** (`getMyCounterparties` вместо `myCounterparties`)
16. ❌ **Использовать GET_SUPPLY_SUPPLIERS для отображения поставщиков в формах** (только партнеры WHOLESALE)
17. ❌ **Создавать интерфейсы TypeScript не соответствующие schema.prisma** (`sku`/`stock` вместо `article`/`quantity`)
18. ❌ **Использовать общие запросы вместо специализированных** (`GET_ALL_PRODUCTS` вместо `GET_ORGANIZATION_PRODUCTS` для конкретного поставщика)
19. ❌ **Показывать расходники в формах создания поставок товаров** (строгая типизация `PRODUCT`/`CONSUMABLE`)
20. ❌ **Фильтровать предметы по типу на фронтенде** (фильтрация должна быть в GraphQL резолвере)
21. ❌ **ИСПОЛЬЗОВАТЬ МОКОВЫЕ ДАННЫЕ БЕЗ РАЗРЕШЕНИЯ** - все компоненты ОБЯЗАТЕЛЬНО должны использовать реальные GraphQL запросы. Моковые данные можно добавлять ТОЛЬКО с явного разрешения пользователя
22. ❌ **ДОБАВЛЯТЬ ПОЛЕ РЫНКА К ТОВАРАМ** - рынок принадлежит организации поставщика (`Organization.market`), товары наследуют рынок через связь с организацией
23. ❌ **ПУТАТЬ РЫНОК И МАРКЕТ** - РЫНОК = физическое место (Садовод, ТЯК), МАРКЕТ = раздел системы (/market)
24. ❌ **ИСПОЛЬЗОВАТЬ НАЗВАНИЯ ОРГАНИЗАЦИЙ В ЛОГИКЕ БЕЗОПАСНОСТИ** - проверки доступа только по `organization.type` и системным ID
25. ❌ **СОЗДАВАТЬ УСЛОВИЯ НА ОСНОВЕ ПОЛЬЗОВАТЕЛЬСКИХ СТРОК** - никаких `if (name.includes())` для определения функционала
26. ❌ **ПУТАТЬ ДАННЫЕ И ФУНКЦИОНАЛ** - "ОПТ Маркет" (название рынка) ≠ "Маркет" (раздел системы)
27. ❌ **ПРЕДСТАВЛЯТЬ ИНТЕРПРЕТАЦИИ КАК ФАКТЫ** - всегда четко разделять прямые цитаты из правил и логические выводы
28. ❌ **ОТВЕЧАТЬ БЕЗ ССЫЛОК НА ИСТОЧНИКИ** - при ссылке на правила всегда указывать номер строки или раздел
29. ❌ **ИСПОЛЬЗОВАТЬ КАТЕГОРИЧНЫЕ УТВЕРЖДЕНИЯ БЕЗ ДОКАЗАТЕЛЬСТВ** - избегать "ТОЧНО!", "ИМЕННО ТАК!" без прямых цитат
### 17.2 ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:
1. ✅ Проверка остатков перед добавлением в корзину
2. ✅ Валидация всех числовых значений (цена > 0, вес > 0)
3. ✅ Автоматическая генерация уникальных артикулов СФ
4. ✅ Логирование всех изменений статусов
5. ✅ Уведомления всех участников при изменении статусов
6. ✅ Обязательная типизация всех предметов
7. ✅ Связь производных типов с родительскими предметами
8. ✅ Проверка доступности товаров перед заказом
9. ✅ Соблюдение жизненного цикла статусов поставок
10. ✅ Фиксация план/факт в процессе создания продукта
11. ✅ **УКАЗЫВАТЬ ИСТОЧНИКИ ИНФОРМАЦИИ** - при ссылке на правила обязательно указывать строку/раздел
12. ✅ **РАЗДЕЛЯТЬ ФАКТЫ И ИНТЕРПРЕТАЦИИ** - четко маркировать что взято из правил, а что является выводом
13. ✅ **ИСПОЛЬЗОВАТЬ ОСТОРОЖНЫЕ ФОРМУЛИРОВКИ** - "согласно правилам", "возможно", "требует уточнения"
### 17.3 📝 ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ С ФАКТАМИ
**При ссылке на правила ОБЯЗАТЕЛЬНО использовать формат:**
✅ **ПРАВИЛЬНО:**
```
📖 ФАКТ из rules-complete.md (строка 2225): "установка цены за единицу"
🧠 МОЯ ИНТЕРПРЕТАЦИЯ: возможно, это происходит в разделе X
❓ ПРЕДПОЛОЖЕНИЕ: требует уточнения у пользователя
⚠️ НЕ НАЙДЕНО в правилах: информация о точном местоположении
```
❌ **НЕПРАВИЛЬНО:**
```
"Да! Точно понимаю! Фулфилмент устанавливает цены в разделе X!"
```
**ОБЯЗАТЕЛЬНАЯ МАРКИРОВКА:**
- 📖 **ФАКТ** - прямая цитата из правил с номером строки
- 🧠 **ИНТЕРПРЕТАЦИЯ** - мой логический вывод (четко обозначен)
- ❓ **ПРЕДПОЛОЖЕНИЕ** - гипотеза, требующая подтверждения
- ⚠️ **НЕ НАЙДЕНО** - информация отсутствует в правилах
**СТОП-СЛОВА (избегать без доказательств):**
❌ "ТОЧНО!", "ИМЕННО ТАК!", "ДА! ПОНИМАЮ!", "АБСОЛЮТНО ВЕРНО!"
✅ "Согласно правилам...", "Не указано, но возможно...", "Требует уточнения"
### 17.4 🔒 ПРАВИЛА БЕЗОПАСНОСТИ: Разделение данных и функционала
#### КРИТИЧЕСКОЕ ПРАВИЛО БЕЗОПАСНОСТИ
**ПРИНЦИП**: Названия организаций, рынков и любые пользовательские данные НИКОГДА не должны влиять на функционал и безопасность системы.
**ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА:**
✅ **ПРАВИЛЬНЫЕ ПРОВЕРКИ:**
- Проверки доступа ТОЛЬКО по типу организации: `organization.type === 'WHOLESALE'`
- Роутинг ТОЛЬКО по предопределенным путям: `/market`, `/supplies` и т.д.
- Валидация ТОЛЬКО по ID и системным полям
- Фильтрация ТОЛЬКО по enum значениям из схемы
❌ **ЗАПРЕЩЕННЫЕ ПРОВЕРКИ (УЯЗВИМОСТИ):**
- Использование `organization.name` в условиях доступа
- Проверки по `organization.market` для определения функционала
- Любые проверки содержимого строк: `includes()`, `startsWith()`, `match()`
- Динамическое создание путей на основе пользовательских данных
**ПРИМЕРЫ:**
```typescript
// ❌ УЯЗВИМОСТЬ - название может быть любым
if (organization.name.includes('Маркет')) {
// предоставить специальный доступ
}
// ❌ УЯЗВИМОСТЬ - пользователь может подделать название
if (organization.market === 'special-market') {
// изменить цены
}
// ✅ БЕЗОПАСНО - проверка по системному типу
if (organization.type === 'WHOLESALE') {
// логика для поставщиков
}
// ✅ БЕЗОПАСНО - проверка по ID из whitelist
if (ALLOWED_FULFILLMENT_IDS.includes(organization.id)) {
// логика для проверенных фулфилментов
}
```
**РАЗДЕЛЕНИЕ КОНТЕКСТОВ:**
1. **ДАННЫЕ (могут быть любыми):**
- Названия организаций: "ОПТ Маркет", "Супер Склад", и т.д.
- Названия рынков: "Садовод", "ТЯК Москва", любые другие
- Любые пользовательские строки
2. **ФУНКЦИОНАЛ (строго определен):**
- Системные разделы: `/market`, `/supplies`, `/partners`
- Типы организаций: `WHOLESALE`, `SELLER`, `FULFILLMENT`, `LOGIST`
- Статусы и enum из Prisma схемы
**ПРАВИЛО**: Физический рынок "ОПТ Маркет" - это просто строка данных. Раздел "Маркет" (/market) - это системный функционал. Они никак не связаны и не должны влиять друг на друга.
### 17.5 📦 УПРАВЛЕНИЕ СВЯЗЯМИ ТОВАР-КАРТОЧКА В РЕЦЕПТУРЕ
#### 17.5.1 Общие принципы
**НАЗНАЧЕНИЕ**: Связь товара с карточкой маркетплейса - это метаданные для учета, НЕ влияющие на физический состав продукта.
**ФОРМУЛА ПРОДУКТА НЕИЗМЕННА**:
```
ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
```
**СВЯЗЬ С МП** = отдельные метаданные для логистики и учета
#### 17.5.2 UI компонент связи с карточками
**РАСПОЛОЖЕНИЕ**: В форме создания поставки, в секции каждого товара
**ТИП КОМПОНЕНТА**: Dropdown с поиском и фильтрацией
**ИСТОЧНИК ДАННЫХ**: База данных карточек маркетплейсов селлера (GraphQL запрос)
#### 17.5.3 Логика состояний карточек
**✅ СВЯЗАНО** - карточка уже привязана к этому товару:
- Показывать зеленую галочку
- Текст: "Название карточки - Связано"
- Можно отвязать (сброс в "Без привязки")
**⚠️ ДОСТУПНО** - карточка свободна для привязки:
- Показывать желтый значок предупреждения
- Текст: "Название карточки - Доступно"
- Можно привязать к текущему товару
**❌ ЗАНЯТО** - карточка привязана к другому товару:
- Показывать красный крестик
- Текст: "Название карточки - Занято (товар: 'Название')"
- Пункт заблокирован (disabled)
- Показывать для информации, но нельзя выбрать
**🔍 БЕЗ ПРИВЯЗКИ** - товар не связан с карточкой:
- Пункт по умолчанию
- Показывать серый значок
- Текст: "Без привязки к карточке"
#### 17.5.4 Техническая реализация
**GraphQL запрос**:
```graphql
query GetSellerCards {
myMarketplaceCards {
id
title
marketplace
article
linkedProductId # null если свободна
linkedProduct {
# для отображения занятости
id
name
}
}
}
```
**Логика фильтрации**:
- Все карточки селлера показываются в dropdown
- Статус определяется по полю `linkedProductId`
- Автосвязка: карточки с похожим названием показываются первыми
**Сохранение**:
- При создании поставки связь сохраняется в поле `marketplaceCardId` рецептуры
- При изменении связи обновляется поле `linkedProductId` в карточке
#### 17.5.5 UX поведение
**ПОИСК В DROPDOWN**:
- Фильтрация по названию карточки
- Фильтрация по артикулу маркетплейса
- Автофокус при открытии
**ГРУППИРОВКА**:
```
[Dropdown: Выберите карточку Wildberries ▼]
├─ 🔍 БЕЗ ПРИВЯЗКИ
├─ ────── ДОСТУПНЫЕ ──────
├─ ⚠️ "Кроссовки Nike Air" - Доступно
├─ ⚠️ "Футболка Adidas" - Доступно
├─ ────── СВЯЗАННЫЕ ──────
├─ ✅ "Джинсы Levi's" - Связано
├─ ────── ЗАНЯТЫЕ ──────
└─ ❌ "Куртка Puma" - Занято (товар "Верхняя одежда") [disabled]
```
**ВАЛИДАЦИЯ**:
- Связь опциональна - можно создать поставку без привязки
- При выборе занятой карточки показывать предупреждение
- При отвязке подтверждать действие
#### 17.5.6 Интеграция с существующими правилами
**СОВМЕСТИМОСТЬ**:
- Не нарушает существующую логику создания поставок
- Дополняет рецептуру метаданными
- Совместима с типами поставок (карточки/поставщики)
**ОБЯЗАТЕЛЬНОСТЬ**:
- Связь с карточкой - ОПЦИОНАЛЬНА
- Товар может существовать без привязки к МП
- Карточка может существовать без привязки к товару
**ПРИОРИТЕТ РАЗРАБОТКИ**: Средний (не блокирует основную функциональность)
---
## 18. 🛠️ GRAPHQL И TYPESCRIPT ПРАВИЛА
### 18.1 Правила именования полей
**ВАЖНО**: Имена полей в GraphQL запросах должны точно соответствовать схеме!
```typescript
// ✅ ПРАВИЛЬНО - соответствует схеме
export const GET_MY_COUNTERPARTIES = gql`
query GetMyCounterparties {
myCounterparties { // <- имя поля в схеме
id
name
type
}
}
`
// Использование в компоненте
const allCounterparties = counterpartiesData?.myCounterparties || []
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует схеме
const allCounterparties = counterpartiesData?.getMyCounterparties || [] // Ошибка!
```
### 18.2 Правила отладки GraphQL
**При проблемах с GraphQL запросами следовать чек-листу**:
1. **Проверить соответствие имен полей схеме**
2. **Добавить fetchPolicy: 'network-only' для обхода кеша**
3. **Логировать данные в браузере и сервере**
4. **Проверить авторизацию пользователя**
5. **Убедиться что резолвер вызывается**
### 18.3 Обязательные поля для отладки
```typescript
const { data, loading, error } = useQuery(QUERY_NAME, {
fetchPolicy: 'network-only', // Обходим кеш при отладке
errorPolicy: 'all', // Показываем все ошибки
})
// Логирование для отладки
console.log('Data:', data)
console.log('Loading:', loading)
console.log('Error:', error)
```
### 18.4 TypeScript Rules
#### **Интерфейсы данных**
**Поля интерфейсов должны соответствовать GraphQL схеме**:
```typescript
// ✅ ПРАВИЛЬНО - соответствует schema.prisma
interface GoodsProduct {
id: string
name: string
article: string // <- соответствует полю в schema
quantity?: number // <- соответствует полю в schema
organization: {
id: string
name: string
}
}
```
```typescript
// ❌ НЕПРАВИЛЬНО - не соответствует schema
interface GoodsProduct {
sku: string // <- в schema поле называется 'article'
stock?: number // <- в schema поле называется 'quantity'
}
```
### 18.5 Система партнерства в GraphQL
**ПРАВИЛА ИСПОЛЬЗОВАНИЯ ПАРТНЕРСТВА**:
- Поставщики в формах берутся только из партнеров с типом `WHOLESALE`
- Используется запрос `GET_MY_COUNTERPARTIES` с фильтрацией по типу
- НЕ используется `GET_SUPPLY_SUPPLIERS` для отображения поставщиков в формах
- Партнерство создается двумя способами: через заказ в маркете или через раздел "Партнеры"
- Двусторонние записи в таблице `Counterparty` при создании партнерства
### 18.6 Архитектурные принципы GraphQL
- **Создавать специализированные резолверы** для каждого контекста использования
- **Использовать параметризованные запросы** (`organizationId`, `type`, `search`) вместо фильтрации на фронтенде
- **Добавлять подробное логирование** в резолверы для отладки (входные параметры, результаты фильтрации)
- **Типы запросов должны отражать бизнес-логику**: `organizationProducts` для товаров конкретной организации
### 18.7 Правила РЫНКОВ и МАРКЕТА
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ:**
- **РЫНОК** 🏪 = физическое место (Садовод, ТЯК)
- **МАРКЕТ** 🛒 = раздел системы `/market`
**ПОЛЕ РЫНКА В SCHEMA:**
- **Organization.market** ✅ - поставщик принадлежит физическому рынку
- **Product.market** ❌ - ЗАПРЕЩЕНО, товары наследуют рынок от организации
- **Отображение рынка товаров**: через `product.organization.market`
- **Фильтрация по рынкам**: через `organization.market`, НЕ через `product.market`
**ЗАПРОСЫ С РЫНКАМИ:**
```graphql
# ✅ ПРАВИЛЬНО - рынок от организации поставщика
query GetProductsWithMarket {
myProducts {
id
name
organization {
market # Физический рынок поставщика
}
}
}
# ✅ ПРАВИЛЬНО - товары в маркете с информацией о рынке
query GetMarketProducts {
marketProducts {
id
name
organization {
market # Рынок поставщика
name # Название поставщика
}
}
}
```
**МАРКЕТ (/market) ПРАВИЛА:**
- **Назначение**: Глобальный каталог всех товаров
- **Фильтрация**: По рынкам поставщиков, типам товаров, категориям
- **Отображение**: Показать рынок поставщика в карточках товаров
- **НЕ путать**: МАРКЕТ ≠ конкретный физический рынок
- **Значения по умолчанию в резолверах** для критических параметров (`type: args.type || "PRODUCT"`)
- **Валидация обязательных параметров** на уровне схемы (`organizationId: ID!`)
- **Кеширование обходить при проблемах** через `fetchPolicy: 'network-only'`
### 18.8 GraphQL правила для поля organization в мутациях
#### 18.8.1 Обязательность поля organization
**ПРАВИЛО**: Все мутации, возвращающие объекты с типом, включающим `organization: Organization!`, ДОЛЖНЫ запрашивать это поле.
**ПРОБЛЕМА**: Apollo Client кэш ожидает поле `organization` в ответе, если оно определено в GraphQL типе как обязательное.
#### 18.8.2 Правильное написание мутаций
**❌ НЕПРАВИЛЬНО** (вызывает ошибку Apollo Client):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
# НЕТ поля organization - ОШИБКА кэша!
}
}
}
```
**✅ ПРАВИЛЬНО** (работает корректно):
```graphql
mutation UpdateLogistics($id: ID!, $input: LogisticsInput!) {
updateLogistics(id: $id, input: $input) {
success
logistics {
id
fromLocation
organization {
# ОБЯЗАТЕЛЬНО включить!
id
name
fullName
}
}
}
}
```
#### 18.8.3 Чек-лист для мутаций
**ОБЯЗАТЕЛЬНАЯ ПРОВЕРКА** перед созданием мутации:
1. ✅ Проверить GraphQL тип возвращаемого объекта
2. ✅ Если есть поле `organization: Organization!` - добавить в запрос
3. ✅ Включить минимальные поля: `id`, `name`, `fullName`
4. ✅ Проверить resolver включает `include: { organization: true }`
**ПРИМЕНЯЕТСЯ К**:
- `CREATE_LOGISTICS` ✅ Исправлено
- `UPDATE_LOGISTICS` ✅ Исправлено
- `CREATE_SERVICE` - проверить при разработке
- `UPDATE_SERVICE` - проверить при разработке
- Все другие мутации с организационными объектами
**ОШИБКА БЕЗ ПОЛЯ**: `Error converting field "organization" of expected non-nullable type`
---
## 19. 🔧 АРХИТЕКТУРНЫЕ ПРИНЦИПЫ
### 19.1 Стандарты разработки
- **ОБЯЗАТЕЛЬНО**: Покрытие тестами критической функциональности
- **ПРАВИЛО**: Следование принципам SOLID
- **ФУНКЦИЯ**: Автоматическое тестирование при развертывании
- **КАЧЕСТВО**: Минимальное покрытие тестами 80%
### 19.2 Документация
- **ОБЯЗАТЕЛЬНО**: Документирование всех API методов
- **ПРАВИЛО**: Комментарии к сложной бизнес-логике
- **ФУНКЦИЯ**: Автоматическая генерация документации
- **СТАНДАРТ**: Актуальная техническая документация
### 19.3 Масштабируемость
- **АРХИТЕКТУРА**: Модульная структура для легкого расширения
- **ПРАВИЛО**: Использование индексов для быстрого поиска
- **ФУНКЦИЯ**: Горизонтальное масштабирование при росте нагрузки
- **ПЛАНИРОВАНИЕ**: Готовность к увеличению нагрузки в 10 раз
### 19.4 Безопасность данных
- **ОБЯЗАТЕЛЬНО**: Шифрование чувствительных данных
- **ПРАВИЛО**: Аудит всех действий пользователей
- **ФУНКЦИЯ**: Контроль доступа на уровне API
- **БЕЗОПАСНОСТЬ**: Двухфакторная аутентификация для критических операций
---
## 20. 🎯 ПРАВИЛА КАЧЕСТВА КОДА
### 20.1 Проверки и валидация
**ОБЯЗАТЕЛЬНЫЕ ПРОВЕРКИ**:
- ✅ Типизация предметов: каждый предмет имеет один из типов: ТОВАР (`PRODUCT`), РАСХОДНИКИ (`CONSUMABLE`), БРАК и ПРОДУКТ (планируются)
- ✅ БРАК и ПРОДУКТ имеют обязательную связь с родительским товаром (parentId)
- ✅ Расходники создаются как универсальный тип, классифицируются при заказе
- ✅ **В формах создания поставок товаров показываются ТОЛЬКО предметы типа ТОВАР** (`PRODUCT`)
- ✅ **В формах создания поставок расходников показываются ТОЛЬКО предметы типа РАСХОДНИКИ** (`CONSUMABLE`)
- ✅ **Фильтрация по типу предмета происходит на уровне GraphQL резолвера**, не на фронтенде
### 20.2 Workflow статусов
- ✅ Соблюдена последовательность: PENDING → SUPPLIER_APPROVED → CONFIRMED → LOGISTICS_CONFIRMED → SHIPPED → IN_TRANSIT → DELIVERED
- ✅ Нет пропуска промежуточных статусов
- ✅ Каждое изменение статуса сопровождается уведомлением
### 20.3 Правила доступа
- ✅ Поставщик НЕ может добавлять собственные товары в корзину
- ✅ Заказ брака ЗАПРЕЩЕН
- ✅ Только активные предметы отображаются в маркете
- ✅ Проверка остатков перед добавлением в корзину
---
## 21. 🔍 ДИАГНОСТИКА И РЕШЕНИЕ ПРОБЛЕМ
### 21.1 Правило уточнений
**КРИТИЧЕСКИ ВАЖНО**: Если я не уверен в выполнении задачи или вижу противоречия в правилах - ОБЯЗАТЕЛЬНО уточнить у пользователя!
### 21.2 КОГДА УТОЧНЯТЬ:
- [ ] Недостаточно информации для правильного выполнения
- [ ] Вижу противоречия между правилами
- [ ] Задача может нарушить критические правила
- [ ] Неясно как применить правило в конкретной ситуации
- [ ] Есть сомнения в интерпретации требований
### 21.3 КАК УТОЧНЯТЬ:
1. Четко сформулировать что именно неясно
2. Указать какие правила/требования конфликтуют
3. Предложить варианты решения если возможно
4. Запросить конкретные уточнения
**❌ НИКОГДА не делать предположений если есть сомнения!**
---
## 22. 📋 КАТЕГОРИИ ТОВАРОВ И РАСХОДНИКОВ
### 22.1 Полный список 28 универсальных категорий товаров
1. Одежда и обувь
2. Косметика и парфюмерия
3. Дом и сад
4. Детские товары
5. Спорт и отдых
6. Электроника
7. Книги
8. Здоровье
9. Автотовары
10. Строительство и ремонт
11. Продукты питания
12. Зоотовары
13. Дача, сад и огород
14. Канцелярские товары
15. Хобби и творчество
16. Украшения и аксессуары
17. Сумки и чемоданы
18. Техника для дома
19. Музыкальные инструменты
20. Игры и игрушки
21. Мебель
22. Товары для красоты
23. Бытовая химия
24. Товары для путешествий
25. Медицинские товары
26. Религиозные товары
27. Антиквариат и коллекционирование
28. Прочие товары
### 22.2 12 специализированных категорий расходников
#### 🎁 **1. УПАКОВКА И ЗАЩИТА**
- Коробки (различных размеров)
- Пакеты (полиэтиленовые, бумажные, фирменные)
- Пузырчатая пленка, воздушные подушки
- Стрейч-пленка, гофрокартон
- Паллетная пленка, защитные уголки
#### 🏷️ **2. МАРКИРОВКА И ИДЕНТИФИКАЦИЯ**
- Этикетки (адресные, штрих-код, QR-код)
- Бирки (ценники, размерники)
- Стикеры и наклейки
- Маркеры и ручки
- Штампы и печати, термоэтикетки
#### 🔧 **3. КРЕПЕЖ И СОЕДИНЕНИЕ**
- Скотч (прозрачный, цветной, армированный)
- Клей и клеевые составы
- Стяжки пластиковые
- Степлер и скобы
- Веревки и шнуры, стрейч-лента
#### 📄 **4. ДОКУМЕНТООБОРОТ И ВКЛАДЫШИ**
- Накладные и сопроводительные документы
- Инструкции по эксплуатации
- Гарантийные талоны
- Рекламные буклеты, визитки и флаеры
- Благодарственные письма, купоны и промокоды
#### 🧼 **5. ГИГИЕНА И БЕЗОПАСНОСТЬ**
- Перчатки (латексные, нитриловые)
- Маски и респираторы
- Антисептики и дезинфекторы
- Салфетки и тряпки
- Фартуки и халаты, бахилы
#### 🛠️ **6. ИНСТРУМЕНТЫ И ПРИСПОСОБЛЕНИЯ**
- Ножи и резаки, ножницы
- Линейки и рулетки
- Упаковочные машины (ленточные)
- Дозаторы скотча
- Пистолеты для термоклея
- Весы и мерная тара
#### 🎨 **7. БРЕНДИНГ И ДИЗАЙН**
- Фирменные пакеты с логотипом
- Брендированные коробки
- Цветная упаковочная бумага
- Ленты и банты
- Наклейки с логотипом компании
- Подарочная упаковка
#### ⚡ **8. СПЕЦИАЛИЗИРОВАННЫЕ МАТЕРИАЛЫ**
- Антистатические пакеты
- Влагопоглотители
- Температурные индикаторы
- Хрупкие наклейки
- Пломбы и пломбировочные материалы
- Защита от краж (магнитные датчики)
#### 🏪 **9. ТОРГОВОЕ ОБОРУДОВАНИЕ**
- Манекены и вешалки
- Ценникодержатели
- Подставки и стойки
- Корзины и тележки
- Зеркала примерочные
- Освещение витрин
#### 🚚 **10. ЛОГИСТИКА И СКЛАДИРОВАНИЕ**
- Паллеты и поддоны
- Контейнеры и ящики
- Стеллажные системы
- Погрузочные ремни
- Защитные чехлы
- Адресные ярлыки для груза
#### 💻 **11. ТЕХНИЧЕСКИЕ РАСХОДНИКИ**
- Картриджи для принтеров
- Термоголовки, красящие ленты
- Батарейки для сканеров
- Чистящие средства для техники
- Запчасти для упаковочного оборудования
#### 🎪 **12. СЕЗОННЫЕ И ПРАЗДНИЧНЫЕ**
- Новогодняя упаковка
- Подарочные мешки
- Праздничные ленты
- Тематические наклейки
- Открытки и поздравления
- Сезонная упаковочная бумага
**ПРИМЕЧАНИЕ**: Данные категории являются рекомендательными и могут быть адаптированы под специфику конкретного поставщика расходников.
---
## 23. 🎖️ ПРИОРИТЕТЫ РАЗРАБОТКИ
### 23.1 ВЫСОКИЙ ПРИОРИТЕТ:
1. 🔴 Безопасность и контроль доступа
2. 🔴 Целостность данных и валидация
3. 🔴 Корректность статусов поставок
4. 🔴 Уведомления участников процесса
5. 🔴 Правильная типизация предметов
6. 🔴 Связи между товарами и производными типами
### 23.2 СРЕДНИЙ ПРИОРИТЕТ:
1. 🟡 Производительность и оптимизация
2. 🟡 Пользовательский опыт
3. 🟡 Аналитика и отчетность
4. 🟡 Интеграции с внешними системами
5. 🟡 Workflow для брака и продуктов
6. 🟡 Разделение расходников по типам
### 23.3 НИЗКИЙ ПРИОРИТЕТ:
1. 🟢 Дополнительные фильтры
2. 🟢 Косметические улучшения
3. 🟢 Экспериментальные функции
4. 🟢 Расширенная кастомизация
---
## 🚨 КРИТИЧЕСКИЕ СИТУАЦИИ И EDGE CASES
### 🔴 Отмена заказов на разных этапах workflow
**PENDING → Отмена разрешена**
- Действие: Удаление заказа без последствий
- Уведомления: Поставщику о отмене
- Влияние на статистику: Нет
**SUPPLIER_APPROVED → Отмена с согласия поставщика**
- Действие: Требуется подтверждение поставщика
- Штрафы: Возможны согласно договору
- Восстановление: Товары возвращаются в доступные остатки
**CONFIRMED/LOGISTICS_CONFIRMED → Отмена критическая**
- Действие: Требуется согласие всех участников
- Штрафы: Логистические расходы
- Альтернатива: Изменение адреса доставки
**SHIPPED/IN_TRANSIT → Отмена невозможна**
- Действие: Только возврат после получения
- Процедура: Через модуль "Возвраты с ПВЗ"
### 🔄 Частичная доставка товаров
**Сценарий**: Поставщик доставил 80 из 100 заказанных единиц
**Алгоритм обработки**:
1. Фулфилмент фиксирует фактическое количество
2. Система создает два отдельных документа:
- DELIVERED (80 единиц) - обрабатывается обычным порядком
- PARTIAL_DELIVERED (20 единиц) - остается в статусе ожидания
3. Селлер получает уведомление о частичной поставке
4. Принятие решения: ждать остаток или отменить недопоставку
### 📊 Превышение лимитов остатков
**Проблема**: Попытка заказать больше чем есть у поставщика
**Техническая реализация**:
```typescript
if (requestedQuantity > availableStock) {
throw new GraphQLError(`Недостаточно товара. Доступно: ${availableStock}, запрошено: ${requestedQuantity}`)
}
```
**UX решение**: Real-time валидация в формах заказа
### 🔍 Дубликаты артикулов
**Сценарий**: Поставщик пытается создать товар с существующим артикулом
**Проверка на уровне БД**:
```sql
UNIQUE INDEX ON products(article, organization_id)
```
**Обработка**: Автоматическое добавление суффикса или предложение изменить артикул
---
## 24. 📎 ТЕХНИЧЕСКИЕ ПРИЛОЖЕНИЯ
### Приложение A: GraphQL запросы фулфилмента
```typescript
// Основные запросы
GET_MY_SERVICES // Услуги фулфилмента
GET_MY_LOGISTICS // Логистические маршруты
GET_MY_EMPLOYEES // Сотрудники организации
GET_FULFILLMENT_WAREHOUSE_STATS // Статистика склада
GET_WAREHOUSE_PRODUCTS // Товары на складе
GET_MY_FULFILLMENT_SUPPLIES // Расходники фулфилмента
GET_EMPLOYEE_SCHEDULE // Табель рабочего времени
// Мутации
;(CREATE_SERVICE, UPDATE_SERVICE, DELETE_SERVICE)
;(CREATE_LOGISTICS, UPDATE_LOGISTICS, DELETE_LOGISTICS)
;(CREATE_EMPLOYEE, UPDATE_EMPLOYEE, DELETE_EMPLOYEE)
UPDATE_EMPLOYEE_SCHEDULE // Обновление табеля
```
### Приложение B: Компоненты фулфилмента
```typescript
// Основные dashboard компоненты
FulfillmentWarehouseDashboard // Склад фулфилмента
FulfillmentStatisticsDashboard // Статистика
ServicesDashboard // Услуги (3 вкладки)
EmployeesDashboard // Сотрудники
SuppliesDashboard // Поставки фулфилмента
// Специализированные компоненты
;(ServicesTab, LogisticsTab, SuppliesTab) // Вкладки услуг
;(EmployeeInlineForm, EmployeeEditInlineForm) // Формы сотрудников
;(FulfillmentSuppliesTab, FulfillmentConsumablesOrdersTab) // Поставки
```
### Приложение C: Специальный роутинг для типов организаций
```typescript
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies') // Специальный роут
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/wholesale-supplies')
break
case 'LOGIST':
router.push('/logist-supplies')
break
}
}
```
---
_Эта база знаний создана путем объединения rules-unified.md (v3.0) и fulfillment-cabinet-rules.md (v1.0) с устранением всех несоответствий и добавлением критически важных улучшений: быстрый справочник, глоссарий терминов, детальные алгоритмы процессов, edge cases._
_Версия: 10.2_
ата создания: 2025_
_Статус: ЕДИНЫЙ ИСТОЧНИК ИСТИНЫ - ГОТОВ К РАЗРАБОТКЕ_
### 🚀 УЛУЧШЕНИЯ v6.0:
- Быстрый справочник критических правил
- 🔤 Полный глоссарий терминов с определениями
- 🎯 Навигация по ролям (разработчики, аналитики, менеджеры)
- 🔄 Детальный алгоритм создания продукта с временными рамками
- 🚨 Раздел критических ситуаций и Edge Cases
- 📌 Связующие блоки между разделами
- 📊 Таблицы SLA и временных рамок
### 🔧 ИСПРАВЛЕНИЯ v6.1:
- Устранено противоречие в моменте создания БРАКА
- Исправлена логическая цепочка: рецептура задается селлером ДО процесса
- Реалистичные временные рамки SLA (рабочие дни вместо часов)
- Унифицирована классификация расходников (по назначению при использовании)
- Согласованы все алгоритмы и процессы между разделами
### 🔧 ОБНОВЛЕНИЯ v6.3:
- **ДОБАВЛЕН КРИТИЧЕСКИЙ ЗАПРЕТ**: Использование моковых данных в продакшене
- **ОБНОВЛЕН ЧЕКЛИСТ**: Добавлена проверка на отсутствие mock данных
- **РЕАЛИЗАЦИЯ**: Полная очистка моковых данных из раздела "Мои поставки" селлера
### 🎨 ИНТЕГРАЦИЯ v6.2:
- Синхронизация с visual-design-rules.md v1.1
- Добавлены визуальные правила для 8 статусов поставок
- Создана цветовая система для 6 модулей фулфилмента
- Визуальный workflow процесса создания продукта
- Перекрестные ссылки между техническими и визуальными правилами
- Покрытие визуальными решениями увеличено с 40% до 85%
### 🚀 КОНСОЛИДАЦИЯ v7.0:
- Интеграция development-checklist.md и CLAUDE.md
- Удаление дублирующих файлов
- Создание единого источника истины
### 🔧 ПОЛНАЯ ИНТЕГРАЦИЯ v8.0:
- Интеграция work-protocols.md (детальные протоколы по сложности)
- Интеграция violation-prevention-protocol.md (СТОП-сигналы и триггеры)
- Интеграция self-validation.md (расширенная система самопроверки)
- Удаление всех дублирующих файлов протоколов
### 🎯 ОПТИМИЗАЦИЯ UI/UX v8.1:
- Добавлен ТРИГГЕР #3 для автоматической активации visual-design-rules.md
- Интегрирован специальный UI/UX протокол в чеклист
- Создана система перекрестных ссылок с visual-design-rules.md
- visual-design-rules.md остается отдельным специализированным файлом
### 📊 ИНТЕГРАЦИЯ DESCRIPTION v9.0:
- Добавлена UI структура создания поставки расходников (3 блока)
- Интегрирована концепция многоуровневых таблиц
- Добавлен механизм учета ПЛАН/ФАКТ в процессе создания продукта
- Расширена детализация рецептуры продукта
- Добавлена опция места хранения готовых продуктов
### 🔧 УТОЧНЕНИЯ ЛОГИКИ v9.1:
- Уточнен статус брака: НЕ РЕАЛИЗОВАНО (еще не дошли до этого этапа)
- Добавлены четкие правила создания предметов по ролям
- Добавлен экономический учет расходников фулфилмента для селлера
- Обновлен механизм ПЛАН/ФАКТ: потери вместо брака при пересчете
- Добавлена заметка о будущей детализации статусов товаров
### 🎨 UI УЛУЧШЕНИЯ v9.2:
- Добавлены детальные правила горизонтального скролла для блока поставщиков
- Реализован горизонтальный скролл в create-suppliers-supply-page.tsx
- Добавлена адаптивность (десктоп 280px, планшет 260px, мобильный 240px)
- Интегрированы ARIA атрибуты для доступности
- Реализовано автоскрытие полосы прокрутки и навигация клавиатурой
### 🔒 БЕЗОПАСНОСТЬ И ТЕРМИНОЛОГИЯ v10.0:
- **ДОБАВЛЕН РАЗДЕЛ 17.3**: Правила безопасности - разделение данных и функционала
- **НОВЫЕ ЗАПРЕТЫ 24-26**: Запрет использования пользовательских данных в логике безопасности
- **РАСШИРЕН ГЛОССАРИЙ**: Контекстно-зависимые термины для SupplyOrder
- **УТОЧНЕНИЕ ТЕРМИНОВ**: Четкое разделение "Маркет" (раздел) vs "Маркетплейс" (внешние площадки)
- **ПРИМЕРЫ УЯЗВИМОСТЕЙ**: Конкретные примеры безопасного и небезопасного кода
### 📝 КАЧЕСТВО ОТВЕТОВ v10.1:
- **НОВЫЕ ЗАПРЕТЫ 27-29**: Запрет представления интерпретаций как фактов
- **ОБЯЗАТЕЛЬНЫЙ ФОРМАТ ОТВЕТОВ 17.3**: Четкое разделение фактов, интерпретаций и предположений
- **СИСТЕМА МАРКИРОВКИ**: 📖 ФАКТ, 🧠 ИНТЕРПРЕТАЦИЯ, ПРЕДПОЛОЖЕНИЕ, НЕ НАЙДЕНО
- **СТОП-СЛОВА**: Список категоричных утверждений для избегания без доказательств
- **ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА 11-13**: Указание источников и осторожные формулировки
### 🔗 ПАРТНЕРСКАЯ И РЕФЕРАЛЬНАЯ СИСТЕМА v10.2:
- **ДОБАВЛЕН РАЗДЕЛ 13.6**: Критическое различие партнерских и реферальных ссылок
- **ЧЕТКИЕ ОПРЕДЕЛЕНИЯ**: Партнерские (?partner=) vs Реферальные (?ref=) ссылки
- **ТЕХНИЧЕСКИЕ ПРАВИЛА**: Различия в обработке кодов в резолверах
- **UI СПЕЦИФИКАЦИИ**: Разные интерфейсы для партнерства и маркетинга
- **ЗАПРЕТЫ ПУТАНИЦЫ**: Строгие правила именования и терминологии
- **ПРИМЕРЫ СЦЕНАРИЕВ**: Деловое партнерство vs маркетинговые кампании

View File

@ -0,0 +1,540 @@
# ПРАВИЛА UI/UX КАБИНЕТА СЕЛЛЕРА (SELLER)
> ⚠️ **ВАЖНО**: Это файл с UI/UX деталями кабинета селлера.
> Общие бизнес-правила находятся в **[rules-complete.md](./rules-complete.md)**
## Когда использовать этот файл:
- Работа с компонентами `/supplies`, `/my-supplies`
- UI/UX специфика кабинета селлера
- Интерфейсы создания поставок
- Визуальные правила компонентов селлера
## 1. 🛍️ СТРУКТУРА КАБИНЕТА СЕЛЛЕРА
### 1.1 Основные разделы
**СЕЛЛЕР (`SELLER`)** имеет доступ к следующим разделам:
- **Мои поставки** (`/my-supplies`) - управление поставками
- **Маркет** (`/market`) - просмотр глобального каталога
- **Партнеры** (`/partners`) - управление контрагентами
- **Мессенджер** (`/messenger`) - связь с партнерами
- **Настройки** (`/settings`) - профиль и настройки
- **Экономика** (`/economics`) - финансовая аналитика
### 1.2 Навигация и роутинг
#### При входе в систему:
```typescript
switch (user?.organization?.type) {
case 'SELLER':
router.push('/my-supplies') // Направляем на страницу поставок
break
}
```
#### Специальная логика роутинга:
> 📖 **Бизнес-логика роутинга**: См. [rules-complete.md#4-система-ролей-и-доступов](./rules-complete.md#4--система-ролей-и-доступов)
## 2. 🎨 UI/UX КОМПОНЕНТЫ
### 2.1 Dashboard компоненты
#### Основные компоненты кабинета:
- `SellerHomePage` - главный компонент селлера
- `SellerEconomicsPage` - экономическая аналитика
- `MySuppliesDashboard` - управление поставками
#### Wrapper-компоненты:
- `HomePageWrapper` - маршрутизация по типам организаций
- `EconomicsPageWrapper` - адаптивная экономика по кабинетам
### 2.2 Детальные правила горизонтального скролла поставщиков
**КНОПКА НАВИГАЦИИ "НАЗАД":**
**Архитектура размещения:**
- **Расположение**: Между сайдбаром и основным контентом
- **Контейнер**: Отдельный `<div className="relative">`
- **НЕ является частью блока 1** - независимый навигационный элемент
- **Позиционирование**: `absolute left-0 top-6`
- **z-index**: 10 (поверх контента)
**Визуальный дизайн:**
```tsx
className =
'absolute left-0 top-6 z-10 w-8 h-8 bg-white/10 backdrop-blur-xl border border-white/20 hover:border-white/40 rounded-full flex items-center justify-center transition-all duration-300 hover:scale-110 hover:bg-white/20 group'
```
**Параметры кнопки:**
- **Размер**: 32×32px (`w-8 h-8`)
- **Форма**: Круглая (`rounded-full`)
- **Фон**: `bg-white/10` с эффектом размытия `backdrop-blur-xl`
- **Граница**: `border border-white/20`, при hover `border-white/40`
- **Иконка**: `ArrowLeft` 16×16px (`h-4 w-4`), цвет `text-white/70`
- **Hover эффекты**:
- Масштабирование `scale-110`
- Изменение фона `bg-white/20`
- Иконка становится белой и увеличивается до `h-5 w-5`
- **Анимация**: `transition-all duration-300`
**Функциональность:**
- **onClick**: Переход на `/supplies?tab=goods&subTab=suppliers`
- **aria-label**: "Вернуться к поставщикам"
- **Семантика**: Кнопка возврата к списку поставок
**СТРУКТУРА И ОТОБРАЖЕНИЕ БЛОКА 1:**
- **БЕЗ ЗАГОЛОВКА** - блок начинается сразу с поиска и контента
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки
**РАЗМЕРЫ И АДАПТИВНОСТЬ:**
- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"
**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
**Критическая Flex-архитектура:**
```css
.parent-container {
display: flex;
gap: 16px;
min-height: 0;
}
.left-block {
flex: 1;
min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
display: flex;
flex-direction: column;
}
.suppliers-container {
height: 180px; /* Общая высота блока */
flex-shrink: 0;
min-width: 0; /* Предотвращает растяжение */
}
.right-block {
width: 384px; /* w-96 */
flex-shrink: 0; /* Защита от сжатия */
}
```
**Контейнер скролла:**
```css
.suppliers-block {
display: flex;
overflow-x: auto;
scroll-behavior: smooth;
gap: 12px;
padding: 0 16px 8px 16px; /* px-4 pb-2 */
height: 176px; /* h-44 */
scrollbar-width: thin;
scrollbar-color: #64748b33 transparent;
}
.suppliers-block:hover {
scrollbar-color: #cbd5e0 #64748b22;
}
.supplier-card {
flex-shrink: 0;
width: 216px; /* Десктоп */
height: 92px; /* Фиксированная высота */
padding: 8px; /* p-2 */
transition: all 0.2s ease;
}
```
**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**
**Структура (3 строки в 92px высоты):**
- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)
**Элементы:**
- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)
**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**
- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`
**ДОСТУПНОСТЬ:**
- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных
### 2.3 Правила блока "Карточки товаров" (Блок 2)
**НАЗНАЧЕНИЕ И ЛОГИКА:**
- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров
**АРХИТЕКТУРА И РАЗМЕРЫ:**
- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере
**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**
- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств
**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**
- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный
**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)
### 2.4 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ
**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.
#### **2.4.1 Размеры и позиционирование**
```tsx
<div className="w-72 flex-shrink-0">
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```
**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:
- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`
#### **2.4.2 Автодобавление товаров**
**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.
```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)
if (newQuantity > 0) {
// Автоматически добавляем товар в корзину
updateProductQuantity(product.id, newQuantity)
} else {
// Удаляем товар из корзины при количестве 0
removeFromCart(product.id)
}
}
```
**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`
#### **2.4.3 Структура корзины**
**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:
1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом
**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине
#### **2.4.4 Единая функция расчета стоимости**
**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:
```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
const product = products.find((p) => p.id === productId)
if (!product) return 0
// Базовая цена товара
let total = (product.pricePerUnit || 0) * quantity
// Добавляем услуги
if (product.services && product.services.length > 0) {
const servicesTotal = product.services.reduce((sum, service) => {
return sum + (service.pricePerUnit || 0) * quantity
}, 0)
total += servicesTotal
}
// Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
if (product.ffConsumables && product.ffConsumables.length > 0) {
const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
}, 0)
total += ffConsumablesTotal
}
// Добавляем расходники продавца
if (product.sellerConsumables && product.sellerConsumables.length > 0) {
const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
return sum + (consumable.pricePerUnit || 0) * quantity
}, 0)
total += sellerConsumablesTotal
}
return total
}
```
#### **2.4.5 Синхронизация данных между блоками**
**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:
1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`
**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:
```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```
#### **2.4.6 Критические требования**
🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:
- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов
🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:
- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества
🚨 **UX КОНСИСТЕНТНОСТЬ**:
- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных
### 2.5 Трёхблочная архитектура страницы "Мои поставки"
**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков
```
┌─────────────────────────────────────────┐
│ 1. БЛОК ТАБОВ (навигация) │
│ - Фиксированная высота │
│ - Glass-эффект │
│ - Иерархическая структура │
├─────────────────────────────────────────┤
│ 2. БЛОК СТАТИСТИКИ (метрики) │
│ - Контекстные данные │
│ - 4 карточки в ряд (desktop) │
│ - Динамическое обновление │
├─────────────────────────────────────────┤
│ 3. ОСНОВНОЙ БЛОК (контент) │
│ - Сохраняет весь функционал │
│ - Таблицы, фильтры, действия │
│ - Высота до низа sidebar │
└─────────────────────────────────────────┘
```
**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов
**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**
- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути
**ФОРМУЛА РАСЧЕТА ВЫСОТЫ**:
```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```
**ПРАВИЛО ВЫРАВНИВАНИЯ**:
- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`
### 2.6 Четырёхблочная архитектура создания поставки расходников
#### **Структура страницы**:
**БЛОК 1: ПОСТАВЩИКИ** _(обязательный, 180px)_:
- БЕЗ заголовка - сразу функциональный контент
- Кнопка навигации "Назад" - между сайдбаром и блоком (см. раздел 2.2)
- Карточки поставщиков из раздела "Партнеры"
- Горизонтальный скролл при превышении ширины
- Выбор только одного поставщика одновременно
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(адаптивная высота - НОВЫЙ БЛОК)_:
- ТОЛЬКО минималистичные карточки товаров 80×112px
- ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- Горизонтальный скролл при множестве товаров
- Клик добавляет товар в блок 3
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(flex-1, детальный каталог)_:
- Детальные карточки выбранных товаров
- Управление количеством и параметрами поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель, 384px)_:
- Корзина поставки с выбранными товарами
- Настройки поставки (фулфилмент-центр, дата, логистика)
- Сортировка: цена, название, категория
- Фильтры: категория, ценовой диапазон
- Карточка с полем ввода количества и кнопками +/-
**БЛОК 3: КОРЗИНА** _(правая часть)_:
- **РАСПОЛОЖЕНИЕ**: Правая часть экрана
- **СОДЕРЖАНИЕ**:
- Счетчик видов расходников
- Детализация по каждому расходнику (название, количество, цена, сумма)
- Общая сумма всех расходников
- **УПРАВЛЕНИЕ**:
- Изменение количества (с валидацией остатков)
- Удаление позиций
- **ОБЯЗАТЕЛЬНЫЕ ПОЛЯ**:
- Выбор фулфилмент-центра (из партнеров)
- Дата поставки (не прошедшая, по умолчанию - текущая)
### 2.7 Многоуровневая таблица поставок
#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
- Порядковый номер поставки
- Количество видов расходников
- Стоимость всей поставки
- Количество категорий
- Статус поставки
#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:
- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
- Название расходника
- Количество
- Цена
- Категория
- Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено
## 3. 🛠️ ГРАФИЧЕСКИЙ ИНТЕРФЕЙС И КОМПОНЕНТЫ
### 3.1 React компоненты селлера
**Основные компоненты:**
- `SellerHomePage` - главная страница селлера (4 типо-зависимых компонента)
- `SellerEconomicsPage` - экономическая аналитика селлера
### 3.2 Роутинг для селлера
```typescript
switch (user?.organization?.type) {
case 'SELLER':
router.push('/supplies')
break
}
```
### 3.3 Структура разделов кабинета
**🛍️ СЕЛЛЕР (`SELLER`):**
- Мои поставки (`/supplies`) - управление заказами товаров
- WB Интеграция (`/wb-integration`) - связь с Wildberries
## 4. 🛠️ GRAPHQL API
### 4.1 Основные запросы (Queries)
#### Получение карточек селлера:
```graphql
query GetSellerCards {
myMarketplaceCards {
id
title
marketplace
article
linkedProductId # null если свободна
linkedProduct {
# для отображения занятости
id
name
}
}
}
```
---
**Последнее обновление**: Август 2025
**Связанные файлы**:
- [rules-complete.md](./rules-complete.md) - Общие бизнес-правила
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила

View File

@ -0,0 +1,1115 @@
# ОБЩИЕ ПРАВИЛА ВИЗУАЛЬНОГО ДИЗАЙНА SFERA
> 📋 **Базовые принципы дизайна системы управления складами и поставками**
---
## 🎨 **1. ЦВЕТОВАЯ СИСТЕМА**
### 1.1 Основная палитра
**PRIMARY COLORS (OKLCH)**:
- **Primary**: `oklch(0.65 0.28 315)` - основной фиолетовый
- **Primary Foreground**: `oklch(0.985 0 0)` - белый текст
- **Secondary**: `oklch(0.94 0.08 315)` - светло-фиолетовый
- **Background**: `oklch(0.98 0.02 320)` - светлый фон
**GLASS SYSTEM**:
- **Base**: `bg-white/10 backdrop-blur border-white/20`
- **Cards**: `bg-white/5 backdrop-blur border-white/10`
- **Buttons**: `glass-button` / `glass-secondary`
### 1.2 Функциональные цвета
**STATUS COLORS**:
- 🟢 **Success**: `green-400/500` - завершенные операции
- 🔴 **Error**: `red-400/500` - ошибки и критичные состояния
- 🟡 **Warning**: `yellow-400/500` - предупреждения
- 🔵 **Info**: `blue-400/500` - информационные сообщения
- 🟣 **Processing**: `purple-400/500` - процессы в работе
**CABINET COLORS**:
- **Селлер**: `blue-400` - синий
- **Фулфилмент**: `purple-400` - фиолетовый
- **Поставщик**: `green-400` - зеленый
- **Логистика**: `orange-400` - оранжевый
### 1.3 Иерархическая цветовая схема
**УРОВНИ ДЕТАЛИЗАЦИИ (для фулфилмента)**:
- 🔵 **Уровень 1 (Магазины)**: уникальные цвета
- ТехноМир: `blue-400/500`
- Стиль и Комфорт: `pink-400/500`
- Зелёный Дом: `emerald-400/500`
- 🟢 **Уровень 2 (Товары)**: `green-500`
- 🟠 **Уровень 3 (Варианты)**: `orange-500`
---
## 🔤 **2. ТИПОГРАФИКА**
### 2.1 Шрифты
**FAMILY**:
- **Sans**: `var(--font-geist-sans)` - основной шрифт
- **Mono**: `var(--font-geist-mono)` - код и техническая информация
### 2.2 Размеры и веса
**HEADINGS**:
- **H1**: `text-3xl font-bold text-white` - заголовки страниц
- **H2**: `text-2xl font-semibold text-white` - секции
- **H3**: `text-xl font-semibold text-white` - подразделы
- **H4**: `text-lg font-medium text-white` - карточки
**BODY TEXT**:
- **Primary**: `text-white` - основной текст
- **Secondary**: `text-white/70` - вспомогательный
- **Muted**: `text-white/60` - дополнительный
- **Disabled**: `text-white/40` - отключенные элементы
**CODE & TECHNICAL**:
- **Code**: `font-mono text-xs text-white/60` - техническая информация
- **Badges**: `text-xs font-medium` - статусы и метки
---
## 🧩 **3. КОМПОНЕНТЫ**
### 3.1 Кнопки
**ВАРИАНТЫ**:
```css
default: bg-primary hover:bg-primary/90
glass: glass-button (основной стиль)
glass-secondary: glass-secondary hover:text-white/90
outline: border hover:bg-accent
ghost: hover:bg-accent/50
destructive: bg-destructive hover:bg-destructive/90
```
**РАЗМЕРЫ**:
- **sm**: `h-8 px-3` - компактные формы
- **default**: `h-9 px-4` - стандартные
- **lg**: `h-10 px-6` - акцентные действия
- **icon**: `size-9` - иконочные кнопки
**ГРАДИЕНТЫ**:
- **Accent**: `bg-gradient-to-r from-purple-600 to-pink-600`
- **Success**: `bg-gradient-to-r from-green-500 to-emerald-500`
- **Info**: `bg-gradient-to-r from-blue-500 to-cyan-500`
### 3.2 Карточки
**БАЗОВЫЕ СТИЛИ**:
```css
glass-card: bg-white/5 backdrop-blur border-white/10
hover: border-white/20 transition-all
interactive: cursor-pointer group
```
**ИНТЕРАКТИВНОСТЬ**:
- **Hover**: `hover:border-white/20 hover:bg-white/10`
- **Scale**: `hover:scale-105 transition-transform`
- **Shadow**: `hover:shadow-xl hover:shadow-purple-500/20`
### 3.3 Формы
**ИНПУТЫ**:
```css
glass-input: backdrop-blur border-white/20
placeholder: placeholder:text-white/50
focus: focus-visible:ring-ring/50
invalid: aria-invalid:border-destructive
```
**СОСТОЯНИЯ**:
- **Default**: `glass-input text-white`
- **Error**: `border-red-500/50 ring-red-500/20`
- **Success**: `border-green-500/50 ring-green-500/20`
- **Disabled**: `opacity-50 pointer-events-none`
---
## ✨ **4. АНИМАЦИИ И ПЕРЕХОДЫ**
### 4.1 Стандартные переходы
**DURATION**:
- **Fast**: `duration-200` - hover эффекты
- **Normal**: `duration-300` - стандартные переходы
- **Slow**: `duration-500` - сложные анимации
**EASING**:
- **Default**: `transition-all` - универсальный
- **Transform**: `transition-transform` - масштабирование
- **Colors**: `transition-colors` - смена цветов
### 4.2 Hover эффекты
**МАСШТАБИРОВАНИЕ**:
```css
hover:scale-105 - легкое увеличение
hover:scale-110 - заметное увеличение
hover:scale-95 - уменьшение при нажатии
hover:-translate-y-1 - поднятие
```
**ЦВЕТОВЫЕ ИЗМЕНЕНИЯ**:
```css
hover:bg-white/10 - осветление фона
hover:text-white - усиление текста
hover:border-white/40 - усиление границ
```
### 4.3 Системные анимации
**LOADING**:
- **Spin**: `animate-spin` - индикаторы загрузки
- **Pulse**: `animate-pulse` - уведомления
- **Bounce**: `animate-bounce` - привлечение внимания
- **Ping**: `animate-ping` - статусы онлайн
---
## 📐 **5. СЕТКИ И ОТСТУПЫ**
### 5.1 Spacing система
**ВНУТРЕННИЕ ОТСТУПЫ**:
- **xs**: `p-2` (8px) - плотные элементы
- **sm**: `p-3` (12px) - компактные карточки
- **md**: `p-4` (16px) - стандартные карточки
- **lg**: `p-6` (24px) - основные секции
- **xl**: `p-8` (32px) - страницы
**ВНЕШНИЕ ОТСТУПЫ**:
- **Между элементами**: `space-y-4` / `gap-4`
- **Между секциями**: `space-y-6` / `gap-6`
- **Между страницами**: `space-y-8`
### 5.2 Responsive сетки
**BREAKPOINTS**:
```css
sm: 640px - мобильные
md: 768px - планшеты
lg: 1024px - десктопы
xl: 1280px - широкие экраны
```
**GRID PATTERNS**:
```css
grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4
grid-cols-2 md:grid-cols-4 lg:grid-cols-6
flex flex-wrap gap-4
```
---
## 🔄 **6. УНИФИКАЦИЯ ИНТЕРФЕЙСОВ**
### 6.1 Раздел "Партнеры" - специальные правила
> 📋 **Детальные правила**: См. [partners-rules.md](./partners-rules.md#🎨-uiux-правила-раздела-партнеры)
**КРИТИЧЕСКИ ВАЖНО**: Все вкладки раздела "Партнеры" должны иметь единую структуру:
#### Обязательные принципы:
- **Блоки статистики**: `grid grid-cols-4 gap-3` с отдельными `glass-card`
- **ЗАПРЕЩЕНО**: Дополнительные обертки `glass-card` в TabsContent
- **Цвета ссылок**: желтая схема (`bg-yellow-500/20`)
- **Табличный формат**: вместо карточного grid-layout
#### Структура блоков статистики:
```tsx
{
/* ПРАВИЛЬНО */
}
;<div className="grid grid-cols-4 gap-3">
<Card className="glass-card p-3">...</Card>
</div>
{
/* ЗАПРЕЩЕНО */
}
;<Card className="glass-card">
<div className="grid...">...</div>
</Card>
```
---
## 🎯 **7. СОСТОЯНИЯ И СТАТУСЫ**
### 6.1 Визуальные индикаторы
**SUCCESS STATES**:
```css
bg-green-500/10 border-green-500/30 text-green-300
CheckCircle - иконка успеха
```
**ERROR STATES**:
```css
bg-red-500/10 border-red-500/30 text-red-300
XCircle - иконка ошибки
```
**WARNING STATES**:
```css
bg-yellow-500/10 border-yellow-500/30 text-yellow-300
AlertTriangle - иконка предупреждения
```
**INFO STATES**:
```css
bg-blue-500/10 border-blue-500/30 text-blue-300
Info - иконка информации
```
### 6.2 Бейджи и метки
**СТАТУСЫ WORKFLOW**:
- **Pending**: `bg-yellow-500/20 text-yellow-300`
- **Approved**: `bg-green-500/20 text-green-300`
- **In Progress**: `bg-blue-500/20 text-blue-300`
- **Completed**: `bg-emerald-500/20 text-emerald-300`
- **Cancelled**: `bg-red-500/20 text-red-300`
---
## 📱 **7. АДАПТИВНОСТЬ**
### 7.1 Mobile-first подход
**ПРИНЦИПЫ**:
- Базовые стили для мобильных
- Прогрессивное улучшение для больших экранов
- Минимальная ширина 320px
- Максимальная производительность
### 7.2 Responsive компоненты
**SIDEBAR**:
```css
Мобильные: overlay sidebar
Планшеты: collapsible sidebar
Десктоп: full sidebar
```
**CARDS**:
```css
Мобильные: 1 колонка
Планшеты: 2 колонки
Десктоп: 3-4 колонки
```
**FORMS**:
```css
Мобильные: stack layout
Планшеты: 2-column layout
Десктоп: optimized layout
```
---
## ♿ **8. ДОСТУПНОСТЬ**
### 8.1 Контрастность
**МИНИМАЛЬНЫЕ ТРЕБОВАНИЯ**:
- Текст на фоне: 4.5:1
- Иконки и элементы: 3:1
- Интерактивные элементы: 4.5:1
**ПРОВЕРКА КОНТРАСТА**:
```css
text-white на bg-white/10
text-white/70 на bg-white/5
text-white/40 на bg-white/10
```
### 8.2 Фокус и навигация
**FOCUS STYLES**:
```css
focus-visible:ring-ring/50 focus-visible:ring-[3px]
focus-visible:border-ring
outline-none
```
**KEYBOARD NAVIGATION**:
- Tab order логичен
- Все интерактивные элементы доступны
- Escape закрывает модалы
- Enter активирует кнопки
---
## 🔧 **9. ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ**
### 9.1 CSS Architecture
**UTILITY-FIRST**:
- Tailwind CSS как основа
- Custom CSS только для уникальных компонентов
- CSS переменные для тем
**NAMING CONVENTIONS**:
```css
glass-card - основные карточки
glass-button - стеклянные кнопки
glass-input - поля ввода
glass-secondary - вторичные элементы
```
### 9.2 Performance
**ОПТИМИЗАЦИЯ**:
- Minimal CSS bundle
- Tree-shaking неиспользуемых стилей
- Critical CSS inline
- Progressive enhancement
**LAZY LOADING**:
- Изображения: `loading="lazy"`
- Компоненты: React.lazy()
- Анимации: только при необходимости
---
## 🎯 **10. ПРАВИЛА ИЕРАРХИИ ТАБОВ**
### 10.1 Принцип отдельного блока табов
**ОБЯЗАТЕЛЬНЫЕ ПРАВИЛА**:
> 1. ТАБЫ ВСЕГДА НАХОДЯТСЯ В ОТДЕЛЬНОМ БЛОКЕ, независимо от количества уровней иерархии
> 2. БЛОК ТАБОВ ИМЕЕТ СТИЛИ КАК У САЙДБАРА
> 3. ТАБЫ ОТДЕЛЕНЫ ОТ РАБОЧЕГО ПРОСТРАНСТВА
**СТИЛИ БЛОКА ТАБОВ**:
```css
bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6
```
**СТИЛИ РАБОЧЕГО ПРОСТРАНСТВА**:
```css
bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl
```
**ЗАПРЕЩЕНО**:
- Размещать табы в блоке с другими модулями
- Смешивать табы с основным контентом
- Использовать glass-card вместо правильных стилей сайдбара
- Объединять блок табов с рабочим пространством
### 10.2 Визуальная иерархия
**УРОВЕНЬ 1 (Главные табы)**:
```css
h-11 /* Высота 44px */
bg-white/15 /* Контрастный фон */
border-white/30 /* Яркая граница */
rounded-xl /* Крупное скругление */
font-semibold /* Жирный шрифт */
purple-500/40 /* Интенсивный градиент */
shadow-lg /* Глубокая тень */
```
**УРОВЕНЬ 2 (Подтабы)**:
```css
h-9 /* Высота 36px */
bg-white/8 /* Средний фон */
border-white/20 /* Средняя граница */
rounded-lg /* Среднее скругление */
font-medium /* Средний шрифт */
white/15 /* Простая активация */
ml-4 /* Отступ показывает иерархию */
```
**УРОВЕНЬ 3 (Подподтабы)**:
```css
h-8 /* Высота 32px */
bg-white/5 /* Слабый фон */
border-white/15 /* Деликатная граница */
rounded-md /* Мелкое скругление */
font-normal /* Обычный шрифт */
white/10 /* Слабая активация */
ml-8 /* Больший отступ */
text-white/50 /* Приглушенный текст */
```
### 10.3 Отступы и spacing
**ИЕРАРХИЧЕСКИЕ ОТСТУПЫ**:
- **Уровень 1**: `ml-0` - прижат к краю
- **Уровень 2**: `ml-4` - показывает подчинение
- **Уровень 3**: `ml-8` - максимальная вложенность
**ВЕРТИКАЛЬНЫЕ ОТСТУПЫ**:
- Между уровнями: `space-y-3`
- После TabsList: `mb-3`
- В контенте: `space-y-0` (без лишних отступов)
### 10.4 Размеры элементов
**ПРОГРЕССИВНОЕ УМЕНЬШЕНИЕ**:
- **Высота табов**: 44px → 36px → 32px
- **Размер иконок**: 16px → 12px → 10px
- **Размер текста**: sm → xs → xs
- **Толщина шрифта**: semibold → medium → normal
### 10.5 Цветовая деградация
**КОНТРАСТНОСТЬ**:
- **Уровень 1**: Максимальная (white/15, border-white/30)
- **Уровень 2**: Средняя (white/8, border-white/20)
- **Уровень 3**: Минимальная (white/5, border-white/15)
**АКТИВАЦИЯ**:
- **Уровень 1**: Градиент + тень + border
- **Уровень 2**: Простой фон white/15
- **Уровень 3**: Слабый фон white/10
---
## 📐 **11. ПРАВИЛО ВЫРАВНИВАНИЯ БЛОКОВ С САЙДБАРОМ**
### 11.1 Принцип выравнивания
**🎯 ОСНОВНОЙ ПРИНЦИП:**
> Все блоки контента справа от сайдбара должны быть выровнены точно по верхнему и нижнему краю сайдбара без отступов.
**📐 ВИЗУАЛЬНАЯ СХЕМА:**
```
┌─────────────────────────────────────┐
│ SIDEBAR │ ← блоки начинаются │ ← ТОП САЙДБАРА
│ │ точно здесь │
│ │ │
│ │ [КОНТЕНТ БЛОКИ] │
│ │ │
│ │ ← блоки заканчиваются │ ← НИЗ САЙДБАРА
│ │ точно здесь │
└─────────────────────────────────────┘
```
### 11.2 Техническая реализация
**✅ ПРАВИЛЬНО:**
```jsx
<div className="h-screen flex overflow-hidden">
<Sidebar />
<main className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}>
<div className="h-full flex flex-col">
{/* Блоки занимают всю доступную область */}
<div className="flex-1 flex gap-2 min-h-0">{/* Блоки без внешних отступов */}</div>
</div>
</main>
</div>
```
**❌ НЕПРАВИЛЬНО:**
```jsx
// НЕ ИСПОЛЬЗОВАТЬ px-2 py-2 в main контейнере!
<main className={`flex-1 ${getSidebarMargin()} px-2 py-2 overflow-hidden`}>
```
### 11.3 Требования к структуре
**MAIN КОНТЕЙНЕР:**
- ✅ БЕЗ `px-2 py-2` отступов
- ✅ Только `overflow-hidden` и `transition-all duration-300`
- ✅ Использовать `${getSidebarMargin()}` для отступа от сайдбара
**БЛОКИ КОНТЕНТА:**
- ✅ Занимают всю высоту: `h-full flex flex-col`
- ✅ Минимальные gap между блоками: `gap-2`
- ✅ Начинаются от самого верха экрана
- ✅ Заканчиваются у самого низа экрана
**SPACING МЕЖДУ БЛОКАМИ:**
- ✅ Горизонтальный gap: `gap-2` (8px)
- ✅ Вертикальный gap: `gap-2` (8px)
-НЕ использовать внешние отступы `px-* py-*`
### 11.4 Области применения
**✅ ПРИМЕНЯЕТСЯ К:**
- Все страницы с сайдбаром
- Дашборды и кабинеты пользователей
- Модальные окна полной высоты
- Списки, таблицы и каталоги
- Формы создания и редактирования
**❌ ИСКЛЮЧЕНИЯ:**
- Модальные окна (центрированные)
- Всплывающие уведомления (toast)
- Dropdown меню
- Контекстные меню
### 11.5 Проверка соответствия
**КРИТЕРИИ СООТВЕТСТВИЯ:**
1. **Верхний край**: Первый блок начинается на уровне верха сайдбара
2. **Нижний край**: Последний блок заканчивается на уровне низа сайдбара
3. **Без отступов**: Отсутствуют `px-* py-*` отступы в main
4. **Только gap**: Используется только `gap-2` между блоками
**ИНСТРУМЕНТЫ ПРОВЕРКИ:**
- Инспектор браузера для проверки CSS
- Визуальное сравнение с краями сайдбара
- Проверка на разных размерах экрана
---
## 📋 **12. ЧЕКЛИСТ ПРИМЕНЕНИЯ**
### 12.1 Перед внедрением компонента
- [ ] Соответствует цветовой палитре системы
- [ ] Использует правильную типографику
- [ ] Имеет корректные состояния (hover, focus, disabled)
- [ ] Адаптивен для всех breakpoints
- [ ] Соответствует требованиям доступности
- [ ] Использует стандартные анимации
- [ ] Оптимизирован для производительности
- [ ] **Блоки выровнены с сайдбаром (правило 11)**
### 12.2 При создании новых компонентов
- [ ] Базируется на существующих паттернах
- [ ] Совместим с UI Kit системы
- [ ] Документирован в Storybook/UI Kit демо
- [ ] Протестирован на различных устройствах
- [ ] Соответствует принципам дизайн-системы
- [ ] **Применяет правило выравнивания с сайдбаром**
---
## 🎨 **13. ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ**
### 13.1 Базовая карточка
```tsx
<Card className="glass-card border-white/10 hover:border-white/20 transition-all">
<CardHeader>
<CardTitle className="text-white">Заголовок</CardTitle>
<CardDescription className="text-white/70">Описание</CardDescription>
</CardHeader>
<CardContent>
<p className="text-white/80">Содержимое карточки</p>
</CardContent>
</Card>
```
### 13.2 Интерактивная кнопка
```tsx
<Button variant="glass" className="hover:scale-105 transition-transform" onClick={handleClick}>
<Icon className="h-4 w-4 mr-2" />
Действие
</Button>
```
### 13.3 Форма с валидацией
```tsx
<div className="space-y-2">
<Label className="text-white/90">Поле ввода</Label>
<Input className="glass-input text-white placeholder:text-white/50" placeholder="Введите значение..." />
{error && <p className="text-red-300 text-xs">{error}</p>}
</div>
```
### 13.4 Правильное выравнивание с сайдбаром
```tsx
// ✅ ПРАВИЛЬНАЯ структура страницы с сайдбаром
function PageWithSidebar() {
const { getSidebarMargin } = useSidebar()
return (
<div className="h-screen flex overflow-hidden">
<Sidebar />
<main className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}>
<div className="h-full flex flex-col">
{/* Структура из 3 блоков согласно rules1.md */}
<div className="flex-1 flex gap-2 min-h-0">
{/* Левые блоки */}
<div className="flex-1 flex flex-col gap-2 min-h-0">
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl">
{/* Блок 1: Основной контент */}
</div>
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-1">
{/* Блок 2: Дополнительный контент */}
</div>
</div>
{/* Правый блок */}
<div className="w-96 flex-shrink-0">
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl h-full">
{/* Блок 3: Боковая панель */}
</div>
</div>
</div>
</div>
</main>
</div>
)
}
```
---
## 14. 🏢 КАБИНЕТ-СПЕЦИФИЧНЫЕ КОМПОНЕНТЫ
> 📌 **СВЯЗАНО С**: [rules-complete.md - Структура кабинетов](#3--структура-кабинетов)
### 14.1 Кабинет фулфилмента
#### 14.1.1 Визуальная система 6 модулей склада
**ЦВЕТОВОЕ КОДИРОВАНИЕ** (обязательная последовательность):
```css
/* 1. ПРОДУКТЫ - готовые к отправке */
.module-products {
@apply bg-green-500/20 border-green-400 text-green-100;
--icon-color: #10b981; /* emerald-500 */
}
/* 2. ТОВАРЫ - базовые товары */
.module-goods {
@apply bg-blue-500/20 border-blue-400 text-blue-100;
--icon-color: #3b82f6; /* blue-500 */
}
/* 3. БРАК - дефектные товары */
.module-defect {
@apply bg-red-500/20 border-red-400 text-red-100;
--icon-color: #ef4444; /* red-500 */
}
/* 4. ВОЗВРАТЫ С ПВЗ - возвращенные товары */
.module-returns {
@apply bg-yellow-500/20 border-yellow-400 text-yellow-100;
--icon-color: #eab308; /* yellow-500 */
}
/* 5. РАСХОДНИКИ СЕЛЛЕРОВ - материалы клиентов */
.module-seller-supplies {
@apply bg-purple-500/20 border-purple-400 text-purple-100;
--icon-color: #a855f7; /* purple-500 */
}
/* 6. РАСХОДНИКИ ФУЛФИЛМЕНТА - операционные материалы (КЛИКАБЕЛЬНЫЙ) */
.module-ff-supplies {
@apply bg-orange-500/20 border-orange-400 text-orange-100 cursor-pointer hover:bg-orange-400/30;
--icon-color: #f97316; /* orange-500 */
transition: all 0.2s ease-in-out;
}
```
#### 14.1.2 3-уровневая иерархия склада
**ВИЗУАЛЬНАЯ СТРУКТУРА**:
```tsx
// УРОВЕНЬ 1: МАГАЗИНЫ (синий - крупные блоки)
<div className="border-l-4 border-blue-500 bg-blue-500/10 pl-4 mb-3">
<div className="flex items-center gap-3">
<div className="w-4 h-4 rounded-full bg-blue-500"></div>
<span className="text-blue-100 font-semibold text-lg">ТехноМир</span>
</div>
{/* УРОВЕНЬ 2: ТОВАРЫ (зеленый - средние блоки) */}
<div className="border-l-4 border-green-500 bg-green-500/10 pl-6 ml-2 mt-2 mb-2">
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-green-500"></div>
<span className="text-green-100 font-medium">Смартфон iPhone 15</span>
</div>
{/* УРОВЕНЬ 3: ВАРИАНТЫ (оранжевый - мелкие блоки) */}
<div className="border-l-2 border-orange-500 bg-orange-500/10 pl-4 ml-1 mt-1">
<div className="flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-orange-500"></div>
<span className="text-orange-100 text-sm">128GB Space Black</span>
</div>
</div>
</div>
</div>
```
### 14.2 Статусы поставок - расширенная цветовая система
**8 СТАТУСОВ WORKFLOW** (согласно rules-complete.md):
```css
/* 1. PENDING - ожидает подтверждения */
.status-pending {
@apply bg-gray-500/20 border-gray-400 text-gray-100;
--dot-color: #6b7280;
}
/* 2. SUPPLIER_APPROVED - подтверждено поставщиком */
.status-supplier-approved {
@apply bg-blue-500/20 border-blue-400 text-blue-100;
--dot-color: #3b82f6;
}
/* 3. CONFIRMED - подтверждено системой */
.status-confirmed {
@apply bg-cyan-500/20 border-cyan-400 text-cyan-100;
--dot-color: #06b6d4;
}
/* 4. LOGISTICS_CONFIRMED - подтверждено логистикой */
.status-logistics-confirmed {
@apply bg-indigo-500/20 border-indigo-400 text-indigo-100;
--dot-color: #6366f1;
}
/* 5. SHIPPED - отправлено */
.status-shipped {
@apply bg-purple-500/20 border-purple-400 text-purple-100;
--dot-color: #a855f7;
}
/* 6. IN_TRANSIT - в пути */
.status-in-transit {
@apply bg-yellow-500/20 border-yellow-400 text-yellow-100;
--dot-color: #eab308;
}
/* 7. DELIVERED - доставлено */
.status-delivered {
@apply bg-green-500/20 border-green-400 text-green-100;
--dot-color: #22c55e;
}
/* 8. COMPLETED - завершено (только для фулфилмента) */
.status-completed {
@apply bg-emerald-600/20 border-emerald-500 text-emerald-100;
--dot-color: #059669;
}
```
### 14.3 Процесс создания продукта - визуальный workflow
**ПОШАГОВЫЙ ИНДИКАТОР** (5 шагов согласно rules-complete.md):
```tsx
const productCreationSteps = [
{ id: 'recipe', label: 'Рецептура задана', status: 'completed' },
{ id: 'arrival', label: 'Поступление на склад', status: 'completed' },
{ id: 'planning', label: 'Планирование работы', status: 'active' },
{ id: 'processing', label: 'Обработка товара', status: 'pending' },
{ id: 'quality', label: 'Контроль качества', status: 'pending' },
{ id: 'completion', label: 'Завершение', status: 'pending' },
]
// Визуальный компонент
;<div className="flex items-center justify-between mb-6">
{productCreationSteps.map((step, index) => (
<div key={step.id} className="flex items-center">
<div
className={`
flex items-center justify-center w-10 h-10 rounded-full border-2 text-sm font-semibold
${step.status === 'completed' ? 'bg-green-500 border-green-500 text-white' : ''}
${step.status === 'active' ? 'bg-blue-500 border-blue-500 text-white animate-pulse' : ''}
${step.status === 'pending' ? 'bg-white/10 border-white/30 text-white/50' : ''}
`}
>
{step.status === 'completed' ? '✓' : index + 1}
</div>
<span className="ml-2 text-sm text-white/70">{step.label}</span>
{index < productCreationSteps.length - 1 && <div className="w-12 h-0.5 bg-white/20 mx-4"></div>}
</div>
))}
</div>
```
### 14.4 Система партнерства - визуальные индикаторы
**ТИПЫ ПАРТНЕРОВ**:
```css
/* WHOLESALE - поставщики */
.partner-wholesale {
@apply bg-emerald-500/20 border-emerald-400;
--icon: '🏭'; /* factory */
}
/* SELLER - селлеры */
.partner-seller {
@apply bg-blue-500/20 border-blue-400;
--icon: '🛍️'; /* shopping */
}
/* FULFILLMENT - фулфилмент центры */
.partner-fulfillment {
@apply bg-purple-500/20 border-purple-400;
--icon: '📦'; /* package */
}
/* LOGIST - логистические компании */
.partner-logist {
@apply bg-orange-500/20 border-orange-400;
--icon: '🚚'; /* truck */
}
```
### 14.5 Кабинет селлера
> 📌 **СВЯЗАНО С**: [rules-complete.md - Кабинет селлера](#9--кабинет-селлера-детальные-правила)
#### 14.5.1 Трёхблочная архитектура страницы "Мои поставки"
**КРИТИЧЕСКИ ВАЖНО**: Правильное выравнивание с сайдбаром
```tsx
// ✅ ПРАВИЛЬНАЯ архитектура (согласно rules-complete.md)
export function SuppliesPage() {
const { getSidebarMargin } = useSidebar();
return (
<div className="h-screen flex overflow-hidden">
<Sidebar />
<main className={`flex-1 ${getSidebarMargin()} overflow-hidden transition-all duration-300`}>
<div className="h-full flex flex-col">
{/* БЛОК 1: ТАБЫ - фиксированная высота, glass-эффект */}
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-6 mb-2">
<TabNavigation />
</div>
{/* БЛОК 2: СТАТИСТИКА - контекстные метрики */}
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl p-4 mb-2">
<SupplyStatistics />
</div>
{/* БЛОК 3: ОСНОВНОЙ КОНТЕНТ - до низа sidebar */}
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-1 overflow-hidden">
<SupplyContent />
</div>
</div>
</main>
</div>
);
}
// ❌ НЕПРАВИЛЬНО (текущее состояние)
<div className="px-2 py-2"> {/* Нарушает архитектуру! */}
```
#### 14.5.2 Контекстная статистика по табам
**Для пути "Фулфилмент → Товар → Карточки/Поставщики":**
```tsx
const suppliesStats = [
{ label: 'Всего поставок', value: '24', color: 'text-blue-400' },
{ label: 'Активных поставок', value: '8', color: 'text-green-400' },
{ label: 'Сумма активных поставок', value: '₽142,350', color: 'text-yellow-400' },
{ label: 'В пути', value: '3', color: 'text-purple-400' },
]
```
**Для пути "Фулфилмент → Расходники селлера":**
```tsx
const consumablesStats = [
{ label: 'Всего поставок', value: '12', color: 'text-blue-400' },
{ label: 'Активных поставок', value: '4', color: 'text-green-400' },
{ label: 'Видов расходников', value: '18', color: 'text-orange-400' },
{ label: 'Критические остатки', value: '2', color: 'text-red-400' },
]
```
**Для путей "Маркетплейсы → Wildberries/Ozon":**
```tsx
const marketplaceStats = [
{ label: 'Поставок на маркетплейс', value: '15', color: 'text-blue-400' },
{ label: 'Товаров отправлено', value: '347', color: 'text-green-400' },
{ label: 'Возвраты за неделю', value: '12', color: 'text-yellow-400' },
{ label: 'Эффективность поставок', value: '94%', color: 'text-emerald-400' },
]
```
#### 14.5.3 Система создания поставок
**Выбор типа поставки:**
```tsx
const supplyTypes = [
{
id: 'goods-cards',
title: 'Карточки товаров',
description: 'Импорт через WB API с автосозданием поставки',
icon: '📱',
color: 'bg-blue-500/20 border-blue-400',
},
{
id: 'goods-suppliers',
title: 'Поставщики товаров',
description: 'Прямой заказ с указанием рецептуры',
icon: '🏭',
color: 'bg-emerald-500/20 border-emerald-400',
},
{
id: 'consumables',
title: 'Расходники селлера',
description: 'Материалы для производства',
icon: '🔧',
color: 'bg-purple-500/20 border-purple-400',
// ВАЖНО: На странице /supplies/create-consumables НЕ отображается заголовок и описание
pageHeader: false,
},
]
```
#### 14.5.4 Интерфейс рецептуры продукта
**3-блочная структура создания рецептуры:**
```tsx
// БЛОК 1: БАЗОВЫЙ ТОВАР (слева)
<div className="w-1/3 bg-white/5 border border-white/10 rounded-xl p-4">
<h3 className="text-white font-semibold mb-3">1. Базовый товар</h3>
<ProductSelector
placeholder="Выберите товар от поставщика"
filterType="PRODUCT"
/>
</div>
// БЛОК 2: УСЛУГИ ФУЛФИЛМЕНТА (центр)
<div className="w-1/3 bg-white/5 border border-white/10 rounded-xl p-4">
<h3 className="text-white font-semibold mb-3">2. Услуги ФФ</h3>
<ServicesSelector
placeholder="Упаковка, маркировка..."
multiSelect={true}
/>
</div>
// БЛОК 3: РАСХОДНИКИ (справа)
<div className="w-1/3 bg-white/5 border border-white/10 rounded-xl p-4">
<h3 className="text-white font-semibold mb-3">3. Расходники</h3>
<ConsumablesSelector
placeholder="Материалы для производства"
filterType="CONSUMABLE"
/>
</div>
```
#### 14.5.5 WB интеграция - визуальные индикаторы
**Статусы синхронизации с WB API:**
```css
/* Успешная синхронизация */
.wb-sync-success {
@apply bg-green-500/20 border-green-400 text-green-100;
--status-icon: '✅';
}
/* Ошибка синхронизации */
.wb-sync-error {
@apply bg-red-500/20 border-red-400 text-red-100;
--status-icon: '❌';
}
/* В процессе синхронизации */
.wb-sync-loading {
@apply bg-yellow-500/20 border-yellow-400 text-yellow-100;
--status-icon: '⏳';
animation: pulse 2s infinite;
}
/* Не настроена */
.wb-sync-none {
@apply bg-gray-500/20 border-gray-400 text-gray-100;
--status-icon: '⚠️';
}
```
---
**📊 СТАТУС**: Действующие правила v1.2 (добавлен кабинет селлера)
**🔄 ОБНОВЛЕНО**: Интеграция с rules-complete.md v6.2
**📅 ДАТА**: 2025, полная синхронизация с техническими требованиями
### 🆕 ДОБАВЛЕНИЯ v1.2:
- ✅ Детальные правила для кабинета селлера (раздел 14.5)
- ✅ Трёхблочная архитектура страницы "Мои поставки"
- ✅ Контекстная статистика по типам поставок
- ✅ Визуальные компоненты создания рецептуры
- ✅ WB интеграция и статусы синхронизации
- ✅ Исправление архитектурного нарушения px-2 py-2

View File

@ -0,0 +1,336 @@
# ПРАВИЛА КАБИНЕТА ПОСТАВЩИКА (WHOLESALE)
> ⚠️ **ВАЖНО**: Это файл с техническими деталями кабинета поставщика.
> Общие бизнес-правила находятся в **[rules-complete.md](./rules-complete.md)**
## Когда использовать этот файл:
- Работа с компонентами `/warehouse`, `/supplier-orders`
- GraphQL запросы для поставщиков
- UI/UX специфика кабинета поставщика
- Технические детали реализации
## 1. 🏪 СТРУКТУРА КАБИНЕТА ПОСТАВЩИКА
### 1.1 Основные разделы
**ПОСТАВЩИК (`WHOLESALE`)** имеет доступ к следующим разделам:
- **Склад** (`/warehouse`) - управление товарами и расходниками
- **Поставки** (`/supplies`) - обработка заказов от селлеров
- **Маркет** (`/market`) - просмотр глобального каталога
- **Партнеры** (`/partners`) - управление контрагентами
- **Мессенджер** (`/messenger`) - связь с партнерами
- **Настройки** (`/settings`) - профиль и API ключи
- **Экономика** (`/economics`) - финансовая аналитика
### 1.2 Навигация и роутинг
#### При входе в систему:
```typescript
switch (user?.organization?.type) {
case 'WHOLESALE':
router.push('/supplies') // Направляем на страницу поставок
break
}
```
#### Специальная логика роутинга:
> 📖 **Бизнес-логика роутинга**: См. [rules-complete.md#4-система-ролей-и-доступов](./rules-complete.md#4--система-ролей-и-доступов)
## 2. 🎨 UI/UX КОМПОНЕНТЫ
### 2.1 Dashboard компоненты
#### Основные компоненты кабинета:
- `WarehouseDashboard` - главный компонент склада
- `SupplierOrdersDashboard` - управление заказами
- `WholesaleEconomicsPage` - экономическая аналитика
- `WholesaleHomePage` - домашняя страница поставщика
#### Wrapper-компоненты:
- `HomePageWrapper` - маршрутизация по типам организаций
- `EconomicsPageWrapper` - адаптивная экономика по кабинетам
#### Специализированные компоненты:
- `SupplierOrderCard` - карточка заказа для поставщика
- `SupplierOrdersContent` - контент страницы заказов
- `SupplierOrdersSearch` - поиск по заказам
- `SupplierOrdersTabs` - табы (активные/завершенные)
- `SupplierOrderStats` - статистика и аналитика заказов
### 2.2 Карточка поставщика в интерфейсе
#### Структура карточки:
```jsx
<div className="supplier-card glass-card">
<div className="flex items-start gap-2">
{/* Аватар организации */}
<OrganizationAvatar organization={supplier} size="sm" />
<div className="flex-1 min-w-0">
{/* Название поставщика */}
<h4 className="text-white font-medium text-sm truncate">{supplier.name || supplier.fullName}</h4>
{/* ИНН и рынок */}
<div className="flex items-center gap-2 mt-1">
<p className="text-white/60 text-xs font-mono">ИНН: {supplier.inn}</p>
{supplier.market && <Badge className="market-badge">{getMarketLabel(supplier.market)}</Badge>}
</div>
</div>
</div>
</div>
```
#### Визуальные правила:
- **Аватар**: Размер `sm`, слева от текста
- **Название**: Приоритет `name` над `fullName`
- **ИНН**: Моноширинный шрифт, цвет `text-white/60`
- **Рынок**: Badge компонент с индивидуальными цветами
### 2.3 Поисковый интерфейс
```jsx
<Input
placeholder="Поиск поставщиков..."
className="bg-white/5 border-white/10 text-white placeholder:text-white/50 pl-10 h-9"
onChange={(e) => handleSearch(e.target.value)}
/>
```
### 2.4 Цветовые схемы рынков
> 📖 **Полная палитра цветов**: См. [visual-design-rules.md](./visual-design-rules.md)
Примеры для рынков:
- **"Садовод"** (`sadovod`): `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (`tyak-moscow`): `bg-blue-500/20 text-blue-300 border-blue-500/30`
## 3. 📊 ФУНКЦИОНАЛЬНЫЕ ВОЗМОЖНОСТИ
> 📖 **Бизнес-правила**: См. [rules-complete.md#10-кабинет-поставщика](./rules-complete.md#10--кабинет-поставщика) для правил создания товаров, обязательных полей и статистики
## 4. 🛠️ GRAPHQL API
### 4.1 Основные запросы (Queries)
#### Получение товаров поставщика:
```graphql
query GetMyProducts {
myProducts {
id
name
article
price
quantity
organization {
id
name
market # Физический рынок поставщика
}
}
}
```
#### Получение заказов:
```graphql
query GetSupplierOrders {
supplyOrders(where: { partnerId: $myOrgId }) {
id
status
totalAmount
organization {
name # Заказчик
}
}
}
```
#### Получение партнеров:
```graphql
query GetMyCounterparties {
myCounterparties {
id
name
type
market
fullName
inn
}
}
```
### 4.2 Мутации (Mutations)
#### Создание товара:
```graphql
mutation CreateProduct($input: ProductInput!) {
createProduct(input: $input) {
success
product {
id
article
organization {
id
name
}
}
}
}
```
#### Обработка заказов поставщиком:
```graphql
mutation ApproveSupplyOrder($orderId: ID!) {
approveSupplyOrder(id: $orderId) {
success
order {
id
status
organization {
id
name
}
}
}
}
mutation RejectSupplyOrder($orderId: ID!, $reason: String) {
rejectSupplyOrder(id: $orderId, reason: $reason) {
success
message
}
}
```
#### Отгрузка заказов:
```graphql
mutation ShipSupplyOrder($orderId: ID!) {
shipSupplyOrder(id: $orderId) {
success
order {
id
status # SHIPPED -> IN_TRANSIT
organization {
id
name
}
}
}
}
```
### 4.3 Правила партнерства
**КРИТИЧЕСКОЕ ПРАВИЛО**: Поставщики в формах берутся ТОЛЬКО из партнеров с типом `WHOLESALE`
```typescript
// ✅ ПРАВИЛЬНО
const suppliers = await useQuery(GET_MY_COUNTERPARTIES, {
variables: { type: 'WHOLESALE' },
})
// ❌ НЕПРАВИЛЬНО
const suppliers = await useQuery(GET_SUPPLY_SUPPLIERS)
```
> 📖 **Система партнерства**: См. [rules-complete.md#13-система-партнерства-и-контрагентов](./rules-complete.md#13--система-партнерства-и-контрагентов)
## 5. 📁 ТЕХНИЧЕСКИЕ КОМПОНЕНТЫ
> 📖 **Архитектура рынков**: См. [rules-complete.md#10-кабинет-поставщика](./rules-complete.md#10--кабинет-поставщика) для бизнес-логики принадлежности к рынкам
### 5.1 Расположение компонентов
```
src/components/
├── warehouse/ # Компоненты склада
│ ├── warehouse-dashboard.tsx
│ ├── product-card.tsx
│ ├── product-form.tsx
│ └── warehouse-statistics.tsx
├── supplier-orders/ # Компоненты заказов
│ ├── supplier-orders-dashboard.tsx
│ ├── supplier-order-card.tsx
│ └── supplier-orders-tabs.tsx
└── economics/ # Экономика
└── wholesale-economics-page.tsx
```
### 5.2 Страницы (Pages)
```
src/app/
├── warehouse/
│ └── page.tsx # Страница склада
├── supplier-orders/
│ └── page.tsx # Страница заказов
└── [общие страницы] # См. rules-complete.md
```
## 6. 🚨 ТЕХНИЧЕСКИЕ ПРАВИЛА И ОГРАНИЧЕНИЯ
> 📖 **Workflow поставок**: См. [rules-complete.md#5-workflow-поставок](./rules-complete.md#5--workflow-поставок) для бизнес-процессов
### 6.1 Обязательные проверки:
- Проверка типа организации: `organization.type === 'WHOLESALE'`
- Валидация прав доступа на уровне GraphQL резолверов
- Контроль остатков при подтверждении заказов
### 6.2 Правила безопасности доступа:
#### Контроль на уровне компонентов:
```typescript
{user?.organization?.type === "WHOLESALE" && (
<WarehouseDashboard />
)}
```
#### Проверки в 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,
},
})
```
### 6.3 Запрещено:
- Создавать товары с типами `DEFECT` или `FINISHED_PRODUCT`
- Изменять статусы заказов минуя workflow
- Показывать данные других поставщиков
> 📖 **Критические запреты**: См. [rules-complete.md#17-критические-запреты](./rules-complete.md#17--критические-запреты)
---
**Последнее обновление**: Декабрь 2024
**Связанные файлы**:
- [rules-complete.md](./rules-complete.md) - Общие бизнес-правила
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила

View File

@ -0,0 +1,1834 @@
# КАТАЛОГ ВСЕХ БИЗНЕС-ПРОЦЕССОВ СИСТЕМЫ
> ⚠️ **НАЗНАЧЕНИЕ**: Полный каталог всех бизнес-процессов и workflow системы управления складами.
> **Источник**: Все процессы из [rules-complete.md](./rules-complete.md) собраны в одном месте для удобного поиска.
---
## 📋 **ОГЛАВЛЕНИЕ**
### Основные процессы:
- [1. Workflow поставок](#1-workflow-поставок) - 8 статусов, 6 этапов
- [2. Процесс создания продукта](#2-процесс-создания-продукта) - 5 шагов с SLA
- [3. UI процессы селлера](#3-ui-процессы-селлера) - 4-блочная система
- [4. Workflow фулфилмента](#4-workflow-фулфилмента) - 3 этапа обработки
- [5. Workflow логистики](#5-workflow-логистики) - 4 этапа доставки
- [6. Система партнерства](#6-система-партнерства) - 2 способа, 4 статуса
- [7. Интеграция с услугами](#7-интеграция-с-услугами) - 5-шаговый workflow
- [8. Критические ситуации](#8-критические-ситуации) - отмены и чрезвычайные
### Вспомогательные процессы:
- [9. Протоколы разработки](#9-протоколы-разработки) - последовательность работы
- [10. Система учета движения товаров](#10-система-учета-движения-товаров)
### Индекс по ролям:
- **Селлер**: процессы 1, 2, 3, 6
- **Поставщик**: процессы 1, 6
- **Фулфилмент**: процессы 1, 2, 4, 7
- **Логистика**: процессы 1, 5
---
## 1. 🚚 **WORKFLOW ПОСТАВОК**
> **Источник**: rules-complete.md, раздел 5, строки 519-563
### 1.1 Детализированная система статусов
**Статусы SupplyOrder (Заказ поставки):**
1. **PENDING** - Ожидает подтверждения поставщиком
2. **SUPPLIER_APPROVED** - Одобрено поставщиком
3. **CONFIRMED** - Подтвержден (готов к обработке)
4. **LOGISTICS_CONFIRMED** - Подтверждено логистикой
5. **SHIPPED** - Отгружено поставщиком
6. **IN_TRANSIT** - В пути (логистика доставляет)
7. **DELIVERED** - Доставлен на фулфилмент
8. **CANCELLED** - Отменен
### 1.2 Пошаговый процесс поставки
**ЭТАП 1: Создание заказа**
1. Селлер заказывает товар/расходники у поставщика
2. Система создает SupplyOrder со статусом `PENDING`
3. Автоматическое уведомление поставщику
**ЭТАП 2: Обработка поставщиком**
4. Поставщик получает оповещение
5. Поставщик нажимает "Одобрить"
6. Статус меняется на `SUPPLIER_APPROVED`
**ЭТАП 3: Передача в фулфилмент**
7. Поставка отображается в кабинете фулфилмента
8. Фулфилмент выбирает ответственного и логистику
9. Статус меняется на `CONFIRMED`
**ЭТАП 4: Логистическое подтверждение**
10. Логистика подтверждает доставку
11. Статус меняется на `LOGISTICS_CONFIRMED`
**ЭТАП 5: Отгрузка**
12. Поставщик отгружает товар
13. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
**ЭТАП 6: Доставка и приемка**
14. Логистика доставляет на фулфилмент
15. Фулфилмент принимает товар
16. Статус меняется на `DELIVERED`
### 1.3 Система уведомлений
**Обязательные уведомления:**
- Поставщику: о новом заказе
- Фулфилменту: о подтвержденной поставке
- Логистике: о назначении на заявку
- Селлеру: об изменении каждого статуса
---
## 2. 🔄 **ПРОЦЕСС СОЗДАНИЯ ПРОДУКТА**
> **Источник**: rules-complete.md, раздел 6, строки 565-740
### 2.1 5-шаговый алгоритм создания
**ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ**: Рецептура задана селлером
**ШАГ 1: Поступление на склад (автоматически)**
- Товар поступает на склад фулфилмента
- Система фиксирует поступление
- Товар получает статус "доступен для обработки"
**ШАГ 2: Планирование работы (менеджер фулфилмента)**
- Менеджер фулфилмента видит товар в интерфейсе
- Планирует обработку согласно рецептуре
- Назначает исполнителя
**ШАГ 3: Обработка товара (исполнитель)**
- Исполнитель берет товар в работу
- Применяет услуги согласно рецептуре
- Использует расходники селлера и фулфилмента
- Товар превращается в продукт
**ШАГ 4: Контроль качества (менеджер/отдел качества)**
- Проверка соответствия рецептуре
- Контроль качества обработки
- Подтверждение или возврат на доработку
**ШАГ 5: Завершение (система + менеджер)**
- Система создает запись о готовом продукте
- Продукт получает статус FINISHED_PRODUCT
- Готов к отправке селлеру
### 2.2 Временные рамки и SLA
| Этап | Время выполнения | Ответственный | KPI |
| ------------ | ---------------- | ------------- | ------------------ |
| Поступление | Мгновенно | Система | 100% автоматизация |
| Планирование | До 2 часов | Менеджер ФФ | 95% в срок |
| Обработка | 1-3 дня | Исполнитель | Согласно сложности |
| Контроль | До 4 часов | ОТК | 99% точность |
### 2.3 Детальная рецептура продукта
**РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
- **БАЗОВЫЙ ТОВАР**: Исходный материал (обязательно)
- Артикул товара
- Количество единиц
- Размерная сетка (если применимо)
- **УСЛУГА ФУЛФИЛМЕНТА**: Из каталога услуг фулфилмента
- Тип услуги (глажка, упаковка, маркировка и т.д.)
- Количество применений
- Специальные требования
- **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
- Фирменная упаковка
- Этикетки, бирки
- Дополнительные аксессуары
- **РАСХОДНИК ФУЛФИЛМЕНТА**: Материалы фулфилмента (опционально)
- Стандартная упаковка
- Защитные материалы
- Маркировочные элементы
- **СВЯЗЬ С МАРКЕТПЛЕЙСОМ**: Привязка к карточке (опционально)
- ID карточки на маркетплейсе
- Артикул маркетплейса
- Особые требования МП
**ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
### 2.4 Пошаговый алгоритм создания продукта
#### **ПРЕДВАРИТЕЛЬНОЕ УСЛОВИЕ: РЕЦЕПТУРА ЗАДАНА** (селлер)
```
Время: при создании заявки на поставку
Действие: селлер указывает рецептуру продукта
Обязательные компоненты:
✓ Базовый товар (от поставщика)
✓ Услуги фулфилмента (упаковка, маркировка и т.д.)
✓ Расходники (материалы для производства)
Результат: рецептура сохраняется в заявке и передается фулфилменту
```
#### **ШАГ 1: ПОСТУПЛЕНИЕ НА СКЛАД** (автоматически)
```
Время: при смене статуса поставки DELIVERED
Действие: товар переходит в статус "на складе"
Ответственный: система
Результат: +Прибыло в статистике товаров
```
#### **ШАГ 2: ПЛАНИРОВАНИЕ РАБОТЫ** (менеджер фулфилмента)
```
Время: в течение 2 рабочих дней после поступления
Действие: назначение параметров обработки
Ответственный: менеджер фулфилмента
Обязательные поля:
✓ Дедлайн выполнения (не более 5 рабочих дней)
✓ Ответственный исполнитель (из списка сотрудников)
✓ Рецептура (товар + услуги + расходники, указанная селлером в заявке на поставку)
Опциональные поля:
- Место хранения готовых продуктов (зона склада, стеллаж, ячейка)
- Комментарии к работе
Результат: поставка переходит во вкладку "В работе"
```
#### **ШАГ 3: ОБРАБОТКА ТОВАРА** (исполнитель)
```
Время: согласно дедлайну (обычно 1-3 дня)
Действие: физическая обработка товара
Ответственный: назначенный сотрудник
Обязательные действия:
1. Проверка качества товара
2. Фиксация фактического количества
3. Выявление и учет брака
4. Применение рецептуры (услуги + расходники)
5. Создание готового продукта
Точки контроля:
- Соответствие плану/факту
- Качество выполнения услуг
- Расход материалов по норме
УЧЕТ ПЛАН/ФАКТ:
- ПЛАН: Количество товаров из поставки селлера (указано в заказе)
- ФАКТ: Реальное количество после обработки = Брак + Хороший товар
- ДЕТАЛИЗАЦИЯ: Учет ведется по каждому размеру/объему/варианту
- КОРРЕКТИРОВКА: Статистика автоматически обновляется на фактические данные
```
#### **ШАГ 4: КОНТРОЛЬ КАЧЕСТВА** (менеджер/отдел качества)
```
Время: сразу после завершения ШАГ 3
Действие: приемка готовой продукции
Ответственный: менеджер или контролер качества
Критерии приемки:
✓ Соответствие рецептуре селлера
✓ Качество выполненных услуг
✓ Правильность упаковки/маркировки
✓ Полнота комплектации
Результат: продукт готов к отправке или отправлен на доработку
```
#### **ШАГ 5: ЗАВЕРШЕНИЕ** (система + менеджер)
```
Время: после успешного прохождения контроля качества
Действие: финализация процесса
Автоматические действия:
- Создание записи FINISHED_PRODUCT в БД
- Обновление статистики: товар "на складе" → продукт "готов"
- Списание использованных расходников
- Уведомление селлера о готовности
Ручные действия менеджера:
- Подтверждение перехода во вкладку "Выполнено"
- Указание фактических расходов материалов
- Добавление комментариев о выполненной работе
```
### 2.5 Временные рамки и SLA
| Этап | Стандартное время | Максимальное время | Ответственный |
| ----------------- | ----------------- | ------------------ | -------------- |
| Планирование | 1 рабочий день | 2 рабочих дня | Менеджер ФФ |
| Обработка | 2-3 рабочих дня | 5 рабочих дней | Исполнитель |
| Контроль качества | 4 часа | 1 рабочий день | Отдел качества |
| Завершение | 2 часа | 4 часа | Менеджер ФФ |
### 2.6 Детальная рецептура продукта
**РЕЦЕПТУРА ПРОДУКТА** (задается селлером при создании поставки):
- **БАЗОВЫЙ ТОВАР**: Исходный материал (обязательно)
- Артикул товара
- Количество единиц
- Размерная сетка (если применимо)
- **УСЛУГА ФУЛФИЛМЕНТА**: Из каталога услуг фулфилмента
- Тип услуги (глажка, упаковка, маркировка и т.д.)
- Количество применений
- Специальные требования
- **РАСХОДНИК СЕЛЛЕРА**: Материалы селлера (опционально)
- Фирменная упаковка
- Этикетки, бирки
- Дополнительные аксессуары
- **РАСХОДНИК ФУЛФИЛМЕНТА**: Материалы фулфилмента (опционально)
- Стандартная упаковка
- Защитные материалы
- Маркировочные элементы
- **СВЯЗЬ С МАРКЕТПЛЕЙСОМ**: Привязка к карточке (опционально)
- ID карточки на маркетплейсе
- Артикул маркетплейса
- Особые требования МП
**ФОРМУЛА**: ПРОДУКТ = Товар + Услуга(и) + Расходники селлера + Расходники ФФ
### 2.7 Учет план/факт в процессе работы
**ПЛАН**: Количество товара из поставки селлера
**ФАКТ**: Реальное количество после пересчета (работник фулфилмента производит сортировку при пересчете)
**ФИКСАЦИЯ ПОТЕРЬ:**
- **КОГДА**: В процессе работы (вкладка "В работе")
- **ЧТО**: Недостача, повреждения (без создания записей брака)
- **КАК**: Корректировка количества в статистике
**WORKFLOW СОЗДАНИЯ ПРОДУКТА:**
1. Товар поступает на склад фулфилмента (статус "на складе")
2. Товар берется в работу (переход в статус "в обработке")
3. Исполнитель производит пересчет и сортировку
4. Создается готовый продукт (тип FINISHED_PRODUCT)
5. Продукт готов к отправке на маркетплейсы
**ВЛИЯНИЕ НА СТАТИСТИКУ:**
- При принятии поставки: +План в статистику
- При выявлении факта: корректировка на реальные данные
- **ФОРМУЛА**: Факт = Потери + Хороший товар
_Где потери - это недостача/повреждения, выявленные при пересчете и сортировке_
- **ЛОГИКА**: Фактическое количество = сумма всех пересчитанных предметов
- **ПЛАН/ФАКТ**: Корректировка статистики при выявлении расхождений
---
## 3. 🎨 **UI ПРОЦЕССЫ СЕЛЛЕРА**
> **Источник**: rules-complete.md, раздел 9, строки 871-1885 (1015 строк)
### 3.1 Структура раздела "Мои поставки"
#### **🏢 ПОСТАВКИ НА ФУЛФИЛМЕНТ**:
- **Товар** - поставка товаров для создания продуктов
- **Карточки** - поставка через WB API с рецептурой (результат: WildberriesSupply)
- **Поставщики** - заказ товаров у поставщиков с рецептурой (результат: SupplyOrder)
- **Расходники селлера** - поставка материалов для товаров селлера
#### **🛒 ПОСТАВКИ НА МАРКЕТПЛЕЙСЫ** _(планируется)_:
- **Wildberries** - прямые поставки на WB
- **Ozon** - прямые поставки на Ozon
### 3.2 UI структура создания поставки расходников селлера
#### **📄 Структура страницы создания поставки:**
**ОБНОВЛЕННАЯ СТРУКТУРА СИСТЕМЫ (4 БЛОКА):**
**БЛОК 1: ПОСТАВЩИКИ** _(адаптивная сетка)_
- **Заголовок**: Минималистичный "🏢 Поставщики" без лишних элементов
- **Поиск**: Компактное поле справа "Поиск поставщиков..." (w-64)
- **Отображение**: Карточки поставщиков из раздела "Партнеры" в адаптивной сетке
- **Выбор**: Клик выделяет карточку поставщика
- **Результат**: Загружаются карточки товаров выбранного поставщика в блок 2
**БЛОК 2: КАРТОЧКИ ТОВАРОВ** _(горизонтальный скролл - НОВЫЙ)_
- **Отображение**: ТОЛЬКО минималистичные карточки товаров 80×112px
- **Содержание**: ТОЛЬКО изображение товара, БЕЗ текста/названий/цен
- **Навигация**: Горизонтальный скролл при множестве товаров
- **Выбор**: Клик добавляет товар в детальный каталог
- **Результат**: Товар добавляется в блок 3 для управления поставкой
**БЛОК 3: ТОВАРЫ ПОСТАВЩИКА** _(детальный каталог)_
- **Отображение**: Детальные карточки выбранных товаров
- **Управление**: Количество, параметры, настройки поставки
- **Результат**: Формирование окончательной поставки
**БЛОК 4: КОРЗИНА И НАСТРОЙКИ** _(правая панель)_
- **Отображение**: Корзина поставки + настройки
- **Управление**: Фулфилмент-центр, дата, логистика
#### **3.2.1 Детальные правила горизонтального скролла поставщиков**
**СТРУКТУРА И ОТОБРАЖЕНИЕ:**
- **Источник данных**: Партнеры типа `WHOLESALE` из раздела "Партнеры"
- **Контейнер**: Фиксированная высота 176px (h-44) с горизонтальным скроллом
- **Блок поставщиков**: Общая высота 180px, включает заголовок + контейнер скролла
- **Направление**: Слева направо (LTR)
- **Поведение**: Плавный скролл с автоскрытием полосы прокрутки
**РАЗМЕРЫ И АДАПТИВНОСТЬ:**
- **Десктоп**: Карточка 216×92px, отступы 12px между карточками, 16px от краев
- **Планшет**: Карточка 200×92px, отступы 12px между карточками
- **Мобильный**: Карточка 184×92px, отступы 12px между карточками
- **Высота блока**: 180px фиксированная для всего блока поставщиков
**ВЗАИМОДЕЙСТВИЕ:**
- **Навигация**: Колесо мыши (Shift+скролл), стрелки клавиатуры, свайп на тач
- **Выбор**: Клик по карточке → активная рамка + загрузка товаров в блок 2
- **Состояния**: Default, Hover (box-shadow), Active (цветная рамка), Loading (скелетон)
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **1-4 карточки**: Выравнивание по левому краю, скролл неактивен
- **5+ карточек**: Полный горизонтальный скролл
- **Нет партнеров**: Заглушка с ссылкой на раздел "Партнеры"
**ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
**Критическая Flex-архитектура:**
```css
.parent-container {
display: flex;
gap: 16px;
min-height: 0;
}
.left-block {
flex: 1;
min-width: 0; /* КРИТИЧЕСКИ ВАЖНО для overflow */
display: flex;
flex-direction: column;
}
.suppliers-container {
height: 180px; /* Общая высота блока */
flex-shrink: 0;
min-width: 0; /* Предотвращает растяжение */
}
.right-block {
width: 384px; /* w-96 */
flex-shrink: 0; /* Защита от сжатия */
}
```
**Контейнер скролла:**
```css
.suppliers-block {
display: flex;
overflow-x: auto;
scroll-behavior: smooth;
gap: 12px;
padding: 0 16px 8px 16px; /* px-4 pb-2 */
height: 176px; /* h-44 */
scrollbar-width: thin;
scrollbar-color: #64748b33 transparent;
}
.suppliers-block:hover {
scrollbar-color: #cbd5e0 #64748b22;
}
.supplier-card {
flex-shrink: 0;
width: 216px; /* Десктоп */
height: 92px; /* Фиксированная высота */
padding: 8px; /* p-2 */
transition: all 0.2s ease;
}
```
**СОДЕРЖАНИЕ КАРТОЧКИ ПОСТАВЩИКА:**
**Структура (3 строки в 92px высоты):**
- **Строка 1**: Название + рейтинг (справа, если есть)
- **Строка 2**: ИНН (формат "ИНН: 1234567890")
- **Строка 3**: Бейдж рынка (отдельная строка)
**Элементы:**
- **Аватар**: Размер xs, слева с gap-2
- **Текст**: text-xs для компактности
- **Отступы**: mb-1 между строками 1-2, mb-0.5 между строками 2-3
- **Padding карточки**: 8px (p-2)
**ЦВЕТОВАЯ СХЕМА РЫНКОВ:**
- **"Садовод"** (sadovod): Зеленый `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (tyak-moscow): Синий `bg-blue-500/20 text-blue-300 border-blue-500/30`
- **Другие/не указан**: Серый `bg-gray-500/20 text-gray-300 border-gray-500/30`
**ДОСТУПНОСТЬ:**
- `role="tablist"` для контейнера
- `role="tab"` для карточек
- `aria-selected="true/false"` для выбранной карточки
- `tabindex="0"` для активной, `-1` для неактивных
#### **3.2.2 Правила блока "Карточки товаров" (Блок 2)**
**НАЗНАЧЕНИЕ И ЛОГИКА:**
- **Источник данных**: Товары выбранного поставщика из Блока 1
- **Триггер отображения**: Клик на карточку поставщика → загрузка карточек товаров
- **Взаимодействие**: Клик на карточку товара → добавление в Блок 3 "Товары поставщика"
- **Поведение**: Горизонтальный скролл при множестве товаров
**АРХИТЕКТУРА И РАЗМЕРЫ:**
- **Внешний контейнер**: bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0
- **Внутренний контейнер скролла**: flex gap-3 overflow-x-auto p-4
- **Стилизация скролла**: scrollbarWidth: 'thin' для тонкой полосы прокрутки
- **Отступы**: padding: 16px (p-4) внутри, gap: 12px (gap-3) между карточками
- **Адаптивная высота**: по содержимому карточек (БЕЗ фиксированной высоты)
- **Визуальное единство**: стеклянный эффект как у других блоков системы
- **БЕЗ заголовков/иконок**: только чистые карточки товаров в контейнере
**РАЗМЕРЫ КАРТОЧЕК ТОВАРОВ:**
- **Компактная карточка**: 80×112px (w-20 h-28), соотношение 5:7
- **Адаптивность**: фиксированный размер для всех устройств
**СОДЕРЖАНИЕ КАРТОЧКИ ТОВАРА:**
- **ТОЛЬКО изображение товара**: 80×112px, object-cover
- **Минималистичный дизайн**: БЕЗ текста, названий, цен, иконок
- **Состояния**: Default, Selected, Active (БЕЗ Hover-эффектов)
- **Рамка**: border-white/10, при выборе border-white/30
- **Фон**: bg-white/5 полупрозрачный
**ДЕЙСТВИЕ:**
Клик на карточку → добавление товара в Блок 3 (детальный каталог)
#### **3.2.3 Правила Блока 3 "Детальный каталог товаров"**
**НАЗНАЧЕНИЕ И СТРУКТУРА:**
- **Контент**: Детальные карточки выбранных товаров с полным управлением
- **Верхняя панель**: Выбор даты + Выбор Fulfillment + Поиск
- **Основная область**: Сетка карточек товаров с детальной информацией
#### **3.2.3.1 Структура верхней панели Блока 3**
**МИНИМАЛИСТИЧНАЯ ПАНЕЛЬ УПРАВЛЕНИЯ:**
- **Выбор даты поставки**: DatePicker для планирования поставки
- **Выбор Fulfillment-центра**: Select dropdown со списком доступных фулфилментов
- **Поиск по товарам**: Input с иконкой поиска и placeholder
- **Компоновка**: Горизонтальная строка с равномерным распределением
**ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ:**
```tsx
// Структура компонентов панели
<div className="flex items-center gap-4 p-4 bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl mb-4">
<DatePicker placeholder="Дата поставки" />
<Select placeholder="Выберите фулфилмент">
<SelectContent>
{fulfillmentCenters.map((center) => (
<SelectItem value={center.id}>{center.name}</SelectItem>
))}
</SelectContent>
</Select>
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-white/40" />
<Input placeholder="Поиск товаров..." className="pl-10 glass-input" />
</div>
</div>
```
#### **3.2.3.2 Структура основной области карточек**
**СЕТКА ТОВАРОВ:**
- **Адаптивная сетка**: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4`
- **Детальные карточки**: Полная информация + количество + управление
- **Состояния**: Default, Selected, Editing
- **Интерактивность**: Изменение количества, удаление, настройки рецептуры
**ФУНКЦИОНАЛЬНОСТЬ ПАНЕЛИ:**
- **Выбор даты**: Планирование времени поставки (обязательное поле)
- **Выбор фулфилмента**: Определение исполнителя поставки (обязательное поле)
- **Поиск**: Фильтрация товаров в каталоге по названию/артикулу
- **Валидация**: Блокировка создания поставки без заполнения даты и фулфилмента
**ГРАНИЧНЫЕ СЛУЧАИ:**
- **Пустой каталог**: Заглушка "Добавьте товары"
- **Нет фулфилментов**: Сообщение "Настройте партнерство с фулфилмент-центрами"
- **Поиск без результатов**: "По запросу ничего не найдено"
#### **3.2.2.1 Структура контейнера Блока 2**
**ДВУХУРОВНЕВАЯ АРХИТЕКТУРА:**
**УРОВЕНЬ 1 - Внешний контейнер (блок):**
```jsx
<div className="bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl flex-shrink-0">
```
- **Назначение**: Визуальное обрамление блока, единство с другими блоками
- **Стилизация**: Стеклянный эффект с размытием и полупрозрачностью
- **Рамка**: Тонкая белая рамка border-white/20 с закруглёнными углами
- **Поведение**: flex-shrink-0 предотвращает сжатие блока
**УРОВЕНЬ 2 - Внутренний контейнер (скролл):**
```jsx
<div className="flex gap-3 overflow-x-auto p-4" style={{ scrollbarWidth: 'thin' }}>
```
- **Назначение**: Горизонтальная прокрутка карточек товаров
- **Раскладка**: Flex с промежутками gap-3 (12px) между карточками
- **Отступы**: padding p-4 (16px) со всех сторон
- **Скролл**: overflow-x-auto с тонкой полосой прокрутки
- **Поведение**: Автоматическое появление скролла при превышении ширины
**ПРАВИЛА КОНТЕЙНЕРОВ:**
- Внешний контейнер НЕ содержит заголовков, иконок, описаний
- Внутренний контейнер содержит ТОЛЬКО карточки товаров
- Высота адаптируется под размер карточек (80×112px + отступы)
- Визуальное единство со всеми блоками формы поставки
**ТЕХНИЧЕСКИЕ ПРАВИЛА:**
- **Условие отображения**: selectedSupplier && products.length > 0
- **Источник данных**: products массив из GraphQL запроса organizationProducts
- **Реактивность**: Автоматическое обновление при смене поставщика
- **Производительность**: React.memo для карточек при большом количестве товаров
- **Доступность**: Клавиатурная навигация (Tab, Enter для выбора)
**UX ПРАВИЛА ВЗАИМОДЕЙСТВИЯ:**
- **Скролл**: Автоматическое появление при превышении ширины контейнера
- **Индикация загрузки**: Скелетоны карточек во время загрузки товаров
- **Пустое состояние**: Скрытие блока при отсутствии поставщика или товаров
- **Фокус**: Первая карточка получает фокус при загрузке товаров
- **Навигация**: Стрелки ←→ для перемещения между карточками
**СОСТОЯНИЯ БЛОКА:**
- **Скрыт**: При отсутствии выбранного поставщика
- **Скрыт**: При отсутствии товаров у поставщика
- **Активен**: При наличии поставщика и товаров
- **Загрузка**: Показ скелетонов карточек во время запроса
**ПРАВИЛА ПРОИЗВОДИТЕЛЬНОСТИ:**
- **Виртуализация**: При количестве товаров > 100
- **Ленивая загрузка изображений**: loading="lazy" для всех изображений
- **Мемоизация**: React.memo для компонентов карточек
- **Дебаунс**: 300мс для поисковых запросов (если будет добавлен поиск)
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные устройства**: Свайп для горизонтальной прокрутки
- **Планшеты**: Сохранение размеров карточек 80×112px
- **Десктоп**: Полная функциональность с клавиатурной навигацией
- **Высокие разрешения**: Сохранение пропорций и читаемости
**ПРАВИЛА БЕЗОПАСНОСТИ И ВАЛИДАЦИИ:**
- **Валидация данных**: Проверка существования product.id перед добавлением
- **Дубликаты**: Предотвращение добавления одного товара дважды в детальный каталог
- **Санитизация**: Безопасное отображение названий товаров (XSS защита)
- **Обработка ошибок**: Graceful degradation при ошибках загрузки изображений
- **Защита от спама**: Дебаунс кликов 200мс для предотвращения множественных добавлений
**ПРАВИЛА ИНТЕГРАЦИИ С ДРУГИМИ БЛОКАМИ:**
- **Блок 1 (Поставщики)**: Слушает изменения selectedSupplier для обновления товаров
- **Блок 3 (Детальный каталог)**: Передаёт выбранные товары через setAllSelectedProducts
- **Блок 4 (Корзина)**: Товары добавляются в корзину из Блока 3, не напрямую из Блока 2
- **Синхронизация состояний**: Реактивное обновление при изменении данных в любом блоке
**ПРАВИЛА АНАЛИТИКИ И МЕТРИК:**
- **Отслеживание кликов**: Логирование добавления товаров в детальный каталог
- **Метрики производительности**: Время загрузки товаров поставщика
- **Пользовательское поведение**: Количество просмотренных товаров на поставщика
- **A/B тестирование**: Готовность к тестированию различных размеров карточек
**ПРАВИЛА ЛОКАЛИЗАЦИИ:**
- **Alt-текст изображений**: На языке интерфейса пользователя
- **Направление скролла**: RTL поддержка для арабского/иврита
- **Размеры карточек**: Неизменны для всех локалей (80×112px)
- **Сообщения об ошибках**: Локализованные уведомления при проблемах загрузки
#### **3.2.1.1 Заголовок и поиск Блока 1**
**МИНИМАЛИСТИЧНЫЙ ДИЗАЙН:**
```jsx
<div className="flex items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Building2 className="h-5 w-5 text-blue-400" />
<h2 className="text-lg font-semibold text-white">Поставщики</h2>
</div>
<div className="w-64">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-white/40 h-4 w-4" />
<Input
placeholder="Поиск поставщиков..."
className="bg-white/5 border-white/10 text-white placeholder:text-white/50 pl-10 h-9"
/>
</div>
</div>
</div>
```
**ПРАВИЛА ЗАГОЛОВКА:**
- **Иконка**: Building2 h-5 w-5 text-blue-400 (без фонового контейнера)
- **Текст**: "Поставщики" (убран избыточный "товаров")
- **Размер**: text-lg font-semibold (увеличен для лучшей читаемости)
- **БЕЗ бэджа**: Убран избыточный бэдж "Создание поставки"
- **Выравнивание**: flex items-center gap-2 (компактное)
**ПРАВИЛА ПОИСКА:**
- **Позиция**: Справа от заголовка (justify-between)
- **Ширина**: w-64 (256px) фиксированная ширина
- **Плейсхолдер**: "Поиск поставщиков..." (конкретное описание)
- **Иконка**: Search h-4 w-4 слева в поле
- **Стили**: Стандартные glass-эффекты, focus:border-white/20
**ПРАВИЛА КНОПКИ "НАЙТИ В МАРКЕТЕ":**
- **Условие**: Показывается только при allCounterparties.length === 0
- **Позиция**: Отдельный блок под заголовком (mt-4)
- **НЕ интегрирована**: В поле поиска (отдельно)
- **Стили**: glass-secondary outline button размера sm
#### **3.2.1.2 Структура карточки поставщика в Блоке 1**
**МИНИМАЛИСТИЧНАЯ КАРТОЧКА ПОСТАВЩИКА:**
**СТРУКТУРА ИНФОРМАЦИИ:**
```jsx
<div className="flex items-start gap-2">
<OrganizationAvatar organization={supplier} size="sm" />
<div className="flex-1 min-w-0">
<h4 className="text-white font-medium text-sm truncate">{supplier.name || supplier.fullName}</h4>
<div className="flex items-center gap-2 mt-1">
<p className="text-white/60 text-xs font-mono">ИНН: {supplier.inn}</p>
{supplier.market && <Badge className="market-badge">{getMarketLabel(supplier.market)}</Badge>}
</div>
</div>
</div>
```
**ПРАВИЛА СОДЕРЖАНИЯ КАРТОЧКИ:**
**✅ ОСТАВИТЬ:**
- **Аватар организации**: OrganizationAvatar size="sm" слева
- **Название поставщика**: supplier.name || supplier.fullName (приоритет name)
- **ИНН**: font-mono, text-white/60, с префиксом "ИНН: "
**🔸 ДОБАВИТЬ:**
- **Принадлежность к рынку**: Badge с названием рынка из supplier.market
- **Рынки**: "Садовод", "ТЯК Москва" и другие из Organization.market поля
**❌ УБРАТЬ:**
- **Рейтинг**: Звездочка и цифра rating (избыточно)
- **Тип бэдж**: "Поставщик" badge (и так понятно из контекста)
- **Адрес**: supplier.address (занимает место, не критично)
**СТИЛИ РЫНОЧНЫХ БЭДЖЕЙ:**
- **Садовод**: bg-green-500/20 text-green-300 border-green-500/30
- **ТЯК Москва**: bg-blue-500/20 text-blue-300 border-blue-500/30
- **По умолчанию**: bg-gray-500/20 text-gray-300 border-gray-500/30
**ПРАВИЛА АДАПТИВНОСТИ:**
- **Мобильные**: Сохранение структуры, truncate для длинных названий
- **Планшеты/десктоп**: Полное отображение в сетке
- **Малые экраны**: line-clamp-1 для названия организации
**СОСТОЯНИЯ КАРТОЧКИ:**
- **Default**: bg-white/5 border-white/10
- **Hover**: hover:border-white/20 hover:bg-white/10
- **Selected**: bg-white/15 border-white/40 shadow-lg
- **Disabled**: opacity-50 cursor-not-allowed (при недоступности)
**ПРАВИЛА ИНТЕГРАЦИИ С РЫНКАМИ:**
**ИСТОЧНИК ДАННЫХ:**
- **Поле БД**: Organization.market (String?) - поле принадлежности к рынку
- **Настройка**: Указывается в настройках кабинета поставщика
- **Опциональность**: Поле может быть пустым (рынок не указан)
**ФУНКЦИЯ getMarketLabel():**
```jsx
const getMarketLabel = (market?: string) => {
const marketLabels = {
'sadovod': 'Садовод',
'tyak-moscow': 'ТЯК Москва',
'opt-market': 'ОПТ Маркет',
}
return marketLabels[market as keyof typeof marketLabels] || market
}
```
**СТИЛИ ДЛЯ РЫНКОВ:**
```jsx
const getMarketBadgeStyle = (market?: string) => {
const styles = {
'sadovod': 'bg-green-500/20 text-green-300 border-green-500/30',
'tyak-moscow': 'bg-blue-500/20 text-blue-300 border-blue-500/30',
'opt-market': 'bg-purple-500/20 text-purple-300 border-purple-500/30',
}
return styles[market as keyof typeof styles] || 'bg-gray-500/20 text-gray-300 border-gray-500/30'
}
```
**ПРАВИЛА ОТОБРАЖЕНИЯ:**
- **Условие**: Показывать badge только если supplier.market существует
- **Размер**: text-xs для соответствия ИНН
- **Позиция**: Справа от ИНН в той же строке
- **Приоритет**: Рынок важнее типа организации для селлера
### 3.3 ПРАВИЛО ПЕРСИСТЕНТНОСТИ ВЫБРАННЫХ ТОВАРОВ
**🎯 ОСНОВНОЙ ПРИНЦИП:**
Выбранные товары в детальном каталоге (блок 3) сохраняются при смене поставщика и могут быть удалены только явным действием пользователя.
**🔄 WORKFLOW СЦЕНАРИИ:**
**СЦЕНАРИЙ 1: Добавление товаров от разных поставщиков**
1. Пользователь выбирает Поставщика А
2. Добавляет Товар 1 и Товар 2 в детальный каталог
3. Переключается на Поставщика Б
4. Товар 1 и Товар 2 остаются в блоке 3
5. Добавляет Товар 3 от Поставщика Б
6. В блоке 3: Товар 1, Товар 2 (от А) + Товар 3 (от Б)
**СЦЕНАРИЙ 2: Визуальная индикация в блоке 2**
- При переключении на поставщика, товары которого уже есть в блоке 3, показываются как "выбранные"
- Товары от других поставщиков в блоке 2 не отображаются
**🛠️ ТЕХНИЧЕСКИЕ ПРАВИЛА:**
**Состояние selectedProductsForDetailView:**
- Глобальное состояние всех выбранных товаров
- НЕ зависит от текущего поставщика
- НЕ очищается при смене поставщика
- Очищается только явными действиями пользователя
**Единственные способы удаления:**
1. Кнопка "Удалить из каталога" в карточке товара (блок 3)
2. Кнопка "Очистить каталог" в заголовке блока 3
3. НЕ при смене поставщика
**🎨 UX ПРАВИЛА:**
- Счетчик товаров: "Детальный каталог (X товаров от Y поставщиков)"
- Визуальная индикация выбранных товаров в блоке 2
- Информация о поставщике для каждого товара в блоке 3
### 3.4 Правила кнопки "Создать поставку" в разделе "Мои поставки"
#### **3.4.1 Общие принципы**
- **КОНТЕКСТНОСТЬ**: Кнопка создания появляется только в активном табе
- **РАСПОЛОЖЕНИЕ**: Правая часть строки таба, на том же уровне что и название
- **СТИЛИСТИКА**: В том же стиле что и сами табы (соответствует уровню иерархии)
- **ФУНКЦИОНАЛЬНОСТЬ**: Кнопка ведет на страницу создания поставки соответствующего типа
#### **3.4.2 Размещение кнопок по табам**
**УРОВЕНЬ 2 (Подтабы фулфилмента):**
- **📦 Товар → Карточки**: Кнопка "Создать поставку" → `/supplies/create-cards`
- **📦 Товар → Поставщики**: Кнопка "Создать поставку" → `/supplies/create-suppliers`
- **🔧 Расходники селлера**: Кнопка "Создать поставку" → `/supplies/create-consumables`
**УРОВЕНЬ 2 (Подтабы маркетплейсов):**
- **🟣 Wildberries**: Кнопка "Создать поставку" → `/supplies/create-wildberries`
- **🔵 Ozon**: Кнопка "Создать поставку" → `/supplies/create-ozon`
#### **3.4.3 ПРАВИЛА КОРЗИНЫ - ЕДИНЫЙ СТАНДАРТ**
**КРИТИЧЕСКИ ВАЖНО**: Все корзины в системе должны следовать единому стандарту дизайна и функциональности.
##### **3.4.3.1 Размеры и позиционирование**
```tsx
<div className="w-72 flex-shrink-0">
<div className="bg-white/10 backdrop-blur border-white/20 p-3 sticky top-0 rounded-2xl">
```
**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**:
- **Ширина**: `w-72` (288px) - фиксированная ширина для всех корзин
- **Флекс**: `flex-shrink-0` - корзина не сжимается
- **Позиция**: `sticky top-0` - прилипает к верху при прокрутке
- **Стиль**: Glass morphism эффект с `backdrop-blur` и `bg-white/10`
##### **3.4.3.2 Автодобавление товаров**
**ПРАВИЛО AUTO-ADD**: При вводе количества товар автоматически добавляется в корзину.
```tsx
// ОБЯЗАТЕЛЬНАЯ РЕАЛИЗАЦИЯ:
const handleQuantityChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value
const newQuantity = inputValue === '' ? 0 : Math.max(0, parseInt(inputValue) || 0)
if (newQuantity > 0) {
// Автоматически добавляем товар в корзину
updateProductQuantity(product.id, newQuantity)
} else {
// Удаляем товар из корзины при количестве 0
removeFromCart(product.id)
}
}
```
#### 3.2.7.5 Синхронизация данных между блоками
**ПРАВИЛО СИНХРОНИЗАЦИИ**: Данные в корзине должны отражать выборы из всех блоков формы:
1. **Дата поставки**: Из Блока 3 (дата пикер)
2. **Фулфилмент-центр**: Название выбранного FF (реальные данные!)
3. **Логистическая компания**: Только партнеры типа `'LOGIST'`
**ПОРЯДОК ОТОБРАЖЕНИЯ В КОРЗИНЕ**:
```
Дата поставки: 08.08.2025
Фулфилмент-центр: ФУЛФИЛМЕНТ РУ
Логистическая компания: [Выпадающий список]
```
#### 3.2.7.6 Критические требования
🚨 **БЕЗОПАСНОСТЬ ТИПОВ**:
- Всегда проверять на `null/undefined`: `selectedSupplier?.id || ''`
- Использовать optional chaining для всех вложенных объектов
🚨 **ПРОИЗВОДИТЕЛЬНОСТЬ**:
- Мемоизация расчетов: `useMemo` для дорогих вычислений
- Debounce для инпутов количества
🚨 **UX КОНСИСТЕНТНОСТЬ**:
- Единые стили для всех корзин в системе
- Одинаковое поведение auto-add во всех формах
- Синхронная валидация данных
````
**ДЕФОЛТНОЕ ЗНАЧЕНИЕ**: Пустой инпут (`value={''}`) вместо `value={0}`
##### **3.4.3.3 Структура корзины**
**ОБЯЗАТЕЛЬНЫЕ ЭЛЕМЕНТЫ**:
1. **Заголовок**: "Корзина (X шт)" с иконкой корзины
2. **Список товаров**:
- Название товара (БЕЗ суффикса "(с рецептурой)")
- Цена за единицу × количество
- Кнопка удаления (X справа)
3. **Мета-информация**: Дата поставки, фулфилмент-центр, логистика
4. **Итого**: Общая сумма с выделением зелёным цветом
5. **Кнопка действия**: "Создать поставку" с градиентом
**ЗАПРЕЩЕНО**: Отображать текст "(с рецептурой)" в названиях товаров в корзине
##### **3.4.3.4 Единая функция расчета стоимости**
**КРИТИЧЕСКИ ВАЖНО**: Использовать единую функцию расчета для избежания расхождений:
```tsx
const getProductTotalWithRecipe = (productId: string, quantity: number) => {
const product = products.find((p) => p.id === productId)
if (!product) return 0
// Базовая цена товара
let total = (product.pricePerUnit || 0) * quantity
// Добавляем услуги
if (product.services && product.services.length > 0) {
const servicesTotal = product.services.reduce((sum, service) => {
return sum + (service.pricePerUnit || 0) * quantity
}, 0)
total += servicesTotal
}
// Добавляем FF расходники (используем .price, НЕ .pricePerUnit!)
if (product.ffConsumables && product.ffConsumables.length > 0) {
const ffConsumablesTotal = product.ffConsumables.reduce((sum, consumable) => {
return sum + (consumable.price || 0) * quantity // ВАЖНО: .price!
}, 0)
total += ffConsumablesTotal
}
// Добавляем расходники продавца
if (product.sellerConsumables && product.sellerConsumables.length > 0) {
const sellerConsumablesTotal = product.sellerConsumables.reduce((sum, consumable) => {
return sum + (consumable.pricePerUnit || 0) * quantity
}, 0)
total += sellerConsumablesTotal
}
return total
}
````
### 3.4 Высота основного блока и функционал
#### **3.4.1 Высота основного блока**
**ФОРМУЛА РАСЧЕТА**:
```css
height: calc(100vh - headerHeight - tabsHeight - statsHeight - margins);
```
**ПРАВИЛО ВЫРАВНИВАНИЯ**:
- Нижняя граница основного блока должна быть на одном уровне с нижней границей sidebar
- При изменении размера окна высота пересчитывается
- Внутренний скролл: `overflow-y-auto`
#### **3.4.2 Сохранение функционала**
**КРИТИЧЕСКИ ВАЖНО**: При добавлении блока статистики весь существующий функционал сохраняется:
- Таблицы с данными поставок
- Фильтры и сортировка
- Кнопки действий
- Детализация при клике
- Пагинация
- Поиск
**ЗАПРЕЩЕНО**:
- Удалять существующие компоненты
- Изменять логику работы таблиц
- Нарушать существующие API вызовы
### 3.5 Табы "Карточки" и "Поставщики" - объединённая логика
#### **3.5.1 Принцип единого типа предмета**
**КЛЮЧЕВОЕ ПРАВИЛО**: Табы "Карточки" и "Поставщики" - это два способа создания поставок одного типа предмета (ТОВАР)
**СПОСОБЫ СОЗДАНИЯ**:
- **Карточки** - импорт товаров через WB API с автоматическим созданием поставки
- **Поставщики** - прямой заказ товаров у поставщика с указанием рецептуры
**РЕЗУЛЬТАТ**: Оба способа создают `SupplyOrder` с товарами типа `PRODUCT`
#### **3.5.2 Общая статистика**
**ПРАВИЛО**: Блок статистики показывает ОДИНАКОВЫЕ данные для обоих табов
**МЕТРИКИ ДЛЯ ТАБОВ "КАРТОЧКИ" И "ПОСТАВЩИКИ"**:
- Всего поставок товаров (из всех источников)
- Активных поставок товаров (в работе)
- Сумма активных поставок товаров
- Товаров в пути (все способы доставки)
**ЗАПРЕЩЕНО**: Разделять статистику по способу создания
#### **3.5.3 Общий основной блок**
**СОДЕРЖИМОЕ**: Единая таблица всех поставок товаров
**ИСТОЧНИКИ ДАННЫХ**:
- Поставки, созданные через импорт карточек WB
- Поставки, созданные через заказ у поставщиков
- Все промежуточные и завершённые поставки
**РАЗЛИЧИЯ ТАБОВ**:
- Только кнопки создания ведут на разные страницы
- Таб "Карточки": `/supplies/create-cards`
- Таб "Поставщики": `/supplies/create-suppliers`
### 3.7 Структура страницы создания поставки расходников
#### **3.7.1 Обязательная структура страницы**
**ПРИНЦИП**: Страница состоит из трёх визуально разделённых блоков
```
┌─────────────────────────────────────────┐
│ 1. БЛОК ТАБОВ (навигация) │
│ - Фиксированная высота │
│ - Glass-эффект │
│ - Иерархическая структура │
├─────────────────────────────────────────┤
│ 2. БЛОК СТАТИСТИКИ (метрики) │
│ - Контекстные данные │
│ - 4 карточки в ряд (desktop) │
│ - Динамическое обновление │
├─────────────────────────────────────────┤
│ 3. ОСНОВНОЙ БЛОК (контент) │
│ - Сохраняет весь функционал │
│ - Таблицы, фильтры, действия │
│ - Высота до низа sidebar │
└─────────────────────────────────────────┘
```
#### **3.5.2 Блок статистики - контекстные метрики**
**ПРАВИЛО**: Статистика меняется в зависимости от выбранных табов
**Для путей "Фулфилмент → Товар → Карточки/Поставщики":**
- Всего поставок
- Активных поставок
- Сумма активных поставок
- В пути
**Для пути "Фулфилмент → Расходники селлера":**
- Всего поставок
- Активных поставок
- Видов расходников
- Критические остатки
**Для путей "Маркетплейсы → Wildberries/Ozon":**
- Поставок на маркетплейс
- Товаров отправлено
- Возвраты за неделю
- Эффективность поставок
### 3.6 Многоуровневая таблица поставок
#### **ПЕРВЫЙ УРОВЕНЬ** _(основной список)_:
- **СОРТИРОВКА**: Номер поставки от большего к меньшему
- **ОБЯЗАТЕЛЬНЫЕ КОЛОНКИ**:
- Порядковый номер поставки
- Количество видов расходников
- Стоимость всей поставки
- Количество категорий
- Статус поставки
#### **ВТОРОЙ УРОВЕНЬ** _(детализация по клику)_:
- **АКТИВАЦИЯ**: По клику на строку первого уровня
- **СОДЕРЖАНИЕ**:
- Название расходника
- Количество
- Цена
- Категория
- Поставщик
- **ОГРАНИЧЕНИЯ**: Только просмотр, редактирование запрещено
---
## 4. 🏭 **WORKFLOW ФУЛФИЛМЕНТА**
> **Источник**: rules-complete.md, раздел 11.2, строки 2003-2022
### 4.1 Трехэтапный процесс
**ЭТАП 1: Приемка товаров**
1. Фулфилмент получает поставки от поставщиков
2. Товары размещаются на складе по модулям
3. Ведется учет поступлений и остатков
**ЭТАП 2: Обработка товаров**
4. Товары обрабатываются согласно рецептурам селлеров
5. Применяются услуги фулфилмента
6. Создаются готовые продукты
**ЭТАП 3: Управление услугами**
7. Фулфилмент предоставляет каталог услуг для рецептур
8. Устанавливает цены на расходники
9. Управляет логистическими маршрутами
### 4.2 Движение товаров
**Поступление товаров**:
- **ПОСТАВКИ**: От поставщиков через систему заказов
- **ВОЗВРАТЫ**: Товары, возвращенные с ПВЗ
- **ПЕРЕМЕЩЕНИЯ**: Между складами и магазинами
**Расход товаров**:
- **ОТГРУЗКА**: Товары отправлены селлерам
- **СПИСАНИЕ**: Брак, утрата, утилизация
- **ВОЗВРАТ**: Возврат поставщику
- **ИСПОЛЬЗОВАНИЕ**: Расходники для операций
---
## 5. 🚚 **WORKFLOW ЛОГИСТИКИ**
> **Источник**: rules-complete.md, раздел 12.2, строки 2063-2089
### 5.1 Четырехэтапный процесс доставки
**ЭТАП 1: Получение заявки**
1. Логистика получает уведомление о новой поставке
2. Заявка появляется в разделе "Заявки" кабинета логистики
3. Логист изучает детали поставки (объем, вес, маршрут)
**ЭТАП 2: Подтверждение доставки**
4. Логист нажимает кнопку "Одобрить"
5. Статус поставки меняется на `LOGISTICS_CONFIRMED`
6. Уведомления отправляются всем участникам
**ЭТАП 3: Забор товара**
7. Логист приезжает к поставщику за товаром
8. Поставщик отгружает товар логисту
9. Поставщик отмечает "Отправлено"
10. Статус меняется на `SHIPPED`, затем `IN_TRANSIT`
**ЭТАП 4: Доставка**
11. Логистика доставляет товар на фулфилмент-центр
12. В кабинете логистики нажимают "Доставлено"
13. Фулфилмент принимает товар и отмечает "Принято"
---
## 6. 🤝 **СИСТЕМА ПАРТНЕРСТВА**
> **Источник**: rules-complete.md, раздел 13.2, строки 2156-2186
### 6.1 Два способа установления партнерства
**СПОСОБ 1: Автоматическое партнерство**
1. Пользователь А указывает email организации Б при создании поставки/заявки
2. Система проверяет: зарегистрирована ли организация с таким email
3. Если ДА → автоматически создается связь Partnership
4. Если НЕТ → отправляется приглашение на email
5. При регистрации по приглашению → автоматически создается Partnership
6. Обе организации видят друг друга в разделе "Партнеры"
7. Могут создавать заказы друг другу
**СПОСОБ 2: Заявочная система**
1. Пользователь А идет в раздел "Партнеры"
2. Нажимает "Добавить партнера"
3. Указывает данные организации Б (ИНН, название)
4. Система создает PartnershipRequest со статусом PENDING
5. Организация Б получает уведомление о заявке
6. Организация Б принимает (ACCEPTED) или отклоняет (REJECTED) заявку
### 6.2 Статусы заявок
**4 статуса PartnershipRequest**:
- **PENDING** - ожидает ответа
- **ACCEPTED** - принята (создается Partnership)
- **REJECTED** - отклонена
- **CANCELLED** - отменена инициатором
---
## 7. 🔧 **ИНТЕГРАЦИЯ С УСЛУГАМИ**
> **Источник**: rules-complete.md, раздел 14.3, строки 2342-2349
### 7.1 5-шаговый workflow использования услуг
1. **Селлер выбирает услугу** из каталога при создании рецептуры
2. **Система включает услугу** в состав заказа
3. **Фулфилмент получает задание** на выполнение услуги
4. **Исполнитель применяет услугу** к товару согласно технологии
5. **Система создает готовый продукт** с учетом всех услуг
### 7.2 Связь с рецептурами
**Архитектура интеграции**:
```
СЕЛЛЕР (создание поставки)
└── Рецептура
├── Товар (от поставщика)
├── Услуги фулфилмента ← Каталог услуг
├── Расходники селлера
└── Расходники фулфилмента
ФУЛФИЛМЕНТ (обработка)
├── Входящие поставки → Товары на складе
└── Услуги → Выполнение по рецептуре
```
---
## 8. 🚨 **КРИТИЧЕСКИЕ СИТУАЦИИ**
> **Источник**: rules-complete.md, раздел 24, строки 3151-3190
### 8.1 Отмена заказов на разных этапах
**ТИП 1: Отмена до подтверждения поставщиком**
- Селлер может отменить заказ в статусе PENDING
- Система меняет статус на CANCELLED
- Уведомление поставщику об отмене
**ТИП 2: Отмена после подтверждения поставщиком**
- Требуется согласие поставщика
- Возможны штрафные санкции
- Согласование через мессенджер
**ТИП 3: Отмена во время транспортировки**
- Связь с логистикой для возврата груза
- Дополнительные транспортные расходы
- Перерасчет стоимости
**ТИП 4: Отмена после доставки**
- Процедура возврата товара
- Контроль качества возвращаемого товара
- Возмещение понесенных расходов
### 8.2 Алгоритм частичной доставки
**ШАГ 1: Выявление недостачи**
- Фулфилмент сверяет план и факт
- Фиксирует недостающие позиции
- Уведомляет всех участников
**ШАГ 2: Принятие решения**
- Селлер выбирает: ждать доставку или принять частично
- Поставщик объясняет причины недостачи
- Согласование дальнейших действий
**ШАГ 3: Обработка частичной доставки**
- Система разделяет заказ на выполненную и невыполненную части
- Перерасчет стоимости и логистики
- Создание нового заказа на недостающее
**ШАГ 4: Документооборот**
- Корректировка документов
- Фиксация фактических показателей
- Закрытие или продление заказа
---
## 9. 🛠️ **ПРОТОКОЛЫ РАЗРАБОТКИ**
> **Источник**: rules-complete.md, раздел "Обязательная последовательность", строки 41-49
### 9.1 7-шаговый workflow разработки
1. **При необходимости обратиться к rules-complete.md** - для справки по бизнес-правилам
2. **Следовать правилам взаимодействия** - честность и прозрачность
3. **Проверить специфичные правила кабинета** - если работа с конкретным типом организации
4. **Использовать TodoWrite** - для планирования задач
5. **Следовать техническим правилам** - GraphQL, TypeScript, система партнерства
6. **Проверять реализацию** - соответствие правилам и архитектуре
7. **Проводить финальную проверку** - качество и корректность результата
### 9.2 Протокол высокой сложности
**3-этапный процесс для сложных задач**:
1. **СТОП! ГЛУБОКИЙ АНАЛИЗ** - уточнить все требования у пользователя
2. **ИССЛЕДОВАНИЕ** - изучить все связанные файлы параллельно
3. **ДЕТАЛЬНЫЙ ПЛАН** - с промежуточными проверками и rollback точками
---
## 10. 📊 **СИСТЕМА УЧЕТА ДВИЖЕНИЯ ТОВАРОВ**
> **Источник**: rules-complete.md, раздел 7, строки 742-770
### 10.1 Принципы учета
**ПРИНЦИП 1: Полная прозрачность**
- Каждое движение товара фиксируется
- Доступна история всех операций
- Отчетность в реальном времени
**ПРИНЦИП 2: Двойной контроль**
- План и факт сверяются системой
- Выявление и анализ расхождений
- Автоматические уведомления об отклонениях
**ПРИНЦИП 3: Статусная модель**
- Каждый товар имеет четкий статус
- Переходы между статусами контролируются
- История изменений сохраняется
**ПРИНЦИП 4: Интеграция ролей**
- Каждая роль видит релевантную информацию
- Права доступа разграничены по функциям
- Совместная работа через единую систему
**ПРИНЦИП 5: Автоматизация**
- Минимум ручного ввода данных
- Автоматические расчеты и уведомления
- Система предотвращения ошибок
---
## 11. 🏪 **КАБИНЕТ ПОСТАВЩИКА**
> **Источник**: [rules-complete.md#10-кабинет-поставщика](./rules-complete.md#10--кабинет-поставщика)
### 11.1 Разделение понятий: РЫНОК vs МАРКЕТ
**🔍 КРИТИЧЕСКОЕ РАЗДЕЛЕНИЕ ПОНЯТИЙ:**
### **РЫНОК** 🏪 - физическое торговое место
- **Назначение**: Географическая принадлежность поставщиков
- **Примеры**: Садовод, ТЯК Москва
- **Структура**: Название + адрес
- **Связь**: Поставщик принадлежит рынку
### **МАРКЕТ** 🛒 - раздел системы для торговли
- **Назначение**: Глобальный каталог товаров в системе
- **Роут**: `/market` - просмотр и заказ товаров
- **Содержание**: Все доступные товары от всех поставщиков
- **Связь**: НЕ связан с физическими рынками
**🏢 АРХИТЕКТУРА ПРИНАДЛЕЖНОСТИ:**
```
РЫНОК (физическое место)
└── Поставщик (Organization.market)
└── Товары/Расходники (наследуют рынок от поставщика)
└── Отображаются в МАРКЕТЕ (/market)
```
**🎯 ПРИНЦИПЫ ИЕРАРХИИ:**
1. **РЫНОК → ПОСТАВЩИК**: Поставщик работает на конкретном рынке
2. **ПОСТАВЩИК → ТОВАРЫ**: Товары принадлежат поставщику с его рынка
3. **ТОВАРЫ → МАРКЕТ**: Все товары показываются в глобальном маркете (/market)
4. **НАСЛЕДОВАНИЕ**: Товары получают рынок от организации поставщика
**🏪 ФИЗИЧЕСКИЕ РЫНКИ В СИСТЕМЕ:**
- **"Садовод"** (`sadovod`) - Москва, 14-й км МКАД
- **Цветовая схема**: `bg-green-500/20 text-green-300 border-green-500/30`
- **"ТЯК Москва"** (`tyak-moscow`) - Москва, Алтуфьевское шоссе, 27
- **Цветовая схема**: `bg-blue-500/20 text-blue-300 border-blue-500/30`
**🛒 МАРКЕТ В СИСТЕМЕ:**
- **Роут**: `/market` - глобальный каталог товаров
- **Функции**: Просмотр, поиск, фильтрация, заказ товаров
- **Источник**: Товары от всех поставщиков всех рынков
- **Отображение рынка**: В карточках поставщиков и товаров
**🔧 ТЕХНИЧЕСКАЯ РЕАЛИЗАЦИЯ:**
- **Поле рынка**: `Organization.market` (String?) - принадлежность поставщика к рынку
- **Настройка рынка**: В настройках организации поставщика
- **Отображение в маркете**: Товары показывают рынок через `product.organization.market`
- **Фильтрация**: В маркете по рынку поставщика
### 11.2 Основные возможности
**СОЗДАНИЕ КАРТОЧЕК**:
- **ТОВАР** - базовые товары поставщика
- **РАСХОДНИКИ** - материалы и вспомогательные товары
### 11.3 Обязательные поля карточки
**Базовые параметры**:
- Фото (система загрузки и управления изображениями)
- Название
- Автоматическая генерация артикула СФ
- Описание
- Количество предметов в единицах
- Количество комплектов (если применимо)
- Категория (28 предустановленных + специализированные для расходников)
- Бренд, Цвет, Размер/объем, Вес, Габариты, Материал
- Цена за единицу и за комплект
- Заказано, В пути, Остаток, Продано
### 11.4 Отображение информации в карточках
**Каждая карточка содержит**:
- Основное изображение
- Название и артикул СФ
- Цена за единицу/комплект
- Категория и статус активности
- Данные о движении: остаток, заказано, в пути, продано
- Индикаторы низких остатков
### 11.5 Статистика поставщика
**Блок статистики включает**:
- **ТОВАРЫ**: Общая статистика товаров поставщика
- **РАСХОДНИКИ**: Материалы и вспомогательные товары
- Классифицируются при заказе в зависимости от заказчика
- Общая статистика по всем расходникам
---
## 12. 🏠 **ОБЩИЕ ПРАВИЛА КАБИНЕТОВ**
> **Источник**: [rules-complete.md#8-общие-правила-кабинетов](./rules-complete.md#8--общие-правила-кабинетов)
### 12.1 Универсальная структура кабинетов
**ВСЕ ТИПЫ КАБИНЕТОВ** включают следующие обязательные разделы:
#### 12.1.1 Страница "Главная"
**СТАТУС**: Реализовано
**ДОСТУП**: Через навигацию в sidebar для всех типов кабинетов
**СОДЕРЖАНИЕ**: Универсальная страница с типо-зависимыми компонентами
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый тип кабинета должен иметь страницу "Главная"
- **НАВИГАЦИЯ**: Доступ через кнопку в sidebar (первая в списке)
- **УНИВЕРСАЛЬНОСТЬ**: Одинаковая структура навигации для всех кабинетов
- **РОУТ**: `/home` с универсальным компонентом HomePageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента: SellerHomePage, FulfillmentHomePage, WholesaleHomePage, LogistHomePage
#### 12.1.2 Раздел "Экономика"
**СТАТУС**: Реализовано в системе
**РАСПОЛОЖЕНИЕ**: Перед настройками в каждом кабинете
**СОДЕРЖАНИЕ**: Пустые разделы-заглушки с пометкой "будет добавлен позже"
**ПРАВИЛА**:
- **ОБЯЗАТЕЛЬНО**: Каждый кабинет имеет раздел "Экономика"
- **РОУТ**: `/economics` с универсальным компонентом EconomicsPageWrapper
- **КОМПОНЕНТЫ**: 4 типо-зависимых компонента экономики: SellerEconomicsPage, FulfillmentEconomicsPage, WholesaleEconomicsPage, LogistEconomicsPage
- **КНОПКА**: "Экономика" в sidebar навигации перед настройками
- **БЕЗОПАСНОСТЬ**: Проверки доступа и безопасности в экономических компонентах
#### 12.1.3 Общие разделы для всех кабинетов
**УНИВЕРСАЛЬНЫЕ РАЗДЕЛЫ** (доступны всем типам):
- 🏠 **Главная** - основная страница кабинета (реализовано)
- 🛒 **Маркет** - просмотр и заказ товаров
- 🤝 **Партнеры** - управление контрагентами
- 💬 **Мессенджер** - внутренняя связь
- 💰 **Экономика** - финансовая аналитика (реализовано)
- ⚙️ **Настройки** - профиль и конфигурация
**СПЕЦИАЛИЗИРОВАННЫЕ РАЗДЕЛЫ** (зависят от типа кабинета):
- Определяются в соответствующих разделах каждого кабинета
### 12.2 Правила sidebar навигации
#### 12.2.1 Структура навигации
**ОБЩИЙ ПРИНЦИП**:
- Условное отображение: `{user?.organization?.type === "TYPE" && (...)}`
- Адаптивность: сворачиваемый sidebar с `getSidebarMargin()`
- Состояния активности: подсветка текущего раздела
**ПОРЯДОК РАЗДЕЛОВ В SIDEBAR**:
1. 🏠 **Главная** (реализовано для всех)
2. **Специализированные разделы** (зависят от типа кабинета)
3. 🛒 **Маркет** (универсальный)
4. 🤝 **Партнеры** (универсальный)
5. 💬 **Мессенджер** (универсальный)
6. 💰 **Экономика** (универсальный, реализовано)
7. ⚙️ **Настройки** (универсальный)
8. **Выход** (универсальный)
#### 12.2.2 Типо-зависимая логика
**АДАПТИВНЫЙ РОУТИНГ**:
```typescript
// Пример: кнопка "Поставки" ведет на разные страницы
const handleSuppliesClick = () => {
switch (user?.organization?.type) {
case 'FULFILLMENT':
router.push('/fulfillment-supplies')
break
case 'SELLER':
router.push('/supplies')
break
case 'WHOLESALE':
router.push('/supplies')
break
case 'LOGIST':
router.push('/logistics-orders')
break
}
}
```
---
## 13. 📋 **КАТЕГОРИИ ТОВАРОВ И РАСХОДНИКОВ**
> **Источник**: [rules-complete.md#22-категории-товаров-и-расходников](./rules-complete.md#22--категории-товаров-и-расходников)
### 13.1 Полный список 28 универсальных категорий товаров
1. Одежда и обувь
2. Косметика и парфюмерия
3. Дом и сад
4. Детские товары
5. Спорт и отдых
6. Электроника
7. Книги
8. Здоровье
9. Автотовары
10. Строительство и ремонт
11. Продукты питания
12. Зоотовары
13. Дача, сад и огород
14. Канцелярские товары
15. Хобби и творчество
16. Украшения и аксессуары
17. Сумки и чемоданы
18. Техника для дома
19. Музыкальные инструменты
20. Игры и игрушки
21. Мебель
22. Товары для красоты
23. Бытовая химия
24. Товары для путешествий
25. Медицинские товары
26. Религиозные товары
27. Антиквариат и коллекционирование
28. Прочие товары
### 13.2 12 специализированных категорий расходников
#### 🎁 **1. УПАКОВКА И ЗАЩИТА**
- Коробки (различных размеров)
- Пакеты (полиэтиленовые, бумажные, фирменные)
- Пузырчатая пленка, воздушные подушки
- Стрейч-пленка, гофрокартон
- Паллетная пленка, защитные уголки
#### 🏷️ **2. МАРКИРОВКА И ИДЕНТИФИКАЦИЯ**
- Этикетки (адресные, штрих-код, QR-код)
- Бирки (ценники, размерники)
- Стикеры и наклейки
- Маркеры и ручки
- Штампы и печати, термоэтикетки
#### 🔧 **3. КРЕПЕЖ И СОЕДИНЕНИЕ**
- Скотч (прозрачный, цветной, армированный)
- Клей и клеевые составы
- Стяжки пластиковые
- Степлер и скобы
- Веревки и шнуры, стрейч-лента
#### 📄 **4. ДОКУМЕНТООБОРОТ И ВКЛАДЫШИ**
- Накладные и сопроводительные документы
- Инструкции по эксплуатации
- Гарантийные талоны
- Рекламные буклеты, визитки и флаеры
- Благодарственные письма, купоны и промокоды
#### 🧼 **5. ГИГИЕНА И БЕЗОПАСНОСТЬ**
- Перчатки (латексные, нитриловые)
- Маски и респираторы
- Антисептики и дезинфекторы
- Салфетки и тряпки
- Фартуки и халаты, бахилы
#### 🛠️ **6. ИНСТРУМЕНТЫ И ПРИСПОСОБЛЕНИЯ**
- Ножи и резаки, ножницы
- Линейки и рулетки
- Упаковочные машины (ленточные)
- Дозаторы скотча
- Пистолеты для термоклея
- Весы и мерная тара
#### 🎨 **7. БРЕНДИНГ И ДИЗАЙН**
- Фирменные пакеты с логотипом
- Брендированные коробки
- Цветная упаковочная бумага
- Ленты и банты
- Наклейки с логотипом компании
- Подарочная упаковка
#### ⚡ **8. СПЕЦИАЛИЗИРОВАННЫЕ МАТЕРИАЛЫ**
- Антистатические пакеты
- Влагопоглотители
- Температурные индикаторы
- Хрупкие наклейки
- Пломбы и пломбировочные материалы
- Защита от краж (магнитные датчики)
#### 🏪 **9. ТОРГОВОЕ ОБОРУДОВАНИЕ**
- Манекены и вешалки
- Ценникодержатели
- Подставки и стойки
- Корзины и тележки
- Зеркала примерочные
- Освещение витрин
#### 🚚 **10. ЛОГИСТИКА И СКЛАДИРОВАНИЕ**
- Паллеты и поддоны
- Контейнеры и ящики
- Стеллажные системы
- Погрузочные ремни
- Защитные чехлы
- Адресные ярлыки для груза
#### 💻 **11. ТЕХНИЧЕСКИЕ РАСХОДНИКИ**
- Картриджи для принтеров
- Термоголовки, красящие ленты
- Батарейки для сканеров
- Чистящие средства для техники
- Запчасти для упаковочного оборудования
#### 🎪 **12. СЕЗОННЫЕ И ПРАЗДНИЧНЫЕ**
- Новогодняя упаковка
- Подарочные мешки
- Праздничные ленты
- Тематические наклейки
- Открытки и поздравления
- Сезонная упаковочная бумага
**ПРИМЕЧАНИЕ**: Данные категории являются рекомендательными и могут быть адаптированы под специфику конкретного поставщика расходников.
---
## 📊 **СТАТИСТИКА ПРОЦЕССОВ**
### По объему (строки):
- **UI процессы селлера**: ~942 строки (самый объемный)
- **Процесс создания продукта**: ~175 строк (самый детализированный)
- **Категории товаров и расходников**: ~141 строка (классификационная система)
- **Кабинет поставщика**: ~103 строки (процессы РЫНОК vs МАРКЕТ)
- **Общие правила кабинетов**: ~96 строк (универсальные процессы)
- **Workflow поставок**: ~45 строк (самый критичный)
- **Система партнерства**: ~31 строка
- **Workflow логистики**: ~27 строк
- **Workflow фулфилмента**: ~20 строк
### По ролям:
- **Селлер**: 6 процессов
- **Поставщик**: 5 процессов
- **Фулфилмент**: 5 процессов
- **Логистика**: 3 процесса
- **Универсальные**: 3 процесса
### По критичности:
- **Критические**: Workflow поставок, Создание продукта, РЫНОК vs МАРКЕТ
- **Важные**: UI процессы, Категории товаров, Общие правила кабинетов
- **Вспомогательные**: Система партнерства, Учет движения, Протоколы разработки
---
**Дата создания**: Август 2025
**Общий объем**: 1733 строки процессов (фактический подсчет)
**Файл содержит**: 1805 строк всего (включая навигацию и статистику)
**Источник**: [rules-complete.md](./rules-complete.md)
**СТАТУС**: ПОЛНОСТЬЮ ЗАПОЛНЕН - все ключевые процессы добавлены
**Связанные файлы**:
- [rules-complete.md](./rules-complete.md) - Основной файл с бизнес-правилами
- [interaction-integrity-rules.md](./interaction-integrity-rules.md) - Методология работы
- [visual-design-rules.md](./visual-design-rules.md) - Визуальные правила

View File

@ -0,0 +1,624 @@
# 📦 НОВЫЕ ПРАВИЛА ФУЛФИЛМЕНТ - СКЛАД И РАСХОДНИКИ
> **Создано на основе глубокого анализа кода разделов склада и расходников кабинета фулфилмент**
>
> **Дата анализа**: 19.08.2025
> **Статус**: ✅ Актуально для текущей версии системы
---
## 📋 СОДЕРЖАНИЕ
1. [🏗️ Архитектурные основы](#1-🏗️-архитектурные-основы)
2. [📊 Раздел "Склад" - детальный план](#2-📊-раздел-склад---детальный-план)
3. [🔧 Подраздел "Расходники фулфилмента" - детальный план](#3-🔧-подраздел-расходники-фулфилмента---детальный-план)
4. [🔄 Интеграция между разделами](#4-🔄-интеграция-между-разделами)
5. [📈 GraphQL API структура](#5-📈-graphql-api-структура)
6. [⚡ Real-time обновления](#6-⚡-real-time-обновления)
7. [🎨 UI/UX компоненты](#7-🎨-uiux-компоненты)
8. [🚀 Оптимизация производительности](#8-🚀-оптимизация-производительности)
---
## 1. 🏗️ АРХИТЕКТУРНЫЕ ОСНОВЫ
### 1.1 Маршруты и страницы
```typescript
// Основные маршруты фулфилмент склада
/fulfillment-warehouse/ Главный дашборд склада
/fulfillment-warehouse/supplies → Расходники фулфилмента
```
### 1.2 Модульная архитектура dashboard склада
Компонент `FulfillmentWarehouseDashboard` реализован по **MODULAR_ARCHITECTURE_PATTERN**:
```
src/components/fulfillment-warehouse/fulfillment-warehouse-dashboard/
├── index.tsx # Главный оркестратор (1,322 строки)
├── types/index.ts # TypeScript интерфейсы (223 строки)
├── hooks/ # Бизнес-логика (4 хука)
│ ├── useWarehouseData.ts # GraphQL запросы и real-time
│ ├── useStoreData.ts # Критическая логика группировки данных
│ ├── useTableState.ts # Управление состоянием таблиц
│ └── useWarehouseStats.ts # Статистика и расчеты
├── blocks/ # UI компоненты-блоки
│ ├── WarehouseStatsBlock.tsx # Статистические карты
│ ├── StoreDataTableBlock.tsx # Таблица данных магазинов
│ ├── SummaryRowBlock.tsx # Строка итогов
│ └── TableHeadersBlock.tsx # Заголовки с сортировкой
└── components/ # Переиспользуемые компоненты
└── StatCard.tsx # Универсальная статистическая карта
```
### 1.3 Основные типы данных
#### 3-уровневая иерархия складских данных:
```typescript
// 🔵 УРОВЕНЬ 1: Магазины (StoreData)
interface StoreData {
id: string
name: string
logo?: string
avatar?: string
products: number // Готовые продукты
goods: number // Товары в обработке
defects: number // Брак
sellerSupplies: number // Расходники селлеров
pvzReturns: number // Возвраты с ПВЗ
items: ProductItem[] // Детализация по товарам
}
// 🟢 УРОВЕНЬ 2: Товары (ProductItem)
interface ProductItem {
id: string
name: string
article: string
productQuantity: number
productPlace?: string
// ... места и количества для каждого типа
variants?: ProductVariant[] // Варианты товара
}
// 🟠 УРОВЕНЬ 3: Варианты товаров (ProductVariant)
interface ProductVariant {
id: string
name: string // Размер, характеристика, вариант упаковки
productQuantity: number
productPlace?: string
// ... аналогично ProductItem
}
```
---
## 2. 📊 РАЗДЕЛ "СКЛАД" - ДЕТАЛЬНЫЙ ПЛАН
### 2.1 Главный дашборд (`/fulfillment-warehouse`)
#### 2.1.1 📈 Статистические карты (WarehouseStatsBlock)
**6 основных метрик склада:**
1. **🔵 Продукты** (`products`)
- Готовые к отправке товары
- Иконка: `Box`
- Показывает: текущий остаток + изменения за сутки + прибыло/убыло
2. **📦 Товары** (`goods`)
- На складе и в обработке
- Иконка: `Package`
- Группировка по магазинам селлеров
3. **⚠️ Брак** (`defects`)
- Требует утилизации
- Иконка: `AlertTriangle`
- Цветовая индикация (красный)
4. **🔄 Возвраты с ПВЗ** (`pvzReturns`)
- К обработке
- Иконка: `RotateCcw`
- Статус: требует сортировки
5. **👥 Расходники селлеров** (`sellerSupplies`)
- Материалы клиентов
- Иконка: `Users`
- **КРИТИЧНО**: Группировка по ВЛАДЕЛЬЦУ, не по названию
6. **🔧 Расходники фулфилмента** (`fulfillmentSupplies`)
- Операционные материалы
- Иконка: `Wrench`
- Кликабельно → переход на `/fulfillment-warehouse/supplies`
#### 2.1.2 🗂️ Детализация по магазинам (3-уровневая таблица)
**Ключевые особенности:**
1. **Поиск и фильтрация**
- Поиск по названию магазина
- Сортировка по всем столбцам
- Показать/скрыть изменения за сутки
2. **Строка итогов**
- Автоматический подсчет всех категорий
- Движения товаров (прибыло/убыло)
- Обновляется в real-time
3. **3-уровневая иерархия**
```
🔵 Магазин
├─ 🟢 Товар 1
│ ├─ 🟠 Размер S
│ ├─ 🟠 Размер M
│ └─ 🟠 Размер L
└─ 🟢 Товар 2
└─ 🟠 Единственный размер
```
4. **Критическая группировка данных**
```typescript
// ⚠️ ВАЖНО: Товары группируются по НАЗВАНИЮ с суммированием
// ⚠️ ВАЖНО: Расходники группируются по СЕЛЛЕРУ-ВЛАДЕЛЬЦУ!
// Группировка товаров по названию
const productGroups = sellerProducts.reduce((acc, product) => {
const key = product.name || 'Без названия'
// Суммируем количества
acc[key].productQuantity += product.productQuantity || 0
}, {})
// Группировка расходников по владельцу
const sellerSuppliesForThisSeller = sellerSupplies.filter(supply =>
supply.type === 'SELLER_CONSUMABLES' &&
supply.sellerId === sellerId
)
```
### 2.2 GraphQL интеграция
#### 2.2.1 Используемые запросы
1. `GET_MY_COUNTERPARTIES` - партнеры (селлеры)
2. `GET_SUPPLY_ORDERS` - заказы поставок
3. `GET_WAREHOUSE_PRODUCTS` - товары на складе
4. `GET_SELLER_SUPPLIES_ON_WAREHOUSE` - расходники селлеров
5. `GET_MY_FULFILLMENT_SUPPLIES` - расходники фулфилмента
6. `GET_FULFILLMENT_WAREHOUSE_STATS` - статистика с изменениями
7. `GET_SUPPLY_MOVEMENTS` - движения товаров (прибыло/убыло)
#### 2.2.2 Стратегия кеширования
```typescript
// Разные стратегии для разных типов данных
fetchPolicy: 'cache-and-network' // Контрагенты, товары, расходники
fetchPolicy: 'no-cache' // Статистика (всегда актуальная)
pollInterval: 30000 // Обновление каждые 30 сек
pollInterval: 60000 // Данные партнеров реже
```
---
## 3. 🔧 ПОДРАЗДЕЛ "РАСХОДНИКИ ФУЛФИЛМЕНТА" - ДЕТАЛЬНЫЙ ПЛАН
### 3.1 Страница расходников (`/fulfillment-warehouse/supplies`)
#### 3.1.1 📊 Статистика расходников (SuppliesStats)
**6 основных показателей:**
1. **📦 Всего позиций** - общее количество видов расходников
2. **✅ Доступно** - расходники в наличии (currentStock > 0)
3. **⚠️ Мало на складе** - требует пополнения (currentStock ≤ minStock)
4. **❌ Нет в наличии** - необходим срочный заказ
5. **💰 Общая стоимость** - суммарная стоимость всех расходников
6. **🚚 В пути** - расходники в доставке + количество категорий
#### 3.1.2 🎛️ Система фильтрации и поиска
```typescript
interface FilterState {
search: string // Поиск по названию и описанию
category: string // Фильтр по категории
status: string // Статус: available/unavailable
supplier: string // Поставщик
lowStock: boolean // Показать только заканчивающиеся
}
interface SortState {
field: 'name' | 'category' | 'status' | 'currentStock' | 'price' | 'supplier'
direction: 'asc' | 'desc'
}
```
#### 3.1.3 📋 Режимы отображения
1. **Grid View** (сетка карточек)
- Визуальные карточки с прогресс-барами
- Индикаторы состояния остатков
- Статусные бейджи
2. **List View** (табличный вид)
- Компактное представление
- Сортировка по столбцам
- Массовые операции
3. **Analytics View** (аналитический режим)
- **Статус**: Планируется к реализации
- Графики потребления
- Прогнозирование остатков
#### 3.1.4 📊 Группировка данных
```typescript
type GroupBy = 'none' | 'category' | 'status' | 'supplier'
// Группировка по категориям, статусу или поставщику
const groupedSupplies = useMemo(() => {
if (groupBy === 'none') return { 'Все расходники': filteredSupplies }
return filteredSupplies.reduce((acc, supply) => {
let key: string
if (groupBy === 'status') {
key = supply.currentStock > 0 ? 'Доступен' : 'Недоступен'
} else {
key = supply[groupBy] || 'Без категории'
}
if (!acc[key]) acc[key] = []
acc[key].push(supply)
return acc
}, {})
}, [filteredSupplies, groupBy])
```
### 3.2 ⚡ Критическая логика консолидации
#### 3.2.1 Объединение одинаковых расходников
```typescript
// НОВОЕ: Группировка по артикулу СФ (более точно)
const consolidatedSupplies = useMemo(() => {
const grouped = supplies.reduce((acc, supply) => {
const key = supply.article // Группировка по артикулу
if (!acc[key]) {
acc[key] = {
...supply,
currentStock: 0,
quantity: 0,
shippedQuantity: 0,
}
}
// Учитываем принятые поставки (все варианты статусов)
if (supply.status === 'доставлено' ||
supply.status === 'На складе' ||
supply.status === 'in-stock') {
const actualQuantity = supply.actualQuantity ?? supply.quantity
acc[key].quantity += actualQuantity
acc[key].shippedQuantity += supply.shippedQuantity || 0
acc[key].currentStock += actualQuantity - (supply.shippedQuantity || 0)
}
return acc
}, {} as Record<string, Supply>)
return Object.values(grouped)
}, [supplies])
```
#### 3.2.2 Статусы расходников
```typescript
const STATUS_CONFIG = {
available: {
label: 'Доступен',
color: 'bg-green-500/20 text-green-300',
icon: CheckCircle,
},
unavailable: {
label: 'Недоступен',
color: 'bg-red-500/20 text-red-300',
icon: AlertTriangle,
},
} as const
const getStatusConfig = (supply: Supply): StatusConfig => {
return supply.currentStock > 0
? STATUS_CONFIG.available
: STATUS_CONFIG.unavailable
}
```
### 3.3 🎨 UI компоненты расходников
#### 3.3.1 SupplyCard - карточка расходника
**Основные элементы:**
- Заголовок с названием и статусным бейджем
- Прогресс-бар остатков с цветовой индикацией
- Метрики: цена, общая стоимость
- Категория и количество поставок
- Информация о поставщике и дате создания
```typescript
// Цветовая индикация прогресс-бара остатков
const stockPercentage = supply.minStock > 0
? (supply.currentStock / supply.minStock) * 100
: 100
// Цвета: зеленый (>50%), желтый (20-50%), красный (<20%)
const color = stockPercentage > 50 ? '#10b981'
: stockPercentage > 20 ? '#f59e0b'
: '#ef4444'
```
#### 3.3.2 SuppliesHeader - заголовок с управлением
**Функциональность:**
- Переключение режимов отображения (grid/list/analytics)
- Управление группировкой данных
- Панель фильтров (сворачиваемая)
- Экспорт данных в CSV
- Обновление данных
#### 3.3.3 SuppliesList - табличное представление
**Возможности:**
- Сортировка по всем столбцам
- Развертывание деталей поставок
- Информация о владельцах расходников
- Компактное отображение больших объемов данных
---
## 4. 🔄 ИНТЕГРАЦИЯ МЕЖДУ РАЗДЕЛАМИ
### 4.1 Связи данных
```mermaid
graph LR
A[Главный склад] --> B[Статистика фулфилмента]
B --> C[Страница расходников]
C --> D[Детали поставок]
A --> E[Расходники селлеров]
E --> F[Группировка по владельцу]
```
### 4.2 Переходы между разделами
1. **Со склада на расходники**: Клик по карте "Расходники фулфилмента"
2. **Навигация через сайдбар**: Двухуровневое меню
3. **Real-time синхронизация**: Обновления отражаются во всех разделах
### 4.3 Общие компоненты
- `Sidebar` - единая боковая навигация
- `AuthGuard` - проверка доступа
- `StatCard` - унифицированные статистические карты
- Glass-morphism дизайн - единый стиль
---
## 5. 📈 GRAPHQL API СТРУКТУРА
### 5.1 Ключевые запросы
#### GET_MY_FULFILLMENT_SUPPLIES
```graphql
query GetMyFulfillmentSupplies {
myFulfillmentSupplies {
id
name
description
article
price
quantity
actualQuantity # Фактически поставленное
shippedQuantity # Отправленное количество
currentStock # = actualQuantity - shippedQuantity
minStock
unit
category
status # доставлено/На складе/in-stock
supplier
createdAt
updatedAt
}
}
```
#### GET_FULFILLMENT_WAREHOUSE_STATS
```graphql
query GetFulfillmentWarehouseStats {
fulfillmentWarehouseStats {
products {
current: Int
change: Int # Изменение за сутки
percentChange: Float
}
goods { current change percentChange }
defects { current change percentChange }
pvzReturns { current change percentChange }
fulfillmentSupplies { current change percentChange }
sellerSupplies { current change percentChange }
}
}
```
#### GET_SELLER_SUPPLIES_ON_WAREHOUSE
```graphql
query GetSellerSuppliesOnWarehouse {
sellerSuppliesOnWarehouse {
id
name
type # MUST be 'SELLER_CONSUMABLES'
currentStock
sellerOwner { # ⚠️ КРИТИЧНО для группировки
id
name
fullName
}
}
}
```
### 5.2 Стратегии оптимизации
1. **Кеширование**: `cache-and-network` для стабильных данных
2. **Polling**: 30-60 секунд для разных типов данных
3. **No-cache**: Для критически важной статистики
4. **Batch запросы**: Группировка связанных запросов
---
## 6. ⚡ REAL-TIME ОБНОВЛЕНИЯ
### 6.1 WebSocket события
```typescript
useRealtime({
onEvent: (evt) => {
switch (evt.type) {
case 'supply-order:new':
case 'supply-order:updated':
refetchOrders()
refetchStats()
refetchWarehouse()
refetchSellerSupplies()
refetchFulfillmentSupplies()
break
case 'warehouse:changed':
refetchStats()
refetchFulfillmentSupplies()
break
}
}
})
```
### 6.2 Частота обновлений
- **Статистика**: Каждые 30 секунд + события
- **Товары на складе**: 30 секунд
- **Расходники**: 30 секунд + manual refresh
- **Контрагенты**: 60 секунд (стабильные данные)
---
## 7. 🎨 UI/UX КОМПОНЕНТЫ
### 7.1 Дизайн-система
**Glass-morphism стиль:**
- `glass-card` - основной класс для карточек
- Полупрозрачные фоны с размытием
- Градиенты blue-to-purple
- Белый текст с различной прозрачностью
### 7.2 Цветовая кодировка
```typescript
// Статусы остатков
const STOCK_COLORS = {
high: '#10b981', // Зеленый (>50%)
medium: '#f59e0b', // Желтый (20-50%)
low: '#ef4444', // Красный (<20%)
empty: '#6b7280', // Серый (0)
}
// Типы товаров
const TYPE_COLORS = {
products: 'blue', // Готовые продукты
goods: 'green', // Товары в обработке
defects: 'red', // Брак
supplies: 'purple', // Расходники
returns: 'orange', // Возвраты
}
```
### 7.3 Иконки и индикаторы
- `Box` - готовые продукты
- `Package` - товары в обработке
- `AlertTriangle` - брак и предупреждения
- `RotateCcw` - возвраты
- `Users` - расходники селлеров
- `Wrench` - расходники фулфилмента
- `TrendingUp/Down` - изменения показателей
---
## 8. 🚀 ОПТИМИЗАЦИЯ ПРОИЗВОДИТЕЛЬНОСТИ
### 8.1 React оптимизации
```typescript
// Мемоизация блоков
export const WarehouseStatsBlock = React.memo<WarehouseStatsBlockProps>(...)
// Оптимизированные вычисления
const storeData = useMemo(() => {
// Сложная логика группировки выполняется только при изменении зависимостей
}, [sellerPartners, allProducts, sellerSupplies])
// Callback оптимизации
const handleSort = useCallback((field: StoreDataField) => {
// Предотвращаем лишние рендеры
}, [])
```
### 8.2 Производительность запросов
1. **Селективное обновление**: Обновляем только измененные блоки
2. **Параллельные запросы**: Используем `Promise.all` для refetch
3. **Оптимистичные обновления**: UI реагирует до получения ответа
4. **Виртуализация**: Планируется для больших списков
### 8.3 Состояние загрузки
```typescript
// Умная индикация загрузки
const loading = counterpartiesLoading || ordersLoading || /* ... */
// Скелетоны для разных состояний
if (loading && storeData.length === 0) {
return <LoadingSkeleton />
}
// Частичная загрузка данных
if (loading) {
return <PartialDataView />
}
```
---
## 🎯 ЗАКЛЮЧЕНИЕ
Разделы склада и расходников фулфилмента представляют собой комплексную систему управления складскими операциями с:
### ✅ **Реализованные возможности:**
- 3-уровневая иерархия данных (магазины → товары → варианты)
- Real-time обновления через WebSocket
- Модульная архитектура с разделением ответственности
- Сложная система группировки и фильтрации данных
- Статистические dashboards с движениями товаров
- Экспорт данных и аналитика
### 🔧 **Критически важные особенности:**
- Расходники селлеров группируются по ВЛАДЕЛЬЦУ (не по названию)
- Товары группируются по названию с суммированием количества
- Консолидация расходников по артикулу СФ
- Строгая валидация типа `SELLER_CONSUMABLES`
### 🚀 **Технические преимущества:**
- GraphQL с оптимизированным кешированием
- React мемоизация и performance оптимизации
- Glass-morphism дизайн с единым стилем
- Responsive layout для разных устройств
**Архитектура готова к масштабированию и дальнейшему развитию функциональности.**

View File

@ -0,0 +1,469 @@
# ПРАВИЛА СОЗДАНИЯ ПОСТАВКИ ТОВАРОВ
**Полный анализ 4-участнической цепочки поставок**
**Дата создания:** 2024-12-19
**Версия:** 1.0
**Основано на глубоком анализе кода системы**
---
## 🎯 ОБЗОР СИСТЕМЫ
### **4 УЧАСТНИКА ПРОЦЕССА:**
1. **СЕЛЛЕР** - создает поставку товаров в кабинете
2. **ПОСТАВЩИК (WHOLESALE)** - одобряет заказ и подготавливает товары
3. **ФУЛФИЛМЕНТ** - принимает товары на склад и обрабатывает
4. **ЛОГИСТИКА** - организует доставку между участниками
### **ПОЛНЫЙ WORKFLOW ЦЕПОЧКИ:**
```
СЕЛЛЕР создает поставку → ПОСТАВЩИК одобряет → ФУЛФИЛМЕНТ принимает → ЛОГИСТИКА доставляет
```
---
## 📋 ЭТАП 1: АНАЛИЗ СОЗДАНИЯ ПОСТАВКИ СЕЛЛЕРОМ
### **Найденный код:**
- **Файл:** `/src/components/supplies/create-suppliers/index.tsx`
- **Компоненты:** `SupplyCreationProvider`, `CartBlock`, `ProductCardsBlock`, `SuppliersBlock`
- **Хуки:** `useSupplyCart`, `useProductCatalog`, `useRecipeBuilder`
### **Процесс создания:**
1. Селлер выбирает товары из каталога
2. Настраивает рецептуру и количества
3. Выбирает поставщика из списка партнеров
4. Выбирает фулфилмент-центр для доставки
5. Создает заказ через мутацию `createSupplyOrder`
### **GraphQL мутация создания:**
```javascript
// src/graphql/mutations.ts
createSupplyOrder: {
organizationId: string, // Селлер (создатель)
partnerId: string, // Выбранный поставщик
items: SupplyOrderItem[], // Товары и количества
fulfillmentCenterId: string, // Куда доставить
deliveryDate: DateTime // Когда доставить
}
```
### ✅ **Что работает корректно:**
- Выбор товаров и настройка рецептуры
- Расчет общей стоимости заказа
- Интеграция с каталогом продуктов
- UI создания поставки
### ❌ **Выявленные проблемы:**
- Нет валидации минимальных количеств заказа
- Отсутствует проверка доступности товаров у поставщика
- Нет уведомления поставщика о новом заказе
---
## 📋 ЭТАП 2: АНАЛИЗ ОДОБРЕНИЯ ПОСТАВЩИКОМ
### **Найденный код:**
- **Файл:** `/src/components/supplier-orders/supplier-orders-tabs.tsx`
- **Резолвер:** `/src/graphql/resolvers.ts:2573-2588` (исправленный фильтр)
- **Мутация:** `supplierApproveOrder`
### **Процесс одобрения:**
1. Поставщик видит входящие заказы в разделе "Заявки/Новые"
2. Проверяет детали заказа (товары, количества, сроки)
3. Видит только кнопки "Одобрить"/"Отклонить" (БЕЗ отображения статуса)
4. При одобрении статус меняется на `SUPPLIER_APPROVED`
### **Исправленный код фильтрации:**
```javascript
// Для кабинета ПОСТАВЩИКА фильтруем по partnerId
let whereClause
if (currentUser.organization.type === 'WHOLESALE') {
// Поставщик видит заказы, где он является поставщиком
whereClause = {
partnerId: currentUser.organization.id,
}
} else {
// Остальные видят заказы, которые они создали
whereClause = {
organizationId: currentUser.organization.id,
}
}
```
### ✅ **Что работает корректно:**
- Корректная фильтрация заказов для поставщиков
- Отображение деталей заказа
- Мутации одобрения/отклонения
### ❌ **Выявленные критические проблемы:**
- **Отображается статус**: поставщик видит "ожидает подтверждения" вместо только кнопок действий
- **Отсутствуют поля ввода**: поставщик не может указать количество грузовых мест (packagesCount) и объем (volume)
- **Нет даты готовности**: поставщик не может указать, когда товары будут готовы к отгрузке
- **Неполная мутация**: `supplierApproveOrder` не принимает дополнительные параметры
---
## 📋 ЭТАП 3: АНАЛИЗ ПРИЕМКИ ФУЛФИЛМЕНТОМ
### **Найденный код:**
- **Файл:** `/src/components/fulfillment-supplies/fulfillment-supplies/fulfillment-detailed-supplies-tab.tsx`
- **Резолвер:** `fulfillmentReceiveOrder` в `/src/graphql/resolvers.ts`
### **Критическая проблема статусов:**
```javascript
// ❌ КОНФЛИКТ: Резолвер ожидает статус SHIPPED
if (supplyOrder.status !== 'SHIPPED') {
return {
success: false,
message: 'Заказ должен быть в статусе SHIPPED для приемки'
}
}
// ❌ Но UI пытается принять заказ со статусом SUPPLIER_APPROVED
// Это блокирует весь процесс приемки!
```
### **Процесс приемки (правильный workflow):**
1. После одобрения поставщиком товары должны отображаться в кабинете фулфилмента:
- **Поставки товаров**: "Входящие поставки / Поставки на фулфилмент / Товар / Новые"
- **Расходники селлера**: "Входящие поставки / Поставки на фулфилмент / Расходники селлера"
2. Фулфилмент выбирает ответственного сотрудника (из раздела "Сотрудники")
3. Фулфилмент выбирает логистического партнера (из раздела "Партнеры / Логистика")
4. Нажимает кнопку "Принять" (НЕ "Принять поставку")
5. Статус меняется на следующий этап
### ❌ **Критические проблемы:**
- **НЕПРАВИЛЬНАЯ ФИЛЬТРАЦИЯ**: поставки товаров отображаются в "Расходники селлера" вместо "Товар/Новые"
- **Нарушен workflow**: отсутствует промежуточный статус между SUPPLIER_APPROVED и LOGISTICS_CONFIRMED
- **Нет UI выбора**: фулфилмент не может выбрать ответственного сотрудника
- **Нет UI выбора**: фулфилмент не может выбрать логистического партнера
- **Блокирующий баг**: невозможно принять товары из-за неправильной проверки статуса
---
## 📋 ЭТАП 4: АНАЛИЗ РОЛИ ЛОГИСТИКИ
### **Найденный код:**
- **Файл:** `/src/components/logistics-orders/logistics-orders-dashboard.tsx`
- **Фильтрация:** по `logisticsPartnerId`
- **Мутации:** `LOGISTICS_CONFIRM_ORDER`, `LOGISTICS_REJECT_ORDER`
### **Процесс работы логистики:**
1. Логистика видит заказы, где назначена как логистический партнер
2. Может подтвердить или отклонить логистическое сопровождение
3. При подтверждении статус меняется на `LOGISTICS_CONFIRMED`
4. После отгрузки статус меняется на `SHIPPED`
### **Статусы, которые логистика может обработать:**
```javascript
// Логистика может подтвердить заказы со статусами:
order.status === 'SUPPLIER_APPROVED' || order.status === 'CONFIRMED'
```
### ✅ **Что работает:**
- Корректная фильтрация заказов для логистических партнеров
- UI для подтверждения/отклонения заказов
- Статистика заказов по статусам
### ❌ **Выявленные проблемы:**
- **Нет маршрутизации**: отсутствует система планирования маршрутов
- **Нет трекинга**: отсутствует детальное отслеживание статуса доставки
- **Нет интеграции**: отсутствует интеграция с внешними логистическими системами
---
## 📋 ЭТАП 5: АНАЛИЗ СТАТУСОВ И ПЕРЕХОДОВ
### **Текущие статусы системы:**
```prisma
enum SupplyOrderStatus {
PENDING // Создан селлером, ждет поставщика
SUPPLIER_APPROVED // Одобрен поставщиком
CONFIRMED // Устаревший статус
LOGISTICS_CONFIRMED // Подтвержден логистикой
SHIPPED // Отправлен в доставку
IN_TRANSIT // Устаревший статус
DELIVERED // Доставлен получателю
CANCELLED // Отменен
}
```
### **Проблемы в переходах статусов:**
#### ❌ **Критическая проблема workflow:**
```
Текущий поток: PENDING → SUPPLIER_APPROVED → ??? → LOGISTICS_CONFIRMED → SHIPPED → DELIVERED
ПРОПУЩЕН ЭТАП!
```
**Отсутствует статус `FULFILLMENT_ACCEPTED`** между одобрением поставщиком и подтверждением логистикой!
#### **Правильный workflow должен быть:**
```
PENDING → SUPPLIER_APPROVED → FULFILLMENT_ACCEPTED → LOGISTICS_CONFIRMED → SHIPPED → DELIVERED
```
### **Анализ переходов по участникам:**
1. **СЕЛЛЕР**: `null → PENDING` (создание)
2. **ПОСТАВЩИК**: `PENDING → SUPPLIER_APPROVED` (одобрение)
3. **ФУЛФИЛМЕНТ**: `SUPPLIER_APPROVED → FULFILLMENT_ACCEPTED` (❌ ОТСУТСТВУЕТ)
4. **ЛОГИСТИКА**: `FULFILLMENT_ACCEPTED → LOGISTICS_CONFIRMED` (подтверждение)
5. **ЛОГИСТИКА**: `LOGISTICS_CONFIRMED → SHIPPED` (отгрузка)
6. **СИСТЕМА**: `SHIPPED → DELIVERED` (финал)
---
## 📋 ЭТАП 6: АНАЛИЗ UI КОМПОНЕНТОВ ВСЕХ УЧАСТНИКОВ
### **6.1 СЕЛЛЕР** (`/src/components/supplies/supplies-dashboard.tsx`)
**Работает корректно:**
- Многоуровневая навигация (фулфилмент/маркетплейсы → товар/расходники → карточки/поставщики)
- Интеграция с `AllSuppliesTab` для отображения поставок
- Статистика и уведомления
- Кнопки создания поставок
### **6.2 ПОСТАВЩИК** (`/src/components/supplier-orders/supplier-orders-dashboard.tsx`)
**Работает:**
- Отображение входящих заявок
- Кнопки одобрения/отклонения
**Критические недостатки:**
- Нет формы ввода дополнительных данных при одобрении
- Отсутствуют поля packagesCount, volume, readyDate
### **6.3 ФУЛФИЛМЕНТ** (`/src/components/fulfillment-supplies/fulfillment-supplies-dashboard.tsx`)
**Работает:**
- Сложная многоуровневая навигация
- Статистика по типам поставок
- Уведомления о новых поставках
**Критические недостатки:**
- Нет формы выбора ответственного сотрудника
- Нет формы выбора логистического партнера
- Компонент `FulfillmentDetailedSuppliesTab` не может принять товары из-за бага статусов
### **6.4 ЛОГИСТИКА** (`/src/components/logistics-orders/logistics-orders-dashboard.tsx`)
**Работает:**
- Фильтрация заказов по логистическому партнеру
- Статистика заказов
- Подтверждение/отклонение заказов
**Недостатки:**
- Отсутствует система маршрутизации
- Нет планировщика доставок
- Нет детального трекинга
---
## 📋 ЭТАП 7: ПОЛНЫЙ СПИСОК ПРОБЕЛОВ И НЕДОСТАЮЩЕЙ ФУНКЦИОНАЛЬНОСТИ
### **🔴 КРИТИЧЕСКИЕ ПРОБЛЕМЫ (11 шт.):**
#### **Backend/Workflow:**
1. **Отсутствует статус `FULFILLMENT_ACCEPTED`** в workflow между SUPPLIER_APPROVED и LOGISTICS_CONFIRMED
2. **Баг в `fulfillmentReceiveOrder`**: резолвер ожидает статус SHIPPED, но получает SUPPLIER_APPROVED
3. **Неполная мутация `supplierApproveOrder`**: не принимает поля packagesCount, volume, readyDate
4. **Отсутствует мутация для промежуточной приемки** фулфилментом с выбором сотрудника и логистики
#### **UI Формы:**
5. **Поставщик не может ввести packagesCount** (количество грузовых мест) при одобрении
6. **Поставщик не может ввести volume** (объем товара в м³) при одобрении
7. **Поставщик не может указать дату готовности** товаров к отгрузке
8. **Фулфилмент не может выбрать ответственного сотрудника** для приемки товаров
9. **Фулфилмент не может выбрать логистического партнера** для дальнейшей доставки
#### **Валидация:**
10. **Нет валидации обязательных полей** при одобрении поставщиком
11. **Нет проверки доступности логистических партнеров** при выборе фулфилментом
### **🟡 ВЫСОКИЙ ПРИОРИТЕТ (6 шт.):**
#### **Бизнес-логика:**
12. **Нет проверки минимальных количеств заказа** при создании поставки селлером
13. **Отсутствует валидация доступности товаров** у поставщика в момент заказа
14. **Нет связи между сотрудниками и фулфилмент-центрами** для корректного выбора
#### **Интеграция и уведомления:**
15. **Отсутствуют автоматические уведомления** поставщику о новых заказах
16. **Нет real-time обновлений статусов** между всеми участниками процесса
17. **Отсутствует система уведомлений** о смене статуса для всех участников
### **🟠 СРЕДНИЙ ПРИОРИТЕТ (3 шт.):**
#### **Логистика и маршрутизация:**
18. **Отсутствует система маршрутизации** для планирования оптимальных доставок
19. **Нет детального трекинга статуса доставки** с промежуточными точками
20. **Отсутствует интеграция с внешними логистическими API** для расчета расстояний и времени
---
## 🎯 СТРУКТУРИРОВАННЫЙ ПЛАН ДОРАБОТКИ
### **ЭТАП 1: КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ WORKFLOW**
**🔴 Приоритет: КРИТИЧЕСКИЙ** | **Время: 2-3 дня**
#### 1.1 Исправление фильтрации в кабинете фулфилмента
- [ ] **КРИТИЧНО**: Исправить неправильную фильтрацию - поставки товаров должны отображаться в "Товар/Новые", а НЕ в "Расходники селлера"
- [ ] **Логика разделения**:
- Если селлер создал поставку товаров → отображать в "Поставки на фулфилмент/Товар/Новые"
- Если селлер создал поставку расходников → отображать в "Поставки на фулфилмент/Расходники селлера"
#### 1.2 Убрать отображение статуса у поставщика
- [ ] **UI поставщика**: Убрать текст "ожидает подтверждения" - оставить только кнопки "Одобрить"/"Отклонить"
- [ ] **Файл**: `/src/components/supplier-orders/supplier-orders-tabs.tsx`
#### 1.3 Создать форму выбора для фулфилмента
- [ ] **Компонент**: Форма с выбором:
- Ответственный сотрудник (из раздела "Сотрудники")
- Логистический партнер (из раздела "Партнеры/Логистика")
- [ ] **Кнопка**: "Принять" (НЕ "Принять поставку")
- [ ] **Интеграция**: Обновить таблицу товаров по образцу "Партнеры/Контрагенты"
### **ЭТАП 2: СТАТУСЫ И BACKEND**
**🔴 Приоритет: КРИТИЧЕСКИЙ** | **Время: 1-2 дня**
#### 2.1 Исправление workflow статусов
- [ ] **Prisma**: Добавить статус `FULFILLMENT_ACCEPTED` в enum SupplyOrderStatus
- [ ] **GraphQL**: Обновить резолверы для поддержки нового workflow
- [ ] **Backend**: Исправить мутацию `fulfillmentReceiveOrder` для корректной работы с SUPPLIER_APPROVED → FULFILLMENT_ACCEPTED
- [ ] **Мутация**: Создать `fulfillmentAcceptOrder` для промежуточной приемки с выбором сотрудника и логистики
### **ЭТАП 3: СИСТЕМА УВЕДОМЛЕНИЙ**
**🟡 Приоритет: ВЫСОКИЙ** | **Время: 1 день**
#### 3.1 Real-time уведомления между участниками
- [ ] **WebSocket**: Настроить уведомления о смене статусов
- [ ] **Email**: Уведомления поставщику о новых заказах
- [ ] **Dashboard**: Обновить бейджи уведомлений для всех участников
### **ЭТАП 4: ИНТЕГРАЦИЯ С ЛОГИСТИКОЙ**
**🟠 Приоритет: СРЕДНИЙ** | **Время: 2-3 дня**
#### 4.1 Система маршрутизации и планирования
- [ ] **Компонент**: Система планирования маршрутов для логистики
- [ ] **API**: Интеграция с внешними сервисами для расчета расстояний
- [ ] **Планировщик**: Календарь доставок и оптимизация маршрутов
#### 4.2 Детальный трекинг доставки
- [ ] **Статусы**: Промежуточные статусы доставки (в пути, на складе, доставлено)
- [ ] **UI**: Компонент отслеживания доставки для всех участников
---
## 📁 ФАЙЛОВАЯ СТРУКТУРА ДЛЯ РЕАЛИЗАЦИИ
### **Backend изменения:**
```
prisma/schema.prisma - добавить FULFILLMENT_ACCEPTED статус
src/graphql/resolvers.ts - исправить переходы статусов
src/graphql/mutations.ts - обновить мутации с доп. полями
src/graphql/typedefs.ts - типы для новых полей
```
### **Frontend компоненты:**
```
src/components/supplier-orders/
├── supplier-approval-form.tsx - новый компонент
└── supplier-orders-tabs.tsx - обновить
src/components/fulfillment-supplies/
├── fulfillment-acceptance-form.tsx - новый компонент
└── fulfillment-detailed-supplies-tab.tsx - обновить
src/components/logistics-orders/
├── route-planner.tsx - новый компонент
└── logistics-orders-dashboard.tsx - обновить
```
---
## 🔧 ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ
### **GraphQL Схемы (обновить):**
```graphql
# Обновить мутацию поставщика:
supplierApproveOrder(
id: String!
packagesCount: Int! # Обязательное
volume: Float! # Обязательное
readyDate: DateTime # Опциональное
notes: String # Опциональное
): SupplyOrderResponse!
# Новая мутация фулфилмента:
fulfillmentAcceptOrder(
id: String!
responsibleEmployee: String! # ID сотрудника
logisticsPartnerId: String! # ID логистики
notes: String # Примечания
): SupplyOrderResponse!
```
### **Prisma Schema (добавить):**
```prisma
enum SupplyOrderStatus {
PENDING
SUPPLIER_APPROVED
FULFILLMENT_ACCEPTED # ← НОВЫЙ СТАТУС
LOGISTICS_CONFIRMED
SHIPPED
DELIVERED
CANCELLED
}
model SupplyOrder {
// ... существующие поля
packagesCount Int? # Активное использование
volume Float? # Активное использование
readyDate DateTime? # Дата готовности от поставщика
responsibleEmployee String? # ID ответственного сотрудника ФФ
acceptanceNotes String? # Примечания при приемке
}
```
---
## ⚠️ КРИТИЧЕСКИЕ ЗАМЕЧАНИЯ ДЛЯ РАЗРАБОТКИ
### **1. Обратная совместимость:**
- НЕ НАРУШАТЬ существующие поставки при добавлении нового статуса
- Добавить миграцию для корректного обновления существующих записей
- Протестировать на существующих данных
### **2. Права доступа:**
- ВАЛИДИРОВАТЬ права каждого участника на каждом этапе
- Поставщик может работать только с заказами где он partnerId
- Фулфилмент может работать только с заказами своего центра
- Логистика может работать только с назначенными ей заказами
### **3. Тестирование:**
- ОБЯЗАТЕЛЬНО протестировать все переходы статусов
- Проверить корректность фильтрации для каждого типа организации
- Тестировать валидацию полей на frontend и backend
### **4. Производительность:**
- Учесть индексы в БД для новых полей
- Оптимизировать запросы при добавлении новых фильтров
- Проверить нагрузку при увеличении количества статусов
---
## 📊 МЕТРИКИ УСПЕХА РЕАЛИЗАЦИИ
### **Функциональные метрики:**
- [ ] Поставщик может успешно одобрить заказ с указанием packagesCount и volume
- [ ] Фулфилмент может выбрать сотрудника и логистику при приемке
- [ ] Все статусы корректно переходят от PENDING до DELIVERED
- [ ] Каждый участник видит только свои заказы в правильных статусах
### **Технические метрики:**
- [ ] Нет ошибок в консоли при переходах статусов
- [ ] Все GraphQL мутации возвращают корректные результаты
- [ ] UI формы корректно валидируют обязательные поля
- [ ] Real-time обновления работают для всех участников
---
**Документ содержит полный анализ существующей системы и детальный план реализации недостающего функционала для создания полноценной 4-участнической цепочки поставок товаров.**