Facturas de cliente
This commit is contained in:
parent
df1aa258d9
commit
877d98f188
@ -0,0 +1,71 @@
|
|||||||
|
import { Criteria } from "@repo/rdx-criteria/server";
|
||||||
|
import { toEmptyString } from "@repo/rdx-ddd";
|
||||||
|
import { Collection } from "@repo/rdx-utils";
|
||||||
|
import { CustomerInvoiceListResponseDTO } from "../../../../common/dto";
|
||||||
|
import { CustomerInvoice } from "../../../domain";
|
||||||
|
|
||||||
|
export class ListCustomerInvoicesAssembler {
|
||||||
|
toDTO(
|
||||||
|
customerInvoices: Collection<CustomerInvoice>,
|
||||||
|
criteria: Criteria
|
||||||
|
): CustomerInvoiceListResponseDTO {
|
||||||
|
const items = customerInvoices.map((invoice) => {
|
||||||
|
const recipient = invoice.recipient.match(
|
||||||
|
(recipient) => recipient.toString(),
|
||||||
|
() => ({
|
||||||
|
tin: "",
|
||||||
|
name: "",
|
||||||
|
street: "",
|
||||||
|
street2: "",
|
||||||
|
city: "",
|
||||||
|
postal_code: "",
|
||||||
|
province: "",
|
||||||
|
country: "",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: invoice.id.toString(),
|
||||||
|
company_id: invoice.companyId.toString(),
|
||||||
|
customer_id: invoice.customerId.toString(),
|
||||||
|
|
||||||
|
invoice_number: invoice.invoiceNumber.toString(),
|
||||||
|
status: invoice.status.toPrimitive(),
|
||||||
|
series: toEmptyString(invoice.series, (value) => value.toString()),
|
||||||
|
|
||||||
|
invoice_date: invoice.invoiceDate.toDateString(),
|
||||||
|
operation_date: toEmptyString(invoice.operationDate, (value) => value.toDateString()),
|
||||||
|
|
||||||
|
recipient: {
|
||||||
|
customer_id: invoice.customerId.toString(),
|
||||||
|
...recipient,
|
||||||
|
},
|
||||||
|
|
||||||
|
items,
|
||||||
|
|
||||||
|
metadata: {
|
||||||
|
entity: "customer-invoice",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalItems = customerInvoices.total();
|
||||||
|
|
||||||
|
return {
|
||||||
|
page: criteria.pageNumber,
|
||||||
|
per_page: criteria.pageSize,
|
||||||
|
total_pages: Math.ceil(totalItems / criteria.pageSize),
|
||||||
|
total_items: totalItems,
|
||||||
|
items: items,
|
||||||
|
metadata: {
|
||||||
|
entity: "customer-invoices",
|
||||||
|
criteria: criteria.toJSON(),
|
||||||
|
//links: {
|
||||||
|
// self: `/api/customer-invoices?page=${criteria.pageNumber}&per_page=${criteria.pageSize}`,
|
||||||
|
// first: `/api/customer-invoices?page=1&per_page=${criteria.pageSize}`,
|
||||||
|
// last: `/api/customer-invoices?page=${Math.ceil(totalItems / criteria.pageSize)}&per_page=${criteria.pageSize}`,
|
||||||
|
//},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import { Criteria } from "@repo/rdx-criteria/server";
|
||||||
import { Collection } from "@repo/rdx-utils";
|
import { toEmptyString } from "@repo/rdx-ddd";
|
||||||
|
import { ArrayElement, Collection } from "@repo/rdx-utils";
|
||||||
import { CustomerInvoiceListResponseDTO } from "../../../../common/dto";
|
import { CustomerInvoiceListResponseDTO } from "../../../../common/dto";
|
||||||
import { CustomerInvoice } from "../../../domain";
|
import { CustomerInvoice } from "../../../domain";
|
||||||
|
|
||||||
@ -8,27 +9,57 @@ export class ListCustomerInvoicesAssembler {
|
|||||||
customerInvoices: Collection<CustomerInvoice>,
|
customerInvoices: Collection<CustomerInvoice>,
|
||||||
criteria: Criteria
|
criteria: Criteria
|
||||||
): CustomerInvoiceListResponseDTO {
|
): CustomerInvoiceListResponseDTO {
|
||||||
const items = customerInvoices.map((invoice) => {
|
const invoices = customerInvoices.map((invoice) => {
|
||||||
return {
|
const recipientDTO = invoice.recipient.match(
|
||||||
id: invoice.id.toPrimitive(),
|
(recipient) => recipient.toString(),
|
||||||
|
() => ({
|
||||||
|
tin: "",
|
||||||
|
name: "",
|
||||||
|
street: "",
|
||||||
|
street2: "",
|
||||||
|
city: "",
|
||||||
|
postal_code: "",
|
||||||
|
province: "",
|
||||||
|
country: "",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const allAmounts = invoice.getAllAmounts();
|
||||||
|
|
||||||
|
const invoiceDTO: ArrayElement<CustomerInvoiceListResponseDTO["items"]> = {
|
||||||
|
id: invoice.id.toString(),
|
||||||
|
company_id: invoice.companyId.toString(),
|
||||||
|
customer_id: invoice.customerId.toString(),
|
||||||
|
|
||||||
invoice_status: invoice.status.toString(),
|
|
||||||
invoice_number: invoice.invoiceNumber.toString(),
|
invoice_number: invoice.invoiceNumber.toString(),
|
||||||
invoice_series: invoice.invoiceSeries.toString(),
|
status: invoice.status.toPrimitive(),
|
||||||
invoice_date: invoice.invoiceDate.toISOString(),
|
series: toEmptyString(invoice.series, (value) => value.toString()),
|
||||||
operation_date: invoice.operationDate.toISOString(),
|
|
||||||
language_code: "ES",
|
|
||||||
currency: "EUR",
|
|
||||||
|
|
||||||
subtotal_price: invoice.calculateSubtotal().toPrimitive(),
|
invoice_date: invoice.invoiceDate.toDateString(),
|
||||||
total_price: invoice.calculateTotal().toPrimitive(),
|
operation_date: toEmptyString(invoice.operationDate, (value) => value.toDateString()),
|
||||||
|
|
||||||
//recipient: CustomerInvoiceParticipantAssembler(customerInvoice.recipient),
|
recipient: {
|
||||||
|
customer_id: invoice.customerId.toString(),
|
||||||
|
...recipientDTO,
|
||||||
|
},
|
||||||
|
|
||||||
|
taxes: invoice.taxes
|
||||||
|
.getAll()
|
||||||
|
.map((taxItem) => taxItem.tax.code)
|
||||||
|
.join(","),
|
||||||
|
|
||||||
|
subtotal_amount: allAmounts.subtotalAmount.toObjectString(),
|
||||||
|
discount_amount: allAmounts.discountAmount.toObjectString(),
|
||||||
|
taxable_amount: allAmounts.taxableAmount.toObjectString(),
|
||||||
|
taxes_amount: allAmounts.taxesAmount.toObjectString(),
|
||||||
|
total_amount: allAmounts.totalAmount.toObjectString(),
|
||||||
|
|
||||||
metadata: {
|
metadata: {
|
||||||
entity: "customer-invoice",
|
entity: "customer-invoice",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return invoiceDTO;
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalItems = customerInvoices.total();
|
const totalItems = customerInvoices.total();
|
||||||
@ -38,7 +69,7 @@ export class ListCustomerInvoicesAssembler {
|
|||||||
per_page: criteria.pageSize,
|
per_page: criteria.pageSize,
|
||||||
total_pages: Math.ceil(totalItems / criteria.pageSize),
|
total_pages: Math.ceil(totalItems / criteria.pageSize),
|
||||||
total_items: totalItems,
|
total_items: totalItems,
|
||||||
items: items,
|
items: invoices,
|
||||||
metadata: {
|
metadata: {
|
||||||
entity: "customer-invoices",
|
entity: "customer-invoices",
|
||||||
criteria: criteria.toJSON(),
|
criteria: criteria.toJSON(),
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import {
|
|||||||
AggregateRoot,
|
AggregateRoot,
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
MoneyValue,
|
|
||||||
Percentage,
|
Percentage,
|
||||||
TextValue,
|
TextValue,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
@ -16,6 +15,7 @@ import {
|
|||||||
CustomerInvoiceNumber,
|
CustomerInvoiceNumber,
|
||||||
CustomerInvoiceSerie,
|
CustomerInvoiceSerie,
|
||||||
CustomerInvoiceStatus,
|
CustomerInvoiceStatus,
|
||||||
|
InvoiceAmount,
|
||||||
InvoiceRecipient,
|
InvoiceRecipient,
|
||||||
} from "../value-objects";
|
} from "../value-objects";
|
||||||
|
|
||||||
@ -38,22 +38,29 @@ export interface CustomerInvoiceProps {
|
|||||||
languageCode: LanguageCode;
|
languageCode: LanguageCode;
|
||||||
currencyCode: CurrencyCode;
|
currencyCode: CurrencyCode;
|
||||||
|
|
||||||
//subtotalAmount: MoneyValue;
|
taxes: Maybe<InvoiceTaxes>;
|
||||||
|
items: CustomerInvoiceItems;
|
||||||
|
|
||||||
discountPercentage: Percentage;
|
discountPercentage: Percentage;
|
||||||
//discountAmount: MoneyValue;
|
}
|
||||||
|
|
||||||
taxes: InvoiceTaxes;
|
export interface ICustomerInvoice {
|
||||||
|
getSubtotalAmount(): InvoiceAmount;
|
||||||
|
getDiscountAmount(): InvoiceAmount;
|
||||||
|
|
||||||
//totalAmount: MoneyValue;
|
getTaxableAmount(): InvoiceAmount;
|
||||||
|
getTaxesAmount(): InvoiceAmount;
|
||||||
items: CustomerInvoiceItems;
|
getTotalAmount(): InvoiceAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CustomerInvoicePatchProps = Partial<Omit<CustomerInvoiceProps, "companyId">>;
|
export type CustomerInvoicePatchProps = Partial<Omit<CustomerInvoiceProps, "companyId">>;
|
||||||
|
|
||||||
export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
export class CustomerInvoice
|
||||||
|
extends AggregateRoot<CustomerInvoiceProps>
|
||||||
|
implements ICustomerInvoice
|
||||||
|
{
|
||||||
private _items!: CustomerInvoiceItems;
|
private _items!: CustomerInvoiceItems;
|
||||||
|
private _taxes!: InvoiceTaxes;
|
||||||
|
|
||||||
protected constructor(props: CustomerInvoiceProps, id?: UniqueID) {
|
protected constructor(props: CustomerInvoiceProps, id?: UniqueID) {
|
||||||
super(props, id);
|
super(props, id);
|
||||||
@ -63,6 +70,11 @@ export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
|||||||
languageCode: props.languageCode,
|
languageCode: props.languageCode,
|
||||||
currencyCode: props.currencyCode,
|
currencyCode: props.currencyCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this._taxes = props.taxes.match(
|
||||||
|
(taxes) => taxes,
|
||||||
|
() => InvoiceTaxes.create({})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static create(props: CustomerInvoiceProps, id?: UniqueID): Result<CustomerInvoice, Error> {
|
static create(props: CustomerInvoiceProps, id?: UniqueID): Result<CustomerInvoice, Error> {
|
||||||
@ -139,101 +151,60 @@ export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
|||||||
return this.props.currencyCode;
|
return this.props.currencyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get subtotalAmount(): MoneyValue {
|
|
||||||
throw new Error("discountAmount not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public get discountPercentage(): Percentage {
|
public get discountPercentage(): Percentage {
|
||||||
return this.props.discountPercentage;
|
return this.props.discountPercentage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get discountAmount(): MoneyValue {
|
|
||||||
throw new Error("discountAmount not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public get taxableAmount(): MoneyValue {
|
|
||||||
throw new Error("taxableAmount not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public get taxAmount(): MoneyValue {
|
|
||||||
throw new Error("discountAmount not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
public get totalAmount(): MoneyValue {
|
|
||||||
throw new Error("totalAmount not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to get the complete list of line items
|
// Method to get the complete list of line items
|
||||||
get items(): CustomerInvoiceItems {
|
public get items(): CustomerInvoiceItems {
|
||||||
return this._items;
|
return this._items;
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasRecipient() {
|
public get taxes(): InvoiceTaxes {
|
||||||
|
return this._taxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get hasRecipient() {
|
||||||
return this.recipient.isSome();
|
return this.recipient.isSome();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*get senderId(): UniqueID {
|
public getSubtotalAmount(): InvoiceAmount {
|
||||||
return this.props.senderId;
|
const itemsSubtotal = this.items.getTotalAmount().convertScale(2);
|
||||||
}*/
|
|
||||||
|
|
||||||
/* get customer(): CustomerInvoiceCustomer | undefined {
|
return InvoiceAmount.create({
|
||||||
return this.props.customer;
|
value: itemsSubtotal.value,
|
||||||
}*/
|
currency_code: this.currencyCode.code,
|
||||||
|
}).data as InvoiceAmount;
|
||||||
/*get purchareOrderNumber() {
|
|
||||||
return this.props.purchareOrderNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get paymentInstructions() {
|
public getDiscountAmount(): InvoiceAmount {
|
||||||
return this.props.paymentInstructions;
|
return this.getSubtotalAmount().percentage(this.discountPercentage) as InvoiceAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
get paymentTerms() {
|
public getTaxableAmount(): InvoiceAmount {
|
||||||
return this.props.paymentTerms;
|
return this.getSubtotalAmount().subtract(this.getDiscountAmount()) as InvoiceAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
get billTo() {
|
public getTaxesAmount(): InvoiceAmount {
|
||||||
return this.props.billTo;
|
return this._getTaxesAmount(this.getTaxableAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
get shipTo() {
|
public getTotalAmount(): InvoiceAmount {
|
||||||
return this.props.shipTo;
|
const taxableAmount = this.getTaxableAmount();
|
||||||
}*/
|
return taxableAmount.add(this._getTaxesAmount(taxableAmount)) as InvoiceAmount;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
public getAllAmounts() {
|
||||||
addLineItem(lineItem: CustomerInvoiceLineItem, position?: number): void {
|
return {
|
||||||
if (position === undefined) {
|
subtotalAmount: this.getSubtotalAmount(),
|
||||||
this._lineItems.push(lineItem);
|
discountAmount: this.getDiscountAmount(),
|
||||||
} else {
|
taxableAmount: this.getTaxableAmount(),
|
||||||
this._lineItems.splice(position, 0, lineItem);
|
taxesAmount: this.getTaxesAmount(),
|
||||||
}
|
totalAmount: this.getTotalAmount(),
|
||||||
}*/
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/*calculateSubtotal(): MoneyValue {
|
private _getTaxesAmount(_taxableAmount: InvoiceAmount): InvoiceAmount {
|
||||||
const customerInvoiceSubtotal = MoneyValue.create({
|
return this._taxes.getTaxesAmount(_taxableAmount);
|
||||||
amount: 0,
|
}
|
||||||
currency_code: this.props.currency,
|
|
||||||
scale: 2,
|
|
||||||
}).data;
|
|
||||||
|
|
||||||
return this._items.getAll().reduce((subtotal, item) => {
|
|
||||||
return subtotal.add(item.calculateTotal());
|
|
||||||
}, customerInvoiceSubtotal);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Method to calculate the total tax in the customerInvoice
|
|
||||||
/*calculateTaxTotal(): MoneyValue {
|
|
||||||
const taxTotal = MoneyValue.create({
|
|
||||||
amount: 0,
|
|
||||||
currency_code: this.props.currency,
|
|
||||||
scale: 2,
|
|
||||||
}).data;
|
|
||||||
|
|
||||||
return taxTotal;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// Method to calculate the total customerInvoice amount, including taxes
|
|
||||||
/*calculateTotal(): MoneyValue {
|
|
||||||
return this.calculateSubtotal().add(this.calculateTaxTotal());
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { CurrencyCode, LanguageCode } from "@repo/rdx-ddd";
|
import { CurrencyCode, LanguageCode } from "@repo/rdx-ddd";
|
||||||
import { Collection } from "@repo/rdx-utils";
|
import { Collection } from "@repo/rdx-utils";
|
||||||
|
import { ItemAmount } from "../../value-objects";
|
||||||
import { CustomerInvoiceItem } from "./customer-invoice-item";
|
import { CustomerInvoiceItem } from "./customer-invoice-item";
|
||||||
|
|
||||||
export interface CustomerInvoiceItemsProps {
|
export interface CustomerInvoiceItemsProps {
|
||||||
@ -26,11 +27,19 @@ export class CustomerInvoiceItems extends Collection<CustomerInvoiceItem> {
|
|||||||
add(item: CustomerInvoiceItem): boolean {
|
add(item: CustomerInvoiceItem): boolean {
|
||||||
// Antes de añadir un nuevo item, debo comprobar que el item a añadir
|
// Antes de añadir un nuevo item, debo comprobar que el item a añadir
|
||||||
// tiene el mismo "currencyCode" y "languageCode" que la colección de items.
|
// tiene el mismo "currencyCode" y "languageCode" que la colección de items.
|
||||||
if (!this._languageCode.equals(item.languageCode) || !this._currencyCode.equals(item.currencyCode)) {
|
if (
|
||||||
|
!this._languageCode.equals(item.languageCode) ||
|
||||||
|
!this._currencyCode.equals(item.currencyCode)
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
return super.add(item)
|
return super.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTotalAmount(): ItemAmount {
|
||||||
|
return this.getAll().reduce(
|
||||||
|
(total, tax) => total.add(tax.getTotalAmount()),
|
||||||
|
ItemAmount.zero(this._currencyCode.code)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Collection } from "@repo/rdx-utils";
|
import { Collection } from "@repo/rdx-utils";
|
||||||
|
import { InvoiceAmount } from "../../value-objects";
|
||||||
import { InvoiceTax } from "./invoice-tax";
|
import { InvoiceTax } from "./invoice-tax";
|
||||||
|
|
||||||
export interface InvoiceTaxesProps {
|
export interface InvoiceTaxesProps {
|
||||||
@ -14,4 +15,11 @@ export class InvoiceTaxes extends Collection<InvoiceTax> {
|
|||||||
public static create(props: InvoiceTaxesProps): InvoiceTaxes {
|
public static create(props: InvoiceTaxesProps): InvoiceTaxes {
|
||||||
return new InvoiceTaxes(props);
|
return new InvoiceTaxes(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getTaxesAmount(taxableAmount: InvoiceAmount): InvoiceAmount {
|
||||||
|
return this.getAll().reduce(
|
||||||
|
(total, tax) => total.add(tax.getTaxAmount(taxableAmount)),
|
||||||
|
InvoiceAmount.zero(taxableAmount.currencyCode)
|
||||||
|
) as InvoiceAmount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,8 @@ export class CustomerInvoiceAddressType extends ValueObject<ICustomerInvoiceAddr
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
|
|||||||
@ -50,8 +50,8 @@ export class CustomerInvoiceItemDescription extends ValueObject<CustomerInvoiceI
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
|
|||||||
@ -42,8 +42,8 @@ export class CustomerInvoiceNumber extends ValueObject<ICustomerInvoiceNumberPro
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
|
|||||||
@ -50,8 +50,8 @@ export class CustomerInvoiceSerie extends ValueObject<ICustomerInvoiceSerieProps
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
|
|||||||
@ -95,7 +95,7 @@ export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusPro
|
|||||||
return CustomerInvoiceStatus.create(nextStatus);
|
return CustomerInvoiceStatus.create(nextStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { MoneyValue, MoneyValueProps } from "@repo/rdx-ddd";
|
import { MoneyValue, MoneyValueProps, Percentage, Quantity } from "@repo/rdx-ddd";
|
||||||
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
type InvoiceAmountProps = Pick<MoneyValueProps, "value" | "currency_code">;
|
type InvoiceAmountProps = Pick<MoneyValueProps, "value" | "currency_code">;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ export class InvoiceAmount extends MoneyValue {
|
|||||||
scale: InvoiceAmount.DEFAULT_SCALE,
|
scale: InvoiceAmount.DEFAULT_SCALE,
|
||||||
currency_code,
|
currency_code,
|
||||||
};
|
};
|
||||||
return MoneyValue.create(props);
|
return Result.ok(new InvoiceAmount(props));
|
||||||
}
|
}
|
||||||
|
|
||||||
static zero(currency_code: string) {
|
static zero(currency_code: string) {
|
||||||
@ -19,6 +20,50 @@ export class InvoiceAmount extends MoneyValue {
|
|||||||
value: 0,
|
value: 0,
|
||||||
currency_code,
|
currency_code,
|
||||||
};
|
};
|
||||||
return InvoiceAmount.create(props);
|
return InvoiceAmount.create(props).data;
|
||||||
|
}
|
||||||
|
|
||||||
|
toObjectString() {
|
||||||
|
return {
|
||||||
|
value: String(this.value),
|
||||||
|
scale: String(this.scale),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure fluent operations keep the subclass type
|
||||||
|
convertScale(newScale: number) {
|
||||||
|
const mv = super.convertScale(newScale);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
add(addend: MoneyValue) {
|
||||||
|
const mv = super.add(addend);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
subtract(subtrahend: MoneyValue) {
|
||||||
|
const mv = super.subtract(subtrahend);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(multiplier: number | Quantity) {
|
||||||
|
const mv = super.multiply(multiplier);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
divide(divisor: number | Quantity) {
|
||||||
|
const mv = super.divide(divisor);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
percentage(percentage: number | Percentage) {
|
||||||
|
const mv = super.percentage(percentage);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new InvoiceAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
Street,
|
Street,
|
||||||
TINNumber,
|
TINNumber,
|
||||||
ValueObject,
|
ValueObject,
|
||||||
|
toEmptyString,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
@ -84,4 +85,17 @@ export class InvoiceRecipient extends ValueObject<InvoiceRecipientProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return {
|
||||||
|
tin: this.tin.toString(),
|
||||||
|
name: this.name.toString(),
|
||||||
|
street: toEmptyString(this.street, (value) => value.toString()),
|
||||||
|
street2: toEmptyString(this.street2, (value) => value.toString()),
|
||||||
|
city: toEmptyString(this.city, (value) => value.toString()),
|
||||||
|
postal_code: toEmptyString(this.postalCode, (value) => value.toString()),
|
||||||
|
province: toEmptyString(this.province, (value) => value.toString()),
|
||||||
|
country: toEmptyString(this.country, (value) => value.toString()),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { MoneyValue, MoneyValueProps } from "@repo/rdx-ddd";
|
import { MoneyValue, MoneyValueProps, Percentage, Quantity } from "@repo/rdx-ddd";
|
||||||
|
import { Result } from "@repo/rdx-utils";
|
||||||
|
|
||||||
type ItemAmountProps = Pick<MoneyValueProps, "value" | "currency_code">;
|
type ItemAmountProps = Pick<MoneyValueProps, "value" | "currency_code">;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ export class ItemAmount extends MoneyValue {
|
|||||||
scale: ItemAmount.DEFAULT_SCALE,
|
scale: ItemAmount.DEFAULT_SCALE,
|
||||||
currency_code,
|
currency_code,
|
||||||
};
|
};
|
||||||
return MoneyValue.create(props);
|
return Result.ok(new ItemAmount(props));
|
||||||
}
|
}
|
||||||
|
|
||||||
static zero(currency_code: string) {
|
static zero(currency_code: string) {
|
||||||
@ -21,4 +22,41 @@ export class ItemAmount extends MoneyValue {
|
|||||||
};
|
};
|
||||||
return ItemAmount.create(props).data;
|
return ItemAmount.create(props).data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure fluent operations keep the subclass type
|
||||||
|
convertScale(newScale: number) {
|
||||||
|
const mv = super.convertScale(newScale);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
add(addend: MoneyValue) {
|
||||||
|
const mv = super.add(addend);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
subtract(subtrahend: MoneyValue) {
|
||||||
|
const mv = super.subtract(subtrahend);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
multiply(multiplier: number | Quantity) {
|
||||||
|
const mv = super.multiply(multiplier);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
divide(divisor: number | Quantity) {
|
||||||
|
const mv = super.divide(divisor);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
|
|
||||||
|
percentage(percentage: number | Percentage) {
|
||||||
|
const mv = super.percentage(percentage);
|
||||||
|
const p = mv.toPrimitive();
|
||||||
|
return new ItemAmount({ value: p.value, currency_code: p.currency_code });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import {
|
|||||||
UtcDate,
|
UtcDate,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
import {
|
import {
|
||||||
CustomerInvoice,
|
CustomerInvoice,
|
||||||
CustomerInvoiceItems,
|
CustomerInvoiceItems,
|
||||||
@ -118,13 +118,11 @@ export class CustomerInvoiceMapper
|
|||||||
);
|
);
|
||||||
|
|
||||||
const discountPercentage = extractOrPushError(
|
const discountPercentage = extractOrPushError(
|
||||||
maybeFromNullableVO(source.discount_percentage_value, (value) =>
|
Percentage.create({
|
||||||
Percentage.create({
|
value: source.discount_amount_scale,
|
||||||
value: value,
|
scale: source.discount_percentage_scale,
|
||||||
scale: source.discount_percentage_scale,
|
}),
|
||||||
})
|
"discount_percentage_value",
|
||||||
),
|
|
||||||
"discount_percentage",
|
|
||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -155,31 +153,7 @@ export class CustomerInvoiceMapper
|
|||||||
// 1) Valores escalares (atributos generales)
|
// 1) Valores escalares (atributos generales)
|
||||||
const attributes = this.mapAttributesToDomain(source, { errors, ...params });
|
const attributes = this.mapAttributesToDomain(source, { errors, ...params });
|
||||||
|
|
||||||
// 2) Comprobar relaciones
|
// 2) Recipient (snapshot en la factura o include)
|
||||||
const requireIncludes = Boolean(params?.requireIncludes);
|
|
||||||
if (requireIncludes) {
|
|
||||||
if (!source.items) {
|
|
||||||
errors.push({
|
|
||||||
path: "items",
|
|
||||||
message: "Items not included in query (requireIncludes=true)",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!source.taxes) {
|
|
||||||
errors.push({
|
|
||||||
path: "taxes",
|
|
||||||
message: "Taxes not included in query (requireIncludes=true)",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attributes.isProforma && !source.current_customer) {
|
|
||||||
errors.push({
|
|
||||||
path: "current_customer",
|
|
||||||
message: "Current customer not included in query (requireIncludes=true)",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3) Recipient (snapshot en la factura o include)
|
|
||||||
const recipientResult = this._recipientMapper.mapToDomain(source, {
|
const recipientResult = this._recipientMapper.mapToDomain(source, {
|
||||||
errors,
|
errors,
|
||||||
attributes,
|
attributes,
|
||||||
@ -194,7 +168,7 @@ export class CustomerInvoiceMapper
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Items (colección)
|
// 3) Items (colección)
|
||||||
const itemsResults = this._itemsMapper.mapArrayToDomain(source.items, {
|
const itemsResults = this._itemsMapper.mapArrayToDomain(source.items, {
|
||||||
errors,
|
errors,
|
||||||
attributes,
|
attributes,
|
||||||
@ -208,7 +182,7 @@ export class CustomerInvoiceMapper
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5) Taxes (colección a nivel factura)
|
// 4) Taxes (colección a nivel factura)
|
||||||
const taxesResults = this._taxesMapper.mapArrayToDomain(source.taxes, {
|
const taxesResults = this._taxesMapper.mapArrayToDomain(source.taxes, {
|
||||||
errors,
|
errors,
|
||||||
attributes,
|
attributes,
|
||||||
@ -222,14 +196,14 @@ export class CustomerInvoiceMapper
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6) Si hubo errores de mapeo, devolvemos colección de validación
|
// 5) Si hubo errores de mapeo, devolvemos colección de validación
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
new ValidationErrorCollection("Customer invoice mapping failed", errors)
|
new ValidationErrorCollection("Customer invoice mapping failed", errors)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7) Construcción del agregado (Dominio)
|
// 6) Construcción del agregado (Dominio)
|
||||||
|
|
||||||
const recipient = recipientResult.data;
|
const recipient = recipientResult.data;
|
||||||
|
|
||||||
@ -261,9 +235,9 @@ export class CustomerInvoiceMapper
|
|||||||
languageCode: attributes.languageCode!,
|
languageCode: attributes.languageCode!,
|
||||||
currencyCode: attributes.currencyCode!,
|
currencyCode: attributes.currencyCode!,
|
||||||
|
|
||||||
//discountPercentage: attributes.discountPercentage!,
|
discountPercentage: attributes.discountPercentage!,
|
||||||
|
|
||||||
taxes,
|
taxes: Maybe.some(taxes),
|
||||||
items,
|
items,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,11 @@ export class InvoiceRecipientMapper {
|
|||||||
source: CustomerInvoiceModel,
|
source: CustomerInvoiceModel,
|
||||||
params?: MapperParamsType
|
params?: MapperParamsType
|
||||||
): Result<Maybe<InvoiceRecipient>, Error> {
|
): Result<Maybe<InvoiceRecipient>, Error> {
|
||||||
|
/**
|
||||||
|
* - Factura === proforma -> datos de "current_customer"
|
||||||
|
* - Factura !== proforma -> snapshot de los datos (campos customer_*)
|
||||||
|
*/
|
||||||
|
|
||||||
const { errors, attributes } = params as {
|
const { errors, attributes } = params as {
|
||||||
errors: ValidationErrorDetail[];
|
errors: ValidationErrorDetail[];
|
||||||
attributes: Partial<CustomerInvoiceProps>;
|
attributes: Partial<CustomerInvoiceProps>;
|
||||||
@ -31,6 +36,13 @@ export class InvoiceRecipientMapper {
|
|||||||
|
|
||||||
const { isProforma } = attributes;
|
const { isProforma } = attributes;
|
||||||
|
|
||||||
|
if (isProforma && !source.current_customer) {
|
||||||
|
errors.push({
|
||||||
|
path: "current_customer",
|
||||||
|
message: "Current customer not included in query (InvoiceRecipientMapper)",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const _name = isProforma ? source.current_customer.name : source.customer_name;
|
const _name = isProforma ? source.current_customer.name : source.customer_name;
|
||||||
const _tin = isProforma ? source.current_customer.tin : source.customer_tin;
|
const _tin = isProforma ? source.current_customer.tin : source.customer_tin;
|
||||||
const _street = isProforma ? source.current_customer.street : source.customer_street;
|
const _street = isProforma ? source.current_customer.street : source.customer_street;
|
||||||
|
|||||||
@ -191,6 +191,12 @@ export class CustomerInvoiceRepository
|
|||||||
as: "current_customer",
|
as: "current_customer",
|
||||||
required: false, // false => LEFT JOIN
|
required: false, // false => LEFT JOIN
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
model: CustomerInvoiceTaxModel,
|
||||||
|
as: "taxes",
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const instances = await CustomerInvoiceModel.findAll({
|
const instances = await CustomerInvoiceModel.findAll({
|
||||||
|
|||||||
@ -1,28 +1,37 @@
|
|||||||
import { MetadataSchema, createListViewResponseSchema } from "@erp/core";
|
import { AmountSchema, MetadataSchema, createListViewResponseSchema } from "@erp/core";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const CustomerInvoiceListResponseSchema = createListViewResponseSchema(
|
export const CustomerInvoiceListResponseSchema = createListViewResponseSchema(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
invoice_status: z.string(),
|
company_id: z.uuid(),
|
||||||
|
customer_id: z.string(),
|
||||||
|
|
||||||
invoice_number: z.string(),
|
invoice_number: z.string(),
|
||||||
invoice_series: z.string(),
|
status: z.string(),
|
||||||
invoice_date: z.iso.datetime({ offset: true }),
|
series: z.string(),
|
||||||
operation_date: z.iso.datetime({ offset: true }),
|
|
||||||
language_code: z.string(),
|
|
||||||
currency: z.string(),
|
|
||||||
|
|
||||||
subtotal_price: z.object({
|
invoice_date: z.string(),
|
||||||
amount: z.number(),
|
operation_date: z.string(),
|
||||||
scale: z.number(),
|
|
||||||
currency_code: z.string(),
|
|
||||||
}),
|
|
||||||
|
|
||||||
total_price: z.object({
|
recipient: {
|
||||||
amount: z.number(),
|
tin: z.string(),
|
||||||
scale: z.number(),
|
name: z.string(),
|
||||||
currency_code: z.string(),
|
street: z.string(),
|
||||||
}),
|
street2: z.string(),
|
||||||
|
city: z.string(),
|
||||||
|
postal_code: z.string(),
|
||||||
|
province: z.string(),
|
||||||
|
country: z.string(),
|
||||||
|
},
|
||||||
|
|
||||||
|
taxes: z.string(),
|
||||||
|
|
||||||
|
subtotal_amount: AmountSchema,
|
||||||
|
discount_amount: AmountSchema,
|
||||||
|
taxable_amount: AmountSchema,
|
||||||
|
taxes_amount: AmountSchema,
|
||||||
|
total_amount: AmountSchema,
|
||||||
|
|
||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
})
|
})
|
||||||
|
|||||||
@ -28,8 +28,8 @@ export class CustomerAddressType extends ValueObject<ICustomerAddressTypeProps>
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
|
|||||||
@ -38,8 +38,8 @@ export class CustomerNumber extends ValueObject<ICustomerNumberProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
|
|||||||
@ -46,8 +46,8 @@ export class CustomerSerie extends ValueObject<ICustomerSerieProps> {
|
|||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
toString() {
|
||||||
return this.getProps();
|
return String(this.props.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
|
|||||||
@ -53,6 +53,10 @@ export class CustomerStatus extends ValueObject<ICustomerStatusProps> {
|
|||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
|
|
||||||
canTransitionTo(nextStatus: string): boolean {
|
canTransitionTo(nextStatus: string): boolean {
|
||||||
return CustomerStatus.TRANSITIONS[this.props.value].includes(nextStatus);
|
return CustomerStatus.TRANSITIONS[this.props.value].includes(nextStatus);
|
||||||
}
|
}
|
||||||
@ -65,8 +69,4 @@ export class CustomerStatus extends ValueObject<ICustomerStatusProps> {
|
|||||||
}
|
}
|
||||||
return CustomerStatus.create(nextStatus);
|
return CustomerStatus.create(nextStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return this.getProps();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,6 +39,8 @@ export class CustomerModel extends Model<
|
|||||||
declare language_code: string;
|
declare language_code: string;
|
||||||
declare currency_code: string;
|
declare currency_code: string;
|
||||||
|
|
||||||
|
declare factuges_id: string;
|
||||||
|
|
||||||
static associate(database: Sequelize) {}
|
static associate(database: Sequelize) {}
|
||||||
|
|
||||||
static hooks(database: Sequelize) {}
|
static hooks(database: Sequelize) {}
|
||||||
@ -166,6 +168,12 @@ export default (database: Sequelize) => {
|
|||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: "active",
|
defaultValue: "active",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
factuges_id: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: true,
|
||||||
|
defaultValue: null,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize: database,
|
sequelize: database,
|
||||||
|
|||||||
@ -35,4 +35,8 @@ export class City extends ValueObject<CityProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,4 +35,8 @@ export class Country extends ValueObject<CountryProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,4 +45,8 @@ export class EmailAddress extends ValueObject<EmailAddressProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,4 +51,8 @@ export class Name extends ValueObject<NameProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,6 +59,10 @@ export class PhoneNumber extends ValueObject<PhoneNumberProps> {
|
|||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
|
|
||||||
getCountryCode(): string | undefined {
|
getCountryCode(): string | undefined {
|
||||||
return parsePhoneNumberWithError(this.props.value).country;
|
return parsePhoneNumberWithError(this.props.value).country;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { Maybe, Result } from "@repo/rdx-utils";
|
import { Maybe, Result } from "@repo/rdx-utils";
|
||||||
|
import { toEmptyString } from "../helpers";
|
||||||
import { City } from "./city";
|
import { City } from "./city";
|
||||||
import { Country } from "./country";
|
import { Country } from "./country";
|
||||||
import { PostalCode } from "./postal-code";
|
import { PostalCode } from "./postal-code";
|
||||||
@ -15,15 +16,6 @@ export interface PostalAddressProps {
|
|||||||
country: Maybe<Country>;
|
country: Maybe<Country>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PostalAddressSnapshot {
|
|
||||||
street: string | null;
|
|
||||||
street2: string | null;
|
|
||||||
city: string | null;
|
|
||||||
postalCode: string | null;
|
|
||||||
province: string | null;
|
|
||||||
country: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PostalAddressPatchProps = Partial<PostalAddressProps>;
|
export type PostalAddressPatchProps = Partial<PostalAddressProps>;
|
||||||
|
|
||||||
export class PostalAddress extends ValueObject<PostalAddressProps> {
|
export class PostalAddress extends ValueObject<PostalAddressProps> {
|
||||||
@ -81,6 +73,17 @@ export class PostalAddress extends ValueObject<PostalAddressProps> {
|
|||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return {
|
||||||
|
street: toEmptyString(this.street, (value) => value.toString()),
|
||||||
|
street2: toEmptyString(this.street2, (value) => value.toString()),
|
||||||
|
city: toEmptyString(this.city, (value) => value.toString()),
|
||||||
|
postal_code: toEmptyString(this.postalCode, (value) => value.toString()),
|
||||||
|
province: toEmptyString(this.province, (value) => value.toString()),
|
||||||
|
country: toEmptyString(this.country, (value) => value.toString()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
toFormat(): string {
|
toFormat(): string {
|
||||||
return `${this.props.street}, ${this.props.street2}, ${this.props.city}, ${this.props.postalCode}, ${this.props.province}, ${this.props.country}`;
|
return `${this.props.street}, ${this.props.street2}, ${this.props.city}, ${this.props.postalCode}, ${this.props.province}, ${this.props.country}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,4 +43,8 @@ export class PostalCode extends ValueObject<PostalCodeProps> {
|
|||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,4 +35,8 @@ export class Province extends ValueObject<ProvinceProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,4 +39,8 @@ export class Slug extends ValueObject<SlugProps> {
|
|||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,4 +35,8 @@ export class Street extends ValueObject<StreetProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,4 +43,8 @@ export class TaxCode extends ValueObject<TaxCodeProps> {
|
|||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,4 +40,8 @@ export class TINNumber extends ValueObject<TINNumberProps> {
|
|||||||
toPrimitive(): string {
|
toPrimitive(): string {
|
||||||
return this.props.value;
|
return this.props.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,4 +29,8 @@ export class URLAddress extends ValueObject<URLAddressProps> {
|
|||||||
toPrimitive() {
|
toPrimitive() {
|
||||||
return this.getProps();
|
return this.getProps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return String(this.props.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,6 +58,10 @@ export class UtcDate extends ValueObject<UtcDateProps> {
|
|||||||
return this.date.toISOString().split("T")[0];
|
return this.date.toISOString().split("T")[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return this.toDateString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Devuelve la fecha en formato UTC con hora (ISO 8601). Ejemplo: 2025-12-31T23:59:59Z.
|
* Devuelve la fecha en formato UTC con hora (ISO 8601). Ejemplo: 2025-12-31T23:59:59Z.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -5,4 +5,5 @@ export * from "./patch-field";
|
|||||||
export * from "./result";
|
export * from "./result";
|
||||||
export * from "./result-collection";
|
export * from "./result-collection";
|
||||||
export * from "./rule-validator";
|
export * from "./rule-validator";
|
||||||
|
export * from "./types";
|
||||||
export * from "./utils";
|
export * from "./utils";
|
||||||
|
|||||||
1
packages/rdx-utils/src/helpers/types.ts
Normal file
1
packages/rdx-utils/src/helpers/types.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type ArrayElement<T> = T extends readonly (infer U)[] ? U : never;
|
||||||
Loading…
Reference in New Issue
Block a user