Facturas de cliente
This commit is contained in:
parent
2e4bb56458
commit
67c76c3185
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -60,5 +60,8 @@
|
|||||||
// other vscode settings
|
// other vscode settings
|
||||||
"[handlebars]": {
|
"[handlebars]": {
|
||||||
"editor.defaultFormatter": "vscode.html-language-features"
|
"editor.defaultFormatter": "vscode.html-language-features"
|
||||||
|
},
|
||||||
|
"[sql]": {
|
||||||
|
"editor.defaultFormatter": "cweijan.vscode-mysql-client2"
|
||||||
} // <- your root font size here
|
} // <- your root font size here
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,9 @@
|
|||||||
import { DomainEntity } from "@repo/rdx-ddd";
|
|
||||||
import { Collection, Result } from "@repo/rdx-utils";
|
import { Collection, Result } from "@repo/rdx-utils";
|
||||||
import { Model } from "sequelize";
|
import { Model } from "sequelize";
|
||||||
|
|
||||||
export type MapperParamsType = Record<string, any>;
|
export type MapperParamsType = Record<string, any>;
|
||||||
|
|
||||||
interface IDomainMapper<TModel extends Model, TEntity extends DomainEntity<any>> {
|
interface IDomainMapper<TModel extends Model, TEntity> {
|
||||||
mapToDomain(source: TModel, params?: MapperParamsType): Result<TEntity, Error>;
|
mapToDomain(source: TModel, params?: MapperParamsType): Result<TEntity, Error>;
|
||||||
mapArrayToDomain(source: TModel[], params?: MapperParamsType): Result<Collection<TEntity>, Error>;
|
mapArrayToDomain(source: TModel[], params?: MapperParamsType): Result<Collection<TEntity>, Error>;
|
||||||
mapArrayAndCountToDomain(
|
mapArrayAndCountToDomain(
|
||||||
@ -14,7 +13,7 @@ interface IDomainMapper<TModel extends Model, TEntity extends DomainEntity<any>>
|
|||||||
): Result<Collection<TEntity>, Error>;
|
): Result<Collection<TEntity>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IPersistenceMapper<TModelAttributes, TEntity extends DomainEntity<any>> {
|
interface IPersistenceMapper<TModelAttributes, TEntity> {
|
||||||
mapToPersistence(source: TEntity, params?: MapperParamsType): TModelAttributes;
|
mapToPersistence(source: TEntity, params?: MapperParamsType): TModelAttributes;
|
||||||
mapCollectionToPersistence(
|
mapCollectionToPersistence(
|
||||||
source: Collection<TEntity>,
|
source: Collection<TEntity>,
|
||||||
@ -22,18 +21,12 @@ interface IPersistenceMapper<TModelAttributes, TEntity extends DomainEntity<any>
|
|||||||
): TModelAttributes[];
|
): TModelAttributes[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISequelizeMapper<
|
export interface ISequelizeMapper<TModel extends Model, TModelAttributes, TEntity>
|
||||||
TModel extends Model,
|
extends IDomainMapper<TModel, TEntity>,
|
||||||
TModelAttributes,
|
|
||||||
TEntity extends DomainEntity<any>,
|
|
||||||
> extends IDomainMapper<TModel, TEntity>,
|
|
||||||
IPersistenceMapper<TModelAttributes, TEntity> {}
|
IPersistenceMapper<TModelAttributes, TEntity> {}
|
||||||
|
|
||||||
export abstract class SequelizeMapper<
|
export abstract class SequelizeMapper<TModel extends Model, TModelAttributes, TEntity>
|
||||||
TModel extends Model,
|
implements ISequelizeMapper<TModel, TModelAttributes, TEntity>
|
||||||
TModelAttributes,
|
|
||||||
TEntity extends DomainEntity<any>,
|
|
||||||
> implements ISequelizeMapper<TModel, TModelAttributes, TEntity>
|
|
||||||
{
|
{
|
||||||
public abstract mapToDomain(source: TModel, params?: MapperParamsType): Result<TEntity, Error>;
|
public abstract mapToDomain(source: TModel, params?: MapperParamsType): Result<TEntity, Error>;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Sequelize, Transaction } from "sequelize";
|
import { Sequelize, Transaction } from "sequelize";
|
||||||
import { TransactionManager } from "../database";
|
import { TransactionManager } from "../database";
|
||||||
|
import { InfrastructureUnavailableError } from "../errors";
|
||||||
|
|
||||||
export class SequelizeTransactionManager extends TransactionManager {
|
export class SequelizeTransactionManager extends TransactionManager {
|
||||||
protected _database: Sequelize | null = null;
|
protected _database: Sequelize | null = null;
|
||||||
@ -26,4 +27,11 @@ export class SequelizeTransactionManager extends TransactionManager {
|
|||||||
super();
|
super();
|
||||||
this._database = database;
|
this._database = database;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get database(): Sequelize {
|
||||||
|
if (!this._database) {
|
||||||
|
throw new InfrastructureUnavailableError("Database not available");
|
||||||
|
}
|
||||||
|
return this._database;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import {
|
|||||||
export interface CustomerInvoiceProps {
|
export interface CustomerInvoiceProps {
|
||||||
companyId: UniqueID;
|
companyId: UniqueID;
|
||||||
|
|
||||||
|
isProforma: boolean;
|
||||||
invoiceNumber: CustomerInvoiceNumber;
|
invoiceNumber: CustomerInvoiceNumber;
|
||||||
status: CustomerInvoiceStatus;
|
status: CustomerInvoiceStatus;
|
||||||
series: Maybe<CustomerInvoiceSerie>;
|
series: Maybe<CustomerInvoiceSerie>;
|
||||||
@ -28,7 +29,7 @@ export interface CustomerInvoiceProps {
|
|||||||
operationDate: Maybe<UtcDate>;
|
operationDate: Maybe<UtcDate>;
|
||||||
|
|
||||||
customerId: UniqueID;
|
customerId: UniqueID;
|
||||||
|
|
||||||
recipient: Maybe<InvoiceRecipient>;
|
recipient: Maybe<InvoiceRecipient>;
|
||||||
|
|
||||||
notes: Maybe<TextValue>;
|
notes: Maybe<TextValue>;
|
||||||
@ -56,7 +57,6 @@ export interface CustomerInvoiceProps {
|
|||||||
|
|
||||||
//totalAmount: MoneyValue;
|
//totalAmount: MoneyValue;
|
||||||
|
|
||||||
|
|
||||||
items: CustomerInvoiceItems;
|
items: CustomerInvoiceItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,17 +79,17 @@ export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
|||||||
const customerInvoice = new CustomerInvoice(props, id);
|
const customerInvoice = new CustomerInvoice(props, id);
|
||||||
|
|
||||||
// Reglas de negocio / validaciones
|
// Reglas de negocio / validaciones
|
||||||
|
|
||||||
|
|
||||||
if (!customerInvoice.isDraft() && !customerInvoice.hasRecipient()) {
|
if (!customerInvoice.isProforma && !customerInvoice.hasRecipient) {
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
new DomainValidationError(
|
new DomainValidationError(
|
||||||
"MISSING_CUSTOMER_DATA",
|
"MISSING_CUSTOMER_DATA",
|
||||||
"customerData",
|
"recipient",
|
||||||
"Customer data must be provided for non-draft invoices"
|
"Customer data must be provided for non-proforma invoices"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔹 Disparar evento de dominio "CustomerInvoiceAuthenticatedEvent"
|
// 🔹 Disparar evento de dominio "CustomerInvoiceAuthenticatedEvent"
|
||||||
//const { customerInvoice } = props;
|
//const { customerInvoice } = props;
|
||||||
//user.addDomainEvent(new CustomerInvoiceAuthenticatedEvent(id, customerInvoice.toString()));
|
//user.addDomainEvent(new CustomerInvoiceAuthenticatedEvent(id, customerInvoice.toString()));
|
||||||
@ -109,6 +109,10 @@ export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
|||||||
return this.props.customerId;
|
return this.props.customerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get isProforma(): boolean {
|
||||||
|
return this.props.isProforma;
|
||||||
|
}
|
||||||
|
|
||||||
public get status(): CustomerInvoiceStatus {
|
public get status(): CustomerInvoiceStatus {
|
||||||
return this.props.status;
|
return this.props.status;
|
||||||
}
|
}
|
||||||
@ -174,12 +178,8 @@ export class CustomerInvoice extends AggregateRoot<CustomerInvoiceProps> {
|
|||||||
return this._items;
|
return this._items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public isDraft() {
|
get hasRecipient() {
|
||||||
return this.status.isDraft();
|
return this.recipient.isSome();
|
||||||
}
|
|
||||||
|
|
||||||
public hasRecipient() {
|
|
||||||
return this.recipient.isSome()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*get senderId(): UniqueID {
|
/*get senderId(): UniqueID {
|
||||||
|
|||||||
@ -7,23 +7,22 @@ interface ICustomerInvoiceStatusProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum INVOICE_STATUS {
|
export enum INVOICE_STATUS {
|
||||||
DRAFT = "draft",
|
DRAFT = "draft", // <- Proforma
|
||||||
EMITTED = "emitted",
|
SENT = "sent", // <- Proforma
|
||||||
SENT = "sent",
|
APPROVED = "approved", // <- Proforma
|
||||||
RECEIVED = "received",
|
REJECTED = "rejected", // <- Proforma
|
||||||
REJECTED = "rejected",
|
EMITTED = "emitted", // <- Factura y enviada a Veri*Factu
|
||||||
}
|
}
|
||||||
export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusProps> {
|
export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusProps> {
|
||||||
private static readonly ALLOWED_STATUSES = ["draft", "emitted", "sent", "received", "rejected"];
|
private static readonly ALLOWED_STATUSES = ["draft", "sent", "approved", "rejected", "emitted"];
|
||||||
private static readonly FIELD = "invoiceStatus";
|
private static readonly FIELD = "invoiceStatus";
|
||||||
private static readonly ERROR_CODE = "INVALID_INVOICE_STATUS";
|
private static readonly ERROR_CODE = "INVALID_INVOICE_STATUS";
|
||||||
|
|
||||||
private static readonly TRANSITIONS: Record<string, string[]> = {
|
private static readonly TRANSITIONS: Record<string, string[]> = {
|
||||||
draft: [INVOICE_STATUS.EMITTED],
|
draft: [INVOICE_STATUS.SENT],
|
||||||
emitted: [INVOICE_STATUS.SENT, INVOICE_STATUS.REJECTED, INVOICE_STATUS.DRAFT],
|
sent: [INVOICE_STATUS.APPROVED, INVOICE_STATUS.REJECTED],
|
||||||
sent: [INVOICE_STATUS.RECEIVED, INVOICE_STATUS.REJECTED],
|
approved: [INVOICE_STATUS.EMITTED],
|
||||||
received: [],
|
rejected: [INVOICE_STATUS.DRAFT],
|
||||||
rejected: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static create(value: string): Result<CustomerInvoiceStatus, Error> {
|
static create(value: string): Result<CustomerInvoiceStatus, Error> {
|
||||||
@ -44,9 +43,9 @@ export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusPro
|
|||||||
: value === "sent"
|
: value === "sent"
|
||||||
? CustomerInvoiceStatus.createSent()
|
? CustomerInvoiceStatus.createSent()
|
||||||
: value === "emitted"
|
: value === "emitted"
|
||||||
? CustomerInvoiceStatus.createSent()
|
? CustomerInvoiceStatus.createEmitted()
|
||||||
: value === ""
|
: value === "approved"
|
||||||
? CustomerInvoiceStatus.createReceived()
|
? CustomerInvoiceStatus.createApproved()
|
||||||
: CustomerInvoiceStatus.createDraft()
|
: CustomerInvoiceStatus.createDraft()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -63,8 +62,8 @@ export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusPro
|
|||||||
return new CustomerInvoiceStatus({ value: INVOICE_STATUS.SENT });
|
return new CustomerInvoiceStatus({ value: INVOICE_STATUS.SENT });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createReceived(): CustomerInvoiceStatus {
|
public static createApproved(): CustomerInvoiceStatus {
|
||||||
return new CustomerInvoiceStatus({ value: INVOICE_STATUS.RECEIVED });
|
return new CustomerInvoiceStatus({ value: INVOICE_STATUS.APPROVED });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createRejected(): CustomerInvoiceStatus {
|
public static createRejected(): CustomerInvoiceStatus {
|
||||||
@ -72,7 +71,7 @@ export class CustomerInvoiceStatus extends ValueObject<ICustomerInvoiceStatusPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
isDraft(): boolean {
|
isDraft(): boolean {
|
||||||
return this.props.value === INVOICE_STATUS.DRAFT
|
return this.props.value === INVOICE_STATUS.DRAFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
getProps(): string {
|
getProps(): string {
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export function getInvoiceDependencies(params: ModuleParams): InvoiceDeps {
|
|||||||
const transactionManager = new SequelizeTransactionManager(database);
|
const transactionManager = new SequelizeTransactionManager(database);
|
||||||
|
|
||||||
if (!_mapper) _mapper = new CustomerInvoiceMapper();
|
if (!_mapper) _mapper = new CustomerInvoiceMapper();
|
||||||
if (!_repo) _repo = new CustomerInvoiceRepository(_mapper);
|
if (!_repo) _repo = new CustomerInvoiceRepository({ mapper: _mapper, database });
|
||||||
if (!_service) _service = new CustomerInvoiceService(_repo);
|
if (!_service) _service = new CustomerInvoiceService(_repo);
|
||||||
if (!_catalogs) _catalogs = { taxes: spainTaxCatalogProvider };
|
if (!_catalogs) _catalogs = { taxes: spainTaxCatalogProvider };
|
||||||
|
|
||||||
|
|||||||
@ -97,7 +97,7 @@ export class CustomerInvoiceItemMapper
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Creación del objeto de dominio
|
// Creación del objeto de dominio
|
||||||
return CustomerInvoiceItem.create(
|
const itemOrError = CustomerInvoiceItem.create(
|
||||||
{
|
{
|
||||||
languageCode: languageCode!,
|
languageCode: languageCode!,
|
||||||
currencyCode: currencyCode!,
|
currencyCode: currencyCode!,
|
||||||
@ -105,9 +105,16 @@ export class CustomerInvoiceItemMapper
|
|||||||
quantity: quantity!,
|
quantity: quantity!,
|
||||||
unitAmount: unitAmount!,
|
unitAmount: unitAmount!,
|
||||||
discountPercentage: discountPercentage!,
|
discountPercentage: discountPercentage!,
|
||||||
|
taxes: "",
|
||||||
},
|
},
|
||||||
itemId
|
itemId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (itemOrError.isFailure) {
|
||||||
|
errors.push({ path: "item", message: itemOrError.error.message });
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemOrError;
|
||||||
}
|
}
|
||||||
|
|
||||||
public mapToPersistence(
|
public mapToPersistence(
|
||||||
|
|||||||
@ -7,16 +7,9 @@ import {
|
|||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
} from "@erp/core/api";
|
} from "@erp/core/api";
|
||||||
import {
|
import {
|
||||||
City,
|
|
||||||
Country,
|
|
||||||
CurrencyCode,
|
CurrencyCode,
|
||||||
LanguageCode,
|
LanguageCode,
|
||||||
Name,
|
|
||||||
Percentage,
|
Percentage,
|
||||||
PostalCode,
|
|
||||||
Province,
|
|
||||||
Street,
|
|
||||||
TINNumber,
|
|
||||||
TextValue,
|
TextValue,
|
||||||
UniqueID,
|
UniqueID,
|
||||||
UtcDate,
|
UtcDate,
|
||||||
@ -34,6 +27,8 @@ import {
|
|||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
import { CustomerInvoiceCreationAttributes, CustomerInvoiceModel } from "../sequelize";
|
import { CustomerInvoiceCreationAttributes, CustomerInvoiceModel } from "../sequelize";
|
||||||
import { CustomerInvoiceItemMapper } from "./customer-invoice-item.mapper";
|
import { CustomerInvoiceItemMapper } from "./customer-invoice-item.mapper";
|
||||||
|
import { InvoiceRecipientMapper } from "./invoice-recipient.mapper";
|
||||||
|
import { TaxesMapper } from "./taxes.mapper";
|
||||||
|
|
||||||
export interface ICustomerInvoiceMapper
|
export interface ICustomerInvoiceMapper
|
||||||
extends ISequelizeMapper<
|
extends ISequelizeMapper<
|
||||||
@ -47,10 +42,14 @@ export class CustomerInvoiceMapper
|
|||||||
implements ICustomerInvoiceMapper
|
implements ICustomerInvoiceMapper
|
||||||
{
|
{
|
||||||
private _itemsMapper: CustomerInvoiceItemMapper;
|
private _itemsMapper: CustomerInvoiceItemMapper;
|
||||||
|
private _recipientMapper: InvoiceRecipientMapper;
|
||||||
|
private _taxesMapper: TaxesMapper;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._itemsMapper = new CustomerInvoiceItemMapper(); // Instanciar el mapper de items
|
this._itemsMapper = new CustomerInvoiceItemMapper(); // Instanciar el mapper de items
|
||||||
|
this._recipientMapper = new InvoiceRecipientMapper();
|
||||||
|
this._taxesMapper = new TaxesMapper();
|
||||||
}
|
}
|
||||||
|
|
||||||
public mapToDomain(
|
public mapToDomain(
|
||||||
@ -67,6 +66,8 @@ export class CustomerInvoiceMapper
|
|||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isProforma = Boolean(source.is_proforma);
|
||||||
|
|
||||||
const status = extractOrPushError(
|
const status = extractOrPushError(
|
||||||
CustomerInvoiceStatus.create(source.status),
|
CustomerInvoiceStatus.create(source.status),
|
||||||
"status",
|
"status",
|
||||||
@ -131,62 +132,25 @@ export class CustomerInvoiceMapper
|
|||||||
errors
|
errors
|
||||||
);
|
);
|
||||||
|
|
||||||
const customerName = extractOrPushError(
|
// Recipient (customer data) (snapshot)
|
||||||
maybeFromNullableVO(source.customer_name, (value) => Name.create(value)),
|
const recipient = this._recipientMapper.mapToDomain(source, {
|
||||||
"customer_name",
|
errors,
|
||||||
errors
|
...params,
|
||||||
);
|
});
|
||||||
|
|
||||||
const customerTin = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_tin, (value) => TINNumber.create(value)),
|
|
||||||
"customer_tin",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerStreet = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_street, (value) => Street.create(value)),
|
|
||||||
"customer_street",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerStreet2 = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_street2, (value) => Street.create(value)),
|
|
||||||
"customer_street2",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerCity = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_city, (value) => City.create(value)),
|
|
||||||
"customer_city",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerProvince = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_province, (value) => Province.create(value)),
|
|
||||||
"customer_province",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerPostalCode = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_postal_code, (value) => PostalCode.create(value)),
|
|
||||||
"customer_postal_code",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const customerCountry = extractOrPushError(
|
|
||||||
maybeFromNullableVO(source.customer_country, (value) => Country.create(value)),
|
|
||||||
"customer_country",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
// Mapear los items de la factura
|
// Mapear los items de la factura
|
||||||
const items = this._itemsMapper.mapArrayToDomain(source.items, {
|
const itemsOrResult = this._itemsMapper.mapArrayToDomain(source.items, {
|
||||||
sourceParent: source,
|
parent: source,
|
||||||
errors,
|
errors,
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mapear los impuestos
|
// Mapear los impuestos
|
||||||
|
const taxesOrResult = this._taxesMapper.mapArrayToDomain(source.taxes, {
|
||||||
|
parent: source,
|
||||||
|
errors,
|
||||||
|
...params,
|
||||||
|
});
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
return Result.fail(
|
return Result.fail(
|
||||||
@ -196,6 +160,8 @@ export class CustomerInvoiceMapper
|
|||||||
|
|
||||||
const invoiceProps: CustomerInvoiceProps = {
|
const invoiceProps: CustomerInvoiceProps = {
|
||||||
companyId: companyId!,
|
companyId: companyId!,
|
||||||
|
|
||||||
|
isProforma: isProforma,
|
||||||
status: status!,
|
status: status!,
|
||||||
series: series!,
|
series: series!,
|
||||||
invoiceNumber: invoiceNumber!,
|
invoiceNumber: invoiceNumber!,
|
||||||
@ -203,6 +169,7 @@ export class CustomerInvoiceMapper
|
|||||||
operationDate: operationDate!,
|
operationDate: operationDate!,
|
||||||
|
|
||||||
customerId: customerId!,
|
customerId: customerId!,
|
||||||
|
recipient: recipient,
|
||||||
|
|
||||||
notes: notes!,
|
notes: notes!,
|
||||||
|
|
||||||
@ -211,9 +178,12 @@ export class CustomerInvoiceMapper
|
|||||||
|
|
||||||
discountPercentage: discountPercentage!,
|
discountPercentage: discountPercentage!,
|
||||||
|
|
||||||
|
taxes: taxesOrResult,
|
||||||
|
|
||||||
items: CustomerInvoiceItems.create({
|
items: CustomerInvoiceItems.create({
|
||||||
languageCode: languageCode!,
|
languageCode: languageCode!,
|
||||||
currencyCode: currencyCode!,
|
currencyCode: currencyCode!,
|
||||||
|
items: itemsOrResult.isSuccess ? itemsOrResult.data.getAll() : [],
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -229,27 +199,39 @@ export class CustomerInvoiceMapper
|
|||||||
): CustomerInvoiceCreationAttributes {
|
): CustomerInvoiceCreationAttributes {
|
||||||
const items = this._itemsMapper.mapCollectionToPersistence(source.items, params);
|
const items = this._itemsMapper.mapCollectionToPersistence(source.items, params);
|
||||||
|
|
||||||
const customer = source.recipient.match((recipient) => ({
|
const customer = source.recipient.match(
|
||||||
customer_id: recipient.id.toPrimitive(),
|
(recipient) =>
|
||||||
customer_tin: recipient.tin.toPrimitive(),
|
({
|
||||||
customer_name: recipient.name.toPrimitive(),
|
customer_id: recipient.id.toPrimitive(),
|
||||||
customer_street: toNullable(recipient.address.street, (street) => street.toPrimitive()),
|
customer_tin: recipient.tin.toPrimitive(),
|
||||||
customer_street2: toNullable(recipient.address.street2, (street2) => street2.toPrimitive()),
|
customer_name: recipient.name.toPrimitive(),
|
||||||
customer_city: toNullable(recipient.address.city, (city) => city.toPrimitive()),
|
customer_street: toNullable(recipient.address.street, (street) => street.toPrimitive()),
|
||||||
customer_province: toNullable(recipient.address.province, (province) => province.toPrimitive()),
|
customer_street2: toNullable(recipient.address.street2, (street2) =>
|
||||||
customer_postal_code: toNullable(recipient.address.postalCode, (postalCode) => postalCode.toPrimitive()),
|
street2.toPrimitive()
|
||||||
customer_country: toNullable(recipient.address.country, (country) => country.toPrimitive()),
|
),
|
||||||
}) as any, () => ({
|
customer_city: toNullable(recipient.address.city, (city) => city.toPrimitive()),
|
||||||
customer_id: source.customerId.toPrimitive(),
|
customer_province: toNullable(recipient.address.province, (province) =>
|
||||||
customer_tin: null,
|
province.toPrimitive()
|
||||||
customer_name: null,
|
),
|
||||||
customer_street: null,
|
customer_postal_code: toNullable(recipient.address.postalCode, (postalCode) =>
|
||||||
customer_street2: null,
|
postalCode.toPrimitive()
|
||||||
customer_city: null,
|
),
|
||||||
customer_province: null,
|
customer_country: toNullable(recipient.address.country, (country) =>
|
||||||
customer_postal_code: null,
|
country.toPrimitive()
|
||||||
customer_country: null,
|
),
|
||||||
})) as any
|
}) as any,
|
||||||
|
() => ({
|
||||||
|
customer_id: source.customerId.toPrimitive(),
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
) as any;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: source.id.toPrimitive(),
|
id: source.id.toPrimitive(),
|
||||||
@ -289,7 +271,6 @@ export class CustomerInvoiceMapper
|
|||||||
|
|
||||||
items,
|
items,
|
||||||
...customer,
|
...customer,
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,119 +0,0 @@
|
|||||||
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
|
|
||||||
import { Name, TINNumber, UniqueID } from "@shared/contexts";
|
|
||||||
import {
|
|
||||||
ICustomerInvoiceCustomerProps,
|
|
||||||
CustomerInvoice,
|
|
||||||
CustomerInvoiceCustomer,
|
|
||||||
CustomerInvoiceParticipantBillingAddress,
|
|
||||||
CustomerInvoiceParticipantShippingAddress,
|
|
||||||
} from "../../domain";
|
|
||||||
import { IInvoicingContext } from "../InvoicingContext";
|
|
||||||
import { CustomerInvoiceParticipant_Model, TCreationCustomerInvoiceParticipant_Model } from "../sequelize";
|
|
||||||
import {
|
|
||||||
ICustomerInvoiceParticipantAddressMapper,
|
|
||||||
createCustomerInvoiceParticipantAddressMapper,
|
|
||||||
} from "./customer-invoiceParticipantAddress.mapper";
|
|
||||||
|
|
||||||
export interface ICustomerInvoiceParticipantMapper
|
|
||||||
extends ISequelizeMapper<
|
|
||||||
CustomerInvoiceParticipant_Model,
|
|
||||||
TCreationCustomerInvoiceParticipant_Model,
|
|
||||||
CustomerInvoiceCustomer
|
|
||||||
> {}
|
|
||||||
|
|
||||||
export const createCustomerInvoiceParticipantMapper = (
|
|
||||||
context: IInvoicingContext
|
|
||||||
): ICustomerInvoiceParticipantMapper =>
|
|
||||||
new CustomerInvoiceParticipantMapper({
|
|
||||||
context,
|
|
||||||
addressMapper: createCustomerInvoiceParticipantAddressMapper(context),
|
|
||||||
});
|
|
||||||
|
|
||||||
class CustomerInvoiceParticipantMapper
|
|
||||||
extends SequelizeMapper<
|
|
||||||
CustomerInvoiceParticipant_Model,
|
|
||||||
TCreationCustomerInvoiceParticipant_Model,
|
|
||||||
CustomerInvoiceCustomer
|
|
||||||
>
|
|
||||||
implements ICustomerInvoiceParticipantMapper
|
|
||||||
{
|
|
||||||
public constructor(props: {
|
|
||||||
addressMapper: ICustomerInvoiceParticipantAddressMapper;
|
|
||||||
context: IInvoicingContext;
|
|
||||||
}) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected toDomainMappingImpl(source: CustomerInvoiceParticipant_Model, params: any) {
|
|
||||||
/*if (!source.billingAddress) {
|
|
||||||
this.handleRequiredFieldError(
|
|
||||||
"billingAddress",
|
|
||||||
new Error("Missing participant's billing address"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!source.shippingAddress) {
|
|
||||||
this.handleRequiredFieldError(
|
|
||||||
"shippingAddress",
|
|
||||||
new Error("Missing participant's shipping address"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
const billingAddress = source.billingAddress
|
|
||||||
? ((this.props.addressMapper as ICustomerInvoiceParticipantAddressMapper).mapToDomain(
|
|
||||||
source.billingAddress,
|
|
||||||
params
|
|
||||||
) as CustomerInvoiceParticipantBillingAddress)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const shippingAddress = source.shippingAddress
|
|
||||||
? ((this.props.addressMapper as ICustomerInvoiceParticipantAddressMapper).mapToDomain(
|
|
||||||
source.shippingAddress,
|
|
||||||
params
|
|
||||||
) as CustomerInvoiceParticipantShippingAddress)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const props: ICustomerInvoiceCustomerProps = {
|
|
||||||
tin: this.mapsValue(source, "tin", TINNumber.create),
|
|
||||||
firstName: this.mapsValue(source, "first_name", Name.create),
|
|
||||||
lastName: this.mapsValue(source, "last_name", Name.create),
|
|
||||||
companyName: this.mapsValue(source, "company_name", Name.create),
|
|
||||||
billingAddress,
|
|
||||||
shippingAddress,
|
|
||||||
};
|
|
||||||
|
|
||||||
const id = this.mapsValue(source, "participant_id", UniqueID.create);
|
|
||||||
const participantOrError = CustomerInvoiceCustomer.create(props, id);
|
|
||||||
|
|
||||||
if (participantOrError.isFailure) {
|
|
||||||
throw participantOrError.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return participantOrError.object;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected toPersistenceMappingImpl(
|
|
||||||
source: CustomerInvoiceCustomer,
|
|
||||||
params: { sourceParent: CustomerInvoice }
|
|
||||||
): TCreationCustomerInvoiceParticipant_Model {
|
|
||||||
const { sourceParent } = params;
|
|
||||||
|
|
||||||
return {
|
|
||||||
customerInvoice_id: sourceParent.id.toPrimitive(),
|
|
||||||
|
|
||||||
participant_id: source.id.toPrimitive(),
|
|
||||||
tin: source.tin.toPrimitive(),
|
|
||||||
first_name: source.firstName.toPrimitive(),
|
|
||||||
last_name: source.lastName.toPrimitive(),
|
|
||||||
company_name: source.companyName.toPrimitive(),
|
|
||||||
|
|
||||||
billingAddress: (
|
|
||||||
this.props.addressMapper as ICustomerInvoiceParticipantAddressMapper
|
|
||||||
).mapToPersistence(source.billingAddress!, { sourceParent: source }),
|
|
||||||
|
|
||||||
shippingAddress: (
|
|
||||||
this.props.addressMapper as ICustomerInvoiceParticipantAddressMapper
|
|
||||||
).mapToPersistence(source.shippingAddress!, { sourceParent: source }),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
import { ISequelizeMapper, SequelizeMapper } from "@/contexts/common/infrastructure";
|
|
||||||
import {
|
|
||||||
City,
|
|
||||||
Country,
|
|
||||||
Email,
|
|
||||||
Note,
|
|
||||||
Phone,
|
|
||||||
PostalCode,
|
|
||||||
Province,
|
|
||||||
Street,
|
|
||||||
UniqueID,
|
|
||||||
} from "@shared/contexts";
|
|
||||||
import {
|
|
||||||
ICustomerInvoiceParticipantAddressProps,
|
|
||||||
CustomerInvoiceCustomer,
|
|
||||||
CustomerInvoiceParticipantAddress,
|
|
||||||
} from "../../domain";
|
|
||||||
import { IInvoicingContext } from "../InvoicingContext";
|
|
||||||
import {
|
|
||||||
CustomerInvoiceParticipantAddress_Model,
|
|
||||||
TCreationCustomerInvoiceParticipantAddress_Model,
|
|
||||||
} from "../sequelize";
|
|
||||||
|
|
||||||
export interface ICustomerInvoiceParticipantAddressMapper
|
|
||||||
extends ISequelizeMapper<
|
|
||||||
CustomerInvoiceParticipantAddress_Model,
|
|
||||||
TCreationCustomerInvoiceParticipantAddress_Model,
|
|
||||||
CustomerInvoiceParticipantAddress
|
|
||||||
> {}
|
|
||||||
|
|
||||||
export const createCustomerInvoiceParticipantAddressMapper = (
|
|
||||||
context: IInvoicingContext
|
|
||||||
): ICustomerInvoiceParticipantAddressMapper => new CustomerInvoiceParticipantAddressMapper({ context });
|
|
||||||
|
|
||||||
class CustomerInvoiceParticipantAddressMapper
|
|
||||||
extends SequelizeMapper<
|
|
||||||
CustomerInvoiceParticipantAddress_Model,
|
|
||||||
TCreationCustomerInvoiceParticipantAddress_Model,
|
|
||||||
CustomerInvoiceParticipantAddress
|
|
||||||
>
|
|
||||||
implements ICustomerInvoiceParticipantAddressMapper
|
|
||||||
{
|
|
||||||
protected toDomainMappingImpl(source: CustomerInvoiceParticipantAddress_Model, params: any) {
|
|
||||||
const id = this.mapsValue(source, "address_id", UniqueID.create);
|
|
||||||
|
|
||||||
const props: ICustomerInvoiceParticipantAddressProps = {
|
|
||||||
type: source.type,
|
|
||||||
street: this.mapsValue(source, "street", Street.create),
|
|
||||||
city: this.mapsValue(source, "city", City.create),
|
|
||||||
province: this.mapsValue(source, "province", Province.create),
|
|
||||||
postalCode: this.mapsValue(source, "postal_code", PostalCode.create),
|
|
||||||
country: this.mapsValue(source, "country", Country.create),
|
|
||||||
email: this.mapsValue(source, "email", Email.create),
|
|
||||||
phone: this.mapsValue(source, "phone", Phone.create),
|
|
||||||
notes: this.mapsValue(source, "notes", Note.create),
|
|
||||||
};
|
|
||||||
|
|
||||||
const addressOrError = CustomerInvoiceParticipantAddress.create(props, id);
|
|
||||||
|
|
||||||
if (addressOrError.isFailure) {
|
|
||||||
throw addressOrError.error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addressOrError.object;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected toPersistenceMappingImpl(
|
|
||||||
source: CustomerInvoiceParticipantAddress,
|
|
||||||
params: { sourceParent: CustomerInvoiceCustomer }
|
|
||||||
) {
|
|
||||||
const { sourceParent } = params;
|
|
||||||
|
|
||||||
return {
|
|
||||||
address_id: source.id.toPrimitive(),
|
|
||||||
participant_id: sourceParent.id.toPrimitive(),
|
|
||||||
type: String(source.type),
|
|
||||||
title: source.title,
|
|
||||||
street: source.street.toPrimitive(),
|
|
||||||
city: source.city.toPrimitive(),
|
|
||||||
postal_code: source.postalCode.toPrimitive(),
|
|
||||||
province: source.province.toPrimitive(),
|
|
||||||
country: source.country.toPrimitive(),
|
|
||||||
email: source.email.toPrimitive(),
|
|
||||||
phone: source.phone.toPrimitive(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
import {
|
||||||
|
City,
|
||||||
|
Country,
|
||||||
|
Name,
|
||||||
|
PostalCode,
|
||||||
|
Province,
|
||||||
|
Street,
|
||||||
|
TINNumber,
|
||||||
|
maybeFromNullableVO,
|
||||||
|
} from "@repo/rdx-ddd";
|
||||||
|
|
||||||
|
import { MapperParamsType, ValidationErrorDetail, extractOrPushError } from "@erp/core/api";
|
||||||
|
import { Maybe, isNullishOrEmpty } from "@repo/rdx-utils";
|
||||||
|
import { InferCreationAttributes } from "sequelize";
|
||||||
|
import { CustomerInvoice, InvoiceRecipient } from "../../domain";
|
||||||
|
import { CustomerInvoiceModel } from "../sequelize";
|
||||||
|
|
||||||
|
export class InvoiceRecipientMapper {
|
||||||
|
public mapToDomain(source: CustomerInvoiceModel, params?: MapperParamsType) {
|
||||||
|
const { errors } = params as {
|
||||||
|
errors: ValidationErrorDetail[];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Customer (snapshot)
|
||||||
|
|
||||||
|
const customerName = extractOrPushError(
|
||||||
|
Name.create(source.customer_name),
|
||||||
|
"customer_name",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerTin = extractOrPushError(
|
||||||
|
TINNumber.create(source.customer_tin),
|
||||||
|
"customer_tin",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerStreet = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_street, (value) => Street.create(value)),
|
||||||
|
"customer_street",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerStreet2 = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_street2, (value) => Street.create(value)),
|
||||||
|
"customer_street2",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerCity = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_city, (value) => City.create(value)),
|
||||||
|
"customer_city",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerProvince = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_province, (value) => Province.create(value)),
|
||||||
|
"customer_province",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerPostalCode = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_postal_code, (value) => PostalCode.create(value)),
|
||||||
|
"customer_postal_code",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const customerCountry = extractOrPushError(
|
||||||
|
maybeFromNullableVO(source.customer_country, (value) => Country.create(value)),
|
||||||
|
"customer_country",
|
||||||
|
errors
|
||||||
|
);
|
||||||
|
|
||||||
|
const recipientOrError = InvoiceRecipient.create({
|
||||||
|
name: customerName!,
|
||||||
|
tin: customerTin!,
|
||||||
|
street: customerStreet!,
|
||||||
|
street2: customerStreet2!,
|
||||||
|
city: customerCity!,
|
||||||
|
postalCode: customerPostalCode!,
|
||||||
|
province: customerProvince!,
|
||||||
|
country: customerCountry!,
|
||||||
|
});
|
||||||
|
|
||||||
|
return isNullishOrEmpty(recipientOrError)
|
||||||
|
? Maybe.none<InvoiceRecipient>()
|
||||||
|
: Maybe.some(recipientOrError.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public mapToPersistence(
|
||||||
|
source: InvoiceRecipient,
|
||||||
|
params?: MapperParamsType
|
||||||
|
): Partial<InferCreationAttributes<CustomerInvoiceModel, {}>> {
|
||||||
|
1;
|
||||||
|
const { index, sourceParent } = params as {
|
||||||
|
index: number;
|
||||||
|
sourceParent: CustomerInvoice;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
import { MapperParamsType, Taxes } from "@erp/core/api";
|
||||||
|
import { InferCreationAttributes } from "sequelize";
|
||||||
|
import { CustomerInvoiceItemModel, CustomerInvoiceItemTaxModel } from "../sequelize";
|
||||||
|
|
||||||
|
export class ItemTaxesMapper {
|
||||||
|
public mapArrayToDomain(item: CustomerInvoiceItemModel, params?: MapperParamsType) {
|
||||||
|
const taxes = Taxes.create({ items: [] });
|
||||||
|
|
||||||
|
item.taxes.split(",").every((tax_code, taxIndex) => {
|
||||||
|
const taxResult = Tax.createFromCode(tax_code, this.taxCatalog);
|
||||||
|
if (taxResult.isSuccess) {
|
||||||
|
taxes.add(taxResult.data);
|
||||||
|
} else {
|
||||||
|
this.errors.push({
|
||||||
|
path: `items[${itemIndex}].taxes[${taxIndex}]`,
|
||||||
|
message: taxResult.error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return taxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public mapToPersistence(
|
||||||
|
source: Taxes,
|
||||||
|
params?: MapperParamsType
|
||||||
|
): InferCreationAttributes<CustomerInvoiceItemTaxModel, {}> {
|
||||||
|
/*const { index, sourceParent } = params as {
|
||||||
|
index: number;
|
||||||
|
sourceParent: CustomerInvoice;
|
||||||
|
};*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
import { MapperParamsType, Taxes } from "@erp/core/api";
|
||||||
|
import { InferCreationAttributes } from "sequelize";
|
||||||
|
import { CustomerInvoiceItemTaxModel, CustomerInvoiceTaxModel } from "../sequelize";
|
||||||
|
|
||||||
|
export class TaxesMapper {
|
||||||
|
public mapArrayToDomain(taxes: CustomerInvoiceTaxModel[], params?: MapperParamsType) {}
|
||||||
|
|
||||||
|
public mapToPersistence(
|
||||||
|
source: Taxes,
|
||||||
|
params?: MapperParamsType
|
||||||
|
): InferCreationAttributes<CustomerInvoiceItemTaxModel, {}> {
|
||||||
|
/*const { index, sourceParent } = params as {
|
||||||
|
index: number;
|
||||||
|
sourceParent: CustomerInvoice;
|
||||||
|
};*/
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -57,7 +57,7 @@ export default (sequelize: Sequelize) => {
|
|||||||
Contact_Model.init(
|
Contact_Model.init(
|
||||||
{
|
{
|
||||||
id: {
|
id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
tin: {
|
tin: {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default (sequelize: Sequelize) => {
|
|||||||
type: DataTypes.UUID,
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
customer_id: new DataTypes.UUID(),
|
customer_id: DataTypes.UUID,
|
||||||
type: DataTypes.STRING(),
|
type: DataTypes.STRING(),
|
||||||
street: DataTypes.STRING(),
|
street: DataTypes.STRING(),
|
||||||
postal_code: DataTypes.STRING(),
|
postal_code: DataTypes.STRING(),
|
||||||
|
|||||||
@ -8,14 +8,14 @@ import {
|
|||||||
} from "sequelize";
|
} from "sequelize";
|
||||||
import { CustomerInvoiceItem } from "../../domain";
|
import { CustomerInvoiceItem } from "../../domain";
|
||||||
|
|
||||||
export type CustomerInvoiceItemTaxesCreationAttributes = InferCreationAttributes<
|
export type CustomerInvoiceItemTaxCreationAttributes = InferCreationAttributes<
|
||||||
CustomerInvoiceItemTaxesModel,
|
CustomerInvoiceItemTaxModel,
|
||||||
{}
|
{ omit: "item" }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export class CustomerInvoiceItemTaxesModel extends Model<
|
export class CustomerInvoiceItemTaxModel extends Model<
|
||||||
InferAttributes<CustomerInvoiceItemTaxesModel>,
|
InferAttributes<CustomerInvoiceItemTaxModel>,
|
||||||
InferCreationAttributes<CustomerInvoiceItemTaxesModel>
|
InferCreationAttributes<CustomerInvoiceItemTaxModel>
|
||||||
> {
|
> {
|
||||||
declare tax_id: string;
|
declare tax_id: string;
|
||||||
declare item_id: string;
|
declare item_id: string;
|
||||||
@ -36,11 +36,12 @@ export class CustomerInvoiceItemTaxesModel extends Model<
|
|||||||
static associate(database: Sequelize) {
|
static associate(database: Sequelize) {
|
||||||
const { CustomerInvoiceItemModel } = database.models;
|
const { CustomerInvoiceItemModel } = database.models;
|
||||||
|
|
||||||
CustomerInvoiceItemTaxesModel.belongsTo(CustomerInvoiceItemModel, {
|
CustomerInvoiceItemTaxModel.belongsTo(CustomerInvoiceItemModel, {
|
||||||
as: "item",
|
as: "item",
|
||||||
targetKey: "item_id",
|
targetKey: "item_id",
|
||||||
foreignKey: "item_id",
|
foreignKey: "item_id",
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
onUpdate: "CASCADE",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +49,10 @@ export class CustomerInvoiceItemTaxesModel extends Model<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default (database: Sequelize) => {
|
export default (database: Sequelize) => {
|
||||||
CustomerInvoiceItemTaxesModel.init(
|
CustomerInvoiceItemTaxModel.init(
|
||||||
{
|
{
|
||||||
tax_id: {
|
tax_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ export default (database: Sequelize) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize: database,
|
sequelize: database,
|
||||||
tableName: "customer_invoices_item_taxes",
|
tableName: "customer_invoice_item_taxes",
|
||||||
|
|
||||||
underscored: true,
|
underscored: true,
|
||||||
|
|
||||||
@ -103,5 +104,5 @@ export default (database: Sequelize) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return CustomerInvoiceItemTaxesModel;
|
return CustomerInvoiceItemTaxModel;
|
||||||
};
|
};
|
||||||
@ -6,16 +6,22 @@ import {
|
|||||||
NonAttribute,
|
NonAttribute,
|
||||||
Sequelize,
|
Sequelize,
|
||||||
} from "sequelize";
|
} from "sequelize";
|
||||||
|
import {
|
||||||
|
CustomerInvoiceItemTaxCreationAttributes,
|
||||||
|
CustomerInvoiceItemTaxModel,
|
||||||
|
} from "./customer-invoice-item-tax.model";
|
||||||
import { CustomerInvoiceModel } from "./customer-invoice.model";
|
import { CustomerInvoiceModel } from "./customer-invoice.model";
|
||||||
|
|
||||||
export type CustomerInvoiceItemCreationAttributes = InferCreationAttributes<
|
export type CustomerInvoiceItemCreationAttributes = InferCreationAttributes<
|
||||||
CustomerInvoiceItemModel,
|
CustomerInvoiceItemModel,
|
||||||
{ omit: "invoice" }
|
{ omit: "invoice" | "taxes" }
|
||||||
>;
|
> & {
|
||||||
|
taxes?: CustomerInvoiceItemTaxCreationAttributes[];
|
||||||
|
};
|
||||||
|
|
||||||
export class CustomerInvoiceItemModel extends Model<
|
export class CustomerInvoiceItemModel extends Model<
|
||||||
InferAttributes<CustomerInvoiceItemModel>,
|
InferAttributes<CustomerInvoiceItemModel>,
|
||||||
InferCreationAttributes<CustomerInvoiceItemModel, { omit: "invoice" }>
|
InferCreationAttributes<CustomerInvoiceItemModel, { omit: "invoice" | "taxes" }>
|
||||||
> {
|
> {
|
||||||
declare item_id: string;
|
declare item_id: string;
|
||||||
declare invoice_id: string;
|
declare invoice_id: string;
|
||||||
@ -55,15 +61,27 @@ export class CustomerInvoiceItemModel extends Model<
|
|||||||
declare total_amount_scale: number;
|
declare total_amount_scale: number;
|
||||||
|
|
||||||
declare invoice: NonAttribute<CustomerInvoiceModel>;
|
declare invoice: NonAttribute<CustomerInvoiceModel>;
|
||||||
|
declare taxes: NonAttribute<CustomerInvoiceItemTaxModel[]>;
|
||||||
|
|
||||||
static associate(database: Sequelize) {
|
static associate(database: Sequelize) {
|
||||||
const { CustomerInvoiceModel, CustomerInvoiceItemModel } = database.models;
|
const { CustomerInvoiceModel, CustomerInvoiceItemModel, CustomerInvoiceItemTaxModel } =
|
||||||
|
database.models;
|
||||||
|
|
||||||
CustomerInvoiceItemModel.belongsTo(CustomerInvoiceModel, {
|
CustomerInvoiceItemModel.belongsTo(CustomerInvoiceModel, {
|
||||||
as: "customerInvoice",
|
as: "invoice",
|
||||||
targetKey: "id",
|
targetKey: "id",
|
||||||
foreignKey: "invoice_id",
|
foreignKey: "invoice_id",
|
||||||
onDelete: "CASCADE",
|
onDelete: "CASCADE",
|
||||||
|
onUpdate: "CASCADE",
|
||||||
|
});
|
||||||
|
|
||||||
|
CustomerInvoiceItemModel.hasMany(CustomerInvoiceItemTaxModel, {
|
||||||
|
as: "taxes",
|
||||||
|
foreignKey: "item_id",
|
||||||
|
sourceKey: "item_id",
|
||||||
|
constraints: true,
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
onUpdate: "CASCADE",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,12 +90,12 @@ export default (database: Sequelize) => {
|
|||||||
CustomerInvoiceItemModel.init(
|
CustomerInvoiceItemModel.init(
|
||||||
{
|
{
|
||||||
item_id: {
|
item_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
invoice_id: {
|
invoice_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -195,7 +213,7 @@ export default (database: Sequelize) => {
|
|||||||
|
|
||||||
underscored: true,
|
underscored: true,
|
||||||
|
|
||||||
indexes: [{ name: "invoice_idx", fields: ["invoice_id"], unique: false }],
|
indexes: [],
|
||||||
|
|
||||||
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
|
||||||
|
|||||||
@ -8,14 +8,14 @@ import {
|
|||||||
} from "sequelize";
|
} from "sequelize";
|
||||||
import { CustomerInvoice } from "../../domain";
|
import { CustomerInvoice } from "../../domain";
|
||||||
|
|
||||||
export type CustomerInvoiceTaxesCreationAttributes = InferCreationAttributes<
|
export type CustomerInvoiceTaxCreationAttributes = InferCreationAttributes<
|
||||||
CustomerInvoiceTaxesModel,
|
CustomerInvoiceTaxModel,
|
||||||
{}
|
{ omit: "invoice" }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export class CustomerInvoiceTaxesModel extends Model<
|
export class CustomerInvoiceTaxModel extends Model<
|
||||||
InferAttributes<CustomerInvoiceTaxesModel>,
|
InferAttributes<CustomerInvoiceTaxModel>,
|
||||||
InferCreationAttributes<CustomerInvoiceTaxesModel>
|
InferCreationAttributes<CustomerInvoiceTaxModel>
|
||||||
> {
|
> {
|
||||||
declare tax_id: string;
|
declare tax_id: string;
|
||||||
declare invoice_id: string;
|
declare invoice_id: string;
|
||||||
@ -36,7 +36,7 @@ export class CustomerInvoiceTaxesModel extends Model<
|
|||||||
static associate(database: Sequelize) {
|
static associate(database: Sequelize) {
|
||||||
const { CustomerInvoiceModel } = database.models;
|
const { CustomerInvoiceModel } = database.models;
|
||||||
|
|
||||||
CustomerInvoiceTaxesModel.belongsTo(CustomerInvoiceModel, {
|
CustomerInvoiceTaxModel.belongsTo(CustomerInvoiceModel, {
|
||||||
as: "invoice",
|
as: "invoice",
|
||||||
targetKey: "id",
|
targetKey: "id",
|
||||||
foreignKey: "invoice_id",
|
foreignKey: "invoice_id",
|
||||||
@ -48,10 +48,10 @@ export class CustomerInvoiceTaxesModel extends Model<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default (database: Sequelize) => {
|
export default (database: Sequelize) => {
|
||||||
CustomerInvoiceTaxesModel.init(
|
CustomerInvoiceTaxModel.init(
|
||||||
{
|
{
|
||||||
tax_id: {
|
tax_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -89,11 +89,17 @@ export default (database: Sequelize) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
sequelize: database,
|
sequelize: database,
|
||||||
tableName: "customer_invoices_taxes",
|
tableName: "customer_invoice_taxes",
|
||||||
|
|
||||||
underscored: true,
|
underscored: true,
|
||||||
|
|
||||||
indexes: [],
|
indexes: [
|
||||||
|
{
|
||||||
|
name: "invoice_id_idx",
|
||||||
|
fields: ["invoice_id"],
|
||||||
|
unique: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
|
||||||
@ -103,5 +109,5 @@ export default (database: Sequelize) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return CustomerInvoiceTaxesModel;
|
return CustomerInvoiceTaxModel;
|
||||||
};
|
};
|
||||||
@ -11,20 +11,28 @@ import {
|
|||||||
CustomerInvoiceItemModel,
|
CustomerInvoiceItemModel,
|
||||||
} from "./customer-invoice-item.model";
|
} from "./customer-invoice-item.model";
|
||||||
|
|
||||||
|
import { CustomerModel } from "@erp/customers/api";
|
||||||
|
import {
|
||||||
|
CustomerInvoiceTaxCreationAttributes,
|
||||||
|
CustomerInvoiceTaxModel,
|
||||||
|
} from "./customer-invoice-tax.model";
|
||||||
|
|
||||||
export type CustomerInvoiceCreationAttributes = InferCreationAttributes<
|
export type CustomerInvoiceCreationAttributes = InferCreationAttributes<
|
||||||
CustomerInvoiceModel,
|
CustomerInvoiceModel,
|
||||||
{ omit: "items" }
|
{ omit: "items" | "taxes" | "currentCustomer" }
|
||||||
> & {
|
> & {
|
||||||
items?: CustomerInvoiceItemCreationAttributes[];
|
items?: CustomerInvoiceItemCreationAttributes[];
|
||||||
|
taxes?: CustomerInvoiceTaxCreationAttributes[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CustomerInvoiceModel extends Model<
|
export class CustomerInvoiceModel extends Model<
|
||||||
InferAttributes<CustomerInvoiceModel>,
|
InferAttributes<CustomerInvoiceModel>,
|
||||||
InferCreationAttributes<CustomerInvoiceModel, { omit: "items" }>
|
InferCreationAttributes<CustomerInvoiceModel, { omit: "items" | "taxes" }>
|
||||||
> {
|
> {
|
||||||
declare id: string;
|
declare id: string;
|
||||||
declare company_id: string;
|
declare company_id: string;
|
||||||
|
|
||||||
|
declare is_proforma: boolean;
|
||||||
declare status: string;
|
declare status: string;
|
||||||
declare series: string;
|
declare series: string;
|
||||||
declare invoice_number: string;
|
declare invoice_number: string;
|
||||||
@ -51,9 +59,9 @@ export class CustomerInvoiceModel extends Model<
|
|||||||
declare taxable_amount_value: number;
|
declare taxable_amount_value: number;
|
||||||
declare taxable_amount_scale: number;
|
declare taxable_amount_scale: number;
|
||||||
|
|
||||||
// Total tax amount / taxes total
|
// Total taxes amount / taxes total
|
||||||
declare tax_amount_value: number;
|
declare taxes_amount_value: number;
|
||||||
declare tax_amount_scale: number;
|
declare taxes_amount_scale: number;
|
||||||
|
|
||||||
// Total
|
// Total
|
||||||
declare total_amount_value: number;
|
declare total_amount_value: number;
|
||||||
@ -72,38 +80,50 @@ export class CustomerInvoiceModel extends Model<
|
|||||||
|
|
||||||
// Relaciones
|
// Relaciones
|
||||||
declare items: NonAttribute<CustomerInvoiceItemModel[]>;
|
declare items: NonAttribute<CustomerInvoiceItemModel[]>;
|
||||||
//declare customer: NonAttribute<CustomerInvoiceParticipant_Model[]>;
|
declare taxes: NonAttribute<CustomerInvoiceTaxModel[]>;
|
||||||
|
declare currentCustomer: NonAttribute<CustomerModel>;
|
||||||
|
|
||||||
static associate(database: Sequelize) {
|
static associate(database: Sequelize) {
|
||||||
const { CustomerInvoiceModel, CustomerInvoiceItemModel } = database.models;
|
const {
|
||||||
|
CustomerInvoiceModel,
|
||||||
|
CustomerInvoiceItemModel,
|
||||||
|
CustomerModel,
|
||||||
|
CustomerInvoiceTaxModel,
|
||||||
|
} = database.models;
|
||||||
|
|
||||||
|
CustomerInvoiceModel.belongsTo(CustomerModel, {
|
||||||
|
as: "currentCustomer",
|
||||||
|
foreignKey: "customer_id",
|
||||||
|
constraints: false,
|
||||||
|
});
|
||||||
|
|
||||||
CustomerInvoiceModel.hasMany(CustomerInvoiceItemModel, {
|
CustomerInvoiceModel.hasMany(CustomerInvoiceItemModel, {
|
||||||
as: "items",
|
as: "items",
|
||||||
foreignKey: "invoice_id",
|
foreignKey: "invoice_id",
|
||||||
sourceKey: "id",
|
sourceKey: "id",
|
||||||
onDelete: "CASCADE",
|
|
||||||
constraints: true,
|
constraints: true,
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
onUpdate: "CASCADE",
|
||||||
|
});
|
||||||
|
|
||||||
|
CustomerInvoiceModel.hasMany(CustomerInvoiceTaxModel, {
|
||||||
|
as: "taxes",
|
||||||
|
foreignKey: "invoice_id",
|
||||||
|
sourceKey: "id",
|
||||||
|
constraints: true,
|
||||||
|
onDelete: "CASCADE",
|
||||||
|
onUpdate: "CASCADE",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static hooks(database: Sequelize) {
|
static hooks(database: Sequelize) {}
|
||||||
// Soft-cascade manual: al borrar una factura, marcamos items como borrados (paranoid).
|
|
||||||
/*CustomerInvoiceModel.addHook("afterDestroy", async (invoice, options) => {
|
|
||||||
if (!invoice?.id) return;
|
|
||||||
await CustomerInvoiceItemModel.destroy({
|
|
||||||
where: { invoice_id: invoice.id },
|
|
||||||
individualHooks: true,
|
|
||||||
transaction: options.transaction,
|
|
||||||
});
|
|
||||||
});*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default (database: Sequelize) => {
|
export default (database: Sequelize) => {
|
||||||
CustomerInvoiceModel.init(
|
CustomerInvoiceModel.init(
|
||||||
{
|
{
|
||||||
id: {
|
id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -112,6 +132,12 @@ export default (database: Sequelize) => {
|
|||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
is_proforma: {
|
||||||
|
type: DataTypes.BOOLEAN,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
|
||||||
status: {
|
status: {
|
||||||
type: new DataTypes.STRING(),
|
type: new DataTypes.STRING(),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
@ -205,12 +231,12 @@ export default (database: Sequelize) => {
|
|||||||
defaultValue: 2,
|
defaultValue: 2,
|
||||||
},
|
},
|
||||||
|
|
||||||
tax_amount_value: {
|
taxes_amount_value: {
|
||||||
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
type: new DataTypes.BIGINT(), // importante: evita problemas de precisión con valores grandes
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
tax_amount_scale: {
|
taxes_amount_scale: {
|
||||||
type: new DataTypes.SMALLINT(),
|
type: new DataTypes.SMALLINT(),
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
defaultValue: 2,
|
defaultValue: 2,
|
||||||
@ -232,41 +258,49 @@ export default (database: Sequelize) => {
|
|||||||
type: DataTypes.UUID,
|
type: DataTypes.UUID,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_tin: {
|
customer_tin: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_name: {
|
customer_name: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_street: {
|
customer_street: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_street2: {
|
customer_street2: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_city: {
|
customer_city: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_province: {
|
customer_province: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_postal_code: {
|
customer_postal_code: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
defaultValue: null,
|
defaultValue: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
customer_country: {
|
customer_country: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: true,
|
allowNull: true,
|
||||||
@ -285,11 +319,7 @@ export default (database: Sequelize) => {
|
|||||||
updatedAt: "updated_at",
|
updatedAt: "updated_at",
|
||||||
deletedAt: "deleted_at",
|
deletedAt: "deleted_at",
|
||||||
|
|
||||||
indexes: [
|
indexes: [{ name: "company_idx", fields: ["company_id"], unique: false }],
|
||||||
{ name: "company_idx", fields: ["company_id"], unique: false },
|
|
||||||
{ name: "idx_company_idx", fields: ["id", "company_id"], unique: true },
|
|
||||||
{ unique: true, fields: ["invoice_number"] },
|
|
||||||
],
|
|
||||||
|
|
||||||
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { EntityNotFoundError, SequelizeRepository, translateSequelizeError } fro
|
|||||||
import { Criteria, CriteriaToSequelizeConverter } from "@repo/rdx-criteria/server";
|
import { Criteria, CriteriaToSequelizeConverter } from "@repo/rdx-criteria/server";
|
||||||
import { UniqueID } from "@repo/rdx-ddd";
|
import { UniqueID } from "@repo/rdx-ddd";
|
||||||
import { Collection, Result } from "@repo/rdx-utils";
|
import { Collection, Result } from "@repo/rdx-utils";
|
||||||
import { Transaction } from "sequelize";
|
import { Sequelize, Transaction } from "sequelize";
|
||||||
import { CustomerInvoice, ICustomerInvoiceRepository } from "../../domain";
|
import { CustomerInvoice, ICustomerInvoiceRepository } from "../../domain";
|
||||||
import { ICustomerInvoiceMapper } from "../mappers/customer-invoice.mapper";
|
import { ICustomerInvoiceMapper } from "../mappers/customer-invoice.mapper";
|
||||||
import { CustomerInvoiceModel } from "./customer-invoice.model";
|
import { CustomerInvoiceModel } from "./customer-invoice.model";
|
||||||
@ -11,11 +11,13 @@ export class CustomerInvoiceRepository
|
|||||||
extends SequelizeRepository<CustomerInvoice>
|
extends SequelizeRepository<CustomerInvoice>
|
||||||
implements ICustomerInvoiceRepository
|
implements ICustomerInvoiceRepository
|
||||||
{
|
{
|
||||||
private readonly mapper!: ICustomerInvoiceMapper;
|
private readonly _database!: Sequelize;
|
||||||
|
private readonly _mapper!: ICustomerInvoiceMapper;
|
||||||
|
|
||||||
constructor(mapper: ICustomerInvoiceMapper) {
|
constructor(params: { mapper: ICustomerInvoiceMapper; database: Sequelize }) {
|
||||||
super();
|
super();
|
||||||
this.mapper = mapper;
|
this._mapper = params.mapper;
|
||||||
|
this._database = params.database;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listado por tenant con criteria saneada
|
// Listado por tenant con criteria saneada
|
||||||
@ -64,9 +66,9 @@ export class CustomerInvoiceRepository
|
|||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
): Promise<Result<CustomerInvoice, Error>> {
|
): Promise<Result<CustomerInvoice, Error>> {
|
||||||
try {
|
try {
|
||||||
const data = this.mapper.mapToPersistence(invoice);
|
const data = this._mapper.mapToPersistence(invoice);
|
||||||
const [instance] = await CustomerInvoiceModel.upsert(data, { transaction, returning: true });
|
const [instance] = await CustomerInvoiceModel.upsert(data, { transaction, returning: true });
|
||||||
const savedInvoice = this.mapper.mapToDomain(instance);
|
const savedInvoice = this._mapper.mapToDomain(instance);
|
||||||
return savedInvoice;
|
return savedInvoice;
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
return Result.fail(translateSequelizeError(err));
|
return Result.fail(translateSequelizeError(err));
|
||||||
@ -121,7 +123,7 @@ export class CustomerInvoiceRepository
|
|||||||
return Result.fail(new EntityNotFoundError("CustomerInvoice", "id", id.toString()));
|
return Result.fail(new EntityNotFoundError("CustomerInvoice", "id", id.toString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const customer = this.mapper.mapToDomain(row);
|
const customer = this._mapper.mapToDomain(row);
|
||||||
return customer;
|
return customer;
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
return Result.fail(translateSequelizeError(err));
|
return Result.fail(translateSequelizeError(err));
|
||||||
@ -145,6 +147,7 @@ export class CustomerInvoiceRepository
|
|||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
): Promise<Result<Collection<CustomerInvoice>, Error>> {
|
): Promise<Result<Collection<CustomerInvoice>, Error>> {
|
||||||
try {
|
try {
|
||||||
|
const { CustomerModel } = this._database.models;
|
||||||
const converter = new CriteriaToSequelizeConverter();
|
const converter = new CriteriaToSequelizeConverter();
|
||||||
const query = converter.convert(criteria);
|
const query = converter.convert(criteria);
|
||||||
|
|
||||||
@ -153,12 +156,22 @@ export class CustomerInvoiceRepository
|
|||||||
company_id: companyId.toString(),
|
company_id: companyId.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
query.include = [
|
||||||
|
{
|
||||||
|
model: CustomerModel,
|
||||||
|
as: "currentCustomer",
|
||||||
|
required: false, // false => LEFT JOIN
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const instances = await CustomerInvoiceModel.findAll({
|
const instances = await CustomerInvoiceModel.findAll({
|
||||||
...query,
|
...query,
|
||||||
transaction,
|
transaction,
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.mapper.mapArrayToDomain(instances);
|
console.log(instances);
|
||||||
|
|
||||||
|
return this._mapper.mapArrayToDomain(instances);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
return Result.fail(translateSequelizeError(err));
|
return Result.fail(translateSequelizeError(err));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,11 +71,11 @@ export default (sequelize: Sequelize) => {
|
|||||||
CustomerInvoiceParticipant_Model.init(
|
CustomerInvoiceParticipant_Model.init(
|
||||||
{
|
{
|
||||||
participant_id: {
|
participant_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
customerInvoice_id: {
|
customerInvoice_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
tin: {
|
tin: {
|
||||||
|
|||||||
@ -44,11 +44,11 @@ export default (sequelize: Sequelize) => {
|
|||||||
CustomerInvoiceParticipantAddress_Model.init(
|
CustomerInvoiceParticipantAddress_Model.init(
|
||||||
{
|
{
|
||||||
address_id: {
|
address_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
participant_id: {
|
participant_id: {
|
||||||
type: new DataTypes.UUID(),
|
type: DataTypes.UUID,
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import customerInvoiceItemTaxesModelInit from "./customer-invoice-item-taxes.model";
|
import customerInvoiceItemTaxesModelInit from "./customer-invoice-item-tax.model";
|
||||||
import customerInvoiceItemModelInit from "./customer-invoice-item.model";
|
import customerInvoiceItemModelInit from "./customer-invoice-item.model";
|
||||||
import customerInvoiceTaxesModelInit from "./customer-invoice-taxes.model";
|
import customerInvoiceTaxesModelInit from "./customer-invoice-tax.model";
|
||||||
import customerInvoiceModelInit from "./customer-invoice.model";
|
import customerInvoiceModelInit from "./customer-invoice.model";
|
||||||
|
|
||||||
export * from "./customer-invoice-item-taxes.model";
|
export * from "./customer-invoice-item-tax.model";
|
||||||
export * from "./customer-invoice-item.model";
|
export * from "./customer-invoice-item.model";
|
||||||
export * from "./customer-invoice-taxes.model";
|
export * from "./customer-invoice-tax.model";
|
||||||
export * from "./customer-invoice.model";
|
export * from "./customer-invoice.model";
|
||||||
export * from "./customer-invoice.repository";
|
export * from "./customer-invoice.repository";
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
||||||
import { customersRouter, models } from "./infrastructure";
|
import { customersRouter, models } from "./infrastructure";
|
||||||
|
|
||||||
|
export * from "./infrastructure/sequelize";
|
||||||
|
|
||||||
export const customersAPIModule: IModuleServer = {
|
export const customersAPIModule: IModuleServer = {
|
||||||
name: "customers",
|
name: "customers",
|
||||||
version: "1.0.0",
|
version: "1.0.0",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user