107 lines
4.1 KiB
TypeScript
107 lines
4.1 KiB
TypeScript
import { DebtService } from '../../src/modules/bot-debt/application/debt.service';
|
|
|
|
describe('DebtService summary/netting', () => {
|
|
let service: DebtService;
|
|
let prisma: any;
|
|
let mockSync: any;
|
|
|
|
beforeEach(async () => {
|
|
prisma = {
|
|
debtGroupMember: { findUnique: jest.fn().mockResolvedValue({}) },
|
|
debtPerson: { findMany: jest.fn() },
|
|
debtTransaction: { findMany: jest.fn() },
|
|
};
|
|
|
|
mockSync = { execute: jest.fn().mockResolvedValue({ id: 'u' }) };
|
|
|
|
service = new DebtService(prisma as any, mockSync as any);
|
|
});
|
|
|
|
function peopleABC() {
|
|
return [
|
|
{ id: 'A', name: 'A' },
|
|
{ id: 'B', name: 'B' },
|
|
{ id: 'C', name: 'C' },
|
|
];
|
|
}
|
|
|
|
it('basic debt A->B 17000', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(17000), type: 'DEBT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([{ from: 'A', to: 'B', amount: '17000' }]);
|
|
});
|
|
|
|
it('accumulation A->B 17k + 10k = 27k', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(17000), type: 'DEBT' },
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(10000), type: 'DEBT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([{ from: 'A', to: 'B', amount: '27000' }]);
|
|
});
|
|
|
|
it('reverse debt A->B 27k B->A 5k = A->B 22k', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(27000), type: 'DEBT' },
|
|
{ fromPersonId: 'B', toPersonId: 'A', amount: BigInt(5000), type: 'DEBT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([{ from: 'A', to: 'B', amount: '22000' }]);
|
|
});
|
|
|
|
it('partial payment A->B 50k debt, payment 20k => A->B 30k', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(50000), type: 'DEBT' },
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(20000), type: 'PAYMENT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([{ from: 'A', to: 'B', amount: '30000' }]);
|
|
});
|
|
|
|
it('overpayment A->B 50k debt, payment 60k => B->A 10k', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(50000), type: 'DEBT' },
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(60000), type: 'PAYMENT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([{ from: 'B', to: 'A', amount: '10000' }]);
|
|
});
|
|
|
|
it('cross substitution A->B 100k B->C 100k C->A 100k => empty', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(100000), type: 'DEBT' },
|
|
{ fromPersonId: 'B', toPersonId: 'C', amount: BigInt(100000), type: 'DEBT' },
|
|
{ fromPersonId: 'C', toPersonId: 'A', amount: BigInt(100000), type: 'DEBT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
expect(res).toEqual([]);
|
|
});
|
|
|
|
it('cross substitution partial A->B 100k B->C 50k => settlement equivalent', async () => {
|
|
prisma.debtPerson.findMany.mockResolvedValue(peopleABC());
|
|
prisma.debtTransaction.findMany.mockResolvedValue([
|
|
{ fromPersonId: 'A', toPersonId: 'B', amount: BigInt(100000), type: 'DEBT' },
|
|
{ fromPersonId: 'B', toPersonId: 'C', amount: BigInt(50000), type: 'DEBT' },
|
|
]);
|
|
|
|
const res = await service.getSummary('u', 'g');
|
|
// possible valid settlements: A->B 50000, A->C 50000 or other equivalent
|
|
expect(res.reduce((acc: any, cur: any) => acc + cur.amount, '')).toBeDefined();
|
|
expect(res.length).toBeGreaterThan(0);
|
|
});
|
|
});
|