feat(supplier-orders): добавить параметры поставки в таблицу заявок
- Добавлены колонки Объём и Грузовые места между Цена товаров и Статус - Реализованы инпуты для ввода volume и packagesCount в статусе PENDING для роли WHOLESALE - Добавлена мутация UPDATE_SUPPLY_PARAMETERS с проверками безопасности - Скрыта строка Поставщик для роли WHOLESALE (поставщик знает свои данные) - Исправлено выравнивание таблицы при скрытии уровня поставщика - Реорганизованы документы: legacy-rules/, docs/, docs-and-reports/ ВНИМАНИЕ: Компонент multilevel-supplies-table.tsx (1697 строк) нарушает правило модульной архитектуры (>800 строк требует рефакторинга) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -625,7 +625,7 @@ query GetMyCounterparties($type: OrganizationType) {
|
||||
### МУТАЦИИ ПОСТАВЩИКОВ:
|
||||
|
||||
```graphql
|
||||
# Одобрение заказа поставщиком с опциональными полями упаковки
|
||||
# Одобрение заказа поставщиком с дополнительными параметрами поставки
|
||||
mutation SupplierApproveOrder(
|
||||
$orderId: ID!
|
||||
$packagesCount: Int
|
||||
@ -635,23 +635,25 @@ mutation SupplierApproveOrder(
|
||||
) {
|
||||
supplierApproveOrder(
|
||||
id: $orderId
|
||||
packagesCount: $packagesCount # Опционально: для логистических расчетов
|
||||
volume: $volume # Опционально: для планирования логистики
|
||||
readyDate: $readyDate # Опционально: дата готовности к отгрузке
|
||||
notes: $notes # Опционально: комментарии
|
||||
packagesCount: $packagesCount # Параметр поставки: количество грузовых мест
|
||||
volume: $volume # Параметр поставки: объем груза
|
||||
readyDate: $readyDate # Параметр поставки: дата готовности к отгрузке
|
||||
notes: $notes # Параметр поставки: дополнительная информация
|
||||
) {
|
||||
success
|
||||
message
|
||||
order {
|
||||
id
|
||||
status # PENDING → SUPPLIER_APPROVED
|
||||
deliveryDate # Основной параметр поставки
|
||||
totalAmount # Ключевой параметр поставки - общая стоимость
|
||||
totalItems # Параметр поставки - количество товаров
|
||||
organization {
|
||||
id
|
||||
name
|
||||
}
|
||||
totalAmount
|
||||
packagesCount # null если не указано
|
||||
volume # null если не указано
|
||||
packagesCount # Параметр поставки (опционально)
|
||||
volume # Параметр поставки (опционально)
|
||||
readyDate # null если не указано
|
||||
notes # null если не указано
|
||||
}
|
||||
|
342
docs/business-processes/EXCHANGE_MODULE_RULES.md
Normal file
342
docs/business-processes/EXCHANGE_MODULE_RULES.md
Normal file
@ -0,0 +1,342 @@
|
||||
# ПРАВИЛА ВНЕДРЕНИЯ МОДУЛЯ "БИРЖА" В СИСТЕМУ SFERA
|
||||
|
||||
## 🎯 ОБЗОР ЗАДАЧИ
|
||||
|
||||
**Цель:** Создание нового раздела "Биржа" во всех кабинетах с переносом функционала из раздела "Маркет"
|
||||
|
||||
**Принцип:** Модульная архитектура с безопасным рефакторингом и сохранением совместимости
|
||||
|
||||
## 📋 ДЕТАЛЬНЫЕ ПРАВИЛА РЕАЛИЗАЦИИ
|
||||
|
||||
### 1. СТРУКТУРНАЯ АРХИТЕКТУРА
|
||||
|
||||
#### 1.1 Создание модульной структуры:
|
||||
|
||||
```
|
||||
src/components/exchange/ # Новый модуль Биржи
|
||||
├── exchange-dashboard.tsx # Главная страница Биржи
|
||||
├── tabs/
|
||||
│ ├── investments-tab.tsx # Перенос из market/investments
|
||||
│ └── market-tab.tsx # Перенос из market/market
|
||||
├── hooks/
|
||||
│ ├── useExchangeData.ts # Хуки для данных биржи
|
||||
│ └── useInvestmentOperations.ts # Логика инвестиций
|
||||
├── components/
|
||||
│ ├── ExchangeHeader.tsx # Заголовок раздела
|
||||
│ └── ExchangeStats.tsx # Статистика биржи
|
||||
└── types/
|
||||
└── exchange.types.ts # TypeScript интерфейы
|
||||
```
|
||||
|
||||
#### 1.2 Обновление навигации:
|
||||
|
||||
```typescript
|
||||
// src/components/dashboard/sidebar.tsx
|
||||
const navigationItems = [
|
||||
// ... существующие пункты
|
||||
{
|
||||
name: 'Биржа',
|
||||
href: '/exchange',
|
||||
icon: TrendingUp, // или Zap, или BarChart3
|
||||
position: 'before-settings', // Над разделом настройки
|
||||
},
|
||||
// ... остальные пункты
|
||||
]
|
||||
```
|
||||
|
||||
### 2. БЕЗОПАСНЫЙ ПЕРЕНОС КОМПОНЕНТОВ
|
||||
|
||||
#### 2.1 Сохранение оригиналов:
|
||||
|
||||
```bash
|
||||
# Создаем backup перед переносом
|
||||
cp -r src/components/market/investments-tab.tsx src/components/market/investments-tab.tsx.backup
|
||||
cp -r src/components/market/market-tab.tsx src/components/market/market-tab.tsx.backup
|
||||
```
|
||||
|
||||
#### 2.2 Поэтапный перенос:
|
||||
|
||||
```typescript
|
||||
// Этап 1: Создание алиасов (временно)
|
||||
export { InvestmentsTab as ExchangeInvestmentsTab } from '../market/investments-tab'
|
||||
export { MarketTab as ExchangeMarketTab } from '../market/market-tab'
|
||||
|
||||
// Этап 2: Копирование с адаптацией
|
||||
// Этап 3: Обновление импортов
|
||||
// Этап 4: Удаление дубликатов
|
||||
```
|
||||
|
||||
### 3. МАРШРУТИЗАЦИЯ И URL
|
||||
|
||||
#### 3.1 Новая структура маршрутов:
|
||||
|
||||
```
|
||||
/exchange # Главная страница Биржи
|
||||
├── /exchange/investments # Инвестиции (было /market/investments)
|
||||
└── /exchange/market # Маркет (было /market/market)
|
||||
|
||||
/market # Остается, но без investments и market
|
||||
├── /market/logistics # Остается
|
||||
├── /market/analytics # Остается
|
||||
└── /market/other-tabs # Остальные вкладки остаются
|
||||
```
|
||||
|
||||
#### 3.2 Редиректы для совместимости:
|
||||
|
||||
```typescript
|
||||
// src/middleware.ts или pages/_app.tsx
|
||||
const redirectRules = [
|
||||
{
|
||||
from: '/market/investments',
|
||||
to: '/exchange/investments',
|
||||
permanent: true,
|
||||
},
|
||||
{
|
||||
from: '/market/market',
|
||||
to: '/exchange/market',
|
||||
permanent: true,
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
### 4. УНИВЕРСАЛЬНОСТЬ ДЛЯ ВСЕХ КАБИНЕТОВ
|
||||
|
||||
#### 4.1 Роль-агностический подход:
|
||||
|
||||
```typescript
|
||||
// src/components/exchange/exchange-dashboard.tsx
|
||||
interface ExchangeDashboardProps {
|
||||
userRole: 'SELLER' | 'WHOLESALE' | 'FULFILLMENT' | 'LOGIST'
|
||||
// Компонент адаптируется под роль, но функционал одинаковый
|
||||
}
|
||||
|
||||
const ExchangeDashboard: FC<ExchangeDashboardProps> = ({ userRole }) => {
|
||||
// Одинаковая логика для всех ролей
|
||||
return (
|
||||
<div className="exchange-dashboard">
|
||||
<ExchangeHeader userRole={userRole} />
|
||||
<ExchangeTabs userRole={userRole} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2 Единая конфигурация:
|
||||
|
||||
```typescript
|
||||
// src/config/exchange.config.ts
|
||||
export const EXCHANGE_CONFIG = {
|
||||
tabs: [
|
||||
{
|
||||
id: 'investments',
|
||||
name: 'Инвестиции',
|
||||
path: '/exchange/investments',
|
||||
availableFor: ['SELLER', 'WHOLESALE', 'FULFILLMENT', 'LOGIST'], // Все роли
|
||||
},
|
||||
{
|
||||
id: 'market',
|
||||
name: 'Маркет',
|
||||
path: '/exchange/market',
|
||||
availableFor: ['SELLER', 'WHOLESALE', 'FULFILLMENT', 'LOGIST'], // Все роли
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### 5. ИКОНКА И UI ЭЛЕМЕНТЫ
|
||||
|
||||
#### 5.1 Выбор иконки:
|
||||
|
||||
```typescript
|
||||
import { TrendingUp } from 'lucide-react' // Основной вариант - рост, тренды
|
||||
// Альтернативы:
|
||||
// import { Zap } from 'lucide-react' // Энергия, быстрота
|
||||
// import { BarChart3 } from 'lucide-react' // Аналитика, графики
|
||||
// import { Activity } from 'lucide-react' // Активность, пульс
|
||||
```
|
||||
|
||||
#### 5.2 Стилизация в соответствии с дизайн-системой:
|
||||
|
||||
```typescript
|
||||
// Используем существующую Glass Morphism систему
|
||||
<div className="glass-card">
|
||||
<div className="flex items-center gap-3">
|
||||
<TrendingUp className="h-5 w-5 text-primary" />
|
||||
<span className="font-semibold">Биржа</span>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
### 6. БЕЗОПАСНОСТЬ И СОВМЕСТИМОСТЬ
|
||||
|
||||
#### 6.1 Проверка существующих зависимостей:
|
||||
|
||||
```bash
|
||||
# Поиск всех ссылок на старые компоненты
|
||||
grep -r "market/investments" src/
|
||||
grep -r "market/market" src/
|
||||
grep -r "/market/investments" src/
|
||||
grep -r "/market/market" src/
|
||||
```
|
||||
|
||||
#### 6.2 Градуальная миграция:
|
||||
|
||||
```typescript
|
||||
// Временный мост-компонент
|
||||
const MarketInvestmentsBridge: FC = () => {
|
||||
// Редирект на новый URL
|
||||
useEffect(() => {
|
||||
router.replace('/exchange/investments')
|
||||
}, [])
|
||||
|
||||
return <div>Перенаправление на новую страницу...</div>
|
||||
}
|
||||
```
|
||||
|
||||
### 7. ТЕСТИРОВАНИЕ И ПРОВЕРКА
|
||||
|
||||
#### 7.1 Чек-лист проверки:
|
||||
|
||||
- [ ] Все ссылки работают корректно
|
||||
- [ ] Редиректы функционируют
|
||||
- [ ] Навигация обновлена во всех кабинетах
|
||||
- [ ] Компоненты отображаются идентично
|
||||
- [ ] Данные загружаются без ошибок
|
||||
- [ ] TypeScript типы корректны
|
||||
|
||||
#### 7.2 Тестирование по ролям:
|
||||
|
||||
```typescript
|
||||
const testScenarios = [
|
||||
{ role: 'SELLER', path: '/exchange' },
|
||||
{ role: 'WHOLESALE', path: '/exchange' },
|
||||
{ role: 'FULFILLMENT', path: '/exchange' },
|
||||
{ role: 'LOGIST', path: '/exchange' },
|
||||
]
|
||||
```
|
||||
|
||||
### 8. ГРАФQL И ДАННЫЕ
|
||||
|
||||
#### 8.1 Анализ существующих компонентов:
|
||||
|
||||
```typescript
|
||||
// ✅ ОБНАРУЖЕНО: Компоненты НЕ ИСПОЛЬЗУЮТ GraphQL
|
||||
// market-investments.tsx - статичные UI карточки
|
||||
// market-business.tsx - статичные UI карточки
|
||||
// Никаких useQuery/useMutation не найдено
|
||||
```
|
||||
|
||||
#### 8.2 Стратегия переноса данных:
|
||||
|
||||
```typescript
|
||||
// Компоненты используют только UI элементы:
|
||||
// - Статичный контент
|
||||
// - Иконки Lucide React
|
||||
// - Glass Morphism карточки
|
||||
// - Никаких внешних API вызовов
|
||||
```
|
||||
|
||||
#### 8.3 Заключение по GraphQL:
|
||||
|
||||
- ❌ **GraphQL запросы НЕ НУЖНЫ** - компоненты статичные
|
||||
- ✅ **Простой перенос** - только UI компоненты
|
||||
- ✅ **Без изменений в resolvers** - данные не загружаются
|
||||
|
||||
### 9. ПЛАН ПОЭТАПНОЙ РЕАЛИЗАЦИИ
|
||||
|
||||
#### Фаза 1: Подготовка
|
||||
|
||||
1. Создание структуры папок
|
||||
2. Анализ зависимостей
|
||||
3. Создание TypeScript интерфейсов
|
||||
|
||||
#### Фаза 2: Создание компонентов
|
||||
|
||||
1. Копирование и адаптация существующих компонентов
|
||||
2. Создание exchange-dashboard.tsx
|
||||
3. Настройка навигации
|
||||
|
||||
#### Фаза 3: Интеграция
|
||||
|
||||
1. Обновление маршрутов
|
||||
2. Настройка редиректов
|
||||
3. Обновление импортов
|
||||
|
||||
#### Фаза 4: Тестирование и очистка
|
||||
|
||||
1. Тестирование всех сценариев
|
||||
2. Удаление дубликатов
|
||||
3. Финальная проверка
|
||||
|
||||
---
|
||||
|
||||
## ✅ ПОДТВЕРЖДЁННЫЕ РЕШЕНИЯ:
|
||||
|
||||
1. **Иконка:** ✅ `TrendingUp` подходит для раздела "Биржа"
|
||||
2. **Позиционирование:** ✅ Размещать прямо перед Settings в сайдбаре
|
||||
3. **GraphQL:** ✅ Изменения НЕ НУЖНЫ - компоненты статичные
|
||||
4. **Уведомления:** ✅ НЕ показывать уведомления о переносе
|
||||
|
||||
## 🎯 ФИНАЛЬНАЯ АРХИТЕКТУРА:
|
||||
|
||||
### Структура переноса:
|
||||
|
||||
```
|
||||
ИЗ: /market (4 вкладки)
|
||||
├── investments ➜ /exchange/investments
|
||||
├── business ➜ /exchange/market
|
||||
├── products ➜ остается в /market
|
||||
└── requests ➜ остается в /market
|
||||
|
||||
В: /exchange (2 вкладки)
|
||||
├── /exchange/investments (было: market-investments.tsx)
|
||||
└── /exchange/market (было: market-business.tsx)
|
||||
```
|
||||
|
||||
### Обновление nav структуры:
|
||||
|
||||
```typescript
|
||||
// sidebar.tsx порядок пунктов:
|
||||
[Home, Supplies, Services, Exchange, Settings, ...]
|
||||
// ↑ новый пункт
|
||||
```
|
||||
|
||||
## 📊 СТАТУС РЕАЛИЗАЦИИ
|
||||
|
||||
**Текущий статус**: ✅ **ПОЛНОСТЬЮ РЕАЛИЗОВАНО**
|
||||
|
||||
**Дата завершения**: 22 августа 2025
|
||||
|
||||
### Выполненные фазы:
|
||||
|
||||
✅ **Фаза 1**: Создана структура папок `src/components/exchange/`
|
||||
✅ **Фаза 2**: Скопированы и адаптированы компоненты из market
|
||||
✅ **Фаза 3**: Обновлена навигация и созданы маршруты
|
||||
✅ **Фаза 4**: Протестировано и очищено
|
||||
|
||||
### Результат реализации:
|
||||
|
||||
- ✅ Раздел "Биржа" доступен во всех кабинетах с иконкой TrendingUp
|
||||
- ✅ Перенесены вкладки "Инвестиции" и "Бизнес" из Маркета в Биржу
|
||||
- ✅ Маркет теперь содержит только "Товары" и "Заявки"
|
||||
- ✅ Сохранена полная функциональность без потери данных
|
||||
- ✅ Безопасная реализация с резервными копиями
|
||||
- ✅ Протестировано - dev сервер запускается корректно
|
||||
- ✅ Типы TypeScript корректны
|
||||
|
||||
### Финальная структура:
|
||||
|
||||
```
|
||||
src/components/exchange/
|
||||
├── exchange-dashboard.tsx ✅ Главная страница Биржи
|
||||
├── tabs/
|
||||
│ ├── investments-tab.tsx ✅ Перенос из market-investments
|
||||
│ └── business-tab.tsx ✅ Перенос из market-business
|
||||
├── types/
|
||||
│ └── exchange.types.ts ✅ TypeScript интерфейсы
|
||||
└── index.ts ✅ Экспорты модуля
|
||||
|
||||
src/app/exchange/page.tsx ✅ Next.js маршрут
|
||||
```
|
||||
|
||||
**ЗАДАЧА ВЫПОЛНЕНА УСПЕШНО!** 🎉
|
@ -36,7 +36,7 @@ interface SupplyOrder {
|
||||
sellerConsumables: Supply[] // Расходники селлера
|
||||
}
|
||||
|
||||
// Упаковочная информация (опциональная)
|
||||
// Параметры поставки (опциональные)
|
||||
packagesCount?: number // Количество грузовых мест
|
||||
volume?: number // Объем груза в м³
|
||||
readyDate?: Date // Дата готовности к отгрузке
|
||||
@ -567,7 +567,7 @@ export class CommercialDataAudit {
|
||||
"quantity": 10
|
||||
// ❌ НЕ видит recipe
|
||||
}],
|
||||
"packagesCount": 2, // ✅ Видит упаковочную информацию
|
||||
"packagesCount": 2, // ✅ Видит параметры поставки
|
||||
"volume": 0.5,
|
||||
// ❌ НЕ видит totalAmount, услуги ФФ, логистику
|
||||
}
|
||||
|
302
docs/business-processes/SUPPLY_PARAMETERS_RULES.md
Normal file
302
docs/business-processes/SUPPLY_PARAMETERS_RULES.md
Normal file
@ -0,0 +1,302 @@
|
||||
# ПРАВИЛА ПАРАМЕТРОВ ПОСТАВКИ
|
||||
|
||||
## 📋 **ОПРЕДЕЛЕНИЕ ПАРАМЕТРОВ ПОСТАВКИ**
|
||||
|
||||
**Параметры поставки** - это все характеристики и данные, которые описывают конкретную поставку товаров в системе SFERA.
|
||||
|
||||
## 🎯 **КЛАССИФИКАЦИЯ ПАРАМЕТРОВ ПОСТАВКИ**
|
||||
|
||||
### **1. ОБЯЗАТЕЛЬНЫЕ ПАРАМЕТРЫ:**
|
||||
- **`id`** - Уникальный идентификатор поставки
|
||||
- **`deliveryDate`** - Дата поставки (когда товары должны быть доставлены)
|
||||
- **`totalAmount`** - Общая стоимость поставки
|
||||
- **`totalItems`** - Количество товаров в поставке
|
||||
- **`organizationId`** - Идентификатор заказчика
|
||||
- **`partnerId`** - Идентификатор поставщика
|
||||
- **`status`** - Статус поставки (PENDING, APPROVED, SHIPPED и т.д.)
|
||||
|
||||
### **2. ЦЕНОВЫЕ ПАРАМЕТРЫ:**
|
||||
- **`totalAmount`** - Общая сумма поставки
|
||||
- **`goodsPrice`** - Стоимость товаров (расчетное поле)
|
||||
- **`servicesPrice`** - Стоимость услуг фулфилмента (расчетное поле)
|
||||
- **`logisticsPrice`** - Стоимость логистических услуг (расчетное поле)
|
||||
- **`sellerConsumablesPrice`** - Стоимость расходников селлера (расчетное поле)
|
||||
- **`ffConsumablesPrice`** - Стоимость расходников фулфилмента (расчетное поле)
|
||||
|
||||
### **3. ТОВАРНЫЕ ПАРАМЕТРЫ:**
|
||||
- **`items[]`** - Массив товаров с количествами и ценами
|
||||
- **`productId`** - ID товара в позиции
|
||||
- **`quantity`** - Количество каждого товара
|
||||
- **`price`** - Цена за единицу товара
|
||||
- **`totalPrice`** - Общая стоимость позиции
|
||||
- **`services[]`** - Массив услуг для товара
|
||||
- **`fulfillmentConsumables[]`** - Расходники фулфилмента для товара
|
||||
- **`sellerConsumables[]`** - Расходники селлера для товара
|
||||
- **`marketplaceCardId`** - ID карточки маркетплейса
|
||||
|
||||
### **4. ЛОГИСТИЧЕСКИЕ ПАРАМЕТРЫ:**
|
||||
- **`packagesCount`** - Количество грузовых мест
|
||||
- **`volume`** - Объём груза в м³
|
||||
- **`routes[]`** - Маршруты доставки
|
||||
- **`fromLocation`** - Точка забора груза
|
||||
- **`toLocation`** - Точка доставки
|
||||
- **`fromAddress`** - Полный адрес забора
|
||||
- **`toAddress`** - Полный адрес доставки
|
||||
- **`distance`** - Расстояние маршрута в км
|
||||
- **`estimatedTime`** - Время доставки в часах
|
||||
- **`logisticsPartnerId`** - ID логистического партнера
|
||||
|
||||
### **5. УПРАВЛЕНЧЕСКИЕ ПАРАМЕТРЫ:**
|
||||
- **`responsibleEmployee`** - Ответственный сотрудник
|
||||
- **`notes`** - Комментарии и дополнительная информация
|
||||
- **`createdAt`** - Дата создания поставки
|
||||
- **`updatedAt`** - Дата последнего обновления
|
||||
- **`fulfillmentCenterId`** - ID фулфилмент центра
|
||||
- **`consumableType`** - Тип расходников
|
||||
|
||||
<!-- ОТКАТ: Расширенная классификация параметров поставки
|
||||
|
||||
### **6. ВРЕМЕННЫЕ ПАРАМЕТРЫ:**
|
||||
- **`deliveryDate`** - Плановая дата доставки
|
||||
- **`readyDate`** - Дата готовности к отгрузке
|
||||
- **`actualDeliveryDate`** - Фактическая дата доставки
|
||||
- **`createdAt`** - Время создания заявки
|
||||
- **`approvedAt`** - Время одобрения поставщиком
|
||||
- **`shippedAt`** - Время отгрузки
|
||||
|
||||
### **7. КОНТАКТНЫЕ ПАРАМЕТРЫ:**
|
||||
- **`supplierContact`** - Контактное лицо поставщика
|
||||
- **`buyerContact`** - Контактное лицо покупателя
|
||||
- **`logisticsContact`** - Контактное лицо логистики
|
||||
- **`fulfillmentContact`** - Контактное лицо фулфилмента
|
||||
|
||||
### **8. АДРЕСНЫЕ ПАРАМЕТРЫ:**
|
||||
- **`pickupAddress`** - Адрес забора груза
|
||||
- **`deliveryAddress`** - Адрес доставки
|
||||
- **`warehouseLocation`** - Местоположение склада
|
||||
- **`marketLocation`** - Адрес торговой точки
|
||||
|
||||
### **9. КАЧЕСТВЕННЫЕ ПАРАМЕТРЫ:**
|
||||
- **`qualityRequirements`** - Требования к качеству товаров
|
||||
- **`temperatureConditions`** - Температурные условия хранения/транспортировки
|
||||
- **`handlingInstructions`** - Инструкции по обращению с грузом
|
||||
- **`packagingType`** - Тип упаковки товаров
|
||||
- **`fragileGoods`** - Отметка о хрупких товарах
|
||||
|
||||
### **10. ФИНАНСОВЫЕ ПАРАМЕТРЫ:**
|
||||
- **`paymentTerms`** - Условия оплаты
|
||||
- **`paymentMethod`** - Способ оплаты
|
||||
- **`currency`** - Валюта расчетов
|
||||
- **`taxRate`** - Налоговая ставка
|
||||
- **`invoiceNumber`** - Номер счета
|
||||
- **`paymentStatus`** - Статус оплаты
|
||||
|
||||
### **11. ТЕХНИЧЕСКИЕ ПАРАМЕТРЫ:**
|
||||
- **`supplyOrderId`** - Уникальный идентификатор поставки
|
||||
- **`supplierOrderNumber`** - Внутренний номер заказа поставщика
|
||||
- **`trackingNumber`** - Трек-номер для отслеживания
|
||||
- **`barcodes`** - Штрих-коды товаров
|
||||
- **`rfidTags`** - RFID метки для автоматизации
|
||||
|
||||
### **12. АНАЛИТИЧЕСКИЕ ПАРАМЕТРЫ:**
|
||||
- **`profitMargin`** - Маржинальность поставки
|
||||
- **`supplierRating`** - Рейтинг поставщика
|
||||
- **`deliveryReliability`** - Надежность доставки
|
||||
- **`orderPriority`** - Приоритет заказа
|
||||
- **`seasonalFactor`** - Сезонный коэффициент
|
||||
|
||||
-->
|
||||
|
||||
## 🔄 **ЖИЗНЕННЫЙ ЦИКЛ ПАРАМЕТРОВ ПОСТАВКИ**
|
||||
|
||||
### **Этап 1: Создание поставки (SELLER)**
|
||||
```typescript
|
||||
// Селлер указывает базовые параметры поставки
|
||||
{
|
||||
deliveryDate: "2025-08-25",
|
||||
totalItems: 100,
|
||||
items: [...products],
|
||||
partnerId: "supplier-123",
|
||||
organizationId: "seller-456"
|
||||
}
|
||||
```
|
||||
|
||||
### **Этап 2: Одобрение поставщиком (WHOLESALE)**
|
||||
```typescript
|
||||
// Поставщик может дополнить параметры поставки
|
||||
{
|
||||
status: "SUPPLIER_APPROVED",
|
||||
packagesCount: 3, // Новый параметр
|
||||
volume: 1.2, // Новый параметр
|
||||
readyDate: "2025-08-24", // Новый параметр
|
||||
notes: "Хрупкий груз" // Новый параметр
|
||||
}
|
||||
```
|
||||
|
||||
### **Этап 3: Логистическое планирование (LOGIST)**
|
||||
```typescript
|
||||
// Логистика использует параметры для расчетов
|
||||
{
|
||||
logisticsPrice: calculateByVolume(volume, distance),
|
||||
routes: [
|
||||
{
|
||||
from: "Садовод",
|
||||
to: "ФФ Центр",
|
||||
packagesCount: 3,
|
||||
volume: 1.2
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 🛡️ **ПРАВИЛА БЕЗОПАСНОСТИ ПАРАМЕТРОВ**
|
||||
|
||||
### **Видимость по ролям:**
|
||||
|
||||
| Параметр поставки | SELLER | WHOLESALE | FULFILLMENT | LOGIST |
|
||||
|------------------|--------|-----------|-------------|---------|
|
||||
| deliveryDate | ✅ | ✅ | ✅ | ✅ |
|
||||
| totalAmount | ✅ | ❌ | ❌ | ❌ |
|
||||
| productPrice | ✅ | ✅ | ❌ | ❌ |
|
||||
| packagesCount | ✅ | ✅ | ✅ | ✅ |
|
||||
| volume | ✅ | ✅ | ✅ | ✅ |
|
||||
| recipe | ✅ | ❌ | ✅ | ❌ |
|
||||
| logisticsPrice | ✅ | ❌ | ✅ | ✅ |
|
||||
|
||||
### **Права на изменение:**
|
||||
|
||||
- **SELLER**: Может изменять до одобрения поставщиком
|
||||
- **WHOLESALE**: Может добавлять логистические параметры при одобрении
|
||||
- **FULFILLMENT**: Не может изменять, только просматривать
|
||||
- **LOGIST**: Может добавлять маршруты и логистические расчеты
|
||||
|
||||
## 🎛️ **UI КОМПОНЕНТЫ ДЛЯ ПАРАМЕТРОВ ПОСТАВКИ**
|
||||
|
||||
### **Форма ввода параметров поставщиком:**
|
||||
|
||||
```jsx
|
||||
<div className="supply-parameters-form">
|
||||
<h3>Параметры поставки</h3>
|
||||
|
||||
{/* Основные параметры */}
|
||||
<Input name="deliveryDate" label="Дата поставки" type="date" required />
|
||||
<Input name="totalAmount" label="Общая стоимость" type="number" readOnly />
|
||||
|
||||
{/* Логистические параметры (опционально) */}
|
||||
<Input name="packagesCount" label="Количество грузовых мест" type="number" />
|
||||
<Input name="volume" label="Объём груза (м³)" type="number" step="0.01" />
|
||||
|
||||
{/* Дополнительные параметры */}
|
||||
<Input name="readyDate" label="Дата готовности" type="date" />
|
||||
<Textarea name="notes" label="Комментарии к поставке" />
|
||||
</div>
|
||||
```
|
||||
|
||||
### **Отображение в таблице заявок:**
|
||||
|
||||
```jsx
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Дата поставки</TableHead>
|
||||
<TableHead>Количество товаров</TableHead>
|
||||
<TableHead>Стоимость товаров</TableHead>
|
||||
{userRole !== 'WHOLESALE' && <TableHead>Общая стоимость</TableHead>}
|
||||
<TableHead>Параметры логистики</TableHead>
|
||||
<TableHead>Статус</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{supplies.map(supply => (
|
||||
<TableRow key={supply.id}>
|
||||
<TableCell>{supply.deliveryDate}</TableCell>
|
||||
<TableCell>{supply.totalItems}</TableCell>
|
||||
<TableCell>{formatCurrency(supply.productPrice)}</TableCell>
|
||||
{userRole !== 'WHOLESALE' && (
|
||||
<TableCell>{formatCurrency(supply.totalAmount)}</TableCell>
|
||||
)}
|
||||
<TableCell>
|
||||
{supply.packagesCount && `${supply.packagesCount} мест`}
|
||||
{supply.volume && ` • ${supply.volume} м³`}
|
||||
</TableCell>
|
||||
<TableCell><StatusBadge status={supply.status} /></TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
```
|
||||
|
||||
## 📊 **ВАЛИДАЦИЯ ПАРАМЕТРОВ ПОСТАВКИ**
|
||||
|
||||
### **Серверная валидация:**
|
||||
|
||||
```typescript
|
||||
function validateSupplyParameters(params: SupplyParameters) {
|
||||
// Обязательные параметры
|
||||
if (!params.deliveryDate) throw new Error('Дата поставки обязательна')
|
||||
if (!params.totalItems || params.totalItems <= 0) {
|
||||
throw new Error('Количество товаров должно быть больше 0')
|
||||
}
|
||||
|
||||
// Логистические параметры
|
||||
if (params.packagesCount && params.packagesCount <= 0) {
|
||||
throw new Error('Количество грузовых мест должно быть положительным')
|
||||
}
|
||||
|
||||
if (params.volume && params.volume <= 0) {
|
||||
throw new Error('Объём груза должен быть положительным')
|
||||
}
|
||||
|
||||
// Даты
|
||||
if (params.readyDate && params.deliveryDate) {
|
||||
if (new Date(params.readyDate) > new Date(params.deliveryDate)) {
|
||||
throw new Error('Дата готовности не может быть позже даты поставки')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔍 **ПОИСК И ФИЛЬТРАЦИЯ ПО ПАРАМЕТРАМ**
|
||||
|
||||
### **GraphQL запрос с фильтрами:**
|
||||
|
||||
```graphql
|
||||
query GetSuppliesByParameters(
|
||||
$deliveryDateFrom: DateTime
|
||||
$deliveryDateTo: DateTime
|
||||
$minAmount: Float
|
||||
$maxAmount: Float
|
||||
$status: SupplyStatus
|
||||
$hasLogisticsParams: Boolean
|
||||
) {
|
||||
mySupplyOrders(
|
||||
filters: {
|
||||
deliveryDate: { gte: $deliveryDateFrom, lte: $deliveryDateTo }
|
||||
totalAmount: { gte: $minAmount, lte: $maxAmount }
|
||||
status: $status
|
||||
packagesCount: { isNull: $hasLogisticsParams }
|
||||
}
|
||||
) {
|
||||
id
|
||||
deliveryDate
|
||||
totalAmount
|
||||
totalItems
|
||||
packagesCount
|
||||
volume
|
||||
status
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📈 **АНАЛИТИКА ПО ПАРАМЕТРАМ ПОСТАВКИ**
|
||||
|
||||
### **Ключевые метрики:**
|
||||
- Средний объём поставки (в м³)
|
||||
- Среднее количество грузовых мест
|
||||
- Распределение по стоимости поставок
|
||||
- Время цикла от создания до доставки
|
||||
- Процент поставок с дополнительными параметрами
|
||||
|
||||
---
|
||||
|
||||
*Все параметры поставки служат для оптимизации логистических процессов и обеспечения прозрачности цепочки поставок в экосистеме SFERA.*
|
@ -191,9 +191,9 @@ model SupplyOrder {
|
||||
totalAmount Decimal @db.Decimal(12, 2) // Общая сумма
|
||||
totalItems Int // Количество позиций
|
||||
|
||||
// Логистические данные
|
||||
packagesCount Int? // Грузовые места
|
||||
volume Float? // Объём в м³
|
||||
// Параметры поставки (дополнительные)
|
||||
packagesCount Int? // Количество грузовых мест - параметр поставки
|
||||
volume Float? // Объём груза в м³ - параметр поставки
|
||||
|
||||
// Управление
|
||||
responsibleEmployee String? // ID ответственного
|
||||
|
333
docs/development/MODULAR_ARCHITECTURE_PATTERN.md
Normal file
333
docs/development/MODULAR_ARCHITECTURE_PATTERN.md
Normal file
@ -0,0 +1,333 @@
|
||||
# 🏗️ Паттерн модульной архитектуры для React компонентов
|
||||
|
||||
> ⚠️ **ОФИЦИАЛЬНЫЙ СТАНДАРТ АРХИТЕКТУРЫ SFERA**
|
||||
> Этот документ описывает **ОБЯЗАТЕЛЬНУЮ** архитектуру для всех новых компонентов >500 строк и рефакторинга существующих >800 строк.
|
||||
|
||||
## 🎯 СТАТУС АРХИТЕКТУРНОГО СТАНДАРТА
|
||||
|
||||
### 🟢 ПРИНЯТЫЕ СТАНДАРТЫ (готовы к использованию):
|
||||
|
||||
- ✅ **create-suppliers-supply-page.tsx** → Модульная архитектура (ФАЗА 1-4 завершены)
|
||||
- ✅ **direct-supply-creation.tsx** → Модульная архитектура (ЭТАПЫ 1-5 завершены)
|
||||
|
||||
### 📋 ПРАВИЛА ПРИМЕНЕНИЯ:
|
||||
|
||||
1. **ВСЕ НОВЫЕ КОМПОНЕНТЫ >500 строк** → создавать по модульной архитектуре
|
||||
2. **Существующие компоненты >800 строк** → рефакторить по возможности
|
||||
3. **Обязательно использовать** этот паттерн для компонентов dashboard, creation, management
|
||||
|
||||
## 🎯 Применимость паттерна
|
||||
|
||||
### Кандидаты для рефакторинга:
|
||||
|
||||
- **Размер**: >800 строк кода
|
||||
- **Сложность**: Множественные состояния и бизнес-логика
|
||||
- **Многообразие UI**: Различные секции интерфейса
|
||||
- **Частые изменения**: Активно развивающиеся компоненты
|
||||
|
||||
### Большие компоненты в SFERA (кандидаты):
|
||||
|
||||
```
|
||||
3052 строки - timesheet-demo.tsx
|
||||
2012 строк - fulfillment-warehouse-dashboard.tsx
|
||||
1654 строки - navigation-demo.tsx
|
||||
1637 строк - direct-supply-creation.tsx ✅ ЗАВЕРШЕН (модульная архитектура)
|
||||
1563 строки - user-settings.tsx
|
||||
1523 строки - advertising-tab.tsx
|
||||
1304 строки - wb-product-cards.tsx
|
||||
```
|
||||
|
||||
## 📁 Универсальная структура модуля
|
||||
|
||||
```
|
||||
src/components/[domain]/[component-name]/
|
||||
├── index.tsx # Главный компонент-оркестратор
|
||||
├── blocks/ # UI блок-компоненты
|
||||
│ ├── [Feature]Block.tsx # Функциональные блоки
|
||||
│ ├── [Section]Block.tsx # Секции интерфейса
|
||||
│ └── [Action]Block.tsx # Блоки действий
|
||||
├── hooks/ # Бизнес-логика
|
||||
│ ├── use[Domain][Action].ts # Специфичная логика
|
||||
│ ├── use[Entity]Management.ts # CRUD операции
|
||||
│ └── use[Feature]State.ts # Управление состоянием
|
||||
├── types/ # TypeScript типы
|
||||
│ └── index.ts # Все интерфейсы модуля
|
||||
└── constants/ # Константы (опционально)
|
||||
└── index.ts # Конфигурация и моки
|
||||
```
|
||||
|
||||
## 🔄 Процесс рефакторинга
|
||||
|
||||
### ЭТАП 1: Анализ и планирование
|
||||
|
||||
1. **Выделить основные секции UI**
|
||||
- Определить логические блоки интерфейса
|
||||
- Найти повторяющиеся паттерны
|
||||
|
||||
2. **Проанализировать состояния**
|
||||
- Сгруппировать связанные useState
|
||||
- Выделить логику управления состоянием
|
||||
|
||||
3. **Найти бизнес-логику**
|
||||
- useEffect с API вызовами
|
||||
- Обработчики форм и событий
|
||||
- Вычисляемые значения
|
||||
|
||||
### ЭТАП 2: Создание типов
|
||||
|
||||
```typescript
|
||||
// types/index.ts
|
||||
export interface [Entity] {
|
||||
id: string
|
||||
// ... поля сущности
|
||||
}
|
||||
|
||||
export interface [Component]Props {
|
||||
// ... props компонента
|
||||
}
|
||||
|
||||
export interface [Block]Props {
|
||||
// ... props блока
|
||||
}
|
||||
```
|
||||
|
||||
### ЭТАП 3: Извлечение hooks
|
||||
|
||||
```typescript
|
||||
// hooks/use[Feature].ts
|
||||
export function use[Feature]() {
|
||||
const [state, setState] = useState()
|
||||
|
||||
const handleAction = useCallback(() => {
|
||||
// бизнес-логика
|
||||
}, [dependencies])
|
||||
|
||||
return {
|
||||
state,
|
||||
handleAction,
|
||||
// ... другие возвращаемые значения
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ЭТАП 4: Создание блок-компонентов
|
||||
|
||||
```typescript
|
||||
// blocks/[Feature]Block.tsx
|
||||
export const [Feature]Block = React.memo(function [Feature]Block({
|
||||
// ... props
|
||||
}: [Feature]BlockProps) {
|
||||
return (
|
||||
<div className="...">
|
||||
{/* UI блока */}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
```
|
||||
|
||||
### ЭТАП 5: Интеграция в главном компоненте
|
||||
|
||||
```typescript
|
||||
// index.tsx
|
||||
export function [Component]() {
|
||||
// Подключение hooks
|
||||
const featureA = useFeatureA()
|
||||
const featureB = useFeatureB()
|
||||
|
||||
// Обработчики с useCallback
|
||||
const handleAction = useCallback((data) => {
|
||||
// координация между features
|
||||
}, [featureA.method, featureB.method])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FeatureABlock {...featureA} onAction={handleAction} />
|
||||
<FeatureBBlock {...featureB} onAction={handleAction} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## ⚡ Оптимизация производительности
|
||||
|
||||
### Мемоизация компонентов
|
||||
|
||||
```typescript
|
||||
// Все блоки обернуть в React.memo
|
||||
export const MyBlock = React.memo(function MyBlock(props) {
|
||||
// ...
|
||||
})
|
||||
|
||||
// Главный компонент: useCallback для обработчиков
|
||||
const handleEvent = useCallback(
|
||||
(data) => {
|
||||
// логика
|
||||
},
|
||||
[dependency1, dependency2],
|
||||
)
|
||||
```
|
||||
|
||||
### Управление ререндерами
|
||||
|
||||
```typescript
|
||||
// В hooks: useMemo для тяжелых вычислений
|
||||
const expensiveValue = useMemo(() => {
|
||||
return heavyCalculation(data)
|
||||
}, [data])
|
||||
|
||||
// Оптимизация зависимостей useCallback
|
||||
const optimizedHandler = useCallback(
|
||||
(item) => {
|
||||
// вместо передачи всего массива
|
||||
// передавать только нужные методы
|
||||
},
|
||||
[addItem, removeItem],
|
||||
) // не [items, addItem, removeItem]
|
||||
```
|
||||
|
||||
## 🧪 Тестирование модульной архитектуры
|
||||
|
||||
### Unit тесты для hooks
|
||||
|
||||
```typescript
|
||||
import { renderHook, act } from '@testing-library/react'
|
||||
import { useFeature } from '../hooks/useFeature'
|
||||
|
||||
describe('useFeature', () => {
|
||||
it('should handle action correctly', () => {
|
||||
const { result } = renderHook(() => useFeature())
|
||||
|
||||
act(() => {
|
||||
result.current.handleAction('test')
|
||||
})
|
||||
|
||||
expect(result.current.state).toEqual(expectedState)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Component тесты для блоков
|
||||
|
||||
```typescript
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { FeatureBlock } from '../blocks/FeatureBlock'
|
||||
|
||||
describe('FeatureBlock', () => {
|
||||
it('should render with props', () => {
|
||||
render(<FeatureBlock data={mockData} onAction={mockHandler} />)
|
||||
expect(screen.getByText('Expected Text')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## 📊 Метрики успеха рефакторинга
|
||||
|
||||
### Количественные метрики
|
||||
|
||||
- **Размер главного файла**: ↓ на 70-85%
|
||||
- **Количество модулей**: ↑ в 5-10 раз
|
||||
- **Время компиляции**: ↓ на 90%+
|
||||
- **Переиспользуемые компоненты**: ↑ с 0 до N
|
||||
|
||||
### Качественные улучшения
|
||||
|
||||
- ✅ Читаемость и понимание кода
|
||||
- ✅ Простота добавления новых фич
|
||||
- ✅ Изолированное тестирование
|
||||
- ✅ Переиспользование в других местах
|
||||
- ✅ Параллельная разработка команды
|
||||
|
||||
## 🚨 Частые ошибки и как их избежать
|
||||
|
||||
### ❌ Чрезмерное дробление
|
||||
|
||||
```typescript
|
||||
// ПЛОХО: слишком много мелких блоков
|
||||
<HeaderBlock />
|
||||
<SubHeaderBlock />
|
||||
<TitleBlock />
|
||||
<ButtonBlock />
|
||||
|
||||
// ХОРОШО: логичные функциональные блоки
|
||||
<HeaderSection />
|
||||
<ActionsSection />
|
||||
```
|
||||
|
||||
### ❌ Плохие зависимости useCallback
|
||||
|
||||
```typescript
|
||||
// ПЛОХО: передача всего объекта
|
||||
const handler = useCallback(() => {
|
||||
doSomething(fullObject)
|
||||
}, [fullObject]) // объект пересоздается каждый рендер
|
||||
|
||||
// ХОРОШО: передача только нужных значений
|
||||
const handler = useCallback(() => {
|
||||
doSomething(fullObject.id, fullObject.name)
|
||||
}, [fullObject.id, fullObject.name])
|
||||
```
|
||||
|
||||
### ❌ Неправильное разделение состояния
|
||||
|
||||
```typescript
|
||||
// ПЛОХО: состояние остается в главном компоненте
|
||||
function MainComponent() {
|
||||
const [complexState, setComplexState] = useState() // управляется извне
|
||||
return <FeatureBlock state={complexState} setState={setComplexState} />
|
||||
}
|
||||
|
||||
// ХОРОШО: состояние инкапсулировано в hook
|
||||
function MainComponent() {
|
||||
const featureData = useFeature() // управляется внутри hook
|
||||
return <FeatureBlock {...featureData} />
|
||||
}
|
||||
```
|
||||
|
||||
## 📋 Чек-лист рефакторинга
|
||||
|
||||
### Перед началом
|
||||
|
||||
- [ ] Компонент больше 800 строк
|
||||
- [ ] Есть несколько логических секций UI
|
||||
- [ ] Множественные useState и useEffect
|
||||
- [ ] Активно развивающийся функционал
|
||||
|
||||
### Планирование
|
||||
|
||||
- [ ] Определены основные UI блоки (3-6 штук)
|
||||
- [ ] Выделена бизнес-логика для hooks (2-5 штук)
|
||||
- [ ] Созданы TypeScript интерфейсы
|
||||
- [ ] План поэтапного рефакторинга готов
|
||||
|
||||
### Реализация
|
||||
|
||||
- [ ] Создана структура папок
|
||||
- [ ] Extracted типы в types/index.ts
|
||||
- [ ] Hooks реализованы и протестированы
|
||||
- [ ] Блоки созданы с React.memo
|
||||
- [ ] Главный компонент интегрирует все части
|
||||
- [ ] Старый файл удален
|
||||
|
||||
### Оптимизация
|
||||
|
||||
- [ ] Все обработчики используют useCallback
|
||||
- [ ] Зависимости useCallback оптимизированы
|
||||
- [ ] Тяжелые вычисления в useMemo
|
||||
- [ ] Компонент работает без ошибок
|
||||
|
||||
### Документация
|
||||
|
||||
- [ ] README для модуля создан
|
||||
- [ ] Примеры использования hooks
|
||||
- [ ] Документация props для блоков
|
||||
- [ ] Архитектурная диаграмма
|
||||
|
||||
## 🎯 Заключение
|
||||
|
||||
Модульная архитектура значительно улучшает качество кода, скорость разработки и поддержки. Применяйте этот паттерн к большим компонентам постепенно, следуя принципам безопасного рефакторинга.
|
||||
|
||||
---
|
||||
|
||||
**Основано на**: Успешном рефакторинге create-suppliers-supply-page.tsx (1,467→240 строк)
|
||||
**Автор паттерна**: Claude Code
|
||||
**Дата**: Август 2025
|
290
docs/organization-types/LOGIST_STATISTICS_RULES.md
Normal file
290
docs/organization-types/LOGIST_STATISTICS_RULES.md
Normal file
@ -0,0 +1,290 @@
|
||||
# ПРАВИЛА ЛОГИСТИКИ, СТАТИСТИКИ И СКЛАДСКИХ СИСТЕМ
|
||||
|
||||
## 📊 АНАЛИТИЧЕСКИЕ ВЫВОДЫ ИЗ КОДА
|
||||
|
||||
### 🚛 1. ЛОГИСТИЧЕСКИЕ МОДУЛИ
|
||||
|
||||
#### 1.1 Логистическая Система Перевозок (LogisticsDashboard)
|
||||
**Файл:** `src/components/logistics/logistics-dashboard.tsx`
|
||||
|
||||
**ОБНАРУЖЕННЫЕ ПРАВИЛА:**
|
||||
- **Статусы маршрутов:** `planned`, `in_transit`, `delivered`, `cancelled`
|
||||
- **Структура маршрута:** точка отправления → точка назначения
|
||||
- **Обязательные поля:** номер маршрута, адреса, груз, цена, расстояние, время
|
||||
- **Цветовая кодировка статусов:**
|
||||
- Запланировано: синий (`text-blue-300 border-blue-400/30`)
|
||||
- В пути: желтый (`text-yellow-300 border-yellow-400/30`)
|
||||
- Доставлено: зеленый (`text-green-300 border-green-400/30`)
|
||||
- Отменено: красный (`text-red-300 border-red-400/30`)
|
||||
|
||||
**КЛЮЧЕВЫЕ ТОЧКИ ДОСТАВКИ:**
|
||||
- Садовод (14-й км МКАД)
|
||||
- SFERAV Logistics (Складская, 15)
|
||||
- Коледино WB (Подольск)
|
||||
- Тверь Ozon (Складская, 88)
|
||||
|
||||
#### 1.2 Система Логистических Заказов (LogisticsOrdersDashboard)
|
||||
**Файл:** `src/components/logistics-orders/logistics-orders-dashboard.tsx`
|
||||
|
||||
**WORKFLOW ЛОГИСТИКИ:**
|
||||
```
|
||||
SUPPLIER_APPROVED → LOGISTICS_CONFIRMED → SHIPPED → DELIVERED
|
||||
↓ ↓ ↓ ↓
|
||||
Требует Подтверждено В пути Доставлено
|
||||
подтверждения логистом
|
||||
```
|
||||
|
||||
**ДЕЙСТВИЯ ЛОГИСТА:**
|
||||
- Подтверждение заказа (`LOGISTICS_CONFIRM_ORDER`)
|
||||
- Отклонение заказа с причиной (`LOGISTICS_REJECT_ORDER`)
|
||||
- Статистика по статусам
|
||||
|
||||
**ПРАВА ЛОГИСТА:**
|
||||
- Подтверждать заказы поставщиков
|
||||
- Отклонять заказы с указанием причины
|
||||
- Просматривать детали маршрута и товаров
|
||||
|
||||
### 📈 2. СИСТЕМА СТАТИСТИКИ И АНАЛИТИКИ
|
||||
|
||||
#### 2.1 Статистика Селлера (SellerStatisticsDashboard)
|
||||
**Файл:** `src/components/seller-statistics/seller-statistics-dashboard.tsx`
|
||||
|
||||
**АРХИТЕКТУРА КЭШИРОВАНИЯ:**
|
||||
- **Локальный кэш:** Map для salesCache и advertisingCache
|
||||
- **Database кэш:** через GraphQL мутации `SAVE_SELLER_STATS_CACHE`
|
||||
- **Время жизни кэша:** 24 часа
|
||||
- **Ключи кэша:** период + даты для custom диапазонов
|
||||
|
||||
**ВКЛАДКИ СТАТИСТИКИ:**
|
||||
1. **Продажи** (SalesTab) - данные о продажах товаров
|
||||
2. **Реклама** (AdvertisingTab) - рекламная статистика
|
||||
3. **Иное** - зарезервировано для будущих функций
|
||||
|
||||
**ПЕРИОДЫ АНАЛИЗА:**
|
||||
- Неделя (`week`)
|
||||
- Месяц
|
||||
- Квартал
|
||||
- Пользовательский диапазон (`custom`)
|
||||
|
||||
#### 2.2 Статистика Фулфилмента (FulfillmentStatisticsDashboard)
|
||||
**Файл:** `src/components/fulfillment-statistics/fulfillment-statistics-dashboard.tsx`
|
||||
|
||||
**БЛОКИ СТАТИСТИКИ:**
|
||||
1. **Накопленная статистика:**
|
||||
- Обработано товаров
|
||||
- Выявлено брака
|
||||
- Поставок получено
|
||||
- Общий доход
|
||||
|
||||
2. **Отгрузка на площадки:**
|
||||
- Wildberries (фиолетовый)
|
||||
- Ozon (синий)
|
||||
- Другие маркетплейсы (зеленый)
|
||||
|
||||
3. **Аналитика производительности:**
|
||||
- Среднее время обработки
|
||||
- Уровень брака
|
||||
- Уровень возвратов
|
||||
- Рейтинг качества
|
||||
|
||||
4. **AI-аналитика и прогнозы:**
|
||||
- Прогноз роста (+23% в следующем квартале)
|
||||
- Оптимизация процессов (-18% времени при автоматизации)
|
||||
- Сезонные тренды (+45% в ноябре-декабре)
|
||||
|
||||
**УПРАВЛЕНИЕ БЛОКАМИ:**
|
||||
- Все блоки сворачиваемые/разворачиваемые
|
||||
- Состояние сохраняется в `expandedSections`
|
||||
|
||||
#### 2.3 Экономическая Система (Economics Modules)
|
||||
**Файлы:** `src/components/economics/*.tsx`
|
||||
|
||||
**СПЕЦИАЛИЗАЦИЯ ПО ТИПАМ ОРГАНИЗАЦИЙ:**
|
||||
- `fulfillment-economics-page.tsx` - экономика фулфилмента
|
||||
- `logist-economics-page.tsx` - экономика логистики
|
||||
- `seller-economics-page.tsx` - экономика селлера
|
||||
- `wholesale-economics-page.tsx` - экономика оптовых поставщиков
|
||||
- `economics-page-wrapper.tsx` - роутер по типу организации
|
||||
|
||||
### 🏬 3. СКЛАДСКИЕ СИСТЕМЫ
|
||||
|
||||
#### 3.1 Wildberries Warehouse (WBWarehouseDashboard)
|
||||
**Файл:** `src/components/wb-warehouse/wb-warehouse-dashboard.tsx`
|
||||
|
||||
**ИНТЕГРАЦИЯ С WB API:**
|
||||
- **Аутентификация:** через API ключи в `organization.apiKeys`
|
||||
- **Валидация ключей:** проверка `marketplace === 'WILDBERRIES'` и `isActive`
|
||||
- **Токен доступа:** из `validationData.token|apiKey|key`
|
||||
|
||||
**АЛГОРИТМ ЗАГРУЗКИ ДАННЫХ:**
|
||||
1. Получение карточек товаров (`WildberriesService.getAllCards`)
|
||||
2. Извлечение nmIds из карточек
|
||||
3. Получение аналитики для каждого nmId (`getStocksReportByOffices`)
|
||||
4. Комбинирование данных через `combineCardsWithIndividualAnalytics`
|
||||
5. Кэширование результата через `SAVE_WB_WAREHOUSE_CACHE`
|
||||
|
||||
**СТРУКТУРА ДАННЫХ СКЛАДА:**
|
||||
```typescript
|
||||
interface WBStock {
|
||||
nmId: number
|
||||
vendorCode: string
|
||||
title: string
|
||||
brand: string
|
||||
price: number
|
||||
stocks: Array<{
|
||||
warehouseId: number
|
||||
warehouseName: string
|
||||
quantity: number
|
||||
quantityFull: number
|
||||
inWayToClient: number
|
||||
inWayFromClient: number
|
||||
}>
|
||||
totalQuantity: number
|
||||
totalReserved: number
|
||||
// ... media, characteristics, etc
|
||||
}
|
||||
```
|
||||
|
||||
**СТАТИСТИКА СКЛАДА:**
|
||||
- Всего товаров
|
||||
- Общий остаток
|
||||
- Зарезервировано
|
||||
- Возвраты от клиентов
|
||||
- Активные склады
|
||||
|
||||
#### 3.2 Общий Склад (WarehouseDashboard)
|
||||
**Файл:** `src/components/warehouse/warehouse-dashboard.tsx`
|
||||
|
||||
**ТОВАРНЫЕ ПОЗИЦИИ:**
|
||||
- **Типы:** `PRODUCT` (товар) / `CONSUMABLE` (расходник)
|
||||
- **Поля:** название, артикул, описание, цена, количество
|
||||
- **Опциональные:** setQuantity, ordered, inTransit, stock, sold
|
||||
|
||||
**ИНТЕГРАЦИЯ С РЫНКАМИ:**
|
||||
- **Поддерживаемые рынки:** `sadovod`, `tyak-moscow`
|
||||
- **Цветовая кодировка:**
|
||||
- Садовод: зеленый (`bg-green-500/20 text-green-300`)
|
||||
- ТЯК Москва: синий (`bg-blue-500/20 text-blue-300`)
|
||||
|
||||
**РЕЖИМЫ ОТОБРАЖЕНИЯ:**
|
||||
- **Карточки** (`cards`) - сетка карточек товаров
|
||||
- **Таблица** (`table`) - табличное представление
|
||||
|
||||
**СТАТУСЫ ОСТАТКОВ:**
|
||||
- 0 единиц: красный (`text-red-400`)
|
||||
- < 10 единиц: желтый (`text-yellow-400`)
|
||||
- ≥ 10 единиц: зеленый (`text-green-400`)
|
||||
|
||||
#### 3.3 Фулфилмент Склад (FulfillmentWarehouse)
|
||||
**Файлы:** `src/components/fulfillment-warehouse/*.tsx`
|
||||
|
||||
**МОДУЛЬНАЯ АРХИТЕКТУРА:**
|
||||
- **Основной:** `fulfillment-warehouse-dashboard.tsx`
|
||||
- **Компоненты:** StatCard, TableHeader, блоки (17 файлов)
|
||||
- **Специализированные:** поставки, статистика, претензии WB
|
||||
|
||||
**ФУНКЦИОНАЛЬНОСТЬ:**
|
||||
- Управление поставками
|
||||
- Статистика склада
|
||||
- Обработка возвратов WB
|
||||
- Детали доставки
|
||||
|
||||
## 🎯 ВЫЯВЛЕННЫЕ СТАНДАРТЫ И ПАТТЕРНЫ
|
||||
|
||||
### 1. АРХИТЕКТУРНЫЕ ПАТТЕРНЫ
|
||||
|
||||
#### Glass Morphism Design
|
||||
```css
|
||||
glass-card: "bg-white/10 backdrop-blur border-white/20"
|
||||
glass-secondary: "bg-white/5 backdrop-blur border-white/10"
|
||||
glass-input: прозрачные инпуты с размытием
|
||||
```
|
||||
|
||||
#### Цветовая Система Статусов
|
||||
- **Синий:** планирование, информация, подтверждение
|
||||
- **Желтый:** ожидание, предупреждения, в процессе
|
||||
- **Зеленый:** успех, доставлено, высокие показатели
|
||||
- **Красный:** ошибки, отмены, критические состояния
|
||||
- **Фиолетовый:** премиум функции, аналитика, WB
|
||||
|
||||
#### Система Кэширования
|
||||
```javascript
|
||||
// Паттерн многоуровневого кэша:
|
||||
1. Local State (Map/useState)
|
||||
2. GraphQL Cache (Apollo)
|
||||
3. Database Cache (через мутации)
|
||||
4. External API (последний ресурс)
|
||||
```
|
||||
|
||||
### 2. БИЗНЕС-ПРАВИЛА
|
||||
|
||||
#### Workflow Логистики
|
||||
```
|
||||
Поставщик → Логист → Фулфилмент → Маркетплейс → Клиент
|
||||
↓ ↓ ↓ ↓ ↓
|
||||
Заказ → Подтверждение → Отгрузка → Доставка → Возврат
|
||||
```
|
||||
|
||||
#### Роли в Логистике
|
||||
- **Поставщик:** создает заказ поставки
|
||||
- **Логист:** подтверждает/отклоняет, организует доставку
|
||||
- **Фулфилмент:** принимает груз, обрабатывает товары
|
||||
- **Система:** автоматически отслеживает статусы
|
||||
|
||||
#### Экономические Правила
|
||||
- Каждый тип организации имеет свой экономический модуль
|
||||
- Данные кэшируются на 24 часа
|
||||
- Поддерживаются пользовательские временные диапазоны
|
||||
- AI-аналитика предоставляет прогнозы и рекомендации
|
||||
|
||||
### 3. ИНТЕГРАЦИОННЫЕ ПРАВИЛА
|
||||
|
||||
#### Маркетплейсы
|
||||
- **Wildberries:** полная интеграция через API, поддержка складов, аналитика
|
||||
- **Ozon:** поддержка в workflow, данные статистики
|
||||
- **Другие:** Яндекс.Маркет, Авито (ограниченная поддержка)
|
||||
|
||||
#### Склады и Рынки
|
||||
- **Садовод:** зеленая палитра, первичные поставщики
|
||||
- **ТЯК Москва:** синяя палитра, альтернативные поставщики
|
||||
- **WB Склады:** автоматическое определение из API данных
|
||||
|
||||
## 🚀 ТЕХНИЧЕСКИЕ ТРЕБОВАНИЯ
|
||||
|
||||
### Обязательные Хуки
|
||||
- `useSidebar()` - управление боковой панелью
|
||||
- `useAuth()` - аутентификация и права доступа
|
||||
- Для WB: проверка `hasWBApiKey` перед загрузкой
|
||||
|
||||
### GraphQL Операции
|
||||
**Логистика:**
|
||||
- `GET_SUPPLY_ORDERS` - получение заказов
|
||||
- `LOGISTICS_CONFIRM_ORDER` - подтверждение логистом
|
||||
- `LOGISTICS_REJECT_ORDER` - отклонение с причиной
|
||||
|
||||
**Статистика:**
|
||||
- `GET_SELLER_STATS_CACHE` - кэш статистики селлера
|
||||
- `SAVE_SELLER_STATS_CACHE` - сохранение кэша
|
||||
- `GET_WB_WAREHOUSE_DATA` - данные склада WB
|
||||
|
||||
**Склады:**
|
||||
- `GET_MY_PRODUCTS` - товары пользователя
|
||||
- `SAVE_WB_WAREHOUSE_CACHE` - кэш WB склада
|
||||
|
||||
### Внешние Сервисы
|
||||
- **WildberriesService:** интеграция с API WB
|
||||
- **Токены:** хранение в `organization.apiKeys`
|
||||
- **Rate Limiting:** 1 секунда между запросами для WB API
|
||||
|
||||
## 📋 ВЫВОДЫ И РЕКОМЕНДАЦИИ
|
||||
|
||||
1. **Логистическая система** полноценно реализована с workflow и статусами
|
||||
2. **Статистические модули** используют сложное многоуровневое кэширование
|
||||
3. **Складские системы** имеют разную степень интеграции (WB - полная, остальные - базовая)
|
||||
4. **Экономические модули** специализированы по типам организаций
|
||||
5. **Дизайн-система** консистентна во всех модулях
|
||||
|
||||
**СЛЕДУЮЩИЕ ШАГИ:**
|
||||
- Документировать API эндпоинты
|
||||
- Описать административную систему
|
||||
- Создать руководства по интеграции
|
@ -902,11 +902,11 @@ function getMarketLabel(market: string): string {
|
||||
}
|
||||
```
|
||||
|
||||
#### **2. ОПЦИОНАЛЬНЫЕ ПОЛЯ УПАКОВКИ ПРИ ОДОБРЕНИИ:**
|
||||
#### **2. ОПЦИОНАЛЬНЫЕ ПАРАМЕТРЫ ПОСТАВКИ ПРИ ОДОБРЕНИИ:**
|
||||
|
||||
```jsx
|
||||
{
|
||||
/* ОПЦИОНАЛЬНЫЕ поля для поставщика - отображаются сразу при одобрении заказа */
|
||||
/* ОПЦИОНАЛЬНЫЕ параметры поставки для поставщика - отображаются при одобрении заказа */
|
||||
}
|
||||
;<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
@ -918,7 +918,7 @@ function getMarketLabel(market: string): string {
|
||||
aria-describedby="packages-help"
|
||||
/>
|
||||
<p id="packages-help" className="text-xs text-white/60 mt-1">
|
||||
Используется логистикой для расчета тарифов
|
||||
Параметр поставки для логистических расчетов
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -926,7 +926,27 @@ function getMarketLabel(market: string): string {
|
||||
<Label htmlFor="volume">Объем груза (м³)</Label>
|
||||
<Input id="volume" type="number" step="0.01" placeholder="0.00 (опционально)" aria-describedby="volume-help" />
|
||||
<p id="volume-help" className="text-xs text-white/60 mt-1">
|
||||
Помогает логистике в планировании маршрутов
|
||||
Параметр поставки для планирования маршрутов
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="deliveryDate">Дата поставки</Label>
|
||||
<GlassDatePicker
|
||||
id="deliveryDate"
|
||||
placeholder="Выберите дату поставки"
|
||||
aria-describedby="delivery-help"
|
||||
/>
|
||||
<p id="delivery-help" className="text-xs text-white/60 mt-1">
|
||||
Основной параметр поставки - когда товары должны быть доставлены
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label htmlFor="totalAmount">Общая стоимость товаров</Label>
|
||||
<Input id="totalAmount" type="number" readOnly className="bg-white/5" />
|
||||
<p className="text-xs text-white/60 mt-1">
|
||||
Ключевой параметр поставки - автоматически рассчитывается
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
Reference in New Issue
Block a user