Docs orders
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ConsumeMessage } from "amqplib";
|
||||
import { Request, Response } from "express"
|
||||
import { SimNosUsecases } from "./SimNOS.usecases.js";
|
||||
import { SimAlaiUsecases } from "./SimAlai.usecases.js";
|
||||
import { EventBus } from "sim-shared/domain/EventBus.port.js";
|
||||
import { Result } from "sim-shared/domain/Result.js";
|
||||
import { SimEvents } from "sim-shared/domain/SimEvents.js";
|
||||
@@ -9,7 +9,7 @@ import { iccidValidator } from "./httpValidators.js";
|
||||
export class SimAlaiController {
|
||||
|
||||
constructor(
|
||||
private uscases: SimNosUsecases,
|
||||
private uscases: SimAlaiUsecases,
|
||||
private eventBus: EventBus,
|
||||
) {
|
||||
}
|
||||
@@ -51,12 +51,12 @@ export class SimAlaiController {
|
||||
await this.eventBus.ack(msg)
|
||||
return result
|
||||
} else {
|
||||
console.error("Error procesando el caso de uso (NOS)", result.error)
|
||||
console.error("Error procesando el caso de uso (Alai)", result.error)
|
||||
this.eventBus.nack(msg)
|
||||
return result
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Error general procesando el caso de uso (NOS)")
|
||||
console.error("Error general procesando el caso de uso (Alai)")
|
||||
this.eventBus.nack(msg)
|
||||
return {
|
||||
error: String(e)
|
||||
|
||||
Binary file not shown.
0
packages/sim-entrada-eventos/README.md
Normal file
0
packages/sim-entrada-eventos/README.md
Normal file
@@ -32,14 +32,23 @@ export class OrderController {
|
||||
}
|
||||
|
||||
public getByQueueId() {
|
||||
return this.controllerGenerator<{ correlation_id: string }, { correlation_id: string }>({
|
||||
return this.controllerGenerator<{ uuid: string }, { correlation_id: string }>({
|
||||
validator: uuidValidator,
|
||||
mapBody: (e) => ({ correlation_id: e.uuid }),
|
||||
useCase: this.orderUseCases.getByQueueId(),
|
||||
onError: (data, error) => { console.error(error) },
|
||||
onSuccess: (data) => console.log(data)
|
||||
})
|
||||
}
|
||||
|
||||
public getByQuery() {
|
||||
return this.controllerGenerator({
|
||||
validator: undefined,
|
||||
useCase: this.orderUseCases.getByQuery(),
|
||||
onError: (data, error) => { console.error(error) },
|
||||
onSuccess: (data) => console.log(data)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
@@ -77,7 +86,7 @@ export class OrderController {
|
||||
})
|
||||
}
|
||||
|
||||
// 2. Transformacion del body
|
||||
// 2. Transformacion del body O => P
|
||||
let data: P = body;
|
||||
try {
|
||||
if (args.mapBody != undefined)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PaginationArgs } from "#domain/common.js";
|
||||
import { OrderQuery } from "sim-shared/domain/Order.js";
|
||||
import { OrderRepository } from "sim-shared/infrastructure/OrderRepository.js";
|
||||
|
||||
|
||||
@@ -36,4 +37,10 @@ export class OrderUsecases {
|
||||
}
|
||||
}
|
||||
|
||||
// WIP
|
||||
public getByQuery() {
|
||||
return async (args: OrderQuery) => {
|
||||
return await this.orderRepository.getOrdersByQuery(args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@ const offerExists = <Validator<{ offer: string }>>{
|
||||
validationFunc: (a: { offer: string }) => offers.has(a.offer),
|
||||
}
|
||||
|
||||
const isUuidv7 = <Validator<{ correlation_id?: string }>>{
|
||||
field: "correlation_id",
|
||||
const isUuidv7 = <Validator<{ uuid?: string }>>{
|
||||
field: "uuid",
|
||||
errorMsg: "El uuid no es un uuidv7 valido",
|
||||
validationFunc: (a) => a.correlation_id != undefined && a.correlation_id.length < 36
|
||||
validationFunc: (a) => a.uuid != undefined && a.uuid.length < 36
|
||||
}
|
||||
|
||||
const definedId = <Validator<{ id?: number }>>{
|
||||
@@ -73,7 +73,7 @@ export const iccidValidator = new BodyValidator<{ iccid: string }>(
|
||||
]
|
||||
)
|
||||
|
||||
export const uuidValidator = new BodyValidator<{ correlation_id?: string }>([
|
||||
export const uuidValidator = new BodyValidator<{ uuid?: string }>([
|
||||
isUuidv7
|
||||
])
|
||||
|
||||
|
||||
@@ -28,13 +28,17 @@ const orderController = new OrderController({
|
||||
* */
|
||||
orderRoutes.get("/", (req, res) => { res.send("ok") })
|
||||
|
||||
orderRoutes.get("/message_id/:correlation_id", orderController.getByQueueId())
|
||||
/*
|
||||
* Ahora es el id de bdd
|
||||
* */
|
||||
orderRoutes.get("/message_id/:id", orderController.getById())
|
||||
|
||||
/** Operaciones pendientes */
|
||||
orderRoutes.get("/pending", orderController.getPending())
|
||||
|
||||
/** Order por id (uuid del mensaje) */
|
||||
orderRoutes.get("/:id", orderController.getById())
|
||||
// TODO: falla
|
||||
orderRoutes.get("/:id", orderController.getByQueueId())
|
||||
|
||||
export { orderRoutes }
|
||||
|
||||
|
||||
@@ -9,8 +9,7 @@ export const connectionsRoutes = Router()
|
||||
const CONNECTIONS_URL = env.CONNECTIONS_URL// TODO: Meter al ENV
|
||||
//const CONNECTIONS_URL = "http://sf-nfc-server.savefamilygps.net"
|
||||
|
||||
console.log("CONNURL: ", CONNECTIONS_URL)
|
||||
|
||||
//console.log("CONNURL: ", CONNECTIONS_URL)
|
||||
connectionsRoutes.use("", createProxyMiddleware({
|
||||
target: CONNECTIONS_URL,
|
||||
changeOrigin: true,
|
||||
|
||||
@@ -94,4 +94,19 @@ export type ErrorOrderDTO =
|
||||
stackTrace?: string
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Se considera cada entrada de conditions como un filtro sobre un campo
|
||||
* cada fila se podrá expresar como campo:filtro
|
||||
* ```json
|
||||
* {
|
||||
* "value": "-gte 200" // Un valor >= 200
|
||||
* "text": "-eq 'busqueda' " // El campo tiene que ser exactamente 'busqueada'
|
||||
* }
|
||||
* ```
|
||||
* TODO: sacar opciones de paginación
|
||||
* */
|
||||
export type OrderQuery = {
|
||||
conditions: Record<string, string>,
|
||||
limit?: number | undefined,
|
||||
offset?: number | undefined,
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { before, describe, it } from "node:test";
|
||||
import { OrderRepository } from "./OrderRepository.js";
|
||||
import { CreateOrderDTO } from "../domain/Order.js";
|
||||
import { CreateOrderDTO, OrderQuery } from "../domain/Order.js";
|
||||
import { postgresClient } from "../config/config.test.js";
|
||||
import assert from "node:assert";
|
||||
import { Query } from "pg";
|
||||
|
||||
const order1 = <CreateOrderDTO>{
|
||||
correlation_id: "fakeRMQid-1234",
|
||||
@@ -169,4 +170,16 @@ describe("Test OrderRepository", {}, (ctx) => {
|
||||
assert(result.data.status === "dlx")
|
||||
assert(result.data.finish_date != null)
|
||||
})
|
||||
|
||||
it("Query generates with parameters", async () => {
|
||||
const params: OrderQuery = {
|
||||
conditions: {
|
||||
status: "-eq 'pending'"
|
||||
}
|
||||
}
|
||||
//@ts-expect-error
|
||||
const res = orderRepo.generateTableQuery("test", params)
|
||||
console.log("Query:", res)
|
||||
assert.ok(res != undefined)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* TODO: Usar
|
||||
*/
|
||||
import { PoolClient, QueryResult, QueryResultRow } from "pg";
|
||||
import { CreateOrderDTO, ErrorOrderDTO, FinishOrderDTO, OrderTracking, UpdateOrderDTO } from "../domain/Order.js";
|
||||
import { CreateOrderDTO, ErrorOrderDTO, FinishOrderDTO, OrderQuery, OrderTracking, UpdateOrderDTO } from "../domain/Order.js";
|
||||
import { Result, tryCatch } from "../domain/Result.js";
|
||||
import { PgClient } from "./PgClient.js";
|
||||
import assert from "node:assert";
|
||||
@@ -55,7 +55,77 @@ export class OrderRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mapeo de prefijos a operadores SQL
|
||||
*/
|
||||
private OPERATOR_MAP: Record<string, string> = {
|
||||
"-eq": "=",
|
||||
"-neq": "!=",
|
||||
"-gt": ">",
|
||||
"-gte": ">=",
|
||||
"-lt": "<",
|
||||
"-lte": "<=",
|
||||
"-like": "LIKE",
|
||||
};
|
||||
|
||||
/**
|
||||
* Tabla general para sacar datos de la tabla en base a unas condiciones
|
||||
* TODO:
|
||||
* - Dar la opción de generar los campos a devolver en vez de *
|
||||
* - Garantizar el numero de parametros de respuesta
|
||||
*/
|
||||
private generateTableQuery(table: string, query: OrderQuery) {
|
||||
const { conditions, limit, offset } = query;
|
||||
const whereClauses: string[] = [];
|
||||
const queryValues: any[] = [];
|
||||
|
||||
let paramIndex = 1; // Para los parametros de PostgreSQL ($1, $2) (que empiezan por 1)
|
||||
|
||||
for (const [column, filter] of Object.entries(conditions)) {
|
||||
const match = filter.match(/^(-\w+)\s+(.+)$/);
|
||||
|
||||
if (match) {
|
||||
const [_, prefix, value] = match;
|
||||
const operator = this.OPERATOR_MAP[prefix];
|
||||
|
||||
if (operator) {
|
||||
// Eliminación de comillas
|
||||
const cleanValue = value.replace(/^'|'$/g, "");
|
||||
|
||||
whereClauses.push(`${column} ${operator} $${paramIndex}`);
|
||||
queryValues.push(operator === "LIKE" ? `%${cleanValue}%` : cleanValue);
|
||||
paramIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Query completa
|
||||
// TODO: Cambair el * por parametros
|
||||
let sql = `SELECT * FROM ${table}`;
|
||||
|
||||
if (whereClauses.length > 0) {
|
||||
sql += ` WHERE ${whereClauses.join(" AND ")}`;
|
||||
}
|
||||
|
||||
// 3. Paginacion
|
||||
if (limit !== undefined) {
|
||||
sql += ` LIMIT ${Number(limit)}`;
|
||||
}
|
||||
if (offset !== undefined) {
|
||||
sql += ` OFFSET ${Number(offset)}`;
|
||||
}
|
||||
|
||||
return {
|
||||
sql,
|
||||
values: queryValues,
|
||||
};
|
||||
}
|
||||
|
||||
public async getOrdersByQuery(args: OrderQuery) {
|
||||
const query = this.generateTableQuery('order_tracking', args)
|
||||
const queryPromise = this.pgClient.query<OrderTracking<Record<string, any>>>(query.sql, query.values)
|
||||
const result = await this.getAll(queryPromise)
|
||||
}
|
||||
|
||||
/**
|
||||
* El tipo <T> representa el contenido del mensaje de los order
|
||||
|
||||
Reference in New Issue
Block a user