2025-09-04 17:57:04 +00:00
|
|
|
import {
|
|
|
|
|
ISequelizeMapper,
|
|
|
|
|
MapperParamsType,
|
|
|
|
|
SequelizeMapper,
|
2025-09-09 18:13:54 +00:00
|
|
|
ValidationErrorCollection,
|
2025-09-04 17:57:04 +00:00
|
|
|
ValidationErrorDetail,
|
|
|
|
|
extractOrPushError,
|
|
|
|
|
} from "@erp/core/api";
|
2025-09-09 18:13:54 +00:00
|
|
|
import { UniqueID, maybeFromNullableVO, toNullable } from "@repo/rdx-ddd";
|
2025-05-26 10:38:45 +00:00
|
|
|
import { Result } from "@repo/rdx-utils";
|
2025-04-22 08:11:50 +00:00
|
|
|
import { InferCreationAttributes } from "sequelize";
|
2025-05-26 10:38:45 +00:00
|
|
|
import {
|
2025-06-11 15:13:44 +00:00
|
|
|
CustomerInvoice,
|
|
|
|
|
CustomerInvoiceItem,
|
|
|
|
|
CustomerInvoiceItemDescription,
|
2025-09-09 18:13:54 +00:00
|
|
|
CustomerInvoiceProps,
|
2025-09-05 11:23:45 +00:00
|
|
|
ItemAmount,
|
|
|
|
|
ItemDiscount,
|
|
|
|
|
ItemQuantity,
|
2025-05-26 10:38:45 +00:00
|
|
|
} from "../../domain";
|
2025-09-09 18:13:54 +00:00
|
|
|
import { CustomerInvoiceItemCreationAttributes, CustomerInvoiceItemModel } from "../sequelize";
|
2025-03-18 08:05:00 +00:00
|
|
|
|
2025-06-11 15:13:44 +00:00
|
|
|
export interface ICustomerInvoiceItemMapper
|
2025-06-12 06:55:17 +00:00
|
|
|
extends ISequelizeMapper<
|
|
|
|
|
CustomerInvoiceItemModel,
|
|
|
|
|
CustomerInvoiceItemCreationAttributes,
|
|
|
|
|
CustomerInvoiceItem
|
|
|
|
|
> {}
|
2025-03-18 08:05:00 +00:00
|
|
|
|
2025-06-11 15:13:44 +00:00
|
|
|
export class CustomerInvoiceItemMapper
|
2025-06-12 06:55:17 +00:00
|
|
|
extends SequelizeMapper<
|
|
|
|
|
CustomerInvoiceItemModel,
|
|
|
|
|
CustomerInvoiceItemCreationAttributes,
|
|
|
|
|
CustomerInvoiceItem
|
|
|
|
|
>
|
2025-06-11 15:13:44 +00:00
|
|
|
implements ICustomerInvoiceItemMapper
|
2025-03-18 08:05:00 +00:00
|
|
|
{
|
2025-09-09 18:13:54 +00:00
|
|
|
private mapAttributesToDomain(source: CustomerInvoiceItemModel, params?: MapperParamsType) {
|
|
|
|
|
const { errors, index, attributes } = params as {
|
|
|
|
|
index: number;
|
2025-09-04 17:57:04 +00:00
|
|
|
errors: ValidationErrorDetail[];
|
2025-09-09 18:13:54 +00:00
|
|
|
attributes: Partial<CustomerInvoiceProps>;
|
2025-09-04 17:57:04 +00:00
|
|
|
};
|
|
|
|
|
|
2025-09-09 18:13:54 +00:00
|
|
|
const itemId = extractOrPushError(
|
|
|
|
|
UniqueID.create(source.item_id),
|
|
|
|
|
`items[${index}].item_id`,
|
2025-09-05 11:23:45 +00:00
|
|
|
errors
|
|
|
|
|
);
|
2025-09-04 17:57:04 +00:00
|
|
|
|
|
|
|
|
const description = extractOrPushError(
|
|
|
|
|
maybeFromNullableVO(source.description, (value) =>
|
|
|
|
|
CustomerInvoiceItemDescription.create(value)
|
|
|
|
|
),
|
2025-09-09 18:13:54 +00:00
|
|
|
`items[${index}].description`,
|
2025-09-04 17:57:04 +00:00
|
|
|
errors
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const quantity = extractOrPushError(
|
2025-09-05 11:23:45 +00:00
|
|
|
maybeFromNullableVO(source.quantity_value, (value) => ItemQuantity.create({ value })),
|
2025-09-09 18:13:54 +00:00
|
|
|
`items[${index}].discount_percentage`,
|
2025-09-04 17:57:04 +00:00
|
|
|
errors
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const unitAmount = extractOrPushError(
|
2025-09-05 11:23:45 +00:00
|
|
|
maybeFromNullableVO(source.unit_amount_value, (value) =>
|
2025-09-09 18:13:54 +00:00
|
|
|
ItemAmount.create({ value, currency_code: attributes.currencyCode!.code })
|
2025-09-05 11:23:45 +00:00
|
|
|
),
|
2025-09-09 18:13:54 +00:00
|
|
|
`items[${index}].unit_amount`,
|
2025-09-04 17:57:04 +00:00
|
|
|
errors
|
|
|
|
|
);
|
|
|
|
|
|
2025-09-09 18:13:54 +00:00
|
|
|
return {
|
|
|
|
|
itemId,
|
|
|
|
|
languageCode: attributes.languageCode,
|
|
|
|
|
currencyCode: attributes.currencyCode,
|
|
|
|
|
description,
|
|
|
|
|
quantity,
|
|
|
|
|
|
|
|
|
|
unitAmount,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public mapToDomain(
|
|
|
|
|
source: CustomerInvoiceItemModel,
|
|
|
|
|
params?: MapperParamsType
|
|
|
|
|
): Result<CustomerInvoiceItem, Error> {
|
|
|
|
|
const { errors, index, requireIncludes } = params as {
|
|
|
|
|
index: number;
|
|
|
|
|
requireIncludes: boolean;
|
|
|
|
|
errors: ValidationErrorDetail[];
|
|
|
|
|
attributes: Partial<CustomerInvoiceProps>;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (requireIncludes) {
|
|
|
|
|
if (!source.taxes) {
|
|
|
|
|
errors.push({
|
|
|
|
|
path: `items[${index}].taxes`,
|
|
|
|
|
message: "Taxes not included in query (requireIncludes=true)",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const attributes = this.mapAttributesToDomain(source, params);
|
|
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
const discountPercentage = extractOrPushError(
|
2025-09-05 11:23:45 +00:00
|
|
|
maybeFromNullableVO(source.discount_percentage_value, (value) =>
|
|
|
|
|
ItemDiscount.create({ value })
|
|
|
|
|
),
|
2025-09-09 18:13:54 +00:00
|
|
|
`items[${index}].discount_percentage`,
|
2025-09-04 17:57:04 +00:00
|
|
|
errors
|
|
|
|
|
);
|
|
|
|
|
|
2025-05-26 10:38:45 +00:00
|
|
|
// Creación del objeto de dominio
|
2025-09-09 18:13:54 +00:00
|
|
|
const createResult = CustomerInvoiceItem.create(
|
2025-04-22 08:11:50 +00:00
|
|
|
{
|
2025-09-09 18:13:54 +00:00
|
|
|
languageCode: attributes.languageCode!,
|
|
|
|
|
currencyCode: attributes.currencyCode!,
|
|
|
|
|
description: attributes.description!,
|
|
|
|
|
quantity: attributes.quantity!,
|
|
|
|
|
unitAmount: attributes.unitAmount!,
|
2025-09-04 17:57:04 +00:00
|
|
|
discountPercentage: discountPercentage!,
|
2025-09-05 11:23:45 +00:00
|
|
|
},
|
2025-09-09 18:13:54 +00:00
|
|
|
attributes.itemId
|
2025-04-22 08:11:50 +00:00
|
|
|
);
|
2025-09-09 15:48:12 +00:00
|
|
|
|
2025-09-09 18:13:54 +00:00
|
|
|
if (createResult.isFailure) {
|
|
|
|
|
return Result.fail(
|
|
|
|
|
new ValidationErrorCollection("Invoice item entity creation failed", [
|
|
|
|
|
{ path: `items[${index}]`, message: createResult.error.message },
|
|
|
|
|
])
|
|
|
|
|
);
|
2025-09-09 15:48:12 +00:00
|
|
|
}
|
|
|
|
|
|
2025-09-09 18:13:54 +00:00
|
|
|
return createResult;
|
2025-03-18 08:05:00 +00:00
|
|
|
}
|
|
|
|
|
|
2025-04-22 08:11:50 +00:00
|
|
|
public mapToPersistence(
|
2025-06-11 15:13:44 +00:00
|
|
|
source: CustomerInvoiceItem,
|
2025-04-22 08:11:50 +00:00
|
|
|
params?: MapperParamsType
|
2025-06-11 15:13:44 +00:00
|
|
|
): InferCreationAttributes<CustomerInvoiceItemModel, {}> {
|
2025-09-05 11:23:45 +00:00
|
|
|
1;
|
2025-04-22 08:11:50 +00:00
|
|
|
const { index, sourceParent } = params as {
|
|
|
|
|
index: number;
|
2025-06-11 15:13:44 +00:00
|
|
|
sourceParent: CustomerInvoice;
|
2025-04-22 08:11:50 +00:00
|
|
|
};
|
2025-03-18 08:05:00 +00:00
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
return {
|
|
|
|
|
item_id: source.id.toPrimitive(),
|
2025-06-12 06:55:17 +00:00
|
|
|
invoice_id: sourceParent.id.toPrimitive(),
|
2025-03-18 08:05:00 +00:00
|
|
|
position: index,
|
|
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
description: toNullable(source.description, (description) => description.toPrimitive()),
|
|
|
|
|
|
|
|
|
|
quantity_value: toNullable(source.quantity, (value) => value.toPrimitive().value),
|
|
|
|
|
quantity_scale: source.quantity.match(
|
|
|
|
|
(value) => value.toPrimitive().scale,
|
2025-09-05 11:23:45 +00:00
|
|
|
() => ItemQuantity.DEFAULT_SCALE
|
|
|
|
|
),
|
2025-04-22 08:11:50 +00:00
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
unit_amount_value: toNullable(source.unitAmount, (value) => value.toPrimitive().value),
|
|
|
|
|
unit_amount_scale: source.unitAmount.match(
|
|
|
|
|
(value) => value.toPrimitive().scale,
|
2025-09-05 11:23:45 +00:00
|
|
|
() => ItemAmount.DEFAULT_SCALE
|
|
|
|
|
),
|
2025-04-22 08:11:50 +00:00
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
subtotal_amount_value: source.subtotalAmount.toPrimitive().value,
|
|
|
|
|
subtotal_amount_scale: source.subtotalAmount.toPrimitive().scale,
|
2025-04-22 08:11:50 +00:00
|
|
|
|
2025-09-05 11:23:45 +00:00
|
|
|
discount_percentage_value: toNullable(
|
|
|
|
|
source.discountPercentage,
|
|
|
|
|
(value) => value.toPrimitive().value
|
|
|
|
|
),
|
2025-09-04 17:57:04 +00:00
|
|
|
discount_percentage_scale: source.discountPercentage.match(
|
|
|
|
|
(value) => value.toPrimitive().scale,
|
2025-09-05 11:23:45 +00:00
|
|
|
() => ItemAmount.DEFAULT_SCALE
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
discount_amount_value: toNullable(
|
|
|
|
|
source.discountAmount,
|
|
|
|
|
(value) => value.toPrimitive().value
|
|
|
|
|
),
|
|
|
|
|
discount_amount_scale: source.discountAmount.match(
|
|
|
|
|
(value) => value.toPrimitive().scale,
|
|
|
|
|
() => ItemDiscount.DEFAULT_SCALE
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
taxable_amount_value: source.taxableAmount.toPrimitive().value,
|
|
|
|
|
taxable_amount_scale: source.taxableAmount.toPrimitive().value,
|
2025-04-22 08:11:50 +00:00
|
|
|
|
2025-09-05 11:23:45 +00:00
|
|
|
taxes_amount_value: source.taxesAmount.toPrimitive().value,
|
|
|
|
|
taxes_amount_scale: source.taxesAmount.toPrimitive().value,
|
2025-04-22 08:11:50 +00:00
|
|
|
|
2025-09-04 17:57:04 +00:00
|
|
|
total_amount_value: source.totalAmount.toPrimitive().value,
|
|
|
|
|
total_amount_scale: source.totalAmount.toPrimitive().scale,
|
2025-03-18 08:05:00 +00:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|