FactuGES_ERP/modules/customers/src/api/application/mappers/update-customer-input.mapper.ts
2026-07-14 20:39:31 +02:00

312 lines
9.4 KiB
TypeScript

import {
City,
Country,
CurrencyCode,
DomainError,
EmailAddress,
LanguageCode,
Name,
PhoneNumber,
type PostalAddressPatchProps,
PostalCode,
Province,
Street,
TINNumber,
TextValue,
URLAddress,
UniqueID,
ValidationErrorCollection,
type ValidationErrorDetail,
extractOrPushError,
maybeFromNullableResult,
} from "@repo/rdx-ddd";
import { Result, toPatchField } from "@repo/rdx-utils";
import type {
UpdateCustomerAddressPatchRequestDTO,
UpdateCustomerByIdRequestDTO,
UpdateCustomerContactPatchRequestDTO,
} from "../../../common";
import type { CustomerPatchProps } from "../../domain";
/**
* UpdateCustomerInputMapper
* Convierte el DTO a las props validadas (CustomerProps).
* No construye directamente el agregado.
* Tri-estado:
* - campo omitido → no se cambia
* - campo con valor null/"" → se quita el valor -> set(None()),
* - campo con valor no-vacío → se pone el nuevo valor -> set(Some(VO)).
*
* @param dto - DTO con los datos a cambiar en el cliente
* @returns Cambios en las propiedades del cliente
*
*/
export interface IUpdateCustomerInputMapper {
map(
dto: UpdateCustomerByIdRequestDTO,
params: { companyId: UniqueID }
): Result<CustomerPatchProps, Error>;
}
export class UpdateCustomerInputMapper implements IUpdateCustomerInputMapper {
public map(
dto: UpdateCustomerByIdRequestDTO,
params: { companyId: UniqueID }
): Result<CustomerPatchProps, Error> {
try {
const errors: ValidationErrorDetail[] = [];
const customerPatchProps: CustomerPatchProps = {};
toPatchField(dto.reference).ifSetOrNull((reference) => {
customerPatchProps.reference = extractOrPushError(
maybeFromNullableResult(reference, (value) => Name.create(value)),
"reference",
errors
);
});
toPatchField(dto.is_company).ifSet((isCompany) => {
customerPatchProps.isCompany = isCompany;
});
toPatchField(dto.name).ifSet((name) => {
customerPatchProps.name = extractOrPushError(Name.create(name), "name", errors);
});
toPatchField(dto.trade_name).ifSetOrNull((tradeName) => {
customerPatchProps.tradeName = extractOrPushError(
maybeFromNullableResult(tradeName, (value) => Name.create(value)),
"trade_name",
errors
);
});
toPatchField(dto.tin).ifSetOrNull((tin) => {
customerPatchProps.tin = extractOrPushError(
maybeFromNullableResult(tin, (value) => TINNumber.create(value)),
"tin",
errors
);
});
toPatchField(dto.legal_record).ifSetOrNull((legalRecord) => {
customerPatchProps.legalRecord = extractOrPushError(
maybeFromNullableResult(legalRecord, (value) => TextValue.create(value)),
"legal_record",
errors
);
});
toPatchField(dto.language_code).ifSet((languageCode) => {
customerPatchProps.languageCode = extractOrPushError(
LanguageCode.create(languageCode),
"language_code",
errors
);
});
toPatchField(dto.currency_code).ifSet((currencyCode) => {
customerPatchProps.currencyCode = extractOrPushError(
CurrencyCode.create(currencyCode),
"currency_code",
errors
);
});
toPatchField(dto.payment_method_id).ifSetOrNull((paymentMethodId) => {
customerPatchProps.paymentMethodId = extractOrPushError(
maybeFromNullableResult(paymentMethodId, (value) => UniqueID.create(value)),
"payment_method_id",
errors
);
});
toPatchField(dto.payment_term_id).ifSetOrNull((paymentTermId) => {
customerPatchProps.paymentTermId = extractOrPushError(
maybeFromNullableResult(paymentTermId, (value) => UniqueID.create(value)),
"payment_term_id",
errors
);
});
toPatchField(dto.tax_regime_code).ifSetOrNull((taxRegimeCode) => {
customerPatchProps.taxRegimeCode = extractOrPushError(
maybeFromNullableResult(taxRegimeCode, (value) => Result.ok(String(value))),
"tax_regime_code",
errors
);
});
toPatchField(dto.uses_equivalence_surcharge).ifSet((usesEquivalenceSurcharge) => {
customerPatchProps.usesEquivalenceSurcharge = usesEquivalenceSurcharge;
});
toPatchField(dto.uses_retention).ifSet((usesRetention) => {
customerPatchProps.usesRetention = usesRetention;
});
this.throwIfValidationErrors(errors);
const addressPatchProps = this.mapPostalAddress(dto.address, errors);
this.throwIfValidationErrors(errors);
if (addressPatchProps) {
customerPatchProps.address = addressPatchProps;
}
this.mapContact(dto.contact, customerPatchProps, errors);
this.throwIfValidationErrors(errors);
return Result.ok(customerPatchProps);
} catch (err: unknown) {
console.error(err);
return Result.fail(new DomainError("Customer props mapping failed (update)", { cause: err }));
}
}
private mapPostalAddress(
dto: UpdateCustomerAddressPatchRequestDTO | undefined,
errors: ValidationErrorDetail[]
): PostalAddressPatchProps | undefined {
if (!dto) {
return undefined;
}
const postalAddressPatchProps: PostalAddressPatchProps = {};
toPatchField(dto.street).ifSetOrNull((street) => {
postalAddressPatchProps.street = extractOrPushError(
maybeFromNullableResult(street, (value) => Street.create(value)),
"address.street",
errors
);
});
toPatchField(dto.street2).ifSetOrNull((street2) => {
postalAddressPatchProps.street2 = extractOrPushError(
maybeFromNullableResult(street2, (value) => Street.create(value)),
"address.street2",
errors
);
});
toPatchField(dto.city).ifSetOrNull((city) => {
postalAddressPatchProps.city = extractOrPushError(
maybeFromNullableResult(city, (value) => City.create(value)),
"address.city",
errors
);
});
toPatchField(dto.province).ifSetOrNull((province) => {
postalAddressPatchProps.province = extractOrPushError(
maybeFromNullableResult(province, (value) => Province.create(value)),
"address.province",
errors
);
});
toPatchField(dto.postal_code).ifSetOrNull((postalCode) => {
postalAddressPatchProps.postalCode = extractOrPushError(
maybeFromNullableResult(postalCode, (value) => PostalCode.create(value)),
"address.postal_code",
errors
);
});
toPatchField(dto.country).ifSetOrNull((country) => {
postalAddressPatchProps.country = extractOrPushError(
maybeFromNullableResult(country, (value) => Country.create(value)),
"address.country",
errors
);
});
return Object.keys(postalAddressPatchProps).length > 0 ? postalAddressPatchProps : undefined;
}
private mapContact(
dto: UpdateCustomerContactPatchRequestDTO | undefined,
customerPatchProps: CustomerPatchProps,
errors: ValidationErrorDetail[]
): void {
if (!dto) {
return;
}
toPatchField(dto.email_primary).ifSetOrNull((emailPrimary) => {
customerPatchProps.emailPrimary = extractOrPushError(
maybeFromNullableResult(emailPrimary, (value) => EmailAddress.create(value)),
"contact.email_primary",
errors
);
});
toPatchField(dto.email_secondary).ifSetOrNull((emailSecondary) => {
customerPatchProps.emailSecondary = extractOrPushError(
maybeFromNullableResult(emailSecondary, (value) => EmailAddress.create(value)),
"contact.email_secondary",
errors
);
});
toPatchField(dto.phone_primary).ifSetOrNull((phonePrimary) => {
customerPatchProps.phonePrimary = extractOrPushError(
maybeFromNullableResult(phonePrimary, (value) => PhoneNumber.create(value)),
"contact.phone_primary",
errors
);
});
toPatchField(dto.phone_secondary).ifSetOrNull((phoneSecondary) => {
customerPatchProps.phoneSecondary = extractOrPushError(
maybeFromNullableResult(phoneSecondary, (value) => PhoneNumber.create(value)),
"contact.phone_secondary",
errors
);
});
toPatchField(dto.mobile_primary).ifSetOrNull((mobilePrimary) => {
customerPatchProps.mobilePrimary = extractOrPushError(
maybeFromNullableResult(mobilePrimary, (value) => PhoneNumber.create(value)),
"contact.mobile_primary",
errors
);
});
toPatchField(dto.mobile_secondary).ifSetOrNull((mobileSecondary) => {
customerPatchProps.mobileSecondary = extractOrPushError(
maybeFromNullableResult(mobileSecondary, (value) => PhoneNumber.create(value)),
"contact.mobile_secondary",
errors
);
});
toPatchField(dto.fax).ifSetOrNull((fax) => {
customerPatchProps.fax = extractOrPushError(
maybeFromNullableResult(fax, (value) => PhoneNumber.create(value)),
"contact.fax",
errors
);
});
toPatchField(dto.website).ifSetOrNull((website) => {
customerPatchProps.website = extractOrPushError(
maybeFromNullableResult(website, (value) => URLAddress.create(value)),
"contact.website",
errors
);
});
}
private throwIfValidationErrors(errors: ValidationErrorDetail[]): void {
if (errors.length > 0) {
throw new ValidationErrorCollection("Proforma props mapping failed", errors);
}
}
}