Compare commits
No commits in common. "cd4b8975c3585762f1fb2d1331a3be5b7ba231a0" and "00627096ed82f428378857ed8dd6e292b78ed708" have entirely different histories.
cd4b8975c3
...
00627096ed
@ -1,15 +0,0 @@
|
|||||||
Especialización backend.
|
|
||||||
|
|
||||||
Contiene:
|
|
||||||
|
|
||||||
- Clean Architecture
|
|
||||||
- DDD
|
|
||||||
- módulos
|
|
||||||
- Sequelize
|
|
||||||
- DTOs
|
|
||||||
- repositorios
|
|
||||||
- fiscalidad
|
|
||||||
- use cases
|
|
||||||
- Express
|
|
||||||
- snapshot builders
|
|
||||||
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
# Frontend ERP Agent
|
|
||||||
|
|
||||||
## Objetivo
|
|
||||||
|
|
||||||
Construir frontend ERP modular, tipado, mantenible y desacoplado.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Stack
|
|
||||||
|
|
||||||
- React
|
|
||||||
- TypeScript
|
|
||||||
- Vite
|
|
||||||
- TanStack Query
|
|
||||||
- React Hook Form
|
|
||||||
- Zod
|
|
||||||
- Zustand (si aplica)
|
|
||||||
- Tailwind/Shadcn/etc
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# Principios
|
|
||||||
|
|
||||||
- UI desacoplada de transporte
|
|
||||||
- SSR/CSR explícito
|
|
||||||
- Estado mínimo global
|
|
||||||
- Formularios tipados
|
|
||||||
- Server state != UI state
|
|
||||||
- Componentes pequeños
|
|
||||||
- Evitar smart components gigantes
|
|
||||||
- Accesibilidad obligatoria
|
|
||||||
- Diseño orientado a features
|
|
||||||
10
.ai/index.md
10
.ai/index.md
@ -1,10 +0,0 @@
|
|||||||
# ERP AI Context
|
|
||||||
|
|
||||||
## Shared => filosofía + convenciones
|
|
||||||
- ./shared/agent.md
|
|
||||||
|
|
||||||
## Backend => dominio + arquitectura + persistencia
|
|
||||||
- ./backend/agent.md
|
|
||||||
|
|
||||||
## Frontend => interacción + UX + estado + rendering
|
|
||||||
- ./frontend/agent.md
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
- Mantener código en inglés.
|
|
||||||
- Comentarios solo si aportan, en español.
|
|
||||||
- No usar any.
|
|
||||||
- No crear abstracciones genéricas prematuras.
|
|
||||||
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
import catalogsAPIModule from "@erp/catalogs/api";
|
|
||||||
import customerInvoicesAPIModule from "@erp/customer-invoices/api";
|
import customerInvoicesAPIModule from "@erp/customer-invoices/api";
|
||||||
import customersAPIModule from "@erp/customers/api";
|
import customersAPIModule from "@erp/customers/api";
|
||||||
import factuGESAPIModule from "@erp/factuges/api";
|
import factuGESAPIModule from "@erp/factuges/api";
|
||||||
@ -9,7 +8,6 @@ import { registerModule } from "./lib";
|
|||||||
|
|
||||||
export const registerModules = () => {
|
export const registerModules = () => {
|
||||||
//registerModule(authAPIModule);
|
//registerModule(authAPIModule);
|
||||||
registerModule(catalogsAPIModule);
|
|
||||||
registerModule(customersAPIModule);
|
registerModule(customersAPIModule);
|
||||||
registerModule(customerInvoicesAPIModule);
|
registerModule(customerInvoicesAPIModule);
|
||||||
registerModule(factuGESAPIModule);
|
registerModule(factuGESAPIModule);
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@erp/catalogs",
|
|
||||||
"description": "Catalogs module",
|
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
|
||||||
"sideEffects": false,
|
|
||||||
"scripts": {
|
|
||||||
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
||||||
"check": "biome check .",
|
|
||||||
"lint": "biome lint .",
|
|
||||||
"clean": "rimraf .turbo node_modules dist"
|
|
||||||
},
|
|
||||||
"exports": {
|
|
||||||
".": "./src/api/index.ts",
|
|
||||||
"./api": "./src/api/index.ts"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@erp/core": "workspace:*",
|
|
||||||
"@erp/auth": "workspace:*",
|
|
||||||
"@repo/rdx-ddd": "workspace:*",
|
|
||||||
"@repo/rdx-utils": "workspace:*",
|
|
||||||
"@repo/rdx-criteria": "workspace:*",
|
|
||||||
"express": "^4.22.1",
|
|
||||||
"sequelize": "^6.37.8",
|
|
||||||
"zod": "^4.3.6"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/express": "^4.17.21",
|
|
||||||
"typescript": "^6.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
export * from "./payment-method-creator.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-updater.di";
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
import { type IPaymentMethodCreator, PaymentMethodCreator } from "../services";
|
|
||||||
|
|
||||||
export const buildPaymentMethodCreator = (params: {
|
|
||||||
repository: IPaymentMethodRepository;
|
|
||||||
}): IPaymentMethodCreator => {
|
|
||||||
const { repository } = params;
|
|
||||||
|
|
||||||
return new PaymentMethodCreator(repository);
|
|
||||||
};
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
import { type IPaymentMethodFinder, PaymentMethodFinder } from "../services";
|
|
||||||
|
|
||||||
export function buildPaymentMethodFinder(
|
|
||||||
repository: IPaymentMethodRepository
|
|
||||||
): IPaymentMethodFinder {
|
|
||||||
return new PaymentMethodFinder(repository);
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
import {
|
|
||||||
CreatePaymentMethodInputMapper,
|
|
||||||
type ICreatePaymentMethodInputMapper,
|
|
||||||
UpdatePaymentMethodInputMapper,
|
|
||||||
} from "../mappers";
|
|
||||||
|
|
||||||
export interface IPaymentMethodInputMappers {
|
|
||||||
createInputMapper: ICreatePaymentMethodInputMapper;
|
|
||||||
updateInputMapper: UpdatePaymentMethodInputMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const buildPaymentMethodInputMappers = (): IPaymentMethodInputMappers => {
|
|
||||||
// Mappers el DTO a las props validadas (PaymentMethodProps) y luego construir agregado
|
|
||||||
const createInputMapper = new CreatePaymentMethodInputMapper();
|
|
||||||
const updateInputMapper = new UpdatePaymentMethodInputMapper();
|
|
||||||
|
|
||||||
return {
|
|
||||||
createInputMapper,
|
|
||||||
updateInputMapper,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
// application/issued-invoices/di/snapshot-builders.di.ts
|
|
||||||
|
|
||||||
import {
|
|
||||||
PaymentMethodFullSnapshotBuilder,
|
|
||||||
PaymentMethodSummarySnapshotBuilder,
|
|
||||||
} from "../snapshot-builders";
|
|
||||||
|
|
||||||
export function buildPaymentMethodSnapshotBuilders() {
|
|
||||||
const fullSnapshotBuilder = new PaymentMethodFullSnapshotBuilder();
|
|
||||||
const summarySnapshotBuilder = new PaymentMethodSummarySnapshotBuilder();
|
|
||||||
|
|
||||||
return {
|
|
||||||
full: fullSnapshotBuilder,
|
|
||||||
summary: summarySnapshotBuilder,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
import { type IPaymentMethodUpdater, PaymentMethodUpdater } from "../services";
|
|
||||||
|
|
||||||
export const buildPaymentMethodUpdater = (params: {
|
|
||||||
repository: IPaymentMethodRepository;
|
|
||||||
}): IPaymentMethodUpdater => {
|
|
||||||
const { repository } = params;
|
|
||||||
|
|
||||||
return new PaymentMethodUpdater(repository);
|
|
||||||
};
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
export * from "./di";
|
|
||||||
export * from "./mappers";
|
|
||||||
export * from "./models";
|
|
||||||
export * from "./repositories";
|
|
||||||
export * from "./services";
|
|
||||||
export * from "./snapshot-builders";
|
|
||||||
export * from "./use-cases";
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
import {
|
|
||||||
DomainError,
|
|
||||||
Name,
|
|
||||||
TextValue,
|
|
||||||
UniqueID,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
type ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
maybeFromNullableResult,
|
|
||||||
} from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { CreatePaymentMethodRequestDTO } from "../../../common";
|
|
||||||
import type { IPaymentMethodCreateProps } from "../../domain";
|
|
||||||
|
|
||||||
export interface ICreatePaymentMethodInputMapper {
|
|
||||||
map(
|
|
||||||
dto: CreatePaymentMethodRequestDTO,
|
|
||||||
params: { companyId: UniqueID }
|
|
||||||
): Result<{ id: UniqueID; props: IPaymentMethodCreateProps }, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class CreatePaymentMethodInputMapper implements ICreatePaymentMethodInputMapper {
|
|
||||||
public map(
|
|
||||||
dto: CreatePaymentMethodRequestDTO,
|
|
||||||
params: { companyId: UniqueID }
|
|
||||||
): Result<{ id: UniqueID; props: IPaymentMethodCreateProps }, Error> {
|
|
||||||
const errors: ValidationErrorDetail[] = [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
const paymentMethodId = extractOrPushError(UniqueID.create(dto.id), "id", errors);
|
|
||||||
|
|
||||||
const name = extractOrPushError(Name.create(dto.name), "name", errors);
|
|
||||||
|
|
||||||
const description = extractOrPushError(
|
|
||||||
maybeFromNullableResult(dto.description, (value) => TextValue.create(value)),
|
|
||||||
"description",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const isActive = extractOrPushError(Result.ok(dto.is_active), "is_active", errors);
|
|
||||||
|
|
||||||
this.throwIfValidationErrors(errors);
|
|
||||||
|
|
||||||
const props = {
|
|
||||||
companyId: params.companyId,
|
|
||||||
name: name!,
|
|
||||||
description: description!,
|
|
||||||
isActive: isActive!,
|
|
||||||
isSystem: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
return Result.ok({
|
|
||||||
id: paymentMethodId!,
|
|
||||||
props,
|
|
||||||
});
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(new DomainError("Payment method props mapping failed", { cause: err }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private throwIfValidationErrors(errors: ValidationErrorDetail[]): void {
|
|
||||||
if (errors.length > 0) {
|
|
||||||
throw new ValidationErrorCollection("Payment method props mapping failed", errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./create-payment-method-input.mapper";
|
|
||||||
export * from "./update-payment-method-by-id-input.mapper";
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
import {
|
|
||||||
DomainError,
|
|
||||||
Name,
|
|
||||||
TextValue,
|
|
||||||
type UniqueID,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
type ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
maybeFromNullableResult,
|
|
||||||
} from "@repo/rdx-ddd";
|
|
||||||
import { Result, isNullishOrEmpty, toPatchField } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { UpdatePaymentMethodByIdRequestDTO } from "../../../common";
|
|
||||||
import type { PaymentMethodPatchProps } from "../../domain";
|
|
||||||
|
|
||||||
export interface IUpdatePaymentMethodInputMapper {
|
|
||||||
map(
|
|
||||||
dto: UpdatePaymentMethodByIdRequestDTO,
|
|
||||||
params: { companyId: UniqueID }
|
|
||||||
): Result<PaymentMethodPatchProps>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @summary Convierte el DTO de update de forma de pago en props de dominio.
|
|
||||||
* @remarks
|
|
||||||
* Respeta semántica PATCH en cabecera:
|
|
||||||
* - omitido: no modificar
|
|
||||||
* - null: limpiar valor cuando el campo lo permite
|
|
||||||
* - valor: asignar nuevo valor
|
|
||||||
*
|
|
||||||
* Para `items`, no aplica patch granular:
|
|
||||||
* - undefined: no tocar líneas
|
|
||||||
* - []: borrar todas las líneas
|
|
||||||
* - [...]: reemplazar colección completa
|
|
||||||
*/
|
|
||||||
|
|
||||||
export class UpdatePaymentMethodInputMapper implements IUpdatePaymentMethodInputMapper {
|
|
||||||
public map(
|
|
||||||
dto: UpdatePaymentMethodByIdRequestDTO,
|
|
||||||
_params: { companyId: UniqueID }
|
|
||||||
): Result<PaymentMethodPatchProps> {
|
|
||||||
try {
|
|
||||||
const errors: ValidationErrorDetail[] = [];
|
|
||||||
const paymentmethodPatchProps: PaymentMethodPatchProps = {};
|
|
||||||
|
|
||||||
toPatchField(dto.name).ifSet((name) => {
|
|
||||||
if (isNullishOrEmpty(name)) {
|
|
||||||
errors.push({
|
|
||||||
path: "name",
|
|
||||||
message: "Name cannot be empty",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
paymentmethodPatchProps.name = extractOrPushError(Name.create(name), "name", errors);
|
|
||||||
});
|
|
||||||
|
|
||||||
toPatchField(dto.description).ifSet((description) => {
|
|
||||||
paymentmethodPatchProps.description = extractOrPushError(
|
|
||||||
maybeFromNullableResult(description, (value) => TextValue.create(value)),
|
|
||||||
"description",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
toPatchField(dto.is_active).ifSet((isActive) => {
|
|
||||||
paymentmethodPatchProps.isActive = isActive;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.throwIfValidationErrors(errors);
|
|
||||||
|
|
||||||
return Result.ok(paymentmethodPatchProps);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
console.error(err);
|
|
||||||
return Result.fail(
|
|
||||||
new DomainError("PaymentMethod props mapping failed (update)", { cause: err })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private throwIfValidationErrors(errors: ValidationErrorDetail[]): void {
|
|
||||||
if (errors.length > 0) {
|
|
||||||
throw new ValidationErrorCollection("PaymentMethod props mapping failed", errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./payment-method-detail.model";
|
|
||||||
export * from "./payment-method-summary.model";
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
export type PaymentMethodDetail = {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
is_active: boolean;
|
|
||||||
created_at: string;
|
|
||||||
updated_at: string;
|
|
||||||
};
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import type { Name, UniqueID } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export type PaymentMethodSummary = {
|
|
||||||
id: UniqueID;
|
|
||||||
companyId: UniqueID;
|
|
||||||
name: Name;
|
|
||||||
isActive: boolean;
|
|
||||||
isSystem: boolean;
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./payment-method-repository.interface";
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
import type { Criteria } from "@repo/rdx-criteria/server";
|
|
||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import type { Collection, Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { PaymentMethod } from "../../domain";
|
|
||||||
import type { PaymentMethodSummary } from "../models";
|
|
||||||
|
|
||||||
export interface IPaymentMethodRepository {
|
|
||||||
create(paymentMethod: PaymentMethod, transaction?: unknown): Promise<Result<void, Error>>;
|
|
||||||
update(paymentMethod: PaymentMethod, transaction?: unknown): Promise<Result<void, Error>>;
|
|
||||||
existsByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<boolean, Error>>;
|
|
||||||
getByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<PaymentMethod, Error>>;
|
|
||||||
findByCriteriaInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<Collection<PaymentMethodSummary>, Error>>;
|
|
||||||
deleteByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<boolean, Error>>;
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
export * from "./payment-method-creator";
|
|
||||||
export * from "./payment-method-disabler";
|
|
||||||
export * from "./payment-method-finder";
|
|
||||||
export * from "./payment-method-public-services";
|
|
||||||
export * from "./payment-method-updater";
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import { type IPaymentMethodCreateProps, PaymentMethod } from "../../domain";
|
|
||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
|
|
||||||
export interface IPaymentMethodCreatorParams {
|
|
||||||
companyId: UniqueID;
|
|
||||||
id: UniqueID;
|
|
||||||
props: IPaymentMethodCreateProps;
|
|
||||||
transaction: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IPaymentMethodCreator {
|
|
||||||
create(params: IPaymentMethodCreatorParams): Promise<Result<PaymentMethod, Error>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PaymentMethodCreator implements IPaymentMethodCreator {
|
|
||||||
constructor(private readonly repository: IPaymentMethodRepository) {}
|
|
||||||
|
|
||||||
async create(params: IPaymentMethodCreatorParams): Promise<Result<PaymentMethod, Error>> {
|
|
||||||
const { companyId, id, props, transaction } = params;
|
|
||||||
|
|
||||||
// 1. Crear agregado
|
|
||||||
const paymentMethodResult = PaymentMethod.create({ ...props, companyId }, id);
|
|
||||||
|
|
||||||
if (paymentMethodResult.isFailure) {
|
|
||||||
return Result.fail(paymentMethodResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentMethod = paymentMethodResult.data;
|
|
||||||
|
|
||||||
// 2. Persistir
|
|
||||||
const saveResult = await this.repository.create(paymentMethod, transaction);
|
|
||||||
if (saveResult.isFailure) {
|
|
||||||
return Result.fail(saveResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(paymentMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
import type { Transaction } from "sequelize";
|
|
||||||
|
|
||||||
import type { PaymentMethod } from "../../domain";
|
|
||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
|
|
||||||
export interface IPaymentMethodDisabler {
|
|
||||||
disable(params: {
|
|
||||||
paymentMethod: PaymentMethod;
|
|
||||||
transaction?: Transaction;
|
|
||||||
}): Promise<Result<PaymentMethod, Error>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PaymentMethodDisabler implements IPaymentMethodDisabler {
|
|
||||||
constructor(private readonly repository: IPaymentMethodRepository) {}
|
|
||||||
|
|
||||||
async disable(params: {
|
|
||||||
paymentMethod: PaymentMethod;
|
|
||||||
transaction?: Transaction;
|
|
||||||
}): Promise<Result<PaymentMethod, Error>> {
|
|
||||||
const { paymentMethod, transaction } = params;
|
|
||||||
|
|
||||||
const disableResult = paymentMethod.disable();
|
|
||||||
if (disableResult.isFailure) {
|
|
||||||
return Result.fail(disableResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const persistenceResult = await this.repository.update(paymentMethod, transaction);
|
|
||||||
if (persistenceResult.isFailure) {
|
|
||||||
return Result.fail(persistenceResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(paymentMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
import type { Criteria } from "@repo/rdx-criteria/server";
|
|
||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import type { Collection, Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { PaymentMethod } from "../../domain";
|
|
||||||
import type { PaymentMethodSummary } from "../models";
|
|
||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
|
|
||||||
export interface IPaymentMethodFinder {
|
|
||||||
findPaymentMethodById(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<PaymentMethod, Error>>;
|
|
||||||
|
|
||||||
paymentmethodExists(
|
|
||||||
companyId: UniqueID,
|
|
||||||
invoiceId: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<boolean, Error>>;
|
|
||||||
|
|
||||||
findPaymentMethodsByCriteria(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<Collection<PaymentMethodSummary>, Error>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PaymentMethodFinder implements IPaymentMethodFinder {
|
|
||||||
constructor(private readonly repository: IPaymentMethodRepository) {}
|
|
||||||
|
|
||||||
async findPaymentMethodById(
|
|
||||||
companyId: UniqueID,
|
|
||||||
paymentmethodId: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<PaymentMethod, Error>> {
|
|
||||||
return this.repository.getByIdInCompany(companyId, paymentmethodId, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
async paymentmethodExists(
|
|
||||||
companyId: UniqueID,
|
|
||||||
paymentmethodId: UniqueID,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<boolean, Error>> {
|
|
||||||
return this.repository.existsByIdInCompany(companyId, paymentmethodId, transaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
async findPaymentMethodsByCriteria(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction?: unknown
|
|
||||||
): Promise<Result<Collection<PaymentMethodSummary>, Error>> {
|
|
||||||
return this.repository.findByCriteriaInCompany(companyId, criteria, transaction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
import type { IPaymentMethodFinder } from "./payment-method-finder";
|
|
||||||
|
|
||||||
export type IPaymentMethodPublicServices = {
|
|
||||||
finder: IPaymentMethodFinder;
|
|
||||||
};
|
|
||||||
@ -1,52 +0,0 @@
|
|||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { PaymentMethod, PaymentMethodPatchProps } from "../../domain";
|
|
||||||
import type { IPaymentMethodRepository } from "../repositories";
|
|
||||||
|
|
||||||
export interface IPaymentMethodUpdater {
|
|
||||||
update(params: {
|
|
||||||
companyId: UniqueID;
|
|
||||||
id: UniqueID;
|
|
||||||
patchProps: PaymentMethodPatchProps;
|
|
||||||
transaction?: unknown;
|
|
||||||
}): Promise<Result<PaymentMethod, Error>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PaymentMethodUpdater implements IPaymentMethodUpdater {
|
|
||||||
constructor(private readonly repository: IPaymentMethodRepository) {}
|
|
||||||
|
|
||||||
async update(params: {
|
|
||||||
companyId: UniqueID;
|
|
||||||
id: UniqueID;
|
|
||||||
patchProps: PaymentMethodPatchProps;
|
|
||||||
transaction?: unknown;
|
|
||||||
}): Promise<Result<PaymentMethod, Error>> {
|
|
||||||
const { companyId, id, patchProps, transaction } = params;
|
|
||||||
|
|
||||||
// Recuperar agregado existente
|
|
||||||
const existingResult = await this.repository.getByIdInCompany(companyId, id, transaction);
|
|
||||||
|
|
||||||
if (existingResult.isFailure) {
|
|
||||||
return Result.fail(existingResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentMethod = existingResult.data;
|
|
||||||
|
|
||||||
// Aplicar cambios en el agregado
|
|
||||||
const updateResult = paymentMethod.update(patchProps);
|
|
||||||
|
|
||||||
if (updateResult.isFailure) {
|
|
||||||
return Result.fail(updateResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Persistir cambios
|
|
||||||
const saveResult = await this.repository.update(paymentMethod, transaction);
|
|
||||||
|
|
||||||
if (saveResult.isFailure) {
|
|
||||||
return Result.fail(saveResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(paymentMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from './payment-method-full-snapshot-builder';
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
import type { GetPaymentMethodByIdResponseDTO } from "@erp/catalogs/common";
|
|
||||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
|
||||||
import { toNullable } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
import type { PaymentMethod } from "../../../domain";
|
|
||||||
|
|
||||||
export interface IPaymentMethodFullSnapshotBuilder
|
|
||||||
extends ISnapshotBuilder<PaymentMethod, GetPaymentMethodByIdResponseDTO> {}
|
|
||||||
|
|
||||||
export class PaymentMethodFullSnapshotBuilder implements IPaymentMethodFullSnapshotBuilder {
|
|
||||||
public toOutput(paymentMethod: PaymentMethod): GetPaymentMethodByIdResponseDTO {
|
|
||||||
return {
|
|
||||||
id: paymentMethod.id.toPrimitive(),
|
|
||||||
name: paymentMethod.name.toPrimitive(),
|
|
||||||
description: toNullable(paymentMethod.description, (value) => value.toPrimitive()),
|
|
||||||
is_active: paymentMethod.isActive,
|
|
||||||
is_system: paymentMethod.isSystem,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./full";
|
|
||||||
export * from "./summary";
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./payment-method-summary-snapshot-builder";
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import type { ISnapshotBuilder } from "@erp/core/api";
|
|
||||||
|
|
||||||
import type { PaymentMethodSummaryDTO } from "../../../../common/";
|
|
||||||
import type { PaymentMethodSummary } from "../../models";
|
|
||||||
|
|
||||||
export interface IPaymentMethodSummarySnapshotBuilder
|
|
||||||
extends ISnapshotBuilder<PaymentMethodSummary, PaymentMethodSummaryDTO> {}
|
|
||||||
|
|
||||||
export class PaymentMethodSummarySnapshotBuilder implements IPaymentMethodSummarySnapshotBuilder {
|
|
||||||
public toOutput(paymentMethod: PaymentMethodSummary): PaymentMethodSummaryDTO {
|
|
||||||
return {
|
|
||||||
id: paymentMethod.id.toString(),
|
|
||||||
company_id: paymentMethod.companyId.toString(),
|
|
||||||
name: paymentMethod.name.toString(),
|
|
||||||
is_system: paymentMethod.isSystem,
|
|
||||||
is_active: paymentMethod.isActive,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,51 +0,0 @@
|
|||||||
import type { CreatePaymentMethodRequestDTO } 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 { ICreatePaymentMethodInputMapper } from "../mappers";
|
|
||||||
import type { IPaymentMethodCreator } from "../services";
|
|
||||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
|
||||||
|
|
||||||
export type CreatePaymentMethodUseCaseInput = {
|
|
||||||
companyId: UniqueID;
|
|
||||||
dto: CreatePaymentMethodRequestDTO;
|
|
||||||
};
|
|
||||||
|
|
||||||
type CreatePaymentMethodUseCaseDeps = {
|
|
||||||
dtoMapper: ICreatePaymentMethodInputMapper;
|
|
||||||
creator: IPaymentMethodCreator;
|
|
||||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
|
||||||
transactionManager: ITransactionManager;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class CreatePaymentMethodUseCase {
|
|
||||||
constructor(private readonly deps: CreatePaymentMethodUseCaseDeps) {}
|
|
||||||
|
|
||||||
public execute(params: CreatePaymentMethodUseCaseInput) {
|
|
||||||
const { dto, companyId } = params;
|
|
||||||
console.log("Executing CreatePaymentMethodUseCase with params:", params);
|
|
||||||
|
|
||||||
const mappedPropsResult = this.deps.dtoMapper.map(dto, { companyId });
|
|
||||||
if (mappedPropsResult.isFailure) {
|
|
||||||
return mappedPropsResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { props, id } = mappedPropsResult.data;
|
|
||||||
|
|
||||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
|
||||||
try {
|
|
||||||
const createResult = await this.deps.creator.create({ companyId, id, props, transaction });
|
|
||||||
|
|
||||||
if (createResult.isFailure) {
|
|
||||||
return createResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const snapshot = this.deps.fullSnapshotBuilder.toOutput(createResult.data);
|
|
||||||
return Result.ok(snapshot);
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import type { ITransactionManager } from "@erp/core/api";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
import type { Transaction } from "sequelize";
|
|
||||||
|
|
||||||
import type { IPaymentMethodDisabler, IPaymentMethodFinder } from "../services";
|
|
||||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
|
||||||
|
|
||||||
export type DisablePaymentMethodByIdUseCaseInput = {
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class DisablePaymentMethodByIdUseCase {
|
|
||||||
constructor(
|
|
||||||
private readonly deps: {
|
|
||||||
finder: IPaymentMethodFinder;
|
|
||||||
disabler: IPaymentMethodDisabler;
|
|
||||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
|
||||||
transactionManager: ITransactionManager;
|
|
||||||
}
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public execute(params: DisablePaymentMethodByIdUseCaseInput) {
|
|
||||||
const { id } = params;
|
|
||||||
|
|
||||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
|
||||||
const tx = transaction as Transaction;
|
|
||||||
try {
|
|
||||||
const findResult = await this.deps.finder.getById(id, tx);
|
|
||||||
if (findResult.isFailure) {
|
|
||||||
return Result.fail(findResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const disableResult = await this.deps.disabler.disable({
|
|
||||||
paymentMethod: findResult.data,
|
|
||||||
transaction: tx,
|
|
||||||
});
|
|
||||||
if (disableResult.isFailure) {
|
|
||||||
return Result.fail(disableResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(this.deps.fullSnapshotBuilder.toOutput(disableResult.data));
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,47 +0,0 @@
|
|||||||
import type { ITransactionManager } from "@erp/core/api";
|
|
||||||
import { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { IPaymentMethodFinder } from "../services";
|
|
||||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
|
||||||
|
|
||||||
export type GetPaymentMethodByIdUseCaseInput = {
|
|
||||||
companyId: UniqueID;
|
|
||||||
payment_method_id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class GetPaymentMethodByIdUseCase {
|
|
||||||
constructor(
|
|
||||||
private readonly finder: IPaymentMethodFinder,
|
|
||||||
private readonly fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder,
|
|
||||||
private readonly transactionManager: ITransactionManager
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public execute(params: GetPaymentMethodByIdUseCaseInput) {
|
|
||||||
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.transactionManager.complete(async (transaction: unknown) => {
|
|
||||||
try {
|
|
||||||
const result = await this.finder.findPaymentMethodById(
|
|
||||||
companyId,
|
|
||||||
paymentMethodId,
|
|
||||||
transaction
|
|
||||||
);
|
|
||||||
if (result.isFailure) {
|
|
||||||
return Result.fail(result.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(this.fullSnapshotBuilder.toOutput(result.data));
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
export * from "./create-payment-method.use-case";
|
|
||||||
export * from "./disable-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";
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
import type { ITransactionManager } from "@erp/core/api";
|
|
||||||
import type { Criteria } from "@repo/rdx-criteria/server";
|
|
||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { IPaymentMethodFinder } from "../services";
|
|
||||||
import type { IPaymentMethodSummarySnapshotBuilder } from "../snapshot-builders";
|
|
||||||
|
|
||||||
type ListPaymentMethodsUseCaseInput = {
|
|
||||||
companyId: UniqueID;
|
|
||||||
criteria: Criteria;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ListPaymentMethodsUseCase {
|
|
||||||
constructor(
|
|
||||||
private readonly finder: IPaymentMethodFinder,
|
|
||||||
private readonly summarySnapshotBuilder: IPaymentMethodSummarySnapshotBuilder,
|
|
||||||
private readonly transactionManager: ITransactionManager
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public execute(params: ListPaymentMethodsUseCaseInput) {
|
|
||||||
const { criteria, companyId } = params;
|
|
||||||
|
|
||||||
return this.transactionManager.complete(async (transaction: unknown) => {
|
|
||||||
try {
|
|
||||||
const result = await this.finder.findPaymentMethodsByCriteria(
|
|
||||||
companyId,
|
|
||||||
criteria,
|
|
||||||
transaction
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.isFailure) {
|
|
||||||
return Result.fail(result.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentMethods = result.data;
|
|
||||||
const totalItems = paymentMethods.total();
|
|
||||||
|
|
||||||
const items = paymentMethods.map((item) => this.summarySnapshotBuilder.toOutput(item));
|
|
||||||
|
|
||||||
const snapshot = {
|
|
||||||
page: criteria.pageNumber,
|
|
||||||
per_page: criteria.pageSize,
|
|
||||||
total_pages: Math.ceil(totalItems / criteria.pageSize),
|
|
||||||
total_items: totalItems,
|
|
||||||
items: items,
|
|
||||||
metadata: {
|
|
||||||
entity: "payment_methods",
|
|
||||||
criteria: criteria.toJSON(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return Result.ok(snapshot);
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
import type { UpdatePaymentMethodByIdRequestDTO } from "@erp/catalogs/common";
|
|
||||||
import type { ITransactionManager } from "@erp/core/api";
|
|
||||||
import { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { IUpdatePaymentMethodInputMapper } from "../mappers";
|
|
||||||
import type { IPaymentMethodFinder, IPaymentMethodUpdater } from "../services";
|
|
||||||
import type { IPaymentMethodFullSnapshotBuilder } from "../snapshot-builders";
|
|
||||||
|
|
||||||
export type UpdatePaymentMethodByIdUseCaseInput = {
|
|
||||||
companyId: UniqueID;
|
|
||||||
payment_method_id: string;
|
|
||||||
dto: UpdatePaymentMethodByIdRequestDTO;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class UpdatePaymentMethodByIdUseCase {
|
|
||||||
constructor(
|
|
||||||
private readonly deps: {
|
|
||||||
updater: IPaymentMethodUpdater;
|
|
||||||
finder: IPaymentMethodFinder;
|
|
||||||
dtoMapper: IUpdatePaymentMethodInputMapper;
|
|
||||||
fullSnapshotBuilder: IPaymentMethodFullSnapshotBuilder;
|
|
||||||
transactionManager: ITransactionManager;
|
|
||||||
}
|
|
||||||
) {}
|
|
||||||
|
|
||||||
public execute(params: UpdatePaymentMethodByIdUseCaseInput) {
|
|
||||||
const { companyId, payment_method_id, dto } = params;
|
|
||||||
|
|
||||||
const idOrError = UniqueID.create(payment_method_id);
|
|
||||||
if (idOrError.isFailure) {
|
|
||||||
return Result.fail(idOrError.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentMethodId = idOrError.data;
|
|
||||||
|
|
||||||
// Mapear DTO → props de dominio
|
|
||||||
const patchPropsResult = this.deps.dtoMapper.map(dto, { companyId });
|
|
||||||
if (patchPropsResult.isFailure) {
|
|
||||||
return patchPropsResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
const patchProps = patchPropsResult.data;
|
|
||||||
|
|
||||||
return this.deps.transactionManager.complete(async (transaction: unknown) => {
|
|
||||||
try {
|
|
||||||
const updateResult = await this.deps.updater.update({
|
|
||||||
companyId,
|
|
||||||
id: paymentMethodId,
|
|
||||||
patchProps,
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (updateResult.isFailure) {
|
|
||||||
return Result.fail(updateResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(this.deps.fullSnapshotBuilder.toOutput(updateResult.data));
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./payment-methods";
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import { DomainError } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export class InvalidPaymentMethodIdError extends DomainError {
|
|
||||||
public readonly code = "PAYMENT_METHOD_INVALID_ID" as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isInvalidPaymentMethodIdError = (e: unknown): e is InvalidPaymentMethodIdError =>
|
|
||||||
e instanceof InvalidPaymentMethodIdError;
|
|
||||||
|
|
||||||
export class InvalidPaymentMethodNameError extends DomainError {
|
|
||||||
public readonly code = "PAYMENT_METHOD_NAME" as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 class PaymentMethodCannotBeDeletedError extends DomainError {
|
|
||||||
public readonly code = "PAYMENT_METHOD_CANNOT_BE_DELETED" as const;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const isPaymentMethodCannotBeDeletedError = (
|
|
||||||
e: unknown
|
|
||||||
): e is PaymentMethodCannotBeDeletedError => e instanceof PaymentMethodCannotBeDeletedError;
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
export * from "./errors";
|
|
||||||
export * from "./payment-method.aggregate";
|
|
||||||
export * from "./payment-method-name";
|
|
||||||
export * from "./payment-method-type";
|
|
||||||
@ -1,28 +0,0 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import { InvalidPaymentMethodNameError } from "./errors";
|
|
||||||
|
|
||||||
export class PaymentMethodName {
|
|
||||||
private constructor(private readonly value: string) {}
|
|
||||||
|
|
||||||
public static create(name: string): Result<PaymentMethodName, Error> {
|
|
||||||
const trimmed = name?.trim() ?? "";
|
|
||||||
if (trimmed.length === 0) {
|
|
||||||
return Result.fail(new InvalidPaymentMethodNameError("Payment method name cannot be empty"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(new PaymentMethodName(trimmed));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromPersistence(name: string): PaymentMethodName {
|
|
||||||
return new PaymentMethodName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public toString(): string {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toPrimitive(): string {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import { InvalidPaymentMethodTypeError } from "./errors";
|
|
||||||
|
|
||||||
export const PAYMENT_METHOD_TYPES = [
|
|
||||||
"cash",
|
|
||||||
"bank_transfer",
|
|
||||||
"card",
|
|
||||||
"direct_debit",
|
|
||||||
"other",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export type PaymentMethodTypeValue = (typeof PAYMENT_METHOD_TYPES)[number];
|
|
||||||
|
|
||||||
export class PaymentMethodType {
|
|
||||||
private constructor(private readonly value: PaymentMethodTypeValue) {}
|
|
||||||
|
|
||||||
public static create(type: string): Result<PaymentMethodType, Error> {
|
|
||||||
const normalized = String(type).trim() as PaymentMethodTypeValue;
|
|
||||||
|
|
||||||
if (!PAYMENT_METHOD_TYPES.includes(normalized)) {
|
|
||||||
return Result.fail(
|
|
||||||
new InvalidPaymentMethodTypeError(
|
|
||||||
`Payment method type must be one of: ${PAYMENT_METHOD_TYPES.join(", ")}`
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(new PaymentMethodType(normalized));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static fromPersistence(type: PaymentMethodTypeValue): PaymentMethodType {
|
|
||||||
return new PaymentMethodType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public toString(): PaymentMethodTypeValue {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toPrimitive(): PaymentMethodTypeValue {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
import { AggregateRoot, type Name, type TextValue, type UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { type Maybe, Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
export interface IPaymentMethodCreateProps {
|
|
||||||
companyId: UniqueID;
|
|
||||||
name: Name;
|
|
||||||
description: Maybe<TextValue>;
|
|
||||||
isActive: boolean;
|
|
||||||
isSystem: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type PaymentMethodPatchProps = Partial<
|
|
||||||
Omit<IPaymentMethodCreateProps, "companyId" | "isSystem">
|
|
||||||
>;
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
public static create(
|
|
||||||
props: IPaymentMethodCreateProps,
|
|
||||||
id?: UniqueID
|
|
||||||
): Result<PaymentMethod, Error> {
|
|
||||||
const validationResult = PaymentMethod.validateCreateProps(props);
|
|
||||||
|
|
||||||
if (validationResult.isFailure) {
|
|
||||||
return Result.fail(validationResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crear instancia
|
|
||||||
const paymentMethod = new PaymentMethod(props, id);
|
|
||||||
|
|
||||||
// Disparar eventos de dominio
|
|
||||||
// ...
|
|
||||||
// ...
|
|
||||||
|
|
||||||
return Result.ok(paymentMethod);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static rehydrate(props: PaymentMethodInternalProps, id: UniqueID): PaymentMethod {
|
|
||||||
return new PaymentMethod(props, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static validateCreateProps(_props: IPaymentMethodCreateProps): Result<void, Error> {
|
|
||||||
return Result.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get companyId(): UniqueID {
|
|
||||||
return this.props.companyId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get name(): Name {
|
|
||||||
return this.props.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get description(): Maybe<TextValue> {
|
|
||||||
return this.props.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isActive(): boolean {
|
|
||||||
return this.props.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get isSystem(): boolean {
|
|
||||||
return this.props.isSystem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public update(props: Partial<PaymentMethodPatchProps>): Result<void, Error> {
|
|
||||||
if (props.name !== undefined) {
|
|
||||||
this.props.name = props.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.description !== undefined) {
|
|
||||||
this.props.description = props.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.isActive !== undefined) {
|
|
||||||
this.props.isActive = props.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
public disable(): Result<void, Error> {
|
|
||||||
if (!this.isActive) {
|
|
||||||
return Result.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.isActive = false;
|
|
||||||
return Result.ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
public toJSON() {
|
|
||||||
return {
|
|
||||||
id: this.id.toPrimitive(),
|
|
||||||
name: this.props.name.toPrimitive(),
|
|
||||||
description: this.props.description,
|
|
||||||
is_active: this.isActive,
|
|
||||||
is_system: this.isSystem,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
import type { IModuleServer } from "@erp/core/api";
|
|
||||||
|
|
||||||
import { models, paymentMethodsRouter } from "./infrastructure";
|
|
||||||
import {
|
|
||||||
buildCatalogsDependencies,
|
|
||||||
buildCatalogsPublicServices,
|
|
||||||
} from "./infrastructure/di/catalogs.di";
|
|
||||||
|
|
||||||
export * from "./infrastructure/persistence/sequelize";
|
|
||||||
|
|
||||||
export const catalogsAPIModule: IModuleServer = {
|
|
||||||
name: "catalogs",
|
|
||||||
version: "1.0.0",
|
|
||||||
dependencies: [],
|
|
||||||
|
|
||||||
async setup(params) {
|
|
||||||
const internal = buildCatalogsDependencies(params);
|
|
||||||
const publicServices = buildCatalogsPublicServices(params, internal);
|
|
||||||
|
|
||||||
params.logger.info("🚀 Catalogs module dependencies registered", {
|
|
||||||
label: this.name,
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
models,
|
|
||||||
services: {
|
|
||||||
paymentMethod: publicServices,
|
|
||||||
},
|
|
||||||
internal,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
async start(params) {
|
|
||||||
const { logger } = params;
|
|
||||||
|
|
||||||
paymentMethodsRouter(params);
|
|
||||||
|
|
||||||
logger.info("🚀 Catalogs module started", {
|
|
||||||
label: this.name,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default catalogsAPIModule;
|
|
||||||
@ -1,23 +0,0 @@
|
|||||||
import type { ModuleParams, SetupParams } from "@erp/core/api";
|
|
||||||
|
|
||||||
import {
|
|
||||||
type PaymentMethodsInternalDeps,
|
|
||||||
buildPaymentMethodsDependencies,
|
|
||||||
buildPaymentMethodsPublicServices,
|
|
||||||
} from "./payment-methods.di";
|
|
||||||
|
|
||||||
export type CatalogsInternalDeps = {
|
|
||||||
paymentMethods: PaymentMethodsInternalDeps;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const buildCatalogsDependencies = (params: ModuleParams): CatalogsInternalDeps => {
|
|
||||||
return {
|
|
||||||
paymentMethods: buildPaymentMethodsDependencies(params),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const buildCatalogsPublicServices = (params: SetupParams, deps: CatalogsInternalDeps) => {
|
|
||||||
return {
|
|
||||||
paymentMethods: buildPaymentMethodsPublicServices(params, deps.paymentMethods),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./catalogs.di";
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import {
|
|
||||||
SequelizePaymentMethodDomainMapper,
|
|
||||||
SequelizePaymentMethodSummaryMapper,
|
|
||||||
} from "../persistence/index";
|
|
||||||
|
|
||||||
export interface IPaymentMethodPersistenceMappers {
|
|
||||||
domainMapper: SequelizePaymentMethodDomainMapper;
|
|
||||||
listMapper: SequelizePaymentMethodSummaryMapper;
|
|
||||||
|
|
||||||
//createMapper: CreatePaymentMethodRequestMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const buildPaymentMethodPersistenceMappers = (): IPaymentMethodPersistenceMappers => {
|
|
||||||
// Mappers para el repositorio
|
|
||||||
const domainMapper = new SequelizePaymentMethodDomainMapper();
|
|
||||||
const listMapper = new SequelizePaymentMethodSummaryMapper();
|
|
||||||
|
|
||||||
// Mappers el DTO a las props validadas (CustomerProps) y luego construir agregado
|
|
||||||
//const createMapper = new CreatePaymentMethodRequestMapper(catalogs);
|
|
||||||
|
|
||||||
return {
|
|
||||||
domainMapper,
|
|
||||||
listMapper,
|
|
||||||
|
|
||||||
//createMapper,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import type { Sequelize } from "sequelize";
|
|
||||||
|
|
||||||
import { SequelizePaymentMethodRepository } from "../persistence";
|
|
||||||
|
|
||||||
import type { IPaymentMethodPersistenceMappers } from "./payment-method-persistence-mappers.di";
|
|
||||||
|
|
||||||
export const buildPaymentMethodRepository = (params: {
|
|
||||||
database: Sequelize;
|
|
||||||
mappers: IPaymentMethodPersistenceMappers;
|
|
||||||
}) => {
|
|
||||||
const { database, mappers } = params;
|
|
||||||
|
|
||||||
return new SequelizePaymentMethodRepository(mappers.domainMapper, mappers.listMapper, database);
|
|
||||||
};
|
|
||||||
@ -1,96 +0,0 @@
|
|||||||
import { type ModuleParams, type SetupParams, buildTransactionManager } from "@erp/core/api";
|
|
||||||
import type { Sequelize } from "sequelize";
|
|
||||||
|
|
||||||
import {
|
|
||||||
buildPaymentMethodCreator,
|
|
||||||
buildPaymentMethodFinder,
|
|
||||||
buildPaymentMethodInputMappers,
|
|
||||||
buildPaymentMethodSnapshotBuilders,
|
|
||||||
} from "../../application";
|
|
||||||
import type { IPaymentMethodRepository } from "../../application/repositories";
|
|
||||||
import type { IPaymentMethodFinder } from "../../application/services";
|
|
||||||
import { PaymentMethodFinder, PaymentMethodUpdater } from "../../application/services";
|
|
||||||
import {
|
|
||||||
CreatePaymentMethodUseCase,
|
|
||||||
type DisablePaymentMethodByIdUseCase,
|
|
||||||
GetPaymentMethodByIdUseCase,
|
|
||||||
ListPaymentMethodsUseCase,
|
|
||||||
UpdatePaymentMethodByIdUseCase,
|
|
||||||
} from "../../application/use-cases";
|
|
||||||
|
|
||||||
import { buildPaymentMethodPersistenceMappers } from "./payment-method-persistence-mappers.di";
|
|
||||||
import { buildPaymentMethodRepository } from "./payment-method-repositories.di";
|
|
||||||
|
|
||||||
export type PaymentMethodsInternalDeps = {
|
|
||||||
repository: IPaymentMethodRepository;
|
|
||||||
useCases: {
|
|
||||||
listPaymentMethods: () => ListPaymentMethodsUseCase;
|
|
||||||
getPaymentMethodById: () => GetPaymentMethodByIdUseCase;
|
|
||||||
createPaymentMethod: () => CreatePaymentMethodUseCase;
|
|
||||||
updatePaymentMethodById: () => UpdatePaymentMethodByIdUseCase;
|
|
||||||
disablePaymentMethodById: () => DisablePaymentMethodByIdUseCase;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const buildPaymentMethodsDependencies = (
|
|
||||||
params: ModuleParams
|
|
||||||
): PaymentMethodsInternalDeps => {
|
|
||||||
const { database } = params;
|
|
||||||
|
|
||||||
// Infrastructure
|
|
||||||
const transactionManager = buildTransactionManager(database as Sequelize);
|
|
||||||
const persistenceMappers = buildPaymentMethodPersistenceMappers();
|
|
||||||
|
|
||||||
const repository = buildPaymentMethodRepository({ database, mappers: persistenceMappers });
|
|
||||||
|
|
||||||
// Application helpers
|
|
||||||
const inputMappers = buildPaymentMethodInputMappers();
|
|
||||||
const finder = buildPaymentMethodFinder(repository);
|
|
||||||
const creator = buildPaymentMethodCreator({ repository });
|
|
||||||
const updater = new PaymentMethodUpdater(repository);
|
|
||||||
//const disabler = new PaymentMethodDisabler(repository);
|
|
||||||
|
|
||||||
const snapshotBuilders = buildPaymentMethodSnapshotBuilders();
|
|
||||||
|
|
||||||
return {
|
|
||||||
repository,
|
|
||||||
useCases: {
|
|
||||||
listPaymentMethods: () =>
|
|
||||||
new ListPaymentMethodsUseCase(finder, snapshotBuilders.summary, transactionManager),
|
|
||||||
getPaymentMethodById: () =>
|
|
||||||
new GetPaymentMethodByIdUseCase(finder, snapshotBuilders.full, transactionManager),
|
|
||||||
createPaymentMethod: () =>
|
|
||||||
new CreatePaymentMethodUseCase({
|
|
||||||
dtoMapper: inputMappers.createInputMapper,
|
|
||||||
creator,
|
|
||||||
fullSnapshotBuilder: snapshotBuilders.full,
|
|
||||||
transactionManager,
|
|
||||||
}),
|
|
||||||
|
|
||||||
updatePaymentMethodById: () =>
|
|
||||||
new UpdatePaymentMethodByIdUseCase({
|
|
||||||
updater,
|
|
||||||
finder,
|
|
||||||
dtoMapper: inputMappers.updateInputMapper,
|
|
||||||
fullSnapshotBuilder: snapshotBuilders.full,
|
|
||||||
transactionManager,
|
|
||||||
}),
|
|
||||||
/*disablePaymentMethodById: () =>
|
|
||||||
new DisablePaymentMethodByIdUseCase({
|
|
||||||
finder,
|
|
||||||
disabler,
|
|
||||||
fullSnapshotBuilder,
|
|
||||||
transactionManager,
|
|
||||||
}),*/
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const buildPaymentMethodsPublicServices = (
|
|
||||||
_params: SetupParams,
|
|
||||||
deps: PaymentMethodsInternalDeps
|
|
||||||
): { finder: IPaymentMethodFinder } => {
|
|
||||||
return {
|
|
||||||
finder: new PaymentMethodFinder(deps.repository),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./payment-methods/payment-methods.routes";
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import {
|
|
||||||
ExpressController,
|
|
||||||
forbidQueryFieldGuard,
|
|
||||||
requireAuthenticatedGuard,
|
|
||||||
requireCompanyContextGuard,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
|
|
||||||
import type { CreatePaymentMethodRequestDTO } from "../../../../../common";
|
|
||||||
import type { CreatePaymentMethodUseCase } from "../../../../application";
|
|
||||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
|
||||||
|
|
||||||
export class CreatePaymentMethodController extends ExpressController {
|
|
||||||
constructor(private readonly useCase: CreatePaymentMethodUseCase) {
|
|
||||||
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 dto = this.req.body satisfies CreatePaymentMethodRequestDTO;
|
|
||||||
const result = await this.useCase.execute({ dto, companyId });
|
|
||||||
|
|
||||||
return result.match(
|
|
||||||
(data) => this.created(data),
|
|
||||||
(err) => this.handleError(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
import { ExpressController } from "@erp/core/api";
|
|
||||||
|
|
||||||
import type { DisablePaymentMethodByIdUseCase } from "../../../../application";
|
|
||||||
|
|
||||||
export class DisablePaymentMethodByIdController extends ExpressController {
|
|
||||||
constructor(private readonly useCase: DisablePaymentMethodByIdUseCase) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async executeImpl() {
|
|
||||||
const id = this.req.params.payment_method_id;
|
|
||||||
const result = await this.useCase.execute({ id });
|
|
||||||
|
|
||||||
return result.match(
|
|
||||||
(data) => this.ok(data),
|
|
||||||
(err) => this.handleError(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
import {
|
|
||||||
ExpressController,
|
|
||||||
forbidQueryFieldGuard,
|
|
||||||
requireAuthenticatedGuard,
|
|
||||||
requireCompanyContextGuard,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
|
|
||||||
import type { GetPaymentMethodByIdUseCase } from "../../../../application";
|
|
||||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
|
||||||
|
|
||||||
export class GetPaymentMethodByIdController extends ExpressController {
|
|
||||||
constructor(private readonly useCase: GetPaymentMethodByIdUseCase) {
|
|
||||||
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,5 +0,0 @@
|
|||||||
export * from "./create-payment-method.controller";
|
|
||||||
export * from "./disable-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";
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
import {
|
|
||||||
ExpressController,
|
|
||||||
forbidQueryFieldGuard,
|
|
||||||
requireAuthenticatedGuard,
|
|
||||||
requireCompanyContextGuard,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
|
||||||
|
|
||||||
import type { ListPaymentMethodsUseCase } from "../../../../application";
|
|
||||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
|
||||||
|
|
||||||
export class ListPaymentMethodsController extends ExpressController {
|
|
||||||
constructor(private readonly useCase: ListPaymentMethodsUseCase) {
|
|
||||||
super();
|
|
||||||
this.errorMapper = paymentmethodsApiErrorMapper;
|
|
||||||
|
|
||||||
// 🔐 Reutiliza guards de auth/tenant y prohíbe 'companyId' en query
|
|
||||||
this.registerGuards(
|
|
||||||
requireAuthenticatedGuard(),
|
|
||||||
requireCompanyContextGuard(),
|
|
||||||
forbidQueryFieldGuard("companyId")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getCriteriaWithDefaultOrder() {
|
|
||||||
if (this.criteria.hasOrder()) {
|
|
||||||
return this.criteria;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { q: quicksearch, filters, pageSize, pageNumber } = this.criteria.toPrimitives();
|
|
||||||
return Criteria.fromPrimitives(filters, "name", "ASC", pageSize, pageNumber, quicksearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async executeImpl() {
|
|
||||||
const companyId = this.getTenantId();
|
|
||||||
if (!companyId) {
|
|
||||||
return this.forbiddenError("Tenant ID not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const criteria = this.getCriteriaWithDefaultOrder();
|
|
||||||
const result = await this.useCase.execute({ criteria, companyId });
|
|
||||||
|
|
||||||
return result.match(
|
|
||||||
(data) =>
|
|
||||||
this.ok(data, {
|
|
||||||
"X-Total-Count": String(data.total_items),
|
|
||||||
"Pagination-Count": String(data.total_pages),
|
|
||||||
"Pagination-Page": String(data.page),
|
|
||||||
"Pagination-Limit": String(data.per_page),
|
|
||||||
}),
|
|
||||||
(err) => this.handleError(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
import type { UpdatePaymentMethodByIdRequestDTO } from "@erp/catalogs/common";
|
|
||||||
import {
|
|
||||||
ExpressController,
|
|
||||||
forbidQueryFieldGuard,
|
|
||||||
requireAuthenticatedGuard,
|
|
||||||
requireCompanyContextGuard,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
|
|
||||||
import type { UpdatePaymentMethodByIdUseCase } from "../../../../application";
|
|
||||||
import { paymentmethodsApiErrorMapper } from "../payment-methods-api-error-mapper";
|
|
||||||
|
|
||||||
export class UpdatePaymentMethodByIdController extends ExpressController {
|
|
||||||
constructor(private readonly useCase: UpdatePaymentMethodByIdUseCase) {
|
|
||||||
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;
|
|
||||||
if (!payment_method_id) {
|
|
||||||
return this.invalidInputError("Payment method ID missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
const dto = this.req.body as UpdatePaymentMethodByIdRequestDTO;
|
|
||||||
|
|
||||||
const result = await this.useCase.execute({ payment_method_id, companyId, dto });
|
|
||||||
|
|
||||||
return result.match(
|
|
||||||
(data) => this.ok(data),
|
|
||||||
(err) => this.handleError(err)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
import {
|
|
||||||
ApiErrorMapper,
|
|
||||||
ConflictApiError,
|
|
||||||
type ErrorToApiRule,
|
|
||||||
ValidationApiError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
|
|
||||||
import {
|
|
||||||
type InvalidPaymentMethodIdError,
|
|
||||||
type PaymentMethodCannotBeDeletedError,
|
|
||||||
isInvalidPaymentMethodIdError,
|
|
||||||
isPaymentMethodCannotBeDeletedError,
|
|
||||||
} from "../../../domain/payment-methods";
|
|
||||||
|
|
||||||
// Crea una regla específica (prioridad alta para sobreescribir mensajes)
|
|
||||||
const paymentmethodDuplicateRule: ErrorToApiRule = {
|
|
||||||
priority: 120,
|
|
||||||
matches: (e) => isInvalidPaymentMethodIdError(e),
|
|
||||||
build: (e) =>
|
|
||||||
new ConflictApiError(
|
|
||||||
(e as InvalidPaymentMethodIdError).message ||
|
|
||||||
"Payment method with the provided id already exists."
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
const paymentmethodCannotBeDeletedRule: ErrorToApiRule = {
|
|
||||||
priority: 120,
|
|
||||||
matches: (e) => isPaymentMethodCannotBeDeletedError(e),
|
|
||||||
build: (e) =>
|
|
||||||
new ValidationApiError(
|
|
||||||
(e as PaymentMethodCannotBeDeletedError).message || "Payment method cannot be deleted."
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cómo aplicarla: crea una nueva instancia del mapper con la regla extra
|
|
||||||
export const paymentmethodsApiErrorMapper: ApiErrorMapper = ApiErrorMapper.default()
|
|
||||||
.register(paymentmethodDuplicateRule)
|
|
||||||
.register(paymentmethodCannotBeDeletedRule);
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
import { mockUser, requireAuthenticated, requireCompanyContext } from "@erp/auth/api";
|
|
||||||
import { type RequestWithAuth, type StartParams, validateRequest } from "@erp/core/api";
|
|
||||||
import { type NextFunction, type Request, type Response, Router } from "express";
|
|
||||||
|
|
||||||
import {
|
|
||||||
CreatePaymentMethodRequestSchema,
|
|
||||||
GetPaymentMethodByIdRequestSchema,
|
|
||||||
ListPaymentMethodsRequestSchema,
|
|
||||||
UpdatePaymentMethodByIdParamsRequestSchema,
|
|
||||||
UpdatePaymentMethodByIdRequestSchema,
|
|
||||||
} from "../../../../common/dto/payment-methods/request";
|
|
||||||
import type { CatalogsInternalDeps } from "../../di/catalogs.di";
|
|
||||||
|
|
||||||
import {
|
|
||||||
CreatePaymentMethodController,
|
|
||||||
DisablePaymentMethodByIdController,
|
|
||||||
GetPaymentMethodByIdController,
|
|
||||||
ListPaymentMethodsController,
|
|
||||||
UpdatePaymentMethodByIdController,
|
|
||||||
} from "./controllers";
|
|
||||||
|
|
||||||
export const paymentMethodsRouter = (params: StartParams) => {
|
|
||||||
const { app, config, getInternal } = params;
|
|
||||||
const deps = getInternal<CatalogsInternalDeps>("catalogs").paymentMethods;
|
|
||||||
|
|
||||||
const router = Router({ mergeParams: true });
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "production") {
|
|
||||||
// 🔐 Autenticación + Tenancy para TODO el router
|
|
||||||
router.use(
|
|
||||||
(req: Request, res: Response, next: NextFunction) =>
|
|
||||||
mockUser(req as RequestWithAuth, res, next) // Debe ir antes de las rutas protegidas
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
router.use([
|
|
||||||
(req: Request, res: Response, next: NextFunction) =>
|
|
||||||
requireAuthenticated()(req as RequestWithAuth, res, next), // Debe ir antes de las rutas protegidas
|
|
||||||
|
|
||||||
(req: Request, res: Response, next: NextFunction) =>
|
|
||||||
requireCompanyContext()(req as RequestWithAuth, res, next), // Debe ir antes de las rutas protegidas
|
|
||||||
]);
|
|
||||||
|
|
||||||
// ----------------------------------------------
|
|
||||||
|
|
||||||
router.get("/", validateRequest(ListPaymentMethodsRequestSchema, "query"), (req, res, next) => {
|
|
||||||
const controller = new ListPaymentMethodsController(deps.useCases.listPaymentMethods());
|
|
||||||
return controller.execute(req, res, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.post("/", validateRequest(CreatePaymentMethodRequestSchema, "body"), (req, res, next) => {
|
|
||||||
const controller = new CreatePaymentMethodController(deps.useCases.createPaymentMethod());
|
|
||||||
return controller.execute(req, res, next);
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
"/:payment_method_id",
|
|
||||||
validateRequest(GetPaymentMethodByIdRequestSchema, "params"),
|
|
||||||
(req, res, next) => {
|
|
||||||
const controller = new GetPaymentMethodByIdController(deps.useCases.getPaymentMethodById());
|
|
||||||
return controller.execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.patch(
|
|
||||||
"/:payment_method_id",
|
|
||||||
validateRequest(UpdatePaymentMethodByIdParamsRequestSchema, "params"),
|
|
||||||
validateRequest(UpdatePaymentMethodByIdRequestSchema, "body"),
|
|
||||||
(req, res, next) => {
|
|
||||||
const controller = new UpdatePaymentMethodByIdController(
|
|
||||||
deps.useCases.updatePaymentMethodById()
|
|
||||||
);
|
|
||||||
return controller.execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
router.patch(
|
|
||||||
"/:payment_method_id/disable",
|
|
||||||
validateRequest(GetPaymentMethodByIdRequestSchema, "params"),
|
|
||||||
(req, res, next) => {
|
|
||||||
const controller = new DisablePaymentMethodByIdController(
|
|
||||||
deps.useCases.disablePaymentMethodById()
|
|
||||||
);
|
|
||||||
return controller.execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
app.use(`${config.server.apiBasePath}/catalogs/payment-methods`, router);
|
|
||||||
};
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./express";
|
|
||||||
export * from "./persistence";
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./sequelize";
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
export * from "./mappers";
|
|
||||||
export * from "./models";
|
|
||||||
export * from "./repositories";
|
|
||||||
|
|
||||||
import paymentMethodModelInit from "./models/sequelize-payment-method.model";
|
|
||||||
|
|
||||||
export const models = [paymentMethodModelInit];
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./sequelize-payment-method-domain.mapper";
|
|
||||||
export * from "./sequelize-payment-method-summary.mapper";
|
|
||||||
@ -1,85 +0,0 @@
|
|||||||
import { type MapperParamsType, SequelizeDomainMapper } from "@erp/core/api";
|
|
||||||
import {
|
|
||||||
Name,
|
|
||||||
TextValue,
|
|
||||||
UniqueID,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
type ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
maybeFromNullableResult,
|
|
||||||
maybeToNullable,
|
|
||||||
} from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import { PaymentMethod } from "../../../../domain";
|
|
||||||
import type { PaymentMethodCreationAttributes, PaymentMethodModel } from "../models";
|
|
||||||
|
|
||||||
export class SequelizePaymentMethodDomainMapper extends SequelizeDomainMapper<
|
|
||||||
PaymentMethodModel,
|
|
||||||
PaymentMethodCreationAttributes,
|
|
||||||
PaymentMethod
|
|
||||||
> {
|
|
||||||
public mapToDomain(
|
|
||||||
source: PaymentMethodModel,
|
|
||||||
params?: MapperParamsType
|
|
||||||
): Result<PaymentMethod, Error> {
|
|
||||||
try {
|
|
||||||
const errors: ValidationErrorDetail[] = [];
|
|
||||||
|
|
||||||
const idResult = UniqueID.create(source.id, true);
|
|
||||||
if (idResult.isFailure) {
|
|
||||||
return Result.fail(idResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const companyId = extractOrPushError(
|
|
||||||
UniqueID.create(source.company_id),
|
|
||||||
"company_id",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
const name = extractOrPushError(Name.create(source.name), "name", errors);
|
|
||||||
|
|
||||||
const description = extractOrPushError(
|
|
||||||
maybeFromNullableResult(source.description, (value) => TextValue.create(value)),
|
|
||||||
"description",
|
|
||||||
errors
|
|
||||||
);
|
|
||||||
|
|
||||||
// Si hubo errores de mapeo, devolvemos colección de validación
|
|
||||||
if (errors.length > 0) {
|
|
||||||
return Result.fail(
|
|
||||||
new ValidationErrorCollection("Payment method props mapping failed", errors)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const paymentMethod = PaymentMethod.rehydrate(
|
|
||||||
{
|
|
||||||
companyId: companyId!,
|
|
||||||
name: name!,
|
|
||||||
description: description!,
|
|
||||||
isActive: source.is_active,
|
|
||||||
isSystem: source.is_system,
|
|
||||||
},
|
|
||||||
idResult.data
|
|
||||||
);
|
|
||||||
|
|
||||||
return Result.ok(paymentMethod);
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(error as Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public mapToPersistence(
|
|
||||||
source: PaymentMethod,
|
|
||||||
params?: MapperParamsType
|
|
||||||
): Result<PaymentMethodCreationAttributes, Error> {
|
|
||||||
return Result.ok<PaymentMethodCreationAttributes>({
|
|
||||||
id: source.id.toPrimitive(),
|
|
||||||
company_id: source.companyId.toPrimitive(),
|
|
||||||
name: source.name.toPrimitive(),
|
|
||||||
description: maybeToNullable(source.description, (description) => description.toPrimitive()),
|
|
||||||
is_active: source.isActive,
|
|
||||||
is_system: source.isSystem,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
import { type MapperParamsType, SequelizeQueryMapper } from "@erp/core/api";
|
|
||||||
import {
|
|
||||||
Name,
|
|
||||||
UniqueID,
|
|
||||||
ValidationErrorCollection,
|
|
||||||
type ValidationErrorDetail,
|
|
||||||
extractOrPushError,
|
|
||||||
} from "@repo/rdx-ddd";
|
|
||||||
import { Result } from "@repo/rdx-utils";
|
|
||||||
|
|
||||||
import type { PaymentMethodSummary } from "../../../../application/models";
|
|
||||||
import type { PaymentMethodModel } from "../models";
|
|
||||||
|
|
||||||
export class SequelizePaymentMethodSummaryMapper extends SequelizeQueryMapper<
|
|
||||||
PaymentMethodModel,
|
|
||||||
PaymentMethodSummary
|
|
||||||
> {
|
|
||||||
public mapToReadModel(
|
|
||||||
raw: PaymentMethodModel,
|
|
||||||
params?: MapperParamsType
|
|
||||||
): Result<PaymentMethodSummary, Error> {
|
|
||||||
const errors: ValidationErrorDetail[] = [];
|
|
||||||
|
|
||||||
// 1) Valores escalares (atributos generales)
|
|
||||||
const companyId = extractOrPushError(UniqueID.create(raw.company_id), "company_id", errors);
|
|
||||||
const id = extractOrPushError(UniqueID.create(raw.id), "id", errors);
|
|
||||||
const name = extractOrPushError(Name.create(raw.name), "name", errors);
|
|
||||||
const isActive = raw.is_active;
|
|
||||||
const isSystem = raw.is_system;
|
|
||||||
|
|
||||||
// Si hubo errores de mapeo, devolvemos colección de validación
|
|
||||||
if (errors.length > 0) {
|
|
||||||
return Result.fail(
|
|
||||||
new ValidationErrorCollection("PaymentMethod mapping failed [mapToDTO]", errors)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok<PaymentMethodSummary>({
|
|
||||||
id: id!,
|
|
||||||
companyId: companyId!,
|
|
||||||
name: name!,
|
|
||||||
isActive: isActive,
|
|
||||||
isSystem: isSystem,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./sequelize-payment-method.model";
|
|
||||||
@ -1,87 +0,0 @@
|
|||||||
import {
|
|
||||||
type CreationOptional,
|
|
||||||
DataTypes,
|
|
||||||
type InferAttributes,
|
|
||||||
type InferCreationAttributes,
|
|
||||||
Model,
|
|
||||||
type Sequelize,
|
|
||||||
} from "sequelize";
|
|
||||||
|
|
||||||
export type PaymentMethodCreationAttributes = InferCreationAttributes<PaymentMethodModel, {}> & {};
|
|
||||||
|
|
||||||
export class PaymentMethodModel extends Model<
|
|
||||||
InferAttributes<PaymentMethodModel>,
|
|
||||||
InferCreationAttributes<PaymentMethodModel>
|
|
||||||
> {
|
|
||||||
declare id: string;
|
|
||||||
declare company_id: string;
|
|
||||||
declare name: string;
|
|
||||||
declare description: CreationOptional<string | null>;
|
|
||||||
declare is_active: boolean;
|
|
||||||
declare is_system: boolean;
|
|
||||||
|
|
||||||
static associate(_database: Sequelize) {}
|
|
||||||
|
|
||||||
static hooks(_database: Sequelize) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default (database: Sequelize) => {
|
|
||||||
PaymentMethodModel.init(
|
|
||||||
{
|
|
||||||
id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
primaryKey: true,
|
|
||||||
},
|
|
||||||
company_id: {
|
|
||||||
type: DataTypes.UUID,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
name: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: false,
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: DataTypes.STRING,
|
|
||||||
allowNull: true,
|
|
||||||
},
|
|
||||||
is_active: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: true,
|
|
||||||
},
|
|
||||||
is_system: {
|
|
||||||
type: DataTypes.BOOLEAN,
|
|
||||||
allowNull: false,
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sequelize: database,
|
|
||||||
modelName: "PaymentMethodModel",
|
|
||||||
tableName: "payment_methods",
|
|
||||||
|
|
||||||
underscored: true,
|
|
||||||
paranoid: true, // softs deletes
|
|
||||||
timestamps: true,
|
|
||||||
|
|
||||||
createdAt: "created_at",
|
|
||||||
updatedAt: "updated_at",
|
|
||||||
deletedAt: "deleted_at",
|
|
||||||
|
|
||||||
indexes: [
|
|
||||||
{
|
|
||||||
name: "idx_payment_methods_company",
|
|
||||||
fields: ["company_id", "deleted_at", "name"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
whereMergeStrategy: "and", // <- cómo tratar el merge de un scope
|
|
||||||
|
|
||||||
defaultScope: {},
|
|
||||||
|
|
||||||
scopes: {},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return PaymentMethodModel;
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./sequelize-payment-method.repository";
|
|
||||||
@ -1,226 +0,0 @@
|
|||||||
import {
|
|
||||||
EntityNotFoundError,
|
|
||||||
InfrastructureRepositoryError,
|
|
||||||
SequelizeRepository,
|
|
||||||
translateSequelizeError,
|
|
||||||
} from "@erp/core/api";
|
|
||||||
import { type Criteria, CriteriaToSequelizeConverter } from "@repo/rdx-criteria/server";
|
|
||||||
import type { UniqueID } from "@repo/rdx-ddd";
|
|
||||||
import { type Collection, Result } from "@repo/rdx-utils";
|
|
||||||
import type { Sequelize, Transaction } from "sequelize";
|
|
||||||
|
|
||||||
import type { IPaymentMethodRepository } from "../../../../application";
|
|
||||||
import type { PaymentMethodSummary } from "../../../../application/models";
|
|
||||||
import type { PaymentMethod } from "../../../../domain";
|
|
||||||
import type { SequelizePaymentMethodSummaryMapper } from "../mappers";
|
|
||||||
import type { SequelizePaymentMethodDomainMapper } from "../mappers/sequelize-payment-method-domain.mapper";
|
|
||||||
import { PaymentMethodModel } from "../models";
|
|
||||||
|
|
||||||
export class SequelizePaymentMethodRepository
|
|
||||||
extends SequelizeRepository<PaymentMethod>
|
|
||||||
implements IPaymentMethodRepository
|
|
||||||
{
|
|
||||||
constructor(
|
|
||||||
private readonly domainMapper: SequelizePaymentMethodDomainMapper,
|
|
||||||
private readonly summaryMapper: SequelizePaymentMethodSummaryMapper,
|
|
||||||
database: Sequelize
|
|
||||||
) {
|
|
||||||
super({ database });
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Crea un nuevo método de pago
|
|
||||||
*
|
|
||||||
* @param paymentMethod - El método de pago nuevo a guardar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<void, Error>
|
|
||||||
*/
|
|
||||||
async create(
|
|
||||||
paymentMethod: PaymentMethod,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<void, Error>> {
|
|
||||||
try {
|
|
||||||
const dtoResult = this.domainMapper.mapToPersistence(paymentMethod);
|
|
||||||
if (dtoResult.isFailure) {
|
|
||||||
return Result.fail(dtoResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
await PaymentMethodModel.create(dtoResult.data, { transaction });
|
|
||||||
return Result.ok();
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Actualiza un método de pago existente.
|
|
||||||
*
|
|
||||||
* @param paymentMethod - El método de pago a actualizar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<void, Error>
|
|
||||||
*/
|
|
||||||
async update(
|
|
||||||
paymentMethod: PaymentMethod,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<void, Error>> {
|
|
||||||
try {
|
|
||||||
const dtoResult = this.domainMapper.mapToPersistence(paymentMethod);
|
|
||||||
if (dtoResult.isFailure) {
|
|
||||||
return Result.fail(dtoResult.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id, ...payload } = dtoResult.data;
|
|
||||||
const [affected] = await PaymentMethodModel.update(payload, {
|
|
||||||
where: { id },
|
|
||||||
transaction,
|
|
||||||
individualHooks: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (affected === 0) {
|
|
||||||
return Result.fail(
|
|
||||||
new InfrastructureRepositoryError("Concurrency conflict or payment method not found")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok();
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Comprueba si existe un PaymentMethod con un `id` dentro de una `company`.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece el método de pago.
|
|
||||||
* @param id - Identificador UUID del método de pago.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<boolean, Error>
|
|
||||||
*/
|
|
||||||
async existsByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<boolean, Error>> {
|
|
||||||
try {
|
|
||||||
const count = await PaymentMethodModel.count({
|
|
||||||
where: { id: id.toString(), company_id: companyId.toString() },
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
return Result.ok(Boolean(count > 0));
|
|
||||||
} catch (error: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recupera un método de pago por su ID y companyId.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece el método de pago.
|
|
||||||
* @param id - Identificador UUID del método de pago.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<PaymentMethod, Error>
|
|
||||||
*/
|
|
||||||
|
|
||||||
async getByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<PaymentMethod, Error>> {
|
|
||||||
try {
|
|
||||||
const row = await PaymentMethodModel.findOne({
|
|
||||||
where: {
|
|
||||||
id: id.toString(),
|
|
||||||
company_id: companyId.toString(),
|
|
||||||
},
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
if (!row) {
|
|
||||||
return Result.fail(new EntityNotFoundError("PaymentMethod", "id", id.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.domainMapper.mapToDomain(row);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recupera múltiples customers dentro de una empresa según un criterio dinámico (búsqueda, paginación, etc.).
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece el cliente.
|
|
||||||
* @param criteria - Criterios de búsqueda.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<Collection<CustomerListDTO>, Error>
|
|
||||||
*
|
|
||||||
* @see Criteria
|
|
||||||
*/
|
|
||||||
async findByCriteriaInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
criteria: Criteria,
|
|
||||||
transaction?: Transaction
|
|
||||||
): Promise<Result<Collection<PaymentMethodSummary>, Error>> {
|
|
||||||
try {
|
|
||||||
const criteriaConverter = new CriteriaToSequelizeConverter();
|
|
||||||
const query = criteriaConverter.convert(criteria, {
|
|
||||||
searchableFields: [],
|
|
||||||
sortableFields: ["name"],
|
|
||||||
enableFullText: true,
|
|
||||||
database: this.database,
|
|
||||||
strictMode: true, // fuerza error si ORDER BY no permitido
|
|
||||||
});
|
|
||||||
|
|
||||||
query.where = {
|
|
||||||
...query.where,
|
|
||||||
company_id: companyId.toString(),
|
|
||||||
deleted_at: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const [rows, count] = await Promise.all([
|
|
||||||
PaymentMethodModel.findAll({
|
|
||||||
...query,
|
|
||||||
transaction,
|
|
||||||
}),
|
|
||||||
PaymentMethodModel.count({
|
|
||||||
where: query.where,
|
|
||||||
distinct: true, // evita duplicados por LEFT JOIN
|
|
||||||
transaction,
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return this.summaryMapper.mapToReadModelCollection(rows, count);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Elimina o marca como eliminado una forma de pago.
|
|
||||||
*
|
|
||||||
* @param companyId - Identificador UUID de la empresa a la que pertenece la forma de pago.
|
|
||||||
* @param id - UUID de la forma de pago a eliminar.
|
|
||||||
* @param transaction - Transacción activa para la operación.
|
|
||||||
* @returns Result<boolean, Error>
|
|
||||||
*/
|
|
||||||
async deleteByIdInCompany(
|
|
||||||
companyId: UniqueID,
|
|
||||||
id: UniqueID,
|
|
||||||
transaction: Transaction
|
|
||||||
): Promise<Result<boolean, Error>> {
|
|
||||||
try {
|
|
||||||
const deleted = await PaymentMethodModel.destroy({
|
|
||||||
where: { id: id.toString(), company_id: companyId.toString() },
|
|
||||||
transaction,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (deleted === 0) {
|
|
||||||
return Result.fail(new EntityNotFoundError("PaymentMethod", "id", id.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result.ok(true);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
return Result.fail(translateSequelizeError(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./payment-methods";
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./request";
|
|
||||||
export * from "./response";
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const CreatePaymentMethodRequestSchema = z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
|
|
||||||
name: z.string(),
|
|
||||||
description: z.string().nullable().optional(),
|
|
||||||
|
|
||||||
is_active: z.boolean(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type CreatePaymentMethodRequestDTO = z.infer<typeof CreatePaymentMethodRequestSchema>;
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const GetPaymentMethodByIdRequestSchema = z.object({
|
|
||||||
payment_method_id: z.uuid(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type GetPaymentMethodByIdRequestDTO = z.infer<typeof GetPaymentMethodByIdRequestSchema>;
|
|
||||||
@ -1,4 +0,0 @@
|
|||||||
export * from "./create-payment-method.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,5 +0,0 @@
|
|||||||
import { CriteriaSchema } from "@erp/core";
|
|
||||||
import type { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const ListPaymentMethodsRequestSchema = CriteriaSchema;
|
|
||||||
export type ListPaymentMethodsRequestDTO = z.infer<typeof ListPaymentMethodsRequestSchema>;
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const UpdatePaymentMethodByIdParamsRequestSchema = z.object({
|
|
||||||
payment_method_id: z.uuid(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const UpdatePaymentMethodByIdRequestSchema = z.object({
|
|
||||||
name: z.string().optional(),
|
|
||||||
description: z.string().nullable().optional(),
|
|
||||||
is_active: z.boolean().optional(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UpdatePaymentMethodByIdParamsRequestDTO = z.infer<
|
|
||||||
typeof UpdatePaymentMethodByIdParamsRequestSchema
|
|
||||||
>;
|
|
||||||
export type UpdatePaymentMethodByIdRequestDTO = z.infer<
|
|
||||||
typeof UpdatePaymentMethodByIdRequestSchema
|
|
||||||
>;
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import type { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { PaymentMethodDetailSchema } from "../shared";
|
|
||||||
|
|
||||||
export const CreatePaymentMethodResponseSchema = PaymentMethodDetailSchema;
|
|
||||||
export type CreatePaymentMethodResponseDTO = z.infer<typeof CreatePaymentMethodResponseSchema>;
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import type { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { PaymentMethodDetailSchema } from "../shared";
|
|
||||||
|
|
||||||
export const DisablePaymentMethodByIdResponseSchema = PaymentMethodDetailSchema;
|
|
||||||
export type DisablePaymentMethodByIdResponseDTO = z.infer<
|
|
||||||
typeof DisablePaymentMethodByIdResponseSchema
|
|
||||||
>;
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import type { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { PaymentMethodDetailSchema } from "../shared";
|
|
||||||
|
|
||||||
export const GetPaymentMethodByIdResponseSchema = PaymentMethodDetailSchema;
|
|
||||||
export type GetPaymentMethodByIdResponseDTO = z.infer<typeof GetPaymentMethodByIdResponseSchema>;
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
export * from "./create-payment-method.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";
|
|
||||||
export * from "./update-payment-method-by-id.response.dto";
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { PaymentMethodSummarySchema } from "../shared";
|
|
||||||
|
|
||||||
export const ListPaymentMethodsResponseSchema = z.array(PaymentMethodSummarySchema);
|
|
||||||
export type ListPaymentMethodsResponseDTO = z.infer<typeof ListPaymentMethodsResponseSchema>;
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import type { z } from "zod/v4";
|
|
||||||
|
|
||||||
import { PaymentMethodDetailSchema } from "../shared";
|
|
||||||
|
|
||||||
export const UpdatePaymentMethodByIdResponseSchema = PaymentMethodDetailSchema;
|
|
||||||
export type UpdatePaymentMethodByIdResponseDTO = z.infer<
|
|
||||||
typeof UpdatePaymentMethodByIdResponseSchema
|
|
||||||
>;
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
export * from "./payment-method-detail.dto";
|
|
||||||
export * from "./payment-method-summary.dto";
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const PaymentMethodDetailSchema = z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
company_id: z.uuid(),
|
|
||||||
|
|
||||||
name: z.string(),
|
|
||||||
description: z.string().nullable(),
|
|
||||||
is_active: z.boolean(),
|
|
||||||
is_system: z.boolean(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type PaymentMethodDetailDTO = z.infer<typeof PaymentMethodDetailSchema>;
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { z } from "zod/v4";
|
|
||||||
|
|
||||||
export const PaymentMethodSummarySchema = z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
company_id: z.uuid(),
|
|
||||||
|
|
||||||
name: z.string(),
|
|
||||||
is_active: z.boolean(),
|
|
||||||
is_system: z.boolean(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type PaymentMethodSummaryDTO = z.infer<typeof PaymentMethodSummarySchema>;
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./dto";
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"paths": {
|
|
||||||
"@erp/catalogs/*": ["./src/*"]
|
|
||||||
},
|
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
||||||
"target": "ES2022",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"lib": ["ES2022"],
|
|
||||||
"module": "ESNext",
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"allowImportingTsExtensions": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"moduleDetection": "force",
|
|
||||||
"noEmit": true,
|
|
||||||
"strict": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noFallthroughCasesInSwitch": true,
|
|
||||||
"noUncheckedSideEffectImports": true
|
|
||||||
},
|
|
||||||
"include": ["src"],
|
|
||||||
"exclude": ["node_modules"]
|
|
||||||
}
|
|
||||||
@ -21,7 +21,7 @@ import {
|
|||||||
ListProformasUseCase,
|
ListProformasUseCase,
|
||||||
ReportProformaUseCase,
|
ReportProformaUseCase,
|
||||||
} from "../use-cases";
|
} from "../use-cases";
|
||||||
import { UpdateProformaByIdUseCase } from "../use-cases/update-proforma-by-id.use-case";
|
import { UpdateProformaUseCase } from "../use-cases/update-proforma.use-case";
|
||||||
|
|
||||||
export function buildGetProformaByIdUseCase(deps: {
|
export function buildGetProformaByIdUseCase(deps: {
|
||||||
finder: IProformaFinder;
|
finder: IProformaFinder;
|
||||||
@ -101,7 +101,7 @@ export function buildUpdateProformaUseCase(deps: {
|
|||||||
fullSnapshotBuilder: IProformaFullSnapshotBuilder;
|
fullSnapshotBuilder: IProformaFullSnapshotBuilder;
|
||||||
transactionManager: ITransactionManager;
|
transactionManager: ITransactionManager;
|
||||||
}) {
|
}) {
|
||||||
return new UpdateProformaByIdUseCase({
|
return new UpdateProformaUseCase({
|
||||||
dtoMapper: deps.dtoMapper,
|
dtoMapper: deps.dtoMapper,
|
||||||
updater: deps.updater,
|
updater: deps.updater,
|
||||||
fullSnapshotBuilder: deps.fullSnapshotBuilder,
|
fullSnapshotBuilder: deps.fullSnapshotBuilder,
|
||||||
|
|||||||
@ -13,6 +13,12 @@ export interface IProformaFinder {
|
|||||||
transaction?: unknown
|
transaction?: unknown
|
||||||
): Promise<Result<Proforma, Error>>;
|
): Promise<Result<Proforma, Error>>;
|
||||||
|
|
||||||
|
findProformaByFactuGESId(
|
||||||
|
companyId: UniqueID,
|
||||||
|
factugesId: string,
|
||||||
|
transaction?: unknown
|
||||||
|
): Promise<Result<Proforma, Error>>;
|
||||||
|
|
||||||
proformaExists(
|
proformaExists(
|
||||||
companyId: UniqueID,
|
companyId: UniqueID,
|
||||||
invoiceId: UniqueID,
|
invoiceId: UniqueID,
|
||||||
@ -37,6 +43,14 @@ export class ProformaFinder implements IProformaFinder {
|
|||||||
return this.repository.getByIdInCompany(companyId, proformaId, transaction);
|
return this.repository.getByIdInCompany(companyId, proformaId, transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findProformaByFactuGESId(
|
||||||
|
companyId: UniqueID,
|
||||||
|
factugesId: string,
|
||||||
|
transaction?: unknown
|
||||||
|
): Promise<Result<Proforma, Error>> {
|
||||||
|
return this.repository.getByFactuGESIdInCompany(companyId, factugesId, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
async proformaExists(
|
async proformaExists(
|
||||||
companyId: UniqueID,
|
companyId: UniqueID,
|
||||||
proformaId: UniqueID,
|
proformaId: UniqueID,
|
||||||
|
|||||||
@ -5,4 +5,4 @@ export * from "./get-proforma-by-id.use-case";
|
|||||||
export * from "./issue-proforma.use-case";
|
export * from "./issue-proforma.use-case";
|
||||||
export * from "./list-proformas.use-case";
|
export * from "./list-proformas.use-case";
|
||||||
export * from "./report-proforma.use-case";
|
export * from "./report-proforma.use-case";
|
||||||
export * from "./update-proforma-by-id.use-case";
|
export * from "./update-proforma.use-case";
|
||||||
|
|||||||
@ -21,7 +21,7 @@ type UpdateProformaUseCaseDeps = {
|
|||||||
transactionManager: ITransactionManager;
|
transactionManager: ITransactionManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class UpdateProformaByIdUseCase {
|
export class UpdateProformaUseCase {
|
||||||
private readonly dtoMapper: IUpdateProformaInputMapper;
|
private readonly dtoMapper: IUpdateProformaInputMapper;
|
||||||
private readonly updater: IProformaUpdater;
|
private readonly updater: IProformaUpdater;
|
||||||
private readonly fullSnapshotBuilder: IProformaFullSnapshotBuilder;
|
private readonly fullSnapshotBuilder: IProformaFullSnapshotBuilder;
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
type IssueProformaUseCase,
|
type IssueProformaUseCase,
|
||||||
type ListProformasUseCase,
|
type ListProformasUseCase,
|
||||||
type ReportProformaUseCase,
|
type ReportProformaUseCase,
|
||||||
type UpdateProformaByIdUseCase,
|
type UpdateProformaUseCase,
|
||||||
buildCreateProformaUseCase,
|
buildCreateProformaUseCase,
|
||||||
buildGetProformaByIdUseCase,
|
buildGetProformaByIdUseCase,
|
||||||
buildIssueProformaUseCase,
|
buildIssueProformaUseCase,
|
||||||
@ -37,7 +37,7 @@ export type ProformasInternalDeps = {
|
|||||||
issueProforma: (publicServices: {
|
issueProforma: (publicServices: {
|
||||||
issuedInvoiceServices: IIssuedInvoicePublicServices;
|
issuedInvoiceServices: IIssuedInvoicePublicServices;
|
||||||
}) => IssueProformaUseCase;
|
}) => IssueProformaUseCase;
|
||||||
updateProforma: () => UpdateProformaByIdUseCase;
|
updateProforma: () => UpdateProformaUseCase;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
deleteProforma: () => DeleteProformaUseCase;
|
deleteProforma: () => DeleteProformaUseCase;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class CreateProformaController extends ExpressController {
|
|||||||
if (!companyId) {
|
if (!companyId) {
|
||||||
return this.forbiddenError("Tenant ID not found");
|
return this.forbiddenError("Tenant ID not found");
|
||||||
}
|
}
|
||||||
const dto = this.req.body satisfies CreateProformaRequestDTO;
|
const dto = this.req.body as CreateProformaRequestDTO;
|
||||||
|
|
||||||
const result = await this.useCase.execute({ dto, companyId });
|
const result = await this.useCase.execute({ dto, companyId });
|
||||||
|
|
||||||
|
|||||||
@ -6,11 +6,11 @@ import {
|
|||||||
} from "@erp/core/api";
|
} from "@erp/core/api";
|
||||||
|
|
||||||
import type { UpdateProformaByIdRequestDTO } from "../../../../../common/dto/index.ts";
|
import type { UpdateProformaByIdRequestDTO } from "../../../../../common/dto/index.ts";
|
||||||
import type { UpdateProformaByIdUseCase } from "../../../../application/index.ts";
|
import type { UpdateProformaUseCase } from "../../../../application/index.ts";
|
||||||
import { proformasApiErrorMapper } from "../proformas-api-error-mapper.ts";
|
import { proformasApiErrorMapper } from "../proformas-api-error-mapper.ts";
|
||||||
|
|
||||||
export class UpdateProformaController extends ExpressController {
|
export class UpdateProformaController extends ExpressController {
|
||||||
public constructor(private readonly useCase: UpdateProformaByIdUseCase) {
|
public constructor(private readonly useCase: UpdateProformaUseCase) {
|
||||||
super();
|
super();
|
||||||
this.errorMapper = proformasApiErrorMapper;
|
this.errorMapper = proformasApiErrorMapper;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod/v4";
|
import { z } from "zod/v4";
|
||||||
|
|
||||||
export const GetProformaByIdRequestSchema = z.object({
|
export const GetProformaByIdRequestSchema = z.object({
|
||||||
proforma_id: z.uuid(),
|
proforma_id: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetProformaByIdRequestDTO = z.infer<typeof GetProformaByIdRequestSchema>;
|
export type GetProformaByIdRequestDTO = z.infer<typeof GetProformaByIdRequestSchema>;
|
||||||
|
|||||||
@ -56,9 +56,6 @@ importers:
|
|||||||
'@erp/auth':
|
'@erp/auth':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../modules/auth
|
version: link:../../modules/auth
|
||||||
'@erp/catalogs':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../modules/catalogs
|
|
||||||
'@erp/core':
|
'@erp/core':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../modules/core
|
version: link:../../modules/core
|
||||||
@ -378,40 +375,6 @@ importers:
|
|||||||
specifier: ^6.0.2
|
specifier: ^6.0.2
|
||||||
version: 6.0.2
|
version: 6.0.2
|
||||||
|
|
||||||
modules/catalogs:
|
|
||||||
dependencies:
|
|
||||||
'@erp/auth':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../auth
|
|
||||||
'@erp/core':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../core
|
|
||||||
'@repo/rdx-criteria':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../packages/rdx-criteria
|
|
||||||
'@repo/rdx-ddd':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../packages/rdx-ddd
|
|
||||||
'@repo/rdx-utils':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../packages/rdx-utils
|
|
||||||
express:
|
|
||||||
specifier: ^4.22.1
|
|
||||||
version: 4.22.1
|
|
||||||
sequelize:
|
|
||||||
specifier: ^6.37.8
|
|
||||||
version: 6.37.8(mysql2@3.22.0(@types/node@25.6.0))(pg-hstore@2.3.4)
|
|
||||||
zod:
|
|
||||||
specifier: ^4.3.6
|
|
||||||
version: 4.3.6
|
|
||||||
devDependencies:
|
|
||||||
'@types/express':
|
|
||||||
specifier: ^4.17.21
|
|
||||||
version: 4.17.25
|
|
||||||
typescript:
|
|
||||||
specifier: ^6.0.2
|
|
||||||
version: 6.0.2
|
|
||||||
|
|
||||||
modules/core:
|
modules/core:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@hookform/resolvers':
|
'@hookform/resolvers':
|
||||||
|
|||||||
@ -7,11 +7,7 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"chatgpt.openOnStartup": true,
|
"chatgpt.openOnStartup": true,
|
||||||
"chat.tools.terminal.autoApprove": {
|
"chat.tools.terminal.autoApprove": {
|
||||||
"pnpm": true,
|
"pnpm": true
|
||||||
"/^cd /home/rodax/Documentos/uecko-erp && ls -l node_modules/@repo/typescript-config/root\\.json && node -p \"require\\.resolve\\('@repo/typescript-config/root\\.json'\\)\"$/": {
|
|
||||||
"approve": true,
|
|
||||||
"matchCommandLine": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user