Добавлены новые зависимости для работы с графиками и статистикой, включая @radix-ui/react-popover, date-fns и react-day-picker. Обновлены компоненты для отображения статистики продаж, улучшена агрегация данных и добавлены функции сортировки в таблицах. Обновлены API маршруты для получения данных о статистике Wildberries. Оптимизирован код для повышения читаемости и производительности.

This commit is contained in:
Bivekich
2025-07-22 14:47:44 +03:00
parent a62a09faca
commit 20c4b665a1
15 changed files with 1688 additions and 486 deletions

View File

@ -645,6 +645,75 @@ export const GET_COUNTERPARTY_SUPPLIES = gql`
}
`
// Wildberries запросы
export const GET_WILDBERRIES_STATISTICS = gql`
query GetWildberriesStatistics($period: String, $startDate: String, $endDate: String) {
getWildberriesStatistics(period: $period, startDate: $startDate, endDate: $endDate) {
success
message
data {
date
sales
orders
advertising
refusals
returns
revenue
buyoutPercentage
}
}
}
`
export const GET_WILDBERRIES_CAMPAIGN_STATS = gql`
query GetWildberriesCampaignStats($input: WildberriesCampaignStatsInput!) {
getWildberriesCampaignStats(input: $input) {
success
message
data {
advertId
views
clicks
ctr
cpc
sum
atbs
orders
cr
shks
sum_price
dates
days {
date
views
clicks
ctr
cpc
sum
atbs
orders
cr
shks
sum_price
}
boosterStats {
date
views
clicks
ctr
cpc
sum
atbs
orders
cr
shks
sum_price
}
}
}
}
`
// Админ запросы
export const ADMIN_ME = gql`
query AdminMe {

View File

@ -5093,6 +5093,98 @@ const wildberriesQueries = {
};
}
},
getWildberriesCampaignStats: async (
_: unknown,
{ input }: {
input: {
campaigns: Array<{
id: number
dates?: string[]
interval?: {
begin: string
end: string
}
}>
}
},
context: Context
) => {
if (!context.user) {
throw new GraphQLError("Требуется авторизация", {
extensions: { code: "UNAUTHENTICATED" },
});
}
try {
// Получаем организацию пользователя и её WB API ключ
const user = await prisma.user.findUnique({
where: { id: context.user.id },
include: {
organization: {
include: {
apiKeys: true,
}
},
},
});
if (!user?.organization) {
throw new GraphQLError("Организация не найдена");
}
if (user.organization.type !== 'SELLER') {
throw new GraphQLError("Доступно только для продавцов");
}
const wbApiKeyRecord = user.organization.apiKeys?.find(
key => key.marketplace === 'WILDBERRIES' && key.isActive
);
if (!wbApiKeyRecord) {
throw new GraphQLError("WB API ключ не настроен");
}
// Создаем экземпляр сервиса
const wbService = new WildberriesService(wbApiKeyRecord.apiKey);
// Преобразуем запросы в нужный формат
const requests = input.campaigns.map(campaign => {
if (campaign.dates && campaign.dates.length > 0) {
return {
id: campaign.id,
dates: campaign.dates
};
} else if (campaign.interval) {
return {
id: campaign.id,
interval: campaign.interval
};
} else {
// Если не указаны ни даты, ни интервал, возвращаем данные только за последние сутки
return {
id: campaign.id
};
}
});
// Получаем статистику кампаний
const campaignStats = await wbService.getCampaignStats(requests);
return {
success: true,
data: campaignStats,
message: null
};
} catch (error) {
console.error('Error fetching WB campaign stats:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Ошибка получения статистики кампаний',
data: [],
};
}
},
};
// Добавляем админ запросы и мутации к основным резолверам

View File

@ -85,6 +85,11 @@ export const typeDefs = gql`
# Отладка рекламы (временно)
debugWildberriesAdverts: DebugAdvertsResponse!
# Статистика кампаний Wildberries
getWildberriesCampaignStats(
input: WildberriesCampaignStatsInput!
): WildberriesCampaignStatsResponse!
}
type Mutation {
@ -934,4 +939,57 @@ export const typeDefs = gql`
status: Int!
type: Int!
}
# Типы для статистики кампаний
input WildberriesCampaignStatsInput {
campaigns: [CampaignStatsRequest!]!
}
input CampaignStatsRequest {
id: Int!
dates: [String!]
interval: CampaignStatsInterval
}
input CampaignStatsInterval {
begin: String!
end: String!
}
type WildberriesCampaignStatsResponse {
success: Boolean!
message: String
data: [WildberriesCampaignStats!]!
}
type WildberriesCampaignStats {
advertId: Int!
views: Int!
clicks: Int!
ctr: Float!
cpc: Float!
sum: Float!
atbs: Int!
orders: Int!
cr: Float!
shks: Int!
sum_price: Float!
dates: [String!]!
days: [WildberriesCampaignDayStats!]!
boosterStats: [WildberriesCampaignDayStats!]!
}
type WildberriesCampaignDayStats {
date: String!
views: Int!
clicks: Int!
ctr: Float!
cpc: Float!
sum: Float!
atbs: Int!
orders: Int!
cr: Float!
shks: Int!
sum_price: Float!
}
`;