import { Router } from 'express'; import { requireAuth, requirePolicy } from '../middleware/auth.js'; import { getCoverageReport, getClientDashboard, getClientSession, getCoverageStats, getCurrentAttendanceStatus, getCurrentBill, getDailyOpsReport, getPaymentChart, getPaymentsSummary, getPersonalInfo, getPerformanceReport, getProfileSectionsStatus, getPrivacySettings, getForecastReport, getNoShowReport, getOrderReorderPreview, listGeofenceIncidents, getReportSummary, getSavings, getStaffDashboard, getStaffReliabilityStats, getStaffProfileCompletion, getStaffSession, getStaffShiftDetail, listAttireChecklist, listAssignedShifts, listBusinessAccounts, listBusinessTeamMembers, listBlockedStaff, listCancelledShifts, listCertificates, listCostCenters, listCoreTeam, listCoverageByDate, listCoverageDispatchCandidates, listCoverageDispatchTeams, listCompletedShifts, listEmergencyContacts, listFaqCategories, listHubManagers, listHubs, listIndustries, listInvoiceHistory, listOpenShifts, listTaxForms, listTimeCardEntries, listSwapRequests, listOrderItemsByDateRange, listPaymentsHistory, listPendingAssignments, listPendingInvoices, listProfileDocuments, listRecentReorders, listSkills, listStaffAvailability, listStaffBankAccounts, listStaffBenefits, listStaffBenefitHistory, listTodayShifts, listVendorRoles, listVendors, searchFaqs, getSpendBreakdown, getSpendReport, } from '../services/mobile-query-service.js'; const defaultQueryService = { getClientDashboard, getClientSession, getCoverageReport, getCoverageStats, getCurrentAttendanceStatus, getCurrentBill, getDailyOpsReport, getPaymentChart, getPaymentsSummary, getPersonalInfo, getPerformanceReport, getProfileSectionsStatus, getPrivacySettings, getForecastReport, getNoShowReport, getOrderReorderPreview, listGeofenceIncidents, getReportSummary, getSavings, getSpendBreakdown, getSpendReport, getStaffDashboard, getStaffReliabilityStats, getStaffProfileCompletion, getStaffSession, getStaffShiftDetail, listAttireChecklist, listAssignedShifts, listBusinessAccounts, listBusinessTeamMembers, listBlockedStaff, listCancelledShifts, listCertificates, listCostCenters, listCoreTeam, listCoverageByDate, listCoverageDispatchCandidates, listCoverageDispatchTeams, listCompletedShifts, listEmergencyContacts, listFaqCategories, listHubManagers, listHubs, listIndustries, listInvoiceHistory, listOpenShifts, listTaxForms, listTimeCardEntries, listSwapRequests, listOrderItemsByDateRange, listPaymentsHistory, listPendingAssignments, listPendingInvoices, listProfileDocuments, listRecentReorders, listSkills, listStaffAvailability, listStaffBankAccounts, listStaffBenefits, listStaffBenefitHistory, listTodayShifts, listVendorRoles, listVendors, searchFaqs, }; function requireQueryParam(name, value) { if (!value) { const error = new Error(`${name} is required`); error.code = 'VALIDATION_ERROR'; error.status = 400; error.details = { field: name }; throw error; } return value; } export function createMobileQueryRouter(queryService = defaultQueryService) { const router = Router(); router.get('/client/session', requireAuth, requirePolicy('client.session.read', 'session'), async (req, res, next) => { try { const data = await queryService.getClientSession(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/dashboard', requireAuth, requirePolicy('client.dashboard.read', 'dashboard'), async (req, res, next) => { try { const data = await queryService.getClientDashboard(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reorders', requireAuth, requirePolicy('orders.reorder.read', 'order'), async (req, res, next) => { try { const items = await queryService.listRecentReorders(req.actor.uid, req.query.limit); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/accounts', requireAuth, requirePolicy('billing.accounts.read', 'billing'), async (req, res, next) => { try { const items = await queryService.listBusinessAccounts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/invoices/pending', requireAuth, requirePolicy('billing.invoices.read', 'billing'), async (req, res, next) => { try { const items = await queryService.listPendingInvoices(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/invoices/history', requireAuth, requirePolicy('billing.invoices.read', 'billing'), async (req, res, next) => { try { const items = await queryService.listInvoiceHistory(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/current-bill', requireAuth, requirePolicy('billing.summary.read', 'billing'), async (req, res, next) => { try { const data = await queryService.getCurrentBill(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/savings', requireAuth, requirePolicy('billing.summary.read', 'billing'), async (req, res, next) => { try { const data = await queryService.getSavings(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/billing/spend-breakdown', requireAuth, requirePolicy('billing.summary.read', 'billing'), async (req, res, next) => { try { const items = await queryService.getSpendBreakdown(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listCoverageByDate(req.actor.uid, { date: requireQueryParam('date', req.query.date) }); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/stats', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const data = await queryService.getCoverageStats(req.actor.uid, { date: requireQueryParam('date', req.query.date) }); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/core-team', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listCoreTeam(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/incidents', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listGeofenceIncidents(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/blocked-staff', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listBlockedStaff(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/swap-requests', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listSwapRequests(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/dispatch-teams', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listCoverageDispatchTeams(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/coverage/dispatch-candidates', requireAuth, requirePolicy('coverage.read', 'coverage'), async (req, res, next) => { try { const items = await queryService.listCoverageDispatchCandidates(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/hubs', requireAuth, requirePolicy('hubs.read', 'hub'), async (req, res, next) => { try { const items = await queryService.listHubs(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/cost-centers', requireAuth, requirePolicy('hubs.read', 'hub'), async (req, res, next) => { try { const items = await queryService.listCostCenters(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/vendors', requireAuth, requirePolicy('vendors.read', 'vendor'), async (req, res, next) => { try { const items = await queryService.listVendors(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/vendors/:vendorId/roles', requireAuth, requirePolicy('vendors.read', 'vendor'), async (req, res, next) => { try { const items = await queryService.listVendorRoles(req.actor.uid, req.params.vendorId); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/hubs/:hubId/managers', requireAuth, requirePolicy('hubs.read', 'hub'), async (req, res, next) => { try { const items = await queryService.listHubManagers(req.actor.uid, req.params.hubId); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/team-members', requireAuth, requirePolicy('hubs.read', 'hub'), async (req, res, next) => { try { const items = await queryService.listBusinessTeamMembers(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/orders/view', requireAuth, requirePolicy('orders.read', 'order'), async (req, res, next) => { try { const items = await queryService.listOrderItemsByDateRange(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/orders/:orderId/reorder-preview', requireAuth, requirePolicy('orders.read', 'order'), async (req, res, next) => { try { const data = await queryService.getOrderReorderPreview(req.actor.uid, req.params.orderId); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/summary', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getReportSummary(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/daily-ops', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getDailyOpsReport(req.actor.uid, { date: requireQueryParam('date', req.query.date) }); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/spend', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getSpendReport(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/coverage', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getCoverageReport(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/forecast', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getForecastReport(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/performance', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getPerformanceReport(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/client/reports/no-show', requireAuth, requirePolicy('reports.read', 'report'), async (req, res, next) => { try { const data = await queryService.getNoShowReport(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/session', requireAuth, requirePolicy('staff.session.read', 'session'), async (req, res, next) => { try { const data = await queryService.getStaffSession(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/stats', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const data = await queryService.getStaffReliabilityStats(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/dashboard', requireAuth, requirePolicy('staff.dashboard.read', 'dashboard'), async (req, res, next) => { try { const data = await queryService.getStaffDashboard(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile-completion', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const data = await queryService.getStaffProfileCompletion(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/availability', requireAuth, requirePolicy('staff.availability.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listStaffAvailability(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/clock-in/shifts/today', requireAuth, requirePolicy('attendance.read', 'attendance'), async (req, res, next) => { try { const items = await queryService.listTodayShifts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/clock-in/status', requireAuth, requirePolicy('attendance.read', 'attendance'), async (req, res, next) => { try { const data = await queryService.getCurrentAttendanceStatus(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/payments/summary', requireAuth, requirePolicy('payments.read', 'payment'), async (req, res, next) => { try { const data = await queryService.getPaymentsSummary(req.actor.uid, req.query); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/payments/history', requireAuth, requirePolicy('payments.read', 'payment'), async (req, res, next) => { try { const items = await queryService.listPaymentsHistory(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/payments/chart', requireAuth, requirePolicy('payments.read', 'payment'), async (req, res, next) => { try { const items = await queryService.getPaymentChart(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/assigned', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const items = await queryService.listAssignedShifts(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/open', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const items = await queryService.listOpenShifts(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/pending', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const items = await queryService.listPendingAssignments(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/cancelled', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const items = await queryService.listCancelledShifts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/completed', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const items = await queryService.listCompletedShifts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/shifts/:shiftId', requireAuth, requirePolicy('shifts.read', 'shift'), async (req, res, next) => { try { const data = await queryService.getStaffShiftDetail(req.actor.uid, req.params.shiftId); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/sections', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const data = await queryService.getProfileSectionsStatus(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/personal-info', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const data = await queryService.getPersonalInfo(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/industries', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listIndustries(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/skills', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listSkills(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/documents', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listProfileDocuments(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/attire', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listAttireChecklist(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/tax-forms', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listTaxForms(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/emergency-contacts', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listEmergencyContacts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/certificates', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listCertificates(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/bank-accounts', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listStaffBankAccounts(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/benefits', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listStaffBenefits(req.actor.uid); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/benefits/history', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listStaffBenefitHistory(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/time-card', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const items = await queryService.listTimeCardEntries(req.actor.uid, req.query); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/profile/privacy', requireAuth, requirePolicy('staff.profile.read', 'staff'), async (req, res, next) => { try { const data = await queryService.getPrivacySettings(req.actor.uid); return res.status(200).json({ ...data, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/faqs', async (req, res, next) => { try { const items = await queryService.listFaqCategories(); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); router.get('/staff/faqs/search', async (req, res, next) => { try { const items = await queryService.searchFaqs(req.query.q || ''); return res.status(200).json({ items, requestId: req.requestId }); } catch (error) { return next(error); } }); return router; }