FactuGES_ERP/modules/customers/src/api/domain/aggregates/customer.aggregate.ts

252 lines
5.7 KiB
TypeScript
Raw Normal View History

2025-08-11 17:49:52 +00:00
import {
AggregateRoot,
2025-11-17 17:20:18 +00:00
type CurrencyCode,
type EmailAddress,
type LanguageCode,
type Name,
type PhoneNumber,
2026-03-09 20:23:48 +00:00
PostalAddress,
2025-11-17 17:20:18 +00:00
type PostalAddressPatchProps,
2026-03-09 20:23:48 +00:00
type PostalAddressProps,
2025-11-17 17:20:18 +00:00
type TINNumber,
type TextValue,
type URLAddress,
type UniqueID,
2025-08-11 17:49:52 +00:00
} from "@repo/rdx-ddd";
2026-03-16 17:45:45 +00:00
import { type Maybe, Result } from "@repo/rdx-utils";
2025-11-17 17:20:18 +00:00
2026-03-25 09:34:17 +00:00
import { type CustomerStatus, CustomerTaxes } from "../value-objects";
2025-08-11 17:49:52 +00:00
2026-03-09 20:23:48 +00:00
export interface ICustomerCreateProps {
2025-08-25 17:42:56 +00:00
companyId: UniqueID;
2025-08-26 18:55:59 +00:00
status: CustomerStatus;
2025-09-01 14:07:59 +00:00
reference: Maybe<Name>;
2025-08-26 18:55:59 +00:00
2025-08-25 17:42:56 +00:00
isCompany: boolean;
2025-09-01 14:07:59 +00:00
name: Name;
tradeName: Maybe<Name>;
tin: Maybe<TINNumber>;
2025-08-26 18:55:59 +00:00
2026-03-09 20:23:48 +00:00
address: PostalAddressProps;
2025-08-26 18:55:59 +00:00
2025-09-16 09:17:29 +00:00
emailPrimary: Maybe<EmailAddress>;
emailSecondary: Maybe<EmailAddress>;
2025-09-26 18:09:14 +00:00
2025-09-16 09:17:29 +00:00
phonePrimary: Maybe<PhoneNumber>;
phoneSecondary: Maybe<PhoneNumber>;
2025-09-26 18:09:14 +00:00
2025-09-16 09:17:29 +00:00
mobilePrimary: Maybe<PhoneNumber>;
mobileSecondary: Maybe<PhoneNumber>;
2025-09-26 18:09:14 +00:00
2025-09-01 14:07:59 +00:00
fax: Maybe<PhoneNumber>;
website: Maybe<URLAddress>;
2025-08-26 18:55:59 +00:00
2025-09-01 14:07:59 +00:00
legalRecord: Maybe<TextValue>;
2025-09-26 18:09:14 +00:00
2026-03-25 09:34:17 +00:00
defaultTaxes: CustomerTaxes;
2025-08-26 18:55:59 +00:00
2025-09-01 14:07:59 +00:00
languageCode: LanguageCode;
currencyCode: CurrencyCode;
2025-08-11 17:49:52 +00:00
}
2026-03-09 20:23:48 +00:00
export type CustomerPatchProps = Partial<
2026-03-16 17:45:45 +00:00
Omit<ICustomerCreateProps, "companyId" | "address" | "status">
2026-03-09 20:23:48 +00:00
> & {
2025-09-01 14:07:59 +00:00
address?: PostalAddressPatchProps;
};
2025-09-27 11:52:30 +00:00
// Customer
export interface ICustomer {
// comportamiento
update(partialCustomer: CustomerPatchProps): Result<Customer, Error>;
// propiedades (getters)
readonly isIndividual: boolean;
readonly isCompany: boolean;
readonly isActive: boolean;
readonly companyId: UniqueID;
readonly reference: Maybe<Name>;
readonly name: Name;
readonly tradeName: Maybe<Name>;
readonly tin: Maybe<TINNumber>;
readonly address: PostalAddress;
readonly emailPrimary: Maybe<EmailAddress>;
readonly emailSecondary: Maybe<EmailAddress>;
readonly phonePrimary: Maybe<PhoneNumber>;
readonly phoneSecondary: Maybe<PhoneNumber>;
readonly mobilePrimary: Maybe<PhoneNumber>;
readonly mobileSecondary: Maybe<PhoneNumber>;
readonly fax: Maybe<PhoneNumber>;
readonly website: Maybe<URLAddress>;
readonly legalRecord: Maybe<TextValue>;
2026-03-25 09:34:17 +00:00
readonly defaultTaxes: CustomerTaxes;
2025-09-27 11:52:30 +00:00
readonly languageCode: LanguageCode;
readonly currencyCode: CurrencyCode;
}
2026-03-25 09:34:17 +00:00
type CustomerInternalProps = Omit<ICustomerCreateProps, "address" | "defaultTaxes"> & {
2026-03-09 20:23:48 +00:00
readonly address: PostalAddress;
2026-03-25 09:34:17 +00:00
readonly defaultTaxes: CustomerTaxes;
2026-03-09 20:23:48 +00:00
};
export class Customer extends AggregateRoot<CustomerInternalProps> implements ICustomer {
static create(props: ICustomerCreateProps, id?: UniqueID): Result<Customer, Error> {
2026-03-29 19:00:07 +00:00
const validationResult = Customer.validateCreateProps(props);
if (validationResult.isFailure) {
return Result.fail(validationResult.error);
}
2026-03-25 09:34:17 +00:00
const { address, defaultTaxes, ...internalProps } = props;
2026-03-09 20:23:48 +00:00
const postalAddressResult = PostalAddress.create(address);
2026-03-07 18:27:23 +00:00
2026-03-09 20:23:48 +00:00
if (postalAddressResult.isFailure) {
return Result.fail(postalAddressResult.error);
}
2026-03-07 18:27:23 +00:00
2026-03-25 09:34:17 +00:00
const taxes = CustomerTaxes.create(defaultTaxes);
if (taxes.isFailure) {
return Result.fail(taxes.error);
}
2026-03-09 20:23:48 +00:00
const contact = new Customer(
{
...internalProps,
2026-03-25 09:34:17 +00:00
defaultTaxes: taxes.data,
2026-03-09 20:23:48 +00:00
address: postalAddressResult.data,
},
id
);
2025-08-11 17:49:52 +00:00
// Reglas de negocio / validaciones
// ...
// ...
2025-09-27 11:52:30 +00:00
// Disparar eventos de dominio
// ...
// ...
2025-08-11 17:49:52 +00:00
return Result.ok(contact);
}
2026-03-29 19:00:07 +00:00
private static validateCreateProps(props: ICustomerCreateProps): Result<void, Error> {
return Result.ok();
}
2026-03-07 18:27:23 +00:00
// Rehidratación desde persistencia
2026-03-09 20:23:48 +00:00
static rehydrate(props: CustomerInternalProps, id: UniqueID): Customer {
2026-03-07 18:27:23 +00:00
return new Customer(props, id);
}
2025-09-02 10:55:45 +00:00
public update(partialCustomer: CustomerPatchProps): Result<Customer, Error> {
const { address: partialAddress, ...rest } = partialCustomer;
2026-03-09 20:23:48 +00:00
Object.assign(this.props, rest);
2025-09-01 14:07:59 +00:00
2025-09-02 10:55:45 +00:00
if (partialAddress) {
2026-03-09 20:23:48 +00:00
const addressResult = this.address.update(partialAddress);
if (addressResult.isFailure) {
return Result.fail(addressResult.error);
2025-09-01 14:07:59 +00:00
}
}
2026-03-09 20:23:48 +00:00
return Result.ok();
2025-09-01 14:07:59 +00:00
}
2026-03-07 18:27:23 +00:00
// Getters
2025-09-01 14:07:59 +00:00
public get isIndividual(): boolean {
return !this.props.isCompany;
}
public get isCompany(): boolean {
return this.props.isCompany;
}
public get isActive(): boolean {
return this.props.status.isActive();
}
public get companyId(): UniqueID {
2025-08-25 17:42:56 +00:00
return this.props.companyId;
}
2025-09-01 14:07:59 +00:00
public get reference(): Maybe<Name> {
2025-08-11 17:49:52 +00:00
return this.props.reference;
}
2025-09-01 14:07:59 +00:00
public get name(): Name {
2025-08-11 17:49:52 +00:00
return this.props.name;
}
2025-09-01 14:07:59 +00:00
public get tradeName(): Maybe<Name> {
2025-08-11 17:49:52 +00:00
return this.props.tradeName;
}
2025-09-01 14:07:59 +00:00
public get tin(): Maybe<TINNumber> {
2025-08-11 17:49:52 +00:00
return this.props.tin;
}
2025-09-01 14:07:59 +00:00
public get address(): PostalAddress {
2025-08-11 17:49:52 +00:00
return this.props.address;
}
2025-09-16 09:17:29 +00:00
public get emailPrimary(): Maybe<EmailAddress> {
return this.props.emailPrimary;
2025-08-11 17:49:52 +00:00
}
2025-09-16 09:17:29 +00:00
public get emailSecondary(): Maybe<EmailAddress> {
return this.props.emailSecondary;
}
public get phonePrimary(): Maybe<PhoneNumber> {
return this.props.phonePrimary;
}
public get phoneSecondary(): Maybe<PhoneNumber> {
return this.props.phoneSecondary;
}
public get mobilePrimary(): Maybe<PhoneNumber> {
return this.props.mobilePrimary;
}
public get mobileSecondary(): Maybe<PhoneNumber> {
return this.props.mobileSecondary;
2025-08-11 17:49:52 +00:00
}
2025-09-01 14:07:59 +00:00
public get fax(): Maybe<PhoneNumber> {
2025-08-11 17:49:52 +00:00
return this.props.fax;
}
2025-09-01 14:07:59 +00:00
public get website(): Maybe<URLAddress> {
2025-08-11 17:49:52 +00:00
return this.props.website;
}
2025-09-01 14:07:59 +00:00
public get legalRecord(): Maybe<TextValue> {
2025-08-11 17:49:52 +00:00
return this.props.legalRecord;
}
2026-03-25 09:34:17 +00:00
public get defaultTaxes(): CustomerTaxes {
2025-09-01 14:07:59 +00:00
return this.props.defaultTaxes;
2025-08-11 17:49:52 +00:00
}
2025-09-01 14:07:59 +00:00
public get languageCode(): LanguageCode {
return this.props.languageCode;
2025-08-11 17:49:52 +00:00
}
2025-09-01 14:07:59 +00:00
public get currencyCode(): CurrencyCode {
2025-08-11 17:49:52 +00:00
return this.props.currencyCode;
}
}