Skip to content

Implement notification system and update .gitignore - #152

Merged
SebaKisser merged 4 commits into
devfrom
OM-505-notification
May 13, 2026
Merged

SebaKisser merged 4 commits into
devfrom
OM-505-notification

Conversation

@CrisNAC

@CrisNAC CrisNAC commented May 13, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

Notas de Lanzamiento

  • New Features

    • Nuevo sistema de notificaciones con capacidad de obtener y marcar notificaciones como leídas.
    • Notificaciones automáticas enviadas a clientes cuando se confirma un pedido.
  • Tests

    • Se añadieron pruebas unitarias para el módulo de notificaciones y confirmación de pedidos.
  • Chores

    • Actualización de configuraciones de proyecto.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 13, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Resumen general

Se implementa un sistema completo de notificaciones que permite crear, recuperar y marcar notificaciones como leídas. Las notificaciones se generan automáticamente cuando se confirma una orden, almacenando una referencia a la entidad relacionada y permitiendo que los usuarios las consulten a través de una API HTTP autenticada.

Cambios

Sistema de notificaciones para órdenes

Capa / Archivo(s) Resumen
Esquema de datos y configuración
prisma/schema.prisma, .gitignore
Se añade campo reference_id: Int? al modelo Notifications para almacenar referencias a entidades. Se actualiza .gitignore para ignorar directorios de cobertura y configuración local.
Servicio de notificaciones
src/modules/notifications/notification.service.js
Se implementan tres servicios: createNotificationService para persistencia dentro de transacciones, getNotificationsService para obtener notificaciones con cálculo de no leídos, y markNotificationAsReadService con validación de propiedad y errores.
Constantes de mensajes
src/modules/notifications/notification.constant.js
Se define NOTIFICATION_MESSAGES con plantilla ORDER_CONFIRMED(orderId) que genera objeto con título, mensaje y referencia a la orden.
Controlador y enrutamiento
src/modules/notifications/notification.controller.js, src/modules/notifications/notification.routes.js
Se implementan dos controladores Express para obtener notificaciones y marcar como leída, y se exponen dos rutas autenticadas con documentación Swagger: GET / y PATCH /:id/read.
Integración en aplicación y órdenes
src/app.js, src/modules/users/orders/order.service.js
Se registra router de notificaciones en /api/notifications. Se actualiza createOrderService para generar automáticamente notificación ORDER_CONFIRMED al completar orden dentro de la transacción de checkout.
Pruebas unitarias
tests/unit/notifications/notification.test.js, tests/unit/order/order.test.js
Suite completa de tests para servicios de notificaciones validando cálculo de no leídos, ownership, validaciones y mapeo de campos. Se actualiza suite de órdenes para incluir mocks de notifications.create en todas las transacciones.

Diagrama de secuencia

sequenceDiagram
  participant Client
  participant OrderAPI as Order API
  participant NotifService as Notification Service
  participant DB
  participant NotifAPI as Notification API
  
  Client->>OrderAPI: POST crear orden
  OrderAPI->>OrderAPI: Validar carrito
  OrderAPI->>NotifService: createNotificationService(tx, ORDER_CONFIRMED)
  NotifService->>DB: INSERT notification
  OrderAPI-->>Client: 200 orden creada
  
  Client->>NotifAPI: GET /api/notifications
  NotifAPI->>NotifService: getNotificationsService(userId)
  NotifService->>DB: SELECT active notifications
  NotifService-->>NotifAPI: notificaciones con unreadCount
  NotifAPI-->>Client: 200 lista de notificaciones
  
  Client->>NotifAPI: PATCH /api/notifications/1/read
  NotifAPI->>NotifService: markNotificationAsReadService(userId, id)
  NotifService->>DB: UPDATE notification read=true
  NotifService-->>NotifAPI: notificación actualizada
  NotifAPI-->>Client: 200 marcada como leída
Loading

Esfuerzo estimado de revisión de código

🎯 3 (Moderado) | ⏱️ ~20 minutos

PRs posiblemente relacionados

  • CrisNAC/BackendMarketplace#79: Ambos PRs tocan las pruebas unitarias de órdenes; este PR actualiza los mocks de prisma.notifications.create en tests/unit/order/order.test.js durante la creación de órdenes, alineándose con la cobertura unitaria expandida para createOrderService.
  • CrisNAC/BackendMarketplace#84: Ambos PRs modifican el mismo flujo de órdenes en src/modules/users/orders/order.service.js—createOrderService—añadiendo en este PR la creación automática de notificación ORDER_CONFIRMED durante la transacción de checkout.

Revisores sugeridos

  • Andoumeda
  • leoAchu16

Poema 🐰

