import { MMReceiveTimesheet } from "../../services/mm-api-service/types/receive-types.js"; import type { IERPTimesheetHandler } from "../../types/erp-connector.js"; /** * A row that has been failing for longer than this is dropped from the retry list, but only in a * run where another row succeeded (the ERP is reachable, so the row itself is the problem). It is * logged as an error and not retried again unless it changes in MM. The clock starts at the row's * first failure, so a backlog row after a long outage gets the full window. */ export declare const TIMESHEET_FAILURE_GIVE_UP_MS: number; type TimesheetOutcome = "success" | "failure" | "pending"; /** A row carried to the next cycle in the checkpoint value. */ export type TimesheetRetryEntry = { timesheet: MMReceiveTimesheet; /** When this version of the row first failed (host clock); null if it has not been attempted. */ firstFailedAt: string | null; attempts: number; }; /** What is stored in MM's timesheet export checkpoint. */ export type TimesheetCheckpointValue = { timestamp: string; failed: TimesheetRetryEntry[]; }; /** * Orders two parseable `updatedAt` values at full precision. `Date` keeps only milliseconds, so * ties are broken on the remaining digits (offsets are whole minutes and do not affect them). */ export declare function compareUpdatedAt(a: string, b: string): number; /** * Validates the retry list read back from the checkpoint. Throws on anything unexpected rather * than dropping rows silently; only this synchronizer writes the value. */ export declare function parseTimesheetRetries(value: unknown): TimesheetRetryEntry[]; /** * Decides which rows go on the next cycle's retry list and which are given up on. * * Only rows that did not succeed are kept: rows that succeeded are behind the checkpoint and never * delivered again. A row keeps its first-failure time and attempt count for as long as the same * version of it is retried; a row that changed in MM starts over. * * When nothing succeeded (the ERP is likely unreachable), only rows that were already on the list * are kept, and the caller leaves the checkpoint where it was so this run's fetched rows come back * next cycle. That keeps the list from growing through a long outage. */ export declare function planTimesheetRetries(options: { latestByRef: ReadonlyMap; carried: readonly TimesheetRetryEntry[]; anySucceeded: boolean; nowMs: number; }): { failed: TimesheetRetryEntry[]; givenUp: TimesheetRetryEntry[]; }; /** * Synchronizes timesheet rows (clock in/out) from MachineMetrics to an ERP system. * * The checkpoint advances past every row fetched, so a row that succeeded is not delivered again. * Rows that failed are stored alongside the checkpoint timestamp in MM and retried on the next * cycle, in `timesheetRef` order with new rows. A person's later rows wait behind their earliest * unfinished row, so the ERP sees each person's clock events in order (see * {@link planTimesheetRetries} and {@link TIMESHEET_FAILURE_GIVE_UP_MS}). * * If MM rejects the checkpoint save, the value is kept in the local SQLite runtime state and saved * to MM at the start of the next cycle, before anything is fetched. Only a container recreate * between the two loses it, and rows since the last saved checkpoint are then delivered again. * * Callers should run labor ticket sync to completion before invoking this, so shop-floor labor * is written/closed before employee-level clock-out. */ export declare class TimesheetERPSynchronizer { static syncToERP(connectorType: string, handler: IERPTimesheetHandler): Promise; } export {}; //# sourceMappingURL=timesheet-erp-synchronizer.d.ts.map