From 3c1010adadb9af34752bb23269aa20538c32688c Mon Sep 17 00:00:00 2001 From: david Date: Thu, 21 Aug 2025 09:44:07 +0200 Subject: [PATCH] . --- .../list-customer-invoices.use-case.ts | 4 +- .../src/common/dto/common/index.ts | 0 modules/customers/package.json | 1 + .../assembler/create-customers.assembler.ts | 18 ++--- .../create-customer.use-case.ts | 20 +++--- .../assembler/get-invoice.assembler.ts | 6 +- .../get-customer/assembler/index.ts | 2 +- .../get-customer/get-customer.use-case.ts | 8 +-- .../helpers/map-dto-to-customer-props.ts | 32 ++++----- .../list-customers/assembler/index.ts | 2 +- .../assembler/list-customers.assembler.ts | 70 +++++++++++++++++++ .../assembler/list-invoices.assembler.ts | 51 -------------- .../list-customers/list-customers.use-case.ts | 16 +++-- .../controllers/list-customers.controller.ts | 2 +- .../express/customers.routes.ts | 1 + .../response/customer-list.response.dto.ts | 2 +- pnpm-lock.yaml | 3 + 17 files changed, 135 insertions(+), 103 deletions(-) delete mode 100644 modules/customer-invoices/src/common/dto/common/index.ts create mode 100644 modules/customers/src/api/application/list-customers/assembler/list-customers.assembler.ts delete mode 100644 modules/customers/src/api/application/list-customers/assembler/list-invoices.assembler.ts diff --git a/modules/customer-invoices/src/api/application/list-customer-invoices/list-customer-invoices.use-case.ts b/modules/customer-invoices/src/api/application/list-customer-invoices/list-customer-invoices.use-case.ts index 52955ac7..b05fb503 100644 --- a/modules/customer-invoices/src/api/application/list-customer-invoices/list-customer-invoices.use-case.ts +++ b/modules/customer-invoices/src/api/application/list-customer-invoices/list-customer-invoices.use-case.ts @@ -1,8 +1,8 @@ import { ITransactionManager } from "@erp/core/api"; -import { CustomerInvoiceListResponseDTO } from "@erp/customer-invoices/common/dto"; import { Criteria } from "@repo/rdx-criteria/server"; import { Result } from "@repo/rdx-utils"; import { Transaction } from "sequelize"; +import { CustomerInvoiceListResponseDTO } from "../../../common/dto"; import { ICustomerInvoiceService } from "../../domain"; import { ListCustomerInvoicesAssembler } from "./assembler"; @@ -31,7 +31,7 @@ export class ListCustomerInvoicesUseCase { return Result.fail(result.error); } - const dto: CustomerInvoiceListResponseDTO = this.assembler.toDTO(result.data, criteria); + const dto = this.assembler.toDTO(result.data, criteria); return Result.ok(dto); } catch (error: unknown) { return Result.fail(error as Error); diff --git a/modules/customer-invoices/src/common/dto/common/index.ts b/modules/customer-invoices/src/common/dto/common/index.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/customers/package.json b/modules/customers/package.json index 4af1fbed..b0803dae 100644 --- a/modules/customers/package.json +++ b/modules/customers/package.json @@ -32,6 +32,7 @@ "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@erp/auth": "workspace:*", "@erp/customers": "workspace:*", "@hookform/resolvers": "^5.0.1", "@repo/rdx-criteria": "workspace:*", diff --git a/modules/customers/src/api/application/create-customer/assembler/create-customers.assembler.ts b/modules/customers/src/api/application/create-customer/assembler/create-customers.assembler.ts index c2713d55..afc9fc7c 100644 --- a/modules/customers/src/api/application/create-customer/assembler/create-customers.assembler.ts +++ b/modules/customers/src/api/application/create-customer/assembler/create-customers.assembler.ts @@ -2,20 +2,20 @@ import { Customer } from "@erp/customers/api/domain"; import { CustomersCreationResultDTO } from "@erp/customers/common/dto"; export class CreateCustomersAssembler { - public toDTO(invoice: Customer): CustomersCreationResultDTO { + public toDTO(customer: Customer): CustomersCreationResultDTO { return { - id: invoice.id.toPrimitive(), + id: customer.id.toPrimitive(), - invoice_status: invoice.status.toString(), - invoice_number: invoice.invoiceNumber.toString(), - invoice_series: invoice.invoiceSeries.toString(), - issue_date: invoice.issueDate.toISOString(), - operation_date: invoice.operationDate.toISOString(), + customer_status: customer.status.toString(), + customer_number: customer.customerNumber.toString(), + customer_series: customer.customerSeries.toString(), + issue_date: customer.issueDate.toISOString(), + operation_date: customer.operationDate.toISOString(), language_code: "ES", currency: "EUR", - //subtotal_price: invoice.calculateSubtotal().toPrimitive(), - //total_price: invoice.calculateTotal().toPrimitive(), + //subtotal_price: customer.calculateSubtotal().toPrimitive(), + //total_price: customer.calculateTotal().toPrimitive(), //recipient: CustomerParticipantAssembler(customer.recipient), diff --git a/modules/customers/src/api/application/create-customer/create-customer.use-case.ts b/modules/customers/src/api/application/create-customer/create-customer.use-case.ts index 400b4720..4ed547b6 100644 --- a/modules/customers/src/api/application/create-customer/create-customer.use-case.ts +++ b/modules/customers/src/api/application/create-customer/create-customer.use-case.ts @@ -14,21 +14,21 @@ export class CreateCustomerUseCase { ) {} public execute(dto: CreateCustomerCommandDTO) { - const invoicePropsOrError = mapDTOToCustomerProps(dto); + const customerPropsOrError = mapDTOToCustomerProps(dto); - if (invoicePropsOrError.isFailure) { - return Result.fail(invoicePropsOrError.error); + if (customerPropsOrError.isFailure) { + return Result.fail(customerPropsOrError.error); } - const { props, id } = invoicePropsOrError.data; + const { props, id } = customerPropsOrError.data; - const invoiceOrError = this.service.build(props, id); + const customerOrError = this.service.build(props, id); - if (invoiceOrError.isFailure) { - return Result.fail(invoiceOrError.error); + if (customerOrError.isFailure) { + return Result.fail(customerOrError.error); } - const newInvoice = invoiceOrError.data; + const newCustomer = customerOrError.data; return this.transactionManager.complete(async (transaction: Transaction) => { try { @@ -42,12 +42,12 @@ export class CreateCustomerUseCase { return Result.fail(new DuplicateEntityError("Customer", id.toString())); } - const result = await this.service.save(newInvoice, transaction); + const result = await this.service.save(newCustomer, transaction); if (result.isFailure) { return Result.fail(result.error); } - const viewDTO = this.assembler.toDTO(newInvoice); + const viewDTO = this.assembler.toDTO(newCustomer); return Result.ok(viewDTO); } catch (error: unknown) { return Result.fail(error as Error); diff --git a/modules/customers/src/api/application/get-customer/assembler/get-invoice.assembler.ts b/modules/customers/src/api/application/get-customer/assembler/get-invoice.assembler.ts index df4c01df..69f3ba91 100644 --- a/modules/customers/src/api/application/get-customer/assembler/get-invoice.assembler.ts +++ b/modules/customers/src/api/application/get-customer/assembler/get-invoice.assembler.ts @@ -6,9 +6,9 @@ export class GetCustomerAssembler { return { id: customer.id.toPrimitive(), - invoice_status: customer.status.toString(), - invoice_number: customer.invoiceNumber.toString(), - invoice_series: customer.invoiceSeries.toString(), + customer_status: customer.status.toString(), + customer_number: customer.customerNumber.toString(), + customer_series: customer.customerSeries.toString(), issue_date: customer.issueDate.toDateString(), operation_date: customer.operationDate.toDateString(), language_code: "ES", diff --git a/modules/customers/src/api/application/get-customer/assembler/index.ts b/modules/customers/src/api/application/get-customer/assembler/index.ts index 346d890f..91baddfe 100644 --- a/modules/customers/src/api/application/get-customer/assembler/index.ts +++ b/modules/customers/src/api/application/get-customer/assembler/index.ts @@ -1 +1 @@ -export * from "./get-invoice.assembler"; +export * from "./get-customer.assembler"; diff --git a/modules/customers/src/api/application/get-customer/get-customer.use-case.ts b/modules/customers/src/api/application/get-customer/get-customer.use-case.ts index 701f89d6..ab63721d 100644 --- a/modules/customers/src/api/application/get-customer/get-customer.use-case.ts +++ b/modules/customers/src/api/application/get-customer/get-customer.use-case.ts @@ -21,12 +21,12 @@ export class GetCustomerUseCase { return this.transactionManager.complete(async (transaction) => { try { - const invoiceOrError = await this.service.getById(idOrError.data, transaction); - if (invoiceOrError.isFailure) { - return Result.fail(invoiceOrError.error); + const customerOrError = await this.service.getById(idOrError.data, transaction); + if (customerOrError.isFailure) { + return Result.fail(customerOrError.error); } - const getDTO = this.assembler.toDTO(invoiceOrError.data); + const getDTO = this.assembler.toDTO(customerOrError.data); return Result.ok(getDTO); } catch (error: unknown) { return Result.fail(error as Error); diff --git a/modules/customers/src/api/application/helpers/map-dto-to-customer-props.ts b/modules/customers/src/api/application/helpers/map-dto-to-customer-props.ts index 1806f23b..b446541b 100644 --- a/modules/customers/src/api/application/helpers/map-dto-to-customer-props.ts +++ b/modules/customers/src/api/application/helpers/map-dto-to-customer-props.ts @@ -19,16 +19,16 @@ import { mapDTOToCustomerItemsProps } from "./map-dto-to-customer-items-props"; export function mapDTOToCustomerProps(dto: CreateCustomerCommandDTO) { const errors: ValidationErrorDetail[] = []; - const invoiceId = extractOrPushError(UniqueID.create(dto.id), "id", errors); + const customerId = extractOrPushError(UniqueID.create(dto.id), "id", errors); - const invoiceNumber = extractOrPushError( - CustomerNumber.create(dto.invoice_number), - "invoice_number", + const customerNumber = extractOrPushError( + CustomerNumber.create(dto.customer_number), + "customer_number", errors ); - const invoiceSeries = extractOrPushError( - CustomerSerie.create(dto.invoice_series), - "invoice_series", + const customerSeries = extractOrPushError( + CustomerSerie.create(dto.customer_series), + "customer_series", errors ); const issueDate = extractOrPushError(UtcDate.createFromISO(dto.issue_date), "issue_date", errors); @@ -51,23 +51,23 @@ export function mapDTOToCustomerProps(dto: CreateCustomerCommandDTO) { return Result.fail(new ValidationErrorCollection(errors)); } - const invoiceProps: CustomerProps = { - invoiceNumber: invoiceNumber!, - invoiceSeries: invoiceSeries!, + const customerProps: CustomerProps = { + customerNumber: customerNumber!, + customerSeries: customerSeries!, issueDate: issueDate!, operationDate: operationDate!, status: CustomerStatus.createDraft(), currency, }; - return Result.ok({ id: invoiceId!, props: invoiceProps }); + return Result.ok({ id: customerId!, props: customerProps }); - /*if (hasNoUndefinedFields(invoiceProps)) { - const invoiceOrError = Customer.create(invoiceProps, invoiceId); - if (invoiceOrError.isFailure) { - return Result.fail(invoiceOrError.error); + /*if (hasNoUndefinedFields(customerProps)) { + const customerOrError = Customer.create(customerProps, customerId); + if (customerOrError.isFailure) { + return Result.fail(customerOrError.error); } - return Result.ok(invoiceOrError.data); + return Result.ok(customerOrError.data); } return Result.fail( diff --git a/modules/customers/src/api/application/list-customers/assembler/index.ts b/modules/customers/src/api/application/list-customers/assembler/index.ts index d4824855..63121daa 100644 --- a/modules/customers/src/api/application/list-customers/assembler/index.ts +++ b/modules/customers/src/api/application/list-customers/assembler/index.ts @@ -1 +1 @@ -export * from "./list-invoices.assembler"; +export * from "./list-customers.assembler"; diff --git a/modules/customers/src/api/application/list-customers/assembler/list-customers.assembler.ts b/modules/customers/src/api/application/list-customers/assembler/list-customers.assembler.ts new file mode 100644 index 00000000..622948d3 --- /dev/null +++ b/modules/customers/src/api/application/list-customers/assembler/list-customers.assembler.ts @@ -0,0 +1,70 @@ +import { Criteria } from "@repo/rdx-criteria/server"; +import { Collection } from "@repo/rdx-utils"; +import { CustomerListResponsetDTO } from "../../../../common/dto"; +import { Customer } from "../../../domain"; + +export class ListCustomersAssembler { + toDTO(customers: Collection, criteria: Criteria): CustomerListResponsetDTO { + const items: CustomerListResponsetDTO["items"] = customers.map((customer) => { + const address = customer.address.toPrimitive(); + + return { + id: customer.id.toPrimitive(), + reference: customer.reference, + + is_freelancer: customer.isFreelancer, + name: customer.name, + trade_name: customer.tradeName.getOrUndefined(), + tin: customer.tin.toString(), + + street: address.street, + city: address.city, + state: address.state, + postal_code: address.postalCode, + country: address.country, + + email: customer.email.getValue(), + phone: customer.phone.getValue(), + fax: customer.fax.getOrUndefined(), + website: customer.website.getOrUndefined(), + + legal_record: customer.legalRecord, + + default_tax: customer.defaultTax, + status: customer.isActive ? 'active' : 'inactive', + lang_code: customer.langCode, + currency_code: customer.currencyCode, + + metadata: { + entity: "customer", + id: customer.id.toPrimitive(), + //created_at: customer.createdAt.toPrimitive(), + //updated_at: customer.updatedAt.toPrimitive() + } + }; + }); + + + + + +const totalItems = customers.total(); + +return { + page: criteria.pageNumber, + per_page: criteria.pageSize, + total_pages: Math.ceil(totalItems / criteria.pageSize), + total_items: totalItems, + items: items, + metadata: { + entity: "customers", + criteria: criteria.toJSON(), + //links: { + // self: `/api/customers?page=${criteria.pageNumber}&per_page=${criteria.pageSize}`, + // first: `/api/customers?page=1&per_page=${criteria.pageSize}`, + // last: `/api/customers?page=${Math.ceil(totalItems / criteria.pageSize)}&per_page=${criteria.pageSize}`, + //}, + }, + }; +}, +} diff --git a/modules/customers/src/api/application/list-customers/assembler/list-invoices.assembler.ts b/modules/customers/src/api/application/list-customers/assembler/list-invoices.assembler.ts deleted file mode 100644 index 0270b704..00000000 --- a/modules/customers/src/api/application/list-customers/assembler/list-invoices.assembler.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Criteria } from "@repo/rdx-criteria/server"; -import { Collection } from "@repo/rdx-utils"; -import { CustomerListResponsetDTO } from "../../../../common/dto"; -import { Customer } from "../../../domain"; - - -export class ListCustomersAssembler { - toDTO(customers: Collection, criteria: Criteria): CustomerListResponsetDTO { - const items = customers.map((invoice) => { - return { - id: invoice.id.toPrimitive(), - - invoice_status: invoice.status.toString(), - invoice_number: invoice.invoiceNumber.toString(), - invoice_series: invoice.invoiceSeries.toString(), - issue_date: invoice.issueDate.toISOString(), - operation_date: invoice.operationDate.toISOString(), - language_code: "ES", - currency: "EUR", - - subtotal_price: invoice.calculateSubtotal().toPrimitive(), - total_price: invoice.calculateTotal().toPrimitive(), - - //recipient: CustomerParticipantAssembler(customer.recipient), - - metadata: { - entity: "customer", - }, - }; - }); - - const totalItems = customers.total(); - - return { - page: criteria.pageNumber, - per_page: criteria.pageSize, - total_pages: Math.ceil(totalItems / criteria.pageSize), - total_items: totalItems, - items: items, - metadata: { - entity: "customers", - criteria: criteria.toJSON(), - //links: { - // self: `/api/customers?page=${criteria.pageNumber}&per_page=${criteria.pageSize}`, - // first: `/api/customers?page=1&per_page=${criteria.pageSize}`, - // last: `/api/customers?page=${Math.ceil(totalItems / criteria.pageSize)}&per_page=${criteria.pageSize}`, - //}, - }, - }; - }, -}; diff --git a/modules/customers/src/api/application/list-customers/list-customers.use-case.ts b/modules/customers/src/api/application/list-customers/list-customers.use-case.ts index b616a920..85edc8d0 100644 --- a/modules/customers/src/api/application/list-customers/list-customers.use-case.ts +++ b/modules/customers/src/api/application/list-customers/list-customers.use-case.ts @@ -1,11 +1,16 @@ import { ITransactionManager } from "@erp/core/api"; -import { ListCustomersResultDTO } from "@erp/customers/common/dto"; import { Criteria } from "@repo/rdx-criteria/server"; import { Result } from "@repo/rdx-utils"; import { Transaction } from "sequelize"; +import { CustomerListResponsetDTO } from "../../../common/dto"; import { ICustomerService } from "../../domain"; import { ListCustomersAssembler } from "./assembler"; +type ListCustomersUseCaseInput = { + tenantId: string; + criteria: Criteria; +}; + export class ListCustomersUseCase { constructor( private readonly customerService: ICustomerService, @@ -13,17 +18,20 @@ export class ListCustomersUseCase { private readonly assembler: ListCustomersAssembler ) {} - public execute(criteria: Criteria): Promise> { + public execute( + params: ListCustomersUseCaseInput + ): Promise> { + const { criteria, tenantId } = params; + return this.transactionManager.complete(async (transaction: Transaction) => { try { const result = await this.customerService.findByCriteria(criteria, transaction); if (result.isFailure) { - console.error(result.error); return Result.fail(result.error); } - const dto: ListCustomersResultDTO = this.assembler.toDTO(result.data, criteria); + const dto = this.assembler.toDTO(result.data, criteria); return Result.ok(dto); } catch (error: unknown) { return Result.fail(error as Error); diff --git a/modules/customers/src/api/infrastructure/express/controllers/list-customers.controller.ts b/modules/customers/src/api/infrastructure/express/controllers/list-customers.controller.ts index 7ed3e40d..7815d615 100644 --- a/modules/customers/src/api/infrastructure/express/controllers/list-customers.controller.ts +++ b/modules/customers/src/api/infrastructure/express/controllers/list-customers.controller.ts @@ -5,7 +5,7 @@ import { forbidQueryFieldGuard, tenantGuard, } from "@erp/core/api"; -import { ListCustomersUseCase } from "../../../../application"; +import { ListCustomersUseCase } from "../../../application"; export class ListCustomersController extends ExpressController { public constructor(private readonly listCustomers: ListCustomersUseCase) { diff --git a/modules/customers/src/api/infrastructure/express/customers.routes.ts b/modules/customers/src/api/infrastructure/express/customers.routes.ts index b703b066..5da1abbc 100644 --- a/modules/customers/src/api/infrastructure/express/customers.routes.ts +++ b/modules/customers/src/api/infrastructure/express/customers.routes.ts @@ -1,3 +1,4 @@ +import { enforceTenant } from "@erp/auth/api"; import { ILogger, ModuleParams, validateRequest } from "@erp/core/api"; import { Application, NextFunction, Request, Response, Router } from "express"; import { Sequelize } from "sequelize"; diff --git a/modules/customers/src/common/dto/response/customer-list.response.dto.ts b/modules/customers/src/common/dto/response/customer-list.response.dto.ts index 7846c99e..934f7513 100644 --- a/modules/customers/src/common/dto/response/customer-list.response.dto.ts +++ b/modules/customers/src/common/dto/response/customer-list.response.dto.ts @@ -3,7 +3,7 @@ import * as z from "zod/v4"; export const CustomerListResponseSchema = createListViewResponseSchema( z.object({ - id: z.string(), + id: z.uuid(), reference: z.string(), is_freelancer: z.boolean(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ad86d07e..e1af4cf1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -583,6 +583,9 @@ importers: '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.1.0) + '@erp/auth': + specifier: workspace:* + version: link:../auth '@erp/core': specifier: workspace:* version: link:../core