feat: link deposits to bill payment

This commit is contained in:
2026-07-14 16:38:38 +08:00
parent eac336a54a
commit 598b4e8acd
12 changed files with 272 additions and 218 deletions

View File

@@ -46,16 +46,28 @@ export class DepositsService {
async create(dto: CreateDepositDto, userId?: number) {
const student = await this.studentRepo.findOne({ where: { id: dto.studentId } });
if (!student) throw new NotFoundException('学生不存在');
const deposit = this.repo.create({
studentId: dto.studentId,
amount: dto.amount,
paidDate: dto.paidDate,
notes: dto.notes,
status: 'paid',
recordedBy: userId,
});
if (Number(dto.amount) <= 0) throw new BadRequestException('收取金额必须大于0');
return this.repo.save(deposit);
const existing = await this.repo.findOne({ where: { studentId: dto.studentId } });
if (existing) {
existing.amount = Number((Number(existing.amount || 0) + Number(dto.amount)).toFixed(2));
existing.paidDate = dto.paidDate;
existing.status = 'paid';
existing.recordedBy = userId ?? null;
if (dto.notes) existing.notes = dto.notes;
return this.repo.save(existing);
}
return this.repo.save(
this.repo.create({
studentId: dto.studentId,
amount: dto.amount,
paidDate: dto.paidDate,
notes: dto.notes,
status: 'paid',
recordedBy: userId,
}),
);
}
async addInstallment(depositId: number, amount: number, dueDate: string) {
@@ -90,18 +102,16 @@ export class DepositsService {
async refund(id: number, dto: RefundDepositDto, userId?: number) {
const deposit = await this.repo.findOne({ where: { id } });
if (!deposit) throw new NotFoundException('押金记录不存在');
if (deposit.status !== 'paid') throw new BadRequestException('该押金已处理');
if (deposit.status !== 'paid' || Number(deposit.amount) <= 0) {
throw new BadRequestException('该学生当前没有可退押金');
}
const deduction = dto.deductionAmount || 0;
const refundAmount = Number(deposit.amount) - deduction;
if (refundAmount < 0) throw new BadRequestException('扣除金额不能大于押金金额');
const refundAmount = Number(deposit.amount);
deposit.refundDate = dto.refundDate;
deposit.deductionAmount = deduction;
deposit.deductionReason = dto.deductionReason || '';
deposit.refundAmount = refundAmount;
deposit.status =
deduction > 0 ? (refundAmount > 0 ? 'partial_refund' : 'deducted') : 'refunded';
deposit.amount = 0;
deposit.status = 'refunded';
if (dto.notes) deposit.notes = dto.notes;
deposit.refundedBy = userId ?? null;
deposit.refundedAt = new Date();