66 lines
1.9 KiB
TypeScript
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 };
|
|
});
|
|
}
|