Formas de pago
This commit is contained in:
parent
cd4b8975c3
commit
32dbd7d31f
@ -50,7 +50,10 @@
|
||||
"noInferrableTypes": "error",
|
||||
"noNamespace": "error",
|
||||
"noNegationElse": "warn",
|
||||
"noNonNullAssertion": "info",
|
||||
"noNonNullAssertion": {
|
||||
"level": "info",
|
||||
"fix": "none"
|
||||
},
|
||||
"noParameterAssign": "error",
|
||||
"noUnusedTemplateLiteral": "error",
|
||||
"noUselessElse": "warn",
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
export * from "./payment-method-creator.di";
|
||||
export * from "./payment-method-deleter.di";
|
||||
export * from "./payment-method-finder.di";
|
||||
export * from "./payment-method-input-mappers.di";
|
||||
export * from "./payment-method-snapshot-builders.di";
|
||||
export * from "./payment-method-status-changer.di";
|
||||
export * from "./payment-method-updater.di";
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
import { type IPaymentMethodDeleter, PaymentMethodDeleter } from "../services";
|
||||
|
||||
export const buildPaymentMethodDeleter = (params: {
|
||||
repository: IPaymentMethodRepository;
|
||||
}): IPaymentMethodDeleter => {
|
||||
const { repository } = params;
|
||||
|
||||
return new PaymentMethodDeleter(repository);
|
||||
};
|
||||
@ -1,8 +1,10 @@
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
import { type IPaymentMethodFinder, PaymentMethodFinder } from "../services";
|
||||
|
||||
export function buildPaymentMethodFinder(
|
||||
repository: IPaymentMethodRepository
|
||||
): IPaymentMethodFinder {
|
||||
export function buildPaymentMethodFinder(params: {
|
||||
repository: IPaymentMethodRepository;
|
||||
}): IPaymentMethodFinder {
|
||||
const { repository } = params;
|
||||
|
||||
return new PaymentMethodFinder(repository);
|
||||
}
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
import { type IPaymentMethodStatusChanger, PaymentMethodStatusChanger } from "../services";
|
||||
|
||||
export const buildPaymentMethodStatusChanger = (params: {
|
||||
repository: IPaymentMethodRepository;
|
||||
}): IPaymentMethodStatusChanger => {
|
||||
const { repository } = params;
|
||||
|
||||
return new PaymentMethodStatusChanger(repository);
|
||||
};
|
||||
@ -1,5 +1,8 @@
|
||||
export * from "./payment-method-creator";
|
||||
export * from "./payment-method-deleter";
|
||||
export * from "./payment-method-disabler";
|
||||
export * from "./payment-method-enabler";
|
||||
export * from "./payment-method-finder";
|
||||
export * from "./payment-method-public-services";
|
||||
export * from "./payment-method-status-changer";
|
||||
export * from "./payment-method-updater";
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { PaymentMethod } from "../../domain";
|
||||
import { PaymentMethodCannotBeDeletedError } from "../../domain";
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
|
||||
export interface IPaymentMethodDeleter {
|
||||
delete(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>>;
|
||||
}
|
||||
|
||||
export class PaymentMethodDeleter implements IPaymentMethodDeleter {
|
||||
public constructor(private readonly repository: IPaymentMethodRepository) {}
|
||||
|
||||
public async delete(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>> {
|
||||
const { paymentMethod, transaction } = params;
|
||||
|
||||
if (paymentMethod.isSystem) {
|
||||
return Result.fail(
|
||||
new PaymentMethodCannotBeDeletedError("System payment methods cannot be deleted.")
|
||||
);
|
||||
}
|
||||
|
||||
const deleteResult = await this.repository.deleteByIdInCompany(
|
||||
paymentMethod.companyId,
|
||||
paymentMethod.id,
|
||||
transaction
|
||||
);
|
||||
|
||||
if (deleteResult.isFailure) {
|
||||
return Result.fail(deleteResult.error);
|
||||
}
|
||||
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import type { Transaction } from "sequelize";
|
||||
|
||||
import type { PaymentMethod } from "../../domain";
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
@ -7,7 +6,7 @@ import type { IPaymentMethodRepository } from "../repositories";
|
||||
export interface IPaymentMethodDisabler {
|
||||
disable(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: Transaction;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>>;
|
||||
}
|
||||
|
||||
@ -16,16 +15,22 @@ export class PaymentMethodDisabler implements IPaymentMethodDisabler {
|
||||
|
||||
async disable(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: Transaction;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>> {
|
||||
const { paymentMethod, transaction } = params;
|
||||
|
||||
const disableResult = paymentMethod.disable();
|
||||
|
||||
if (disableResult.isFailure) {
|
||||
return Result.fail(disableResult.error);
|
||||
}
|
||||
|
||||
if (!disableResult.data) {
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
|
||||
const persistenceResult = await this.repository.update(paymentMethod, transaction);
|
||||
|
||||
if (persistenceResult.isFailure) {
|
||||
return Result.fail(persistenceResult.error);
|
||||
}
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { PaymentMethod } from "../../domain";
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
|
||||
export interface IPaymentMethodEnabler {
|
||||
enable(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>>;
|
||||
}
|
||||
|
||||
export class PaymentMethodEnabler implements IPaymentMethodEnabler {
|
||||
constructor(private readonly repository: IPaymentMethodRepository) {}
|
||||
|
||||
async enable(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>> {
|
||||
const { paymentMethod, transaction } = params;
|
||||
|
||||
const enableResult = paymentMethod.enable();
|
||||
|
||||
if (enableResult.isFailure) {
|
||||
return Result.fail(enableResult.error);
|
||||
}
|
||||
|
||||
if (!enableResult.data) {
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
|
||||
const persistenceResult = await this.repository.update(paymentMethod, transaction);
|
||||
|
||||
if (persistenceResult.isFailure) {
|
||||
return Result.fail(persistenceResult.error);
|
||||
}
|
||||
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { PaymentMethod } from "../../domain";
|
||||
import type { IPaymentMethodRepository } from "../repositories";
|
||||
|
||||
export type PaymentMethodStatusChangeAction = "enable" | "disable";
|
||||
|
||||
export interface IPaymentMethodStatusChanger {
|
||||
changeStatus(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
action: PaymentMethodStatusChangeAction;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>>;
|
||||
}
|
||||
|
||||
export class PaymentMethodStatusChanger implements IPaymentMethodStatusChanger {
|
||||
public constructor(private readonly repository: IPaymentMethodRepository) {}
|
||||
|
||||
public async changeStatus(params: {
|
||||
paymentMethod: PaymentMethod;
|
||||
action: PaymentMethodStatusChangeAction;
|
||||
transaction?: unknown;
|
||||
}): Promise<Result<PaymentMethod, Error>> {
|
||||
const { paymentMethod, action, transaction } = params;
|
||||
|
||||
const statusResult = action === "enable" ? paymentMethod.enable() : paymentMethod.disable();
|
||||
|
||||
if (statusResult.isFailure) {
|
||||
return Result.fail(statusResult.error);
|
||||
}
|
||||
|
||||
if (!statusResult.data) {
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
|
||||
const persistenceResult = await this.repository.update(paymentMethod, transaction);
|
||||
|
||||
if (persistenceResult.isFailure) {
|
||||
return Result.fail(persistenceResult.error);
|
||||
}
|
||||
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
}
|
||||
@ -40,6 +40,13 @@ export class PaymentMethodUpdater implements IPaymentMethodUpdater {
|
||||
return Result.fail(updateResult.error);
|
||||
}
|
||||
|
||||
const hasChanges = updateResult.data;
|
||||
|
||||
if (!hasChanges) {
|
||||
// No hay cambios, retornar el agregado original
|
||||
return Result.ok(paymentMethod);
|
||||
}
|
||||
|
||||
// Persistir cambios
|
||||
const saveResult = await this.repository.update(paymentMethod, transaction);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ export class PaymentMethodFullSnapshotBuilder implements IPaymentMethodFullSnaps
|
||||
public toOutput(paymentMethod: PaymentMethod): GetPaymentMethodByIdResponseDTO {
|
||||
return {
|
||||
id: paymentMethod.id.toPrimitive(),
|
||||
company_id: paymentMethod.companyId.toPrimitive(),
|
||||
name: paymentMethod.name.toPrimitive(),
|
||||
description: toNullable(paymentMethod.description, (value) => value.toPrimitive()),
|
||||
is_active: paymentMethod.isActive,
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
import type { ITransactionManager } from "@erp/core/api";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { IPaymentMethodDeleter, IPaymentMethodFinder } from "../services";
|
||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
||||
|
||||
export type DeletePaymentMethodByIdUseCaseInput = {
|
||||
companyId: UniqueID;
|
||||
payment_method_id: string;
|
||||
};
|
||||
|
||||
export class DeletePaymentMethodByIdUseCase {
|
||||
constructor(
|
||||
private readonly deps: {
|
||||
finder: IPaymentMethodFinder;
|
||||
deleter: IPaymentMethodDeleter;
|
||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
||||
transactionManager: ITransactionManager;
|
||||
}
|
||||
) {}
|
||||
|
||||
public execute(params: DeletePaymentMethodByIdUseCaseInput) {
|
||||
const { payment_method_id, companyId } = params;
|
||||
|
||||
const idOrError = UniqueID.create(payment_method_id);
|
||||
if (idOrError.isFailure) return Result.fail(idOrError.error);
|
||||
|
||||
const paymentMethodId = idOrError.data;
|
||||
|
||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
||||
try {
|
||||
const findResult = await this.deps.finder.findPaymentMethodById(
|
||||
companyId,
|
||||
paymentMethodId,
|
||||
transaction
|
||||
);
|
||||
if (findResult.isFailure) {
|
||||
return Result.fail(findResult.error);
|
||||
}
|
||||
|
||||
const deleteResult = await this.deps.deleter.delete({
|
||||
paymentMethod: findResult.data,
|
||||
transaction,
|
||||
});
|
||||
|
||||
if (deleteResult.isFailure) {
|
||||
return Result.fail(deleteResult.error);
|
||||
}
|
||||
|
||||
return Result.ok(this.deps.fullSnapshotBuilder.toOutput(deleteResult.data));
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,39 +1,50 @@
|
||||
import type { ITransactionManager } from "@erp/core/api";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import type { Transaction } from "sequelize";
|
||||
|
||||
import type { IPaymentMethodDisabler, IPaymentMethodFinder } from "../services";
|
||||
import type { IPaymentMethodFinder, IPaymentMethodStatusChanger } from "../services";
|
||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
||||
|
||||
export type DisablePaymentMethodByIdUseCaseInput = {
|
||||
id: string;
|
||||
companyId: UniqueID;
|
||||
payment_method_id: string;
|
||||
};
|
||||
|
||||
export class DisablePaymentMethodByIdUseCase {
|
||||
constructor(
|
||||
private readonly deps: {
|
||||
finder: IPaymentMethodFinder;
|
||||
disabler: IPaymentMethodDisabler;
|
||||
changer: IPaymentMethodStatusChanger;
|
||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
||||
transactionManager: ITransactionManager;
|
||||
}
|
||||
) {}
|
||||
|
||||
public execute(params: DisablePaymentMethodByIdUseCaseInput) {
|
||||
const { id } = params;
|
||||
const { payment_method_id, companyId } = params;
|
||||
|
||||
const idOrError = UniqueID.create(payment_method_id);
|
||||
if (idOrError.isFailure) return Result.fail(idOrError.error);
|
||||
|
||||
const paymentMethodId = idOrError.data;
|
||||
|
||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
||||
const tx = transaction as Transaction;
|
||||
try {
|
||||
const findResult = await this.deps.finder.getById(id, tx);
|
||||
const findResult = await this.deps.finder.findPaymentMethodById(
|
||||
companyId,
|
||||
paymentMethodId,
|
||||
transaction
|
||||
);
|
||||
if (findResult.isFailure) {
|
||||
return Result.fail(findResult.error);
|
||||
}
|
||||
|
||||
const disableResult = await this.deps.disabler.disable({
|
||||
const disableResult = await this.deps.changer.changeStatus({
|
||||
paymentMethod: findResult.data,
|
||||
transaction: tx,
|
||||
action: "disable",
|
||||
transaction,
|
||||
});
|
||||
|
||||
if (disableResult.isFailure) {
|
||||
return Result.fail(disableResult.error);
|
||||
}
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
import type { ITransactionManager } from "@erp/core/api";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
|
||||
import type { IPaymentMethodFinder, IPaymentMethodStatusChanger } from "../services";
|
||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
||||
|
||||
export type EnablePaymentMethodByIdUseCaseInput = {
|
||||
companyId: UniqueID;
|
||||
payment_method_id: string;
|
||||
};
|
||||
|
||||
export class EnablePaymentMethodByIdUseCase {
|
||||
constructor(
|
||||
private readonly deps: {
|
||||
finder: IPaymentMethodFinder;
|
||||
changer: IPaymentMethodStatusChanger;
|
||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
||||
transactionManager: ITransactionManager;
|
||||
}
|
||||
) {}
|
||||
|
||||
public execute(params: EnablePaymentMethodByIdUseCaseInput) {
|
||||
const { payment_method_id, companyId } = params;
|
||||
|
||||
const idOrError = UniqueID.create(payment_method_id);
|
||||
if (idOrError.isFailure) return Result.fail(idOrError.error);
|
||||
|
||||
const paymentMethodId = idOrError.data;
|
||||
|
||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
||||
try {
|
||||
const findResult = await this.deps.finder.findPaymentMethodById(
|
||||
companyId,
|
||||
paymentMethodId,
|
||||
transaction
|
||||
);
|
||||
if (findResult.isFailure) {
|
||||
return Result.fail(findResult.error);
|
||||
}
|
||||
|
||||
const enableResult = await this.deps.changer.changeStatus({
|
||||
paymentMethod: findResult.data,
|
||||
action: "enable",
|
||||
transaction,
|
||||
});
|
||||
|
||||
if (enableResult.isFailure) {
|
||||
return Result.fail(enableResult.error);
|
||||
}
|
||||
|
||||
return Result.ok(this.deps.fullSnapshotBuilder.toOutput(enableResult.data));
|
||||
} catch (error: unknown) {
|
||||
return Result.fail(error as Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
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";
|
||||
export * from "./enable-payment-method-by-id.use-case";
|
||||
export * from "./get-payment-method-by-id.use-case";
|
||||
export * from "./list-payment-methods.use-case";
|
||||
export * from "./update-payment-method-by-id.use-case";
|
||||
|
||||
@ -7,6 +7,8 @@ export class InvalidPaymentMethodIdError extends DomainError {
|
||||
export const isInvalidPaymentMethodIdError = (e: unknown): e is InvalidPaymentMethodIdError =>
|
||||
e instanceof InvalidPaymentMethodIdError;
|
||||
|
||||
//
|
||||
|
||||
export class InvalidPaymentMethodNameError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_NAME" as const;
|
||||
}
|
||||
@ -14,10 +16,17 @@ export class InvalidPaymentMethodNameError extends DomainError {
|
||||
export const isInvalidPaymentMethodNameError = (e: unknown): e is InvalidPaymentMethodNameError =>
|
||||
e instanceof InvalidPaymentMethodNameError;
|
||||
|
||||
//
|
||||
|
||||
export class PaymentMethodNotFoundError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_NOT_FOUND" as const;
|
||||
}
|
||||
|
||||
export const isPaymentMethodNotFoundError = (e: unknown): e is PaymentMethodNotFoundError =>
|
||||
e instanceof PaymentMethodNotFoundError;
|
||||
|
||||
//
|
||||
|
||||
export class PaymentMethodCannotBeDeletedError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_CANNOT_BE_DELETED" as const;
|
||||
}
|
||||
@ -25,3 +34,33 @@ export class PaymentMethodCannotBeDeletedError extends DomainError {
|
||||
export const isPaymentMethodCannotBeDeletedError = (
|
||||
e: unknown
|
||||
): e is PaymentMethodCannotBeDeletedError => e instanceof PaymentMethodCannotBeDeletedError;
|
||||
|
||||
//
|
||||
|
||||
export class PaymentMethodCannotBeDisabledError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_CANNOT_BE_DISABLED" as const;
|
||||
}
|
||||
|
||||
export const isPaymentMethodCannotBeDisabledError = (
|
||||
e: unknown
|
||||
): e is PaymentMethodCannotBeDisabledError => e instanceof PaymentMethodCannotBeDisabledError;
|
||||
|
||||
//
|
||||
|
||||
export class PaymentMethodCannotBeEnabledError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_CANNOT_BE_ENABLED" as const;
|
||||
}
|
||||
|
||||
export const isPaymentMethodCannotBeEnabledError = (
|
||||
e: unknown
|
||||
): e is PaymentMethodCannotBeEnabledError => e instanceof PaymentMethodCannotBeEnabledError;
|
||||
|
||||
//
|
||||
|
||||
export class PaymentMethodCannotBeUpdatedError extends DomainError {
|
||||
public readonly code = "PAYMENT_METHOD_CANNOT_BE_UPDATED" as const;
|
||||
}
|
||||
|
||||
export const isPaymentMethodCannotBeUpdatedError = (
|
||||
e: unknown
|
||||
): e is PaymentMethodCannotBeUpdatedError => e instanceof PaymentMethodCannotBeUpdatedError;
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { AggregateRoot, type Name, type TextValue, type UniqueID } from "@repo/rdx-ddd";
|
||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
||||
|
||||
import { PaymentMethodCannotBeDisabledError, PaymentMethodCannotBeUpdatedError } from "./errors";
|
||||
|
||||
export interface IPaymentMethodCreateProps {
|
||||
companyId: UniqueID;
|
||||
name: Name;
|
||||
@ -9,14 +11,14 @@ export interface IPaymentMethodCreateProps {
|
||||
isSystem: boolean;
|
||||
}
|
||||
|
||||
export type PaymentMethodPatchProps = Partial<
|
||||
Omit<IPaymentMethodCreateProps, "companyId" | "isSystem">
|
||||
>;
|
||||
export type PaymentMethodPatchProps = Partial<{
|
||||
name: Name;
|
||||
description: Maybe<TextValue>;
|
||||
isActive: boolean;
|
||||
}>;
|
||||
|
||||
export type PaymentMethodInternalProps = IPaymentMethodCreateProps;
|
||||
|
||||
export type PaymentMethodProps = PaymentMethodPatchProps;
|
||||
|
||||
export class PaymentMethod extends AggregateRoot<PaymentMethodInternalProps> {
|
||||
protected constructor(props: PaymentMethodInternalProps, id?: UniqueID) {
|
||||
super(props, id); // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
@ -46,7 +48,23 @@ export class PaymentMethod extends AggregateRoot<PaymentMethodInternalProps> {
|
||||
return new PaymentMethod(props, id);
|
||||
}
|
||||
|
||||
private static validateCreateProps(_props: IPaymentMethodCreateProps): Result<void, Error> {
|
||||
private static validateCreateProps(props: IPaymentMethodCreateProps): Result<void, Error> {
|
||||
if (!props.companyId) {
|
||||
return Result.fail(new Error("Payment method company ID is required"));
|
||||
}
|
||||
|
||||
if (!props.name) {
|
||||
return Result.fail(new Error("Payment method name is required"));
|
||||
}
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
private static validatePatchProps(patchProps: PaymentMethodPatchProps): Result<void, Error> {
|
||||
if (Object.keys(patchProps).length === 0) {
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
return Result.ok();
|
||||
}
|
||||
|
||||
@ -70,38 +88,96 @@ export class PaymentMethod extends AggregateRoot<PaymentMethodInternalProps> {
|
||||
return this.props.isSystem;
|
||||
}
|
||||
|
||||
public update(props: Partial<PaymentMethodPatchProps>): Result<void, Error> {
|
||||
if (props.name !== undefined) {
|
||||
this.props.name = props.name;
|
||||
public update(patchProps: PaymentMethodPatchProps): Result<boolean, Error> {
|
||||
if (this.isSystem) {
|
||||
return Result.fail(
|
||||
new PaymentMethodCannotBeUpdatedError("System payment methods cannot be updated.")
|
||||
);
|
||||
}
|
||||
const validationResult = PaymentMethod.validatePatchProps(patchProps);
|
||||
|
||||
if (validationResult.isFailure) {
|
||||
return Result.fail(validationResult.error);
|
||||
}
|
||||
|
||||
if (props.description !== undefined) {
|
||||
this.props.description = props.description;
|
||||
let hasChanges = false;
|
||||
|
||||
if (
|
||||
patchProps.name !== undefined &&
|
||||
this.props.name.toPrimitive() !== patchProps.name.toPrimitive()
|
||||
) {
|
||||
this.props.name = patchProps.name;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (props.isActive !== undefined) {
|
||||
this.props.isActive = props.isActive;
|
||||
if (
|
||||
patchProps.description !== undefined &&
|
||||
!PaymentMethod.sameDescription(this.props.description, patchProps.description)
|
||||
) {
|
||||
this.props.description = patchProps.description;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return Result.ok();
|
||||
if (patchProps.isActive !== undefined && this.props.isActive !== patchProps.isActive) {
|
||||
this.props.isActive = patchProps.isActive;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
return Result.ok(hasChanges);
|
||||
}
|
||||
|
||||
public disable(): Result<void, Error> {
|
||||
public disable(): Result<boolean, Error> {
|
||||
if (this.isSystem) {
|
||||
return Result.fail(
|
||||
new PaymentMethodCannotBeDisabledError("System payment methods cannot be disabled.")
|
||||
);
|
||||
}
|
||||
|
||||
if (!this.isActive) {
|
||||
return Result.ok();
|
||||
return Result.ok(false);
|
||||
}
|
||||
|
||||
this.props.isActive = false;
|
||||
return Result.ok();
|
||||
|
||||
return Result.ok(true);
|
||||
}
|
||||
|
||||
public enable(): Result<boolean, Error> {
|
||||
if (this.isSystem) {
|
||||
return Result.ok(false);
|
||||
}
|
||||
|
||||
if (this.isActive) {
|
||||
return Result.ok(false);
|
||||
}
|
||||
|
||||
this.props.isActive = true;
|
||||
|
||||
return Result.ok(true);
|
||||
}
|
||||
|
||||
public toJSON() {
|
||||
return {
|
||||
id: this.id.toPrimitive(),
|
||||
name: this.props.name.toPrimitive(),
|
||||
description: this.props.description,
|
||||
company_id: this.companyId.toPrimitive(),
|
||||
name: this.name.toPrimitive(),
|
||||
description: this.description.match(
|
||||
(value) => value.toPrimitive(),
|
||||
() => null
|
||||
),
|
||||
is_active: this.isActive,
|
||||
is_system: this.isSystem,
|
||||
};
|
||||
}
|
||||
|
||||
private static sameDescription(current: Maybe<TextValue>, next: Maybe<TextValue>): boolean {
|
||||
return current.match(
|
||||
(currentValue) =>
|
||||
next.match(
|
||||
(nextValue) => currentValue.toPrimitive() === nextValue.toPrimitive(),
|
||||
() => false
|
||||
),
|
||||
() => next.isNone()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,16 +3,21 @@ import type { Sequelize } from "sequelize";
|
||||
|
||||
import {
|
||||
buildPaymentMethodCreator,
|
||||
buildPaymentMethodDeleter,
|
||||
buildPaymentMethodFinder,
|
||||
buildPaymentMethodInputMappers,
|
||||
buildPaymentMethodSnapshotBuilders,
|
||||
buildPaymentMethodStatusChanger,
|
||||
buildPaymentMethodUpdater,
|
||||
} from "../../application";
|
||||
import type { IPaymentMethodRepository } from "../../application/repositories";
|
||||
import type { IPaymentMethodFinder } from "../../application/services";
|
||||
import { PaymentMethodFinder, PaymentMethodUpdater } from "../../application/services";
|
||||
import { PaymentMethodFinder } from "../../application/services";
|
||||
import {
|
||||
CreatePaymentMethodUseCase,
|
||||
type DisablePaymentMethodByIdUseCase,
|
||||
DeletePaymentMethodByIdUseCase,
|
||||
DisablePaymentMethodByIdUseCase,
|
||||
EnablePaymentMethodByIdUseCase,
|
||||
GetPaymentMethodByIdUseCase,
|
||||
ListPaymentMethodsUseCase,
|
||||
UpdatePaymentMethodByIdUseCase,
|
||||
@ -28,7 +33,9 @@ export type PaymentMethodsInternalDeps = {
|
||||
getPaymentMethodById: () => GetPaymentMethodByIdUseCase;
|
||||
createPaymentMethod: () => CreatePaymentMethodUseCase;
|
||||
updatePaymentMethodById: () => UpdatePaymentMethodByIdUseCase;
|
||||
deletePaymentMethodById: () => DeletePaymentMethodByIdUseCase;
|
||||
disablePaymentMethodById: () => DisablePaymentMethodByIdUseCase;
|
||||
enablePaymentMethodById: () => EnablePaymentMethodByIdUseCase;
|
||||
};
|
||||
};
|
||||
|
||||
@ -45,10 +52,11 @@ export const buildPaymentMethodsDependencies = (
|
||||
|
||||
// Application helpers
|
||||
const inputMappers = buildPaymentMethodInputMappers();
|
||||
const finder = buildPaymentMethodFinder(repository);
|
||||
const finder = buildPaymentMethodFinder({ repository });
|
||||
const creator = buildPaymentMethodCreator({ repository });
|
||||
const updater = new PaymentMethodUpdater(repository);
|
||||
//const disabler = new PaymentMethodDisabler(repository);
|
||||
const updater = buildPaymentMethodUpdater({ repository });
|
||||
const deleter = buildPaymentMethodDeleter({ repository });
|
||||
const statusChanger = buildPaymentMethodStatusChanger({ repository });
|
||||
|
||||
const snapshotBuilders = buildPaymentMethodSnapshotBuilders();
|
||||
|
||||
@ -57,8 +65,10 @@ export const buildPaymentMethodsDependencies = (
|
||||
useCases: {
|
||||
listPaymentMethods: () =>
|
||||
new ListPaymentMethodsUseCase(finder, snapshotBuilders.summary, transactionManager),
|
||||
|
||||
getPaymentMethodById: () =>
|
||||
new GetPaymentMethodByIdUseCase(finder, snapshotBuilders.full, transactionManager),
|
||||
|
||||
createPaymentMethod: () =>
|
||||
new CreatePaymentMethodUseCase({
|
||||
dtoMapper: inputMappers.createInputMapper,
|
||||
@ -75,13 +85,30 @@ export const buildPaymentMethodsDependencies = (
|
||||
fullSnapshotBuilder: snapshotBuilders.full,
|
||||
transactionManager,
|
||||
}),
|
||||
/*disablePaymentMethodById: () =>
|
||||
|
||||
deletePaymentMethodById: () =>
|
||||
new DeletePaymentMethodByIdUseCase({
|
||||
deleter,
|
||||
finder,
|
||||
fullSnapshotBuilder: snapshotBuilders.full,
|
||||
transactionManager,
|
||||
}),
|
||||
|
||||
disablePaymentMethodById: () =>
|
||||
new DisablePaymentMethodByIdUseCase({
|
||||
finder,
|
||||
disabler,
|
||||
fullSnapshotBuilder,
|
||||
changer: statusChanger,
|
||||
fullSnapshotBuilder: snapshotBuilders.full,
|
||||
transactionManager,
|
||||
}),*/
|
||||
}),
|
||||
|
||||
enablePaymentMethodById: () =>
|
||||
new EnablePaymentMethodByIdUseCase({
|
||||
finder,
|
||||
changer: statusChanger,
|
||||
fullSnapshotBuilder: snapshotBuilders.full,
|
||||
transactionManager,
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -7,13 +7,13 @@ import {
|
||||
|
||||
import type { CreatePaymentMethodRequestDTO } from "../../../../../common";
|
||||
import type { CreatePaymentMethodUseCase } from "../../../../application";
|
||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class CreatePaymentMethodController extends ExpressController {
|
||||
constructor(private readonly useCase: CreatePaymentMethodUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentmethodsApiErrorMapper;
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
import {
|
||||
ExpressController,
|
||||
forbidQueryFieldGuard,
|
||||
requireAuthenticatedGuard,
|
||||
requireCompanyContextGuard,
|
||||
} from "@erp/core/api";
|
||||
|
||||
import type { DeletePaymentMethodByIdUseCase } from "../../../../application";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class DeletePaymentMethodByIdController extends ExpressController {
|
||||
constructor(private readonly useCase: DeletePaymentMethodByIdUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
requireAuthenticatedGuard(),
|
||||
requireCompanyContextGuard(),
|
||||
forbidQueryFieldGuard("companyId")
|
||||
);
|
||||
}
|
||||
|
||||
protected async executeImpl() {
|
||||
const companyId = this.getTenantId();
|
||||
if (!companyId) {
|
||||
return this.forbiddenError("Tenant ID not found");
|
||||
}
|
||||
|
||||
const { payment_method_id } = this.req.params;
|
||||
const result = await this.useCase.execute({ payment_method_id, companyId });
|
||||
|
||||
return result.match(
|
||||
(data) => this.ok(data),
|
||||
(err) => this.handleError(err)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,35 @@
|
||||
import { ExpressController } from "@erp/core/api";
|
||||
import {
|
||||
ExpressController,
|
||||
forbidQueryFieldGuard,
|
||||
requireAuthenticatedGuard,
|
||||
requireCompanyContextGuard,
|
||||
} from "@erp/core/api";
|
||||
|
||||
import type { DisablePaymentMethodByIdUseCase } from "../../../../application";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class DisablePaymentMethodByIdController extends ExpressController {
|
||||
constructor(private readonly useCase: DisablePaymentMethodByIdUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
requireAuthenticatedGuard(),
|
||||
requireCompanyContextGuard(),
|
||||
forbidQueryFieldGuard("companyId")
|
||||
);
|
||||
}
|
||||
|
||||
protected async executeImpl() {
|
||||
const id = this.req.params.payment_method_id;
|
||||
const result = await this.useCase.execute({ id });
|
||||
const companyId = this.getTenantId();
|
||||
if (!companyId) {
|
||||
return this.forbiddenError("Tenant ID not found");
|
||||
}
|
||||
|
||||
const { payment_method_id } = this.req.params;
|
||||
const result = await this.useCase.execute({ payment_method_id, companyId });
|
||||
|
||||
return result.match(
|
||||
(data) => this.ok(data),
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
import {
|
||||
ExpressController,
|
||||
forbidQueryFieldGuard,
|
||||
requireAuthenticatedGuard,
|
||||
requireCompanyContextGuard,
|
||||
} from "@erp/core/api";
|
||||
|
||||
import type { EnablePaymentMethodByIdUseCase } from "../../../../application";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class EnablePaymentMethodByIdController extends ExpressController {
|
||||
constructor(private readonly useCase: EnablePaymentMethodByIdUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
requireAuthenticatedGuard(),
|
||||
requireCompanyContextGuard(),
|
||||
forbidQueryFieldGuard("companyId")
|
||||
);
|
||||
}
|
||||
|
||||
protected async executeImpl() {
|
||||
const companyId = this.getTenantId();
|
||||
if (!companyId) {
|
||||
return this.forbiddenError("Tenant ID not found");
|
||||
}
|
||||
|
||||
const { payment_method_id } = this.req.params;
|
||||
const result = await this.useCase.execute({ payment_method_id, companyId });
|
||||
|
||||
return result.match(
|
||||
(data) => this.ok(data),
|
||||
(err) => this.handleError(err)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -6,13 +6,13 @@ import {
|
||||
} from "@erp/core/api";
|
||||
|
||||
import type { GetPaymentMethodByIdUseCase } from "../../../../application";
|
||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class GetPaymentMethodByIdController extends ExpressController {
|
||||
constructor(private readonly useCase: GetPaymentMethodByIdUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentmethodsApiErrorMapper;
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
export * from "./create-payment-method.controller";
|
||||
export * from "./delete-payment-method-by-id.controller";
|
||||
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 "./update-payment-method-by-id.controller";
|
||||
|
||||
@ -7,12 +7,12 @@ import {
|
||||
import { Criteria } from "@repo/rdx-criteria/server";
|
||||
|
||||
import type { ListPaymentMethodsUseCase } from "../../../../application";
|
||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class ListPaymentMethodsController extends ExpressController {
|
||||
constructor(private readonly useCase: ListPaymentMethodsUseCase) {
|
||||
super();
|
||||
this.errorMapper = paymentmethodsApiErrorMapper;
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
|
||||
@ -7,13 +7,13 @@ import {
|
||||
} from "@erp/core/api";
|
||||
|
||||
import type { UpdatePaymentMethodByIdUseCase } from "../../../../application";
|
||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
import { paymentMethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
||||
|
||||
export class UpdatePaymentMethodByIdController extends ExpressController {
|
||||
constructor(private readonly useCase: UpdatePaymentMethodByIdUseCase) {
|
||||
super();
|
||||
|
||||
this.errorMapper = paymentmethodsApiErrorMapper;
|
||||
this.errorMapper = paymentMethodsApiErrorMapper;
|
||||
|
||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
||||
this.registerGuards(
|
||||
|
||||
@ -2,37 +2,96 @@ import {
|
||||
ApiErrorMapper,
|
||||
ConflictApiError,
|
||||
type ErrorToApiRule,
|
||||
NotFoundApiError,
|
||||
ValidationApiError,
|
||||
} from "@erp/core/api";
|
||||
|
||||
import {
|
||||
type InvalidPaymentMethodIdError,
|
||||
type InvalidPaymentMethodNameError,
|
||||
type PaymentMethodCannotBeDeletedError,
|
||||
type PaymentMethodCannotBeDisabledError,
|
||||
type PaymentMethodCannotBeEnabledError,
|
||||
type PaymentMethodCannotBeUpdatedError,
|
||||
type PaymentMethodNotFoundError,
|
||||
isInvalidPaymentMethodIdError,
|
||||
isInvalidPaymentMethodNameError,
|
||||
isPaymentMethodCannotBeDeletedError,
|
||||
isPaymentMethodCannotBeDisabledError,
|
||||
isPaymentMethodCannotBeEnabledError,
|
||||
isPaymentMethodCannotBeUpdatedError,
|
||||
isPaymentMethodNotFoundError,
|
||||
} from "../../../domain/payment-methods";
|
||||
|
||||
// Crea una regla específica (prioridad alta para sobreescribir mensajes)
|
||||
const paymentmethodDuplicateRule: ErrorToApiRule = {
|
||||
const invalidPaymentMethodIdRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: (e) => isInvalidPaymentMethodIdError(e),
|
||||
build: (e) =>
|
||||
matches: isInvalidPaymentMethodIdError,
|
||||
build: (error) =>
|
||||
new ConflictApiError(
|
||||
(e as InvalidPaymentMethodIdError).message ||
|
||||
(error as InvalidPaymentMethodIdError).message ||
|
||||
"Payment method with the provided id already exists."
|
||||
),
|
||||
};
|
||||
|
||||
const paymentmethodCannotBeDeletedRule: ErrorToApiRule = {
|
||||
const invalidPaymentMethodNameRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: (e) => isPaymentMethodCannotBeDeletedError(e),
|
||||
build: (e) =>
|
||||
matches: isInvalidPaymentMethodNameError,
|
||||
build: (error) =>
|
||||
new ValidationApiError(
|
||||
(e as PaymentMethodCannotBeDeletedError).message || "Payment method cannot be deleted."
|
||||
(error as InvalidPaymentMethodNameError).message || "Payment method name is invalid."
|
||||
),
|
||||
};
|
||||
|
||||
// Cómo aplicarla: crea una nueva instancia del mapper con la regla extra
|
||||
export const paymentmethodsApiErrorMapper: ApiErrorMapper = ApiErrorMapper.default()
|
||||
.register(paymentmethodDuplicateRule)
|
||||
.register(paymentmethodCannotBeDeletedRule);
|
||||
const paymentMethodNotFoundRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: isPaymentMethodNotFoundError,
|
||||
build: (error) =>
|
||||
new NotFoundApiError(
|
||||
(error as PaymentMethodNotFoundError).message || "Payment method not found."
|
||||
),
|
||||
};
|
||||
|
||||
const paymentMethodCannotBeDeletedRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: isPaymentMethodCannotBeDeletedError,
|
||||
build: (error) =>
|
||||
new ValidationApiError(
|
||||
(error as PaymentMethodCannotBeDeletedError).message || "Payment method cannot be deleted."
|
||||
),
|
||||
};
|
||||
|
||||
const paymentMethodCannotBeDisabledRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: isPaymentMethodCannotBeDisabledError,
|
||||
build: (error) =>
|
||||
new ValidationApiError(
|
||||
(error as PaymentMethodCannotBeDisabledError).message || "Payment method cannot be disabled."
|
||||
),
|
||||
};
|
||||
|
||||
const paymentMethodCannotBeEnabledRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: isPaymentMethodCannotBeEnabledError,
|
||||
build: (error) =>
|
||||
new ValidationApiError(
|
||||
(error as PaymentMethodCannotBeEnabledError).message || "Payment method cannot be enabled."
|
||||
),
|
||||
};
|
||||
|
||||
const paymentMethodCannotBeUpdatedRule: ErrorToApiRule = {
|
||||
priority: 120,
|
||||
matches: isPaymentMethodCannotBeUpdatedError,
|
||||
build: (error) =>
|
||||
new ValidationApiError(
|
||||
(error as PaymentMethodCannotBeUpdatedError).message || "Payment method cannot be updated."
|
||||
),
|
||||
};
|
||||
|
||||
export const paymentMethodsApiErrorMapper: ApiErrorMapper = ApiErrorMapper.default()
|
||||
.register(invalidPaymentMethodIdRule)
|
||||
.register(invalidPaymentMethodNameRule)
|
||||
.register(paymentMethodNotFoundRule)
|
||||
.register(paymentMethodCannotBeDeletedRule)
|
||||
.register(paymentMethodCannotBeDisabledRule)
|
||||
.register(paymentMethodCannotBeEnabledRule)
|
||||
.register(paymentMethodCannotBeUpdatedRule);
|
||||
|
||||
@ -4,16 +4,19 @@ import { type NextFunction, type Request, type Response, Router } from "express"
|
||||
|
||||
import {
|
||||
CreatePaymentMethodRequestSchema,
|
||||
DeletePaymentMethodByIdRequestSchema,
|
||||
GetPaymentMethodByIdRequestSchema,
|
||||
ListPaymentMethodsRequestSchema,
|
||||
UpdatePaymentMethodByIdParamsRequestSchema,
|
||||
UpdatePaymentMethodByIdRequestSchema,
|
||||
} from "../../../../common/dto/payment-methods/request";
|
||||
} from "../../../../common";
|
||||
import type { CatalogsInternalDeps } from "../../di/catalogs.di";
|
||||
|
||||
import {
|
||||
CreatePaymentMethodController,
|
||||
DeletePaymentMethodByIdController,
|
||||
DisablePaymentMethodByIdController,
|
||||
EnablePaymentMethodByIdController,
|
||||
GetPaymentMethodByIdController,
|
||||
ListPaymentMethodsController,
|
||||
UpdatePaymentMethodByIdController,
|
||||
@ -64,7 +67,18 @@ export const paymentMethodsRouter = (params: StartParams) => {
|
||||
}
|
||||
);
|
||||
|
||||
router.patch(
|
||||
router.delete(
|
||||
"/:payment_method_id",
|
||||
validateRequest(DeletePaymentMethodByIdRequestSchema, "params"),
|
||||
(req, res, next) => {
|
||||
const controller = new DeletePaymentMethodByIdController(
|
||||
deps.useCases.deletePaymentMethodById()
|
||||
);
|
||||
return controller.execute(req, res, next);
|
||||
}
|
||||
);
|
||||
|
||||
router.put(
|
||||
"/:payment_method_id",
|
||||
validateRequest(UpdatePaymentMethodByIdParamsRequestSchema, "params"),
|
||||
validateRequest(UpdatePaymentMethodByIdRequestSchema, "body"),
|
||||
@ -87,5 +101,16 @@ export const paymentMethodsRouter = (params: StartParams) => {
|
||||
}
|
||||
);
|
||||
|
||||
router.patch(
|
||||
"/:payment_method_id/enable",
|
||||
validateRequest(GetPaymentMethodByIdRequestSchema, "params"),
|
||||
(req, res, next) => {
|
||||
const controller = new EnablePaymentMethodByIdController(
|
||||
deps.useCases.enablePaymentMethodById()
|
||||
);
|
||||
return controller.execute(req, res, next);
|
||||
}
|
||||
);
|
||||
|
||||
app.use(`${config.server.apiBasePath}/catalogs/payment-methods`, router);
|
||||
};
|
||||
|
||||
@ -21,7 +21,7 @@ export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper<
|
||||
> {
|
||||
public mapToDomain(
|
||||
source: PaymentMethodModel,
|
||||
params?: MapperParamsType
|
||||
_params?: MapperParamsType
|
||||
): Result<PaymentMethod, Error> {
|
||||
try {
|
||||
const errors: ValidationErrorDetail[] = [];
|
||||
@ -71,7 +71,7 @@ export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper<
|
||||
|
||||
public mapToPersistence(
|
||||
source: PaymentMethod,
|
||||
params?: MapperParamsType
|
||||
_params?: MapperParamsType
|
||||
): Result<PaymentMethodCreationAttributes, Error> {
|
||||
return Result.ok<PaymentMethodCreationAttributes>({
|
||||
id: source.id.toPrimitive(),
|
||||
|
||||
@ -17,7 +17,7 @@ export class SequelizePaymentMethodSummaryMapper extends SequelizeQueryMapper<
|
||||
> {
|
||||
public mapToReadModel(
|
||||
raw: PaymentMethodModel,
|
||||
params?: MapperParamsType
|
||||
_params?: MapperParamsType
|
||||
): Result<PaymentMethodSummary, Error> {
|
||||
const errors: ValidationErrorDetail[] = [];
|
||||
|
||||
|
||||
@ -71,12 +71,14 @@ export class SequelizePaymentMethodRepository
|
||||
}
|
||||
|
||||
const { id, ...payload } = dtoResult.data;
|
||||
const [affected] = await PaymentMethodModel.update(payload, {
|
||||
const [affected, updated] = await PaymentMethodModel.update(payload, {
|
||||
where: { id },
|
||||
transaction,
|
||||
individualHooks: true,
|
||||
});
|
||||
|
||||
console.log("Update result:", { affected, updated });
|
||||
|
||||
if (affected === 0) {
|
||||
return Result.fail(
|
||||
new InfrastructureRepositoryError("Concurrency conflict or payment method not found")
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import { z } from "zod/v4";
|
||||
|
||||
export const DeletePaymentMethodByIdRequestSchema = z.object({
|
||||
payment_method_id: z.uuid(),
|
||||
});
|
||||
|
||||
export type DeletePaymentMethodByIdRequestDTO = z.infer<
|
||||
typeof DeletePaymentMethodByIdRequestSchema
|
||||
>;
|
||||
@ -1,4 +1,5 @@
|
||||
export * from "./create-payment-method.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";
|
||||
export * from "./update-payment-method-by-id.request.dto";
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { translateZodValidationError } from "../helpers";
|
||||
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface NameProps {
|
||||
@ -24,7 +26,7 @@ export class Name extends ValueObject<NameProps> {
|
||||
if (!valueIsValid.success) {
|
||||
return Result.fail(translateZodValidationError("Name creation failed", valueIsValid.error));
|
||||
}
|
||||
return Result.ok(new Name({ value }));
|
||||
return Result.ok(new Name({ value: valueIsValid.data }));
|
||||
}
|
||||
|
||||
static generateAcronym(name: string): string {
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import { translateZodValidationError } from "../helpers";
|
||||
|
||||
import { ValueObject } from "./value-object";
|
||||
|
||||
interface TextValueProps {
|
||||
|
||||
@ -16,6 +16,7 @@ export interface IMaybe<T> {
|
||||
getOrUndefined(): T | undefined;
|
||||
map<U>(fn: (value: T) => U): IMaybe<U>;
|
||||
match<U>(someFn: (value: T) => U, noneFn: () => U): U;
|
||||
equals(other: IMaybe<T>): boolean;
|
||||
}
|
||||
|
||||
export function isMaybe<T = unknown>(input: unknown): input is Maybe<T> {
|
||||
@ -40,6 +41,18 @@ export class Maybe<T> implements IMaybe<T> {
|
||||
return new Maybe<T>();
|
||||
}
|
||||
|
||||
equals(other: IMaybe<T>): boolean {
|
||||
if (this.isNone() && other.isNone()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.isSome() && other.isSome()) {
|
||||
return this.unwrap() === other.unwrap();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
isSome(): boolean {
|
||||
return this.value !== undefined;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user