test: harden business boundary conditions
This commit is contained in:
@@ -7,6 +7,8 @@ import { DepositInstallment } from '../entities/deposit-installment.entity';
|
||||
|
||||
import { CreateDepositDto, RefundDepositDto } from './dto/deposit.dto';
|
||||
|
||||
const money = (value: number | string | null | undefined) => Number(Number(value || 0).toFixed(2));
|
||||
|
||||
@Injectable()
|
||||
export class DepositsService {
|
||||
|
||||
@@ -46,14 +48,22 @@ export class DepositsService {
|
||||
async create(dto: CreateDepositDto, userId?: number) {
|
||||
const student = await this.studentRepo.findOne({ where: { id: dto.studentId } });
|
||||
if (!student) throw new NotFoundException('学生不存在');
|
||||
if (Number(dto.amount) <= 0) throw new BadRequestException('收取金额必须大于0');
|
||||
const amount = money(dto.amount);
|
||||
if (!Number.isFinite(dto.amount) || Math.abs(dto.amount * 100 - Math.round(dto.amount * 100)) > 1e-8) {
|
||||
throw new BadRequestException('收取金额最多保留两位小数');
|
||||
}
|
||||
if (amount <= 0) throw new BadRequestException('收取金额必须大于0');
|
||||
|
||||
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.amount = money(Number(existing.amount || 0) + amount);
|
||||
existing.paidDate = dto.paidDate;
|
||||
existing.status = 'paid';
|
||||
existing.recordedBy = userId ?? null;
|
||||
existing.refundDate = null as unknown as string;
|
||||
existing.refundAmount = null as unknown as number;
|
||||
existing.refundedBy = null;
|
||||
existing.refundedAt = null;
|
||||
if (dto.notes) existing.notes = dto.notes;
|
||||
return this.repo.save(existing);
|
||||
}
|
||||
@@ -61,7 +71,7 @@ export class DepositsService {
|
||||
return this.repo.save(
|
||||
this.repo.create({
|
||||
studentId: dto.studentId,
|
||||
amount: dto.amount,
|
||||
amount,
|
||||
paidDate: dto.paidDate,
|
||||
notes: dto.notes,
|
||||
status: 'paid',
|
||||
@@ -71,12 +81,17 @@ export class DepositsService {
|
||||
}
|
||||
|
||||
async addInstallment(depositId: number, amount: number, dueDate: string) {
|
||||
const normalizedAmount = money(amount);
|
||||
if (!Number.isFinite(amount) || Math.abs(amount * 100 - Math.round(amount * 100)) > 1e-8) {
|
||||
throw new BadRequestException('分期金额最多保留两位小数');
|
||||
}
|
||||
if (normalizedAmount <= 0) throw new BadRequestException('分期金额必须大于0');
|
||||
const deposit = await this.repo.findOne({ where: { id: depositId } });
|
||||
if (!deposit) throw new NotFoundException('押金记录不存在');
|
||||
|
||||
const installment = this.installmentRepo.create({
|
||||
depositId,
|
||||
amount,
|
||||
amount: normalizedAmount,
|
||||
dueDate,
|
||||
status: 'pending',
|
||||
});
|
||||
@@ -106,7 +121,7 @@ export class DepositsService {
|
||||
throw new BadRequestException('该学生当前没有可退押金');
|
||||
}
|
||||
|
||||
const refundAmount = Number(deposit.amount);
|
||||
const refundAmount = money(deposit.amount);
|
||||
|
||||
deposit.refundDate = dto.refundDate;
|
||||
deposit.refundAmount = refundAmount;
|
||||
|
||||
Reference in New Issue
Block a user