import { requireAuth, requireCap } from '../auth.js' import { getConfig } from '../db.js' async function fcFetch(path) { const apiKey = await getConfig('forecasting_api_key') const baseUrl = (await getConfig('forecasting_url')) || 'http://10.10.10.113:3080' if (!apiKey) throw new Error('Forecasting API key not configured — add it in Settings') const res = await fetch(`${baseUrl}/forecasting/api/public${path}`, { headers: { 'X-API-Key': apiKey }, signal: AbortSignal.timeout(15000), }) if (!res.ok) throw new Error(`Forecasting API ${res.status} — ${path}`) return res.json() } function daysBetween(from, to) { const a = new Date(from + 'T00:00:00') const b = new Date(to + 'T00:00:00') return Math.max(1, Math.ceil((b - a) / 86_400_000) + 1) } export async function netSalesRoutes(fastify) { fastify.addHook('preHandler', requireAuth) // Returns daily net sales and prior-year net sales for a date range. fastify.get('/api/net-sales', { preHandler: requireCap('view') }, async (request, reply) => { const { from, to } = request.query if (!from || !to) return reply.status(400).send({ error: 'from and to required' }) const MAX_DAYS = 365 const totalDays = daysBetween(from, to) const allDays = [] // Batch into ≤365-day chunks if range exceeds API limit let batchStart = new Date(from + 'T00:00:00') const end = new Date(to + 'T00:00:00') while (batchStart <= end) { const remaining = Math.ceil((end - batchStart) / 86_400_000) + 1 const batchDays = Math.min(remaining, MAX_DAYS) const startStr = batchStart.toISOString().slice(0, 10) const data = await fcFetch(`/forecast/revenue?start_date=${startStr}&days=${batchDays}&type=all&dow_align=true`) for (const d of (data?.data ?? [])) { allDays.push({ date: d.date, net_sales: parseFloat(d.total?.otb ?? 0), py_sales: parseFloat(d.total?.prior_final ?? 0), accom: parseFloat(d.accom?.otb ?? 0), dry: parseFloat(d.dry?.otb ?? 0), wet: parseFloat(d.wet?.otb ?? 0), is_past: d.is_past ?? true, }) } batchStart.setDate(batchStart.getDate() + batchDays) } return { days: allDays } }) }