Facturas de cliente

This commit is contained in:
David Arranz 2025-09-10 18:06:29 +02:00
parent 8c867eb7f3
commit df1aa258d9
15 changed files with 210 additions and 161 deletions

View File

@ -7,39 +7,41 @@ type GetCustomerInvoiceItemsByInvoiceIdResponseDTO = GetCustomerInvoiceByIdRespo
export class GetCustomerInvoiceItemsAssembler { export class GetCustomerInvoiceItemsAssembler {
toDTO(invoice: CustomerInvoice): GetCustomerInvoiceItemsByInvoiceIdResponseDTO { toDTO(invoice: CustomerInvoice): GetCustomerInvoiceItemsByInvoiceIdResponseDTO {
const { items } = invoice; const { items } = invoice;
return items.map((item, index) => ({
id: item.id.toString(),
position: String(index),
description: toEmptyString(item.description, (value) => value.toPrimitive()),
quantity: item.quantity.match( return items.map((item, index) => {
(quantity) => { const amounts = item.getAllAmounts();
const { value, scale } = quantity.toPrimitive();
return { value: value.toString(), scale: scale.toString() };
},
() => ({ value: "", scale: "" })
),
unit_amount: item.unitAmount.match( return {
(unitAmount) => { id: item.id.toString(),
const { value, scale } = unitAmount.toPrimitive(); position: String(index),
return { value: value.toString(), scale: scale.toString() }; description: toEmptyString(item.description, (value) => value.toPrimitive()),
},
() => ({ value: "", scale: "" })
),
discount_percentage: item.discountPercentage.match( quantity: item.quantity.match(
(discountPercentage) => { (quantity) => {
const { value, scale } = discountPercentage.toPrimitive(); const { value, scale } = quantity.toPrimitive();
return { value: value.toString(), scale: scale.toString() }; return { value: value.toString(), scale: scale.toString() };
}, },
() => ({ value: "", scale: "" }) () => ({ value: "", scale: "" })
), ),
total_amount: { unit_amount: item.unitAmount.match(
value: item.totalAmount.toPrimitive().value.toString(), (unitAmount) => {
scale: item.totalAmount.toPrimitive().scale.toString(), const { value, scale } = unitAmount.toPrimitive();
}, return { value: value.toString(), scale: scale.toString() };
})); },
() => ({ value: "", scale: "" })
),
discount_percentage: item.discountPercentage.match(
(discountPercentage) => {
const { value, scale } = discountPercentage.toPrimitive();
return { value: value.toString(), scale: scale.toString() };
},
() => ({ value: "", scale: "" })
),
total_amount: amounts.totalAmount.toPrimitive(),
};
});
} }
} }

View File

@ -14,22 +14,22 @@ export class GetCustomerInvoiceAssembler {
const items = this._itemsAssembler.toDTO(invoice); const items = this._itemsAssembler.toDTO(invoice);
return { return {
id: invoice.id.toPrimitive(), id: invoice.id.toString(),
company_id: invoice.companyId.toPrimitive(), company_id: invoice.companyId.toString(),
invoice_number: invoice.invoiceNumber.toString(), invoice_number: invoice.invoiceNumber.toString(),
status: invoice.status.toPrimitive(), status: invoice.status.toPrimitive(),
series: invoice.series.toString(), series: toEmptyString(invoice.series, (value) => value.toString()),
invoice_date: invoice.invoiceDate.toDateString(), invoice_date: invoice.invoiceDate.toDateString(),
operation_date: toEmptyString(invoice.operationDate, (value) => value.toDateString()), operation_date: toEmptyString(invoice.operationDate, (value) => value.toDateString()),
notes: toEmptyString(invoice.notes, (value) => value.toPrimitive()), notes: toEmptyString(invoice.notes, (value) => value.toString()),
language_code: invoice.languageCode.toPrimitive(), language_code: invoice.languageCode.toString(),
currency_code: invoice.currencyCode.toPrimitive(), currency_code: invoice.currencyCode.toString(),
subtotal_amount: { /*subtotal_amount: {
value: invoice.subtotalAmount.value.toString(), value: invoice.subtotalAmount.value.toString(),
scale: invoice.subtotalAmount.scale.toString(), scale: invoice.subtotalAmount.scale.toString(),
}, },
@ -57,14 +57,13 @@ export class GetCustomerInvoiceAssembler {
total_amount: { total_amount: {
value: invoice.totalAmount.value.toString(), value: invoice.totalAmount.value.toString(),
scale: invoice.totalAmount.scale.toString(), scale: invoice.totalAmount.scale.toString(),
}, },*/
items, items,
metadata: { metadata: {
entity: "customer-invoices", entity: "customer-invoices",
}, },
}; };
} }
} }

