@happyvertical/smrt-timesheets 0.55.24 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +60 -0
- package/README.md +190 -12
- package/agents/period-rollup.md +20 -0
- package/dist/attendance/context.d.ts +80 -0
- package/dist/attendance/context.d.ts.map +1 -0
- package/dist/attendance/correction-models.d.ts +39 -0
- package/dist/attendance/correction-models.d.ts.map +1 -0
- package/dist/attendance/correction-service.d.ts +118 -0
- package/dist/attendance/correction-service.d.ts.map +1 -0
- package/dist/attendance/models.d.ts +57 -0
- package/dist/attendance/models.d.ts.map +1 -1
- package/dist/attendance/segments.d.ts +20 -0
- package/dist/attendance/segments.d.ts.map +1 -0
- package/dist/attendance/service.d.ts +106 -22
- package/dist/attendance/service.d.ts.map +1 -1
- package/dist/attendance/write.d.ts +12 -0
- package/dist/attendance/write.d.ts.map +1 -0
- package/dist/attendance.d.ts +2 -0
- package/dist/attendance.d.ts.map +1 -1
- package/dist/attendance.js +3 -323
- package/dist/chunks/{attendance-Cpo4mIID.js → attendance-Cw75uJnT.js} +3 -3
- package/dist/chunks/{attendance-Cpo4mIID.js.map → attendance-Cw75uJnT.js.map} +1 -1
- package/dist/chunks/attendance-DJNytMTN.js +1246 -0
- package/dist/chunks/attendance-DJNytMTN.js.map +1 -0
- package/dist/chunks/models-tUePZ5x7.js +372 -0
- package/dist/chunks/models-tUePZ5x7.js.map +1 -0
- package/dist/chunks/{rollup-Du6uaqyM.js → rollup-CzCb-DxI.js} +211 -6
- package/dist/chunks/rollup-CzCb-DxI.js.map +1 -0
- package/dist/chunks/service-time-entry-BJVSGx33.js +286 -0
- package/dist/chunks/service-time-entry-BJVSGx33.js.map +1 -0
- package/dist/chunks/time-entry-actions-ChT1lcOp.js +576 -0
- package/dist/chunks/time-entry-actions-ChT1lcOp.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -334
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +2020 -168
- package/dist/models/service-snapshots.d.ts.map +1 -1
- package/dist/models/service-time-entry.d.ts +36 -1
- package/dist/models/service-time-entry.d.ts.map +1 -1
- package/dist/recipes.d.ts +124 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/rollup/correction-guard.d.ts +12 -0
- package/dist/rollup/correction-guard.d.ts.map +1 -0
- package/dist/rollup/models.d.ts +31 -1
- package/dist/rollup/models.d.ts.map +1 -1
- package/dist/rollup/service.d.ts +25 -7
- package/dist/rollup/service.d.ts.map +1 -1
- package/dist/rollup/types.d.ts +18 -0
- package/dist/rollup/types.d.ts.map +1 -1
- package/dist/rollup/write.d.ts +2 -0
- package/dist/rollup/write.d.ts.map +1 -1
- package/dist/rollup.d.ts +3 -2
- package/dist/rollup.d.ts.map +1 -1
- package/dist/rollup.js +2 -2
- package/dist/services/action-principal.d.ts +54 -0
- package/dist/services/action-principal.d.ts.map +1 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/time-entry-actions.d.ts +83 -0
- package/dist/services/time-entry-actions.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +902 -40
- package/package.json +8 -7
- package/dist/attendance.js.map +0 -1
- package/dist/chunks/models-_ZbpXWnb.js +0 -176
- package/dist/chunks/models-_ZbpXWnb.js.map +0 -1
- package/dist/chunks/rollup-Du6uaqyM.js.map +0 -1
- package/dist/chunks/service-time-entry-BGj39_EC.js +0 -227
- package/dist/chunks/service-time-entry-BGj39_EC.js.map +0 -1
|
@@ -8,7 +8,14 @@ export declare class AttendancePunch extends SmrtObject {
|
|
|
8
8
|
durationSeconds: number;
|
|
9
9
|
unpaidBreakSeconds: number;
|
|
10
10
|
reviewRequired: boolean;
|
|
11
|
+
/** Why the scheduler closed this punch; empty unless `autoClose` did. Write-once. */
|
|
12
|
+
autoCloseReason: string;
|
|
11
13
|
recordedOffline: boolean;
|
|
14
|
+
/** Optional short consumer-owned capture label (`device`, `web`, `import`, ...); `''` when unknown. */
|
|
15
|
+
source: string;
|
|
16
|
+
/** Qualified type of the device that captured the punch; both device columns or neither. */
|
|
17
|
+
deviceRefType: string;
|
|
18
|
+
deviceRefId: string;
|
|
12
19
|
serviceTimeEntryId: string | null;
|
|
13
20
|
/** Unique while open; closed rows retain independent non-null slots on every dialect. */
|
|
14
21
|
openSlot: string;
|
|
@@ -22,15 +29,60 @@ export declare class AttendanceBreak extends SmrtObject {
|
|
|
22
29
|
startedAt: Date;
|
|
23
30
|
endedAt: Date | null;
|
|
24
31
|
paid: boolean;
|
|
32
|
+
/** Optional short consumer-owned label (`meal`, `rest`, ...); `''` when unspecified. */
|
|
33
|
+
kind: string;
|
|
25
34
|
openSlot: string;
|
|
26
35
|
save(): Promise<this>;
|
|
27
36
|
private saveConsistent;
|
|
37
|
+
delete(): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
declare const SEGMENT_CLOSE_REASONS: readonly ["stop", "switch", "break", "punchOut"];
|
|
40
|
+
/** Why a work segment ended; `''` while it is open. */
|
|
41
|
+
export type AttendanceSegmentCloseReason = (typeof SEGMENT_CLOSE_REASONS)[number] | '';
|
|
42
|
+
/**
|
|
43
|
+
* A running unit of work inside one attendance punch: a work reference plus an
|
|
44
|
+
* optional second (task) reference as queryable columns, so job costing can
|
|
45
|
+
* index and join them. At most one segment is open per punch (`openSlot`). A
|
|
46
|
+
* segment never spans a break; `startBreak` and `punchOut` close it. Segments
|
|
47
|
+
* are attendance evidence and are not themselves service time entries.
|
|
48
|
+
*/
|
|
49
|
+
export declare class AttendanceSegment extends SmrtObject {
|
|
50
|
+
tenantId: string;
|
|
51
|
+
punchId: string;
|
|
52
|
+
/** Qualified class name of the work context (for example a work order). */
|
|
53
|
+
workRefType: string;
|
|
54
|
+
workRefId: string;
|
|
55
|
+
/** Optional second reference (for example an operation); both or neither. */
|
|
56
|
+
taskRefType: string;
|
|
57
|
+
taskRefId: string;
|
|
58
|
+
/** Optional short consumer lane label. */
|
|
59
|
+
kind: string;
|
|
60
|
+
description: string;
|
|
61
|
+
startedAt: Date;
|
|
62
|
+
endedAt: Date | null;
|
|
63
|
+
/** Elapsed whole seconds, set when the segment closes. */
|
|
64
|
+
durationSeconds: number;
|
|
65
|
+
/** `stop`, `switch`, `break` or `punchOut` once closed; `''` while open. */
|
|
66
|
+
closedReason: AttendanceSegmentCloseReason;
|
|
67
|
+
/** Set when a replay time policy asked for review of this segment's boundary. */
|
|
68
|
+
reviewRequired: boolean;
|
|
69
|
+
openSlot: string;
|
|
70
|
+
save(): Promise<this>;
|
|
71
|
+
private saveConsistent;
|
|
72
|
+
delete(): Promise<void>;
|
|
28
73
|
}
|
|
29
74
|
/** Durable success or conflict; conflicts do not mutate attendance. */
|
|
30
75
|
export interface AttendanceReplayOutcome {
|
|
31
76
|
clientId: string;
|
|
32
77
|
punchId?: string;
|
|
78
|
+
/** Work segment a replayed work action started, switched to, stopped or resumed. */
|
|
79
|
+
segmentId?: string;
|
|
80
|
+
/** Effective time stored when a `resolveAt` policy changed it (ISO 8601). */
|
|
81
|
+
resolvedAt?: string;
|
|
82
|
+
/** Refusal message (with `code`); present exactly when the tap was refused. */
|
|
33
83
|
error?: string;
|
|
84
|
+
/** Typed refusal reason; see `AttendanceRefusalCode`. */
|
|
85
|
+
code?: string;
|
|
34
86
|
}
|
|
35
87
|
/** Durable offline-tap outcome; never exposed through generated operations. */
|
|
36
88
|
export declare class AttendanceReplay extends SmrtObject {
|
|
@@ -52,8 +104,13 @@ export declare class AttendancePunchCollection extends SmrtCollection<Attendance
|
|
|
52
104
|
export declare class AttendanceBreakCollection extends SmrtCollection<AttendanceBreak> {
|
|
53
105
|
static readonly _itemClass: typeof AttendanceBreak;
|
|
54
106
|
}
|
|
107
|
+
/** Work segments for job costing and attendance review. */
|
|
108
|
+
export declare class AttendanceSegmentCollection extends SmrtCollection<AttendanceSegment> {
|
|
109
|
+
static readonly _itemClass: typeof AttendanceSegment;
|
|
110
|
+
}
|
|
55
111
|
/** Internal durable replay ledger. */
|
|
56
112
|
export declare class AttendanceReplayCollection extends SmrtCollection<AttendanceReplay> {
|
|
57
113
|
static readonly _itemClass: typeof AttendanceReplay;
|
|
58
114
|
}
|
|
115
|
+
export {};
|
|
59
116
|
//# sourceMappingURL=models.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/attendance/models.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,cAAc,EACd,UAAU,EAGX,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/attendance/models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type AttendanceContext, type AttendanceWork } from './context.js';
|
|
2
|
+
import type { AttendancePunch, AttendanceSegment, AttendanceSegmentCloseReason } from './models.js';
|
|
3
|
+
/** The open segment of a punch, or null. */
|
|
4
|
+
export declare function openSegment(tx: AttendanceContext, punch: AttendancePunch): Promise<AttendanceSegment | null>;
|
|
5
|
+
/** All segments of a punch, oldest first. */
|
|
6
|
+
export declare function listSegments(tx: AttendanceContext, punch: AttendancePunch): Promise<AttendanceSegment[]>;
|
|
7
|
+
/** Close the punch's open segment, if any. Returns it, or null when none was open. */
|
|
8
|
+
export declare function closeOpenSegment(tx: AttendanceContext, punch: AttendancePunch, at: Date, reason: Exclude<AttendanceSegmentCloseReason, ''>): Promise<AttendanceSegment | null>;
|
|
9
|
+
/** Open a segment; refuses while a break or another segment is open. */
|
|
10
|
+
export declare function beginSegment(tx: AttendanceContext, punch: AttendancePunch, at: Date, work: AttendanceWork): Promise<AttendanceSegment>;
|
|
11
|
+
/** Atomically close the open segment and open the next at the same instant. */
|
|
12
|
+
export declare function replaceSegment(tx: AttendanceContext, punch: AttendancePunch, at: Date, work: AttendanceWork): Promise<AttendanceSegment>;
|
|
13
|
+
/** Close the open segment (`stop`); refuses when none is open. */
|
|
14
|
+
export declare function endSegment(tx: AttendanceContext, punch: AttendancePunch, at: Date): Promise<AttendanceSegment>;
|
|
15
|
+
/**
|
|
16
|
+
* Reopen the work a break interrupted: a new segment with the same references
|
|
17
|
+
* as the latest segment, which must have been closed by `startBreak`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function continueSegment(tx: AttendanceContext, punch: AttendancePunch, at: Date): Promise<AttendanceSegment>;
|
|
20
|
+
//# sourceMappingURL=segments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/attendance/segments.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,cAAc,EAEpB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,4BAA4B,EAC7B,MAAM,aAAa,CAAC;AASrB,4CAA4C;AAC5C,wBAAsB,WAAW,CAC/B,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAMnC;AAED,6CAA6C;AAC7C,wBAAsB,YAAY,CAChC,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAK9B;AAED,sFAAsF;AACtF,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,EACtB,EAAE,EAAE,IAAI,EACR,MAAM,EAAE,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC,GAChD,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CASnC;AAED,wEAAwE;AACxE,wBAAsB,YAAY,CAChC,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,EACtB,EAAE,EAAE,IAAI,EACR,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CA4B5B;AAED,+EAA+E;AAC/E,wBAAsB,cAAc,CAClC,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,EACtB,EAAE,EAAE,IAAI,EACR,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,iBAAiB,CAAC,CAQ5B;AAED,kEAAkE;AAClE,wBAAsB,UAAU,CAC9B,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,EACtB,EAAE,EAAE,IAAI,GACP,OAAO,CAAC,iBAAiB,CAAC,CAK5B;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,eAAe,EACtB,EAAE,EAAE,IAAI,GACP,OAAO,CAAC,iBAAiB,CAAC,CAoB5B"}
|
|
@@ -1,27 +1,77 @@
|
|
|
1
1
|
import type { DatabaseInterface } from '@happyvertical/sql';
|
|
2
|
-
import {
|
|
2
|
+
import { type AttendanceActor, type AttendanceBreakOptions, AttendanceConflict, type AttendanceContext, type AttendanceDeviceRef, type AttendancePunchOptions, type AttendanceRefusalCode, type AttendanceWork } from './context.js';
|
|
3
|
+
import { AttendancePunch, type AttendanceReplayOutcome, AttendanceSegment } from './models.js';
|
|
4
|
+
export { type AttendanceActor, type AttendanceBreakOptions, AttendanceConflict, type AttendanceContext, type AttendanceDeviceRef, type AttendancePunchOptions, type AttendanceRefusalCode, type AttendanceWork, validateAttendanceWork, } from './context.js';
|
|
3
5
|
export type { AttendanceReplayOutcome } from './models.js';
|
|
4
|
-
|
|
5
|
-
export interface AttendanceActor {
|
|
6
|
-
tenantId: string;
|
|
7
|
-
profileId: string;
|
|
8
|
-
}
|
|
9
|
-
/** Explicit work attribution for a closed punch's draft evidence entry. */
|
|
10
|
-
export interface AttendanceWork {
|
|
11
|
-
workRefType: string;
|
|
12
|
-
workRefId: string;
|
|
13
|
-
description: string;
|
|
14
|
-
}
|
|
6
|
+
export * from './segments.js';
|
|
15
7
|
/** Offline command with a durable client-generated identifier and device timestamp. */
|
|
16
8
|
export interface AttendanceTap {
|
|
17
9
|
clientId: string;
|
|
18
10
|
at: string;
|
|
19
|
-
action:
|
|
11
|
+
action: AttendanceTapAction;
|
|
20
12
|
paid?: boolean;
|
|
13
|
+
/** Required by `startWork` and `switchWork`; also links evidence on `punchOut`. */
|
|
21
14
|
work?: AttendanceWork;
|
|
15
|
+
/** Recorded on the punch by `punchIn`; hashed with the tap. */
|
|
16
|
+
source?: string;
|
|
17
|
+
/** Recorded on the punch by `punchIn`; hashed with the tap. */
|
|
18
|
+
device?: AttendanceDeviceRef;
|
|
19
|
+
/** Recorded on the break by `startBreak`; hashed with the tap. */
|
|
20
|
+
kind?: string;
|
|
21
|
+
}
|
|
22
|
+
/** Punch and break actions plus the work-segment actions (`stopWork` is "pause"). */
|
|
23
|
+
export type AttendanceTapAction = 'punchIn' | 'punchOut' | 'startBreak' | 'endBreak' | 'startWork' | 'switchWork' | 'stopWork' | 'resumeWork';
|
|
24
|
+
/** What a time policy sees for one tap that has not been replayed yet. */
|
|
25
|
+
export interface AttendanceTimeInput {
|
|
26
|
+
/** The tap exactly as sent. */
|
|
27
|
+
tap: AttendanceTap;
|
|
28
|
+
/** The tap's device time. */
|
|
29
|
+
deviceAt: Date;
|
|
30
|
+
/** When the server received the batch. */
|
|
31
|
+
serverNow: Date;
|
|
32
|
+
/** `serverNow - deviceAt` in milliseconds: how long the tap waited. */
|
|
33
|
+
waitedMs: number;
|
|
34
|
+
/** The trusted actor the tap replays for. */
|
|
35
|
+
actor: AttendanceActor;
|
|
36
|
+
}
|
|
37
|
+
/** The effective time a policy chose, and whether a person should look at it. */
|
|
38
|
+
export interface AttendanceResolvedTime {
|
|
39
|
+
at: Date;
|
|
40
|
+
/** Flags the resulting work segment (punches are always flagged offline). */
|
|
41
|
+
reviewRequired?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Why a consumer refuses or rewrites the stored reason of a refused tap. */
|
|
44
|
+
export interface AttendanceRefusal {
|
|
45
|
+
code: AttendanceRefusalCode;
|
|
46
|
+
/** Replaces the default message when given. */
|
|
47
|
+
message?: string;
|
|
22
48
|
}
|
|
23
|
-
/**
|
|
24
|
-
export
|
|
49
|
+
/** A resolved auto-close deadline and, optionally, why the punch closed then. */
|
|
50
|
+
export interface AttendanceAutoCloseDecision {
|
|
51
|
+
deadline: Date;
|
|
52
|
+
/** Recorded as `autoCloseReason` (1 to 200 characters); defaults to `deadline`. */
|
|
53
|
+
reason?: string;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Fixed maximum open seconds, or a per-punch resolver returning the deadline
|
|
57
|
+
* (a Date or a decision) or null to leave the punch open.
|
|
58
|
+
*/
|
|
59
|
+
export type AttendanceAutoCloseDeadline = number | ((punch: AttendancePunch) => Date | AttendanceAutoCloseDecision | null | undefined | Promise<Date | AttendanceAutoCloseDecision | null | undefined>);
|
|
60
|
+
export interface AttendanceReplayOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Choose each tap's effective time (for example the device time inside a
|
|
63
|
+
* window, else the server arrival time). The receipt still hashes the tap as
|
|
64
|
+
* sent, so retries with the same clientId match; the resolved time is what is
|
|
65
|
+
* stored. Called once per tap that has no receipt yet, inside its transaction.
|
|
66
|
+
*/
|
|
67
|
+
resolveAt?: (input: AttendanceTimeInput) => AttendanceResolvedTime | Promise<AttendanceResolvedTime>;
|
|
68
|
+
/** Clock for `serverNow`; defaults to `new Date()` per tap. */
|
|
69
|
+
now?: () => Date;
|
|
70
|
+
/**
|
|
71
|
+
* Name the stored code (and optionally message) of a refused tap. Without it,
|
|
72
|
+
* the refusal's own `AttendanceConflict.code` is stored.
|
|
73
|
+
*/
|
|
74
|
+
refusal?: (tap: AttendanceTap, error: AttendanceConflict) => AttendanceRefusal | undefined | void;
|
|
25
75
|
}
|
|
26
76
|
/**
|
|
27
77
|
* Attendance mutations bound to a trusted tenant/profile. Applications authorize
|
|
@@ -34,31 +84,65 @@ export declare class AttendanceService {
|
|
|
34
84
|
private readonly actor;
|
|
35
85
|
constructor(db: DatabaseInterface, actor: AttendanceActor);
|
|
36
86
|
private identity;
|
|
87
|
+
/**
|
|
88
|
+
* Run `operation` in the actor's serialized attendance transaction. The
|
|
89
|
+
* context's collections share the executor, so corrections and replay can
|
|
90
|
+
* compose several attendance mutations (with the segment helpers) atomically.
|
|
91
|
+
* Results that are punches or segments are re-read after commit.
|
|
92
|
+
*/
|
|
93
|
+
withTransaction<T>(operation: (context: AttendanceContext) => Promise<T>): Promise<T>;
|
|
37
94
|
private transact;
|
|
38
95
|
private date;
|
|
39
96
|
private open;
|
|
40
97
|
private chronological;
|
|
41
98
|
/** Open one punch; the database unique slot also protects direct model writers. */
|
|
42
|
-
punchIn(at?: Date): Promise<AttendancePunch>;
|
|
99
|
+
punchIn(at?: Date, options?: AttendancePunchOptions): Promise<AttendancePunch>;
|
|
43
100
|
/** Close the punch and any active break; optionally create linked draft evidence. */
|
|
44
101
|
punchOut(at: Date, work?: AttendanceWork): Promise<AttendancePunch>;
|
|
45
102
|
/** Begin a break; paid defaults false and must be explicitly configured by the caller. */
|
|
46
|
-
startBreak(at: Date, paid?: boolean): Promise<AttendancePunch>;
|
|
47
|
-
/**
|
|
48
|
-
|
|
103
|
+
startBreak(at: Date, paid?: boolean, options?: AttendanceBreakOptions): Promise<AttendancePunch>;
|
|
104
|
+
/**
|
|
105
|
+
* End the current break. With `{ resumeWork: true }` the work interrupted by
|
|
106
|
+
* `startBreak` resumes at the same instant, atomically with the break end.
|
|
107
|
+
*/
|
|
108
|
+
endBreak(at: Date, options?: {
|
|
109
|
+
resumeWork?: boolean;
|
|
110
|
+
}): Promise<AttendancePunch>;
|
|
111
|
+
/** Open a work segment in the open punch; refuses during a break or while one is open. */
|
|
112
|
+
startWork(at: Date, work: AttendanceWork): Promise<AttendanceSegment>;
|
|
113
|
+
/** Atomically close the open segment and open the next one at `at`. */
|
|
114
|
+
switchWork(at: Date, work: AttendanceWork): Promise<AttendanceSegment>;
|
|
115
|
+
/** Close the open segment without starting another. */
|
|
116
|
+
stopWork(at: Date): Promise<AttendanceSegment>;
|
|
117
|
+
/** Reopen the work a break interrupted (the latest segment must have closed on `startBreak`). */
|
|
118
|
+
resumeWork(at: Date): Promise<AttendanceSegment>;
|
|
119
|
+
/** The open work segment of the actor's open punch, or null. */
|
|
120
|
+
currentWork(): Promise<AttendanceSegment | null>;
|
|
121
|
+
/** Work segments of one of the actor's punches, oldest first. */
|
|
122
|
+
segments(punchId: string): Promise<AttendanceSegment[]>;
|
|
49
123
|
private transition;
|
|
124
|
+
/** Run one replayed tap on `tx`; work actions share the punch changes' transaction. */
|
|
125
|
+
private apply;
|
|
50
126
|
private validateWork;
|
|
51
127
|
private link;
|
|
52
128
|
/** Idempotently link a closed, owned punch to draft service evidence. */
|
|
53
129
|
linkServiceTimeEntry(punchId: string, work: AttendanceWork): Promise<AttendancePunch>;
|
|
54
|
-
/**
|
|
55
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Close the open punch once its deadline has passed, flagging it for review.
|
|
132
|
+
* `deadline` is either a fixed maximum open duration in seconds (closing at
|
|
133
|
+
* `startedAt + seconds`, reason `maxDuration`) or a resolver called with the
|
|
134
|
+
* open punch that returns its deadline (a `Date`, or `{ deadline, reason }`),
|
|
135
|
+
* or null to leave it open. The consumer owns time zones and shop-day rules.
|
|
136
|
+
* The open work segment and break close at the deadline; returns the closed
|
|
137
|
+
* punch, or null when nothing was due.
|
|
138
|
+
*/
|
|
139
|
+
autoClose(now: Date, deadline: AttendanceAutoCloseDeadline): Promise<AttendancePunch | null>;
|
|
56
140
|
/**
|
|
57
141
|
* Replay device timestamps in order (ties use clientId). Committed attendance
|
|
58
142
|
* wins: stale/state-conflicting taps get durable refusals; identical retries
|
|
59
143
|
* return the same outcome, changed payloads using a key are rejected. A
|
|
60
144
|
* database failure rolls back its tap and receipt and remains retryable.
|
|
61
145
|
*/
|
|
62
|
-
replay(taps: readonly AttendanceTap[]): Promise<AttendanceReplayOutcome[]>;
|
|
146
|
+
replay(taps: readonly AttendanceTap[], options?: AttendanceReplayOptions): Promise<AttendanceReplayOutcome[]>;
|
|
63
147
|
}
|
|
64
148
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/attendance/service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/attendance/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
/** True while `object` is being saved by `AttendanceCorrectionService`. */
|
|
3
|
+
export declare function isCorrectionWrite(object: SmrtObject): boolean;
|
|
4
|
+
/** Save `object` with closed-interval immutability lifted for this one write. */
|
|
5
|
+
export declare function persistCorrection<T extends SmrtObject>(object: T): Promise<T>;
|
|
6
|
+
/** Delete a closed break or segment through the correction capability. */
|
|
7
|
+
export declare function deleteCorrection<T extends SmrtObject>(object: T): Promise<void>;
|
|
8
|
+
/** True while `AttendanceService.autoClose` is saving `object`. */
|
|
9
|
+
export declare function isAutoCloseWrite(object: SmrtObject): boolean;
|
|
10
|
+
/** Save `object` with its auto-close reason writable for this one write. */
|
|
11
|
+
export declare function persistAutoClose<T extends SmrtObject>(object: T): Promise<T>;
|
|
12
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/attendance/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAO3D,2EAA2E;AAC3E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAE7D;AAED,iFAAiF;AACjF,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,UAAU,EAC1D,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,CAAC,CAAC,CAQZ;AAED,0EAA0E;AAC1E,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EACzD,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,IAAI,CAAC,CAOf;AAMD,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAE5D;AAED,4EAA4E;AAC5E,wBAAsB,gBAAgB,CAAC,CAAC,SAAS,UAAU,EACzD,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,CAAC,CAAC,CAQZ"}
|
package/dist/attendance.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Tenant-scoped punches, breaks, automatic close and offline replay. */
|
|
2
2
|
import './__smrt-register__.js';
|
|
3
|
+
export * from './attendance/correction-models.js';
|
|
4
|
+
export * from './attendance/correction-service.js';
|
|
3
5
|
export * from './attendance/models.js';
|
|
4
6
|
export * from './attendance/service.js';
|
|
5
7
|
//# sourceMappingURL=attendance.d.ts.map
|
package/dist/attendance.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"attendance.d.ts","sourceRoot":"","sources":["../src/attendance.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,wBAAwB,CAAC;AAEhC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"attendance.d.ts","sourceRoot":"","sources":["../src/attendance.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,wBAAwB,CAAC;AAEhC,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC"}
|