# СИСТЕМА УПРАВЛЕНИЯ СКЛАДАМИ SFERA ## 🎯 ОБЗОР СИСТЕМЫ Система управления складами SFERA обеспечивает полный цикл складских операций для различных типов хранилищ: Wildberries склады, общие склады организаций и фулфилмент-центры. Включает интеграцию с внешними API, управление товарами и расходниками, статистику и аналитику. ## 🏗️ АРХИТЕКТУРА СКЛАДСКОЙ СИСТЕМЫ ### Основные компоненты: - **WBWarehouseDashboard** - интеграция со складами Wildberries - **WarehouseDashboard** - общее управление складом организации - **FulfillmentWarehouse** - специализированные складские операции фулфилмента - **Интеграция с маркетплейсами** - синхронизация данных - **Система кэширования** - оптимизация работы с внешними API ## 📦 1. WILDBERRIES СКЛАД (WBWarehouseDashboard) ### 1.1 Архитектура компонента **Основано на коде:** `src/components/wb-warehouse/wb-warehouse-dashboard.tsx` ```typescript export function WBWarehouseDashboard() { // Состояние данных WB Warehouse const [stocks, setStocks] = useState([]) const [warehouses, setWarehouses] = useState([]) const [loading, setLoading] = useState(false) const [initialized, setInitialized] = useState(false) // Статистика const [totalProducts, setTotalProducts] = useState(0) const [totalStocks, setTotalStocks] = useState(0) const [totalReserved, setTotalReserved] = useState(0) const [totalFromClient, setTotalFromClient] = useState(0) const [activeWarehouses, setActiveWarehouses] = useState(0) // Analytics data const [analyticsData, setAnalyticsData] = useState([]) } ``` ### 1.2 Структура данных WB склада #### 1.2.1 Товарная позиция (WBStock) ```typescript interface WBStock { nmId: number // Номенклатурный номер WB 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 // Зарезервировано photos: any[] // Фотографии товара mediaFiles: any[] // Медиафайлы characteristics: any[] // Характеристики subjectName: string // Категория товара description: string // Описание } ``` #### 1.2.2 Склад Wildberries (WBWarehouse) ```typescript interface WBWarehouse { id: number // ID склада name: string // Название склада cargoType: number // Тип груза deliveryType: number // Тип доставки } ``` ### 1.3 Система аутентификации WB API **Проверка API ключей:** ```typescript // Проверка настройки API ключа const hasWBApiKey = user?.organization?.apiKeys?.find((key) => key.marketplace === 'WILDBERRIES')?.isActive // Извлечение токена доступа const wbApiKey = user?.organization?.apiKeys?.find((key) => key.marketplace === 'WILDBERRIES') const validationData = wbApiKey.validationData as Record const apiToken = validationData?.token || validationData?.apiKey || validationData?.key || (wbApiKey as { apiKey?: string }).apiKey ``` ### 1.4 Алгоритм загрузки данных из WB API **5-этапный процесс:** #### Этап 1: Получение карточек товаров ```typescript // 1. Получаем карточки товаров const cards = await WildberriesService.getAllCards(apiToken).catch(() => []) console.warn('WB Warehouse: Loaded cards:', cards.length) const nmIds = cards.map((card) => card.nmID).filter((id) => id > 0) console.warn('WB Warehouse: NM IDs to process:', nmIds.length) ``` #### Этап 2: Получение аналитики по товарам ```typescript // 2. Получаем аналитику для каждого товара индивидуально const analyticsResults = [] for (const nmId of nmIds) { try { const result = await wbService.getStocksReportByOffices({ nmIds: [nmId], stockType: '', }) analyticsResults.push({ nmId, data: result }) await new Promise((resolve) => setTimeout(resolve, 1000)) // Rate limiting } catch (error) { console.error(`WB Warehouse: Error fetching analytics for nmId ${nmId}:`, error) } } ``` #### Этап 3: Комбинирование данных ```typescript // 3. Комбинируем данные const combinedStocks = combineCardsWithIndividualAnalytics(cards, analyticsResults) // Функция комбинирования const combineCardsWithIndividualAnalytics = (cards: any[], analyticsResults: any[]): WBStock[] => { const stocksMap = new Map() // Создаем карту аналитических данных const analyticsMap = new Map() analyticsResults.forEach((result) => { analyticsMap.set(result.nmId, result.data) }) cards.forEach((card) => { const stock: WBStock = { nmId: card.nmID, vendorCode: String(card.vendorCode || card.supplierVendorCode || ''), title: String(card.title || card.object || `Товар ${card.nmID}`), brand: String(card.brand || ''), // ... остальные поля } // Получаем аналитические данные для данного nmId const analytics = analyticsMap.get(card.nmID) if (analytics && analytics.data && analytics.data.regions) { analytics.data.regions.forEach((region: any) => { if (region.offices && Array.isArray(region.offices)) { region.offices.forEach((office: any) => { stock.stocks.push({ warehouseId: office.officeID || 0, warehouseName: String(office.officeName || 'Неизвестный склад'), quantity: Number(office.metrics?.stockCount) || 0, quantityFull: Number(office.metrics?.stockCount) || 0, inWayToClient: Number(office.metrics?.toClientCount) || 0, inWayFromClient: Number(office.metrics?.fromClientCount) || 0, }) }) } }) } // Подсчитываем общие показатели stock.totalQuantity = stock.stocks.reduce((sum, s) => sum + s.quantity, 0) stock.totalReserved = stock.stocks.reduce((sum, s) => sum + s.inWayToClient, 0) stocksMap.set(card.nmID, stock) }) return Array.from(stocksMap.values()) } ``` #### Этап 4: Извлечение складов ```typescript // 4. Извлекаем склады и обновляем статистику const extractWarehousesFromStocks = (stocksData: WBStock[]): WBWarehouse[] => { const warehousesMap = new Map() stocksData.forEach((item) => { item.stocks.forEach((stock) => { if (!warehousesMap.has(stock.warehouseId)) { warehousesMap.set(stock.warehouseId, { id: stock.warehouseId, name: stock.warehouseName, cargoType: 0, deliveryType: 0, }) } }) }) return Array.from(warehousesMap.values()) } ``` #### Этап 5: Кэширование результата ```typescript // 5. Сохраняем в кеш await saveCache({ variables: { input: { data: JSON.stringify({ stocks: combinedStocks, warehouses: extractedWarehouses, analyticsData: analyticsData, }), totalProducts: stats.totalProducts, totalStocks: stats.totalStocks, totalReserved: stats.totalReserved, }, }, }) ``` ### 1.5 Система кэширования WB данных **Двухуровневая система:** #### GraphQL Cache ```typescript const { data: _cacheData, loading: cacheLoading, refetch: refetchCache, } = useQuery(GET_WB_WAREHOUSE_DATA, { skip: !hasWBApiKey, fetchPolicy: 'cache-and-network', }) const [saveCache] = useMutation(SAVE_WB_WAREHOUSE_CACHE) ``` #### Логика работы с кэшем ```typescript const loadWarehouseData = async () => { // Сначала проверяем кэш try { const result = await refetchCache() const cacheResponse = result.data?.getWBWarehouseData if (cacheResponse?.success && cacheResponse?.fromCache && cacheResponse?.cache) { // Данные найдены в кэше loadWarehouseDataFromCache(cacheResponse.cache) } else { // Кеша нет или он устарел, загружаем из API await loadWarehouseDataFromAPI() } } catch (error) { console.error('WB Warehouse: Error checking cache:', error) await loadWarehouseDataFromAPI() } } ``` ### 1.6 Статистика WB склада **Автоматически рассчитываемые метрики:** ```typescript const updateStatistics = (stocksData: WBStock[], _warehousesData: WBWarehouse[]) => { // Общее количество товаров setTotalProducts(stocksData.length) // Общий остаток const totalStocksCount = stocksData.reduce((sum, item) => sum + item.totalQuantity, 0) setTotalStocks(totalStocksCount) // Зарезервировано const totalReservedCount = stocksData.reduce((sum, item) => sum + item.totalReserved, 0) setTotalReserved(totalReservedCount) // Возвраты от клиентов const totalFromClientCount = stocksData.reduce( (sum, item) => sum + item.stocks.reduce((stockSum, stock) => stockSum + stock.inWayFromClient, 0), 0, ) setTotalFromClient(totalFromClientCount) // Активные склады const warehousesWithStock = new Set(stocksData.flatMap((item) => item.stocks.map((s) => s.warehouseId))) setActiveWarehouses(warehousesWithStock.size) } ``` ### 1.7 Структура WB дашборда **3 основные вкладки:** ```typescript Склад фулфилмент Склад Wildberries Мой склад ``` ## 🏪 2. ОБЩИЙ СКЛАД ОРГАНИЗАЦИИ (WarehouseDashboard) ### 2.1 Архитектура компонента **Основано на коде:** `src/components/warehouse/warehouse-dashboard.tsx` ```typescript export function WarehouseDashboard() { const [isDialogOpen, setIsDialogOpen] = useState(false) const [editingProduct, setEditingProduct] = useState(null) const [searchQuery, setSearchQuery] = useState('') const [viewMode, setViewMode] = useState<'cards' | 'table'>('cards') const { data, loading, error, refetch } = useQuery(GET_MY_PRODUCTS, { errorPolicy: 'all', }) } ``` ### 2.2 Структура товарной позиции **Интерфейс Product:** ```typescript interface Product { id: string name: string // Название товара article: string // Артикул description: string // Описание price: number // Цена pricePerSet?: number // Цена за комплект quantity: number // Количество setQuantity?: number // Количество в комплекте ordered?: number // Заказано inTransit?: number // В пути stock?: number // На складе sold?: number // Продано type: 'PRODUCT' | 'CONSUMABLE' // Тип: товар или расходник category: { id: string; name: string } | null brand: string // Бренд color: string // Цвет size: string // Размер weight: number // Вес dimensions: string // Размеры material: string // Материал images: string[] // Изображения mainImage: string // Главное изображение isActive: boolean // Активность createdAt: string // Дата создания updatedAt: string // Дата обновления organization: { id: string; market?: string } } ``` ### 2.3 Система типов товаров **2 основных типа:** | Тип | Значение | Описание | Цвет бейджа | | ------------ | --------- | -------------------------- | ---------------------------------------------- | | `PRODUCT` | Товар | Основной товар для продажи | Синий (`bg-blue-500/20 text-blue-300`) | | `CONSUMABLE` | Расходник | Вспомогательные материалы | Оранжевый (`bg-orange-500/20 text-orange-300`) | ### 2.4 Интеграция с рынками **Поддерживаемые рынки из кода:** ```typescript const getMarketBadge = (market?: string) => { if (!market) return null const marketStyles = { 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', } const marketLabels = { sadovod: 'Садовод', 'tyak-moscow': 'ТЯК Москва', } const style = marketStyles[market as keyof typeof marketStyles] || 'bg-gray-500/20 text-gray-300 border-gray-500/30' const label = marketLabels[market as keyof typeof marketLabels] || market return ( {label} ) } ``` **Цветовая кодировка рынков:** - **Садовод** (`sadovod`): Зеленый - **ТЯК Москва** (`tyak-moscow`): Синий - **Неизвестный рынок**: Серый ### 2.5 Система остатков товаров **Цветовая индикация количества:** ```typescript {product.stock || product.quantity || 0} ``` ### 2.6 Режимы отображения товаров **2 режима просмотра:** #### Режим карточек (`cards`) ```typescript
{filteredProducts.map((product) => ( ))}
``` #### Режим таблицы (`table`) ```typescript // 12-колоночная сетка
Фото
Название
Артикул
Тип
Рынок
Цена
Остаток
Заказано
В пути
Продано
Действия
``` ### 2.7 Функционал поиска и фильтрации **Мультипоисковая система:** ```typescript const filteredProducts = products.filter((product) => { const matchesSearch = !searchQuery || product.name.toLowerCase().includes(searchQuery.toLowerCase()) || product.article.toLowerCase().includes(searchQuery.toLowerCase()) || product.category?.name?.toLowerCase().includes(searchQuery.toLowerCase()) || product.brand?.toLowerCase().includes(searchQuery.toLowerCase()) return matchesSearch }) ``` **Поисковые поля:** - Название товара - Артикул - Категория - Бренд ### 2.8 Управление товарами **CRUD операции:** ```typescript // Создание товара const handleCreateProduct = () => { setEditingProduct(null) setIsDialogOpen(true) } // Редактирование товара const handleEditProduct = (product: Product) => { setEditingProduct(product) setIsDialogOpen(true) } // Сохранение товара const handleProductSaved = () => { setIsDialogOpen(false) setEditingProduct(null) refetch() // Обновление списка } // Удаление товара const handleProductDeleted = () => { refetch() // Обновление списка } ``` ### 2.9 Статистика общего склада **Компонент WarehouseStatistics:** ```typescript ``` **Потенциальные метрики:** - Общее количество товаров - Общая стоимость склада - Количество по типам (товары/расходники) - Статистика по рынкам - Товары с критически низкими остатками ## 🏭 3. ФУЛФИЛМЕНТ СКЛАД (FulfillmentWarehouse) ### 3.1 Модульная архитектура **Основано на файлах:** `src/components/fulfillment-warehouse/` ``` fulfillment-warehouse/ ├── fulfillment-warehouse-dashboard.tsx // Главный компонент ├── fulfillment-warehouse-dashboard/ // Модульная структура │ ├── blocks/ // Блоки функциональности │ │ ├── StatCard.tsx // Карточка статистики │ │ ├── StoreDataTableBlock.tsx // Блок таблицы данных │ │ ├── SummaryRowBlock.tsx // Блок итогов │ │ ├── TableHeadersBlock.tsx // Заголовки таблиц │ │ └── WarehouseStatsBlock.tsx // Блок статистики склада │ ├── components/ // Переиспользуемые компоненты │ │ ├── StatCard.tsx // Статистическая карточка │ │ └── TableHeader.tsx // Заголовок таблицы │ ├── hooks/ // Специализированные хуки │ ├── types/ // Типы данных │ ├── utils/ // Утилиты │ └── index.tsx // Главный экспорт ├── delivery-details.tsx // Детали доставки ├── supplies-stats.tsx // Статистика поставок ├── wb-return-claims.tsx // Претензии WB ├── supplies-list.tsx // Список поставок ├── supplies-grid.tsx // Сетка поставок ├── supply-card.tsx // Карточка поставки ├── supplies-header.tsx // Заголовок поставок └── fulfillment-supplies-page.tsx // Страница поставок фулфилмента ``` ### 3.2 Специализированные функции **17 компонентов фулфилмент склада:** #### 3.2.1 Управление поставками - **supplies-list.tsx** - список входящих поставок - **supplies-grid.tsx** - сетчатое отображение поставок - **supply-card.tsx** - карточка отдельной поставки - **supplies-header.tsx** - заголовок и фильтры - **supplies-stats.tsx** - статистика по поставкам #### 3.2.2 Статистика и аналитика - **StatCard.tsx** (2 версии) - карточки метрик - **WarehouseStatsBlock.tsx** - блок статистики склада - **SummaryRowBlock.tsx** - итоговые строки #### 3.2.3 Специальные операции - **wb-return-claims.tsx** - обработка возвратов WB - **delivery-details.tsx** - детали доставки - **StoreDataTableBlock.tsx** - управление данными магазинов #### 3.2.4 UI компоненты - **TableHeader.tsx** - заголовки таблиц - **TableHeadersBlock.tsx** - блок заголовков ### 3.3 Интеграция с основным дашбордом **Связь с WBWarehouseDashboard:** ```typescript ``` Фулфилмент склад интегрирован как одна из вкладок WB дашборда, обеспечивая единый интерфейс для всех типов складских операций. ## 🔗 4. ИНТЕГРАЦИЯ С ВНЕШНИМИ СИСТЕМАМИ ### 4.1 Wildberries Service **Класс для работы с WB API:** ```typescript import { WildberriesService } from '@/services/wildberries-service' // Инициализация сервиса const wbService = new WildberriesService(apiToken) // Основные методы - WildberriesService.getAllCards(apiToken) // Получение карточек товаров - wbService.getStocksReportByOffices({...}) // Аналитика по складам ``` **Rate Limiting:** ```typescript // Задержка между запросами для соблюдения лимитов API await new Promise((resolve) => setTimeout(resolve, 1000)) ``` ### 4.2 GraphQL интеграция **Основные запросы и мутации:** #### Запросы ```typescript // Товары организации GET_MY_PRODUCTS // Данные WB склада GET_WB_WAREHOUSE_DATA ``` #### Мутации ```typescript // Сохранение кэша WB склада SAVE_WB_WAREHOUSE_CACHE // Операции с товарами (создание, обновление, удаление) CREATE_PRODUCT UPDATE_PRODUCT DELETE_PRODUCT ``` ### 4.3 Система событий **Потенциальные события склада:** - Изменение остатков товаров - Поступление новых товаров - Отгрузка товаров - Возвраты от клиентов - Обновление данных от внешних API ## 🎨 5. UI/UX ПАТТЕРНЫ СКЛАДОВ ### 5.1 Адаптивные сетки **Responsive layouts для разных типов складов:** ```typescript // Карточки товаров (WB и общий склад)
// Таблица товаров (12-колоночная сетка)
// Статистика (4 карточки)
``` ### 5.2 Состояния загрузки **Паттерны loading states:** ```typescript // Загрузка товаров {loading ? (

