From da7cad207cdd28d04e9da535668dc31c7501384c Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev Date: Sat, 4 Apr 2026 09:28:52 +0700 Subject: [PATCH] Add manager user and bonus queries --- src/resolvers.js | 98 ++++++++++++++++++++++++++++++++++++++++++++++ src/schema.graphql | 24 ++++++++++++ 2 files changed, 122 insertions(+) diff --git a/src/resolvers.js b/src/resolvers.js index c1be655..faf2e00 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -468,6 +468,46 @@ export const resolvers = { }); }, + managerUsers: async (_, __, context) => { + requireRole(context, 'MANAGER'); + const users = await context.prisma.user.findMany({ + where: { role: 'CLIENT' }, + include: { + counterpartyProfile: { + select: { + companyName: true, + inn: true, + }, + }, + clientOrders: { + select: { + createdAt: true, + }, + orderBy: { createdAt: 'desc' }, + take: 1, + }, + _count: { + select: { + clientOrders: true, + }, + }, + }, + orderBy: { createdAt: 'desc' }, + }); + + return users.map((user) => ({ + id: user.id, + email: user.email, + fullName: user.fullName, + role: user.role, + companyName: user.counterpartyProfile?.companyName ?? null, + inn: user.counterpartyProfile?.inn ?? null, + createdAt: user.createdAt, + orderCount: user._count.clientOrders, + lastOrderAt: user.clientOrders[0]?.createdAt ?? null, + })); + }, + managerOrders: (_, { status }, context) => { const manager = requireRole(context, 'MANAGER'); return context.prisma.order.findMany({ @@ -483,6 +523,62 @@ export const resolvers = { }); }, + managerBonusBalances: async (_, __, context) => { + requireRole(context, 'MANAGER'); + + const [users, transactionsAgg, pendingWithdrawalsAgg] = await Promise.all([ + context.prisma.user.findMany({ + where: { role: 'CLIENT' }, + include: { + counterpartyProfile: { + select: { + companyName: true, + }, + }, + }, + orderBy: { createdAt: 'desc' }, + }), + context.prisma.bonusTransaction.groupBy({ + by: ['userId'], + _sum: { amount: true }, + _count: { _all: true }, + }), + context.prisma.rewardWithdrawalRequest.groupBy({ + by: ['requesterId'], + where: { status: 'PENDING' }, + _sum: { amount: true }, + }), + ]); + + const txMap = new Map(transactionsAgg.map((item) => [ + item.userId, + { + balance: Number(item._sum.amount ?? 0), + transactionsCount: item._count._all, + }, + ])); + + const pendingMap = new Map(pendingWithdrawalsAgg.map((item) => [ + item.requesterId, + Number(item._sum.amount ?? 0), + ])); + + return users.map((user) => { + const tx = txMap.get(user.id); + const pendingWithdrawalAmount = pendingMap.get(user.id) ?? 0; + + return { + userId: user.id, + email: user.email, + fullName: user.fullName, + companyName: user.counterpartyProfile?.companyName ?? null, + balance: (tx?.balance ?? 0) - pendingWithdrawalAmount, + pendingWithdrawalAmount, + transactionsCount: tx?.transactionsCount ?? 0, + }; + }); + }, + registrationRequests: (_, { status }, context) => { requireRole(context, 'MANAGER'); return context.prisma.registrationRequest.findMany({ @@ -1103,6 +1199,7 @@ export const resolvers = { code: orderCode(), kind: 'READY', customerId: customer.id, + managerId: customer.role === 'MANAGER' ? customer.id : null, deliveryAddressId: selectedAddress.id, deliveryAddress: presentDeliveryAddress(selectedAddress), status: 'NEW', @@ -1140,6 +1237,7 @@ export const resolvers = { code: orderCode(), kind: 'CALCULATION', customerId: customer.id, + managerId: customer.role === 'MANAGER' ? customer.id : null, deliveryAddressId: selectedAddress.id, deliveryAddress: presentDeliveryAddress(selectedAddress), status: 'NEW', diff --git a/src/schema.graphql b/src/schema.graphql index 2da2997..f8a8e87 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -136,6 +136,18 @@ type RegistrationRequest { updatedAt: DateTime! } +type ManagerUser { + id: ID! + email: String! + fullName: String! + role: UserRole! + companyName: String + inn: String + createdAt: DateTime! + orderCount: Int! + lastOrderAt: DateTime +} + type MessengerConnection { id: ID! userId: ID! @@ -284,6 +296,16 @@ type ReferralStats { pendingWithdrawals: [RewardWithdrawalRequest!]! } +type ManagerBonusBalance { + userId: ID! + email: String! + fullName: String! + companyName: String + balance: Float! + pendingWithdrawalAmount: Float! + transactionsCount: Int! +} + type Query { healthcheck: String! me: User @@ -296,7 +318,9 @@ type Query { clientProducts: [Product!]! myOrders: [Order!]! myCurrentOrders: [Order!]! + managerUsers: [ManagerUser!]! managerOrders(status: OrderStatus): [Order!]! + managerBonusBalances: [ManagerBonusBalance!]! registrationRequests(status: RegistrationStatus): [RegistrationRequest!]! referralStats: ReferralStats! }