Files
RayLab-Core/tests/unit/debt.service.spec.ts
Rayyan c3ce5c2f22
Deploy / deploy (push) Successful in 1m4s
bot telegram debt init
2026-09-03 00:35:24 +07:00

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);
});
});