Files
mercadodevida/project/src/modules/admin/api/notifications.routes.ts

66 lines
1.9 KiB
TypeScript

import { FastifyInstance } from 'fastify';
import { Pool } from 'pg';
export function notificationsRoutes(fastify: FastifyInstance, pool: Pool) {
// GET /api/admin/notifications
// Returns pending counts for bell icon
fastify.get('/admin/notifications', async (req) => {
const [ordersRows] = await Promise.all([
pool.query<{ pending: string; shipped_24h: string; awaiting_payment: string }>(`
SELECT
COUNT(*) FILTER (WHERE state = 'PENDING') AS pending,
COUNT(*) FILTER (
WHERE state = 'SHIPPED'
AND updated_at < NOW() - INTERVAL '24 hours'
) AS shipped_24h,
COUNT(*) FILTER (
WHERE payment_status = 'AWAITING'
AND state = 'PENDING'
) AS awaiting_payment
FROM pos_orders
WHERE deleted_at IS NULL
AND created_at > NOW() - INTERVAL '30 days'
`),
]);
const row = ordersRows.rows[0];
const items = [];
const pending = parseInt(row?.pending ?? '0', 10);
if (pending > 0) {
items.push({
id: 'pending_orders',
type: 'pending_orders',
count: pending,
message: 'Pedidos pendientes de procesar',
href: '/orders?state=PENDING',
});
}
const shipped24h = parseInt(row?.shipped_24h ?? '0', 10);
if (shipped24h > 0) {
items.push({
id: 'stale_shipped',
type: 'stale_shipped',
count: shipped24h,
message: 'Enviados sin actualizar en +24h',
href: '/orders?state=SHIPPED&stale=true',
});
}
const awaiting = parseInt(row?.awaiting_payment ?? '0', 10);
if (awaiting > 0) {
items.push({
id: 'awaiting_payment',
type: 'awaiting_payment',
count: awaiting,
message: 'Esperando confirmación de pago',
href: '/orders?payment_status=AWAITING',
});
}
return { items };
});
}