From efe13fe66408043e18579fcfcf5055cee08e66d0 Mon Sep 17 00:00:00 2001 From: wangziqi Date: Sun, 5 Jul 2026 19:33:45 +0800 Subject: [PATCH] feat: add long-term rental independent billing in generate logic --- apps/server/src/bills/bills.service.ts | 30 ++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/server/src/bills/bills.service.ts b/apps/server/src/bills/bills.service.ts index eacb87c..c6f18ec 100644 --- a/apps/server/src/bills/bills.service.ts +++ b/apps/server/src/bills/bills.service.ts @@ -73,18 +73,44 @@ export class BillsService { const occupancies = await this.occRepo .createQueryBuilder('o') .leftJoinAndSelect('o.student', 'student') + .leftJoinAndSelect('o.room', 'room') .where('o.roomId = :roomId', { roomId }) .andWhere('o.billingStartDate <= :periodEnd', { periodEnd }) .andWhere('(o.billingEndDate IS NULL OR o.billingEndDate >= :periodStart)', { periodStart }) .getMany(); - if (occupancies.length === 0) continue; + + // 分离长租与短租入住记录 + const shortTermOccs = occupancies.filter((o) => o.rentalType !== 'long'); + const longTermOccs = occupancies.filter((o) => o.rentalType === 'long'); + + // 长租:按月租费独立计费,不参与人天数分摊 + for (const occ of longTermOccs) { + const monthlyRate = Number(occ.room?.monthlyRate || 0); + if (!studentBillData.has(occ.studentId)) { + studentBillData.set(occ.studentId, { shared: 0, items: [] }); + } + const data = studentBillData.get(occ.studentId)!; + data.shared += monthlyRate; + data.items.push({ + roomId, + expenseType: 'rent', + description: `长租月租费 (${occ.room?.roomNumber || '未知房间'})`, + days: 0, + totalRoomDays: 0, + roomTotalAmount: monthlyRate, + studentAmount: monthlyRate, + }); + } + + // 短租:原人天数加权分摊逻辑 + if (shortTermOccs.length === 0) continue; // 计算每个学生的计费天数 const studentDays: { studentId: number; days: number }[] = []; let totalDays = 0; - for (const occ of occupancies) { + for (const occ of shortTermOccs) { const start = new Date( Math.max(new Date(occ.billingStartDate).getTime(), pStart.getTime()), );