From 475ab9fec3a6909b2c3c553af8bd1a9a68bd018b Mon Sep 17 00:00:00 2001 From: david Date: Fri, 22 May 2026 21:20:47 +0200 Subject: [PATCH] . --- .../snapshot-builders/full/index.ts | 2 +- .../payment-terms/repositories/index.ts | 2 +- .../payment-terms/services/index.ts | 12 ++-- .../services/payment-term-updater.ts | 3 + .../delete-payment-term-by-id.use-case.ts | 2 +- .../disable-payment-term-by-id.use-case.ts | 2 +- .../enable-payment-term-by-id.use-case.ts | 2 +- .../src/api/domain/payment-terms/errors.ts | 8 +-- .../payment-terms/payment-term-due-days.ts | 4 ++ .../payment-term-due-rules.collection.ts | 53 ++++++++++++++++-- .../payment-terms/payment-term.aggregate.ts | 55 +++++++++---------- 11 files changed, 96 insertions(+), 49 deletions(-) diff --git a/modules/catalogs/src/api/application/payment-methods/snapshot-builders/full/index.ts b/modules/catalogs/src/api/application/payment-methods/snapshot-builders/full/index.ts index d22b69f7..aeac11e0 100644 --- a/modules/catalogs/src/api/application/payment-methods/snapshot-builders/full/index.ts +++ b/modules/catalogs/src/api/application/payment-methods/snapshot-builders/full/index.ts @@ -1 +1 @@ -export * from './payment-method-full-snapshot-builder'; +export * from "./payment-method-full-snapshot-builder"; diff --git a/modules/catalogs/src/api/application/payment-terms/repositories/index.ts b/modules/catalogs/src/api/application/payment-terms/repositories/index.ts index e0a81431..b0004e2c 100644 --- a/modules/catalogs/src/api/application/payment-terms/repositories/index.ts +++ b/modules/catalogs/src/api/application/payment-terms/repositories/index.ts @@ -1 +1 @@ -export * from './payment-term-repository.interface'; +export * from "./payment-term-repository.interface"; diff --git a/modules/catalogs/src/api/application/payment-terms/services/index.ts b/modules/catalogs/src/api/application/payment-terms/services/index.ts index ba5f8de6..d832b626 100644 --- a/modules/catalogs/src/api/application/payment-terms/services/index.ts +++ b/modules/catalogs/src/api/application/payment-terms/services/index.ts @@ -1,6 +1,6 @@ -export * from './payment-term-creator'; -export * from './payment-term-deleter'; -export * from './payment-term-finder'; -export * from './payment-term-public-services'; -export * from './payment-term-status-changer'; -export * from './payment-term-updater'; +export * from "./payment-term-creator"; +export * from "./payment-term-deleter"; +export * from "./payment-term-finder"; +export * from "./payment-term-public-services"; +export * from "./payment-term-status-changer"; +export * from "./payment-term-updater"; diff --git a/modules/catalogs/src/api/application/payment-terms/services/payment-term-updater.ts b/modules/catalogs/src/api/application/payment-terms/services/payment-term-updater.ts index 17f57701..b465f861 100644 --- a/modules/catalogs/src/api/application/payment-terms/services/payment-term-updater.ts +++ b/modules/catalogs/src/api/application/payment-terms/services/payment-term-updater.ts @@ -30,6 +30,8 @@ export class PaymentTermUpdater implements IPaymentTermUpdater { } const paymentTerm = existingResult.data; + + // Aplicar cambios en el agregado const updateResult = paymentTerm.update(patchProps); if (updateResult.isFailure) { return Result.fail(updateResult.error); @@ -39,6 +41,7 @@ export class PaymentTermUpdater implements IPaymentTermUpdater { return Result.ok(paymentTerm); } + // Persistir cambios const saveResult = await this.repository.update(paymentTerm, transaction); if (saveResult.isFailure) { return Result.fail(saveResult.error); diff --git a/modules/catalogs/src/api/application/payment-terms/use-cases/delete-payment-term-by-id.use-case.ts b/modules/catalogs/src/api/application/payment-terms/use-cases/delete-payment-term-by-id.use-case.ts index 73e44a9c..ced4b4b8 100644 --- a/modules/catalogs/src/api/application/payment-terms/use-cases/delete-payment-term-by-id.use-case.ts +++ b/modules/catalogs/src/api/application/payment-terms/use-cases/delete-payment-term-by-id.use-case.ts @@ -1,5 +1,5 @@ import type { ITransactionManager } from "@erp/core/api"; -import type { UniqueID } from "@repo/rdx-ddd"; +import { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { IPaymentTermDeleter, IPaymentTermFinder } from "../services"; diff --git a/modules/catalogs/src/api/application/payment-terms/use-cases/disable-payment-term-by-id.use-case.ts b/modules/catalogs/src/api/application/payment-terms/use-cases/disable-payment-term-by-id.use-case.ts index 5d62c374..d203b017 100644 --- a/modules/catalogs/src/api/application/payment-terms/use-cases/disable-payment-term-by-id.use-case.ts +++ b/modules/catalogs/src/api/application/payment-terms/use-cases/disable-payment-term-by-id.use-case.ts @@ -1,5 +1,5 @@ import type { ITransactionManager } from "@erp/core/api"; -import type { UniqueID } from "@repo/rdx-ddd"; +import { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { IPaymentTermFinder, IPaymentTermStatusChanger } from "../services"; diff --git a/modules/catalogs/src/api/application/payment-terms/use-cases/enable-payment-term-by-id.use-case.ts b/modules/catalogs/src/api/application/payment-terms/use-cases/enable-payment-term-by-id.use-case.ts index a0404838..356ce6b8 100644 --- a/modules/catalogs/src/api/application/payment-terms/use-cases/enable-payment-term-by-id.use-case.ts +++ b/modules/catalogs/src/api/application/payment-terms/use-cases/enable-payment-term-by-id.use-case.ts @@ -1,5 +1,5 @@ import type { ITransactionManager } from "@erp/core/api"; -import type { UniqueID } from "@repo/rdx-ddd"; +import { UniqueID } from "@repo/rdx-ddd"; import { Result } from "@repo/rdx-utils"; import type { IPaymentTermFinder, IPaymentTermStatusChanger } from "../services"; diff --git a/modules/catalogs/src/api/domain/payment-terms/errors.ts b/modules/catalogs/src/api/domain/payment-terms/errors.ts index 46d92975..0c11628a 100644 --- a/modules/catalogs/src/api/domain/payment-terms/errors.ts +++ b/modules/catalogs/src/api/domain/payment-terms/errors.ts @@ -108,10 +108,10 @@ export class PaymentTermDueRuleMismatch extends DomainError { * @param options - Opciones nativas de Error (puedes pasar `cause`). */ constructor(position: number, options?: ErrorOptions) { - super( - `Error. Payment term due rule with position '${position}' rejected due to currency/language mismatch.`, - options - ); + const causeMessage = options?.cause + ? String(options.cause) + : `Payment term due rule with position '${position}' rejected due to mismatch with existing rules.`; + super(causeMessage, options); this.name = "PaymentTermDueRuleMismatch"; } } diff --git a/modules/catalogs/src/api/domain/payment-terms/payment-term-due-days.ts b/modules/catalogs/src/api/domain/payment-terms/payment-term-due-days.ts index eb33ef59..72caa904 100644 --- a/modules/catalogs/src/api/domain/payment-terms/payment-term-due-days.ts +++ b/modules/catalogs/src/api/domain/payment-terms/payment-term-due-days.ts @@ -32,6 +32,10 @@ export class PaymentTermDueDays extends ValueObject<{ value: number }> { return this.props.value; } + public toString(): string { + return this.props.value.toString(); + } + public getProps() { return this.props; } diff --git a/modules/catalogs/src/api/domain/payment-terms/payment-term-due-rules.collection.ts b/modules/catalogs/src/api/domain/payment-terms/payment-term-due-rules.collection.ts index ce5677be..334c2c09 100644 --- a/modules/catalogs/src/api/domain/payment-terms/payment-term-due-rules.collection.ts +++ b/modules/catalogs/src/api/domain/payment-terms/payment-term-due-rules.collection.ts @@ -27,13 +27,36 @@ export class PaymentTermDueRules super(props.rules ?? []); } - public static create(props: PaymentTermDueRulesProps): PaymentTermDueRules { - const { rules } = props; + public totalPercentage(): number { + return this.getAll().reduce((acc, rule) => acc + rule.percentage.value, 0); + } - if (!rules || rules.length === 0) { - return new PaymentTermDueRules({ rules: [] }); + public hasTotalPercentage100(): boolean { + return this.totalPercentage() === 10000; + } + + public add(item: PaymentTermDueRule): boolean { + const ordered = PaymentTermDueRules.validateRules([...this.getAll(), item]); + this.items = ordered; + if (this.totalItems !== null) { + this.totalItems = ordered.length; } + return true; + } + public addCollection(collection: Collection): boolean { + const ordered = PaymentTermDueRules.validateRules([...this.getAll(), ...collection.getAll()]); + this.items = ordered; + if (this.totalItems !== null) { + this.totalItems = ordered.length; + } + return true; + } + + private static validateRules( + rules: PaymentTermDueRule[], + requireExactTotal = false + ): PaymentTermDueRule[] { const ordered = [...rules].sort( (first, second) => first.dueDays.toPrimitive() - second.dueDays.toPrimitive() ); @@ -56,12 +79,30 @@ export class PaymentTermDueRules totalPercentage += percentage.value; } - if (totalPercentage !== 10000) { + if (requireExactTotal) { + if (totalPercentage !== 10000) { + throw new PaymentTermPercentageSumMismatchError( + "Payment term due rule percentages must sum exactly 100.00." + ); + } + } else if (totalPercentage > 10000) { throw new PaymentTermPercentageSumMismatchError( - "Payment term due rule percentages must sum exactly 100.00." + "Payment term due rule percentages must not exceed 100.00." ); } + return ordered; + } + + public static create(props: PaymentTermDueRulesProps): PaymentTermDueRules { + const { rules } = props; + + if (!rules || rules.length === 0) { + return new PaymentTermDueRules({ rules: [] }); + } + + const ordered = PaymentTermDueRules.validateRules(rules, true); + return new PaymentTermDueRules({ rules: ordered }); } } diff --git a/modules/catalogs/src/api/domain/payment-terms/payment-term.aggregate.ts b/modules/catalogs/src/api/domain/payment-terms/payment-term.aggregate.ts index b85813b5..d4ff8a1f 100644 --- a/modules/catalogs/src/api/domain/payment-terms/payment-term.aggregate.ts +++ b/modules/catalogs/src/api/domain/payment-terms/payment-term.aggregate.ts @@ -5,6 +5,7 @@ import { PaymentTermCannotBeDisabledError, PaymentTermCannotBeUpdatedError, PaymentTermDueRuleMismatch, + PaymentTermPercentageSumMismatchError, } from "./errors"; import { PaymentTermDueRule, @@ -107,12 +108,25 @@ export class PaymentTerm extends AggregateRoot { return Result.fail(ruleResult.error); } - const added = this._dueRules.add(ruleResult.data); - - if (!added) { - return Result.fail(new PaymentTermDueRuleMismatch(index)); + try { + const added = this._dueRules.add(ruleResult.data); + if (!added) { + return Result.fail(new PaymentTermDueRuleMismatch(index)); + } + } catch (err) { + const error = err as Error; + return Result.fail(new PaymentTermDueRuleMismatch(index, { cause: error.message })); } } + + if (!this._dueRules.hasTotalPercentage100()) { + return Result.fail( + new PaymentTermPercentageSumMismatchError( + "Payment term due rule percentages must sum exactly 100.00." + ) + ); + } + return Result.ok(); } @@ -140,7 +154,7 @@ export class PaymentTerm extends AggregateRoot { return this._dueRules; } - public update(patchProps: PaymentTermPatchProps): Result { + public update(patchProps: PaymentTermPatchProps): Result { if (this.isSystem) { return Result.fail( new PaymentTermCannotBeUpdatedError("System payment terms cannot be updated.") @@ -152,28 +166,15 @@ export class PaymentTerm extends AggregateRoot { return Result.fail(validationResult.error); } - let hasChanges = false; + const { dueRules, ...otherProps } = patchProps; - if ( - patchProps.name !== undefined && - patchProps.name.toPrimitive() !== this.props.name.toPrimitive() - ) { - this.props.name = patchProps.name; - hasChanges = true; - } + const candidateProps: PaymentTermInternalProps = { + ...this.props, + ...otherProps, + }; - if ( - patchProps.description !== undefined && - !PaymentTerm.sameDescription(this.props.description, patchProps.description) - ) { - this.props.description = patchProps.description; - hasChanges = true; - } - - if (patchProps.isActive !== undefined && this.props.isActive !== patchProps.isActive) { - this.props.isActive = patchProps.isActive; - hasChanges = true; - } + // Aplicar cambios + Object.assign(this.props, candidateProps); // Reemplazo de items (si se proporciona) if (patchProps.dueRules !== undefined) { @@ -181,11 +182,9 @@ export class PaymentTerm extends AggregateRoot { if (initializeResult.isFailure) { return Result.fail(initializeResult.error); } - - hasChanges = true; } - return Result.ok(hasChanges); + return Result.ok(); } public disable(): Result {