Un conejo salta feliz por este PR,
Notificaciones ahora hacen brillar,
Cada orden confirmada, un mensaje a enviar, 🔔
Y usuarios contentos pueden consultar,
¡Qué alegría de sistema para comunicar!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed El título es claro y específico, resumiendo los cambios principales: la implementación de un sistema de notificaciones y actualización del archivo .gitignore. Cubre adecuadamente los dos aspectos principales del changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OM-505-notification

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@CrisNAC
CrisNAC requested review from Andoumeda, SebaKisser and leoAchu16 and removed request for Andoumeda and leoAchu16 May 13, 2026 19:58
@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/modules/users/orders/order.service.js (1)

384-386: 💤 Low value

Simplificar la creación de la notificación usando todos los campos del mensaje.

La destructuración en la línea 385 extrae solo title y message, pero luego se pasa reference_id: order.id_order por separado. Sin embargo, NOTIFICATION_MESSAGES.ORDER_CONFIRMED(order.id_order) ya incluye reference_id con el mismo valor. Podrías simplificar el código usando el spread operator.

♻️ Simplificación propuesta
     // crear notificación de nuevo pedido para el cliente
-    const { title, message } = NOTIFICATION_MESSAGES.ORDER_CONFIRMED(order.id_order);
-    await createNotificationService(tx, { userId: resolvedUserId, title, message, reference_id: order.id_order });
+    const notificationData = NOTIFICATION_MESSAGES.ORDER_CONFIRMED(order.id_order);
+    await createNotificationService(tx, { userId: resolvedUserId, ...notificationData });

Esto evita duplicar order.id_order y hace el código más mantenible si se agregan más campos al mensaje en el futuro.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/users/orders/order.service.js` around lines 384 - 386, La
creación de la notificación duplica el campo reference_id: llama
NOTIFICATION_MESSAGES.ORDER_CONFIRMED(order.id_order) y solo extraes title y
message antes de pasar reference_id por separado; en su lugar, pasa todo el
objeto de mensaje retornado por NOTIFICATION_MESSAGES.ORDER_CONFIRMED junto con
userId y tx a createNotificationService (manteniendo resolvedUserId y tx), por
ejemplo usando el spread del resultado de NOTIFICATION_MESSAGES.ORDER_CONFIRMED
en el segundo argumento de createNotificationService para evitar duplicación y
facilitar futuras extensiones.
src/modules/notifications/notification.service.js (1)

18-47: ⚡ Quick win

Considerar optimizar el cálculo de notificaciones no leídas.

El unreadCount se calcula filtrando en memoria todas las notificaciones después de traerlas desde la base de datos (línea 34). Para usuarios con muchas notificaciones, esto puede ser ineficiente. Una consulta separada con agregación o el uso de _count de Prisma sería más performante.

♻️ Optimización propuesta
 export const getNotificationsService = async (authenticatedUserId) => {
     const resolvedUserId = parsePositiveInteger(authenticatedUserId, "userId");
 
-    const notifications = await prisma.notifications.findMany({
+    const [notifications, unreadCount] = await Promise.all([
+        prisma.notifications.findMany({
-        where: { fk_user: resolvedUserId, status: true },
+            where: { fk_user: resolvedUserId, status: true },
-        orderBy: { created_at: "desc" },
+            orderBy: { created_at: "desc" },
-        select: {
+            select: {
-            id_notification: true,
+                id_notification: true,
-            title: true,
+                title: true,
-            message: true,
+                message: true,
-            read: true,
+                read: true,
-            reference_id: true,
+                reference_id: true,
-            created_at: true
+                created_at: true
+            }
+        }),
+        prisma.notifications.count({
+            where: { fk_user: resolvedUserId, status: true, read: false }
+        })
-        }
-    });
+    ]);
 
-    const unreadCount = notifications.filter((n) => !n.read).length;
-
     return {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/modules/notifications/notification.service.js` around lines 18 - 47, In
getNotificationsService replace the in-memory unreadCount calculation (currently
using notifications.filter(...) after the prisma.notifications.findMany call)
with a DB-side count to avoid loading all rows: run a separate Prisma
count/aggregate query (e.g., prisma.notifications.count or
prisma.notifications.aggregate) with where: { fk_user: resolvedUserId, status:
true, read: false } to compute unreadCount, keep the existing
prisma.notifications.findMany only for the list mapping, and assign the count
result to unreadCount.
tests/unit/notifications/notification.test.js (2)

23-29: ⚡ Quick win

Falta validar referenceId en el mapeo de notificaciones.

Con el nuevo contrato del PR, estos tests pueden pasar aunque se rompa el mapeo de reference_id a referenceId.

