From b72ac4217329314deec8a43028958d4217a5b41b Mon Sep 17 00:00:00 2001 From: Veronika Smirnova Date: Fri, 8 Aug 2025 16:37:51 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=20=D0=B7=D0=B0=D1=89=D0=B8=D1=89=D0=B5=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9=20=D1=80=D0=B5=D0=B7=D0=B5=D1=80=D0=B2=D0=BD=D0=BE=D0=B9?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BF=D0=B8=D0=B8=20rules-complete.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Создан файл rules-complete-BACKUP.md как полная резервная копия - Добавлено предупреждение о запрете редактирования без разрешения - Файл содержит 3636 строк всех бизнес-правил системы - Резерв создан для защиты от случайных изменений ⚠️ ВАЖНО: Файл rules-complete-BACKUP.md ЗАПРЕЩЕНО редактировать без явного разрешения пользователя\! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- rules-complete-BACKUP.md | 3648 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 3648 insertions(+) create mode 100644 rules-complete-BACKUP.md diff --git a/rules-complete-BACKUP.md b/rules-complete-BACKUP.md new file mode 100644 index 0000000..2287ff1 --- /dev/null +++ b/rules-complete-BACKUP.md @@ -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 +// Структура компонентов панели +
+ + +
+ + +
+
+``` + +#### **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 +
+``` + +- **Назначение**: Визуальное обрамление блока, единство с другими блоками +- **Стилизация**: Стеклянный эффект с размытием и полупрозрачностью +- **Рамка**: Тонкая белая рамка border-white/20 с закруглёнными углами +- **Поведение**: flex-shrink-0 предотвращает сжатие блока + +**УРОВЕНЬ 2 - Внутренний контейнер (скролл):** + +```jsx +
+``` + +- **Назначение**: Горизонтальная прокрутка карточек товаров +- **Раскладка**: 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 +
+
+ +

Поставщики

+
+
+
+ + +
+
+
+``` + +**ПРАВИЛА ЗАГОЛОВКА:** + +- **Иконка**: 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 +
+ +
+

{supplier.name || supplier.fullName}

+
+

ИНН: {supplier.inn}

+ {supplier.market && {getMarketLabel(supplier.market)}} +
+
+
+``` + +**ПРАВИЛА СОДЕРЖАНИЯ КАРТОЧКИ:** + +**✅ ОСТАВИТЬ:** + +- **Аватар организации**: 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 +
+
+``` + +**ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ**: + +- **Ширина**: `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) => { + 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**: Указание источников и осторожные формулировки