test: harden business boundary conditions
This commit is contained in:
@@ -50,3 +50,70 @@ describe('WalletsService payment rules', () => {
|
||||
expect(ctx.saved.some((row) => row.type === 'bill_refund' && Number(row.amount) === 40)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('WalletsService financial boundaries', () => {
|
||||
it('caps a debit at total minus already paid even when outstandingAmount is stale', async () => {
|
||||
const ctx = manager(50);
|
||||
const service = new WalletsService({} as any, {} as any, {} as any, {} as any);
|
||||
const bill = {
|
||||
id: 10,
|
||||
studentId: 10,
|
||||
totalAmount: 100,
|
||||
paidAmount: 90,
|
||||
outstandingAmount: 100,
|
||||
status: 'partially_paid',
|
||||
} as Bill;
|
||||
|
||||
await service.debitBill(ctx.value as any, bill);
|
||||
|
||||
expect(bill).toMatchObject({ paidAmount: 100, outstandingAmount: 0, status: 'paid' });
|
||||
expect(ctx.wallet.balance).toBe(40);
|
||||
expect(ctx.saved.some((row) => row.type === 'bill_payment' && row.amount === -10)).toBe(true);
|
||||
});
|
||||
|
||||
it('caps a refund at the bill total when paidAmount is corrupt', async () => {
|
||||
const ctx = manager(10);
|
||||
const service = new WalletsService({} as any, {} as any, {} as any, {} as any);
|
||||
const bill = {
|
||||
id: 11,
|
||||
studentId: 10,
|
||||
totalAmount: 100,
|
||||
paidAmount: 150,
|
||||
outstandingAmount: 0,
|
||||
status: 'paid',
|
||||
} as Bill;
|
||||
|
||||
await service.refundBill(ctx.value as any, bill, '冲正');
|
||||
|
||||
expect(ctx.wallet.balance).toBe(110);
|
||||
expect(ctx.saved.some((row) => row.type === 'bill_refund' && row.amount === 100)).toBe(true);
|
||||
});
|
||||
|
||||
it('does not issue a second refund for an already cancelled bill', async () => {
|
||||
const ctx = manager(10);
|
||||
const service = new WalletsService({} as any, {} as any, {} as any, {} as any);
|
||||
const bill = {
|
||||
id: 12,
|
||||
studentId: 10,
|
||||
totalAmount: 100,
|
||||
paidAmount: 100,
|
||||
outstandingAmount: 0,
|
||||
status: 'cancelled',
|
||||
} as Bill;
|
||||
|
||||
await service.refundBill(ctx.value as any, bill, '重复取消');
|
||||
|
||||
expect(ctx.wallet.balance).toBe(10);
|
||||
expect(ctx.saved).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('rejects an amount that rounds to zero before opening a transaction', async () => {
|
||||
const dataSource = { transaction: jest.fn() };
|
||||
const service = new WalletsService({} as any, {} as any, {} as any, dataSource as any);
|
||||
|
||||
await expect(service.changeBalance({ studentId: 1, amount: 0.004, type: 'adjustment' })).rejects.toBeInstanceOf(
|
||||
BadRequestException,
|
||||
);
|
||||
expect(dataSource.transaction).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user