-
+ |
+
+
+
+
+ Дата создания:{" "}
+ {formatDate(order.createdAt)}
+
+
+
+
+
+ Поставщик:{" "}
+ {order.partner.name ||
+ order.partner.fullName}
+
+
+
Состав заказа:
diff --git a/src/components/fulfillment-supplies/fulfillment-supplies/fulfillment-supplies-tab.tsx b/src/components/fulfillment-supplies/fulfillment-supplies/fulfillment-supplies-tab.tsx
index 4be6b05..d98f3cf 100644
--- a/src/components/fulfillment-supplies/fulfillment-supplies/fulfillment-supplies-tab.tsx
+++ b/src/components/fulfillment-supplies/fulfillment-supplies/fulfillment-supplies-tab.tsx
@@ -39,6 +39,10 @@ export function FulfillmentSuppliesTab() {
});
const pendingCount = pendingData?.pendingSuppliesCount?.total || 0;
+ const ourSupplyOrdersCount =
+ pendingData?.pendingSuppliesCount?.ourSupplyOrders || 0;
+ const sellerSupplyOrdersCount =
+ pendingData?.pendingSuppliesCount?.sellerSupplyOrders || 0;
// Проверяем URL параметр при загрузке
useEffect(() => {
@@ -79,12 +83,13 @@ export function FulfillmentSuppliesTab() {
Наши расходники
Наши
Н
+
Расходники селлеров
Селлеры
С
-
+
{
+ return (
+ order.organizationId !== currentOrganizationId && // Создали НЕ мы (селлер)
+ order.fulfillmentCenterId === currentOrganizationId // Получатель - мы
+ );
+ });
+
const formatCurrency = (amount: number) => {
return new Intl.NumberFormat("ru-RU", {
style: "currency",
@@ -76,58 +99,83 @@ export function SellerMaterialsTab() {
const getStatusBadge = (status: string) => {
const statusConfig = {
- planned: {
+ PENDING: {
color: "text-blue-300 border-blue-400/30",
- label: "Запланировано",
+ label: "Ожидает подтверждения",
},
- "in-transit": {
+ CONFIRMED: {
color: "text-yellow-300 border-yellow-400/30",
+ label: "Подтверждено",
+ },
+ IN_TRANSIT: {
+ color: "text-orange-300 border-orange-400/30",
label: "В пути",
},
- delivered: {
+ DELIVERED: {
color: "text-green-300 border-green-400/30",
label: "Доставлено",
},
- "in-processing": {
- color: "text-purple-300 border-purple-400/30",
- label: "Обрабатывается",
+ CANCELLED: {
+ color: "text-red-300 border-red-400/30",
+ label: "Отменено",
},
};
const config =
- statusConfig[status as keyof typeof statusConfig] || statusConfig.planned;
-
- return (
-
- {config.label}
-
- );
+ statusConfig[status as keyof typeof statusConfig] || statusConfig.PENDING;
+ return {config.label};
};
- const filteredMaterials = mockSellerMaterials.filter((material) => {
+ // Фильтрация поставок
+ const filteredOrders = sellerSupplyOrders.filter((order) => {
const matchesSearch =
- material.materialName.toLowerCase().includes(searchTerm.toLowerCase()) ||
- material.seller.toLowerCase().includes(searchTerm.toLowerCase()) ||
- material.category.toLowerCase().includes(searchTerm.toLowerCase());
+ order.organization.name
+ ?.toLowerCase()
+ .includes(searchTerm.toLowerCase()) ||
+ order.organization.fullName
+ ?.toLowerCase()
+ .includes(searchTerm.toLowerCase()) ||
+ order.items.some((item) =>
+ item.product.name.toLowerCase().includes(searchTerm.toLowerCase())
+ );
const matchesStatus =
- statusFilter === "all" || material.status === statusFilter;
+ statusFilter === "all" || order.status === statusFilter;
return matchesSearch && matchesStatus;
});
- const getTotalValue = () => {
- return filteredMaterials.reduce(
- (sum, material) => sum + material.totalValue,
- 0
+ if (loading) {
+ return (
+
+
+
+ Загрузка расходников селлеров...
+
+
);
+ }
+
+ if (error) {
+ return (
+
+
+
+
+ Ошибка загрузки расходников селлеров
+
+ {error.message}
+
+
+ );
+ }
+
+ const getTotalValue = () => {
+ return filteredOrders.reduce((sum, order) => sum + order.totalAmount, 0);
};
const getTotalQuantity = () => {
- return filteredMaterials.reduce(
- (sum, material) => sum + material.quantity,
- 0
- );
+ return filteredOrders.reduce((sum, order) => sum + order.totalItems, 0);
};
return (
@@ -143,7 +191,7 @@ export function SellerMaterialsTab() {
Поставок
- {filteredMaterials.length}
+ {filteredOrders.length}
@@ -205,49 +253,67 @@ export function SellerMaterialsTab() {
className="glass-input text-white text-sm px-3 py-2 rounded-lg bg-white/5 border border-white/10"
>
-
-
-
-
+
+
+
+
+
{/* Список материалов */}
-
- {filteredMaterials.map((material) => (
+ {filteredOrders.length === 0 ? (
+
+
+
+
+ Нет поставок от селлеров
+
+
+ Здесь будут отображаться расходники, которые селлеры заказывают для доставки на ваш склад.
+
+
+
+ ) : (
+
+ {filteredOrders.map((order) => (
- {material.materialName}
+ {order.organization.name || order.organization.fullName}
- {getStatusBadge(material.status)}
+ {getStatusBadge(order.status)}
Селлер
- {material.seller}
+
+ {order.organization.name || order.organization.fullName}
+
- Категория
- {material.category}
+ Дата доставки
+
+ {formatDate(order.deliveryDate)}
+
Количество
- {material.quantity.toLocaleString()} шт.
+ {order.totalItems.toLocaleString()} шт.
- Ожидается
-
- {formatDate(material.expectedDate)}
+ Общая стоимость
+
+ {formatCurrency(order.totalAmount)}
@@ -255,15 +321,9 @@ export function SellerMaterialsTab() {
- Цена за ед.:{" "}
+ Дата заказа:{" "}
- {formatCurrency(material.unitPrice)}
-
-
-
- Общая стоимость:{" "}
-
- {formatCurrency(material.totalValue)}
+ {formatDate(order.createdAt)}
@@ -271,8 +331,8 @@ export function SellerMaterialsTab() {
- Назначение:{" "}
- {material.purpose}
+ Статус:{" "}
+ {order.status}
@@ -289,7 +349,8 @@ export function SellerMaterialsTab() {
))}
-
+
+ )}
);
diff --git a/src/graphql/queries.ts b/src/graphql/queries.ts
index 418acdd..9ccd61d 100644
--- a/src/graphql/queries.ts
+++ b/src/graphql/queries.ts
@@ -827,7 +827,7 @@ export const GET_WILDBERRIES_CAMPAIGNS_LIST = gql`
}
}
}
-`
+`;
export const GET_EXTERNAL_ADS = gql`
query GetExternalAds($dateFrom: String!, $dateTo: String!) {
@@ -948,6 +948,8 @@ export const GET_PENDING_SUPPLIES_COUNT = gql`
query GetPendingSuppliesCount {
pendingSuppliesCount {
supplyOrders
+ ourSupplyOrders
+ sellerSupplyOrders
incomingRequests
total
}
diff --git a/src/graphql/resolvers.ts b/src/graphql/resolvers.ts
index 37fbc6f..d1409b9 100644
--- a/src/graphql/resolvers.ts
+++ b/src/graphql/resolvers.ts
@@ -790,28 +790,28 @@ export const resolvers = {
}
// Считаем заказы поставок, требующие действий
- const pendingSupplyOrders = await prisma.supplyOrder.count({
+
+ // Наши расходники (созданные нами для себя) - требуют действий по статусам
+ const ourSupplyOrders = await prisma.supplyOrder.count({
where: {
- OR: [
- // Заказы со статусом PENDING где мы - поставщик (нужно подтвердить)
- {
- status: "PENDING",
- partnerId: currentUser.organization.id,
- },
- // Заказы со статусом PENDING где мы - получатель ФФ (нужно подтвердить)
- {
- status: "PENDING",
- fulfillmentCenterId: currentUser.organization.id,
- },
- // Заказы со статусом IN_TRANSIT где мы - получатель ФФ (нужно подтвердить получение)
- {
- status: "IN_TRANSIT",
- fulfillmentCenterId: currentUser.organization.id,
- },
- ],
+ organizationId: currentUser.organization.id, // Создали мы
+ fulfillmentCenterId: currentUser.organization.id, // Получатель - мы
+ status: { in: ["CONFIRMED", "IN_TRANSIT"] }, // Подтверждено или в пути
},
});
+ // Расходники селлеров (созданные другими для нас) - требуют подтверждения получения
+ const sellerSupplyOrders = await prisma.supplyOrder.count({
+ where: {
+ fulfillmentCenterId: currentUser.organization.id, // Получатель - мы
+ organizationId: { not: currentUser.organization.id }, // Создали НЕ мы
+ status: "IN_TRANSIT", // В пути - нужно подтвердить получение
+ },
+ });
+
+ // Общий счетчик поставок
+ const pendingSupplyOrders = ourSupplyOrders + sellerSupplyOrders;
+
// Считаем входящие заявки на партнерство со статусом PENDING
const pendingIncomingRequests = await prisma.counterpartyRequest.count({
where: {
@@ -822,6 +822,8 @@ export const resolvers = {
return {
supplyOrders: pendingSupplyOrders,
+ ourSupplyOrders: ourSupplyOrders, // Наши расходники
+ sellerSupplyOrders: sellerSupplyOrders, // Расходники селлеров
incomingRequests: pendingIncomingRequests,
total: pendingSupplyOrders + pendingIncomingRequests,
};
@@ -3284,12 +3286,16 @@ export const resolvers = {
},
// Создать заказ поставки расходников
- // Процесс: Селлер → Поставщик → Логистика → Фулфилмент
- // 1. Селлер создает заказ у поставщика расходников
+ // Два сценария:
+ // 1. Селлер → Поставщик → Фулфилмент (селлер заказывает для фулфилмент-центра)
+ // 2. Фулфилмент → Поставщик → Фулфилмент (фулфилмент заказывает для себя)
+ //
+ // Процесс: Заказчик → Поставщик → [Логистика] → Фулфилмент
+ // 1. Заказчик (селлер или фулфилмент) создает заказ у поставщика расходников
// 2. Поставщик получает заказ и готовит товары
// 3. Логистика транспортирует товары на склад фулфилмента
// 4. Фулфилмент принимает товары на склад
- // 5. Все участники видят информацию о поставке в своих кабинетах
+ // 5. Расходники создаются в системе фулфилмент-центра
createSupplyOrder: async (
_: unknown,
args: {
@@ -3488,6 +3494,7 @@ export const resolvers = {
});
// Создаем расходники на основе заказанных товаров
+ // Расходники создаются в организации получателя (фулфилмент-центре)
const suppliesData = args.input.items.map((item) => {
const product = products.find((p) => p.id === item.productId)!;
const productWithCategory = supplyOrder.items.find(
@@ -3506,7 +3513,8 @@ export const resolvers = {
supplier: partner.name || partner.fullName || "Не указан",
minStock: Math.round(item.quantity * 0.1), // 10% от заказанного как минимальный остаток
currentStock: 0, // Пока товар не пришел
- organizationId: currentUser.organization!.id,
+ // Расходники создаются в организации получателя (фулфилмент-центре)
+ organizationId: fulfillmentCenterId || currentUser.organization!.id,
};
});
diff --git a/src/graphql/typedefs.ts b/src/graphql/typedefs.ts
index d0d388b..cb7557d 100644
--- a/src/graphql/typedefs.ts
+++ b/src/graphql/typedefs.ts
@@ -602,6 +602,8 @@ export const typeDefs = gql`
type PendingSuppliesCount {
supplyOrders: Int!
+ ourSupplyOrders: Int! # Наши расходники
+ sellerSupplyOrders: Int! # Расходники селлеров
incomingRequests: Int!
total: Int!
}
|