fix: simplify balance billing and govern operation logs

This commit is contained in:
hectorzhao
2026-07-14 17:40:32 +08:00
parent f35691f185
commit 28dad93e3e
40 changed files with 740 additions and 395 deletions
+12 -3
View File
@@ -23,11 +23,14 @@ function createPrismaMock() {
update: jest.fn().mockResolvedValue({ id: 'cert-1' }),
},
tenantAccount: {
findMany: jest.fn().mockResolvedValue([{ tenantId: 'tenant-1', balanceCents: 12000, smsUnits: 300, creditCents: 5000, status: 'active' }]),
findMany: jest.fn().mockResolvedValue([{ tenantId: 'tenant-1', balanceCents: 12000, status: 'active' }]),
},
smsMessageRecord: {
groupBy: jest.fn().mockResolvedValue([{ tenantId: 'tenant-1', _sum: { amountCents: 350 } }]),
},
accountTransaction: {
groupBy: jest.fn().mockResolvedValue([{ tenantId: 'tenant-1', _sum: { amountCents: 125 } }]),
},
};
}
@@ -78,7 +81,7 @@ describe('TenantsService', () => {
expect(prisma.tenant.update).not.toHaveBeenCalled();
});
it('lists management rows with real account and today spend fields', async () => {
it('lists management rows with real account, today spend and actual refund fields', async () => {
const prisma = createPrismaMock();
const service = new TenantsService(prisma as never);
@@ -86,8 +89,9 @@ describe('TenantsService', () => {
expect.objectContaining({
id: 'tenant-1',
name: '测试企业',
account: expect.objectContaining({ balanceCents: 12000, creditCents: 5000 }),
account: expect.objectContaining({ balanceCents: 12000 }),
todaySpendCents: 350,
todayRefundCents: 125,
}),
]);
expect(prisma.tenant.findMany).toHaveBeenCalledWith(expect.objectContaining({
@@ -99,5 +103,10 @@ describe('TenantsService', () => {
by: ['tenantId'],
_sum: { amountCents: true },
}));
expect(prisma.accountTransaction.groupBy).toHaveBeenCalledWith(expect.objectContaining({
by: ['tenantId'],
where: expect.objectContaining({ transactionType: 'refunded' }),
_sum: { amountCents: true },
}));
});
});
+8 -1
View File
@@ -45,7 +45,7 @@ export class TenantsService {
async listManagementRows() {
const sinceToday = startOfToday();
const [tenants, accounts, todaySpendGroups] = await Promise.all([
const [tenants, accounts, todaySpendGroups, todayRefundGroups] = await Promise.all([
this.prisma.tenant.findMany({
where: { status: { not: 'deleted' } },
include: { enterpriseCertifications: { orderBy: { submittedAt: 'desc' }, take: 1 } },
@@ -57,13 +57,20 @@ export class TenantsService {
where: { queuedAt: { gte: sinceToday } },
_sum: { amountCents: true },
}),
this.prisma.accountTransaction.groupBy({
by: ['tenantId'],
where: { transactionType: 'refunded', createdAt: { gte: sinceToday } },
_sum: { amountCents: true },
}),
]);
const accountsByTenant = new Map(accounts.map((account) => [account.tenantId, account]));
const todaySpendByTenant = new Map(todaySpendGroups.map((group) => [group.tenantId, group._sum.amountCents ?? 0]));
const todayRefundByTenant = new Map(todayRefundGroups.map((group) => [group.tenantId, group._sum.amountCents ?? 0]));
return tenants.map((tenant) => ({
...withEnterpriseProfile(tenant),
account: accountsByTenant.get(tenant.id) ?? null,
todaySpendCents: todaySpendByTenant.get(tenant.id) ?? 0,
todayRefundCents: todayRefundByTenant.get(tenant.id) ?? 0,
}));
}