@open-mercato/core 0.9.1-develop.7518.1.343d9198f1 → 0.9.1-develop.7532.1.8eac7e198f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/modules/auth/api/logout.js +6 -1
- package/dist/modules/auth/api/logout.js.map +2 -2
- package/dist/modules/auth/api/session/refresh.js +6 -1
- package/dist/modules/auth/api/session/refresh.js.map +2 -2
- package/dist/modules/catalog/ai-tools/mutation-pack.js +10 -5
- package/dist/modules/catalog/ai-tools/mutation-pack.js.map +2 -2
- package/dist/modules/catalog/ai-tools/types.js.map +2 -2
- package/dist/modules/customer_accounts/api/login.js +14 -7
- package/dist/modules/customer_accounts/api/login.js.map +2 -2
- package/dist/modules/customer_accounts/services/customerUserService.js +10 -10
- package/dist/modules/customer_accounts/services/customerUserService.js.map +2 -2
- package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js +1 -1
- package/dist/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.js.map +1 -1
- package/dist/modules/forms/api/form-submissions/[id]/submit/route.js +12 -2
- package/dist/modules/forms/api/form-submissions/[id]/submit/route.js.map +2 -2
- package/dist/modules/forms/api/form-submissions/route.js +16 -1
- package/dist/modules/forms/api/form-submissions/route.js.map +2 -2
- package/dist/modules/forms/api/public/submissions/[id]/submit/route.js +6 -1
- package/dist/modules/forms/api/public/submissions/[id]/submit/route.js.map +2 -2
- package/dist/modules/forms/api/runtime-helpers.js +16 -0
- package/dist/modules/forms/api/runtime-helpers.js.map +2 -2
- package/dist/modules/forms/data/validators.js.map +2 -2
- package/dist/modules/forms/lib/portal-subject-policy.js +17 -0
- package/dist/modules/forms/lib/portal-subject-policy.js.map +7 -0
- package/dist/modules/forms/lib/runtime-principal.js +27 -10
- package/dist/modules/forms/lib/runtime-principal.js.map +2 -2
- package/dist/modules/forms/services/distribution-service.js +35 -13
- package/dist/modules/forms/services/distribution-service.js.map +2 -2
- package/dist/modules/forms/services/submission-service.js +4 -0
- package/dist/modules/forms/services/submission-service.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +54 -24
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +4 -0
- package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-tags.js +27 -8
- package/dist/modules/staff/commands/timesheets-tags.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +19 -7
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/commands/claims.js +1 -1
- package/dist/modules/warranty_claims/commands/claims.js.map +2 -2
- package/dist/modules/warranty_claims/subscribers/return-shipment-tracking.js +6 -6
- package/dist/modules/warranty_claims/subscribers/return-shipment-tracking.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +19 -3
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/workflows/lib/async-activity-wait.js +43 -0
- package/dist/modules/workflows/lib/async-activity-wait.js.map +7 -0
- package/dist/modules/workflows/lib/parallel-handler.js +20 -14
- package/dist/modules/workflows/lib/parallel-handler.js.map +2 -2
- package/dist/modules/workflows/lib/workflow-executor.js +21 -23
- package/dist/modules/workflows/lib/workflow-executor.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/auth/api/logout.ts +6 -1
- package/src/modules/auth/api/session/refresh.ts +6 -1
- package/src/modules/catalog/ai-tools/mutation-pack.ts +14 -5
- package/src/modules/catalog/ai-tools/types.ts +1 -0
- package/src/modules/customer_accounts/api/login.ts +15 -7
- package/src/modules/customer_accounts/services/customerUserService.ts +34 -10
- package/src/modules/forms/api/distributions/[distributionId]/invitations/[invitationId]/route.ts +1 -1
- package/src/modules/forms/api/form-submissions/[id]/submit/route.ts +16 -3
- package/src/modules/forms/api/form-submissions/route.ts +21 -2
- package/src/modules/forms/api/public/submissions/[id]/submit/route.ts +7 -0
- package/src/modules/forms/api/runtime-helpers.ts +16 -0
- package/src/modules/forms/data/validators.ts +2 -1
- package/src/modules/forms/i18n/de.json +1 -0
- package/src/modules/forms/i18n/en.json +1 -0
- package/src/modules/forms/i18n/es.json +1 -0
- package/src/modules/forms/i18n/ko.json +1 -0
- package/src/modules/forms/i18n/pl.json +1 -0
- package/src/modules/forms/lib/portal-subject-policy.ts +42 -0
- package/src/modules/forms/lib/runtime-principal.ts +35 -11
- package/src/modules/forms/services/distribution-service.ts +35 -13
- package/src/modules/forms/services/submission-service.ts +12 -0
- package/src/modules/staff/commands/leave-requests.ts +54 -23
- package/src/modules/staff/commands/timesheets-entries.ts +4 -0
- package/src/modules/staff/commands/timesheets-tags.ts +37 -8
- package/src/modules/staff/i18n/de.json +2 -0
- package/src/modules/staff/i18n/en.json +2 -0
- package/src/modules/staff/i18n/es.json +2 -0
- package/src/modules/staff/i18n/ko.json +2 -0
- package/src/modules/staff/i18n/pl.json +2 -0
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +20 -8
- package/src/modules/warranty_claims/commands/claims.ts +1 -1
- package/src/modules/warranty_claims/subscribers/return-shipment-tracking.ts +5 -5
- package/src/modules/wms/commands/inventory-actions.ts +30 -10
- package/src/modules/workflows/lib/async-activity-wait.ts +71 -0
- package/src/modules/workflows/lib/parallel-handler.ts +24 -15
- package/src/modules/workflows/lib/workflow-executor.ts +24 -27
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/leave-requests.ts"],
|
|
4
|
-
"sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { CommandHandler, CommandRuntimeContext } 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 { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { PlannerAvailabilityRule } from '@open-mercato/core/modules/planner/data/entities'\nimport { StaffLeaveRequest, type StaffLeaveRequestStatus } from '../data/entities'\nimport {\n staffLeaveRequestCreateSchema,\n staffLeaveRequestDecisionSchema,\n staffLeaveRequestUpdateSchema,\n type StaffLeaveRequestCreateInput,\n type StaffLeaveRequestDecisionInput,\n type StaffLeaveRequestUpdateInput,\n} from '../data/validators'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\nimport { E } from '#generated/entities.ids.generated'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { buildFeatureNotificationFromType, buildNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { notificationTypes } from '../notifications'\nimport { staffLeaveRequestCrudEvents } from '../lib/crud'\nimport { plannerAvailabilityRuleCrudEvents } from '../../planner/lib/crud'\n\nconst leaveRequestCrudIndexer: CrudIndexerConfig<StaffLeaveRequest> = {\n entityType: E.staff.staff_leave_request,\n}\n\nconst availabilityRuleCrudIndexer: CrudIndexerConfig<PlannerAvailabilityRule> = {\n entityType: E.planner.planner_availability_rule,\n cacheAliases: ['planner.availability'],\n}\n\ntype LeaveRequestSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n memberId: string\n startDate: string\n endDate: string\n timezone: string\n status: StaffLeaveRequestStatus\n unavailabilityReasonEntryId: string | null\n unavailabilityReasonValue: string | null\n note: string | null\n decisionComment: string | null\n submittedByUserId: string | null\n decidedByUserId: string | null\n decidedAt: string | null\n deletedAt: string | null\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestUndoPayload = {\n before?: LeaveRequestSnapshot | null\n after?: LeaveRequestSnapshot | null\n availabilityRuleIds?: string[]\n}\n\nfunction parseUuidCandidate(value: string | null | undefined): string | null {\n if (!value) return null\n const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/\n return uuidRegex.test(value) ? value : null\n}\n\nfunction resolveAuthUserId(ctx: { auth?: { sub?: string | null; isApiKey?: boolean } | null }): string | null {\n if (!ctx.auth || ctx.auth.isApiKey) return null\n return parseUuidCandidate(ctx.auth.sub ?? null)\n}\n\nfunction formatDateKey(value: Date): string {\n const year = value.getUTCFullYear()\n const month = String(value.getUTCMonth() + 1).padStart(2, '0')\n const day = String(value.getUTCDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\nfunction listDateKeysInRange(start: Date, end: Date): string[] {\n const dates: string[] = []\n const current = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate()))\n const last = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate()))\n while (current <= last) {\n dates.push(formatDateKey(current))\n current.setUTCDate(current.getUTCDate() + 1)\n }\n return dates\n}\n\nfunction formatDuration(minutes: number): string {\n const clamped = Math.max(1, minutes)\n const hours = Math.floor(clamped / 60)\n const mins = clamped % 60\n if (hours > 0 && mins > 0) return `PT${hours}H${mins}M`\n if (hours > 0) return `PT${hours}H`\n return `PT${mins}M`\n}\n\nfunction buildAvailabilityRrule(start: Date, end: Date): string {\n const dtStart = start.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z'\n const durationMinutes = Math.max(1, Math.round((end.getTime() - start.getTime()) / 60000))\n const duration = formatDuration(durationMinutes)\n return `DTSTART:${dtStart}\\nDURATION:${duration}\\nRRULE:FREQ=DAILY;COUNT=1`\n}\n\nfunction buildFullDayRrule(date: string): string | null {\n const [year, month, day] = date.split('-').map((part) => Number(part))\n if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) return null\n const start = new Date(Date.UTC(year, month - 1, day, 0, 0, 0))\n const end = new Date(start.getTime() + 24 * 60 * 60 * 1000)\n return buildAvailabilityRrule(start, end)\n}\n\nasync function loadLeaveRequestSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<LeaveRequestSnapshot | null> {\n const request = await findOneWithDecryption(\n em,\n StaffLeaveRequest,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!request) return null\n const memberId = typeof request.member === 'string' ? request.member : request.member.id\n return {\n id: request.id,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n memberId,\n startDate: request.startDate.toISOString(),\n endDate: request.endDate.toISOString(),\n timezone: request.timezone,\n status: request.status,\n unavailabilityReasonEntryId: request.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: request.unavailabilityReasonValue ?? null,\n note: request.note ?? null,\n decisionComment: request.decisionComment ?? null,\n submittedByUserId: request.submittedByUserId ?? null,\n decidedByUserId: request.decidedByUserId ?? null,\n decidedAt: request.decidedAt ? request.decidedAt.toISOString() : null,\n deletedAt: request.deletedAt ? request.deletedAt.toISOString() : null,\n createdAt: request.createdAt ? request.createdAt.toISOString() : null,\n updatedAt: request.updatedAt ? request.updatedAt.toISOString() : null,\n }\n}\n\nfunction leaveRequestSeedFromSnapshot(snapshot: LeaveRequestSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n member: snapshot.memberId,\n startDate: new Date(snapshot.startDate),\n endDate: new Date(snapshot.endDate),\n timezone: snapshot.timezone,\n status: snapshot.status,\n unavailabilityReasonEntryId: snapshot.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: snapshot.unavailabilityReasonValue ?? null,\n note: snapshot.note ?? null,\n decisionComment: snapshot.decisionComment ?? null,\n submittedByUserId: snapshot.submittedByUserId ?? null,\n decidedByUserId: snapshot.decidedByUserId ?? null,\n decidedAt: snapshot.decidedAt ? new Date(snapshot.decidedAt) : null,\n createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nasync function requireLeaveRequest(\n em: EntityManager,\n id: string,\n scope: ReturnType<typeof explicitStaffCommandScope>,\n): Promise<StaffLeaveRequest> {\n const request = await findOneWithDecryption(\n em,\n StaffLeaveRequest,\n applyScopeToWhere<StaffLeaveRequest>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!request) throw new CrudHttpError(404, { error: 'Leave request not found.' })\n return request\n}\n\nfunction ensurePendingStatus(request: StaffLeaveRequest): void {\n if (request.status !== 'pending') {\n throw new CrudHttpError(400, { error: 'Leave request is already finalized.' })\n }\n}\n\nasync function createUnavailabilityRules(params: {\n em: EntityManager\n tenantId: string\n organizationId: string\n memberId: string\n timezone: string\n dates: string[]\n note: string | null\n reasonEntryId: string | null\n reasonValue: string | null\n}): Promise<string[]> {\n const now = new Date()\n const createdIds: string[] = []\n params.dates.forEach((date) => {\n const rrule = buildFullDayRrule(date)\n if (!rrule) return\n const ruleId = randomUUID()\n const rule = params.em.create(PlannerAvailabilityRule, {\n id: ruleId,\n tenantId: params.tenantId,\n organizationId: params.organizationId,\n subjectType: 'member',\n subjectId: params.memberId,\n timezone: params.timezone,\n rrule,\n exdates: [],\n kind: 'unavailability',\n note: params.note,\n unavailabilityReasonEntryId: params.reasonEntryId,\n unavailabilityReasonValue: params.reasonValue,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n params.em.persist(rule)\n createdIds.push(ruleId)\n })\n return createdIds\n}\n\nasync function invalidateAvailabilityCache(params: {\n container: CommandRuntimeContext['container']\n tenantId: string | null\n organizationId: string | null\n ruleIds: string[]\n}) {\n if (!params.ruleIds.length) return\n const resource = 'planner.availability'\n const fallbackTenant = params.tenantId ?? null\n for (const ruleId of params.ruleIds) {\n await invalidateCrudCache(\n params.container,\n resource,\n { id: ruleId, organizationId: params.organizationId, tenantId: params.tenantId },\n fallbackTenant,\n 'updated',\n )\n }\n}\n\nconst createLeaveRequestCommand: CommandHandler<StaffLeaveRequestCreateInput, { requestId: string }> = {\n id: 'staff.leave-requests.create',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestCreateSchema.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 const member = await requireTeamMember(\n em,\n parsed.memberId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const submittedByUserId = parsed.submittedByUserId ?? resolveAuthUserId(ctx)\n const now = new Date()\n const request = em.create(StaffLeaveRequest, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n member,\n startDate: parsed.startDate,\n endDate: parsed.endDate,\n timezone: parsed.timezone,\n status: 'pending',\n unavailabilityReasonEntryId: parsed.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: parsed.unavailabilityReasonValue ?? null,\n note: parsed.note ?? null,\n decisionComment: null,\n submittedByUserId,\n decidedByUserId: null,\n decidedAt: null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(request)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n // Create notification for users who can approve/reject leave requests\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.pending')\n if (typeDef) {\n const memberName = member.displayName || 'Team member'\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildFeatureNotificationFromType(typeDef, {\n requiredFeature: 'staff.leave_requests.manage',\n bodyVariables: {\n memberName,\n startDate: startDateStr,\n endDate: endDateStr,\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.createForFeature(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n\n return { requestId: request.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n return {\n actionLabel: translate('staff.audit.leaveRequests.create', 'Create leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (request) {\n request.deletedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n }\n },\n redo: makeCreateRedo<StaffLeaveRequest, LeaveRequestSnapshot, StaffLeaveRequestCreateInput, { requestId: string }>({\n entityClass: StaffLeaveRequest,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: leaveRequestSeedFromSnapshot,\n findRow: ({ em, id, snapshot }) =>\n findOneWithDecryption(\n em,\n StaffLeaveRequest,\n scopedStaffSnapshotWhere(id, staffSnapshotScopeFromSnapshot(snapshot)),\n undefined,\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n ),\n buildResult: (entity) => ({ requestId: entity.id }),\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n }),\n}\n\nconst updateLeaveRequestCommand: CommandHandler<StaffLeaveRequestUpdateInput, { requestId: string }> = {\n id: 'staff.leave-requests.update',\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const request = await requireLeaveRequest(em, parsed.id, scope)\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n if (parsed.memberId !== undefined) {\n const member = await requireTeamMember(em, parsed.memberId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n request.member = member\n }\n if (parsed.startDate !== undefined) request.startDate = parsed.startDate\n if (parsed.endDate !== undefined) request.endDate = parsed.endDate\n if (parsed.timezone !== undefined) request.timezone = parsed.timezone\n if (parsed.unavailabilityReasonEntryId !== undefined) request.unavailabilityReasonEntryId = parsed.unavailabilityReasonEntryId ?? null\n if (parsed.unavailabilityReasonValue !== undefined) request.unavailabilityReasonValue = parsed.unavailabilityReasonValue ?? null\n if (parsed.note !== undefined) request.note = parsed.note ?? null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n return { requestId: request.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n const changes = after\n ? buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'memberId',\n 'startDate',\n 'endDate',\n 'timezone',\n 'unavailabilityReasonEntryId',\n 'unavailabilityReasonValue',\n 'note',\n ])\n : {}\n return {\n actionLabel: translate('staff.audit.leaveRequests.update', 'Update leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: after ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before || !after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (!request) return\n request.startDate = new Date(before.startDate)\n request.endDate = new Date(before.endDate)\n request.timezone = before.timezone\n request.status = before.status\n request.unavailabilityReasonEntryId = before.unavailabilityReasonEntryId\n request.unavailabilityReasonValue = before.unavailabilityReasonValue\n request.note = before.note\n request.decisionComment = before.decisionComment\n request.decidedByUserId = before.decidedByUserId\n request.decidedAt = before.decidedAt ? new Date(before.decidedAt) : null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nconst deleteLeaveRequestCommand: CommandHandler<{ id: string }, { requestId: string }> = {\n id: 'staff.leave-requests.delete',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.pick({ id: true }).parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n request.deletedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n return { requestId: request.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n return {\n actionLabel: translate('staff.audit.leaveRequests.delete', 'Delete leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (!request) return\n request.deletedAt = null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nconst acceptLeaveRequestCommand: CommandHandler<StaffLeaveRequestDecisionInput, { requestId: string; ruleIds: string[] }> = {\n id: 'staff.leave-requests.accept',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n const memberId = typeof request.member === 'string' ? request.member : request.member.id\n const decidedByUserId = parsed.decidedByUserId ?? resolveAuthUserId(ctx)\n const now = new Date()\n const dates = listDateKeysInRange(request.startDate, request.endDate)\n let createdRuleIds: string[] = []\n\n await em.transactional(async (trx) => {\n request.status = 'approved'\n request.decisionComment = parsed.decisionComment ?? null\n request.decidedByUserId = decidedByUserId\n request.decidedAt = now\n request.updatedAt = now\n trx.persist(request)\n\n createdRuleIds = await createUnavailabilityRules({\n em: trx,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n memberId,\n timezone: request.timezone,\n dates,\n note: request.note ?? null,\n reasonEntryId: request.unavailabilityReasonEntryId ?? null,\n reasonValue: request.unavailabilityReasonValue ?? null,\n })\n await trx.flush()\n })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n if (createdRuleIds.length) {\n const rules = await em.find(PlannerAvailabilityRule, { id: { $in: createdRuleIds } })\n for (const rule of rules) {\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: rule,\n identifiers: {\n id: rule.id,\n organizationId: rule.organizationId,\n tenantId: rule.tenantId,\n },\n events: plannerAvailabilityRuleCrudEvents,\n indexer: availabilityRuleCrudIndexer,\n })\n }\n }\n await invalidateAvailabilityCache({\n container: ctx.container,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n ruleIds: createdRuleIds,\n })\n\n // Send notification to the requester\n if (request.submittedByUserId) {\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.approved')\n if (typeDef) {\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildNotificationFromType(typeDef, {\n recipientUserId: request.submittedByUserId,\n bodyVariables: {\n startDate: startDateStr,\n endDate: endDateStr,\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.create(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n }\n\n return { requestId: request.id, ruleIds: createdRuleIds }\n },\n buildLog: async ({ result, ctx, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(\n em,\n result.requestId,\n staffSnapshotScopeFromSnapshot(before) ?? staffSnapshotScopeFromContext(ctx),\n )\n return {\n actionLabel: translate('staff.audit.leaveRequests.accept', 'Approve leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: after?.memberId ?? before?.memberId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n availabilityRuleIds: result.ruleIds,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n const availabilityRuleIds = payload?.availabilityRuleIds ?? []\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!request) return\n\n // Fetch rules before mutating so the query cannot reset unit-of-work tracking\n // between the request scalar mutations and the flush (SPEC-018 Problem 1).\n const rules = availabilityRuleIds.length\n ? await em.find(PlannerAvailabilityRule, { id: { $in: availabilityRuleIds } })\n : []\n\n await withAtomicFlush(em, [\n () => {\n request.status = before.status\n request.decisionComment = before.decisionComment\n request.decidedByUserId = before.decidedByUserId\n request.decidedAt = before.decidedAt ? new Date(before.decidedAt) : null\n request.updatedAt = new Date()\n\n if (rules.length) {\n const now = new Date()\n rules.forEach((rule) => {\n rule.deletedAt = now\n rule.updatedAt = now\n })\n }\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n for (const rule of rules) {\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: rule,\n identifiers: {\n id: rule.id,\n organizationId: rule.organizationId,\n tenantId: rule.tenantId,\n },\n events: plannerAvailabilityRuleCrudEvents,\n indexer: availabilityRuleCrudIndexer,\n })\n }\n await invalidateAvailabilityCache({\n container: ctx.container,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n ruleIds: availabilityRuleIds,\n })\n },\n}\n\nconst rejectLeaveRequestCommand: CommandHandler<StaffLeaveRequestDecisionInput, { requestId: string }> = {\n id: 'staff.leave-requests.reject',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n request.status = 'rejected'\n request.decisionComment = parsed.decisionComment ?? null\n request.decidedByUserId = parsed.decidedByUserId ?? resolveAuthUserId(ctx)\n request.decidedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n // Send notification to the requester\n if (request.submittedByUserId) {\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.rejected')\n if (typeDef) {\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildNotificationFromType(typeDef, {\n recipientUserId: request.submittedByUserId,\n bodyVariables: {\n startDate: startDateStr,\n endDate: endDateStr,\n reason: request.decisionComment ?? '',\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.create(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n }\n\n return { requestId: request.id }\n },\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n buildLog: async ({ result, ctx, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(\n em,\n result.requestId,\n staffSnapshotScopeFromSnapshot(before) ?? staffSnapshotScopeFromContext(ctx),\n )\n return {\n actionLabel: translate('staff.audit.leaveRequests.reject', 'Reject leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: after?.memberId ?? before?.memberId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!request) return\n request.status = before.status\n request.decisionComment = before.decisionComment\n request.decidedByUserId = before.decidedByUserId\n request.decidedAt = before.decidedAt ? new Date(before.decidedAt) : null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nregisterCommand(createLeaveRequestCommand)\nregisterCommand(updateLeaveRequestCommand)\nregisterCommand(deleteLeaveRequestCommand)\nregisterCommand(acceptLeaveRequestCommand)\nregisterCommand(rejectLeaveRequestCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from 'crypto'\nimport type { CommandHandler, CommandRuntimeContext } 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 { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges } from '@open-mercato/shared/lib/commands/helpers'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { PlannerAvailabilityRule } from '@open-mercato/core/modules/planner/data/entities'\nimport { StaffLeaveRequest, StaffTeamMember, type StaffLeaveRequestStatus } from '../data/entities'\nimport {\n staffLeaveRequestCreateSchema,\n staffLeaveRequestDecisionSchema,\n staffLeaveRequestUpdateSchema,\n type StaffLeaveRequestCreateInput,\n type StaffLeaveRequestDecisionInput,\n type StaffLeaveRequestUpdateInput,\n} from '../data/validators'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n scopeForDecryption,\n scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\nimport { E } from '#generated/entities.ids.generated'\nimport { resolveNotificationService } from '../../notifications/lib/notificationService'\nimport { buildFeatureNotificationFromType, buildNotificationFromType } from '../../notifications/lib/notificationBuilder'\nimport { notificationTypes } from '../notifications'\nimport { staffLeaveRequestCrudEvents } from '../lib/crud'\nimport { plannerAvailabilityRuleCrudEvents } from '../../planner/lib/crud'\n\nconst leaveRequestCrudIndexer: CrudIndexerConfig<StaffLeaveRequest> = {\n entityType: E.staff.staff_leave_request,\n}\n\nconst availabilityRuleCrudIndexer: CrudIndexerConfig<PlannerAvailabilityRule> = {\n entityType: E.planner.planner_availability_rule,\n cacheAliases: ['planner.availability'],\n}\n\ntype LeaveRequestSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n memberId: string\n startDate: string\n endDate: string\n timezone: string\n status: StaffLeaveRequestStatus\n unavailabilityReasonEntryId: string | null\n unavailabilityReasonValue: string | null\n note: string | null\n decisionComment: string | null\n submittedByUserId: string | null\n decidedByUserId: string | null\n decidedAt: string | null\n deletedAt: string | null\n createdAt: string | null\n updatedAt: string | null\n}\n\ntype LeaveRequestUndoPayload = {\n before?: LeaveRequestSnapshot | null\n after?: LeaveRequestSnapshot | null\n availabilityRuleIds?: string[]\n}\n\nfunction parseUuidCandidate(value: string | null | undefined): string | null {\n if (!value) return null\n const uuidRegex = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/\n return uuidRegex.test(value) ? value : null\n}\n\nfunction resolveAuthUserId(ctx: { auth?: { sub?: string | null; isApiKey?: boolean } | null }): string | null {\n if (!ctx.auth || ctx.auth.isApiKey) return null\n return parseUuidCandidate(ctx.auth.sub ?? null)\n}\n\nfunction formatDateKey(value: Date): string {\n const year = value.getUTCFullYear()\n const month = String(value.getUTCMonth() + 1).padStart(2, '0')\n const day = String(value.getUTCDate()).padStart(2, '0')\n return `${year}-${month}-${day}`\n}\n\nfunction listDateKeysInRange(start: Date, end: Date): string[] {\n const dates: string[] = []\n const current = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate()))\n const last = new Date(Date.UTC(end.getUTCFullYear(), end.getUTCMonth(), end.getUTCDate()))\n while (current <= last) {\n dates.push(formatDateKey(current))\n current.setUTCDate(current.getUTCDate() + 1)\n }\n return dates\n}\n\nfunction formatDuration(minutes: number): string {\n const clamped = Math.max(1, minutes)\n const hours = Math.floor(clamped / 60)\n const mins = clamped % 60\n if (hours > 0 && mins > 0) return `PT${hours}H${mins}M`\n if (hours > 0) return `PT${hours}H`\n return `PT${mins}M`\n}\n\nfunction buildAvailabilityRrule(start: Date, end: Date): string {\n const dtStart = start.toISOString().replace(/[-:]/g, '').split('.')[0] + 'Z'\n const durationMinutes = Math.max(1, Math.round((end.getTime() - start.getTime()) / 60000))\n const duration = formatDuration(durationMinutes)\n return `DTSTART:${dtStart}\\nDURATION:${duration}\\nRRULE:FREQ=DAILY;COUNT=1`\n}\n\nfunction buildFullDayRrule(date: string): string | null {\n const [year, month, day] = date.split('-').map((part) => Number(part))\n if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) return null\n const start = new Date(Date.UTC(year, month - 1, day, 0, 0, 0))\n const end = new Date(start.getTime() + 24 * 60 * 60 * 1000)\n return buildAvailabilityRrule(start, end)\n}\n\nasync function loadLeaveRequestSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<LeaveRequestSnapshot | null> {\n const request = await findOneWithDecryption(\n em,\n StaffLeaveRequest,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!request) return null\n const memberId = typeof request.member === 'string' ? request.member : request.member.id\n return {\n id: request.id,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n memberId,\n startDate: request.startDate.toISOString(),\n endDate: request.endDate.toISOString(),\n timezone: request.timezone,\n status: request.status,\n unavailabilityReasonEntryId: request.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: request.unavailabilityReasonValue ?? null,\n note: request.note ?? null,\n decisionComment: request.decisionComment ?? null,\n submittedByUserId: request.submittedByUserId ?? null,\n decidedByUserId: request.decidedByUserId ?? null,\n decidedAt: request.decidedAt ? request.decidedAt.toISOString() : null,\n deletedAt: request.deletedAt ? request.deletedAt.toISOString() : null,\n createdAt: request.createdAt ? request.createdAt.toISOString() : null,\n updatedAt: request.updatedAt ? request.updatedAt.toISOString() : null,\n }\n}\n\nfunction leaveRequestSeedFromSnapshot(snapshot: LeaveRequestSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n member: snapshot.memberId,\n startDate: new Date(snapshot.startDate),\n endDate: new Date(snapshot.endDate),\n timezone: snapshot.timezone,\n status: snapshot.status,\n unavailabilityReasonEntryId: snapshot.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: snapshot.unavailabilityReasonValue ?? null,\n note: snapshot.note ?? null,\n decisionComment: snapshot.decisionComment ?? null,\n submittedByUserId: snapshot.submittedByUserId ?? null,\n decidedByUserId: snapshot.decidedByUserId ?? null,\n decidedAt: snapshot.decidedAt ? new Date(snapshot.decidedAt) : null,\n createdAt: snapshot.createdAt ? new Date(snapshot.createdAt) : new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nasync function requireLeaveRequest(\n em: EntityManager,\n id: string,\n scope: ReturnType<typeof explicitStaffCommandScope>,\n): Promise<StaffLeaveRequest> {\n const request = await findOneWithDecryption(\n em,\n StaffLeaveRequest,\n applyScopeToWhere<StaffLeaveRequest>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!request) throw new CrudHttpError(404, { error: 'Leave request not found.' })\n return request\n}\n\nfunction ensurePendingStatus(request: StaffLeaveRequest): void {\n if (request.status !== 'pending') {\n throw new CrudHttpError(400, { error: 'Leave request is already finalized.' })\n }\n}\n\nasync function ensureUndoablePending(request: StaffLeaveRequest): Promise<void> {\n if (request.status === 'pending') return\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n 'staff.leaveRequests.errors.undoAfterDecision',\n 'This leave request has already been approved or rejected and can no longer be undone. Undo the decision first.',\n ),\n })\n}\n\nasync function requireUndoMember(em: EntityManager, snapshot: LeaveRequestSnapshot): Promise<StaffTeamMember> {\n const scope = explicitStaffCommandScope(snapshot.tenantId, snapshot.organizationId)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: snapshot.memberId, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (member) return member\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n 'staff.leaveRequests.errors.undoMemberMissing',\n 'The original team member of this leave request no longer exists, so the change cannot be undone.',\n ),\n })\n}\n\nasync function createUnavailabilityRules(params: {\n em: EntityManager\n tenantId: string\n organizationId: string\n memberId: string\n timezone: string\n dates: string[]\n note: string | null\n reasonEntryId: string | null\n reasonValue: string | null\n}): Promise<string[]> {\n const now = new Date()\n const createdIds: string[] = []\n params.dates.forEach((date) => {\n const rrule = buildFullDayRrule(date)\n if (!rrule) return\n const ruleId = randomUUID()\n const rule = params.em.create(PlannerAvailabilityRule, {\n id: ruleId,\n tenantId: params.tenantId,\n organizationId: params.organizationId,\n subjectType: 'member',\n subjectId: params.memberId,\n timezone: params.timezone,\n rrule,\n exdates: [],\n kind: 'unavailability',\n note: params.note,\n unavailabilityReasonEntryId: params.reasonEntryId,\n unavailabilityReasonValue: params.reasonValue,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n params.em.persist(rule)\n createdIds.push(ruleId)\n })\n return createdIds\n}\n\nasync function invalidateAvailabilityCache(params: {\n container: CommandRuntimeContext['container']\n tenantId: string | null\n organizationId: string | null\n ruleIds: string[]\n}) {\n if (!params.ruleIds.length) return\n const resource = 'planner.availability'\n const fallbackTenant = params.tenantId ?? null\n for (const ruleId of params.ruleIds) {\n await invalidateCrudCache(\n params.container,\n resource,\n { id: ruleId, organizationId: params.organizationId, tenantId: params.tenantId },\n fallbackTenant,\n 'updated',\n )\n }\n}\n\nconst createLeaveRequestCommand: CommandHandler<StaffLeaveRequestCreateInput, { requestId: string }> = {\n id: 'staff.leave-requests.create',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestCreateSchema.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 const member = await requireTeamMember(\n em,\n parsed.memberId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const submittedByUserId = parsed.submittedByUserId ?? resolveAuthUserId(ctx)\n const now = new Date()\n const request = em.create(StaffLeaveRequest, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n member,\n startDate: parsed.startDate,\n endDate: parsed.endDate,\n timezone: parsed.timezone,\n status: 'pending',\n unavailabilityReasonEntryId: parsed.unavailabilityReasonEntryId ?? null,\n unavailabilityReasonValue: parsed.unavailabilityReasonValue ?? null,\n note: parsed.note ?? null,\n decisionComment: null,\n submittedByUserId,\n decidedByUserId: null,\n decidedAt: null,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(request)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n // Create notification for users who can approve/reject leave requests\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.pending')\n if (typeDef) {\n const memberName = member.displayName || 'Team member'\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildFeatureNotificationFromType(typeDef, {\n requiredFeature: 'staff.leave_requests.manage',\n bodyVariables: {\n memberName,\n startDate: startDateStr,\n endDate: endDateStr,\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.createForFeature(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n\n return { requestId: request.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n return {\n actionLabel: translate('staff.audit.leaveRequests.create', 'Create leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (!request || request.deletedAt) return\n await ensureUndoablePending(request)\n request.deletedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n redo: makeCreateRedo<StaffLeaveRequest, LeaveRequestSnapshot, StaffLeaveRequestCreateInput, { requestId: string }>({\n entityClass: StaffLeaveRequest,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: leaveRequestSeedFromSnapshot,\n findRow: ({ em, id, snapshot }) =>\n findOneWithDecryption(\n em,\n StaffLeaveRequest,\n scopedStaffSnapshotWhere(id, staffSnapshotScopeFromSnapshot(snapshot)),\n undefined,\n { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },\n ),\n buildResult: (entity) => ({ requestId: entity.id }),\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n }),\n}\n\nconst updateLeaveRequestCommand: CommandHandler<StaffLeaveRequestUpdateInput, { requestId: string }> = {\n id: 'staff.leave-requests.update',\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const request = await requireLeaveRequest(em, parsed.id, scope)\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n if (parsed.memberId !== undefined) {\n const member = await requireTeamMember(em, parsed.memberId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n request.member = member\n }\n if (parsed.startDate !== undefined) request.startDate = parsed.startDate\n if (parsed.endDate !== undefined) request.endDate = parsed.endDate\n if (parsed.timezone !== undefined) request.timezone = parsed.timezone\n if (parsed.unavailabilityReasonEntryId !== undefined) request.unavailabilityReasonEntryId = parsed.unavailabilityReasonEntryId ?? null\n if (parsed.unavailabilityReasonValue !== undefined) request.unavailabilityReasonValue = parsed.unavailabilityReasonValue ?? null\n if (parsed.note !== undefined) request.note = parsed.note ?? null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n return { requestId: request.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before))\n const changes = after\n ? buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'memberId',\n 'startDate',\n 'endDate',\n 'timezone',\n 'unavailabilityReasonEntryId',\n 'unavailabilityReasonValue',\n 'note',\n ])\n : {}\n return {\n actionLabel: translate('staff.audit.leaveRequests.update', 'Update leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: before.id,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: before.memberId ?? null,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: after ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before || !after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (!request || request.deletedAt) return\n await ensureUndoablePending(request)\n const currentMemberId = typeof request.member === 'string' ? request.member : request.member.id\n if (before.memberId !== currentMemberId) {\n request.member = await requireUndoMember(em, before)\n }\n request.startDate = new Date(before.startDate)\n request.endDate = new Date(before.endDate)\n request.timezone = before.timezone\n request.unavailabilityReasonEntryId = before.unavailabilityReasonEntryId\n request.unavailabilityReasonValue = before.unavailabilityReasonValue\n request.note = before.note\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nconst deleteLeaveRequestCommand: CommandHandler<{ id: string }, { requestId: string }> = {\n id: 'staff.leave-requests.delete',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.pick({ id: true }).parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n request.deletedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n return { requestId: request.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadLeaveRequestSnapshot(em, result.requestId, staffSnapshotScopeFromContext(ctx))\n return {\n actionLabel: translate('staff.audit.leaveRequests.delete', 'Delete leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: snapshot?.memberId ?? null,\n tenantId: snapshot?.tenantId ?? null,\n organizationId: snapshot?.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\n if (!request) return\n request.deletedAt = null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nconst acceptLeaveRequestCommand: CommandHandler<StaffLeaveRequestDecisionInput, { requestId: string; ruleIds: string[] }> = {\n id: 'staff.leave-requests.accept',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n const memberId = typeof request.member === 'string' ? request.member : request.member.id\n const decidedByUserId = parsed.decidedByUserId ?? resolveAuthUserId(ctx)\n const now = new Date()\n const dates = listDateKeysInRange(request.startDate, request.endDate)\n let createdRuleIds: string[] = []\n\n await em.transactional(async (trx) => {\n request.status = 'approved'\n request.decisionComment = parsed.decisionComment ?? null\n request.decidedByUserId = decidedByUserId\n request.decidedAt = now\n request.updatedAt = now\n trx.persist(request)\n\n createdRuleIds = await createUnavailabilityRules({\n em: trx,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n memberId,\n timezone: request.timezone,\n dates,\n note: request.note ?? null,\n reasonEntryId: request.unavailabilityReasonEntryId ?? null,\n reasonValue: request.unavailabilityReasonValue ?? null,\n })\n await trx.flush()\n })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n if (createdRuleIds.length) {\n const rules = await em.find(PlannerAvailabilityRule, { id: { $in: createdRuleIds } })\n for (const rule of rules) {\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: rule,\n identifiers: {\n id: rule.id,\n organizationId: rule.organizationId,\n tenantId: rule.tenantId,\n },\n events: plannerAvailabilityRuleCrudEvents,\n indexer: availabilityRuleCrudIndexer,\n })\n }\n }\n await invalidateAvailabilityCache({\n container: ctx.container,\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n ruleIds: createdRuleIds,\n })\n\n // Send notification to the requester\n if (request.submittedByUserId) {\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.approved')\n if (typeDef) {\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildNotificationFromType(typeDef, {\n recipientUserId: request.submittedByUserId,\n bodyVariables: {\n startDate: startDateStr,\n endDate: endDateStr,\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.create(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n }\n\n return { requestId: request.id, ruleIds: createdRuleIds }\n },\n buildLog: async ({ result, ctx, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(\n em,\n result.requestId,\n staffSnapshotScopeFromSnapshot(before) ?? staffSnapshotScopeFromContext(ctx),\n )\n return {\n actionLabel: translate('staff.audit.leaveRequests.accept', 'Approve leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: after?.memberId ?? before?.memberId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n availabilityRuleIds: result.ruleIds,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n const availabilityRuleIds = payload?.availabilityRuleIds ?? []\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!request) return\n\n // Fetch rules before mutating so the query cannot reset unit-of-work tracking\n // between the request scalar mutations and the flush (SPEC-018 Problem 1).\n const rules = availabilityRuleIds.length\n ? await em.find(PlannerAvailabilityRule, { id: { $in: availabilityRuleIds } })\n : []\n\n await withAtomicFlush(em, [\n () => {\n request.status = before.status\n request.decisionComment = before.decisionComment\n request.decidedByUserId = before.decidedByUserId\n request.decidedAt = before.decidedAt ? new Date(before.decidedAt) : null\n request.updatedAt = new Date()\n\n if (rules.length) {\n const now = new Date()\n rules.forEach((rule) => {\n rule.deletedAt = now\n rule.updatedAt = now\n })\n }\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n for (const rule of rules) {\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: rule,\n identifiers: {\n id: rule.id,\n organizationId: rule.organizationId,\n tenantId: rule.tenantId,\n },\n events: plannerAvailabilityRuleCrudEvents,\n indexer: availabilityRuleCrudIndexer,\n })\n }\n await invalidateAvailabilityCache({\n container: ctx.container,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n ruleIds: availabilityRuleIds,\n })\n },\n}\n\nconst rejectLeaveRequestCommand: CommandHandler<StaffLeaveRequestDecisionInput, { requestId: string }> = {\n id: 'staff.leave-requests.reject',\n async execute(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await requireLeaveRequest(em, parsed.id, commandActorScope(ctx))\n ensureTenantScope(ctx, request.tenantId)\n ensureOrganizationScope(ctx, request.organizationId)\n ensurePendingStatus(request)\n\n request.status = 'rejected'\n request.decisionComment = parsed.decisionComment ?? null\n request.decidedByUserId = parsed.decidedByUserId ?? resolveAuthUserId(ctx)\n request.decidedAt = new Date()\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n\n // Send notification to the requester\n if (request.submittedByUserId) {\n try {\n const notificationService = resolveNotificationService(ctx.container)\n const typeDef = notificationTypes.find((type) => type.type === 'staff.leave_request.rejected')\n if (typeDef) {\n const startDateStr = request.startDate.toLocaleDateString()\n const endDateStr = request.endDate.toLocaleDateString()\n\n const notificationInput = buildNotificationFromType(typeDef, {\n recipientUserId: request.submittedByUserId,\n bodyVariables: {\n startDate: startDateStr,\n endDate: endDateStr,\n reason: request.decisionComment ?? '',\n },\n sourceEntityType: 'staff:leave_request',\n sourceEntityId: request.id,\n linkHref: `/backend/staff/leave-requests/${request.id}`,\n })\n\n await notificationService.create(notificationInput, {\n tenantId: request.tenantId,\n organizationId: request.organizationId,\n })\n }\n } catch {\n // Notification creation is non-critical, don't fail the command\n }\n }\n\n return { requestId: request.id }\n },\n async prepare(rawInput, ctx) {\n const parsed = staffLeaveRequestDecisionSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadLeaveRequestSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n buildLog: async ({ result, ctx, snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as LeaveRequestSnapshot | undefined\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadLeaveRequestSnapshot(\n em,\n result.requestId,\n staffSnapshotScopeFromSnapshot(before) ?? staffSnapshotScopeFromContext(ctx),\n )\n return {\n actionLabel: translate('staff.audit.leaveRequests.reject', 'Reject leave request'),\n resourceKind: 'staff.leave_request',\n resourceId: result.requestId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: after?.memberId ?? before?.memberId ?? null,\n tenantId: after?.tenantId ?? before?.tenantId ?? null,\n organizationId: after?.organizationId ?? before?.organizationId ?? null,\n snapshotBefore: before ?? null,\n snapshotAfter: after ?? null,\n payload: {\n undo: {\n before: before ?? null,\n after: after ?? null,\n } satisfies LeaveRequestUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<LeaveRequestUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const request = await em.findOne(StaffLeaveRequest, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\n if (!request) return\n request.status = before.status\n request.decisionComment = before.decisionComment\n request.decidedByUserId = before.decidedByUserId\n request.decidedAt = before.decidedAt ? new Date(before.decidedAt) : null\n request.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: request,\n identifiers: {\n id: request.id,\n organizationId: request.organizationId,\n tenantId: request.tenantId,\n },\n events: staffLeaveRequestCrudEvents,\n indexer: leaveRequestCrudIndexer,\n })\n },\n}\n\nregisterCommand(createLeaveRequestCommand)\nregisterCommand(updateLeaveRequestCommand)\nregisterCommand(deleteLeaveRequestCommand)\nregisterCommand(acceptLeaveRequestCommand)\nregisterCommand(rejectLeaveRequestCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -496,6 +496,7 @@ const createTimeEntryCommand = {
|
|
|
496
496
|
const em = ctx.container.resolve("em").fork();
|
|
497
497
|
const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
|
|
498
498
|
if (entry) {
|
|
499
|
+
assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
|
|
499
500
|
entry.deletedAt = /* @__PURE__ */ new Date();
|
|
500
501
|
await em.flush();
|
|
501
502
|
await emitCrudUndoSideEffects({
|
|
@@ -653,6 +654,7 @@ const startTimerCommand = {
|
|
|
653
654
|
const em = ctx.container.resolve("em").fork();
|
|
654
655
|
const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
|
|
655
656
|
if (entry) {
|
|
657
|
+
assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
|
|
656
658
|
entry.deletedAt = /* @__PURE__ */ new Date();
|
|
657
659
|
await em.flush();
|
|
658
660
|
await emitCrudUndoSideEffects({
|
|
@@ -830,6 +832,7 @@ const updateTimeEntryCommand = {
|
|
|
830
832
|
const em = ctx.container.resolve("em").fork();
|
|
831
833
|
const entry = await em.findOne(StaffTimeEntry, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
|
|
832
834
|
if (!entry) return;
|
|
835
|
+
assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
|
|
833
836
|
entry.date = before.date;
|
|
834
837
|
entry.durationMinutes = before.durationMinutes;
|
|
835
838
|
entry.roundedMinutes = before.roundedMinutes ?? null;
|
|
@@ -964,6 +967,7 @@ const deleteTimeEntryCommand = {
|
|
|
964
967
|
});
|
|
965
968
|
em.persist(entry);
|
|
966
969
|
} else {
|
|
970
|
+
assertTimeEntryUnlocked(entry, (await resolveTranslations()).translate);
|
|
967
971
|
entry.staffMemberId = before.staffMemberId;
|
|
968
972
|
entry.date = before.date;
|
|
969
973
|
entry.durationMinutes = before.durationMinutes;
|