@happyvertical/smrt-timesheets 0.54.2 → 0.54.4
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/dist/attendance.js +2 -2
- package/dist/chunks/{attendance-BpBPQuHV.js → attendance-iPLiq8yw.js} +3 -3
- package/dist/chunks/{attendance-BpBPQuHV.js.map → attendance-iPLiq8yw.js.map} +1 -1
- package/dist/chunks/{models-Du3jXEvt.js → models-DyK99luq.js} +12 -2
- package/dist/chunks/models-DyK99luq.js.map +1 -0
- package/dist/chunks/{rollup-BHW5XQh1.js → rollup-C_JC3hUx.js} +12 -3
- package/dist/chunks/rollup-C_JC3hUx.js.map +1 -0
- package/dist/chunks/service-time-entry-DOEXLPZh.js +227 -0
- package/dist/chunks/service-time-entry-DOEXLPZh.js.map +1 -0
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +3 -2
- package/dist/rollup.js +1 -1
- package/dist/smrt-knowledge.json +3 -3
- package/package.json +7 -7
- package/dist/chunks/models-Du3jXEvt.js.map +0 -1
- package/dist/chunks/rollup-BHW5XQh1.js.map +0 -1
- package/dist/chunks/service-time-entry-DGt3ZoVw.js +0 -219
- package/dist/chunks/service-time-entry-DGt3ZoVw.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-time-entry-DOEXLPZh.js","names":[],"sources":["../../src/__smrt-register__.ts","../../src/models/json.ts","../../src/models/service-time-entry.ts"],"sourcesContent":["// Generated by @happyvertical/smrt-core smrtPlugin at library build time.\n// The package manifest is inlined so self-registration cannot miss when a\n// downstream bundler relocates this module away from dist/manifest.json\n// (https://github.com/happyvertical/smrt/issues/1506,\n// https://github.com/happyvertical/smrt/issues/1507).\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\nObjectRegistry.registerPackageManifest(JSON.parse(\"{\\\"version\\\":\\\"1.0.0\\\",\\\"timestamp\\\":0,\\\"packageName\\\":\\\"@happyvertical/smrt-timesheets\\\",\\\"packageVersion\\\":\\\"0.54.4\\\",\\\"objects\\\":{\\\"@happyvertical/smrt-timesheets:AttendancePunch\\\":{\\\"name\\\":\\\"attendancepunch\\\",\\\"className\\\":\\\"AttendancePunch\\\",\\\"qualifiedName\\\":\\\"@happyvertical/smrt-timesheets:AttendancePunch\\\",\\\"collection\\\":\\\"attendancepunches\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\":{}},\\\"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\\\":{}},\\\"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\\\":{}},\\\"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\\\",\\\"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\\\",\\\"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\\\":{}},\\\"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\\\",\\\"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\\\",\\\"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\\\",\\\"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\\\"],\\\"stampsConstructors\\\":true}\"));\n","/**\n * Parse a JSON value stored as text, returning `fallback` on malformed input.\n * Stored JSON may predate a schema change, so reads never throw.\n */\nexport function parseTimesheetJson<T>(value: string, fallback: T): T {\n try {\n return JSON.parse(value) as T;\n } catch {\n return fallback;\n }\n}\n","import {\n crossPackageRef,\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n SERVICE_TIME_ENTRY_STATUS_TRANSITIONS,\n type ServiceEvidence,\n type ServiceParticipantKind,\n type ServiceTimeEntrySource,\n type ServiceTimeEntryStatus,\n} from '../types.js';\nimport { parseTimesheetJson } from './json.js';\n\n/**\n * Fields that may not change once an entry is approved (or corrected). A\n * subtype that adds its own work context extends the list through\n * {@link ServiceTimeEntry.frozenFieldNames}.\n */\nexport const SERVICE_TIME_ENTRY_FROZEN_FIELDS = [\n 'tenantId',\n 'workRefType',\n 'workRefId',\n 'participantKind',\n 'participantProfileId',\n 'agentRef',\n 'source',\n 'description',\n 'startedAt',\n 'endedAt',\n 'durationSeconds',\n 'evidence',\n 'correctionOfId',\n] as const;\n\nfunction toColumn(key: string): string {\n return key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction frozenView(\n source: Record<string, unknown>,\n fields: readonly string[],\n): string {\n const result: Record<string, unknown> = {};\n for (const key of fields) {\n let value = source[key] ?? null;\n if ((key === 'startedAt' || key === 'endedAt') && value) {\n const date = value instanceof Date ? value : new Date(String(value));\n value = Number.isNaN(date.getTime()) ? String(value) : date.toISOString();\n }\n if (key === 'durationSeconds' && value !== null) value = Number(value);\n result[key] = value === '' ? null : value;\n }\n return JSON.stringify(result);\n}\n\nconst loadedStatus = new WeakMap<ServiceTimeEntry, ServiceTimeEntryStatus>();\n\n/**\n * A person or agent worked this long on this thing, and someone approved it.\n *\n * The base entry carries a generic work reference (`workRefType` qualified\n * class name + `workRefId`) and no domain-specific foreign key; a domain adds\n * its own context by subclassing over the same `service_time_entries` table\n * (smrt-support's subtype adds `caseId` / `specialistId`). Entries carry no\n * rate: charge and compensation live on the immutable snapshot models.\n *\n * Status moves `draft → submitted → approved | rejected`; an approved entry\n * never changes, and a correction is a new row whose `correctionOfId` points\n * at the entry it corrects, which flips to `corrected`.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_time_entries',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: ['@happyvertical/smrt-projects:ServiceTimeEntry'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceTimeEntry extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @field({ type: 'text', nullable: true }) workRefType: string | null = null;\n @field({ type: 'text', nullable: true }) workRefId: string | null = null;\n @field({ type: 'text' }) participantKind: ServiceParticipantKind = 'human';\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', { nullable: true })\n participantProfileId: string | null = null;\n @field({ type: 'text' }) agentRef: string = '';\n @field({ type: 'text' }) source: ServiceTimeEntrySource = 'manual';\n @field({ type: 'text' }) description: string = '';\n startedAt: Date | null = null;\n endedAt: Date | null = null;\n /** Integer seconds, or null for an explicit decimal-hours-only source. */\n @field({ type: 'integer', nullable: true })\n durationSeconds: number | null = 0;\n @field({ type: 'text' }) evidence: string = '[]';\n @field({ type: 'text' }) status: ServiceTimeEntryStatus = 'draft';\n submittedAt: Date | null = null;\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', { nullable: true })\n submittedByProfileId: string | null = null;\n approvedAt: Date | null = null;\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', { nullable: true })\n approvedByProfileId: string | null = null;\n @field({ type: 'text' }) approvalPath: string = '';\n rejectedAt: Date | null = null;\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', { nullable: true })\n rejectedByProfileId: string | null = null;\n @field({ type: 'text' }) rejectionReason: string = '';\n @foreignKey('ServiceTimeEntry') correctionOfId: string | null = null;\n @field({ type: 'text' }) metadata: string = '{}';\n\n getEvidence(): ServiceEvidence[] {\n return parseTimesheetJson(this.evidence, []);\n }\n setEvidence(value: ServiceEvidence[]): void {\n this.evidence = JSON.stringify(value ?? []);\n }\n getMetadata(): Record<string, unknown> {\n return parseTimesheetJson(this.metadata, {});\n }\n setMetadata(value: Record<string, unknown>): void {\n this.metadata = JSON.stringify(value ?? {});\n }\n /** Original decimal-hours text, without binary floating-point conversion. */\n durationHoursExact(): string | null {\n const evidence = this.getEvidence();\n const quantities = (Array.isArray(evidence) ? evidence : []).filter(\n (item) => item?.kind === SERVICE_DURATION_HOURS_EVIDENCE,\n );\n if (quantities.length === 0) return null;\n if (quantities.length !== 1)\n throw new Error(\n 'Service time requires exactly one decimal-hours quantity.',\n );\n return validateDurationHours(quantities[0].hours);\n }\n\n /** Numeric convenience for display; use durationHoursExact() for exact terms. */\n durationHours(): number {\n if (this.durationSeconds !== null) return this.durationSeconds / 3600;\n const hours = this.durationHoursExact();\n if (hours === null)\n throw new Error('Service time has no supported duration quantity.');\n return Number(hours);\n }\n\n /** Guard for consumers whose policies require independently supplied seconds. */\n requireDurationSeconds(): number {\n if (this.durationSeconds === null)\n throw new Error(\n 'Decimal-hours-only service time has no measured durationSeconds; use durationHoursExact() with an hours-aware policy.',\n );\n return this.durationSeconds;\n }\n\n /**\n * Fields frozen once the entry is approved. Subtypes that add work context\n * (e.g. a support case) return `[...super.frozenFieldNames(), ...]`.\n */\n protected frozenFieldNames(): readonly string[] {\n return SERVICE_TIME_ENTRY_FROZEN_FIELDS;\n }\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved()) loadedStatus.set(this, this.status);\n return this;\n }\n\n override async save(): Promise<this> {\n const hours = this.durationHoursExact();\n if (hours !== null) {\n if (\n this.durationSeconds !== null ||\n this.startedAt ||\n this.endedAt ||\n this.source === 'timer'\n )\n throw new Error(\n 'Decimal-hours-only service time cannot also supply seconds or timestamps.',\n );\n } else if (this.durationSeconds === null) {\n throw new Error(\n 'Null durationSeconds requires explicit decimal-hours evidence.',\n );\n }\n const prior = await this.readPrior();\n if (\n prior &&\n prior.status !== this.status &&\n !SERVICE_TIME_ENTRY_STATUS_TRANSITIONS[prior.status].includes(this.status)\n ) {\n throw new Error(\n `ServiceTimeEntry ${this.id}: illegal status transition '${prior.status}' → '${this.status}'.`,\n );\n }\n if (\n prior &&\n (prior.status === 'approved' || prior.status === 'corrected')\n ) {\n const current = frozenView(\n this as unknown as Record<string, unknown>,\n this.frozenFieldNames(),\n );\n if (current !== prior.frozen) {\n throw new Error(\n 'Approved ServiceTimeEntry evidence is immutable; create a correction instead.',\n );\n }\n }\n const result = (await super.save()) as this;\n loadedStatus.set(this, this.status);\n return result;\n }\n\n private async readPrior(): Promise<{\n status: ServiceTimeEntryStatus;\n frozen: string;\n } | null> {\n if (!this.id) return null;\n const fields = this.frozenFieldNames();\n try {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (!row?.status) return null;\n const values: Record<string, unknown> = {};\n for (const key of fields) {\n values[key] = row[toColumn(key)];\n }\n return {\n status: row.status as ServiceTimeEntryStatus,\n frozen: frozenView(values, fields),\n };\n } catch {\n const status = loadedStatus.get(this);\n return status\n ? {\n status,\n frozen: frozenView(\n this as unknown as Record<string, unknown>,\n fields,\n ),\n }\n : null;\n }\n }\n}\n\n/** Collection over `service_time_entries`. */\nexport class ServiceTimeEntryCollection extends SmrtCollection<ServiceTimeEntry> {\n static readonly _itemClass = ServiceTimeEntry;\n async forWork(\n workRefType: string,\n workRefId: string,\n ): Promise<ServiceTimeEntry[]> {\n return this.list({\n where: { workRefType, workRefId },\n orderBy: 'created_at ASC',\n });\n }\n async pendingApproval(): Promise<ServiceTimeEntry[]> {\n return this.list({\n where: { status: 'submitted' },\n orderBy: 'submitted_at ASC',\n });\n }\n}\n\n/** Reserved evidence kind for a source quantity with no measured elapsed seconds. */\nexport const SERVICE_DURATION_HOURS_EVIDENCE =\n '@happyvertical/smrt-timesheets:duration-hours';\n\n/** Validate without normalizing the original accepted decimal text. */\nexport function validateDurationHours(value: unknown): string {\n if (\n typeof value !== 'string' ||\n !/^\\d+(?:\\.\\d+)?$/.test(value) ||\n !Number.isFinite(Number(value)) ||\n Number(value) <= 0 ||\n Number(value) >= Number.MAX_SAFE_INTEGER\n )\n throw new Error(\n 'Service time durationHours must be positive plain decimal text within the supported numeric range.',\n );\n return value;\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import { a as validateDurationHours, i as ServiceTimeEntryCollection, n as SERVICE_TIME_ENTRY_FROZEN_FIELDS, r as ServiceTimeEntry, t as SERVICE_DURATION_HOURS_EVIDENCE } from "./chunks/service-time-entry-
|
|
2
|
-
import { a as AttendanceReplay, i as AttendancePunchCollection, n as AttendanceBreakCollection, o as AttendanceReplayCollection, r as AttendancePunch, t as AttendanceBreak } from "./chunks/models-
|
|
1
|
+
import { a as validateDurationHours, i as ServiceTimeEntryCollection, n as SERVICE_TIME_ENTRY_FROZEN_FIELDS, r as ServiceTimeEntry, t as SERVICE_DURATION_HOURS_EVIDENCE } from "./chunks/service-time-entry-DOEXLPZh.js";
|
|
2
|
+
import { a as AttendanceReplay, i as AttendancePunchCollection, n as AttendanceBreakCollection, o as AttendanceReplayCollection, r as AttendancePunch, t as AttendanceBreak } from "./chunks/models-DyK99luq.js";
|
|
3
3
|
import { SERVICE_TIME_ENTRY_STATUS_TRANSITIONS } from "./types.js";
|
|
4
4
|
import { AttendanceConflict, AttendanceService } from "./attendance.js";
|
|
5
|
-
import { a as PeriodTimecard, c as TimecardAdjustmentCollection, o as PeriodTimecardCollection, s as TimecardAdjustment, t as PeriodRollupService } from "./chunks/rollup-
|
|
5
|
+
import { a as PeriodTimecard, c as TimecardAdjustmentCollection, o as PeriodTimecardCollection, s as TimecardAdjustment, t as PeriodRollupService } from "./chunks/rollup-C_JC3hUx.js";
|
|
6
6
|
import { TIMESHEETS_MODULE_META, TIMESHEETS_UI_SLOTS } from "./ui.js";
|
|
7
7
|
import { SmrtCollection, SmrtObject, ValidationError, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
8
8
|
import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
|
|
9
9
|
//#region src/models/service-snapshots.ts
|
|
10
10
|
var __defProp = Object.defineProperty;
|
|
11
11
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value
|
|
17
|
+
}) : obj[key] = value;
|
|
12
18
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
13
19
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
14
20
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
15
21
|
if (kind && result) __defProp(target, key, result);
|
|
16
22
|
return result;
|
|
17
23
|
};
|
|
24
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
18
25
|
function assertSnapshotMinorUnits(model, amount) {
|
|
19
26
|
if (typeof amount !== "number" || !Number.isSafeInteger(amount)) throw new ValidationError(`${model}.amount must be a safe integer number of minor units (cents) \u2014 got ${String(amount)}. $19.99 is 1999.`, "VALIDATION_INVALID_VALUE", {
|
|
20
27
|
fieldName: "amount",
|
|
@@ -87,6 +94,7 @@ var ServiceChargeSnapshot = class extends SmrtObject {
|
|
|
87
94
|
return result;
|
|
88
95
|
}
|
|
89
96
|
};
|
|
97
|
+
__publicField(ServiceChargeSnapshot, "__smrtPackage__", "@happyvertical/smrt-timesheets");
|
|
90
98
|
__decorateClass([tenantId({ nullable: true })], ServiceChargeSnapshot.prototype, "tenantId", 2);
|
|
91
99
|
__decorateClass([foreignKey("ServiceTimeEntry", { required: true })], ServiceChargeSnapshot.prototype, "timeEntryId", 2);
|
|
92
100
|
__decorateClass([field({ type: "text" })], ServiceChargeSnapshot.prototype, "currency", 2);
|
|
@@ -132,6 +140,7 @@ var ServiceCompensationSnapshot = class extends SmrtObject {
|
|
|
132
140
|
return result;
|
|
133
141
|
}
|
|
134
142
|
};
|
|
143
|
+
__publicField(ServiceCompensationSnapshot, "__smrtPackage__", "@happyvertical/smrt-timesheets");
|
|
135
144
|
__decorateClass([tenantId({ nullable: true })], ServiceCompensationSnapshot.prototype, "tenantId", 2);
|
|
136
145
|
__decorateClass([foreignKey("ServiceTimeEntry", { required: true })], ServiceCompensationSnapshot.prototype, "timeEntryId", 2);
|
|
137
146
|
__decorateClass([field({ type: "text" })], ServiceCompensationSnapshot.prototype, "currency", 2);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/models/service-snapshots.ts","../src/services/service-evidence-service.ts"],"sourcesContent":["import {\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n ValidationError,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\n/**\n * Refuse an amount that is not a JavaScript-safe integer number of minor\n * units. SQLite stores `19.99` in an INTEGER column without complaint and\n * PostgreSQL rejects it only at the driver, so the model boundary is the one\n * place both engines (and every writer: collections, `ServiceEvidenceService`,\n * resolvers) get the same answer. Sign is not constrained here.\n */\nexport function assertSnapshotMinorUnits(model: string, amount: unknown): void {\n if (typeof amount !== 'number' || !Number.isSafeInteger(amount)) {\n throw new ValidationError(\n `${model}.amount must be a safe integer number of minor units (cents) — ` +\n `got ${String(amount)}. $19.99 is 1999.`,\n 'VALIDATION_INVALID_VALUE',\n {\n fieldName: 'amount',\n value: amount,\n expectedType: 'safe integer minor units',\n },\n );\n }\n}\n\nconst chargeSnapshot = new WeakMap<ServiceChargeSnapshot, string>();\nconst compensationSnapshot = new WeakMap<ServiceCompensationSnapshot, string>();\n\nasync function immutableCommercialSnapshot(\n object: SmrtObject,\n fields: string[],\n): Promise<string | null> {\n if (!object.id) return null;\n try {\n const row = await object.db.get(object.tableName, { id: object.id });\n if (!row) return null;\n return JSON.stringify(\n Object.fromEntries(\n fields.map((key) => [\n key,\n row[key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`)] ?? null,\n ]),\n ),\n );\n } catch {\n return null;\n }\n}\n\nfunction commercialSnapshot(\n object: Record<string, unknown>,\n fields: string[],\n): string {\n return JSON.stringify(\n Object.fromEntries(fields.map((key) => [key, object[key] ?? null])),\n );\n}\n\nconst CHARGE_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'pricingVersion',\n 'strategy',\n 'rateSnapshot',\n 'sourceChargeRef',\n];\nconst COMPENSATION_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'termsVersion',\n 'rateSnapshot',\n];\n\n/**\n * Immutable client-charge snapshot for one approved time entry. Money is\n * integer minor units, consistent with smrt-commerce (#2401).\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_charge_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceChargeSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceChargeSnapshot extends SmrtObject {\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Client charge in **integer minor units** of {@link currency} — `$19.99` is\n * `1999`. The `= 0` initializer is load-bearing: SMRT maps an integer literal\n * to INTEGER and a decimal literal to DECIMAL (#2401).\n *\n * Copied verbatim from the upstream `ClientCharge.amount`, so the two carry\n * the same unit by construction; a split would land cents in a major-units\n * column with no error anywhere.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) pricingVersion: string = '';\n @field({ type: 'text' }) strategy: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n @field({ type: 'text' }) sourceChargeRef: string = '';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n chargeSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(): Promise<this> {\n assertSnapshotMinorUnits('ServiceChargeSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, CHARGE_FIELDS)) ??\n chargeSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceChargeSnapshot is immutable; append an upstream adjustment instead.',\n );\n const result = (await super.save()) as this;\n chargeSnapshot.set(this, current);\n return result;\n }\n}\n\n/**\n * Immutable provider-compensation snapshot for one approved time entry,\n * kept separate from the client charge so the margin is `charge - compensation`.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_compensation_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceCompensationSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceCompensationSnapshot extends SmrtObject {\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Provider earning in **integer minor units** of {@link currency} (#2401).\n *\n * Converts with {@link ServiceChargeSnapshot.amount}: the delivery margin is\n * `charge - compensation`, so a mixed pair would make that subtraction\n * meaningless.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) termsVersion: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n compensationSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(): Promise<this> {\n assertSnapshotMinorUnits('ServiceCompensationSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, COMPENSATION_FIELDS)) ??\n compensationSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceCompensationSnapshot is immutable; create explicit settlement evidence instead.',\n );\n const result = (await super.save()) as this;\n compensationSnapshot.set(this, current);\n return result;\n }\n}\n\n/** Collection over `service_charge_snapshots`. */\nexport class ServiceChargeSnapshotCollection extends SmrtCollection<ServiceChargeSnapshot> {\n static readonly _itemClass = ServiceChargeSnapshot;\n}\n/** Collection over `service_compensation_snapshots`. */\nexport class ServiceCompensationSnapshotCollection extends SmrtCollection<ServiceCompensationSnapshot> {\n static readonly _itemClass = ServiceCompensationSnapshot;\n}\n","import type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport {\n ServiceChargeSnapshotCollection,\n ServiceCompensationSnapshotCollection,\n} from '../models/service-snapshots.js';\nimport type { ServiceTimeEntry } from '../models/service-time-entry.js';\nimport {\n SERVICE_DURATION_HOURS_EVIDENCE,\n ServiceTimeEntryCollection,\n validateDurationHours,\n} from '../models/service-time-entry.js';\nimport type {\n ServiceEvidence,\n ServiceParticipantKind,\n ServiceTimeEntrySource,\n} from '../types.js';\n\n/**\n * Input for {@link ServiceEvidenceService.record}. The work reference is the\n * qualified class name and id of whatever the time was spent on.\n */\nexport interface RecordServiceTimeInput {\n tenantId?: string | null;\n workRefType?: string | null;\n workRefId?: string | null;\n participantKind: ServiceParticipantKind;\n participantProfileId?: string | null;\n agentRef?: string;\n source: ServiceTimeEntrySource;\n description: string;\n startedAt?: Date | null;\n endedAt?: Date | null;\n durationSeconds?: number | null;\n /** Exact positive decimal text; exclusive with seconds and timestamps. */\n durationHours?: string;\n evidence?: ServiceEvidence[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface CommercialSnapshot {\n /**\n * Integer minor units of `currency` — `$19.99` is `1999` (#2401).\n *\n * Written straight into `ServiceChargeSnapshot.amount` /\n * `ServiceCompensationSnapshot.amount`, INTEGER columns whose `save()`\n * refuses anything but a safe integer on every engine. A fractional\n * major-unit value (`19.99`) is rejected; a whole one (`150` for $150.00)\n * is not detectable and is stored 100× too small, so return minor units.\n */\n amount: number;\n currency?: string;\n version: string;\n strategy?: string;\n terms: Record<string, unknown>;\n sourceRef?: string;\n}\n\nexport interface ServiceCommercialResolver {\n /** Pure preflight: reject unsupported evidence before approval or snapshot writes. */\n validateEntry?(entry: ServiceTimeEntry): void | Promise<void>;\n priceClient(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n compensateProvider(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n}\n\n/**\n * Records, submits, approves, and corrects time entries. Approval writes one\n * immutable client-charge and one provider-compensation snapshot per entry;\n * a correction is a new entry pointing at the approved one, which flips to\n * `corrected` with its snapshots intact.\n */\nexport class ServiceEvidenceService {\n constructor(\n private readonly entries: ServiceTimeEntryCollection,\n private readonly charges: ServiceChargeSnapshotCollection,\n private readonly compensation: ServiceCompensationSnapshotCollection,\n private readonly commercial?: ServiceCommercialResolver,\n ) {}\n\n static async create(\n options: SmrtClassOptions = {},\n commercial?: ServiceCommercialResolver,\n ): Promise<ServiceEvidenceService> {\n const [entries, charges, compensation] = await Promise.all([\n ServiceTimeEntryCollection.create(options),\n ServiceChargeSnapshotCollection.create(options),\n ServiceCompensationSnapshotCollection.create(options),\n ]);\n return new ServiceEvidenceService(\n entries,\n charges,\n compensation,\n commercial,\n );\n }\n\n async record(input: RecordServiceTimeInput): Promise<ServiceTimeEntry> {\n if (!['timer', 'manual', 'import', 'agent'].includes(input.source))\n throw new Error('Unsupported service time source.');\n if (Boolean(input.workRefType) !== Boolean(input.workRefId))\n throw new Error('workRefType and workRefId must be provided together.');\n if (!(input.workRefType && input.workRefId))\n throw new Error('Service time requires a work reference.');\n if (input.participantKind === 'human' && !input.participantProfileId)\n throw new Error('Human service time requires participantProfileId.');\n if (input.participantKind === 'agent' && !input.agentRef)\n throw new Error('Agent service time requires agentRef.');\n if (input.source === 'timer' && (!input.startedAt || !input.endedAt))\n throw new Error('Timer service time requires startedAt and endedAt.');\n if (input.startedAt && input.endedAt && input.startedAt >= input.endedAt)\n throw new Error('Service time startedAt must be before endedAt.');\n const { durationHours, ...fields } = input;\n if (\n input.evidence?.some(\n (item) => item?.kind === SERVICE_DURATION_HOURS_EVIDENCE,\n )\n )\n throw new Error(\n 'Use durationHours to supply reserved decimal-hours evidence.',\n );\n const hours =\n durationHours === undefined ? null : validateDurationHours(durationHours);\n if (\n hours !== null &&\n (input.durationSeconds != null || input.startedAt || input.endedAt)\n )\n throw new Error(\n 'Decimal-hours-only service time cannot also supply seconds or timestamps.',\n );\n if (hours === null && input.durationSeconds === null)\n throw new Error('Null durationSeconds requires durationHours.');\n const duration =\n hours !== null\n ? null\n : (input.durationSeconds ??\n (input.startedAt && input.endedAt\n ? Math.round(\n (input.endedAt.getTime() - input.startedAt.getTime()) / 1000,\n )\n : 0));\n if (duration !== null && (!Number.isSafeInteger(duration) || duration <= 0))\n throw new Error(\n 'Service time durationSeconds must be a positive integer.',\n );\n const entry = await this.entries.create({\n ...fields,\n durationSeconds: duration,\n evidence: JSON.stringify([\n ...(input.evidence ?? []),\n ...(hours === null\n ? []\n : [{ kind: SERVICE_DURATION_HOURS_EVIDENCE, hours }]),\n ]),\n metadata: JSON.stringify(input.metadata ?? {}),\n status: 'draft',\n submittedAt: null,\n submittedByProfileId: null,\n approvedAt: null,\n approvedByProfileId: null,\n approvalPath: '',\n rejectedAt: null,\n rejectedByProfileId: null,\n rejectionReason: '',\n correctionOfId: null,\n });\n await entry.save();\n return entry;\n }\n\n async submit(\n entry: ServiceTimeEntry,\n profileId?: string,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'draft' && entry.status !== 'rejected')\n throw new Error('Only draft or rejected service time may be submitted.');\n entry.status = 'submitted';\n entry.submittedAt = new Date();\n entry.submittedByProfileId = profileId ?? null;\n return entry.save();\n }\n\n async approve(\n entry: ServiceTimeEntry,\n options: { actorProfileId?: string; approvalPath: string },\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'submitted' && entry.status !== 'approved')\n throw new Error(\n 'Only submitted service time or an incomplete approval may be approved.',\n );\n if (!this.commercial)\n throw new Error(\n 'A ServiceCommercialResolver is required to approve service time.',\n );\n const timeEntryId = entry.id;\n if (!timeEntryId)\n throw new Error('ServiceTimeEntry must be saved before approval.');\n const existingCharge = (\n await this.charges.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n const existingCompensation = (\n await this.compensation.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n if (entry.status === 'approved' && existingCharge && existingCompensation)\n return entry;\n\n await this.commercial.validateEntry?.(entry);\n\n // Commit approval before either commercial resolver runs. The subscription\n // resolver creates an approved ClientCharge as part of priceClient(), so a\n // failed approval must never leave billable spend behind.\n if (entry.status === 'submitted') {\n entry.status = 'approved';\n entry.approvedAt = new Date();\n entry.approvedByProfileId = options.actorProfileId ?? null;\n entry.approvalPath = options.approvalPath;\n try {\n await entry.save();\n } catch (error) {\n const revisionConflict =\n error instanceof Error &&\n 'code' in error &&\n error.code === 'RUNTIME_REVISION_CONFLICT';\n if (!revisionConflict) throw error;\n const concurrent = await this.entries.get(timeEntryId);\n if (concurrent?.status !== 'approved') throw error;\n entry = concurrent;\n await this.commercial.validateEntry?.(entry);\n }\n }\n const provider = existingCompensation\n ? null\n : await this.commercial.compensateProvider(entry);\n if (provider) {\n const snapshotId = await deterministicSnapshotId(\n 'service-compensation-snapshot',\n timeEntryId,\n );\n try {\n await this.compensation.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: provider.amount,\n currency: provider.currency ?? 'USD',\n termsVersion: provider.version,\n rateSnapshot: JSON.stringify(provider.terms),\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.compensation.get(snapshotId)) ??\n (\n await this.compensation.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n const client = existingCharge\n ? null\n : await this.commercial.priceClient(entry);\n if (client) {\n const snapshotId = await deterministicSnapshotId(\n 'service-charge-snapshot',\n timeEntryId,\n );\n try {\n await this.charges.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: client.amount,\n currency: client.currency ?? 'USD',\n pricingVersion: client.version,\n strategy: client.strategy ?? '',\n rateSnapshot: JSON.stringify(client.terms),\n sourceChargeRef: client.sourceRef ?? '',\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.charges.get(snapshotId)) ??\n (\n await this.charges.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n return entry;\n }\n\n async correct(\n entry: ServiceTimeEntry,\n input: RecordServiceTimeInput,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'approved')\n throw new Error('Only approved service time may be corrected.');\n if (input.tenantId !== undefined && input.tenantId !== entry.tenantId) {\n throw new Error(\n 'Service time corrections must remain in the original tenant.',\n );\n }\n const correction = await this.record({\n ...input,\n tenantId: entry.tenantId,\n });\n correction.correctionOfId = entry.id ?? null;\n await correction.save();\n entry.status = 'corrected';\n await entry.save();\n return correction;\n }\n}\n\nasync function deterministicSnapshotId(\n kind: string,\n timeEntryId: string,\n): Promise<string> {\n const bytes = new TextEncoder().encode(JSON.stringify([kind, timeEntryId]));\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n const uuid = digest.slice(0, 16);\n uuid[6] = (uuid[6] & 0x0f) | 0x50;\n uuid[8] = (uuid[8] & 0x3f) | 0x80;\n const hex = Array.from(uuid, (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20),\n ].join('-');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/models/service-snapshots.ts","../src/services/service-evidence-service.ts"],"sourcesContent":["import {\n field,\n foreignKey,\n SmrtCollection,\n SmrtObject,\n smrt,\n ValidationError,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\n/**\n * Refuse an amount that is not a JavaScript-safe integer number of minor\n * units. SQLite stores `19.99` in an INTEGER column without complaint and\n * PostgreSQL rejects it only at the driver, so the model boundary is the one\n * place both engines (and every writer: collections, `ServiceEvidenceService`,\n * resolvers) get the same answer. Sign is not constrained here.\n */\nexport function assertSnapshotMinorUnits(model: string, amount: unknown): void {\n if (typeof amount !== 'number' || !Number.isSafeInteger(amount)) {\n throw new ValidationError(\n `${model}.amount must be a safe integer number of minor units (cents) — ` +\n `got ${String(amount)}. $19.99 is 1999.`,\n 'VALIDATION_INVALID_VALUE',\n {\n fieldName: 'amount',\n value: amount,\n expectedType: 'safe integer minor units',\n },\n );\n }\n}\n\nconst chargeSnapshot = new WeakMap<ServiceChargeSnapshot, string>();\nconst compensationSnapshot = new WeakMap<ServiceCompensationSnapshot, string>();\n\nasync function immutableCommercialSnapshot(\n object: SmrtObject,\n fields: string[],\n): Promise<string | null> {\n if (!object.id) return null;\n try {\n const row = await object.db.get(object.tableName, { id: object.id });\n if (!row) return null;\n return JSON.stringify(\n Object.fromEntries(\n fields.map((key) => [\n key,\n row[key.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`)] ?? null,\n ]),\n ),\n );\n } catch {\n return null;\n }\n}\n\nfunction commercialSnapshot(\n object: Record<string, unknown>,\n fields: string[],\n): string {\n return JSON.stringify(\n Object.fromEntries(fields.map((key) => [key, object[key] ?? null])),\n );\n}\n\nconst CHARGE_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'pricingVersion',\n 'strategy',\n 'rateSnapshot',\n 'sourceChargeRef',\n];\nconst COMPENSATION_FIELDS = [\n 'timeEntryId',\n 'amount',\n 'currency',\n 'termsVersion',\n 'rateSnapshot',\n];\n\n/**\n * Immutable client-charge snapshot for one approved time entry. Money is\n * integer minor units, consistent with smrt-commerce (#2401).\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_charge_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceChargeSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceChargeSnapshot extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Client charge in **integer minor units** of {@link currency} — `$19.99` is\n * `1999`. The `= 0` initializer is load-bearing: SMRT maps an integer literal\n * to INTEGER and a decimal literal to DECIMAL (#2401).\n *\n * Copied verbatim from the upstream `ClientCharge.amount`, so the two carry\n * the same unit by construction; a split would land cents in a major-units\n * column with no error anywhere.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) pricingVersion: string = '';\n @field({ type: 'text' }) strategy: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n @field({ type: 'text' }) sourceChargeRef: string = '';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n chargeSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(): Promise<this> {\n assertSnapshotMinorUnits('ServiceChargeSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n CHARGE_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, CHARGE_FIELDS)) ??\n chargeSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceChargeSnapshot is immutable; append an upstream adjustment instead.',\n );\n const result = (await super.save()) as this;\n chargeSnapshot.set(this, current);\n return result;\n }\n}\n\n/**\n * Immutable provider-compensation snapshot for one approved time entry,\n * kept separate from the client charge so the margin is `charge - compensation`.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'service_compensation_snapshots',\n // Moved from smrt-projects in #3288; stored references keep resolving.\n previousQualifiedNames: [\n '@happyvertical/smrt-projects:ServiceCompensationSnapshot',\n ],\n conflictColumns: ['time_entry_id'],\n api: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n})\nexport class ServiceCompensationSnapshot extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-timesheets\";\n @tenantId({ nullable: true }) tenantId: string | null = null;\n @foreignKey('ServiceTimeEntry', { required: true }) timeEntryId: string = '';\n /**\n * Provider earning in **integer minor units** of {@link currency} (#2401).\n *\n * Converts with {@link ServiceChargeSnapshot.amount}: the delivery margin is\n * `charge - compensation`, so a mixed pair would make that subtraction\n * meaningless.\n */\n amount: number = 0;\n @field({ type: 'text' }) currency: string = 'USD';\n @field({ type: 'text' }) termsVersion: string = '';\n @field({ type: 'text' }) rateSnapshot: string = '{}';\n createdAt: Date = new Date();\n\n override async initialize(): Promise<this> {\n await super.initialize();\n if (await this.isSaved())\n compensationSnapshot.set(\n this,\n commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n ),\n );\n return this;\n }\n\n override async save(): Promise<this> {\n assertSnapshotMinorUnits('ServiceCompensationSnapshot', this.amount);\n const current = commercialSnapshot(\n this as unknown as Record<string, unknown>,\n COMPENSATION_FIELDS,\n );\n const prior =\n (await immutableCommercialSnapshot(this, COMPENSATION_FIELDS)) ??\n compensationSnapshot.get(this) ??\n null;\n if (prior && prior !== current)\n throw new Error(\n 'ServiceCompensationSnapshot is immutable; create explicit settlement evidence instead.',\n );\n const result = (await super.save()) as this;\n compensationSnapshot.set(this, current);\n return result;\n }\n}\n\n/** Collection over `service_charge_snapshots`. */\nexport class ServiceChargeSnapshotCollection extends SmrtCollection<ServiceChargeSnapshot> {\n static readonly _itemClass = ServiceChargeSnapshot;\n}\n/** Collection over `service_compensation_snapshots`. */\nexport class ServiceCompensationSnapshotCollection extends SmrtCollection<ServiceCompensationSnapshot> {\n static readonly _itemClass = ServiceCompensationSnapshot;\n}\n","import type { SmrtClassOptions } from '@happyvertical/smrt-core';\nimport {\n ServiceChargeSnapshotCollection,\n ServiceCompensationSnapshotCollection,\n} from '../models/service-snapshots.js';\nimport type { ServiceTimeEntry } from '../models/service-time-entry.js';\nimport {\n SERVICE_DURATION_HOURS_EVIDENCE,\n ServiceTimeEntryCollection,\n validateDurationHours,\n} from '../models/service-time-entry.js';\nimport type {\n ServiceEvidence,\n ServiceParticipantKind,\n ServiceTimeEntrySource,\n} from '../types.js';\n\n/**\n * Input for {@link ServiceEvidenceService.record}. The work reference is the\n * qualified class name and id of whatever the time was spent on.\n */\nexport interface RecordServiceTimeInput {\n tenantId?: string | null;\n workRefType?: string | null;\n workRefId?: string | null;\n participantKind: ServiceParticipantKind;\n participantProfileId?: string | null;\n agentRef?: string;\n source: ServiceTimeEntrySource;\n description: string;\n startedAt?: Date | null;\n endedAt?: Date | null;\n durationSeconds?: number | null;\n /** Exact positive decimal text; exclusive with seconds and timestamps. */\n durationHours?: string;\n evidence?: ServiceEvidence[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface CommercialSnapshot {\n /**\n * Integer minor units of `currency` — `$19.99` is `1999` (#2401).\n *\n * Written straight into `ServiceChargeSnapshot.amount` /\n * `ServiceCompensationSnapshot.amount`, INTEGER columns whose `save()`\n * refuses anything but a safe integer on every engine. A fractional\n * major-unit value (`19.99`) is rejected; a whole one (`150` for $150.00)\n * is not detectable and is stored 100× too small, so return minor units.\n */\n amount: number;\n currency?: string;\n version: string;\n strategy?: string;\n terms: Record<string, unknown>;\n sourceRef?: string;\n}\n\nexport interface ServiceCommercialResolver {\n /** Pure preflight: reject unsupported evidence before approval or snapshot writes. */\n validateEntry?(entry: ServiceTimeEntry): void | Promise<void>;\n priceClient(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n compensateProvider(entry: ServiceTimeEntry): Promise<CommercialSnapshot>;\n}\n\n/**\n * Records, submits, approves, and corrects time entries. Approval writes one\n * immutable client-charge and one provider-compensation snapshot per entry;\n * a correction is a new entry pointing at the approved one, which flips to\n * `corrected` with its snapshots intact.\n */\nexport class ServiceEvidenceService {\n constructor(\n private readonly entries: ServiceTimeEntryCollection,\n private readonly charges: ServiceChargeSnapshotCollection,\n private readonly compensation: ServiceCompensationSnapshotCollection,\n private readonly commercial?: ServiceCommercialResolver,\n ) {}\n\n static async create(\n options: SmrtClassOptions = {},\n commercial?: ServiceCommercialResolver,\n ): Promise<ServiceEvidenceService> {\n const [entries, charges, compensation] = await Promise.all([\n ServiceTimeEntryCollection.create(options),\n ServiceChargeSnapshotCollection.create(options),\n ServiceCompensationSnapshotCollection.create(options),\n ]);\n return new ServiceEvidenceService(\n entries,\n charges,\n compensation,\n commercial,\n );\n }\n\n async record(input: RecordServiceTimeInput): Promise<ServiceTimeEntry> {\n if (!['timer', 'manual', 'import', 'agent'].includes(input.source))\n throw new Error('Unsupported service time source.');\n if (Boolean(input.workRefType) !== Boolean(input.workRefId))\n throw new Error('workRefType and workRefId must be provided together.');\n if (!(input.workRefType && input.workRefId))\n throw new Error('Service time requires a work reference.');\n if (input.participantKind === 'human' && !input.participantProfileId)\n throw new Error('Human service time requires participantProfileId.');\n if (input.participantKind === 'agent' && !input.agentRef)\n throw new Error('Agent service time requires agentRef.');\n if (input.source === 'timer' && (!input.startedAt || !input.endedAt))\n throw new Error('Timer service time requires startedAt and endedAt.');\n if (input.startedAt && input.endedAt && input.startedAt >= input.endedAt)\n throw new Error('Service time startedAt must be before endedAt.');\n const { durationHours, ...fields } = input;\n if (\n input.evidence?.some(\n (item) => item?.kind === SERVICE_DURATION_HOURS_EVIDENCE,\n )\n )\n throw new Error(\n 'Use durationHours to supply reserved decimal-hours evidence.',\n );\n const hours =\n durationHours === undefined ? null : validateDurationHours(durationHours);\n if (\n hours !== null &&\n (input.durationSeconds != null || input.startedAt || input.endedAt)\n )\n throw new Error(\n 'Decimal-hours-only service time cannot also supply seconds or timestamps.',\n );\n if (hours === null && input.durationSeconds === null)\n throw new Error('Null durationSeconds requires durationHours.');\n const duration =\n hours !== null\n ? null\n : (input.durationSeconds ??\n (input.startedAt && input.endedAt\n ? Math.round(\n (input.endedAt.getTime() - input.startedAt.getTime()) / 1000,\n )\n : 0));\n if (duration !== null && (!Number.isSafeInteger(duration) || duration <= 0))\n throw new Error(\n 'Service time durationSeconds must be a positive integer.',\n );\n const entry = await this.entries.create({\n ...fields,\n durationSeconds: duration,\n evidence: JSON.stringify([\n ...(input.evidence ?? []),\n ...(hours === null\n ? []\n : [{ kind: SERVICE_DURATION_HOURS_EVIDENCE, hours }]),\n ]),\n metadata: JSON.stringify(input.metadata ?? {}),\n status: 'draft',\n submittedAt: null,\n submittedByProfileId: null,\n approvedAt: null,\n approvedByProfileId: null,\n approvalPath: '',\n rejectedAt: null,\n rejectedByProfileId: null,\n rejectionReason: '',\n correctionOfId: null,\n });\n await entry.save();\n return entry;\n }\n\n async submit(\n entry: ServiceTimeEntry,\n profileId?: string,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'draft' && entry.status !== 'rejected')\n throw new Error('Only draft or rejected service time may be submitted.');\n entry.status = 'submitted';\n entry.submittedAt = new Date();\n entry.submittedByProfileId = profileId ?? null;\n return entry.save();\n }\n\n async approve(\n entry: ServiceTimeEntry,\n options: { actorProfileId?: string; approvalPath: string },\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'submitted' && entry.status !== 'approved')\n throw new Error(\n 'Only submitted service time or an incomplete approval may be approved.',\n );\n if (!this.commercial)\n throw new Error(\n 'A ServiceCommercialResolver is required to approve service time.',\n );\n const timeEntryId = entry.id;\n if (!timeEntryId)\n throw new Error('ServiceTimeEntry must be saved before approval.');\n const existingCharge = (\n await this.charges.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n const existingCompensation = (\n await this.compensation.list({ where: { timeEntryId }, limit: 1 })\n )[0];\n if (entry.status === 'approved' && existingCharge && existingCompensation)\n return entry;\n\n await this.commercial.validateEntry?.(entry);\n\n // Commit approval before either commercial resolver runs. The subscription\n // resolver creates an approved ClientCharge as part of priceClient(), so a\n // failed approval must never leave billable spend behind.\n if (entry.status === 'submitted') {\n entry.status = 'approved';\n entry.approvedAt = new Date();\n entry.approvedByProfileId = options.actorProfileId ?? null;\n entry.approvalPath = options.approvalPath;\n try {\n await entry.save();\n } catch (error) {\n const revisionConflict =\n error instanceof Error &&\n 'code' in error &&\n error.code === 'RUNTIME_REVISION_CONFLICT';\n if (!revisionConflict) throw error;\n const concurrent = await this.entries.get(timeEntryId);\n if (concurrent?.status !== 'approved') throw error;\n entry = concurrent;\n await this.commercial.validateEntry?.(entry);\n }\n }\n const provider = existingCompensation\n ? null\n : await this.commercial.compensateProvider(entry);\n if (provider) {\n const snapshotId = await deterministicSnapshotId(\n 'service-compensation-snapshot',\n timeEntryId,\n );\n try {\n await this.compensation.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: provider.amount,\n currency: provider.currency ?? 'USD',\n termsVersion: provider.version,\n rateSnapshot: JSON.stringify(provider.terms),\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.compensation.get(snapshotId)) ??\n (\n await this.compensation.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n const client = existingCharge\n ? null\n : await this.commercial.priceClient(entry);\n if (client) {\n const snapshotId = await deterministicSnapshotId(\n 'service-charge-snapshot',\n timeEntryId,\n );\n try {\n await this.charges.create({\n id: snapshotId,\n tenantId: entry.tenantId,\n timeEntryId,\n amount: client.amount,\n currency: client.currency ?? 'USD',\n pricingVersion: client.version,\n strategy: client.strategy ?? '',\n rateSnapshot: JSON.stringify(client.terms),\n sourceChargeRef: client.sourceRef ?? '',\n _insertOnly: true,\n });\n } catch (error) {\n const concurrent =\n (await this.charges.get(snapshotId)) ??\n (\n await this.charges.list({\n where: { timeEntryId },\n limit: 1,\n })\n )[0];\n if (!concurrent) throw error;\n }\n }\n return entry;\n }\n\n async correct(\n entry: ServiceTimeEntry,\n input: RecordServiceTimeInput,\n ): Promise<ServiceTimeEntry> {\n if (entry.status !== 'approved')\n throw new Error('Only approved service time may be corrected.');\n if (input.tenantId !== undefined && input.tenantId !== entry.tenantId) {\n throw new Error(\n 'Service time corrections must remain in the original tenant.',\n );\n }\n const correction = await this.record({\n ...input,\n tenantId: entry.tenantId,\n });\n correction.correctionOfId = entry.id ?? null;\n await correction.save();\n entry.status = 'corrected';\n await entry.save();\n return correction;\n }\n}\n\nasync function deterministicSnapshotId(\n kind: string,\n timeEntryId: string,\n): Promise<string> {\n const bytes = new TextEncoder().encode(JSON.stringify([kind, timeEntryId]));\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n const uuid = digest.slice(0, 16);\n uuid[6] = (uuid[6] & 0x0f) | 0x50;\n uuid[8] = (uuid[8] & 0x3f) | 0x80;\n const hex = Array.from(uuid, (byte) =>\n byte.toString(16).padStart(2, '0'),\n ).join('');\n return [\n hex.slice(0, 8),\n hex.slice(8, 12),\n hex.slice(12, 16),\n hex.slice(16, 20),\n hex.slice(20),\n ].join('-');\n}\n"],"mappings":"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"}
|
package/dist/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": "1.0.0",
|
|
3
3
|
"timestamp": 0,
|
|
4
4
|
"packageName": "@happyvertical/smrt-timesheets",
|
|
5
|
-
"packageVersion": "0.54.
|
|
5
|
+
"packageVersion": "0.54.4",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-timesheets:AttendancePunch": {
|
|
8
8
|
"name": "attendancepunch",
|
|
@@ -3325,5 +3325,6 @@
|
|
|
3325
3325
|
"smrtDependencies": [
|
|
3326
3326
|
"@happyvertical/smrt-core",
|
|
3327
3327
|
"@happyvertical/smrt-tenancy"
|
|
3328
|
-
]
|
|
3328
|
+
],
|
|
3329
|
+
"stampsConstructors": true
|
|
3329
3330
|
}
|
package/dist/rollup.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as PeriodTimecard, c as TimecardAdjustmentCollection, o as PeriodTimecardCollection, s as TimecardAdjustment, t as PeriodRollupService } from "./chunks/rollup-
|
|
1
|
+
import { a as PeriodTimecard, c as TimecardAdjustmentCollection, o as PeriodTimecardCollection, s as TimecardAdjustment, t as PeriodRollupService } from "./chunks/rollup-C_JC3hUx.js";
|
|
2
2
|
export { PeriodRollupService, PeriodTimecard, PeriodTimecardCollection, TimecardAdjustment, TimecardAdjustmentCollection };
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
"sensitiveFieldsExcluded": true,
|
|
4
4
|
"generatedAt": "1970-01-01T00:00:00.000Z",
|
|
5
5
|
"packageName": "@happyvertical/smrt-timesheets",
|
|
6
|
-
"packageVersion": "0.54.
|
|
6
|
+
"packageVersion": "0.54.4",
|
|
7
7
|
"sourceManifestPath": "dist/manifest.json",
|
|
8
8
|
"agentDocPath": "AGENTS.md",
|
|
9
9
|
"sourceHashes": {
|
|
10
|
-
"manifest": "
|
|
11
|
-
"packageJson": "
|
|
10
|
+
"manifest": "f2f071827dbb95d816be8150958ce953cfdee3d7a1086340930fcd39785da1d5",
|
|
11
|
+
"packageJson": "9506b53905f014af81b0f79b69745b199a645abdbcc4a38c0bef7814378bed8e",
|
|
12
12
|
"agents": "21421ad5f02335e4c994227122c13b881d10e9f9d55ae09c3ac8ffa4bc2a7e09",
|
|
13
13
|
"moduleDoc:agents/period-rollup.md": "5fb741659d81dbef2e4850c10c2d65f09e3f5a83e8a88e2e0f19585f25158a6a"
|
|
14
14
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-timesheets",
|
|
3
|
-
"version": "0.54.
|
|
3
|
+
"version": "0.54.4",
|
|
4
4
|
"smrtJsdoc": "strict",
|
|
5
5
|
"description": "Shared time entries for the SMRT framework: who worked how long on what, approval and correction, with immutable charge and compensation snapshots",
|
|
6
6
|
"type": "module",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
}
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@happyvertical/smrt-core": "0.54.
|
|
43
|
-
"@happyvertical/smrt-tenancy": "0.54.
|
|
44
|
-
"@happyvertical/smrt-types": "0.54.
|
|
45
|
-
"@happyvertical/smrt-ui": "0.54.
|
|
46
|
-
"@happyvertical/sql": "^0.
|
|
42
|
+
"@happyvertical/smrt-core": "0.54.4",
|
|
43
|
+
"@happyvertical/smrt-tenancy": "0.54.4",
|
|
44
|
+
"@happyvertical/smrt-types": "0.54.4",
|
|
45
|
+
"@happyvertical/smrt-ui": "0.54.4",
|
|
46
|
+
"@happyvertical/sql": "^0.102.1"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"svelte": "^5.57.0"
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@happyvertical/smrt-vitest": "0.54.
|
|
57
|
+
"@happyvertical/smrt-vitest": "0.54.4",
|
|
58
58
|
"@sveltejs/package": "^2.5.8",
|
|
59
59
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
60
60
|
"@types/node": "24.13.6",
|