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, payment_method: payment,
subtotal_amount: allAmounts.subtotalAmount.toObjectString(), subtotal_amount: allAmounts.subtotalAmount.toObjectString(),
items_discount_amount: allAmounts.itemDiscountAmount.toObjectString(),
discount_percentage: invoice.discountPercentage.toObjectString(), discount_percentage: invoice.discountPercentage.toObjectString(),
discount_amount: allAmounts.headerDiscountAmount.toObjectString(),
discount_amount: allAmounts.discountAmount.toObjectString(),
taxable_amount: allAmounts.taxableAmount.toObjectString(), taxable_amount: allAmounts.taxableAmount.toObjectString(),
taxes_amount: allAmounts.taxesAmount.toObjectString(), taxes_amount: allAmounts.taxesAmount.toObjectString(),
total_amount: allAmounts.totalAmount.toObjectString(), total_amount: allAmounts.totalAmount.toObjectString(),

View File

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

View File

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

View File

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