Facturas de cliente y clientes
This commit is contained in:
parent
d7bce7fb56
commit
78cd1299bf
@ -67,14 +67,5 @@ export function createApp(): Application {
|
|||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Registrar rutas de la API
|
|
||||||
// app.use("/api/v1", v1Routes());
|
|
||||||
//initModules(app, database);
|
|
||||||
|
|
||||||
// Gestión global de errores.
|
|
||||||
// Siempre al final de la cadena de middlewares
|
|
||||||
// y después de las rutas.
|
|
||||||
//app.use(globalErrorHandler);
|
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,7 @@ const serverConnection = (conn: any) => {
|
|||||||
//const sequelizeConn = createSequelizeAdapter();
|
//const sequelizeConn = createSequelizeAdapter();
|
||||||
//const firebirdConn = createFirebirdAdapter();
|
//const firebirdConn = createFirebirdAdapter();
|
||||||
|
|
||||||
// Cargar paquetes de la aplicación
|
// Cargar paquetes de la aplicación: customers, invoices, routes...
|
||||||
registerModules();
|
registerModules();
|
||||||
|
|
||||||
const app = createApp();
|
const app = createApp();
|
||||||
|
|||||||
@ -1 +1,25 @@
|
|||||||
export * from "./v1.routes";
|
export * from "./v1.routes";
|
||||||
|
|
||||||
|
import { Router } from "express";
|
||||||
|
|
||||||
|
export const v1Routes = (): Router => {
|
||||||
|
const routes = Router({ mergeParams: true });
|
||||||
|
|
||||||
|
routes.get("/hello", (req, res) => {
|
||||||
|
res.send("Hello world!");
|
||||||
|
});
|
||||||
|
|
||||||
|
//authRouter(routes);
|
||||||
|
//usersRouter(routes);
|
||||||
|
//accountsRouter(routes);
|
||||||
|
|
||||||
|
// Sales
|
||||||
|
//invoicesRouter(routes);
|
||||||
|
|
||||||
|
return routes;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gestión global de errores.
|
||||||
|
// Siempre al final de la cadena de middlewares
|
||||||
|
// y después de las rutas.
|
||||||
|
//app.use(globalErrorHandler);
|
||||||
|
|||||||
@ -1,63 +0,0 @@
|
|||||||
import { getDatabase } from "@/config";
|
|
||||||
|
|
||||||
import {
|
|
||||||
buildGetInvoiceController,
|
|
||||||
buildListInvoicesController,
|
|
||||||
} from "@/contexts/invoices/presentation";
|
|
||||||
import { NextFunction, Request, Response, Router } from "express";
|
|
||||||
|
|
||||||
export const invoicesRouter = (appRouter: Router) => {
|
|
||||||
const routes: Router = Router({ mergeParams: true });
|
|
||||||
const database = getDatabase();
|
|
||||||
|
|
||||||
routes.get(
|
|
||||||
"/",
|
|
||||||
//checkTabContext,
|
|
||||||
//checkUser,
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
buildListInvoicesController(database).execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
routes.get(
|
|
||||||
"/:invoiceId",
|
|
||||||
//checkTabContext,
|
|
||||||
//checkUser,
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
buildGetInvoiceController(database).execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/*routes.post(
|
|
||||||
"/",
|
|
||||||
validateAndParseBody(ICreateInvoiceRequestSchema, { sanitize: false }),
|
|
||||||
//checkTabContext,
|
|
||||||
//checkUser,
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
buildCreateInvoiceController(database).execute(req, res, next);
|
|
||||||
}
|
|
||||||
);*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
routes.put(
|
|
||||||
"/:invoiceId",
|
|
||||||
validateAndParseBody(IUpdateInvoiceRequestSchema),
|
|
||||||
checkTabContext,
|
|
||||||
//checkUser,
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
buildUpdateInvoiceController().execute(req, res, next);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
routes.delete(
|
|
||||||
"/:invoiceId",
|
|
||||||
validateAndParseBody(IDeleteInvoiceRequestSchema),
|
|
||||||
checkTabContext,
|
|
||||||
//checkUser,
|
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
|
||||||
buildDeleteInvoiceController().execute(req, res, next);
|
|
||||||
}
|
|
||||||
);*/
|
|
||||||
|
|
||||||
appRouter.use("/invoices", routes);
|
|
||||||
};
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
// src/common/middlewares/validate-dto.ts
|
// src/common/middlewares/validate-dto.ts
|
||||||
import { ExpressController, ValidationApiError } from "@erp/core/api";
|
import { ExpressController, InternalApiError, ValidationApiError } from "@erp/core/api";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ZodSchema } from "zod/v4";
|
import { ZodSchema } from "zod/v4";
|
||||||
|
|
||||||
@ -42,28 +42,41 @@ export const validateRequest = <T extends "body" | "query" | "params">(
|
|||||||
return async (req, res, next) => {
|
return async (req, res, next) => {
|
||||||
console.debug(`Validating request ${source} with schema.`);
|
console.debug(`Validating request ${source} with schema.`);
|
||||||
console.debug(req[source]);
|
console.debug(req[source]);
|
||||||
const result = schema.safeParse(req[source]);
|
|
||||||
|
|
||||||
if (!result.success) {
|
if (!schema) {
|
||||||
// Construye errores detallados
|
console.debug("ERROR: Undefined schema!!");
|
||||||
const validationErrors = result.error.issues.map((err) => ({
|
return ExpressController.errorResponse(new InternalApiError("Undefined schema"), res);
|
||||||
field: err.path.join("."),
|
|
||||||
message: err.message,
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.debug(validationErrors);
|
|
||||||
|
|
||||||
return ExpressController.errorResponse(
|
|
||||||
new ValidationApiError("Validation failed", validationErrors),
|
|
||||||
res
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si pasa la validación, opcionalmente reescribe req.body
|
try {
|
||||||
if (options?.sanitize ?? true) {
|
const result = schema.safeParse(req[source]);
|
||||||
req[source] = result.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
if (!result.success) {
|
||||||
|
// Construye errores detallados
|
||||||
|
const validationErrors = result.error.issues.map((err) => ({
|
||||||
|
field: err.path.join("."),
|
||||||
|
message: err.message,
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.debug(validationErrors);
|
||||||
|
|
||||||
|
return ExpressController.errorResponse(
|
||||||
|
new ValidationApiError("Validation failed", validationErrors),
|
||||||
|
res
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si pasa la validación, opcionalmente reescribe req.body
|
||||||
|
if (options?.sanitize ?? true) {
|
||||||
|
req[source] = result.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
|
} catch (err) {
|
||||||
|
const error = err as Error;
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
return ExpressController.errorResponse(new InternalApiError(error.message), res);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export * from "./critera.dto";
|
export * from "./critera.dto";
|
||||||
export * from "./error.dto";
|
export * from "./error.dto";
|
||||||
export * from "./list.view.dto";
|
export * from "./list-view.response.dto";
|
||||||
export * from "./metadata.dto";
|
export * from "./metadata.dto";
|
||||||
export * from "./money.dto";
|
export * from "./money.dto";
|
||||||
export * from "./percentage.dto";
|
export * from "./percentage.dto";
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { MetadataSchema } from "./metadata.dto";
|
|||||||
* @param itemSchema Esquema Zod del elemento T
|
* @param itemSchema Esquema Zod del elemento T
|
||||||
* @returns Zod schema para ListViewDTO<T>
|
* @returns Zod schema para ListViewDTO<T>
|
||||||
*/
|
*/
|
||||||
export const createListViewResultSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>
|
export const createListViewResponseSchema = <T extends z.ZodTypeAny>(itemSchema: T) =>
|
||||||
z.object({
|
z.object({
|
||||||
page: z.number().int().min(1, "Page must be a positive integer"),
|
page: z.number().int().min(1, "Page must be a positive integer"),
|
||||||
per_page: z.number().int().min(1, "Items per page must be a positive integer"),
|
per_page: z.number().int().min(1, "Items per page must be a positive integer"),
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { ITransactionManager } from "@erp/core/api";
|
import { ITransactionManager } from "@erp/core/api";
|
||||||
import { ListCustomerInvoicesResultDTO } from "@erp/customer-invoices/common/dto";
|
import { CustomerInvoiceListResponseDTO } from "@erp/customer-invoices/common/dto";
|
||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import { Criteria } from "@repo/rdx-criteria/server";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { Transaction } from "sequelize";
|
import { Transaction } from "sequelize";
|
||||||
@ -13,7 +13,7 @@ export class ListCustomerInvoicesUseCase {
|
|||||||
private readonly presenter: ListCustomerInvoicesPresenter
|
private readonly presenter: ListCustomerInvoicesPresenter
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public execute(criteria: Criteria): Promise<Result<ListCustomerInvoicesResultDTO, Error>> {
|
public execute(criteria: Criteria): Promise<Result<CustomerInvoiceListResponseDTO, Error>> {
|
||||||
return this.transactionManager.complete(async (transaction: Transaction) => {
|
return this.transactionManager.complete(async (transaction: Transaction) => {
|
||||||
try {
|
try {
|
||||||
const result = await this.customerInvoiceService.findByCriteria(criteria, transaction);
|
const result = await this.customerInvoiceService.findByCriteria(criteria, transaction);
|
||||||
@ -22,7 +22,7 @@ export class ListCustomerInvoicesUseCase {
|
|||||||
return Result.fail(result.error);
|
return Result.fail(result.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const dto: ListCustomerInvoicesResultDTO = this.presenter.toDTO(result.data, criteria);
|
const dto: CustomerInvoiceListResponseDTO = this.presenter.toDTO(result.data, criteria);
|
||||||
return Result.ok(dto);
|
return Result.ok(dto);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
return Result.fail(error as Error);
|
return Result.fail(error as Error);
|
||||||
|
|||||||
@ -1,20 +1,20 @@
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import { Criteria } from "@repo/rdx-criteria/server";
|
||||||
import { Collection } from "@repo/rdx-utils";
|
import { Collection } from "@repo/rdx-utils";
|
||||||
import { ListCustomerInvoicesResultDTO } from "../../../../common/dto";
|
import { CustomerInvoiceListResponseDTO } from "../../../../common/dto";
|
||||||
import { CustomerInvoice } from "../../../domain";
|
import { CustomerInvoice } from "../../../domain";
|
||||||
|
|
||||||
export interface ListCustomerInvoicesPresenter {
|
export interface ListCustomerInvoicesPresenter {
|
||||||
toDTO: (
|
toDTO: (
|
||||||
customerInvoices: Collection<CustomerInvoice>,
|
customerInvoices: Collection<CustomerInvoice>,
|
||||||
criteria: Criteria
|
criteria: Criteria
|
||||||
) => ListCustomerInvoicesResultDTO;
|
) => CustomerInvoiceListResponseDTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const listCustomerInvoicesPresenter: ListCustomerInvoicesPresenter = {
|
export const listCustomerInvoicesPresenter: ListCustomerInvoicesPresenter = {
|
||||||
toDTO: (
|
toDTO: (
|
||||||
customerInvoices: Collection<CustomerInvoice>,
|
customerInvoices: Collection<CustomerInvoice>,
|
||||||
criteria: Criteria
|
criteria: Criteria
|
||||||
): ListCustomerInvoicesResultDTO => {
|
): CustomerInvoiceListResponseDTO => {
|
||||||
const items = customerInvoices.map((invoice) => {
|
const items = customerInvoices.map((invoice) => {
|
||||||
return {
|
return {
|
||||||
id: invoice.id.toPrimitive(),
|
id: invoice.id.toPrimitive(),
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { Application, NextFunction, Request, Response, Router } from "express";
|
|||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import {
|
import {
|
||||||
CreateCustomerInvoiceCommandSchema,
|
CreateCustomerInvoiceCommandSchema,
|
||||||
|
CustomerInvoiceListRequestSchema,
|
||||||
DeleteCustomerInvoiceByIdQuerySchema,
|
DeleteCustomerInvoiceByIdQuerySchema,
|
||||||
DeleteCustomerInvoiceByIdQuerySchema as GetCustomerInvoiceByIdQuerySchema,
|
DeleteCustomerInvoiceByIdQuerySchema as GetCustomerInvoiceByIdQuerySchema,
|
||||||
} from "../../../common/dto";
|
} from "../../../common/dto";
|
||||||
@ -27,7 +28,7 @@ export const customerInvoicesRouter = (params: ModuleParams) => {
|
|||||||
"/",
|
"/",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
//checkUser,
|
//checkUser,
|
||||||
validateRequest(CustomerInvoiceListCriteriaSchema, "params"),
|
validateRequest(CustomerInvoiceListRequestSchema, "params"),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildListCustomerInvoicesController(database).execute(req, res, next);
|
buildListCustomerInvoicesController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,24 +0,0 @@
|
|||||||
export interface IUpdateCustomerInvoiceRequestDTO {
|
|
||||||
is_freelancer: boolean;
|
|
||||||
name: string;
|
|
||||||
trade_name: string;
|
|
||||||
tin: string;
|
|
||||||
|
|
||||||
street: string;
|
|
||||||
city: string;
|
|
||||||
state: string;
|
|
||||||
postal_code: string;
|
|
||||||
country: string;
|
|
||||||
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
fax: string;
|
|
||||||
website: string;
|
|
||||||
|
|
||||||
legal_record: string;
|
|
||||||
|
|
||||||
default_tax: number;
|
|
||||||
lang_code: string;
|
|
||||||
currency_code: string;
|
|
||||||
logo: string;
|
|
||||||
}
|
|
||||||
@ -1,80 +0,0 @@
|
|||||||
import { IMetadataDTO, IMoneyDTO, IQuantityDTO } from "@erp/core";
|
|
||||||
|
|
||||||
export interface IListCustomerInvoicesResponseDTO {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
invoice_status: string;
|
|
||||||
invoice_number: string;
|
|
||||||
invoice_series: string;
|
|
||||||
issue_date: string;
|
|
||||||
operation_date: string;
|
|
||||||
language_code: string;
|
|
||||||
currency: string;
|
|
||||||
|
|
||||||
subtotal: IMoneyDTO;
|
|
||||||
total: IMoneyDTO;
|
|
||||||
|
|
||||||
metadata?: IMetadataDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IGetCustomerInvoiceResponseDTO {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
invoice_status: string;
|
|
||||||
invoice_number: string;
|
|
||||||
invoice_series: string;
|
|
||||||
issue_date: string;
|
|
||||||
operation_date: string;
|
|
||||||
language_code: string;
|
|
||||||
currency: string;
|
|
||||||
|
|
||||||
subtotal: IMoneyDTO;
|
|
||||||
total: IMoneyDTO;
|
|
||||||
|
|
||||||
items: {
|
|
||||||
description: string;
|
|
||||||
quantity: IQuantityDTO;
|
|
||||||
unit_measure: string;
|
|
||||||
unit_price: IMoneyDTO;
|
|
||||||
subtotal: IMoneyDTO;
|
|
||||||
//tax_amount: IMoneyDTO;
|
|
||||||
total: IMoneyDTO;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
//customer:
|
|
||||||
|
|
||||||
metadata?: IMetadataDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICreateCustomerInvoiceResponseDTO {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
invoice_status: string;
|
|
||||||
invoice_number: string;
|
|
||||||
invoice_series: string;
|
|
||||||
issue_date: string;
|
|
||||||
operation_date: string;
|
|
||||||
language_code: string;
|
|
||||||
currency: string;
|
|
||||||
|
|
||||||
subtotal: IMoneyDTO;
|
|
||||||
total: IMoneyDTO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inferir el tipo en TypeScript desde el esquema Zod
|
|
||||||
//export type IUpdateAcccountResponseDTO = z.infer<typeof IUpdateAcccountResponseDTOSchema>;
|
|
||||||
|
|
||||||
export interface IUpdateCustomerInvoiceResponseDTO {
|
|
||||||
id: string;
|
|
||||||
|
|
||||||
invoice_status: string;
|
|
||||||
invoice_number: string;
|
|
||||||
invoice_series: string;
|
|
||||||
issue_date: string;
|
|
||||||
operation_date: string;
|
|
||||||
language_code: string;
|
|
||||||
currency: string;
|
|
||||||
|
|
||||||
subtotal: IMoneyDTO;
|
|
||||||
total: IMoneyDTO;
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
import * as z from "zod/v4";
|
|
||||||
|
|
||||||
export const ICreateCustomerInvoiceRequestSchema = z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
customerInvoice_number: z.string().min(1),
|
|
||||||
customerInvoice_series: z.string().min(1),
|
|
||||||
issue_date: z.string().refine((date) => {
|
|
||||||
const dateStr = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid YYYY-MM-DD format");
|
|
||||||
return dateStr.safeParse(date).success;
|
|
||||||
}),
|
|
||||||
operation_date: z.string().refine((date) => {
|
|
||||||
const dateStr = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid YYYY-MM-DD format");
|
|
||||||
return dateStr.safeParse(date).success;
|
|
||||||
}),
|
|
||||||
//customerId: z.string().uuid(),
|
|
||||||
lang_code: z.string().min(1),
|
|
||||||
currency_code: z.string().min(1),
|
|
||||||
|
|
||||||
items: z
|
|
||||||
.array(
|
|
||||||
z.object({
|
|
||||||
//id: z.string().uuid(),
|
|
||||||
description: z.string().optional(),
|
|
||||||
unit_price: z
|
|
||||||
.object({
|
|
||||||
amount: z.number().positive(),
|
|
||||||
scale: z.number().positive(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
quantity: z
|
|
||||||
.object({
|
|
||||||
amount: z.number().positive(),
|
|
||||||
scale: z.number().positive(),
|
|
||||||
})
|
|
||||||
.optional(),
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.optional(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const IUpdateCustomerInvoiceRequestSchema = z.object({});
|
|
||||||
|
|
||||||
export const IDeleteCustomerInvoiceRequestSchema = z.object({});
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const CreateCustomerInvoiceCommandSchema = z.object({
|
export const CreateCustomerInvoiceRequestSchema = z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
invoice_status: z.string(),
|
invoice_status: z.string(),
|
||||||
invoice_number: z.string().min(1, "Customer invoice number is required"),
|
invoice_number: z.string().min(1, "Customer invoice number is required"),
|
||||||
@ -33,4 +33,4 @@ export const CreateCustomerInvoiceCommandSchema = z.object({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CreateCustomerInvoiceCommandDTO = z.infer<typeof CreateCustomerInvoiceCommandSchema>;
|
export type CreateCustomerInvoiceRequestDTO = z.infer<typeof CreateCustomerInvoiceRequestSchema>;
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { CriteriaSchema } from "@erp/core";
|
||||||
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
|
export const CustomerInvoiceListRequestSchema = CriteriaSchema;
|
||||||
|
export type CustomerInvoiceListRequestDTO = z.infer<typeof CustomerInvoiceListRequestSchema>;
|
||||||
@ -6,10 +6,8 @@ import * as z from "zod/v4";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const DeleteCustomerInvoiceByIdQuerySchema = z.object({
|
export const DeleteCustomerByIdRequestSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type DeleteCustomerInvoiceByIdQueryDTO = z.infer<
|
export type DeleteCustomerByIdRequestDTO = z.infer<typeof DeleteCustomerByIdRequestSchema>;
|
||||||
typeof DeleteCustomerInvoiceByIdQuerySchema
|
|
||||||
>;
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
import * as z from "zod/v4";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Este DTO es utilizado por el endpoint:
|
|
||||||
* `GET /customer-invoices/:id` (consultar una factura por ID).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const GetCustomerInvoiceByIdQuerySchema = z.object({
|
|
||||||
id: z.string(),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type GetCustomerInvoiceByIdQueryDTO = z.infer<typeof GetCustomerInvoiceByIdQuerySchema>;
|
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
|
export const GetCustomerInvoiceByIdRequestSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type GetCustomerInvoiceByIdRequestDTO = z.infer<typeof GetCustomerInvoiceByIdRequestSchema>;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
export * from "./create-customer-invoice.command.dto";
|
export * from "./create-customer-invoice.request.dto";
|
||||||
export * from "./delete-customer-invoice-by-id.command.dto";
|
export * from "./customer-invoices-list.request.dto";
|
||||||
export * from "./get-customer-invoice-by-id.query.dto";
|
export * from "./delete-customer-invoice-by-id.request.dto";
|
||||||
export * from "./list-customer-invoices.query.dto";
|
export * from "./get-customer-invoice-by-id.request.dto";
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
import * as z from "zod/v4";
|
|
||||||
|
|
||||||
import { criteriaSchema } from "@erp/core/criteria"; // El esquema genérico validado antes
|
|
||||||
|
|
||||||
export const CustomerInvoiceListCriteriaSchema = criteriaSchema;
|
|
||||||
export type CustomerInvoiceListCriteria = z.infer<typeof CustomerInvoiceListCriteriaSchema>;
|
|
||||||
|
|
||||||
export type ListCustomerInvoicesQueryDTO = z.infer<typeof ListCustomerInvoicesQuerySchema>;
|
|
||||||
@ -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 GetCustomerInvoiceByIdResultSchema = z.object({
|
export const CustomerInvoicesCreationResponseSchema = 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,6 @@ export const GetCustomerInvoiceByIdResultSchema = z.object({
|
|||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetCustomerInvoiceByIdResultDTO = z.infer<typeof GetCustomerInvoiceByIdResultSchema>;
|
export type CustomerInvoicesCreationResponseDTO = z.infer<
|
||||||
|
typeof CustomerInvoicesCreationResponseSchema
|
||||||
|
>;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { MetadataSchema, createListViewResultSchema } from "@erp/core";
|
import { MetadataSchema, createListViewResponseSchema } from "@erp/core";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const ListCustomerInvoicesResultSchema = createListViewResultSchema(
|
export const CustomerInvoiceListResponseSchema = createListViewResponseSchema(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
invoice_status: z.string(),
|
invoice_status: z.string(),
|
||||||
@ -28,4 +28,4 @@ export const ListCustomerInvoicesResultSchema = createListViewResultSchema(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export type ListCustomerInvoicesResultDTO = z.infer<typeof ListCustomerInvoicesResultSchema>;
|
export type CustomerInvoiceListResponseDTO = z.infer<typeof CustomerInvoiceListResponseSchema>;
|
||||||
@ -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 CustomerInvoicesCreationResultSchema = z.object({
|
export const GetCustomerInvoiceByIdResponseSchema = 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,6 +14,6 @@ export const CustomerInvoicesCreationResultSchema = z.object({
|
|||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CustomerInvoicesCreationResultDTO = z.infer<
|
export type GetCustomerInvoiceByIdResponseDTO = z.infer<
|
||||||
typeof CustomerInvoicesCreationResultSchema
|
typeof GetCustomerInvoiceByIdResponseSchema
|
||||||
>;
|
>;
|
||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./customer-invoice-creation.result.dto";
|
export * from "./customer-invoice-creation.response.dto";
|
||||||
export * from "./get-customer-invoice-by-id.result.dto";
|
export * from "./customer-invoices-list.response.dto";
|
||||||
export * from "./list-customer-invoices.result.dto";
|
export * from "./get-customer-invoice-by-id.response.dto";
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
import { useDataSource, useQueryKey } from "@erp/core/client";
|
import { useDataSource, useQueryKey } from "@erp/core/client";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { ListCustomerInvoicesResultDTO } from "../../common/dto";
|
import { CustomerInvoiceListResponseDTO } from "../../common/dto";
|
||||||
|
|
||||||
// Obtener todas las facturas
|
// Obtener todas las facturas
|
||||||
export const useCustomerInvoicesQuery = (params: any) => {
|
export const useCustomerInvoicesQuery = (params: any) => {
|
||||||
const dataSource = useDataSource();
|
const dataSource = useDataSource();
|
||||||
const keys = useQueryKey();
|
const keys = useQueryKey();
|
||||||
|
|
||||||
return useQuery<ListCustomerInvoicesResultDTO>({
|
return useQuery<CustomerInvoiceListResponseDTO>({
|
||||||
queryKey: keys().data().resource("customer-invoices").action("list").params(params).get(),
|
queryKey: keys().data().resource("customer-invoices").action("list").params(params).get(),
|
||||||
queryFn: (context) => {
|
queryFn: (context) => {
|
||||||
console.log(dataSource.getBaseUrl());
|
console.log(dataSource.getBaseUrl());
|
||||||
const { signal } = context;
|
const { signal } = context;
|
||||||
return dataSource.getList<ListCustomerInvoicesResultDTO>("customer-invoices", {
|
return dataSource.getList<CustomerInvoiceListResponseDTO>("customer-invoices", {
|
||||||
signal,
|
signal,
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -2,13 +2,13 @@ import { SequelizeTransactionManager } from "@erp/core/api";
|
|||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import { GetCustomerUseCase, getCustomerPresenter } from "../../application";
|
import { GetCustomerUseCase, getCustomerPresenter } from "../../application";
|
||||||
import { CustomerService } from "../../domain";
|
import { CustomerService } from "../../domain";
|
||||||
import { customerMapper } from "../../infrastructure";
|
import { CustomerRepository, customerMapper } from "../../infrastructure";
|
||||||
import { GetCustomerController } from "./get-invoice.controller";
|
import { GetCustomerController } from "./get-invoice.controller";
|
||||||
|
|
||||||
export const buildGetCustomerController = (database: Sequelize) => {
|
export const buildGetCustomerController = (database: Sequelize) => {
|
||||||
const transactionManager = new SequelizeTransactionManager(database);
|
const transactionManager = new SequelizeTransactionManager(database);
|
||||||
const repository = new CustomerRepository(database, customerMapper);
|
const repository = new CustomerRepository(database, customerMapper);
|
||||||
const customerService = new CustomerService(customerRepository);
|
const customerService = new CustomerService(repository);
|
||||||
const presenter = getCustomerPresenter;
|
const presenter = getCustomerPresenter;
|
||||||
|
|
||||||
const useCase = new GetCustomerUseCase(customerService, transactionManager, presenter);
|
const useCase = new GetCustomerUseCase(customerService, transactionManager, presenter);
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
import { IModuleServer, ModuleParams } from "@erp/core/api";
|
||||||
import { customersRouter, models } from "./infrastructure";
|
import { customersRouter, models } from "./infrastructure";
|
||||||
//import { customersRouter, models } from "./infrastructure";
|
|
||||||
|
|
||||||
export const customersAPIModule: IModuleServer = {
|
export const customersAPIModule: IModuleServer = {
|
||||||
name: "customers",
|
name: "customers",
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import { ILogger, ModuleParams, validateRequest } from "@erp/core/api";
|
|||||||
import { Application, NextFunction, Request, Response, Router } from "express";
|
import { Application, NextFunction, Request, Response, Router } from "express";
|
||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import {
|
import {
|
||||||
CreateCustomerCommandSchema,
|
CreateCustomerRequestSchema,
|
||||||
CustomerListCriteriaSchema,
|
CustomerListRequestSchema,
|
||||||
DeleteCustomerByIdQuerySchema,
|
DeleteCustomerByIdRequestSchema,
|
||||||
GetCustomerByIdQuerySchema,
|
GetCustomerByIdRequestSchema,
|
||||||
} from "../../../common/dto";
|
} from "../../../common/dto";
|
||||||
import {
|
import {
|
||||||
buildCreateCustomersController,
|
buildCreateCustomersController,
|
||||||
@ -28,7 +28,7 @@ export const customersRouter = (params: ModuleParams) => {
|
|||||||
"/",
|
"/",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
//checkUser,
|
//checkUser,
|
||||||
validateRequest(CustomerListCriteriaSchema, "params"),
|
validateRequest(CustomerListRequestSchema, "params"),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildListCustomersController(database).execute(req, res, next);
|
buildListCustomersController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ export const customersRouter = (params: ModuleParams) => {
|
|||||||
"/:id",
|
"/:id",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
//checkUser,
|
//checkUser,
|
||||||
validateRequest(GetCustomerByIdQuerySchema, "params"),
|
validateRequest(GetCustomerByIdRequestSchema, "params"),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildGetCustomerController(database).execute(req, res, next);
|
buildGetCustomerController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
@ -48,7 +48,7 @@ export const customersRouter = (params: ModuleParams) => {
|
|||||||
"/",
|
"/",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
//checkUser,
|
//checkUser,
|
||||||
validateRequest(CreateCustomerCommandSchema),
|
validateRequest(CreateCustomerRequestSchema),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildCreateCustomersController(database).execute(req, res, next);
|
buildCreateCustomersController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ export const customersRouter = (params: ModuleParams) => {
|
|||||||
"/:id",
|
"/:id",
|
||||||
//checkTabContext,
|
//checkTabContext,
|
||||||
//checkUser,
|
//checkUser,
|
||||||
validateRequest(DeleteCustomerByIdQuerySchema, "params"),
|
validateRequest(DeleteCustomerByIdRequestSchema, "params"),
|
||||||
(req: Request, res: Response, next: NextFunction) => {
|
(req: Request, res: Response, next: NextFunction) => {
|
||||||
buildDeleteCustomerController(database).execute(req, res, next);
|
buildDeleteCustomerController(database).execute(req, res, next);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const CreateCustomerCommandSchema = z.object({
|
export const CreateCustomerRequestSchema = z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
invoice_status: z.string(),
|
invoice_status: z.string(),
|
||||||
invoice_number: z.string().min(1, "Customer invoice number is required"),
|
invoice_number: z.string().min(1, "Customer invoice number is required"),
|
||||||
@ -33,4 +33,4 @@ export const CreateCustomerCommandSchema = z.object({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CreateCustomerCommandDTO = z.infer<typeof CreateCustomerCommandSchema>;
|
export type CreateCustomerRequestDTO = z.infer<typeof CreateCustomerRequestSchema>;
|
||||||
@ -1,33 +0,0 @@
|
|||||||
import * as z from "zod/v4";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DTO que transporta los parámetros de la consulta (paginación, filtros, etc.)
|
|
||||||
* para la búsqueda de facturas de cliente.
|
|
||||||
*
|
|
||||||
* Este DTO es utilizado por el endpoint:
|
|
||||||
* `GET /customers` (listado / búsqueda de facturas).
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const CustomerListCriteriaSchema = z.object({
|
|
||||||
page: z.number().int().min(1).default(1),
|
|
||||||
pageSize: z.number().int().min(1).max(100).default(25),
|
|
||||||
fromDate: z
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.refine((val) => !val || !Number.isNaN(Date.parse(val)), {
|
|
||||||
message: "Invalid date format for fromDate",
|
|
||||||
}),
|
|
||||||
toDate: z
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.refine((val) => !val || !Number.isNaN(Date.parse(val)), {
|
|
||||||
message: "Invalid date format for toDate",
|
|
||||||
}),
|
|
||||||
status: z.enum(["DRAFT", "POSTED", "PAID", "CANCELLED"]).default("DRAFT"),
|
|
||||||
customerId: z.string().optional(),
|
|
||||||
sortBy: z.enum(["issueDate", "totalAmount", "number"]).default("issueDate"),
|
|
||||||
sortDir: z.enum(["ASC", "DESC"]).default("DESC"),
|
|
||||||
});
|
|
||||||
|
|
||||||
export type ListCustomersQueryDTO = z.infer<typeof CustomerListCriteriaSchema>;
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
import { CriteriaSchema } from "@erp/core";
|
||||||
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
|
export const CustomerListRequestSchema = CriteriaSchema;
|
||||||
|
export type CustomerListRequestDTO = z.infer<typeof CustomerListRequestSchema>;
|
||||||
@ -6,8 +6,8 @@ import * as z from "zod/v4";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const DeleteCustomerByIdParamsSchema = z.object({
|
export const DeleteCustomerByIdRequestSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type DeleteCustomerByIdParamsDTO = z.infer<typeof DeleteCustomerByIdParamsSchema>;
|
export type DeleteCustomerByIdRequestDTO = z.infer<typeof DeleteCustomerByIdRequestSchema>;
|
||||||
@ -6,8 +6,8 @@ import * as z from "zod/v4";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const GetCustomerByIdParamsSchema = z.object({
|
export const GetCustomerByIdRequestSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetCustomerByIdParamsDTO = z.infer<typeof GetCustomerByIdParamsSchema>;
|
export type GetCustomerByIdRequestDTO = z.infer<typeof GetCustomerByIdRequestSchema>;
|
||||||
@ -1 +1,5 @@
|
|||||||
export * from "./list-customers.query.dto";
|
export * from "./create-customer.request.dto";
|
||||||
|
export * from "./customer-list.request.dto";
|
||||||
|
export * from "./delete-customer-by-id.request.dto";
|
||||||
|
export * from "./get-customer-by-id.request.dto";
|
||||||
|
export * from "./update-customer.request.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 GetCustomerByIdResultSchema = z.object({
|
export const CustomerCreationResponseSchema = 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 GetCustomerByIdResultSchema = z.object({
|
|||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetCustomerByIdResultDTO = z.infer<typeof GetCustomerByIdResultSchema>;
|
export type CustomerCreationResponseDTO = z.infer<typeof CustomerCreationResponseSchema>;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { MetadataSchema, createListViewResultSchema } from "@erp/core";
|
import { MetadataSchema, createListViewResponseSchema } from "@erp/core";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const CustomerListResponseSchema = createListViewResultSchema(
|
export const CustomerListResponseSchema = createListViewResponseSchema(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
reference: z.string(),
|
reference: z.string(),
|
||||||
|
|||||||
@ -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 CustomerCreatedResponseSchema = z.object({
|
export const GetCustomerByIdResponseSchema = 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 CustomerCreatedResponseSchema = z.object({
|
|||||||
metadata: MetadataSchema.optional(),
|
metadata: MetadataSchema.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CustomerCreatedResponseDTO = z.infer<typeof CustomerCreatedResponseSchema>;
|
export type GetCustomerByIdResponseDTO = z.infer<typeof GetCustomerByIdResponseSchema>;
|
||||||
@ -1 +1,3 @@
|
|||||||
|
export * from "./customer-creation.result.dto";
|
||||||
export * from "./customer-list.response.dto";
|
export * from "./customer-list.response.dto";
|
||||||
|
export * from "./get-customer-by-id.response.dto";
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user