Arreglado cálculo de totales de factura

This commit is contained in:
David Arranz 2025-11-06 17:16:18 +01:00
parent 5c51093b1d
commit 55983f0295
4 changed files with 58 additions and 17 deletions

View File

@ -69,10 +69,11 @@ export class CustomerInvoiceFullPresenter extends Presenter<
payment_method: payment,
subtotal_amount: allAmounts.subtotalAmount.toObjectString(),
items_discount_amount: allAmounts.itemDiscountAmount.toObjectString(),
discount_percentage: invoice.discountPercentage.toObjectString(),
discount_amount: allAmounts.headerDiscountAmount.toObjectString(),
discount_amount: allAmounts.discountAmount.toObjectString(),
taxable_amount: allAmounts.taxableAmount.toObjectString(),
taxes_amount: allAmounts.taxesAmount.toObjectString(),
total_amount: allAmounts.totalAmount.toObjectString(),

View File

@ -60,11 +60,13 @@ export type CustomerInvoicePatchProps = Partial<
};
export interface ICustomerInvoice {
canTransitionTo(nextStatus: string): boolean;
hasRecipient: boolean;
hasPaymentMethod: boolean;
getSubtotalAmount(): InvoiceAmount;
getDiscountAmount(): InvoiceAmount;
_getSubtotalAmount(): InvoiceAmount;
getHeaderDiscountAmount(): InvoiceAmount;
getTaxableAmount(): InvoiceAmount;
getTaxesAmount(): InvoiceAmount;
@ -92,6 +94,18 @@ export class CustomerInvoice
currencyCode: props.currencyCode,
});
}
getHeaderDiscountAmount(): InvoiceAmount {
throw new Error("Method not implemented.");
}
getTaxableAmount(): InvoiceAmount {
throw new Error("Method not implemented.");
}
getTaxesAmount(): InvoiceAmount {
throw new Error("Method not implemented.");
}
getTotalAmount(): InvoiceAmount {
throw new Error("Method not implemented.");
}
static create(props: CustomerInvoiceProps, id?: UniqueID): Result<CustomerInvoice, Error> {
const customerInvoice = new CustomerInvoice(props, id);
@ -155,6 +169,10 @@ export class CustomerInvoice
return this.props.status;
}
canTransitionTo(nextStatus: string): boolean {
return this.props.status.canTransitionTo(nextStatus);
}
public get series(): Maybe<CustomerInvoiceSerie> {
return this.props.series;
}
@ -216,15 +234,19 @@ export class CustomerInvoice
return this.paymentMethod.isSome();
}
private _getDiscountAmount(subtotalAmount: InvoiceAmount): InvoiceAmount {
return subtotalAmount.percentage(this.discountPercentage);
private _getHeaderDiscountAmount(
subtotalAmount: InvoiceAmount,
itemsDiscountAmount: InvoiceAmount
): InvoiceAmount {
return subtotalAmount.subtract(itemsDiscountAmount).percentage(this.discountPercentage);
}
private _getTaxableAmount(
subtotalAmount: InvoiceAmount,
discountAmount: InvoiceAmount
itemsDiscountAmount: InvoiceAmount,
headerDiscountAmount: InvoiceAmount
): InvoiceAmount {
return subtotalAmount.subtract(discountAmount);
return subtotalAmount.subtract(itemsDiscountAmount).subtract(headerDiscountAmount);
}
private _getTaxesAmount(taxableAmount: InvoiceAmount): InvoiceAmount {
@ -247,7 +269,7 @@ export class CustomerInvoice
return taxableAmount.add(taxesAmount);
}
public getSubtotalAmount(): InvoiceAmount {
public _getSubtotalAmount(): InvoiceAmount {
const itemsSubtotal = this.items.getSubtotalAmount().convertScale(2);
return InvoiceAmount.create({
@ -256,12 +278,21 @@ export class CustomerInvoice
}).data as InvoiceAmount;
}
public getDiscountAmount(): InvoiceAmount {
return this._getDiscountAmount(this.getSubtotalAmount());
public _getItemsDiscountAmount(): InvoiceAmount {
const itemsDiscountAmount = this.items.getDiscountAmount().convertScale(2);
return InvoiceAmount.create({
value: itemsDiscountAmount.value,
currency_code: this.currencyCode.code,
}).data as InvoiceAmount;
}
/*public getHeaderDiscountAmount(): InvoiceAmount {
return this._getHeaderDiscountAmount(this.getSubtotalAmount());
}
public getTaxableAmount(): InvoiceAmount {
return this._getTaxableAmount(this.getSubtotalAmount(), this.getDiscountAmount());
return this._getTaxableAmount(this.getSubtotalAmount(), this.getHeaderDiscountAmount());
}
public getTaxesAmount(): InvoiceAmount {
@ -273,7 +304,7 @@ export class CustomerInvoice
const taxesAmount = this._getTaxesAmount(taxableAmount);
return this._getTotalAmount(taxableAmount, taxesAmount);
}
}*/
public getTaxes(): InvoiceTaxTotal[] {
const itemTaxes = this.items.getTaxesAmountByTaxes();
@ -294,15 +325,23 @@ export class CustomerInvoice
}
public getAllAmounts() {
const subtotalAmount = this.getSubtotalAmount();
const discountAmount = this._getDiscountAmount(subtotalAmount);
const taxableAmount = this._getTaxableAmount(subtotalAmount, discountAmount);
const subtotalAmount = this._getSubtotalAmount(); // Sin IVA ni dtos de línea
const itemDiscountAmount = this._getItemsDiscountAmount(); // Suma de los Importes de descuentos de linea
const headerDiscountAmount = this._getHeaderDiscountAmount(subtotalAmount, itemDiscountAmount); // Importe de descuento de cabecera
const taxableAmount = this._getTaxableAmount(
subtotalAmount,
itemDiscountAmount,
headerDiscountAmount
); //
const taxesAmount = this._getTaxesAmount(taxableAmount);
const totalAmount = this._getTotalAmount(taxableAmount, taxesAmount);
return {
subtotalAmount,
discountAmount,
itemDiscountAmount,
headerDiscountAmount,
taxableAmount,
taxesAmount,
totalAmount,

View File

@ -53,7 +53,7 @@ export class CustomerInvoiceItems extends Collection<CustomerInvoiceItem> {
*/
public getSubtotalAmount(): ItemAmount {
return this.getAll().reduce(
(total, tax) => total.add(tax.getSubtotalAmount()),
(total, item) => total.add(item.getSubtotalAmount()),
ItemAmount.zero(this._currencyCode.code)
);
}

View File

@ -48,6 +48,7 @@ export const GetCustomerInvoiceByIdResponseSchema = z.object({
.optional(),
subtotal_amount: MoneySchema,
items_discount_amount: MoneySchema,
discount_percentage: PercentageSchema,
discount_amount: MoneySchema,
taxable_amount: MoneySchema,