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 { DomainValidationError } from "./domain-validation-error";
|
||||
import { DuplicateEntityError } from "./duplicate-entity-error";
|
||||
import { EntityNotFoundError } from "./entity-not-found-error";
|
||||
import { ForbiddenApiError } from "./forbidden-api-error";
|
||||
import { InternalApiError } from "./internal-api-error";
|
||||
import { NotFoundApiError } from "./not-found-api-error";
|
||||
@ -79,6 +80,10 @@ export const errorMapper = {
|
||||
return new ConflictApiError(error.message);
|
||||
}
|
||||
|
||||
if (error instanceof EntityNotFoundError) {
|
||||
return new NotFoundApiError(error.message);
|
||||
}
|
||||
|
||||
// 3. 🔍 Errores individuales de validación
|
||||
if (
|
||||
message.includes("invalid") ||
|
||||
|
||||
@ -2,6 +2,7 @@ export * from "./api-error";
|
||||
export * from "./conflict-api-error";
|
||||
export * from "./domain-validation-error";
|
||||
export * from "./duplicate-entity-error";
|
||||
export * from "./entity-not-found-error";
|
||||
export * from "./error-mapper";
|
||||
export * from "./forbidden-api-error";
|
||||
export * from "./internal-api-error";
|
||||
|
||||
@ -1,24 +1,38 @@
|
||||
import { UniqueID } from "@/core/common/domain";
|
||||
import { ITransactionManager } from "@/core/common/infrastructure/database";
|
||||
import { logger } from "@/core/logger";
|
||||
import { EntityNotFoundError, ITransactionManager } from "@erp/core/api";
|
||||
import { DeleteCustomerInvoiceByIdQueryDTO } from "@erp/customer-invoices/common/dto";
|
||||
import { UniqueID } from "@repo/rdx-ddd";
|
||||
import { Result } from "@repo/rdx-utils";
|
||||
import { ICustomerInvoiceService } from "../domain";
|
||||
import { ICustomerInvoiceService } from "../../domain";
|
||||
|
||||
export class DeleteCustomerInvoiceUseCase {
|
||||
constructor(
|
||||
private readonly customerInvoiceService: ICustomerInvoiceService,
|
||||
private readonly service: ICustomerInvoiceService,
|
||||
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) => {
|
||||
try {
|
||||
return await this.customerInvoiceService.deleteCustomerInvoiceById(
|
||||
customerInvoiceID,
|
||||
transaction
|
||||
);
|
||||
const existsCheck = await this.service.existsById(id, 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) {
|
||||
logger.error(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";
|
||||
|
||||
export interface GetCustomerInvoicePresenter {
|
||||
toDTO: (customerInvoice: CustomerInvoice) => GetCustomerInvoiceResultDTO;
|
||||
toDTO: (customerInvoice: CustomerInvoice) => GetCustomerInvoiceByIdResultDTO;
|
||||
}
|
||||
|
||||
export const getCustomerInvoicePresenter: GetCustomerInvoicePresenter = {
|
||||
toDTO: (customerInvoice: CustomerInvoice): GetCustomerInvoiceResultDTO => ({
|
||||
toDTO: (customerInvoice: CustomerInvoice): GetCustomerInvoiceByIdResultDTO => ({
|
||||
id: customerInvoice.id.toPrimitive(),
|
||||
|
||||
invoice_status: customerInvoice.status.toString(),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export * from "./create-customer-invoice";
|
||||
//export * from "./delete-customer-invoice";
|
||||
export * from "./delete-customer-invoice";
|
||||
export * from "./get-customer-invoice";
|
||||
export * from "./list-customer-invoices";
|
||||
//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 "./delete-customer-invoice";
|
||||
export * from "./delete-customer-invoice";
|
||||
export * from "./get-customer-invoice";
|
||||
export * from "./list-customer-invoices";
|
||||
///export * from "./update-customer-invoice";
|
||||
|
||||
@ -29,5 +29,5 @@ export interface ICustomerInvoiceService {
|
||||
transaction?: any
|
||||
): 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.
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,11 +3,13 @@ import { Application, NextFunction, Request, Response, Router } from "express";
|
||||
import { Sequelize } from "sequelize";
|
||||
import {
|
||||
CreateCustomerInvoiceCommandSchema,
|
||||
GetCustomerInvoiceByIdQuerySchema,
|
||||
DeleteCustomerInvoiceByIdQuerySchema,
|
||||
DeleteCustomerInvoiceByIdQuerySchema as GetCustomerInvoiceByIdQuerySchema,
|
||||
ListCustomerInvoicesQuerySchema,
|
||||
} from "../../../common/dto";
|
||||
import {
|
||||
buildCreateCustomerInvoicesController,
|
||||
buildDeleteCustomerInvoiceController,
|
||||
buildGetCustomerInvoiceController,
|
||||
buildListCustomerInvoicesController,
|
||||
} from "../../controllers";
|
||||
@ -60,17 +62,17 @@ export const customerInvoicesRouter = (params: ModuleParams) => {
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
buildUpdateCustomerInvoiceController().execute(req, res, next);
|
||||
}
|
||||
);
|
||||
);*/
|
||||
|
||||
routes.delete(
|
||||
"/:customerInvoiceId",
|
||||
validateAndParseBody(IDeleteCustomerInvoiceRequestSchema),
|
||||
checkTabContext,
|
||||
"/:id",
|
||||
//checkTabContext,
|
||||
//checkUser,
|
||||
validateRequest(DeleteCustomerInvoiceByIdQuerySchema, "params"),
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
buildDeleteCustomerInvoiceController().execute(req, res, next);
|
||||
buildDeleteCustomerInvoiceController(database).execute(req, res, next);
|
||||
}
|
||||
);*/
|
||||
);
|
||||
|
||||
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 "./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";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { MetadataSchema } from "@erp/core";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
export const GetCustomerInvoiceResultSchema = z.object({
|
||||
export const GetCustomerInvoiceByIdResultSchema = z.object({
|
||||
id: z.uuid(),
|
||||
invoice_status: z.string(),
|
||||
invoice_number: z.string(),
|
||||
@ -14,4 +14,4 @@ export const GetCustomerInvoiceResultSchema = z.object({
|
||||
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 "./get-customer-invoice.result.dto";
|
||||
export * from "./get-customer-invoice-by-id.result.dto";
|
||||
export * from "./list-customer-invoices.result.dto";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user