@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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/auth.js +148 -82
- package/dist/helpers/integration/auth.js.map +2 -2
- package/dist/modules/sales/api/document-addresses/route.js +96 -6
- package/dist/modules/sales/api/document-addresses/route.js.map +2 -2
- package/dist/modules/sales/commands/documentAddresses.js +7 -0
- package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
- package/dist/modules/staff/commands/activities.js +23 -12
- package/dist/modules/staff/commands/activities.js.map +2 -2
- package/dist/modules/staff/commands/addresses.js +20 -12
- package/dist/modules/staff/commands/addresses.js.map +2 -2
- package/dist/modules/staff/commands/comments.js +18 -11
- package/dist/modules/staff/commands/comments.js.map +2 -2
- package/dist/modules/staff/commands/job-histories.js +23 -12
- package/dist/modules/staff/commands/job-histories.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +37 -19
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/commands/shared.js +28 -1
- package/dist/modules/staff/commands/shared.js.map +2 -2
- package/dist/modules/staff/commands/tag-assignments.js +20 -3
- package/dist/modules/staff/commands/tag-assignments.js.map +2 -2
- package/dist/modules/staff/commands/team-members.js +21 -11
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/commands/team-roles.js +21 -11
- package/dist/modules/staff/commands/team-roles.js.map +2 -2
- package/dist/modules/staff/commands/teams.js +21 -11
- package/dist/modules/staff/commands/teams.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +24 -14
- package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-projects.js +34 -18
- package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
- package/dist/modules/workflows/api/instances/route.js +1 -1
- package/dist/modules/workflows/api/instances/route.js.map +2 -2
- package/package.json +7 -7
- package/src/helpers/integration/auth.ts +178 -86
- package/src/modules/sales/api/document-addresses/route.ts +140 -7
- package/src/modules/sales/commands/documentAddresses.ts +8 -0
- package/src/modules/staff/commands/activities.ts +23 -11
- package/src/modules/staff/commands/addresses.ts +20 -11
- package/src/modules/staff/commands/comments.ts +18 -10
- package/src/modules/staff/commands/job-histories.ts +27 -11
- package/src/modules/staff/commands/leave-requests.ts +38 -19
- package/src/modules/staff/commands/shared.ts +38 -0
- package/src/modules/staff/commands/tag-assignments.ts +19 -2
- package/src/modules/staff/commands/team-members.ts +21 -10
- package/src/modules/staff/commands/team-roles.ts +21 -10
- package/src/modules/staff/commands/teams.ts +21 -10
- package/src/modules/staff/commands/timesheets-entries.ts +24 -13
- package/src/modules/staff/commands/timesheets-projects.ts +34 -17
- 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/addresses.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { StaffTeamMemberAddress } from '../data/entities'\nimport {\n staffTeamMemberAddressCreateSchema,\n staffTeamMemberAddressUpdateSchema,\n type StaffTeamMemberAddressCreateInput,\n type StaffTeamMemberAddressUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberAddressCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\n\nconst addressCrudIndexer: CrudIndexerConfig<StaffTeamMemberAddress> = {\n entityType: E.staff.staff_team_member_address,\n}\n\ntype AddressSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n name: string | null\n purpose: string | null\n companyName: string | null\n addressLine1: string\n addressLine2: string | null\n buildingNumber: string | null\n flatNumber: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n isPrimary: boolean\n}\n\ntype AddressUndoPayload = {\n before?: AddressSnapshot | null\n after?: AddressSnapshot | null\n}\n\nasync function loadAddressSnapshot(em: EntityManager, id: string): Promise<AddressSnapshot | null> {\n const address = await em.findOne(StaffTeamMemberAddress, { id })\n if (!address) return null\n return {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n memberId: typeof address.member === 'string' ? address.member : address.member.id,\n name: address.name ?? null,\n purpose: address.purpose ?? null,\n companyName: address.companyName ?? null,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? null,\n buildingNumber: address.buildingNumber ?? null,\n flatNumber: address.flatNumber ?? null,\n city: address.city ?? null,\n region: address.region ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n latitude: address.latitude ?? null,\n longitude: address.longitude ?? null,\n isPrimary: address.isPrimary,\n }\n}\n\nasync function enforcePrimaryAddress(em: EntityManager, memberId: string, addressId: string): Promise<void> {\n await em.nativeUpdate(\n StaffTeamMemberAddress,\n { member: memberId, id: { $ne: addressId }, isPrimary: true },\n { isPrimary: false }\n )\n}\n\nconst createAddressCommand: CommandHandler<StaffTeamMemberAddressCreateInput, { addressId: string }> = {\n id: 'staff.team-member-addresses.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberAddressCreateSchema.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.entityId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const address = em.create(StaffTeamMemberAddress, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n name: parsed.name ?? null,\n purpose: parsed.purpose ?? null,\n companyName: parsed.companyName ?? null,\n addressLine1: parsed.addressLine1,\n addressLine2: parsed.addressLine2 ?? null,\n buildingNumber: parsed.buildingNumber ?? null,\n flatNumber: parsed.flatNumber ?? null,\n city: parsed.city ?? null,\n region: parsed.region ?? null,\n postalCode: parsed.postalCode ?? null,\n country: parsed.country ?? null,\n latitude: parsed.latitude ?? null,\n longitude: parsed.longitude ?? null,\n isPrimary: parsed.isPrimary ?? false,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n await em.flush()\n\n if (address.isPrimary) {\n await enforcePrimaryAddress(em, member.id, address.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadAddressSnapshot(em, result.addressId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as AddressSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.create', 'Create address'),\n resourceKind: 'staff.team_member_address',\n resourceId: result.addressId,\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 AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const addressId = logEntry?.resourceId ?? null\n if (!addressId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const address = await em.findOne(StaffTeamMemberAddress, { id: addressId })\n if (address) {\n em.remove(address)\n await em.flush()\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<AddressSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for address create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(\n em,\n after.memberId,\n explicitStaffCommandScope(after.tenantId, after.organizationId),\n 'Team member not found',\n )\n let address = await em.findOne(StaffTeamMemberAddress, { id: after.id })\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n member,\n name: after.name,\n purpose: after.purpose,\n companyName: after.companyName,\n addressLine1: after.addressLine1,\n addressLine2: after.addressLine2,\n buildingNumber: after.buildingNumber,\n flatNumber: after.flatNumber,\n city: after.city,\n region: after.region,\n postalCode: after.postalCode,\n country: after.country,\n latitude: after.latitude,\n longitude: after.longitude,\n isPrimary: after.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = after.name\n address.purpose = after.purpose\n address.companyName = after.companyName\n address.addressLine1 = after.addressLine1\n address.addressLine2 = after.addressLine2\n address.buildingNumber = after.buildingNumber\n address.flatNumber = after.flatNumber\n address.city = after.city\n address.region = after.region\n address.postalCode = after.postalCode\n address.country = after.country\n address.latitude = after.latitude\n address.longitude = after.longitude\n address.isPrimary = after.isPrimary\n }\n await em.flush()\n if (after.isPrimary) {\n await enforcePrimaryAddress(em, after.memberId, after.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n}\n\nconst updateAddressCommand: CommandHandler<StaffTeamMemberAddressUpdateInput, { addressId: string }> = {\n id: 'staff.team-member-addresses.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberAddressUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadAddressSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberAddressUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const address = await em.findOne(\n StaffTeamMemberAddress,\n applyScopeToWhere<StaffTeamMemberAddress>({ id: parsed.id }, scope),\n )\n if (!address) throw new CrudHttpError(404, { error: 'Address not found' })\n ensureTenantScope(ctx, address.tenantId)\n ensureOrganizationScope(ctx, address.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n address.member = member\n }\n if (parsed.name !== undefined) address.name = parsed.name ?? null\n if (parsed.purpose !== undefined) address.purpose = parsed.purpose ?? null\n if (parsed.companyName !== undefined) address.companyName = parsed.companyName ?? null\n if (parsed.addressLine1 !== undefined) address.addressLine1 = parsed.addressLine1\n if (parsed.addressLine2 !== undefined) address.addressLine2 = parsed.addressLine2 ?? null\n if (parsed.buildingNumber !== undefined) address.buildingNumber = parsed.buildingNumber ?? null\n if (parsed.flatNumber !== undefined) address.flatNumber = parsed.flatNumber ?? null\n if (parsed.city !== undefined) address.city = parsed.city ?? null\n if (parsed.region !== undefined) address.region = parsed.region ?? null\n if (parsed.postalCode !== undefined) address.postalCode = parsed.postalCode ?? null\n if (parsed.country !== undefined) address.country = parsed.country ?? null\n if (parsed.latitude !== undefined) address.latitude = parsed.latitude ?? null\n if (parsed.longitude !== undefined) address.longitude = parsed.longitude ?? null\n if (parsed.isPrimary !== undefined) address.isPrimary = parsed.isPrimary\n\n await em.flush()\n\n if (address.isPrimary) {\n await enforcePrimaryAddress(em, typeof address.member === 'string' ? address.member : address.member.id, address.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadAddressSnapshot(em, result.addressId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as AddressSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as AddressSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n [\n 'memberId',\n 'name',\n 'purpose',\n 'companyName',\n 'addressLine1',\n 'addressLine2',\n 'buildingNumber',\n 'flatNumber',\n 'city',\n 'region',\n 'postalCode',\n 'country',\n 'latitude',\n 'longitude',\n 'isPrimary',\n ],\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.update', 'Update address'),\n resourceKind: 'staff.team_member_address',\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: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<AddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let address = await em.findOne(StaffTeamMemberAddress, { id: before.id })\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n name: before.name,\n purpose: before.purpose,\n companyName: before.companyName,\n addressLine1: before.addressLine1,\n addressLine2: before.addressLine2,\n buildingNumber: before.buildingNumber,\n flatNumber: before.flatNumber,\n city: before.city,\n region: before.region,\n postalCode: before.postalCode,\n country: before.country,\n latitude: before.latitude,\n longitude: before.longitude,\n isPrimary: before.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = before.name\n address.purpose = before.purpose\n address.companyName = before.companyName\n address.addressLine1 = before.addressLine1\n address.addressLine2 = before.addressLine2\n address.buildingNumber = before.buildingNumber\n address.flatNumber = before.flatNumber\n address.city = before.city\n address.region = before.region\n address.postalCode = before.postalCode\n address.country = before.country\n address.latitude = before.latitude\n address.longitude = before.longitude\n address.isPrimary = before.isPrimary\n }\n await em.flush()\n if (before.isPrimary) {\n await enforcePrimaryAddress(em, before.memberId, before.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n },\n}\n\nconst deleteAddressCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { addressId: string }> =\n {\n id: 'staff.team-member-addresses.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Address id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadAddressSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Address id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const address = await em.findOne(\n StaffTeamMemberAddress,\n applyScopeToWhere<StaffTeamMemberAddress>({ id }, scope),\n )\n if (!address) throw new CrudHttpError(404, { error: 'Address not found' })\n ensureTenantScope(ctx, address.tenantId)\n ensureOrganizationScope(ctx, address.organizationId)\n em.remove(address)\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: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n return { addressId: address.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as AddressSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.delete', 'Delete address'),\n resourceKind: 'staff.team_member_address',\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 payload: {\n undo: {\n before,\n } satisfies AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<AddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n let address = await em.findOne(StaffTeamMemberAddress, { id: before.id })\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n name: before.name,\n purpose: before.purpose,\n companyName: before.companyName,\n addressLine1: before.addressLine1,\n addressLine2: before.addressLine2,\n buildingNumber: before.buildingNumber,\n flatNumber: before.flatNumber,\n city: before.city,\n region: before.region,\n postalCode: before.postalCode,\n country: before.country,\n latitude: before.latitude,\n longitude: before.longitude,\n isPrimary: before.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = before.name\n address.purpose = before.purpose\n address.companyName = before.companyName\n address.addressLine1 = before.addressLine1\n address.addressLine2 = before.addressLine2\n address.buildingNumber = before.buildingNumber\n address.flatNumber = before.flatNumber\n address.city = before.city\n address.region = before.region\n address.postalCode = before.postalCode\n address.country = before.country\n address.latitude = before.latitude\n address.longitude = before.longitude\n address.isPrimary = before.isPrimary\n }\n await em.flush()\n if (before.isPrimary) {\n await enforcePrimaryAddress(em, before.memberId, before.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n },\n }\n\nregisterCommand(createAddressCommand)\nregisterCommand(updateAddressCommand)\nregisterCommand(deleteAddressCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { StaffTeamMemberAddress } from '../data/entities'\nimport {\n staffTeamMemberAddressCreateSchema,\n staffTeamMemberAddressUpdateSchema,\n type StaffTeamMemberAddressCreateInput,\n type StaffTeamMemberAddressUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberAddressCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n scopedStaffSnapshotWhere,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\n\nconst addressCrudIndexer: CrudIndexerConfig<StaffTeamMemberAddress> = {\n entityType: E.staff.staff_team_member_address,\n}\n\ntype AddressSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n name: string | null\n purpose: string | null\n companyName: string | null\n addressLine1: string\n addressLine2: string | null\n buildingNumber: string | null\n flatNumber: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n isPrimary: boolean\n}\n\ntype AddressUndoPayload = {\n before?: AddressSnapshot | null\n after?: AddressSnapshot | null\n}\n\nasync function loadAddressSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<AddressSnapshot | null> {\n const address = await em.findOne(StaffTeamMemberAddress, scopedStaffSnapshotWhere(id, scope))\n if (!address) return null\n return {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n memberId: typeof address.member === 'string' ? address.member : address.member.id,\n name: address.name ?? null,\n purpose: address.purpose ?? null,\n companyName: address.companyName ?? null,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? null,\n buildingNumber: address.buildingNumber ?? null,\n flatNumber: address.flatNumber ?? null,\n city: address.city ?? null,\n region: address.region ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n latitude: address.latitude ?? null,\n longitude: address.longitude ?? null,\n isPrimary: address.isPrimary,\n }\n}\n\nasync function enforcePrimaryAddress(em: EntityManager, memberId: string, addressId: string): Promise<void> {\n await em.nativeUpdate(\n StaffTeamMemberAddress,\n { member: memberId, id: { $ne: addressId }, isPrimary: true },\n { isPrimary: false }\n )\n}\n\nconst createAddressCommand: CommandHandler<StaffTeamMemberAddressCreateInput, { addressId: string }> = {\n id: 'staff.team-member-addresses.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberAddressCreateSchema.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.entityId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const address = em.create(StaffTeamMemberAddress, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n name: parsed.name ?? null,\n purpose: parsed.purpose ?? null,\n companyName: parsed.companyName ?? null,\n addressLine1: parsed.addressLine1,\n addressLine2: parsed.addressLine2 ?? null,\n buildingNumber: parsed.buildingNumber ?? null,\n flatNumber: parsed.flatNumber ?? null,\n city: parsed.city ?? null,\n region: parsed.region ?? null,\n postalCode: parsed.postalCode ?? null,\n country: parsed.country ?? null,\n latitude: parsed.latitude ?? null,\n longitude: parsed.longitude ?? null,\n isPrimary: parsed.isPrimary ?? false,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n await em.flush()\n\n if (address.isPrimary) {\n await enforcePrimaryAddress(em, member.id, address.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadAddressSnapshot(em, result.addressId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as AddressSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.create', 'Create address'),\n resourceKind: 'staff.team_member_address',\n resourceId: result.addressId,\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 AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<AddressUndoPayload>(logEntry)\n const after = payload?.after\n const addressId = after?.id ?? logEntry?.resourceId ?? null\n if (!addressId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const address = await em.findOne(StaffTeamMemberAddress, scopedStaffSnapshotWhere(addressId, staffSnapshotScopeFromSnapshot(after)))\n if (address) {\n em.remove(address)\n await em.flush()\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<AddressSnapshot>(logEntry)\n if (!after) {\n throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for address create' })\n }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshotScope = staffSnapshotScopeFromSnapshot(after)\n const member = await requireTeamMember(\n em,\n after.memberId,\n explicitStaffCommandScope(after.tenantId, after.organizationId),\n 'Team member not found',\n )\n let address = await em.findOne(StaffTeamMemberAddress, scopedStaffSnapshotWhere(after.id, snapshotScope))\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: after.id,\n organizationId: after.organizationId,\n tenantId: after.tenantId,\n member,\n name: after.name,\n purpose: after.purpose,\n companyName: after.companyName,\n addressLine1: after.addressLine1,\n addressLine2: after.addressLine2,\n buildingNumber: after.buildingNumber,\n flatNumber: after.flatNumber,\n city: after.city,\n region: after.region,\n postalCode: after.postalCode,\n country: after.country,\n latitude: after.latitude,\n longitude: after.longitude,\n isPrimary: after.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = after.name\n address.purpose = after.purpose\n address.companyName = after.companyName\n address.addressLine1 = after.addressLine1\n address.addressLine2 = after.addressLine2\n address.buildingNumber = after.buildingNumber\n address.flatNumber = after.flatNumber\n address.city = after.city\n address.region = after.region\n address.postalCode = after.postalCode\n address.country = after.country\n address.latitude = after.latitude\n address.longitude = after.longitude\n address.isPrimary = after.isPrimary\n }\n await em.flush()\n if (after.isPrimary) {\n await enforcePrimaryAddress(em, after.memberId, after.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n}\n\nconst updateAddressCommand: CommandHandler<StaffTeamMemberAddressUpdateInput, { addressId: string }> = {\n id: 'staff.team-member-addresses.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberAddressUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadAddressSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberAddressUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const address = await em.findOne(\n StaffTeamMemberAddress,\n applyScopeToWhere<StaffTeamMemberAddress>({ id: parsed.id }, scope),\n )\n if (!address) throw new CrudHttpError(404, { error: 'Address not found' })\n ensureTenantScope(ctx, address.tenantId)\n ensureOrganizationScope(ctx, address.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n address.member = member\n }\n if (parsed.name !== undefined) address.name = parsed.name ?? null\n if (parsed.purpose !== undefined) address.purpose = parsed.purpose ?? null\n if (parsed.companyName !== undefined) address.companyName = parsed.companyName ?? null\n if (parsed.addressLine1 !== undefined) address.addressLine1 = parsed.addressLine1\n if (parsed.addressLine2 !== undefined) address.addressLine2 = parsed.addressLine2 ?? null\n if (parsed.buildingNumber !== undefined) address.buildingNumber = parsed.buildingNumber ?? null\n if (parsed.flatNumber !== undefined) address.flatNumber = parsed.flatNumber ?? null\n if (parsed.city !== undefined) address.city = parsed.city ?? null\n if (parsed.region !== undefined) address.region = parsed.region ?? null\n if (parsed.postalCode !== undefined) address.postalCode = parsed.postalCode ?? null\n if (parsed.country !== undefined) address.country = parsed.country ?? null\n if (parsed.latitude !== undefined) address.latitude = parsed.latitude ?? null\n if (parsed.longitude !== undefined) address.longitude = parsed.longitude ?? null\n if (parsed.isPrimary !== undefined) address.isPrimary = parsed.isPrimary\n\n await em.flush()\n\n if (address.isPrimary) {\n await enforcePrimaryAddress(em, typeof address.member === 'string' ? address.member : address.member.id, address.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n\n return { addressId: address.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadAddressSnapshot(em, result.addressId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as AddressSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as AddressSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n [\n 'memberId',\n 'name',\n 'purpose',\n 'companyName',\n 'addressLine1',\n 'addressLine2',\n 'buildingNumber',\n 'flatNumber',\n 'city',\n 'region',\n 'postalCode',\n 'country',\n 'latitude',\n 'longitude',\n 'isPrimary',\n ],\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.update', 'Update address'),\n resourceKind: 'staff.team_member_address',\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: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<AddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshotScope = staffSnapshotScopeFromSnapshot(before)\n let address = await em.findOne(StaffTeamMemberAddress, scopedStaffSnapshotWhere(before.id, snapshotScope))\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n name: before.name,\n purpose: before.purpose,\n companyName: before.companyName,\n addressLine1: before.addressLine1,\n addressLine2: before.addressLine2,\n buildingNumber: before.buildingNumber,\n flatNumber: before.flatNumber,\n city: before.city,\n region: before.region,\n postalCode: before.postalCode,\n country: before.country,\n latitude: before.latitude,\n longitude: before.longitude,\n isPrimary: before.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = before.name\n address.purpose = before.purpose\n address.companyName = before.companyName\n address.addressLine1 = before.addressLine1\n address.addressLine2 = before.addressLine2\n address.buildingNumber = before.buildingNumber\n address.flatNumber = before.flatNumber\n address.city = before.city\n address.region = before.region\n address.postalCode = before.postalCode\n address.country = before.country\n address.latitude = before.latitude\n address.longitude = before.longitude\n address.isPrimary = before.isPrimary\n }\n await em.flush()\n if (before.isPrimary) {\n await enforcePrimaryAddress(em, before.memberId, before.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n },\n}\n\nconst deleteAddressCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { addressId: string }> =\n {\n id: 'staff.team-member-addresses.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Address id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadAddressSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Address id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const address = await em.findOne(\n StaffTeamMemberAddress,\n applyScopeToWhere<StaffTeamMemberAddress>({ id }, scope),\n )\n if (!address) throw new CrudHttpError(404, { error: 'Address not found' })\n ensureTenantScope(ctx, address.tenantId)\n ensureOrganizationScope(ctx, address.organizationId)\n em.remove(address)\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: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n return { addressId: address.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as AddressSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberAddresses.delete', 'Delete address'),\n resourceKind: 'staff.team_member_address',\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 payload: {\n undo: {\n before,\n } satisfies AddressUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<AddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshotScope = staffSnapshotScopeFromSnapshot(before)\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n let address = await em.findOne(StaffTeamMemberAddress, scopedStaffSnapshotWhere(before.id, snapshotScope))\n if (!address) {\n address = em.create(StaffTeamMemberAddress, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n name: before.name,\n purpose: before.purpose,\n companyName: before.companyName,\n addressLine1: before.addressLine1,\n addressLine2: before.addressLine2,\n buildingNumber: before.buildingNumber,\n flatNumber: before.flatNumber,\n city: before.city,\n region: before.region,\n postalCode: before.postalCode,\n country: before.country,\n latitude: before.latitude,\n longitude: before.longitude,\n isPrimary: before.isPrimary,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(address)\n } else {\n address.member = member\n address.name = before.name\n address.purpose = before.purpose\n address.companyName = before.companyName\n address.addressLine1 = before.addressLine1\n address.addressLine2 = before.addressLine2\n address.buildingNumber = before.buildingNumber\n address.flatNumber = before.flatNumber\n address.city = before.city\n address.region = before.region\n address.postalCode = before.postalCode\n address.country = before.country\n address.latitude = before.latitude\n address.longitude = before.longitude\n address.isPrimary = before.isPrimary\n }\n await em.flush()\n if (before.isPrimary) {\n await enforcePrimaryAddress(em, before.memberId, before.id)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: address,\n identifiers: {\n id: address.id,\n organizationId: address.organizationId,\n tenantId: address.tenantId,\n },\n events: staffTeamMemberAddressCrudEvents,\n indexer: addressCrudIndexer,\n })\n },\n }\n\nregisterCommand(createAddressCommand)\nregisterCommand(updateAddressCommand)\nregisterCommand(deleteAddressCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -16,15 +16,18 @@ import {
|
|
|
16
16
|
ensureTenantScope,
|
|
17
17
|
explicitStaffCommandScope,
|
|
18
18
|
extractUndoPayload,
|
|
19
|
-
requireTeamMember
|
|
19
|
+
requireTeamMember,
|
|
20
|
+
scopedStaffSnapshotWhere,
|
|
21
|
+
staffSnapshotScopeFromContext,
|
|
22
|
+
staffSnapshotScopeFromSnapshot
|
|
20
23
|
} from "./shared.js";
|
|
21
24
|
import { makeCreateRedo } from "@open-mercato/shared/lib/commands/redo";
|
|
22
25
|
import { E } from "../../../generated/entities.ids.generated.js";
|
|
23
26
|
const commentCrudIndexer = {
|
|
24
27
|
entityType: E.staff.staff_team_member_comment
|
|
25
28
|
};
|
|
26
|
-
async function loadCommentSnapshot(em, id) {
|
|
27
|
-
const comment = await em.findOne(StaffTeamMemberComment,
|
|
29
|
+
async function loadCommentSnapshot(em, id, scope) {
|
|
30
|
+
const comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(id, scope));
|
|
28
31
|
if (!comment) return null;
|
|
29
32
|
return {
|
|
30
33
|
id: comment.id,
|
|
@@ -84,7 +87,7 @@ const createCommentCommand = {
|
|
|
84
87
|
},
|
|
85
88
|
captureAfter: async (_input, result, ctx) => {
|
|
86
89
|
const em = ctx.container.resolve("em").fork();
|
|
87
|
-
return await loadCommentSnapshot(em, result.commentId);
|
|
90
|
+
return await loadCommentSnapshot(em, result.commentId, staffSnapshotScopeFromContext(ctx));
|
|
88
91
|
},
|
|
89
92
|
buildLog: async ({ result, snapshots }) => {
|
|
90
93
|
const { translate } = await resolveTranslations();
|
|
@@ -106,10 +109,12 @@ const createCommentCommand = {
|
|
|
106
109
|
};
|
|
107
110
|
},
|
|
108
111
|
undo: async ({ logEntry, ctx }) => {
|
|
109
|
-
const
|
|
112
|
+
const payload = extractUndoPayload(logEntry);
|
|
113
|
+
const after = payload?.after;
|
|
114
|
+
const commentId = after?.id ?? logEntry?.resourceId ?? null;
|
|
110
115
|
if (!commentId) return;
|
|
111
116
|
const em = ctx.container.resolve("em").fork();
|
|
112
|
-
const existing = await em.findOne(StaffTeamMemberComment,
|
|
117
|
+
const existing = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(commentId, staffSnapshotScopeFromSnapshot(after)));
|
|
113
118
|
if (existing) {
|
|
114
119
|
em.remove(existing);
|
|
115
120
|
await em.flush();
|
|
@@ -145,7 +150,7 @@ const updateCommentCommand = {
|
|
|
145
150
|
async prepare(rawInput, ctx) {
|
|
146
151
|
const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput);
|
|
147
152
|
const em = ctx.container.resolve("em");
|
|
148
|
-
const snapshot = await loadCommentSnapshot(em, parsed.id);
|
|
153
|
+
const snapshot = await loadCommentSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx));
|
|
149
154
|
return snapshot ? { before: snapshot } : {};
|
|
150
155
|
},
|
|
151
156
|
async execute(rawInput, ctx) {
|
|
@@ -187,7 +192,7 @@ const updateCommentCommand = {
|
|
|
187
192
|
},
|
|
188
193
|
captureAfter: async (_input, result, ctx) => {
|
|
189
194
|
const em = ctx.container.resolve("em").fork();
|
|
190
|
-
return await loadCommentSnapshot(em, result.commentId);
|
|
195
|
+
return await loadCommentSnapshot(em, result.commentId, staffSnapshotScopeFromContext(ctx));
|
|
191
196
|
},
|
|
192
197
|
buildLog: async ({ snapshots }) => {
|
|
193
198
|
const { translate } = await resolveTranslations();
|
|
@@ -223,7 +228,8 @@ const updateCommentCommand = {
|
|
|
223
228
|
const before = payload?.before;
|
|
224
229
|
if (!before) return;
|
|
225
230
|
const em = ctx.container.resolve("em").fork();
|
|
226
|
-
|
|
231
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
232
|
+
let comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(before.id, snapshotScope));
|
|
227
233
|
const member = await requireTeamMember(
|
|
228
234
|
em,
|
|
229
235
|
before.memberId,
|
|
@@ -272,7 +278,7 @@ const deleteCommentCommand = {
|
|
|
272
278
|
async prepare(input, ctx) {
|
|
273
279
|
const id = requireId(input, "Comment id required");
|
|
274
280
|
const em = ctx.container.resolve("em");
|
|
275
|
-
const snapshot = await loadCommentSnapshot(em, id);
|
|
281
|
+
const snapshot = await loadCommentSnapshot(em, id, staffSnapshotScopeFromContext(ctx));
|
|
276
282
|
return snapshot ? { before: snapshot } : {};
|
|
277
283
|
},
|
|
278
284
|
async execute(input, ctx) {
|
|
@@ -328,13 +334,14 @@ const deleteCommentCommand = {
|
|
|
328
334
|
const before = payload?.before;
|
|
329
335
|
if (!before) return;
|
|
330
336
|
const em = ctx.container.resolve("em").fork();
|
|
337
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
331
338
|
const member = await requireTeamMember(
|
|
332
339
|
em,
|
|
333
340
|
before.memberId,
|
|
334
341
|
explicitStaffCommandScope(before.tenantId, before.organizationId),
|
|
335
342
|
"Team member not found"
|
|
336
343
|
);
|
|
337
|
-
let comment = await em.findOne(StaffTeamMemberComment,
|
|
344
|
+
let comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(before.id, snapshotScope));
|
|
338
345
|
if (!comment) {
|
|
339
346
|
comment = em.create(StaffTeamMemberComment, {
|
|
340
347
|
id: before.id,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/comments.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId, normalizeAuthorUserId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\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 type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberComment } from '../data/entities'\nimport {\n staffTeamMemberCommentCreateSchema,\n staffTeamMemberCommentUpdateSchema,\n type StaffTeamMemberCommentCreateInput,\n type StaffTeamMemberCommentUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCommentCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n} from './shared'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { E } from '#generated/entities.ids.generated'\n\nconst commentCrudIndexer: CrudIndexerConfig<StaffTeamMemberComment> = {\n entityType: E.staff.staff_team_member_comment,\n}\n\ntype CommentSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n body: string\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype CommentUndoPayload = {\n before?: CommentSnapshot | null\n after?: CommentSnapshot | null\n}\n\nasync function loadCommentSnapshot(em: EntityManager, id: string): Promise<CommentSnapshot | null> {\n const comment = await em.findOne(StaffTeamMemberComment, { id })\n if (!comment) return null\n return {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n memberId: typeof comment.member === 'string' ? comment.member : comment.member.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n}\n\nconst createCommentCommand: CommandHandler<\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-comments.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(\n em,\n parsed.entityId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const comment = em.create(StaffTeamMemberComment, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n body: parsed.body,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id, authorUserId: comment.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as CommentSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberComments.create', 'Create note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: result.commentId,\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 CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const commentId = logEntry?.resourceId ?? null\n if (!commentId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberComment, { id: commentId })\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n redo: makeCreateRedo<\n StaffTeamMemberComment,\n CommentSnapshot,\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n >({\n entityClass: StaffTeamMemberComment,\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n seedFromSnapshot: (snapshot) => ({\n id: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n body: snapshot.body,\n authorUserId: snapshot.authorUserId,\n appearanceIcon: snapshot.appearanceIcon,\n appearanceColor: snapshot.appearanceColor,\n }),\n beforeRestore: async ({ em, snapshot }) => {\n const member = await requireTeamMember(\n em,\n snapshot.memberId,\n explicitStaffCommandScope(snapshot.tenantId, snapshot.organizationId),\n 'Team member not found',\n )\n return { member }\n },\n buildResult: (entity) => ({ commentId: entity.id, authorUserId: entity.authorUserId ?? null }),\n }),\n}\n\nconst updateCommentCommand: CommandHandler<StaffTeamMemberCommentUpdateInput, { commentId: string }> = {\n id: 'staff.team-member-comments.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const comment = await em.findOne(\n StaffTeamMemberComment,\n applyScopeToWhere<StaffTeamMemberComment>({ id: parsed.id }, scope),\n )\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n comment.member = member\n }\n if (parsed.body !== undefined) comment.body = parsed.body\n if (parsed.authorUserId !== undefined) comment.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) comment.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) comment.appearanceColor = parsed.appearanceColor ?? null\n\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as CommentSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n ['memberId', 'body', 'authorUserId', 'appearanceIcon', 'appearanceColor']\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberComments.update', 'Update note'),\n resourceKind: 'staff.team_member_comment',\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: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n },\n}\n\nconst deleteCommentCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { commentId: string }> =\n {\n id: 'staff.team-member-comments.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const comment = await em.findOne(\n StaffTeamMemberComment,\n applyScopeToWhere<StaffTeamMemberComment>({ id }, scope),\n )\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n em.remove(comment)\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n return { commentId: comment.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberComments.delete', 'Delete note'),\n resourceKind: 'staff.team_member_comment',\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 payload: {\n undo: {\n before,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n let comment = await em.findOne(StaffTeamMemberComment, { id: before.id })\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n },\n }\n\nregisterCommand(createCommentCommand)\nregisterCommand(updateCommentCommand)\nregisterCommand(deleteCommentCommand)\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB,yBAAyB,cAAc,WAAW,6BAA6B;AAG7G,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AAEpC,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OAGK;AACP,SAAS,wCAAwC;AACjD;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects, buildChanges, requireId, normalizeAuthorUserId } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\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 type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { StaffTeamMemberComment } from '../data/entities'\nimport {\n staffTeamMemberCommentCreateSchema,\n staffTeamMemberCommentUpdateSchema,\n type StaffTeamMemberCommentCreateInput,\n type StaffTeamMemberCommentUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCommentCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n requireTeamMember,\n scopedStaffSnapshotWhere,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\n} from './shared'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { E } from '#generated/entities.ids.generated'\n\nconst commentCrudIndexer: CrudIndexerConfig<StaffTeamMemberComment> = {\n entityType: E.staff.staff_team_member_comment,\n}\n\ntype CommentSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n memberId: string\n body: string\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype CommentUndoPayload = {\n before?: CommentSnapshot | null\n after?: CommentSnapshot | null\n}\n\nasync function loadCommentSnapshot(em: EntityManager, id: string, scope?: StaffSnapshotScope | null): Promise<CommentSnapshot | null> {\n const comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(id, scope))\n if (!comment) return null\n return {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n memberId: typeof comment.member === 'string' ? comment.member : comment.member.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n}\n\nconst createCommentCommand: CommandHandler<\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n> = {\n id: 'staff.team-member-comments.create',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const normalizedAuthor = normalizeAuthorUserId(parsed.authorUserId, ctx.auth)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await requireTeamMember(\n em,\n parsed.entityId,\n scope,\n 'Team member not found',\n )\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n const comment = em.create(StaffTeamMemberComment, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n member,\n body: parsed.body,\n authorUserId: normalizedAuthor,\n appearanceIcon: parsed.appearanceIcon ?? null,\n appearanceColor: parsed.appearanceColor ?? null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id, authorUserId: comment.authorUserId ?? null }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as CommentSnapshot | undefined\n return {\n actionLabel: translate('staff.audit.teamMemberComments.create', 'Create note'),\n resourceKind: 'staff.team_member_comment',\n resourceId: result.commentId,\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 CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const after = payload?.after\n const commentId = after?.id ?? logEntry?.resourceId ?? null\n if (!commentId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(commentId, staffSnapshotScopeFromSnapshot(after)))\n if (existing) {\n em.remove(existing)\n await em.flush()\n }\n },\n redo: makeCreateRedo<\n StaffTeamMemberComment,\n CommentSnapshot,\n StaffTeamMemberCommentCreateInput,\n { commentId: string; authorUserId: string | null }\n >({\n entityClass: StaffTeamMemberComment,\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n seedFromSnapshot: (snapshot) => ({\n id: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n body: snapshot.body,\n authorUserId: snapshot.authorUserId,\n appearanceIcon: snapshot.appearanceIcon,\n appearanceColor: snapshot.appearanceColor,\n }),\n beforeRestore: async ({ em, snapshot }) => {\n const member = await requireTeamMember(\n em,\n snapshot.memberId,\n explicitStaffCommandScope(snapshot.tenantId, snapshot.organizationId),\n 'Team member not found',\n )\n return { member }\n },\n buildResult: (entity) => ({ commentId: entity.id, authorUserId: entity.authorUserId ?? null }),\n }),\n}\n\nconst updateCommentCommand: CommandHandler<StaffTeamMemberCommentUpdateInput, { commentId: string }> = {\n id: 'staff.team-member-comments.update',\n async prepare(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberCommentUpdateSchema.parse(rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const comment = await em.findOne(\n StaffTeamMemberComment,\n applyScopeToWhere<StaffTeamMemberComment>({ id: parsed.id }, scope),\n )\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n\n if (parsed.entityId !== undefined) {\n const member = await requireTeamMember(em, parsed.entityId, scope, 'Team member not found')\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n comment.member = member\n }\n if (parsed.body !== undefined) comment.body = parsed.body\n if (parsed.authorUserId !== undefined) comment.authorUserId = parsed.authorUserId ?? null\n if (parsed.appearanceIcon !== undefined) comment.appearanceIcon = parsed.appearanceIcon ?? null\n if (parsed.appearanceColor !== undefined) comment.appearanceColor = parsed.appearanceColor ?? null\n\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n\n return { commentId: comment.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadCommentSnapshot(em, result.commentId, staffSnapshotScopeFromContext(ctx))\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as CommentSnapshot | undefined\n const changes =\n afterSnapshot && before\n ? buildChanges(\n before as unknown as Record<string, unknown>,\n afterSnapshot as unknown as Record<string, unknown>,\n ['memberId', 'body', 'authorUserId', 'appearanceIcon', 'appearanceColor']\n )\n : {}\n return {\n actionLabel: translate('staff.audit.teamMemberComments.update', 'Update note'),\n resourceKind: 'staff.team_member_comment',\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: afterSnapshot ?? null,\n changes,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshotScope = staffSnapshotScopeFromSnapshot(before)\n let comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(before.id, snapshotScope))\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n },\n}\n\nconst deleteCommentCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { commentId: string }> =\n {\n id: 'staff.team-member-comments.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadCommentSnapshot(em, id, staffSnapshotScopeFromContext(ctx))\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Comment id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const comment = await em.findOne(\n StaffTeamMemberComment,\n applyScopeToWhere<StaffTeamMemberComment>({ id }, scope),\n )\n if (!comment) throw new CrudHttpError(404, { error: 'Comment not found' })\n ensureTenantScope(ctx, comment.tenantId)\n ensureOrganizationScope(ctx, comment.organizationId)\n em.remove(comment)\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n return { commentId: comment.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as CommentSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMemberComments.delete', 'Delete note'),\n resourceKind: 'staff.team_member_comment',\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 payload: {\n undo: {\n before,\n } satisfies CommentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<CommentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshotScope = staffSnapshotScopeFromSnapshot(before)\n const member = await requireTeamMember(\n em,\n before.memberId,\n explicitStaffCommandScope(before.tenantId, before.organizationId),\n 'Team member not found',\n )\n let comment = await em.findOne(StaffTeamMemberComment, scopedStaffSnapshotWhere(before.id, snapshotScope))\n if (!comment) {\n comment = em.create(StaffTeamMemberComment, {\n id: before.id,\n organizationId: before.organizationId,\n tenantId: before.tenantId,\n member,\n body: before.body,\n authorUserId: before.authorUserId,\n appearanceIcon: before.appearanceIcon,\n appearanceColor: before.appearanceColor,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(comment)\n } else {\n comment.member = member\n comment.body = before.body\n comment.authorUserId = before.authorUserId\n comment.appearanceIcon = before.appearanceIcon\n comment.appearanceColor = before.appearanceColor\n }\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: comment,\n identifiers: {\n id: comment.id,\n organizationId: comment.organizationId,\n tenantId: comment.tenantId,\n },\n events: staffTeamMemberCommentCrudEvents,\n indexer: commentCrudIndexer,\n })\n },\n }\n\nregisterCommand(createCommentCommand)\nregisterCommand(updateCommentCommand)\nregisterCommand(deleteCommentCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
ensureTenantScope,
|
|
15
15
|
explicitStaffCommandScope,
|
|
16
16
|
extractUndoPayload,
|
|
17
|
-
requireTeamMember
|
|
17
|
+
requireTeamMember,
|
|
18
|
+
scopedStaffSnapshotWhere,
|
|
19
|
+
staffSnapshotScopeFromContext,
|
|
20
|
+
staffSnapshotScopeFromSnapshot
|
|
18
21
|
} from "./shared.js";
|
|
19
22
|
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
20
23
|
import { resolveRedoSnapshot } from "@open-mercato/shared/lib/commands/redo";
|
|
@@ -28,8 +31,8 @@ const JOB_HISTORY_LOCK_RESOURCE_KIND = "staff.jobHistory";
|
|
|
28
31
|
const jobHistoryCrudIndexer = {
|
|
29
32
|
entityType: E.staff.staff_team_member_job_history
|
|
30
33
|
};
|
|
31
|
-
async function loadJobHistorySnapshot(em, id) {
|
|
32
|
-
const record = await em.findOne(StaffTeamMemberJobHistory,
|
|
34
|
+
async function loadJobHistorySnapshot(em, id, scope) {
|
|
35
|
+
const record = await em.findOne(StaffTeamMemberJobHistory, scopedStaffSnapshotWhere(id, scope));
|
|
33
36
|
if (!record) return null;
|
|
34
37
|
return {
|
|
35
38
|
id: record.id,
|
|
@@ -91,7 +94,7 @@ const createJobHistoryCommand = {
|
|
|
91
94
|
},
|
|
92
95
|
captureAfter: async (_input, result, ctx) => {
|
|
93
96
|
const em = ctx.container.resolve("em").fork();
|
|
94
|
-
return await loadJobHistorySnapshot(em, result.jobHistoryId);
|
|
97
|
+
return await loadJobHistorySnapshot(em, result.jobHistoryId, staffSnapshotScopeFromContext(ctx));
|
|
95
98
|
},
|
|
96
99
|
buildLog: async ({ result, snapshots }) => {
|
|
97
100
|
const { translate } = await resolveTranslations();
|
|
@@ -113,10 +116,15 @@ const createJobHistoryCommand = {
|
|
|
113
116
|
};
|
|
114
117
|
},
|
|
115
118
|
undo: async ({ logEntry, ctx }) => {
|
|
116
|
-
const
|
|
119
|
+
const payload = extractUndoPayload(logEntry);
|
|
120
|
+
const after = payload?.after ?? null;
|
|
121
|
+
const jobHistoryId = after?.id ?? logEntry?.resourceId ?? null;
|
|
117
122
|
if (!jobHistoryId) return;
|
|
118
123
|
const em = ctx.container.resolve("em").fork();
|
|
119
|
-
const record = await em.findOne(
|
|
124
|
+
const record = await em.findOne(
|
|
125
|
+
StaffTeamMemberJobHistory,
|
|
126
|
+
scopedStaffSnapshotWhere(jobHistoryId, staffSnapshotScopeFromSnapshot(after))
|
|
127
|
+
);
|
|
120
128
|
if (record) {
|
|
121
129
|
em.remove(record);
|
|
122
130
|
await em.flush();
|
|
@@ -128,13 +136,14 @@ const createJobHistoryCommand = {
|
|
|
128
136
|
throw new CrudHttpError(400, { error: "[internal] redo snapshot unavailable for job history create" });
|
|
129
137
|
}
|
|
130
138
|
const em = ctx.container.resolve("em").fork();
|
|
139
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(after);
|
|
131
140
|
const member = await requireTeamMember(
|
|
132
141
|
em,
|
|
133
142
|
after.memberId,
|
|
134
143
|
explicitStaffCommandScope(after.tenantId, after.organizationId),
|
|
135
144
|
"Team member not found"
|
|
136
145
|
);
|
|
137
|
-
let record = await em.findOne(StaffTeamMemberJobHistory,
|
|
146
|
+
let record = await em.findOne(StaffTeamMemberJobHistory, scopedStaffSnapshotWhere(after.id, snapshotScope));
|
|
138
147
|
if (!record) {
|
|
139
148
|
record = em.create(StaffTeamMemberJobHistory, {
|
|
140
149
|
id: after.id,
|
|
@@ -180,7 +189,7 @@ const updateJobHistoryCommand = {
|
|
|
180
189
|
async prepare(rawInput, ctx) {
|
|
181
190
|
const parsed = staffTeamMemberJobHistoryUpdateSchema.parse(rawInput);
|
|
182
191
|
const em = ctx.container.resolve("em");
|
|
183
|
-
const snapshot = await loadJobHistorySnapshot(em, parsed.id);
|
|
192
|
+
const snapshot = await loadJobHistorySnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx));
|
|
184
193
|
return snapshot ? { before: snapshot } : {};
|
|
185
194
|
},
|
|
186
195
|
async execute(rawInput, ctx) {
|
|
@@ -238,7 +247,7 @@ const updateJobHistoryCommand = {
|
|
|
238
247
|
},
|
|
239
248
|
captureAfter: async (_input, result, ctx) => {
|
|
240
249
|
const em = ctx.container.resolve("em").fork();
|
|
241
|
-
return await loadJobHistorySnapshot(em, result.jobHistoryId);
|
|
250
|
+
return await loadJobHistorySnapshot(em, result.jobHistoryId, staffSnapshotScopeFromContext(ctx));
|
|
242
251
|
},
|
|
243
252
|
buildLog: async ({ snapshots }) => {
|
|
244
253
|
const { translate } = await resolveTranslations();
|
|
@@ -274,7 +283,8 @@ const updateJobHistoryCommand = {
|
|
|
274
283
|
const before = payload?.before;
|
|
275
284
|
if (!before) return;
|
|
276
285
|
const em = ctx.container.resolve("em").fork();
|
|
277
|
-
|
|
286
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
287
|
+
let record = await em.findOne(StaffTeamMemberJobHistory, scopedStaffSnapshotWhere(before.id, snapshotScope));
|
|
278
288
|
const member = await requireTeamMember(
|
|
279
289
|
em,
|
|
280
290
|
before.memberId,
|
|
@@ -325,7 +335,7 @@ const deleteJobHistoryCommand = {
|
|
|
325
335
|
async prepare(input, ctx) {
|
|
326
336
|
const id = requireId(input, "Job history id required");
|
|
327
337
|
const em = ctx.container.resolve("em");
|
|
328
|
-
const snapshot = await loadJobHistorySnapshot(em, id);
|
|
338
|
+
const snapshot = await loadJobHistorySnapshot(em, id, staffSnapshotScopeFromContext(ctx));
|
|
329
339
|
return snapshot ? { before: snapshot } : {};
|
|
330
340
|
},
|
|
331
341
|
async execute(input, ctx) {
|
|
@@ -397,13 +407,14 @@ const deleteJobHistoryCommand = {
|
|
|
397
407
|
const before = payload?.before;
|
|
398
408
|
if (!before) return;
|
|
399
409
|
const em = ctx.container.resolve("em").fork();
|
|
410
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
400
411
|
const member = await requireTeamMember(
|
|
401
412
|
em,
|
|
402
413
|
before.memberId,
|
|
403
414
|
explicitStaffCommandScope(before.tenantId, before.organizationId),
|
|
404
415
|
"Team member not found"
|
|
405
416
|
);
|
|
406
|
-
let record = await em.findOne(StaffTeamMemberJobHistory,
|
|
417
|
+
let record = await em.findOne(StaffTeamMemberJobHistory, scopedStaffSnapshotWhere(before.id, snapshotScope));
|
|
407
418
|
if (!record) {
|
|
408
419
|
record = em.create(StaffTeamMemberJobHistory, {
|
|
409
420
|
id: before.id,
|