Facturas de cliente
This commit is contained in:
parent
b87082754b
commit
91c00e7344
6
modules/core/src/api/errors/entity-not-found-error.ts
Normal file
6
modules/core/src/api/errors/entity-not-found-error.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export class EntityNotFoundError extends Error {
|
||||||
|
constructor(entity: string, id: string | number) {
|
||||||
|
super(`Entity '${entity}' with ID '${id}' was not found.`);
|
||||||
|
this.name = "EntityNotFoundError";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,7 @@ import { ApiError } from "./api-error";
|
|||||||
import { ConflictApiError } from "./conflict-api-error";
|
import { ConflictApiError } from "./conflict-api-error";
|
||||||
import { DomainValidationError } from "./domain-validation-error";
|
import { DomainValidationError } from "./domain-validation-error";
|
||||||
import { DuplicateEntityError } from "./duplicate-entity-error";
|
import { DuplicateEntityError } from "./duplicate-entity-error";
|
||||||
|
import { EntityNotFoundError } from "./entity-not-found-error";
|
||||||
import { ForbiddenApiError } from "./forbidden-api-error";
|
import { ForbiddenApiError } from "./forbidden-api-error";
|
||||||
import { InternalApiError } from "./internal-api-error";
|
import { InternalApiError } from "./internal-api-error";
|
||||||
import { NotFoundApiError } from "./not-found-api-error";
|
import { NotFoundApiError } from "./not-found-api-error";
|
||||||
@ -79,6 +80,10 @@ export const errorMapper = {
|
|||||||
return new ConflictApiError(error.message);
|
return new ConflictApiError(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error instanceof EntityNotFoundError) {
|
||||||
|
return new NotFoundApiError(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
// 3. 🔍 Errores individuales de validación
|
// 3. 🔍 Errores individuales de validación
|
||||||
if (
|
if (
|
||||||
message.includes("invalid") ||
|
message.includes("invalid") ||
|
||||||
|
|||||||
@ -2,6 +2,7 @@ export * from "./api-error";
|
|||||||
export * from "./conflict-api-error";
|
export * from "./conflict-api-error";
|
||||||
export * from "./domain-validation-error";
|
export * from "./domain-validation-error";
|
||||||
export * from "./duplicate-entity-error";
|
export * from "./duplicate-entity-error";
|
||||||
|
export * from "./entity-not-found-error";
|
||||||
export * from "./error-mapper";
|
export * from "./error-mapper";
|
||||||
export * from "./forbidden-api-error";
|
export * from "./forbidden-api-error";
|
||||||
export * from "./internal-api-error";
|
export * from "./internal-api-error";
|
||||||
|
|||||||
@ -1,24 +1,38 @@
|
|||||||
import { UniqueID } from "@/core/common/domain";
|
import { EntityNotFoundError, ITransactionManager } from "@erp/core/api";
|
||||||
import { ITransactionManager } from "@/core/common/infrastructure/database";
|
import { DeleteCustomerInvoiceByIdQueryDTO } from "@erp/customer-invoices/common/dto";
|
||||||
import { logger } from "@/core/logger";
|
import { UniqueID } from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { ICustomerInvoiceService } from "../domain";
|
import { ICustomerInvoiceService } from "../../domain";
|
||||||
|
|
||||||
export class DeleteCustomerInvoiceUseCase {
|
export class DeleteCustomerInvoiceUseCase {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly customerInvoiceService: ICustomerInvoiceService,
|
private readonly service: ICustomerInvoiceService,
|
||||||
private readonly transactionManager: ITransactionManager
|
private readonly transactionManager: ITransactionManager
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public execute(customerInvoiceID: UniqueID): Promise<Result<boolean, Error>> {
|
public execute(dto: DeleteCustomerInvoiceByIdQueryDTO) {
|
||||||
|
const idOrError = UniqueID.create(dto.id);
|
||||||
|
|
||||||
|
if (idOrError.isFailure) {
|
||||||
|
return Result.fail(idOrError.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
const id = idOrError.data;
|
||||||
|
|
||||||
return this.transactionManager.complete(async (transaction) => {
|
return this.transactionManager.complete(async (transaction) => {
|
||||||
try {
|
try {
|
||||||
return await this.customerInvoiceService.deleteCustomerInvoiceById(
|
const existsCheck = await this.service.existsById(id, transaction);
|
||||||
customerInvoiceID,
|
|
||||||
transaction
|
if (existsCheck.isFailure) {
|
||||||
);
|
return Result.fail(existsCheck.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsCheck.data) {
|
||||||
|
return Result.fail(new EntityNotFoundError("CustomerInvoice", id.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.service.deleteById(id, transaction);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
logger.error(error as Error);
|
|
||||||
return Result.fail(error as Error);
|
return Result.fail(error as Error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { GetCustomerInvoiceResultDTO } from "../../../../common/dto";
|
import { GetCustomerInvoiceByIdResultDTO } from "../../../../common/dto";
|
||||||
import { CustomerInvoice } from "../../../domain";
|
import { CustomerInvoice } from "../../../domain";
|
||||||
|
|
||||||
export interface GetCustomerInvoicePresenter {
|
export interface GetCustomerInvoicePresenter {
|
||||||
toDTO: (customerInvoice: CustomerInvoice) => GetCustomerInvoiceResultDTO;
|
toDTO: (customerInvoice: CustomerInvoice) => GetCustomerInvoiceByIdResultDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getCustomerInvoicePresenter: GetCustomerInvoicePresenter = {
|
export const getCustomerInvoicePresenter: GetCustomerInvoicePresenter = {
|
||||||
toDTO: (customerInvoice: CustomerInvoice): GetCustomerInvoiceResultDTO => ({
|
toDTO: (customerInvoice: CustomerInvoice): GetCustomerInvoiceByIdResultDTO => ({
|
||||||
id: customerInvoice.id.toPrimitive(),
|
id: customerInvoice.id.toPrimitive(),
|
||||||
|
|
||||||
invoice_status: customerInvoice.status.toString(),
|
invoice_status: customerInvoice.status.toString(),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
export * from "./create-customer-invoice";
|
export * from "./create-customer-invoice";
|
||||||
//export * from "./delete-customer-invoice";
|
export * from "./delete-customer-invoice";
|
||||||
export * from "./get-customer-invoice";
|
export * from "./get-customer-invoice";
|
||||||
export * from "./list-customer-invoices";
|
export * from "./list-customer-invoices";
|
||||||
//export * from "./update-customer-invoice";
|
//export * from "./update-customer-invoice";
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
import { ExpressController, errorMapper } from "@erp/core/api";
|
||||||
|
import { DeleteCustomerInvoiceUseCase } from "../../application";
|
||||||
|
|
||||||
|
export class DeleteCustomerInvoiceController extends ExpressController {
|
||||||
|
public constructor(private readonly deleteCustomerInvoice: DeleteCustomerInvoiceUseCase) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeImpl(): Promise<any> {
|
||||||
|
const { id } = this.req.params;
|
||||||
|
|
||||||
|
/*
|
||||||
|
const user = this.req.user; // asumimos middleware authenticateJWT inyecta user
|
||||||
|
|
||||||
|
if (!user || !user.companyId) {
|
||||||
|
this.unauthorized(res, "Unauthorized: user or company not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const result = await this.deleteCustomerInvoice.execute({ id });
|
||||||
|
|
||||||
|
if (result.isFailure) {
|
||||||
|
const apiError = errorMapper.toApiError(result.error);
|
||||||
|
return this.handleApiError(apiError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.ok(result.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { DeleteCustomerInvoiceUseCase } from "@/contexts/customer-invoices/application";
|
|
||||||
import { ExpressController } from "@/core/common/presentation";
|
|
||||||
|
|
||||||
export class DeleteCustomerInvoiceController extends ExpressController {
|
|
||||||
public constructor(private readonly deleteCustomerInvoice: DeleteCustomerInvoiceUseCase) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
async executeImpl(): Promise<any> {
|
|
||||||
return this.noContent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { SequelizeTransactionManager } from "@erp/core/api";
|
||||||
|
import { Sequelize } from "sequelize";
|
||||||
|
import { DeleteCustomerInvoiceUseCase } from "../../application";
|
||||||
|
import { CustomerInvoiceService } from "../../domain";
|
||||||
|
import { CustomerInvoiceMapper, CustomerInvoiceRepository } from "../../infrastructure";
|
||||||
|
import { DeleteCustomerInvoiceController } from "./delete-invoice.controller";
|
||||||
|
|
||||||
|
export const buildDeleteCustomerInvoiceController = (database: Sequelize) => {
|
||||||
|
const transactionManager = new SequelizeTransactionManager(database);
|
||||||
|
const customerInvoiceRepository = new CustomerInvoiceRepository(
|
||||||
|
database,
|
||||||
|
new CustomerInvoiceMapper()
|
||||||
|
);
|
||||||
|
const customerInvoiceService = new CustomerInvoiceService(customerInvoiceRepository);
|
||||||
|
|
||||||
|
const useCase = new DeleteCustomerInvoiceUseCase(customerInvoiceService, transactionManager);
|
||||||
|
|
||||||
|
return new DeleteCustomerInvoiceController(useCase);
|
||||||
|
};
|
||||||
@ -1,14 +0,0 @@
|
|||||||
import { DeleteCustomerInvoiceUseCase } from "@/contexts/customer-invoices/application";
|
|
||||||
import { CustomerInvoiceService } from "@/contexts/customer-invoices/domain";
|
|
||||||
import { customerInvoiceRepository } from "@/contexts/customer-invoices/intrastructure";
|
|
||||||
import { SequelizeTransactionManager } from "@/core/common/infrastructure";
|
|
||||||
import { DeleteCustomerInvoiceController } from "./delete-customer-invoice.controller";
|
|
||||||
|
|
||||||
export const buildDeleteCustomerInvoiceController = () => {
|
|
||||||
const transactionManager = new SequelizeTransactionManager();
|
|
||||||
const customerInvoiceService = new CustomerInvoiceService(customerInvoiceRepository);
|
|
||||||
|
|
||||||
const useCase = new DeleteCustomerInvoiceUseCase(customerInvoiceService, transactionManager);
|
|
||||||
|
|
||||||
return new DeleteCustomerInvoiceController(useCase);
|
|
||||||
};
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
export * from "./create-customer-invoice";
|
export * from "./create-customer-invoice";
|
||||||
//export * from "./delete-customer-invoice";
|
export * from "./delete-customer-invoice";
|
||||||
export * from "./get-customer-invoice";
|
export * from "./get-customer-invoice";
|
||||||
export * from "./list-customer-invoices";
|
export * from "./list-customer-invoices";
|
||||||
///export * from "./update-customer-invoice";
|
///export * from "./update-customer-invoice";
|
||||||
|
|||||||
@ -29,5 +29,5 @@ export interface ICustomerInvoiceService {
|
|||||||
transaction?: any
|
transaction?: any
|
||||||
): Promise<Result<CustomerInvoice, Error>>;
|
): Promise<Result<CustomerInvoice, Error>>;
|
||||||
|
|
||||||
deleteById(id: UniqueID, transaction?: any): Promise<Result<boolean, Error>>;
|
deleteById(id: UniqueID, transaction?: any): Promise<Result<void, Error>>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,7 +144,7 @@ export class CustomerInvoiceService implements ICustomerInvoiceService {
|
|||||||
* @param transaction - Transacción activa para la operación.
|
* @param transaction - Transacción activa para la operación.
|
||||||
* @returns Result<boolean, Error> - Resultado de la operación.
|
* @returns Result<boolean, Error> - Resultado de la operación.
|
||||||
*/
|
*/
|
||||||
async deleteById(id: UniqueID, transaction?: Transaction): Promise<Result<boolean, Error>> {
|
async deleteById(id: UniqueID, transaction?: Transaction): Promise<Result<void, Error>> {
|
||||||
return this.repository.deleteById(id, transaction);
|
return this.repository.deleteById(id, transaction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,13 @@ import { Application, NextFunction, Request, Response, Router } from "express";
|
|||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import {
|
import {
|
||||||
CreateCustomerInvoiceCommandSchema,
|
CreateCustomerInvoiceCommandSchema,
|
||||||
GetCustomerInvoiceByIdQuerySchema,
|
DeleteCustomerInvoiceByIdQuerySchema,
|
||||||
|
DeleteCustomerInvoiceByIdQuerySchema as GetCustomerInvoiceByIdQuerySchema,
|
||||||
ListCustomerInvoicesQuerySchema,
|
ListCustomerInvoicesQuerySchema,
|
||||||
} from "../../../common/dto";
|
} from "../../../common/dto";
|
||||||
import {
|
import {
|
||||||
buildCreateCustomerInvoicesController,
|
buildCreateCustomerInvoicesController,
|
||||||
|
buildDeleteCustomerInvoiceController,
|
||||||
buildGetCustomerInvoiceController,
|
buildGetCustomerInvoiceController,
|
||||||
buildListCustomerInvoicesController,
|
buildListCustomerInvoicesController,
|
||||||
} from "../../controllers";
|
} from "../../controllers";
|
||||||
@ -60,17 +62,17 @@ export const customerInvoicesRouter = (params: ModuleParams) => {
|
|||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildUpdateCustomerInvoiceController().execute(req, res, next);
|
buildUpdateCustomerInvoiceController().execute(req, res, next);
|
||||||
}
|
}
|
||||||
);
|
);*/
|
||||||
|
|
||||||
routes.delete(
|
routes.delete(
|
||||||
"/:customerInvoiceId",
|
"/:id",
|
||||||
validateAndParseBody(IDeleteCustomerInvoiceRequestSchema),
|
//checkTabContext,
|
||||||
checkTabContext,
|
|
||||||
//checkUser,
|
//checkUser,
|
||||||
|
validateRequest(DeleteCustomerInvoiceByIdQuerySchema, "params"),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildDeleteCustomerInvoiceController().execute(req, res, next);
|
buildDeleteCustomerInvoiceController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
);*/
|
);
|
||||||
|
|
||||||
app.use(`${baseRoutePath}/customer-invoices`, routes);
|
app.use(`${baseRoutePath}/customer-invoices`, routes);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,15 @@
|
|||||||
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Este DTO es utilizado por el endpoint:
|
||||||
|
* `DELETE /customer-invoices/:id` (eliminar una factura por ID).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const DeleteCustomerInvoiceByIdQuerySchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type DeleteCustomerInvoiceByIdQueryDTO = z.infer<
|
||||||
|
typeof DeleteCustomerInvoiceByIdQuerySchema
|
||||||
|
>;
|
||||||
@ -1,3 +1,4 @@
|
|||||||
export * from "./create-customer-invoice.command.dto";
|
export * from "./create-customer-invoice.command.dto";
|
||||||
export * from "./get-customer-invoice.query.dto";
|
export * from "./delete-customer-invoice-by-id.command.dto";
|
||||||
|
export * from "./get-customer-invoice-by-id.query.dto";
|
||||||
export * from "./list-customer-invoices.query.dto";
|
export * from "./list-customer-invoices.query.dto";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { MetadataSchema } from "@erp/core";
|
import { MetadataSchema } from "@erp/core";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const GetCustomerInvoiceResultSchema = z.object({
|
export const GetCustomerInvoiceByIdResultSchema = z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
invoice_status: z.string(),
|
invoice_status: z.string(),
|
||||||
invoice_number: z.string(),
|
invoice_number: z.string(),
|
||||||
@ -14,4 +14,4 @@ export const GetCustomerInvoiceResultSchema = z.object({
|
|||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetCustomerInvoiceResultDTO = z.infer<typeof GetCustomerInvoiceResultSchema>;
|
export type GetCustomerInvoiceByIdResultDTO = z.infer<typeof GetCustomerInvoiceByIdResultSchema>;
|
||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./customer-invoice-creation.result.dto";
|
export * from "./customer-invoice-creation.result.dto";
|
||||||
export * from "./get-customer-invoice.result.dto";
|
export * from "./get-customer-invoice-by-id.result.dto";
|
||||||
export * from "./list-customer-invoices.result.dto";
|
export * from "./list-customer-invoices.result.dto";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user