💡 Propuesta de ajuste
 const mockNotificationUnread = {
     id_notification: 1,
+    reference_id: 100,
     title: "¡Pedido confirmado!",
     message: "Tu pedido `#100` fue confirmado correctamente.",
     read: false,
     created_at: "2026-01-01T00:00:00.000Z",
 };

 const mockNotificationRead = {
     id_notification: 2,
+    reference_id: 101,
     title: "¡Pedido confirmado!",
     message: "Tu pedido `#101` fue confirmado correctamente.",
     read: true,
     created_at: "2026-01-01T00:00:00.000Z",
 };
@@
         expect(notification).toMatchObject({
             id: 1,
+            referenceId: 100,
             title: "¡Pedido confirmado!",
             message: "Tu pedido `#100` fue confirmado correctamente.",
             read: false,
             createdAt: "2026-01-01T00:00:00.000Z",
         });
@@
         expect(result).toMatchObject({
             id: 1,
+            referenceId: 100,
             title: "¡Pedido confirmado!",
             read: true,
             createdAt: "2026-01-01T00:00:00.000Z",
         });

Also applies to: 31-37, 73-85, 136-153

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/notifications/notification.test.js` around lines 23 - 29, The
tests are missing assertions for the new referenceId mapping so they don't catch
regressions; update the notification mocks (e.g., mockNotificationUnread and the
other mocks at the referenced blocks) to include the backend field reference_id,
and add assertions in the relevant tests (the test that maps notifications and
any expectations around mapped objects) to check that the mapped object has
referenceId === mock.reference_id; locate the mapping logic test where
notifications are transformed (look for variable names like
mockNotificationUnread, the mapping function under test, and assertions checking
title/message/read) and add the referenceId assertion for each corresponding
mock.

3-6: ⚡ Quick win

La suite no cubre createNotificationService.

Queda sin testear la escritura de notificaciones (incluyendo validaciones y persistencia de reference_id) en el mismo módulo.

Also applies to: 39-41, 95-97

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/notifications/notification.test.js` around lines 3 - 6, The tests
currently cover getNotificationsService and markNotificationAsReadService but do
not exercise createNotificationService; add unit tests for
createNotificationService in the notification.test.js suite that assert (1)
input validation errors are thrown for missing/invalid fields, (2) a
notification is persisted to the store when valid input is provided, and (3) the
reference_id field is saved and retrievable; use the existing test setup/mocks
used for getNotificationsService/markNotificationAsReadService (reusing the same
mocked repository or DB helper) and call createNotificationService with both
invalid and valid payloads, then verify persistence by querying via
getNotificationsService or the mocked repository and asserting reference_id
equals the provided value.
tests/unit/order/order.test.js (1)

55-57: ⚡ Quick win

Se mockea notifications.create, pero no se verifica que se use correctamente.

Así los tests pasan aunque el servicio deje de crear notificaciones o las cree con payload inválido.

