Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added src/config/.gitkeep
Empty file.
2 changes: 0 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import productCategoryRoutes from "./modules/commerce/product-categories/product
import productTagRoutes from "./modules/commerce/product-tags/product-tag.routes.js";
import userRoutes from "./modules/users/users/routes/users.routes.js";
import sessionRoutes from "./modules/session/routes/session.routes.js";
import addressesRoutes from "./modules/users/addresses/routes/addresses.routes.js";

dotenv.config();
const app = express();
Expand All @@ -31,7 +30,6 @@ app.use("/products", productRoutes);
app.use("/products/categories", productCategoryRoutes);
app.use("/products/tags", productTagRoutes);
app.use("/api/users", userRoutes);
app.use("/api/addresses", addressesRoutes);

app.listen(PORT, () => {
console.log(`Servidor corriendo en http://localhost:${PORT}`);
Expand Down
Empty file.
12 changes: 6 additions & 6 deletions src/modules/commerce/commerces/store.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export const createStore = async (req, res) => {
*/
export const getStoreById = async (req, res) => {
try {
const { id } = req.params;
const store = await getStoreByIdService(id);
const { id_store } = req.params;
const store = await getStoreByIdService(id_store);
return res.status(200).json(store);
} catch (error) {
return res.status(error.status || 500).json({
Expand All @@ -55,8 +55,8 @@ export const getStoreById = async (req, res) => {
*/
export const getAllProductsByStore = async (req, res) => {
try {
const { id } = req.params;
const products = await getAllProductsByStoreService(id);
const { id_store } = req.params;
const products = await getAllProductsByStoreService(id_store);
return res.status(200).json(products);
} catch (error) {
return res.status(error.status || 500).json({
Expand All @@ -73,9 +73,9 @@ export const getAllProductsByStore = async (req, res) => {
*/
export const filterStoreProducts = async (req, res) => {
try {
const { id } = req.params;
const { id_store } = req.params;
const { category, price_min, price_max } = req.query;
const products = await filterStorePriductsService(id, { category, price_min, price_max });
const products = await filterStorePriductsService(id_store, { category, price_min, price_max });
Comment on lines 74 to +78

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Discrepancia en nombres de parámetros de filtro.

El controlador extrae price_min y price_max del query string, pero el servicio filterStorePriductsService espera minPrice y maxPrice según los snippets relevantes (líneas 319 y 334-338 de store.service.js). Esto causará que los filtros de precio no funcionen.

🐛 Corrección propuesta
 export const filterStoreProducts = async (req, res) => {
   try {
     const { id_store } = req.params;
-    const { category, price_min, price_max } = req.query;
-    const products = await filterStorePriductsService(id_store, { category, price_min, price_max });
+    const { category, price_min, price_max, name, visible, sortBy, sortOrder } = req.query;
+    const products = await filterStorePriductsService(id_store, { 
+      category, 
+      minPrice: price_min, 
+      maxPrice: price_max,
+      name,
+      visible,
+      sortBy,
+      sortOrder
+    });
     return res.status(200).json(products);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const filterStoreProducts = async (req, res) => {
try {
const { id } = req.params;
const { id_store } = req.params;
const { category, price_min, price_max } = req.query;
const products = await filterStorePriductsService(id, { category, price_min, price_max });
const products = await filterStorePriductsService(id_store, { category, price_min, price_max });
export const filterStoreProducts = async (req, res) => {
try {
const { id_store } = req.params;
const { category, price_min, price_max, name, visible, sortBy, sortOrder } = req.query;
const products = await filterStorePriductsService(id_store, {
category,
minPrice: price_min,
maxPrice: price_max,
name,
visible,
sortBy,
sortOrder
});
return res.status(200).json(products);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.controller.js` around lines 74 - 78, El
controlador filterStoreProducts está pasando price_min y price_max desde
req.query al servicio filterStorePriductsService, pero ese servicio espera las
claves minPrice y maxPrice; actualiza la llamada a filterStorePriductsService
para transformar/renombrar { price_min, price_max } a { minPrice: price_min,
maxPrice: price_max } (dejando category igual) para que los filtros de precio
funcionen correctamente; verifica también el uso del identificador id_store al
pasar el primer argumento.

return res.status(200).json(products);
} catch (error) {
return res.status(error.status || 500).json({
Expand Down
6 changes: 3 additions & 3 deletions src/modules/commerce/commerces/store.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
const router = Router();

router.post("/", createStore);
router.get("/:id", getStoreById);
router.get("/products/:id", getAllProductsByStore);
router.get("/products/filter/:id", filterStoreProducts);
router.get("/:id_store", getStoreById);
router.get("/:id_store/products", getAllProductsByStore);
router.get("/:id_store/products/filter", filterStoreProducts);

export default router;
50 changes: 22 additions & 28 deletions src/modules/commerce/commerces/store.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ export const createStoreService = async (data) => {
throw { status: 404, message: "Usuario no encontrado" };
}

// Verificar que sea SELLER
// if (usuario.role !== "SELLER") {
// throw { status: 403, message: "El usuario no es vendedor" };
// }
// vrificar que sea SELLER
if (usuario.role !== "SELLER") {
throw { status: 403, message: "El usuario no es vendedor" };
}
Comment on lines +89 to +92

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Buscar si existe algún endpoint o servicio para actualizar el rol del usuario a SELLER
rg -n "SELLER" --type js -C 3

Repository: CrisNAC/BackendMarketplace

Length of output: 1256


🏁 Script executed:

# Ver el contexto completo de la función que contiene la validación SELLER
head -n 110 src/modules/commerce/commerces/store.service.js | tail -n 50

Repository: CrisNAC/BackendMarketplace

Length of output: 1430


🏁 Script executed:

# Buscar endpoints o servicios que asignen o actualicen el rol SELLER
rg -n "(role|SELLER)" --type js -i -C 2 | grep -E "(update|assign|change|set)" -i

Repository: CrisNAC/BackendMarketplace

Length of output: 52


🏁 Script executed:

# Buscar endpoints de usuarios que podrían actualizar roles
rg -n "role" src/modules --type js -l

Repository: CrisNAC/BackendMarketplace

Length of output: 272


🏁 Script executed:

# Buscar si hay algún servicio de autenticación o usuarios
fd -e js | xargs grep -l "user.*role" -i | head -20

Repository: CrisNAC/BackendMarketplace

Length of output: 124


🏁 Script executed:

# Ver el servicio de usuarios completo
cat -n src/modules/users/users/services/users.services.js

Repository: CrisNAC/BackendMarketplace

Length of output: 1549


🏁 Script executed:

# Ver el controlador de sesión
cat -n src/modules/session/controllers/session.controllers.js

Repository: CrisNAC/BackendMarketplace

Length of output: 4673


🏁 Script executed:

# Buscar en toda la carpeta de usuarios si hay algún endpoint o función que actualice roles
rg -n "role" src/modules/users --type js -B 2 -A 2

Repository: CrisNAC/BackendMarketplace

Length of output: 872


🏁 Script executed:

# Buscar archivos de rutas
find src -name "*route*" -o -name "*routes*" | head -20

Repository: CrisNAC/BackendMarketplace

Length of output: 448


🏁 Script executed:

# Buscar controladores de usuarios
find src/modules/users -name "*controller*" -o -name "*controllers*"

Repository: CrisNAC/BackendMarketplace

Length of output: 162


🏁 Script executed:

# Buscar cualquier función que actualice usuarios o roles
rg -n "update.*user|role.*update" --type js -i

Repository: CrisNAC/BackendMarketplace

Length of output: 52


🏁 Script executed:

# Buscar en el schema de prisma si existe referencia al rol
find . -name "schema.prisma" -o -name "*.prisma"

Repository: CrisNAC/BackendMarketplace

Length of output: 92


🏁 Script executed:

# Ver las rutas disponibles para usuarios
cat -n src/modules/users/users/routes/users.routes.js

Repository: CrisNAC/BackendMarketplace

Length of output: 353


🏁 Script executed:

# Ver los controladores de usuarios
cat -n src/modules/users/users/controllers/users.controllers.js

Repository: CrisNAC/BackendMarketplace

Length of output: 1613


🏁 Script executed:

# Ver la estructura de usuarios en el schema
grep -n "model.*[Uu]ser\|role\|SELLER\|CUSTOMER" prisma/schema.prisma -A 10 -B 2

Repository: CrisNAC/BackendMarketplace

Length of output: 842


No existe mecanismo para asignar el rol SELLER a los usuarios.

La validación de rol SELLER en la función está correcta, pero presenta un problema crítico: los nuevos usuarios se crean con rol "CUSTOMER" por defecto (users.services.js línea 35), y el único endpoint disponible es /api/users/register que no permite actualizar el rol. No hay ningún endpoint ni servicio en el código que permita cambiar el rol de "CUSTOMER" a "SELLER".

Esto hace que los usuarios nunca puedan crear una tienda, a menos que se actualice manualmente la base de datos o se implemente un endpoint para asignar el rol SELLER (por ejemplo, desde un panel de administrador o mediante una solicitud de vendedor).

Se debe agregar un mecanismo para que los usuarios puedan obtener el rol SELLER, o aclarar si esta restricción es intencional y será gestionada mediante otro proceso fuera de la API.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/modules/commerce/commerces/store.service.js` around lines 89 - 92, The
code prevents creation of a store because new users default to role "CUSTOMER"
(users.services.js line 35) and there is no way to change to "SELLER"; add a
controlled role-assignment flow by implementing a service method (e.g.,
updateUserRole or promoteToSeller in users.services.js) and a new
controller/route (e.g., POST /api/users/promote or /api/users/assign-role) that
updates the user's role from CUSTOMER to SELLER, and ensure proper authorization
checks (only admins or verified owner requests allowed) and validation are
enforced before calling the existing store creation check in store.service.js
(the usuario.role !== "SELLER" guard).


// verificar que no tenga tienda
const tiendaExistente = await prisma.stores.findUnique({
Expand Down Expand Up @@ -130,20 +130,14 @@ export const createStoreService = async (data) => {
await tx.addresses.create({
data: {
fk_user,
fk_store: store.id,
fk_store: store.id_store,
address: address.trim(),
city: city.trim(),
region: region.trim(),
postal_code
}
});

// Actualizamos rol del usuario a SELLER al crearse el comercio
await tx.users.update({
where: { id_user: fk_user },
data: { role: "SELLER" }
});

return store;
});

Expand All @@ -161,22 +155,22 @@ export const createStoreService = async (data) => {

/**
* Obtiene un comercio por su ID, incluyendo datos del vendedor, categoría, productos visibles y direcciones activas. Realiza validaciones básicas y maneja errores.
* @param {*} id
* @param {*} id_store
* @returns
*/
export const getStoreByIdService = async (id) => {
export const getStoreByIdService = async (id_store) => {
try {
// validaciones básicas
if (!id) {
if (!id_store) {
throw { status: 400, message: "ID de tienda es requerido" };
}
if (isNaN(Number(id))) {
if (isNaN(Number(id_store))) {
throw { status: 400, message: "ID de tienda debe ser un número" };
}

// Buscar comercio
const store = await prisma.stores.findUnique({
where: { id_store: Number(id) },
where: { id_store: Number(id_store) },
// Datos del comercio
select: {
id_store: true,
Expand Down Expand Up @@ -237,21 +231,21 @@ export const getStoreByIdService = async (id) => {

/**
* Obtiene todos los productos de una tienda específica, filtrando por productos activos y visibles. Realiza validaciones básicas y maneja errores.
* @param {*} id
* @param {*} id_store
* @returns
*/
export const getAllProductsByStoreService = async (id) => {
export const getAllProductsByStoreService = async (id_store) => {
try {
// validaciones básicas
if (!id) {
if (!id_store) {
throw { status: 400, message: "ID de tienda es requerido" };
}
if (isNaN(Number(id))) {
if (isNaN(Number(id_store))) {
throw { status: 400, message: "ID de tienda debe ser un número" };
}
// Verificar que la tienda exista
const store = await prisma.stores.findUnique({
where: { id_store: Number(id) },
where: { id_store: Number(id_store) },
select: { id_store: true }
});
// Si no se encuentra la tienda, lanzar error 404
Expand All @@ -261,7 +255,7 @@ export const getAllProductsByStoreService = async (id) => {
// Obtener productos activos y visibles de la tienda
const products = await prisma.products.findMany({
where: {
fk_store: Number(id),
fk_store: Number(id_store),
status: true
},
select: {
Expand Down Expand Up @@ -299,22 +293,22 @@ export const getAllProductsByStoreService = async (id) => {

/**
* Obtiene productos de una tienda específica aplicando filtros dinámicos como nombre, categoría, visibilidad y rango de precios. Realiza validaciones básicas y maneja errores.
* @param {*} id
* @param {*} id_store
* @param {*} filters
* @returns
*/
export const filterStorePriductsService = async (id, filters) => {
export const filterStorePriductsService = async (id_store, filters) => {
try {
// validaciones básicas
if (!id) {
if (!id_store) {
throw { status: 400, message: "ID de tienda es requerido" };
}
if (isNaN(Number(id))) {
if (isNaN(Number(id_store))) {
throw { status: 400, message: "ID de tienda debe ser un número" };
}
// Verificar que la tienda exista
const store = await prisma.stores.findUnique({
where: { id_store: Number(id) },
where: { id_store: Number(id_store) },
select: { id_store: true }
});
// Si no se encuentra la tienda, lanzar error 404
Expand All @@ -325,7 +319,7 @@ export const filterStorePriductsService = async (id, filters) => {
const { name, category, visible, minPrice, maxPrice, sortBy, sortOrder } = filters;
// Condiciones base para productos activos de la tienda
const whereConditions = {
fk_store: Number(id),
fk_store: Number(id_store),
status: true
};
if (name) {
Expand Down
Empty file.
50 changes: 0 additions & 50 deletions src/modules/users/addresses/controllers/addresses.controller.js

This file was deleted.

12 changes: 0 additions & 12 deletions src/modules/users/addresses/routes/addresses.routes.js

This file was deleted.

Loading