Добавлен новый функционал для обработки заказов поставок расходников в компоненте CreateConsumablesSupplyPage. Реализован выбор фулфилмент-центра, улучшена логика создания заказа с учетом нового поля fulfillmentCenterId. Обновлен компонент SuppliesConsumablesTab для отображения заказов поставок с новыми данными. Оптимизированы стили и структура кода для повышения удобства использования.

This commit is contained in:
Veronika Smirnova
2025-07-24 14:12:20 +03:00
parent 441d2daefb
commit 41228f4c17
6 changed files with 1036 additions and 1170 deletions

View File

@ -97,7 +97,7 @@ const generateToken = (payload: AuthTokenPayload): string => {
const verifyToken = (token: string): AuthTokenPayload => {
try {
return jwt.verify(token, process.env.JWT_SECRET!) as AuthTokenPayload;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
throw new GraphQLError("Недействительный токен", {
extensions: { code: "UNAUTHENTICATED" },
@ -169,7 +169,7 @@ function parseLiteral(ast: unknown): unknown {
fields?: unknown[];
values?: unknown[];
};
switch (astNode.kind) {
case Kind.STRING:
case Kind.BOOLEAN:
@ -291,7 +291,7 @@ export const resolvers = {
// Получаем исходящие заявки для добавления флага hasOutgoingRequest
const outgoingRequests = await prisma.counterpartyRequest.findMany({
where: {
where: {
senderId: currentUser.organization.id,
status: "PENDING",
},
@ -302,7 +302,7 @@ export const resolvers = {
// Получаем входящие заявки для добавления флага hasIncomingRequest
const incomingRequests = await prisma.counterpartyRequest.findMany({
where: {
where: {
receiverId: currentUser.organization.id,
status: "PENDING",
},
@ -366,7 +366,7 @@ export const resolvers = {
const counterparties = await prisma.counterparty.findMany({
where: { organizationId: currentUser.organization.id },
include: {
include: {
counterparty: {
include: {
users: true,
@ -397,7 +397,7 @@ export const resolvers = {
}
return await prisma.counterpartyRequest.findMany({
where: {
where: {
receiverId: currentUser.organization.id,
status: "PENDING",
},
@ -437,7 +437,7 @@ export const resolvers = {
}
return await prisma.counterpartyRequest.findMany({
where: {
where: {
senderId: currentUser.organization.id,
status: { in: ["PENDING", "REJECTED"] },
},
@ -506,7 +506,7 @@ export const resolvers = {
receiverOrganization: {
include: {
users: true,
},
},
},
},
orderBy: { createdAt: "asc" },
@ -537,7 +537,7 @@ export const resolvers = {
// Получаем всех контрагентов
const counterparties = await prisma.counterparty.findMany({
where: { organizationId: currentUser.organization.id },
include: {
include: {
counterparty: {
include: {
users: true,
@ -550,7 +550,7 @@ export const resolvers = {
const conversations = await Promise.all(
counterparties.map(async (cp) => {
const counterpartyId = cp.counterparty.id;
// Последнее сообщение с этим контрагентом
const lastMessage = await prisma.message.findFirst({
where: {
@ -608,7 +608,10 @@ export const resolvers = {
// Фильтруем null значения и сортируем по времени последнего сообщения
return conversations
.filter((conv) => conv !== null)
.sort((a, b) => new Date(b!.updatedAt).getTime() - new Date(a!.updatedAt).getTime());
.sort(
(a, b) =>
new Date(b!.updatedAt).getTime() - new Date(a!.updatedAt).getTime()
);
},
// Мои услуги
@ -664,6 +667,57 @@ export const resolvers = {
});
},
// Заказы поставок расходников
supplyOrders: async (_: unknown, __: unknown, context: Context) => {
if (!context.user) {
throw new GraphQLError("Требуется авторизация", {
extensions: { code: "UNAUTHENTICATED" },
});
}
const currentUser = await prisma.user.findUnique({
where: { id: context.user.id },
include: { organization: true },
});
if (!currentUser?.organization) {
throw new GraphQLError("У пользователя нет организации");
}
// Возвращаем заказы где текущая организация является заказчиком или поставщиком
return await prisma.supplyOrder.findMany({
where: {
OR: [
{ organizationId: currentUser.organization.id }, // Заказы созданные организацией
{ partnerId: currentUser.organization.id }, // Заказы где организация - поставщик
],
},
include: {
partner: {
include: {
users: true,
},
},
organization: {
include: {
users: true,
},
},
items: {
include: {
product: {
include: {
category: true,
organization: true,
},
},
},
},
},
orderBy: { createdAt: "desc" },
});
},
// Логистика организации
myLogistics: async (_: unknown, __: unknown, context: Context) => {
if (!context.user) {
@ -743,7 +797,7 @@ export const resolvers = {
return await prisma.product.findMany({
where: { organizationId: currentUser.organization.id },
include: {
include: {
category: true,
organization: true,
},
@ -785,7 +839,7 @@ export const resolvers = {
return await prisma.product.findMany({
where,
include: {
include: {
category: true,
organization: {
include: {
@ -899,7 +953,9 @@ export const resolvers = {
});
if (!targetOrganization || targetOrganization.type !== "FULFILLMENT") {
throw new GraphQLError("Расходники доступны только у фулфилмент центров");
throw new GraphQLError(
"Расходники доступны только у фулфилмент центров"
);
}
return await prisma.supply.findMany({
@ -1068,7 +1124,7 @@ export const resolvers = {
}
const employee = await prisma.employee.findFirst({
where: {
where: {
id: args.id,
organizationId: currentUser.organization.id,
},
@ -1155,7 +1211,7 @@ export const resolvers = {
args.phone,
args.code
);
if (!verificationResult.success) {
return {
success: false,
@ -1214,7 +1270,7 @@ export const resolvers = {
};
console.log("verifySmsCode - Returning result:", {
success: result.success,
success: result.success,
hasToken: !!result.token,
hasUser: !!result.user,
message: result.message,
@ -1318,28 +1374,28 @@ export const resolvers = {
addressFull: organizationData.addressFull,
ogrn: organizationData.ogrn,
ogrnDate: organizationData.ogrnDate,
// Статус организации
status: organizationData.status,
actualityDate: organizationData.actualityDate,
registrationDate: organizationData.registrationDate,
liquidationDate: organizationData.liquidationDate,
// Руководитель
managementName: organizationData.managementName,
managementPost: organizationData.managementPost,
// ОПФ
opfCode: organizationData.opfCode,
opfFull: organizationData.opfFull,
opfShort: organizationData.opfShort,
// Коды статистики
okato: organizationData.okato,
oktmo: organizationData.oktmo,
okpo: organizationData.okpo,
okved: organizationData.okved,
// Контакты
phones: organizationData.phones
? JSON.parse(JSON.stringify(organizationData.phones))
@ -1347,12 +1403,12 @@ export const resolvers = {
emails: organizationData.emails
? JSON.parse(JSON.stringify(organizationData.emails))
: null,
// Финансовые данные
employeeCount: organizationData.employeeCount,
revenue: organizationData.revenue,
taxSystem: organizationData.taxSystem,
type: type,
dadataData: JSON.parse(JSON.stringify(organizationData.rawData)),
},
@ -1455,7 +1511,7 @@ export const resolvers = {
const tradeMark = validationResults[0]?.data?.tradeMark;
const sellerName = validationResults[0]?.data?.sellerName;
const shopName = tradeMark || sellerName || "Магазин";
const organization = await prisma.organization.create({
data: {
inn:
@ -1598,7 +1654,7 @@ export const resolvers = {
where: { id: existingKey.id },
data: {
apiKey,
validationData: JSON.parse(JSON.stringify(validationResult.data)),
validationData: JSON.parse(JSON.stringify(validationResult.data)),
isActive: true,
},
});
@ -1624,7 +1680,7 @@ export const resolvers = {
message: "API ключ успешно добавлен",
apiKey: newKey,
};
}
}
} catch (error) {
console.error("Error adding marketplace API key:", error);
return {
@ -1697,7 +1753,7 @@ export const resolvers = {
const user = await prisma.user.findUnique({
where: { id: context.user.id },
include: {
include: {
organization: {
include: {
apiKeys: true,
@ -1712,7 +1768,7 @@ export const resolvers = {
try {
const { input } = args;
// Обновляем данные пользователя (аватар, имя управляющего)
const userUpdateData: { avatar?: string; managerName?: string } = {};
if (input.avatar) {
@ -1721,14 +1777,14 @@ export const resolvers = {
if (input.managerName) {
userUpdateData.managerName = input.managerName;
}
if (Object.keys(userUpdateData).length > 0) {
await prisma.user.update({
where: { id: context.user.id },
data: userUpdateData,
});
}
// Подготавливаем данные для обновления организации
const updateData: {
phones?: object;
@ -1736,20 +1792,20 @@ export const resolvers = {
managementName?: string;
managementPost?: string;
} = {};
// Название организации больше не обновляется через профиль
// Для селлеров устанавливается при регистрации, для остальных - при смене ИНН
// Обновляем контактные данные в JSON поле phones
if (input.orgPhone) {
updateData.phones = [{ value: input.orgPhone, type: "main" }];
}
// Обновляем email в JSON поле emails
// Обновляем email в JSON поле emails
if (input.email) {
updateData.emails = [{ value: input.email, type: "main" }];
}
// Сохраняем дополнительные контакты в custom полях
// Пока добавим их как дополнительные JSON поля
const customContacts: {
@ -1763,13 +1819,13 @@ export const resolvers = {
corrAccount?: string;
};
} = {};
// managerName теперь сохраняется в поле пользователя, а не в JSON
if (input.telegram) {
customContacts.telegram = input.telegram;
}
if (input.whatsapp) {
customContacts.whatsapp = input.whatsapp;
}
@ -1787,7 +1843,7 @@ export const resolvers = {
corrAccount: input.corrAccount,
};
}
// Если есть дополнительные контакты, сохраним их в поле managementPost временно
// В идеале нужно добавить отдельную таблицу для контактов
if (Object.keys(customContacts).length > 0) {
@ -1806,7 +1862,7 @@ export const resolvers = {
// Получаем обновленного пользователя
const updatedUser = await prisma.user.findUnique({
where: { id: context.user.id },
include: {
include: {
organization: {
include: {
apiKeys: true,
@ -1842,7 +1898,7 @@ export const resolvers = {
const user = await prisma.user.findUnique({
where: { id: context.user.id },
include: {
include: {
organization: {
include: {
apiKeys: true,
@ -1940,7 +1996,7 @@ export const resolvers = {
// Получаем обновленного пользователя
const updatedUser = await prisma.user.findUnique({
where: { id: context.user.id },
include: {
include: {
organization: {
include: {
apiKeys: true,
@ -2591,8 +2647,8 @@ export const resolvers = {
}
// conversationId имеет формат "currentOrgId-counterpartyId"
const [, counterpartyId] = args.conversationId.split('-');
const [, counterpartyId] = args.conversationId.split("-");
if (!counterpartyId) {
throw new GraphQLError("Неверный ID беседы");
}
@ -2989,13 +3045,22 @@ export const resolvers = {
},
// Создать заказ поставки расходников
// Процесс: Селлер → Поставщик → Логистика → Фулфилмент
// 1. Селлер создает заказ у поставщика расходников
// 2. Поставщик получает заказ и готовит товары
// 3. Логистика транспортирует товары на склад фулфилмента
// 4. Фулфилмент принимает товары на склад
// 5. Все участники видят информацию о поставке в своих кабинетах
createSupplyOrder: async (
_: unknown,
args: {
input: {
partnerId: string;
deliveryDate: string;
fulfillmentCenterId?: string; // ID фулфилмент-центра для доставки
logisticsPartnerId?: string; // ID логистической компании
items: Array<{ productId: string; quantity: number }>;
notes?: string; // Дополнительные заметки к заказу
};
},
context: Context
@ -3015,13 +3080,40 @@ export const resolvers = {
throw new GraphQLError("У пользователя нет организации");
}
// Проверяем, что это фулфилмент центр
if (currentUser.organization.type !== "FULFILLMENT") {
// Проверяем тип организации и определяем роль в процессе поставки
const allowedTypes = ["FULFILLMENT", "SELLER", "LOGIST"];
if (!allowedTypes.includes(currentUser.organization.type)) {
throw new GraphQLError(
"Заказы поставок доступны только для фулфилмент центров"
"Заказы поставок недоступны для данного типа организации"
);
}
// Определяем роль организации в процессе поставки
const organizationRole = currentUser.organization.type;
let fulfillmentCenterId = args.input.fulfillmentCenterId;
// Если заказ создает фулфилмент-центр, он сам является получателем
if (organizationRole === "FULFILLMENT") {
fulfillmentCenterId = currentUser.organization.id;
}
// Если указан фулфилмент-центр, проверяем его существование
if (fulfillmentCenterId) {
const fulfillmentCenter = await prisma.organization.findFirst({
where: {
id: fulfillmentCenterId,
type: "FULFILLMENT",
},
});
if (!fulfillmentCenter) {
return {
success: false,
message: "Указанный фулфилмент-центр не найден",
};
}
}
// Проверяем, что партнер существует и является оптовиком
const partner = await prisma.organization.findFirst({
where: {
@ -3104,6 +3196,16 @@ export const resolvers = {
});
try {
// Определяем начальный статус в зависимости от роли организации
let initialStatus = "PENDING";
if (organizationRole === "SELLER") {
initialStatus = "PENDING"; // Селлер создает заказ, ждет подтверждения поставщика
} else if (organizationRole === "FULFILLMENT") {
initialStatus = "PENDING"; // Фулфилмент заказывает для своего склада
} else if (organizationRole === "LOGIST") {
initialStatus = "CONFIRMED"; // Логист может сразу подтверждать заказы
}
const supplyOrder = await prisma.supplyOrder.create({
data: {
partnerId: args.input.partnerId,
@ -3111,6 +3213,7 @@ export const resolvers = {
totalAmount: new Prisma.Decimal(totalAmount),
totalItems: totalItems,
organizationId: currentUser.organization.id,
status: initialStatus as any,
items: {
create: orderItems,
},
@ -3145,7 +3248,7 @@ export const resolvers = {
const productWithCategory = supplyOrder.items.find(
(orderItem) => orderItem.productId === item.productId
)?.product;
return {
name: product.name,
description: product.description || `Заказано у ${partner.name}`,
@ -3167,10 +3270,31 @@ export const resolvers = {
data: suppliesData,
});
// Формируем сообщение в зависимости от роли организации
let successMessage = "";
if (organizationRole === "SELLER") {
successMessage = `Заказ поставки расходников создан! Расходники будут доставлены ${
fulfillmentCenterId
? "на указанный фулфилмент-склад"
: "согласно настройкам"
}. Ожидайте подтверждения от поставщика.`;
} else if (organizationRole === "FULFILLMENT") {
successMessage = `Заказ поставки расходников создан для вашего склада! Ожидайте подтверждения от поставщика и координации с логистикой.`;
} else if (organizationRole === "LOGIST") {
successMessage = `Заказ поставки создан и подтвержден! Координируйте доставку расходников от поставщика на фулфилмент-склад.`;
}
return {
success: true,
message: `Заказ поставки создан успешно! Добавлено ${suppliesData.length} расходников в каталог.`,
message: successMessage,
order: supplyOrder,
processInfo: {
role: organizationRole,
supplier: partner.name || partner.fullName,
fulfillmentCenter: fulfillmentCenterId,
logistics: args.input.logisticsPartnerId,
status: initialStatus,
},
};
} catch (error) {
console.error("Error creating supply order:", error);
@ -3185,22 +3309,22 @@ export const resolvers = {
createProduct: async (
_: unknown,
args: {
input: {
name: string;
article: string;
description?: string;
price: number;
quantity: number;
categoryId?: string;
brand?: string;
color?: string;
size?: string;
weight?: number;
dimensions?: string;
material?: string;
images?: string[];
mainImage?: string;
isActive?: boolean;
input: {
name: string;
article: string;
description?: string;
price: number;
quantity: number;
categoryId?: string;
brand?: string;
color?: string;
size?: string;
weight?: number;
dimensions?: string;
material?: string;
images?: string[];
mainImage?: string;
isActive?: boolean;
};
},
context: Context
@ -3260,7 +3384,7 @@ export const resolvers = {
isActive: args.input.isActive ?? true,
organizationId: currentUser.organization.id,
},
include: {
include: {
category: true,
organization: true,
},
@ -3284,23 +3408,23 @@ export const resolvers = {
updateProduct: async (
_: unknown,
args: {
id: string;
input: {
name: string;
article: string;
description?: string;
price: number;
quantity: number;
categoryId?: string;
brand?: string;
color?: string;
size?: string;
weight?: number;
dimensions?: string;
material?: string;
images?: string[];
mainImage?: string;
isActive?: boolean;
id: string;
input: {
name: string;
article: string;
description?: string;
price: number;
quantity: number;
categoryId?: string;
brand?: string;
color?: string;
size?: string;
weight?: number;
dimensions?: string;
material?: string;
images?: string[];
mainImage?: string;
isActive?: boolean;
};
},
context: Context
@ -3366,11 +3490,13 @@ export const resolvers = {
weight: args.input.weight,
dimensions: args.input.dimensions,
material: args.input.material,
images: args.input.images ? JSON.stringify(args.input.images) : undefined,
images: args.input.images
? JSON.stringify(args.input.images)
: undefined,
mainImage: args.input.mainImage,
isActive: args.input.isActive ?? true,
},
include: {
include: {
category: true,
organization: true,
},
@ -3655,7 +3781,7 @@ export const resolvers = {
if (existingCartItem) {
// Обновляем количество
const newQuantity = existingCartItem.quantity + args.quantity;
if (newQuantity > product.quantity) {
return {
success: false,
@ -4195,7 +4321,7 @@ export const resolvers = {
try {
const employee = await prisma.employee.update({
where: {
where: {
id: args.id,
organizationId: currentUser.organization.id,
},
@ -4257,7 +4383,7 @@ export const resolvers = {
try {
await prisma.employee.delete({
where: {
where: {
id: args.id,
organizationId: currentUser.organization.id,
},
@ -4405,7 +4531,7 @@ export const resolvers = {
if (parent.users) {
return parent.users;
}
// Иначе загружаем отдельно
return await prisma.user.findMany({
where: { organizationId: parent.id },
@ -4416,7 +4542,7 @@ export const resolvers = {
if (parent.services) {
return parent.services;
}
// Иначе загружаем отдельно
return await prisma.service.findMany({
where: { organizationId: parent.id },
@ -4429,7 +4555,7 @@ export const resolvers = {
if (parent.supplies) {
return parent.supplies;
}
// Иначе загружаем отдельно
return await prisma.supply.findMany({
where: { organizationId: parent.id },
@ -4478,7 +4604,7 @@ export const resolvers = {
if (parent.organization) {
return parent.organization;
}
// Иначе загружаем отдельно если есть organizationId
if (parent.organizationId) {
return await prisma.organization.findUnique({
@ -4497,7 +4623,7 @@ export const resolvers = {
Product: {
images: (parent: { images: unknown }) => {
// Если images это строка JSON, парсим её в массив
if (typeof parent.images === 'string') {
if (typeof parent.images === "string") {
try {
return JSON.parse(parent.images);
} catch {
@ -4814,14 +4940,14 @@ const adminQueries = {
const limit = args.limit || 50;
const offset = args.offset || 0;
// Строим условие поиска
const whereCondition: Prisma.UserWhereInput = args.search
? {
OR: [
{ phone: { contains: args.search, mode: "insensitive" } },
{ managerName: { contains: args.search, mode: "insensitive" } },
{
{
organization: {
OR: [
{ name: { contains: args.search, mode: "insensitive" } },
@ -4889,7 +5015,7 @@ const adminMutations = {
args.password,
admin.password
);
if (!isPasswordValid) {
return {
success: false,
@ -4905,7 +5031,7 @@ const adminMutations = {
// Создать токен
const token = jwt.sign(
{
{
adminId: admin.id,
username: admin.username,
type: "admin",
@ -4963,19 +5089,19 @@ const wildberriesQueries = {
organization: {
include: {
apiKeys: true,
}
},
},
},
});
if (!user?.organization || user.organization.type !== 'SELLER') {
if (!user?.organization || user.organization.type !== "SELLER") {
throw new GraphQLError("Доступно только для продавцов");
}
const wbApiKeyRecord = user.organization.apiKeys?.find(
key => key.marketplace === 'WILDBERRIES' && key.isActive
(key) => key.marketplace === "WILDBERRIES" && key.isActive
);
if (!wbApiKeyRecord) {
throw new GraphQLError("WB API ключ не настроен");
}
@ -4985,8 +5111,8 @@ const wildberriesQueries = {
// Получаем кампании во всех статусах
const [active, completed, paused] = await Promise.all([
wbService.getAdverts(9).catch(() => []), // активные
wbService.getAdverts(7).catch(() => []), // завершенные
wbService.getAdverts(11).catch(() => []) // на паузе
wbService.getAdverts(7).catch(() => []), // завершенные
wbService.getAdverts(11).catch(() => []), // на паузе
]);
const allCampaigns = [...active, ...completed, ...paused];
@ -4995,30 +5121,34 @@ const wildberriesQueries = {
success: true,
message: `Found ${active.length} active, ${completed.length} completed, ${paused.length} paused campaigns`,
campaignsCount: allCampaigns.length,
campaigns: allCampaigns.map(c => ({
campaigns: allCampaigns.map((c) => ({
id: c.advertId,
name: c.name,
status: c.status,
type: c.type
}))
type: c.type,
})),
};
} catch (error) {
console.error('Error debugging WB adverts:', error);
console.error("Error debugging WB adverts:", error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error',
message: error instanceof Error ? error.message : "Unknown error",
campaignsCount: 0,
campaigns: []
campaigns: [],
};
}
},
getWildberriesStatistics: async (
_: unknown,
{ period, startDate, endDate }: {
period?: 'week' | 'month' | 'quarter'
startDate?: string
endDate?: string
{
period,
startDate,
endDate,
}: {
period?: "week" | "month" | "quarter";
startDate?: string;
endDate?: string;
},
context: Context
) => {
@ -5036,7 +5166,7 @@ const wildberriesQueries = {
organization: {
include: {
apiKeys: true,
}
},
},
},
});
@ -5045,14 +5175,14 @@ const wildberriesQueries = {
throw new GraphQLError("Организация не найдена");
}
if (user.organization.type !== 'SELLER') {
if (user.organization.type !== "SELLER") {
throw new GraphQLError("Доступно только для продавцов");
}
const wbApiKeyRecord = user.organization.apiKeys?.find(
key => key.marketplace === 'WILDBERRIES' && key.isActive
(key) => key.marketplace === "WILDBERRIES" && key.isActive
);
if (!wbApiKeyRecord) {
throw new GraphQLError("WB API ключ не настроен");
}
@ -5073,7 +5203,9 @@ const wildberriesQueries = {
dateFrom = WildberriesService.getDatePeriodAgo(period);
dateTo = WildberriesService.formatDate(new Date());
} else {
throw new GraphQLError("Необходимо указать либо period, либо startDate и endDate");
throw new GraphQLError(
"Необходимо указать либо period, либо startDate и endDate"
);
}
// Получаем статистику
@ -5082,13 +5214,16 @@ const wildberriesQueries = {
return {
success: true,
data: statistics,
message: null
message: null,
};
} catch (error) {
console.error('Error fetching WB statistics:', error);
console.error("Error fetching WB statistics:", error);
return {
success: false,
message: error instanceof Error ? error.message : 'Ошибка получения статистики',
message:
error instanceof Error
? error.message
: "Ошибка получения статистики",
data: [],
};
}
@ -5096,17 +5231,19 @@ const wildberriesQueries = {
getWildberriesCampaignStats: async (
_: unknown,
{ input }: {
{
input,
}: {
input: {
campaigns: Array<{
id: number
dates?: string[]
id: number;
dates?: string[];
interval?: {
begin: string
end: string
}
}>
}
begin: string;
end: string;
};
}>;
};
},
context: Context
) => {
@ -5124,7 +5261,7 @@ const wildberriesQueries = {
organization: {
include: {
apiKeys: true,
}
},
},
},
});
@ -5133,14 +5270,14 @@ const wildberriesQueries = {
throw new GraphQLError("Организация не найдена");
}
if (user.organization.type !== 'SELLER') {
if (user.organization.type !== "SELLER") {
throw new GraphQLError("Доступно только для продавцов");
}
const wbApiKeyRecord = user.organization.apiKeys?.find(
key => key.marketplace === 'WILDBERRIES' && key.isActive
(key) => key.marketplace === "WILDBERRIES" && key.isActive
);
if (!wbApiKeyRecord) {
throw new GraphQLError("WB API ключ не настроен");
}
@ -5149,21 +5286,21 @@ const wildberriesQueries = {
const wbService = new WildberriesService(wbApiKeyRecord.apiKey);
// Преобразуем запросы в нужный формат
const requests = input.campaigns.map(campaign => {
const requests = input.campaigns.map((campaign) => {
if (campaign.dates && campaign.dates.length > 0) {
return {
id: campaign.id,
dates: campaign.dates
dates: campaign.dates,
};
} else if (campaign.interval) {
return {
id: campaign.id,
interval: campaign.interval
interval: campaign.interval,
};
} else {
// Если не указаны ни даты, ни интервал, возвращаем данные только за последние сутки
return {
id: campaign.id
id: campaign.id,
};
}
});
@ -5174,13 +5311,16 @@ const wildberriesQueries = {
return {
success: true,
data: campaignStats,
message: null
message: null,
};
} catch (error) {
console.error('Error fetching WB campaign stats:', error);
console.error("Error fetching WB campaign stats:", error);
return {
success: false,
message: error instanceof Error ? error.message : 'Ошибка получения статистики кампаний',
message:
error instanceof Error
? error.message
: "Ошибка получения статистики кампаний",
data: [],
};
}