mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-25 09:09:48 +00:00
Merge pull request #979 from yk-a11y/fix/credit-note-apply-invoice-validation
fix: validate credit note per-entry amount against each invoice due amount
This commit is contained in:
@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { sumBy } from 'lodash';
|
import { sumBy } from 'lodash';
|
||||||
import {
|
import {
|
||||||
|
ICreditNoteAppliedToInvoice,
|
||||||
ICreditNoteAppliedToInvoiceModel,
|
ICreditNoteAppliedToInvoiceModel,
|
||||||
IApplyCreditToInvoicesDTO,
|
IApplyCreditToInvoicesDTO,
|
||||||
IApplyCreditToInvoicesCreatedPayload,
|
IApplyCreditToInvoicesCreatedPayload,
|
||||||
@@ -17,6 +18,7 @@ import { CreditNote } from '@/modules/CreditNotes/models/CreditNote';
|
|||||||
import { CreditNoteAppliedInvoice } from '../models/CreditNoteAppliedInvoice';
|
import { CreditNoteAppliedInvoice } from '../models/CreditNoteAppliedInvoice';
|
||||||
import { CommandCreditNoteDTOTransform } from '@/modules/CreditNotes/commands/CommandCreditNoteDTOTransform.service';
|
import { CommandCreditNoteDTOTransform } from '@/modules/CreditNotes/commands/CommandCreditNoteDTOTransform.service';
|
||||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||||
|
import { ApplyCreditNoteToInvoicesDto } from '../dtos/ApplyCreditNoteToInvoices.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CreditNoteApplyToInvoices {
|
export class CreditNoteApplyToInvoices {
|
||||||
@@ -48,7 +50,7 @@ export class CreditNoteApplyToInvoices {
|
|||||||
*/
|
*/
|
||||||
public async applyCreditNoteToInvoices(
|
public async applyCreditNoteToInvoices(
|
||||||
creditNoteId: number,
|
creditNoteId: number,
|
||||||
applyCreditToInvoicesDTO: IApplyCreditToInvoicesDTO,
|
applyCreditToInvoicesDTO: ApplyCreditNoteToInvoicesDto,
|
||||||
): Promise<CreditNoteAppliedInvoice[]> {
|
): Promise<CreditNoteAppliedInvoice[]> {
|
||||||
// Saves the credit note or throw not found service error.
|
// Saves the credit note or throw not found service error.
|
||||||
const creditNote = await this.creditNoteModel()
|
const creditNote = await this.creditNoteModel()
|
||||||
@@ -71,7 +73,7 @@ export class CreditNoteApplyToInvoices {
|
|||||||
// Validate invoices has remaining amount to apply.
|
// Validate invoices has remaining amount to apply.
|
||||||
this.validateInvoicesRemainingAmount(
|
this.validateInvoicesRemainingAmount(
|
||||||
appliedInvoicesEntries,
|
appliedInvoicesEntries,
|
||||||
creditNoteAppliedModel.amount,
|
creditNoteAppliedModel.entries,
|
||||||
);
|
);
|
||||||
// Validate the credit note remaining amount.
|
// Validate the credit note remaining amount.
|
||||||
this.creditNoteDTOTransform.validateCreditRemainingAmount(
|
this.creditNoteDTOTransform.validateCreditRemainingAmount(
|
||||||
@@ -122,18 +124,20 @@ export class CreditNoteApplyToInvoices {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the invoice remaining amount.
|
* Validate each invoice has sufficient remaining amount for the applied credit.
|
||||||
* @param {ISaleInvoice[]} invoices
|
* @param {ISaleInvoice[]} invoices
|
||||||
* @param {number} amount
|
* @param {ICreditNoteAppliedToInvoice[]} entries
|
||||||
*/
|
*/
|
||||||
private validateInvoicesRemainingAmount = (
|
private validateInvoicesRemainingAmount = (
|
||||||
invoices: SaleInvoice[],
|
invoices: SaleInvoice[],
|
||||||
amount: number,
|
entries: ICreditNoteAppliedToInvoice[],
|
||||||
) => {
|
) => {
|
||||||
const invalidInvoices = invoices.filter(
|
const invoiceMap = new Map(invoices.map((inv) => [inv.id, inv]));
|
||||||
(invoice) => invoice.dueAmount < amount,
|
const invalidEntries = entries.filter((entry) => {
|
||||||
);
|
const invoice = invoiceMap.get(entry.invoiceId);
|
||||||
if (invalidInvoices.length > 0) {
|
return invoice != null && invoice.dueAmount < entry.amount;
|
||||||
|
});
|
||||||
|
if (invalidEntries.length > 0) {
|
||||||
throw new ServiceError(ERRORS.INVOICES_HAS_NO_REMAINING_AMOUNT);
|
throw new ServiceError(ERRORS.INVOICES_HAS_NO_REMAINING_AMOUNT);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export interface IApplyCreditToInvoicesDeletedPayload {
|
|||||||
export interface ICreditNoteAppliedToInvoice {
|
export interface ICreditNoteAppliedToInvoice {
|
||||||
amount: number;
|
amount: number;
|
||||||
creditNoteId: number;
|
creditNoteId: number;
|
||||||
|
invoiceId: number;
|
||||||
}
|
}
|
||||||
export interface ICreditNoteAppliedToInvoiceModel {
|
export interface ICreditNoteAppliedToInvoiceModel {
|
||||||
amount: number;
|
amount: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user