View File

@ -10,12 +10,13 @@ import {
UtcDate, UtcDate,
} from "@repo/rdx-ddd"; } from "@repo/rdx-ddd";
import { Maybe, Result } from "@repo/rdx-utils"; import { Maybe, Result } from "@repo/rdx-utils";
import { CustomerInvoiceItems, InvoiceRecipient } from "../entities"; import { CustomerInvoiceItems } from "../entities";
import { InvoiceTaxes } from "../entities/invoice-taxes"; import { InvoiceTaxes } from "../entities/invoice-taxes";
import { import {
CustomerInvoiceNumber, CustomerInvoiceNumber,
CustomerInvoiceSerie, CustomerInvoiceSerie,
CustomerInvoiceStatus, CustomerInvoiceStatus,
InvoiceRecipient,
} from "../value-objects"; } from "../value-objects";
export interface CustomerInvoiceProps { export interface CustomerInvoiceProps {

View File

@ -5,8 +5,6 @@ import { InvoiceAmount } from "../../value-objects/invoice-amount";
export interface InvoiceTaxProps { export interface InvoiceTaxProps {
tax: Tax; tax: Tax;
taxableAmount: InvoiceAmount;
taxesAmount: InvoiceAmount;
} }
export class InvoiceTax extends DomainEntity<InvoiceTaxProps> { export class InvoiceTax extends DomainEntity<InvoiceTaxProps> {
@ -24,14 +22,6 @@ export class InvoiceTax extends DomainEntity<InvoiceTaxProps> {
return this.props.tax; return this.props.tax;
} }
public get taxableAmount(): InvoiceAmount {
return this.props.taxableAmount;
}
public get taxesAmount(): InvoiceAmount {
return this.props.taxesAmount;
}
getProps(): InvoiceTaxProps { getProps(): InvoiceTaxProps {
return this.props; return this.props;
} }
@ -39,4 +29,8 @@ export class InvoiceTax extends DomainEntity<InvoiceTaxProps> {
toPrimitive() { toPrimitive() {
return this.getProps(); return this.getProps();
} }
public getTaxAmount(taxableAmount: InvoiceAmount): InvoiceAmount {
return taxableAmount.percentage(this.tax.percentage);
}
} }

View File

@ -9,13 +9,13 @@ export interface ItemTaxProps {
export class ItemTax extends DomainEntity<ItemTaxProps> { export class ItemTax extends DomainEntity<ItemTaxProps> {
static create(props: ItemTaxProps, id?: UniqueID): Result<ItemTax, Error> { static create(props: ItemTaxProps, id?: UniqueID): Result<ItemTax, Error> {
const invoiceTax = new ItemTax(props, id); const itemTax = new ItemTax(props, id);
// Reglas de negocio / validaciones // Reglas de negocio / validaciones
// ... // ...
// ... // ...
return Result.ok(invoiceTax); return Result.ok(itemTax);
} }
public get tax(): Tax { public get tax(): Tax {

View File

@ -4,6 +4,7 @@ export * from "./customer-invoice-number";
export * from "./customer-invoice-serie"; export * from "./customer-invoice-serie";
export * from "./customer-invoice-status"; export * from "./customer-invoice-status";
export * from "./invoice-amount"; export * from "./invoice-amount";
export * from "./invoice-recipient";
export * from "./item-amount"; export * from "./item-amount";
export * from "./item-discount"; export * from "./item-discount";
export * from "./item-quantity"; export * from "./item-quantity";

View File

@ -6,19 +6,20 @@ import {
ValidationErrorDetail, ValidationErrorDetail,
extractOrPushError, extractOrPushError,
} from "@erp/core/api"; } from "@erp/core/api";
import { UniqueID, maybeFromNullableVO, toNullable } from "@repo/rdx-ddd"; import { UniqueID, maybeFromNullableVO } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils"; import { Result } from "@repo/rdx-utils";
import { InferCreationAttributes } from "sequelize"; import { InferCreationAttributes } from "sequelize";
import { import {
CustomerInvoice,
CustomerInvoiceItem, CustomerInvoiceItem,
CustomerInvoiceItemDescription, CustomerInvoiceItemDescription,
CustomerInvoiceProps, CustomerInvoiceProps,
ItemAmount, ItemAmount,
ItemDiscount, ItemDiscount,
ItemQuantity, ItemQuantity,
ItemTaxes,
} from "../../domain"; } from "../../domain";
import { CustomerInvoiceItemCreationAttributes, CustomerInvoiceItemModel } from "../sequelize"; import { CustomerInvoiceItemCreationAttributes, CustomerInvoiceItemModel } from "../sequelize";
import { ItemTaxesMapper } from "./item-taxes.mapper";
export interface ICustomerInvoiceItemMapper export interface ICustomerInvoiceItemMapper
extends ISequelizeMapper< extends ISequelizeMapper<
@ -35,6 +36,13 @@ export class CustomerInvoiceItemMapper
> >
implements ICustomerInvoiceItemMapper implements ICustomerInvoiceItemMapper
{ {
private _taxesMapper: ItemTaxesMapper;
constructor(params: MapperParamsType) {
super();
this._taxesMapper = new ItemTaxesMapper(params);
}
private mapAttributesToDomain(source: CustomerInvoiceItemModel, params?: MapperParamsType) { private mapAttributesToDomain(source: CustomerInvoiceItemModel, params?: MapperParamsType) {
const { errors, index, attributes } = params as { const { errors, index, attributes } = params as {
index: number; index: number;
@ -92,6 +100,10 @@ export class CustomerInvoiceItemMapper
attributes: Partial<CustomerInvoiceProps>; attributes: Partial<CustomerInvoiceProps>;
}; };
// 1) Valores escalares (atributos generales)
const attributes = this.mapAttributesToDomain(source, params);
// 2) Comprobar relaciones
if (requireIncludes) { if (requireIncludes) {
if (!source.taxes) { if (!source.taxes) {
errors.push({ errors.push({
@ -101,8 +113,7 @@ export class CustomerInvoiceItemMapper
} }
} }
const attributes = this.mapAttributesToDomain(source, params); // 3) Importes
const discountPercentage = extractOrPushError( const discountPercentage = extractOrPushError(
maybeFromNullableVO(source.discount_percentage_value, (value) => maybeFromNullableVO(source.discount_percentage_value, (value) =>
ItemDiscount.create({ value }) ItemDiscount.create({ value })
@ -111,7 +122,25 @@ export class CustomerInvoiceItemMapper
errors errors
); );
// Creación del objeto de dominio // 4) Taxes (colección a nivel de item/línea)
const taxesResults = this._taxesMapper.mapArrayToDomain(source.taxes, {
attributes,
...params,
});
if (taxesResults.isFailure) {
errors.push({
path: `taxes[${index}].discount_percentage`,
message: taxesResults.error.message,
});
}
// 5) Construcción del elemento de dominio
const taxes = ItemTaxes.create({
items: taxesResults.data.getAll(),
});
const createResult = CustomerInvoiceItem.create( const createResult = CustomerInvoiceItem.create(
{ {
languageCode: attributes.languageCode!, languageCode: attributes.languageCode!,
@ -120,6 +149,7 @@ export class CustomerInvoiceItemMapper
quantity: attributes.quantity!, quantity: attributes.quantity!,
unitAmount: attributes.unitAmount!, unitAmount: attributes.unitAmount!,
discountPercentage: discountPercentage!, discountPercentage: discountPercentage!,
taxes,
}, },
attributes.itemId attributes.itemId
); );
@ -139,12 +169,15 @@ export class CustomerInvoiceItemMapper
source: CustomerInvoiceItem, source: CustomerInvoiceItem,
params?: MapperParamsType params?: MapperParamsType
): InferCreationAttributes<CustomerInvoiceItemModel, {}> { ): InferCreationAttributes<CustomerInvoiceItemModel, {}> {
1; throw new Error("not implemented");
const { index, sourceParent } = params as { /*
const { index, sourceParent } = params as {
index: number; index: number;
sourceParent: CustomerInvoice; sourceParent: CustomerInvoice;
}; };
return { return {
item_id: source.id.toPrimitive(), item_id: source.id.toPrimitive(),
invoice_id: sourceParent.id.toPrimitive(), invoice_id: sourceParent.id.toPrimitive(),
@ -193,6 +226,6 @@ export class CustomerInvoiceItemMapper
total_amount_value: source.totalAmount.toPrimitive().value, total_amount_value: source.totalAmount.toPrimitive().value,
total_amount_scale: source.totalAmount.toPrimitive().scale, total_amount_scale: source.totalAmount.toPrimitive().scale,
}; };*/
} }
} }

View File

@ -1,4 +1,3 @@
import { JsonTaxCatalogProvider } from "@erp/core";
import { import {
ISequelizeMapper, ISequelizeMapper,
MapperParamsType, MapperParamsType,
@ -15,7 +14,6 @@ import {
UniqueID, UniqueID,
UtcDate, UtcDate,
maybeFromNullableVO, maybeFromNullableVO,
toNullable,
} from "@repo/rdx-ddd"; } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils"; import { Result } from "@repo/rdx-utils";
import { import {
@ -47,11 +45,10 @@ export class CustomerInvoiceMapper
private _recipientMapper: InvoiceRecipientMapper; private _recipientMapper: InvoiceRecipientMapper;
private _taxesMapper: TaxesMapper; private _taxesMapper: TaxesMapper;
constructor(params: { constructor(params: MapperParamsType) {
taxCatalog: JsonTaxCatalogProvider;
}) {
super(); super();
this._itemsMapper = new CustomerInvoiceItemMapper(); // Instanciar el mapper de items
this._itemsMapper = new CustomerInvoiceItemMapper(params); // Instanciar el mapper de items
this._recipientMapper = new InvoiceRecipientMapper(); this._recipientMapper = new InvoiceRecipientMapper();
this._taxesMapper = new TaxesMapper(params); this._taxesMapper = new TaxesMapper(params);
} }
@ -155,8 +152,10 @@ export class CustomerInvoiceMapper
try { try {
const errors: ValidationErrorDetail[] = []; const errors: ValidationErrorDetail[] = [];
// 1) Valores escalares (atributos generales)
const attributes = this.mapAttributesToDomain(source, { errors, ...params }); const attributes = this.mapAttributesToDomain(source, { errors, ...params });
// 2) Comprobar relaciones
const requireIncludes = Boolean(params?.requireIncludes); const requireIncludes = Boolean(params?.requireIncludes);
if (requireIncludes) { if (requireIncludes) {
if (!source.items) { if (!source.items) {
@ -190,13 +189,13 @@ export class CustomerInvoiceMapper
if (recipientResult.isFailure) { if (recipientResult.isFailure) {
errors.push({ errors.push({
path: "recipient", path: "recipient",
message: recipientResult.error.message, message: recipientResult.error.message,
}); });
} }
// 4) Items (colección) // 4) Items (colección)
const itemsResults = this._itemsMapper.mapArrayToDomain(source.items, { const itemsResults = this._itemsMapper.mapArrayToDomain(source.items, {
requireIncludes,
errors, errors,
attributes, attributes,
...params, ...params,
@ -219,7 +218,7 @@ export class CustomerInvoiceMapper
if (taxesResults.isFailure) { if (taxesResults.isFailure) {
errors.push({ errors.push({
path: "taxes", path: "taxes",
message: recipientResult.error.message, message: taxesResults.error.message,
}); });
} }
@ -262,7 +261,7 @@ export class CustomerInvoiceMapper
languageCode: attributes.languageCode!, languageCode: attributes.languageCode!,
currencyCode: attributes.currencyCode!, currencyCode: attributes.currencyCode!,
discountPercentage: attributes.discountPercentage!, //discountPercentage: attributes.discountPercentage!,
taxes, taxes,
items, items,
@ -288,7 +287,9 @@ export class CustomerInvoiceMapper
source: CustomerInvoice, source: CustomerInvoice,
params?: MapperParamsType params?: MapperParamsType
): CustomerInvoiceCreationAttributes { ): CustomerInvoiceCreationAttributes {
const items = this._itemsMapper.mapCollectionToPersistence(source.items, params); throw new Error("not implemented");
/*const items = this._itemsMapper.mapCollectionToPersistence(source.items, params);
const customer = source.recipient.match( const customer = source.recipient.match(
(recipient) => (recipient) =>
@ -363,6 +364,6 @@ export class CustomerInvoiceMapper
items, items,
...customer, ...customer,
}; };*/
} }
} }

View File

@ -16,8 +16,7 @@ import {
extractOrPushError, extractOrPushError,
} from "@erp/core/api"; } from "@erp/core/api";
import { Maybe, Result } from "@repo/rdx-utils"; import { Maybe, Result } from "@repo/rdx-utils";
import { InferCreationAttributes } from "sequelize"; import { CustomerInvoiceProps, InvoiceRecipient } from "../../domain";
import { CustomerInvoice, CustomerInvoiceProps, InvoiceRecipient } from "../../domain";
import { CustomerInvoiceModel } from "../sequelize"; import { CustomerInvoiceModel } from "../sequelize";
export class InvoiceRecipientMapper { export class InvoiceRecipientMapper {
@ -105,14 +104,4 @@ export class InvoiceRecipientMapper {
return Result.ok(Maybe.some(createResult.data)); return Result.ok(Maybe.some(createResult.data));
} }
public mapToPersistence(
source: InvoiceRecipient,
params?: MapperParamsType
): Partial<InferCreationAttributes<CustomerInvoiceModel, {}>> {
const { index, sourceParent } = params as {
index: number;
sourceParent: CustomerInvoice;
};
}
} }

View File

@ -1,32 +1,68 @@
import { MapperParamsType, Taxes } from "@erp/core/api"; import { JsonTaxCatalogProvider } from "@erp/core";
import { InferCreationAttributes } from "sequelize"; import {
import { CustomerInvoiceItemModel, CustomerInvoiceItemTaxModel } from "../sequelize"; MapperParamsType,
SequelizeMapper,
Tax,
ValidationErrorCollection,
ValidationErrorDetail,
extractOrPushError,
} from "@erp/core/api";
import { Result } from "@repo/rdx-utils";
import { ItemTax } from "../../domain";
import { CustomerInvoiceItemCreationAttributes, CustomerInvoiceItemTaxModel } from "../sequelize";
export class ItemTaxesMapper { export class ItemTaxesMapper extends SequelizeMapper<
public mapArrayToDomain(item: CustomerInvoiceItemModel, params?: MapperParamsType) { CustomerInvoiceItemTaxModel,
const taxes = Taxes.create({ items: [] }); CustomerInvoiceItemCreationAttributes,
ItemTax
> {
private _taxCatalog!: JsonTaxCatalogProvider;
item.taxes.split(",").every((tax_code, taxIndex) => { constructor(params: MapperParamsType) {
const taxResult = Tax.createFromCode(tax_code, this.taxCatalog); super();
if (taxResult.isSuccess) { const { taxCatalog } = params as {
taxes.add(taxResult.data); taxCatalog: JsonTaxCatalogProvider;
} else { };
this.errors.push({
path: `items[${itemIndex}].taxes[${taxIndex}]`, if (!taxCatalog) {
message: taxResult.error.message, throw new Error('taxCatalog not defined ("ItemTaxesMapper")');
}); }
}
}); this._taxCatalog = taxCatalog;
return taxes; }
public mapToDomain(
source: CustomerInvoiceItemTaxModel,
params?: MapperParamsType
): Result<ItemTax, Error> {
const { errors, index } = params as {
index: number;
errors: ValidationErrorDetail[];
};
const tax = extractOrPushError(
Tax.createFromCode(source.tax_code, this._taxCatalog),
`taxes[${index}].tax_code`,
errors
);
// Creación del objeto de dominio
const createResult = ItemTax.create({ tax: tax! });
if (createResult.isFailure) {
return Result.fail(
new ValidationErrorCollection("Invoice item tax creation failed", [
{ path: `taxes[${index}]`, message: createResult.error.message },
])
);
}
return createResult;
} }
public mapToPersistence( public mapToPersistence(
source: Taxes, source: ItemTax,
params?: MapperParamsType params?: MapperParamsType
): InferCreationAttributes<CustomerInvoiceItemTaxModel, {}> { ): CustomerInvoiceItemCreationAttributes {
/*const { index, sourceParent } = params as { throw new Error("not implemented");
index: number;
sourceParent: CustomerInvoice;
};*/
} }
} }

View File

@ -3,20 +3,14 @@ import {
MapperParamsType, MapperParamsType,
SequelizeMapper, SequelizeMapper,
Tax, Tax,
Taxes,
ValidationErrorCollection, ValidationErrorCollection,
ValidationErrorDetail, ValidationErrorDetail,
extractOrPushError, extractOrPushError,
} from "@erp/core/api"; } from "@erp/core/api";
import { Result } from "@repo/rdx-utils"; import { Result } from "@repo/rdx-utils";
import { InferCreationAttributes } from "sequelize"; import { CustomerInvoiceProps } from "../../domain";
import { CustomerInvoiceProps, InvoiceAmount } from "../../domain";
import { InvoiceTax } from "../../domain/entities/invoice-taxes"; import { InvoiceTax } from "../../domain/entities/invoice-taxes";
import { import { CustomerInvoiceTaxCreationAttributes, CustomerInvoiceTaxModel } from "../sequelize";
CustomerInvoiceItemTaxModel,
CustomerInvoiceTaxCreationAttributes,
CustomerInvoiceTaxModel,
} from "../sequelize";
export class TaxesMapper extends SequelizeMapper< export class TaxesMapper extends SequelizeMapper<
CustomerInvoiceTaxModel, CustomerInvoiceTaxModel,
@ -25,11 +19,16 @@ export class TaxesMapper extends SequelizeMapper<
> { > {
private _taxCatalog: JsonTaxCatalogProvider; private _taxCatalog: JsonTaxCatalogProvider;
constructor(params: { constructor(params: MapperParamsType) {
taxCatalog: JsonTaxCatalogProvider;
}) {
super(); super();
const { taxCatalog } = params; const { taxCatalog } = params as {
taxCatalog: JsonTaxCatalogProvider;
};
if (!taxCatalog) {
throw new Error('taxCatalog not defined ("TaxesMapper")');
}
this._taxCatalog = taxCatalog; this._taxCatalog = taxCatalog;
} }
@ -39,7 +38,6 @@ export class TaxesMapper extends SequelizeMapper<
): Result<InvoiceTax, Error> { ): Result<InvoiceTax, Error> {
const { errors, index, attributes } = params as { const { errors, index, attributes } = params as {
index: number; index: number;
requireIncludes: boolean;
errors: ValidationErrorDetail[]; errors: ValidationErrorDetail[];
attributes: Partial<CustomerInvoiceProps>; attributes: Partial<CustomerInvoiceProps>;
}; };
@ -50,48 +48,14 @@ export class TaxesMapper extends SequelizeMapper<
errors errors
); );
const taxableAmount = extractOrPushError(
InvoiceAmount.create({
value: source.taxable_amount_value,
currency_code: attributes.currencyCode?.code,
}),
`taxes[${index}].taxable_amount_value`,
errors
);
if (source.taxable_amount_scale !== InvoiceAmount.DEFAULT_SCALE) {
errors.push({
path: `taxes[${index}].taxable_amount_scale`,
message: "Invalid taxable amount scale",
});
}
const taxesAmount = extractOrPushError(
InvoiceAmount.create({
value: source.taxes_amount_value,
currency_code: attributes.currencyCode?.code,
}),
`taxes[${index}].taxes_amount_value`,
errors
);
if (source.taxes_amount_scale !== InvoiceAmount.DEFAULT_SCALE) {
errors.push({
path: `taxes[${index}].taxes_amount_scale`,
message: "Invalid taxes amount scale",
});
}
// Creación del objeto de dominio // Creación del objeto de dominio
const createResult = InvoiceTax.create({ const createResult = InvoiceTax.create({
tax: tax!, tax: tax!,
taxableAmount: taxableAmount!,
taxesAmount: taxesAmount!,
}); });
if (createResult.isFailure) { if (createResult.isFailure) {
return Result.fail( return Result.fail(
new ValidationErrorCollection("Invoice taxes creation failed", [ new ValidationErrorCollection("Invoice tax creation failed", [
{ path: `taxes[${index}]`, message: createResult.error.message }, { path: `taxes[${index}]`, message: createResult.error.message },
]) ])
); );
@ -101,12 +65,9 @@ export class TaxesMapper extends SequelizeMapper<
} }
public mapToPersistence( public mapToPersistence(
source: Taxes, source: InvoiceTax,
params?: MapperParamsType params?: MapperParamsType
): InferCreationAttributes<CustomerInvoiceItemTaxModel, {}> { ): CustomerInvoiceTaxCreationAttributes {
/*const { index, sourceParent } = params as { throw new Error("not implemented");
index: number;
sourceParent: CustomerInvoice;
};*/
} }
} }

View File

@ -5,6 +5,9 @@ import { Collection, Result } from "@repo/rdx-utils";
import { Sequelize, Transaction } from "sequelize"; import { Sequelize, Transaction } from "sequelize";
import { CustomerInvoice, ICustomerInvoiceRepository } from "../../domain"; import { CustomerInvoice, ICustomerInvoiceRepository } from "../../domain";
import { ICustomerInvoiceMapper } from "../mappers/customer-invoice.mapper"; import { ICustomerInvoiceMapper } from "../mappers/customer-invoice.mapper";
import { CustomerInvoiceItemTaxModel } from "./customer-invoice-item-tax.model";
import { CustomerInvoiceItemModel } from "./customer-invoice-item.model";
import { CustomerInvoiceTaxModel } from "./customer-invoice-tax.model";
import { CustomerInvoiceModel } from "./customer-invoice.model"; import { CustomerInvoiceModel } from "./customer-invoice.model";
export class CustomerInvoiceRepository export class CustomerInvoiceRepository
@ -124,6 +127,23 @@ export class CustomerInvoiceRepository
as: "current_customer", as: "current_customer",
required: false, // false => LEFT JOIN required: false, // false => LEFT JOIN
}, },
{
model: CustomerInvoiceItemModel,
as: "items",
required: false,
include: [
{
model: CustomerInvoiceItemTaxModel,
as: "taxes",
required: false,
},
],
},
{
model: CustomerInvoiceTaxModel,
as: "taxes",
required: false,
},
], ],
transaction, transaction,
}); });

View File

@ -49,4 +49,8 @@ export class CurrencyCode extends ValueObject<CurrencyCodeProps> {
toPrimitive(): string { toPrimitive(): string {
return this.props.value; return this.props.value;
} }
toString(): string {
return String(this.props.value);
}
} }

View File

@ -49,4 +49,8 @@ export class LanguageCode extends ValueObject<LanguageCodeProps> {
toPrimitive(): string { toPrimitive(): string {
return this.props.value; return this.props.value;
} }
toString(): string {
return String(this.props.value);
}
} }

View File

@ -34,6 +34,10 @@ export class TextValue extends ValueObject<TextValueProps> {
} }
toPrimitive(): string { toPrimitive(): string {
return this.toString();
}
toString(): string {
return String(this.getProps()); return String(this.getProps());
} }
} }