first commit

This commit is contained in:
Veronika Smirnova
2025-08-22 18:05:11 +03:00
parent 6e3201f491
commit 6ff4ca20db
26 changed files with 244 additions and 130 deletions

View File

@ -63,7 +63,7 @@ export async function GET(req: NextRequest) {
// Heartbeat to keep connection alive // Heartbeat to keep connection alive
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
try { try {
controller.enqueue(encoder.encode(`:\n\n`)) controller.enqueue(encoder.encode(':\n\n'))
} catch (e) { } catch (e) {
clearInterval(intervalId) clearInterval(intervalId)
} }

View File

@ -25,20 +25,20 @@ const server = new ApolloServer<Context>({
operationType, operationType,
operationName, operationName,
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
variables: requestContext.request.variables variables: requestContext.request.variables,
}) })
}, },
didEncounterErrors(requestContext) { didEncounterErrors(requestContext) {
console.error('❌ GraphQL ERROR:', { console.error('❌ GraphQL ERROR:', {
errors: requestContext.errors?.map(e => e.message), errors: requestContext.errors?.map(e => e.message),
operationName: requestContext.request.operationName, operationName: requestContext.request.operationName,
timestamp: new Date().toISOString() timestamp: new Date().toISOString(),
}) })
},
} }
} },
} },
} ],
]
}) })
// Создаем Next.js handler // Создаем Next.js handler

View File

@ -6,8 +6,8 @@ import React, { useState } from 'react'
import { Sidebar } from '@/components/dashboard/sidebar' import { Sidebar } from '@/components/dashboard/sidebar'
import { GET_PENDING_SUPPLIES_COUNT } from '@/graphql/queries' import { GET_PENDING_SUPPLIES_COUNT } from '@/graphql/queries'
import { useSidebar } from '@/hooks/useSidebar'
import { useRealtime } from '@/hooks/useRealtime' import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
// Импорты компонентов подразделов // Импорты компонентов подразделов
import { FulfillmentConsumablesOrdersTab } from './fulfillment-supplies/fulfillment-consumables-orders-tab' import { FulfillmentConsumablesOrdersTab } from './fulfillment-supplies/fulfillment-consumables-orders-tab'

View File

