703 lines
19 KiB
TypeScript
703 lines
19 KiB
TypeScript
import {
|
|
DiscountPercentage,
|
|
Tax,
|
|
type TaxCalculationBehavior,
|
|
type TaxGroup,
|
|
TaxPercentage,
|
|
} from "@erp/core/api";
|
|
import {
|
|
InvoiceAmount,
|
|
type InvoiceSerie,
|
|
ItemAmount,
|
|
ItemDescription,
|
|
ItemQuantity,
|
|
type ProformaItemTaxesProps,
|
|
} from "@erp/customer-invoices/api/domain";
|
|
import {
|
|
City,
|
|
Country,
|
|
CurrencyCode,
|
|
DomainError,
|
|
EmailAddress,
|
|
LanguageCode,
|
|
Name,
|
|
PhoneNumber,
|
|
type PostalAddressProps,
|
|
PostalCode,
|
|
Province,
|
|
Street,
|
|
TINNumber,
|
|
TextValue,
|
|
URLAddress,
|
|
type UniqueID,
|
|
UtcDate,
|
|
ValidationErrorCollection,
|
|
type ValidationErrorDetail,
|
|
extractOrPushError,
|
|
isValidationErrorCollection,
|
|
maybeFromNullableResult,
|
|
} from "@repo/rdx-ddd";
|
|
import { Maybe, Result } from "@repo/rdx-utils";
|
|
|
|
import type {
|
|
CreateProformaFromFactugesRequestDTO,
|
|
CreateProformaItemFromFactugesRequestDTO,
|
|
} from "../../../common";
|
|
|
|
export type ProformaCustomerLookup = {
|
|
tin: TINNumber;
|
|
};
|
|
|
|
export type ProformaPaymentLookup = {
|
|
factuges_id: string;
|
|
};
|
|
|
|
export type ProformaCustomerDraft = {
|
|
isCompany: boolean;
|
|
name: Name;
|
|
tin: TINNumber;
|
|
address: PostalAddressProps;
|
|
emailPrimary: Maybe<EmailAddress>;
|
|
emailSecondary: Maybe<EmailAddress>;
|
|
phonePrimary: Maybe<PhoneNumber>;
|
|
phoneSecondary: Maybe<PhoneNumber>;
|
|
mobilePrimary: Maybe<PhoneNumber>;
|
|
mobileSecondary: Maybe<PhoneNumber>;
|
|
website: Maybe<URLAddress>;
|
|
languageCode: LanguageCode;
|
|
currencyCode: CurrencyCode;
|
|
};
|
|
|
|
export type ProformaDraftItem = {
|
|
position: string;
|
|
description: Maybe<ItemDescription>;
|
|
quantity: Maybe<ItemQuantity>;
|
|
unitAmount: Maybe<ItemAmount>;
|
|
subtotalAmount: Maybe<ItemAmount>;
|
|
itemDiscountPercentage: Maybe<DiscountPercentage>;
|
|
itemDiscountAmount: Maybe<ItemAmount>;
|
|
globalDiscountPercentage: DiscountPercentage;
|
|
globalDiscountAmount: Maybe<ItemAmount>;
|
|
totalDiscountAmount: Maybe<ItemAmount>;
|
|
taxableAmount: Maybe<ItemAmount>;
|
|
taxes: ProformaItemTaxesProps;
|
|
taxesAmount: Maybe<ItemAmount>;
|
|
totalAmount: Maybe<ItemAmount>;
|
|
languageCode: LanguageCode;
|
|
currencyCode: CurrencyCode;
|
|
};
|
|
|
|
export type ProformaDraft = {
|
|
factugesID: string;
|
|
proformaSeriesCode: Maybe<InvoiceSerie>;
|
|
targetInvoiceSeriesCode: Maybe<InvoiceSerie>;
|
|
invoiceDate: UtcDate;
|
|
operationDate: Maybe<UtcDate>;
|
|
reference: Maybe<string>;
|
|
description: Maybe<string>;
|
|
notes: Maybe<TextValue>;
|
|
languageCode: LanguageCode;
|
|
currencyCode: CurrencyCode;
|
|
subtotalAmount: Maybe<InvoiceAmount>;
|
|
globalDiscountPercentage: DiscountPercentage;
|
|
itemsDiscountAmount: Maybe<InvoiceAmount>;
|
|
taxableAmount: Maybe<InvoiceAmount>;
|
|
taxConfig: FactugesDefaultProformaTaxConfig;
|
|
taxes: ProformaItemTaxesProps;
|
|
taxesAmount: Maybe<InvoiceAmount>;
|
|
totalAmount: Maybe<InvoiceAmount>;
|
|
items: ProformaDraftItem[];
|
|
};
|
|
|
|
export type ProformaPaymentDraft = {
|
|
payment_id: string;
|
|
factuges_id: string;
|
|
description: string;
|
|
};
|
|
|
|
export type FactugesProformaPayload = {
|
|
customerLookup: ProformaCustomerLookup;
|
|
paymentLookup: ProformaPaymentLookup;
|
|
customerDraft: ProformaCustomerDraft;
|
|
proformaDraft: ProformaDraft;
|
|
};
|
|
|
|
type FactugesDefaultProformaTaxConfig = {
|
|
taxMode: "single";
|
|
defaultIvaCode: Maybe<string>;
|
|
usesEquivalenceSurcharge: false;
|
|
defaultRecCode: Maybe<string>;
|
|
usesRetention: false;
|
|
defaultRetentionCode: Maybe<string>;
|
|
};
|
|
|
|
const FACTUGES_DEFAULT_PROFORMA_TAX_CONFIG: FactugesDefaultProformaTaxConfig = {
|
|
taxMode: "single",
|
|
defaultIvaCode: Maybe.some("iva_21"),
|
|
usesEquivalenceSurcharge: false,
|
|
defaultRecCode: Maybe.none(),
|
|
usesRetention: false,
|
|
defaultRetentionCode: Maybe.none(),
|
|
};
|
|
|
|
export interface ICreateProformaFromFactugesInputMapper {
|
|
map(
|
|
dto: CreateProformaFromFactugesRequestDTO,
|
|
params: { companyId: UniqueID }
|
|
): Result<FactugesProformaPayload>;
|
|
}
|
|
|
|
export class CreateProformaFromFactugesInputMapper
|
|
implements ICreateProformaFromFactugesInputMapper
|
|
{
|
|
public map(
|
|
dto: CreateProformaFromFactugesRequestDTO,
|
|
params: { companyId: UniqueID }
|
|
): Result<FactugesProformaPayload> {
|
|
try {
|
|
const errors: ValidationErrorDetail[] = [];
|
|
const { companyId } = params;
|
|
const currencyCode = CurrencyCode.fromEUR();
|
|
|
|
const proformaProps = this.mapProformaProps(dto, {
|
|
companyId,
|
|
currencyCode,
|
|
errors,
|
|
});
|
|
|
|
const customerProps = this.mapCustomerProps(dto, {
|
|
companyId,
|
|
currencyCode,
|
|
errors,
|
|
});
|
|
|
|
this.throwIfValidationErrors(errors);
|
|
|
|
return Result.ok({
|
|
customerLookup: {
|
|
tin: customerProps.tin,
|
|
},
|
|
paymentLookup: {
|
|
factuges_id: dto.payment_method_id,
|
|
},
|
|
customerDraft: customerProps,
|
|
proformaDraft: proformaProps,
|
|
});
|
|
} catch (err: unknown) {
|
|
const error = isValidationErrorCollection(err)
|
|
? (err as ValidationErrorCollection)
|
|
: new DomainError("Customer props mapping failed", { cause: (err as Error).message });
|
|
return Result.fail(error);
|
|
}
|
|
}
|
|
|
|
private mapProformaProps(
|
|
dto: CreateProformaFromFactugesRequestDTO,
|
|
params: {
|
|
companyId: UniqueID;
|
|
currencyCode: CurrencyCode;
|
|
errors: ValidationErrorDetail[];
|
|
}
|
|
): ProformaDraft {
|
|
const errors: ValidationErrorDetail[] = [];
|
|
|
|
//const defaultStatus = InvoiceStatus.fromApproved();
|
|
|
|
//const proformaId = extractOrPushError(UniqueID.create(dto.id), "id", errors);
|
|
|
|
/**
|
|
* Complementa los datos legacy con los defaults actuales de proformas.
|
|
*
|
|
* La serie legacy `series` no se usa porque la numeracion documental
|
|
* se resuelve mediante `document-series`.
|
|
*/
|
|
|
|
/*const proformaNumber = extractOrPushError(
|
|
InvoiceNumber.create(dto.),
|
|
"invoice_number",
|
|
errors
|
|
);*/
|
|
|
|
const factugesID = String(dto.factuges_id);
|
|
|
|
const reference = extractOrPushError(
|
|
maybeFromNullableResult(dto.reference, (value) => Result.ok(String(value))),
|
|
"reference",
|
|
errors
|
|
);
|
|
|
|
const invoiceDate = extractOrPushError(
|
|
UtcDate.createFromISO(dto.proforma_date),
|
|
"invoice_date",
|
|
errors
|
|
);
|
|
|
|
const operationDate = extractOrPushError(
|
|
maybeFromNullableResult(dto.operation_date, (value) => UtcDate.createFromISO(value)),
|
|
"operation_date",
|
|
errors
|
|
);
|
|
|
|
const description = extractOrPushError(
|
|
maybeFromNullableResult(dto.description, (value) => Result.ok(String(value))),
|
|
"description",
|
|
errors
|
|
);
|
|
|
|
const notes = extractOrPushError(
|
|
maybeFromNullableResult(dto.notes, (value) => TextValue.create(value)),
|
|
"notes",
|
|
errors
|
|
);
|
|
|
|
const languageCode = extractOrPushError(
|
|
LanguageCode.create(dto.customer.language_code),
|
|
"language_code",
|
|
errors
|
|
);
|
|
|
|
const currencyCode = CurrencyCode.fromEUR();
|
|
|
|
const subtotalAmount = extractOrPushError(
|
|
maybeFromNullableResult(dto.subtotal_amount_value, (value) =>
|
|
InvoiceAmount.create({ value: Number(value) })
|
|
),
|
|
"subtotal_amount_value",
|
|
params.errors
|
|
);
|
|
|
|
const globalDiscountPercentage = extractOrPushError(
|
|
DiscountPercentage.create({ value: Number(dto.global_discount_percentage_value) }),
|
|
"global_discount_percentage_value",
|
|
params.errors
|
|
);
|
|
|
|
const itemsDiscountAmount = extractOrPushError(
|
|
maybeFromNullableResult(dto.discount_amount_value, (value) =>
|
|
InvoiceAmount.create({ value: Number(value) })
|
|
),
|
|
"discount_amount_value",
|
|
params.errors
|
|
);
|
|
|
|
const taxableAmount = extractOrPushError(
|
|
maybeFromNullableResult(dto.taxable_amount_value, (value) =>
|
|
InvoiceAmount.create({ value: Number(value) })
|
|
),
|
|
"taxable_amount_value",
|
|
params.errors
|
|
);
|
|
|
|
// TODO: Determinar cómo calcular los impuestos de la cabecera de la proforma
|
|
const taxes: ProformaItemTaxesProps = {
|
|
iva: Maybe.none(),
|
|
retention: Maybe.none(),
|
|
rec: Maybe.none(),
|
|
};
|
|
|
|
const taxesAmount = extractOrPushError(
|
|
maybeFromNullableResult(dto.taxes_amount_value, (value) =>
|
|
InvoiceAmount.create({ value: Number(value) })
|
|
),
|
|
"taxes_amount_value",
|
|
params.errors
|
|
);
|
|
|
|
const totalAmount = extractOrPushError(
|
|
maybeFromNullableResult(dto.total_amount_value, (value) =>
|
|
InvoiceAmount.create({ value: Number(value) })
|
|
),
|
|
"total_amount_value",
|
|
params.errors
|
|
);
|
|
|
|
const itemsProps = this.mapItemsProps(dto, {
|
|
languageCode: languageCode!,
|
|
currencyCode: currencyCode,
|
|
globalDiscountPercentage: globalDiscountPercentage!,
|
|
errors,
|
|
});
|
|
|
|
const props: ProformaDraft = {
|
|
//companyId,
|
|
//status: defaultStatus,
|
|
|
|
//invoiceNumber: proformaNumber!,
|
|
factugesID: factugesID,
|
|
proformaSeriesCode: Maybe.none(),
|
|
targetInvoiceSeriesCode: Maybe.none(),
|
|
|
|
invoiceDate: invoiceDate!,
|
|
operationDate: operationDate!,
|
|
|
|
//customerId: customerId!,
|
|
//recipient,
|
|
|
|
reference: reference!,
|
|
description: description!,
|
|
notes: notes!,
|
|
|
|
languageCode: languageCode!,
|
|
currencyCode: currencyCode!,
|
|
|
|
subtotalAmount: subtotalAmount!,
|
|
globalDiscountPercentage: globalDiscountPercentage!,
|
|
itemsDiscountAmount: itemsDiscountAmount!,
|
|
|
|
taxableAmount: taxableAmount!,
|
|
taxConfig: FACTUGES_DEFAULT_PROFORMA_TAX_CONFIG,
|
|
taxes: taxes,
|
|
taxesAmount: taxesAmount!,
|
|
totalAmount: totalAmount!,
|
|
|
|
items: itemsProps,
|
|
};
|
|
|
|
return props;
|
|
}
|
|
|
|
private mapCustomerProps(
|
|
dto: CreateProformaFromFactugesRequestDTO,
|
|
params: {
|
|
companyId: UniqueID;
|
|
currencyCode: CurrencyCode;
|
|
errors: ValidationErrorDetail[];
|
|
}
|
|
): ProformaCustomerDraft {
|
|
const { customer } = dto;
|
|
const { errors, currencyCode } = params;
|
|
|
|
const isCompany = customer.is_company === "1";
|
|
const name = extractOrPushError(Name.create(customer.name), "name", errors);
|
|
const tinNumber = extractOrPushError(TINNumber.create(customer.tin), "tin", errors);
|
|
|
|
const street = extractOrPushError(
|
|
maybeFromNullableResult(customer.street, (value) => Street.create(value)),
|
|
"street",
|
|
errors
|
|
);
|
|
|
|
const city = extractOrPushError(
|
|
maybeFromNullableResult(customer.city, (value) => City.create(value)),
|
|
"city",
|
|
errors
|
|
);
|
|
|
|
const province = extractOrPushError(
|
|
maybeFromNullableResult(customer.province, (value) => Province.create(value)),
|
|
"province",
|
|
errors
|
|
);
|
|
|
|
const postalCode = extractOrPushError(
|
|
maybeFromNullableResult(customer.postal_code, (value) => PostalCode.create(value)),
|
|
"postal_code",
|
|
errors
|
|
);
|
|
|
|
const country = extractOrPushError(
|
|
maybeFromNullableResult(customer.country, (value) => Country.create(value)),
|
|
"country",
|
|
errors
|
|
);
|
|
|
|
const primaryEmailAddress = extractOrPushError(
|
|
maybeFromNullableResult(customer.email_primary, (value) => EmailAddress.create(value)),
|
|
"email_primary",
|
|
errors
|
|
);
|
|
|
|
const secondaryEmailAddress = extractOrPushError(
|
|
maybeFromNullableResult(customer.email_secondary, (value) => EmailAddress.create(value)),
|
|
"email_secondary",
|
|
errors
|
|
);
|
|
|
|
const primaryPhoneNumber = extractOrPushError(
|
|
maybeFromNullableResult(customer.phone_primary, (value) => PhoneNumber.create(value)),
|
|
"phone_primary",
|
|
errors
|
|
);
|
|
|
|
const secondaryPhoneNumber = extractOrPushError(
|
|
maybeFromNullableResult(customer.phone_secondary, (value) => PhoneNumber.create(value)),
|
|
"phone_secondary",
|
|
errors
|
|
);
|
|
|
|
const primaryMobileNumber = extractOrPushError(
|
|
maybeFromNullableResult(customer.mobile_primary, (value) => PhoneNumber.create(value)),
|
|
"mobile_primary",
|
|
errors
|
|
);
|
|
|
|
const secondaryMobileNumber = extractOrPushError(
|
|
maybeFromNullableResult(customer.mobile_secondary, (value) => PhoneNumber.create(value)),
|
|
"mobile_secondary",
|
|
errors
|
|
);
|
|
|
|
const website = extractOrPushError(
|
|
maybeFromNullableResult(customer.website, (value) => URLAddress.create(value)),
|
|
"website",
|
|
errors
|
|
);
|
|
|
|
const languageCode = extractOrPushError(
|
|
LanguageCode.create(customer.language_code),
|
|
"language_code",
|
|
errors
|
|
);
|
|
|
|
this.throwIfValidationErrors(errors);
|
|
|
|
const postalAddressProps: PostalAddressProps = {
|
|
street: street!,
|
|
street2: Maybe.none(),
|
|
city: city!,
|
|
postalCode: postalCode!,
|
|
province: province!,
|
|
country: country!,
|
|
};
|
|
|
|
const customerProps: ProformaCustomerDraft = {
|
|
isCompany: isCompany,
|
|
name: name!,
|
|
tin: tinNumber!,
|
|
|
|
address: postalAddressProps!,
|
|
|
|
emailPrimary: primaryEmailAddress!,
|
|
emailSecondary: secondaryEmailAddress!,
|
|
|
|
phonePrimary: primaryPhoneNumber!,
|
|
phoneSecondary: secondaryPhoneNumber!,
|
|
|
|
mobilePrimary: primaryMobileNumber!,
|
|
mobileSecondary: secondaryMobileNumber!,
|
|
|
|
//fax: Maybe.none(),
|
|
website: website!,
|
|
|
|
//legalRecord: Maybe.none(),
|
|
|
|
//defaultTaxes: customerTaxes!,
|
|
|
|
languageCode: languageCode!,
|
|
currencyCode: currencyCode!,
|
|
};
|
|
|
|
return customerProps;
|
|
}
|
|
|
|
private mapItemsProps(
|
|
dto: CreateProformaFromFactugesRequestDTO,
|
|
params: {
|
|
languageCode: LanguageCode;
|
|
currencyCode: CurrencyCode;
|
|
globalDiscountPercentage: DiscountPercentage;
|
|
errors: ValidationErrorDetail[];
|
|
}
|
|
): ProformaDraftItem[] {
|
|
const itemsProps: ProformaDraftItem[] = [];
|
|
|
|
dto.items.forEach((item, index) => {
|
|
const position = String(item.position);
|
|
|
|
const description = extractOrPushError(
|
|
maybeFromNullableResult(item.description, (value) => ItemDescription.create(value)),
|
|
`items[${index}].description`,
|
|
params.errors
|
|
);
|
|
|
|
const quantity = extractOrPushError(
|
|
maybeFromNullableResult(item.quantity_value, (value) =>
|
|
ItemQuantity.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].quantity_value`,
|
|
params.errors
|
|
);
|
|
|
|
const unitAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.unit_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].unit_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const subtotalAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.subtotal_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].subtotal_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const itemDiscountPercentage = extractOrPushError(
|
|
maybeFromNullableResult(item.item_discount_percentage_value, (value) =>
|
|
DiscountPercentage.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].item_discount_percentage_value`,
|
|
params.errors
|
|
);
|
|
|
|
const itemDiscountAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.item_discount_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].item_discount_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const globalDiscountAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.global_discount_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].global_discount_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const totalDiscountAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.total_discount_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].total_discount_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const taxableAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.taxable_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].taxable_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const taxesAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.taxes_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].taxes_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const totalAmount = extractOrPushError(
|
|
maybeFromNullableResult(item.total_amount_value, (value) =>
|
|
ItemAmount.create({ value: Number(value) })
|
|
),
|
|
`items[${index}].total_amount_value`,
|
|
params.errors
|
|
);
|
|
|
|
const taxes = this.mapItemTaxesProps(item, {
|
|
itemIndex: index,
|
|
errors: params.errors,
|
|
});
|
|
|
|
const _item: ProformaDraftItem = {
|
|
position,
|
|
description: description!,
|
|
|
|
quantity: quantity!,
|
|
unitAmount: unitAmount!,
|
|
subtotalAmount: subtotalAmount!,
|
|
|
|
itemDiscountPercentage: itemDiscountPercentage!,
|
|
itemDiscountAmount: itemDiscountAmount!,
|
|
globalDiscountPercentage: params.globalDiscountPercentage,
|
|
globalDiscountAmount: globalDiscountAmount!,
|
|
totalDiscountAmount: totalDiscountAmount!,
|
|
|
|
taxableAmount: taxableAmount!,
|
|
taxes,
|
|
taxesAmount: taxesAmount!,
|
|
totalAmount: totalAmount!,
|
|
|
|
languageCode: params.languageCode,
|
|
currencyCode: params.currencyCode,
|
|
};
|
|
|
|
itemsProps.push(_item);
|
|
});
|
|
|
|
this.throwIfValidationErrors(params.errors);
|
|
|
|
return itemsProps;
|
|
}
|
|
|
|
/* Devuelve las propiedades de los impustos de una línea de detalle */
|
|
|
|
private mapItemTaxesProps(
|
|
_itemDTO: CreateProformaItemFromFactugesRequestDTO,
|
|
params: { itemIndex: number; errors: ValidationErrorDetail[] }
|
|
): ProformaItemTaxesProps {
|
|
const iva = extractOrPushError(
|
|
this.mapTaxToDomain({
|
|
code: "iva_21",
|
|
percentageValue: 21,
|
|
group: "iva",
|
|
calculationBehavior: "additive",
|
|
fieldPath: `items[${params.itemIndex}].iva`,
|
|
}),
|
|
`items[${params.itemIndex}].iva`,
|
|
params.errors
|
|
);
|
|
|
|
this.throwIfValidationErrors(params.errors);
|
|
|
|
return {
|
|
iva: iva ?? Maybe.none(),
|
|
retention: Maybe.none(),
|
|
rec: Maybe.none(),
|
|
};
|
|
}
|
|
|
|
private mapTaxToDomain(params: {
|
|
code: string | null;
|
|
percentageValue: number | null;
|
|
percentageScale?: number;
|
|
group: TaxGroup;
|
|
calculationBehavior: TaxCalculationBehavior;
|
|
fieldPath: string;
|
|
}): Result<Maybe<Tax>, Error> {
|
|
if (params.code === null || params.code.trim() === "") {
|
|
return Result.ok(Maybe.none());
|
|
}
|
|
|
|
if (params.percentageValue === null) {
|
|
return Result.fail(
|
|
new Error(`${params.fieldPath}.percentage_value is required when tax code is present`)
|
|
);
|
|
}
|
|
|
|
const percentageResult = TaxPercentage.create({
|
|
value: params.percentageValue,
|
|
});
|
|
|
|
if (percentageResult.isFailure) {
|
|
return Result.fail(percentageResult.error);
|
|
}
|
|
|
|
const taxResult = Tax.create({
|
|
code: params.code,
|
|
name: params.code,
|
|
rate: percentageResult.data,
|
|
group: params.group,
|
|
calculationBehavior: params.calculationBehavior,
|
|
});
|
|
|
|
if (taxResult.isFailure) {
|
|
return Result.fail(taxResult.error);
|
|
}
|
|
|
|
return Result.ok(Maybe.some(taxResult.data));
|
|
}
|
|
|
|
private throwIfValidationErrors(errors: ValidationErrorDetail[]): void {
|
|
if (errors.length > 0) {
|
|
throw new ValidationErrorCollection("Customer proforma props mapping failed", errors);
|
|
}
|
|
}
|
|
}
|