22 lines
1.3 KiB
TypeScript
22 lines
1.3 KiB
TypeScript
import type { ClockEvent } from './clock';
|
|
|
|
export const workDate = (instant:string) => {
|
|
const date = new Date(instant);
|
|
if (!Number.isFinite(date.getTime())) throw new Error('Invalid scan time');
|
|
return new Intl.DateTimeFormat('en-CA',{timeZone:'Africa/Johannesburg',year:'numeric',month:'2-digit',day:'2-digit'}).format(date);
|
|
};
|
|
export function clockAction(last:ClockEvent|null, site:string, now:string):'in'|'out' {
|
|
return last?.direction==='in' && workDate(last.scanned_at)===workDate(now) && last.site===site ? 'out' : 'in';
|
|
}
|
|
|
|
/** An earlier IN interrupted by another IN is still missing its physical OUT. */
|
|
export function missedClockIns(events:ClockEvent[], now:string):ClockEvent[] {
|
|
const open=new Map<string,ClockEvent>();const missed:ClockEvent[]=[];
|
|
for (const event of [...events].sort((a,b)=>Date.parse(a.scanned_at)-Date.parse(b.scanned_at)||a.id.localeCompare(b.id))) {
|
|
const previous=open.get(event.employee);
|
|
if (event.direction==='in') { if(previous)missed.push(previous);open.set(event.employee,event); }
|
|
else if(previous && previous.site===event.site && workDate(previous.scanned_at)===workDate(event.scanned_at)) open.delete(event.employee);
|
|
}
|
|
for(const event of open.values())if(workDate(event.scanned_at)<workDate(now))missed.push(event);
|
|
return missed;
|
|
}
|