Добавлены новые зависимости для работы с графиками и статистикой, включая @radix-ui/react-popover, date-fns и react-day-picker. Обновлены компоненты для отображения статистики продаж, улучшена агрегация данных и добавлены функции сортировки в таблицах. Обновлены API маршруты для получения данных о статистике Wildberries. Оптимизирован код для повышения читаемости и производительности.
This commit is contained in:
@ -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 {
|
||||
|
@ -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: [],
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Добавляем админ запросы и мутации к основным резолверам
|
||||
|
@ -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!
|
||||
}
|
||||
`;
|
||||
|
Reference in New Issue
Block a user