fix: validate credit note per-entry amount against each invoice due amount

The `validateInvoicesRemainingAmount` method was incorrectly comparing the
total credit amount (sum of all entries) against each individual invoice's
due amount. This caused valid credit note applications to be rejected when
applying to multiple invoices where the total exceeded any single invoice's
due amount.

Changed the validation to compare each invoice's due amount against only the
specific entry amount being applied to that invoice.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yong ke Weng
2026-02-21 09:50:39 -05:00
parent 80e545072d
commit 75b98c39d8

View File

@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Knex } from 'knex';
import { sumBy } from 'lodash';
import {
ICreditNoteAppliedToInvoice,
ICreditNoteAppliedToInvoiceModel,
IApplyCreditToInvoicesDTO,
IApplyCreditToInvoicesCreatedPayload,
@@ -71,7 +72,7 @@ export class CreditNoteApplyToInvoices {
// Validate invoices has remaining amount to apply.
this.validateInvoicesRemainingAmount(
appliedInvoicesEntries,
creditNoteAppliedModel.amount,
creditNoteAppliedModel.entries,
);
// Validate the credit note remaining amount.
this.creditNoteDTOTransform.validateCreditRemainingAmount(
@@ -122,17 +123,18 @@ export class CreditNoteApplyToInvoices {
};
/**
* Validate the invoice remaining amount.
* Validate each invoice has sufficient remaining amount for the applied credit.
* @param {ISaleInvoice[]} invoices
* @param {number} amount
* @param {ICreditNoteAppliedToInvoice[]} entries
*/
private validateInvoicesRemainingAmount = (
invoices: SaleInvoice[],
amount: number,
entries: ICreditNoteAppliedToInvoice[],
) => {
const invalidInvoices = invoices.filter(
(invoice) => invoice.dueAmount < amount,
);
const invalidInvoices = invoices.filter((invoice) => {
const entry = entries.find((e) => e.invoiceId === invoice.id);
return entry && invoice.dueAmount < entry.amount;
});
if (invalidInvoices.length > 0) {
throw new ServiceError(ERRORS.INVOICES_HAS_NO_REMAINING_AMOUNT);
}