From 05f048cc72ccf925b5992e6766b37059d7e4f77b Mon Sep 17 00:00:00 2001 From: david Date: Sat, 7 Mar 2026 22:39:21 +0100 Subject: [PATCH] . --- .../di/issued-invoice-snapshot-builders.di.ts | 4 +- .../di/issued-invoice-use-cases.di.ts | 6 +- .../api/application/issued-invoices/index.ts | 1 - .../issued-invoices/mappers/index.ts | 2 - .../issued-invoice-domain-mapper.interface.ts | 9 - ...issued-invoice-summary-mapper.interface.ts | 8 - .../snapshot-builders/index.ts | 2 +- .../snapshot-builders/list/index.ts | 2 - .../snapshot-builders/summary/index.ts | 2 + ...ssued-invoice-summary-snapshot-builder.ts} | 10 +- ...ued-invoice-summary-snapshot.interface.ts} | 2 +- .../list-issued-invoices.use-case.ts | 6 +- .../di/proforma-snapshot-builders.di.ts | 6 +- .../proformas/di/proforma-use-cases.di.ts | 10 +- .../create-proforma-input.mapper.ts | 4 +- .../application/proformas/mappers/index.ts | 5 +- .../proformas/mappers/inputs/index.ts | 2 - .../proforma-domain-mapper.interface.ts | 9 - .../mappers/proforma-list-mapper.interface.ts | 8 - .../update-proforma-input.mapper.ts | 4 +- .../api/application/proformas/models/index.ts | 2 +- ...proforma-resume.ts => proforma-summary.ts} | 2 +- .../proforma-repository.interface.ts | 4 +- .../proformas/services/proforma-finder.ts | 6 +- .../proformas/snapshot-builders/index.ts | 2 +- .../proformas/snapshot-builders/list/index.ts | 2 - .../snapshot-builders/summary/index.ts | 2 + .../proforma-summary-snapshot-builder.ts} | 12 +- .../proforma-summary-snapshot.interface.ts} | 2 +- .../use-cases/list-proformas.use-case.ts | 6 +- .../aggregates/customer-invoice.aggregate.ts | 343 ------------------ .../customer-invoice-base.aggregate.NOVALE | 73 ---- .../issued-invoice-persistence-mappers.di.ts | 28 ++ .../di/issued-invoice-repositories.di.ts | 21 +- .../issued-invoices/di/issued-invoices.di.ts | 10 +- .../sequelize-issued-invoice-domain.mapper.ts | 17 +- ...lize-issued-invoice-taxes-domain.mapper.ts | 4 +- .../persistence/sequelize/mappers/index.ts | 2 +- .../sequelize/mappers/list/index.ts | 1 - .../sequelize/mappers/summary/index.ts | 1 + ...ssued-invoice-recipient-summary.mapper.ts} | 2 +- ...equelize-issued-invoice-summary.mapper.ts} | 28 +- ...uelize-verifactu-record-summary.mapper.ts} | 4 +- .../repositories/issued-invoice.repository.ts | 10 +- .../di/proforma-persistence-mappers.di.ts | 17 +- .../proformas/di/proformas.di.ts | 75 +--- .../sequelize-proforma-domain.mapper.ts | 10 +- .../persistence/sequelize/mappers/index.ts | 2 +- .../sequelize/mappers/list/index.ts | 1 - .../sequelize/mappers/summary/index.ts | 1 + ...lize-proforma-recipient-summary.mapper.ts} | 23 +- .../sequelize-proforma-summary.mapper.ts} | 22 +- .../repositories/proforma.repository.ts | 20 +- .../api/application/di/customer-finder.di.ts | 8 +- .../di/customer-snapshot-builders.di.ts | 27 +- .../application/di/customer-use-cases.di.ts | 32 +- .../customers/src/api/application/di/index.ts | 4 +- .../customers/src/api/application/index.ts | 1 - .../customer-domain-mapper.interface.ts | 7 - .../customer-summary-mapper.interface.ts | 7 - .../src/api/application/mappers/index.ts | 2 - .../application/services/customer-finder.ts | 6 +- .../application/snapshot-builders/index.ts | 2 +- .../customer-list-item-snapshot-builder.ts | 14 - .../customer-list-item-snapshot.interface.ts | 1 - .../snapshot-builders/list/index.ts | 2 - .../customer-summary-snapshot-builder.ts | 49 +++ .../customer-summary-snapshot.interface.ts | 35 ++ .../snapshot-builders/summary/index.ts | 2 + .../use-cases/list-customers.use-case.ts | 11 +- modules/customers/src/api/index.ts | 18 +- .../src/api/infrastructure/dependencies.ts | 76 ---- .../di/customer-persistence-mappers.di.ts | 32 +- .../di/customer-public-services.ts | 24 ++ .../di/customer-repositories.di.ts | 4 +- .../src/api/infrastructure/di/customers.di.ts | 35 +- .../src/api/infrastructure/di/index.ts | 3 +- .../express/customers.routes.ts | 53 +-- .../infrastructure/mappers/domain/index.ts | 2 +- ...mapper.ts => sequelize-customer.mapper.ts} | 10 +- .../src/api/infrastructure/mappers/index.ts | 2 +- .../infrastructure/mappers/queries/index.ts | 1 - .../infrastructure/mappers/summary/index.ts | 1 + .../sequelize-customer-summary.mapper.ts} | 2 +- .../repositories/customer.repository.ts | 80 +++- 85 files changed, 450 insertions(+), 960 deletions(-) delete mode 100644 modules/customer-invoices/src/api/application/issued-invoices/mappers/index.ts delete mode 100644 modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-domain-mapper.interface.ts delete mode 100644 modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-summary-mapper.interface.ts delete mode 100644 modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/index.ts create mode 100644 modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/index.ts rename modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/{list/issued-invoice-list-item-snapshot-builder.ts => summary/issued-invoice-summary-snapshot-builder.ts} (78%) rename modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/{list/issued-invoice-list-item-snapshot.interface.ts => summary/issued-invoice-summary-snapshot.interface.ts} (95%) rename modules/customer-invoices/src/api/application/proformas/mappers/{inputs => }/create-proforma-input.mapper.ts (99%) delete mode 100644 modules/customer-invoices/src/api/application/proformas/mappers/inputs/index.ts delete mode 100644 modules/customer-invoices/src/api/application/proformas/mappers/proforma-domain-mapper.interface.ts delete mode 100644 modules/customer-invoices/src/api/application/proformas/mappers/proforma-list-mapper.interface.ts rename modules/customer-invoices/src/api/application/proformas/mappers/{inputs => }/update-proforma-input.mapper.ts (96%) rename modules/customer-invoices/src/api/application/proformas/models/{proforma-resume.ts => proforma-summary.ts} (96%) delete mode 100644 modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/index.ts create mode 100644 modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/index.ts rename modules/customer-invoices/src/api/application/proformas/snapshot-builders/{list/proforma-list-item-snapshot-builder.ts => summary/proforma-summary-snapshot-builder.ts} (75%) rename modules/customer-invoices/src/api/application/proformas/snapshot-builders/{list/proforma-list-item-snapshot.interface.ts => summary/proforma-summary-snapshot.interface.ts} (95%) delete mode 100644 modules/customer-invoices/src/api/domain/aggregates/customer-invoice.aggregate.ts delete mode 100644 modules/customer-invoices/src/api/domain/common/customer-invoice-base.aggregate.NOVALE create mode 100644 modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-persistence-mappers.di.ts delete mode 100644 modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/index.ts create mode 100644 modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/index.ts rename modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/{list/sequelize-issued-invoice-recipient.list.mapper.ts => summary/sequelize-issued-invoice-recipient-summary.mapper.ts} (99%) rename modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/{list/sequelize-issued-invoice.list.mapper.ts => summary/sequelize-issued-invoice-summary.mapper.ts} (89%) rename modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/{list/sequelize-verifactu-record.list.mapper.ts => summary/sequelize-verifactu-record-summary.mapper.ts} (94%) delete mode 100644 modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/index.ts create mode 100644 modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/index.ts rename modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/{list/sequelize-proforma-recipient.list.mapper.ts => summary/sequelize-proforma-recipient-summary.mapper.ts} (85%) rename modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/{list/sequelize-proforma.list.mapper.ts => summary/sequelize-proforma-summary.mapper.ts} (90%) delete mode 100644 modules/customers/src/api/application/mappers/customer-domain-mapper.interface.ts delete mode 100644 modules/customers/src/api/application/mappers/customer-summary-mapper.interface.ts delete mode 100644 modules/customers/src/api/application/mappers/index.ts delete mode 100644 modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot-builder.ts delete mode 100644 modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot.interface.ts delete mode 100644 modules/customers/src/api/application/snapshot-builders/list/index.ts create mode 100644 modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot-builder.ts create mode 100644 modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot.interface.ts create mode 100644 modules/customers/src/api/application/snapshot-builders/summary/index.ts delete mode 100644 modules/customers/src/api/infrastructure/dependencies.ts create mode 100644 modules/customers/src/api/infrastructure/di/customer-public-services.ts rename modules/customers/src/api/infrastructure/mappers/domain/{customer.mapper.ts => sequelize-customer.mapper.ts} (97%) delete mode 100644 modules/customers/src/api/infrastructure/mappers/queries/index.ts create mode 100644 modules/customers/src/api/infrastructure/mappers/summary/index.ts rename modules/customers/src/api/infrastructure/mappers/{queries/customer-summary.mapper.ts => summary/sequelize-customer-summary.mapper.ts} (99%) diff --git a/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-snapshot-builders.di.ts b/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-snapshot-builders.di.ts index 66850b2f..2681858f 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-snapshot-builders.di.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-snapshot-builders.di.ts @@ -1,6 +1,6 @@ // application/issued-invoices/di/snapshot-builders.di.ts -import { IssuedInvoiceListItemSnapshotBuilder } from "../snapshot-builders"; +import { IssuedInvoiceSummarySnapshotBuilder } from "../snapshot-builders"; import { IssuedInvoiceFullSnapshotBuilder, IssuedInvoiceItemsFullSnapshotBuilder, @@ -30,7 +30,7 @@ export function buildIssuedInvoiceSnapshotBuilders() { taxesBuilder ); - const listSnapshotBuilder = new IssuedInvoiceListItemSnapshotBuilder(); + const listSnapshotBuilder = new IssuedInvoiceSummarySnapshotBuilder(); const itemsReportBuilder = new IssuedInvoiceReportItemSnapshotBuilder(); const taxesReportBuilder = new IssuedInvoiceReportTaxSnapshotBuilder(); diff --git a/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-use-cases.di.ts b/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-use-cases.di.ts index 828730aa..69bb2d7c 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-use-cases.di.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/di/issued-invoice-use-cases.di.ts @@ -1,7 +1,7 @@ import type { ITransactionManager } from "@erp/core/api"; import type { IIssuedInvoiceFinder, IssuedInvoiceDocumentGeneratorService } from "../services"; -import type { IIssuedInvoiceListItemSnapshotBuilder } from "../snapshot-builders"; +import type { IIssuedInvoiceSummarySnapshotBuilder } from "../snapshot-builders"; import type { IIssuedInvoiceFullSnapshotBuilder } from "../snapshot-builders/full"; import type { IIssuedInvoiceReportSnapshotBuilder } from "../snapshot-builders/report"; import { @@ -24,12 +24,12 @@ export function buildGetIssuedInvoiceByIdUseCase(deps: { export function buildListIssuedInvoicesUseCase(deps: { finder: IIssuedInvoiceFinder; - itemSnapshotBuilder: IIssuedInvoiceListItemSnapshotBuilder; + summarySnapshotBuilder: IIssuedInvoiceSummarySnapshotBuilder; transactionManager: ITransactionManager; }) { return new ListIssuedInvoicesUseCase( deps.finder, - deps.itemSnapshotBuilder, + deps.summarySnapshotBuilder, deps.transactionManager ); } diff --git a/modules/customer-invoices/src/api/application/issued-invoices/index.ts b/modules/customer-invoices/src/api/application/issued-invoices/index.ts index b68ea0dc..21fd64a4 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/index.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/index.ts @@ -1,5 +1,4 @@ export * from "./di"; -export * from "./mappers"; export * from "./models"; export * from "./repositories"; export * from "./services"; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/mappers/index.ts b/modules/customer-invoices/src/api/application/issued-invoices/mappers/index.ts deleted file mode 100644 index 9c8fdfbb..00000000 --- a/modules/customer-invoices/src/api/application/issued-invoices/mappers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./issued-invoice-domain-mapper.interface"; -export * from "./issued-invoice-list-mapper.interface"; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-domain-mapper.interface.ts b/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-domain-mapper.interface.ts deleted file mode 100644 index ebeca5bd..00000000 --- a/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-domain-mapper.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { MapperParamsType } from "@erp/core/api"; -import type { Result } from "@repo/rdx-utils"; - -import type { IssuedInvoice } from "../../../domain"; - -export interface IIssuedInvoiceDomainMapper { - mapToPersistence(invoice: IssuedInvoice, params?: MapperParamsType): Result; - mapToDomain(raw: unknown, params?: MapperParamsType): Result; -} diff --git a/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-summary-mapper.interface.ts b/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-summary-mapper.interface.ts deleted file mode 100644 index 2d4727c1..00000000 --- a/modules/customer-invoices/src/api/application/issued-invoices/mappers/issued-invoice-summary-mapper.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { MapperParamsType } from "@erp/core/api"; -import type { Result } from "@repo/rdx-utils"; - -import type { IssuedInvoiceSummary } from "../models"; - -export interface IIssuedInvoiceSummaryMapper { - mapToDTO(raw: unknown, params?: MapperParamsType): Result; -} diff --git a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/index.ts b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/index.ts index c2be1212..3b83e1ff 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/index.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/index.ts @@ -1,2 +1,2 @@ export * from "./full"; -export * from "./list"; +export * from "./summary"; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/index.ts b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/index.ts deleted file mode 100644 index c3dabd99..00000000 --- a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./issued-invoice-list-item-snapshot.interface"; -export * from "./issued-invoice-list-item-snapshot-builder"; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/index.ts b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/index.ts new file mode 100644 index 00000000..6814712a --- /dev/null +++ b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/index.ts @@ -0,0 +1,2 @@ +export * from "./issued-invoice-summary-snapshot.interface"; +export * from "./issued-invoice-summary-snapshot-builder"; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot-builder.ts b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot-builder.ts similarity index 78% rename from modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot-builder.ts rename to modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot-builder.ts index 22743b80..afca7ef6 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot-builder.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot-builder.ts @@ -3,13 +3,13 @@ import { maybeToEmptyString } from "@repo/rdx-ddd"; import type { IssuedInvoiceSummary } from "../../models"; -import type { IIssuedInvoiceListItemSnapshot } from "./issued-invoice-list-item-snapshot.interface"; +import type { IIssuedInvoiceSummarySnapshot } from "./issued-invoice-summary-snapshot.interface"; -export interface IIssuedInvoiceListItemSnapshotBuilder - extends ISnapshotBuilder {} +export interface IIssuedInvoiceSummarySnapshotBuilder + extends ISnapshotBuilder {} -export class IssuedInvoiceListItemSnapshotBuilder implements IIssuedInvoiceListItemSnapshotBuilder { - toOutput(invoice: IssuedInvoiceSummary): IIssuedInvoiceListItemSnapshot { +export class IssuedInvoiceSummarySnapshotBuilder implements IIssuedInvoiceSummarySnapshotBuilder { + toOutput(invoice: IssuedInvoiceSummary): IIssuedInvoiceSummarySnapshot { const recipient = invoice.recipient.toObjectString(); const verifactu = invoice.verifactu.match( diff --git a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot.interface.ts b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot.interface.ts similarity index 95% rename from modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot.interface.ts rename to modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot.interface.ts index 45f26615..b64675f5 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/list/issued-invoice-list-item-snapshot.interface.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/snapshot-builders/summary/issued-invoice-summary-snapshot.interface.ts @@ -1,4 +1,4 @@ -export interface IIssuedInvoiceListItemSnapshot { +export interface IIssuedInvoiceSummarySnapshot { id: string; company_id: string; diff --git a/modules/customer-invoices/src/api/application/issued-invoices/use-cases/list-issued-invoices.use-case.ts b/modules/customer-invoices/src/api/application/issued-invoices/use-cases/list-issued-invoices.use-case.ts index ebe0794f..695a1b9f 100644 --- a/modules/customer-invoices/src/api/application/issued-invoices/use-cases/list-issued-invoices.use-case.ts +++ b/modules/customer-invoices/src/api/application/issued-invoices/use-cases/list-issued-invoices.use-case.ts @@ -5,7 +5,7 @@ import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; import type { IIssuedInvoiceFinder } from "../services"; -import type { IIssuedInvoiceListItemSnapshotBuilder } from "../snapshot-builders"; +import type { IIssuedInvoiceSummarySnapshotBuilder } from "../snapshot-builders"; type ListIssuedInvoicesUseCaseInput = { companyId: UniqueID; @@ -15,7 +15,7 @@ type ListIssuedInvoicesUseCaseInput = { export class ListIssuedInvoicesUseCase { constructor( private readonly finder: IIssuedInvoiceFinder, - private readonly listItemSnapshotBuilder: IIssuedInvoiceListItemSnapshotBuilder, + private readonly summarySnapshotBuilder: IIssuedInvoiceSummarySnapshotBuilder, private readonly transactionManager: ITransactionManager ) {} @@ -37,7 +37,7 @@ export class ListIssuedInvoicesUseCase { const invoices = result.data; const totalInvoices = invoices.total(); - const items = invoices.map((item) => this.listItemSnapshotBuilder.toOutput(item)); + const items = invoices.map((item) => this.summarySnapshotBuilder.toOutput(item)); const snapshot = { page: criteria.pageNumber, diff --git a/modules/customer-invoices/src/api/application/proformas/di/proforma-snapshot-builders.di.ts b/modules/customer-invoices/src/api/application/proformas/di/proforma-snapshot-builders.di.ts index d0785194..a4a50edf 100644 --- a/modules/customer-invoices/src/api/application/proformas/di/proforma-snapshot-builders.di.ts +++ b/modules/customer-invoices/src/api/application/proformas/di/proforma-snapshot-builders.di.ts @@ -4,9 +4,9 @@ import { ProformaFullSnapshotBuilder, ProformaItemReportSnapshotBuilder, ProformaItemsFullSnapshotBuilder, - ProformaListItemSnapshotBuilder, ProformaRecipientFullSnapshotBuilder, ProformaReportSnapshotBuilder, + ProformaSummarySnapshotBuilder, ProformaTaxReportSnapshotBuilder, ProformaTaxesFullSnapshotBuilder, } from "../snapshot-builders"; @@ -24,7 +24,7 @@ export function buildProformaSnapshotBuilders() { taxesBuilder ); - const listSnapshotBuilder = new ProformaListItemSnapshotBuilder(); + const summarySnapshotBuilder = new ProformaSummarySnapshotBuilder(); const itemsReportBuilder = new ProformaItemReportSnapshotBuilder(); const taxesReportBuilder = new ProformaTaxReportSnapshotBuilder(); @@ -35,7 +35,7 @@ export function buildProformaSnapshotBuilders() { return { full: fullSnapshotBuilder, - list: listSnapshotBuilder, + summary: summarySnapshotBuilder, report: reportSnapshotBuilder, }; } diff --git a/modules/customer-invoices/src/api/application/proformas/di/proforma-use-cases.di.ts b/modules/customer-invoices/src/api/application/proformas/di/proforma-use-cases.di.ts index bd7d7991..1601c96d 100644 --- a/modules/customer-invoices/src/api/application/proformas/di/proforma-use-cases.di.ts +++ b/modules/customer-invoices/src/api/application/proformas/di/proforma-use-cases.di.ts @@ -7,8 +7,8 @@ import type { ProformaDocumentGeneratorService, } from "../services"; import type { - IProformaListItemSnapshotBuilder, IProformaReportSnapshotBuilder, + IProformaSummarySnapshotBuilder, } from "../snapshot-builders"; import type { IProformaFullSnapshotBuilder } from "../snapshot-builders/full"; import { GetProformaByIdUseCase, ListProformasUseCase, ReportProformaUseCase } from "../use-cases"; @@ -24,10 +24,14 @@ export function buildGetProformaByIdUseCase(deps: { export function buildListProformasUseCase(deps: { finder: IProformaFinder; - itemSnapshotBuilder: IProformaListItemSnapshotBuilder; + summarySnapshotBuilder: IProformaSummarySnapshotBuilder; transactionManager: ITransactionManager; }) { - return new ListProformasUseCase(deps.finder, deps.itemSnapshotBuilder, deps.transactionManager); + return new ListProformasUseCase( + deps.finder, + deps.summarySnapshotBuilder, + deps.transactionManager + ); } export function buildReportProformaUseCase(deps: { diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/create-proforma-input.mapper.ts b/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts similarity index 99% rename from modules/customer-invoices/src/api/application/proformas/mappers/inputs/create-proforma-input.mapper.ts rename to modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts index 5029cf3f..70ae0f4e 100644 --- a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/create-proforma-input.mapper.ts +++ b/modules/customer-invoices/src/api/application/proformas/mappers/create-proforma-input.mapper.ts @@ -15,7 +15,7 @@ import { } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../../common"; +import type { CreateProformaItemRequestDTO, CreateProformaRequestDTO } from "../../../../common"; import { type IProformaItemProps, type IProformaProps, @@ -28,7 +28,7 @@ import { ItemDescription, ItemQuantity, type ProformaItemTaxesProps, -} from "../../../../domain"; +} from "../../../domain"; /** * CreateProformaPropsMapper diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/index.ts b/modules/customer-invoices/src/api/application/proformas/mappers/index.ts index 3e39ef5b..dff878fb 100644 --- a/modules/customer-invoices/src/api/application/proformas/mappers/index.ts +++ b/modules/customer-invoices/src/api/application/proformas/mappers/index.ts @@ -1,3 +1,2 @@ -export * from "./inputs"; -export * from "./proforma-domain-mapper.interface"; -export * from "./proforma-list-mapper.interface"; +export * from "./create-proforma-input.mapper"; +export * from "./update-proforma-input.mapper"; diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/index.ts b/modules/customer-invoices/src/api/application/proformas/mappers/inputs/index.ts deleted file mode 100644 index dff878fb..00000000 --- a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./create-proforma-input.mapper"; -export * from "./update-proforma-input.mapper"; diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/proforma-domain-mapper.interface.ts b/modules/customer-invoices/src/api/application/proformas/mappers/proforma-domain-mapper.interface.ts deleted file mode 100644 index a849ae74..00000000 --- a/modules/customer-invoices/src/api/application/proformas/mappers/proforma-domain-mapper.interface.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { MapperParamsType } from "@erp/core/api"; -import type { Result } from "@repo/rdx-utils"; - -import type { Proforma } from "../../../domain"; - -export interface IProformaDomainMapper { - mapToPersistence(proforma: Proforma, params?: MapperParamsType): Result; - mapToDomain(raw: unknown, params?: MapperParamsType): Result; -} diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/proforma-list-mapper.interface.ts b/modules/customer-invoices/src/api/application/proformas/mappers/proforma-list-mapper.interface.ts deleted file mode 100644 index c98fddf8..00000000 --- a/modules/customer-invoices/src/api/application/proformas/mappers/proforma-list-mapper.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { MapperParamsType } from "@erp/core/api"; -import type { Result } from "@repo/rdx-utils"; - -import type { ProformaListDTO } from "../models"; - -export interface IProformaListMapper { - mapToDTO(raw: unknown, params?: MapperParamsType): Result; -} diff --git a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/update-proforma-input.mapper.ts b/modules/customer-invoices/src/api/application/proformas/mappers/update-proforma-input.mapper.ts similarity index 96% rename from modules/customer-invoices/src/api/application/proformas/mappers/inputs/update-proforma-input.mapper.ts rename to modules/customer-invoices/src/api/application/proformas/mappers/update-proforma-input.mapper.ts index 4aa6c288..76ccc0a3 100644 --- a/modules/customer-invoices/src/api/application/proformas/mappers/inputs/update-proforma-input.mapper.ts +++ b/modules/customer-invoices/src/api/application/proformas/mappers/update-proforma-input.mapper.ts @@ -12,8 +12,8 @@ import { } from "@repo/rdx-ddd"; import { Result, isNullishOrEmpty, toPatchField } from "@repo/rdx-utils"; -import type { UpdateProformaByIdRequestDTO } from "../../../../../common/dto"; -import type { ProformaPatchProps } from "../../../../domain"; +import type { UpdateProformaByIdRequestDTO } from "../../../../common/dto"; +import { InvoiceSerie, type ProformaPatchProps } from "../../../domain"; /** * UpdateProformaPropsMapper diff --git a/modules/customer-invoices/src/api/application/proformas/models/index.ts b/modules/customer-invoices/src/api/application/proformas/models/index.ts index f1197467..3030fae7 100644 --- a/modules/customer-invoices/src/api/application/proformas/models/index.ts +++ b/modules/customer-invoices/src/api/application/proformas/models/index.ts @@ -1 +1 @@ -export * from "./proforma-resume"; +export * from "./proforma-summary"; diff --git a/modules/customer-invoices/src/api/application/proformas/models/proforma-resume.ts b/modules/customer-invoices/src/api/application/proformas/models/proforma-summary.ts similarity index 96% rename from modules/customer-invoices/src/api/application/proformas/models/proforma-resume.ts rename to modules/customer-invoices/src/api/application/proformas/models/proforma-summary.ts index dc1bf449..142ba444 100644 --- a/modules/customer-invoices/src/api/application/proformas/models/proforma-resume.ts +++ b/modules/customer-invoices/src/api/application/proformas/models/proforma-summary.ts @@ -9,7 +9,7 @@ import type { InvoiceStatus, } from "../../../domain"; -export type ProformaListDTO = { +export type ProformaSummary = { id: UniqueID; companyId: UniqueID; diff --git a/modules/customer-invoices/src/api/application/proformas/repositories/proforma-repository.interface.ts b/modules/customer-invoices/src/api/application/proformas/repositories/proforma-repository.interface.ts index 53b9c524..56cef017 100644 --- a/modules/customer-invoices/src/api/application/proformas/repositories/proforma-repository.interface.ts +++ b/modules/customer-invoices/src/api/application/proformas/repositories/proforma-repository.interface.ts @@ -3,7 +3,7 @@ import type { UniqueID } from "@repo/rdx-ddd"; import type { Collection, Result } from "@repo/rdx-utils"; import type { InvoiceStatus, Proforma } from "../../../domain"; -import type { ProformaListDTO } from "../models"; +import type { ProformaSummary } from "../models"; export interface IProformaRepository { create(proforma: Proforma, transaction?: unknown): Promise>; @@ -26,7 +26,7 @@ export interface IProformaRepository { companyId: UniqueID, criteria: Criteria, transaction: unknown - ): Promise, Error>>; + ): Promise, Error>>; deleteByIdInCompany( companyId: UniqueID, diff --git a/modules/customer-invoices/src/api/application/proformas/services/proforma-finder.ts b/modules/customer-invoices/src/api/application/proformas/services/proforma-finder.ts index d2c9e54a..05bef01c 100644 --- a/modules/customer-invoices/src/api/application/proformas/services/proforma-finder.ts +++ b/modules/customer-invoices/src/api/application/proformas/services/proforma-finder.ts @@ -4,7 +4,7 @@ import type { Collection, Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; import type { Proforma } from "../../../domain"; -import type { ProformaListDTO } from "../models"; +import type { ProformaSummary } from "../models"; import type { IProformaRepository } from "../repositories"; export interface IProformaFinder { @@ -24,7 +24,7 @@ export interface IProformaFinder { companyId: UniqueID, criteria: Criteria, transaction?: Transaction - ): Promise, Error>>; + ): Promise, Error>>; } export class ProformaFinder implements IProformaFinder { @@ -50,7 +50,7 @@ export class ProformaFinder implements IProformaFinder { companyId: UniqueID, criteria: Criteria, transaction?: Transaction - ): Promise, Error>> { + ): Promise, Error>> { return this.repository.findByCriteriaInCompany(companyId, criteria, transaction, {}); } } diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/index.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/index.ts index 188f634f..a23ae1ee 100644 --- a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/index.ts +++ b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/index.ts @@ -1,3 +1,3 @@ export * from "./full"; -export * from "./list"; export * from "./report"; +export * from "./summary"; diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/index.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/index.ts deleted file mode 100644 index 062b00a2..00000000 --- a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./proforma-list-item-snapshot.interface"; -export * from "./proforma-list-item-snapshot-builder"; diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/index.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/index.ts new file mode 100644 index 00000000..82158c8d --- /dev/null +++ b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/index.ts @@ -0,0 +1,2 @@ +export * from "./proforma-summary-snapshot.interface"; +export * from "./proforma-summary-snapshot-builder"; diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot-builder.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot-builder.ts similarity index 75% rename from modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot-builder.ts rename to modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot-builder.ts index c2bd5dfe..359261ce 100644 --- a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot-builder.ts +++ b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot-builder.ts @@ -1,15 +1,15 @@ import type { ISnapshotBuilder } from "@erp/core/api"; import { maybeToEmptyString } from "@repo/rdx-ddd"; -import type { ProformaListDTO } from "../../models"; +import type { ProformaSummary } from "../../models"; -import type { IProformaListItemSnapshot } from "./proforma-list-item-snapshot.interface"; +import type { IProformaSummarySnapshot } from "./proforma-summary-snapshot.interface"; -export interface IProformaListItemSnapshotBuilder - extends ISnapshotBuilder {} +export interface IProformaSummarySnapshotBuilder + extends ISnapshotBuilder {} -export class ProformaListItemSnapshotBuilder implements IProformaListItemSnapshotBuilder { - toOutput(proforma: ProformaListDTO): IProformaListItemSnapshot { +export class ProformaSummarySnapshotBuilder implements IProformaSummarySnapshotBuilder { + toOutput(proforma: ProformaSummary): IProformaSummarySnapshot { const recipient = proforma.recipient.toObjectString(); return { diff --git a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot.interface.ts b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot.interface.ts similarity index 95% rename from modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot.interface.ts rename to modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot.interface.ts index 5f4d664d..1ff4cf9e 100644 --- a/modules/customer-invoices/src/api/application/proformas/snapshot-builders/list/proforma-list-item-snapshot.interface.ts +++ b/modules/customer-invoices/src/api/application/proformas/snapshot-builders/summary/proforma-summary-snapshot.interface.ts @@ -1,4 +1,4 @@ -export interface IProformaListItemSnapshot { +export interface IProformaSummarySnapshot { id: string; company_id: string; diff --git a/modules/customer-invoices/src/api/application/proformas/use-cases/list-proformas.use-case.ts b/modules/customer-invoices/src/api/application/proformas/use-cases/list-proformas.use-case.ts index b6fd2e4d..11b47bc7 100644 --- a/modules/customer-invoices/src/api/application/proformas/use-cases/list-proformas.use-case.ts +++ b/modules/customer-invoices/src/api/application/proformas/use-cases/list-proformas.use-case.ts @@ -5,7 +5,7 @@ import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; import type { IProformaFinder } from "../services"; -import type { IProformaListItemSnapshotBuilder } from "../snapshot-builders"; +import type { IProformaSummarySnapshotBuilder } from "../snapshot-builders"; type ListProformasUseCaseInput = { companyId: UniqueID; @@ -15,7 +15,7 @@ type ListProformasUseCaseInput = { export class ListProformasUseCase { constructor( private readonly finder: IProformaFinder, - private readonly listItemSnapshotBuilder: IProformaListItemSnapshotBuilder, + private readonly summarySnapshotBuilder: IProformaSummarySnapshotBuilder, private readonly transactionManager: ITransactionManager ) {} @@ -33,7 +33,7 @@ export class ListProformasUseCase { const proformas = result.data; const totalProformas = proformas.total(); - const items = proformas.map((item) => this.listItemSnapshotBuilder.toOutput(item)); + const items = proformas.map((item) => this.summarySnapshotBuilder.toOutput(item)); const snapshot = { page: criteria.pageNumber, diff --git a/modules/customer-invoices/src/api/domain/aggregates/customer-invoice.aggregate.ts b/modules/customer-invoices/src/api/domain/aggregates/customer-invoice.aggregate.ts deleted file mode 100644 index 9eb46685..00000000 --- a/modules/customer-invoices/src/api/domain/aggregates/customer-invoice.aggregate.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { - AggregateRoot, - type CurrencyCode, - DomainValidationError, - type LanguageCode, - type Percentage, - type TextValue, - type UniqueID, - type UtcDate, -} from "@repo/rdx-ddd"; -import { Collection, type Maybe, Result } from "@repo/rdx-utils"; - -import { - CustomerInvoiceItems, - type InvoicePaymentMethod, - type VerifactuRecord, -} from "../common/entities"; -import { - InvoiceAmount, - type InvoiceNumber, - type InvoiceRecipient, - type InvoiceSerie, - type InvoiceStatus, - InvoiceTaxGroup, - type ItemAmount, -} from "../common/value-objects"; - -export interface CustomerInvoiceProps { - companyId: UniqueID; - - isProforma: boolean; - status: InvoiceStatus; - - proformaId: Maybe; // <- proforma padre en caso de issue - - series: Maybe; - invoiceNumber: InvoiceNumber; - - invoiceDate: UtcDate; - operationDate: Maybe; - - customerId: UniqueID; - recipient: Maybe; - - reference: Maybe; - description: Maybe; - notes: Maybe; - - languageCode: LanguageCode; - currencyCode: CurrencyCode; - - items: CustomerInvoiceItems; - - paymentMethod: Maybe; - - discountPercentage: Percentage; - - verifactu: Maybe; -} - -export type CustomerInvoicePatchProps = Partial< - Omit -> & { - items?: CustomerInvoiceItems; -}; - -export interface ICustomerInvoice { - canTransitionTo(nextStatus: string): boolean; - - hasRecipient: boolean; - hasPaymentMethod: boolean; - - //getTaxes(): Collection; - getProps(): CustomerInvoiceProps; -} - -export class CustomerInvoice - extends AggregateRoot - implements ICustomerInvoice -{ - private _items!: CustomerInvoiceItems; - - protected constructor(props: CustomerInvoiceProps, id?: UniqueID) { - super(props, id); - this._items = - props.items || - CustomerInvoiceItems.create({ - languageCode: props.languageCode, - currencyCode: props.currencyCode, - globalDiscountPercentage: props.discountPercentage, - }); - } - - static create(props: CustomerInvoiceProps, id?: UniqueID): Result { - const customerInvoice = new CustomerInvoice(props, id); - - // Reglas de negocio / validaciones - - if (!(customerInvoice.isProforma || customerInvoice.hasRecipient)) { - return Result.fail( - new DomainValidationError( - "MISSING_CUSTOMER_DATA", - "recipient", - "Customer data must be provided for non-proforma invoices" - ) - ); - } - - // 🔹 Disparar evento de dominio "CustomerInvoiceAuthenticatedEvent" - //const { customerInvoice } = props; - //user.addDomainEvent(new CustomerInvoiceAuthenticatedEvent(id, customerInvoice.toString())); - - return Result.ok(customerInvoice); - } - - // Getters - - public get companyId(): UniqueID { - return this.props.companyId; - } - - public get customerId(): UniqueID { - return this.props.customerId; - } - - public get isProforma(): boolean { - return this.props.isProforma; - } - - public get proformaId(): Maybe { - return this.props.proformaId; - } - - public get status(): InvoiceStatus { - return this.props.status; - } - - canTransitionTo(nextStatus: string): boolean { - return this.props.status.canTransitionTo(nextStatus); - } - - public get series(): Maybe { - return this.props.series; - } - - public get invoiceNumber() { - return this.props.invoiceNumber; - } - - public get invoiceDate(): UtcDate { - return this.props.invoiceDate; - } - - public get operationDate(): Maybe { - return this.props.operationDate; - } - - public get reference(): Maybe { - return this.props.reference; - } - - public get description(): Maybe { - return this.props.description; - } - - public get notes(): Maybe { - return this.props.notes; - } - - public get recipient(): Maybe { - return this.props.recipient; - } - - public get paymentMethod(): Maybe { - return this.props.paymentMethod; - } - - public get languageCode(): LanguageCode { - return this.props.languageCode; - } - - public get currencyCode(): CurrencyCode { - return this.props.currencyCode; - } - - public get verifactu(): Maybe { - return this.props.verifactu; - } - - public get discountPercentage(): Percentage { - return this.props.discountPercentage; - } - - // Method to get the complete list of line items - - public get items(): CustomerInvoiceItems { - return this._items; - } - - public get hasRecipient() { - return this.recipient.isSome(); - } - - public get hasPaymentMethod() { - return this.paymentMethod.isSome(); - } - - // Helpers - - /** - * @summary Convierte un ItemAmount a InvoiceAmount (mantiene moneda y escala homogénea). - */ - private _toInvoiceAmount(itemAmount: ItemAmount): InvoiceAmount { - return InvoiceAmount.create({ - value: itemAmount.convertScale(InvoiceAmount.DEFAULT_SCALE).value, - currency_code: this.currencyCode.code, - }).data; - } - - // Cálculos - - /** - * @summary Calcula todos los totales de factura a partir de los totales de las líneas. - * La cabecera NO recalcula lógica de porcentaje — toda la lógica está en Item/Items. - */ - public calculateAllAmounts() { - const itemsTotals = this.items.calculateAllAmounts(); - - const subtotalAmount = this._toInvoiceAmount(itemsTotals.subtotalAmount); - - const itemDiscountAmount = this._toInvoiceAmount(itemsTotals.itemDiscountAmount); - const globalDiscountAmount = this._toInvoiceAmount(itemsTotals.globalDiscountAmount); - const totalDiscountAmount = this._toInvoiceAmount(itemsTotals.totalDiscountAmount); - - const taxableAmount = this._toInvoiceAmount(itemsTotals.taxableAmount); - const taxesAmount = this._toInvoiceAmount(itemsTotals.taxesAmount); - const totalAmount = this._toInvoiceAmount(itemsTotals.totalAmount); - - const taxGroups = this._groupTaxes(); - - return { - subtotalAmount, - itemDiscountAmount, - globalDiscountAmount, - totalDiscountAmount, - taxableAmount, - taxesAmount, - totalAmount, - taxGroups, - } as const; - } - - // Métodos públicos - - public getProps(): CustomerInvoiceProps { - return this.props; - } - - public update(partialInvoice: CustomerInvoicePatchProps): Result { - const { items, ...rest } = partialInvoice; - - const updatedProps = { - ...this.props, - ...rest, - } as CustomerInvoiceProps; - - /*if (partialAddress) { - const updatedAddressOrError = this.address.update(partialAddress); - if (updatedAddressOrError.isFailure) { - return Result.fail(updatedAddressOrError.error); - } - - updatedProps.address = updatedAddressOrError.data; - }*/ - - return CustomerInvoice.create(updatedProps, this.id); - } - - public getSubtotalAmount(): InvoiceAmount { - return this.calculateAllAmounts().subtotalAmount; - } - - public getItemDiscountAmount(): InvoiceAmount { - return this.calculateAllAmounts().itemDiscountAmount; - } - - public getGlobalDiscountAmount(): InvoiceAmount { - return this.calculateAllAmounts().globalDiscountAmount; - } - - public getTotalDiscountAmount(): InvoiceAmount { - return this.calculateAllAmounts().totalDiscountAmount; - } - - public getTaxableAmount(): InvoiceAmount { - return this.calculateAllAmounts().taxableAmount; - } - - public getTaxesAmount(): InvoiceAmount { - return this.calculateAllAmounts().taxesAmount; - } - - public getTotalAmount(): InvoiceAmount { - return this.calculateAllAmounts().totalAmount; - } - - public getTaxes(): Collection { - return this._groupTaxes(); - } - - /** - * @summary Agrupa impuestos a nivel factura usando el trío (iva|rec|ret), - * construyendo InvoiceTaxGroup desde los datos de los ítems. - */ - private _groupTaxes(): Collection { - const map = this.items.groupTaxesByCode(); - const groups: InvoiceTaxGroup[] = []; - - for (const [, entry] of map.entries()) { - const { taxes, taxable } = entry; - - const iva = taxes.iva.unwrap(); // IVA siempre obligatorio - const rec = taxes.rec; // Maybe - const retention = taxes.retention; // Maybe - - const invoiceAmount = InvoiceAmount.create({ - value: taxable.convertScale(InvoiceAmount.DEFAULT_SCALE).value, - currency_code: this.currencyCode.code, - }).data; - - const item = InvoiceTaxGroup.create({ - iva, - rec, - retention, - taxableAmount: invoiceAmount, - }).data; - - groups.push(item); - } - - return new Collection(groups); - } -} diff --git a/modules/customer-invoices/src/api/domain/common/customer-invoice-base.aggregate.NOVALE b/modules/customer-invoices/src/api/domain/common/customer-invoice-base.aggregate.NOVALE deleted file mode 100644 index c768a4aa..00000000 --- a/modules/customer-invoices/src/api/domain/common/customer-invoice-base.aggregate.NOVALE +++ /dev/null @@ -1,73 +0,0 @@ -import { - AggregateRoot, - type CurrencyCode, - type LanguageCode, - type Percentage, - type TextValue, - type UniqueID, - type UtcDate, -} from "@repo/rdx-ddd"; -import type { Maybe } from "@repo/rdx-utils"; - -import type { CustomerInvoiceItems, InvoicePaymentMethod } from "./entities"; -import type { InvoiceNumber, InvoiceRecipient, InvoiceSerie, InvoiceStatus } from "./value-objects"; - -export interface ICustomerInvoiceBaseProps { - companyId: UniqueID; - invoiceNumber: InvoiceNumber; - invoiceDate: UtcDate; - - status: InvoiceStatus; - - series: Maybe; - - operationDate: Maybe; - - customerId: UniqueID; - recipient: Maybe; - - reference: Maybe; - description: Maybe; - notes: Maybe; - - languageCode: LanguageCode; - currencyCode: CurrencyCode; - - items: CustomerInvoiceItems; - - paymentMethod: Maybe; - - discountPercentage: Percentage; -} - -export abstract class CustomerInvoiceBase< - TProps extends ICustomerInvoiceBaseProps, -> extends AggregateRoot { - protected constructor(props: TProps, id?: UniqueID) { - super(props, id); - } - - public get companyId(): UniqueID { - return this.props.companyId; - } - - public get invoiceNumber(): InvoiceNumber { - return this.props.invoiceNumber; - } - - public get invoiceDate(): UtcDate { - return this.props.invoiceDate; - } - - public get currencyCode(): CurrencyCode { - return this.props.currencyCode; - } - - public get languageCode(): LanguageCode { - return this.props.languageCode; - } - - public get recipient(): Maybe { - return this.props.recipient; - } -} diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-persistence-mappers.di.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-persistence-mappers.di.ts new file mode 100644 index 00000000..5f8f7fa2 --- /dev/null +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-persistence-mappers.di.ts @@ -0,0 +1,28 @@ +import type { ICatalogs } from "@erp/core/api"; + +import { + SequelizeIssuedInvoiceDomainMapper, + SequelizeIssuedInvoiceSummaryMapper, +} from "../persistence"; + +export interface IIssuedInvoicePersistenceMappers { + domainMapper: SequelizeIssuedInvoiceDomainMapper; + summaryMapper: SequelizeIssuedInvoiceSummaryMapper; +} + +export const buildIssuedInvoicePersistenceMappers = ( + catalogs: ICatalogs +): IIssuedInvoicePersistenceMappers => { + const { taxCatalog } = catalogs; + + // Mappers para el repositorio + const domainMapper = new SequelizeIssuedInvoiceDomainMapper({ + taxCatalog, + }); + const summaryMapper = new SequelizeIssuedInvoiceSummaryMapper(); + + return { + domainMapper, + summaryMapper, + }; +}; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-repositories.di.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-repositories.di.ts index 34575b78..3ed35a26 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-repositories.di.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoice-repositories.di.ts @@ -1,19 +1,14 @@ -import { SpainTaxCatalogProvider } from "@erp/core"; import type { Sequelize } from "sequelize"; -import { - IssuedInvoiceRepository, - SequelizeIssuedInvoiceDomainMapper, - SequelizeIssuedInvoiceListMapper, -} from "../persistence"; +import { IssuedInvoiceRepository } from "../persistence"; -export const buildIssuedInvoiceRepository = (database: Sequelize) => { - const taxCatalog = SpainTaxCatalogProvider(); +import type { IIssuedInvoicePersistenceMappers } from "./issued-invoice-persistence-mappers.di"; - const domainMapper = new SequelizeIssuedInvoiceDomainMapper({ - taxCatalog, - }); - const listMapper = new SequelizeIssuedInvoiceListMapper(); +export const buildIssuedInvoiceRepository = (params: { + database: Sequelize; + mappers: IIssuedInvoicePersistenceMappers; +}) => { + const { database, mappers } = params; - return new IssuedInvoiceRepository(domainMapper, listMapper, database); + return new IssuedInvoiceRepository(mappers.domainMapper, mappers.summaryMapper, database); }; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoices.di.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoices.di.ts index 79c8be4c..3700cbad 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoices.di.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/di/issued-invoices.di.ts @@ -1,4 +1,4 @@ -import { type ModuleParams, buildTransactionManager } from "@erp/core/api"; +import { type ModuleParams, buildCatalogs, buildTransactionManager } from "@erp/core/api"; import { type GetIssuedInvoiceByIdUseCase, @@ -12,6 +12,7 @@ import { } from "../../../application/issued-invoices"; import { buildIssuedInvoiceDocumentService } from "./issued-invoice-documents.di"; +import { buildIssuedInvoicePersistenceMappers } from "./issued-invoice-persistence-mappers.di"; import { buildIssuedInvoiceRepository } from "./issued-invoice-repositories.di"; export type IssuedInvoicesInternalDeps = { @@ -27,7 +28,10 @@ export function buildIssuedInvoicesDependencies(params: ModuleParams): IssuedInv // Infrastructure const transactionManager = buildTransactionManager(database); - const repository = buildIssuedInvoiceRepository(database); + const catalogs = buildCatalogs(); + const persistenceMappers = buildIssuedInvoicePersistenceMappers(catalogs); + + const repository = buildIssuedInvoiceRepository({ database, mappers: persistenceMappers }); // Application helpers const finder = buildIssuedInvoiceFinder(repository); @@ -40,7 +44,7 @@ export function buildIssuedInvoicesDependencies(params: ModuleParams): IssuedInv listIssuedInvoices: () => buildListIssuedInvoicesUseCase({ finder, - itemSnapshotBuilder: snapshotBuilders.list, + summarySnapshotBuilder: snapshotBuilders.list, transactionManager, }), diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-domain.mapper.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-domain.mapper.ts index d41ed268..8312e874 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-domain.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-domain.mapper.ts @@ -1,4 +1,4 @@ -import { type MapperParamsType, SequelizeDomainMapper } from "@erp/core/api"; +import { DiscountPercentage, type MapperParamsType, SequelizeDomainMapper } from "@erp/core/api"; import { CurrencyCode, LanguageCode, @@ -13,9 +13,7 @@ import { } from "@repo/rdx-ddd"; import { Maybe, Result, isNullishOrEmpty } from "@repo/rdx-utils"; -import type { IIssuedInvoiceDomainMapper } from "../../../../../../application"; import { - DiscountPercentage, type IIssuedInvoiceProps, InvoiceAmount, InvoiceNumber, @@ -36,14 +34,11 @@ import { SequelizeIssuedInvoiceRecipientDomainMapper } from "./sequelize-issued- import { SequelizeIssuedInvoiceTaxesDomainMapper } from "./sequelize-issued-invoice-taxes-domain.mapper"; import { SequelizeIssuedInvoiceVerifactuDomainMapper } from "./sequelize-verifactu-record-domain.mapper"; -export class SequelizeIssuedInvoiceDomainMapper - extends SequelizeDomainMapper< - CustomerInvoiceModel, - CustomerInvoiceCreationAttributes, - IssuedInvoice - > - implements IIssuedInvoiceDomainMapper -{ +export class SequelizeIssuedInvoiceDomainMapper extends SequelizeDomainMapper< + CustomerInvoiceModel, + CustomerInvoiceCreationAttributes, + IssuedInvoice +> { private _itemsMapper: SequelizeIssuedInvoiceItemDomainMapper; private _recipientMapper: SequelizeIssuedInvoiceRecipientDomainMapper; private _taxesMapper: SequelizeIssuedInvoiceTaxesDomainMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-taxes-domain.mapper.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-taxes-domain.mapper.ts index 67a8dc8a..7fc75e20 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-taxes-domain.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/domain/sequelize-issued-invoice-taxes-domain.mapper.ts @@ -1,5 +1,5 @@ import type { JsonTaxCatalogProvider } from "@erp/core"; -import { type MapperParamsType, SequelizeDomainMapper } from "@erp/core/api"; +import { type MapperParamsType, SequelizeDomainMapper, TaxPercentage } from "@erp/core/api"; import { Percentage, UniqueID, @@ -19,8 +19,6 @@ import { type IssuedInvoice, IssuedInvoiceTax, ItemAmount, - ItemDiscountPercentage, - TaxPercentage, } from "../../../../../../domain"; import type { CustomerInvoiceTaxCreationAttributes, diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/index.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/index.ts index 9b0ff906..b7726c46 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/index.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/index.ts @@ -1,2 +1,2 @@ export * from "./domain"; -export * from "./list"; +export * from "./summary"; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/index.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/index.ts deleted file mode 100644 index 1a7689db..00000000 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./sequelize-issued-invoice.list.mapper"; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/index.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/index.ts new file mode 100644 index 00000000..e5586981 --- /dev/null +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/index.ts @@ -0,0 +1 @@ +export * from "./sequelize-issued-invoice-summary.mapper"; diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice-recipient.list.mapper.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-recipient-summary.mapper.ts similarity index 99% rename from modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice-recipient.list.mapper.ts rename to modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-recipient-summary.mapper.ts index ade5b2f3..07f3b567 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice-recipient.list.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-recipient-summary.mapper.ts @@ -22,7 +22,7 @@ export class SequelizeIssuedInvoiceRecipientListMapper extends SequelizeQueryMap CustomerInvoiceModel, InvoiceRecipient > { - public mapToDTO( + public mapToReadModel( raw: CustomerInvoiceModel, params?: MapperParamsType ): Result { diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice.list.mapper.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-summary.mapper.ts similarity index 89% rename from modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice.list.mapper.ts rename to modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-summary.mapper.ts index ac8e2856..be6877bb 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-issued-invoice.list.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-issued-invoice-summary.mapper.ts @@ -11,10 +11,7 @@ import { } from "@repo/rdx-ddd"; import { Maybe, Result } from "@repo/rdx-utils"; -import type { - IIssuedInvoiceSummaryMapper, - IssuedInvoiceSummary, -} from "../../../../../../application"; +import type { IssuedInvoiceSummary } from "../../../../../../application"; import { InvoiceAmount, InvoiceNumber, @@ -24,20 +21,20 @@ import { } from "../../../../../../domain"; import type { CustomerInvoiceModel } from "../../../../../common"; -import { SequelizeIssuedInvoiceRecipientListMapper } from "./sequelize-issued-invoice-recipient.list.mapper"; -import { SequelizeVerifactuRecordListMapper } from "./sequelize-verifactu-record.list.mapper"; +import { SequelizeIssuedInvoiceRecipientListMapper } from "./sequelize-issued-invoice-recipient-summary.mapper"; +import { SequelizeVerifactuRecordSummaryMapper } from "./sequelize-verifactu-record-summary.mapper"; -export class SequelizeIssuedInvoiceListMapper - extends SequelizeQueryMapper - implements IIssuedInvoiceSummaryMapper -{ +export class SequelizeIssuedInvoiceSummaryMapper extends SequelizeQueryMapper< + CustomerInvoiceModel, + IssuedInvoiceSummary +> { private _recipientMapper: SequelizeIssuedInvoiceRecipientListMapper; - private _verifactuMapper: SequelizeVerifactuRecordListMapper; + private _verifactuMapper: SequelizeVerifactuRecordSummaryMapper; constructor() { super(); this._recipientMapper = new SequelizeIssuedInvoiceRecipientListMapper(); - this._verifactuMapper = new SequelizeVerifactuRecordListMapper(); + this._verifactuMapper = new SequelizeVerifactuRecordSummaryMapper(); } public mapToReadModel( @@ -50,7 +47,7 @@ export class SequelizeIssuedInvoiceListMapper const attributes = this._mapAttributesToReadModel(raw, { errors, ...params }); // 2) Recipient (snapshot en la factura o include) - const recipientResult = this._recipientMapper.mapToDTO(raw, { + const recipientResult = this._recipientMapper.mapToReadModel(raw, { errors, attributes, ...params, @@ -66,7 +63,10 @@ export class SequelizeIssuedInvoiceListMapper // 4) Verifactu record let verifactu: Maybe = Maybe.none(); if (raw.verifactu) { - const verifactuResult = this._verifactuMapper.mapToDTO(raw.verifactu, { errors, ...params }); + const verifactuResult = this._verifactuMapper.mapToReadModel(raw.verifactu, { + errors, + ...params, + }); if (verifactuResult.isFailure) { errors.push({ diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-verifactu-record.list.mapper.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-verifactu-record-summary.mapper.ts similarity index 94% rename from modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-verifactu-record.list.mapper.ts rename to modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-verifactu-record-summary.mapper.ts index e0e492a5..aa9f7bdc 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/list/sequelize-verifactu-record.list.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/mappers/summary/sequelize-verifactu-record-summary.mapper.ts @@ -12,11 +12,11 @@ import { Result } from "@repo/rdx-utils"; import { VerifactuRecord, VerifactuRecordEstado } from "../../../../../../domain"; import type { VerifactuRecordModel } from "../../../../../common"; -export class SequelizeVerifactuRecordListMapper extends SequelizeQueryMapper< +export class SequelizeVerifactuRecordSummaryMapper extends SequelizeQueryMapper< VerifactuRecordModel, VerifactuRecord > { - public mapToDTO( + public mapToReadModel( raw: VerifactuRecordModel, params?: MapperParamsType ): Result { diff --git a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/repositories/issued-invoice.repository.ts b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/repositories/issued-invoice.repository.ts index 41875bf8..f7d223bf 100644 --- a/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/repositories/issued-invoice.repository.ts +++ b/modules/customer-invoices/src/api/infrastructure/issued-invoices/persistence/sequelize/repositories/issued-invoice.repository.ts @@ -14,7 +14,7 @@ import { } from "../../../../common"; import type { SequelizeIssuedInvoiceDomainMapper, - SequelizeIssuedInvoiceListMapper, + SequelizeIssuedInvoiceSummaryMapper, } from "../mappers"; export class IssuedInvoiceRepository @@ -23,7 +23,7 @@ export class IssuedInvoiceRepository { constructor( private readonly domainMapper: SequelizeIssuedInvoiceDomainMapper, - private readonly listMapper: SequelizeIssuedInvoiceListMapper, + private readonly summaryMapper: SequelizeIssuedInvoiceSummaryMapper, database: Sequelize ) { super({ database }); @@ -216,8 +216,8 @@ export class IssuedInvoiceRepository const { CustomerModel } = this.database.models; try { - const converter = new CriteriaToSequelizeConverter(); - const query = converter.convert(criteria, { + const criteriaConverter = new CriteriaToSequelizeConverter(); + const query = criteriaConverter.convert(criteria, { searchableFields: ["invoice_number", "reference", "description"], mappings: { reference: "CustomerInvoiceModel.reference", @@ -301,7 +301,7 @@ export class IssuedInvoiceRepository }), ]); - return this.listMapper.mapToReadModelCollection(rows, count); + return this.summaryMapper.mapToReadModelCollection(rows, count); } catch (err: unknown) { return Result.fail(translateSequelizeError(err)); } diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/di/proforma-persistence-mappers.di.ts b/modules/customer-invoices/src/api/infrastructure/proformas/di/proforma-persistence-mappers.di.ts index 3bda0abd..4780ea67 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/di/proforma-persistence-mappers.di.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/di/proforma-persistence-mappers.di.ts @@ -1,14 +1,11 @@ -import { - CreateProformaInputMapper, - type ICatalogs, - type IProformaDomainMapper, - type IProformaListMapper, -} from "../../../application"; -import { SequelizeProformaDomainMapper, SequelizeProformaListMapper } from "../persistence"; +import type { ICatalogs } from "@erp/core/api"; + +import { CreateProformaInputMapper } from "../../../application"; +import { SequelizeProformaDomainMapper, SequelizeProformaSummaryMapper } from "../persistence"; export interface IProformaPersistenceMappers { - domainMapper: IProformaDomainMapper; - listMapper: IProformaListMapper; + domainMapper: SequelizeProformaDomainMapper; + listMapper: SequelizeProformaSummaryMapper; createMapper: CreateProformaInputMapper; } @@ -22,7 +19,7 @@ export const buildProformaPersistenceMappers = ( const domainMapper = new SequelizeProformaDomainMapper({ taxCatalog, }); - const listMapper = new SequelizeProformaListMapper(); + const listMapper = new SequelizeProformaSummaryMapper(); // Mappers el DTO a las props validadas (CustomerProps) y luego construir agregado const createMapper = new CreateProformaInputMapper({ taxCatalog }); diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/di/proformas.di.ts b/modules/customer-invoices/src/api/infrastructure/proformas/di/proformas.di.ts index 50b0fa2c..b5f1528e 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/di/proformas.di.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/di/proformas.di.ts @@ -60,7 +60,7 @@ export function buildProformasDependencies(params: ModuleParams): ProformasInter listProformas: () => buildListProformasUseCase({ finder, - itemSnapshotBuilder: snapshotBuilders.list, + summarySnapshotBuilder: snapshotBuilders.summary, transactionManager, }), @@ -90,76 +90,3 @@ export function buildProformasDependencies(params: ModuleParams): ProformasInter }, }; } - -/*const mapperRegistry = new InMemoryMapperRegistry(); -mapperRegistry - .registerDomainMapper( - { resource: "customer-invoice" }, - new CustomerInvoiceDomainMapper({ taxCatalog: catalogs.taxes }) - ) - .registerQueryMappers([ - { - key: { resource: "customer-invoice", query: "LIST" }, - mapper: new CustomerInvoiceListMapper(), - }, - ]); - -// Repository & Services -const numberGenerator = new SequelizeInvoiceNumberGenerator(); - - -const appService = new CustomerInvoiceApplicationService(repository, numberGenerator); - -// Presenter Registry -const presenterRegistry = new InMemoryPresenterRegistry(); -presenterRegistry.registerPresenters([ - // FULL - { - key: { resource: "proforma-items", projection: "FULL" }, - presenter: new ProformaItemsFullPresenter(presenterRegistry), - }, - { - key: { resource: "proforma-recipient", projection: "FULL" }, - presenter: new ProformaRecipientFullPresenter(presenterRegistry), - }, - { - key: { resource: "proforma", projection: "FULL" }, - presenter: new ProformaFullPresenter(presenterRegistry), - }, - - // LIST - { - key: { resource: "proforma", projection: "LIST" }, - presenter: new ProformaListPresenter(presenterRegistry), - }, - - // REPORT - { - key: { resource: "proforma", projection: "REPORT" }, - presenter: new ProformaReportPresenter(presenterRegistry), - }, - { - key: { resource: "proforma-taxes", projection: "REPORT" }, - presenter: new ProformaTaxesReportPresenter(presenterRegistry), - }, - { - key: { resource: "proforma-items", projection: "REPORT" }, - presenter: new ProformaItemsReportPresenter(presenterRegistry), - }, -]); - -const useCases: ProformasDeps["useCases"] = { - // Proformas - list_proformas: () => new ListProformasUseCase(appService, transactionManager, presenterRegistry), - get_proforma: () => new GetProformaUseCase(appService, transactionManager, presenterRegistry), - create_proforma: () => - new CreateProformaUseCase(appService, transactionManager, presenterRegistry, catalogs.taxes), - update_proforma: () => - new UpdateProformaUseCase(appService, transactionManager, presenterRegistry), - delete_proforma: () => new DeleteProformaUseCase(appService, transactionManager), - report_proforma: () => - new ReportProformaUseCase(appService, transactionManager, presenterRegistry), - issue_proforma: () => new IssueProformaUseCase(appService, transactionManager, presenterRegistry), - changeStatus_proforma: () => new ChangeStatusProformaUseCase(appService, transactionManager), - - */ diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts index 8dca65e6..1d0024e4 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/domain/sequelize-proforma-domain.mapper.ts @@ -13,7 +13,6 @@ import { } from "@repo/rdx-ddd"; import { Maybe, Result, isNullishOrEmpty } from "@repo/rdx-utils"; -import type { IProformaDomainMapper } from "../../../../../../application"; import { type IProformaProps, InvoiceNumber, @@ -32,10 +31,11 @@ import { SequelizeProformaItemDomainMapper } from "./sequelize-proforma-item-dom import { SequelizeProformaRecipientDomainMapper } from "./sequelize-proforma-recipient-domain.mapper"; import { SequelizeProformaTaxesDomainMapper } from "./sequelize-proforma-taxes-domain.mapper"; -export class SequelizeProformaDomainMapper - extends SequelizeDomainMapper - implements IProformaDomainMapper -{ +export class SequelizeProformaDomainMapper extends SequelizeDomainMapper< + CustomerInvoiceModel, + CustomerInvoiceCreationAttributes, + Proforma +> { private _itemsMapper: SequelizeProformaItemDomainMapper; private _recipientMapper: SequelizeProformaRecipientDomainMapper; private _taxesMapper: SequelizeProformaTaxesDomainMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/index.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/index.ts index 9b0ff906..b7726c46 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/index.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/index.ts @@ -1,2 +1,2 @@ export * from "./domain"; -export * from "./list"; +export * from "./summary"; diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/index.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/index.ts deleted file mode 100644 index cf9c3925..00000000 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./sequelize-proforma.list.mapper"; diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/index.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/index.ts new file mode 100644 index 00000000..7ef0da1b --- /dev/null +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/index.ts @@ -0,0 +1 @@ +export * from "./sequelize-proforma-summary.mapper"; diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma-recipient.list.mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-recipient-summary.mapper.ts similarity index 85% rename from modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma-recipient.list.mapper.ts rename to modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-recipient-summary.mapper.ts index 25980b91..305e721e 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma-recipient.list.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-recipient-summary.mapper.ts @@ -1,8 +1,4 @@ -import { - type IQueryMapperWithBulk, - type MapperParamsType, - SequelizeQueryMapper, -} from "@erp/core/api"; +import { type MapperParamsType, SequelizeQueryMapper } from "@erp/core/api"; import { City, Country, @@ -18,18 +14,15 @@ import { } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import type { ProformaListDTO } from "../../../../../../application"; +import type { ProformaSummary } from "../../../../../../application"; import { InvoiceRecipient } from "../../../../../../domain"; import type { CustomerInvoiceModel } from "../../../../../common"; -interface IInvoiceRecipientListMapper - extends IQueryMapperWithBulk {} - -export class SequelizeInvoiceRecipientListMapper - extends SequelizeQueryMapper - implements IInvoiceRecipientListMapper -{ - public mapToDTO( +export class SequelizeInvoiceRecipientSummaryMapper extends SequelizeQueryMapper< + CustomerInvoiceModel, + InvoiceRecipient +> { + public mapToReadModel( raw: CustomerInvoiceModel, params?: MapperParamsType ): Result { @@ -39,7 +32,7 @@ export class SequelizeInvoiceRecipientListMapper const { errors, attributes } = params as { errors: ValidationErrorDetail[]; - attributes: Partial; + attributes: Partial; }; const { isProforma } = attributes; diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma.list.mapper.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-summary.mapper.ts similarity index 90% rename from modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma.list.mapper.ts rename to modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-summary.mapper.ts index ba7a6814..b13f38fc 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/list/sequelize-proforma.list.mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/mappers/summary/sequelize-proforma-summary.mapper.ts @@ -11,7 +11,7 @@ import { } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import type { IProformaListMapper, ProformaListDTO } from "../../../../../../application"; +import type { ProformaSummary } from "../../../../../../application"; import { InvoiceAmount, InvoiceNumber, @@ -20,30 +20,30 @@ import { } from "../../../../../../domain"; import type { CustomerInvoiceModel } from "../../../../../common"; -import { SequelizeInvoiceRecipientListMapper } from "./sequelize-proforma-recipient.list.mapper"; +import { SequelizeInvoiceRecipientSummaryMapper } from "./sequelize-proforma-recipient-summary.mapper"; -export class SequelizeProformaListMapper - extends SequelizeQueryMapper - implements IProformaListMapper -{ - private _recipientMapper: SequelizeInvoiceRecipientListMapper; +export class SequelizeProformaSummaryMapper extends SequelizeQueryMapper< + CustomerInvoiceModel, + ProformaSummary +> { + private _recipientMapper: SequelizeInvoiceRecipientSummaryMapper; constructor() { super(); - this._recipientMapper = new SequelizeInvoiceRecipientListMapper(); + this._recipientMapper = new SequelizeInvoiceRecipientSummaryMapper(); } - public mapToDTO( + public mapToReadModel( raw: CustomerInvoiceModel, params?: MapperParamsType - ): Result { + ): Result { const errors: ValidationErrorDetail[] = []; // 1) Valores escalares (atributos generales) const attributes = this.mapAttributesToDTO(raw, { errors, ...params }); // 2) Recipient (snapshot en la factura o include) - const recipientResult = this._recipientMapper.mapToDTO(raw, { + const recipientResult = this._recipientMapper.mapToReadModel(raw, { errors, attributes, ...params, diff --git a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts index df19136c..17e5e6c4 100644 --- a/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts +++ b/modules/customer-invoices/src/api/infrastructure/proformas/persistence/sequelize/repositories/proforma.repository.ts @@ -9,26 +9,22 @@ import type { UniqueID } from "@repo/rdx-ddd"; import { type Collection, Result } from "@repo/rdx-utils"; import type { FindOptions, InferAttributes, OrderItem, Sequelize, Transaction } from "sequelize"; -import type { - IProformaDomainMapper, - IProformaListMapper, - IProformaRepository, - ProformaListDTO, -} from "../../../../../application"; +import type { IProformaRepository, ProformaSummary } from "../../../../../application"; import type { InvoiceStatus, Proforma } from "../../../../../domain"; import { CustomerInvoiceItemModel, CustomerInvoiceModel, CustomerInvoiceTaxModel, } from "../../../../common"; +import type { SequelizeProformaDomainMapper, SequelizeProformaSummaryMapper } from "../mappers"; export class ProformaRepository extends SequelizeRepository implements IProformaRepository { constructor( - private readonly domainMapper: IProformaDomainMapper, - private readonly listMapper: IProformaListMapper, + private readonly domainMapper: SequelizeProformaDomainMapper, + private readonly summaryMapper: SequelizeProformaSummaryMapper, database: Sequelize ) { super({ database }); @@ -339,12 +335,12 @@ export class ProformaRepository criteria: Criteria, transaction: Transaction, options: FindOptions> = {} - ): Promise, Error>> { + ): Promise, Error>> { const { CustomerModel } = this.database.models; try { - const converter = new CriteriaToSequelizeConverter(); - const query = converter.convert(criteria, { + const criteriaConverter = new CriteriaToSequelizeConverter(); + const query = criteriaConverter.convert(criteria, { searchableFields: ["invoice_number", "reference", "description"], mappings: { reference: "CustomerInvoiceModel.reference", @@ -424,7 +420,7 @@ export class ProformaRepository }), ]); - return this.listMapper.mapToReadModelCollection(rows, count); + return this.summaryMapper.mapToReadModelCollection(rows, count); } catch (err: unknown) { return Result.fail(translateSequelizeError(err)); } diff --git a/modules/customers/src/api/application/di/customer-finder.di.ts b/modules/customers/src/api/application/di/customer-finder.di.ts index e673d320..c9b5f1c2 100644 --- a/modules/customers/src/api/application/di/customer-finder.di.ts +++ b/modules/customers/src/api/application/di/customer-finder.di.ts @@ -1,6 +1,6 @@ -import type { IProformaRepository } from "../repositories"; -import { type IProformaFinder, ProformaFinder } from "../services"; +import type { ICustomerRepository } from "../repositories"; +import { CustomerFinder, type ICustomerFinder } from "../services"; -export function buildProformaFinder(repository: IProformaRepository): IProformaFinder { - return new ProformaFinder(repository); +export function buildCustomerFinder(repository: ICustomerRepository): ICustomerFinder { + return new CustomerFinder(repository); } diff --git a/modules/customers/src/api/application/di/customer-snapshot-builders.di.ts b/modules/customers/src/api/application/di/customer-snapshot-builders.di.ts index aa7e7b05..db028b82 100644 --- a/modules/customers/src/api/application/di/customer-snapshot-builders.di.ts +++ b/modules/customers/src/api/application/di/customer-snapshot-builders.di.ts @@ -1,18 +1,9 @@ // application/issued-invoices/di/snapshot-builders.di.ts -import { - CustomerFullSnapshotBuilder, - CustomerItemReportSnapshotBuilder, - CustomerItemsFullSnapshotBuilder, - CustomerListItemSnapshotBuilder, - CustomerRecipientFullSnapshotBuilder, - CustomerReportSnapshotBuilder, - CustomerTaxReportSnapshotBuilder, - CustomerTaxesFullSnapshotBuilder, -} from "../snapshot-builders"; +import { CustomerSummarySnapshotBuilder } from "../snapshot-builders"; export function buildCustomerSnapshotBuilders() { - const itemsBuilder = new CustomerItemsFullSnapshotBuilder(); + /*const itemsBuilder = new CustomerItemsFullSnapshotBuilder(); const taxesBuilder = new CustomerTaxesFullSnapshotBuilder(); @@ -22,20 +13,20 @@ export function buildCustomerSnapshotBuilders() { itemsBuilder, recipientBuilder, taxesBuilder - ); + );*/ - const listSnapshotBuilder = new CustomerListItemSnapshotBuilder(); + const summarySnapshotBuilder = new CustomerSummarySnapshotBuilder(); - const itemsReportBuilder = new CustomerItemReportSnapshotBuilder(); + /*const itemsReportBuilder = new CustomerItemReportSnapshotBuilder(); const taxesReportBuilder = new CustomerTaxReportSnapshotBuilder(); const reportSnapshotBuilder = new CustomerReportSnapshotBuilder( itemsReportBuilder, taxesReportBuilder - ); + );*/ return { - full: fullSnapshotBuilder, - list: listSnapshotBuilder, - report: reportSnapshotBuilder, + //full: fullSnapshotBuilder, + summary: summarySnapshotBuilder, + //report: reportSnapshotBuilder, }; } diff --git a/modules/customers/src/api/application/di/customer-use-cases.di.ts b/modules/customers/src/api/application/di/customer-use-cases.di.ts index cc300ae9..c163edb7 100644 --- a/modules/customers/src/api/application/di/customer-use-cases.di.ts +++ b/modules/customers/src/api/application/di/customer-use-cases.di.ts @@ -1,36 +1,30 @@ import type { ITransactionManager } from "@erp/core/api"; -import type { ICreateCustomerInputMapper } from "../mappers"; -import type { - ICustomerCreator, - ICustomerFinder, - CustomerDocumentGeneratorService, -} from "../services"; -import type { - ICustomerListItemSnapshotBuilder, - ICustomerReportSnapshotBuilder, -} from "../snapshot-builders"; -import type { ICustomerFullSnapshotBuilder } from "../snapshot-builders/full"; -import { GetCustomerByIdUseCase, ListCustomersUseCase, ReportCustomerUseCase } from "../use-cases"; -import { CreateCustomerUseCase } from "../use-cases/create-customer"; +import type { ICustomerFinder } from "../services"; +import type { ICustomerSummarySnapshotBuilder } from "../snapshot-builders"; +import { ListCustomersUseCase } from "../use-cases"; -export function buildGetCustomerByIdUseCase(deps: { +/*export function buildGetCustomerByIdUseCase(deps: { finder: ICustomerFinder; fullSnapshotBuilder: ICustomerFullSnapshotBuilder; transactionManager: ITransactionManager; }) { return new GetCustomerByIdUseCase(deps.finder, deps.fullSnapshotBuilder, deps.transactionManager); -} +}*/ export function buildListCustomersUseCase(deps: { finder: ICustomerFinder; - itemSnapshotBuilder: ICustomerListItemSnapshotBuilder; + summarySnapshotBuilder: ICustomerSummarySnapshotBuilder; transactionManager: ITransactionManager; }) { - return new ListCustomersUseCase(deps.finder, deps.itemSnapshotBuilder, deps.transactionManager); + return new ListCustomersUseCase( + deps.finder, + deps.summarySnapshotBuilder, + deps.transactionManager + ); } -export function buildReportCustomerUseCase(deps: { +/*export function buildReportCustomerUseCase(deps: { finder: ICustomerFinder; fullSnapshotBuilder: ICustomerFullSnapshotBuilder; reportSnapshotBuilder: ICustomerReportSnapshotBuilder; @@ -58,7 +52,7 @@ export function buildCreateCustomerUseCase(deps: { fullSnapshotBuilder: deps.fullSnapshotBuilder, transactionManager: deps.transactionManager, }); -} +}*/ /*export function buildUpdateCustomerUseCase(deps: { finder: ICustomerFinder; diff --git a/modules/customers/src/api/application/di/index.ts b/modules/customers/src/api/application/di/index.ts index 4e27b007..75d14c0c 100644 --- a/modules/customers/src/api/application/di/index.ts +++ b/modules/customers/src/api/application/di/index.ts @@ -1,5 +1,5 @@ -export * from "./customer-creator.di"; +//export * from "./customer-creator.di"; export * from "./customer-finder.di"; -export * from "./customer-input-mappers.di"; +//export * from "./customer-input-mappers.di"; export * from "./customer-snapshot-builders.di"; export * from "./customer-use-cases.di"; diff --git a/modules/customers/src/api/application/index.ts b/modules/customers/src/api/application/index.ts index b68ea0dc..21fd64a4 100644 --- a/modules/customers/src/api/application/index.ts +++ b/modules/customers/src/api/application/index.ts @@ -1,5 +1,4 @@ export * from "./di"; -export * from "./mappers"; export * from "./models"; export * from "./repositories"; export * from "./services"; diff --git a/modules/customers/src/api/application/mappers/customer-domain-mapper.interface.ts b/modules/customers/src/api/application/mappers/customer-domain-mapper.interface.ts deleted file mode 100644 index 0fe0039f..00000000 --- a/modules/customers/src/api/application/mappers/customer-domain-mapper.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { DomainMapperWithBulk } from "@erp/core/api"; - -import type { Customer } from "../../domain"; -import type { CustomerCreationAttributes, CustomerModel } from "../../infrastructure"; - -export interface ICustomerDomainMapper - extends DomainMapperWithBulk {} diff --git a/modules/customers/src/api/application/mappers/customer-summary-mapper.interface.ts b/modules/customers/src/api/application/mappers/customer-summary-mapper.interface.ts deleted file mode 100644 index 442346a7..00000000 --- a/modules/customers/src/api/application/mappers/customer-summary-mapper.interface.ts +++ /dev/null @@ -1,7 +0,0 @@ -import type { IQueryMapperWithBulk } from "@erp/core/api"; - -import type { CustomerModel } from "../../infrastructure"; -import type { CustomerSummary } from "../models"; - -export interface ICustomerSummaryMapper - extends IQueryMapperWithBulk {} diff --git a/modules/customers/src/api/application/mappers/index.ts b/modules/customers/src/api/application/mappers/index.ts deleted file mode 100644 index 8377a3ba..00000000 --- a/modules/customers/src/api/application/mappers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./customer-domain-mapper.interface"; -export * from "./customer-summary-mapper.interface"; diff --git a/modules/customers/src/api/application/services/customer-finder.ts b/modules/customers/src/api/application/services/customer-finder.ts index dfb4880f..6492df5b 100644 --- a/modules/customers/src/api/application/services/customer-finder.ts +++ b/modules/customers/src/api/application/services/customer-finder.ts @@ -4,7 +4,7 @@ import type { Collection, Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; import type { Customer } from "../../domain"; -import type { CustomerListDTO } from "../dtos"; +import type { CustomerSummary } from "../models"; import type { ICustomerRepository } from "../repositories"; export interface ICustomerFinder { @@ -24,7 +24,7 @@ export interface ICustomerFinder { companyId: UniqueID, criteria: Criteria, transaction?: Transaction - ): Promise, Error>>; + ): Promise, Error>>; } export class CustomerFinder implements ICustomerFinder { @@ -50,7 +50,7 @@ export class CustomerFinder implements ICustomerFinder { companyId: UniqueID, criteria: Criteria, transaction?: Transaction - ): Promise, Error>> { + ): Promise, Error>> { return this.repository.findByCriteriaInCompany(companyId, criteria, transaction); } } diff --git a/modules/customers/src/api/application/snapshot-builders/index.ts b/modules/customers/src/api/application/snapshot-builders/index.ts index 2a83d3de..3fa03b33 100644 --- a/modules/customers/src/api/application/snapshot-builders/index.ts +++ b/modules/customers/src/api/application/snapshot-builders/index.ts @@ -1,3 +1,3 @@ //export * from "./full"; -export * from "./list"; +export * from "./summary"; //export * from "./report"; diff --git a/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot-builder.ts b/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot-builder.ts deleted file mode 100644 index 376d2d54..00000000 --- a/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot-builder.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { ISnapshotBuilder } from "@erp/core/api"; - -import type { CustomerListDTO } from "../../dtos"; - -import type { ICustomerListItemSnapshot } from "./customer-list-item-snapshot.interface"; - -export interface ICustomerListItemSnapshotBuilder - extends ISnapshotBuilder {} - -export class CustomerListItemSnapshotBuilder implements ICustomerListItemSnapshotBuilder { - toOutput(customer: CustomerListDTO): ICustomerListItemSnapshot { - return {}; - } -} diff --git a/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot.interface.ts b/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot.interface.ts deleted file mode 100644 index c55a2708..00000000 --- a/modules/customers/src/api/application/snapshot-builders/list/customer-list-item-snapshot.interface.ts +++ /dev/null @@ -1 +0,0 @@ -export type ICustomerListItemSnapshot = {}; diff --git a/modules/customers/src/api/application/snapshot-builders/list/index.ts b/modules/customers/src/api/application/snapshot-builders/list/index.ts deleted file mode 100644 index 5218181e..00000000 --- a/modules/customers/src/api/application/snapshot-builders/list/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./customer-list-item-snapshot.interface"; -export * from "./customer-list-item-snapshot-builder"; diff --git a/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot-builder.ts b/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot-builder.ts new file mode 100644 index 00000000..9d78d845 --- /dev/null +++ b/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot-builder.ts @@ -0,0 +1,49 @@ +import type { ISnapshotBuilder } from "@erp/core/api"; +import { maybeToEmptyString } from "@repo/rdx-ddd"; + +import type { CustomerSummary } from "../../models"; + +import type { ICustomerSummarySnapshot } from "./customer-summary-snapshot.interface"; + +export interface ICustomerSummarySnapshotBuilder + extends ISnapshotBuilder {} + +export class CustomerSummarySnapshotBuilder implements ICustomerSummarySnapshotBuilder { + toOutput(customer: CustomerSummary): ICustomerSummarySnapshot { + const { address } = customer; + + return { + id: customer.id.toString(), + company_id: customer.companyId.toString(), + status: customer.status.toString(), + reference: maybeToEmptyString(customer.reference, (value) => value.toString()), + + is_company: String(customer.isCompany), + name: customer.name.toString(), + trade_name: maybeToEmptyString(customer.tradeName, (value) => value.toString()), + tin: maybeToEmptyString(customer.tin, (value) => value.toString()), + + street: maybeToEmptyString(address.street, (value) => value.toString()), + street2: maybeToEmptyString(address.street2, (value) => value.toString()), + city: maybeToEmptyString(address.city, (value) => value.toString()), + postal_code: maybeToEmptyString(address.postalCode, (value) => value.toString()), + province: maybeToEmptyString(address.province, (value) => value.toString()), + country: maybeToEmptyString(address.country, (value) => value.toString()), + + email_primary: maybeToEmptyString(customer.emailPrimary, (value) => value.toString()), + email_secondary: maybeToEmptyString(customer.emailSecondary, (value) => value.toString()), + + phone_primary: maybeToEmptyString(customer.phonePrimary, (value) => value.toString()), + phone_secondary: maybeToEmptyString(customer.phoneSecondary, (value) => value.toString()), + + mobile_primary: maybeToEmptyString(customer.mobilePrimary, (value) => value.toString()), + mobile_secondary: maybeToEmptyString(customer.mobileSecondary, (value) => value.toString()), + + fax: maybeToEmptyString(customer.fax, (value) => value.toString()), + website: maybeToEmptyString(customer.website, (value) => value.toString()), + + language_code: customer.languageCode.code, + currency_code: customer.currencyCode.code, + }; + } +} diff --git a/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot.interface.ts b/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot.interface.ts new file mode 100644 index 00000000..654e21ec --- /dev/null +++ b/modules/customers/src/api/application/snapshot-builders/summary/customer-summary-snapshot.interface.ts @@ -0,0 +1,35 @@ +export type ICustomerSummarySnapshot = { + id: string; + company_id: string; + status: string; + reference: string; + + is_company: string; + name: string; + trade_name: string; + tin: string; + + street: string; + street2: string; + city: string; + postal_code: string; + province: string; + country: string; + + email_primary: string; + email_secondary: string; + + phone_primary: string; + phone_secondary: string; + + mobile_primary: string; + mobile_secondary: string; + + fax: string; + website: string; + + language_code: string; + currency_code: string; + + metadata?: Record; +}; diff --git a/modules/customers/src/api/application/snapshot-builders/summary/index.ts b/modules/customers/src/api/application/snapshot-builders/summary/index.ts new file mode 100644 index 00000000..1b83be43 --- /dev/null +++ b/modules/customers/src/api/application/snapshot-builders/summary/index.ts @@ -0,0 +1,2 @@ +export * from "./customer-summary-snapshot.interface"; +export * from "./customer-summary-snapshot-builder"; diff --git a/modules/customers/src/api/application/use-cases/list-customers.use-case.ts b/modules/customers/src/api/application/use-cases/list-customers.use-case.ts index c93fe04f..aba9f99a 100644 --- a/modules/customers/src/api/application/use-cases/list-customers.use-case.ts +++ b/modules/customers/src/api/application/use-cases/list-customers.use-case.ts @@ -4,9 +4,8 @@ import type { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; -import type { ListCustomersResponseDTO } from "../../../common/dto"; import type { ICustomerFinder } from "../services"; -import type { ICustomerListItemSnapshotBuilder } from "../snapshot-builders/list"; +import type { ICustomerSummarySnapshotBuilder } from "../snapshot-builders/summary"; type ListCustomersUseCaseInput = { companyId: UniqueID; @@ -16,13 +15,11 @@ type ListCustomersUseCaseInput = { export class ListCustomersUseCase { constructor( private readonly finder: ICustomerFinder, - private readonly listItemSnapshotBuilder: ICustomerListItemSnapshotBuilder, + private readonly summarySnapshotBuilder: ICustomerSummarySnapshotBuilder, private readonly transactionManager: ITransactionManager ) {} - public execute( - params: ListCustomersUseCaseInput - ): Promise> { + public execute(params: ListCustomersUseCaseInput) { const { criteria, companyId } = params; return this.transactionManager.complete(async (transaction: Transaction) => { @@ -36,7 +33,7 @@ export class ListCustomersUseCase { const customers = result.data; const totalCustomers = customers.total(); - const items = customers.map((item) => this.listItemSnapshotBuilder.toOutput(item)); + const items = customers.map((item) => this.summarySnapshotBuilder.toOutput(item)); const snapshot = { page: criteria.pageNumber, diff --git a/modules/customers/src/api/index.ts b/modules/customers/src/api/index.ts index 9055941f..e3087dad 100644 --- a/modules/customers/src/api/index.ts +++ b/modules/customers/src/api/index.ts @@ -1,6 +1,7 @@ import type { IModuleServer } from "@erp/core/api"; import { customersRouter, models } from "./infrastructure"; +import { buildCustomersDependencies, buildCustomerServices, CustomersInternalDeps } from "./infrastructure/di"; export * from "./infrastructure/sequelize"; @@ -19,12 +20,11 @@ export const customersAPIModule: IModuleServer = { async setup(params) { const { env: ENV, app, database, baseRoutePath: API_BASE_PATH, logger } = params; - // 1) Dominio interno - //const customerInternalDeps = buildCustomerDependencies(params); + const customerInternalDeps = buildCustomersDependencies(params); // 2) Servicios públicos (Application Services) - //const customerServices = buildCustomerServices(customerInternalDeps); + const customerServices = buildCustomerServices(customerInternalDeps); logger.info("🚀 Customers module dependencies registered", { label: this.name, @@ -35,14 +35,10 @@ export const customersAPIModule: IModuleServer = { models, // Servicios expuestos a otros módulos - services: { - //customers: customerServices, - }, - + services: customerServices, + // Implementación privada del módulo - internal: { - //customers: customerInternalDeps, - }, + internal:customerInternalDeps, }; }, @@ -57,7 +53,7 @@ export const customersAPIModule: IModuleServer = { const { app, baseRoutePath, logger, getInternal } = params; // Recuperamos el dominio interno del módulo - const customersInternalDeps = getInternal("customers", "customers"); + const customersInternalDeps = getInternal("customers"); // Registro de rutas HTTP customersRouter(params, customersInternalDeps); diff --git a/modules/customers/src/api/infrastructure/dependencies.ts b/modules/customers/src/api/infrastructure/dependencies.ts deleted file mode 100644 index 99d6016d..00000000 --- a/modules/customers/src/api/infrastructure/dependencies.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { IMapperRegistry, IPresenterRegistry, ModuleParams } from "@erp/core/api"; -import { - InMemoryMapperRegistry, - InMemoryPresenterRegistry, - SequelizeTransactionManager, -} from "@erp/core/api"; - -import { - CreateCustomerUseCase, - GetCustomerUseCase, - ListCustomersUseCase, - UpdateCustomerUseCase, -} from "../application"; -import { CustomerApplicationService } from "../application/customer-application.service"; -import { CustomerFullPresenter, ListCustomersPresenter } from "../application/presenters"; - -import { CustomerDomainMapper, CustomerSummaryMapper } from "./mappers"; -import { CustomerRepository } from "./sequelize"; - -export type CustomerDeps = { - transactionManager: SequelizeTransactionManager; - mapperRegistry: IMapperRegistry; - presenterRegistry: IPresenterRegistry; - repo: CustomerRepository; - service: CustomerApplicationService; - build: { - list: () => ListCustomersUseCase; - get: () => GetCustomerUseCase; - create: () => CreateCustomerUseCase; - update: () => UpdateCustomerUseCase; - //delete: () => DeleteCustomerUseCase; - }; -}; - -export function buildCustomerDependencies(params: ModuleParams): CustomerDeps { - const { database } = params; - const transactionManager = new SequelizeTransactionManager(database); - - // Mapper Registry - const mapperRegistry = new InMemoryMapperRegistry(); - mapperRegistry - .registerDomainMapper({ resource: "customer" }, new CustomerDomainMapper()) - .registerQueryMapper({ resource: "customer", query: "LIST" }, new CustomerSummaryMapper()); - - // Repository & Services - const repo = new CustomerRepository({ mapperRegistry, database }); - const service = new CustomerApplicationService(repo); - - // Presenter Registry - const presenterRegistry = new InMemoryPresenterRegistry(); - presenterRegistry.registerPresenters([ - { - key: { resource: "customer", projection: "FULL" }, - presenter: new CustomerFullPresenter(presenterRegistry), - }, - { - key: { resource: "customer", projection: "LIST" }, - presenter: new ListCustomersPresenter(presenterRegistry), - }, - ]); - - return { - transactionManager, - repo, - mapperRegistry, - presenterRegistry, - service, - build: { - list: () => new ListCustomersUseCase(service, transactionManager, presenterRegistry), - get: () => new GetCustomerUseCase(service, transactionManager, presenterRegistry), - create: () => new CreateCustomerUseCase(service, transactionManager, presenterRegistry), - update: () => new UpdateCustomerUseCase(service, transactionManager, presenterRegistry), - //delete: () => new DeleteCustomerUseCase(_service!, transactionManager!), - }, - }; -} diff --git a/modules/customers/src/api/infrastructure/di/customer-persistence-mappers.di.ts b/modules/customers/src/api/infrastructure/di/customer-persistence-mappers.di.ts index 92400af5..8b1f658c 100644 --- a/modules/customers/src/api/infrastructure/di/customer-persistence-mappers.di.ts +++ b/modules/customers/src/api/infrastructure/di/customer-persistence-mappers.di.ts @@ -1,36 +1,24 @@ -import { - CreateCustomerInputMapper, - type ICatalogs, - type ICustomerDomainMapper, - type ICustomerListMapper, -} from "../../../application"; -import { SequelizeCustomerDomainMapper, SequelizeCustomerListMapper } from "../persistence"; +import { SequelizeCustomerDomainMapper, SequelizeCustomerSummaryMapper } from "../mappers"; export interface ICustomerPersistenceMappers { - domainMapper: ICustomerDomainMapper; - listMapper: ICustomerListMapper; + domainMapper: SequelizeCustomerDomainMapper; + summaryMapper: SequelizeCustomerSummaryMapper; - createMapper: CreateCustomerInputMapper; + //createMapper: CreateCustomerInputMapper; } -export const buildCustomerPersistenceMappers = ( - catalogs: ICatalogs -): ICustomerPersistenceMappers => { - const { taxCatalog } = catalogs; - +export const buildCustomerPersistenceMappers = (): ICustomerPersistenceMappers => { // Mappers para el repositorio - const domainMapper = new SequelizeCustomerDomainMapper({ - taxCatalog, - }); - const listMapper = new SequelizeCustomerListMapper(); + const domainMapper = new SequelizeCustomerDomainMapper(); + const summaryMapper = new SequelizeCustomerSummaryMapper(); // Mappers el DTO a las props validadas (CustomerProps) y luego construir agregado - const createMapper = new CreateCustomerInputMapper({ taxCatalog }); + //const createMapper = new CreateCustomerInputMapper(); return { domainMapper, - listMapper, + summaryMapper, - createMapper, + //createMapper, }; }; diff --git a/modules/customers/src/api/infrastructure/di/customer-public-services.ts b/modules/customers/src/api/infrastructure/di/customer-public-services.ts new file mode 100644 index 00000000..7cb843fa --- /dev/null +++ b/modules/customers/src/api/infrastructure/di/customer-public-services.ts @@ -0,0 +1,24 @@ +import type { CustomersInternalDeps } from "./customers.di"; + +export type CustomersServicesDeps = { + services: { + listCustomers: (filters: unknown, context: unknown) => null; + getCustomerById: (id: unknown, context: unknown) => null; + generateCustomerReport: (id: unknown, options: unknown, context: unknown) => null; + }; +}; + +export function buildCustomerServices(deps: CustomersInternalDeps): CustomersServicesDeps { + return { + services: { + listCustomers: (filters, context) => null, + //internal.useCases.listCustomers().execute(filters, context), + + getCustomerById: (id, context) => null, + //internal.useCases.getCustomerById().execute(id, context), + + generateCustomerReport: (id, options, context) => null, + //internal.useCases.reportCustomer().execute(id, options, context), + }, + }; +} diff --git a/modules/customers/src/api/infrastructure/di/customer-repositories.di.ts b/modules/customers/src/api/infrastructure/di/customer-repositories.di.ts index 59ef66cc..e1c893ce 100644 --- a/modules/customers/src/api/infrastructure/di/customer-repositories.di.ts +++ b/modules/customers/src/api/infrastructure/di/customer-repositories.di.ts @@ -1,6 +1,6 @@ import type { Sequelize } from "sequelize"; -import { CustomerRepository } from "../persistence"; +import { CustomerRepository } from "../sequelize"; import type { ICustomerPersistenceMappers } from "./customer-persistence-mappers.di"; @@ -10,5 +10,5 @@ export const buildCustomerRepository = (params: { }) => { const { database, mappers } = params; - return new CustomerRepository(mappers.domainMapper, mappers.listMapper, database); + return new CustomerRepository(mappers.domainMapper, mappers.summaryMapper, database); }; diff --git a/modules/customers/src/api/infrastructure/di/customers.di.ts b/modules/customers/src/api/infrastructure/di/customers.di.ts index 2dc3c272..7fb87006 100644 --- a/modules/customers/src/api/infrastructure/di/customers.di.ts +++ b/modules/customers/src/api/infrastructure/di/customers.di.ts @@ -1,11 +1,21 @@ import { type ModuleParams, buildCatalogs, buildTransactionManager } from "@erp/core/api"; +import { + type ListCustomersUseCase, + buildCustomerFinder, + buildCustomerSnapshotBuilders, + buildListCustomersUseCase, +} from "../../application"; + +import { buildCustomerPersistenceMappers } from "./customer-persistence-mappers.di"; +import { buildCustomerRepository } from "./customer-repositories.di"; + export type CustomersInternalDeps = { useCases: { listCustomers: () => ListCustomersUseCase; - getCustomerById: () => GetCustomerByIdUseCase; - reportCustomer: () => ReportCustomerUseCase; - createCustomer: () => CreateCustomerUseCase; + //getCustomerById: () => GetCustomerByIdUseCase; + //reportCustomer: () => ReportCustomerUseCase; + //createCustomer: () => CreateCustomerUseCase; /* updateCustomer: () => UpdateCustomerUseCase; @@ -15,25 +25,24 @@ export type CustomersInternalDeps = { }; }; - export function buildCustomersDependencies(params: ModuleParams): CustomersInternalDeps { const { database } = params; // Infrastructure const transactionManager = buildTransactionManager(database); const catalogs = buildCatalogs(); - const persistenceMappers = buildCustomerPersistenceMappers(catalogs); + const persistenceMappers = buildCustomerPersistenceMappers(); const repository = buildCustomerRepository({ database, mappers: persistenceMappers }); - const numberService = buildCustomerNumberGenerator(); + //const numberService = buildCustomerNumberGenerator(); // Application helpers - const inputMappers = buildCustomerInputMappers(catalogs); + //const inputMappers = buildCustomerInputMappers(catalogs); const finder = buildCustomerFinder(repository); - const creator = buildCustomerCreator({ numberService, repository }); + //const creator = buildCustomerCreator({ numberService, repository }); - const snapshotBuilders = buildCustomersnapshotBuilders(); - const documentGeneratorPipeline = buildCustomerDocumentService(params); + const snapshotBuilders = buildCustomerSnapshotBuilders(); + //const documentGeneratorPipeline = buildCustomerDocumentService(params); // Internal use cases (factories) return { @@ -41,11 +50,11 @@ export function buildCustomersDependencies(params: ModuleParams): CustomersInter listCustomers: () => buildListCustomersUseCase({ finder, - itemSnapshotBuilder: snapshotBuilders.list, + summarySnapshotBuilder: snapshotBuilders.summary, transactionManager, }), - getCustomerById: () => + /*getCustomerById: () => buildGetCustomerByIdUseCase({ finder, fullSnapshotBuilder: snapshotBuilders.full, @@ -67,7 +76,7 @@ export function buildCustomersDependencies(params: ModuleParams): CustomersInter dtoMapper: inputMappers.createInputMapper, fullSnapshotBuilder: snapshotBuilders.full, transactionManager, - }), + }),*/ }, }; } diff --git a/modules/customers/src/api/infrastructure/di/index.ts b/modules/customers/src/api/infrastructure/di/index.ts index 47860a30..02056462 100644 --- a/modules/customers/src/api/infrastructure/di/index.ts +++ b/modules/customers/src/api/infrastructure/di/index.ts @@ -1 +1,2 @@ -export * from "./customers.di"; \ No newline at end of file +export * from "./customer-public-services"; +export * from "./customers.di"; diff --git a/modules/customers/src/api/infrastructure/express/customers.routes.ts b/modules/customers/src/api/infrastructure/express/customers.routes.ts index 7d632a41..cf4f7bb7 100644 --- a/modules/customers/src/api/infrastructure/express/customers.routes.ts +++ b/modules/customers/src/api/infrastructure/express/customers.routes.ts @@ -1,39 +1,22 @@ import { - type RequestWithAuth, mockUser, requireAuthenticated, requireCompanyContext, } from "@erp/auth/api"; -import { type ModuleParams, validateRequest } from "@erp/core/api"; -import type { ILogger } from "@repo/rdx-logger"; -import { type Application, type NextFunction, type Request, type Response, Router } from "express"; -import type { Sequelize } from "sequelize"; +import { type ModuleParams, RequestWithAuth, validateRequest } from "@erp/core/api"; +import { type NextFunction, type Request, type Response, Router } from "express"; import { - CreateCustomerRequestSchema, - CustomerListRequestSchema, - GetCustomerByIdRequestSchema, - UpdateCustomerByIdParamsRequestSchema, - UpdateCustomerByIdRequestSchema, + CustomerListRequestSchema } from "../../../common/dto"; -import { buildCustomerDependencies } from "../dependencies"; +import type { CustomersInternalDeps } from "../di"; import { - CreateCustomerController, - GetCustomerController, - ListCustomersController, - UpdateCustomerController, + ListCustomersController } from "./controllers"; -export const customersRouter = (params: ModuleParams, deps: CustomerInternalDeps) => { - const { app, baseRoutePath, logger } = params as { - app: Application; - database: Sequelize; - baseRoutePath: string; - logger: ILogger; - }; - - const deps = buildCustomerDependencies(params); +export const customersRouter = (params: ModuleParams, deps: CustomersInternalDeps) => { + const { app, config } = params; const router: Router = Router({ mergeParams: true }); @@ -62,49 +45,49 @@ export const customersRouter = (params: ModuleParams, deps: CustomerInternalDeps validateRequest(CustomerListRequestSchema, "params"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.build.list(); + const useCase = deps.useCases.listCustomers(); const controller = new ListCustomersController(useCase /*, deps.presenters.list */); return controller.execute(req, res, next); } ); - router.get( + /* router.get( "/:customer_id", //checkTabContext, validateRequest(GetCustomerByIdRequestSchema, "params"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.build.get(); + const useCase = deps.useCases.get(); const controller = new GetCustomerController(useCase); return controller.execute(req, res, next); } - ); + ); */ - router.post( + /* router.post( "/", //checkTabContext, validateRequest(CreateCustomerRequestSchema, "body"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.build.create(); + const useCase = deps.useCases.create(); const controller = new CreateCustomerController(useCase); return controller.execute(req, res, next); } - ); + ); */ - router.put( + /* router.put( "/:customer_id", //checkTabContext, validateRequest(UpdateCustomerByIdParamsRequestSchema, "params"), validateRequest(UpdateCustomerByIdRequestSchema, "body"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.build.update(); + const useCase = deps.useCases.update(); const controller = new UpdateCustomerController(useCase); return controller.execute(req, res, next); } ); - + */ /*router.delete( "/:customer_id", //checkTabContext, @@ -117,5 +100,5 @@ export const customersRouter = (params: ModuleParams, deps: CustomerInternalDeps } );*/ - app.use(`${baseRoutePath}/customers`, router); + app.use(`${config.server.apiBasePath}/customers`, router); }; diff --git a/modules/customers/src/api/infrastructure/mappers/domain/index.ts b/modules/customers/src/api/infrastructure/mappers/domain/index.ts index 7f5fae75..7e81600d 100644 --- a/modules/customers/src/api/infrastructure/mappers/domain/index.ts +++ b/modules/customers/src/api/infrastructure/mappers/domain/index.ts @@ -1 +1 @@ -export * from "./customer.mapper"; +export * from "./sequelize-customer.mapper"; diff --git a/modules/customers/src/api/infrastructure/mappers/domain/customer.mapper.ts b/modules/customers/src/api/infrastructure/mappers/domain/sequelize-customer.mapper.ts similarity index 97% rename from modules/customers/src/api/infrastructure/mappers/domain/customer.mapper.ts rename to modules/customers/src/api/infrastructure/mappers/domain/sequelize-customer.mapper.ts index e5d40eb5..7695b93d 100644 --- a/modules/customers/src/api/infrastructure/mappers/domain/customer.mapper.ts +++ b/modules/customers/src/api/infrastructure/mappers/domain/sequelize-customer.mapper.ts @@ -1,5 +1,4 @@ import { type MapperParamsType, SequelizeDomainMapper } from "@erp/core/api"; -import type { ICustomerDomainMapper } from "@erp/customers/api/application"; import { City, Country, @@ -28,10 +27,11 @@ import { Collection, Result } from "@repo/rdx-utils"; import { Customer, CustomerStatus, type ICustomerProps } from "../../../domain"; import type { CustomerCreationAttributes, CustomerModel } from "../../sequelize"; -export class CustomerDomainMapper - extends SequelizeDomainMapper - implements ICustomerDomainMapper -{ +export class SequelizeCustomerDomainMapper extends SequelizeDomainMapper< + CustomerModel, + CustomerCreationAttributes, + Customer +> { public mapToDomain(source: CustomerModel, params?: MapperParamsType): Result { try { const errors: ValidationErrorDetail[] = []; diff --git a/modules/customers/src/api/infrastructure/mappers/index.ts b/modules/customers/src/api/infrastructure/mappers/index.ts index 9e03d7a9..b7726c46 100644 --- a/modules/customers/src/api/infrastructure/mappers/index.ts +++ b/modules/customers/src/api/infrastructure/mappers/index.ts @@ -1,2 +1,2 @@ export * from "./domain"; -export * from "./queries"; +export * from "./summary"; diff --git a/modules/customers/src/api/infrastructure/mappers/queries/index.ts b/modules/customers/src/api/infrastructure/mappers/queries/index.ts deleted file mode 100644 index 6565e4ad..00000000 --- a/modules/customers/src/api/infrastructure/mappers/queries/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./customer-summary.mapper"; diff --git a/modules/customers/src/api/infrastructure/mappers/summary/index.ts b/modules/customers/src/api/infrastructure/mappers/summary/index.ts new file mode 100644 index 00000000..5f61f134 --- /dev/null +++ b/modules/customers/src/api/infrastructure/mappers/summary/index.ts @@ -0,0 +1 @@ +export * from "./sequelize-customer-summary.mapper"; diff --git a/modules/customers/src/api/infrastructure/mappers/queries/customer-summary.mapper.ts b/modules/customers/src/api/infrastructure/mappers/summary/sequelize-customer-summary.mapper.ts similarity index 99% rename from modules/customers/src/api/infrastructure/mappers/queries/customer-summary.mapper.ts rename to modules/customers/src/api/infrastructure/mappers/summary/sequelize-customer-summary.mapper.ts index 2d130c04..da876bb7 100644 --- a/modules/customers/src/api/infrastructure/mappers/queries/customer-summary.mapper.ts +++ b/modules/customers/src/api/infrastructure/mappers/summary/sequelize-customer-summary.mapper.ts @@ -26,7 +26,7 @@ import type { CustomerSummary, ICustomerSummaryMapper } from "../../../applicati import { CustomerStatus } from "../../../domain"; import type { CustomerModel } from "../../sequelize"; -export class CustomerSummaryMapper +export class SequelizeCustomerSummaryMapper extends SequelizeQueryMapper implements ICustomerSummaryMapper { diff --git a/modules/customers/src/api/infrastructure/sequelize/repositories/customer.repository.ts b/modules/customers/src/api/infrastructure/sequelize/repositories/customer.repository.ts index 3e1a50f4..f0355ae2 100644 --- a/modules/customers/src/api/infrastructure/sequelize/repositories/customer.repository.ts +++ b/modules/customers/src/api/infrastructure/sequelize/repositories/customer.repository.ts @@ -7,11 +7,11 @@ import { import { type Criteria, CriteriaToSequelizeConverter } from "@repo/rdx-criteria/server"; import type { UniqueID } from "@repo/rdx-ddd"; import { type Collection, Result } from "@repo/rdx-utils"; -import type { Sequelize, Transaction } from "sequelize"; +import type { FindOptions, InferAttributes, OrderItem, Sequelize, Transaction } from "sequelize"; import type { CustomerSummary, ICustomerRepository } from "../../../application"; import type { Customer } from "../../../domain"; -import type { ICustomerDomainMapper, ICustomerListMapper } from "../../mappers"; +import type { SequelizeCustomerDomainMapper, SequelizeCustomerSummaryMapper } from "../../mappers"; import { CustomerModel } from "../models/customer.model"; export class CustomerRepository @@ -19,8 +19,8 @@ export class CustomerRepository implements ICustomerRepository { constructor( - private readonly domainMapper: ICustomerDomainMapper, - private readonly listMapper: ICustomerListMapper, + private readonly domainMapper: SequelizeCustomerDomainMapper, + private readonly summaryMapper: SequelizeCustomerSummaryMapper, database: Sequelize ) { super({ database }); @@ -120,23 +120,42 @@ export class CustomerRepository async getByIdInCompany( companyId: UniqueID, id: UniqueID, - transaction?: Transaction + transaction?: Transaction, + options: FindOptions> = {} ): Promise> { try { - const mapper: ICustomerDomainMapper = this._registry.getDomainMapper({ - resource: "customer", - }); + // Normalización defensiva de order/include + const normalizedOrder = Array.isArray(options.order) + ? options.order + : options.order + ? [options.order] + : []; - const row = await CustomerModel.findOne({ - where: { id: id.toString(), company_id: companyId.toString() }, + const normalizedInclude = Array.isArray(options.include) + ? options.include + : options.include + ? [options.include] + : []; + + const mergedOptions: FindOptions> = { + ...options, + where: { + ...(options.where ?? {}), + id: id.toString(), + company_id: companyId.toString(), + }, + order: normalizedOrder, + include: normalizedInclude, transaction, - }); + }; + + const row = await CustomerModel.findOne(mergedOptions); if (!row) { return Result.fail(new EntityNotFoundError("Customer", "id", id.toString())); } - const customer = mapper.mapToDomain(row); + const customer = this.domainMapper.mapToDomain(row); return customer; } catch (error: unknown) { return Result.fail(translateSequelizeError(error)); @@ -156,7 +175,8 @@ export class CustomerRepository async findByCriteriaInCompany( companyId: UniqueID, criteria: Criteria, - transaction?: Transaction + transaction?: Transaction, + options: FindOptions> = {} ): Promise, Error>> { try { const criteriaConverter = new CriteriaToSequelizeConverter(); @@ -182,18 +202,48 @@ export class CustomerRepository strictMode: true, // fuerza error si ORDER BY no permitido }); + // Normalización defensiva de order/include + const normalizedOrder = Array.isArray(options.order) + ? options.order + : options.order + ? [options.order] + : []; + + const normalizedInclude = Array.isArray(options.include) + ? options.include + : options.include + ? [options.include] + : []; + query.where = { ...query.where, company_id: companyId.toString(), deleted_at: null, }; + query.order = [...(query.order as OrderItem[]), ...normalizedOrder]; + + query.include = normalizedInclude; + + // Reemplazar findAndCountAll por findAll + count (más control y mejor rendimiento) + /* const { rows, count } = await CustomerModel.findAndCountAll({ ...query, transaction, - }); + });*/ + const [rows, count] = await Promise.all([ + CustomerModel.findAll({ + ...query, + transaction, + }), + CustomerModel.count({ + where: query.where, + distinct: true, // evita duplicados por LEFT JOIN + transaction, + }), + ]); - return this.listMapper.mapToDTOCollection(rows, count); + return this.summaryMapper.mapToReadModelCollection(rows, count); } catch (err: unknown) { return Result.fail(translateSequelizeError(err)); }