💡 Propuesta de aserción mínima
   it("crea la orden correctamente con dirección válida", async () => {
@@
     const result = await createOrderService(1, {
@@
     expect(result).toMatchObject({
       id: 100,
       status: "PENDING",
       total: 200,
     });
+    expect(prisma.notifications.create).toHaveBeenCalledWith(
+      expect.objectContaining({
+        data: expect.objectContaining({
+          fk_user: 1,
+          read: false,
+        }),
+      })
+    );
@@
   });
   it("SELLER puede pasar de PENDING a PROCESSING", async () => {
+    const txNotificationsCreate = vi.fn().mockResolvedValue({});
     prisma.$transaction.mockImplementation(async (fn) =>
       fn({
@@
-        notifications: { create: vi.fn().mockResolvedValue({}) },
+        notifications: { create: txNotificationsCreate },
       })
     );
@@
     const result = await updateOrderStatusService(1, 100, "PROCESSING");
     expect(result.status).toBe("PROCESSING");
+    expect(txNotificationsCreate).toHaveBeenCalled();
   });

Also applies to: 257-257, 282-282, 306-306, 331-331, 544-545, 565-566, 586-587, 636-637, 680-681, 744-745, 777-778

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/order/order.test.js` around lines 55 - 57, Se está haciendo mock
de notifications.create (vi.fn()) pero no se verifica su uso; añade en cada test
donde se mockea (por ejemplo en order.test.js donde se define notifications: {
create: vi.fn() }) una aserción que confirme que notifications.create fue
llamada y con el payload esperado (por ejemplo usando
expect(notifications.create).toHaveBeenCalled() y
expect(notifications.create).toHaveBeenCalledWith(<expectedPayload>/expect.objectContaining({...})
según el caso); aplica la misma verificación a todas las demás instancias
señaladas (líneas 257, 282, 306, 331, 544-545, 565-566, 586-587, 636-637,
680-681, 744-745, 777-778) para evitar falsos positivos cuando el servicio deje
de crear notificaciones o cambie el formato del payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@prisma/schema.prisma`:
- Line 53: Add a discriminator field to accompany reference_id so the schema can
identify which entity the ID points to (e.g., add a new enum type like
ReferenceType and a field such as reference_type or reference_entity on the same
model that contains reference_id); update the model that holds reference_id
(look for the reference_id field) to include the new enum-typed field and
migrate the DB accordingly, and adjust application logic to validate
reference_id against reference_type when resolving relations or performing
cascades (this preserves integrity and enables safer deletes/queries).

---

Nitpick comments:
In `@src/modules/notifications/notification.service.js`:
- Around line 18-47: In getNotificationsService replace the in-memory
unreadCount calculation (currently using notifications.filter(...) after the
prisma.notifications.findMany call) with a DB-side count to avoid loading all
rows: run a separate Prisma count/aggregate query (e.g.,
prisma.notifications.count or prisma.notifications.aggregate) with where: {
fk_user: resolvedUserId, status: true, read: false } to compute unreadCount,
keep the existing prisma.notifications.findMany only for the list mapping, and
assign the count result to unreadCount.

In `@src/modules/users/orders/order.service.js`:
- Around line 384-386: La creación de la notificación duplica el campo
reference_id: llama NOTIFICATION_MESSAGES.ORDER_CONFIRMED(order.id_order) y solo
extraes title y message antes de pasar reference_id por separado; en su lugar,
pasa todo el objeto de mensaje retornado por
NOTIFICATION_MESSAGES.ORDER_CONFIRMED junto con userId y tx a
createNotificationService (manteniendo resolvedUserId y tx), por ejemplo usando
el spread del resultado de NOTIFICATION_MESSAGES.ORDER_CONFIRMED en el segundo
argumento de createNotificationService para evitar duplicación y facilitar
futuras extensiones.

In `@tests/unit/notifications/notification.test.js`:
- Around line 23-29: The tests are missing assertions for the new referenceId
mapping so they don't catch regressions; update the notification mocks (e.g.,
mockNotificationUnread and the other mocks at the referenced blocks) to include
the backend field reference_id, and add assertions in the relevant tests (the
test that maps notifications and any expectations around mapped objects) to
check that the mapped object has referenceId === mock.reference_id; locate the
mapping logic test where notifications are transformed (look for variable names
like mockNotificationUnread, the mapping function under test, and assertions
checking title/message/read) and add the referenceId assertion for each
corresponding mock.
- Around line 3-6: The tests currently cover getNotificationsService and
markNotificationAsReadService but do not exercise createNotificationService; add
unit tests for createNotificationService in the notification.test.js suite that
assert (1) input validation errors are thrown for missing/invalid fields, (2) a
notification is persisted to the store when valid input is provided, and (3) the
reference_id field is saved and retrievable; use the existing test setup/mocks
used for getNotificationsService/markNotificationAsReadService (reusing the same
mocked repository or DB helper) and call createNotificationService with both
invalid and valid payloads, then verify persistence by querying via
getNotificationsService or the mocked repository and asserting reference_id
equals the provided value.

In `@tests/unit/order/order.test.js`:
- Around line 55-57: Se está haciendo mock de notifications.create (vi.fn())
pero no se verifica su uso; añade en cada test donde se mockea (por ejemplo en
order.test.js donde se define notifications: { create: vi.fn() }) una aserción
que confirme que notifications.create fue llamada y con el payload esperado (por
ejemplo usando expect(notifications.create).toHaveBeenCalled() y
expect(notifications.create).toHaveBeenCalledWith(<expectedPayload>/expect.objectContaining({...})
según el caso); aplica la misma verificación a todas las demás instancias
señaladas (líneas 257, 282, 306, 331, 544-545, 565-566, 586-587, 636-637,
680-681, 744-745, 777-778) para evitar falsos positivos cuando el servicio deje
de crear notificaciones o cambie el formato del payload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29283320-20d9-497f-bba1-83266d90342a

📥 Commits

Reviewing files that changed from the base of the PR and between e255702 and 585fffb.

📒 Files selected for processing (11)
  • .gitignore
  • prisma/schema.prisma
  • src/app.js
  • src/modules/commerce/orders/.gitkeep
  • src/modules/notifications/notification.constant.js
  • src/modules/notifications/notification.controller.js
  • src/modules/notifications/notification.routes.js
  • src/modules/notifications/notification.service.js
  • src/modules/users/orders/order.service.js
  • tests/unit/notifications/notification.test.js
  • tests/unit/order/order.test.js

Comment thread prisma/schema.prisma
@SebaKisser
SebaKisser merged commit fb5da4a into dev May 13, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants