From 3b347681ba8f67fafbbc92197f8efb541384d601 Mon Sep 17 00:00:00 2001 From: Pablinux Date: Mon, 6 Oct 2025 09:18:19 -0500 Subject: [PATCH] =?UTF-8?q?feat(api):=20Agrega=20endpoint=20para=20b=C3=BA?= =?UTF-8?q?squeda=20de=20clientes=20y=20estado=20de=20membres=C3=ADa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Se ha creado una nueva ruta en la API v2 (`GET /api/v2/search-client-member-status`) para dar soporte al frontend en la búsqueda dinámica de clientes para el registro de pagos. Cambios principales: - Se crea el archivo `api_v2_controlador.js` en la carpeta `controladores` para alojar la nueva lógica. - La nueva API busca clientes por nombre o RUC/cédula. - Para cada cliente encontrado, se realiza una consulta a la tabla `clientes_miembros` para determinar si es un miembro activo y si tiene valores vencidos. - Se registra la nueva ruta en `rt_api_v2.js`, asociándola con su controlador. - Se actualiza la colección de Postman (`APP_SIGMA_NODE.postman_collection.json`) para incluir y documentar el nuevo endpoint. Esta funcionalidad es clave para mejorar la experiencia de usuario en el formulario de registro de pagos, permitiendo una selección de cliente más ágil e informativa. --- src/controladores/controlador_api_v2.js | 61 +++++++++++++ ... => APP_SIGMA_WEB.postman_collection.json} | 39 ++++++++- src/rutas/rt_api_v2.js | 86 +++---------------- 3 files changed, 112 insertions(+), 74 deletions(-) create mode 100644 src/controladores/controlador_api_v2.js rename src/data/{APP_SIGMA_NODE.postman_collection.json => APP_SIGMA_WEB.postman_collection.json} (85%) diff --git a/src/controladores/controlador_api_v2.js b/src/controladores/controlador_api_v2.js new file mode 100644 index 0000000..9a95aec --- /dev/null +++ b/src/controladores/controlador_api_v2.js @@ -0,0 +1,61 @@ +const controlador = {}; + +/** + * @description Busca clientes y verifica su estado de membresía. + * Busca por nombre o RUC/cédula. + * Si el cliente es miembro, añade información sobre su estado y si tiene valores vencidos. + * Ruta: GET /api/v2/search-client-member-status + */ +controlador.searchClientMemberStatus = (req, res) => { + const { query } = req.query; + + if (!query || query.length < 2) { + return res.status(400).json({ error: 'Se requiere un término de búsqueda de al menos 2 caracteres.' }); + } + + req.getConnection((err, conn) => { + if (err) { + console.error("Error de conexión a la BD:", err); + return res.status(500).json({ error: 'Error interno del servidor.' }); + } + + // Paso 1: Buscar clientes que coincidan con el término de búsqueda. + const clientSql = ` + SELECT + c.client_id, + c.client_nombre, + c.client_rucCed + FROM clientes c + WHERE c.client_nombre LIKE ? OR c.client_rucCed LIKE ? + LIMIT 10 + `; + const searchTerm = `%${query}%`; + + conn.query(clientSql, [searchTerm, searchTerm], (err, clients) => { + if (err) { + console.error("Error en la búsqueda de clientes:", err); + return res.status(500).json({ error: 'Error al buscar clientes.' }); + } + + // Paso 2: Para cada cliente, verificar si es miembro y su estado. + const promises = clients.map(client => new Promise((resolve, reject) => { + const memberSql = `SELECT estado, fecha_fin FROM clientes_miembros WHERE client_id = ? ORDER BY fecha_fin DESC LIMIT 1`; + conn.query(memberSql, [client.client_id], (err, memberStatus) => { + if (err) return reject(err); + const isMember = memberStatus.length > 0; + const hasOverdue = isMember && (memberStatus[0].estado === 'VENCIDO' || new Date(memberStatus[0].fecha_fin) < new Date()); + resolve({ ...client, isMember, hasOverdue, memberStatus: isMember ? memberStatus[0].estado : null }); + }); + })); + + Promise.all(promises) + .then(results => res.status(200).json(results)) + .catch(error => { + console.error("Error verificando estado de miembros:", error); + res.status(500).json({ error: 'Error al verificar estado de miembros.' }); + }); + }); + }); +}; + +module.exports = controlador; \ No newline at end of file diff --git a/src/data/APP_SIGMA_NODE.postman_collection.json b/src/data/APP_SIGMA_WEB.postman_collection.json similarity index 85% rename from src/data/APP_SIGMA_NODE.postman_collection.json rename to src/data/APP_SIGMA_WEB.postman_collection.json index dffb0a1..10a267c 100644 --- a/src/data/APP_SIGMA_NODE.postman_collection.json +++ b/src/data/APP_SIGMA_WEB.postman_collection.json @@ -1,7 +1,7 @@ { "info": { "_postman_id": "1710a3ae-fba9-4526-8084-a066897ddadd", - "name": "APP_SIGMA_NODE", + "name": "APP-SIGMA-WEB", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", "_exporter_id": "11858928" }, @@ -244,6 +244,41 @@ } ], "description": "Endpoints para la gestión de documentos electrónicos sincronizados desde n8n." + }, + { + "name": "API V2", + "item": [ + { + "name": "Buscar Cliente y Estado de Membresía", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "http://localhost:3001/api/v2/search-client-member-status?query=pablo", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "3001", + "path": [ + "api", + "v2", + "search-client-member-status" + ], + "query": [ + { + "key": "query", + "value": "pablo", + "description": "Término de búsqueda para nombre o RUC/cédula del cliente." + } + ] + }, + "description": "Busca clientes por nombre o RUC/cédula y devuelve su estado de membresía (si aplica)." + }, + "response": [] + } + ], + "description": "Nuevos endpoints para la versión 2 de la API." } ] -} \ No newline at end of file +} diff --git a/src/rutas/rt_api_v2.js b/src/rutas/rt_api_v2.js index 99c04f6..5fa9bc4 100644 --- a/src/rutas/rt_api_v2.js +++ b/src/rutas/rt_api_v2.js @@ -1,90 +1,32 @@ const express = require('express'); -const rutas = express.Router(); +const rutas = express.Router(); -const controladorPedidosApi = require('../controladores/controlador_pedidos_api'); -const controladorItemsApi = require('../controladores/controlador_items_api'); -const controladorClientesApi = require('../controladores/controlador_clientes_api'); // Importar el nuevo controlador de clientes +const apiV2Controller = require('../controladores/controlador_api_v2'); -// --- Rutas para la nueva API de Pedidos V2 --- +// Aquí puedes añadir tus nuevas rutas de la API v2 /** * @swagger - * /api/v2/items: + * /api/v2/search-client-member-status: * get: - * summary: Obtiene la lista de productos para la app de pedidos v2. - * tags: [Pedidos V2] + * summary: Busca clientes y verifica el estado de su membresía. + * tags: [API V2] * parameters: * - in: query - * name: consulta + * name: query * schema: * type: string - * description: Término de búsqueda para filtrar productos. - * - in: query - * name: gp_precio - * schema: - * type: string - * description: Grupo de precios a aplicar (ej. PUBLICO). + * required: true + * description: Término de búsqueda para nombre o RUC/cédula del cliente (mínimo 2 caracteres). * responses: * 200: - * description: Una lista de productos. + * description: Una lista de clientes con su estado de membresía. + * 400: + * description: El término de búsqueda es muy corto. * 500: - * description: Error del servidor. + * description: Error interno del servidor. */ -rutas.get('/api/v2/items', controladorItemsApi.getItemsForV2); +rutas.get('/api/v2/search-client-member-status', apiV2Controller.searchClientMemberStatus); -/** - * @swagger - * /api/v2/clientes: - * get: - * summary: Obtiene la lista de clientes para la app de pedidos v2. - * tags: [Pedidos V2] - * parameters: - * - in: query - * name: consulta - * schema: - * type: string - * description: Término de búsqueda para filtrar clientes por nombre o RUC/CI. - * responses: - * 200: - * description: Una lista de clientes. - * 500: - * description: Error del servidor. - */ -rutas.get('/api/v2/clientes', controladorClientesApi.getClientesForV2); - -/** - * @swagger - * /api/v2/pedidos: - * post: - * summary: Crea un nuevo pedido de forma transaccional. - * tags: [Pedidos V2] - * requestBody: - * required: true - * content: - * application/json: - * schema: - * type: object - * properties: - * clienteId: { type: integer, example: 1 } - * user: { type: string, example: 'WebAppUser' } - * estado: { type: string, example: 'ACTIVO' } - * valor: { type: number, example: 112.00 } - * iva: { type: number, example: 12.00 } - * plataforma: { type: string, example: 'APP-SIGMA-WEB-V2' } - * origen: { type: string, example: 'WebApp' } - * items: - * type: array - * items: - * type: object - * properties: - * cod: { type: string, example: 'PROD-001' } - * cant: { type: integer, example: 2 } - * precio: { type: number, example: 50.00 } - * responses: - * 201: { description: Pedido creado exitosamente. } - * 400: { description: Datos inválidos. } - * 500: { description: Error del servidor. } - */ -rutas.post('/api/v2/pedidos', controladorPedidosApi.crearPedido); module.exports = rutas; \ No newline at end of file