Clientes y facturas de cliente
This commit is contained in:
parent
26442edd60
commit
e93d48b930
@ -26,7 +26,8 @@
|
||||
"noForEach": "off",
|
||||
"noBannedTypes": "info",
|
||||
"noUselessFragments": "off",
|
||||
"useOptionalChain": "off"
|
||||
"useOptionalChain": "off",
|
||||
"noThisInStatic": "off"
|
||||
},
|
||||
"suspicious": {
|
||||
"noImplicitAnyLet": "info",
|
||||
|
||||
@ -141,11 +141,6 @@ export class Tax extends ValueObject<TaxProps> {
|
||||
return `${this.toNumber().toFixed(this.scale)}%`;
|
||||
}
|
||||
|
||||
/** Calcula el importe del impuesto sobre una base imponible */
|
||||
calculateAmount(baseAmount: number): number {
|
||||
return (baseAmount * this.toNumber()) / 100;
|
||||
}
|
||||
|
||||
isZero(): boolean {
|
||||
return this.toNumber() === 0;
|
||||
}
|
||||
@ -159,6 +154,7 @@ export class Tax extends ValueObject<TaxProps> {
|
||||
greaterThan(other: Tax): boolean {
|
||||
return this.toNumber() > other.toNumber();
|
||||
}
|
||||
|
||||
lessThan(other: Tax): boolean {
|
||||
return this.toNumber() < other.toNumber();
|
||||
}
|
||||
|
||||
@ -1,17 +1,8 @@
|
||||
import { Collection } from "@repo/rdx-utils";
|
||||
import { Tax } from "./tax";
|
||||
|
||||
export interface TaxesProps {
|
||||
items?: Tax[];
|
||||
}
|
||||
|
||||
export class Taxes extends Collection<Tax> {
|
||||
constructor(props: TaxesProps) {
|
||||
const { items } = props;
|
||||
super(items);
|
||||
}
|
||||
|
||||
public static create(props: TaxesProps): Taxes {
|
||||
return new Taxes(props);
|
||||
public static create<T extends Taxes>(this: new (items: Tax[]) => T, items: Tax[]): T {
|
||||
return new this(items);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,45 +44,4 @@ export abstract class SequelizeDomainMapper<TModel extends Model, TModelAttribut
|
||||
|
||||
return Result.ok(results.objects);
|
||||
}
|
||||
|
||||
/*protected _safeMap<T>(operation: () => T, key: string): Result<T, Error> {
|
||||
try {
|
||||
return Result.ok(operation());
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
protected _mapsValue(
|
||||
row: TModel,
|
||||
key: string,
|
||||
customMapFn: (value: any, params: MapperParamsType) => Result<any, Error>,
|
||||
params: MapperParamsType = { defaultValue: null }
|
||||
): Result<any, Error> {
|
||||
return customMapFn(row?.dataValues[key] ?? params.defaultValue, params);
|
||||
}
|
||||
|
||||
protected _mapsAssociation(
|
||||
row: TModel,
|
||||
associationName: string,
|
||||
customMapper: DomainMapperWithBulk<any, any>,
|
||||
params: MapperParamsType = {}
|
||||
): Result<any, Error> {
|
||||
if (!customMapper) {
|
||||
Result.fail(Error(`Custom mapper undefined for ${associationName}`));
|
||||
}
|
||||
|
||||
const { filter, ...otherParams } = params;
|
||||
let associationRows = row?.dataValues[associationName] ?? [];
|
||||
|
||||
if (filter) {
|
||||
associationRows = Array.isArray(associationRows)
|
||||
? associationRows.filter(filter)
|
||||
: filter(associationRows);
|
||||
}
|
||||
|
||||
return Array.isArray(associationRows)
|
||||
? customMapper.mapToDomainCollection(associationRows, associationRows.length, otherParams)
|
||||
: customMapper.mapToDomain(associationRows, otherParams);
|
||||
}*/
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ export class CreateCustomerInvoicePropsMapper {
|
||||
|
||||
discountPercentage: discountPercentage!,
|
||||
|
||||
taxes: Taxes.create({ items: [] }),
|
||||
taxes: Taxes.create([]),
|
||||
items: items,
|
||||
};
|
||||
|
||||
@ -219,7 +219,7 @@ export class CreateCustomerInvoicePropsMapper {
|
||||
}
|
||||
|
||||
private mapTaxes(item: CreateCustomerInvoiceItemRequestDTO, itemIndex: number) {
|
||||
const taxes = Taxes.create({ items: [] });
|
||||
const taxes = Taxes.create([]);
|
||||
|
||||
item.taxes.split(",").every((tax_code, taxIndex) => {
|
||||
const taxResult = Tax.createFromCode(tax_code, this.taxCatalog);
|
||||
|
||||
@ -10,7 +10,6 @@ import {
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Maybe, Result } from "@repo/rdx-utils";
|
||||
import { CustomerInvoiceItems, InvoicePaymentMethod } from "../entities";
|
||||
import { InvoiceTaxes } from "../entities/invoice-taxes";
|
||||
import {
|
||||
CustomerInvoiceNumber,
|
||||
CustomerInvoiceSerie,
|
||||
@ -23,9 +22,10 @@ export interface CustomerInvoiceProps {
|
||||
companyId: UniqueID;
|
||||
|
||||
isProforma: boolean;
|
||||
invoiceNumber: CustomerInvoiceNumber;
|
||||
status: CustomerInvoiceStatus;
|
||||
|
||||
series: Maybe<CustomerInvoiceSerie>;
|
||||
invoiceNumber: Maybe<CustomerInvoiceNumber>;
|
||||
|
||||
invoiceDate: UtcDate;
|
||||
operationDate: Maybe<UtcDate>;
|
||||
@ -33,6 +33,7 @@ export interface CustomerInvoiceProps {
|
||||
customerId: UniqueID;
|
||||
recipient: Maybe<InvoiceRecipient>;
|
||||
|
||||
reference: Maybe<string>;
|
||||
notes: Maybe<TextValue>;
|
||||
|
||||
languageCode: LanguageCode;
|
||||
@ -44,9 +45,9 @@ export interface CustomerInvoiceProps {
|
||||
|
||||
discountPercentage: Percentage;
|
||||
|
||||
verifactu_qr: string;
|
||||
/*verifactu_qr: string;
|
||||
verifactu_url: string;
|
||||
verifactu_status: string;
|
||||
verifactu_status: string;*/
|
||||
}
|
||||
|
||||
export interface ICustomerInvoice {
|
||||
@ -139,6 +140,10 @@ export class CustomerInvoice
|
||||
return this.props.operationDate;
|
||||
}
|
||||
|
||||
public get reference(): Maybe<string> {
|
||||
return this.props.reference;
|
||||
}
|
||||
|
||||
public get notes(): Maybe<TextValue> {
|
||||
return this.props.notes;
|
||||
}
|
||||
@ -168,7 +173,7 @@ export class CustomerInvoice
|
||||
return this._items;
|
||||
}
|
||||
|
||||
public get taxes(): InvoiceTaxes {
|
||||
public get taxes() {
|
||||
return this.items.getTaxesAmountByTaxes();
|
||||
}
|
||||
|
||||
@ -192,7 +197,12 @@ export class CustomerInvoice
|
||||
}
|
||||
|
||||
private _getTaxesAmount(taxableAmount: InvoiceAmount): InvoiceAmount {
|
||||
return this._taxes.getTaxesAmount(taxableAmount);
|
||||
let amount = InvoiceAmount.zero(this.currencyCode.code);
|
||||
|
||||
for (const tax of this.taxes) {
|
||||
amount = amount.add(tax.taxesAmount);
|
||||
}
|
||||
return amount;
|
||||
}
|
||||
|
||||
private _getTotalAmount(taxableAmount: InvoiceAmount, taxesAmount: InvoiceAmount): InvoiceAmount {
|
||||
@ -249,7 +259,7 @@ export class CustomerInvoice
|
||||
...this.props,
|
||||
status: CustomerInvoiceStatus.createEmitted(),
|
||||
isProforma: false,
|
||||
invoiceNumber: newInvoiceNumber,
|
||||
invoiceNumber: Maybe.some(newInvoiceNumber),
|
||||
},
|
||||
this.id
|
||||
);
|
||||
|
||||
@ -2,7 +2,6 @@ import { Tax } from "@erp/core/api";
|
||||
import { CurrencyCode, LanguageCode } from "@repo/rdx-ddd";
|
||||
import { Collection } from "@repo/rdx-utils";
|
||||
import { ItemAmount } from "../../value-objects";
|
||||
import { InvoiceTax, InvoiceTaxes } from "../invoice-taxes";
|
||||
import { CustomerInvoiceItem } from "./customer-invoice-item";
|
||||
|
||||
export interface CustomerInvoiceItemsProps {
|
||||
@ -73,31 +72,33 @@ export class CustomerInvoiceItems extends Collection<CustomerInvoiceItem> {
|
||||
);
|
||||
}
|
||||
|
||||
public getTaxesAmountByTaxes(): InvoiceTaxes {
|
||||
InvoiceTaxes.create({});
|
||||
public getTaxesAmountByTaxes() {
|
||||
const resultMap = new Map<Tax, { taxableAmount: ItemAmount; taxesAmount: ItemAmount }>();
|
||||
|
||||
const taxesMap = new Map<Tax, ItemAmount>();
|
||||
const currencyCode = this._currencyCode.code;
|
||||
|
||||
for (const item of this.getAll()) {
|
||||
for (const { tax, taxesAmount } of item.getTaxesAmountByTaxes()) {
|
||||
const current = taxesMap.get(tax) ?? ItemAmount.zero(currencyCode);
|
||||
taxesMap.set(tax, current.add(taxesAmount));
|
||||
for (const { taxableAmount, tax, taxesAmount } of item.getTaxesAmountByTaxes()) {
|
||||
const { taxableAmount: taxableCurrent, taxesAmount: taxesCurrent } = resultMap.get(tax) ?? {
|
||||
taxableAmount: ItemAmount.zero(currencyCode),
|
||||
taxesAmount: ItemAmount.zero(currencyCode),
|
||||
};
|
||||
resultMap.set(tax, {
|
||||
taxableAmount: taxableCurrent.add(taxableAmount),
|
||||
taxesAmount: taxesCurrent.add(taxesAmount),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const items: InvoiceTax[] = [];
|
||||
for (const [tax, taxesAmount] of taxesMap) {
|
||||
items.push(
|
||||
InvoiceTax.create({
|
||||
tax,
|
||||
taxesAmount,
|
||||
}).data
|
||||
);
|
||||
const items = [];
|
||||
for (const [tax, { taxableAmount, taxesAmount }] of resultMap) {
|
||||
items.push({
|
||||
taxableAmount,
|
||||
tax,
|
||||
taxesAmount,
|
||||
});
|
||||
}
|
||||
|
||||
return InvoiceTaxes.create({
|
||||
items: items,
|
||||
});
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
import { Tax } from "@erp/core/api";
|
||||
import { DomainEntity, UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { ItemAmount } from "../../value-objects";
|
||||
|
||||
export interface ItemTaxProps {
|
||||
tax: Tax;
|
||||
}
|
||||
|
||||
export class ItemTax extends DomainEntity<ItemTaxProps> {
|
||||
static create(props: ItemTaxProps, id?: UniqueID): Result<ItemTax, Error> {
|
||||
const itemTax = new ItemTax(props, id);
|
||||
|
||||
// Reglas de negocio / validaciones
|
||||
// ...
|
||||
// ...
|
||||
|
||||
return Result.ok(itemTax);
|
||||
}
|
||||
|
||||
public get tax(): Tax {
|
||||
return this.props.tax;
|
||||
}
|
||||
|
||||
getProps(): ItemTaxProps {
|
||||
return this.props;
|
||||
}
|
||||
|
||||
toPrimitive() {
|
||||
return this.getProps();
|
||||
}
|
||||
|
||||
public getTaxAmount(taxableAmount: ItemAmount): ItemAmount {
|
||||
return taxableAmount.percentage(this.tax.percentage);
|
||||
}
|
||||
}
|
||||
@ -1,24 +1,14 @@
|
||||
import { Collection } from "@repo/rdx-utils";
|
||||
import { Tax, Taxes } from "@erp/core/api";
|
||||
import { ItemAmount } from "../../value-objects";
|
||||
import { ItemTax } from "./item-tax";
|
||||
|
||||
export interface ItemTaxesProps {
|
||||
items?: ItemTax[];
|
||||
}
|
||||
|
||||
export class ItemTaxes extends Collection<ItemTax> {
|
||||
constructor(props: ItemTaxesProps) {
|
||||
const { items = [] } = props;
|
||||
super(items);
|
||||
}
|
||||
|
||||
public static create(props: ItemTaxesProps): ItemTaxes {
|
||||
return new ItemTaxes(props);
|
||||
export class ItemTaxes extends Taxes {
|
||||
constructor(items: Tax[] = [], totalItems: number | null = null) {
|
||||
super(items, totalItems);
|
||||
}
|
||||
|
||||
public getTaxesAmount(taxableAmount: ItemAmount): ItemAmount {
|
||||
return this.getAll().reduce(
|
||||
(total, tax) => total.add(tax.getTaxAmount(taxableAmount)),
|
||||
(total, tax) => total.add(taxableAmount.percentage(tax.percentage)),
|
||||
ItemAmount.zero(taxableAmount.currencyCode)
|
||||
);
|
||||
}
|
||||
@ -26,21 +16,22 @@ export class ItemTaxes extends Collection<ItemTax> {
|
||||
public getTaxesAmountByTaxCode(taxCode: string, taxableAmount: ItemAmount): ItemAmount {
|
||||
const currencyCode = taxableAmount.currencyCode;
|
||||
|
||||
return this.filter((itemTax) => itemTax.tax.code === taxCode).reduce((totalAmount, itemTax) => {
|
||||
return itemTax.getTaxAmount(taxableAmount).add(totalAmount);
|
||||
return this.filter((itemTax) => itemTax.code === taxCode).reduce((totalAmount, itemTax) => {
|
||||
return taxableAmount.percentage(itemTax.percentage).add(totalAmount);
|
||||
}, ItemAmount.zero(currencyCode));
|
||||
}
|
||||
|
||||
public getTaxesAmountByTaxes(taxableAmount: ItemAmount): {
|
||||
public getTaxesAmountByTaxes(taxableAmount: ItemAmount) {
|
||||
return this.getAll().map((taxItem) => ({
|
||||
tax: taxItem.tax,
|
||||
taxesAmount: this.getTaxesAmountByTaxCode(taxItem.tax.code, taxableAmount),
|
||||
taxableAmount,
|
||||
tax: taxItem,
|
||||
taxesAmount: this.getTaxesAmountByTaxCode(taxItem.code, taxableAmount),
|
||||
}));
|
||||
}
|
||||
|
||||
public getCodesToString(): string {
|
||||
return this.getAll()
|
||||
.map((taxItem) => taxItem.tax.code)
|
||||
.map((taxItem) => taxItem.code)
|
||||
.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,9 +146,7 @@ export class CustomerInvoiceItemDomainMapper
|
||||
|
||||
// 5) Construcción del elemento de dominio
|
||||
|
||||
const taxes = ItemTaxes.create({
|
||||
items: taxesResults.data.getAll(),
|
||||
});
|
||||
const taxes = ItemTaxes.create(taxesResults.data.getAll());
|
||||
|
||||
const createResult = CustomerInvoiceItem.create(
|
||||
{
|
||||
@ -231,6 +229,8 @@ export class CustomerInvoiceItemDomainMapper
|
||||
|
||||
total_amount_value: allAmounts.totalAmount.value,
|
||||
total_amount_scale: allAmounts.totalAmount.scale,
|
||||
|
||||
taxes: taxesResults.data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,4 @@
|
||||
import {
|
||||
ISequelizeDomainMapper,
|
||||
InfrastructureError,
|
||||
MapperParamsType,
|
||||
SequelizeDomainMapper,
|
||||
} from "@erp/core/api";
|
||||
import { ISequelizeDomainMapper, MapperParamsType, SequelizeDomainMapper } from "@erp/core/api";
|
||||
import {
|
||||
CurrencyCode,
|
||||
LanguageCode,
|
||||
@ -17,7 +12,7 @@ import {
|
||||
maybeFromNullableVO,
|
||||
toNullable,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Maybe, Result } from "@repo/rdx-utils";
|
||||
import { Collection, Maybe, Result } from "@repo/rdx-utils";
|
||||
import {
|
||||
CustomerInvoice,
|
||||
CustomerInvoiceItems,
|
||||
@ -27,7 +22,6 @@ import {
|
||||
CustomerInvoiceStatus,
|
||||
InvoicePaymentMethod,
|
||||
} from "../../../domain";
|
||||
import { InvoiceTaxes } from "../../../domain/entities/invoice-taxes";
|
||||
import { CustomerInvoiceCreationAttributes, CustomerInvoiceModel } from "../../sequelize";
|
||||
import { CustomerInvoiceItemDomainMapper as CustomerInvoiceItemFullMapper } from "./customer-invoice-item.mapper";
|
||||
import { InvoiceRecipientDomainMapper as InvoiceRecipientFullMapper } from "./invoice-recipient.mapper";
|
||||
@ -132,7 +126,7 @@ export class CustomerInvoiceDomainMapper
|
||||
);
|
||||
|
||||
const invoiceNumber = extractOrPushError(
|
||||
CustomerInvoiceNumber.create(source.invoice_number),
|
||||
maybeFromNullableVO(source.invoice_number, (value) => CustomerInvoiceNumber.create(value)),
|
||||
"invoice_number",
|
||||
errors
|
||||
);
|
||||
@ -149,6 +143,12 @@ export class CustomerInvoiceDomainMapper
|
||||
errors
|
||||
);
|
||||
|
||||
const reference = extractOrPushError(
|
||||
maybeFromNullableVO(source.reference, (value) => Result.ok(String(value))),
|
||||
"reference",
|
||||
errors
|
||||
);
|
||||
|
||||
const notes = extractOrPushError(
|
||||
maybeFromNullableVO(source.notes, (value) => TextValue.create(value)),
|
||||
"notes",
|
||||
@ -186,6 +186,7 @@ export class CustomerInvoiceDomainMapper
|
||||
invoiceNumber,
|
||||
invoiceDate,
|
||||
operationDate,
|
||||
reference,
|
||||
notes,
|
||||
languageCode,
|
||||
currencyCode,
|
||||
@ -274,10 +275,6 @@ export class CustomerInvoiceDomainMapper
|
||||
const recipient = recipientResult.data;
|
||||
const paymentMethod = paymentMethodResult.data;
|
||||
|
||||
const taxes = InvoiceTaxes.create({
|
||||
items: taxesResults.data.getAll(),
|
||||
});
|
||||
|
||||
const items = CustomerInvoiceItems.create({
|
||||
languageCode: attributes.languageCode!,
|
||||
currencyCode: attributes.currencyCode!,
|
||||
@ -297,6 +294,7 @@ export class CustomerInvoiceDomainMapper
|
||||
customerId: attributes.customerId!,
|
||||
recipient: recipient,
|
||||
|
||||
reference: attributes.reference!,
|
||||
notes: attributes.notes!,
|
||||
|
||||
languageCode: attributes.languageCode!,
|
||||
@ -306,7 +304,6 @@ export class CustomerInvoiceDomainMapper
|
||||
|
||||
paymentMethod: paymentMethod!,
|
||||
|
||||
taxes: taxes,
|
||||
items,
|
||||
};
|
||||
|
||||
@ -345,8 +342,11 @@ export class CustomerInvoiceDomainMapper
|
||||
});
|
||||
}
|
||||
|
||||
const items = itemsResult.data;
|
||||
|
||||
// 1) Taxes
|
||||
const taxesResult = this._taxesMapper.mapToPersistenceArray(source.taxes, {
|
||||
|
||||
const taxesResult = this._taxesMapper.mapToPersistenceArray(new Collection(source.taxes), {
|
||||
errors,
|
||||
parent: source,
|
||||
...params,
|
||||
@ -358,18 +358,31 @@ export class CustomerInvoiceDomainMapper
|
||||
});
|
||||
}
|
||||
|
||||
const taxes = taxesResult.data;
|
||||
|
||||
// 3) Calcular totales
|
||||
const allAmounts = source.getAllAmounts();
|
||||
|
||||
// 4) Construir parte
|
||||
const invoiceValues: Partial<CustomerInvoiceCreationAttributes> = {
|
||||
// 4) Cliente
|
||||
const recipient = this._mapRecipientToPersistence(source);
|
||||
|
||||
// 7) Si hubo errores de mapeo, devolvemos colección de validación
|
||||
if (errors.length > 0) {
|
||||
return Result.fail(
|
||||
new ValidationErrorCollection("Customer invoice mapping to persistence failed", errors)
|
||||
);
|
||||
}
|
||||
|
||||
const invoiceValues: CustomerInvoiceCreationAttributes = {
|
||||
id: source.id.toPrimitive(),
|
||||
company_id: source.companyId.toPrimitive(),
|
||||
|
||||
is_proforma: source.isProforma,
|
||||
status: source.status.toPrimitive(),
|
||||
series: toNullable(source.series, (series) => series.toPrimitive()),
|
||||
invoice_number: source.invoiceNumber.toPrimitive(),
|
||||
invoice_number: toNullable(source.invoiceNumber, (invoiceNumber) =>
|
||||
invoiceNumber.toPrimitive()
|
||||
),
|
||||
invoice_date: source.invoiceDate.toPrimitive(),
|
||||
operation_date: toNullable(source.operationDate, (operationDate) =>
|
||||
operationDate.toPrimitive()
|
||||
@ -377,6 +390,7 @@ export class CustomerInvoiceDomainMapper
|
||||
language_code: source.languageCode.toPrimitive(),
|
||||
currency_code: source.currencyCode.toPrimitive(),
|
||||
|
||||
reference: toNullable(source.reference, (reference) => reference),
|
||||
notes: toNullable(source.notes, (notes) => notes.toPrimitive()),
|
||||
|
||||
subtotal_amount_value: allAmounts.subtotalAmount.value,
|
||||
@ -397,61 +411,58 @@ export class CustomerInvoiceDomainMapper
|
||||
total_amount_value: allAmounts.totalAmount.value,
|
||||
total_amount_scale: allAmounts.totalAmount.scale,
|
||||
|
||||
customer_id: source.customerId.toPrimitive(),
|
||||
|
||||
payment_method_id: toNullable(source.paymentMethod, (payment) => payment.toObjectString().id),
|
||||
payment_method_description: toNullable(
|
||||
source.paymentMethod,
|
||||
(payment) => payment.toObjectString().payment_description
|
||||
),
|
||||
|
||||
customer_id: source.customerId.toPrimitive(),
|
||||
...recipient,
|
||||
taxes,
|
||||
items,
|
||||
};
|
||||
|
||||
// 5) Cliente / Recipient ??
|
||||
// Si es proforma no guardamos los campos como históricos (snapshots)
|
||||
if (source.isProforma) {
|
||||
Object.assign(invoiceValues, {
|
||||
customer_tin: null,
|
||||
customer_name: null,
|
||||
customer_street: null,
|
||||
customer_street2: null,
|
||||
customer_city: null,
|
||||
customer_province: null,
|
||||
customer_postal_code: null,
|
||||
customer_country: null,
|
||||
return Result.ok<CustomerInvoiceCreationAttributes>(invoiceValues);
|
||||
}
|
||||
|
||||
protected _mapRecipientToPersistence(source: CustomerInvoice, params?: MapperParamsType) {
|
||||
const { errors } = params as {
|
||||
errors: ValidationErrorDetail[];
|
||||
};
|
||||
|
||||
const recipient = source.recipient.getOrUndefined();
|
||||
|
||||
if (!source.isProforma && !recipient) {
|
||||
errors.push({
|
||||
path: "recipient",
|
||||
message: "[CustomerInvoiceDomainMapper] Issued customer invoice w/o recipient data",
|
||||
});
|
||||
} else {
|
||||
const recipient = source.recipient.getOrUndefined();
|
||||
if (!recipient) {
|
||||
return Result.fail(
|
||||
new InfrastructureError(
|
||||
"[CustomerInvoiceDomainMapper] Issued customer invoice w/o recipient data"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Object.assign(invoiceValues, {
|
||||
customer_tin: recipient.tin.toPrimitive(),
|
||||
customer_name: recipient.name.toPrimitive(),
|
||||
customer_street: toNullable(recipient.street, (v) => v.toPrimitive()),
|
||||
customer_street2: toNullable(recipient.street2, (v) => v.toPrimitive()),
|
||||
customer_city: toNullable(recipient.city, (v) => v.toPrimitive()),
|
||||
customer_province: toNullable(recipient.province, (v) => v.toPrimitive()),
|
||||
customer_postal_code: toNullable(recipient.postalCode, (v) => v.toPrimitive()),
|
||||
customer_country: toNullable(recipient.country, (v) => v.toPrimitive()),
|
||||
} as Partial<CustomerInvoiceCreationAttributes>);
|
||||
}
|
||||
|
||||
// 7) Si hubo errores de mapeo, devolvemos colección de validación
|
||||
if (errors.length > 0) {
|
||||
return Result.fail(
|
||||
new ValidationErrorCollection("Customer invoice mapping to persistence failed", errors)
|
||||
);
|
||||
}
|
||||
const recipientValues = {
|
||||
customer_tin: !source.isProforma ? recipient!.tin.toPrimitive() : null,
|
||||
customer_name: !source.isProforma ? recipient!.name.toPrimitive() : null,
|
||||
customer_street: !source.isProforma
|
||||
? toNullable(recipient!.street, (v) => v.toPrimitive())
|
||||
: null,
|
||||
customer_street2: !source.isProforma
|
||||
? toNullable(recipient!.street2, (v) => v.toPrimitive())
|
||||
: null,
|
||||
customer_city: !source.isProforma
|
||||
? toNullable(recipient!.city, (v) => v.toPrimitive())
|
||||
: null,
|
||||
customer_province: !source.isProforma
|
||||
? toNullable(recipient!.province, (v) => v.toPrimitive())
|
||||
: null,
|
||||
customer_postal_code: !source.isProforma
|
||||
? toNullable(recipient!.postalCode, (v) => v.toPrimitive())
|
||||
: null,
|
||||
customer_country: !source.isProforma
|
||||
? toNullable(recipient!.country, (v) => v.toPrimitive())
|
||||
: null,
|
||||
};
|
||||
|
||||
return Result.ok<CustomerInvoiceCreationAttributes>({
|
||||
...invoiceValues,
|
||||
items: itemsResult.data,
|
||||
taxes: taxesResult.data,
|
||||
});
|
||||
return recipientValues;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,21 +1,15 @@
|
||||
import { JsonTaxCatalogProvider } from "@erp/core";
|
||||
import { MapperParamsType, SequelizeDomainMapper, Tax } from "@erp/core/api";
|
||||
import {
|
||||
ValidationErrorCollection,
|
||||
ValidationErrorDetail,
|
||||
extractOrPushError,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { UniqueID, ValidationErrorDetail } from "@repo/rdx-ddd";
|
||||
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { InferCreationAttributes } from "sequelize";
|
||||
import { CustomerInvoice, CustomerInvoiceProps } from "../../../domain";
|
||||
import { InvoiceTax } from "../../../domain/entities/invoice-taxes";
|
||||
import { CustomerInvoice, CustomerInvoiceItemProps, ItemAmount } from "../../../domain";
|
||||
import { CustomerInvoiceTaxCreationAttributes, CustomerInvoiceTaxModel } from "../../sequelize";
|
||||
|
||||
export class TaxesDomainMapper extends SequelizeDomainMapper<
|
||||
CustomerInvoiceTaxModel,
|
||||
CustomerInvoiceTaxCreationAttributes,
|
||||
InvoiceTax
|
||||
{ taxableAmount: ItemAmount; tax: Tax; taxesAmount: ItemAmount }
|
||||
> {
|
||||
private _taxCatalog: JsonTaxCatalogProvider;
|
||||
|
||||
@ -35,60 +29,57 @@ export class TaxesDomainMapper extends SequelizeDomainMapper<
|
||||
public mapToDomain(
|
||||
source: CustomerInvoiceTaxModel,
|
||||
params?: MapperParamsType
|
||||
): Result<InvoiceTax, Error> {
|
||||
const { errors, index, attributes } = params as {
|
||||
index: number;
|
||||
errors: ValidationErrorDetail[];
|
||||
attributes: Partial<CustomerInvoiceProps>;
|
||||
): Result<
|
||||
{
|
||||
taxableAmount: ItemAmount;
|
||||
tax: Tax;
|
||||
taxesAmount: ItemAmount;
|
||||
},
|
||||
Error
|
||||
> {
|
||||
const { attributes } = params as {
|
||||
attributes: Partial<CustomerInvoiceItemProps>;
|
||||
};
|
||||
|
||||
const tax = extractOrPushError(
|
||||
Tax.createFromCode(source.tax_code, this._taxCatalog),
|
||||
`taxes[${index}].tax_code`,
|
||||
errors
|
||||
);
|
||||
|
||||
// Creación del objeto de dominio
|
||||
const createResult = InvoiceTax.create({
|
||||
tax: tax!,
|
||||
return Result.ok({
|
||||
taxableAmount: ItemAmount.create({
|
||||
value: source.taxable_amount_value,
|
||||
currency_code: attributes.currencyCode!.code,
|
||||
}).data,
|
||||
tax: Tax.createFromCode(source.tax_code, this._taxCatalog).data,
|
||||
taxesAmount: ItemAmount.create({
|
||||
value: source.taxes_amount_value,
|
||||
currency_code: attributes.currencyCode!.code,
|
||||
}).data,
|
||||
});
|
||||
|
||||
if (createResult.isFailure) {
|
||||
return Result.fail(
|
||||
new ValidationErrorCollection("Invoice tax creation failed", [
|
||||
{ path: `taxes[${index}]`, message: createResult.error.message },
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return createResult;
|
||||
}
|
||||
|
||||
public mapToPersistence(
|
||||
source: InvoiceTax,
|
||||
source: {
|
||||
taxableAmount: ItemAmount;
|
||||
tax: Tax;
|
||||
taxesAmount: ItemAmount;
|
||||
},
|
||||
params?: MapperParamsType
|
||||
): Result<InferCreationAttributes<CustomerInvoiceTaxModel, {}>, Error> {
|
||||
): Result<CustomerInvoiceTaxCreationAttributes, Error> {
|
||||
const { errors, parent } = params as {
|
||||
index: number;
|
||||
parent: CustomerInvoice;
|
||||
errors: ValidationErrorDetail[];
|
||||
};
|
||||
|
||||
|
||||
const taxableAmount = parent.getTaxableAmount()
|
||||
const taxesAmount =
|
||||
source;
|
||||
|
||||
return Result.ok({
|
||||
tax_id: source.id.toPrimitive(),
|
||||
tax_id: UniqueID.generateNewID().toPrimitive(),
|
||||
invoice_id: parent.id.toPrimitive(),
|
||||
|
||||
tax_code: source.tax.code,
|
||||
|
||||
taxable_amount_value: taxableAmount.value,
|
||||
taxable_amount_scale: taxableAmount.scale,
|
||||
taxable_amount_value: source.taxableAmount.value,
|
||||
taxable_amount_scale: source.taxableAmount.scale,
|
||||
|
||||
taxes_amount_value: taxesAmount.value,
|
||||
taxes_amount_scale: taxesAmount.scale,
|
||||
taxes_amount_value: source.taxesAmount.value,
|
||||
taxes_amount_scale: source.taxesAmount.scale,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,13 +5,15 @@ import {
|
||||
SequelizeDomainMapper,
|
||||
Tax,
|
||||
} from "@erp/core/api";
|
||||
import { CustomerInvoiceItem, ItemTax } from "@erp/customer-invoices/api/domain";
|
||||
|
||||
import {
|
||||
UniqueID,
|
||||
ValidationErrorCollection,
|
||||
ValidationErrorDetail,
|
||||
extractOrPushError,
|
||||
} from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { CustomerInvoiceItem } from "../../../domain";
|
||||
import {
|
||||
CustomerInvoiceItemTaxCreationAttributes,
|
||||
CustomerInvoiceItemTaxModel,
|
||||
@ -21,14 +23,14 @@ export interface IItemTaxesDomainMapper
|
||||
extends ISequelizeDomainMapper<
|
||||
CustomerInvoiceItemTaxModel,
|
||||
CustomerInvoiceItemTaxCreationAttributes,
|
||||
ItemTax
|
||||
Tax
|
||||
> {}
|
||||
|
||||
export class ItemTaxesDomainMapper
|
||||
extends SequelizeDomainMapper<
|
||||
CustomerInvoiceItemTaxModel,
|
||||
CustomerInvoiceItemTaxCreationAttributes,
|
||||
ItemTax
|
||||
Tax
|
||||
>
|
||||
implements IItemTaxesDomainMapper
|
||||
{
|
||||
@ -50,7 +52,7 @@ export class ItemTaxesDomainMapper
|
||||
public mapToDomain(
|
||||
source: CustomerInvoiceItemTaxModel,
|
||||
params?: MapperParamsType
|
||||
): Result<ItemTax, Error> {
|
||||
): Result<Tax, Error> {
|
||||
const { errors, index } = params as {
|
||||
index: number;
|
||||
errors: ValidationErrorDetail[];
|
||||
@ -63,7 +65,7 @@ export class ItemTaxesDomainMapper
|
||||
);
|
||||
|
||||
// Creación del objeto de dominio
|
||||
const createResult = ItemTax.create({ tax: tax! });
|
||||
const createResult = Tax.create(tax!);
|
||||
if (createResult.isFailure) {
|
||||
return Result.fail(
|
||||
new ValidationErrorCollection("Invoice item tax creation failed", [
|
||||
@ -76,7 +78,7 @@ export class ItemTaxesDomainMapper
|
||||
}
|
||||
|
||||
public mapToPersistence(
|
||||
source: ItemTax,
|
||||
source: Tax,
|
||||
params?: MapperParamsType
|
||||
): Result<CustomerInvoiceItemTaxCreationAttributes, Error> {
|
||||
const { errors, parent } = params as {
|
||||
@ -85,13 +87,13 @@ export class ItemTaxesDomainMapper
|
||||
};
|
||||
|
||||
const taxableAmount = parent.getTaxableAmount();
|
||||
const taxAmount = source.getTaxAmount(taxableAmount);
|
||||
const taxAmount = taxableAmount.percentage(source.percentage);
|
||||
|
||||
return Result.ok({
|
||||
tax_id: source.id.toPrimitive(),
|
||||
tax_id: UniqueID.generateNewID().toPrimitive(),
|
||||
item_id: parent.id.toPrimitive(),
|
||||
|
||||
tax_code: source.tax.code,
|
||||
tax_code: source.code,
|
||||
|
||||
taxable_amount_value: taxableAmount.value,
|
||||
taxable_amount_scale: taxableAmount.scale,
|
||||
|
||||
@ -68,26 +68,26 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxable_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxable_amount_scale: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
allowNull: false,
|
||||
defaultValue: 2,
|
||||
defaultValue: 4,
|
||||
},
|
||||
|
||||
taxes_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxes_amount_scale: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
allowNull: false,
|
||||
defaultValue: 2,
|
||||
defaultValue: 4,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {
|
||||
CreationOptional,
|
||||
DataTypes,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
@ -28,38 +29,39 @@ export class CustomerInvoiceItemModel extends Model<
|
||||
|
||||
declare position: number;
|
||||
|
||||
declare description: string;
|
||||
declare description: CreationOptional<string | null>;
|
||||
|
||||
declare quantity_value: number;
|
||||
declare quantity_value: CreationOptional<number | null>;
|
||||
declare quantity_scale: number;
|
||||
|
||||
declare unit_amount_value: number;
|
||||
declare unit_amount_value: CreationOptional<number | null>;
|
||||
declare unit_amount_scale: number;
|
||||
|
||||
// Subtotal
|
||||
declare subtotal_amount_value: number;
|
||||
declare subtotal_amount_value: CreationOptional<number | null>;
|
||||
declare subtotal_amount_scale: number;
|
||||
|
||||
// Discount percentage
|
||||
declare discount_percentage_value: number;
|
||||
declare discount_percentage_value: CreationOptional<number | null>;
|
||||
declare discount_percentage_scale: number;
|
||||
|
||||
// Discount amount
|
||||
declare discount_amount_value: number;
|
||||
declare discount_amount_value: CreationOptional<number | null>;
|
||||
declare discount_amount_scale: number;
|
||||
|
||||
// Taxable amount (base imponible)
|
||||
declare taxable_amount_value: number;
|
||||
declare taxable_amount_value: CreationOptional<number | null>;
|
||||
declare taxable_amount_scale: number;
|
||||
|
||||
// Total taxes amount / taxes total
|
||||
declare taxes_amount_value: number;
|
||||
declare taxes_amount_value: CreationOptional<number | null>;
|
||||
declare taxes_amount_scale: number;
|
||||
|
||||
// Total
|
||||
declare total_amount_value: number;
|
||||
declare total_amount_value: CreationOptional<number | null>;
|
||||
declare total_amount_scale: number;
|
||||
|
||||
// Relaciones
|
||||
declare invoice: NonAttribute<CustomerInvoiceModel>;
|
||||
declare taxes: NonAttribute<CustomerInvoiceItemTaxModel[]>;
|
||||
|
||||
|
||||
@ -67,8 +67,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxable_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxable_amount_scale: {
|
||||
@ -79,8 +79,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxes_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
taxes_amount_scale: {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {
|
||||
CreationOptional,
|
||||
DataTypes,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
@ -34,15 +35,20 @@ export class CustomerInvoiceModel extends Model<
|
||||
|
||||
declare is_proforma: boolean;
|
||||
declare status: string;
|
||||
declare series: string;
|
||||
declare invoice_number: string;
|
||||
declare invoice_date: string;
|
||||
declare operation_date: string;
|
||||
declare language_code: string;
|
||||
declare currency_code: string;
|
||||
//declare xxxxxx
|
||||
declare series: CreationOptional<string | null>;
|
||||
declare invoice_number: CreationOptional<string | null>;
|
||||
declare invoice_date: CreationOptional<string>;
|
||||
declare operation_date: CreationOptional<string | null>;
|
||||
declare language_code: CreationOptional<string>;
|
||||
declare currency_code: CreationOptional<string>;
|
||||
|
||||
declare notes: string;
|
||||
declare reference: CreationOptional<string | null>;
|
||||
|
||||
declare notes: CreationOptional<string | null>;
|
||||
|
||||
// Método de pago
|
||||
declare payment_method_id: CreationOptional<string | null>;
|
||||
declare payment_method_description: CreationOptional<string | null>;
|
||||
|
||||
// Subtotal
|
||||
declare subtotal_amount_value: number;
|
||||
@ -70,18 +76,14 @@ export class CustomerInvoiceModel extends Model<
|
||||
|
||||
// Customer
|
||||
declare customer_id: string;
|
||||
declare customer_tin: string;
|
||||
declare customer_name: string;
|
||||
declare customer_street: string;
|
||||
declare customer_street2: string;
|
||||
declare customer_city: string;
|
||||
declare customer_province: string;
|
||||
declare customer_postal_code: string;
|
||||
declare customer_country: string;
|
||||
|
||||
// Método de pago
|
||||
declare payment_method_id: string;
|
||||
declare payment_method_description: string;
|
||||
declare customer_tin: CreationOptional<string | null>;
|
||||
declare customer_name: CreationOptional<string | null>;
|
||||
declare customer_street: CreationOptional<string | null>;
|
||||
declare customer_street2: CreationOptional<string | null>;
|
||||
declare customer_city: CreationOptional<string | null>;
|
||||
declare customer_province: CreationOptional<string | null>;
|
||||
declare customer_postal_code: CreationOptional<string | null>;
|
||||
declare customer_country: CreationOptional<string | null>;
|
||||
|
||||
// Relaciones
|
||||
declare items: NonAttribute<CustomerInvoiceItemModel[]>;
|
||||
@ -163,8 +165,7 @@ export default (database: Sequelize) => {
|
||||
|
||||
invoice_date: {
|
||||
type: new DataTypes.DATEONLY(),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
},
|
||||
|
||||
operation_date: {
|
||||
@ -182,6 +183,13 @@ export default (database: Sequelize) => {
|
||||
currency_code: {
|
||||
type: new DataTypes.STRING(3),
|
||||
allowNull: false,
|
||||
defaultValue: "EUR",
|
||||
},
|
||||
|
||||
reference: {
|
||||
type: new DataTypes.STRING(),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
},
|
||||
|
||||
notes: {
|
||||
@ -207,6 +215,7 @@ export default (database: Sequelize) => {
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
subtotal_amount_scale: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
allowNull: false,
|
||||
@ -215,8 +224,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
discount_percentage_value: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
discount_percentage_scale: {
|
||||
@ -227,8 +236,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
discount_amount_value: {
|
||||
type: new DataTypes.BIGINT(),
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
discount_amount_scale: {
|
||||
@ -239,8 +248,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxable_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
taxable_amount_scale: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
@ -250,8 +259,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
taxes_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
taxes_amount_scale: {
|
||||
type: new DataTypes.SMALLINT(),
|
||||
@ -261,8 +270,8 @@ export default (database: Sequelize) => {
|
||||
|
||||
total_amount_value: {
|
||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||
allowNull: true,
|
||||
defaultValue: null,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
|
||||
total_amount_scale: {
|
||||
|
||||
@ -30,14 +30,18 @@ export interface CustomerProps {
|
||||
|
||||
emailPrimary: Maybe<EmailAddress>;
|
||||
emailSecondary: Maybe<EmailAddress>;
|
||||
|
||||
phonePrimary: Maybe<PhoneNumber>;
|
||||
phoneSecondary: Maybe<PhoneNumber>;
|
||||
|
||||
mobilePrimary: Maybe<PhoneNumber>;
|
||||
mobileSecondary: Maybe<PhoneNumber>;
|
||||
|
||||
fax: Maybe<PhoneNumber>;
|
||||
website: Maybe<URLAddress>;
|
||||
|
||||
legalRecord: Maybe<TextValue>;
|
||||
|
||||
defaultTaxes: Collection<TaxCode>;
|
||||
|
||||
languageCode: LanguageCode;
|
||||
|
||||
@ -171,7 +171,7 @@ export class CustomerDomainMapper
|
||||
// source.default_taxes is stored as a comma-separated string
|
||||
const defaultTaxes = new Collection<TaxCode>();
|
||||
if (!isNullishOrEmpty(source.default_taxes)) {
|
||||
source.default_taxes.split(",").map((taxCode, index) => {
|
||||
source.default_taxes!.split(",").map((taxCode, index) => {
|
||||
const tax = extractOrPushError(TaxCode.create(taxCode), `default_taxes.${index}`, errors);
|
||||
if (tax) {
|
||||
defaultTaxes.add(tax!);
|
||||
|
||||
@ -1,4 +1,11 @@
|
||||
import { DataTypes, InferAttributes, InferCreationAttributes, Model, Sequelize } from "sequelize";
|
||||
import {
|
||||
CreationOptional,
|
||||
DataTypes,
|
||||
InferAttributes,
|
||||
InferCreationAttributes,
|
||||
Model,
|
||||
Sequelize,
|
||||
} from "sequelize";
|
||||
|
||||
export type CustomerCreationAttributes = InferCreationAttributes<CustomerModel, {}> & {};
|
||||
|
||||
@ -13,43 +20,43 @@ export class CustomerModel extends Model<
|
||||
|
||||
declare id: string;
|
||||
declare company_id: string;
|
||||
declare reference: string;
|
||||
declare reference: CreationOptional<string | null>;
|
||||
|
||||
declare is_company: boolean;
|
||||
declare name: string;
|
||||
declare trade_name: string;
|
||||
declare tin: string;
|
||||
declare trade_name: CreationOptional<string | null>;
|
||||
declare tin: CreationOptional<string | null>;
|
||||
|
||||
declare street: string;
|
||||
declare street2: string;
|
||||
declare city: string;
|
||||
declare province: string;
|
||||
declare postal_code: string;
|
||||
declare country: string;
|
||||
declare street: CreationOptional<string | null>;
|
||||
declare street2: CreationOptional<string | null>;
|
||||
declare city: CreationOptional<string | null>;
|
||||
declare province: CreationOptional<string | null>;
|
||||
declare postal_code: CreationOptional<string | null>;
|
||||
declare country: CreationOptional<string | null>;
|
||||
|
||||
// Correos electrónicos
|
||||
declare email_primary: string;
|
||||
declare email_secondary: string;
|
||||
declare email_primary: CreationOptional<string | null>;
|
||||
declare email_secondary: CreationOptional<string | null>;
|
||||
|
||||
// Teléfonos fijos
|
||||
declare phone_primary: string;
|
||||
declare phone_secondary: string;
|
||||
declare phone_primary: CreationOptional<string | null>;
|
||||
declare phone_secondary: CreationOptional<string | null>;
|
||||
|
||||
// Móviles
|
||||
declare mobile_primary: string;
|
||||
declare mobile_secondary: string;
|
||||
declare mobile_primary: CreationOptional<string | null>;
|
||||
declare mobile_secondary: CreationOptional<string | null>;
|
||||
|
||||
declare fax: string;
|
||||
declare website: string;
|
||||
declare fax: CreationOptional<string | null>;
|
||||
declare website: CreationOptional<string | null>;
|
||||
|
||||
declare legal_record: string;
|
||||
declare legal_record: CreationOptional<string | null>;
|
||||
|
||||
declare default_taxes: string;
|
||||
declare default_taxes: CreationOptional<string | null>;
|
||||
declare status: string;
|
||||
declare language_code: string;
|
||||
declare currency_code: string;
|
||||
declare language_code: CreationOptional<string>;
|
||||
declare currency_code: CreationOptional<string>;
|
||||
|
||||
declare factuges_id: string;
|
||||
declare factuges_id: CreationOptional<string | null>;
|
||||
|
||||
static associate(database: Sequelize) {}
|
||||
|
||||
@ -187,6 +194,12 @@ export default (database: Sequelize) => {
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: "active",
|
||||
},
|
||||
|
||||
language_code: {
|
||||
type: DataTypes.STRING(2),
|
||||
allowNull: false,
|
||||
@ -199,12 +212,6 @@ export default (database: Sequelize) => {
|
||||
defaultValue: "EUR",
|
||||
},
|
||||
|
||||
status: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
defaultValue: "active",
|
||||
},
|
||||
|
||||
factuges_id: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: true,
|
||||
|
||||
@ -21,7 +21,12 @@ export function maybeFromNullableString(input?: string | null): Maybe<string> {
|
||||
}
|
||||
|
||||
/** Maybe<T> -> null para transporte */
|
||||
export function toNullable<T>(m: Maybe<T>, map?: (t: T) => any): any | null {
|
||||
export function toNullable<T, R>(m: Maybe<T>, map: (t: T) => R): R | null {
|
||||
if (!m || m.isNone()) return null;
|
||||
return map(m.unwrap() as T);
|
||||
}
|
||||
|
||||
export function toNullable2<T>(m: Maybe<T>, map?: (t: T) => unknown): unknown | null {
|
||||
if (!m || m.isNone()) return null;
|
||||
const v = m.unwrap() as T;
|
||||
return map ? String(map(v)) : String(v);
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
* Ofrece métodos básicos para manipular, consultar y recorrer los elementos.
|
||||
*/
|
||||
export class Collection<T> {
|
||||
private items: T[];
|
||||
private totalItems: number;
|
||||
protected items: T[];
|
||||
protected totalItems: number;
|
||||
|
||||
/**
|
||||
* Crea una nueva colección.
|
||||
@ -46,7 +46,7 @@ export class Collection<T> {
|
||||
return this.removeByIndex(index);
|
||||
}
|
||||
|
||||
public removeByIndex(index: number) {
|
||||
removeByIndex(index: number) {
|
||||
if (index !== -1) {
|
||||
this.items.splice(index, 1);
|
||||
if (this.totalItems !== null) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user