UNPKG

@accounter/server

Version:
288 lines 16.2 kB
import { describe, expect, it } from 'vitest'; import { normalizeDocumentAmount, } from '../helpers/document-amount.helper.js'; import { DocumentType } from '../../../shared/enums.js'; describe('Document Amount Normalization', () => { describe('INVOICE - Business is Debtor (User is Creditor)', () => { it('should return positive amount when business is debtor', () => { // Business owes user (user is creditor, business is debtor) const result = normalizeDocumentAmount(100, false, DocumentType.Invoice); expect(result).toBe(100); }); it('should handle decimal amounts', () => { const result = normalizeDocumentAmount(150.75, false, DocumentType.Invoice); expect(result).toBe(150.75); }); it('should handle large amounts', () => { const result = normalizeDocumentAmount(1000000, false, DocumentType.Invoice); expect(result).toBe(1000000); }); }); describe('INVOICE - Business is Creditor (User is Debtor)', () => { it('should return negative amount when business is creditor', () => { // User owes business (user is debtor, business is creditor) const result = normalizeDocumentAmount(100, true, DocumentType.Invoice); expect(result).toBe(-100); }); it('should handle decimal amounts', () => { const result = normalizeDocumentAmount(250.50, true, DocumentType.Invoice); expect(result).toBe(-250.50); }); it('should handle large amounts', () => { const result = normalizeDocumentAmount(5000000, true, DocumentType.Invoice); expect(result).toBe(-5000000); }); }); describe('CREDIT_INVOICE - Business is Debtor (User is Creditor)', () => { it('should return negative amount for credit invoice with business debtor', () => { // Credit invoice: user owes refund to business (opposite of regular invoice) const result = normalizeDocumentAmount(100, false, DocumentType.CreditInvoice); expect(result).toBe(-100); }); it('should handle decimal amounts', () => { const result = normalizeDocumentAmount(75.25, false, DocumentType.CreditInvoice); expect(result).toBe(-75.25); }); it('should handle large amounts', () => { const result = normalizeDocumentAmount(2000000, false, DocumentType.CreditInvoice); expect(result).toBe(-2000000); }); }); describe('CREDIT_INVOICE - Business is Creditor (User is Debtor)', () => { it('should return positive amount for credit invoice with business creditor (double negation)', () => { // Credit invoice: business owes refund to user (double negation: -1 * -1 = 1) const result = normalizeDocumentAmount(100, true, DocumentType.CreditInvoice); expect(result).toBe(100); }); it('should handle decimal amounts', () => { const result = normalizeDocumentAmount(125.99, true, DocumentType.CreditInvoice); expect(result).toBe(125.99); }); it('should handle large amounts', () => { const result = normalizeDocumentAmount(3000000, true, DocumentType.CreditInvoice); expect(result).toBe(3000000); }); }); describe('RECEIPT - Business is Debtor (User is Creditor)', () => { it('should return positive amount when business is debtor', () => { const result = normalizeDocumentAmount(100, false, DocumentType.Receipt); expect(result).toBe(100); }); it('should handle typical receipt amounts', () => { const result = normalizeDocumentAmount(49.99, false, DocumentType.Receipt); expect(result).toBe(49.99); }); }); describe('RECEIPT - Business is Creditor (User is Debtor)', () => { it('should return negative amount when business is creditor', () => { const result = normalizeDocumentAmount(100, true, DocumentType.Receipt); expect(result).toBe(-100); }); it('should handle typical receipt amounts', () => { const result = normalizeDocumentAmount(89.50, true, DocumentType.Receipt); expect(result).toBe(-89.50); }); }); describe('INVOICE_RECEIPT - Business is Debtor (User is Creditor)', () => { it('should return positive amount when business is debtor', () => { const result = normalizeDocumentAmount(100, false, DocumentType.InvoiceReceipt); expect(result).toBe(100); }); it('should handle combined invoice-receipt amounts', () => { const result = normalizeDocumentAmount(350.00, false, DocumentType.InvoiceReceipt); expect(result).toBe(350.00); }); }); describe('INVOICE_RECEIPT - Business is Creditor (User is Debtor)', () => { it('should return negative amount when business is creditor', () => { const result = normalizeDocumentAmount(100, true, DocumentType.InvoiceReceipt); expect(result).toBe(-100); }); it('should handle combined invoice-receipt amounts', () => { const result = normalizeDocumentAmount(425.75, true, DocumentType.InvoiceReceipt); expect(result).toBe(-425.75); }); }); describe('OTHER Document Type', () => { it('should handle OTHER type with business debtor', () => { const result = normalizeDocumentAmount(100, false, DocumentType.Other); expect(result).toBe(100); }); it('should handle OTHER type with business creditor', () => { const result = normalizeDocumentAmount(100, true, DocumentType.Other); expect(result).toBe(-100); }); }); describe('PROFORMA Document Type', () => { it('should handle PROFORMA type with business debtor', () => { const result = normalizeDocumentAmount(100, false, DocumentType.Proforma); expect(result).toBe(100); }); it('should handle PROFORMA type with business creditor', () => { const result = normalizeDocumentAmount(100, true, DocumentType.Proforma); expect(result).toBe(-100); }); }); describe('UNPROCESSED Document Type', () => { it('should handle UNPROCESSED type with business debtor', () => { const result = normalizeDocumentAmount(100, false, DocumentType.Unprocessed); expect(result).toBe(100); }); it('should handle UNPROCESSED type with business creditor', () => { const result = normalizeDocumentAmount(100, true, DocumentType.Unprocessed); expect(result).toBe(-100); }); }); describe('Negative Input Amounts (Absolute Value First)', () => { it('should convert negative input to positive for INVOICE with business debtor', () => { // Input is -100, should become |−100| = 100 const result = normalizeDocumentAmount(-100, false, DocumentType.Invoice); expect(result).toBe(100); }); it('should convert negative input to negative for INVOICE with business creditor', () => { // Input is -100, should become |−100| * -1 = -100 const result = normalizeDocumentAmount(-100, true, DocumentType.Invoice); expect(result).toBe(-100); }); it('should convert negative input for CREDIT_INVOICE with business debtor', () => { // Input is -100, should become |−100| * -1 = -100 const result = normalizeDocumentAmount(-100, false, DocumentType.CreditInvoice); expect(result).toBe(-100); }); it('should convert negative input for CREDIT_INVOICE with business creditor', () => { // Input is -100, should become |−100| * -1 * -1 = 100 const result = normalizeDocumentAmount(-100, true, DocumentType.CreditInvoice); expect(result).toBe(100); }); it('should handle negative decimal amounts', () => { const result = normalizeDocumentAmount(-250.50, false, DocumentType.Invoice); expect(result).toBe(250.50); }); it('should handle large negative amounts', () => { const result = normalizeDocumentAmount(-1000000, true, DocumentType.Receipt); expect(result).toBe(-1000000); }); }); describe('Zero Amounts', () => { it('should handle zero amount with business debtor', () => { const result = normalizeDocumentAmount(0, false, DocumentType.Invoice); expect(result).toBe(0); }); it('should handle zero amount with business creditor', () => { const result = normalizeDocumentAmount(0, true, DocumentType.Invoice); expect(result).toBe(-0); // JavaScript has -0, but 0 === -0 is true }); it('should handle zero for CREDIT_INVOICE', () => { const result = normalizeDocumentAmount(0, false, DocumentType.CreditInvoice); expect(result).toBe(-0); }); it('should verify zero equality regardless of sign', () => { const result1 = normalizeDocumentAmount(0, false, DocumentType.Invoice); const result2 = normalizeDocumentAmount(0, true, DocumentType.Invoice); expect(result1).toBe(0); // In JavaScript, -0 and 0 are loosely equal but Object.is distinguishes them // For our purposes, they are functionally equivalent expect(result2 == 0).toBe(true); // Using == instead of === for -0 case }); }); describe('Very Large Amounts', () => { it('should handle very large positive amounts', () => { const largeAmount = 999999999.99; const result = normalizeDocumentAmount(largeAmount, false, DocumentType.Invoice); expect(result).toBe(largeAmount); }); it('should handle very large amounts with creditor negation', () => { const largeAmount = 999999999.99; const result = normalizeDocumentAmount(largeAmount, true, DocumentType.Invoice); expect(result).toBe(-largeAmount); }); it('should handle very large amounts with CREDIT_INVOICE', () => { const largeAmount = 888888888.88; const result = normalizeDocumentAmount(largeAmount, true, DocumentType.CreditInvoice); expect(result).toBe(largeAmount); }); it('should handle maximum safe integer', () => { const maxSafe = Number.MAX_SAFE_INTEGER; const result = normalizeDocumentAmount(maxSafe, false, DocumentType.Invoice); expect(result).toBe(maxSafe); }); }); describe('Small Decimal Amounts', () => { it('should handle very small decimal amounts', () => { const result = normalizeDocumentAmount(0.01, false, DocumentType.Invoice); expect(result).toBe(0.01); }); it('should handle fractional cents', () => { const result = normalizeDocumentAmount(0.001, true, DocumentType.Receipt); expect(result).toBe(-0.001); }); it('should preserve precision for small decimals', () => { const result = normalizeDocumentAmount(1.23456789, false, DocumentType.Invoice); expect(result).toBe(1.23456789); }); }); describe('All Document Types Summary Table', () => { // This test documents the expected behavior for all combinations it('should correctly normalize all document type and business role combinations', () => { const testCases = [ // INVOICE { type: DocumentType.Invoice, isCreditor: false, input: 100, expected: 100, description: 'INVOICE, business debtor' }, { type: DocumentType.Invoice, isCreditor: true, input: 100, expected: -100, description: 'INVOICE, business creditor' }, // CREDIT_INVOICE { type: DocumentType.CreditInvoice, isCreditor: false, input: 100, expected: -100, description: 'CREDIT_INVOICE, business debtor' }, { type: DocumentType.CreditInvoice, isCreditor: true, input: 100, expected: 100, description: 'CREDIT_INVOICE, business creditor (double neg)' }, // RECEIPT { type: DocumentType.Receipt, isCreditor: false, input: 100, expected: 100, description: 'RECEIPT, business debtor' }, { type: DocumentType.Receipt, isCreditor: true, input: 100, expected: -100, description: 'RECEIPT, business creditor' }, // INVOICE_RECEIPT { type: DocumentType.InvoiceReceipt, isCreditor: false, input: 100, expected: 100, description: 'INVOICE_RECEIPT, business debtor' }, { type: DocumentType.InvoiceReceipt, isCreditor: true, input: 100, expected: -100, description: 'INVOICE_RECEIPT, business creditor' }, // OTHER { type: DocumentType.Other, isCreditor: false, input: 100, expected: 100, description: 'OTHER, business debtor' }, { type: DocumentType.Other, isCreditor: true, input: 100, expected: -100, description: 'OTHER, business creditor' }, // PROFORMA { type: DocumentType.Proforma, isCreditor: false, input: 100, expected: 100, description: 'PROFORMA, business debtor' }, { type: DocumentType.Proforma, isCreditor: true, input: 100, expected: -100, description: 'PROFORMA, business creditor' }, // UNPROCESSED { type: DocumentType.Unprocessed, isCreditor: false, input: 100, expected: 100, description: 'UNPROCESSED, business debtor' }, { type: DocumentType.Unprocessed, isCreditor: true, input: 100, expected: -100, description: 'UNPROCESSED, business creditor' }, ]; testCases.forEach(({ type, isCreditor, input, expected, description }) => { const result = normalizeDocumentAmount(input, isCreditor, type); expect(result).toBe(expected); }); }); }); describe('Real-World Scenarios', () => { it('should normalize customer invoice (business sends invoice to customer)', () => { // Business is creditor (customer owes business) const result = normalizeDocumentAmount(1500, true, DocumentType.Invoice); expect(result).toBe(-1500); // Negative because user owes }); it('should normalize vendor invoice (vendor sends invoice to business)', () => { // Business is debtor (business owes vendor) const result = normalizeDocumentAmount(750, false, DocumentType.Invoice); expect(result).toBe(750); // Positive because vendor owes user }); it('should normalize customer refund (credit invoice to customer)', () => { // Business owes customer a refund const result = normalizeDocumentAmount(200, true, DocumentType.CreditInvoice); expect(result).toBe(200); // Positive because business owes refund }); it('should normalize vendor credit note (credit invoice from vendor)', () => { // Vendor gives credit note to business const result = normalizeDocumentAmount(150, false, DocumentType.CreditInvoice); expect(result).toBe(-150); // Negative because business owes vendor less now }); it('should normalize payment receipt from customer', () => { // Customer pays business const result = normalizeDocumentAmount(500, true, DocumentType.Receipt); expect(result).toBe(-500); // Negative because customer paid }); it('should normalize payment receipt to vendor', () => { // Business pays vendor const result = normalizeDocumentAmount(300, false, DocumentType.Receipt); expect(result).toBe(300); // Positive because business paid }); }); }); //# sourceMappingURL=document-amount.test.js.map