Загрузка товаров...

) : ( )} // Инициализация WB склада {!initialized ? (
Инициализация склада...
) : ( )} ``` ### 5.3 Пустые состояния **Empty states для разных сценариев:** ```typescript // Нет товаров

{searchQuery ? 'Товары не найдены' : 'Склад пуст'}

{searchQuery ? 'Попробуйте изменить критерии поиска' : 'Добавьте ваш первый товар на склад'}

// Нет API ключа WB {!hasWBApiKey && (

API ключ не настроен

Настройте интеграцию с Wildberries для работы со складом

)} ``` ### 5.4 Модальные окна **Dialog системы для управления товарами:** ```typescript {editingProduct ? 'Редактировать товар/расходник' : 'Добавить товар/расходник'} setIsDialogOpen(false)} /> ``` ## ⚡ 6. ПРОИЗВОДИТЕЛЬНОСТЬ И ОПТИМИЗАЦИЯ ### 6.1 Кэширование данных **Многоуровневое кэширование WB:** 1. **React State** - локальное состояние компонента 2. **Apollo Cache** - GraphQL кэш 3. **Database Cache** - серверное кэширование 4. **Rate Limiting** - ограничение запросов к внешним API ### 6.2 Виртуализация больших списков **Потенциальные оптимизации:** - React Virtualized для больших списков товаров - Pagination для табличного режима - Lazy loading изображений товаров ### 6.3 Оптимизация запросов **Стратегии загрузки:** ```typescript // Параллельная загрузка данных const [loadCards, loadAnalytics] = await Promise.allSettled([ WildberriesService.getAllCards(apiToken), getAnalyticsData(nmIds), ]) // Batch операции для множественных обновлений const batchUpdate = products.map((product) => updateProduct(product)) await Promise.all(batchUpdate) ``` ## 📊 7. МЕТРИКИ И KPI СКЛАДОВ ### 7.1 Ключевые показатели WB склада **Автоматически рассчитываемые метрики:** - Общее количество товаров - Общий остаток по всем складам - Количество зарезервированных товаров - Возвраты от клиентов - Количество активных складов ### 7.2 Метрики общего склада **Потенциальные KPI:** - Оборачиваемость товаров - Средняя стоимость единицы товара - Доля товаров vs расходников - Критически низкие остатки - Время пополнения склада ### 7.3 Фулфилмент метрики **Операционные показатели:** - Скорость обработки поставок - Эффективность сотрудников - Качество упаковки - Время отгрузки - Уровень ошибок ## 🔒 8. БЕЗОПАСНОСТЬ И КОНТРОЛЬ ДОСТУПА ### 8.1 Проверка API ключей ```typescript // Валидация ключей WB if (!wbApiKey?.isActive) { toast.error('API ключ Wildberries не настроен') return } if (!apiToken) { toast.error('Токен API не найден') return } ``` ### 8.2 Фильтрация данных по организации ```typescript // Безопасность на уровне запросов const { data, loading, error } = useQuery(GET_MY_PRODUCTS, { variables: { organizationId: user?.organization?.id }, errorPolicy: 'all', }) ``` ### 8.3 Обработка ошибок ```typescript // Graceful error handling try { const result = await wbService.getStocksReportByOffices(params) } catch (error) { console.error(`Error fetching analytics for nmId ${nmId}:`, error) // Продолжаем обработку других товаров continue } ``` ## 🔄 9. WORKFLOW СКЛАДСКИХ ОПЕРАЦИЙ ### 9.1 Стандартный процесс WB ``` 1. Настройка API ключа WB ↓ 2. Загрузка карточек товаров ↓ 3. Получение аналитики по остаткам ↓ 4. Комбинирование данных ↓ 5. Кэширование результата ↓ 6. Отображение в интерфейсе ``` ### 9.2 Процесс управления общим складом ``` 1. Добавление товара/расходника ↓ 2. Указание характеристик и рынка ↓ 3. Загрузка изображений ↓ 4. Сохранение в базе данных ↓ 5. Обновление статистики ↓ 6. Отслеживание остатков ``` ### 9.3 Фулфилмент операции ``` 1. Получение поставки от поставщика ↓ 2. Приемка и проверка товаров ↓ 3. Размещение на складе ↓ 4. Обработка заказов селлеров ↓ 5. Упаковка и отгрузка ↓ 6. Обновление остатков ``` ## 📦 10. ДЕТАЛИЗАЦИЯ ВКЛАДОК WB СКЛАДА ### 10.1 Вкладка Wildberries (WildberriesWarehouseTab) **Основано на коде:** `src/components/wb-warehouse/wildberries-warehouse-tab.tsx` **Модульные компоненты:** ```typescript // Импортируемые компоненты для вкладки WB import { LoadingSkeleton } from './loading-skeleton' // Скелетоны загрузки import { SearchBar } from './search-bar' // Поиск по товарам import { StatsCards } from './stats-cards' // Карточки статистики import { StockTableRow } from './stock-table-row' // Строка таблицы остатков import { TableHeader } from './table-header' // Заголовок таблицы ``` **Структура WBStock (детализированная):** ```typescript interface WBStock { nmId: number // Номенклатурный номер WB vendorCode: string // Артикул поставщика title: string // Название товара brand: string // Бренд price: number // Цена stocks: Array<{ // Остатки по складам WB warehouseId: number // ID склада warehouseName: string // Название склада quantity: number // Доступно для продажи quantityFull: number // Полное количество inWayToClient: number // В пути к клиенту (зарезервировано) inWayFromClient: number // Возвраты от клиентов }> totalQuantity: number // Общее количество totalReserved: number // Общее зарезервировано photos: any[] // Фотографии mediaFiles: any[] // Медиафайлы characteristics: any[] // Характеристики subjectName: string // Категория description: string // Описание } ``` **Props интерфейс WildberriesWarehouseTab:** ```typescript interface WildberriesWarehouseTabProps { stocks: WBStock[] // Массив товаров WB warehouses: WBWarehouse[] // Склады WB loading: boolean // Состояние загрузки initialized: boolean // Флаг инициализации cacheLoading: boolean // Загрузка из кэша totalProducts: number // Общее количество товаров totalStocks: number // Общие остатки totalReserved: number // Зарезервировано totalFromClient: number // Возвраты от клиентов activeWarehouses: number // Активные склады analyticsData: any[] // Аналитические данные onRefresh: () => Promise // Функция обновления } ``` **Система поиска и фильтрации:** ```typescript const filteredStocks = stocks.filter((item) => { if (!searchTerm) return true const search = searchTerm.toLowerCase() return ( item.title.toLowerCase().includes(search) || String(item.nmId).includes(search) || item.brand.toLowerCase().includes(search) || item.vendorCode.toLowerCase().includes(search) ) }) ``` **Функциональные возможности:** - Поиск товаров по номенклатуре или названию - Статистические карточки с общими показателями - Табличное отображение остатков по всем складам WB - Аналитика по складам WB (до 6 блоков) - Скелетоны загрузки для улучшения UX - Функция обновления данных с обработкой ошибок ### 10.2 Вкладка Мой склад (MyWarehouseTab) **Основано на коде:** `src/components/wb-warehouse/my-warehouse-tab.tsx` **Структура товара собственного склада:** ```typescript interface MyWarehouseItem { id: string // Уникальный ID sku: string // SKU товара name: string // Название category: string // Категория quantity: number // Количество price: number // Цена location: string // Местоположение на складе status: 'in_stock' | 'low_stock' | 'out_of_stock' // Статус остатков lastUpdated: string // Последнее обновление } ``` **Статусы остатков:** - **`in_stock`** - достаточно товара - **`low_stock`** - мало товара (критические остатки) - **`out_of_stock`** - товара нет **Функции управления статусами:** ```typescript const getStatusColor = (status: string) => { switch (status) { case 'in_stock': return 'text-green-400' case 'low_stock': return 'text-yellow-400' case 'out_of_stock': return 'text-red-400' default: return 'text-white/60' } } const getStatusText = (status: string) => { switch (status) { case 'in_stock': return 'В наличии' case 'low_stock': return 'Мало' case 'out_of_stock': return 'Нет в наличии' default: return 'Неизвестно' } } ``` **Статистические расчеты:** ```typescript const totalItems = items.length const totalQuantity = items.reduce((sum, item) => sum + item.quantity, 0) const totalValue = items.reduce((sum, item) => sum + item.quantity * item.price, 0) const lowStockItems = items.filter((item) => item.status === 'low_stock' || item.status === 'out_of_stock').length ``` **Статистические карточки:** - **"Общее кол-во товаров"** (Package, синий) - totalItems - **"Общее количество"** (Warehouse, зеленый) - totalQuantity - **"Общая стоимость"** (₽ символ, фиолетовый) - totalValue в рублях - **"Требует внимания"** (⚠ символ, желтый) - lowStockItems **UI компоненты:** - Поиск по SKU и названию товара - Кнопка добавления нового товара - Карточки статистики по статусам остатков - Таблица с местоположением товаров на складе - 7-колоночная таблица: SKU, Название, Категория, Количество, Цена, Локация, Статус ### 10.3 Вкладка Фулфилмент (FulfillmentWarehouseTab) **Основано на коде:** `src/components/wb-warehouse/fulfillment-warehouse-tab.tsx` **Интеграция с основным модулем FulfillmentWarehouse:** ```typescript // Использует 17+ компонентов из fulfillment-warehouse/ import { FulfillmentWarehouseDashboard } from '@/components/fulfillment-warehouse' ``` **Связь с фулфилмент операциями:** - Приемка поставок от поставщиков - Обработка товаров - Упаковка и отгрузка на маркетплейсы - Работа с возвратами - Управление расходниками ### 10.4 Дополнительные UI компоненты #### LoadingSkeleton ```typescript // Анимированные скелетоны для loading состояний // Улучшают воспринимаемую производительность ``` #### SearchBar ```typescript // Универсальная строка поиска для всех типов складов // Поддерживает поиск по различным полям ``` #### StatsCards ```typescript // Карточки ключевых метрик склада // Отображают общую статистику и тренды ``` #### StockTableRow ```typescript // Строка таблицы остатков с подробной информацией // Поддерживает различные форматы данных ``` #### TableHeader ```typescript // Заголовок таблицы с сортировкой и фильтрацией // Адаптивный дизайн для различных разрешений ``` ## 🎯 ЗАКЛЮЧЕНИЕ Система управления складами SFERA представляет собой комплексное решение для различных типов складских операций с глубокой интеграцией с внешними маркетплейсами и современным пользовательским интерфейсом. Ключевые преимущества: - **Полная интеграция с Wildberries** - синхронизация остатков и аналитики - **Универсальное управление товарами** - товары и расходники в едином интерфейсе - **Модульная архитектура фулфилмента** - 17+ специализированных компонентов - **Многоуровневое кэширование** - оптимизация работы с внешними API - **Адаптивный дизайн** - корректная работа на всех устройствах - **Системы безопасности** - проверка доступа и валидация данных - **Glass Morphism UI** - современный и привлекательный интерфейс