import { getConfig, getWorkforceShifts, upsertWorkforceShifts } from '../db.js' import { fetchShifts, fetchTimesheetShifts } from './workforce.js' function fmtDate(d) { return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}` } export async function runRotaSync() { const deptIds = (await getConfig('workforce_departments', [])) || [] if (!deptIds.length) throw new Error('No HK departments selected — configure in Category Settings') const today = new Date() const fromDate = new Date(today); fromDate.setDate(fromDate.getDate() - 7) const toDate = new Date(today); toDate.setDate(toDate.getDate() + 28) const from = fmtDate(fromDate) const to = fmtDate(toDate) // API limit: max 7 days per request — split into weekly chunks const chunks = [] const cur = new Date(fromDate) while (cur <= toDate) { const chunkFrom = fmtDate(cur) const chunkToDate = new Date(cur) chunkToDate.setDate(chunkToDate.getDate() + 6) if (chunkToDate > toDate) chunkToDate.setTime(toDate.getTime()) chunks.push({ from: chunkFrom, to: fmtDate(chunkToDate) }) cur.setDate(cur.getDate() + 7) } const staffMap = {} for (const chunk of chunks) { const chunkStaff = await fetchShifts(chunk.from, chunk.to, deptIds) for (const member of chunkStaff) { if (!staffMap[member.id]) staffMap[member.id] = { id: member.id, name: member.name, days: {} } Object.assign(staffMap[member.id].days, member.days) } } const byDate = {} for (const member of Object.values(staffMap)) { for (const [date, shift] of Object.entries(member.days)) { if (!byDate[date]) byDate[date] = [] byDate[date].push({ id: member.id, name: member.name, hours: shift.hours, times: shift.times }) } } // Skip dates already replaced with timesheet actuals const existing = await getWorkforceShifts(from, to) const timesheetDates = new Set( Object.entries(existing).filter(([, d]) => d.source === 'timesheet').map(([date]) => date) ) const dailyRows = [] const day = new Date(fromDate) while (day <= toDate) { const d = fmtDate(day) if (!timesheetDates.has(d)) dailyRows.push({ date: d, staff: byDate[d] || [], source: 'workforce' }) day.setDate(day.getDate() + 1) } await upsertWorkforceShifts(dailyRows) return { ok: true, from, to, dates_synced: dailyRows.length } } export async function runTimesheetSync(days = 7) { const deptIds = (await getConfig('workforce_departments', [])) || [] if (!deptIds.length) throw new Error('No HK departments selected — configure in Category Settings') const today = new Date() const fromDate = new Date(today); fromDate.setDate(fromDate.getDate() - days) const from = fmtDate(fromDate) const to = fmtDate(today) const staffList = await fetchTimesheetShifts(from, to, deptIds) const byDate = {} for (const member of staffList) { for (const [date, shift] of Object.entries(member.days)) { if (!byDate[date]) byDate[date] = [] byDate[date].push({ id: member.id, name: member.name, hours: shift.hours, times: shift.times, status: shift.status }) } } const dailyRows = [] const day = new Date(fromDate) while (day <= today) { const d = fmtDate(day) dailyRows.push({ date: d, staff: byDate[d] || [], source: 'timesheet' }) day.setDate(day.getDate() + 1) } await upsertWorkforceShifts(dailyRows) return { ok: true, from, to, dates_synced: dailyRows.length } }