feat(tests): integrate qenv for dynamic configuration and enhance SKR API tests
This commit is contained in:
@@ -96,6 +96,8 @@ export class JournalEntry extends SmartDataDbDoc<JournalEntry, JournalEntry> {
|
||||
this.postedAt = null;
|
||||
this.createdBy = 'system';
|
||||
|
||||
// Normalize any negative amounts to the correct side
|
||||
this.sanitizeLines();
|
||||
// Calculate totals
|
||||
this.calculateTotals();
|
||||
}
|
||||
@@ -107,6 +109,36 @@ export class JournalEntry extends SmartDataDbDoc<JournalEntry, JournalEntry> {
|
||||
return `JE-${timestamp}-${random}`;
|
||||
}
|
||||
|
||||
private sanitizeLines(): void {
|
||||
for (const line of this.lines) {
|
||||
// Check if both debit and credit are set (not allowed)
|
||||
if (line.debit !== undefined && line.debit !== 0 &&
|
||||
line.credit !== undefined && line.credit !== 0) {
|
||||
throw new Error('A line cannot have both debit and credit amounts');
|
||||
}
|
||||
|
||||
// Handle negative debit - convert to positive credit
|
||||
if (line.debit !== undefined && line.debit < 0) {
|
||||
line.credit = Math.abs(line.debit);
|
||||
delete (line as any).debit;
|
||||
}
|
||||
|
||||
// Handle negative credit - convert to positive debit
|
||||
if (line.credit !== undefined && line.credit < 0) {
|
||||
line.debit = Math.abs(line.credit);
|
||||
delete (line as any).credit;
|
||||
}
|
||||
|
||||
// Check that at least one side has a positive value
|
||||
const hasDebit = line.debit !== undefined && line.debit > 0;
|
||||
const hasCredit = line.credit !== undefined && line.credit > 0;
|
||||
|
||||
if (!hasDebit && !hasCredit) {
|
||||
throw new Error('Either debit or credit must be a positive number');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private calculateTotals(): void {
|
||||
this.totalDebits = 0;
|
||||
this.totalCredits = 0;
|
||||
@@ -204,6 +236,8 @@ export class JournalEntry extends SmartDataDbDoc<JournalEntry, JournalEntry> {
|
||||
throw new Error('Journal entry is already posted');
|
||||
}
|
||||
|
||||
// Normalize any negative amounts to the correct side
|
||||
this.sanitizeLines();
|
||||
// Validate before posting
|
||||
await this.validate();
|
||||
|
||||
@@ -230,28 +264,41 @@ export class JournalEntry extends SmartDataDbDoc<JournalEntry, JournalEntry> {
|
||||
transactions.push(transaction);
|
||||
} else {
|
||||
// Complex entry: multiple debits and/or credits
|
||||
// Create transactions to balance the entry
|
||||
for (const debitLine of debitLines) {
|
||||
for (const creditLine of creditLines) {
|
||||
const amount = Math.min(debitLine.debit || 0, creditLine.credit || 0);
|
||||
// Build working queues with remaining amounts (don't mutate original lines)
|
||||
const debitQueue = debitLines.map(l => ({
|
||||
line: l,
|
||||
remaining: l.debit || 0
|
||||
}));
|
||||
|
||||
const creditQueue = creditLines.map(l => ({
|
||||
line: l,
|
||||
remaining: l.credit || 0
|
||||
}));
|
||||
|
||||
if (amount > 0) {
|
||||
// Create transactions to balance the entry
|
||||
for (const d of debitQueue) {
|
||||
for (const c of creditQueue) {
|
||||
const amount = Math.min(d.remaining, c.remaining);
|
||||
|
||||
if (amount > 0.0000001) { // small epsilon to avoid float artifacts
|
||||
const transaction = await Transaction.createTransaction({
|
||||
date: this.date,
|
||||
debitAccount: debitLine.accountNumber,
|
||||
creditAccount: creditLine.accountNumber,
|
||||
amount: amount,
|
||||
description: `${this.description} - ${debitLine.description || creditLine.description || ''}`,
|
||||
debitAccount: d.line.accountNumber,
|
||||
creditAccount: c.line.accountNumber,
|
||||
amount: Math.round(amount * 100) / 100, // round to 2 decimals
|
||||
description: `${this.description} - ${d.line.description || c.line.description || ''}`,
|
||||
reference: this.reference,
|
||||
skrType: this.skrType,
|
||||
costCenter: debitLine.costCenter || creditLine.costCenter,
|
||||
costCenter: d.line.costCenter || c.line.costCenter,
|
||||
});
|
||||
transactions.push(transaction);
|
||||
|
||||
// Reduce amounts for tracking
|
||||
if (debitLine.debit) debitLine.debit -= amount;
|
||||
if (creditLine.credit) creditLine.credit -= amount;
|
||||
|
||||
// Reduce remaining amounts in working copies (not original lines)
|
||||
d.remaining -= amount;
|
||||
c.remaining -= amount;
|
||||
}
|
||||
|
||||
if (d.remaining <= 0.0000001) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -299,6 +346,8 @@ export class JournalEntry extends SmartDataDbDoc<JournalEntry, JournalEntry> {
|
||||
}
|
||||
|
||||
public async beforeSave(): Promise<void> {
|
||||
// Normalize any negative amounts to the correct side
|
||||
this.sanitizeLines();
|
||||
// Recalculate totals before saving
|
||||
this.calculateTotals();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user