function nightlyMaintenance() { const cutoff = Date.now() - 14*3600000; rows_(CFG.SHEETS.SHIFTS) .filter(s => String(s.status)==='OPEN' && new Date(s.clock_in).getTime() < cutoff) .forEach(s => { append_(CFG.SHEETS.NOTIFICATIONS,{ notification_id:uuid_('NOT'), user_id:'', type:'OPEN_SHIFT_WARNING', title:'Pravděpodobně chybí odchod', message:'Směna '+s.shift_id+' je otevřená déle než 14 hodin.', url:'', read_at:'', created_at:now_(), email_sent_at:'' }); }); } function monthlyMaintenance() { const d = new Date(); d.setMonth(d.getMonth()-1); const p = Utilities.formatDate(d,CFG.TZ,'yyyy-MM'); rows_(CFG.SHEETS.EMPLOYEES) .filter(e => e.active === true || String(e.active).toUpperCase()==='TRUE') .forEach(e => { const exists = findOne_(CFG.SHEETS.MONTH_CLOSURES,r=>String(r.employee_id)===String(e.employee_id)&&String(r.period)===p); if (!exists) append_(CFG.SHEETS.MONTH_CLOSURES,{ closure_id:uuid_('CLOSE'),employee_id:e.employee_id,period:p, employee_confirmed_at:'',manager_approved_at:'',manager_approved_by:'',locked_at:'',status:'WAITING_EMPLOYEE' }); }); }