This commit is contained in:
David Arranz 2026-03-23 18:51:49 +01:00
parent 969f47357d
commit 8a0e776ce3
16 changed files with 161 additions and 214 deletions

View File

@ -18,8 +18,6 @@ import { InfrastructureUnavailableError } from "../../errors/infrastructure-unav
* 👉 Este traductor pertenece a la infraestructura (persistencia)
*/
export function translateSequelizeError(err: unknown): Error {
console.error(err);
// 1) Duplicados (índices únicos)
if (err instanceof UniqueConstraintError) {
// Tomamos el primer detalle (puede haber varios)

View File

@ -1,4 +1,3 @@
import { ProformaFactory } from "../factories";
import type { IProformaRepository } from "../repositories";
import { type IProformaCreator, type IProformaNumberGenerator, ProformaCreator } from "../services";
@ -7,11 +6,9 @@ export const buildProformaCreator = (params: {
repository: IProformaRepository;
}): IProformaCreator => {
const { numberService, repository } = params;
const factory = new ProformaFactory();
return new ProformaCreator({
numberService,
factory,
repository,
});
};

View File

@ -1,2 +0,0 @@
export * from "./proforma-factory";
export * from "./proforma-factory.interface";

View File

@ -1,17 +0,0 @@
import type { UniqueID } from "@repo/rdx-ddd";
import type { Result } from "@repo/rdx-utils";
import type { IProformaCreateProps, Proforma } from "../../../domain";
export interface IProformaFactory {
/**
* Crea una proforma válida para una empresa a partir de props ya validadas.
*
* No persiste el agregado.
*/
createProforma(
companyId: UniqueID,
props: Omit<IProformaCreateProps, "companyId">,
proformaId?: UniqueID
): Result<Proforma, Error>;
}

View File

@ -1,16 +0,0 @@
import type { UniqueID } from "@repo/rdx-ddd";
import type { Result } from "@repo/rdx-utils";
import { type IProformaCreateProps, Proforma } from "../../../domain";
import type { IProformaFactory } from "./proforma-factory.interface";
export class ProformaFactory implements IProformaFactory {
createProforma(
companyId: UniqueID,
props: Omit<IProformaCreateProps, "companyId">,
proformaId?: UniqueID
): Result<Proforma, Error> {
return Proforma.create({ ...props, companyId }, proformaId);
}
}

View File

@ -18,7 +18,7 @@ import { Maybe, Result } from "@repo/rdx-utils";
import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../common";
import {
type IProformaCreateProps,
type IProformaItemProps,
type IProformaItemCreateProps,
InvoiceNumber,
InvoicePaymentMethod,
type InvoiceRecipient,
@ -210,8 +210,8 @@ export class CreateProformaInputMapper /*implements ICreateProformaInputMapper*/
globalDiscountPercentage: DiscountPercentage;
errors: ValidationErrorDetail[];
}
): IProformaItemProps[] {
const itemsProps: IProformaItemProps[] = [];
): IProformaItemCreateProps[] {
const itemsProps: IProformaItemCreateProps[] = [];
dto.items.forEach((item, index) => {
const description = extractOrPushError(

View File

@ -2,8 +2,7 @@ import type { UniqueID } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import type { Transaction } from "sequelize";
import type { IProformaCreateProps, Proforma } from "../../../domain";
import type { IProformaFactory } from "../factories";
import { type IProformaCreateProps, Proforma } from "../../../domain";
import type { IProformaRepository } from "../repositories";
import type { IProformaNumberGenerator } from "./proforma-number-generator.interface";
@ -21,18 +20,15 @@ export interface IProformaCreator {
type ProformaCreatorDeps = {
numberService: IProformaNumberGenerator;
factory: IProformaFactory;
repository: IProformaRepository;
};
export class ProformaCreator implements IProformaCreator {
private readonly numberService: IProformaNumberGenerator;
private readonly factory: IProformaFactory;
private readonly repository: IProformaRepository;
constructor(deps: ProformaCreatorDeps) {
this.numberService = deps.numberService;
this.factory = deps.factory;
this.repository = deps.repository;
}
@ -55,20 +51,13 @@ export class ProformaCreator implements IProformaCreator {
const invoiceNumber = numberResult.data;
// 2. Crear agregado
const buildResult = this.factory.createProforma(
companyId,
{
...props,
invoiceNumber,
},
id
);
const proformaResult = Proforma.create({ ...props, invoiceNumber, companyId }, id);
if (buildResult.isFailure) {
return Result.fail(buildResult.error);
if (proformaResult.isFailure) {
return Result.fail(proformaResult.error);
}
const proforma = buildResult.data;
const proforma = proformaResult.data;
// 3. Persistir
const saveResult = await this.repository.create(proforma, transaction);

View File

@ -18,12 +18,12 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder
private readonly taxesBuilder: IProformaTaxesFullSnapshotBuilder
) {}
toOutput(invoice: Proforma): IProformaFullSnapshot {
const items = this.itemsBuilder.toOutput(invoice.items);
const recipient = this.recipientBuilder.toOutput(invoice);
const taxes = this.taxesBuilder.toOutput(invoice.taxes());
toOutput(proforma: Proforma): IProformaFullSnapshot {
const items = this.itemsBuilder.toOutput(proforma.items);
const recipient = this.recipientBuilder.toOutput(proforma);
const taxes = this.taxesBuilder.toOutput(proforma.taxes());
const payment = invoice.paymentMethod.match(
const payment = proforma.paymentMethod.match(
(payment) => {
const { id, payment_description } = payment.toObjectString();
return {
@ -34,27 +34,27 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder
() => undefined
);
const allTotals = invoice.totals();
const allTotals = proforma.totals();
return {
id: invoice.id.toString(),
company_id: invoice.companyId.toString(),
id: proforma.id.toString(),
company_id: proforma.companyId.toString(),
invoice_number: invoice.invoiceNumber.toString(),
status: invoice.status.toPrimitive(),
series: maybeToEmptyString(invoice.series, (value) => value.toString()),
invoice_number: proforma.invoiceNumber.toString(),
status: proforma.status.toPrimitive(),
series: maybeToEmptyString(proforma.series, (value) => value.toString()),
invoice_date: invoice.invoiceDate.toDateString(),
operation_date: maybeToEmptyString(invoice.operationDate, (value) => value.toDateString()),
invoice_date: proforma.invoiceDate.toDateString(),
operation_date: maybeToEmptyString(proforma.operationDate, (value) => value.toDateString()),
reference: maybeToEmptyString(invoice.reference, (value) => value.toString()),
description: maybeToEmptyString(invoice.description, (value) => value.toString()),
notes: maybeToEmptyString(invoice.notes, (value) => value.toString()),
reference: maybeToEmptyString(proforma.reference, (value) => value.toString()),
description: maybeToEmptyString(proforma.description, (value) => value.toString()),
notes: maybeToEmptyString(proforma.notes, (value) => value.toString()),
language_code: invoice.languageCode.toString(),
currency_code: invoice.currencyCode.toString(),
language_code: proforma.languageCode.toString(),
currency_code: proforma.currencyCode.toString(),
customer_id: invoice.customerId.toString(),
customer_id: proforma.customerId.toString(),
recipient,
payment_method: payment,
@ -62,7 +62,7 @@ export class ProformaFullSnapshotBuilder implements IProformaFullSnapshotBuilder
subtotal_amount: allTotals.subtotalAmount.toObjectString(),
items_discount_amount: allTotals.itemDiscountAmount.toObjectString(),
global_discount_percentage: invoice.globalDiscountPercentage.toObjectString(),
global_discount_percentage: proforma.globalDiscountPercentage.toObjectString(),
global_discount_amount: allTotals.globalDiscountAmount.toObjectString(),
total_discount_amount: allTotals.totalDiscountAmount.toObjectString(),

View File

@ -21,7 +21,7 @@ import {
type ItemAmount,
} from "../../common/value-objects";
import {
type IProformaItemProps,
type IProformaItemCreateProps,
type IProformaItems,
ProformaItem,
ProformaItems,
@ -52,7 +52,7 @@ export interface IProformaCreateProps {
paymentMethod: Maybe<InvoicePaymentMethod>;
items: IProformaItemProps[];
items: IProformaItemCreateProps[];
globalDiscountPercentage: DiscountPercentage;
}
@ -104,18 +104,32 @@ export type ProformaPatchProps = Partial<Omit<IProformaCreateProps, "companyId"
//items?: ProformaItems;
};
type InternalProformaProps = Omit<IProformaCreateProps, "items">;
export type InternalProformaProps = Omit<IProformaCreateProps, "items">;
export class Proforma extends AggregateRoot<InternalProformaProps> implements IProforma {
private readonly _items: ProformaItems;
protected constructor(props: InternalProformaProps, items: ProformaItems, id?: UniqueID) {
super(props, id);
this._items = items;
}
// Creación funcional
static create(props: IProformaCreateProps, id?: UniqueID): Result<Proforma, Error> {
const internalItems = ProformaItems.create({
items: [],
languageCode: props.languageCode,
currencyCode: props.currencyCode,
globalDiscountPercentage: props.globalDiscountPercentage,
});
const { items, ...internalProps } = props;
const proforma = new Proforma(internalProps, id);
const proforma = new Proforma(internalProps, internalItems, id);
const addItemsResult = proforma.initializeItems(items);
const initializeResult = proforma.initializeItems(items);
if (addItemsResult.isFailure) {
return Result.fail(addItemsResult.error);
if (initializeResult.isFailure) {
return Result.fail(initializeResult.error);
}
// Reglas de negocio / validaciones
@ -128,21 +142,25 @@ export class Proforma extends AggregateRoot<InternalProformaProps> implements IP
}
// Rehidratación desde persistencia
static rehydrate(props: InternalProformaProps, id: UniqueID): Proforma {
return new Proforma(props, id);
static rehydrate(props: InternalProformaProps, items: ProformaItems, id: UniqueID): Proforma {
return new Proforma(props, items, id);
}
private readonly _items: ProformaItems;
private initializeItems(itemsProps: IProformaItemCreateProps[]): Result<void, Error> {
for (const [index, itemProps] of itemsProps.entries()) {
const itemResult = ProformaItem.create(itemProps);
protected constructor(props: InternalProformaProps, id?: UniqueID) {
super(props, id);
if (itemResult.isFailure) {
return Result.fail(itemResult.error);
}
this._items = ProformaItems.create({
languageCode: props.languageCode,
currencyCode: props.currencyCode,
globalDiscountPercentage: props.globalDiscountPercentage,
items: [],
});
const added = this._items.add(itemResult.data);
if (!added) {
return Result.fail(new ProformaItemMismatch(index));
}
}
return Result.ok();
}
// Getters
@ -206,7 +224,7 @@ export class Proforma extends AggregateRoot<InternalProformaProps> implements IP
return this.props.globalDiscountPercentage;
}
public get items(): IProformaItems {
public get items(): ProformaItems {
return this._items;
}
@ -277,7 +295,7 @@ export class Proforma extends AggregateRoot<InternalProformaProps> implements IP
return new ProformaTaxesCalculator(this.items).calculate();
}
public addItem(props: IProformaItemProps): Result<void, Error> {
public addItem(props: IProformaItemCreateProps): Result<void, Error> {
const taxesResult = ProformaItemTaxes.create(props.taxes);
if (taxesResult.isFailure) return Result.fail(taxesResult.error);
@ -318,23 +336,6 @@ export class Proforma extends AggregateRoot<InternalProformaProps> implements IP
// Helpers
private initializeItems(itemsProps: IProformaItemProps[]): Result<void, Error> {
for (const [index, itemProps] of itemsProps.entries()) {
const itemResult = ProformaItem.create(itemProps);
if (itemResult.isFailure) {
return Result.fail(itemResult.error);
}
const added = this._items.add(itemResult.data);
if (!added) {
return Result.fail(new ProformaItemMismatch(index));
}
}
return Result.ok();
}
/**
* @summary Convierte un ItemAmount a InvoiceAmount (mantiene moneda y escala homogénea).
*/

View File

@ -25,7 +25,7 @@ import {
*
*/
export interface IProformaItemProps {
export interface IProformaItemCreateProps {
description: Maybe<ItemDescription>;
quantity: Maybe<ItemQuantity>; // Cantidad de unidades
@ -87,22 +87,25 @@ export interface IProformaItem {
isValued(): boolean; // Indica si el item tiene cantidad o precio (o ambos) para ser considerado "valorizado"
}
type CreateProformaItemProps = IProformaItemProps;
type InternalProformaItemProps = Omit<IProformaItemProps, "taxes"> & {
type InternalProformaItemProps = Omit<IProformaItemCreateProps, "taxes"> & {
taxes: ProformaItemTaxes;
};
export class ProformaItem extends DomainEntity<InternalProformaItemProps> implements IProformaItem {
public static create(props: CreateProformaItemProps, id?: UniqueID): Result<ProformaItem, Error> {
const taxesResult = ProformaItemTaxes.create(props.taxes);
public static create(
props: IProformaItemCreateProps,
id?: UniqueID
): Result<ProformaItem, Error> {
const { taxes, ...internalProps } = props;
const taxesResult = ProformaItemTaxes.create(taxes);
if (taxesResult.isFailure) {
return Result.fail(taxesResult.error);
}
const item = new ProformaItem(
{
...props,
...internalProps,
taxes: taxesResult.data,
},
id
@ -155,7 +158,7 @@ export class ProformaItem extends DomainEntity<InternalProformaItemProps> implem
return this.props.taxes;
}
getProps(): IProformaItemProps {
getProps(): IProformaItemCreateProps {
return this.props;
}

View File

@ -5,15 +5,10 @@ import { Collection, Result } from "@repo/rdx-utils";
import { ProformaItemMismatch } from "../../errors";
import { ProformaItemsTotalsCalculator } from "../../services/proforma-items-totals-calculator";
import type {
IProformaItem,
IProformaItemProps,
IProformaItemTotals,
ProformaItem,
} from "./proforma-item.entity";
import type { IProformaItem, IProformaItemTotals, ProformaItem } from "./proforma-item.entity";
export interface IProformaItemsProps {
items: IProformaItemProps[];
items?: ProformaItem[];
// Estos campos vienen de la cabecera,
// pero se necesitan para cálculos y representaciones de la línea.
@ -22,8 +17,19 @@ export interface IProformaItemsProps {
currencyCode: CurrencyCode; // Para cálculos y formateos de moneda
}
type CreateProformaProps = IProformaItemsProps;
type InternalProformaProps = Omit<IProformaItemsProps, "items">;
/*type ProformaItemCreateProps = {
items: IProformaItemCreateProps[];
// Estos campos vienen de la cabecera,
// pero se necesitan para cálculos y representaciones de la línea.
globalDiscountPercentage: DiscountPercentage; // % descuento de la cabecera
languageCode: LanguageCode; // Para formateos específicos de idioma
currencyCode: CurrencyCode; // Para cálculos y formateos de moneda
};
type InternalProformaProps = Omit<ProformaItemCreateProps, "items"> & {
items: ProformaItem[];
};*/
export interface IProformaItems {
// OJO, no extendemos de Collection<IProformaItem> para no exponer
@ -38,21 +44,23 @@ export interface IProformaItems {
}
export class ProformaItems extends Collection<ProformaItem> implements IProformaItems {
static create(props: CreateProformaProps): ProformaItems {
return new ProformaItems(props);
}
public readonly languageCode!: LanguageCode;
public readonly currencyCode!: CurrencyCode;
public readonly globalDiscountPercentage!: DiscountPercentage;
protected constructor(props: InternalProformaProps) {
super([]);
private constructor(props: IProformaItemsProps) {
super(props.items ?? []);
this.languageCode = props.languageCode;
this.currencyCode = props.currencyCode;
this.globalDiscountPercentage = props.globalDiscountPercentage;
this.ensureSameCurrencyAndLanguage(this.items);
if (this.items.length > 0) {
this.ensureSameContext(this.items);
}
}
static create(props: IProformaItemsProps): ProformaItems {
return new ProformaItems(props);
}
public add(item: ProformaItem): boolean {
@ -105,10 +113,15 @@ export class ProformaItems extends Collection<ProformaItem> implements IProforma
return new ProformaItemsTotalsCalculator(this).calculate();
}
private ensureSameCurrencyAndLanguage(items: IProformaItem[]): void {
private ensureSameContext(items: IProformaItem[]): void {
for (const item of items) {
if (!item.currencyCode.equals(this.currencyCode)) {
throw new Error("[ProformaItems] All items must share the same currency.");
const same =
item.languageCode.equals(this.languageCode) &&
item.currencyCode.equals(this.currencyCode) &&
item.globalDiscountPercentage.equals(this.globalDiscountPercentage);
if (!same) {
throw new Error("[ProformaItems] All items must share the same context.");
}
}
}

View File

@ -17,7 +17,7 @@ import { Maybe, Result } from "@repo/rdx-utils";
import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../../common";
import {
type IProformaCreateProps,
type IProformaItemProps,
type IProformaItemCreateProps,
InvoiceNumber,
InvoicePaymentMethod,
type InvoiceRecipient,
@ -148,7 +148,7 @@ export class CreateProformaRequestMapper {
);
}
const proformaProps: Omit<IProformaCreateProps, "items"> & { items: IProformaItemProps[] } = {
const proformaProps: Omit<IProformaCreateProps, "items"> & { items: IProformaItemCreateProps[] } = {
companyId,
status: defaultStatus!,
@ -181,7 +181,7 @@ export class CreateProformaRequestMapper {
}
}
private mapItems(items: CreateProformaItemRequestDTO[]): IProformaItemProps[] {
private mapItems(items: CreateProformaItemRequestDTO[]): IProformaItemCreateProps[] {
const proformaItems = CustomerInvoiceItems.create({
currencyCode: this.currencyCode!,
languageCode: this.languageCode!,

View File

@ -14,7 +14,7 @@ import {
import { Maybe, Result, isNullishOrEmpty } from "@repo/rdx-utils";
import {
type IProformaCreateProps,
type InternalProformaProps,
InvoiceNumber,
InvoicePaymentMethod,
InvoiceSerie,
@ -67,7 +67,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
const status = extractOrPushError(InvoiceStatus.create(raw.status), "status", errors);
const series = extractOrPushError(
maybeFromNullableResult(raw.series, (v) => InvoiceSerie.create(v)),
maybeFromNullableResult(raw.series, (value) => InvoiceSerie.create(value)),
"series",
errors
);
@ -86,7 +86,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
);
const operationDate = extractOrPushError(
maybeFromNullableResult(raw.operation_date, (v) => UtcDate.createFromISO(v)),
maybeFromNullableResult(raw.operation_date, (value) => UtcDate.createFromISO(value)),
"operation_date",
errors
);
@ -195,11 +195,15 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
});
// 3) Items (colección)
const itemsResults = this._itemsMapper.mapToDomainCollection(raw.items, raw.items.length, {
errors,
parent: attributes,
...params,
});
const itemCollectionResults = this._itemsMapper.mapToDomainCollection(
raw.items,
raw.items.length,
{
errors,
parent: attributes,
...params,
}
);
// 4) Si hubo errores de mapeo, devolvemos colección de validación
if (errors.length > 0) {
@ -209,15 +213,14 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
}
// 6) Construcción del agregado (Dominio)
const items = ProformaItems.create({
languageCode: attributes.languageCode!,
currencyCode: attributes.currencyCode!,
globalDiscountPercentage: attributes.globalDiscountPercentage!,
items: itemsResults.data.getAll(),
items: itemCollectionResults.data.getAll(),
});
const invoiceProps: IProformaCreateProps = {
const invoiceProps: InternalProformaProps = {
companyId: attributes.companyId!,
status: attributes.status!,
@ -239,21 +242,12 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
globalDiscountPercentage: attributes.globalDiscountPercentage!,
paymentMethod: attributes.paymentMethod!,
items,
};
const createResult = Proforma.create(invoiceProps, attributes.invoiceId);
const invoiceId = attributes.invoiceId!;
const proforma = Proforma.rehydrate(invoiceProps, items, invoiceId);
if (createResult.isFailure) {
return Result.fail(
new ValidationErrorCollection("Customer invoice entity creation failed", [
{ path: "invoice", message: createResult.error.message },
])
);
}
return Result.ok(createResult.data);
return Result.ok(proforma);
} catch (err: unknown) {
return Result.fail(err as Error);
}
@ -312,7 +306,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
const allAmounts = source.totals(); // Da los totales ya calculados
const invoiceValues: Partial<CustomerInvoiceCreationAttributes> = {
const proformaValues: Partial<CustomerInvoiceCreationAttributes> = {
// Identificación
id: source.id.toPrimitive(),
company_id: source.companyId.toPrimitive(),
@ -360,6 +354,15 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
taxable_amount_value: allAmounts.taxableAmount.value,
taxable_amount_scale: allAmounts.taxableAmount.scale,
iva_amount_value: allAmounts.ivaAmount.value,
iva_amount_scale: allAmounts.ivaAmount.scale,
rec_amount_value: allAmounts.recAmount.value,
rec_amount_scale: allAmounts.recAmount.scale,
retention_amount_value: allAmounts.retentionAmount.value,
retention_amount_scale: allAmounts.retentionAmount.scale,
taxes_amount_value: allAmounts.taxesAmount.value,
taxes_amount_scale: allAmounts.taxesAmount.scale,
@ -374,7 +377,7 @@ export class SequelizeProformaDomainMapper extends SequelizeDomainMapper<
};
return Result.ok<CustomerInvoiceCreationAttributes>(
invoiceValues as CustomerInvoiceCreationAttributes
proformaValues as CustomerInvoiceCreationAttributes
);
}
}

View File

@ -17,7 +17,7 @@ import { Result } from "@repo/rdx-utils";
import {
type IProformaCreateProps,
type IProformaItemProps,
type IProformaItemCreateProps,
ItemAmount,
ItemDescription,
ItemQuantity,
@ -54,7 +54,7 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper<
private mapAttributesToDomain(
raw: CustomerInvoiceItemModel,
params?: MapperParamsType
): Partial<IProformaItemProps & ProformaItemTaxesProps> & { itemId?: UniqueID } {
): Partial<IProformaItemCreateProps & ProformaItemTaxesProps> & { itemId?: UniqueID } {
const { errors, index, parent } = params as {
index: number;
errors: ValidationErrorDetail[];
@ -160,7 +160,8 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper<
});
// 2) Construcción del elemento de dominio
const createResult = ProformaItem.create(
const itemId = attributes.itemId!;
const newItem = ProformaItem.rehydrate(
{
languageCode: attributes.languageCode!,
currencyCode: attributes.currencyCode!,
@ -171,18 +172,18 @@ export class SequelizeProformaItemDomainMapper extends SequelizeDomainMapper<
globalDiscountPercentage: attributes.globalDiscountPercentage!,
taxes: taxesResult.data,
},
attributes.itemId
itemId
);
if (createResult.isFailure) {
/*if (createResult.isFailure) {
return Result.fail(
new ValidationErrorCollection("Invoice item entity creation failed", [
{ path: `items[${index}]`, message: createResult.error.message },
])
);
}
}*/
return createResult;
return Result.ok(newItem);
}
public mapToPersistence(

View File

@ -365,8 +365,6 @@ export class ProformaRepository
? [options.include]
: [];
console.log(query.where);
query.where = {
...query.where,
...(options.where ?? {}),

View File

@ -1,7 +1,7 @@
import type { JsonTaxCatalogProvider } from "@erp/core";
import { DiscountPercentage, Tax } from "@erp/core/api";
import {
type IProformaItemProps,
type IProformaItemCreateProps,
InvoicePaymentMethod,
InvoiceSerie,
ItemAmount,
@ -9,7 +9,6 @@ import {
ItemQuantity,
type ProformaItemTaxesProps,
} from "@erp/customer-invoices/api/domain";
import type { CustomerTaxesProps } from "@erp/customers/api/domain";
import {
City,
Country,
@ -91,7 +90,7 @@ export interface IProformaFromFactuGESProps {
paymentMethod: Maybe<InvoicePaymentMethod>;
items: IProformaItemProps[];
items: IProformaItemCreateProps[];
globalDiscountPercentage: DiscountPercentage;
};
}
@ -409,29 +408,6 @@ export class CreateProformaFromFactugesInputMapper
return customerProps;
}
private mapCustomerTaxesProps(
dto: CreateProformaFromFactugesRequestDTO["customer"],
params: {
errors: ValidationErrorDetail[];
}
): CustomerTaxesProps {
const { errors } = params;
const iva = extractOrPushError(
maybeFromNullableResult("iva_21", (value) => Tax.createFromCode(value, this.taxCatalog)),
"iva_21",
errors
);
this.throwIfValidationErrors(errors);
return {
iva: iva!,
rec: Maybe.none(),
retention: Maybe.none(),
};
}
private mapItemsProps(
dto: CreateProformaFromFactugesRequestDTO,
params: {
@ -440,8 +416,8 @@ export class CreateProformaFromFactugesInputMapper
globalDiscountPercentage: DiscountPercentage;
errors: ValidationErrorDetail[];
}
): IProformaItemProps[] {
const itemsProps: IProformaItemProps[] = [];
): IProformaItemCreateProps[] {
const itemsProps: IProformaItemCreateProps[] = [];
dto.items.forEach((item, index) => {
const description = extractOrPushError(
@ -482,15 +458,18 @@ export class CreateProformaFromFactugesInputMapper
this.throwIfValidationErrors(params.errors);
itemsProps.push({
description: description!,
quantity: quantity!,
unitAmount: unitAmount!,
itemDiscountPercentage: discountPercentage!,
taxes,
globalDiscountPercentage: params.globalDiscountPercentage,
languageCode: params.languageCode,
currencyCode: params.currencyCode,
description: description!,
quantity: quantity!,
unitAmount: unitAmount!,
itemDiscountPercentage: discountPercentage!,
taxes,
});
});