diff --git a/docs/catalogs/payment-methods-design.md b/docs/catalogs/payment-methods-design.md index 487aa9ff..bf08d15a 100644 --- a/docs/catalogs/payment-methods-design.md +++ b/docs/catalogs/payment-methods-design.md @@ -15,7 +15,6 @@ Campos persistidos y expuestos para administración: - `is_active` - `is_system` - `is_default` -- `system_key` - `created_at` - `updated_at` - `deleted_at` @@ -24,17 +23,8 @@ Campos persistidos y expuestos para administración: Reglas: -- `is_system = true` implica `system_key != null` -- `is_system = false` implica `system_key = null` - `is_system = true` no se puede editar, desactivar ni eliminar -Identidad estable de métodos del sistema: - -- `cash` -- `bank_transfer` -- `card` -- `direct_debit` - ## Active and default Reglas: @@ -46,26 +36,6 @@ Reglas: La unicidad del default se garantiza mediante servicio transaccional y bloqueo por empresa. No se fuerza con constraint SQL adicional para evitar una solución opaca en MariaDB. -## Bootstrap - -Endpoint explícito e idempotente: - -- `POST /catalogs/payment-methods/bootstrap-system` - -Comportamiento: - -- crea los cuatro métodos del sistema que falten -- restaura un system method soft-deleted si ya existía por `system_key` -- resincroniza `name`, `is_system`, `is_active`, `is_default = false` y `system_key` -- si la empresa no tiene default, establece `cash` como default inicial - -Métodos creados: - -- `Efectivo` -- `Transferencia bancaria` -- `Tarjeta` -- `Domiciliación bancaria` - ## Delete policy Un método solo puede eliminarse si: diff --git a/docs/catalogs/sql/remove-payment-method-system-key.sql b/docs/catalogs/sql/remove-payment-method-system-key.sql new file mode 100644 index 00000000..9d7d09d8 --- /dev/null +++ b/docs/catalogs/sql/remove-payment-method-system-key.sql @@ -0,0 +1,35 @@ +SET @index_exists := ( + SELECT COUNT(1) + FROM information_schema.statistics + WHERE table_schema = DATABASE() + AND table_name = 'payment_methods' + AND index_name = 'uq_payment_methods_company_system_key' +); + +SET @drop_index_sql := IF( + @index_exists > 0, + 'DROP INDEX `uq_payment_methods_company_system_key` ON `payment_methods`', + 'SELECT 1' +); + +PREPARE stmt FROM @drop_index_sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SET @column_exists := ( + SELECT COUNT(1) + FROM information_schema.columns + WHERE table_schema = DATABASE() + AND table_name = 'payment_methods' + AND column_name = 'system_key' +); + +SET @drop_column_sql := IF( + @column_exists > 0, + 'ALTER TABLE `payment_methods` DROP COLUMN `system_key`', + 'SELECT 1' +); + +PREPARE stmt FROM @drop_column_sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/modules/catalogs/src/api/application/payment-methods/mappers/create-payment-method-input.mapper.ts b/modules/catalogs/src/api/application/payment-methods/mappers/create-payment-method-input.mapper.ts index 314f532f..901f1c9f 100644 --- a/modules/catalogs/src/api/application/payment-methods/mappers/create-payment-method-input.mapper.ts +++ b/modules/catalogs/src/api/application/payment-methods/mappers/create-payment-method-input.mapper.ts @@ -8,7 +8,7 @@ import { extractOrPushError, maybeFromNullableResult, } from "@repo/rdx-ddd"; -import { Maybe, Result } from "@repo/rdx-utils"; +import { Result } from "@repo/rdx-utils"; import type { CreatePaymentMethodRequestDTO } from "../../../../common"; import type { IPaymentMethodCreateProps } from "../../../domain"; @@ -49,7 +49,6 @@ export class CreatePaymentMethodInputMapper implements ICreatePaymentMethodInput isActive: isActive!, isSystem: false, isDefault: false, - systemKey: Maybe.none(), }; return Result.ok({ diff --git a/modules/catalogs/src/api/application/payment-methods/repositories/payment-method-repository.interface.ts b/modules/catalogs/src/api/application/payment-methods/repositories/payment-method-repository.interface.ts index 757e98a1..b6940e05 100644 --- a/modules/catalogs/src/api/application/payment-methods/repositories/payment-method-repository.interface.ts +++ b/modules/catalogs/src/api/application/payment-methods/repositories/payment-method-repository.interface.ts @@ -2,7 +2,7 @@ import type { Criteria } from "@repo/rdx-criteria/server"; import type { UniqueID } from "@repo/rdx-ddd"; import type { Collection, Maybe, Result } from "@repo/rdx-utils"; -import type { PaymentMethod, PaymentMethodSystemKey } from "../../../domain"; +import type { PaymentMethod } from "../../../domain"; import type { PaymentMethodSummary } from "../models"; export interface IPaymentMethodRepository { @@ -32,29 +32,7 @@ export interface IPaymentMethodRepository { companyId: UniqueID, transaction?: unknown ): Promise, Error>>; - findBySystemKeyInCompany( - companyId: UniqueID, - systemKey: PaymentMethodSystemKey, - transaction?: unknown, - options?: { includeDeleted?: boolean } - ): Promise, Error>>; - restoreByIdInCompany( - companyId: UniqueID, - id: UniqueID, - transaction?: unknown - ): Promise>; - syncSystemPaymentMethodState(params: { - companyId: UniqueID; - id: UniqueID; - name: string; - isDefault: boolean; - systemKey: PaymentMethodSystemKey; - transaction?: unknown; - }): Promise>; - lockByCompanyId( - companyId: UniqueID, - transaction?: unknown - ): Promise>; + lockByCompanyId(companyId: UniqueID, transaction?: unknown): Promise>; deleteByIdInCompany( companyId: UniqueID, id: UniqueID, diff --git a/modules/catalogs/src/api/application/payment-methods/services/__tests__/payment-method-services.test.ts b/modules/catalogs/src/api/application/payment-methods/services/__tests__/payment-method-services.test.ts index 55f030af..c3344624 100644 --- a/modules/catalogs/src/api/application/payment-methods/services/__tests__/payment-method-services.test.ts +++ b/modules/catalogs/src/api/application/payment-methods/services/__tests__/payment-method-services.test.ts @@ -1,13 +1,11 @@ import { describe, test } from "node:test"; import assert from "node:assert/strict"; -import type { Criteria } from "@repo/rdx-criteria/server"; import { EntityNotFoundError } from "@erp/core/api"; import { Name, UniqueID } from "@repo/rdx-ddd"; import { Collection, Maybe, Result } from "@repo/rdx-utils"; import { PaymentMethod } from "../../../../domain/payment-methods/payment-method.aggregate"; -import { BootstrapSystemPaymentMethodsService } from "../bootstrap-system-payment-methods.service"; import { PaymentMethodDeleter } from "../payment-method-deleter"; import { SetDefaultPaymentMethodService } from "../set-default-payment-method.service"; import type { IPaymentMethodRepository } from "../../repositories"; @@ -66,7 +64,7 @@ class InMemoryPaymentMethodRepository implements IPaymentMethodRepository { } async findByCriteriaInCompany(): Promise, Error>> { - return Result.ok(Collection.create([])); + return Result.ok(new Collection([])); } async findDefaultInCompany(companyId: UniqueID): Promise, Error>> { @@ -81,80 +79,6 @@ class InMemoryPaymentMethodRepository implements IPaymentMethodRepository { return paymentMethod ? Result.ok(Maybe.some(paymentMethod)) : Result.ok(Maybe.none()); } - async findBySystemKeyInCompany( - companyId: UniqueID, - systemKey: "cash" | "bank_transfer" | "card" | "direct_debit", - _transaction?: unknown, - options?: { includeDeleted?: boolean } - ): Promise, Error>> { - const paymentMethod = - [...this.items.values()].find((item) => { - const matchesCompany = item.companyId.toString() === companyId.toString(); - const matchesKey = item.systemKey.match( - (value) => value === systemKey, - () => false - ); - const includeDeleted = options?.includeDeleted === true; - - return ( - matchesCompany && - matchesKey && - (includeDeleted || !this.deleted.has(item.id.toString())) - ); - }) ?? null; - - return paymentMethod ? Result.ok(Maybe.some(paymentMethod)) : Result.ok(Maybe.none()); - } - - async restoreByIdInCompany(companyId: UniqueID, id: UniqueID): Promise> { - const result = await this.existsByIdInCompany(companyId, id); - if (result.isFailure) { - return Result.fail(result.error); - } - - if (!result.data) { - return Result.ok(false); - } - - this.deleted.delete(id.toString()); - return Result.ok(true); - } - - async syncSystemPaymentMethodState(params: { - companyId: UniqueID; - id: UniqueID; - name: string; - isDefault: boolean; - systemKey: "cash" | "bank_transfer" | "card" | "direct_debit"; - }): Promise> { - const paymentMethodResult = await this.getByIdInCompany(params.companyId, params.id); - if (paymentMethodResult.isFailure) { - return Result.fail(paymentMethodResult.error); - } - - const current = paymentMethodResult.data; - const nameResult = Name.create(params.name); - assert.equal(nameResult.isSuccess, true); - - const updatedResult = PaymentMethod.create( - { - companyId: current.companyId, - name: nameResult.data, - description: current.description, - isActive: true, - isSystem: true, - isDefault: params.isDefault, - systemKey: Maybe.some(params.systemKey), - }, - current.id - ); - - assert.equal(updatedResult.isSuccess, true); - this.items.set(current.id.toString(), updatedResult.data); - - return Result.ok(); - } - async lockByCompanyId(): Promise> { return Result.ok(); } @@ -180,7 +104,6 @@ const buildPaymentMethod = (params: { isActive?: boolean; isSystem?: boolean; isDefault?: boolean; - systemKey?: "cash" | "bank_transfer" | "card" | "direct_debit"; }) => { const nameResult = Name.create(params.name); assert.equal(nameResult.isSuccess, true); @@ -193,7 +116,6 @@ const buildPaymentMethod = (params: { isActive: params.isActive ?? true, isSystem: params.isSystem ?? false, isDefault: params.isDefault ?? false, - systemKey: params.systemKey ? Maybe.some(params.systemKey) : Maybe.none(), }, UniqueID.generateNewID() ); @@ -302,46 +224,12 @@ describe("Payment method services", () => { assert.equal(result.isFailure, true); }); - test("bootstrap creates four system methods and exactly one default", async () => { - const repository = new InMemoryPaymentMethodRepository(); - const setDefaultService = new SetDefaultPaymentMethodService(repository); - const service = new BootstrapSystemPaymentMethodsService({ - repository, - setDefaultService, - }); - const companyId = UniqueID.generateNewID(); - - const result = await service.bootstrap({ companyId }); - - assert.equal(result.isSuccess, true); - assert.equal(result.data.length, 4); - assert.equal(result.data.filter((item) => item.isDefault).length, 1); - assert.equal(result.data.some((item) => item.systemKey.match((key) => key === "cash", () => false) && item.isDefault), true); - }); - - test("bootstrap is idempotent", async () => { - const repository = new InMemoryPaymentMethodRepository(); - const setDefaultService = new SetDefaultPaymentMethodService(repository); - const service = new BootstrapSystemPaymentMethodsService({ - repository, - setDefaultService, - }); - const companyId = UniqueID.generateNewID(); - - const first = await service.bootstrap({ companyId }); - const second = await service.bootstrap({ companyId }); - - assert.equal(first.isSuccess, true); - assert.equal(second.isSuccess, true); - assert.equal(second.data.length, 4); - }); - test("delete blocks referenced payment methods", async () => { const repository = new InMemoryPaymentMethodRepository(); const deleter = new PaymentMethodDeleter({ repository, usageChecker: { - findUsage: async () => Result.ok(["customers"]), + findUsage: async () => Result.ok([{ source: "customers" }]), }, }); const companyId = UniqueID.generateNewID(); @@ -352,9 +240,32 @@ describe("Payment method services", () => { await repository.create(paymentMethod); - const result = await deleter.deleteById({ + const result = await deleter.delete({ + paymentMethod, + }); + + assert.equal(result.isFailure, true); + }); + + test("delete blocks system payment methods", async () => { + const repository = new InMemoryPaymentMethodRepository(); + const deleter = new PaymentMethodDeleter({ + repository, + usageChecker: { + findUsage: async () => Result.ok([]), + }, + }); + const companyId = UniqueID.generateNewID(); + const paymentMethod = buildPaymentMethod({ companyId, - id: paymentMethod.id, + name: "Transferencia", + isSystem: true, + }); + + await repository.create(paymentMethod); + + const result = await deleter.delete({ + paymentMethod, }); assert.equal(result.isFailure, true); diff --git a/modules/catalogs/src/api/application/payment-methods/services/bootstrap-system-payment-methods.service.ts b/modules/catalogs/src/api/application/payment-methods/services/bootstrap-system-payment-methods.service.ts deleted file mode 100644 index b660b8be..00000000 --- a/modules/catalogs/src/api/application/payment-methods/services/bootstrap-system-payment-methods.service.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { Name, UniqueID } from "@repo/rdx-ddd"; -import { Maybe, Result } from "@repo/rdx-utils"; - -import { PaymentMethod, type PaymentMethodSystemKey } from "../../../domain"; -import type { IPaymentMethodRepository } from "../repositories"; -import type { ISetDefaultPaymentMethodService } from "./set-default-payment-method.service"; - -type SystemPaymentMethodDefinition = { - systemKey: PaymentMethodSystemKey; - name: string; - isDefault: boolean; -}; - -const SYSTEM_PAYMENT_METHOD_DEFINITIONS: SystemPaymentMethodDefinition[] = [ - { - systemKey: "cash", - name: "Efectivo", - isDefault: true, - }, - { - systemKey: "bank_transfer", - name: "Transferencia bancaria", - isDefault: false, - }, - { - systemKey: "card", - name: "Tarjeta", - isDefault: false, - }, - { - systemKey: "direct_debit", - name: "Domiciliación bancaria", - isDefault: false, - }, -]; - -export interface IBootstrapSystemPaymentMethodsService { - bootstrap(params: { - companyId: UniqueID; - transaction?: unknown; - }): Promise>; -} - -export class BootstrapSystemPaymentMethodsService implements IBootstrapSystemPaymentMethodsService { - public constructor( - private readonly deps: { - repository: IPaymentMethodRepository; - setDefaultService: ISetDefaultPaymentMethodService; - } - ) {} - - public async bootstrap(params: { - companyId: UniqueID; - transaction?: unknown; - }): Promise> { - const { companyId, transaction } = params; - - const lockResult = await this.deps.repository.lockByCompanyId(companyId, transaction); - if (lockResult.isFailure) { - return Result.fail(lockResult.error); - } - - const bootstrappedPaymentMethods: PaymentMethod[] = []; - - for (const definition of SYSTEM_PAYMENT_METHOD_DEFINITIONS) { - const paymentMethodResult = await this.ensureSystemPaymentMethod({ - companyId, - definition, - transaction, - }); - - if (paymentMethodResult.isFailure) { - return Result.fail(paymentMethodResult.error); - } - - bootstrappedPaymentMethods.push(paymentMethodResult.data); - } - - const currentDefaultResult = await this.deps.repository.findDefaultInCompany( - companyId, - transaction - ); - if (currentDefaultResult.isFailure) { - return Result.fail(currentDefaultResult.error); - } - - if (currentDefaultResult.data.isNone()) { - const cashPaymentMethod = bootstrappedPaymentMethods.find( - (paymentMethod) => - paymentMethod.systemKey.match( - (systemKey) => systemKey === "cash", - () => false - ) - ); - - if (!cashPaymentMethod) { - return Result.fail(new Error("Cash system payment method bootstrap failed.")); - } - - const setDefaultResult = await this.deps.setDefaultService.setDefault({ - companyId, - paymentMethodId: cashPaymentMethod.id, - transaction, - }); - - if (setDefaultResult.isFailure) { - return Result.fail(setDefaultResult.error); - } - - const updatedItems = bootstrappedPaymentMethods.map((paymentMethod) => - paymentMethod.id.toString() === setDefaultResult.data.id.toString() - ? setDefaultResult.data - : paymentMethod - ); - - return Result.ok(updatedItems); - } - - return Result.ok(bootstrappedPaymentMethods); - } - - private async ensureSystemPaymentMethod(params: { - companyId: UniqueID; - definition: SystemPaymentMethodDefinition; - transaction?: unknown; - }): Promise> { - const { companyId, definition, transaction } = params; - - const existingResult = await this.deps.repository.findBySystemKeyInCompany( - companyId, - definition.systemKey, - transaction, - { includeDeleted: true } - ); - - if (existingResult.isFailure) { - return Result.fail(existingResult.error); - } - - if (existingResult.data.isSome()) { - const existingPaymentMethod = existingResult.data.unwrap(); - - const restoreResult = await this.deps.repository.restoreByIdInCompany( - companyId, - existingPaymentMethod.id, - transaction - ); - - if (restoreResult.isFailure) { - return Result.fail(restoreResult.error); - } - - const syncResult = await this.deps.repository.syncSystemPaymentMethodState({ - companyId, - id: existingPaymentMethod.id, - name: definition.name, - isDefault: false, - systemKey: definition.systemKey, - transaction, - }); - - if (syncResult.isFailure) { - return Result.fail(syncResult.error); - } - - const refreshedResult = await this.deps.repository.getByIdInCompany( - companyId, - existingPaymentMethod.id, - transaction - ); - - if (refreshedResult.isFailure) { - return Result.fail(refreshedResult.error); - } - - return Result.ok(refreshedResult.data); - } - - const nameResult = Name.create(definition.name); - if (nameResult.isFailure) { - return Result.fail(nameResult.error); - } - - const paymentMethodResult = PaymentMethod.create( - { - companyId, - name: nameResult.data, - description: Maybe.none(), - isActive: true, - isSystem: true, - isDefault: false, - systemKey: Maybe.some(definition.systemKey), - }, - UniqueID.generateNewID() - ); - - if (paymentMethodResult.isFailure) { - return Result.fail(paymentMethodResult.error); - } - - const createResult = await this.deps.repository.create(paymentMethodResult.data, transaction); - if (createResult.isFailure) { - return Result.fail(createResult.error); - } - - return Result.ok(paymentMethodResult.data); - } -} diff --git a/modules/catalogs/src/api/application/payment-methods/services/index.ts b/modules/catalogs/src/api/application/payment-methods/services/index.ts index c274fec1..2658804f 100644 --- a/modules/catalogs/src/api/application/payment-methods/services/index.ts +++ b/modules/catalogs/src/api/application/payment-methods/services/index.ts @@ -1,5 +1,4 @@ export * from "./payment-method-creator"; -export * from "./bootstrap-system-payment-methods.service"; export * from "./payment-method-deleter"; export * from "./payment-method-disabler"; export * from "./payment-method-enabler"; diff --git a/modules/catalogs/src/api/application/payment-methods/use-cases/bootstrap-system-payment-methods.use-case.ts b/modules/catalogs/src/api/application/payment-methods/use-cases/bootstrap-system-payment-methods.use-case.ts deleted file mode 100644 index e295f09b..00000000 --- a/modules/catalogs/src/api/application/payment-methods/use-cases/bootstrap-system-payment-methods.use-case.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { BootstrapSystemPaymentMethodsResponseDTO } from "@erp/catalogs/common"; -import type { ITransactionManager } from "@erp/core/api"; -import type { UniqueID } from "@repo/rdx-ddd"; -import { Result } from "@repo/rdx-utils"; - -import type { IBootstrapSystemPaymentMethodsService } from "../services"; -import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders"; - -export type BootstrapSystemPaymentMethodsUseCaseInput = { - companyId: UniqueID; -}; - -export class BootstrapSystemPaymentMethodsUseCase { - public constructor( - private readonly deps: { - bootstrapService: IBootstrapSystemPaymentMethodsService; - fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder; - transactionManager: ITransactionManager; - } - ) {} - - public execute( - params: BootstrapSystemPaymentMethodsUseCaseInput - ): Promise> { - const { companyId } = params; - - return this.deps.transactionManager.complete(async (transaction: unknown) => { - try { - const result = await this.deps.bootstrapService.bootstrap({ - companyId, - transaction, - }); - - if (result.isFailure) { - return Result.fail(result.error); - } - - return Result.ok({ - items: result.data.map((paymentMethod) => this.deps.fullSnapshotBuilder.toOutput(paymentMethod)), - }); - } catch (error: unknown) { - return Result.fail(error as Error); - } - }); - } -} diff --git a/modules/catalogs/src/api/application/payment-methods/use-cases/index.ts b/modules/catalogs/src/api/application/payment-methods/use-cases/index.ts index 4d3891b1..ab403b2a 100644 --- a/modules/catalogs/src/api/application/payment-methods/use-cases/index.ts +++ b/modules/catalogs/src/api/application/payment-methods/use-cases/index.ts @@ -1,4 +1,3 @@ -export * from "./bootstrap-system-payment-methods.use-case"; export * from "./create-payment-method.use-case"; export * from "./delete-payment-method-by-id.use-case"; export * from "./disable-payment-method-by-id.use-case"; diff --git a/modules/catalogs/src/api/domain/payment-methods/__tests__/payment-method.aggregate.test.ts b/modules/catalogs/src/api/domain/payment-methods/__tests__/payment-method.aggregate.test.ts index 7107e21a..a5f3dd2e 100644 --- a/modules/catalogs/src/api/domain/payment-methods/__tests__/payment-method.aggregate.test.ts +++ b/modules/catalogs/src/api/domain/payment-methods/__tests__/payment-method.aggregate.test.ts @@ -22,7 +22,6 @@ const createPaymentMethod = (params?: { isActive: params?.isActive ?? true, isSystem: params?.isSystem ?? false, isDefault: params?.isDefault ?? false, - systemKey: Maybe.none(), }, UniqueID.generateNewID() ); @@ -45,7 +44,6 @@ describe("PaymentMethod aggregate", () => { isActive: false, isSystem: false, isDefault: true, - systemKey: Maybe.none(), }, UniqueID.generateNewID() ); @@ -81,7 +79,6 @@ describe("PaymentMethod aggregate", () => { isActive: true, isSystem: true, isDefault: false, - systemKey: Maybe.some("cash"), }, UniqueID.generateNewID() ); @@ -105,4 +102,29 @@ describe("PaymentMethod aggregate", () => { assert.equal(result.isSuccess, true); }); + + test("blocks deleting system payment methods", () => { + const paymentMethod = createPaymentMethod({ isSystem: true }); + + const result = paymentMethod.ensureCanBeDeleted(); + + assert.equal(result.isFailure, true); + }); + + test("blocks disabling system payment methods", () => { + const paymentMethod = createPaymentMethod({ isSystem: true }); + + const result = paymentMethod.disable(); + + assert.equal(result.isFailure, true); + }); + + test("keeps enable idempotent for system payment methods", () => { + const paymentMethod = createPaymentMethod({ isSystem: true }); + + const result = paymentMethod.enable(); + + assert.equal(result.isSuccess, true); + assert.equal(result.data, false); + }); }); diff --git a/modules/catalogs/src/api/domain/payment-methods/index.ts b/modules/catalogs/src/api/domain/payment-methods/index.ts index f1911097..16cffcb8 100644 --- a/modules/catalogs/src/api/domain/payment-methods/index.ts +++ b/modules/catalogs/src/api/domain/payment-methods/index.ts @@ -1,4 +1,3 @@ export * from "./errors"; export * from "./payment-method.aggregate"; export * from "./payment-method-name"; -export * from "./payment-method-system-key"; diff --git a/modules/catalogs/src/api/domain/payment-methods/payment-method-system-key.ts b/modules/catalogs/src/api/domain/payment-methods/payment-method-system-key.ts deleted file mode 100644 index 565c2089..00000000 --- a/modules/catalogs/src/api/domain/payment-methods/payment-method-system-key.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const PAYMENT_METHOD_SYSTEM_KEYS = [ - "cash", - "bank_transfer", - "card", - "direct_debit", -] as const; - -export type PaymentMethodSystemKey = (typeof PAYMENT_METHOD_SYSTEM_KEYS)[number]; - -export const isPaymentMethodSystemKey = (value: string): value is PaymentMethodSystemKey => { - return PAYMENT_METHOD_SYSTEM_KEYS.includes(value as PaymentMethodSystemKey); -}; diff --git a/modules/catalogs/src/api/domain/payment-methods/payment-method.aggregate.ts b/modules/catalogs/src/api/domain/payment-methods/payment-method.aggregate.ts index 7c057f89..5c16edc1 100644 --- a/modules/catalogs/src/api/domain/payment-methods/payment-method.aggregate.ts +++ b/modules/catalogs/src/api/domain/payment-methods/payment-method.aggregate.ts @@ -7,7 +7,6 @@ import { PaymentMethodCannotBeDeletedError, PaymentMethodCannotBeUpdatedError, } from "./errors"; -import type { PaymentMethodSystemKey } from "./payment-method-system-key"; export interface IPaymentMethodCreateProps { companyId: UniqueID; @@ -16,7 +15,6 @@ export interface IPaymentMethodCreateProps { isActive: boolean; isSystem: boolean; isDefault: boolean; - systemKey: Maybe; } export type PaymentMethodPatchProps = Partial<{ @@ -71,14 +69,6 @@ export class PaymentMethod extends AggregateRoot { ); } - if (props.isSystem && props.systemKey.isNone()) { - return Result.fail(new Error("System payment methods require a system key.")); - } - - if (!props.isSystem && props.systemKey.isSome()) { - return Result.fail(new Error("Custom payment methods cannot define a system key.")); - } - return Result.ok(); } @@ -114,10 +104,6 @@ export class PaymentMethod extends AggregateRoot { return this.props.isDefault; } - public get systemKey(): Maybe { - return this.props.systemKey; - } - public update(patchProps: PaymentMethodPatchProps): Result { if (this.isSystem) { return Result.fail( diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/di/payment-methods.di.ts b/modules/catalogs/src/api/infrastructure/payment-methods/di/payment-methods.di.ts index eeb955a6..5cbb22e5 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/di/payment-methods.di.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/di/payment-methods.di.ts @@ -3,8 +3,6 @@ import type { Sequelize } from "sequelize"; import { type IPaymentMethodPublicFinder, - BootstrapSystemPaymentMethodsService, - BootstrapSystemPaymentMethodsUseCase, PaymentMethodPublicFinder, PaymentMethodPublicModelMapper, SetDefaultPaymentMethodByIdUseCase, @@ -43,7 +41,6 @@ export type PaymentMethodsInternalDeps = { disablePaymentMethodById: () => DisablePaymentMethodByIdUseCase; enablePaymentMethodById: () => EnablePaymentMethodByIdUseCase; setDefaultPaymentMethodById: () => SetDefaultPaymentMethodByIdUseCase; - bootstrapSystemPaymentMethods: () => BootstrapSystemPaymentMethodsUseCase; }; }; @@ -67,10 +64,6 @@ export const buildPaymentMethodsDependencies = ( const deleter = buildPaymentMethodDeleter({ repository, usageChecker }); const statusChanger = buildPaymentMethodStatusChanger({ repository }); const setDefaultService = new SetDefaultPaymentMethodService(repository); - const bootstrapService = new BootstrapSystemPaymentMethodsService({ - repository, - setDefaultService, - }); const snapshotBuilders = buildPaymentMethodSnapshotBuilders(); @@ -130,13 +123,6 @@ export const buildPaymentMethodsDependencies = ( fullSnapshotBuilder: snapshotBuilders.full, transactionManager, }), - - bootstrapSystemPaymentMethods: () => - new BootstrapSystemPaymentMethodsUseCase({ - bootstrapService, - fullSnapshotBuilder: snapshotBuilders.full, - transactionManager, - }), }, }; }; diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/bootstrap-system-payment-methods.controller.ts b/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/bootstrap-system-payment-methods.controller.ts deleted file mode 100644 index b2bd1a1a..00000000 --- a/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/bootstrap-system-payment-methods.controller.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - ExpressController, - forbidQueryFieldGuard, - requireAuthenticatedGuard, - requireCompanyContextGuard, -} from "@erp/core/api"; - -import type { BootstrapSystemPaymentMethodsUseCase } from "../../../../application"; -import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper"; - -export class BootstrapSystemPaymentMethodsController extends ExpressController { - constructor(private readonly useCase: BootstrapSystemPaymentMethodsUseCase) { - super(); - - this.errorMapper = paymentMethodsApiErrorMapper; - - this.registerGuards( - requireAuthenticatedGuard(), - requireCompanyContextGuard(), - forbidQueryFieldGuard("companyId") - ); - } - - protected async executeImpl() { - const companyId = this.getTenantId(); - if (!companyId) { - return this.forbiddenError("Tenant ID not found"); - } - - const result = await this.useCase.execute({ companyId }); - - return result.match( - (data) => this.ok(data), - (err) => this.handleError(err) - ); - } -} diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/index.ts b/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/index.ts index 5614f368..80143715 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/index.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/express/controllers/index.ts @@ -4,6 +4,5 @@ export * from "./disable-payment-method-by-id.controller"; export * from "./enable-payment-method-by-id.controller"; export * from "./get-payment-method-by-id.controller"; export * from "./list-payment-methods.controller"; -export * from "./bootstrap-system-payment-methods.controller"; export * from "./set-default-payment-method-by-id.controller"; export * from "./update-payment-method-by-id.controller"; diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/express/payment-methods.routes.ts b/modules/catalogs/src/api/infrastructure/payment-methods/express/payment-methods.routes.ts index 2e5228da..981f6838 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/express/payment-methods.routes.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/express/payment-methods.routes.ts @@ -3,7 +3,6 @@ import { requireIdentityTenantMembership } from "@erp/identity/api"; import { type NextFunction, type Request, type Response, Router } from "express"; import { - BootstrapSystemPaymentMethodsRequestSchema, CreatePaymentMethodRequestSchema, DeletePaymentMethodByIdRequestSchema, GetPaymentMethodByIdRequestSchema, @@ -15,7 +14,6 @@ import { import type { CatalogsInternalDeps } from "../../di/catalogs.di"; import { - BootstrapSystemPaymentMethodsController, CreatePaymentMethodController, DeletePaymentMethodByIdController, DisablePaymentMethodByIdController, @@ -47,17 +45,6 @@ export const paymentMethodsRouter = (params: StartParams) => { } ); - router.post( - "/bootstrap-system", - validateRequest(BootstrapSystemPaymentMethodsRequestSchema, "body"), - (req: Request, res: Response, next: NextFunction) => { - const controller = new BootstrapSystemPaymentMethodsController( - deps.useCases.bootstrapSystemPaymentMethods() - ); - return controller.execute(req, res, next); - } - ); - router.post( "/", validateRequest(CreatePaymentMethodRequestSchema, "body"), diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/mappers/sequelize-payment-method-domain.mapper.ts b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/mappers/sequelize-payment-method-domain.mapper.ts index d1dc0125..86aff98d 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/mappers/sequelize-payment-method-domain.mapper.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/mappers/sequelize-payment-method-domain.mapper.ts @@ -11,7 +11,7 @@ import { } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; -import { PaymentMethod, isPaymentMethodSystemKey } from "../../../../../domain"; +import { PaymentMethod } from "../../../../../domain"; import type { PaymentMethodCreationAttributes, PaymentMethodModel } from "../models"; export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper< @@ -44,15 +44,6 @@ export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper< "description", errors ); - const systemKey = extractOrPushError( - maybeFromNullableResult(source.system_key, (value) => - isPaymentMethodSystemKey(value) - ? Result.ok(value) - : Result.fail(new Error(`Invalid payment method system key: ${value}`)) - ), - "system_key", - errors - ); // Si hubo errores de mapeo, devolvemos colección de validación if (errors.length > 0) { @@ -69,7 +60,6 @@ export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper< isActive: source.is_active, isSystem: source.is_system, isDefault: source.is_default, - systemKey: systemKey!, }, idResult.data ); @@ -92,10 +82,6 @@ export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper< is_active: source.isActive, is_system: source.isSystem, is_default: source.isDefault, - system_key: source.systemKey.match( - (systemKey) => systemKey, - () => null - ), }); } } diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/models/sequelize-payment-method.model.ts b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/models/sequelize-payment-method.model.ts index ae94b909..d95d3491 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/models/sequelize-payment-method.model.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/models/sequelize-payment-method.model.ts @@ -20,7 +20,6 @@ export class PaymentMethodModel extends Model< declare is_active: boolean; declare is_system: boolean; declare is_default: boolean; - declare system_key: CreationOptional; static associate(_database: Sequelize) {} @@ -65,11 +64,6 @@ export default (database: Sequelize) => { allowNull: false, defaultValue: false, }, - system_key: { - type: DataTypes.STRING(40), - allowNull: true, - defaultValue: null, - }, }, { sequelize: database, @@ -91,13 +85,6 @@ export default (database: Sequelize) => { defaultScope: {}, scopes: {}, - indexes: [ - { - name: "uq_payment_methods_company_system_key", - fields: ["company_id", "system_key"], - unique: true, - }, - ], } ); diff --git a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/repositories/sequelize-payment-method.repository.ts b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/repositories/sequelize-payment-method.repository.ts index 6aded0c8..8158ece9 100644 --- a/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/repositories/sequelize-payment-method.repository.ts +++ b/modules/catalogs/src/api/infrastructure/payment-methods/persistence/sequelize/repositories/sequelize-payment-method.repository.ts @@ -11,7 +11,7 @@ import type { Sequelize, Transaction } from "sequelize"; import type { IPaymentMethodRepository } from "../../../../../application"; import type { PaymentMethodSummary } from "../../../../../application/payment-methods/models"; -import type { PaymentMethod, PaymentMethodSystemKey } from "../../../../../domain"; +import type { PaymentMethod } from "../../../../../domain"; import type { SequelizePaymentMethodSummaryMapper } from "../mappers"; import type { SequelizePaymentMethodDomainMapper } from "../mappers/sequelize-payment-method-domain.mapper"; import { PaymentMethodModel } from "../models"; @@ -202,90 +202,6 @@ export class SequelizePaymentMethodRepository } } - public async findBySystemKeyInCompany( - companyId: UniqueID, - systemKey: PaymentMethodSystemKey, - transaction?: Transaction, - options?: { includeDeleted?: boolean } - ): Promise, Error>> { - try { - const row = await PaymentMethodModel.findOne({ - where: { - company_id: companyId.toString(), - system_key: systemKey, - }, - paranoid: !(options?.includeDeleted ?? false), - transaction, - }); - - if (!row) { - return Result.ok(Maybe.none()); - } - - const mappedResult = this.domainMapper.mapToDomain(row); - if (mappedResult.isFailure) { - return Result.fail(mappedResult.error); - } - - return Result.ok(Maybe.some(mappedResult.data)); - } catch (error: unknown) { - return Result.fail(translateSequelizeError(error)); - } - } - - public async restoreByIdInCompany( - companyId: UniqueID, - id: UniqueID, - transaction?: Transaction - ): Promise> { - try { - const restored = await PaymentMethodModel.restore({ - where: { - id: id.toString(), - company_id: companyId.toString(), - }, - transaction, - }); - - return Result.ok(restored > 0); - } catch (error: unknown) { - return Result.fail(translateSequelizeError(error)); - } - } - - public async syncSystemPaymentMethodState(params: { - companyId: UniqueID; - id: UniqueID; - name: string; - isDefault: boolean; - systemKey: PaymentMethodSystemKey; - transaction?: Transaction; - }): Promise> { - try { - await PaymentMethodModel.update( - { - name: params.name, - is_active: true, - is_system: true, - is_default: params.isDefault, - system_key: params.systemKey, - }, - { - where: { - id: params.id.toString(), - company_id: params.companyId.toString(), - }, - paranoid: false, - transaction: params.transaction, - } - ); - - return Result.ok(); - } catch (error: unknown) { - return Result.fail(translateSequelizeError(error)); - } - } - public async lockByCompanyId( companyId: UniqueID, transaction?: Transaction diff --git a/modules/catalogs/src/common/dto/payment-methods/request/bootstrap-system-payment-methods.request.dto.ts b/modules/catalogs/src/common/dto/payment-methods/request/bootstrap-system-payment-methods.request.dto.ts deleted file mode 100644 index 34026b1b..00000000 --- a/modules/catalogs/src/common/dto/payment-methods/request/bootstrap-system-payment-methods.request.dto.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { z } from "zod/v4"; - -export const BootstrapSystemPaymentMethodsRequestSchema = z.object({}); - -export type BootstrapSystemPaymentMethodsRequestDTO = z.infer< - typeof BootstrapSystemPaymentMethodsRequestSchema ->; diff --git a/modules/catalogs/src/common/dto/payment-methods/request/index.ts b/modules/catalogs/src/common/dto/payment-methods/request/index.ts index 0e5779a7..7cedbbaf 100644 --- a/modules/catalogs/src/common/dto/payment-methods/request/index.ts +++ b/modules/catalogs/src/common/dto/payment-methods/request/index.ts @@ -1,5 +1,4 @@ export * from "./create-payment-method.request.dto"; -export * from "./bootstrap-system-payment-methods.request.dto"; export * from "./delete-payment-method-by-id.request.dto"; export * from "./get-payment-method-by-id.request.dto"; export * from "./list-payment-methods.request.dto"; diff --git a/modules/catalogs/src/common/dto/payment-methods/response/bootstrap-system-payment-methods.response.dto.ts b/modules/catalogs/src/common/dto/payment-methods/response/bootstrap-system-payment-methods.response.dto.ts deleted file mode 100644 index c914516e..00000000 --- a/modules/catalogs/src/common/dto/payment-methods/response/bootstrap-system-payment-methods.response.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { z } from "zod/v4"; - -import { PaymentMethodDetailSchema } from "../shared"; - -export const BootstrapSystemPaymentMethodsResponseSchema = z.object({ - items: z.array(PaymentMethodDetailSchema), -}); - -export type BootstrapSystemPaymentMethodsResponseDTO = z.infer< - typeof BootstrapSystemPaymentMethodsResponseSchema ->; diff --git a/modules/catalogs/src/common/dto/payment-methods/response/index.ts b/modules/catalogs/src/common/dto/payment-methods/response/index.ts index 52bb2443..9d15b390 100644 --- a/modules/catalogs/src/common/dto/payment-methods/response/index.ts +++ b/modules/catalogs/src/common/dto/payment-methods/response/index.ts @@ -1,5 +1,4 @@ export * from "./create-payment-method.response.dto"; -export * from "./bootstrap-system-payment-methods.response.dto"; export * from "./disable-payment-method-by-id.response.dto"; export * from "./get-payment-method-by-id.response.dto"; export * from "./list-payment-methods.response.dto"; diff --git a/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/linux/FastReportCliGenerator b/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/linux/FastReportCliGenerator index fea5bf34..3c1eee87 100755 Binary files a/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/linux/FastReportCliGenerator and b/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/linux/FastReportCliGenerator differ diff --git a/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/windows/FastReportCliGenerator.exe b/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/windows/FastReportCliGenerator.exe index 82c6cf0b..df6b937b 100755 Binary files a/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/windows/FastReportCliGenerator.exe and b/tools/fastreportcli-net-core-skia/FastReportCliGenerator/publish/windows/FastReportCliGenerator.exe differ