@open-mercato/core 0.6.6-develop.6429.1.2fba7258d1 → 0.6.6-develop.6450.1.b493fb430c
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/customers/api/people/[id]/route.js +73 -2
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/planner/commands/shared.js +1 -8
- package/dist/modules/planner/commands/shared.js.map +2 -2
- package/dist/modules/resources/commands/shared.js +1 -7
- package/dist/modules/resources/commands/shared.js.map +2 -2
- package/dist/modules/shipping_carriers/api/cancel/route.js +2 -2
- package/dist/modules/shipping_carriers/api/cancel/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/points/route.js +2 -2
- package/dist/modules/shipping_carriers/api/points/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/rates/route.js +2 -2
- package/dist/modules/shipping_carriers/api/rates/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/shipments/route.js +2 -2
- package/dist/modules/shipping_carriers/api/shipments/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/tracking/refresh/route.js +2 -2
- package/dist/modules/shipping_carriers/api/tracking/refresh/route.js.map +2 -2
- package/dist/modules/shipping_carriers/api/tracking/route.js +2 -2
- package/dist/modules/shipping_carriers/api/tracking/route.js.map +2 -2
- package/dist/modules/shipping_carriers/lib/upstream-error-response.js +13 -0
- package/dist/modules/shipping_carriers/lib/upstream-error-response.js.map +7 -0
- package/dist/modules/staff/commands/activities.js +46 -8
- package/dist/modules/staff/commands/activities.js.map +2 -2
- package/dist/modules/staff/commands/addresses.js +40 -7
- package/dist/modules/staff/commands/addresses.js.map +2 -2
- package/dist/modules/staff/commands/comments.js +46 -8
- package/dist/modules/staff/commands/comments.js.map +2 -2
- package/dist/modules/staff/commands/job-histories.js +40 -7
- package/dist/modules/staff/commands/job-histories.js.map +2 -2
- package/dist/modules/staff/commands/leave-requests.js +31 -9
- package/dist/modules/staff/commands/leave-requests.js.map +2 -2
- package/dist/modules/staff/commands/shared.js +56 -7
- package/dist/modules/staff/commands/shared.js.map +2 -2
- package/dist/modules/staff/commands/tag-assignments.js +18 -7
- package/dist/modules/staff/commands/tag-assignments.js.map +2 -2
- package/dist/modules/staff/commands/team-members.js +16 -5
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/commands/team-roles.js +16 -5
- package/dist/modules/staff/commands/team-roles.js.map +2 -2
- package/dist/modules/staff/commands/teams.js +16 -5
- package/dist/modules/staff/commands/teams.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-entries.js +17 -5
- package/dist/modules/staff/commands/timesheets-entries.js.map +2 -2
- package/dist/modules/staff/commands/timesheets-projects.js +22 -9
- package/dist/modules/staff/commands/timesheets-projects.js.map +2 -2
- package/dist/modules/sync_excel/lib/upload-storage.js +9 -6
- package/dist/modules/sync_excel/lib/upload-storage.js.map +2 -2
- package/dist/modules/translations/api/get/locales.js +2 -1
- package/dist/modules/translations/api/get/locales.js.map +2 -2
- package/dist/modules/translations/api/put/locales.js +1 -1
- package/dist/modules/translations/api/put/locales.js.map +2 -2
- package/dist/modules/workflows/examples/sales-pipeline-definition.json +8 -8
- package/dist/modules/workflows/lib/activity-executor.js +39 -3
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/customers/api/people/[id]/route.ts +107 -2
- package/src/modules/planner/commands/shared.ts +2 -11
- package/src/modules/resources/commands/shared.ts +2 -10
- package/src/modules/shipping_carriers/api/cancel/route.ts +2 -2
- package/src/modules/shipping_carriers/api/points/route.ts +2 -2
- package/src/modules/shipping_carriers/api/rates/route.ts +2 -2
- package/src/modules/shipping_carriers/api/shipments/route.ts +2 -2
- package/src/modules/shipping_carriers/api/tracking/refresh/route.ts +2 -2
- package/src/modules/shipping_carriers/api/tracking/route.ts +2 -2
- package/src/modules/shipping_carriers/i18n/de.json +1 -0
- package/src/modules/shipping_carriers/i18n/en.json +1 -0
- package/src/modules/shipping_carriers/i18n/es.json +1 -0
- package/src/modules/shipping_carriers/i18n/pl.json +1 -0
- package/src/modules/shipping_carriers/lib/upstream-error-response.ts +11 -0
- package/src/modules/staff/commands/activities.ts +46 -8
- package/src/modules/staff/commands/addresses.ts +40 -7
- package/src/modules/staff/commands/comments.ts +46 -8
- package/src/modules/staff/commands/job-histories.ts +40 -7
- package/src/modules/staff/commands/leave-requests.ts +36 -9
- package/src/modules/staff/commands/shared.ts +71 -8
- package/src/modules/staff/commands/tag-assignments.ts +18 -7
- package/src/modules/staff/commands/team-members.ts +16 -5
- package/src/modules/staff/commands/team-roles.ts +16 -5
- package/src/modules/staff/commands/teams.ts +16 -5
- package/src/modules/staff/commands/timesheets-entries.ts +17 -5
- package/src/modules/staff/commands/timesheets-projects.ts +22 -9
- package/src/modules/sync_excel/lib/upload-storage.ts +8 -6
- package/src/modules/translations/api/get/locales.ts +1 -0
- package/src/modules/translations/api/put/locales.ts +1 -1
- package/src/modules/workflows/AGENTS.md +2 -1
- package/src/modules/workflows/examples/sales-pipeline-definition.json +8 -8
- package/src/modules/workflows/lib/activity-executor.ts +49 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/shared.ts"],
|
|
4
|
-
"sourcesContent": ["import
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { ensureOrganizationScope, ensureTenantScope } from '@open-mercato/shared/lib/commands/scope'\nimport { extractUndoPayload } from '@open-mercato/shared/lib/commands/undo'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { StaffTeamMember } from '../data/entities'\n\nexport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload }\n\nexport type StaffCommandScope = {\n tenantId: string | null\n organizationId: string | null\n requireTenant: boolean\n requireOrganization: boolean\n}\n\nexport function commandActorScope(ctx: CommandRuntimeContext): StaffCommandScope {\n const isPrivilegedActor = ctx.auth?.isSuperAdmin === true || ctx.systemActor === true\n const tenantId = isPrivilegedActor ? null : (ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null)\n const organizationId = isPrivilegedActor ? null : (ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null)\n const organizationUnrestricted =\n isPrivilegedActor || (organizationId === null && tenantId !== null && ctx.organizationScope?.allowedIds === null)\n return {\n tenantId,\n organizationId: organizationUnrestricted ? null : organizationId,\n requireTenant: !isPrivilegedActor,\n requireOrganization: !organizationUnrestricted,\n }\n}\n\nexport function explicitStaffCommandScope(tenantId: string | null, organizationId: string | null): StaffCommandScope {\n return {\n tenantId,\n organizationId,\n requireTenant: true,\n requireOrganization: true,\n }\n}\n\nexport function commandInputScope(ctx: CommandRuntimeContext, tenantId: string, organizationId: string): StaffCommandScope {\n if (ctx.auth?.isSuperAdmin === true || ctx.systemActor === true) {\n return explicitStaffCommandScope(tenantId, organizationId)\n }\n\n ensureTenantScope(ctx, tenantId)\n ensureOrganizationScope(ctx, organizationId)\n\n const actorTenantId = ctx.auth?.tenantId ?? ctx.organizationScope?.tenantId ?? null\n if (!actorTenantId || actorTenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n\n if (!ctx.organizationScope) {\n const currentOrganizationId = ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null\n if (!currentOrganizationId || currentOrganizationId !== organizationId) {\n throw new CrudHttpError(403, { error: 'Forbidden' })\n }\n }\n\n return explicitStaffCommandScope(tenantId, organizationId)\n}\n\nexport function applyScopeToWhere<TEntity extends object>(\n where: FilterQuery<TEntity>,\n scope: StaffCommandScope,\n): FilterQuery<TEntity> {\n const scoped = { ...(where as Record<string, unknown>) }\n if (scope.requireTenant || scope.tenantId !== null) scoped.tenantId = scope.tenantId\n if (scope.requireOrganization || scope.organizationId !== null) scoped.organizationId = scope.organizationId\n return scoped as FilterQuery<TEntity>\n}\n\nexport function scopeForDecryption(scope: StaffCommandScope): { tenantId: string | null; organizationId: string | null } {\n return { tenantId: scope.tenantId, organizationId: scope.organizationId }\n}\n\nexport async function requireTeamMember(\n em: EntityManager,\n memberId: string,\n scope: StaffCommandScope,\n message = 'Team member not found',\n): Promise<StaffTeamMember> {\n const member = await em.findOne(\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: memberId, deletedAt: null }, scope),\n )\n if (!member) throw new CrudHttpError(404, { error: message })\n return member\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,qBAAqB;AAC9B,SAAS,yBAAyB,yBAAyB;AAC3D,SAAS,0BAA0B;AAEnC,SAAS,uBAAuB;AAWzB,SAAS,kBAAkB,KAA+C;AAC/E,QAAM,oBAAoB,IAAI,MAAM,iBAAiB,QAAQ,IAAI,gBAAgB;AACjF,QAAM,WAAW,oBAAoB,OAAQ,IAAI,MAAM,YAAY,IAAI,mBAAmB,YAAY;AACtG,QAAM,iBAAiB,oBAAoB,OAAQ,IAAI,0BAA0B,IAAI,MAAM,SAAS;AACpG,QAAM,2BACJ,qBAAsB,mBAAmB,QAAQ,aAAa,QAAQ,IAAI,mBAAmB,eAAe;AAC9G,SAAO;AAAA,IACL;AAAA,IACA,gBAAgB,2BAA2B,OAAO;AAAA,IAClD,eAAe,CAAC;AAAA,IAChB,qBAAqB,CAAC;AAAA,EACxB;AACF;AAEO,SAAS,0BAA0B,UAAyB,gBAAkD;AACnH,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,qBAAqB;AAAA,EACvB;AACF;AAEO,SAAS,kBAAkB,KAA4B,UAAkB,gBAA2C;AACzH,MAAI,IAAI,MAAM,iBAAiB,QAAQ,IAAI,gBAAgB,MAAM;AAC/D,WAAO,0BAA0B,UAAU,cAAc;AAAA,EAC3D;AAEA,oBAAkB,KAAK,QAAQ;AAC/B,0BAAwB,KAAK,cAAc;AAE3C,QAAM,gBAAgB,IAAI,MAAM,YAAY,IAAI,mBAAmB,YAAY;AAC/E,MAAI,CAAC,iBAAiB,kBAAkB,UAAU;AAChD,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,EACrD;AAEA,MAAI,CAAC,IAAI,mBAAmB;AAC1B,UAAM,wBAAwB,IAAI,0BAA0B,IAAI,MAAM,SAAS;AAC/E,QAAI,CAAC,yBAAyB,0BAA0B,gBAAgB;AACtE,YAAM,IAAI,cAAc,KAAK,EAAE,OAAO,YAAY,CAAC;AAAA,IACrD;AAAA,EACF;AAEA,SAAO,0BAA0B,UAAU,cAAc;AAC3D;AAEO,SAAS,kBACd,OACA,OACsB;AACtB,QAAM,SAAS,EAAE,GAAI,MAAkC;AACvD,MAAI,MAAM,iBAAiB,MAAM,aAAa,KAAM,QAAO,WAAW,MAAM;AAC5E,MAAI,MAAM,uBAAuB,MAAM,mBAAmB,KAAM,QAAO,iBAAiB,MAAM;AAC9F,SAAO;AACT;AAEO,SAAS,mBAAmB,OAAsF;AACvH,SAAO,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe;AAC1E;AAEA,eAAsB,kBACpB,IACA,UACA,OACA,UAAU,yBACgB;AAC1B,QAAM,SAAS,MAAM,GAAG;AAAA,IACtB;AAAA,IACA,kBAAmC,EAAE,IAAI,UAAU,WAAW,KAAK,GAAG,KAAK;AAAA,EAC7E;AACA,MAAI,CAAC,OAAQ,OAAM,IAAI,cAAc,KAAK,EAAE,OAAO,QAAQ,CAAC;AAC5D,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,7 +8,15 @@ import {
|
|
|
8
8
|
staffTeamMemberTagAssignmentSchema
|
|
9
9
|
} from "../data/validators.js";
|
|
10
10
|
import { staffTeamMemberCrudEvents } from "../lib/crud.js";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
applyScopeToWhere,
|
|
13
|
+
commandInputScope,
|
|
14
|
+
ensureOrganizationScope,
|
|
15
|
+
ensureTenantScope,
|
|
16
|
+
explicitStaffCommandScope,
|
|
17
|
+
extractUndoPayload,
|
|
18
|
+
scopeForDecryption
|
|
19
|
+
} from "./shared.js";
|
|
12
20
|
function normalizeTagList(values) {
|
|
13
21
|
const set = /* @__PURE__ */ new Set();
|
|
14
22
|
values.forEach((value) => {
|
|
@@ -26,12 +34,13 @@ const assignTeamMemberTagCommand = {
|
|
|
26
34
|
ensureTenantScope(ctx, parsed.tenantId);
|
|
27
35
|
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
28
36
|
const em = ctx.container.resolve("em").fork();
|
|
37
|
+
const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId);
|
|
29
38
|
const member = await findOneWithDecryption(
|
|
30
39
|
em,
|
|
31
40
|
StaffTeamMember,
|
|
32
|
-
{ id: parsed.memberId, deletedAt: null },
|
|
41
|
+
applyScopeToWhere({ id: parsed.memberId, deletedAt: null }, scope),
|
|
33
42
|
void 0,
|
|
34
|
-
|
|
43
|
+
scopeForDecryption(scope)
|
|
35
44
|
);
|
|
36
45
|
if (!member) throw new CrudHttpError(404, { error: "Team member not found." });
|
|
37
46
|
ensureTenantScope(ctx, member.tenantId);
|
|
@@ -111,12 +120,13 @@ const assignTeamMemberTagCommand = {
|
|
|
111
120
|
const before = payload?.before;
|
|
112
121
|
if (!before) return { memberId: logEntry.resourceId ?? "" };
|
|
113
122
|
const em = ctx.container.resolve("em").fork();
|
|
123
|
+
const scope = explicitStaffCommandScope(before.tenantId, before.organizationId);
|
|
114
124
|
const member = await findOneWithDecryption(
|
|
115
125
|
em,
|
|
116
126
|
StaffTeamMember,
|
|
117
|
-
{ id: before.memberId, deletedAt: null },
|
|
127
|
+
applyScopeToWhere({ id: before.memberId, deletedAt: null }, scope),
|
|
118
128
|
void 0,
|
|
119
|
-
|
|
129
|
+
scopeForDecryption(scope)
|
|
120
130
|
);
|
|
121
131
|
if (!member) throw new CrudHttpError(404, { error: "Team member not found." });
|
|
122
132
|
const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : []);
|
|
@@ -148,12 +158,13 @@ const unassignTeamMemberTagCommand = {
|
|
|
148
158
|
ensureTenantScope(ctx, parsed.tenantId);
|
|
149
159
|
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
150
160
|
const em = ctx.container.resolve("em").fork();
|
|
161
|
+
const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId);
|
|
151
162
|
const member = await findOneWithDecryption(
|
|
152
163
|
em,
|
|
153
164
|
StaffTeamMember,
|
|
154
|
-
{ id: parsed.memberId, deletedAt: null },
|
|
165
|
+
applyScopeToWhere({ id: parsed.memberId, deletedAt: null }, scope),
|
|
155
166
|
void 0,
|
|
156
|
-
|
|
167
|
+
scopeForDecryption(scope)
|
|
157
168
|
);
|
|
158
169
|
if (!member) throw new CrudHttpError(404, { error: "Team member not found." });
|
|
159
170
|
ensureTenantScope(ctx, member.tenantId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/tag-assignments.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { StaffTeamMember } from '../data/entities'\nimport {\n staffTeamMemberTagAssignmentSchema,\n type StaffTeamMemberTagAssignmentInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\n\ntype TeamMemberTagAssignmentSnapshot = {\n tag: string\n memberId: string\n tenantId: string\n organizationId: string\n}\n\ntype TeamMemberTagAssignmentUndoPayload = {\n before?: TeamMemberTagAssignmentSnapshot | null\n}\n\nfunction normalizeTagList(values: Array<string | null | undefined>): string[] {\n const set = new Set<string>()\n values.forEach((value) => {\n if (typeof value !== 'string') return\n const trimmed = value.trim()\n if (trimmed.length > 0) set.add(trimmed)\n })\n return Array.from(set)\n}\n\nconst assignTeamMemberTagCommand: CommandHandler<StaffTeamMemberTagAssignmentInput, { memberId: string }> = {\n id: 'staff.team-members.tags.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberTagAssignmentSchema.parse(rawInput)\n const tagValue = parsed.tag.trim()\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: parsed.memberId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (currentTags.includes(tagValue)) {\n throw new CrudHttpError(409, { error: 'Tag already assigned.' })\n }\n member.tags = normalizeTagList([...currentTags, tagValue])\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ input }) => {\n const { translate } = await resolveTranslations()\n const parsed = staffTeamMemberTagAssignmentSchema.parse(input)\n return {\n actionLabel: translate('staff.audit.teamMembers.tags.assign', 'Assign team member tag'),\n resourceKind: 'staff.teamMemberTagAssignment',\n resourceId: parsed.memberId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n payload: {\n undo: {\n before: {\n tag: parsed.tag.trim(),\n memberId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies TeamMemberTagAssignmentSnapshot,\n } satisfies TeamMemberTagAssignmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.memberId })\n if (!member) return\n const nextTags = normalizeTagList(\n Array.isArray(member.tags) ? member.tags.filter((tag) => tag !== before.tag) : [],\n )\n member.tags = nextTags\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return { memberId: logEntry.resourceId ?? '' }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: before.memberId, deletedAt: null },\n undefined,\n { tenantId: before.tenantId, organizationId: before.organizationId },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (!currentTags.includes(before.tag)) {\n member.tags = normalizeTagList([...currentTags, before.tag])\n member.updatedAt = new Date()\n await em.flush()\n }\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n}\n\nconst unassignTeamMemberTagCommand: CommandHandler<StaffTeamMemberTagAssignmentInput, { memberId: string }> = {\n id: 'staff.team-members.tags.unassign',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberTagAssignmentSchema.parse(rawInput)\n const tagValue = parsed.tag.trim()\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: parsed.memberId, deletedAt: null },\n undefined,\n { tenantId: parsed.tenantId, organizationId: parsed.organizationId },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (!currentTags.includes(tagValue)) {\n throw new CrudHttpError(404, { error: 'Tag assignment not found.' })\n }\n member.tags = normalizeTagList(currentTags.filter((tag) => tag !== tagValue))\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ input }) => {\n const { translate } = await resolveTranslations()\n const parsed = staffTeamMemberTagAssignmentSchema.parse(input)\n return {\n actionLabel: translate('staff.audit.teamMembers.tags.unassign', 'Unassign team member tag'),\n resourceKind: 'staff.teamMemberTagAssignment',\n resourceId: parsed.memberId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n payload: {\n undo: {\n before: {\n tag: parsed.tag.trim(),\n memberId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies TeamMemberTagAssignmentSnapshot,\n } satisfies TeamMemberTagAssignmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.memberId })\n if (!member) return\n const currentTags = Array.isArray(member.tags) ? member.tags : []\n if (!currentTags.includes(before.tag)) {\n member.tags = normalizeTagList([...currentTags, before.tag])\n member.updatedAt = new Date()\n await em.flush()\n }\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n },\n}\n\nregisterCommand(assignTeamMemberTagCommand)\nregisterCommand(unassignTeamMemberTagCommand)\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,uBAAuB;AAEhC,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,qBAAqB,+BAA+B;AAE7D,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,OAEK;AACP,SAAS,iCAAiC;AAC1C,
|
|
4
|
+
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { StaffTeamMember } from '../data/entities'\nimport {\n staffTeamMemberTagAssignmentSchema,\n type StaffTeamMemberTagAssignmentInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n explicitStaffCommandScope,\n extractUndoPayload,\n scopeForDecryption,\n} from './shared'\n\ntype TeamMemberTagAssignmentSnapshot = {\n tag: string\n memberId: string\n tenantId: string\n organizationId: string\n}\n\ntype TeamMemberTagAssignmentUndoPayload = {\n before?: TeamMemberTagAssignmentSnapshot | null\n}\n\nfunction normalizeTagList(values: Array<string | null | undefined>): string[] {\n const set = new Set<string>()\n values.forEach((value) => {\n if (typeof value !== 'string') return\n const trimmed = value.trim()\n if (trimmed.length > 0) set.add(trimmed)\n })\n return Array.from(set)\n}\n\nconst assignTeamMemberTagCommand: CommandHandler<StaffTeamMemberTagAssignmentInput, { memberId: string }> = {\n id: 'staff.team-members.tags.assign',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberTagAssignmentSchema.parse(rawInput)\n const tagValue = parsed.tag.trim()\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.memberId, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (currentTags.includes(tagValue)) {\n throw new CrudHttpError(409, { error: 'Tag already assigned.' })\n }\n member.tags = normalizeTagList([...currentTags, tagValue])\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ input }) => {\n const { translate } = await resolveTranslations()\n const parsed = staffTeamMemberTagAssignmentSchema.parse(input)\n return {\n actionLabel: translate('staff.audit.teamMembers.tags.assign', 'Assign team member tag'),\n resourceKind: 'staff.teamMemberTagAssignment',\n resourceId: parsed.memberId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n payload: {\n undo: {\n before: {\n tag: parsed.tag.trim(),\n memberId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies TeamMemberTagAssignmentSnapshot,\n } satisfies TeamMemberTagAssignmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.memberId })\n if (!member) return\n const nextTags = normalizeTagList(\n Array.isArray(member.tags) ? member.tags.filter((tag) => tag !== before.tag) : [],\n )\n member.tags = nextTags\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return { memberId: logEntry.resourceId ?? '' }\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = explicitStaffCommandScope(before.tenantId, before.organizationId)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: before.memberId, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (!currentTags.includes(before.tag)) {\n member.tags = normalizeTagList([...currentTags, before.tag])\n member.updatedAt = new Date()\n await em.flush()\n }\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n}\n\nconst unassignTeamMemberTagCommand: CommandHandler<StaffTeamMemberTagAssignmentInput, { memberId: string }> = {\n id: 'staff.team-members.tags.unassign',\n async execute(rawInput, ctx) {\n const parsed = staffTeamMemberTagAssignmentSchema.parse(rawInput)\n const tagValue = parsed.tag.trim()\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.memberId, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n const currentTags = normalizeTagList(Array.isArray(member.tags) ? member.tags : [])\n if (!currentTags.includes(tagValue)) {\n throw new CrudHttpError(404, { error: 'Tag assignment not found.' })\n }\n member.tags = normalizeTagList(currentTags.filter((tag) => tag !== tagValue))\n member.updatedAt = new Date()\n await em.flush()\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ input }) => {\n const { translate } = await resolveTranslations()\n const parsed = staffTeamMemberTagAssignmentSchema.parse(input)\n return {\n actionLabel: translate('staff.audit.teamMembers.tags.unassign', 'Unassign team member tag'),\n resourceKind: 'staff.teamMemberTagAssignment',\n resourceId: parsed.memberId,\n parentResourceKind: 'staff.teamMember',\n parentResourceId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n payload: {\n undo: {\n before: {\n tag: parsed.tag.trim(),\n memberId: parsed.memberId,\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n } satisfies TeamMemberTagAssignmentSnapshot,\n } satisfies TeamMemberTagAssignmentUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberTagAssignmentUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.memberId })\n if (!member) return\n const currentTags = Array.isArray(member.tags) ? member.tags : []\n if (!currentTags.includes(before.tag)) {\n member.tags = normalizeTagList([...currentTags, before.tag])\n member.updatedAt = new Date()\n await em.flush()\n }\n\n const dataEngine = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n },\n events: staffTeamMemberCrudEvents,\n })\n },\n}\n\nregisterCommand(assignTeamMemberTagCommand)\nregisterCommand(unassignTeamMemberTagCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -13,7 +13,15 @@ import {
|
|
|
13
13
|
staffTeamMemberUpdateSchema
|
|
14
14
|
} from "../data/validators.js";
|
|
15
15
|
import { staffTeamMemberCrudEvents } from "../lib/crud.js";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
applyScopeToWhere,
|
|
18
|
+
commandActorScope,
|
|
19
|
+
commandInputScope,
|
|
20
|
+
ensureOrganizationScope,
|
|
21
|
+
ensureTenantScope,
|
|
22
|
+
extractUndoPayload,
|
|
23
|
+
scopeForDecryption
|
|
24
|
+
} from "./shared.js";
|
|
17
25
|
import { E } from "../../../generated/entities.ids.generated.js";
|
|
18
26
|
const teamMemberCrudIndexer = {
|
|
19
27
|
entityType: E.staff.staff_team_member
|
|
@@ -125,6 +133,7 @@ const createTeamMemberCommand = {
|
|
|
125
133
|
const { parsed, custom } = parseWithCustomFields(staffTeamMemberCreateSchema, rawInput);
|
|
126
134
|
ensureTenantScope(ctx, parsed.tenantId);
|
|
127
135
|
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
136
|
+
commandInputScope(ctx, parsed.tenantId, parsed.organizationId);
|
|
128
137
|
const em = ctx.container.resolve("em").fork();
|
|
129
138
|
const roleIds = normalizeStringList(parsed.roleIds);
|
|
130
139
|
const tags = normalizeStringList(parsed.tags);
|
|
@@ -258,12 +267,13 @@ const updateTeamMemberCommand = {
|
|
|
258
267
|
async execute(rawInput, ctx) {
|
|
259
268
|
const { parsed, custom } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput);
|
|
260
269
|
const em = ctx.container.resolve("em").fork();
|
|
270
|
+
const scope = commandActorScope(ctx);
|
|
261
271
|
const member = await findOneWithDecryption(
|
|
262
272
|
em,
|
|
263
273
|
StaffTeamMember,
|
|
264
|
-
{ id: parsed.id, deletedAt: null },
|
|
274
|
+
applyScopeToWhere({ id: parsed.id, deletedAt: null }, scope),
|
|
265
275
|
void 0,
|
|
266
|
-
|
|
276
|
+
scopeForDecryption(scope)
|
|
267
277
|
);
|
|
268
278
|
if (!member) throw new CrudHttpError(404, { error: "Team member not found." });
|
|
269
279
|
ensureTenantScope(ctx, member.tenantId);
|
|
@@ -415,12 +425,13 @@ const deleteTeamMemberCommand = {
|
|
|
415
425
|
const id = input?.id;
|
|
416
426
|
if (!id) throw new CrudHttpError(400, { error: "Member id is required." });
|
|
417
427
|
const em = ctx.container.resolve("em").fork();
|
|
428
|
+
const scope = commandActorScope(ctx);
|
|
418
429
|
const member = await findOneWithDecryption(
|
|
419
430
|
em,
|
|
420
431
|
StaffTeamMember,
|
|
421
|
-
{ id, deletedAt: null },
|
|
432
|
+
applyScopeToWhere({ id, deletedAt: null }, scope),
|
|
422
433
|
void 0,
|
|
423
|
-
|
|
434
|
+
scopeForDecryption(scope)
|
|
424
435
|
);
|
|
425
436
|
if (!member) throw new CrudHttpError(404, { error: "Team member not found." });
|
|
426
437
|
ensureTenantScope(ctx, member.tenantId);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/team-members.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { buildCustomFieldResetMap, diffCustomFieldChanges, loadCustomFieldSnapshot, type CustomFieldSnapshot } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { StaffTeam, StaffTeamMember, StaffTeamRole } from '../data/entities'\nimport {\n staffTeamMemberCreateSchema,\n staffTeamMemberUpdateSchema,\n type StaffTeamMemberCreateInput,\n type StaffTeamMemberUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst teamMemberCrudIndexer: CrudIndexerConfig<StaffTeamMember> = {\n entityType: E.staff.staff_team_member,\n}\n\ntype TeamMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n teamId: string | null\n displayName: string\n description: string | null\n userId: string | null\n roleIds: string[]\n tags: string[]\n isActive: boolean\n deletedAt: string | null\n}\n\ntype TeamMemberUndoPayload = {\n before?: TeamMemberSnapshot | null\n after?: TeamMemberSnapshot | null\n customBefore?: CustomFieldSnapshot | null\n customAfter?: CustomFieldSnapshot | null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const set = new Set<string>()\n value.forEach((entry) => {\n if (typeof entry === 'string') {\n const trimmed = entry.trim()\n if (trimmed.length) set.add(trimmed)\n }\n })\n return Array.from(set)\n}\n\nasync function loadTeamMemberSnapshot(em: EntityManager, id: string): Promise<TeamMemberSnapshot | null> {\n const member = await findOneWithDecryption(em, StaffTeamMember, { id }, undefined, { tenantId: null, organizationId: null })\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n teamId: member.teamId ?? null,\n displayName: member.displayName,\n description: member.description ?? null,\n userId: member.userId ?? null,\n roleIds: Array.isArray(member.roleIds) ? member.roleIds : [],\n tags: Array.isArray(member.tags) ? member.tags : [],\n isActive: member.isActive ?? true,\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTeamMemberCustomSnapshot(\n em: EntityManager,\n snapshot: TeamMemberSnapshot,\n): Promise<CustomFieldSnapshot> {\n return loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member,\n recordId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n}\n\nfunction teamMemberSeedFromSnapshot(snapshot: TeamMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n teamId: snapshot.teamId ?? null,\n displayName: snapshot.displayName,\n description: snapshot.description ?? null,\n userId: snapshot.userId ?? null,\n roleIds: Array.isArray(snapshot.roleIds) ? snapshot.roleIds : [],\n tags: Array.isArray(snapshot.tags) ? snapshot.tags : [],\n availabilityRuleSetId: null,\n isActive: snapshot.isActive,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst redoTeamMemberCreate = makeCreateRedo<StaffTeamMember, TeamMemberSnapshot, StaffTeamMemberCreateInput, { memberId: string }>({\n entityClass: StaffTeamMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: teamMemberSeedFromSnapshot,\n buildResult: (entity) => ({ memberId: entity.id }),\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n})\n\nasync function ensureRolesExist(em: EntityManager, roleIds: string[], tenantId: string, organizationId: string): Promise<void> {\n if (!roleIds.length) return\n const roles = await findWithDecryption(\n em,\n StaffTeamRole,\n { id: { $in: roleIds }, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (roles.length !== roleIds.length) {\n throw new CrudHttpError(400, { error: 'One or more team roles were not found.' })\n }\n}\n\nasync function ensureUserExists(em: EntityManager, userId: string, tenantId: string, organizationId: string): Promise<void> {\n const user = await findOneWithDecryption(\n em,\n User,\n { id: userId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!user) throw new CrudHttpError(400, { error: 'User not found.' })\n if (user.tenantId && user.tenantId !== tenantId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this tenant.' })\n }\n if (user.organizationId && user.organizationId !== organizationId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this organization.' })\n }\n}\n\nasync function ensureTeamExists(em: EntityManager, teamId: string, tenantId: string, organizationId: string): Promise<void> {\n const team = await findOneWithDecryption(\n em,\n StaffTeam,\n { id: teamId, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!team) throw new CrudHttpError(400, { error: 'Team not found.' })\n}\n\nconst createTeamMemberCommand: CommandHandler<StaffTeamMemberCreateInput, { memberId: string }> = {\n id: 'staff.team-members.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roleIds = normalizeStringList(parsed.roleIds)\n const tags = normalizeStringList(parsed.tags)\n if (parsed.userId) {\n await ensureUserExists(em, parsed.userId, parsed.tenantId, parsed.organizationId)\n }\n if (parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, parsed.tenantId, parsed.organizationId)\n }\n await ensureRolesExist(em, roleIds, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const member = em.create(StaffTeamMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n teamId: parsed.teamId ?? null,\n displayName: parsed.displayName,\n description: parsed.description ?? null,\n userId: parsed.userId ?? null,\n roleIds,\n tags,\n availabilityRuleSetId: parsed.availabilityRuleSetId ?? null,\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { snapshot, custom }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.create', 'Create team member'),\n resourceKind: 'staff.teamMember',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n customAfter: custom,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: after.id })\n if (member) {\n member.deletedAt = 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: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const result = await redoTeamMemberCreate({ input: undefined as unknown as StaffTeamMemberCreateInput, ctx, logEntry })\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const customAfter = payload?.customAfter\n if (customAfter && Object.keys(customAfter).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine') as DataEngine,\n entityId: E.staff.staff_team_member,\n recordId: result.memberId,\n tenantId: payload?.after?.tenantId ?? '',\n organizationId: payload?.after?.organizationId ?? '',\n values: customAfter,\n })\n }\n return result\n },\n}\n\nconst updateTeamMemberCommand: CommandHandler<StaffTeamMemberUpdateInput, { memberId: string; updatedAt: string | null }> = {\n id: 'staff.team-members.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, parsed.id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: parsed.id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n // Resolve validation queries BEFORE mutating scalars: `ensure*` runs `em.find`,\n // which would otherwise reset unit-of-work tracking between mutations and the\n // flush and silently drop earlier scalar changes (SPEC-018 Problem 1).\n if (parsed.userId !== undefined && parsed.userId) {\n await ensureUserExists(em, parsed.userId, member.tenantId, member.organizationId)\n }\n if (parsed.teamId !== undefined && parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, member.tenantId, member.organizationId)\n }\n let nextRoleIds: string[] | undefined\n if (parsed.roleIds !== undefined) {\n nextRoleIds = normalizeStringList(parsed.roleIds)\n await ensureRolesExist(em, nextRoleIds, member.tenantId, member.organizationId)\n }\n\n await withAtomicFlush(em, [\n () => {\n if (parsed.userId !== undefined) member.userId = parsed.userId ?? null\n if (parsed.teamId !== undefined) member.teamId = parsed.teamId ?? null\n if (parsed.roleIds !== undefined) member.roleIds = nextRoleIds ?? []\n if (parsed.tags !== undefined) member.tags = normalizeStringList(parsed.tags)\n if (parsed.availabilityRuleSetId !== undefined) member.availabilityRuleSetId = parsed.availabilityRuleSetId ?? null\n if (parsed.displayName !== undefined) member.displayName = parsed.displayName\n if (parsed.description !== undefined) member.description = parsed.description ?? null\n if (parsed.isActive !== undefined) member.isActive = parsed.isActive\n member.updatedAt = new Date()\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n // Return the freshly-bumped updatedAt so non-CrudForm callers (e.g. the\n // availability schedule switcher) can refresh their optimistic-lock token\n // and not falsely 409 on the next sequential edit (#2848).\n return { memberId: member.id, updatedAt: member.updatedAt ? member.updatedAt.toISOString() : null }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTeamMemberSnapshot(em, before.id)\n if (!after) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const customAfter = await loadTeamMemberCustomSnapshot(em, after)\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'teamId',\n 'displayName',\n 'description',\n 'userId',\n 'roleIds',\n 'tags',\n 'isActive',\n 'deletedAt',\n ])\n const customChanges = diffCustomFieldChanges(customBefore, customAfter)\n if (Object.keys(customChanges).length) {\n changes.customFields = { from: customBefore ?? null, to: customAfter ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.update', 'Update team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n customBefore: customBefore ?? null,\n customAfter,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) return\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = Array.isArray(before.roleIds) ? before.roleIds : []\n member.tags = Array.isArray(before.tags) ? before.tags : []\n member.isActive = before.isActive\n member.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore || payload.customAfter) {\n const reset = buildCustomFieldResetMap(payload.customBefore ?? undefined, payload.customAfter ?? undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nconst deleteTeamMemberCommand: CommandHandler<{ id?: string }, { memberId: string }> = {\n id: 'staff.team-members.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n member.deletedAt = new Date()\n member.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: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.delete', 'Delete team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n customBefore: customBefore ?? null,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) {\n member = em.create(StaffTeamMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n teamId: before.teamId ?? null,\n displayName: before.displayName,\n description: before.description ?? null,\n userId: before.userId ?? null,\n roleIds: before.roleIds ?? [],\n tags: before.tags ?? [],\n isActive: before.isActive,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = before.roleIds ?? []\n member.tags = before.tags ?? []\n member.isActive = before.isActive\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore) {\n const reset = buildCustomFieldResetMap(payload.customBefore, undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTeamMemberCommand)\nregisterCommand(updateTeamMemberCommand)\nregisterCommand(deleteTeamMemberCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { buildCustomFieldResetMap, diffCustomFieldChanges, loadCustomFieldSnapshot, type CustomFieldSnapshot } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { StaffTeam, StaffTeamMember, StaffTeamRole } from '../data/entities'\nimport {\n staffTeamMemberCreateSchema,\n staffTeamMemberUpdateSchema,\n type StaffTeamMemberCreateInput,\n type StaffTeamMemberUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport {\n applyScopeToWhere,\n commandActorScope,\n commandInputScope,\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n scopeForDecryption,\n} from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst teamMemberCrudIndexer: CrudIndexerConfig<StaffTeamMember> = {\n entityType: E.staff.staff_team_member,\n}\n\ntype TeamMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n teamId: string | null\n displayName: string\n description: string | null\n userId: string | null\n roleIds: string[]\n tags: string[]\n isActive: boolean\n deletedAt: string | null\n}\n\ntype TeamMemberUndoPayload = {\n before?: TeamMemberSnapshot | null\n after?: TeamMemberSnapshot | null\n customBefore?: CustomFieldSnapshot | null\n customAfter?: CustomFieldSnapshot | null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const set = new Set<string>()\n value.forEach((entry) => {\n if (typeof entry === 'string') {\n const trimmed = entry.trim()\n if (trimmed.length) set.add(trimmed)\n }\n })\n return Array.from(set)\n}\n\nasync function loadTeamMemberSnapshot(em: EntityManager, id: string): Promise<TeamMemberSnapshot | null> {\n const member = await findOneWithDecryption(em, StaffTeamMember, { id }, undefined, { tenantId: null, organizationId: null })\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n teamId: member.teamId ?? null,\n displayName: member.displayName,\n description: member.description ?? null,\n userId: member.userId ?? null,\n roleIds: Array.isArray(member.roleIds) ? member.roleIds : [],\n tags: Array.isArray(member.tags) ? member.tags : [],\n isActive: member.isActive ?? true,\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTeamMemberCustomSnapshot(\n em: EntityManager,\n snapshot: TeamMemberSnapshot,\n): Promise<CustomFieldSnapshot> {\n return loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member,\n recordId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n}\n\nfunction teamMemberSeedFromSnapshot(snapshot: TeamMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n teamId: snapshot.teamId ?? null,\n displayName: snapshot.displayName,\n description: snapshot.description ?? null,\n userId: snapshot.userId ?? null,\n roleIds: Array.isArray(snapshot.roleIds) ? snapshot.roleIds : [],\n tags: Array.isArray(snapshot.tags) ? snapshot.tags : [],\n availabilityRuleSetId: null,\n isActive: snapshot.isActive,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst redoTeamMemberCreate = makeCreateRedo<StaffTeamMember, TeamMemberSnapshot, StaffTeamMemberCreateInput, { memberId: string }>({\n entityClass: StaffTeamMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: teamMemberSeedFromSnapshot,\n buildResult: (entity) => ({ memberId: entity.id }),\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n})\n\nasync function ensureRolesExist(em: EntityManager, roleIds: string[], tenantId: string, organizationId: string): Promise<void> {\n if (!roleIds.length) return\n const roles = await findWithDecryption(\n em,\n StaffTeamRole,\n { id: { $in: roleIds }, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (roles.length !== roleIds.length) {\n throw new CrudHttpError(400, { error: 'One or more team roles were not found.' })\n }\n}\n\nasync function ensureUserExists(em: EntityManager, userId: string, tenantId: string, organizationId: string): Promise<void> {\n const user = await findOneWithDecryption(\n em,\n User,\n { id: userId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!user) throw new CrudHttpError(400, { error: 'User not found.' })\n if (user.tenantId && user.tenantId !== tenantId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this tenant.' })\n }\n if (user.organizationId && user.organizationId !== organizationId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this organization.' })\n }\n}\n\nasync function ensureTeamExists(em: EntityManager, teamId: string, tenantId: string, organizationId: string): Promise<void> {\n const team = await findOneWithDecryption(\n em,\n StaffTeam,\n { id: teamId, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!team) throw new CrudHttpError(400, { error: 'Team not found.' })\n}\n\nconst createTeamMemberCommand: CommandHandler<StaffTeamMemberCreateInput, { memberId: string }> = {\n id: 'staff.team-members.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n commandInputScope(ctx, parsed.tenantId, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roleIds = normalizeStringList(parsed.roleIds)\n const tags = normalizeStringList(parsed.tags)\n if (parsed.userId) {\n await ensureUserExists(em, parsed.userId, parsed.tenantId, parsed.organizationId)\n }\n if (parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, parsed.tenantId, parsed.organizationId)\n }\n await ensureRolesExist(em, roleIds, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const member = em.create(StaffTeamMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n teamId: parsed.teamId ?? null,\n displayName: parsed.displayName,\n description: parsed.description ?? null,\n userId: parsed.userId ?? null,\n roleIds,\n tags,\n availabilityRuleSetId: parsed.availabilityRuleSetId ?? null,\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { snapshot, custom }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.create', 'Create team member'),\n resourceKind: 'staff.teamMember',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n customAfter: custom,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: after.id })\n if (member) {\n member.deletedAt = 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: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const result = await redoTeamMemberCreate({ input: undefined as unknown as StaffTeamMemberCreateInput, ctx, logEntry })\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const customAfter = payload?.customAfter\n if (customAfter && Object.keys(customAfter).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine') as DataEngine,\n entityId: E.staff.staff_team_member,\n recordId: result.memberId,\n tenantId: payload?.after?.tenantId ?? '',\n organizationId: payload?.after?.organizationId ?? '',\n values: customAfter,\n })\n }\n return result\n },\n}\n\nconst updateTeamMemberCommand: CommandHandler<StaffTeamMemberUpdateInput, { memberId: string; updatedAt: string | null }> = {\n id: 'staff.team-members.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, parsed.id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id: parsed.id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n // Resolve validation queries BEFORE mutating scalars: `ensure*` runs `em.find`,\n // which would otherwise reset unit-of-work tracking between mutations and the\n // flush and silently drop earlier scalar changes (SPEC-018 Problem 1).\n if (parsed.userId !== undefined && parsed.userId) {\n await ensureUserExists(em, parsed.userId, member.tenantId, member.organizationId)\n }\n if (parsed.teamId !== undefined && parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, member.tenantId, member.organizationId)\n }\n let nextRoleIds: string[] | undefined\n if (parsed.roleIds !== undefined) {\n nextRoleIds = normalizeStringList(parsed.roleIds)\n await ensureRolesExist(em, nextRoleIds, member.tenantId, member.organizationId)\n }\n\n await withAtomicFlush(em, [\n () => {\n if (parsed.userId !== undefined) member.userId = parsed.userId ?? null\n if (parsed.teamId !== undefined) member.teamId = parsed.teamId ?? null\n if (parsed.roleIds !== undefined) member.roleIds = nextRoleIds ?? []\n if (parsed.tags !== undefined) member.tags = normalizeStringList(parsed.tags)\n if (parsed.availabilityRuleSetId !== undefined) member.availabilityRuleSetId = parsed.availabilityRuleSetId ?? null\n if (parsed.displayName !== undefined) member.displayName = parsed.displayName\n if (parsed.description !== undefined) member.description = parsed.description ?? null\n if (parsed.isActive !== undefined) member.isActive = parsed.isActive\n member.updatedAt = new Date()\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n // Return the freshly-bumped updatedAt so non-CrudForm callers (e.g. the\n // availability schedule switcher) can refresh their optimistic-lock token\n // and not falsely 409 on the next sequential edit (#2848).\n return { memberId: member.id, updatedAt: member.updatedAt ? member.updatedAt.toISOString() : null }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTeamMemberSnapshot(em, before.id)\n if (!after) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const customAfter = await loadTeamMemberCustomSnapshot(em, after)\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'teamId',\n 'displayName',\n 'description',\n 'userId',\n 'roleIds',\n 'tags',\n 'isActive',\n 'deletedAt',\n ])\n const customChanges = diffCustomFieldChanges(customBefore, customAfter)\n if (Object.keys(customChanges).length) {\n changes.customFields = { from: customBefore ?? null, to: customAfter ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.update', 'Update team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n customBefore: customBefore ?? null,\n customAfter,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) return\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = Array.isArray(before.roleIds) ? before.roleIds : []\n member.tags = Array.isArray(before.tags) ? before.tags : []\n member.isActive = before.isActive\n member.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore || payload.customAfter) {\n const reset = buildCustomFieldResetMap(payload.customBefore ?? undefined, payload.customAfter ?? undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nconst deleteTeamMemberCommand: CommandHandler<{ id?: string }, { memberId: string }> = {\n id: 'staff.team-members.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const scope = commandActorScope(ctx)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n applyScopeToWhere<StaffTeamMember>({ id, deletedAt: null }, scope),\n undefined,\n scopeForDecryption(scope),\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n member.deletedAt = new Date()\n member.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: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.delete', 'Delete team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n customBefore: customBefore ?? null,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) {\n member = em.create(StaffTeamMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n teamId: before.teamId ?? null,\n displayName: before.displayName,\n description: before.description ?? null,\n userId: before.userId ?? null,\n roleIds: before.roleIds ?? [],\n tags: before.tags ?? [],\n isActive: before.isActive,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = before.roleIds ?? []\n member.tags = before.tags ?? []\n member.isActive = before.isActive\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore) {\n const reset = buildCustomFieldResetMap(payload.customBefore, undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTeamMemberCommand)\nregisterCommand(updateTeamMemberCommand)\nregisterCommand(deleteTeamMemberCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -11,7 +11,15 @@ import {
|
|
|
11
11
|
staffTeamRoleUpdateSchema
|
|
12
12
|
} from "../data/validators.js";
|
|
13
13
|
import { staffTeamRoleCrudEvents } from "../lib/crud.js";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
applyScopeToWhere,
|
|
16
|
+
commandActorScope,
|
|
17
|
+
commandInputScope,
|
|
18
|
+
ensureOrganizationScope,
|
|
19
|
+
ensureTenantScope,
|
|
20
|
+
extractUndoPayload,
|
|
21
|
+
scopeForDecryption
|
|
22
|
+
} from "./shared.js";
|
|
15
23
|
import { E } from "../../../generated/entities.ids.generated.js";
|
|
16
24
|
const teamRoleCrudIndexer = {
|
|
17
25
|
entityType: E.staff.staff_team_role
|
|
@@ -61,6 +69,7 @@ const createTeamRoleCommand = {
|
|
|
61
69
|
const { parsed, custom } = parseWithCustomFields(staffTeamRoleCreateSchema, rawInput);
|
|
62
70
|
ensureTenantScope(ctx, parsed.tenantId);
|
|
63
71
|
ensureOrganizationScope(ctx, parsed.organizationId);
|
|
72
|
+
commandInputScope(ctx, parsed.tenantId, parsed.organizationId);
|
|
64
73
|
const em = ctx.container.resolve("em").fork();
|
|
65
74
|
if (parsed.teamId) {
|
|
66
75
|
await ensureTeamExists(em, parsed.teamId, parsed.tenantId, parsed.organizationId);
|
|
@@ -185,12 +194,13 @@ const updateTeamRoleCommand = {
|
|
|
185
194
|
async execute(rawInput, ctx) {
|
|
186
195
|
const { parsed, custom } = parseWithCustomFields(staffTeamRoleUpdateSchema, rawInput);
|
|
187
196
|
const em = ctx.container.resolve("em").fork();
|
|
197
|
+
const scope = commandActorScope(ctx);
|
|
188
198
|
const role = await findOneWithDecryption(
|
|
189
199
|
em,
|
|
190
200
|
StaffTeamRole,
|
|
191
|
-
{ id: parsed.id, deletedAt: null },
|
|
201
|
+
applyScopeToWhere({ id: parsed.id, deletedAt: null }, scope),
|
|
192
202
|
void 0,
|
|
193
|
-
|
|
203
|
+
scopeForDecryption(scope)
|
|
194
204
|
);
|
|
195
205
|
if (!role) throw new CrudHttpError(404, { error: "Team role not found." });
|
|
196
206
|
ensureTenantScope(ctx, role.tenantId);
|
|
@@ -326,12 +336,13 @@ const deleteTeamRoleCommand = {
|
|
|
326
336
|
const id = input?.id;
|
|
327
337
|
if (!id) throw new CrudHttpError(400, { error: "Role id is required." });
|
|
328
338
|
const em = ctx.container.resolve("em").fork();
|
|
339
|
+
const scope = commandActorScope(ctx);
|
|
329
340
|
const role = await findOneWithDecryption(
|
|
330
341
|
em,
|
|
331
342
|
StaffTeamRole,
|
|
332
|
-
{ id, deletedAt: null },
|
|
343
|
+
applyScopeToWhere({ id, deletedAt: null }, scope),
|
|
333
344
|
void 0,
|
|
334
|
-
|
|
345
|
+
scopeForDecryption(scope)
|
|
335
346
|
);
|
|
336
347
|
if (!role) throw new CrudHttpError(404, { error: "Team role not found." });
|
|
337
348
|
ensureTenantScope(ctx, role.tenantId);
|