@open-mercato/core 0.6.6-develop.6460.1.f94c74174c → 0.6.6-develop.6465.1.019f0fb26f

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.
Files changed (50) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/auth.js +148 -82
  3. package/dist/helpers/integration/auth.js.map +2 -2
  4. package/dist/modules/sales/api/document-addresses/route.js +96 -6
  5. package/dist/modules/sales/api/document-addresses/route.js.map +2 -2
  6. package/dist/modules/sales/commands/documentAddresses.js +7 -0
  7. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  8. package/dist/modules/staff/commands/activities.js +23 -12
  9. package/dist/modules/staff/commands/activities.js.map +2 -2
  10. package/dist/modules/staff/commands/addresses.js +20 -12
  11. package/dist/modules/staff/commands/addresses.js.map +2 -2
  12. package/dist/modules/staff/commands/comments.js +18 -11
  13. package/dist/modules/staff/commands/comments.js.map +2 -2
  14. package/dist/modules/staff/commands/job-histories.js +23 -12
  15. package/dist/modules/staff/commands/job-histories.js.map +2 -2
  16. package/dist/modules/staff/commands/leave-requests.js +37 -19
  17. package/dist/modules/staff/commands/leave-requests.js.map +2 -2
  18. package/dist/modules/staff/commands/shared.js +28 -1
  19. package/dist/modules/staff/commands/shared.js.map +2 -2
  20. package/dist/modules/staff/commands/tag-assignments.js +20 -3
  21. package/dist/modules/staff/commands/tag-assignments.js.map +2 -2
  22. package/dist/modules/staff/commands/team-members.js +21 -11
  23. package/dist/modules/staff/commands/team-members.js.map +2 -2
  24. package/dist/modules/staff/commands/team-roles.js +21 -11
  25. package/dist/modules/staff/commands/team-roles.js.map +2 -2
  26. package/dist/modules/staff/commands/teams.js +21 -11
  27. package/dist/modules/staff/commands/teams.js.map +2 -2
  28. package/dist/modules/staff/commands/timesheets-entries.js +24 -14
  29. package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
  30. package/dist/modules/staff/commands/timesheets-projects.js +34 -18
  31. package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
  32. package/dist/modules/workflows/api/instances/route.js +1 -1
  33. package/dist/modules/workflows/api/instances/route.js.map +2 -2
  34. package/package.json +7 -7
  35. package/src/helpers/integration/auth.ts +178 -86
  36. package/src/modules/sales/api/document-addresses/route.ts +140 -7
  37. package/src/modules/sales/commands/documentAddresses.ts +8 -0
  38. package/src/modules/staff/commands/activities.ts +23 -11
  39. package/src/modules/staff/commands/addresses.ts +20 -11
  40. package/src/modules/staff/commands/comments.ts +18 -10
  41. package/src/modules/staff/commands/job-histories.ts +27 -11
  42. package/src/modules/staff/commands/leave-requests.ts +38 -19
  43. package/src/modules/staff/commands/shared.ts +38 -0
  44. package/src/modules/staff/commands/tag-assignments.ts +19 -2
  45. package/src/modules/staff/commands/team-members.ts +21 -10
  46. package/src/modules/staff/commands/team-roles.ts +21 -10
  47. package/src/modules/staff/commands/teams.ts +21 -10
  48. package/src/modules/staff/commands/timesheets-entries.ts +24 -13
  49. package/src/modules/staff/commands/timesheets-projects.ts +34 -17
  50. package/src/modules/workflows/api/instances/route.ts +2 -2
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/timesheets-entries.ts"],
4
- "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTimeEntry, StaffTimeEntrySegment, StaffTimeProject, type StaffTimeEntrySource } from '../data/entities'\nimport { emitStaffEvent } from '../events'\n\nconst timeEntryCrudIndexer: CrudIndexerConfig<StaffTimeEntry> = {\n entityType: 'staff:staff_time_entry',\n}\nimport {\n staffTimeEntryCreateSchema,\n staffTimeEntryStartTimerSchema,\n staffTimeEntryUpdateSchema,\n type StaffTimeEntryCreateInput,\n type StaffTimeEntryStartTimerInput,\n type StaffTimeEntryUpdateInput,\n} from '../data/validators'\nimport { staffTimeEntryCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n} from './shared'\nimport { getStaffMemberByUserId } from '../lib/staffMemberResolver'\n\ntype RbacServiceLike = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n scope: { tenantId: string | null; organizationId: string | null },\n ) => Promise<boolean>\n}\n\n/**\n * Returns true when the caller holds `staff.timesheets.manage_all`, honoring\n * wildcard ACL grants (`staff.*`, `*`) and the super-admin flag via the cached\n * rbacService. Returns false when no auth context (e.g. system/CLI ctx) so\n * write paths that lack a caller identity are NOT silently elevated.\n */\nasync function callerHasManageAll(ctx: {\n auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null\n container: { resolve: (token: string) => unknown }\n}): Promise<boolean> {\n const userId = ctx.auth?.sub\n if (!userId) return false\n try {\n const rbac = ctx.container.resolve('rbacService') as RbacServiceLike | undefined\n if (!rbac?.userHasAllFeatures) return false\n return await rbac.userHasAllFeatures(\n userId,\n ['staff.timesheets.manage_all'],\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n } catch {\n return false\n }\n}\n\nasync function resolveCallerStaffMemberId(\n em: EntityManager,\n ctx: { auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null },\n): Promise<string | null> {\n const userId = ctx.auth?.sub\n if (!userId) return null\n const member = await getStaffMemberByUserId(\n em,\n userId,\n ctx.auth?.tenantId ?? null,\n ctx.auth?.orgId ?? null,\n )\n return member?.id ?? null\n}\n\n/**\n * Verifies the referenced time project exists and is in-scope (same tenant + org,\n * not soft-deleted). Throws 422 if the ID is provided but unresolvable.\n * No-op when projectId is null/undefined (timeProjectId is optional on entries).\n */\nasync function assertTimeProjectInScope(\n em: EntityManager,\n projectId: string | null | undefined,\n tenantId: string,\n organizationId: string,\n): Promise<void> {\n if (!projectId) return\n const exists = await em.findOne(\n StaffTimeProject,\n { id: projectId, tenantId, organizationId, deletedAt: null },\n { fields: ['id'] },\n )\n if (!exists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n}\n\ntype TimeEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n staffMemberId: string\n date: string\n durationMinutes: number\n startedAt: string | null\n endedAt: string | null\n notes: string | null\n timeProjectId: string | null\n customerId: string | null\n dealId: string | null\n orderId: string | null\n source: string\n deletedAt: string | null\n}\n\ntype TimeEntryUndoPayload = {\n before?: TimeEntrySnapshot | null\n after?: TimeEntrySnapshot | null\n}\n\nasync function loadTimeEntrySnapshot(em: EntityManager, id: string): Promise<TimeEntrySnapshot | null> {\n const entry = await findOneWithDecryption(em, StaffTimeEntry, { id }, undefined, { tenantId: null, organizationId: null })\n if (!entry) return null\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n staffMemberId: entry.staffMemberId,\n date: entry.date instanceof Date ? entry.date.toISOString().split('T')[0] : String(entry.date),\n durationMinutes: entry.durationMinutes,\n startedAt: entry.startedAt ? entry.startedAt.toISOString() : null,\n endedAt: entry.endedAt ? entry.endedAt.toISOString() : null,\n notes: entry.notes ?? null,\n timeProjectId: entry.timeProjectId ?? null,\n customerId: entry.customerId ?? null,\n dealId: entry.dealId ?? null,\n orderId: entry.orderId ?? null,\n source: entry.source,\n deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeEntrySeedFromSnapshot(snapshot: TimeEntrySnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n staffMemberId: snapshot.staffMemberId,\n date: snapshot.date,\n durationMinutes: snapshot.durationMinutes,\n startedAt: snapshot.startedAt ? new Date(snapshot.startedAt) : null,\n endedAt: snapshot.endedAt ? new Date(snapshot.endedAt) : null,\n notes: snapshot.notes ?? null,\n timeProjectId: snapshot.timeProjectId ?? null,\n customerId: snapshot.customerId ?? null,\n dealId: snapshot.dealId ?? null,\n orderId: snapshot.orderId ?? null,\n source: (snapshot.source ?? 'manual') as StaffTimeEntrySource,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeEntryCommand: CommandHandler<StaffTimeEntryCreateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only create entries attributed to themselves. Silent override\n // (mirrors `bulk/route.ts` behavior) so the request body's staffMemberId\n // can't forge an entry under a colleague's identity.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n // Validate referenced timeProjectId is in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const entry = em.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: parsed.durationMinutes,\n startedAt: parsed.startedAt ?? null,\n endedAt: parsed.endedAt ?? null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: parsed.customerId ?? null,\n dealId: parsed.dealId ?? null,\n orderId: parsed.orderId ?? null,\n source: parsed.source ?? 'manual',\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(entry)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.create', 'Create time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: after.id })\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeEntry, TimeEntrySnapshot, StaffTimeEntryCreateInput, { timeEntryId: string }>({\n entityClass: StaffTimeEntry,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeEntrySeedFromSnapshot,\n buildResult: (entity) => ({ timeEntryId: entity.id }),\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n }),\n}\n\nconst startTimerCommand: CommandHandler<StaffTimeEntryStartTimerInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.start_timer',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryStartTimerSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement mirrors createTimeEntryCommand: callers without\n // `staff.timesheets.manage_all` can only start their own timer, so the\n // request body's staffMemberId can't start a timer under a colleague's id.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const scopeCtx = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }\n\n // Create the timer entry AND start it inside a single transaction so a\n // partial failure can never leave an orphaned, never-started timer entry\n // (issue #3311 \u2014 the legacy two-request create-then-start flow). The\n // single-active-timer invariant (#2855) is re-checked here so a second\n // surface cannot create a parallel running timer for the same staff member.\n const { entry, startedAt } = await em.transactional(async (trx) => {\n const otherRunningEntry = await findOneWithDecryption(\n trx,\n StaffTimeEntry,\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n startedAt: { $ne: null },\n endedAt: null,\n deletedAt: null,\n },\n {},\n scopeCtx,\n )\n if (otherRunningEntry) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n 'staff.timesheets.errors.timerAlreadyRunning',\n 'Another timer is already running. Stop it before starting a new one.',\n ),\n })\n }\n\n const startedAt = new Date()\n const entry = trx.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: 0,\n startedAt,\n endedAt: null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: null,\n dealId: null,\n orderId: null,\n source: 'timer',\n createdAt: startedAt,\n updatedAt: startedAt,\n deletedAt: null,\n })\n // Flush so the DB-generated id is populated before the work segment\n // references it; both writes commit together when the transaction closes.\n await trx.flush()\n\n const segmentData = {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeEntryId: entry.id,\n startedAt,\n segmentType: 'work' as const,\n }\n trx.create(StaffTimeEntrySegment, segmentData as never)\n await trx.flush()\n\n return { entry, startedAt }\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n void emitStaffEvent('staff.timesheets.time_entry.timer_started', {\n id: entry.id,\n staffMemberId: effectiveStaffMemberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n startedAt: startedAt.toISOString(),\n }, { persistent: true }).catch((err) => {\n console.error('[staff.timesheets] emit timer_started failed', err)\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.startTimer', 'Start timer'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: after.id })\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n}\n\nconst updateTimeEntryCommand: CommandHandler<StaffTimeEntryUpdateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, parsed.id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n applyScopeToWhere<StaffTimeEntry>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only update entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n // Validate referenced timeProjectId is in-scope when it's being changed to a non-null value.\n if (parsed.timeProjectId !== undefined && parsed.timeProjectId !== null) {\n await assertTimeProjectInScope(em, parsed.timeProjectId, entry.tenantId, entry.organizationId)\n }\n\n if (parsed.date !== undefined) entry.date = parsed.date\n if (parsed.durationMinutes !== undefined) entry.durationMinutes = parsed.durationMinutes\n if (parsed.timeProjectId !== undefined) entry.timeProjectId = parsed.timeProjectId ?? null\n if (parsed.customerId !== undefined) entry.customerId = parsed.customerId ?? null\n if (parsed.dealId !== undefined) entry.dealId = parsed.dealId ?? null\n if (parsed.orderId !== undefined) entry.orderId = parsed.orderId ?? null\n if (parsed.notes !== undefined) entry.notes = parsed.notes ?? null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeEntrySnapshot(em, before.id)\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'date',\n 'durationMinutes',\n 'timeProjectId',\n 'customerId',\n 'dealId',\n 'orderId',\n 'notes',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.update', 'Update time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) return\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.notes = before.notes ?? null\n entry.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nconst deleteTimeEntryCommand: CommandHandler<{ id?: string }, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n applyScopeToWhere<StaffTimeEntry>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only delete entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n entry.deletedAt = new Date()\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.delete', 'Delete time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await em.findOne(StaffTimeEntry, { id: before.id })\n if (!entry) {\n entry = em.create(StaffTimeEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n staffMemberId: before.staffMemberId,\n date: before.date as unknown as Date,\n durationMinutes: before.durationMinutes,\n startedAt: before.startedAt ? new Date(before.startedAt) : null,\n endedAt: before.endedAt ? new Date(before.endedAt) : null,\n notes: before.notes ?? null,\n timeProjectId: before.timeProjectId ?? null,\n customerId: before.customerId ?? null,\n dealId: before.dealId ?? null,\n orderId: before.orderId ?? null,\n source: (before.source ?? 'manual') as StaffTimeEntrySource,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n } else {\n entry.staffMemberId = before.staffMemberId\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.startedAt = before.startedAt ? new Date(before.startedAt) : null\n entry.endedAt = before.endedAt ? new Date(before.endedAt) : null\n entry.notes = before.notes ?? null\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.source = (before.source ?? 'manual') as StaffTimeEntrySource\n entry.deletedAt = null\n entry.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeEntryCommand)\nregisterCommand(startTimerCommand)\nregisterCommand(updateTimeEntryCommand)\nregisterCommand(deleteTimeEntryCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTimeEntry, StaffTimeEntrySegment, StaffTimeProject, type StaffTimeEntrySource } from '../data/entities'\nimport { emitStaffEvent } from '../events'\n\nconst timeEntryCrudIndexer: CrudIndexerConfig<StaffTimeEntry> = {\n entityType: 'staff:staff_time_entry',\n}\nimport {\n staffTimeEntryCreateSchema,\n staffTimeEntryStartTimerSchema,\n staffTimeEntryUpdateSchema,\n type StaffTimeEntryCreateInput,\n type StaffTimeEntryStartTimerInput,\n type StaffTimeEntryUpdateInput,\n} from '../data/validators'\nimport { staffTimeEntryCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\nimport { getStaffMemberByUserId } from '../lib/staffMemberResolver'\n\ntype RbacServiceLike = {\n userHasAllFeatures: (\n userId: string,\n required: string[],\n scope: { tenantId: string | null; organizationId: string | null },\n ) => Promise<boolean>\n}\n\n/**\n * Returns true when the caller holds `staff.timesheets.manage_all`, honoring\n * wildcard ACL grants (`staff.*`, `*`) and the super-admin flag via the cached\n * rbacService. Returns false when no auth context (e.g. system/CLI ctx) so\n * write paths that lack a caller identity are NOT silently elevated.\n */\nasync function callerHasManageAll(ctx: {\n auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null\n container: { resolve: (token: string) => unknown }\n}): Promise<boolean> {\n const userId = ctx.auth?.sub\n if (!userId) return false\n try {\n const rbac = ctx.container.resolve('rbacService') as RbacServiceLike | undefined\n if (!rbac?.userHasAllFeatures) return false\n return await rbac.userHasAllFeatures(\n userId,\n ['staff.timesheets.manage_all'],\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n } catch {\n return false\n }\n}\n\nasync function resolveCallerStaffMemberId(\n em: EntityManager,\n ctx: { auth?: { sub?: string | null; tenantId?: string | null; orgId?: string | null } | null },\n): Promise<string | null> {\n const userId = ctx.auth?.sub\n if (!userId) return null\n const member = await getStaffMemberByUserId(\n em,\n userId,\n ctx.auth?.tenantId ?? null,\n ctx.auth?.orgId ?? null,\n )\n return member?.id ?? null\n}\n\n/**\n * Verifies the referenced time project exists and is in-scope (same tenant + org,\n * not soft-deleted). Throws 422 if the ID is provided but unresolvable.\n * No-op when projectId is null/undefined (timeProjectId is optional on entries).\n */\nasync function assertTimeProjectInScope(\n em: EntityManager,\n projectId: string | null | undefined,\n tenantId: string,\n organizationId: string,\n): Promise<void> {\n if (!projectId) return\n const exists = await em.findOne(\n StaffTimeProject,\n { id: projectId, tenantId, organizationId, deletedAt: null },\n { fields: ['id'] },\n )\n if (!exists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n}\n\ntype TimeEntrySnapshot = {\n id: string\n tenantId: string\n organizationId: string\n staffMemberId: string\n date: string\n durationMinutes: number\n startedAt: string | null\n endedAt: string | null\n notes: string | null\n timeProjectId: string | null\n customerId: string | null\n dealId: string | null\n orderId: string | null\n source: string\n deletedAt: string | null\n}\n\ntype TimeEntryUndoPayload = {\n before?: TimeEntrySnapshot | null\n after?: TimeEntrySnapshot | null\n}\n\nasync function loadTimeEntrySnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeEntrySnapshot | null> {\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!entry) return null\n return {\n id: entry.id,\n tenantId: entry.tenantId,\n organizationId: entry.organizationId,\n staffMemberId: entry.staffMemberId,\n date: entry.date instanceof Date ? entry.date.toISOString().split('T')[0] : String(entry.date),\n durationMinutes: entry.durationMinutes,\n startedAt: entry.startedAt ? entry.startedAt.toISOString() : null,\n endedAt: entry.endedAt ? entry.endedAt.toISOString() : null,\n notes: entry.notes ?? null,\n timeProjectId: entry.timeProjectId ?? null,\n customerId: entry.customerId ?? null,\n dealId: entry.dealId ?? null,\n orderId: entry.orderId ?? null,\n source: entry.source,\n deletedAt: entry.deletedAt ? entry.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeEntrySeedFromSnapshot(snapshot: TimeEntrySnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n staffMemberId: snapshot.staffMemberId,\n date: snapshot.date,\n durationMinutes: snapshot.durationMinutes,\n startedAt: snapshot.startedAt ? new Date(snapshot.startedAt) : null,\n endedAt: snapshot.endedAt ? new Date(snapshot.endedAt) : null,\n notes: snapshot.notes ?? null,\n timeProjectId: snapshot.timeProjectId ?? null,\n customerId: snapshot.customerId ?? null,\n dealId: snapshot.dealId ?? null,\n orderId: snapshot.orderId ?? null,\n source: (snapshot.source ?? 'manual') as StaffTimeEntrySource,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeEntryCommand: CommandHandler<StaffTimeEntryCreateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only create entries attributed to themselves. Silent override\n // (mirrors `bulk/route.ts` behavior) so the request body's staffMemberId\n // can't forge an entry under a colleague's identity.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n // Validate referenced timeProjectId is in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const entry = em.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: parsed.durationMinutes,\n startedAt: parsed.startedAt ?? null,\n endedAt: parsed.endedAt ?? null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: parsed.customerId ?? null,\n dealId: parsed.dealId ?? null,\n orderId: parsed.orderId ?? null,\n source: parsed.source ?? 'manual',\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(entry)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.create', 'Create time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeEntry, TimeEntrySnapshot, StaffTimeEntryCreateInput, { timeEntryId: string }>({\n entityClass: StaffTimeEntry,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeEntrySeedFromSnapshot,\n buildResult: (entity) => ({ timeEntryId: entity.id }),\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n }),\n}\n\nconst startTimerCommand: CommandHandler<StaffTimeEntryStartTimerInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.start_timer',\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryStartTimerSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Ownership enforcement mirrors createTimeEntryCommand: callers without\n // `staff.timesheets.manage_all` can only start their own timer, so the\n // request body's staffMemberId can't start a timer under a colleague's id.\n let effectiveStaffMemberId = parsed.staffMemberId\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.noStaffMember', 'No staff member linked to your account.'),\n })\n }\n effectiveStaffMemberId = callerStaffMemberId\n }\n\n await assertTimeProjectInScope(em, parsed.timeProjectId ?? null, parsed.tenantId, parsed.organizationId)\n\n const scopeCtx = { tenantId: parsed.tenantId, organizationId: parsed.organizationId }\n\n // Create the timer entry AND start it inside a single transaction so a\n // partial failure can never leave an orphaned, never-started timer entry\n // (issue #3311 \u2014 the legacy two-request create-then-start flow). The\n // single-active-timer invariant (#2855) is re-checked here so a second\n // surface cannot create a parallel running timer for the same staff member.\n const { entry, startedAt } = await em.transactional(async (trx) => {\n const otherRunningEntry = await findOneWithDecryption(\n trx,\n StaffTimeEntry,\n {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n startedAt: { $ne: null },\n endedAt: null,\n deletedAt: null,\n },\n {},\n scopeCtx,\n )\n if (otherRunningEntry) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n 'staff.timesheets.errors.timerAlreadyRunning',\n 'Another timer is already running. Stop it before starting a new one.',\n ),\n })\n }\n\n const startedAt = new Date()\n const entry = trx.create(StaffTimeEntry, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n staffMemberId: effectiveStaffMemberId,\n date: parsed.date,\n durationMinutes: 0,\n startedAt,\n endedAt: null,\n notes: parsed.notes ?? null,\n timeProjectId: parsed.timeProjectId ?? null,\n customerId: null,\n dealId: null,\n orderId: null,\n source: 'timer',\n createdAt: startedAt,\n updatedAt: startedAt,\n deletedAt: null,\n })\n // Flush so the DB-generated id is populated before the work segment\n // references it; both writes commit together when the transaction closes.\n await trx.flush()\n\n const segmentData = {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeEntryId: entry.id,\n startedAt,\n segmentType: 'work' as const,\n }\n trx.create(StaffTimeEntrySegment, segmentData as never)\n await trx.flush()\n\n return { entry, startedAt }\n })\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n void emitStaffEvent('staff.timesheets.time_entry.timer_started', {\n id: entry.id,\n staffMemberId: effectiveStaffMemberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n startedAt: startedAt.toISOString(),\n }, { persistent: true }).catch((err) => {\n console.error('[staff.timesheets] emit timer_started failed', err)\n })\n\n return { timeEntryId: entry.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeEntrySnapshot(em, result.timeEntryId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.startTimer', 'Start timer'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (entry) {\n entry.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n })\n }\n },\n}\n\nconst updateTimeEntryCommand: CommandHandler<StaffTimeEntryUpdateInput, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeEntryUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n applyScopeToWhere<StaffTimeEntry>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only update entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n // Validate referenced timeProjectId is in-scope when it's being changed to a non-null value.\n if (parsed.timeProjectId !== undefined && parsed.timeProjectId !== null) {\n await assertTimeProjectInScope(em, parsed.timeProjectId, entry.tenantId, entry.organizationId)\n }\n\n if (parsed.date !== undefined) entry.date = parsed.date\n if (parsed.durationMinutes !== undefined) entry.durationMinutes = parsed.durationMinutes\n if (parsed.timeProjectId !== undefined) entry.timeProjectId = parsed.timeProjectId ?? null\n if (parsed.customerId !== undefined) entry.customerId = parsed.customerId ?? null\n if (parsed.dealId !== undefined) entry.dealId = parsed.dealId ?? null\n if (parsed.orderId !== undefined) entry.orderId = parsed.orderId ?? null\n if (parsed.notes !== undefined) entry.notes = parsed.notes ?? null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeEntrySnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'date',\n 'durationMinutes',\n 'timeProjectId',\n 'customerId',\n 'dealId',\n 'orderId',\n 'notes',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.update', 'Update time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!entry) return\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.notes = before.notes ?? null\n entry.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nconst deleteTimeEntryCommand: CommandHandler<{ id?: string }, { timeEntryId: string }> = {\n id: 'staff.timesheets.time_entries.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeEntrySnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time entry id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const entry = await findOneWithDecryption(\n em,\n StaffTimeEntry,\n applyScopeToWhere<StaffTimeEntry>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!entry) throw new CrudHttpError(404, { error: 'Time entry not found.' })\n ensureTenantScope(ctx, entry.tenantId)\n ensureOrganizationScope(ctx, entry.organizationId)\n\n // Ownership enforcement: callers without `staff.timesheets.manage_all`\n // can only delete entries they own.\n if (!(await callerHasManageAll(ctx))) {\n const callerStaffMemberId = await resolveCallerStaffMemberId(em, ctx)\n if (!callerStaffMemberId || entry.staffMemberId !== callerStaffMemberId) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(403, {\n error: translate('staff.timesheets.errors.notOwner', 'You can only manage your own time entries.'),\n })\n }\n }\n\n entry.deletedAt = new Date()\n entry.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n\n return { timeEntryId: entry.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeEntrySnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_entries.delete', 'Delete time entry'),\n resourceKind: 'staff.timesheets.time_entry',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeEntryUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeEntryUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!entry) {\n entry = em.create(StaffTimeEntry, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n staffMemberId: before.staffMemberId,\n date: before.date as unknown as Date,\n durationMinutes: before.durationMinutes,\n startedAt: before.startedAt ? new Date(before.startedAt) : null,\n endedAt: before.endedAt ? new Date(before.endedAt) : null,\n notes: before.notes ?? null,\n timeProjectId: before.timeProjectId ?? null,\n customerId: before.customerId ?? null,\n dealId: before.dealId ?? null,\n orderId: before.orderId ?? null,\n source: (before.source ?? 'manual') as StaffTimeEntrySource,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(entry)\n } else {\n entry.staffMemberId = before.staffMemberId\n entry.date = before.date as unknown as Date\n entry.durationMinutes = before.durationMinutes\n entry.startedAt = before.startedAt ? new Date(before.startedAt) : null\n entry.endedAt = before.endedAt ? new Date(before.endedAt) : null\n entry.notes = before.notes ?? null\n entry.timeProjectId = before.timeProjectId ?? null\n entry.customerId = before.customerId ?? null\n entry.dealId = before.dealId ?? null\n entry.orderId = before.orderId ?? null\n entry.source = (before.source ?? 'manual') as StaffTimeEntrySource\n entry.deletedAt = null\n entry.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: entry,\n identifiers: { id: entry.id, organizationId: entry.organizationId, tenantId: entry.tenantId },\n events: staffTimeEntryCrudEvents,\n indexer: timeEntryCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeEntryCommand)\nregisterCommand(startTimerCommand)\nregisterCommand(updateTimeEntryCommand)\nregisterCommand(deleteTimeEntryCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": ["startedAt", "entry"]
7
7
  }
