@happyvertical/smrt-timesheets 0.55.6 → 0.55.8

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.
@@ -0,0 +1,227 @@
1
+ import { SERVICE_TIME_ENTRY_STATUS_TRANSITIONS } from "../types.js";
2
+ import { ObjectRegistry, SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
3
+ import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
+ //#region src/__smrt-register__.ts
5
+ ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-timesheets","packageVersion":"0.55.8","objects":{"@happyvertical/smrt-timesheets:AttendancePunch":{"name":"attendancepunch","className":"AttendancePunch","qualifiedName":"@happyvertical/smrt-timesheets:AttendancePunch","collection":"attendancepunches","description":"A tenant-scoped interval of attendance, independent of billable work.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"profileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile"},"startedAt":{"type":"datetime","required":false},"endedAt":{"type":"datetime","required":false},"durationSeconds":{"type":"integer","required":true,"default":0},"unpaidBreakSeconds":{"type":"integer","required":true,"default":0},"reviewRequired":{"type":"boolean","required":true,"default":false},"recordedOffline":{"type":"boolean","required":true,"default":false},"serviceTimeEntryId":{"type":"foreignKey","required":false,"related":"ServiceTimeEntry","_meta":{"nullable":true}},"openSlot":{"type":"text","required":true,"_meta":{"required":true}}},"methods":{"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"attendance_punches","indexes":[{"name":"attendance_punches_open_owner_key","columns":["tenantId","profileId","openSlot"],"unique":true}],"api":{"include":["list","get"]},"cli":{"include":["list","get"]},"mcp":{"include":["list","get"]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"AttendancePunch","collectionExportName":"AttendancePunchCollection","validationRules":[{"field":"durationSeconds","rule":"required","fieldType":"integer"},{"field":"unpaidBreakSeconds","rule":"required","fieldType":"integer"},{"field":"reviewRequired","rule":"required","fieldType":"boolean"},{"field":"recordedOffline","rule":"required","fieldType":"boolean"},{"field":"openSlot","rule":"required","fieldType":"text"}],"schema":{"tableName":"attendance_punches","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_punches\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"profile_id\\" UUID,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"duration_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"unpaid_break_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"review_required\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"recorded_offline\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"service_time_entry_id\\" UUID,\\n \\"open_slot\\" TEXT NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"duration_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"unpaid_break_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"review_required":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"recorded_offline":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"service_time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"open_slot":{"type":"TEXT","notNull":true,"unique":false}},"indexes":[{"name":"attendance_punches_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_punches_open_owner_key","columns":["tenant_id","profile_id","open_slot"],"unique":true},{"name":"attendance_punches_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"attendance_punches_profile_id_idx","columns":["profile_id"]},{"name":"attendance_punches_service_time_entry_id_idx","columns":["service_time_entry_id"]}],"version":"eeca63b1"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:AttendanceBreak":{"name":"attendancebreak","className":"AttendanceBreak","qualifiedName":"@happyvertical/smrt-timesheets:AttendanceBreak","collection":"attendancebreaks","description":"A paid or unpaid break inside one attendance punch.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"punchId":{"type":"foreignKey","required":false,"related":"AttendancePunch"},"startedAt":{"type":"datetime","required":false},"endedAt":{"type":"datetime","required":false},"paid":{"type":"boolean","required":true,"default":false},"openSlot":{"type":"text","required":true,"_meta":{"required":true}}},"methods":{"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"attendance_breaks","indexes":[{"name":"attendance_breaks_open_punch_key","columns":["tenantId","punchId","openSlot"],"unique":true}],"api":{"include":["list","get"]},"cli":{"include":["list","get"]},"mcp":{"include":["list","get"]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"AttendanceBreak","collectionExportName":"AttendanceBreakCollection","validationRules":[{"field":"paid","rule":"required","fieldType":"boolean"},{"field":"openSlot","rule":"required","fieldType":"text"}],"schema":{"tableName":"attendance_breaks","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_breaks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"punch_id\\" UUID,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"paid\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"open_slot\\" TEXT NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"punch_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"attendance_punches","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"paid":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"open_slot":{"type":"TEXT","notNull":true,"unique":false}},"indexes":[{"name":"attendance_breaks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_breaks_open_punch_key","columns":["tenant_id","punch_id","open_slot"],"unique":true},{"name":"attendance_breaks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"attendance_breaks_punch_id_idx","columns":["punch_id"]}],"version":"00cb739e"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:AttendanceReplay":{"name":"attendancereplay","className":"AttendanceReplay","qualifiedName":"@happyvertical/smrt-timesheets:AttendanceReplay","collection":"attendancereplays","description":"Durable offline-tap outcome; never exposed through generated operations.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"replayKey":{"type":"text","required":true,"_meta":{"required":true,"unique":true}},"content":{"type":"text","required":false,"_meta":{}},"outcome":{"type":"text","required":false,"_meta":{}}},"methods":{"getOutcome":{"name":"getOutcome","async":false,"parameters":[],"returnType":"AttendanceReplayOutcome","isStatic":false,"isPublic":true},"setOutcome":{"name":"setOutcome","async":false,"parameters":[{"name":"value","type":"AttendanceReplayOutcome","optional":false}],"returnType":"void","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"attendance_replays","sensitive":true,"api":{"include":[]},"cli":{"include":[]},"mcp":{"include":[]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"AttendanceReplay","collectionExportName":"AttendanceReplayCollection","validationRules":[{"field":"replayKey","rule":"required","fieldType":"text"}],"schema":{"tableName":"attendance_replays","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_replays\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"replay_key\\" TEXT NOT NULL UNIQUE,\\n \\"content\\" TEXT,\\n \\"outcome\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"replay_key":{"type":"TEXT","notNull":true,"unique":true},"content":{"type":"TEXT","notNull":false,"unique":false},"outcome":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"attendance_replays_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_replays_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"f051b7b6"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:AttendancePunchCollection":{"name":"attendancepunchcollection","className":"AttendancePunchCollection","qualifiedName":"@happyvertical/smrt-timesheets:AttendancePunchCollection","collection":"attendancepunches","description":"Punches for attendance and period rollup.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"attendance_punches"},"extends":"SmrtCollection","extendsTypeArg":"AttendancePunch","exportName":"AttendancePunchCollection","collectionExportName":"AttendancePunchCollectionCollection","schema":{"tableName":"attendance_punches","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_punches\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"profile_id\\" UUID,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"duration_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"unpaid_break_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"review_required\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"recorded_offline\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"service_time_entry_id\\" UUID,\\n \\"open_slot\\" TEXT NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"duration_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"unpaid_break_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"review_required":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"recorded_offline":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"service_time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"open_slot":{"type":"TEXT","notNull":true,"unique":false}},"indexes":[{"name":"attendance_punches_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_punches_open_owner_key","columns":["tenant_id","profile_id","open_slot"],"unique":true},{"name":"attendance_punches_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"attendance_punches_profile_id_idx","columns":["profile_id"]},{"name":"attendance_punches_service_time_entry_id_idx","columns":["service_time_entry_id"]}],"version":"eeca63b1"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:AttendanceBreakCollection":{"name":"attendancebreakcollection","className":"AttendanceBreakCollection","qualifiedName":"@happyvertical/smrt-timesheets:AttendanceBreakCollection","collection":"attendancebreaks","description":"Break intervals for net duration and period clipping.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"attendance_breaks"},"extends":"SmrtCollection","extendsTypeArg":"AttendanceBreak","exportName":"AttendanceBreakCollection","collectionExportName":"AttendanceBreakCollectionCollection","schema":{"tableName":"attendance_breaks","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_breaks\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"punch_id\\" UUID,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"paid\\" BOOLEAN NOT NULL DEFAULT FALSE,\\n \\"open_slot\\" TEXT NOT NULL\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"punch_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"attendance_punches","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"paid":{"type":"BOOLEAN","notNull":true,"unique":false,"default":false},"open_slot":{"type":"TEXT","notNull":true,"unique":false}},"indexes":[{"name":"attendance_breaks_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_breaks_open_punch_key","columns":["tenant_id","punch_id","open_slot"],"unique":true},{"name":"attendance_breaks_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"attendance_breaks_punch_id_idx","columns":["punch_id"]}],"version":"00cb739e"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:AttendanceReplayCollection":{"name":"attendancereplaycollection","className":"AttendanceReplayCollection","qualifiedName":"@happyvertical/smrt-timesheets:AttendanceReplayCollection","collection":"attendancereplays","description":"Internal durable replay ledger.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/attendance/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"attendance_replays"},"extends":"SmrtCollection","extendsTypeArg":"AttendanceReplay","exportName":"AttendanceReplayCollection","collectionExportName":"AttendanceReplayCollectionCollection","schema":{"tableName":"attendance_replays","ddl":"CREATE TABLE IF NOT EXISTS \\"attendance_replays\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"replay_key\\" TEXT NOT NULL UNIQUE,\\n \\"content\\" TEXT,\\n \\"outcome\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"replay_key":{"type":"TEXT","notNull":true,"unique":true},"content":{"type":"TEXT","notNull":false,"unique":false},"outcome":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"attendance_replays_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"attendance_replays_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"f051b7b6"},"importPath":"@happyvertical/smrt-timesheets/attendance"},"@happyvertical/smrt-timesheets:ServiceChargeSnapshot":{"name":"servicechargesnapshot","className":"ServiceChargeSnapshot","qualifiedName":"@happyvertical/smrt-timesheets:ServiceChargeSnapshot","collection":"servicechargesnapshots","description":"Immutable client-charge snapshot for one approved time entry. Money is integer minor units, consistent with smrt-commerce (#2401).","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-snapshots.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"timeEntryId":{"type":"foreignKey","required":true,"related":"ServiceTimeEntry","_meta":{"required":true}},"amount":{"type":"integer","required":false,"default":0},"currency":{"type":"text","required":false,"_meta":{}},"pricingVersion":{"type":"text","required":false,"_meta":{}},"strategy":{"type":"text","required":false,"_meta":{}},"rateSnapshot":{"type":"text","required":false,"_meta":{}},"sourceChargeRef":{"type":"text","required":false,"_meta":{}},"createdAt":{"type":"datetime","required":false}},"methods":{"initialize":{"name":"initialize","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"service_charge_snapshots","previousQualifiedNames":["@happyvertical/smrt-projects:ServiceChargeSnapshot"],"conflictColumns":["time_entry_id"],"api":{"include":["list","get"]},"cli":{"include":["list","get"]},"mcp":{"include":["list","get"]},"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"ServiceChargeSnapshot","collectionExportName":"ServiceChargeSnapshotCollection","validationRules":[{"field":"timeEntryId","rule":"required","fieldType":"foreignKey"}],"schema":{"tableName":"service_charge_snapshots","ddl":"CREATE TABLE IF NOT EXISTS \\"service_charge_snapshots\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"time_entry_id\\" UUID NOT NULL,\\n \\"amount\\" INTEGER DEFAULT 0,\\n \\"currency\\" TEXT,\\n \\"pricing_version\\" TEXT,\\n \\"strategy\\" TEXT,\\n \\"rate_snapshot\\" TEXT,\\n \\"source_charge_ref\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"CASCADE","onUpdate":"CASCADE"}},"amount":{"type":"INTEGER","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false},"pricing_version":{"type":"TEXT","notNull":false,"unique":false},"strategy":{"type":"TEXT","notNull":false,"unique":false},"rate_snapshot":{"type":"TEXT","notNull":false,"unique":false},"source_charge_ref":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_charge_snapshots_time_entry_id_idx","columns":["time_entry_id"],"unique":true},{"name":"service_charge_snapshots_slug_context_idx","columns":["slug","context"]},{"name":"service_charge_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"1393a1e2"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:ServiceCompensationSnapshot":{"name":"servicecompensationsnapshot","className":"ServiceCompensationSnapshot","qualifiedName":"@happyvertical/smrt-timesheets:ServiceCompensationSnapshot","collection":"servicecompensationsnapshots","description":"Immutable provider-compensation snapshot for one approved time entry, kept separate from the client charge so the margin is charge - compensation.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-snapshots.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"timeEntryId":{"type":"foreignKey","required":true,"related":"ServiceTimeEntry","_meta":{"required":true}},"amount":{"type":"integer","required":false,"default":0},"currency":{"type":"text","required":false,"_meta":{}},"termsVersion":{"type":"text","required":false,"_meta":{}},"rateSnapshot":{"type":"text","required":false,"_meta":{}},"createdAt":{"type":"datetime","required":false}},"methods":{"initialize":{"name":"initialize","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"service_compensation_snapshots","previousQualifiedNames":["@happyvertical/smrt-projects:ServiceCompensationSnapshot"],"conflictColumns":["time_entry_id"],"api":{"include":["list","get"]},"cli":{"include":["list","get"]},"mcp":{"include":["list","get"]},"tenantScoped":{"mode":"optional"}},"extends":"SmrtObject","exportName":"ServiceCompensationSnapshot","collectionExportName":"ServiceCompensationSnapshotCollection","validationRules":[{"field":"timeEntryId","rule":"required","fieldType":"foreignKey"}],"schema":{"tableName":"service_compensation_snapshots","ddl":"CREATE TABLE IF NOT EXISTS \\"service_compensation_snapshots\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"time_entry_id\\" UUID NOT NULL,\\n \\"amount\\" INTEGER DEFAULT 0,\\n \\"currency\\" TEXT,\\n \\"terms_version\\" TEXT,\\n \\"rate_snapshot\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"CASCADE","onUpdate":"CASCADE"}},"amount":{"type":"INTEGER","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false},"terms_version":{"type":"TEXT","notNull":false,"unique":false},"rate_snapshot":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_compensation_snapshots_time_entry_id_idx","columns":["time_entry_id"],"unique":true},{"name":"service_compensation_snapshots_slug_context_idx","columns":["slug","context"]},{"name":"service_compensation_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"cd8670e5"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:ServiceChargeSnapshotCollection":{"name":"servicechargesnapshotcollection","className":"ServiceChargeSnapshotCollection","qualifiedName":"@happyvertical/smrt-timesheets:ServiceChargeSnapshotCollection","collection":"servicechargesnapshots","description":"Collection over service_charge_snapshots.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-snapshots.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"service_charge_snapshots"},"extends":"SmrtCollection","extendsTypeArg":"ServiceChargeSnapshot","exportName":"ServiceChargeSnapshotCollection","collectionExportName":"ServiceChargeSnapshotCollectionCollection","schema":{"tableName":"service_charge_snapshots","ddl":"CREATE TABLE IF NOT EXISTS \\"service_charge_snapshots\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"time_entry_id\\" UUID NOT NULL,\\n \\"amount\\" INTEGER DEFAULT 0,\\n \\"currency\\" TEXT,\\n \\"pricing_version\\" TEXT,\\n \\"strategy\\" TEXT,\\n \\"rate_snapshot\\" TEXT,\\n \\"source_charge_ref\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"CASCADE","onUpdate":"CASCADE"}},"amount":{"type":"INTEGER","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false},"pricing_version":{"type":"TEXT","notNull":false,"unique":false},"strategy":{"type":"TEXT","notNull":false,"unique":false},"rate_snapshot":{"type":"TEXT","notNull":false,"unique":false},"source_charge_ref":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_charge_snapshots_time_entry_id_idx","columns":["time_entry_id"],"unique":true},{"name":"service_charge_snapshots_slug_context_idx","columns":["slug","context"]},{"name":"service_charge_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"1393a1e2"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:ServiceCompensationSnapshotCollection":{"name":"servicecompensationsnapshotcollection","className":"ServiceCompensationSnapshotCollection","qualifiedName":"@happyvertical/smrt-timesheets:ServiceCompensationSnapshotCollection","collection":"servicecompensationsnapshots","description":"Collection over service_compensation_snapshots.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-snapshots.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"service_compensation_snapshots"},"extends":"SmrtCollection","extendsTypeArg":"ServiceCompensationSnapshot","exportName":"ServiceCompensationSnapshotCollection","collectionExportName":"ServiceCompensationSnapshotCollectionCollection","schema":{"tableName":"service_compensation_snapshots","ddl":"CREATE TABLE IF NOT EXISTS \\"service_compensation_snapshots\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"time_entry_id\\" UUID NOT NULL,\\n \\"amount\\" INTEGER DEFAULT 0,\\n \\"currency\\" TEXT,\\n \\"terms_version\\" TEXT,\\n \\"rate_snapshot\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"time_entry_id":{"type":"UUID","referenceKind":"foreignKey","notNull":true,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"CASCADE","onUpdate":"CASCADE"}},"amount":{"type":"INTEGER","notNull":false,"unique":false,"default":0},"currency":{"type":"TEXT","notNull":false,"unique":false},"terms_version":{"type":"TEXT","notNull":false,"unique":false},"rate_snapshot":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_compensation_snapshots_time_entry_id_idx","columns":["time_entry_id"],"unique":true},{"name":"service_compensation_snapshots_slug_context_idx","columns":["slug","context"]},{"name":"service_compensation_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"cd8670e5"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:ServiceTimeEntry":{"name":"servicetimeentry","className":"ServiceTimeEntry","qualifiedName":"@happyvertical/smrt-timesheets:ServiceTimeEntry","collection":"servicetimeentries","description":"A person or agent worked this long on this thing, and someone approved it.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-time-entry.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":false,"_meta":{"sqlType":"UUID","nullable":true,"__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":false,"autoPopulate":true,"nullable":true,"mode":"optional","field":"tenantId","allowSuperAdminBypass":false}}},"workRefType":{"type":"text","required":false,"_meta":{"nullable":true}},"workRefId":{"type":"text","required":false,"_meta":{"nullable":true}},"participantKind":{"type":"text","required":false,"_meta":{},"enum":["human","agent"]},"participantProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"nullable":true}},"agentRef":{"type":"text","required":false,"_meta":{}},"source":{"type":"text","required":false,"_meta":{},"enum":["timer","manual","import","agent"]},"description":{"type":"text","required":false,"_meta":{}},"startedAt":{"type":"datetime","required":false},"endedAt":{"type":"datetime","required":false},"durationSeconds":{"type":"integer","required":false,"_meta":{"nullable":true}},"evidence":{"type":"text","required":false,"_meta":{}},"status":{"type":"text","required":false,"_meta":{},"enum":["draft","submitted","approved","rejected","corrected"]},"submittedAt":{"type":"datetime","required":false},"submittedByProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"nullable":true}},"approvedAt":{"type":"datetime","required":false},"approvedByProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"nullable":true}},"approvalPath":{"type":"text","required":false,"_meta":{}},"rejectedAt":{"type":"datetime","required":false},"rejectedByProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"nullable":true}},"rejectionReason":{"type":"text","required":false,"_meta":{}},"correctionOfId":{"type":"foreignKey","required":false,"related":"ServiceTimeEntry"},"metadata":{"type":"text","required":false,"_meta":{}}},"methods":{"getEvidence":{"name":"getEvidence","async":false,"parameters":[],"returnType":"ServiceEvidence[]","isStatic":false,"isPublic":true},"setEvidence":{"name":"setEvidence","async":false,"parameters":[{"name":"value","type":"ServiceEvidence[]","optional":false}],"returnType":"void","isStatic":false,"isPublic":true},"getMetadata":{"name":"getMetadata","async":false,"parameters":[],"returnType":"Record<string, unknown>","isStatic":false,"isPublic":true},"setMetadata":{"name":"setMetadata","async":false,"parameters":[{"name":"value","type":"Record<string, unknown>","optional":false}],"returnType":"void","isStatic":false,"isPublic":true},"durationHoursExact":{"name":"durationHoursExact","async":false,"parameters":[],"returnType":"string | null","isStatic":false,"isPublic":true},"durationHours":{"name":"durationHours","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"requireDurationSeconds":{"name":"requireDurationSeconds","async":false,"parameters":[],"returnType":"number","isStatic":false,"isPublic":true},"initialize":{"name":"initialize","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"service_time_entries","previousQualifiedNames":["@happyvertical/smrt-projects:ServiceTimeEntry"],"api":{"include":["list","get"]},"cli":{"include":["list","get"]},"mcp":{"include":["list","get"]},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"ServiceTimeEntry","collectionExportName":"ServiceTimeEntryCollection","schema":{"tableName":"service_time_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"service_time_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"work_ref_type\\" TEXT,\\n \\"work_ref_id\\" TEXT,\\n \\"participant_kind\\" TEXT,\\n \\"participant_profile_id\\" UUID,\\n \\"agent_ref\\" TEXT,\\n \\"source\\" TEXT,\\n \\"description\\" TEXT,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"duration_seconds\\" INTEGER,\\n \\"evidence\\" TEXT,\\n \\"status\\" TEXT,\\n \\"submitted_at\\" TIMESTAMP,\\n \\"submitted_by_profile_id\\" UUID,\\n \\"approved_at\\" TIMESTAMP,\\n \\"approved_by_profile_id\\" UUID,\\n \\"approval_path\\" TEXT,\\n \\"rejected_at\\" TIMESTAMP,\\n \\"rejected_by_profile_id\\" UUID,\\n \\"rejection_reason\\" TEXT,\\n \\"correction_of_id\\" UUID,\\n \\"metadata\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"work_ref_type":{"type":"TEXT","notNull":false,"unique":false},"work_ref_id":{"type":"TEXT","notNull":false,"unique":false},"participant_kind":{"type":"TEXT","notNull":false,"unique":false},"participant_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"agent_ref":{"type":"TEXT","notNull":false,"unique":false},"source":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"duration_seconds":{"type":"INTEGER","notNull":false,"unique":false},"evidence":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"submitted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"submitted_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"approved_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"approved_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"approval_path":{"type":"TEXT","notNull":false,"unique":false},"rejected_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"rejected_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"rejection_reason":{"type":"TEXT","notNull":false,"unique":false},"correction_of_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"metadata":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_time_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"service_time_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"service_time_entries_participant_profile_id_idx","columns":["participant_profile_id"]},{"name":"service_time_entries_submitted_by_profile_id_idx","columns":["submitted_by_profile_id"]},{"name":"service_time_entries_approved_by_profile_id_idx","columns":["approved_by_profile_id"]},{"name":"service_time_entries_rejected_by_profile_id_idx","columns":["rejected_by_profile_id"]},{"name":"service_time_entries_correction_of_id_idx","columns":["correction_of_id"]}],"version":"05578ed7"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:ServiceTimeEntryCollection":{"name":"servicetimeentrycollection","className":"ServiceTimeEntryCollection","qualifiedName":"@happyvertical/smrt-timesheets:ServiceTimeEntryCollection","collection":"servicetimeentries","description":"Collection over service_time_entries.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/models/service-time-entry.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{"forWork":{"name":"forWork","async":true,"parameters":[{"name":"workRefType","type":"string","optional":false},{"name":"workRefId","type":"string","optional":false}],"returnType":"Promise<ServiceTimeEntry[]>","isStatic":false,"isPublic":true},"pendingApproval":{"name":"pendingApproval","async":true,"parameters":[],"returnType":"Promise<ServiceTimeEntry[]>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"service_time_entries"},"extends":"SmrtCollection","extendsTypeArg":"ServiceTimeEntry","exportName":"ServiceTimeEntryCollection","collectionExportName":"ServiceTimeEntryCollectionCollection","schema":{"tableName":"service_time_entries","ddl":"CREATE TABLE IF NOT EXISTS \\"service_time_entries\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID,\\n \\"work_ref_type\\" TEXT,\\n \\"work_ref_id\\" TEXT,\\n \\"participant_kind\\" TEXT,\\n \\"participant_profile_id\\" UUID,\\n \\"agent_ref\\" TEXT,\\n \\"source\\" TEXT,\\n \\"description\\" TEXT,\\n \\"started_at\\" TIMESTAMP,\\n \\"ended_at\\" TIMESTAMP,\\n \\"duration_seconds\\" INTEGER,\\n \\"evidence\\" TEXT,\\n \\"status\\" TEXT,\\n \\"submitted_at\\" TIMESTAMP,\\n \\"submitted_by_profile_id\\" UUID,\\n \\"approved_at\\" TIMESTAMP,\\n \\"approved_by_profile_id\\" UUID,\\n \\"approval_path\\" TEXT,\\n \\"rejected_at\\" TIMESTAMP,\\n \\"rejected_by_profile_id\\" UUID,\\n \\"rejection_reason\\" TEXT,\\n \\"correction_of_id\\" UUID,\\n \\"metadata\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":false,"unique":false},"work_ref_type":{"type":"TEXT","notNull":false,"unique":false},"work_ref_id":{"type":"TEXT","notNull":false,"unique":false},"participant_kind":{"type":"TEXT","notNull":false,"unique":false},"participant_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"agent_ref":{"type":"TEXT","notNull":false,"unique":false},"source":{"type":"TEXT","notNull":false,"unique":false},"description":{"type":"TEXT","notNull":false,"unique":false},"started_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ended_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"duration_seconds":{"type":"INTEGER","notNull":false,"unique":false},"evidence":{"type":"TEXT","notNull":false,"unique":false},"status":{"type":"TEXT","notNull":false,"unique":false},"submitted_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"submitted_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"approved_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"approved_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"approval_path":{"type":"TEXT","notNull":false,"unique":false},"rejected_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"rejected_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"rejection_reason":{"type":"TEXT","notNull":false,"unique":false},"correction_of_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"service_time_entries","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"metadata":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"service_time_entries_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true,"nullsNotDistinct":true},{"name":"service_time_entries_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"service_time_entries_participant_profile_id_idx","columns":["participant_profile_id"]},{"name":"service_time_entries_submitted_by_profile_id_idx","columns":["submitted_by_profile_id"]},{"name":"service_time_entries_approved_by_profile_id_idx","columns":["approved_by_profile_id"]},{"name":"service_time_entries_rejected_by_profile_id_idx","columns":["rejected_by_profile_id"]},{"name":"service_time_entries_correction_of_id_idx","columns":["correction_of_id"]}],"version":"05578ed7"},"importPath":"@happyvertical/smrt-timesheets"},"@happyvertical/smrt-timesheets:PeriodTimecard":{"name":"periodtimecard","className":"PeriodTimecard","qualifiedName":"@happyvertical/smrt-timesheets:PeriodTimecard","collection":"periodtimecards","description":"One person's immutable-on-confirmation period snapshot, in integer seconds.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/rollup/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"profileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"onDelete":"RESTRICT"}},"startsAt":{"type":"datetime","required":false},"endsAt":{"type":"datetime","required":false},"timezone":{"type":"text","required":false},"rulesVersion":{"type":"text","required":false},"rulesSnapshot":{"type":"text","required":false,"_meta":{}},"sourceSnapshot":{"type":"text","required":false,"_meta":{}},"regularSeconds":{"type":"integer","required":true,"default":0},"overtimeSeconds":{"type":"integer","required":true,"default":0},"totalSeconds":{"type":"integer","required":true,"default":0},"status":{"type":"text","required":false,"_meta":{},"enum":["open","confirmed"]},"confirmedAt":{"type":"datetime","required":false},"confirmedByProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"nullable":true,"onDelete":"RESTRICT"}}},"methods":{"getSources":{"name":"getSources","async":false,"parameters":[],"returnType":"TimecardSource[]","isStatic":false,"isPublic":true},"getRules":{"name":"getRules","async":false,"parameters":[],"returnType":"Record<string, unknown>","isStatic":false,"isPublic":true},"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"period_timecards","sensitive":true,"api":{"include":[]},"cli":{"include":[]},"mcp":{"include":[]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"PeriodTimecard","collectionExportName":"PeriodTimecardCollection","validationRules":[{"field":"regularSeconds","rule":"required","fieldType":"integer"},{"field":"overtimeSeconds","rule":"required","fieldType":"integer"},{"field":"totalSeconds","rule":"required","fieldType":"integer"}],"schema":{"tableName":"period_timecards","ddl":"CREATE TABLE IF NOT EXISTS \\"period_timecards\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"profile_id\\" UUID,\\n \\"starts_at\\" TIMESTAMP,\\n \\"ends_at\\" TIMESTAMP,\\n \\"timezone\\" TEXT,\\n \\"rules_version\\" TEXT,\\n \\"rules_snapshot\\" TEXT,\\n \\"source_snapshot\\" TEXT,\\n \\"regular_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"overtime_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"total_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"status\\" TEXT,\\n \\"confirmed_at\\" TIMESTAMP,\\n \\"confirmed_by_profile_id\\" UUID\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"starts_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ends_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"timezone":{"type":"TEXT","notNull":false,"unique":false},"rules_version":{"type":"TEXT","notNull":false,"unique":false},"rules_snapshot":{"type":"TEXT","notNull":false,"unique":false},"source_snapshot":{"type":"TEXT","notNull":false,"unique":false},"regular_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"overtime_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"total_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"status":{"type":"TEXT","notNull":false,"unique":false},"confirmed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"confirmed_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false}},"indexes":[{"name":"period_timecards_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"period_timecards_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"period_timecards_profile_id_idx","columns":["profile_id"]},{"name":"period_timecards_confirmed_by_profile_id_idx","columns":["confirmed_by_profile_id"]}],"version":"8153dc2a"},"importPath":"@happyvertical/smrt-timesheets/rollup"},"@happyvertical/smrt-timesheets:TimecardAdjustment":{"name":"timecardadjustment","className":"TimecardAdjustment","qualifiedName":"@happyvertical/smrt-timesheets:TimecardAdjustment","collection":"timecardadjustments","description":"Attributed append-only signed seconds; the confirmed base card never changes.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/rollup/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{"tenantId":{"type":"text","required":true,"_meta":{"sqlType":"UUID","__tenancy":{"isTenantIdField":true,"autoFilter":true,"required":true,"autoPopulate":true,"nullable":false,"mode":"required","field":"tenantId","allowSuperAdminBypass":false}}},"timecardId":{"type":"foreignKey","required":false,"related":"PeriodTimecard","_meta":{"onDelete":"RESTRICT"}},"profileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"onDelete":"RESTRICT"}},"actorProfileId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-profiles:Profile","_meta":{"onDelete":"RESTRICT"}},"operationId":{"type":"text","required":false},"regularSeconds":{"type":"integer","required":true,"default":0},"overtimeSeconds":{"type":"integer","required":true,"default":0},"reason":{"type":"text","required":false}},"methods":{"save":{"name":"save","async":true,"parameters":[],"returnType":"Promise<this>","isStatic":false,"isPublic":true},"delete":{"name":"delete","async":true,"parameters":[],"returnType":"Promise<void>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableName":"timecard_adjustments","sensitive":true,"api":{"include":[]},"cli":{"include":[]},"mcp":{"include":[]},"tenantScoped":{"mode":"required"},"conflictColumns":["tenant_id","slug","context"]},"extends":"SmrtObject","exportName":"TimecardAdjustment","collectionExportName":"TimecardAdjustmentCollection","validationRules":[{"field":"regularSeconds","rule":"required","fieldType":"integer"},{"field":"overtimeSeconds","rule":"required","fieldType":"integer"}],"schema":{"tableName":"timecard_adjustments","ddl":"CREATE TABLE IF NOT EXISTS \\"timecard_adjustments\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"timecard_id\\" UUID,\\n \\"profile_id\\" UUID,\\n \\"actor_profile_id\\" UUID,\\n \\"operation_id\\" TEXT,\\n \\"regular_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"overtime_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"reason\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"timecard_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"period_timecards","column":"id","onDelete":"RESTRICT","onUpdate":"CASCADE"}},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"actor_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"operation_id":{"type":"TEXT","notNull":false,"unique":false},"regular_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"overtime_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"reason":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"timecard_adjustments_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"timecard_adjustments_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"timecard_adjustments_timecard_id_idx","columns":["timecard_id"]},{"name":"timecard_adjustments_profile_id_idx","columns":["profile_id"]},{"name":"timecard_adjustments_actor_profile_id_idx","columns":["actor_profile_id"]}],"version":"582afe16"},"importPath":"@happyvertical/smrt-timesheets/rollup"},"@happyvertical/smrt-timesheets:PeriodTimecardCollection":{"name":"periodtimecardcollection","className":"PeriodTimecardCollection","qualifiedName":"@happyvertical/smrt-timesheets:PeriodTimecardCollection","collection":"periodtimecards","description":"Scoped persistence collection; mutations must use PeriodRollupService.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/rollup/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"period_timecards"},"extends":"SmrtCollection","extendsTypeArg":"PeriodTimecard","exportName":"PeriodTimecardCollection","collectionExportName":"PeriodTimecardCollectionCollection","schema":{"tableName":"period_timecards","ddl":"CREATE TABLE IF NOT EXISTS \\"period_timecards\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"profile_id\\" UUID,\\n \\"starts_at\\" TIMESTAMP,\\n \\"ends_at\\" TIMESTAMP,\\n \\"timezone\\" TEXT,\\n \\"rules_version\\" TEXT,\\n \\"rules_snapshot\\" TEXT,\\n \\"source_snapshot\\" TEXT,\\n \\"regular_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"overtime_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"total_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"status\\" TEXT,\\n \\"confirmed_at\\" TIMESTAMP,\\n \\"confirmed_by_profile_id\\" UUID\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"starts_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"ends_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"timezone":{"type":"TEXT","notNull":false,"unique":false},"rules_version":{"type":"TEXT","notNull":false,"unique":false},"rules_snapshot":{"type":"TEXT","notNull":false,"unique":false},"source_snapshot":{"type":"TEXT","notNull":false,"unique":false},"regular_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"overtime_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"total_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"status":{"type":"TEXT","notNull":false,"unique":false},"confirmed_at":{"type":"TIMESTAMP","notNull":false,"unique":false},"confirmed_by_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false}},"indexes":[{"name":"period_timecards_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"period_timecards_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"period_timecards_profile_id_idx","columns":["profile_id"]},{"name":"period_timecards_confirmed_by_profile_id_idx","columns":["confirmed_by_profile_id"]}],"version":"8153dc2a"},"importPath":"@happyvertical/smrt-timesheets/rollup"},"@happyvertical/smrt-timesheets:TimecardAdjustmentCollection":{"name":"timecardadjustmentcollection","className":"TimecardAdjustmentCollection","qualifiedName":"@happyvertical/smrt-timesheets:TimecardAdjustmentCollection","collection":"timecardadjustments","description":"Scoped append-only adjustment collection.","filePath":"/home/runner/work/smrt/smrt/packages/timesheets/src/rollup/models.ts","packageName":"@happyvertical/smrt-timesheets","fields":{},"methods":{},"decoratorConfig":{"tableName":"timecard_adjustments"},"extends":"SmrtCollection","extendsTypeArg":"TimecardAdjustment","exportName":"TimecardAdjustmentCollection","collectionExportName":"TimecardAdjustmentCollectionCollection","schema":{"tableName":"timecard_adjustments","ddl":"CREATE TABLE IF NOT EXISTS \\"timecard_adjustments\\" (\\n \\"id\\" UUID PRIMARY KEY NOT NULL,\\n \\"slug\\" TEXT NOT NULL,\\n \\"context\\" TEXT NOT NULL DEFAULT '',\\n \\"created_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"updated_at\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\"tenant_id\\" UUID NOT NULL,\\n \\"timecard_id\\" UUID,\\n \\"profile_id\\" UUID,\\n \\"actor_profile_id\\" UUID,\\n \\"operation_id\\" TEXT,\\n \\"regular_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"overtime_seconds\\" INTEGER NOT NULL DEFAULT 0,\\n \\"reason\\" TEXT\\n);","columns":{"id":{"type":"UUID","primaryKey":true,"referenceKind":"id","notNull":true},"slug":{"type":"TEXT","notNull":true},"context":{"type":"TEXT","notNull":true,"default":""},"created_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"updated_at":{"type":"TIMESTAMP","notNull":true,"default":"current_timestamp"},"tenant_id":{"type":"UUID","referenceKind":"tenantId","notNull":true,"unique":false},"timecard_id":{"type":"UUID","referenceKind":"foreignKey","notNull":false,"unique":false,"foreignKey":{"table":"period_timecards","column":"id","onDelete":"RESTRICT","onUpdate":"CASCADE"}},"profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"actor_profile_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false,"unique":false},"operation_id":{"type":"TEXT","notNull":false,"unique":false},"regular_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"overtime_seconds":{"type":"INTEGER","notNull":true,"unique":false,"default":0},"reason":{"type":"TEXT","notNull":false,"unique":false}},"indexes":[{"name":"timecard_adjustments_slug_context_idx","columns":["tenant_id","slug","context"],"unique":true},{"name":"timecard_adjustments_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"timecard_adjustments_timecard_id_idx","columns":["timecard_id"]},{"name":"timecard_adjustments_profile_id_idx","columns":["profile_id"]},{"name":"timecard_adjustments_actor_profile_id_idx","columns":["actor_profile_id"]}],"version":"582afe16"},"importPath":"@happyvertical/smrt-timesheets/rollup"}},"moduleType":"smrt","smrtDependencies":["@happyvertical/smrt-core","@happyvertical/smrt-tenancy"],"browser":{"status":"server-only","issues":["#3624"],"reason":"node:crypto","via":["@happyvertical/smrt-tenancy"]},"stampsConstructors":true}`));
6
+ //#endregion
7
+ //#region src/models/json.ts
8
+ function parseTimesheetJson(value, fallback) {
9
+ try {
10
+ return JSON.parse(value);
11
+ } catch {
12
+ return fallback;
13
+ }
14
+ }
15
+ //#endregion
16
+ //#region src/models/service-time-entry.ts
17
+ var __defProp = Object.defineProperty;
18
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
19
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value
24
+ }) : obj[key] = value;
25
+ var __decorateClass = (decorators, target, key, kind) => {
26
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
27
+ for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
28
+ if (kind && result) __defProp(target, key, result);
29
+ return result;
30
+ };
31
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
32
+ var SERVICE_TIME_ENTRY_FROZEN_FIELDS = [
33
+ "tenantId",
34
+ "workRefType",
35
+ "workRefId",
36
+ "participantKind",
37
+ "participantProfileId",
38
+ "agentRef",
39
+ "source",
40
+ "description",
41
+ "startedAt",
42
+ "endedAt",
43
+ "durationSeconds",
44
+ "evidence",
45
+ "correctionOfId"
46
+ ];
47
+ function toColumn(key) {
48
+ return key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
49
+ }
50
+ function frozenView(source, fields) {
51
+ const result = {};
52
+ for (const key of fields) {
53
+ let value = source[key] ?? null;
54
+ if ((key === "startedAt" || key === "endedAt") && value) {
55
+ const date = value instanceof Date ? value : new Date(String(value));
56
+ value = Number.isNaN(date.getTime()) ? String(value) : date.toISOString();
57
+ }
58
+ if (key === "durationSeconds" && value !== null) value = Number(value);
59
+ result[key] = value === "" ? null : value;
60
+ }
61
+ return JSON.stringify(result);
62
+ }
63
+ var loadedStatus = /* @__PURE__ */ new WeakMap();
64
+ var ServiceTimeEntry = class extends SmrtObject {
65
+ tenantId = null;
66
+ workRefType = null;
67
+ workRefId = null;
68
+ participantKind = "human";
69
+ participantProfileId = null;
70
+ agentRef = "";
71
+ source = "manual";
72
+ description = "";
73
+ startedAt = null;
74
+ endedAt = null;
75
+ durationSeconds = 0;
76
+ evidence = "[]";
77
+ status = "draft";
78
+ submittedAt = null;
79
+ submittedByProfileId = null;
80
+ approvedAt = null;
81
+ approvedByProfileId = null;
82
+ approvalPath = "";
83
+ rejectedAt = null;
84
+ rejectedByProfileId = null;
85
+ rejectionReason = "";
86
+ correctionOfId = null;
87
+ metadata = "{}";
88
+ getEvidence() {
89
+ return parseTimesheetJson(this.evidence, []);
90
+ }
91
+ setEvidence(value) {
92
+ this.evidence = JSON.stringify(value ?? []);
93
+ }
94
+ getMetadata() {
95
+ return parseTimesheetJson(this.metadata, {});
96
+ }
97
+ setMetadata(value) {
98
+ this.metadata = JSON.stringify(value ?? {});
99
+ }
100
+ /** Original decimal-hours text, without binary floating-point conversion. */
101
+ durationHoursExact() {
102
+ const evidence = this.getEvidence();
103
+ const quantities = (Array.isArray(evidence) ? evidence : []).filter((item) => item?.kind === SERVICE_DURATION_HOURS_EVIDENCE);
104
+ if (quantities.length === 0) return null;
105
+ if (quantities.length !== 1) throw new Error("Service time requires exactly one decimal-hours quantity.");
106
+ return validateDurationHours(quantities[0].hours);
107
+ }
108
+ /** Numeric convenience for display; use durationHoursExact() for exact terms. */
109
+ durationHours() {
110
+ if (this.durationSeconds !== null) return this.durationSeconds / 3600;
111
+ const hours = this.durationHoursExact();
112
+ if (hours === null) throw new Error("Service time has no supported duration quantity.");
113
+ return Number(hours);
114
+ }
115
+ /** Guard for consumers whose policies require independently supplied seconds. */
116
+ requireDurationSeconds() {
117
+ if (this.durationSeconds === null) throw new Error("Decimal-hours-only service time has no measured durationSeconds; use durationHoursExact() with an hours-aware policy.");
118
+ return this.durationSeconds;
119
+ }
120
+ /**
121
+ * Fields frozen once the entry is approved. Subtypes that add work context
122
+ * (e.g. a support case) return `[...super.frozenFieldNames(), ...]`.
123
+ */
124
+ frozenFieldNames() {
125
+ return SERVICE_TIME_ENTRY_FROZEN_FIELDS;
126
+ }
127
+ async initialize() {
128
+ await super.initialize();
129
+ if (await this.isSaved()) loadedStatus.set(this, this.status);
130
+ return this;
131
+ }
132
+ async save() {
133
+ if (this.durationHoursExact() !== null) {
134
+ if (this.durationSeconds !== null || this.startedAt || this.endedAt || this.source === "timer") throw new Error("Decimal-hours-only service time cannot also supply seconds or timestamps.");
135
+ } else if (this.durationSeconds === null) throw new Error("Null durationSeconds requires explicit decimal-hours evidence.");
136
+ const prior = await this.readPrior();
137
+ if (prior && prior.status !== this.status && !SERVICE_TIME_ENTRY_STATUS_TRANSITIONS[prior.status].includes(this.status)) throw new Error(`ServiceTimeEntry ${this.id}: illegal status transition '${prior.status}' \u2192 '${this.status}'.`);
138
+ if (prior && (prior.status === "approved" || prior.status === "corrected")) {
139
+ if (frozenView(this, this.frozenFieldNames()) !== prior.frozen) throw new Error("Approved ServiceTimeEntry evidence is immutable; create a correction instead.");
140
+ }
141
+ const result = await super.save();
142
+ loadedStatus.set(this, this.status);
143
+ return result;
144
+ }
145
+ async readPrior() {
146
+ if (!this.id) return null;
147
+ const fields = this.frozenFieldNames();
148
+ try {
149
+ const row = await this.db.get(this.tableName, { id: this.id });
150
+ if (!row?.status) return null;
151
+ const values = {};
152
+ for (const key of fields) values[key] = row[toColumn(key)];
153
+ return {
154
+ status: row.status,
155
+ frozen: frozenView(values, fields)
156
+ };
157
+ } catch {
158
+ const status = loadedStatus.get(this);
159
+ return status ? {
160
+ status,
161
+ frozen: frozenView(this, fields)
162
+ } : null;
163
+ }
164
+ }
165
+ };
166
+ __publicField(ServiceTimeEntry, "__smrtPackage__", "@happyvertical/smrt-timesheets");
167
+ __decorateClass([tenantId({ nullable: true })], ServiceTimeEntry.prototype, "tenantId", 2);
168
+ __decorateClass([field({
169
+ type: "text",
170
+ nullable: true
171
+ })], ServiceTimeEntry.prototype, "workRefType", 2);
172
+ __decorateClass([field({
173
+ type: "text",
174
+ nullable: true
175
+ })], ServiceTimeEntry.prototype, "workRefId", 2);
176
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "participantKind", 2);
177
+ __decorateClass([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], ServiceTimeEntry.prototype, "participantProfileId", 2);
178
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "agentRef", 2);
179
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "source", 2);
180
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "description", 2);
181
+ __decorateClass([field({
182
+ type: "integer",
183
+ nullable: true
184
+ })], ServiceTimeEntry.prototype, "durationSeconds", 2);
185
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "evidence", 2);
186
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "status", 2);
187
+ __decorateClass([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], ServiceTimeEntry.prototype, "submittedByProfileId", 2);
188
+ __decorateClass([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], ServiceTimeEntry.prototype, "approvedByProfileId", 2);
189
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "approvalPath", 2);
190
+ __decorateClass([crossPackageRef("@happyvertical/smrt-profiles:Profile", { nullable: true })], ServiceTimeEntry.prototype, "rejectedByProfileId", 2);
191
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "rejectionReason", 2);
192
+ __decorateClass([foreignKey("ServiceTimeEntry")], ServiceTimeEntry.prototype, "correctionOfId", 2);
193
+ __decorateClass([field({ type: "text" })], ServiceTimeEntry.prototype, "metadata", 2);
194
+ ServiceTimeEntry = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
195
+ tableName: "service_time_entries",
196
+ previousQualifiedNames: ["@happyvertical/smrt-projects:ServiceTimeEntry"],
197
+ api: { include: ["list", "get"] },
198
+ cli: { include: ["list", "get"] },
199
+ mcp: { include: ["list", "get"] }
200
+ })], ServiceTimeEntry);
201
+ var ServiceTimeEntryCollection = class extends SmrtCollection {
202
+ static _itemClass = ServiceTimeEntry;
203
+ async forWork(workRefType, workRefId) {
204
+ return this.list({
205
+ where: {
206
+ workRefType,
207
+ workRefId
208
+ },
209
+ orderBy: "created_at ASC"
210
+ });
211
+ }
212
+ async pendingApproval() {
213
+ return this.list({
214
+ where: { status: "submitted" },
215
+ orderBy: "submitted_at ASC"
216
+ });
217
+ }
218
+ };
219
+ var SERVICE_DURATION_HOURS_EVIDENCE = "@happyvertical/smrt-timesheets:duration-hours";
220
+ function validateDurationHours(value) {
221
+ if (typeof value !== "string" || !/^\d+(?:\.\d+)?$/.test(value) || !Number.isFinite(Number(value)) || Number(value) <= 0 || Number(value) >= Number.MAX_SAFE_INTEGER) throw new Error("Service time durationHours must be positive plain decimal text within the supported numeric range.");
222
+ return value;
223
+ }
224
+ //#endregion
225
+ export { validateDurationHours as a, ServiceTimeEntryCollection as i, SERVICE_TIME_ENTRY_FROZEN_FIELDS as n, parseTimesheetJson as o, ServiceTimeEntry as r, SERVICE_DURATION_HOURS_EVIDENCE as t };
226
+
227
+ //# sourceMappingURL=service-time-entry-DJOG0D_N.js.map