From eac336a54a56071dc62c60faa95fc3f0cd76894f Mon Sep 17 00:00:00 2001 From: xiong Date: Tue, 14 Jul 2026 14:53:07 +0800 Subject: [PATCH] fix: include contained room expenses in bill generation --- apps/server/src/bills/bills.service.spec.ts | 37 +++++++++++++++++++++ apps/server/src/bills/bills.service.ts | 4 +-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/apps/server/src/bills/bills.service.spec.ts b/apps/server/src/bills/bills.service.spec.ts index 7b926df..fea9a6b 100644 --- a/apps/server/src/bills/bills.service.spec.ts +++ b/apps/server/src/bills/bills.service.spec.ts @@ -166,6 +166,43 @@ describe('BillsService — generateBills', () => { ).toBeCloseTo(300, 0); }); + it('includes room expenses whose periods are inside the generated bill period', async () => { + const qb = mockQueryBuilder([ + { + id: 1, roomId: 1, expenseType: 'water', + amount: '300' as unknown as number, periodStart: '2026-07-01', periodEnd: '2026-07-31', + } as RoomExpense, + ]); + (roomExpRepo.createQueryBuilder as jest.Mock).mockReturnValue(qb); + + (occRepo.createQueryBuilder as jest.Mock).mockReturnValue( + mockQueryBuilder([ + { + id: 1, studentId: 10, roomId: 1, + billingStartDate: '2026-07-01', billingEndDate: null as unknown as string, + stayType: 'short', room: undefined, + } as Occupancy, + ]), + ); + + (personalExpRepo.createQueryBuilder as jest.Mock).mockReturnValue( + mockQueryBuilder([]), + ); + + const result = await service.generateBills({ + periodStart: '2026-06-29', + periodEnd: '2026-07-31', + }); + + expect(result.count).toBe(1); + expect(qb.where).toHaveBeenCalledWith( + 'e.periodStart >= :periodStart AND e.periodEnd <= :periodEnd', + { periodStart: '2026-06-29', periodEnd: '2026-07-31' }, + ); + const savedCalls = (billRepo.save as jest.Mock).mock.calls as Array<[Record]>; + expect(Number(savedCalls[0][0].sharedAmount)).toBeCloseTo(300, 0); + }); + it('mixed → long-term get individual bills, short-term share expenses', async () => { // Room 1: two expenses (roomExpRepo.createQueryBuilder as jest.Mock).mockReturnValue( diff --git a/apps/server/src/bills/bills.service.ts b/apps/server/src/bills/bills.service.ts index 908c6a9..8a977b5 100644 --- a/apps/server/src/bills/bills.service.ts +++ b/apps/server/src/bills/bills.service.ts @@ -50,10 +50,10 @@ export class BillsService { .execute(); } - // 获取所有有费用的宿舍 + // 获取账单周期内所有有费用的宿舍 const roomExpenses = await this.roomExpRepo .createQueryBuilder('e') - .where('e.periodStart = :periodStart AND e.periodEnd = :periodEnd', { + .where('e.periodStart >= :periodStart AND e.periodEnd <= :periodEnd', { periodStart, periodEnd, })