@ -137,12 +137,12 @@ const formatCurrency = (amount: number) => {
} }
// Функция для форматирования даты // Функция для форматирования даты
const formatDate = (dateString: string) => { const _formatDate = (dateString: string) => {
return new Date(dateString).toLocaleDateString('ru-RU') return new Date(dateString).toLocaleDateString('ru-RU')
} }
// Функция для отображения статуса // Функция для отображения статуса
const getStatusBadge = (status: string) => { const _getStatusBadge = (status: string) => {
const statusConfig = { const statusConfig = {
PENDING: { PENDING: {
label: 'Ожидает одобрения поставщика', label: 'Ожидает одобрения поставщика',
@ -217,7 +217,7 @@ export function FulfillmentDetailedSuppliesTab() {
// Получаем поставки с многоуровневой структурой для фулфилмента // Получаем поставки с многоуровневой структурой для фулфилмента
// Фильтруем поставки где мы являемся получателем (фулфилмент-центром) // Фильтруем поставки где мы являемся получателем (фулфилмент-центром)
// И это расходники фулфилмента (FULFILLMENT_CONSUMABLES) // И это расходники фулфилмента (FULFILLMENT_CONSUMABLES)
const ourSupplyOrders: SupplyOrder[] = (data?.mySupplyOrders || []).filter((order: any) => { const ourSupplyOrders: SupplyOrder[] = (data?.mySupplyOrders || []).filter((order: SupplyOrder) => {
// Проверяем что order существует и имеет нужные поля // Проверяем что order существует и имеет нужные поля
if (!order || !order.fulfillmentCenterId) return false if (!order || !order.fulfillmentCenterId) return false
@ -246,11 +246,11 @@ export function FulfillmentDetailedSuppliesTab() {
break break
case 'cancel': case 'cancel':
// Отменить поставку (если разрешено) // Отменить поставку (если разрешено)
console.log('Отмена поставки:', supplyId) console.warn('Отмена поставки:', supplyId)
toast.info('Функция отмены поставки в разработке') toast.info('Функция отмены поставки в разработке')
break break
default: default:
console.log('Неизвестное действие фулфилмента:', action, supplyId) console.warn('Неизвестное действие фулфилмента:', action, supplyId)
} }
} catch (error) { } catch (error) {
console.error('Ошибка при выполнении действия фулфилмента:', error) console.error('Ошибка при выполнении действия фулфилмента:', error)
@ -260,7 +260,7 @@ export function FulfillmentDetailedSuppliesTab() {
// Функция для приема заказа фулфилментом // Функция для приема заказа фулфилментом
const handleReceiveOrder = async (orderId: string) => { const _handleReceiveOrder = async (orderId: string) => {
try { try {
await fulfillmentReceiveOrder({ await fulfillmentReceiveOrder({
variables: { id: orderId }, variables: { id: orderId },

View File

@ -18,6 +18,7 @@ import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { Separator } from '@/components/ui/separator' import { Separator } from '@/components/ui/separator'
import { ASSIGN_LOGISTICS_TO_SUPPLY } from '@/graphql/mutations'
import { import {
GET_SUPPLY_ORDERS, GET_SUPPLY_ORDERS,
GET_MY_EMPLOYEES, GET_MY_EMPLOYEES,
@ -26,7 +27,6 @@ import {
GET_PENDING_SUPPLIES_COUNT, GET_PENDING_SUPPLIES_COUNT,
GET_WAREHOUSE_PRODUCTS, GET_WAREHOUSE_PRODUCTS,
} from '@/graphql/queries' } from '@/graphql/queries'
import { ASSIGN_LOGISTICS_TO_SUPPLY } from '@/graphql/mutations'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
interface SupplyOrder { interface SupplyOrder {

View File

@ -1,6 +1,7 @@
'use client' 'use client'
import { TrendingUp, TrendingDown } from 'lucide-react' import { TrendingUp, TrendingDown } from 'lucide-react'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
interface StatCardProps { interface StatCardProps {

View File

@ -1,5 +1,5 @@
import React from 'react'
import { ChevronDown, ChevronRight, Eye } from 'lucide-react' import { ChevronDown, ChevronRight, Eye } from 'lucide-react'
import React from 'react'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'

View File

@ -1,10 +1,10 @@
import React from 'react'
import { Search } from 'lucide-react' import { Search } from 'lucide-react'
import React from 'react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { TableHeader } from '../components/TableHeader'
import { TableHeader } from '../components/TableHeader'
import type { TableHeadersBlockProps, StoreDataField } from '../types' import type { TableHeadersBlockProps, StoreDataField } from '../types'
/** /**

View File

@ -1,8 +1,7 @@
import React from 'react'
import { Package, Box, AlertTriangle, RotateCcw, Users, Wrench } from 'lucide-react' import { Package, Box, AlertTriangle, RotateCcw, Users, Wrench } from 'lucide-react'
import React from 'react'
import { StatCard } from '../components/StatCard' import { StatCard } from '../components/StatCard'
import type { WarehouseStatsBlockProps } from '../types' import type { WarehouseStatsBlockProps } from '../types'
/** /**
@ -19,7 +18,7 @@ import type { WarehouseStatsBlockProps } from '../types'
export const WarehouseStatsBlock = React.memo<WarehouseStatsBlockProps>(({ export const WarehouseStatsBlock = React.memo<WarehouseStatsBlockProps>(({
warehouseStats, warehouseStats,
warehouseStatsData, warehouseStatsData,
isStatsLoading isStatsLoading,
}) => { }) => {
return ( return (
<div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-6 gap-3"> <div className="grid grid-cols-2 md:grid-cols-3 xl:grid-cols-6 gap-3">

View File

@ -19,7 +19,7 @@ export function useStoreData(
sellerSupplies: any[], sellerSupplies: any[],
searchTerm: string, searchTerm: string,
sortField: StoreDataField, sortField: StoreDataField,
sortOrder: 'asc' | 'desc' sortOrder: 'asc' | 'desc',
): UseStoreDataReturn { ): UseStoreDataReturn {
// === СОЗДАНИЕ СТРУКТУРИРОВАННЫХ ДАННЫХ СКЛАДА === // === СОЗДАНИЕ СТРУКТУРИРОВАННЫХ ДАННЫХ СКЛАДА ===
@ -206,7 +206,7 @@ export function useStoreData(
// Фильтрация по поисковому термину // Фильтрация по поисковому термину
if (searchTerm) { if (searchTerm) {
filtered = filtered.filter(store => filtered = filtered.filter(store =>
store.name.toLowerCase().includes(searchTerm.toLowerCase()) store.name.toLowerCase().includes(searchTerm.toLowerCase()),
) )
} }
@ -258,7 +258,7 @@ export function useStoreData(
defectsChange: 0, defectsChange: 0,
sellerSuppliesChange: 0, sellerSuppliesChange: 0,
pvzReturnsChange: 0, pvzReturnsChange: 0,
} },
) )
}, [filteredAndSortedStores]) }, [filteredAndSortedStores])

View File

@ -15,7 +15,7 @@ export function useWarehouseStats(
supplyOrders: any[], supplyOrders: any[],
warehouseStatsData: any, warehouseStatsData: any,
warehouseStatsLoading: boolean, warehouseStatsLoading: boolean,
sellerSupplies: any[] = [] sellerSupplies: any[] = [],
): UseWarehouseStatsReturn { ): UseWarehouseStatsReturn {
// === РАСЧЕТ ПОСТУПЛЕНИЙ РАСХОДНИКОВ ЗА СУТКИ === // === РАСЧЕТ ПОСТУПЛЕНИЙ РАСХОДНИКОВ ЗА СУТКИ ===

View File

@ -47,10 +47,11 @@ import {
GET_SUPPLY_MOVEMENTS, // Движения товаров (прибыло/убыло) GET_SUPPLY_MOVEMENTS, // Движения товаров (прибыло/убыло)
} from '@/graphql/queries' } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useSidebar } from '@/hooks/useSidebar'
import { useRealtime } from '@/hooks/useRealtime' import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
import { WbReturnClaims } from '../wb-return-claims' import { WbReturnClaims } from '../wb-return-claims'
import { StatCard } from './blocks/StatCard' import { StatCard } from './blocks/StatCard'
// Типы данных для 3-уровневой иерархии // Типы данных для 3-уровневой иерархии
@ -284,37 +285,37 @@ export function FulfillmentWarehouseDashboard() {
current: stats.products?.current || 0, current: stats.products?.current || 0,
change: stats.products?.change || 0, change: stats.products?.change || 0,
arrived: movements?.arrived?.products || 0, arrived: movements?.arrived?.products || 0,
departed: movements?.departed?.products || 0 departed: movements?.departed?.products || 0,
}, },
goods: { goods: {
current: stats.goods?.current || 0, current: stats.goods?.current || 0,
change: stats.goods?.change || 0, change: stats.goods?.change || 0,
arrived: movements?.arrived?.goods || 0, arrived: movements?.arrived?.goods || 0,
departed: movements?.departed?.goods || 0 departed: movements?.departed?.goods || 0,
}, },
defects: { defects: {
current: stats.defects?.current || 0, current: stats.defects?.current || 0,
change: stats.defects?.change || 0, change: stats.defects?.change || 0,
arrived: movements?.arrived?.defects || 0, arrived: movements?.arrived?.defects || 0,
departed: movements?.departed?.defects || 0 departed: movements?.departed?.defects || 0,
}, },
pvzReturns: { pvzReturns: {
current: stats.pvzReturns?.current || 0, current: stats.pvzReturns?.current || 0,
change: stats.pvzReturns?.change || 0, change: stats.pvzReturns?.change || 0,
arrived: movements?.arrived?.pvzReturns || 0, arrived: movements?.arrived?.pvzReturns || 0,
departed: movements?.departed?.pvzReturns || 0 departed: movements?.departed?.pvzReturns || 0,
}, },
fulfillmentSupplies: { fulfillmentSupplies: {
current: stats.fulfillmentSupplies?.current || 0, current: stats.fulfillmentSupplies?.current || 0,
change: stats.fulfillmentSupplies?.change || 0, change: stats.fulfillmentSupplies?.change || 0,
arrived: movements?.arrived?.fulfillmentSupplies || 0, arrived: movements?.arrived?.fulfillmentSupplies || 0,
departed: movements?.departed?.fulfillmentSupplies || 0 departed: movements?.departed?.fulfillmentSupplies || 0,
}, },
sellerSupplies: { sellerSupplies: {
current: stats.sellerSupplies?.current || 0, current: stats.sellerSupplies?.current || 0,
change: stats.sellerSupplies?.change || 0, change: stats.sellerSupplies?.change || 0,
arrived: movements?.arrived?.sellerSupplies || 0, arrived: movements?.arrived?.sellerSupplies || 0,
departed: movements?.departed?.sellerSupplies || 0 departed: movements?.departed?.sellerSupplies || 0,
}, },
} }
} }
@ -329,37 +330,37 @@ export function FulfillmentWarehouseDashboard() {
current: warehouseProducts.filter((p: any) => p.type === 'PRODUCT').length, current: warehouseProducts.filter((p: any) => p.type === 'PRODUCT').length,
change: 0, change: 0,
arrived: movements?.arrived?.products || 0, arrived: movements?.arrived?.products || 0,
departed: movements?.departed?.products || 0 departed: movements?.departed?.products || 0,
}, },
goods: { goods: {
current: warehouseProducts.filter((p: any) => p.type === 'GOODS').length, current: warehouseProducts.filter((p: any) => p.type === 'GOODS').length,
change: 0, change: 0,
arrived: movements?.arrived?.goods || 0, arrived: movements?.arrived?.goods || 0,
departed: movements?.departed?.goods || 0 departed: movements?.departed?.goods || 0,
}, },
defects: { defects: {
current: warehouseProducts.filter((p: any) => p.type === 'DEFECTS').length, current: warehouseProducts.filter((p: any) => p.type === 'DEFECTS').length,
change: 0, change: 0,
arrived: movements?.arrived?.defects || 0, arrived: movements?.arrived?.defects || 0,
departed: movements?.departed?.defects || 0 departed: movements?.departed?.defects || 0,
}, },
pvzReturns: { pvzReturns: {
current: warehouseProducts.filter((p: any) => p.type === 'PVZ_RETURNS').length, current: warehouseProducts.filter((p: any) => p.type === 'PVZ_RETURNS').length,
change: 0, change: 0,
arrived: movements?.arrived?.pvzReturns || 0, arrived: movements?.arrived?.pvzReturns || 0,
departed: movements?.departed?.pvzReturns || 0 departed: movements?.departed?.pvzReturns || 0,
}, },
fulfillmentSupplies: { fulfillmentSupplies: {
current: fulfillmentSupplies.length, current: fulfillmentSupplies.length,
change: 0, change: 0,
arrived: movements?.arrived?.fulfillmentSupplies || 0, arrived: movements?.arrived?.fulfillmentSupplies || 0,
departed: movements?.departed?.fulfillmentSupplies || 0 departed: movements?.departed?.fulfillmentSupplies || 0,
}, },
sellerSupplies: { sellerSupplies: {
current: sellerSupplies.length, current: sellerSupplies.length,
change: 0, change: 0,
arrived: movements?.arrived?.sellerSupplies || 0, arrived: movements?.arrived?.sellerSupplies || 0,
departed: movements?.departed?.sellerSupplies || 0 departed: movements?.departed?.sellerSupplies || 0,
}, },
} }
}, [warehouseStatsData, warehouseData, sellerSuppliesData, fulfillmentSuppliesData, supplyMovementsData]) }, [warehouseStatsData, warehouseData, sellerSuppliesData, fulfillmentSuppliesData, supplyMovementsData])
@ -448,7 +449,7 @@ export function FulfillmentWarehouseDashboard() {
sellerSuppliesQuantity: 0, sellerSuppliesQuantity: 0,
pvzReturnsQuantity: 0, pvzReturnsQuantity: 0,
sellerSuppliesOwners: [], sellerSuppliesOwners: [],
variants: [] variants: [],
} }
} }
@ -464,7 +465,7 @@ export function FulfillmentWarehouseDashboard() {
// КРИТИЧНО: Группировка расходников селлера по ВЛАДЕЛЬЦУ (не по названию!) // КРИТИЧНО: Группировка расходников селлера по ВЛАДЕЛЬЦУ (не по названию!)
const sellerSuppliesForThisSeller = sellerSupplies.filter((supply: any) => const sellerSuppliesForThisSeller = sellerSupplies.filter((supply: any) =>
supply.type === 'SELLER_CONSUMABLES' && supply.type === 'SELLER_CONSUMABLES' &&
supply.sellerId === sellerId supply.sellerId === sellerId,
) )
console.warn(`📦 Расходники для селлера ${sellerName}:`, sellerSuppliesForThisSeller.length) console.warn(`📦 Расходники для селлера ${sellerName}:`, sellerSuppliesForThisSeller.length)
@ -484,7 +485,7 @@ export function FulfillmentWarehouseDashboard() {
sellerSuppliesQuantity: 0, sellerSuppliesQuantity: 0,
pvzReturnsQuantity: 0, pvzReturnsQuantity: 0,
sellerSuppliesOwners: [ownerKey], sellerSuppliesOwners: [ownerKey],
variants: [] variants: [],
} }
} }
@ -504,7 +505,7 @@ export function FulfillmentWarehouseDashboard() {
sellerSupplies: acc.sellerSupplies + (item.sellerSuppliesQuantity || 0), sellerSupplies: acc.sellerSupplies + (item.sellerSuppliesQuantity || 0),
pvzReturns: acc.pvzReturns + (item.pvzReturnsQuantity || 0), pvzReturns: acc.pvzReturns + (item.pvzReturnsQuantity || 0),
}), }),
{ products: 0, goods: 0, defects: 0, sellerSupplies: 0, pvzReturns: 0 } { products: 0, goods: 0, defects: 0, sellerSupplies: 0, pvzReturns: 0 },
) )
console.warn(`📊 Итоги для ${sellerName}:`, totals) console.warn(`📊 Итоги для ${sellerName}:`, totals)
@ -541,7 +542,7 @@ export function FulfillmentWarehouseDashboard() {
if (searchTerm) { if (searchTerm) {
filtered = filtered.filter((store) => filtered = filtered.filter((store) =>
store.name.toLowerCase().includes(searchTerm.toLowerCase()) store.name.toLowerCase().includes(searchTerm.toLowerCase()),
) )
} }
@ -573,7 +574,7 @@ export function FulfillmentWarehouseDashboard() {
sellerSupplies: acc.sellerSupplies + store.sellerSupplies, sellerSupplies: acc.sellerSupplies + store.sellerSupplies,
pvzReturns: acc.pvzReturns + store.pvzReturns, pvzReturns: acc.pvzReturns + store.pvzReturns,
}), }),
{ products: 0, goods: 0, defects: 0, sellerSupplies: 0, pvzReturns: 0 } { products: 0, goods: 0, defects: 0, sellerSupplies: 0, pvzReturns: 0 },
) )
}, [filteredAndSortedStores]) }, [filteredAndSortedStores])

View File

@ -0,0 +1,57 @@
'use client'
import { Building, Users, Target, Briefcase } from 'lucide-react'
import { Card } from '@/components/ui/card'
export function MarketBusiness() {
return (
<div className="h-full flex flex-col space-y-4 overflow-hidden">
{/* Заголовок с иконкой */}
<div className="flex items-center space-x-3 flex-shrink-0 mb-4">
<Briefcase className="h-6 w-6 text-orange-400" />
<div>
<h3 className="text-lg font-semibold text-white">Бизнес</h3>
<p className="text-white/60 text-sm">Бизнес-возможности и развитие</p>
</div>
</div>
{/* Контент раздела */}
<div className="flex-1 overflow-auto space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<Building className="h-8 w-8 text-orange-400" />
<h4 className="text-lg font-semibold text-white">Франшизы</h4>
</div>
<p className="text-white/60 text-sm">Готовые бизнес-решения и франшизы в сфере логистики и торговли</p>
</Card>
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<Users className="h-8 w-8 text-blue-400" />
<h4 className="text-lg font-semibold text-white">Партнёрство</h4>
</div>
<p className="text-white/60 text-sm">Поиск бизнес-партнёров для совместных проектов и развития</p>
</Card>
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<Target className="h-8 w-8 text-green-400" />
<h4 className="text-lg font-semibold text-white">Консалтинг</h4>
</div>
<p className="text-white/60 text-sm">Бизнес-консультации и стратегическое планирование развития</p>
</Card>
</div>
<div className="text-center py-8">
<div className="w-16 h-16 bg-white/10 rounded-full flex items-center justify-center mx-auto mb-4">
<Briefcase className="h-8 w-8 text-white/40" />
</div>
<p className="text-white/60 text-lg mb-2">Раздел в разработке</p>
<p className="text-white/40 text-sm">Бизнес-функционал будет доступен в ближайших обновлениях</p>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,61 @@
'use client'
import { TrendingUp, DollarSign, BarChart3 } from 'lucide-react'
import { Card } from '@/components/ui/card'
export function MarketInvestments() {
return (
<div className="h-full flex flex-col space-y-4 overflow-hidden">
{/* Заголовок с иконкой */}
<div className="flex items-center space-x-3 flex-shrink-0 mb-4">
<TrendingUp className="h-6 w-6 text-green-400" />
<div>
<h3 className="text-lg font-semibold text-white">Инвестиции</h3>
<p className="text-white/60 text-sm">Инвестиционные возможности и проекты</p>
</div>
</div>
{/* Контент раздела */}
<div className="flex-1 overflow-auto space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<DollarSign className="h-8 w-8 text-green-400" />
<h4 className="text-lg font-semibold text-white">Инвестиционные проекты</h4>
</div>
<p className="text-white/60 text-sm">
Поиск и анализ перспективных инвестиционных проектов в сфере логистики и e-commerce
</p>
</Card>
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<BarChart3 className="h-8 w-8 text-blue-400" />
<h4 className="text-lg font-semibold text-white">Аналитика рынка</h4>
</div>
<p className="text-white/60 text-sm">
Исследования и аналитические отчёты для принятия инвестиционных решений
</p>
</Card>
<Card className="bg-white/5 backdrop-blur border-white/10 p-6">
<div className="flex items-center space-x-3 mb-4">
<TrendingUp className="h-8 w-8 text-purple-400" />
<h4 className="text-lg font-semibold text-white">Доходность</h4>
</div>
<p className="text-white/60 text-sm">Отслеживание доходности инвестиций и планирование бюджета</p>
</Card>
</div>
<div className="text-center py-8">
<div className="w-16 h-16 bg-white/10 rounded-full flex items-center justify-center mx-auto mb-4">
<TrendingUp className="h-8 w-8 text-white/40" />
</div>
<p className="text-white/60 text-lg mb-2">Раздел в разработке</p>
<p className="text-white/40 text-sm">Функционал инвестиций будет доступен в ближайших обновлениях</p>
</div>
</div>
</div>
)
}

View File

@ -22,9 +22,9 @@ import {
} from '@/graphql/mutations' } from '@/graphql/mutations'
import { GET_MESSAGES, GET_CONVERSATIONS } from '@/graphql/queries' import { GET_MESSAGES, GET_CONVERSATIONS } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useRealtime } from '@/hooks/useRealtime'
import { MessengerAttachments } from './messenger-attachments' import { MessengerAttachments } from './messenger-attachments'
import { useRealtime } from '@/hooks/useRealtime'
interface Organization { interface Organization {
id: string id: string

View File

@ -9,8 +9,8 @@ import { Sidebar } from '@/components/dashboard/sidebar'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { GET_CONVERSATIONS, GET_MY_COUNTERPARTIES } from '@/graphql/queries' import { GET_CONVERSATIONS, GET_MY_COUNTERPARTIES } from '@/graphql/queries'
import { useSidebar } from '@/hooks/useSidebar'
import { useRealtime } from '@/hooks/useRealtime' import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
import { MessengerChat } from './messenger-chat' import { MessengerChat } from './messenger-chat'
import { MessengerConversations } from './messenger-conversations' import { MessengerConversations } from './messenger-conversations'

View File

@ -6,8 +6,8 @@ import { Sidebar } from '@/components/dashboard/sidebar'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { GET_INCOMING_REQUESTS } from '@/graphql/queries' import { GET_INCOMING_REQUESTS } from '@/graphql/queries'
import { useSidebar } from '@/hooks/useSidebar'
import { useRealtime } from '@/hooks/useRealtime' import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
import { MarketCounterparties } from '../market/market-counterparties' import { MarketCounterparties } from '../market/market-counterparties'
import { MarketFulfillment } from '../market/market-fulfillment' import { MarketFulfillment } from '../market/market-fulfillment'

View File

@ -3,18 +3,19 @@
import { useQuery, useMutation } from '@apollo/client' import { useQuery, useMutation } from '@apollo/client'
import { Clock, CheckCircle, Settings, Truck, Package, Calendar, Search } from 'lucide-react' import { Clock, CheckCircle, Settings, Truck, Package, Calendar, Search } from 'lucide-react'
import { useState, useMemo } from 'react' import { useState, useMemo } from 'react'
import { toast } from 'sonner'
import { MultiLevelSuppliesTable } from '@/components/supplies/multilevel-supplies-table'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import { GET_SUPPLY_ORDERS, GET_MY_SUPPLY_ORDERS } from '@/graphql/queries'
import { SUPPLIER_APPROVE_ORDER, SUPPLIER_REJECT_ORDER, SUPPLIER_SHIP_ORDER } from '@/graphql/mutations' import { SUPPLIER_APPROVE_ORDER, SUPPLIER_REJECT_ORDER, SUPPLIER_SHIP_ORDER } from '@/graphql/mutations'
import { GET_SUPPLY_ORDERS, GET_MY_SUPPLY_ORDERS } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { toast } from 'sonner'
import { MultiLevelSuppliesTable } from '@/components/supplies/multilevel-supplies-table'
import { SupplierOrderStats } from './supplier-order-stats' import { SupplierOrderStats } from './supplier-order-stats'
import { SupplierOrdersSearch } from './supplier-orders-search' import { SupplierOrdersSearch } from './supplier-orders-search'

View File

@ -263,7 +263,7 @@ function ProductTableRow({
console.log('🎯 Услуги ФФ:', { console.log('🎯 Услуги ФФ:', {
fulfillmentServicesCount: fulfillmentServices.length, fulfillmentServicesCount: fulfillmentServices.length,
fulfillmentServices: fulfillmentServices, fulfillmentServices: fulfillmentServices,
selectedFulfillment: selectedFulfillment selectedFulfillment: selectedFulfillment,
}) })
return null return null
})()} })()}
@ -288,7 +288,7 @@ function ProductTableRow({
productId: product.id, productId: product.id,
serviceName: service.name, serviceName: service.name,
isSelected: isSelected, isSelected: isSelected,
newRecipe: newRecipe newRecipe: newRecipe,
}) })
onRecipeChange(product.id, newRecipe) onRecipeChange(product.id, newRecipe)
@ -453,7 +453,7 @@ function MarketplaceCardSelector({ productId, onCardSelect, selectedCardId }: Ma
dataExists: !!data, dataExists: !!data,
warehouseDataExists: !!data?.getWBWarehouseData, warehouseDataExists: !!data?.getWBWarehouseData,
cacheExists: !!data?.getWBWarehouseData?.cache, cacheExists: !!data?.getWBWarehouseData?.cache,
rawData: data rawData: data,
}) })
// Извлекаем карточки из кеша склада WB, как на странице склада // Извлекаем карточки из кеша склада WB, как на странице склада
@ -464,7 +464,7 @@ function MarketplaceCardSelector({ productId, onCardSelect, selectedCardId }: Ma
hasWBData: !!data?.getWBWarehouseData, hasWBData: !!data?.getWBWarehouseData,
hasCache: !!data?.getWBWarehouseData?.cache, hasCache: !!data?.getWBWarehouseData?.cache,
cache: data?.getWBWarehouseData?.cache, cache: data?.getWBWarehouseData?.cache,
cacheData: data?.getWBWarehouseData?.cache?.data cacheData: data?.getWBWarehouseData?.cache?.data,
}) })
const cacheData = data?.getWBWarehouseData?.cache?.data const cacheData = data?.getWBWarehouseData?.cache?.data
@ -512,7 +512,7 @@ function MarketplaceCardSelector({ productId, onCardSelect, selectedCardId }: Ma
}} }}
> >
<SelectTrigger className="glass-input h-7 text-xs border-white/20"> <SelectTrigger className="glass-input h-7 text-xs border-white/20">
<SelectValue placeholder={loading ? "..." : "WB"} /> <SelectValue placeholder={loading ? '...' : 'WB'} />
</SelectTrigger> </SelectTrigger>
<SelectContent className="glass-card border-white/20 max-h-[200px] overflow-y-auto"> <SelectContent className="glass-card border-white/20 max-h-[200px] overflow-y-auto">
<SelectItem value="none">Не выбрано</SelectItem> <SelectItem value="none">Не выбрано</SelectItem>

View File

@ -145,7 +145,7 @@ export function useSupplyCart({ selectedSupplier, allCounterparties, productReci
console.log('🔎 Проверка услуг для товаров:', { console.log('🔎 Проверка услуг для товаров:', {
selectedGoods: selectedGoods.map(item => ({ id: item.id, name: item.name })), selectedGoods: selectedGoods.map(item => ({ id: item.id, name: item.name })),
productRecipesKeys: Object.keys(productRecipes), productRecipesKeys: Object.keys(productRecipes),
productRecipes: productRecipes productRecipes: productRecipes,
}) })
const result = selectedGoods.every((item) => { const result = selectedGoods.every((item) => {
@ -215,7 +215,7 @@ export function useSupplyCart({ selectedSupplier, allCounterparties, productReci
fulfillmentConsumables: recipe.selectedFFConsumables || [], fulfillmentConsumables: recipe.selectedFFConsumables || [],
sellerConsumables: recipe.selectedSellerConsumables || [], sellerConsumables: recipe.selectedSellerConsumables || [],
marketplaceCardId: recipe.selectedWBCard || null, marketplaceCardId: recipe.selectedWBCard || null,
} },
} }
}), }),
notes: selectedGoods notes: selectedGoods
@ -232,7 +232,7 @@ export function useSupplyCart({ selectedSupplier, allCounterparties, productReci
selectedGoodsCount: selectedGoods.length, selectedGoodsCount: selectedGoods.length,
deliveryDateType: typeof deliveryDate, deliveryDateType: typeof deliveryDate,
deliveryDateValue: deliveryDate, deliveryDateValue: deliveryDate,
convertedDate: new Date(deliveryDate).toISOString() convertedDate: new Date(deliveryDate).toISOString(),
}) })
console.warn('🔍 ДЕТАЛЬНАЯ ПРОВЕРКА inputData перед отправкой:', JSON.stringify(inputData, null, 2)) console.warn('🔍 ДЕТАЛЬНАЯ ПРОВЕРКА inputData перед отправкой:', JSON.stringify(inputData, null, 2))

View File

@ -147,7 +147,7 @@ export function CreateSuppliersSupplyPage() {
(productId: string, recipe: ProductRecipe) => { (productId: string, recipe: ProductRecipe) => {
console.log('📝 handleRecipeChange вызван:', { console.log('📝 handleRecipeChange вызван:', {
productId: productId, productId: productId,
recipe: recipe recipe: recipe,
}) })
setProductRecipes((prev) => ({ setProductRecipes((prev) => ({

View File

@ -6,45 +6,38 @@ import {
Calendar, Calendar,
DollarSign, DollarSign,
Search, Search,
Filter,
ChevronDown, ChevronDown,
ChevronRight, ChevronRight,
Smartphone, Smartphone,
Eye,
MoreHorizontal,
MapPin, MapPin,
TrendingUp,
AlertTriangle,
Warehouse,
} from 'lucide-react' } from 'lucide-react'
import React, { useState } from 'react' import React, { useState } from 'react'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card' import { Card } from '@/components/ui/card'
import { Input } from '@/components/ui/input' import { Input } from '@/components/ui/input'
import { formatCurrency } from '@/lib/utils' import { formatCurrency } from '@/lib/utils'
// Простые компоненты таблицы // Простые компоненты таблицы
const Table = ({ children, ...props }: any) => ( const Table = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => (
<div className="w-full overflow-auto" {...props}> <div className="w-full overflow-auto" {...props}>
<table className="w-full">{children}</table> <table className="w-full">{children}</table>
</div> </div>
) )
const TableHeader = ({ children, ...props }: any) => <thead {...props}>{children}</thead> const TableHeader = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => <thead {...props}>{children}</thead>
const TableBody = ({ children, ...props }: any) => <tbody {...props}>{children}</tbody> const TableBody = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => <tbody {...props}>{children}</tbody>
const TableRow = ({ children, className, ...props }: any) => ( const TableRow = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<tr className={className} {...props}> <tr className={className} {...props}>
{children} {children}
</tr> </tr>
) )
const TableHead = ({ children, className, ...props }: any) => ( const TableHead = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<th className={`px-4 py-3 text-left font-medium ${className}`} {...props}> <th className={`px-4 py-3 text-left font-medium ${className}`} {...props}>
{children} {children}
</th> </th>
) )
const TableCell = ({ children, className, ...props }: any) => ( const TableCell = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<td className={`px-4 py-3 ${className}`} {...props}> <td className={`px-4 py-3 ${className}`} {...props}>
{children} {children}
</td> </td>
@ -94,7 +87,7 @@ interface GoodsSupplyRoute {
} }
// Основной интерфейс поставки товаров согласно rules2.md 9.5.4 // Основной интерфейс поставки товаров согласно rules2.md 9.5.4
interface GoodsSupply { interface _GoodsSupply {
id: string id: string
number: string number: string
creationMethod: 'cards' | 'suppliers' // 📱 карточки / 🏢 поставщик creationMethod: 'cards' | 'suppliers' // 📱 карточки / 🏢 поставщик
@ -243,7 +236,7 @@ function CreationMethodIcon({ method }: { method: 'cards' | 'suppliers' }) {
} }
// Компонент для статуса поставки // Компонент для статуса поставки
function StatusBadge({ status }: { status: string }) { function _StatusBadge({ status }: { status: string }) {
const getStatusColor = (status: string) => { const getStatusColor = (status: string) => {
switch (status.toLowerCase()) { switch (status.toLowerCase()) {
case 'pending': case 'pending':

View File

@ -3,9 +3,6 @@
import { import {
Package, Package,
Building2, Building2,
DollarSign,
ChevronDown,
ChevronRight,
MapPin, MapPin,
Truck, Truck,
Clock, Clock,
@ -17,7 +14,6 @@ import { createPortal } from 'react-dom'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card } from '@/components/ui/card'
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -137,25 +133,25 @@ interface MultiLevelSuppliesTableProps {
} }
// Простые компоненты таблицы // Простые компоненты таблицы
const Table = ({ children, ...props }: any) => ( const Table = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => (
<div className="w-full" {...props}> <div className="w-full" {...props}>
<table className="w-full">{children}</table> <table className="w-full">{children}</table>
</div> </div>
) )
const TableHeader = ({ children, ...props }: any) => <thead {...props}>{children}</thead> const TableHeader = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => <thead {...props}>{children}</thead>
const TableBody = ({ children, ...props }: any) => <tbody {...props}>{children}</tbody> const TableBody = ({ children, ...props }: { children: React.ReactNode; [key: string]: unknown }) => <tbody {...props}>{children}</tbody>
const TableRow = ({ children, className, ...props }: any) => ( const TableRow = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<tr className={className} {...props}> <tr className={className} {...props}>
{children} {children}
</tr> </tr>
) )
const TableHead = ({ children, className, ...props }: any) => ( const TableHead = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<th className={`px-4 py-3 text-left ${className}`} {...props}> <th className={`px-4 py-3 text-left ${className}`} {...props}>
{children} {children}
</th> </th>
) )
const TableCell = ({ children, className, ...props }: any) => ( const TableCell = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
<td className={`px-4 py-3 ${className}`} {...props}> <td className={`px-4 py-3 ${className}`} {...props}>
{children} {children}
</td> </td>
@ -214,7 +210,7 @@ function ContextMenu({
isOpen, isOpen,
position, position,
onClose, onClose,
onCancel onCancel,
}: { }: {
isOpen: boolean isOpen: boolean
position: { x: number; y: number } position: { x: number; y: number }
@ -241,7 +237,7 @@ function ContextMenu({
top: position.y, top: position.y,
zIndex: 9999, zIndex: 9999,
backgroundColor: 'rgb(17, 24, 39)', backgroundColor: 'rgb(17, 24, 39)',
borderColor: 'rgba(255, 255, 255, 0.2)' borderColor: 'rgba(255, 255, 255, 0.2)',
}} }}
> >
<button <button
@ -266,7 +262,7 @@ function CancelConfirmDialog({
isOpen, isOpen,
onClose, onClose,
onConfirm, onConfirm,
supplyId supplyId,
}: { }: {
isOpen: boolean isOpen: boolean
onClose: () => void onClose: () => void
@ -306,7 +302,7 @@ function CancelConfirmDialog({
// Основной компонент многоуровневой таблицы поставок // Основной компонент многоуровневой таблицы поставок
export function MultiLevelSuppliesTable({ export function MultiLevelSuppliesTable({
supplies = [], supplies = [],
loading = false, loading: _loading = false,
userRole = 'SELLER', userRole = 'SELLER',
onSupplyAction, onSupplyAction,
}: MultiLevelSuppliesTableProps) { }: MultiLevelSuppliesTableProps) {
@ -323,24 +319,26 @@ export function MultiLevelSuppliesTable({
}>({ }>({
isOpen: false, isOpen: false,
position: { x: 0, y: 0 }, position: { x: 0, y: 0 },
supplyId: null supplyId: null,
}) })
const [cancelDialogOpen, setCancelDialogOpen] = useState(false) const [cancelDialogOpen, setCancelDialogOpen] = useState(false)
// Безопасная диагностика данных услуг ФФ // Диагностика данных услуг ФФ (только в dev режиме)
console.log('🔍 ДИАГНОСТИКА: Данные поставок и рецептур:', supplies.map(supply => ({ if (process.env.NODE_ENV === 'development') {
console.warn('🔍 ДИАГНОСТИКА: Данные поставок и рецептур:', supplies.map(supply => ({
id: supply.id, id: supply.id,
itemsCount: supply.items?.length || 0, itemsCount: supply.items?.length || 0,
items: supply.items?.slice(0, 2).map(item => ({ // Берем только первые 2 товара для диагностики items: supply.items?.slice(0, 2).map(item => ({
id: item.id, id: item.id,
productName: item.product?.name, productName: item.product?.name,
hasRecipe: !!item.recipe, hasRecipe: !!item.recipe,
recipe: item.recipe, // Полная структура рецептуры recipe: item.recipe,
services: item.services, // Массив ID услуг services: item.services,
fulfillmentConsumables: item.fulfillmentConsumables, // Массив ID расходников ФФ fulfillmentConsumables: item.fulfillmentConsumables,
sellerConsumables: item.sellerConsumables // Массив ID расходников селлера sellerConsumables: item.sellerConsumables,
})) })),
}))) })))
}
// Массив цветов для различения поставок (с лучшим контрастом) // Массив цветов для различения поставок (с лучшим контрастом)
const supplyColors = [ const supplyColors = [
@ -351,13 +349,13 @@ export function MultiLevelSuppliesTable({
'rgba(248, 113, 113, 0.8)', // Красный 'rgba(248, 113, 113, 0.8)', // Красный
'rgba(34, 211, 238, 0.8)', // Голубой 'rgba(34, 211, 238, 0.8)', // Голубой
'rgba(74, 222, 128, 0.8)', // Зеленый (переместил на 7 позицию) 'rgba(74, 222, 128, 0.8)', // Зеленый (переместил на 7 позицию)
'rgba(250, 204, 21, 0.8)' // Желтый 'rgba(250, 204, 21, 0.8)', // Желтый
] ]
const getSupplyColor = (index: number) => supplyColors[index % supplyColors.length] const getSupplyColor = (index: number) => supplyColors[index % supplyColors.length]
// Функция для получения цвета фона строки в зависимости от уровня иерархии // Функция для получения цвета фона строки в зависимости от уровня иерархии
const getLevelBackgroundColor = (level: number, supplyIndex: number) => { const getLevelBackgroundColor = (level: number, _supplyIndex: number) => {
const alpha = 0.08 + (level * 0.03) // Больше прозрачности: начальное значение 0.08, шаг 0.03 const alpha = 0.08 + (level * 0.03) // Больше прозрачности: начальное значение 0.08, шаг 0.03
// Цвета для разных уровней (соответствуют цветам точек) // Цвета для разных уровней (соответствуют цветам точек)
@ -366,7 +364,7 @@ export function MultiLevelSuppliesTable({
2: 'rgba(96, 165, 250, ', // Синий для маршрута 2: 'rgba(96, 165, 250, ', // Синий для маршрута
3: 'rgba(74, 222, 128, ', // Зеленый для поставщика 3: 'rgba(74, 222, 128, ', // Зеленый для поставщика
4: 'rgba(244, 114, 182, ', // Розовый для товара 4: 'rgba(244, 114, 182, ', // Розовый для товара
5: 'rgba(250, 204, 21, ' // Желтый для рецептуры 5: 'rgba(250, 204, 21, ', // Желтый для рецептуры
} }
const baseColor = levelColors[level as keyof typeof levelColors] || 'rgba(75, 85, 99, ' const baseColor = levelColors[level as keyof typeof levelColors] || 'rgba(75, 85, 99, '
@ -429,7 +427,7 @@ export function MultiLevelSuppliesTable({
setContextMenu({ setContextMenu({
isOpen: true, isOpen: true,
position: { x: e.clientX, y: e.clientY }, position: { x: e.clientX, y: e.clientY },
supplyId: supply.id supplyId: supply.id,
}) })
} }
@ -449,7 +447,7 @@ export function MultiLevelSuppliesTable({
} }
// Функция для отображения действий в зависимости от роли пользователя // Функция для отображения действий в зависимости от роли пользователя
const renderActionButtons = (supply: SupplyOrderFromGraphQL) => { const _renderActionButtons = (supply: SupplyOrderFromGraphQL) => {
const { status, id } = supply const { status, id } = supply
switch (userRole) { switch (userRole) {
@ -499,11 +497,14 @@ export function MultiLevelSuppliesTable({
case 'SELLER': // Селлер case 'SELLER': // Селлер
return ( return (
<CancelButton <Button
supplyId={id} size="sm"
status={status} variant="outline"
onCancel={handleCancelSupply} className="text-red-400 border-red-400 hover:bg-red-400/10"
/> onClick={() => handleCancelSupply(id)}
>
Отменить
</Button>
) )
case 'FULFILLMENT': // Фулфилмент case 'FULFILLMENT': // Фулфилмент
@ -666,7 +667,7 @@ export function MultiLevelSuppliesTable({
MozUserSelect: 'none', MozUserSelect: 'none',
msUserSelect: 'none', msUserSelect: 'none',
userSelect: 'none', userSelect: 'none',
backgroundColor: getLevelBackgroundColor(1, index) backgroundColor: getLevelBackgroundColor(1, index),
}} }}
onClick={() => { onClick={() => {
toggleSupplyExpansion(supply.id) toggleSupplyExpansion(supply.id)
@ -787,9 +788,9 @@ export function MultiLevelSuppliesTable({
: [{ : [{
id: `route-${supply.id}`, id: `route-${supply.id}`,
createdDate: supply.deliveryDate, createdDate: supply.deliveryDate,
fromLocation: "Садовод", fromLocation: 'Садовод',
toLocation: "SFERAV Logistics ФФ", toLocation: 'SFERAV Logistics ФФ',
price: 0 price: 0,
}] }]
return mockRoutes.map((route) => { return mockRoutes.map((route) => {
@ -1033,7 +1034,7 @@ export function MultiLevelSuppliesTable({
item.totalPrice + item.totalPrice +
(item.recipe?.services || []).reduce((sum, service) => sum + service.price * item.quantity, 0) + (item.recipe?.services || []).reduce((sum, service) => sum + service.price * item.quantity, 0) +
(item.recipe?.fulfillmentConsumables || []).reduce((sum, consumable) => sum + consumable.price * item.quantity, 0) + (item.recipe?.fulfillmentConsumables || []).reduce((sum, consumable) => sum + consumable.price * item.quantity, 0) +
(item.recipe?.sellerConsumables || []).reduce((sum, consumable) => sum + consumable.price * item.quantity, 0) (item.recipe?.sellerConsumables || []).reduce((sum, consumable) => sum + consumable.price * item.quantity, 0),
)} )}
</span> </span>
</TableCell> </TableCell>

View File

@ -10,8 +10,8 @@ import { Alert, AlertDescription } from '@/components/ui/alert'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { GET_PENDING_SUPPLIES_COUNT, GET_MY_SUPPLY_ORDERS } from '@/graphql/queries' import { GET_PENDING_SUPPLIES_COUNT, GET_MY_SUPPLY_ORDERS } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth' import { useAuth } from '@/hooks/useAuth'
import { useSidebar } from '@/hooks/useSidebar'
import { useRealtime } from '@/hooks/useRealtime' import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
import { AllSuppliesTab } from './fulfillment-supplies/all-supplies-tab' import { AllSuppliesTab } from './fulfillment-supplies/all-supplies-tab'
import { RealSupplyOrdersTab } from './fulfillment-supplies/real-supply-orders-tab' import { RealSupplyOrdersTab } from './fulfillment-supplies/real-supply-orders-tab'

View File

@ -84,7 +84,7 @@ const autoCreateWarehouseEntry = async (sellerId: string, fulfillmentId: string)
products: [], // Пустой массив продуктов products: [], // Пустой массив продуктов
} }
console.warn(`✅ AUTO WAREHOUSE ENTRY CREATED:`, { console.warn('✅ AUTO WAREHOUSE ENTRY CREATED:', {
sellerId, sellerId,
storeName: warehouseEntry.storeName, storeName: warehouseEntry.storeName,
storeOwner: warehouseEntry.storeOwner, storeOwner: warehouseEntry.storeOwner,
@ -933,7 +933,7 @@ export const resolvers = {
userId: context.user.id, userId: context.user.id,
organizationType: currentUser.organization.type, organizationType: currentUser.organization.type,
organizationId: currentUser.organization.id, organizationId: currentUser.organization.id,
organizationName: currentUser.organization.name organizationName: currentUser.organization.name,
}) })
try { try {
@ -990,7 +990,7 @@ export const resolvers = {
acc[order.status] = (acc[order.status] || 0) + 1 acc[order.status] = (acc[order.status] || 0) + 1
return acc return acc
}, {}), }, {}),
orderIds: orders.map(o => o.id) orderIds: orders.map(o => o.id),
}) })
return orders return orders
@ -1770,7 +1770,7 @@ export const resolvers = {
// Получаем всех партнеров-селлеров // Получаем всех партнеров-селлеров
const counterparties = await prisma.counterparty.findMany({ const counterparties = await prisma.counterparty.findMany({
where: { where: {
organizationId: currentUser.organization.id organizationId: currentUser.organization.id,
}, },
include: { include: {
counterparty: true, counterparty: true,
@ -2678,14 +2678,14 @@ export const resolvers = {
...item, ...item,
recipe, recipe,
} }
}) }),
) )
return { return {
...order, ...order,
items: processedItems, items: processedItems,
} }
}) }),
) )
console.warn('✅ Данные обработаны для многоуровневой таблицы') console.warn('✅ Данные обработаны для многоуровневой таблицы')
@ -3868,7 +3868,7 @@ export const resolvers = {
await autoCreateWarehouseEntry(request.senderId, request.receiverId) await autoCreateWarehouseEntry(request.senderId, request.receiverId)
console.warn(`✅ AUTO WAREHOUSE ENTRY: Created for seller ${request.senderId} with fulfillment ${request.receiverId}`) console.warn(`✅ AUTO WAREHOUSE ENTRY: Created for seller ${request.senderId} with fulfillment ${request.receiverId}`)
} catch (error) { } catch (error) {
console.error(`❌ AUTO WAREHOUSE ENTRY ERROR:`, error) console.error('❌ AUTO WAREHOUSE ENTRY ERROR:', error)
// Не прерываем основной процесс, если не удалось создать запись склада // Не прерываем основной процесс, если не удалось создать запись склада
} }
} else if (request.sender.type === 'FULFILLMENT' && request.receiver.type === 'SELLER') { } else if (request.sender.type === 'FULFILLMENT' && request.receiver.type === 'SELLER') {
@ -3877,7 +3877,7 @@ export const resolvers = {
await autoCreateWarehouseEntry(request.receiverId, request.senderId) await autoCreateWarehouseEntry(request.receiverId, request.senderId)
console.warn(`✅ AUTO WAREHOUSE ENTRY: Created for seller ${request.receiverId} with fulfillment ${request.senderId}`) console.warn(`✅ AUTO WAREHOUSE ENTRY: Created for seller ${request.receiverId} with fulfillment ${request.senderId}`)
} catch (error) { } catch (error) {
console.error(`❌ AUTO WAREHOUSE ENTRY ERROR:`, error) console.error('❌ AUTO WAREHOUSE ENTRY ERROR:', error)
} }
} }
} }
@ -5089,7 +5089,7 @@ export const resolvers = {
console.warn('🔍 Автоматическое определение типа расходников:', { console.warn('🔍 Автоматическое определение типа расходников:', {
organizationType: currentUser.organization.type, organizationType: currentUser.organization.type,
consumableType: consumableType, consumableType: consumableType,
inputType: args.input.consumableType // Для отладки inputType: args.input.consumableType, // Для отладки
}) })
// Подготавливаем данные для создания заказа // Подготавливаем данные для создания заказа
@ -5188,7 +5188,7 @@ export const resolvers = {
toAddress: fulfillmentCenterId ? toAddress: fulfillmentCenterId ?
(await prisma.organization.findUnique({ (await prisma.organization.findUnique({
where: { id: fulfillmentCenterId }, where: { id: fulfillmentCenterId },
select: { addressFull: true, address: true } select: { addressFull: true, address: true },
}))?.addressFull || null : null, }))?.addressFull || null : null,
status: 'pending', status: 'pending',
createdDate: new Date(), createdDate: new Date(),

View File

@ -1,4 +1,4 @@
"use client" 'use client'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'