diff --git a/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice-items.full.presenter.ts b/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice-items.full.presenter.ts index 16cd71b3..e4f9d8ae 100644 --- a/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice-items.full.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice-items.full.presenter.ts @@ -1,12 +1,12 @@ import { Presenter } from "@erp/core/api"; +import type { GetIssuedInvoiceByIdResponseDTO } from "@erp/customer-invoices/common"; import { toEmptyString } from "@repo/rdx-ddd"; import type { ArrayElement } from "@repo/rdx-utils"; -import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto"; import type { CustomerInvoiceItem, CustomerInvoiceItems } from "../../../domain"; type GetCustomerInvoiceItemByInvoiceIdResponseDTO = ArrayElement< - GetIssueInvoiceByIdResponseDTO["items"] + GetIssuedInvoiceByIdResponseDTO["items"] >; export class CustomerInvoiceItemsFullPresenter extends Presenter { @@ -49,7 +49,7 @@ export class CustomerInvoiceItemsFullPresenter extends Presenter { }; } - toOutput(invoiceItems: CustomerInvoiceItems): GetIssueInvoiceByIdResponseDTO["items"] { + toOutput(invoiceItems: CustomerInvoiceItems): GetIssuedInvoiceByIdResponseDTO["items"] { return invoiceItems.map(this._mapItem); } } diff --git a/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice.full.presenter.ts b/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice.full.presenter.ts index a5274a6b..69ebca47 100644 --- a/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice.full.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/domain/customer-invoice.full.presenter.ts @@ -1,7 +1,7 @@ import { Presenter } from "@erp/core/api"; import { toEmptyString } from "@repo/rdx-ddd"; -import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto"; +import type { GetIssuedInvoiceByIdResponseDTO } from "../../../../common/dto"; import type { CustomerInvoice } from "../../../domain"; import type { CustomerInvoiceItemsFullPresenter } from "./customer-invoice-items.full.presenter"; @@ -9,9 +9,9 @@ import type { RecipientInvoiceFullPresenter } from "./recipient-invoice.full.rep export class CustomerInvoiceFullPresenter extends Presenter< CustomerInvoice, - GetIssueInvoiceByIdResponseDTO + GetIssuedInvoiceByIdResponseDTO > { - toOutput(invoice: CustomerInvoice): GetIssueInvoiceByIdResponseDTO { + toOutput(invoice: CustomerInvoice): GetIssuedInvoiceByIdResponseDTO { const itemsPresenter = this.presenterRegistry.getPresenter({ resource: "customer-invoice-items", projection: "FULL", diff --git a/modules/customer-invoices/src/api/application/presenters/domain/recipient-invoice.full.representer.ts b/modules/customer-invoices/src/api/application/presenters/domain/recipient-invoice.full.representer.ts index 1da9f750..c9a89111 100644 --- a/modules/customer-invoices/src/api/application/presenters/domain/recipient-invoice.full.representer.ts +++ b/modules/customer-invoices/src/api/application/presenters/domain/recipient-invoice.full.representer.ts @@ -1,10 +1,10 @@ import { Presenter } from "@erp/core/api"; import { DomainValidationError, toEmptyString } from "@repo/rdx-ddd"; -import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto"; +import type { GetIssuedInvoiceByIdResponseDTO } from "../../../../common/dto"; import type { CustomerInvoice, InvoiceRecipient } from "../../../domain"; -type GetRecipientInvoiceByInvoiceIdResponseDTO = GetIssueInvoiceByIdResponseDTO["recipient"]; +type GetRecipientInvoiceByInvoiceIdResponseDTO = GetIssuedInvoiceByIdResponseDTO["recipient"]; export class RecipientInvoiceFullPresenter extends Presenter { toOutput(invoice: CustomerInvoice): GetRecipientInvoiceByInvoiceIdResponseDTO { diff --git a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-items.report.presenter.ts b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-items.report.presenter.ts index 8fa0d6b7..dc1bb006 100644 --- a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-items.report.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-items.report.presenter.ts @@ -1,9 +1,9 @@ import { MoneyDTOHelper, PercentageDTOHelper, QuantityDTOHelper } from "@erp/core"; import { type IPresenterOutputParams, Presenter } from "@erp/core/api"; -import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common"; +import type { GetIssuedInvoiceByIdResponseDTO } from "@erp/customer-invoices/common"; import type { ArrayElement } from "@repo/rdx-utils"; -type CustomerInvoiceItemsDTO = GetIssueInvoiceByIdResponseDTO["items"]; +type CustomerInvoiceItemsDTO = GetIssuedInvoiceByIdResponseDTO["items"]; type CustomerInvoiceItemDTO = ArrayElement; export class CustomerInvoiceItemsReportPersenter extends Presenter< diff --git a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-taxes.report.presenter.ts b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-taxes.report.presenter.ts index 9ec499e4..43b0dd4a 100644 --- a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-taxes.report.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice-taxes.report.presenter.ts @@ -1,9 +1,9 @@ import { type JsonTaxCatalogProvider, MoneyDTOHelper, SpainTaxCatalogProvider } from "@erp/core"; import { type IPresenterOutputParams, Presenter } from "@erp/core/api"; -import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common"; +import type { GetIssuedInvoiceByIdResponseDTO } from "@erp/customer-invoices/common"; import type { ArrayElement } from "@repo/rdx-utils"; -type CustomerInvoiceTaxesDTO = GetIssueInvoiceByIdResponseDTO["taxes"]; +type CustomerInvoiceTaxesDTO = GetIssuedInvoiceByIdResponseDTO["taxes"]; type CustomerInvoiceTaxDTO = ArrayElement; export class CustomerInvoiceTaxesReportPresenter extends Presenter< diff --git a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice.report.presenter.ts b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice.report.presenter.ts index 21c3333e..2509ffd7 100644 --- a/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice.report.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/queries/customer-invoice.report.presenter.ts @@ -1,14 +1,14 @@ import { DateHelper, MoneyDTOHelper, PercentageDTOHelper } from "@erp/core"; import { Presenter } from "@erp/core/api"; -import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto"; +import type { GetIssuedInvoiceByIdResponseDTO } from "../../../../common/dto"; export class CustomerInvoiceReportPresenter extends Presenter< - GetIssueInvoiceByIdResponseDTO, + GetIssuedInvoiceByIdResponseDTO, unknown > { private _formatPaymentMethodDTO( - paymentMethod?: GetIssueInvoiceByIdResponseDTO["payment_method"] + paymentMethod?: GetIssuedInvoiceByIdResponseDTO["payment_method"] ) { if (!paymentMethod) { return ""; @@ -17,7 +17,7 @@ export class CustomerInvoiceReportPresenter extends Presenter< return paymentMethod.payment_description ?? ""; } - toOutput(invoiceDTO: GetIssueInvoiceByIdResponseDTO) { + toOutput(invoiceDTO: GetIssuedInvoiceByIdResponseDTO) { const itemsPresenter = this.presenterRegistry.getPresenter({ resource: "customer-invoice-items", projection: "REPORT", diff --git a/modules/customer-invoices/src/api/application/presenters/queries/list-customer-invoices.presenter.ts b/modules/customer-invoices/src/api/application/presenters/queries/list-customer-invoices.presenter.ts index 9f84cad6..375b6172 100644 --- a/modules/customer-invoices/src/api/application/presenters/queries/list-customer-invoices.presenter.ts +++ b/modules/customer-invoices/src/api/application/presenters/queries/list-customer-invoices.presenter.ts @@ -3,14 +3,14 @@ import type { Criteria } from "@repo/rdx-criteria/server"; import { toEmptyString } from "@repo/rdx-ddd"; import type { ArrayElement, Collection } from "@repo/rdx-utils"; -import type { ListIssueInvoicesResponseDTO } from "../../../../common/dto"; +import type { ListIssuedInvoicesResponseDTO } from "../../../../common/dto"; import type { CustomerInvoiceListDTO } from "../../../infrastructure"; export class ListCustomerInvoicesPresenter extends Presenter { protected _mapInvoice(invoice: CustomerInvoiceListDTO) { const recipientDTO = invoice.recipient.toObjectString(); - const invoiceDTO: ArrayElement = { + const invoiceDTO: ArrayElement = { id: invoice.id.toString(), company_id: invoice.companyId.toString(), is_proforma: invoice.isProforma, @@ -50,7 +50,7 @@ export class ListCustomerInvoicesPresenter extends Presenter { toOutput(params: { customerInvoices: Collection; criteria: Criteria; - }): ListIssueInvoicesResponseDTO { + }): ListIssuedInvoicesResponseDTO { const { customerInvoices, criteria } = params; const invoices = customerInvoices.map((invoice) => this._mapInvoice(invoice)); diff --git a/modules/customer-invoices/src/api/application/services/customer-invoice-application.service.ts b/modules/customer-invoices/src/api/application/services/customer-invoice-application.service.ts index df04399a..75dabd0e 100644 --- a/modules/customer-invoices/src/api/application/services/customer-invoice-application.service.ts +++ b/modules/customer-invoices/src/api/application/services/customer-invoice-application.service.ts @@ -48,7 +48,7 @@ export class CustomerInvoiceApplicationService { * @param transaction - Transacción activa para la operación. * @returns Result - El agregado construido o un error si falla la creación. */ - async getNextIssueInvoiceNumber( + async getNextIssuedInvoiceNumber( companyId: UniqueID, series: Maybe, transaction: Transaction @@ -80,7 +80,7 @@ export class CustomerInvoiceApplicationService { * @param transaction - Transacción activa para la operación. * @returns Result - La factura guardada o un error si falla la operación. */ - async createIssueInvoiceInCompany( + async createIssuedInvoiceInCompany( companyId: UniqueID, invoice: CustomerInvoice, transaction: Transaction @@ -90,7 +90,7 @@ export class CustomerInvoiceApplicationService { return Result.fail(result.error); } - return this.getIssueInvoiceByIdInCompany(companyId, invoice.id, transaction); + return this.getIssuedInvoiceByIdInCompany(companyId, invoice.id, transaction); } /** @@ -157,7 +157,7 @@ export class CustomerInvoiceApplicationService { /** * - * Comprueba si existe o no en persistencia una proforma con el ID proporcionado + * Comprueba si existe o no en persistencia una factura con el ID proporcionado * * @param companyId - Identificador de la empresa a la que pertenece la factura. * @param invoiceId - Identificador UUID de la factura. @@ -165,7 +165,7 @@ export class CustomerInvoiceApplicationService { * @returns Result - Existe la factura o no. */ - async existsIssueInvoiceByIdInCompany( + async existsIssuedInvoiceByIdInCompany( companyId: UniqueID, invoiceId: UniqueID, transaction?: Transaction @@ -178,7 +178,7 @@ export class CustomerInvoiceApplicationService { /** * Obtiene una colección de proformas que cumplen con los filtros definidos en un objeto Criteria. * - * @param companyId - Identificador de la empresa a la que pertenece la factura. + * @param companyId - Identificador de la empresa a la que pertenece la proforma. * @param criteria - Objeto con condiciones de filtro, paginación y orden. * @param transaction - Transacción activa para la operación. * @returns Result, Error> - Colección de proformas o error. @@ -203,7 +203,7 @@ export class CustomerInvoiceApplicationService { * @param transaction - Transacción activa para la operación. * @returns Result, Error> - Colección de facturas o error. */ - async findIssueInvoiceByCriteriaInCompany( + async findIssuedInvoiceByCriteriaInCompany( companyId: UniqueID, criteria: Criteria, transaction?: Transaction @@ -222,7 +222,7 @@ export class CustomerInvoiceApplicationService { * @param transaction - Transacción activa para la operación. * @returns Result - Factura encontrada o error. */ - async getIssueInvoiceByIdInCompany( + async getIssuedInvoiceByIdInCompany( companyId: UniqueID, invoiceId: UniqueID, transaction?: Transaction diff --git a/modules/customer-invoices/src/api/application/use-cases/index.ts b/modules/customer-invoices/src/api/application/use-cases/index.ts index 457e40a2..de2b09ca 100644 --- a/modules/customer-invoices/src/api/application/use-cases/index.ts +++ b/modules/customer-invoices/src/api/application/use-cases/index.ts @@ -1,2 +1,2 @@ -export * from "./issue-invoices"; +export * from "./issued-invoices"; export * from "./proformas"; diff --git a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/index.ts b/modules/customer-invoices/src/api/application/use-cases/issue-invoices/index.ts deleted file mode 100644 index 5b88288d..00000000 --- a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./get-issue-invoice.use-case"; -export * from "./list-issue-invoices.use-case"; -export * from "./report-issue-invoice.use-case"; diff --git a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/get-issue-invoice.use-case.ts b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/get-issued-invoice.use-case.ts similarity index 86% rename from modules/customer-invoices/src/api/application/use-cases/issue-invoices/get-issue-invoice.use-case.ts rename to modules/customer-invoices/src/api/application/use-cases/issued-invoices/get-issued-invoice.use-case.ts index 9b9b9276..4713dd5b 100644 --- a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/get-issue-invoice.use-case.ts +++ b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/get-issued-invoice.use-case.ts @@ -5,19 +5,19 @@ import { Result } from "@repo/rdx-utils"; import type { CustomerInvoiceFullPresenter } from "../../presenters/domain"; import type { CustomerInvoiceApplicationService } from "../../services"; -type GetIssueInvoiceUseCaseInput = { +type GetIssuedInvoiceUseCaseInput = { companyId: UniqueID; invoice_id: string; }; -export class GetIssueInvoiceUseCase { +export class GetIssuedInvoiceUseCase { constructor( private readonly service: CustomerInvoiceApplicationService, private readonly transactionManager: ITransactionManager, private readonly presenterRegistry: IPresenterRegistry ) {} - public execute(params: GetIssueInvoiceUseCaseInput) { + public execute(params: GetIssuedInvoiceUseCaseInput) { const { invoice_id, companyId } = params; const idOrError = UniqueID.create(invoice_id); @@ -33,7 +33,7 @@ export class GetIssueInvoiceUseCase { return this.transactionManager.complete(async (transaction) => { try { - const invoiceOrError = await this.service.getIssueInvoiceByIdInCompany( + const invoiceOrError = await this.service.getIssuedInvoiceByIdInCompany( companyId, invoiceId, transaction diff --git a/modules/customer-invoices/src/api/application/use-cases/issued-invoices/index.ts b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/index.ts new file mode 100644 index 00000000..e5ef5e1e --- /dev/null +++ b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/index.ts @@ -0,0 +1,3 @@ +export * from "./get-issued-invoice.use-case"; +export * from "./list-issued-invoices.use-case"; +export * from "./report-issued-invoice.use-case"; diff --git a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/list-issue-invoices.use-case.ts b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/list-issued-invoices.use-case.ts similarity index 80% rename from modules/customer-invoices/src/api/application/use-cases/issue-invoices/list-issue-invoices.use-case.ts rename to modules/customer-invoices/src/api/application/use-cases/issued-invoices/list-issued-invoices.use-case.ts index 45be42aa..bb44c35b 100644 --- a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/list-issue-invoices.use-case.ts +++ b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/list-issued-invoices.use-case.ts @@ -4,16 +4,16 @@ import type { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; -import type { ListIssueInvoicesResponseDTO } from "../../../../common/dto"; +import type { ListIssuedInvoicesResponseDTO } from "../../../../common/dto"; import type { ListCustomerInvoicesPresenter } from "../../presenters"; import type { CustomerInvoiceApplicationService } from "../../services"; -type ListIssueInvoicesUseCaseInput = { +type ListIssuedInvoicesUseCaseInput = { companyId: UniqueID; criteria: Criteria; }; -export class ListIssueInvoicesUseCase { +export class ListIssuedInvoicesUseCase { constructor( private readonly service: CustomerInvoiceApplicationService, private readonly transactionManager: ITransactionManager, @@ -21,8 +21,8 @@ export class ListIssueInvoicesUseCase { ) {} public execute( - params: ListIssueInvoicesUseCaseInput - ): Promise> { + params: ListIssuedInvoicesUseCaseInput + ): Promise> { const { criteria, companyId } = params; const presenter = this.presenterRegistry.getPresenter({ resource: "customer-invoice", @@ -31,7 +31,7 @@ export class ListIssueInvoicesUseCase { return this.transactionManager.complete(async (transaction: Transaction) => { try { - const result = await this.service.findIssueInvoiceByCriteriaInCompany( + const result = await this.service.findIssuedInvoiceByCriteriaInCompany( companyId, criteria, transaction diff --git a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/report-issue-invoice.use-case.ts b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/report-issued-invoice.use-case.ts similarity index 87% rename from modules/customer-invoices/src/api/application/use-cases/issue-invoices/report-issue-invoice.use-case.ts rename to modules/customer-invoices/src/api/application/use-cases/issued-invoices/report-issued-invoice.use-case.ts index 059153d0..dc84a5b4 100644 --- a/modules/customer-invoices/src/api/application/use-cases/issue-invoices/report-issue-invoice.use-case.ts +++ b/modules/customer-invoices/src/api/application/use-cases/issued-invoices/report-issued-invoice.use-case.ts @@ -5,19 +5,19 @@ import { Result } from "@repo/rdx-utils"; import type { CustomerInvoiceApplicationService } from "../../services"; import type { CustomerInvoiceReportPDFPresenter } from "../proformas"; -type ReportIssueInvoiceUseCaseInput = { +type ReportIssuedInvoiceUseCaseInput = { companyId: UniqueID; invoice_id: string; }; -export class ReportIssueInvoiceUseCase { +export class ReportIssuedInvoiceUseCase { constructor( private readonly service: CustomerInvoiceApplicationService, private readonly transactionManager: ITransactionManager, private readonly presenterRegistry: IPresenterRegistry ) {} - public async execute(params: ReportIssueInvoiceUseCaseInput) { + public async execute(params: ReportIssuedInvoiceUseCaseInput) { const { invoice_id, companyId } = params; const idOrError = UniqueID.create(invoice_id); @@ -35,7 +35,7 @@ export class ReportIssueInvoiceUseCase { return this.transactionManager.complete(async (transaction) => { try { - const invoiceOrError = await this.service.getIssueInvoiceByIdInCompany( + const invoiceOrError = await this.service.getIssuedInvoiceByIdInCompany( companyId, invoiceId, transaction diff --git a/modules/customer-invoices/src/api/application/use-cases/proformas/issue-proforma.use-case.ts b/modules/customer-invoices/src/api/application/use-cases/proformas/issue-proforma.use-case.ts index 9bb5780f..35c0400b 100644 --- a/modules/customer-invoices/src/api/application/use-cases/proformas/issue-proforma.use-case.ts +++ b/modules/customer-invoices/src/api/application/use-cases/proformas/issue-proforma.use-case.ts @@ -9,7 +9,7 @@ import { import type { CustomerInvoiceFullPresenter } from "../../presenters"; import type { CustomerInvoiceApplicationService } from "../../services"; -type IssueCustomerInvoiceUseCaseInput = { +type IssueProformaUseCaseInput = { companyId: UniqueID; proforma_id: string; }; @@ -23,7 +23,7 @@ type IssueCustomerInvoiceUseCaseInput = { * - Marca la proforma como "issued" * - Persiste ambas dentro de la misma transacción */ -export class IssueProformaInvoiceUseCase { +export class IssueProformaUseCase { private readonly issueDomainService: IssueCustomerInvoiceDomainService; private readonly proformaDomainService: ProformaCustomerInvoiceDomainService; @@ -36,7 +36,7 @@ export class IssueProformaInvoiceUseCase { this.proformaDomainService = new ProformaCustomerInvoiceDomainService(); } - public execute(params: IssueCustomerInvoiceUseCaseInput) { + public execute(params: IssueProformaUseCaseInput) { const { proforma_id, companyId } = params; const idOrError = UniqueID.create(proforma_id); if (idOrError.isFailure) return Result.fail(idOrError.error); @@ -59,7 +59,7 @@ export class IssueProformaInvoiceUseCase { const proforma = proformaResult.data; /** 2. Generar nueva factura */ - const nextNumberResult = await this.service.getNextIssueInvoiceNumber( + const nextNumberResult = await this.service.getNextIssuedInvoiceNumber( companyId, proforma.series, transaction @@ -74,7 +74,7 @@ export class IssueProformaInvoiceUseCase { if (issuedInvoiceOrError.isFailure) return Result.fail(issuedInvoiceOrError.error); /** 5. Guardar la nueva factura */ - const saveInvoiceResult = await this.service.createIssueInvoiceInCompany( + const saveInvoiceResult = await this.service.createIssuedInvoiceInCompany( companyId, issuedInvoiceOrError.data, transaction diff --git a/modules/customer-invoices/src/api/application/use-cases/proformas/list-proformas.use-case.ts b/modules/customer-invoices/src/api/application/use-cases/proformas/list-proformas.use-case.ts index 1e9b3681..377897de 100644 --- a/modules/customer-invoices/src/api/application/use-cases/proformas/list-proformas.use-case.ts +++ b/modules/customer-invoices/src/api/application/use-cases/proformas/list-proformas.use-case.ts @@ -4,7 +4,7 @@ import type { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { Transaction } from "sequelize"; -import type { ListIssueInvoicesResponseDTO } from "../../../../common/dto"; +import type { ListIssuedInvoicesResponseDTO } from "../../../../common/dto"; import type { ListCustomerInvoicesPresenter } from "../../presenters"; import type { CustomerInvoiceApplicationService } from "../../services"; @@ -22,7 +22,7 @@ export class ListProformasUseCase { public execute( params: ListProformasUseCaseInput - ): Promise> { + ): Promise> { const { criteria, companyId } = params; const presenter = this.presenterRegistry.getPresenter({ resource: "customer-invoice", diff --git a/modules/customer-invoices/src/api/domain/entities/customer-invoice-items/customer-invoice-items.ts b/modules/customer-invoices/src/api/domain/entities/customer-invoice-items/customer-invoice-items.ts index 004e76ee..f0225fe5 100644 --- a/modules/customer-invoices/src/api/domain/entities/customer-invoice-items/customer-invoice-items.ts +++ b/modules/customer-invoices/src/api/domain/entities/customer-invoice-items/customer-invoice-items.ts @@ -1,9 +1,11 @@ -import { Tax } from "@erp/core/api"; -import { CurrencyCode, LanguageCode } from "@repo/rdx-ddd"; +import type { Tax } from "@erp/core/api"; +import type { CurrencyCode, LanguageCode } from "@repo/rdx-ddd"; import { Collection } from "@repo/rdx-utils"; + import { ItemAmount } from "../../value-objects"; import { ItemTaxes } from "../item-taxes"; -import { CustomerInvoiceItem } from "./customer-invoice-item"; + +import type { CustomerInvoiceItem } from "./customer-invoice-item"; export interface CustomerInvoiceItemsProps { items?: CustomerInvoiceItem[]; @@ -39,8 +41,9 @@ export class CustomerInvoiceItems extends Collection { // Antes de añadir un nuevo item, debo comprobar que el item a añadir // tiene el mismo "currencyCode" y "languageCode" que la colección de items. if ( - !this._languageCode.equals(item.languageCode) || - !this._currencyCode.equals(item.currencyCode) + !( + this._languageCode.equals(item.languageCode) && this._currencyCode.equals(item.currencyCode) + ) ) { return false; } diff --git a/modules/customer-invoices/src/api/domain/value-objects/invoice-recipient/invoice-recipient.ts b/modules/customer-invoices/src/api/domain/value-objects/invoice-recipient/invoice-recipient.ts index 4d5b5a7f..dd24e568 100644 --- a/modules/customer-invoices/src/api/domain/value-objects/invoice-recipient/invoice-recipient.ts +++ b/modules/customer-invoices/src/api/domain/value-objects/invoice-recipient/invoice-recipient.ts @@ -1,15 +1,15 @@ import { - City, - Country, - Name, - PostalCode, - Province, - Street, - TINNumber, + type City, + type Country, + type Name, + type PostalCode, + type Province, + type Street, + type TINNumber, ValueObject, toEmptyString, } from "@repo/rdx-ddd"; -import { Maybe, Result } from "@repo/rdx-utils"; +import { type Maybe, Result } from "@repo/rdx-utils"; export interface InvoiceRecipientProps { name: Name; diff --git a/modules/customer-invoices/src/api/index.ts b/modules/customer-invoices/src/api/index.ts index ad24c39f..3fdba499 100644 --- a/modules/customer-invoices/src/api/index.ts +++ b/modules/customer-invoices/src/api/index.ts @@ -3,7 +3,7 @@ import type { UniqueID } from "@repo/rdx-ddd"; import type { Transaction } from "sequelize"; import { buildCustomerInvoiceDependencies, models, proformasRouter } from "./infrastructure"; -import { issueInvoicesRouter } from "./infrastructure/express/issue-invoices.routes"; +import { issuedInvoicesRouter } from "./infrastructure/express/issued-invoices.routes"; export const customerInvoicesAPIModule: IModuleServer = { name: "customer-invoices", @@ -14,7 +14,7 @@ export const customerInvoicesAPIModule: IModuleServer = { // const contacts = getService("contacts"); const { logger } = params; proformasRouter(params); - issueInvoicesRouter(params); + issuedInvoicesRouter(params); logger.info("🚀 CustomerInvoices module initialized", { label: this.name }); }, diff --git a/modules/customer-invoices/src/api/infrastructure/dependencies.ts b/modules/customer-invoices/src/api/infrastructure/dependencies.ts index 1a530474..893a0cfe 100644 --- a/modules/customer-invoices/src/api/infrastructure/dependencies.ts +++ b/modules/customer-invoices/src/api/infrastructure/dependencies.ts @@ -20,14 +20,14 @@ import { CustomerInvoiceReportPresenter, CustomerInvoiceTaxesReportPresenter, DeleteProformaUseCase, - GetIssueInvoiceUseCase, + GetIssuedInvoiceUseCase, GetProformaUseCase, - IssueProformaInvoiceUseCase, + IssueProformaUseCase, ListCustomerInvoicesPresenter, - ListIssueInvoicesUseCase, + ListIssuedInvoicesUseCase, ListProformasUseCase, RecipientInvoiceFullPresenter, - ReportIssueInvoiceUseCase, + ReportIssuedInvoiceUseCase, ReportProformaUseCase, UpdateProformaUseCase, } from "../application"; @@ -52,12 +52,12 @@ export type CustomerInvoiceDeps = { update_proforma: () => UpdateProformaUseCase; delete_proforma: () => DeleteProformaUseCase; report_proforma: () => ReportProformaUseCase; - issue_proforma: () => IssueProformaInvoiceUseCase; + issue_proforma: () => IssueProformaUseCase; changeStatus_proforma: () => ChangeStatusProformaUseCase; - list_issue_invoices: () => ListIssueInvoicesUseCase; - get_issue_invoice: () => GetIssueInvoiceUseCase; - report_issue_invoice: () => ReportIssueInvoiceUseCase; + list_issued_invoices: () => ListIssuedInvoicesUseCase; + get_issued_invoice: () => GetIssuedInvoiceUseCase; + report_issued_invoice: () => ReportIssuedInvoiceUseCase; }; }; @@ -144,16 +144,16 @@ export function buildCustomerInvoiceDependencies(params: ModuleParams): Customer report_proforma: () => new ReportProformaUseCase(appService, transactionManager, presenterRegistry), issue_proforma: () => - new IssueProformaInvoiceUseCase(appService, transactionManager, presenterRegistry), + new IssueProformaUseCase(appService, transactionManager, presenterRegistry), changeStatus_proforma: () => new ChangeStatusProformaUseCase(appService, transactionManager), // Issue Invoices - list_issue_invoices: () => - new ListIssueInvoicesUseCase(appService, transactionManager, presenterRegistry), - get_issue_invoice: () => - new GetIssueInvoiceUseCase(appService, transactionManager, presenterRegistry), - report_issue_invoice: () => - new ReportIssueInvoiceUseCase(appService, transactionManager, presenterRegistry), + list_issued_invoices: () => + new ListIssuedInvoicesUseCase(appService, transactionManager, presenterRegistry), + get_issued_invoice: () => + new GetIssuedInvoiceUseCase(appService, transactionManager, presenterRegistry), + report_issued_invoice: () => + new ReportIssuedInvoiceUseCase(appService, transactionManager, presenterRegistry), }; return { diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/index.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/index.ts index 457e40a2..de2b09ca 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/index.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/index.ts @@ -1,2 +1,2 @@ -export * from "./issue-invoices"; +export * from "./issued-invoices"; export * from "./proformas"; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/index.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/index.ts deleted file mode 100644 index ebf6e6c8..00000000 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./get-issue-invoice.controller"; -export * from "./list-issue-invoices.controller"; -export * from "./report-issue-invoice.controller"; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/get-issue-invoice.controller.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/get-issued-invoice.controller.ts similarity index 85% rename from modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/get-issue-invoice.controller.ts rename to modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/get-issued-invoice.controller.ts index 6bb2fd44..027b5c6a 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/get-issue-invoice.controller.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/get-issued-invoice.controller.ts @@ -1,10 +1,10 @@ import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api"; -import type { GetIssueInvoiceUseCase } from "../../../../application"; +import type { GetIssuedInvoiceUseCase } from "../../../../application"; import { customerInvoicesApiErrorMapper } from "../../customer-invoices-api-error-mapper"; export class GetIssueInvoiceController extends ExpressController { - public constructor(private readonly useCase: GetIssueInvoiceUseCase) { + public constructor(private readonly useCase: GetIssuedInvoiceUseCase) { super(); this.errorMapper = customerInvoicesApiErrorMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/index.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/index.ts new file mode 100644 index 00000000..9a41c812 --- /dev/null +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/index.ts @@ -0,0 +1,3 @@ +export * from "./get-issued-invoice.controller"; +export * from "./list-issued-invoices.controller"; +export * from "./report-issued-invoice.controller"; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/list-issue-invoices.controller.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/list-issued-invoices.controller.ts similarity index 86% rename from modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/list-issue-invoices.controller.ts rename to modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/list-issued-invoices.controller.ts index 24a9f150..8cd49683 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/list-issue-invoices.controller.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/list-issued-invoices.controller.ts @@ -1,11 +1,11 @@ import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api"; import { Criteria } from "@repo/rdx-criteria/server"; -import type { ListIssueInvoicesUseCase } from "../../../../application"; +import type { ListIssuedInvoicesUseCase } from "../../../../application"; import { customerInvoicesApiErrorMapper } from "../../customer-invoices-api-error-mapper"; -export class ListIssueInvoicesController extends ExpressController { - public constructor(private readonly useCase: ListIssueInvoicesUseCase) { +export class ListIssuedInvoicesController extends ExpressController { + public constructor(private readonly useCase: ListIssuedInvoicesUseCase) { super(); this.errorMapper = customerInvoicesApiErrorMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/report-issue-invoice.controller.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/report-issued-invoice.controller.ts similarity index 79% rename from modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/report-issue-invoice.controller.ts rename to modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/report-issued-invoice.controller.ts index b46f2dcc..034e1b23 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/issue-invoices/report-issue-invoice.controller.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/issued-invoices/report-issued-invoice.controller.ts @@ -1,10 +1,10 @@ import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api"; -import type { ReportIssueInvoiceUseCase } from "../../../../application"; +import type { ReportIssuedInvoiceUseCase } from "../../../../application"; import { customerInvoicesApiErrorMapper } from "../../customer-invoices-api-error-mapper"; -export class ReportIssueInvoiceController extends ExpressController { - public constructor(private readonly useCase: ReportIssueInvoiceUseCase) { +export class ReportIssuedInvoiceController extends ExpressController { + public constructor(private readonly useCase: ReportIssuedInvoiceUseCase) { super(); this.errorMapper = customerInvoicesApiErrorMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/express/controllers/proformas/issue-proforma.controller.ts b/modules/customer-invoices/src/api/infrastructure/express/controllers/proformas/issue-proforma.controller.ts index a2698b59..667f8744 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/controllers/proformas/issue-proforma.controller.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/controllers/proformas/issue-proforma.controller.ts @@ -1,10 +1,10 @@ import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api"; -import type { IssueProformaInvoiceUseCase } from "../../../../application"; +import type { IssueProformaUseCase } from "../../../../application"; import { customerInvoicesApiErrorMapper } from "../../customer-invoices-api-error-mapper"; export class IssueProformaController extends ExpressController { - public constructor(private readonly useCase: IssueProformaInvoiceUseCase) { + public constructor(private readonly useCase: IssueProformaUseCase) { super(); this.errorMapper = customerInvoicesApiErrorMapper; diff --git a/modules/customer-invoices/src/api/infrastructure/express/customer-invoices-api-error-mapper.ts b/modules/customer-invoices/src/api/infrastructure/express/customer-invoices-api-error-mapper.ts index 718c1aa6..0ffc0aa4 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/customer-invoices-api-error-mapper.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/customer-invoices-api-error-mapper.ts @@ -11,9 +11,11 @@ import { import { type CustomerInvoiceIdAlreadyExistsError, type EntityIsNotProformaError, + type InvalidProformaTransitionError, type ProformaCannotBeConvertedToInvoiceError, isCustomerInvoiceIdAlreadyExistsError, isEntityIsNotProformaError, + isInvalidProformaTransitionError, isProformaCannotBeConvertedToInvoiceError, isProformaCannotBeDeletedError, } from "../../domain"; @@ -38,6 +40,15 @@ const entityIsNotProformaError: ErrorToApiRule = { ), }; +const proformaTransitionRule: ErrorToApiRule = { + priority: 120, + matches: (e) => isInvalidProformaTransitionError(e), + build: (e) => + new ValidationApiError( + (e as InvalidProformaTransitionError).message || "Invalid transition for proforma." + ), +}; + const proformaConversionRule: ErrorToApiRule = { priority: 120, matches: (e) => isProformaCannotBeConvertedToInvoiceError(e), @@ -62,4 +73,5 @@ export const customerInvoicesApiErrorMapper: ApiErrorMapper = ApiErrorMapper.def .register(invoiceDuplicateRule) .register(entityIsNotProformaError) .register(proformaConversionRule) - .register(proformaCannotBeDeletedRule); + .register(proformaCannotBeDeletedRule) + .register(proformaTransitionRule); diff --git a/modules/customer-invoices/src/api/infrastructure/express/index.ts b/modules/customer-invoices/src/api/infrastructure/express/index.ts index 1901664b..f8fd815e 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/index.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/index.ts @@ -1,2 +1,2 @@ -export * from "./issue-invoices.routes"; +export * from "./issued-invoices.routes"; export * from "./proformas.routes"; diff --git a/modules/customer-invoices/src/api/infrastructure/express/issue-invoices.routes.ts b/modules/customer-invoices/src/api/infrastructure/express/issued-invoices.routes.ts similarity index 78% rename from modules/customer-invoices/src/api/infrastructure/express/issue-invoices.routes.ts rename to modules/customer-invoices/src/api/infrastructure/express/issued-invoices.routes.ts index 98fa1fd7..b1404a0c 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/issue-invoices.routes.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/issued-invoices.routes.ts @@ -6,18 +6,18 @@ import type { Sequelize } from "sequelize"; import { GetIssueInvoiceByIdRequestSchema, - ListIssueInvoicesRequestSchema, + ListIssuedInvoicesRequestSchema, ReportIssueInvoiceByIdRequestSchema, } from "../../../common/dto"; import { buildCustomerInvoiceDependencies } from "../dependencies"; import { GetIssueInvoiceController, - ListIssueInvoicesController, - ReportIssueInvoiceController, + ListIssuedInvoicesController, + ReportIssuedInvoiceController, } from "./controllers"; -export const issueInvoicesRouter = (params: ModuleParams) => { +export const issuedInvoicesRouter = (params: ModuleParams) => { const { app, baseRoutePath, logger } = params as { app: Application; database: Sequelize; @@ -49,10 +49,10 @@ export const issueInvoicesRouter = (params: ModuleParams) => { router.get( "/", //checkTabContext, - validateRequest(ListIssueInvoicesRequestSchema, "params"), + validateRequest(ListIssuedInvoicesRequestSchema, "params"), async (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.useCases.list_issue_invoices(); - const controller = new ListIssueInvoicesController(useCase /*, deps.presenters.list */); + const useCase = deps.useCases.list_issued_invoices(); + const controller = new ListIssuedInvoicesController(useCase /*, deps.presenters.list */); return controller.execute(req, res, next); } ); @@ -62,7 +62,7 @@ export const issueInvoicesRouter = (params: ModuleParams) => { //checkTabContext, validateRequest(GetIssueInvoiceByIdRequestSchema, "params"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.useCases.get_issue_invoice(); + const useCase = deps.useCases.get_issued_invoice(); const controller = new GetIssueInvoiceController(useCase); return controller.execute(req, res, next); } @@ -73,11 +73,11 @@ export const issueInvoicesRouter = (params: ModuleParams) => { //checkTabContext, validateRequest(ReportIssueInvoiceByIdRequestSchema, "params"), (req: Request, res: Response, next: NextFunction) => { - const useCase = deps.useCases.report_issue_invoice(); - const controller = new ReportIssueInvoiceController(useCase); + const useCase = deps.useCases.report_issued_invoice(); + const controller = new ReportIssuedInvoiceController(useCase); return controller.execute(req, res, next); } ); - app.use(`${baseRoutePath}/issue-invoices`, router); + app.use(`${baseRoutePath}/issued-invoices`, router); }; diff --git a/modules/customer-invoices/src/api/infrastructure/express/proformas.routes.ts b/modules/customer-invoices/src/api/infrastructure/express/proformas.routes.ts index add75c8f..ea6ba2e1 100644 --- a/modules/customer-invoices/src/api/infrastructure/express/proformas.routes.ts +++ b/modules/customer-invoices/src/api/infrastructure/express/proformas.routes.ts @@ -1,5 +1,9 @@ import { type RequestWithAuth, enforceTenant, enforceUser, mockUser } 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 { ChangeStatusProformaByIdParamsRequestSchema, ChangeStatusProformaByIdRequestSchema, @@ -11,11 +15,7 @@ import { ReportProformaByIdRequestSchema, UpdateProformaByIdParamsRequestSchema, UpdateProformaByIdRequestSchema, -} from "@erp/customer-invoices/common"; -import type { ILogger } from "@repo/rdx-logger"; -import { type Application, type NextFunction, type Request, type Response, Router } from "express"; -import type { Sequelize } from "sequelize"; - +} from "../../../common"; import { buildCustomerInvoiceDependencies } from "../dependencies"; import { @@ -23,7 +23,7 @@ import { CreateProformaController, DeleteProformaController, GetProformaController, - IssueProformaController, + IssueProformaController as IssuedProformaController, ListProformasController, ReportProformaController, UpdateProformaController, @@ -150,7 +150,7 @@ export const proformasRouter = (params: ModuleParams) => { (req: Request, res: Response, next: NextFunction) => { const useCase = deps.useCases.issue_proforma(); - const controller = new IssueProformaController(useCase); + const controller = new IssuedProformaController(useCase); return controller.execute(req, res, next); } ); diff --git a/modules/customer-invoices/src/common/dto/request/index.ts b/modules/customer-invoices/src/common/dto/request/index.ts index 457e40a2..de2b09ca 100644 --- a/modules/customer-invoices/src/common/dto/request/index.ts +++ b/modules/customer-invoices/src/common/dto/request/index.ts @@ -1,2 +1,2 @@ -export * from "./issue-invoices"; +export * from "./issued-invoices"; export * from "./proformas"; diff --git a/modules/customer-invoices/src/common/dto/request/issue-invoices/index.ts b/modules/customer-invoices/src/common/dto/request/issue-invoices/index.ts deleted file mode 100644 index 1c4bb67f..00000000 --- a/modules/customer-invoices/src/common/dto/request/issue-invoices/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./get-issue-invoice-by-id.request.dto"; -export * from "./list-issue-invoices.request.dto"; -export * from "./report-issue-invoice-by-id.request.dto"; diff --git a/modules/customer-invoices/src/common/dto/request/issue-invoices/list-issue-invoices.request.dto.ts b/modules/customer-invoices/src/common/dto/request/issue-invoices/list-issue-invoices.request.dto.ts deleted file mode 100644 index 618e85c8..00000000 --- a/modules/customer-invoices/src/common/dto/request/issue-invoices/list-issue-invoices.request.dto.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CriteriaSchema } from "@erp/core"; -import { z } from "zod/v4"; - -export const ListIssueInvoicesRequestSchema = CriteriaSchema; -export type ListIssueInvoicesRequestDTO = z.infer; diff --git a/modules/customer-invoices/src/common/dto/request/issue-invoices/get-issue-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/issued-invoices/get-issued-invoice-by-id.request.dto.ts similarity index 100% rename from modules/customer-invoices/src/common/dto/request/issue-invoices/get-issue-invoice-by-id.request.dto.ts rename to modules/customer-invoices/src/common/dto/request/issued-invoices/get-issued-invoice-by-id.request.dto.ts diff --git a/modules/customer-invoices/src/common/dto/request/issued-invoices/index.ts b/modules/customer-invoices/src/common/dto/request/issued-invoices/index.ts new file mode 100644 index 00000000..ef691808 --- /dev/null +++ b/modules/customer-invoices/src/common/dto/request/issued-invoices/index.ts @@ -0,0 +1,3 @@ +export * from "./get-issued-invoice-by-id.request.dto"; +export * from "./list-issued-invoices.request.dto"; +export * from "./report-issued-invoice-by-id.request.dto"; diff --git a/modules/customer-invoices/src/common/dto/request/issued-invoices/list-issued-invoices.request.dto.ts b/modules/customer-invoices/src/common/dto/request/issued-invoices/list-issued-invoices.request.dto.ts new file mode 100644 index 00000000..6540bbc5 --- /dev/null +++ b/modules/customer-invoices/src/common/dto/request/issued-invoices/list-issued-invoices.request.dto.ts @@ -0,0 +1,5 @@ +import { CriteriaSchema } from "@erp/core"; +import type { z } from "zod/v4"; + +export const ListIssuedInvoicesRequestSchema = CriteriaSchema; +export type ListIssuedInvoicesRequestDTO = z.infer; diff --git a/modules/customer-invoices/src/common/dto/request/issue-invoices/report-issue-invoice-by-id.request.dto.ts b/modules/customer-invoices/src/common/dto/request/issued-invoices/report-issued-invoice-by-id.request.dto.ts similarity index 100% rename from modules/customer-invoices/src/common/dto/request/issue-invoices/report-issue-invoice-by-id.request.dto.ts rename to modules/customer-invoices/src/common/dto/request/issued-invoices/report-issued-invoice-by-id.request.dto.ts diff --git a/modules/customer-invoices/src/common/dto/response/index.ts b/modules/customer-invoices/src/common/dto/response/index.ts index 457e40a2..de2b09ca 100644 --- a/modules/customer-invoices/src/common/dto/response/index.ts +++ b/modules/customer-invoices/src/common/dto/response/index.ts @@ -1,2 +1,2 @@ -export * from "./issue-invoices"; +export * from "./issued-invoices"; export * from "./proformas"; diff --git a/modules/customer-invoices/src/common/dto/response/issue-invoices/index.ts b/modules/customer-invoices/src/common/dto/response/issue-invoices/index.ts deleted file mode 100644 index 61996aea..00000000 --- a/modules/customer-invoices/src/common/dto/response/issue-invoices/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./get-issue-invoice-by-id.response.dto"; -export * from "./list-issue-invoices.response.dto"; diff --git a/modules/customer-invoices/src/common/dto/response/issue-invoices/get-issue-invoice-by-id.response.dto.ts b/modules/customer-invoices/src/common/dto/response/issued-invoices/get-issued-invoice-by-id.response.dto.ts similarity index 91% rename from modules/customer-invoices/src/common/dto/response/issue-invoices/get-issue-invoice-by-id.response.dto.ts rename to modules/customer-invoices/src/common/dto/response/issued-invoices/get-issued-invoice-by-id.response.dto.ts index f8f7f5f0..28104031 100644 --- a/modules/customer-invoices/src/common/dto/response/issue-invoices/get-issue-invoice-by-id.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/issued-invoices/get-issued-invoice-by-id.response.dto.ts @@ -1,7 +1,7 @@ import { MetadataSchema, MoneySchema, PercentageSchema, QuantitySchema } from "@erp/core"; import { z } from "zod/v4"; -export const GetIssueInvoiceByIdResponseSchema = z.object({ +export const GetIssuedInvoiceByIdResponseSchema = z.object({ id: z.uuid(), company_id: z.uuid(), @@ -79,4 +79,4 @@ export const GetIssueInvoiceByIdResponseSchema = z.object({ metadata: MetadataSchema.optional(), }); -export type GetIssueInvoiceByIdResponseDTO = z.infer; +export type GetIssuedInvoiceByIdResponseDTO = z.infer; diff --git a/modules/customer-invoices/src/common/dto/response/issued-invoices/index.ts b/modules/customer-invoices/src/common/dto/response/issued-invoices/index.ts new file mode 100644 index 00000000..c4748721 --- /dev/null +++ b/modules/customer-invoices/src/common/dto/response/issued-invoices/index.ts @@ -0,0 +1,2 @@ +export * from "./get-issued-invoice-by-id.response.dto"; +export * from "./list-issued-invoices.response.dto"; diff --git a/modules/customer-invoices/src/common/dto/response/issue-invoices/list-issue-invoices.response.dto.ts b/modules/customer-invoices/src/common/dto/response/issued-invoices/list-issued-invoices.response.dto.ts similarity index 86% rename from modules/customer-invoices/src/common/dto/response/issue-invoices/list-issue-invoices.response.dto.ts rename to modules/customer-invoices/src/common/dto/response/issued-invoices/list-issued-invoices.response.dto.ts index ca372be0..293536af 100644 --- a/modules/customer-invoices/src/common/dto/response/issue-invoices/list-issue-invoices.response.dto.ts +++ b/modules/customer-invoices/src/common/dto/response/issued-invoices/list-issued-invoices.response.dto.ts @@ -6,7 +6,7 @@ import { } from "@erp/core"; import { z } from "zod/v4"; -export const ListIssueInvoicesResponseSchema = createPaginatedListSchema( +export const ListIssuedInvoicesResponseSchema = createPaginatedListSchema( z.object({ id: z.uuid(), company_id: z.uuid(), @@ -51,4 +51,4 @@ export const ListIssueInvoicesResponseSchema = createPaginatedListSchema( }) ); -export type ListIssueInvoicesResponseDTO = z.infer; +export type ListIssuedInvoicesResponseDTO = z.infer; diff --git a/modules/customer-invoices/src/common/locales/en.json b/modules/customer-invoices/src/common/locales/en.json index 0807031e..bcaa6349 100644 --- a/modules/customer-invoices/src/common/locales/en.json +++ b/modules/customer-invoices/src/common/locales/en.json @@ -1,16 +1,20 @@ { "common": { + "more_actions": "More actions", "append_empty_row": "Append row", "append_empty_row_tooltip": "Append a empty row", + "edit_row": "Edit", "duplicate_row": "Duplicate", "duplicate_selected_rows": "Duplicate", "duplicate_selected_rows_tooltip": "Duplicate selected row(s)", "remove_selected_rows": "Remove", "remove_selected_rows_tooltip": "Remove selected row(s)", + "download_pdf": "Download PDF", + "send_email": "Send email", "insert_row_above": "Insert row above", "insert_row_below": "Insert row below", - "remove_row": "Remove", + "delete_row": "Delete", "actions": "Actions", "rows_selected": "{{count}} fila(s) seleccionadas.", @@ -22,12 +26,15 @@ }, "catalog": { - "status": { - "draft": "Draft", - "issued": "Issued", - "sent": "Sent", - "received": "Received", - "rejected": "Rejected" + "proformas": { + "status": { + "all": "All", + "draft": "Draft", + "sent": "Sent", + "approved": "Approved", + "rejected": "Rejected", + "issued": "Issued" + } } }, "pages": { @@ -40,9 +47,11 @@ "grid_columns": { "invoice_number": "Inv. number", "series": "Serie", + "reference": "Reference", "status": "Status", "invoice_date": "Proforma date", "operation_date": "Operation date", + "recipient": "Customer", "recipient_tin": "TIN", "recipient_name": "Customer name", "recipient_street": "Street", @@ -50,7 +59,10 @@ "recipient_province": "Province", "recipient_postal_code": "Postal code", "recipient_country": "Country", - "total_amount": "Total price" + "subtotal_amount": "Subtotal", + "discount_amount": "Discount", + "taxes_amount": "Taxes", + "total_amount": "Total" } }, "create": { diff --git a/modules/customer-invoices/src/common/locales/es.json b/modules/customer-invoices/src/common/locales/es.json index 5d4b3487..6be4f815 100644 --- a/modules/customer-invoices/src/common/locales/es.json +++ b/modules/customer-invoices/src/common/locales/es.json @@ -1,16 +1,20 @@ { "common": { + "more_actions": "Más acciones", "append_empty_row": "Añadir fila", "append_empty_row_tooltip": "Añadir una fila vacía", + "edit_row": "Modificar", "duplicate_row": "Duplicar", "duplicate_selected_rows": "Duplicar", "duplicate_selected_rows_tooltip": "Duplicar fila(s) seleccionada(s)", "remove_selected_rows": "Eliminar", "remove_selected_rows_tooltip": "Eliminar fila(s) seleccionada(s)", + "download_pdf": "Descargar en PDF", + "send_email": "Enviar por email", "insert_row_above": "Insertar fila arriba", "insert_row_below": "Insertar fila abajo", - "remove_row": "Eliminar", + "delete_row": "Eliminar", "actions": "Acciones", "rows_selected": "{{count}} fila(s) seleccionadas.", @@ -21,12 +25,15 @@ "clear": "Limpiar" }, "catalog": { - "status": { - "draft": "Borrador", - "issued": "Emitida", - "sent": "Enviada", - "received": "Recibida", - "rejected": "Rechazada" + "proformas": { + "status": { + "all": "Todas", + "draft": "Borradores", + "sent": "Enviadas", + "approved": "Aprovadas", + "rejected": "Rechazadas", + "issued": "Emitidas" + } } }, "pages": { @@ -39,9 +46,11 @@ "grid_columns": { "invoice_number": "Nº proforma", "series": "Serie", + "reference": "Reference", "status": "Estado", "invoice_date": "Fecha de proforma", "operation_date": "Fecha de operación", + "recipient": "Cliente", "recipient_tin": "NIF/CIF", "recipient_name": "Cliente", "recipient_street": "Dirección", @@ -49,6 +58,9 @@ "recipient_province": "Provincia", "recipient_postal_code": "Código postal", "recipient_country": "País", + "subtotal_amount": "Subtotal", + "discount_amount": "Descuentos", + "taxes_amount": "Impuestos", "total_amount": "Importe total" } }, diff --git a/modules/customer-invoices/src/web/adapters/invoice-dto.adapter.ts b/modules/customer-invoices/src/web/adapters/invoice-dto.adapter.ts index 9698a3c6..dcb0842f 100644 --- a/modules/customer-invoices/src/web/adapters/invoice-dto.adapter.ts +++ b/modules/customer-invoices/src/web/adapters/invoice-dto.adapter.ts @@ -1,7 +1,7 @@ import { MoneyDTOHelper, PercentageDTOHelper, QuantityDTOHelper } from "@erp/core"; import type { - GetIssueInvoiceByIdResponseDTO, + GetIssuedInvoiceByIdResponseDTO, UpdateCustomerInvoiceByIdRequestDTO, } from "../../common"; import type { InvoiceContextValue } from "../context"; @@ -11,7 +11,7 @@ import type { InvoiceFormData } from "../schemas/invoice.form.schema"; * Convierte el DTO completo de API a datos numéricos para el formulario. */ export const invoiceDtoToFormAdapter = { - fromDto(dto: GetIssueInvoiceByIdResponseDTO, context: InvoiceContextValue): InvoiceFormData { + fromDto(dto: GetIssuedInvoiceByIdResponseDTO, context: InvoiceContextValue): InvoiceFormData { const { taxCatalog } = context; return { invoice_number: dto.invoice_number, diff --git a/modules/customer-invoices/src/web/globals.css b/modules/customer-invoices/src/web/globals.css index c407c45a..64dffa04 100644 --- a/modules/customer-invoices/src/web/globals.css +++ b/modules/customer-invoices/src/web/globals.css @@ -1,2 +1 @@ -@source "./components"; -@source "./pages"; +@source "**/*.{ts,tsx}"; diff --git a/modules/customer-invoices/src/web/issue-invoices/hooks/index.ts b/modules/customer-invoices/src/web/issue-invoices/hooks/index.ts deleted file mode 100644 index a38a2a65..00000000 --- a/modules/customer-invoices/src/web/issue-invoices/hooks/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./use-issue-invoice-query"; -export * from "./use-issue-invoices-query"; diff --git a/modules/customer-invoices/src/web/issue-invoices/issue-invoice.api.schema.ts b/modules/customer-invoices/src/web/issue-invoices/issue-invoice.api.schema.ts deleted file mode 100644 index cd90b687..00000000 --- a/modules/customer-invoices/src/web/issue-invoices/issue-invoice.api.schema.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { - GetIssueInvoiceByIdResponseSchema, - ListIssueInvoicesResponseSchema, -} from "@erp/customer-invoices/common"; -import type { ArrayElement } from "@repo/rdx-utils"; -import type { z } from "zod/v4"; - -// IssueInvoices -export const IssueInvoiceSchema = GetIssueInvoiceByIdResponseSchema.omit({ - metadata: true, -}); - -export type IssueInvoice = z.infer; -export type IssueInvoiceRecipient = IssueInvoice["recipient"]; -export type IssueInvoiceItem = ArrayElement; - -// Resultado de consulta con criteria (paginado, etc.) -export const IssueInvoiceSummaryPageSchema = ListIssueInvoicesResponseSchema.omit({ - metadata: true, -}); - -export type IssueInvoiceSummaryPage = z.infer; -export type IssueInvoiceSummary = Omit, "metadata">; diff --git a/modules/customer-invoices/src/web/issued-invoices/hooks/index.ts b/modules/customer-invoices/src/web/issued-invoices/hooks/index.ts new file mode 100644 index 00000000..cef8ba5f --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/hooks/index.ts @@ -0,0 +1,2 @@ +export * from "./use-issued-invoice-query"; +export * from "./use-issued-invoices-query"; diff --git a/modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoice-query.ts b/modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoice-query.ts similarity index 65% rename from modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoice-query.ts rename to modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoice-query.ts index 9d6e112d..94f989af 100644 --- a/modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoice-query.ts +++ b/modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoice-query.ts @@ -1,26 +1,26 @@ import { useDataSource } from "@erp/core/hooks"; import { type DefaultError, type QueryKey, useQuery } from "@tanstack/react-query"; -import type { IssueInvoice } from "../issue-invoice.api.schema"; +import type { IssueInvoice } from "../issued-invoice.api.schema"; -export const ISSUE_INVOICE_QUERY_KEY = (id: string): QueryKey => ["issue-invoice", id] as const; +export const ISSUED_INVOICE_QUERY_KEY = (id: string): QueryKey => ["issued-invoice", id] as const; type InvoiceQueryOptions = { enabled?: boolean; }; -export const useIssueInvoiceQuery = (issueInvoiceId?: string, options?: InvoiceQueryOptions) => { +export const useIssuedInvoiceQuery = (issuedInvoiceId?: string, options?: InvoiceQueryOptions) => { const dataSource = useDataSource(); - const enabled = (options?.enabled ?? true) && !!issueInvoiceId; + const enabled = (options?.enabled ?? true) && !!issuedInvoiceId; return useQuery({ - queryKey: ISSUE_INVOICE_QUERY_KEY(issueInvoiceId ?? "unknown"), + queryKey: ISSUED_INVOICE_QUERY_KEY(issuedInvoiceId ?? "unknown"), queryFn: async (context) => { const { signal } = context; - if (!issueInvoiceId) { - if (!issueInvoiceId) throw new Error("issueInvoiceId is required"); + if (!issuedInvoiceId) { + if (!issuedInvoiceId) throw new Error("issueInvoiceId is required"); } - return await dataSource.getOne("issue-invoices", issueInvoiceId, { + return await dataSource.getOne("issued-invoices", issuedInvoiceId, { signal, }); }, diff --git a/modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoices-query.ts b/modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoices-query.ts similarity index 64% rename from modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoices-query.ts rename to modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoices-query.ts index a368e01c..07804d5a 100644 --- a/modules/customer-invoices/src/web/issue-invoices/hooks/use-issue-invoices-query.ts +++ b/modules/customer-invoices/src/web/issued-invoices/hooks/use-issued-invoices-query.ts @@ -2,10 +2,10 @@ import type { CriteriaDTO } from "@erp/core"; import { useDataSource } from "@erp/core/hooks"; import { type DefaultError, type QueryKey, useQuery } from "@tanstack/react-query"; -import type { IssueInvoiceSummaryPage } from "../issue-invoice.api.schema"; +import type { IssuedInvoicesummaryPage } from "../issued-invoice.api.schema"; -export const ISSUE_INVOICES_QUERY_KEY = (criteria: CriteriaDTO): QueryKey => [ - "issue-invoice", +export const ISSUED_INVOICES_QUERY_KEY = (criteria: CriteriaDTO): QueryKey => [ + "issued-invoice", { pageNumber: criteria.pageNumber ?? 0, pageSize: criteria.pageSize ?? 10, @@ -16,21 +16,21 @@ export const ISSUE_INVOICES_QUERY_KEY = (criteria: CriteriaDTO): QueryKey => [ }, ]; -type IssueInvoicesQueryOptions = { +type IssuedInvoicesQueryOptions = { enabled?: boolean; criteria?: CriteriaDTO; }; // Obtener todas las facturas -export const useIssueInvoicesQuery = (options?: IssueInvoicesQueryOptions) => { +export const useIssuedInvoicesQuery = (options?: IssuedInvoicesQueryOptions) => { const dataSource = useDataSource(); const enabled = options?.enabled ?? true; const criteria = options?.criteria ?? {}; - return useQuery({ - queryKey: ISSUE_INVOICES_QUERY_KEY(criteria), + return useQuery({ + queryKey: ISSUED_INVOICES_QUERY_KEY(criteria), queryFn: async ({ signal }) => { - return await dataSource.getList("issue-invoices", { + return await dataSource.getList("issued-invoices", { signal, ...criteria, }); diff --git a/modules/customer-invoices/src/web/issue-invoices/index.ts b/modules/customer-invoices/src/web/issued-invoices/index.ts similarity index 100% rename from modules/customer-invoices/src/web/issue-invoices/index.ts rename to modules/customer-invoices/src/web/issued-invoices/index.ts diff --git a/modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume-dto.adapter.ts b/modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume-dto.adapter.ts similarity index 87% rename from modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume-dto.adapter.ts rename to modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume-dto.adapter.ts index 68520563..ee99761b 100644 --- a/modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume-dto.adapter.ts +++ b/modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume-dto.adapter.ts @@ -1,16 +1,16 @@ import { MoneyDTOHelper, PercentageDTOHelper, formatCurrency } from "@erp/core"; -import type { IssueInvoiceSummaryPage } from "./issue-invoice.api.schema"; +import type { IssuedInvoicesummaryPage } from "./issued-invoice.api.schema"; import type { - IssueInvoiceSummaryData, - IssueInvoiceSummaryPageData, -} from "./issue-invoice-resume.form.schema"; + IssuedInvoicesummaryData, + IssuedInvoicesummaryPageData, +} from "./issued-invoice-resume.form.schema"; /** * Convierte el DTO completo de API a datos numéricos para el formulario. */ export const IssueInvoiceResumeDtoAdapter = { - fromDto(pageDto: IssueInvoiceSummaryPage, context?: unknown): IssueInvoiceSummaryPageData { + fromDto(pageDto: IssuedInvoicesummaryPage, context?: unknown): IssuedInvoicesummaryPageData { return { ...pageDto, items: pageDto.items.map( @@ -64,7 +64,7 @@ export const IssueInvoiceResumeDtoAdapter = { ), //taxes: dto.taxes, - }) as unknown as IssueInvoiceSummaryData + }) as unknown as IssuedInvoicesummaryData ), }; }, diff --git a/modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume.form.schema.ts b/modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume.form.schema.ts similarity index 56% rename from modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume.form.schema.ts rename to modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume.form.schema.ts index 8cd0f94e..d657b331 100644 --- a/modules/customer-invoices/src/web/issue-invoices/issue-invoice-resume.form.schema.ts +++ b/modules/customer-invoices/src/web/issued-invoices/issued-invoice-resume.form.schema.ts @@ -1,6 +1,6 @@ -import type { IssueInvoiceSummary, IssueInvoiceSummaryPage } from "./issue-invoice.api.schema"; +import type { IssuedInvoicesummary, IssuedInvoicesummaryPage } from "./issued-invoice.api.schema"; -export type IssueInvoiceSummaryData = IssueInvoiceSummary & { +export type IssuedInvoicesummaryData = IssuedInvoicesummary & { subtotal_amount_fmt: string; subtotal_amount: number; @@ -20,6 +20,6 @@ export type IssueInvoiceSummaryData = IssueInvoiceSummary & { total_amount: number; }; -export type IssueInvoiceSummaryPageData = IssueInvoiceSummaryPage & { - items: IssueInvoiceSummary[]; +export type IssuedInvoicesummaryPageData = IssuedInvoicesummaryPage & { + items: IssuedInvoicesummary[]; }; diff --git a/modules/customer-invoices/src/web/issued-invoices/issued-invoice.api.schema.ts b/modules/customer-invoices/src/web/issued-invoices/issued-invoice.api.schema.ts new file mode 100644 index 00000000..39ec9442 --- /dev/null +++ b/modules/customer-invoices/src/web/issued-invoices/issued-invoice.api.schema.ts @@ -0,0 +1,26 @@ +import { + GetIssuedInvoiceByIdResponseSchema, + ListIssuedInvoicesResponseSchema, +} from "@erp/customer-invoices/common"; +import type { ArrayElement } from "@repo/rdx-utils"; +import type { z } from "zod/v4"; + +// IssuedInvoices +export const IssuedInvoiceschema = GetIssuedInvoiceByIdResponseSchema.omit({ + metadata: true, +}); + +export type IssueInvoice = z.infer; +export type IssueInvoiceRecipient = IssueInvoice["recipient"]; +export type IssueInvoiceItem = ArrayElement; + +// Resultado de consulta con criteria (paginado, etc.) +export const IssuedInvoicesummaryPageSchema = ListIssuedInvoicesResponseSchema.omit({ + metadata: true, +}); + +export type IssuedInvoicesummaryPage = z.infer; +export type IssuedInvoicesummary = Omit< + ArrayElement, + "metadata" +>; diff --git a/modules/customer-invoices/src/web/pages/list/invoices-list-grid.tsx b/modules/customer-invoices/src/web/pages/list/invoices-list-grid.tsx index be1c8d71..6664a381 100644 --- a/modules/customer-invoices/src/web/pages/list/invoices-list-grid.tsx +++ b/modules/customer-invoices/src/web/pages/list/invoices-list-grid.tsx @@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom"; import { usePinnedPreviewSheet } from "../../hooks"; import { useTranslation } from "../../i18n"; -import { useProformasGridColumns } from "../../proformas/pages/list/use-proformas-grid-columns"; import type { InvoiceSummaryFormData, InvoicesPageFormData } from "../../schemas"; export type InvoiceUpdateCompProps = { diff --git a/modules/customer-invoices/src/web/pages/list/invoices-list-page.tsx b/modules/customer-invoices/src/web/pages/list/invoices-list-page.tsx index b2004da1..95ec7b74 100644 --- a/modules/customer-invoices/src/web/pages/list/invoices-list-page.tsx +++ b/modules/customer-invoices/src/web/pages/list/invoices-list-page.tsx @@ -10,8 +10,6 @@ import { invoiceResumeDtoToFormAdapter } from "../../adapters/invoice-resume-dto import { useInvoicesQuery } from "../../hooks"; import { useTranslation } from "../../i18n"; -import { InvoicesListGrid } from "./invoices-list-grid"; - export const InvoiceListPage = () => { const { t } = useTranslation(); const navigate = useNavigate(); @@ -95,16 +93,7 @@ export const InvoiceListPage = () => {
- + <>hola
diff --git a/modules/customer-invoices/src/web/proformas/pages/list/hooks/index.ts b/modules/customer-invoices/src/web/proformas/pages/list/hooks/index.ts index cfe5fc47..928ebc83 100644 --- a/modules/customer-invoices/src/web/proformas/pages/list/hooks/index.ts +++ b/modules/customer-invoices/src/web/proformas/pages/list/hooks/index.ts @@ -1 +1,2 @@ +export * from "./use-proformas-grid-columns"; export * from "./use-proformas-list"; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-grid-columns.tsx b/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-grid-columns.tsx new file mode 100644 index 00000000..8e03940a --- /dev/null +++ b/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-grid-columns.tsx @@ -0,0 +1,443 @@ +import { formatDate } from "@erp/core/client"; +import { DataTableColumnHeader } from "@repo/rdx-ui/components"; +import { + Button, + ButtonGroup, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@repo/shadcn-ui/components"; +import type { ColumnDef } from "@tanstack/react-table"; +import { + CopyIcon, + DownloadIcon, + EditIcon, + MailIcon, + MoreVerticalIcon, + Trash2Icon, +} from "lucide-react"; +import * as React from "react"; + +import { useTranslation } from "../../../../i18n"; +import type { ProformaSummaryData } from "../../../schema"; +import { ProformaStatusBadge } from "../ui"; + +type GridActionHandlers = { + onEdit?: (proforma: ProformaSummaryData) => void; + onDuplicate?: (proforma: ProformaSummaryData) => void; + onDownloadPdf?: (proforma: ProformaSummaryData) => void; + onSendEmail?: (proforma: ProformaSummaryData) => void; + onDelete?: (proforma: ProformaSummaryData) => void; +}; + +export function useProformasGridColumns( + actionHandlers: GridActionHandlers = {} +): ColumnDef[] { + const { t } = useTranslation(); + const { onEdit, onDuplicate, onDownloadPdf, onSendEmail, onDelete } = actionHandlers; + + return React.useMemo[]>( + () => [ + // Nº + { + accessorKey: "invoice_number", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
{row.original.invoice_number}
+ ), + enableHiding: false, + enableSorting: false, + size: 160, + minSize: 120, + meta: { + title: t("pages.proformas.list.grid_columns.invoice_number"), + }, + }, + // Estado + { + accessorKey: "status", + header: ({ column }) => ( + + ), + cell: ({ row }) => , + enableSorting: false, + size: 140, + minSize: 120, + meta: { + title: t("pages.proformas.list.grid_columns.status"), + }, + }, + { + id: "recipient", + header: ({ column }) => ( + + ), + accessorFn: (row) => row.recipient.name, // para ordenar/buscar por nombre + enableHiding: false, + size: 140, + minSize: 120, + cell: ({ row }) => { + const c = row.original.recipient; + return ( +
+
+
+ {c.name} +
+
+ {c.tin && {c.tin}} +
+
+
+ ); + }, + meta: { + title: t("pages.proformas.list.grid_columns.recipient"), + }, + }, + // Serie + { + accessorKey: "series", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.original.series}
, + enableSorting: false, + size: 120, + minSize: 100, + meta: { + title: t("pages.proformas.list.grid_columns.series"), + }, + }, + // Referencia + { + accessorKey: "reference", + header: ({ column }) => ( + + ), + cell: ({ row }) =>
{row.original.reference}
, + enableSorting: false, + size: 120, + minSize: 100, + meta: { + title: t("pages.proformas.list.grid_columns.reference"), + }, + }, + + // Fecha factura + { + accessorKey: "invoice_date", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {formatDate(row.original.invoice_date)} +
+ ), + enableSorting: false, + size: 140, + minSize: 120, + meta: { + title: t("pages.proformas.list.grid_columns.invoice_date"), + }, + }, + // Fecha operación + { + accessorKey: "operation_date", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {formatDate(row.original.operation_date)} +
+ ), + enableSorting: false, + size: 140, + minSize: 120, + meta: { + title: t("pages.proformas.list.grid_columns.operation_date"), + }, + }, + + // Subtotal amount + { + accessorKey: "subtotal_amount_fmt", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.subtotal_amount_fmt} +
+ ), + enableSorting: false, + size: 120, + minSize: 100, + meta: { + title: t("pages.proformas.list.grid_columns.subtotal_amount"), + }, + }, + + // Discount amount + { + accessorKey: "discount_amount_fmt", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.discount_amount_fmt} +
+ ), + enableSorting: false, + size: 120, + minSize: 100, + meta: { + title: t("pages.proformas.list.grid_columns.discount_amount"), + }, + }, + + // Taxes amount + { + accessorKey: "taxes_amount_fmt", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
{row.original.taxes_amount_fmt}
+ ), + enableSorting: false, + size: 120, + minSize: 100, + meta: { + title: t("pages.proformas.list.grid_columns.taxes_amount"), + }, + }, + + // Total amount + { + accessorKey: "total_amount_fmt", + header: ({ column }) => ( + + ), + cell: ({ row }) => ( +
+ {row.original.total_amount_fmt} +
+ ), + enableSorting: false, + size: 140, + minSize: 120, + meta: { + title: t("pages.proformas.list.grid_columns.total_amount"), + }, + }, + + // ───────────────────────────── + // Acciones + // ───────────────────────────── + { + id: "actions", + header: () => {t("common.actions")}, + enableSorting: false, + enableHiding: false, + size: 110, + minSize: 96, + cell: ({ row }) => { + const proforma = row.original; + const stop = (e: React.MouseEvent | React.KeyboardEvent) => e.stopPropagation(); + + return ( + + {/* Editar (acción primaria) */} + + + + + {t("common.edit_row")} + + + {/* Duplicar */} + + + + + {t("common.duplicate_row")} + + + {/* Descargar en PDF */} + + + + + {t("common.download_pdf")} + + + + + + + {t("common.delete_row")} + + + {/* Menú demás acciones */} + {/** biome-ignore lint/suspicious/noSelfCompare: */} + {false === false && ( + + + + + + onDuplicate?.(proforma)} + > + + {t("common.duplicate_row")} + + + onDownloadPdf?.(proforma)} + > + + {t("common.download_pdf")} + + onSendEmail?.(proforma)} + > + + {t("common.send_email")} + {" "} + + onDelete?.(proforma)} + > + + {t("common.delete_row")} + + + + )} + + ); + }, + meta: { + title: t("common.actions"), + }, + }, + ], + [t, onEdit, onDuplicate, onDownloadPdf, onSendEmail, onDelete] + ); +} diff --git a/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-list.ts b/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-list.ts index 472814d7..792776c8 100644 --- a/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-list.ts +++ b/modules/customer-invoices/src/web/proformas/pages/list/hooks/use-proformas-list.ts @@ -11,19 +11,23 @@ export const useProformasList = () => { const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(10); const [search, setSearch] = useState(""); + const [status, setStatus] = useState("all"); const debouncedQ = useDebounce(search, 300); - const criteria = useMemo( - () => ({ + const criteria = useMemo(() => { + const baseFilters = + status !== "all" ? [{ field: "status", operator: "CONTAINS", value: status }] : []; + + return { q: debouncedQ || "", pageSize, pageNumber: pageIndex, order: "desc", orderBy: "invoice_date", - }), - [pageSize, pageIndex, debouncedQ] - ); + filters: baseFilters, + }; + }, [pageSize, pageIndex, debouncedQ, status]); const query = useProformasQuery({ criteria }); const data = useMemo( @@ -33,6 +37,8 @@ export const useProformasList = () => { const setSearchValue = (value: string) => setSearch(value.trim().replace(/\s+/g, " ")); + const setStatusFilter = (newStatus: string) => setStatus(newStatus); + return { ...query, data, @@ -42,5 +48,6 @@ export const useProformasList = () => { setPageIndex, setPageSize, setSearchValue, + setStatusFilter, }; }; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx b/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx index 052c130d..664ba898 100644 --- a/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx +++ b/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx @@ -51,6 +51,7 @@ export const ProformaListPage = () => { onPageChange={list.setPageIndex} onPageSizeChange={list.setPageSize} onSearchChange={list.setSearchValue} + onStatusFilterChange={list.setStatusFilter} pageIndex={list.pageIndex} pageSize={list.pageSize} searchValue={list.search} diff --git a/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx.bak b/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx.bak deleted file mode 100644 index add6ac0a..00000000 --- a/modules/customer-invoices/src/web/proformas/pages/list/proforma-list-page.tsx.bak +++ /dev/null @@ -1,114 +0,0 @@ -import type { CriteriaDTO } from "@erp/core"; -import { PageHeader } from "@erp/core/components"; -import { ErrorAlert } from "@erp/customers/components"; -import { AppContent, AppHeader, BackHistoryButton, useDebounce } from "@repo/rdx-ui/components"; -import { Button } from "@repo/shadcn-ui/components"; -import { PlusIcon } from "lucide-react"; -import { useMemo, useState } from "react"; -import { useNavigate } from "react-router-dom"; - -import { useTranslation } from "../../../i18n"; -import { useProformasQuery } from "../../hooks"; -import { ProformaSummaryDtoAdapter } from "../../../adapters/proforma-summary-dto.adapter"; - -import { ProformasGrid } from "./proformas-grid"; - -export const ProformaListPage = () => { - const { t } = useTranslation(); - const navigate = useNavigate(); - - const [pageIndex, setPageIndex] = useState(0); - const [pageSize, setPageSize] = useState(10); - const [search, setSearch] = useState(""); - - const debouncedQ = useDebounce(search, 300); - - const criteria = useMemo( - () => - ({ - q: debouncedQ || "", - pageSize, - pageNumber: pageIndex, - order: "desc", - orderBy: "invoice_date", - }) as CriteriaDTO, - [pageSize, pageIndex, debouncedQ] - ); - - const { data, isLoading, isError, error } = useProformasQuery({ - criteria, - }); - - const proformaPageData = useMemo(() => { - if (!data) return undefined; - return ProformaSummaryDtoAdapter.fromDto(data); - }, [data]); - - const handlePageChange = (newPageIndex: number) => { - setPageIndex(newPageIndex); - }; - - const handlePageSizeChange = (newSize: number) => { - setPageSize(newSize); - setPageIndex(0); - }; - - const handleSearchChange = (value: string) => { - // Normalización ligera: recorta y colapsa espacios internos - const cleaned = value.trim().replace(/\s+/g, " "); - setSearch(cleaned); - setPageIndex(0); - }; - - if (isError || !proformaPageData) { - return ( - - - - - ); - } - - return ( - <> - - - - - } - title={t("pages.proformas.list.title")} - /> - - -
-
- -
-
-
- - ); -}; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/proformas-grid.tsx b/modules/customer-invoices/src/web/proformas/pages/list/proformas-grid.tsx deleted file mode 100644 index 4bf9f84f..00000000 --- a/modules/customer-invoices/src/web/proformas/pages/list/proformas-grid.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { SimpleSearchInput } from "@erp/core/components"; -import { DataTable, SkeletonDataTable } from "@repo/rdx-ui/components"; -import { - Button, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@repo/shadcn-ui/components"; -import { FileDownIcon, FilterIcon } from "lucide-react"; -import { useState } from "react"; -import { useNavigate } from "react-router-dom"; - -import { usePinnedPreviewSheet } from "../../../hooks"; -import { useTranslation } from "../../../i18n"; -import type { InvoiceSummaryFormData } from "../../../schemas"; -import type { ProformaSummaryPageData } from "../../schema/proforma-summary.web.schema"; - -import { useProformasGridColumns } from "./use-proformas-grid-columns"; - -export type ProformaGridProps = { - data: ProformaSummaryPageData; - loading?: boolean; - - pageIndex: number; - pageSize: number; - onPageChange?: (pageNumber: number) => void; - onPageSizeChange?: (pageSize: number) => void; - - searchValue: string; - onSearchChange: (value: string) => void; - - onRowClick?: ( - row: ProformaSummaryPageData, - index: number, - event: React.MouseEvent - ) => void; -}; - -// Create new GridExample component -export const ProformasGrid = ({ - data, - - loading, - pageIndex, - pageSize, - onPageChange, - onPageSizeChange, - searchValue, - onSearchChange, - onRowClick, -}: ProformaGridProps) => { - const { t } = useTranslation(); - const navigate = useNavigate(); - const { items, total_items } = data; - - // Hook con Sheet de shadcn - const preview = usePinnedPreviewSheet({ - persistKey: "invoice-preview-pin", - widthClass: "w-[500px]", - }); - - const [statusFilter, setStatusFilter] = useState("todas"); - - const columns = useProformasGridColumns({ - onEdit: (proforma) => navigate(`/proformas/${proforma.id}/edit`), - onDuplicate: (proforma) => null, //duplicateInvoice(inv.id), - onDownloadPdf: (proforma) => null, //downloadInvoicePdf(inv.id), - onSendEmail: (proforma) => null, //sendInvoiceEmail(inv.id), - onDelete: (proforma) => null, //confirmDelete(inv.id), - }); - - // Navegación accesible (click o teclado) - /*const goToRow = useCallback( - (id: string, newTab = false) => { - const url = `/customer-invoices/${id}/edit`; - newTab ? window.open(url, "_blank", "noopener,noreferrer") : navigate(url); - }, - [navigate] - );*/ - - /*const onRowClicked = useCallback( - (e: RowClickedEvent) => { - if (!e.data) return; - const newTab = e.event instanceof MouseEvent && (e.event.metaKey || e.event.ctrlKey); - goToRow(e.data.id, newTab); - }, - [goToRow] - ); - - const onCellKeyDown = useCallback( - (e: CellKeyDownEvent) => { - if (!e.data) return; - - const ev = e.event; - if (!(ev && ev instanceof KeyboardEvent)) return; - - const key = ev.key; - if (key === "Enter" || key === " ") { - ev.preventDefault(); - goToRow(e.data.id); - } - if ((ev.ctrlKey || ev.metaKey) && key === "Enter") { - ev.preventDefault(); - goToRow(e.data.id, true); - } - }, - [goToRow] - ); - - const handleRowClick = useCallback( - (invoice: InvoiceSummaryFormData, _i: number, e: React.MouseEvent) => { - const url = `/customer-invoices/${invoice.id}/edit`; - if (e.metaKey || e.ctrlKey) { - window.open(url, "_blank", "noopener,noreferrer"); - return; - } - preview.open(invoice); - }, - [preview] - );*/ - - if (loading) { - return ( -
- -
- ); - } - - // Render principal - return ( -
- {/* Barra de filtros */} -
- - - -
-
-
- -
- - {/* - {({ item, isPinned, close, togglePin }) => ( - - )} - */} -
-
- ); -}; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/ui/index.ts b/modules/customer-invoices/src/web/proformas/pages/list/ui/index.ts index cf0040bf..c4e562db 100644 --- a/modules/customer-invoices/src/web/proformas/pages/list/ui/index.ts +++ b/modules/customer-invoices/src/web/proformas/pages/list/ui/index.ts @@ -1 +1,2 @@ +export * from "./proforma-status-badge"; export * from "./proformas-grid"; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/ui/proforma-status-badge.tsx b/modules/customer-invoices/src/web/proformas/pages/list/ui/proforma-status-badge.tsx new file mode 100644 index 00000000..8c499a7d --- /dev/null +++ b/modules/customer-invoices/src/web/proformas/pages/list/ui/proforma-status-badge.tsx @@ -0,0 +1,68 @@ +import { Badge } from "@repo/shadcn-ui/components"; +import { cn } from "@repo/shadcn-ui/lib/utils"; +import { forwardRef } from "react"; + +import { useTranslation } from "../../../../i18n"; + +export type ProformaStatus = "draft" | "sent" | "approved" | "rejected" | "issued"; + +export type ProformaStatusBadgeProps = { + status: string | ProformaStatus; // permitir cualquier valor + dotVisible?: boolean; + className?: string; +}; + +const statusColorConfig: Record = { + draft: { + badge: + "bg-gray-500/10 dark:bg-gray-500/20 hover:bg-gray-500/10 text-gray-600 border-gray-400/60", + dot: "bg-gray-500", + }, + sent: { + badge: + "bg-amber-500/10 dark:bg-amber-500/20 hover:bg-amber-500/10 text-amber-500 border-amber-600/60", + dot: "bg-amber-500", + }, + approved: { + badge: + "bg-emerald-500/10 dark:bg-emerald-500/20 hover:bg-emerald-500/10 text-emerald-500 border-emerald-600/60", + dot: "bg-emerald-500", + }, + rejected: { + badge: "bg-red-500/10 dark:bg-red-500/20 hover:bg-red-500/10 text-red-500 border-red-600/60", + dot: "bg-red-500", + }, + issued: { + badge: + "bg-blue-600/10 dark:bg-blue-600/20 hover:bg-blue-600/10 text-blue-500 border-blue-600/60", + dot: "bg-blue-500", + }, +}; + +export const ProformaStatusBadge = forwardRef( + ({ status, dotVisible, className, ...props }, ref) => { + const { t } = useTranslation(); + + const normalizedStatus = status.toLowerCase() as ProformaStatus; + const config = statusColorConfig[normalizedStatus]; + const commonClassName = + "transition-colors duration-200 cursor-pointer shadow-none rounded-full"; + + if (!config) { + return ( + + {status} + + ); + } + + return ( + + {dotVisible &&
} + {t(`catalog.proformas.status.${normalizedStatus}`, { defaultValue: status })} + + ); + } +); + +ProformaStatusBadge.displayName = "ProformaStatusBadge"; diff --git a/modules/customer-invoices/src/web/proformas/pages/list/ui/proformas-grid.tsx b/modules/customer-invoices/src/web/proformas/pages/list/ui/proformas-grid.tsx index 4fc7801a..1c930ef3 100644 --- a/modules/customer-invoices/src/web/proformas/pages/list/ui/proformas-grid.tsx +++ b/modules/customer-invoices/src/web/proformas/pages/list/ui/proformas-grid.tsx @@ -1,18 +1,18 @@ import { SimpleSearchInput } from "@erp/core/components"; import { DataTable, SkeletonDataTable } from "@repo/rdx-ui/components"; import { - Button, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@repo/shadcn-ui/components"; -import { FileDownIcon, FilterIcon } from "lucide-react"; +import { FilterIcon } from "lucide-react"; +import { useNavigate } from "react-router-dom"; import { useTranslation } from "../../../../i18n"; import type { ProformaSummaryPageData } from "../../../schema/proforma-summary.web.schema"; -import { useProformasGridColumns } from "../use-proformas-grid-columns"; +import { useProformasGridColumns } from "../hooks"; interface ProformasGridProps { data: ProformaSummaryPageData; @@ -25,6 +25,7 @@ interface ProformasGridProps { onPageSizeChange: (s: number) => void; onRowClick?: (id: string) => void; onExportClick?: () => void; + onStatusFilterChange?: (newStatus: string) => void; } export const ProformasGrid = ({ @@ -38,10 +39,19 @@ export const ProformasGrid = ({ onPageSizeChange, onRowClick, onExportClick, + onStatusFilterChange, }: ProformasGridProps) => { + const navigate = useNavigate(); const { t } = useTranslation(); const { items, total_items } = data; - const columns = useProformasGridColumns(); + + const columns = useProformasGridColumns({ + onEdit: (proforma) => navigate(`/proformas/${proforma.id}/edit`), + onDuplicate: (proforma) => null, //duplicateInvoice(inv.id), + onDownloadPdf: (proforma) => null, //downloadInvoicePdf(inv.id), + onSendEmail: (proforma) => null, //sendInvoiceEmail(inv.id), + onDelete: (proforma) => null, //confirmDelete(inv.id), + }); if (loading) return ( @@ -55,33 +65,37 @@ export const ProformasGrid = ({ return (
-
- - - {t("filters.all")} - {t("filters.draft")} - {t("filters.sent")} + {t("catalog.proformas.status.all")} + {t("catalog.proformas.status.draft")} + {t("catalog.proformas.status.sent")} + {t("catalog.proformas.status.approved")} + {t("catalog.proformas.status.rejected")} + {t("catalog.proformas.status.issued")} -
onRowClick?.(row.id)} + onRowClick={(row, _index) => onRowClick?.(row.id)} pageIndex={pageIndex} pageSize={pageSize} totalItems={total_items} diff --git a/modules/customer-invoices/src/web/proformas/pages/list/use-proformas-grid-columns.tsx b/modules/customer-invoices/src/web/proformas/pages/list/use-proformas-grid-columns.tsx deleted file mode 100644 index 7481c114..00000000 --- a/modules/customer-invoices/src/web/proformas/pages/list/use-proformas-grid-columns.tsx +++ /dev/null @@ -1,314 +0,0 @@ -import { formatDate } from "@erp/core/client"; -import { DataTableColumnHeader } from "@repo/rdx-ui/components"; -import { - Avatar, - AvatarFallback, - Badge, - Button, - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, - Tooltip, - TooltipContent, - TooltipTrigger, -} from "@repo/shadcn-ui/components"; -import type { ColumnDef } from "@tanstack/react-table"; -import { - Building2Icon, - CopyIcon, - DownloadIcon, - EditIcon, - MailIcon, - MoreVerticalIcon, - Trash2Icon, - User2Icon, -} from "lucide-react"; -import * as React from "react"; - -import { useTranslation } from "../../../i18n"; -import type { InvoiceSummaryFormData } from "../../../schemas"; -import { CustomerInvoiceStatusBadge } from "../../../shared/ui/components"; - -type GridActionHandlers = { - onEdit?: (invoice: InvoiceSummaryFormData) => void; - onDuplicate?: (invoice: InvoiceSummaryFormData) => void; - onDownloadPdf?: (invoice: InvoiceSummaryFormData) => void; - onSendEmail?: (invoice: InvoiceSummaryFormData) => void; - onDelete?: (invoice: InvoiceSummaryFormData) => void; -}; - -function initials(name: string) { - const parts = name.trim().split(/\s+/).slice(0, 2); - return parts.map((p) => p[0]?.toUpperCase() ?? "").join("") || "?"; -} - -const KindBadge = ({ isCompany }: { isCompany: boolean }) => ( - - {isCompany ? : } - {isCompany ? "Company" : "Person"} - -); - -const Soft = ({ children }: { children: React.ReactNode }) => ( - {children} -); - -export function useProformasGridColumns( - actionHandlers: GridActionHandlers = {} -): ColumnDef[] { - const { t } = useTranslation(); - const { onEdit, onDuplicate, onDownloadPdf, onSendEmail, onDelete } = actionHandlers; - - return React.useMemo[]>( - () => [ - // Nº - { - accessorKey: "invoice_number", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
{row.original.invoice_number}
- ), - enableHiding: false, - enableSorting: false, - size: 160, - minSize: 120, - }, - // Estado - { - accessorKey: "status", - header: ({ column }) => ( - - ), - cell: ({ row }) => , - enableSorting: false, - size: 140, - minSize: 120, - }, - { - id: "recipient", - header: ({ column }) => ( - - ), - accessorFn: (row) => row.recipient.name, // para ordenar/buscar por nombre - enableHiding: false, - size: 140, - minSize: 120, - cell: ({ row }) => { - const c = row.original.recipient; - const isCompany = String(c.is_company).toLowerCase() === "true"; - return ( -
- - {initials(c.name)} - -
-
- {c.name} - {c.trade_name && ({c.trade_name})} -
-
- {c.tin && {c.tin}} - -
-
-
- ); - }, - }, - // Serie - { - accessorKey: "series", - header: ({ column }) => ( - - ), - cell: ({ row }) =>
{row.original.series}
, - enableSorting: false, - size: 120, - minSize: 100, - }, - // Referencia - { - accessorKey: "reference", - header: ({ column }) => ( - - ), - cell: ({ row }) =>
{row.original.reference}
, - enableSorting: false, - size: 120, - minSize: 100, - }, - - // Fecha factura - { - accessorKey: "invoice_date", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {formatDate(row.original.invoice_date)} -
- ), - enableSorting: false, - size: 140, - minSize: 120, - }, - // Fecha operación - { - accessorKey: "operation_date", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {formatDate(row.original.operation_date)} -
- ), - enableSorting: false, - size: 140, - minSize: 120, - }, - - // Total - { - accessorKey: "total_amount_fmt", - header: ({ column }) => ( - - ), - cell: ({ row }) => ( -
- {row.original.total_amount_fmt} -
- ), - enableSorting: false, - size: 140, - minSize: 120, - }, - - // ───────────────────────────── - // Acciones - // ───────────────────────────── - { - id: "actions", - header: () => {t("common.actions")}, - enableSorting: false, - enableHiding: false, - size: 110, - minSize: 96, - cell: ({ row }) => { - const invoice = row.original; - const stop = (e: React.MouseEvent | React.KeyboardEvent) => e.stopPropagation(); - - return ( -
- {/* Editar (acción primaria) */} - - - - - {t("common.edit")} - - - {/* Menú demás acciones */} - - - - - - onDuplicate?.(invoice)} - > - - {t("common.duplicate")} - - - onDownloadPdf?.(invoice)} - > - - {t("common.download_pdf")} - - onSendEmail?.(invoice)} - > - - {t("common.send_email")} - {" "} - - onDelete?.(invoice)} - > - - {t("common.delete")} - - - -
- ); - }, - }, - ], - [t, onEdit, onDuplicate, onDownloadPdf, onSendEmail, onDelete] - ); -} diff --git a/modules/customer-invoices/src/web/proformas/schema/proforma-summary.web.schema.ts b/modules/customer-invoices/src/web/proformas/schema/proforma-summary.web.schema.ts index cea670dc..ef1ff213 100644 --- a/modules/customer-invoices/src/web/proformas/schema/proforma-summary.web.schema.ts +++ b/modules/customer-invoices/src/web/proformas/schema/proforma-summary.web.schema.ts @@ -13,7 +13,7 @@ export type ProformaSummaryData = ProformaSummary & { taxable_amount_fmt: string; taxable_amount: number; - taxes_amoun_fmt: string; + taxes_amount_fmt: string; taxes_amount: number; total_amount_fmt: string; @@ -21,5 +21,5 @@ export type ProformaSummaryData = ProformaSummary & { }; export type ProformaSummaryPageData = ProformaSummaryPage & { - items: ProformaSummary[]; + items: ProformaSummaryData[]; }; diff --git a/modules/customer-invoices/src/web/proformas/schema/proforma.api.schema.ts b/modules/customer-invoices/src/web/proformas/schema/proforma.api.schema.ts index 9170d026..e48a915c 100644 --- a/modules/customer-invoices/src/web/proformas/schema/proforma.api.schema.ts +++ b/modules/customer-invoices/src/web/proformas/schema/proforma.api.schema.ts @@ -1,7 +1,7 @@ import { CreateProformaRequestSchema, GetProformaByIdResponseSchema, - ListProformasResponseSchema, + type ListProformasResponseDTO, UpdateProformaByIdRequestSchema, } from "@erp/customer-invoices/common"; import type { ArrayElement } from "@repo/rdx-utils"; @@ -23,9 +23,5 @@ export type CreateProformaInput = z.infer; // Cuerp export type UpdateProformaInput = z.infer; // Cuerpo para actualizar // Resultado de consulta con criteria (paginado, etc.) -export const ProformaSummaryPageSchema = ListProformasResponseSchema.omit({ - metadata: true, -}); - -export type ProformaSummaryPage = z.infer; +export type ProformaSummaryPage = Omit; export type ProformaSummary = Omit, "metadata">; diff --git a/modules/customer-invoices/src/web/schemas/invoices.api.schema.ts b/modules/customer-invoices/src/web/schemas/invoices.api.schema.ts index bbd4b34a..2ece0648 100644 --- a/modules/customer-invoices/src/web/schemas/invoices.api.schema.ts +++ b/modules/customer-invoices/src/web/schemas/invoices.api.schema.ts @@ -1,18 +1,18 @@ import type { ArrayElement } from "@repo/rdx-utils"; import type { z } from "zod/v4"; -import { GetIssueInvoiceByIdResponseSchema, ListIssueInvoicesResponseSchema } from "../../common"; +import { GetIssuedInvoiceByIdResponseSchema, ListIssuedInvoicesResponseSchema } from "../../common"; -export const IssueInvoiceSchema = GetIssueInvoiceByIdResponseSchema.omit({ +export const IssuedInvoiceschema = GetIssuedInvoiceByIdResponseSchema.omit({ metadata: true, }); -export type IssueInvoice = z.infer; +export type IssueInvoice = z.infer; export type IssueInvoiceRecipient = IssueInvoice["recipient"]; export type IssueInvoiceItem = ArrayElement; // Resultado de consulta con criteria (paginado, etc.) -export const IssueInvoicesPageSchema = ListIssueInvoicesResponseSchema.omit({ +export const IssuedInvoicesPageSchema = ListIssuedInvoicesResponseSchema.omit({ metadata: true, }); diff --git a/modules/customer-invoices/src/web/shared/ui/components/customer-invoice-status-badge.tsx b/modules/customer-invoices/src/web/shared/ui/components/customer-invoice-status-badge.tsx deleted file mode 100644 index 7a9bc66e..00000000 --- a/modules/customer-invoices/src/web/shared/ui/components/customer-invoice-status-badge.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { Badge } from "@repo/shadcn-ui/components"; -import { cn } from "@repo/shadcn-ui/lib/utils"; -import { forwardRef } from "react"; - -import { useTranslation } from "../../../i18n"; - -export type CustomerInvoiceStatus = "draft" | "sent" | "approved" | "rejected" | "issued"; - -export type CustomerInvoiceStatusBadgeProps = { - status: string | CustomerInvoiceStatus; // permitir cualquier valor - dotVisible?: boolean; - className?: string; -}; - -const statusColorConfig: Record = { - draft: { - badge: - "bg-gray-500/10 dark:bg-gray-500/20 hover:bg-gray-500/10 text-gray-600 border-gray-400/60", - dot: "bg-gray-500", - }, - sent: { - badge: - "bg-amber-500/10 dark:bg-amber-500/20 hover:bg-amber-500/10 text-amber-500 border-amber-600/60", - dot: "bg-amber-500", - }, - approved: { - badge: - "bg-emerald-500/10 dark:bg-emerald-500/20 hover:bg-emerald-500/10 text-emerald-500 border-emerald-600/60", - dot: "bg-emerald-500", - }, - rejected: { - badge: "bg-red-500/10 dark:bg-red-500/20 hover:bg-red-500/10 text-red-500 border-red-600/60", - dot: "bg-red-500", - }, - issued: { - badge: - "bg-blue-600/10 dark:bg-blue-600/20 hover:bg-blue-600/10 text-blue-500 border-blue-600/60", - dot: "bg-blue-500", - }, -}; - -export const CustomerInvoiceStatusBadge = forwardRef< - HTMLDivElement, - CustomerInvoiceStatusBadgeProps ->(({ status, dotVisible, className, ...props }, ref) => { - const { t } = useTranslation(); - const normalizedStatus = status.toLowerCase() as CustomerInvoiceStatus; - const config = statusColorConfig[normalizedStatus]; - const commonClassName = "transition-colors duration-200 cursor-pointer shadow-none rounded-full"; - - if (!config) { - return ( - - {status} - - ); - } - - return ( - - {dotVisible &&
} - {t(`catalog.status.${normalizedStatus}`, { defaultValue: status })} - - ); -}); - -CustomerInvoiceStatusBadge.displayName = "CustomerInvoiceStatusBadge"; diff --git a/modules/customer-invoices/src/web/shared/ui/components/index.tsx b/modules/customer-invoices/src/web/shared/ui/components/index.tsx index ea27c124..f312fc17 100644 --- a/modules/customer-invoices/src/web/shared/ui/components/index.tsx +++ b/modules/customer-invoices/src/web/shared/ui/components/index.tsx @@ -1,6 +1,7 @@ +export * from "../../../proformas/pages/list/ui/proforma-status-badge"; + export * from "./customer-invoice-editor-skeleton"; export * from "./customer-invoice-prices-card"; -export * from "./customer-invoice-status-badge"; export * from "./customer-invoice-taxes-multi-select"; export * from "./editor"; export * from "./editor/invoice-tax-summary"; diff --git a/modules/customer-invoices/tsconfig.json b/modules/customer-invoices/tsconfig.json index a58a3f4c..b4a95fde 100644 --- a/modules/customer-invoices/tsconfig.json +++ b/modules/customer-invoices/tsconfig.json @@ -28,6 +28,6 @@ "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true }, - "include": ["src", "../core/src/common/helpers/date-helper.ts"], + "include": ["src"], "exclude": ["node_modules"] }