@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
|
@@ -49,6 +49,29 @@ function applyScopeToWhere(where, scope) {
|
|
|
49
49
|
function scopeForDecryption(scope) {
|
|
50
50
|
return { tenantId: scope.tenantId, organizationId: scope.organizationId };
|
|
51
51
|
}
|
|
52
|
+
const NULL_DECRYPTION_SCOPE = { tenantId: null, organizationId: null };
|
|
53
|
+
function staffSnapshotScopeFromContext(ctx) {
|
|
54
|
+
const tenantId = ctx.auth?.tenantId ?? null;
|
|
55
|
+
if (!tenantId) return null;
|
|
56
|
+
return { tenantId };
|
|
57
|
+
}
|
|
58
|
+
function staffSnapshotScopeFromSnapshot(source) {
|
|
59
|
+
if (!source?.tenantId || !source.organizationId) return null;
|
|
60
|
+
return { tenantId: source.tenantId, organizationId: source.organizationId };
|
|
61
|
+
}
|
|
62
|
+
function scopedStaffSnapshotWhere(id, scope) {
|
|
63
|
+
const where = { id };
|
|
64
|
+
if (scope?.tenantId) where.tenantId = scope.tenantId;
|
|
65
|
+
if (scope?.organizationId) where.organizationId = scope.organizationId;
|
|
66
|
+
return where;
|
|
67
|
+
}
|
|
68
|
+
function staffSnapshotDecryptionScope(scope) {
|
|
69
|
+
if (!scope) return NULL_DECRYPTION_SCOPE;
|
|
70
|
+
return {
|
|
71
|
+
tenantId: scope.tenantId ?? null,
|
|
72
|
+
organizationId: scope.organizationId ?? null
|
|
73
|
+
};
|
|
74
|
+
}
|
|
52
75
|
async function requireTeamMember(em, memberId, scope, message = "Team member not found") {
|
|
53
76
|
const member = await em.findOne(
|
|
54
77
|
StaffTeamMember,
|
|
@@ -66,6 +89,10 @@ export {
|
|
|
66
89
|
explicitStaffCommandScope,
|
|
67
90
|
extractUndoPayload,
|
|
68
91
|
requireTeamMember,
|
|
69
|
-
scopeForDecryption
|
|
92
|
+
scopeForDecryption,
|
|
93
|
+
scopedStaffSnapshotWhere,
|
|
94
|
+
staffSnapshotDecryptionScope,
|
|
95
|
+
staffSnapshotScopeFromContext,
|
|
96
|
+
staffSnapshotScopeFromSnapshot
|
|
70
97
|
};
|
|
71
98
|
//# sourceMappingURL=shared.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/shared.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { 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": "AACA,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;",
|
|
4
|
+
"sourcesContent": ["import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { 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 type StaffSnapshotScope = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\ntype StaffSnapshotScopeSource = {\n tenantId?: string | null\n organizationId?: string | null\n}\n\nconst NULL_DECRYPTION_SCOPE = { tenantId: null, organizationId: null } as const\n\nexport function staffSnapshotScopeFromContext(ctx: CommandRuntimeContext): StaffSnapshotScope | null {\n const tenantId = ctx.auth?.tenantId ?? null\n if (!tenantId) return null\n return { tenantId }\n}\n\nexport function staffSnapshotScopeFromSnapshot(source: StaffSnapshotScopeSource | null | undefined): StaffSnapshotScope | null {\n if (!source?.tenantId || !source.organizationId) return null\n return { tenantId: source.tenantId, organizationId: source.organizationId }\n}\n\nexport function scopedStaffSnapshotWhere(id: string, scope?: StaffSnapshotScope | null) {\n const where: { id: string; tenantId?: string; organizationId?: string } = { id }\n if (scope?.tenantId) where.tenantId = scope.tenantId\n if (scope?.organizationId) where.organizationId = scope.organizationId\n return where\n}\n\nexport function staffSnapshotDecryptionScope(scope?: StaffSnapshotScope | null) {\n if (!scope) return NULL_DECRYPTION_SCOPE\n return {\n tenantId: scope.tenantId ?? null,\n organizationId: scope.organizationId ?? null,\n }\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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
ensureTenantScope,
|
|
16
16
|
explicitStaffCommandScope,
|
|
17
17
|
extractUndoPayload,
|
|
18
|
-
scopeForDecryption
|
|
18
|
+
scopeForDecryption,
|
|
19
|
+
scopedStaffSnapshotWhere,
|
|
20
|
+
staffSnapshotDecryptionScope,
|
|
21
|
+
staffSnapshotScopeFromSnapshot
|
|
19
22
|
} from "./shared.js";
|
|
20
23
|
function normalizeTagList(values) {
|
|
21
24
|
const set = /* @__PURE__ */ new Set();
|
|
@@ -94,7 +97,14 @@ const assignTeamMemberTagCommand = {
|
|
|
94
97
|
const before = payload?.before;
|
|
95
98
|
if (!before) return;
|
|
96
99
|
const em = ctx.container.resolve("em").fork();
|
|
97
|
-
const
|
|
100
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
101
|
+
const member = await findOneWithDecryption(
|
|
102
|
+
em,
|
|
103
|
+
StaffTeamMember,
|
|
104
|
+
scopedStaffSnapshotWhere(before.memberId, snapshotScope),
|
|
105
|
+
void 0,
|
|
106
|
+
staffSnapshotDecryptionScope(snapshotScope)
|
|
107
|
+
);
|
|
98
108
|
if (!member) return;
|
|
99
109
|
const nextTags = normalizeTagList(
|
|
100
110
|
Array.isArray(member.tags) ? member.tags.filter((tag) => tag !== before.tag) : []
|
|
@@ -218,7 +228,14 @@ const unassignTeamMemberTagCommand = {
|
|
|
218
228
|
const before = payload?.before;
|
|
219
229
|
if (!before) return;
|
|
220
230
|
const em = ctx.container.resolve("em").fork();
|
|
221
|
-
const
|
|
231
|
+
const snapshotScope = staffSnapshotScopeFromSnapshot(before);
|
|
232
|
+
const member = await findOneWithDecryption(
|
|
233
|
+
em,
|
|
234
|
+
StaffTeamMember,
|
|
235
|
+
scopedStaffSnapshotWhere(before.memberId, snapshotScope),
|
|
236
|
+
void 0,
|
|
237
|
+
staffSnapshotDecryptionScope(snapshotScope)
|
|
238
|
+
);
|
|
222
239
|
if (!member) return;
|
|
223
240
|
const currentTags = Array.isArray(member.tags) ? member.tags : [];
|
|
224
241
|
if (!currentTags.includes(before.tag)) {
|
|
@@ -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 {\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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
|
|
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 scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromSnapshot,\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 snapshotScope = staffSnapshotScopeFromSnapshot(before)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n scopedStaffSnapshotWhere(before.memberId, snapshotScope),\n undefined,\n staffSnapshotDecryptionScope(snapshotScope),\n )\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 snapshotScope = staffSnapshotScopeFromSnapshot(before)\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n scopedStaffSnapshotWhere(before.memberId, snapshotScope),\n undefined,\n staffSnapshotDecryptionScope(snapshotScope),\n )\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
|
}
|
|
@@ -20,7 +20,11 @@ import {
|
|
|
20
20
|
ensureOrganizationScope,
|
|
21
21
|
ensureTenantScope,
|
|
22
22
|
extractUndoPayload,
|
|
23
|
-
scopeForDecryption
|
|
23
|
+
scopeForDecryption,
|
|
24
|
+
scopedStaffSnapshotWhere,
|
|
25
|
+
staffSnapshotDecryptionScope,
|
|
26
|
+
staffSnapshotScopeFromContext,
|
|
27
|
+
staffSnapshotScopeFromSnapshot
|
|
24
28
|
} from "./shared.js";
|
|
25
29
|
import { E } from "../../../generated/entities.ids.generated.js";
|
|
26
30
|
const teamMemberCrudIndexer = {
|
|
@@ -37,8 +41,14 @@ function normalizeStringList(value) {
|
|
|
37
41
|
});
|
|
38
42
|
return Array.from(set);
|
|
39
43
|
}
|
|
40
|
-
async function loadTeamMemberSnapshot(em, id) {
|
|
41
|
-
const member = await findOneWithDecryption(
|
|
44
|
+
async function loadTeamMemberSnapshot(em, id, scope) {
|
|
45
|
+
const member = await findOneWithDecryption(
|
|
46
|
+
em,
|
|
47
|
+
StaffTeamMember,
|
|
48
|
+
scopedStaffSnapshotWhere(id, scope),
|
|
49
|
+
void 0,
|
|
50
|
+
staffSnapshotDecryptionScope(scope)
|
|
51
|
+
);
|
|
42
52
|
if (!member) return null;
|
|
43
53
|
return {
|
|
44
54
|
id: member.id,
|
|
@@ -187,14 +197,14 @@ const createTeamMemberCommand = {
|
|
|
187
197
|
},
|
|
188
198
|
captureAfter: async (_input, result, ctx) => {
|
|
189
199
|
const em = ctx.container.resolve("em").fork();
|
|
190
|
-
const snapshot = await loadTeamMemberSnapshot(em, result.memberId);
|
|
200
|
+
const snapshot = await loadTeamMemberSnapshot(em, result.memberId, staffSnapshotScopeFromContext(ctx));
|
|
191
201
|
if (!snapshot) return null;
|
|
192
202
|
const custom = await loadTeamMemberCustomSnapshot(em, snapshot);
|
|
193
203
|
return { snapshot, custom };
|
|
194
204
|
},
|
|
195
205
|
buildLog: async ({ result, ctx }) => {
|
|
196
206
|
const em = ctx.container.resolve("em").fork();
|
|
197
|
-
const snapshot = await loadTeamMemberSnapshot(em, result.memberId);
|
|
207
|
+
const snapshot = await loadTeamMemberSnapshot(em, result.memberId, staffSnapshotScopeFromContext(ctx));
|
|
198
208
|
if (!snapshot) return null;
|
|
199
209
|
const custom = await loadTeamMemberCustomSnapshot(em, snapshot);
|
|
200
210
|
const { translate } = await resolveTranslations();
|
|
@@ -218,7 +228,7 @@ const createTeamMemberCommand = {
|
|
|
218
228
|
const after = payload?.after;
|
|
219
229
|
if (!after) return;
|
|
220
230
|
const em = ctx.container.resolve("em").fork();
|
|
221
|
-
const member = await em.findOne(StaffTeamMember,
|
|
231
|
+
const member = await em.findOne(StaffTeamMember, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
|
|
222
232
|
if (member) {
|
|
223
233
|
member.deletedAt = /* @__PURE__ */ new Date();
|
|
224
234
|
await em.flush();
|
|
@@ -259,7 +269,7 @@ const updateTeamMemberCommand = {
|
|
|
259
269
|
async prepare(rawInput, ctx) {
|
|
260
270
|
const { parsed } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput);
|
|
261
271
|
const em = ctx.container.resolve("em");
|
|
262
|
-
const snapshot = await loadTeamMemberSnapshot(em, parsed.id);
|
|
272
|
+
const snapshot = await loadTeamMemberSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx));
|
|
263
273
|
if (!snapshot) return {};
|
|
264
274
|
const custom = await loadTeamMemberCustomSnapshot(em, snapshot);
|
|
265
275
|
return { before: snapshot, customBefore: custom };
|
|
@@ -329,7 +339,7 @@ const updateTeamMemberCommand = {
|
|
|
329
339
|
const before = snapshots.before;
|
|
330
340
|
if (!before) return null;
|
|
331
341
|
const em = ctx.container.resolve("em").fork();
|
|
332
|
-
const after = await loadTeamMemberSnapshot(em, before.id);
|
|
342
|
+
const after = await loadTeamMemberSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before));
|
|
333
343
|
if (!after) return null;
|
|
334
344
|
const customBefore = snapshots.customBefore ?? void 0;
|
|
335
345
|
const customAfter = await loadTeamMemberCustomSnapshot(em, after);
|
|
@@ -372,7 +382,7 @@ const updateTeamMemberCommand = {
|
|
|
372
382
|
const before = payload?.before;
|
|
373
383
|
if (!before) return;
|
|
374
384
|
const em = ctx.container.resolve("em").fork();
|
|
375
|
-
const member = await em.findOne(StaffTeamMember,
|
|
385
|
+
const member = await em.findOne(StaffTeamMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
|
|
376
386
|
if (!member) return;
|
|
377
387
|
member.teamId = before.teamId ?? null;
|
|
378
388
|
member.displayName = before.displayName;
|
|
@@ -416,7 +426,7 @@ const deleteTeamMemberCommand = {
|
|
|
416
426
|
const id = input?.id;
|
|
417
427
|
if (!id) throw new CrudHttpError(400, { error: "Member id is required." });
|
|
418
428
|
const em = ctx.container.resolve("em");
|
|
419
|
-
const snapshot = await loadTeamMemberSnapshot(em, id);
|
|
429
|
+
const snapshot = await loadTeamMemberSnapshot(em, id, staffSnapshotScopeFromContext(ctx));
|
|
420
430
|
if (!snapshot) return {};
|
|
421
431
|
const custom = await loadTeamMemberCustomSnapshot(em, snapshot);
|
|
422
432
|
return { before: snapshot, customBefore: custom };
|
|
@@ -479,7 +489,7 @@ const deleteTeamMemberCommand = {
|
|
|
479
489
|
const before = payload?.before;
|
|
480
490
|
if (!before) return;
|
|
481
491
|
const em = ctx.container.resolve("em").fork();
|
|
482
|
-
let member = await em.findOne(StaffTeamMember,
|
|
492
|
+
let member = await em.findOne(StaffTeamMember, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
|
|
483
493
|
if (!member) {
|
|
484
494
|
member = em.create(StaffTeamMember, {
|
|
485
495
|
id: before.id,
|
|
@@ -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 {\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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",
|
|
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 scopedStaffSnapshotWhere,\n staffSnapshotDecryptionScope,\n staffSnapshotScopeFromContext,\n staffSnapshotScopeFromSnapshot,\n type StaffSnapshotScope,\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, scope?: StaffSnapshotScope | null): Promise<TeamMemberSnapshot | null> {\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n scopedStaffSnapshotWhere(id, scope),\n undefined,\n staffSnapshotDecryptionScope(scope),\n )\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n 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, staffSnapshotScopeFromContext(ctx))\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, staffSnapshotScopeFromContext(ctx))\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, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)))\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, staffSnapshotScopeFromContext(ctx))\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, staffSnapshotScopeFromSnapshot(before))\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, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\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, staffSnapshotScopeFromContext(ctx))\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, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)))\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
|
}
|
|
@@ -18,14 +18,24 @@ import {
|
|
|
18
18
|
ensureOrganizationScope,
|
|
19
19
|
ensureTenantScope,
|
|
20
20
|
extractUndoPayload,
|
|
21
|
-
scopeForDecryption
|
|
21
|
+
scopeForDecryption,
|
|
22
|
+
scopedStaffSnapshotWhere,
|
|
23
|
+
staffSnapshotDecryptionScope,
|
|
24
|
+
staffSnapshotScopeFromContext,
|
|
25
|
+
staffSnapshotScopeFromSnapshot
|
|
22
26
|
} from "./shared.js";
|
|
23
27
|
import { E } from "../../../generated/entities.ids.generated.js";
|
|
24
28
|
const teamRoleCrudIndexer = {
|
|
25
29
|
entityType: E.staff.staff_team_role
|
|
26
30
|
};
|
|
27
|
-
async function loadTeamRoleSnapshot(em, id) {
|
|
28
|
-
const role = await findOneWithDecryption(
|
|
31
|
+
async function loadTeamRoleSnapshot(em, id, scope) {
|
|
32
|
+
const role = await findOneWithDecryption(
|
|
33
|
+
em,
|
|
34
|
+
StaffTeamRole,
|
|
35
|
+
scopedStaffSnapshotWhere(id, scope),
|
|
36
|
+
void 0,
|
|
37
|
+
staffSnapshotDecryptionScope(scope)
|
|
38
|
+
);
|
|
29
39
|
if (!role) return null;
|
|
30
40
|
return {
|
|
31
41
|
id: role.id,
|
|
@@ -114,14 +124,14 @@ const createTeamRoleCommand = {
|
|
|
114
124
|
},
|
|
115
125
|
captureAfter: async (_input, result, ctx) => {
|
|
116
126
|
const em = ctx.container.resolve("em").fork();
|
|
117
|
-
const snapshot = await loadTeamRoleSnapshot(em, result.roleId);
|
|
127
|
+
const snapshot = await loadTeamRoleSnapshot(em, result.roleId, staffSnapshotScopeFromContext(ctx));
|
|
118
128
|
if (!snapshot) return null;
|
|
119
129
|
const custom = await loadTeamRoleCustomSnapshot(em, snapshot);
|
|
120
130
|
return { snapshot, custom };
|
|
121
131
|
},
|
|
122
132
|
buildLog: async ({ result, ctx }) => {
|
|
123
133
|
const em = ctx.container.resolve("em").fork();
|
|
124
|
-
const snapshot = await loadTeamRoleSnapshot(em, result.roleId);
|
|
134
|
+
const snapshot = await loadTeamRoleSnapshot(em, result.roleId, staffSnapshotScopeFromContext(ctx));
|
|
125
135
|
if (!snapshot) return null;
|
|
126
136
|
const custom = await loadTeamRoleCustomSnapshot(em, snapshot);
|
|
127
137
|
const { translate } = await resolveTranslations();
|
|
@@ -145,7 +155,7 @@ const createTeamRoleCommand = {
|
|
|
145
155
|
const after = payload?.after;
|
|
146
156
|
if (!after) return;
|
|
147
157
|
const em = ctx.container.resolve("em").fork();
|
|
148
|
-
const role = await em.findOne(StaffTeamRole,
|
|
158
|
+
const role = await em.findOne(StaffTeamRole, scopedStaffSnapshotWhere(after.id, staffSnapshotScopeFromSnapshot(after)));
|
|
149
159
|
if (role) {
|
|
150
160
|
role.deletedAt = /* @__PURE__ */ new Date();
|
|
151
161
|
await em.flush();
|
|
@@ -186,7 +196,7 @@ const updateTeamRoleCommand = {
|
|
|
186
196
|
async prepare(rawInput, ctx) {
|
|
187
197
|
const { parsed } = parseWithCustomFields(staffTeamRoleUpdateSchema, rawInput);
|
|
188
198
|
const em = ctx.container.resolve("em");
|
|
189
|
-
const snapshot = await loadTeamRoleSnapshot(em, parsed.id);
|
|
199
|
+
const snapshot = await loadTeamRoleSnapshot(em, parsed.id, staffSnapshotScopeFromContext(ctx));
|
|
190
200
|
if (!snapshot) return {};
|
|
191
201
|
const custom = await loadTeamRoleCustomSnapshot(em, snapshot);
|
|
192
202
|
return { before: snapshot, customBefore: custom };
|
|
@@ -244,7 +254,7 @@ const updateTeamRoleCommand = {
|
|
|
244
254
|
const before = snapshots.before;
|
|
245
255
|
if (!before) return null;
|
|
246
256
|
const em = ctx.container.resolve("em").fork();
|
|
247
|
-
const after = await loadTeamRoleSnapshot(em, before.id);
|
|
257
|
+
const after = await loadTeamRoleSnapshot(em, before.id, staffSnapshotScopeFromSnapshot(before));
|
|
248
258
|
if (!after) return null;
|
|
249
259
|
const customBefore = snapshots.customBefore ?? void 0;
|
|
250
260
|
const customAfter = await loadTeamRoleCustomSnapshot(em, after);
|
|
@@ -285,7 +295,7 @@ const updateTeamRoleCommand = {
|
|
|
285
295
|
const before = payload?.before;
|
|
286
296
|
if (!before) return;
|
|
287
297
|
const em = ctx.container.resolve("em").fork();
|
|
288
|
-
const role = await em.findOne(StaffTeamRole,
|
|
298
|
+
const role = await em.findOne(StaffTeamRole, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
|
|
289
299
|
if (!role) return;
|
|
290
300
|
role.teamId = before.teamId ?? null;
|
|
291
301
|
role.name = before.name;
|
|
@@ -327,7 +337,7 @@ const deleteTeamRoleCommand = {
|
|
|
327
337
|
const id = input?.id;
|
|
328
338
|
if (!id) throw new CrudHttpError(400, { error: "Role id is required." });
|
|
329
339
|
const em = ctx.container.resolve("em");
|
|
330
|
-
const snapshot = await loadTeamRoleSnapshot(em, id);
|
|
340
|
+
const snapshot = await loadTeamRoleSnapshot(em, id, staffSnapshotScopeFromContext(ctx));
|
|
331
341
|
if (!snapshot) return {};
|
|
332
342
|
const custom = await loadTeamRoleCustomSnapshot(em, snapshot);
|
|
333
343
|
return { before: snapshot, customBefore: custom };
|
|
@@ -411,7 +421,7 @@ const deleteTeamRoleCommand = {
|
|
|
411
421
|
const before = payload?.before;
|
|
412
422
|
if (!before) return;
|
|
413
423
|
const em = ctx.container.resolve("em").fork();
|
|
414
|
-
let role = await em.findOne(StaffTeamRole,
|
|
424
|
+
let role = await em.findOne(StaffTeamRole, scopedStaffSnapshotWhere(before.id, staffSnapshotScopeFromSnapshot(before)));
|
|
415
425
|
if (!role) {
|
|
416
426
|
role = em.create(StaffTeamRole, {
|
|
417
427
|
id: before.id,
|