@@ -25,7 +25,11 @@ import {
25
25
  ensureOrganizationScope,
26
26
  ensureTenantScope,
27
27
  extractUndoPayload,
28
- scopeForDecryption
28
+ scopeForDecryption,
29
+ scopedStaffSnapshotWhere,
30
+ staffSnapshotDecryptionScope,
31
+ staffSnapshotScopeFromContext,
32
+ staffSnapshotScopeFromSnapshot
29
33
  } from "./shared.js";
30
34
  function isUniqueViolation(error) {
31
35
  if (error instanceof UniqueConstraintViolationException) return true;
@@ -35,8 +39,14 @@ function isUniqueViolation(error) {
35
39
  const message = error.message;
36
40
  return typeof message === "string" && message.toLowerCase().includes("duplicate key");
37
41
  }
38
- async function loadTimeProjectSnapshot(em, id) {
39
- const project = await findOneWithDecryption(em, StaffTimeProject, { id }, void 0, { tenantId: null, organizationId: null });
42
+ async function loadTimeProjectSnapshot(em, id, scope) {
43
+ const project = await findOneWithDecryption(
44
+ em,
45
+ StaffTimeProject,
46
+ scopedStaffSnapshotWhere(id, scope),
47
+ void 0,
48
+ staffSnapshotDecryptionScope(scope)
49
+ );
40
50
  if (!project) return null;
41
51
  return {
42
52
  id: project.id,
@@ -55,8 +65,14 @@ async function loadTimeProjectSnapshot(em, id) {
55
65
  deletedAt: project.deletedAt ? project.deletedAt.toISOString() : null
56
66
  };
57
67
  }
58
- async function loadTimeProjectMemberSnapshot(em, id) {
59
- const member = await findOneWithDecryption(em, StaffTimeProjectMember, { id }, void 0, { tenantId: null, organizationId: null });
68
+ async function loadTimeProjectMemberSnapshot(em, id, scope) {
69
+ const member = await findOneWithDecryption(
70
+ em,
71
+ StaffTimeProjectMember,
72
+ scopedStaffSnapshotWhere(id, scope),
73
+ void 0,
74
+ staffSnapshotDecryptionScope(scope)
75
+ );
60
76
  if (!member) return null;
61
77
  return {
62
78
  id: member.id,
@@ -164,13 +180,13 @@ const createTimeProjectCommand = {
164
180
  },
165
181
  captureAfter: async (_input, result, ctx) => {
166
182
  const em = ctx.container.resolve("em").fork();
167
- const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId);
183
+ const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx));
168
184
  if (!snapshot) return null;
169
185
  return { snapshot };
170
186
  },
171
187
  buildLog: async ({ result, ctx }) => {
172
188
  const em = ctx.container.resolve("em").fork();
173
- const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId);
189
+ const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx));
174
190
  if (!snapshot) return null;
175
191
  const { translate } = await resolveTranslations();
176
192
  return {
@@ -192,7 +208,7 @@ const createTimeProjectCommand = {
192
208
  const after = payload?.after;
193
209
  if (!after) return;
194
210
  const em = ctx.container.resolve("em").fork();
195
- const project = await em.findOne(StaffTimeProject, { id: after.id });
211
+ const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
196
212
  if (project) {
197
213
  project.deletedAt = /* @__PURE__ */ new Date();
198
214
  await em.flush();
@@ -223,7 +239,7 @@ const updateTimeProjectCommand = {
223
239
  async prepare(rawInput, ctx) {
224
240
  const parsed = staffTimeProjectUpdateSchema.parse(rawInput);
225
241
  const em = ctx.container.resolve("em");
226
- const snapshot = await loadTimeProjectSnapshot(em, parsed.id);
242
+ const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx));
227
243
  if (!snapshot) return {};
228
244
  return { before: snapshot };
229
245
  },
@@ -282,7 +298,7 @@ const updateTimeProjectCommand = {
282
298
  const before = snapshots.before;
283
299
  if (!before) return null;
284
300
  const em = ctx.container.resolve("em").fork();
285
- const after = await loadTimeProjectSnapshot(em, before.id);
301
+ const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before));
286
302
  if (!after) return null;
287
303
  const changes = buildChanges(before, after, [
288
304
  "name",
@@ -320,7 +336,7 @@ const updateTimeProjectCommand = {
320
336
  const before = payload?.before;
321
337
  if (!before) return;
322
338
  const em = ctx.container.resolve("em").fork();
323
- const project = await em.findOne(StaffTimeProject, { id: before.id });
339
+ const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
324
340
  if (!project) return;
325
341
  project.name = before.name;
326
342
  project.customerId = before.customerId ?? null;
@@ -355,7 +371,7 @@ const deleteTimeProjectCommand = {
355
371
  const id = input?.id;
356
372
  if (!id) throw new CrudHttpError(400, { error: "Time project id is required." });
357
373
  const em = ctx.container.resolve("em");
358
- const snapshot = await loadTimeProjectSnapshot(em, id);
374
+ const snapshot = await loadTimeProjectSnapshot(em, id, staffSnapshotScopeFromContext(ctx));
359
375
  if (!snapshot) return {};
360
376
  return { before: snapshot };
361
377
  },
@@ -414,7 +430,7 @@ const deleteTimeProjectCommand = {
414
430
  const before = payload?.before;
415
431
  if (!before) return;
416
432
  const em = ctx.container.resolve("em").fork();
417
- let project = await em.findOne(StaffTimeProject, { id: before.id });
433
+ let project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
418
434
  if (!project) {
419
435
  project = em.create(StaffTimeProject, {
420
436
  id: before.id,
@@ -527,13 +543,13 @@ const assignTimeProjectMemberCommand = {
527
543
  },
528
544
  captureAfter: async (_input, result, ctx) => {
529
545
  const em = ctx.container.resolve("em").fork();
530
- const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId);
546
+ const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx));
531
547
  if (!snapshot) return null;
532
548
  return { snapshot };
533
549
  },
534
550
  buildLog: async ({ result, ctx }) => {
535
551
  const em = ctx.container.resolve("em").fork();
536
- const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId);
552
+ const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx));
537
553
  if (!snapshot) return null;
538
554
  const { translate } = await resolveTranslations();
539
555
  return {
@@ -555,7 +571,7 @@ const assignTimeProjectMemberCommand = {
555
571
  const after = payload?.after;
556
572
  if (!after) return;
557
573
  const em = ctx.container.resolve("em").fork();
558
- const member = await em.findOne(StaffTimeProjectMember, { id: after.id });
574
+ const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
559
575
  if (member) {
560
576
  member.deletedAt = /* @__PURE__ */ new Date();
561
577
  await em.flush();
@@ -583,7 +599,7 @@ const unassignTimeProjectMemberCommand = {
583
599
  const id = input?.id;
584
600
  if (!id) throw new CrudHttpError(400, { error: "Time project member id is required." });
585
601
  const em = ctx.container.resolve("em");
586
- const snapshot = await loadTimeProjectMemberSnapshot(em, id);
602
+ const snapshot = await loadTimeProjectMemberSnapshot(em, id, staffSnapshotScopeFromContext(ctx));
587
603
  if (!snapshot) return {};
588
604
  return { before: snapshot };
589
605
  },
@@ -638,7 +654,7 @@ const unassignTimeProjectMemberCommand = {
638
654
  const before = payload?.before;
639
655
  if (!before) return;
640
656
  const em = ctx.container.resolve("em").fork();
641
- let member = await em.findOne(StaffTimeProjectMember, { id: before.id });
657
+ let member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
642
658
  if (!member) {
643
659
  member = em.create(StaffTimeProjectMember, {
644
660
  id: before.id,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/staff/commands/timesheets-projects.ts"],
4
- "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMember, StaffTimeProject, StaffTimeProjectMember, type StaffTimeProjectStatus, type StaffTimeProjectMemberStatus } from '../data/entities'\n\nconst timeProjectCrudIndexer: CrudIndexerConfig<StaffTimeProject> = {\n entityType: 'staff:staff_time_project',\n}\nconst timeProjectMemberCrudIndexer: CrudIndexerConfig<StaffTimeProjectMember> = {\n entityType: 'staff:staff_time_project_member',\n}\nimport {\n staffTimeProjectCreateSchema,\n staffTimeProjectUpdateSchema,\n staffTimeProjectMemberAssignSchema,\n staffTimeProjectMemberUpdateSchema,\n type StaffTimeProjectCreateInput,\n type StaffTimeProjectUpdateInput,\n type StaffTimeProjectMemberAssignInput,\n type StaffTimeProjectMemberUpdateInput,\n} from '../data/validators'\nimport { staffTimeProjectCrudEvents, staffTimeProjectMemberCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n} from './shared'\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const message = (error as { message?: string }).message\n return typeof message === 'string' && message.toLowerCase().includes('duplicate key')\n}\n\ntype TimeProjectSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n name: string\n customerId: string | null\n code: string\n description: string | null\n projectType: string | null\n color: string | null\n status: string\n ownerUserId: string | null\n costCenter: string | null\n startDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectUndoPayload = {\n before?: TimeProjectSnapshot | null\n after?: TimeProjectSnapshot | null\n}\n\ntype TimeProjectMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n timeProjectId: string\n staffMemberId: string\n role: string | null\n status: string\n showInGrid: boolean\n assignedStartDate: string\n assignedEndDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectMemberUndoPayload = {\n before?: TimeProjectMemberSnapshot | null\n after?: TimeProjectMemberSnapshot | null\n}\n\nasync function loadTimeProjectSnapshot(em: EntityManager, id: string): Promise<TimeProjectSnapshot | null> {\n const project = await findOneWithDecryption(em, StaffTimeProject, { id }, undefined, { tenantId: null, organizationId: null })\n if (!project) return null\n return {\n id: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n name: project.name,\n customerId: project.customerId ?? null,\n code: project.code,\n description: project.description ?? null,\n projectType: project.projectType ?? null,\n color: project.color ?? null,\n status: project.status,\n ownerUserId: project.ownerUserId ?? null,\n costCenter: project.costCenter ?? null,\n startDate: project.startDate instanceof Date ? project.startDate.toISOString().split('T')[0] : (project.startDate ?? null),\n deletedAt: project.deletedAt ? project.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTimeProjectMemberSnapshot(em: EntityManager, id: string): Promise<TimeProjectMemberSnapshot | null> {\n const member = await findOneWithDecryption(em, StaffTimeProjectMember, { id }, undefined, { tenantId: null, organizationId: null })\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n timeProjectId: member.timeProjectId,\n staffMemberId: member.staffMemberId,\n role: member.role ?? null,\n status: member.status,\n showInGrid: member.showInGrid ?? false,\n assignedStartDate: member.assignedStartDate instanceof Date ? member.assignedStartDate.toISOString().split('T')[0] : String(member.assignedStartDate),\n assignedEndDate: member.assignedEndDate instanceof Date ? member.assignedEndDate.toISOString().split('T')[0] : (member.assignedEndDate ?? null),\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeProjectSeedFromSnapshot(snapshot: TimeProjectSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n name: snapshot.name,\n customerId: snapshot.customerId ?? null,\n code: snapshot.code,\n description: snapshot.description ?? null,\n projectType: snapshot.projectType ?? null,\n color: snapshot.color ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: snapshot.ownerUserId ?? null,\n costCenter: snapshot.costCenter ?? null,\n startDate: snapshot.startDate ? new Date(snapshot.startDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nfunction timeProjectMemberSeedFromSnapshot(snapshot: TimeProjectMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n timeProjectId: snapshot.timeProjectId,\n staffMemberId: snapshot.staffMemberId,\n role: snapshot.role ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: snapshot.showInGrid ?? false,\n assignedStartDate: new Date(snapshot.assignedStartDate),\n assignedEndDate: snapshot.assignedEndDate ? new Date(snapshot.assignedEndDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeProjectCommand: CommandHandler<StaffTimeProjectCreateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const now = new Date()\n const project = em.create(StaffTimeProject, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n name: parsed.name,\n customerId: parsed.customerId ?? null,\n code: parsed.code,\n description: parsed.description ?? null,\n projectType: parsed.projectType ?? null,\n color: parsed.color ?? null,\n status: parsed.status ?? 'active',\n ownerUserId: parsed.ownerUserId ?? null,\n costCenter: parsed.costCenter ?? null,\n startDate: parsed.startDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(project)\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.create', 'Create time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, { id: after.id })\n if (project) {\n project.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProject, TimeProjectSnapshot, StaffTimeProjectCreateInput, { timeProjectId: string }>({\n entityClass: StaffTimeProject,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectId: entity.id }),\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n }),\n}\n\nconst updateTimeProjectCommand: CommandHandler<StaffTimeProjectUpdateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n if (parsed.name !== undefined) project.name = parsed.name\n if (parsed.customerId !== undefined) project.customerId = parsed.customerId ?? null\n if (parsed.code !== undefined) project.code = parsed.code\n if (parsed.description !== undefined) project.description = parsed.description ?? null\n if (parsed.projectType !== undefined) project.projectType = parsed.projectType ?? null\n if (parsed.color !== undefined) project.color = parsed.color ?? null\n if (parsed.status !== undefined) project.status = parsed.status\n if (parsed.ownerUserId !== undefined) project.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.costCenter !== undefined) project.costCenter = parsed.costCenter ?? null\n if (parsed.startDate !== undefined) project.startDate = parsed.startDate ?? null\n project.updatedAt = new Date()\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id)\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'name',\n 'customerId',\n 'code',\n 'description',\n 'projectType',\n 'color',\n 'status',\n 'ownerUserId',\n 'costCenter',\n 'startDate',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.update', 'Update time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, { id: before.id })\n if (!project) return\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.color = before.color ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst deleteTimeProjectCommand: CommandHandler<{ id?: string }, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n project.deletedAt = new Date()\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.delete', 'Delete time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let project = await em.findOne(StaffTimeProject, { id: before.id })\n if (!project) {\n project = em.create(StaffTimeProject, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n name: before.name,\n customerId: before.customerId ?? null,\n code: before.code,\n description: before.description ?? null,\n projectType: before.projectType ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: before.ownerUserId ?? null,\n costCenter: before.costCenter ?? null,\n startDate: before.startDate ? new Date(before.startDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(project)\n } else {\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.deletedAt = null\n project.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst assignTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectMemberAssignSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Validate referenced project and staff member are in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n const projectExists = await em.findOne(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.timeProjectId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!projectExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n const memberExists = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.staffMemberId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!memberExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n fieldErrors: {\n staffMemberId: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n },\n })\n }\n\n const now = new Date()\n const member = em.create(StaffTimeProjectMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeProjectId: parsed.timeProjectId,\n staffMemberId: parsed.staffMemberId,\n role: parsed.role ?? null,\n status: parsed.status ?? 'active',\n showInGrid: false,\n assignedStartDate: parsed.assignedStartDate,\n assignedEndDate: parsed.assignedEndDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId)\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId)\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.assign', 'Assign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, { id: after.id })\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProjectMember, TimeProjectMemberSnapshot, StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }>({\n entityClass: StaffTimeProjectMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectMemberSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectMemberId: entity.id }),\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n }),\n}\n\nconst unassignTimeProjectMemberCommand: CommandHandler<{ id?: string }, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.unassign',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectMemberSnapshot(em, id)\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Time project member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.unassign', 'Unassign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTimeProjectMember, { id: before.id })\n if (!member) {\n member = em.create(StaffTimeProjectMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n timeProjectId: before.timeProjectId,\n staffMemberId: before.staffMemberId,\n role: before.role ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: before.showInGrid ?? false,\n assignedStartDate: new Date(before.assignedStartDate),\n assignedEndDate: before.assignedEndDate ? new Date(before.assignedEndDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.timeProjectId = before.timeProjectId\n member.staffMemberId = before.staffMemberId\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedStartDate = new Date(before.assignedStartDate)\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeProjectCommand)\nregisterCommand(updateTimeProjectCommand)\nregisterCommand(deleteTimeProjectCommand)\nregisterCommand(assignTimeProjectMemberCommand)\nregisterCommand(unassignTimeProjectMemberCommand)\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { UniqueConstraintViolationException } from '@mikro-orm/core'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMember, StaffTimeProject, StaffTimeProjectMember, type StaffTimeProjectStatus, type StaffTimeProjectMemberStatus } from '../data/entities'\n\nconst timeProjectCrudIndexer: CrudIndexerConfig<StaffTimeProject> = {\n entityType: 'staff:staff_time_project',\n}\nconst timeProjectMemberCrudIndexer: CrudIndexerConfig<StaffTimeProjectMember> = {\n entityType: 'staff:staff_time_project_member',\n}\nimport {\n staffTimeProjectCreateSchema,\n staffTimeProjectUpdateSchema,\n staffTimeProjectMemberAssignSchema,\n staffTimeProjectMemberUpdateSchema,\n type StaffTimeProjectCreateInput,\n type StaffTimeProjectUpdateInput,\n type StaffTimeProjectMemberAssignInput,\n type StaffTimeProjectMemberUpdateInput,\n} from '../data/validators'\nimport { staffTimeProjectCrudEvents, staffTimeProjectMemberCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\n\nfunction isUniqueViolation(error: unknown): boolean {\n if (error instanceof UniqueConstraintViolationException) return true\n if (!error || typeof error !== 'object') return false\n const code = (error as { code?: string }).code\n if (code === '23505') return true\n const message = (error as { message?: string }).message\n return typeof message === 'string' && message.toLowerCase().includes('duplicate key')\n}\n\ntype TimeProjectSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n name: string\n customerId: string | null\n code: string\n description: string | null\n projectType: string | null\n color: string | null\n status: string\n ownerUserId: string | null\n costCenter: string | null\n startDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectUndoPayload = {\n before?: TimeProjectSnapshot | null\n after?: TimeProjectSnapshot | null\n}\n\ntype TimeProjectMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n timeProjectId: string\n staffMemberId: string\n role: string | null\n status: string\n showInGrid: boolean\n assignedStartDate: string\n assignedEndDate: string | null\n deletedAt: string | null\n}\n\ntype TimeProjectMemberUndoPayload = {\n before?: TimeProjectMemberSnapshot | null\n after?: TimeProjectMemberSnapshot | null\n}\n\nasync function loadTimeProjectSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectSnapshot | null> {\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!project) return null\n return {\n id: project.id,\n tenantId: project.tenantId,\n organizationId: project.organizationId,\n name: project.name,\n customerId: project.customerId ?? null,\n code: project.code,\n description: project.description ?? null,\n projectType: project.projectType ?? null,\n color: project.color ?? null,\n status: project.status,\n ownerUserId: project.ownerUserId ?? null,\n costCenter: project.costCenter ?? null,\n startDate: project.startDate instanceof Date ? project.startDate.toISOString().split('T')[0] : (project.startDate ?? null),\n deletedAt: project.deletedAt ? project.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTimeProjectMemberSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<TimeProjectMemberSnapshot | null> {\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n timeProjectId: member.timeProjectId,\n staffMemberId: member.staffMemberId,\n role: member.role ?? null,\n status: member.status,\n showInGrid: member.showInGrid ?? false,\n assignedStartDate: member.assignedStartDate instanceof Date ? member.assignedStartDate.toISOString().split('T')[0] : String(member.assignedStartDate),\n assignedEndDate: member.assignedEndDate instanceof Date ? member.assignedEndDate.toISOString().split('T')[0] : (member.assignedEndDate ?? null),\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nfunction timeProjectSeedFromSnapshot(snapshot: TimeProjectSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n name: snapshot.name,\n customerId: snapshot.customerId ?? null,\n code: snapshot.code,\n description: snapshot.description ?? null,\n projectType: snapshot.projectType ?? null,\n color: snapshot.color ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: snapshot.ownerUserId ?? null,\n costCenter: snapshot.costCenter ?? null,\n startDate: snapshot.startDate ? new Date(snapshot.startDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nfunction timeProjectMemberSeedFromSnapshot(snapshot: TimeProjectMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n timeProjectId: snapshot.timeProjectId,\n staffMemberId: snapshot.staffMemberId,\n role: snapshot.role ?? null,\n status: (snapshot.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: snapshot.showInGrid ?? false,\n assignedStartDate: new Date(snapshot.assignedStartDate),\n assignedEndDate: snapshot.assignedEndDate ? new Date(snapshot.assignedEndDate) : null,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst createTimeProjectCommand: CommandHandler<StaffTimeProjectCreateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.create',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const now = new Date()\n const project = em.create(StaffTimeProject, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n name: parsed.name,\n customerId: parsed.customerId ?? null,\n code: parsed.code,\n description: parsed.description ?? null,\n projectType: parsed.projectType ?? null,\n color: parsed.color ?? null,\n status: parsed.status ?? 'active',\n ownerUserId: parsed.ownerUserId ?? null,\n costCenter: parsed.costCenter ?? null,\n startDate: parsed.startDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(project)\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectSnapshot(em, result.timeProjectId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.create', 'Create time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (project) {\n project.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProject, TimeProjectSnapshot, StaffTimeProjectCreateInput, { timeProjectId: string }>({\n entityClass: StaffTimeProject,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectId: entity.id }),\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n }),\n}\n\nconst updateTimeProjectCommand: CommandHandler<StaffTimeProjectUpdateInput, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n if (parsed.name !== undefined) project.name = parsed.name\n if (parsed.customerId !== undefined) project.customerId = parsed.customerId ?? null\n if (parsed.code !== undefined) project.code = parsed.code\n if (parsed.description !== undefined) project.description = parsed.description ?? null\n if (parsed.projectType !== undefined) project.projectType = parsed.projectType ?? null\n if (parsed.color !== undefined) project.color = parsed.color ?? null\n if (parsed.status !== undefined) project.status = parsed.status\n if (parsed.ownerUserId !== undefined) project.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.costCenter !== undefined) project.costCenter = parsed.costCenter ?? null\n if (parsed.startDate !== undefined) project.startDate = parsed.startDate ?? null\n project.updatedAt = new Date()\n try {\n await em.flush()\n } catch (err) {\n if (isUniqueViolation(err)) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.'),\n fieldErrors: { code: translate('staff.timesheets.errors.projectCodeDuplicate', 'A project with this code already exists.') },\n })\n }\n throw err\n }\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTimeProjectSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n if (!after) return null\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'name',\n 'customerId',\n 'code',\n 'description',\n 'projectType',\n 'color',\n 'status',\n 'ownerUserId',\n 'costCenter',\n 'startDate',\n 'deletedAt',\n ])\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.update', 'Update time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) return\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.color = before.color ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'updated',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst deleteTimeProjectCommand: CommandHandler<{ id?: string }, { timeProjectId: string }> = {\n id: 'staff.timesheets.time_projects.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const project = await findOneWithDecryption(\n em,\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!project) throw new CrudHttpError(404, { error: 'Time project not found.' })\n ensureTenantScope(ctx, project.tenantId)\n ensureOrganizationScope(ctx, project.organizationId)\n\n project.deletedAt = new Date()\n project.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n return { timeProjectId: project.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_projects.delete', 'Delete time project'),\n resourceKind: 'staff.timesheets.time_project',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let project = await em.findOne(StaffTimeProject, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!project) {\n project = em.create(StaffTimeProject, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n name: before.name,\n customerId: before.customerId ?? null,\n code: before.code,\n description: before.description ?? null,\n projectType: before.projectType ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectStatus,\n ownerUserId: before.ownerUserId ?? null,\n costCenter: before.costCenter ?? null,\n startDate: before.startDate ? new Date(before.startDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(project)\n } else {\n project.name = before.name\n project.customerId = before.customerId ?? null\n project.code = before.code\n project.description = before.description ?? null\n project.projectType = before.projectType ?? null\n project.status = (before.status ?? 'active') as StaffTimeProjectStatus\n project.ownerUserId = before.ownerUserId ?? null\n project.costCenter = before.costCenter ?? null\n project.startDate = before.startDate ? new Date(before.startDate) : null\n project.deletedAt = null\n project.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: project,\n identifiers: {\n id: project.id,\n organizationId: project.organizationId,\n tenantId: project.tenantId,\n },\n events: staffTimeProjectCrudEvents,\n indexer: timeProjectCrudIndexer,\n })\n },\n}\n\nconst assignTimeProjectMemberCommand: CommandHandler<StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTimeProjectMemberAssignSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n\n // Validate referenced project and staff member are in-scope before persisting.\n // Without this check a foreign or stale UUID would produce a dangling reference.\n const projectExists = await em.findOne(\n StaffTimeProject,\n applyScopeToWhere<StaffTimeProject>({ id: parsed.timeProjectId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!projectExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n fieldErrors: {\n timeProjectId: translate('staff.timesheets.errors.projectNotFound', 'Time project not found or not accessible.'),\n },\n })\n }\n const memberExists = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.staffMemberId, deletedAt: null }, scope),\n { fields: ['id'] },\n )\n if (!memberExists) {\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(422, {\n error: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n fieldErrors: {\n staffMemberId: translate('staff.timesheets.errors.staffMemberNotFound', 'Staff member not found or not accessible.'),\n },\n })\n }\n\n const now = new Date()\n const member = em.create(StaffTimeProjectMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n timeProjectId: parsed.timeProjectId,\n staffMemberId: parsed.staffMemberId,\n role: parsed.role ?? null,\n status: parsed.status ?? 'active',\n showInGrid: false,\n assignedStartDate: parsed.assignedStartDate,\n assignedEndDate: parsed.assignedEndDate ?? null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n return { snapshot }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTimeProjectMemberSnapshot(em, result.timeProjectMemberId, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.assign', 'Assign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n })\n }\n },\n redo: makeCreateRedo<StaffTimeProjectMember, TimeProjectMemberSnapshot, StaffTimeProjectMemberAssignInput, { timeProjectMemberId: string }>({\n entityClass: StaffTimeProjectMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: timeProjectMemberSeedFromSnapshot,\n buildResult: (entity) => ({ timeProjectMemberId: entity.id }),\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n }),\n}\n\nconst unassignTimeProjectMemberCommand: CommandHandler<{ id?: string }, { timeProjectMemberId: string }> = {\n id: 'staff.timesheets.time_project_members.unassign',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTimeProjectMemberSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n if (!snapshot) return {}\n return { before: snapshot }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Time project member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTimeProjectMember,\n applyScopeToWhere<StaffTimeProjectMember>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Time project member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n await emitCrudSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'deleted',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n\n return { timeProjectMemberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TimeProjectMemberSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.timesheets.time_project_members.unassign', 'Unassign time project member'),\n resourceKind: 'staff.timesheets.time_project_member',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies TimeProjectMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TimeProjectMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTimeProjectMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!member) {\n member = em.create(StaffTimeProjectMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n timeProjectId: before.timeProjectId,\n staffMemberId: before.staffMemberId,\n role: before.role ?? null,\n status: (before.status ?? 'active') as StaffTimeProjectMemberStatus,\n showInGrid: before.showInGrid ?? false,\n assignedStartDate: new Date(before.assignedStartDate),\n assignedEndDate: before.assignedEndDate ? new Date(before.assignedEndDate) : null,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.timeProjectId = before.timeProjectId\n member.staffMemberId = before.staffMemberId\n member.role = before.role ?? null\n member.status = (before.status ?? 'active') as StaffTimeProjectMemberStatus\n member.assignedStartDate = new Date(before.assignedStartDate)\n member.assignedEndDate = before.assignedEndDate ? new Date(before.assignedEndDate) : null\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n await emitCrudUndoSideEffects({\n dataEngine: ctx.container.resolve('dataEngine'),\n action: 'created',\n entity: member,\n identifiers: { id: member.id, organizationId: member.organizationId, tenantId: member.tenantId },\n events: staffTimeProjectMemberCrudEvents,\n indexer: timeProjectMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTimeProjectCommand)\nregisterCommand(updateTimeProjectCommand)\nregisterCommand(deleteTimeProjectCommand)\nregisterCommand(assignTimeProjectMemberCommand)\nregisterCommand(unassignTimeProjectMemberCommand)\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -147,7 +147,7 @@ async function POST(request) {
147
147
  const input = validation.data;
148
148
  const metadata2 = {
149
149
  ...input.metadata,
150
- initiatedBy: input.metadata?.initiatedBy || auth.sub
150
+ initiatedBy: auth.sub
151
151
  };
152
152
  const instance = await workflowExecutor.startWorkflow(em, {
153
153
  workflowId: input.workflowId,