Facturas de cliente
This commit is contained in:
parent
096abdccb2
commit
ac11eaffdf
@ -0,0 +1,12 @@
|
||||
import { MoneyDTO } from "@erp/core";
|
||||
import { MoneyValue } from "@repo/rdx-ddd";
|
||||
|
||||
export function formatMoneyDTO(amount: MoneyDTO, locale: string) {
|
||||
const money = MoneyValue.create({
|
||||
value: Number(amount.value),
|
||||
currency_code: amount.currency_code,
|
||||
scale: Number(amount.scale),
|
||||
}).data;
|
||||
|
||||
return money.format(locale);
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from "./format-money-dto";
|
||||
export * from "./map-dto-to-customer-invoice-props";
|
||||
|
||||
@ -1,16 +1,21 @@
|
||||
import { ValidationErrorCollection, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||
import {
|
||||
ValidationErrorCollection,
|
||||
ValidationErrorDetail,
|
||||
extractOrPushError,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
||||
import {
|
||||
CustomerInvoiceItem,
|
||||
CustomerInvoiceItemDescription,
|
||||
ItemAmount,
|
||||
ItemDiscount,
|
||||
ItemQuantity,
|
||||
} from "../../domain";
|
||||
import { extractOrPushError } from "./extract-or-push-error";
|
||||
import { hasNoUndefinedFields } from "./has-no-undefined-fields";
|
||||
|
||||
export function mapDTOToCustomerInvoiceItemsProps(
|
||||
dtoItems: Pick<CreateCustomerInvoiceCommandDTO, "items">["items"]
|
||||
dtoItems: Pick<CreateCustomerInvoiceRequestDTO, "items">["items"]
|
||||
): Result<CustomerInvoiceItem[], ValidationErrorCollection> {
|
||||
const errors: ValidationErrorDetail[] = [];
|
||||
const items: CustomerInvoiceItem[] = [];
|
||||
@ -25,9 +30,8 @@ export function mapDTOToCustomerInvoiceItemsProps(
|
||||
);
|
||||
|
||||
const quantity = extractOrPushError(
|
||||
CustomerInvoiceItemQuantity.create({
|
||||
amount: item.quantity.amount,
|
||||
scale: item.quantity.scale,
|
||||
ItemQuantity.create({
|
||||
value: Number(item.quantity),
|
||||
}),
|
||||
path("quantity"),
|
||||
errors
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
import { ValidationErrorCollection, ValidationErrorDetail } from "@erp/core/api";
|
||||
import { UniqueID, UtcDate } from "@repo/rdx-ddd";
|
||||
import {
|
||||
CurrencyCode,
|
||||
UniqueID,
|
||||
UtcDate,
|
||||
ValidationErrorCollection,
|
||||
ValidationErrorDetail,
|
||||
extractOrPushError,
|
||||
maybeFromNullableVO,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { CreateCustomerInvoiceCommandDTO } from "../../../common/dto";
|
||||
import { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
||||
import {
|
||||
CustomerInvoiceNumber,
|
||||
CustomerInvoiceProps,
|
||||
CustomerInvoiceSerie,
|
||||
CustomerInvoiceStatus,
|
||||
} from "../../domain";
|
||||
import { extractOrPushError } from "./extract-or-push-error";
|
||||
import { mapDTOToCustomerInvoiceItemsProps } from "./map-dto-to-customer-invoice-items-props";
|
||||
|
||||
/**
|
||||
@ -21,7 +27,7 @@ import { mapDTOToCustomerInvoiceItemsProps } from "./map-dto-to-customer-invoice
|
||||
*
|
||||
*/
|
||||
|
||||
export function mapDTOToCustomerInvoiceProps(dto: CreateCustomerInvoiceCommandDTO) {
|
||||
export function mapDTOToCustomerInvoiceProps(dto: CreateCustomerInvoiceRequestDTO) {
|
||||
const errors: ValidationErrorDetail[] = [];
|
||||
|
||||
const invoiceId = extractOrPushError(UniqueID.create(dto.id), "id", errors);
|
||||
@ -32,7 +38,7 @@ export function mapDTOToCustomerInvoiceProps(dto: CreateCustomerInvoiceCommandDT
|
||||
errors
|
||||
);
|
||||
const invoiceSeries = extractOrPushError(
|
||||
CustomerInvoiceSerie.create(dto.invoice_series),
|
||||
maybeFromNullableVO(dto.invoice_series, (value) => CustomerInvoiceSerie.create(value)),
|
||||
"invoice_series",
|
||||
errors
|
||||
);
|
||||
@ -42,13 +48,16 @@ export function mapDTOToCustomerInvoiceProps(dto: CreateCustomerInvoiceCommandDT
|
||||
errors
|
||||
);
|
||||
const operationDate = extractOrPushError(
|
||||
UtcDate.createFromISO(dto.operation_date),
|
||||
maybeFromNullableVO(dto.operation_date, (value) => UtcDate.createFromISO(value)),
|
||||
"operation_date",
|
||||
errors
|
||||
);
|
||||
|
||||
//const currency = extractOrPushError(Currency.(dto.currency), "currency", errors);
|
||||
const currency = dto.currency;
|
||||
const currencyCode = extractOrPushError(
|
||||
CurrencyCode.create(dto.currency_code),
|
||||
"currency",
|
||||
errors
|
||||
);
|
||||
|
||||
// 🔄 Validar y construir los items de factura con helper especializado
|
||||
const itemsResult = mapDTOToCustomerInvoiceItemsProps(dto.items);
|
||||
@ -57,16 +66,16 @@ export function mapDTOToCustomerInvoiceProps(dto: CreateCustomerInvoiceCommandDT
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
return Result.fail(new ValidationErrorCollection(errors));
|
||||
return Result.fail(new ValidationErrorCollection("Customer dto mapping failed", errors));
|
||||
}
|
||||
|
||||
const invoiceProps: CustomerInvoiceProps = {
|
||||
invoiceNumber: invoiceNumber!,
|
||||
invoiceSeries: invoiceSeries!,
|
||||
series: invoiceSeries!,
|
||||
invoiceDate: invoiceDate!,
|
||||
operationDate: operationDate!,
|
||||
status: CustomerInvoiceStatus.createDraft(),
|
||||
currency,
|
||||
currencyCode: currencyCode!,
|
||||
};
|
||||
|
||||
return Result.ok({ id: invoiceId!, props: invoiceProps });
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
import { Presenter } from "@erp/core/api";
|
||||
import { GetCustomerInvoiceByIdResponseDTO } from "../../../../common/dto";
|
||||
import { formatMoneyDTO } from "../../helpers";
|
||||
|
||||
export class CustomerInvoiceReportPresenter extends Presenter<
|
||||
GetCustomerInvoiceByIdResponseDTO,
|
||||
unknown
|
||||
> {
|
||||
toOutput(invoiceDTO: GetCustomerInvoiceByIdResponseDTO) {
|
||||
const locale = invoiceDTO.language_code;
|
||||
|
||||
return {
|
||||
...invoiceDTO,
|
||||
total_amount: formatMoneyDTO(invoiceDTO.total_amount, locale),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from "./customer-invoice.report.presenter";
|
||||
export * from "./list-customer-invoices.presenter";
|
||||
|
||||
@ -11,13 +11,20 @@ export class CustomerInvoiceReportHTMLPresenter extends Presenter {
|
||||
projection: "FULL",
|
||||
});
|
||||
|
||||
const prePresenter = this.presenterRegistry.getPresenter({
|
||||
resource: "customer-invoice",
|
||||
projection: "REPORT",
|
||||
format: "JSON",
|
||||
});
|
||||
|
||||
const invoiceDTO = dtoPresenter.toOutput(customerInvoice);
|
||||
const prettyDTO = prePresenter.toOutput(invoiceDTO);
|
||||
|
||||
// Obtener y compilar la plantilla HTML
|
||||
const templateHtml = readFileSync(
|
||||
path.join(__dirname, "./templates/customer-invoice/template.hbs")
|
||||
).toString();
|
||||
const template = handlebars.compile(templateHtml, {});
|
||||
return template(invoiceDTO);
|
||||
return template(prettyDTO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@
|
||||
<!-- Badge TOTAL superpuesto -->
|
||||
<div class="absolute -top-7 right-0">
|
||||
<div class="relative bg-[#f08119] text-white text-sm font-semibold px-3 py-1 shadow">
|
||||
TOTAL: {{total_amount.value}} €
|
||||
TOTAL: {{total_amount}} €
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
CustomerInvoiceItemsFullPresenter,
|
||||
CustomerInvoiceReportHTMLPresenter,
|
||||
CustomerInvoiceReportPDFPresenter,
|
||||
CustomerInvoiceReportPresenter,
|
||||
GetCustomerInvoiceUseCase,
|
||||
ListCustomerInvoicesPresenter,
|
||||
ListCustomerInvoicesUseCase,
|
||||
@ -99,6 +100,14 @@ export function buildCustomerInvoiceDependencies(params: ModuleParams): Customer
|
||||
},
|
||||
presenter: new ListCustomerInvoicesPresenter(presenterRegistry),
|
||||
},
|
||||
{
|
||||
key: {
|
||||
resource: "customer-invoice",
|
||||
projection: "REPORT",
|
||||
format: "JSON",
|
||||
},
|
||||
presenter: new CustomerInvoiceReportPresenter(presenterRegistry),
|
||||
},
|
||||
{
|
||||
key: {
|
||||
resource: "customer-invoice",
|
||||
|
||||
@ -119,7 +119,7 @@ export class CustomerInvoiceDomainMapper
|
||||
|
||||
const discountPercentage = extractOrPushError(
|
||||
Percentage.create({
|
||||
value: source.discount_amount_scale,
|
||||
value: source.discount_percentage_value,
|
||||
scale: source.discount_percentage_scale,
|
||||
}),
|
||||
"discount_percentage_value",
|
||||
@ -206,9 +206,7 @@ export class CustomerInvoiceDomainMapper
|
||||
|
||||
// 5) Si hubo errores de mapeo, devolvemos colección de validación
|
||||
if (errors.length > 0) {
|
||||
return Result.fail(
|
||||
new ValidationErrorCollection("Customer invoice mapping failed", errors)
|
||||
);
|
||||
return Result.fail(new ValidationErrorCollection("Customer mapping failed", errors));
|
||||
}
|
||||
|
||||
// 6) Construcción del agregado (Dominio)
|
||||
|
||||
@ -207,7 +207,7 @@ export class MoneyValue extends ValueObject<MoneyValueProps> implements IMoneyVa
|
||||
|
||||
/**
|
||||
* Devuelve una cadena con el importe formateado.
|
||||
* Ejemplo: 123456 -> €1,234.56
|
||||
* Ejemplo: 123456 -> 1.234,56 €
|
||||
* @param locale Código de idioma y país (ej. "es-ES")
|
||||
* @returns Importe formateado
|
||||
*/
|
||||
@ -222,6 +222,6 @@ export class MoneyValue extends ValueObject<MoneyValueProps> implements IMoneyVa
|
||||
minimumFractionDigits: scale,
|
||||
maximumFractionDigits: scale,
|
||||
useGrouping: true,
|
||||
}).format(value);
|
||||
}).format(this.formattedValue);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user