@open-mercato/core 0.10.1-develop.7724.1.95e4e7d38e → 0.10.1-develop.7727.1.0b89c4f800
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/directory/commands/organizations.js +39 -0
- package/dist/modules/directory/commands/organizations.js.map +2 -2
- package/dist/modules/directory/lib/hierarchy.js +34 -2
- package/dist/modules/directory/lib/hierarchy.js.map +2 -2
- package/dist/modules/planner/api/availability-date-specific.js +2 -7
- package/dist/modules/planner/api/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/commands/availability-date-specific.js +14 -31
- package/dist/modules/planner/commands/availability-date-specific.js.map +2 -2
- package/dist/modules/planner/commands/availability-weekly.js +8 -22
- package/dist/modules/planner/commands/availability-weekly.js.map +2 -2
- package/dist/modules/planner/lib/availabilityMerge.js +10 -18
- package/dist/modules/planner/lib/availabilityMerge.js.map +2 -2
- package/dist/modules/planner/lib/availabilityTimezone.js +161 -0
- package/dist/modules/planner/lib/availabilityTimezone.js.map +7 -0
- package/package.json +8 -7
- package/src/modules/directory/commands/organizations.ts +45 -0
- package/src/modules/directory/i18n/de.json +1 -0
- package/src/modules/directory/i18n/en.json +1 -0
- package/src/modules/directory/i18n/es.json +1 -0
- package/src/modules/directory/i18n/ko.json +1 -0
- package/src/modules/directory/i18n/pl.json +1 -0
- package/src/modules/directory/lib/hierarchy.ts +41 -2
- package/src/modules/planner/api/availability-date-specific.ts +5 -10
- package/src/modules/planner/commands/availability-date-specific.ts +14 -33
- package/src/modules/planner/commands/availability-weekly.ts +15 -24
- package/src/modules/planner/lib/availabilityMerge.ts +13 -19
- package/src/modules/planner/lib/availabilityTimezone.ts +242 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -3,6 +3,7 @@ import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
|
3
3
|
import { Organization, Tenant } from "@open-mercato/core/modules/directory/data/entities";
|
|
4
4
|
import { organizationCreateSchema, organizationUpdateSchema } from "@open-mercato/core/modules/directory/data/validators";
|
|
5
5
|
import {
|
|
6
|
+
findOrganizationParentCycle,
|
|
6
7
|
lockOrganizationHierarchyForTenant,
|
|
7
8
|
rebuildHierarchyForTenant
|
|
8
9
|
} from "@open-mercato/core/modules/directory/lib/hierarchy";
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
requireId,
|
|
29
30
|
buildChanges
|
|
30
31
|
} from "@open-mercato/shared/lib/commands/helpers";
|
|
32
|
+
import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
31
33
|
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
32
34
|
import { toOptionalString } from "@open-mercato/shared/lib/string/coerce";
|
|
33
35
|
import { slugify } from "@open-mercato/shared/lib/slugify";
|
|
@@ -206,6 +208,26 @@ async function restoreChildParents(em, tenantId, snapshots) {
|
|
|
206
208
|
}
|
|
207
209
|
if (toPersist.length) await em.persist(toPersist).flush();
|
|
208
210
|
}
|
|
211
|
+
const REPLAY_CYCLE_ERROR_KEY = "directory.organizations.errors.replayCycle";
|
|
212
|
+
async function assertReplayKeepsHierarchyAcyclic(em, tenantId, organizationIds) {
|
|
213
|
+
const filter = {
|
|
214
|
+
tenant: tenantId,
|
|
215
|
+
deletedAt: null
|
|
216
|
+
};
|
|
217
|
+
const organizations = await findWithDecryption(em, Organization, filter, void 0, {
|
|
218
|
+
tenantId,
|
|
219
|
+
organizationId: null
|
|
220
|
+
});
|
|
221
|
+
if (!findOrganizationParentCycle(organizations, organizationIds)) return;
|
|
222
|
+
const { translate } = await resolveTranslations();
|
|
223
|
+
throw new CrudHttpError(409, {
|
|
224
|
+
error: translate(
|
|
225
|
+
REPLAY_CYCLE_ERROR_KEY,
|
|
226
|
+
"The organization hierarchy changed since this action, so it can't be reverted without making an organization its own ancestor."
|
|
227
|
+
),
|
|
228
|
+
code: REPLAY_CYCLE_ERROR_KEY
|
|
229
|
+
});
|
|
230
|
+
}
|
|
209
231
|
function normalizeChildIds(ids, exclude) {
|
|
210
232
|
const excludeSet = new Set(exclude);
|
|
211
233
|
return Array.from(new Set(ids)).filter((id) => !excludeSet.has(id));
|
|
@@ -403,6 +425,11 @@ const createOrganizationCommand = {
|
|
|
403
425
|
organization.parentId = null;
|
|
404
426
|
await em.flush();
|
|
405
427
|
}
|
|
428
|
+
await assertReplayKeepsHierarchyAcyclic(
|
|
429
|
+
em,
|
|
430
|
+
tenantId,
|
|
431
|
+
childrenBefore.map((entry) => entry.childId).filter((childId) => childId !== after.id)
|
|
432
|
+
);
|
|
406
433
|
await rebuildHierarchyForTenant(em, tenantId);
|
|
407
434
|
}
|
|
408
435
|
], { transaction: true });
|
|
@@ -473,6 +500,10 @@ const createOrganizationCommand = {
|
|
|
473
500
|
}
|
|
474
501
|
}
|
|
475
502
|
await assignChildren(em, tenantId, after.id, after.childParents.map((entry) => entry.childId));
|
|
503
|
+
await assertReplayKeepsHierarchyAcyclic(em, tenantId, [
|
|
504
|
+
after.id,
|
|
505
|
+
...after.childParents.map((entry) => entry.childId)
|
|
506
|
+
]);
|
|
476
507
|
await rebuildHierarchyForTenant(em, tenantId);
|
|
477
508
|
}
|
|
478
509
|
], { transaction: true });
|
|
@@ -691,6 +722,10 @@ const updateOrganizationCommand = {
|
|
|
691
722
|
}
|
|
692
723
|
const childSnapshots = before.childParents;
|
|
693
724
|
await restoreChildParents(em, tenantId, childSnapshots);
|
|
725
|
+
await assertReplayKeepsHierarchyAcyclic(em, tenantId, [
|
|
726
|
+
before.id,
|
|
727
|
+
...(childSnapshots ?? []).map((entry) => entry.childId)
|
|
728
|
+
]);
|
|
694
729
|
await rebuildHierarchyForTenant(em, tenantId);
|
|
695
730
|
}
|
|
696
731
|
], { transaction: true });
|
|
@@ -853,6 +888,10 @@ const deleteOrganizationCommand = {
|
|
|
853
888
|
}
|
|
854
889
|
}
|
|
855
890
|
await restoreChildParents(em, tenantId, before.childParents);
|
|
891
|
+
await assertReplayKeepsHierarchyAcyclic(em, tenantId, [
|
|
892
|
+
before.id,
|
|
893
|
+
...(before.childParents ?? []).map((entry) => entry.childId)
|
|
894
|
+
]);
|
|
856
895
|
await rebuildHierarchyForTenant(em, tenantId);
|
|
857
896
|
}
|
|
858
897
|
], { transaction: true });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/directory/commands/organizations.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { organizationCreateSchema, organizationUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport {\n lockOrganizationHierarchyForTenant,\n rebuildHierarchyForTenant,\n} from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport {\n enforceTenantSelection,\n normalizeTenantId,\n resolveIsSuperAdmin,\n} from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { E } from '#generated/entities.ids.generated'\nimport type { CrudEmitContext, CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n diffCustomFieldChanges,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { extractUndoPayload, reviveSnapshotDates } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n buildChanges,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { toOptionalString } from '@open-mercato/shared/lib/string/coerce'\nimport { slugify } from '@open-mercato/shared/lib/slugify'\n\nexport const organizationCrudEvents: CrudEventsConfig = {\n module: 'directory',\n entity: 'organization',\n persistent: true,\n buildPayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n id: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n organizationId: orgCtx.identifiers.id,\n }\n },\n}\n\nexport const organizationCrudIndexer: CrudIndexerConfig = {\n entityType: E.directory.organization,\n buildUpsertPayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n entityType: E.directory.organization,\n recordId: orgCtx.identifiers.id,\n organizationId: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n }\n },\n buildDeletePayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n entityType: E.directory.organization,\n recordId: orgCtx.identifiers.id,\n organizationId: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n }\n },\n}\n\ntype OrganizationTenantShape = {\n __tenantId?: unknown\n tenant?: string | { id?: unknown; getEntity?: () => { id?: unknown } }\n tenantId?: unknown\n tenant_id?: unknown\n}\n\ntype SerializedOrganization = ReturnType<typeof serializeOrganization>\n\ntype ChildParentSnapshot = {\n childId: string\n parentId: string | null\n}\n\ntype OrganizationUndoSnapshot = {\n id: string\n tenantId: string | null\n createdAt?: string | null\n name: string\n slug?: string | null\n logoUrl?: string | null\n logoPreserveAspectRatio?: boolean\n isActive: boolean\n parentId: string | null\n childParents: ChildParentSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype OrganizationSnapshots = {\n view: SerializedOrganization\n undo: OrganizationUndoSnapshot\n}\n\ntype OrganizationActorScope = {\n isUnrestricted: boolean\n tenantId: string | null\n}\n\ntype AuthorizedOrganizationTarget = {\n organization: Organization\n tenantId: string\n}\n\nexport function resolveTenantIdFromEntity(entity: Organization): string | null {\n const shape = entity as unknown as OrganizationTenantShape\n const cached = toOptionalString(shape.__tenantId)\n if (cached) return cached\n const tenantRef = shape.tenant\n if (typeof tenantRef === 'string') return tenantRef\n if (tenantRef && typeof tenantRef === 'object') {\n const direct = toOptionalString(tenantRef.id)\n if (direct) return direct\n if (typeof tenantRef.getEntity === 'function') {\n const nested = tenantRef.getEntity()\n const nestedId = nested ? toOptionalString(nested.id) : null\n if (nestedId) return nestedId\n }\n }\n const fallback = toOptionalString(shape.tenantId) || toOptionalString(shape.tenant_id)\n return fallback\n}\n\nasync function resolveOrganizationActorScope(ctx: CommandRuntimeContext): Promise<OrganizationActorScope> {\n if (ctx.systemActor === true) return { isUnrestricted: true, tenantId: null }\n const tenantId = normalizeTenantId(ctx.auth?.tenantId ?? null) ?? null\n const isSuperAdmin = await resolveIsSuperAdmin(ctx)\n return { isUnrestricted: isSuperAdmin, tenantId }\n}\n\nfunction buildOrganizationTargetFilter(\n id: string,\n scope: OrganizationActorScope,\n): FilterQuery<Organization> | null {\n if (!scope.isUnrestricted && !scope.tenantId) return null\n return {\n id,\n deletedAt: null,\n ...(scope.isUnrestricted ? {} : { tenant: scope.tenantId }),\n } as FilterQuery<Organization>\n}\n\nasync function loadAuthorizedOrganizationTarget(\n em: EntityManager,\n id: string,\n ctx: CommandRuntimeContext,\n): Promise<AuthorizedOrganizationTarget> {\n const scope = await resolveOrganizationActorScope(ctx)\n const filter = buildOrganizationTargetFilter(id, scope)\n if (!filter) throw new CrudHttpError(404, { error: 'Not found' })\n const organization = await em.findOne(Organization, filter)\n if (!organization) throw new CrudHttpError(404, { error: 'Not found' })\n const tenantId = resolveTenantIdFromEntity(organization)\n if (!tenantId || (!scope.isUnrestricted && tenantId !== scope.tenantId)) {\n throw new CrudHttpError(404, { error: 'Not found' })\n }\n return { organization, tenantId }\n}\n\nfunction buildOrganizationMutationFilter(\n id: string,\n tenantId: string,\n): FilterQuery<Organization> {\n return {\n id,\n deletedAt: null,\n tenant: tenantId,\n } as FilterQuery<Organization>\n}\n\nasync function assertOrganizationUndoTenantAccess(\n ctx: CommandRuntimeContext,\n targetTenantId: string,\n): Promise<void> {\n const scope = await resolveOrganizationActorScope(ctx)\n if (!scope.isUnrestricted && scope.tenantId !== targetTenantId) {\n throw new CrudHttpError(404, { error: 'Not found' })\n }\n}\n\nfunction buildOrganizationUndoTargetFilter(\n id: string,\n tenantId: string,\n): FilterQuery<Organization> {\n return { id, tenant: tenantId } as FilterQuery<Organization>\n}\n\nfunction serializeOrganization(entity: Organization, custom?: Record<string, unknown> | null) {\n return {\n id: String(entity.id),\n tenantId: resolveTenantIdFromEntity(entity),\n name: entity.name,\n slug: entity.slug ?? null,\n logoUrl: entity.logoUrl ?? null,\n logoPreserveAspectRatio: !!entity.logoPreserveAspectRatio,\n isActive: !!entity.isActive,\n parentId: entity.parentId ?? null,\n ancestorIds: Array.isArray(entity.ancestorIds) ? [...entity.ancestorIds] : [],\n childIds: Array.isArray(entity.childIds) ? [...entity.childIds] : [],\n descendantIds: Array.isArray(entity.descendantIds) ? [...entity.descendantIds] : [],\n createdAt: entity.createdAt ? entity.createdAt.toISOString() : null,\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n }\n}\n\nfunction captureOrganizationSnapshots(\n entity: Organization,\n childParents: ChildParentSnapshot[],\n custom?: Record<string, unknown> | null\n): OrganizationSnapshots {\n const tenantId = resolveTenantIdFromEntity(entity)\n return {\n view: serializeOrganization(entity, custom),\n undo: {\n id: String(entity.id),\n tenantId,\n createdAt: entity.createdAt ? entity.createdAt.toISOString() : null,\n name: entity.name,\n slug: entity.slug ?? null,\n logoUrl: entity.logoUrl ?? null,\n logoPreserveAspectRatio: !!entity.logoPreserveAspectRatio,\n isActive: !!entity.isActive,\n parentId: entity.parentId ?? null,\n childParents: (childParents ?? []).map((entry) => ({\n childId: String(entry.childId),\n parentId: entry.parentId,\n })),\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n },\n }\n}\n\nasync function loadChildParentSnapshots(\n em: EntityManager,\n tenantId: string | null,\n childIds: Iterable<string>\n): Promise<ChildParentSnapshot[]> {\n if (!tenantId) return []\n const ids = Array.from(new Set(Array.from(childIds ?? []).map((id) => String(id)).filter(Boolean)))\n if (!ids.length) return []\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: ids },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, filter)\n if (!children.length) return []\n const map = new Map(children.map((child) => [String(child.id), child.parentId ? String(child.parentId) : null]))\n return ids\n .filter((id) => map.has(id))\n .map((id) => ({\n childId: id,\n parentId: map.get(id) ?? null,\n }))\n}\n\nasync function restoreChildParents(em: EntityManager, tenantId: string, snapshots: ChildParentSnapshot[]) {\n if (!snapshots?.length) return\n const ids = Array.from(new Set(snapshots.map((entry) => entry.childId).filter(Boolean)))\n if (!ids.length) return\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: ids },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, filter)\n if (!children.length) return\n const desired = new Map(snapshots.map((entry) => [entry.childId, entry.parentId ?? null]))\n const toPersist: Organization[] = []\n for (const child of children) {\n const id = String(child.id)\n if (!desired.has(id)) continue\n const nextParent = desired.get(id) ?? null\n if (child.parentId !== nextParent) {\n child.parentId = nextParent\n toPersist.push(child)\n }\n }\n if (toPersist.length) await em.persist(toPersist).flush()\n}\n\nfunction normalizeChildIds(ids: readonly string[], exclude: string[]): string[] {\n const excludeSet = new Set(exclude)\n return Array.from(new Set(ids)).filter((id) => !excludeSet.has(id))\n}\n\nasync function ensureParentExists(em: EntityManager, tenantId: string, parentId: string | null): Promise<void> {\n if (!parentId) return\n const parentFilter: FilterQuery<Organization> = { id: parentId, tenant: tenantId, deletedAt: null }\n const parent = await em.findOne(Organization, parentFilter)\n if (!parent) throw new CrudHttpError(400, { error: 'Parent not found' })\n}\n\nasync function ensureChildrenValid(em: EntityManager, tenantId: string, childIds: string[]): Promise<void> {\n if (!childIds.length) return\n const childFilter: FilterQuery<Organization> = { id: { $in: childIds }, tenant: tenantId, deletedAt: null }\n const children = await em.find(Organization, childFilter)\n if (children.length !== childIds.length) throw new CrudHttpError(400, { error: 'Invalid child assignment' })\n}\n\nasync function assignChildren(\n em: EntityManager,\n tenantId: string,\n recordId: string,\n desiredChildIds: Iterable<string>\n): Promise<void> {\n const targetIds = Array.from(new Set(desiredChildIds)).filter((id) => id !== recordId)\n if (!targetIds.length) return\n const filter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null, id: { $in: targetIds } }\n const children = await em.find(Organization, filter)\n const toPersist: Organization[] = []\n for (const child of children) {\n if (String(child.id) === recordId) continue\n if (child.parentId !== recordId) {\n child.parentId = recordId\n toPersist.push(child)\n }\n }\n if (toPersist.length) await em.persist(toPersist).flush()\n}\n\nasync function clearRemovedChildren(em: EntityManager, tenantId: string, recordId: string, desiredChildIds: Set<string>): Promise<void> {\n const currentFilter: FilterQuery<Organization> = { tenant: tenantId, parentId: recordId, deletedAt: null }\n const current = await em.find(Organization, currentFilter)\n const toPersist = current.filter((child) => !desiredChildIds.has(String(child.id)))\n if (!toPersist.length) return\n for (const child of toPersist) child.parentId = null\n await em.persist(toPersist).flush()\n}\n\nasync function resolveUniqueSlug(em: EntityManager, tenantId: string, baseSlug: string, excludeId?: string): Promise<string> {\n let candidate = baseSlug\n let suffix = 0\n const maxAttempts = 50\n while (suffix < maxAttempts) {\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n slug: candidate,\n } as unknown as FilterQuery<Organization>\n const existing = await em.findOne(Organization, filter)\n if (!existing || (excludeId && String(existing.id) === excludeId)) return candidate\n suffix += 1\n candidate = `${baseSlug}-${suffix}`\n }\n return `${baseSlug}-${Date.now()}`\n}\n\nconst createOrganizationCommand: CommandHandler<Record<string, unknown>, Organization> = {\n id: 'directory.organizations.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(organizationCreateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const tenantId = await enforceTenantSelection(ctx, parsed.tenantId)\n if (!tenantId) throw new CrudHttpError(400, { error: 'Tenant scope required' })\n\n const parentId = parsed.parentId ?? null\n const childIds = normalizeChildIds(parsed.childIds ?? [], parentId ? [parentId] : [])\n if (parentId && childIds.includes(parentId)) throw new CrudHttpError(400, { error: 'Child cannot equal parent' })\n\n const tenantRef = em.getReference(Tenant, tenantId)\n const baseSlug = parsed.slug ? parsed.slug : slugify(parsed.name)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let organization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n if (parentId) {\n await ensureParentExists(em, tenantId, parentId)\n }\n await ensureChildrenValid(em, tenantId, childIds)\n const childParentsBefore = await loadChildParentSnapshots(em, tenantId, childIds)\n const slug = baseSlug ? await resolveUniqueSlug(em, tenantId, baseSlug) : null\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n tenant: tenantRef,\n name: parsed.name,\n slug,\n logoUrl: parsed.logoUrl ?? null,\n logoPreserveAspectRatio: parsed.logoPreserveAspectRatio ?? false,\n isActive: parsed.isActive ?? true,\n parentId,\n },\n })\n setInternalTenantId(organization, tenantId)\n const recordId = String(organization.id)\n\n if (childIds.length) {\n await assignChildren(em, tenantId, recordId, childIds)\n }\n const childParentsAfter = await loadChildParentSnapshots(em, tenantId, childIds)\n setUndoMeta(organization, { childParentsBefore, childParentsAfter })\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.directory.organization,\n recordId,\n tenantId,\n organizationId: recordId,\n values: custom,\n })\n\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const recordId = String(organization.id)\n const identifiers = { id: recordId, organizationId: recordId, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: organization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return organization\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n return serializeOrganization(result, custom)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const meta = getUndoMeta(result)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n const afterSnapshots = captureOrganizationSnapshots(result, meta.childParentsAfter ?? [], custom)\n return {\n actionLabel: translate('directory.audit.organizations.create', 'Create organization'),\n resourceKind: 'directory.organization',\n resourceId: String(result.id),\n tenantId,\n snapshotAfter: afterSnapshots.view,\n payload: {\n undo: {\n after: afterSnapshots.undo,\n childrenBefore: meta.childParentsBefore ?? [],\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const after = payload?.after\n const childrenBefore = payload?.childrenBefore ?? []\n if (!after) return\n const tenantId = after.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n await restoreChildParents(em, tenantId, childrenBefore)\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(undefined, after.custom)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: after.id,\n tenantId,\n organizationId: after.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n organization = await de.deleteOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(after.id, tenantId),\n soft: true,\n softDeleteField: 'deletedAt',\n })\n if (organization) {\n organization.isActive = false\n organization.parentId = null\n await em.flush()\n }\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: organization,\n identifiers: { id: after.id, tenantId, organizationId: after.id },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<OrganizationUndoSnapshot>(logEntry)\n if (!after) throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for organization create' })\n const tenantId = after.tenantId\n if (!tenantId) throw new CrudHttpError(400, { error: '[internal] redo snapshot missing tenant for organization create' })\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const existing = await em.findOne(Organization, buildOrganizationUndoTargetFilter(after.id, tenantId))\n if (existing) {\n existing.deletedAt = null\n existing.name = after.name\n if (after.slug !== undefined) existing.slug = after.slug ?? null\n if (after.logoUrl !== undefined) existing.logoUrl = after.logoUrl ?? null\n if (after.logoPreserveAspectRatio !== undefined) existing.logoPreserveAspectRatio = !!after.logoPreserveAspectRatio\n existing.isActive = after.isActive\n existing.parentId = after.parentId\n await em.flush()\n organization = existing\n } else {\n const snapshotAfter = logEntry.snapshotAfter\n const createdAt = after.createdAt ?? (\n snapshotAfter && typeof snapshotAfter === 'object' && 'createdAt' in snapshotAfter\n ? snapshotAfter.createdAt\n : undefined\n )\n const creationTime = typeof createdAt === 'string' || createdAt instanceof Date\n ? reviveSnapshotDates({ createdAt }, ['createdAt'])\n : {}\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n id: after.id,\n ...creationTime,\n name: after.name,\n slug: after.slug ?? null,\n logoUrl: after.logoUrl ?? null,\n logoPreserveAspectRatio: after.logoPreserveAspectRatio ?? false,\n tenant: em.getReference(Tenant, tenantId),\n isActive: after.isActive,\n parentId: after.parentId,\n },\n })\n }\n setInternalTenantId(organization, tenantId)\n\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: after.id,\n tenantId,\n organizationId: after.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n\n await assignChildren(em, tenantId, after.id, after.childParents.map((entry) => entry.childId))\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const identifiers = { id: after.id, organizationId: after.id, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: organization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return organization\n },\n}\n\nconst updateOrganizationCommand: CommandHandler<Record<string, unknown>, Organization> = {\n id: 'directory.organizations.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(organizationUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: current, tenantId } = await loadAuthorizedOrganizationTarget(em, parsed.id, ctx)\n const currentChildIds = Array.isArray(current.childIds) ? current.childIds : []\n const requestedChildIds = Array.isArray(parsed.childIds) ? parsed.childIds : []\n const combinedChildIds = new Set<string>([...currentChildIds.map(String), ...requestedChildIds.map(String)])\n const childParentsBefore = tenantId\n ? await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n : []\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(current.id),\n tenantId,\n organizationId: String(current.id),\n })\n return { before: captureOrganizationSnapshots(current, childParentsBefore, custom) }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(organizationUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const { tenantId } = await loadAuthorizedOrganizationTarget(em, parsed.id, ctx)\n\n const parentProvided = parsed.parentId !== undefined\n const childrenProvided = parsed.childIds !== undefined\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let resolvedOrganization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const existing = await em.findOne(\n Organization,\n buildOrganizationMutationFilter(parsed.id, tenantId),\n { refresh: true },\n )\n if (!existing) throw new CrudHttpError(404, { error: 'Not found' })\n\n const parentId = parentProvided ? parsed.parentId ?? null : existing.parentId ?? null\n if (parentProvided && parentId) {\n if (parentId === parsed.id) throw new CrudHttpError(400, { error: 'Organization cannot be its own parent' })\n if (Array.isArray(existing.descendantIds) && existing.descendantIds.includes(parentId)) {\n throw new CrudHttpError(400, { error: 'Cannot assign descendant as parent' })\n }\n await ensureParentExists(em, tenantId, parentId)\n }\n\n const normalizedChildIds = normalizeChildIds(parsed.childIds ?? [], [parsed.id, parentProvided ? parentId ?? '' : ''])\n if (normalizedChildIds.some((id) => id === parentId)) throw new CrudHttpError(400, { error: 'Child cannot equal parent' })\n if (Array.isArray(existing.ancestorIds) && normalizedChildIds.some((id) => existing.ancestorIds.includes(id))) {\n throw new CrudHttpError(400, { error: 'Cannot assign ancestor as child' })\n }\n\n if (normalizedChildIds.length) {\n await ensureChildrenValid(em, tenantId, normalizedChildIds)\n const childFilter = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: normalizedChildIds },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, childFilter)\n for (const child of children) {\n if (Array.isArray(child.descendantIds) && child.descendantIds.includes(parsed.id)) {\n throw new CrudHttpError(400, { error: 'Cannot assign descendant cycle' })\n }\n }\n }\n\n const combinedChildIds = new Set<string>([\n ...normalizedChildIds.map(String),\n ...(Array.isArray(existing.childIds) ? existing.childIds.map(String) : []),\n ])\n const childParentsBefore = await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n\n let resolvedSlug: string | null | undefined\n if (parsed.slug !== undefined) {\n resolvedSlug = parsed.slug ? await resolveUniqueSlug(em, tenantId, parsed.slug, parsed.id) : parsed.slug\n }\n\n const organization = await de.updateOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(parsed.id, tenantId),\n apply: (entity) => {\n if (parsed.name !== undefined) entity.name = parsed.name\n if (resolvedSlug !== undefined) entity.slug = resolvedSlug\n if (parsed.logoUrl !== undefined) entity.logoUrl = parsed.logoUrl ?? null\n if (parsed.logoPreserveAspectRatio !== undefined) entity.logoPreserveAspectRatio = parsed.logoPreserveAspectRatio\n if (parsed.isActive !== undefined) entity.isActive = parsed.isActive\n if (parentProvided) entity.parentId = parentId\n },\n })\n if (!organization) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(organization, tenantId)\n\n const recordId = String(organization.id)\n const desiredChildIds = new Set(normalizedChildIds.filter((id) => id !== recordId))\n if (childrenProvided) {\n await clearRemovedChildren(em, tenantId, recordId, desiredChildIds)\n await assignChildren(em, tenantId, recordId, desiredChildIds)\n }\n const childParentsAfter = await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n setUndoMeta(organization, { childParentsBefore, childParentsAfter })\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.directory.organization,\n recordId,\n tenantId,\n organizationId: recordId,\n values: custom,\n })\n\n await rebuildHierarchyForTenant(em, tenantId)\n resolvedOrganization = organization\n },\n ], { transaction: true })\n\n const recordId = String(resolvedOrganization.id)\n const identifiers = { id: recordId, organizationId: recordId, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: resolvedOrganization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return resolvedOrganization\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n return serializeOrganization(result, custom)\n },\n buildLog: async ({ snapshots, result, ctx }) => {\n const { translate } = await resolveTranslations()\n const meta = getUndoMeta(result)\n const beforeSnapshots = snapshots.before as OrganizationSnapshots | undefined\n const beforeRecord = beforeSnapshots?.view ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n const after = serializeOrganization(result, custom)\n const changes = buildChanges(beforeRecord, after as Record<string, unknown>, ['name', 'slug', 'logoUrl', 'logoPreserveAspectRatio', 'isActive', 'parentId'])\n const customDiff = diffCustomFieldChanges(beforeRecord?.custom, custom)\n for (const [key, diff] of Object.entries(customDiff)) {\n changes[`cf_${key}`] = diff\n }\n return {\n actionLabel: translate('directory.audit.organizations.update', 'Update organization'),\n resourceKind: 'directory.organization',\n resourceId: String(result.id),\n changes,\n tenantId: after.tenantId,\n payload: {\n undo: {\n before: beforeSnapshots?.undo ?? null,\n after: captureOrganizationSnapshots(result, meta.childParentsAfter ?? [], custom).undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before) return\n const tenantId = before.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let updated: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n updated = await de.updateOrmEntity({\n entity: Organization,\n where: buildOrganizationUndoTargetFilter(before.id, tenantId),\n apply: (entity) => {\n entity.name = before.name\n if (before.slug !== undefined) entity.slug = before.slug\n if (before.logoUrl !== undefined) entity.logoUrl = before.logoUrl ?? null\n if (before.logoPreserveAspectRatio !== undefined) entity.logoPreserveAspectRatio = !!before.logoPreserveAspectRatio\n entity.isActive = before.isActive\n entity.parentId = before.parentId\n },\n })\n if (!updated) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(updated, tenantId)\n const reset = buildCustomFieldResetMap(before.custom, after?.custom)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: before.id,\n tenantId,\n organizationId: before.id,\n values: resetValues,\n notify: false,\n })\n }\n const childSnapshots = before.childParents\n await restoreChildParents(em, tenantId, childSnapshots)\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: updated,\n identifiers: {\n id: before.id,\n tenantId,\n organizationId: before.id,\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n}\n\nconst deleteOrganizationCommand: CommandHandler<{ body: any; query: Record<string, string> }, Organization> = {\n id: 'directory.organizations.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Organization id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: existing, tenantId } = await loadAuthorizedOrganizationTarget(em, id, ctx)\n const childParentsBefore = tenantId\n ? await loadChildParentSnapshots(em, tenantId, Array.isArray(existing.childIds) ? existing.childIds : [])\n : []\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(existing.id),\n tenantId,\n organizationId: String(existing.id),\n })\n return { before: captureOrganizationSnapshots(existing, childParentsBefore, custom) }\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Organization id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: existing, tenantId } = await loadAuthorizedOrganizationTarget(em, id, ctx)\n\n const parentId = existing.parentId ?? null\n const childSnapshotsBefore = await loadChildParentSnapshots(\n em,\n tenantId,\n Array.isArray(existing.childIds) ? existing.childIds : [],\n )\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let resolvedDeleted!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const deleted = await de.deleteOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(id, tenantId),\n soft: true,\n softDeleteField: 'deletedAt',\n })\n if (!deleted) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(deleted, tenantId)\n deleted.isActive = false\n deleted.parentId = null\n resolvedDeleted = deleted\n },\n async () => {\n const deleted = resolvedDeleted\n const childrenFilter: FilterQuery<Organization> = { tenant: tenantId, parentId: id, deletedAt: null }\n const children = await em.find(Organization, childrenFilter)\n const toPersist: Organization[] = []\n for (const child of children) {\n child.parentId = parentId\n toPersist.push(child)\n }\n toPersist.push(deleted)\n if (toPersist.length) em.persist(toPersist)\n setUndoMeta(deleted, { childParentsBefore: childSnapshotsBefore })\n },\n async () => {\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const identifiers = { id, organizationId: id, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: resolvedDeleted,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return resolvedDeleted\n },\n buildLog: async ({ snapshots, input }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as OrganizationSnapshots | undefined\n const beforeSnapshot = beforeSnapshots?.view ?? null\n const beforeUndo = beforeSnapshots?.undo ?? null\n const id = String(input?.body?.id ?? input?.query?.id ?? '')\n const fallbackId = beforeSnapshot?.id ?? null\n const fallbackTenant = beforeSnapshot?.tenantId ?? null\n return {\n actionLabel: translate('directory.audit.organizations.delete', 'Delete organization'),\n resourceKind: 'directory.organization',\n resourceId: id || fallbackId || null,\n snapshotBefore: beforeSnapshot ?? null,\n tenantId: beforeUndo?.tenantId ?? fallbackTenant,\n payload: {\n undo: {\n before: beforeUndo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const tenantId = before.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n organization = await em.findOne(\n Organization,\n buildOrganizationUndoTargetFilter(before.id, tenantId),\n )\n if (organization) {\n organization.deletedAt = null\n organization.isActive = before.isActive\n organization.name = before.name\n if (before.slug !== undefined) organization.slug = before.slug\n organization.parentId = before.parentId\n await em.flush()\n if (tenantId) setInternalTenantId(organization, tenantId)\n } else {\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n id: before.id,\n name: before.name,\n slug: before.slug ?? null,\n tenant: tenantId ? em.getReference(Tenant, tenantId) : undefined,\n isActive: before.isActive,\n parentId: before.parentId,\n },\n })\n if (tenantId) setInternalTenantId(organization, tenantId)\n }\n if (tenantId) {\n const customValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(customValues).length) {\n const resetValues = customValues as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: before.id,\n tenantId,\n organizationId: before.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n await restoreChildParents(em, tenantId, before.childParents)\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: organization,\n identifiers: {\n id: before.id,\n tenantId,\n organizationId: before.id,\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n}\n\ntype OrganizationUndoPayload = {\n before?: OrganizationUndoSnapshot | null\n after?: OrganizationUndoSnapshot | null\n childrenBefore?: ChildParentSnapshot[] | null\n}\n\ntype OrganizationUndoMeta = {\n childParentsBefore?: ChildParentSnapshot[]\n childParentsAfter?: ChildParentSnapshot[]\n}\n\nconst UNDO_META_KEY: unique symbol = Symbol('directory.organization.undoMeta')\n\nfunction getUndoMeta(entity: Organization): OrganizationUndoMeta {\n return (Reflect.get(entity, UNDO_META_KEY) as OrganizationUndoMeta | undefined) ?? {}\n}\n\nfunction setUndoMeta(entity: Organization, meta: Partial<OrganizationUndoMeta>) {\n const current = getUndoMeta(entity)\n Reflect.set(entity, UNDO_META_KEY, { ...current, ...meta })\n}\n\nregisterCommand(createOrganizationCommand)\nregisterCommand(updateOrganizationCommand)\nregisterCommand(deleteOrganizationCommand)\n\nfunction setInternalTenantId(entity: Organization, tenantId: string) {\n Reflect.set(entity, '__tenantId', tenantId)\n}\n\nfunction tenantIdFromContext(ctx: CrudEmitContext<Organization>): string | null {\n return resolveTenantIdFromEntity(ctx.entity) ?? ctx.identifiers.tenantId ?? null\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\nimport { organizationCreateSchema, organizationUpdateSchema } from '@open-mercato/core/modules/directory/data/validators'\nimport {\n findOrganizationParentCycle,\n lockOrganizationHierarchyForTenant,\n rebuildHierarchyForTenant,\n} from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport {\n enforceTenantSelection,\n normalizeTenantId,\n resolveIsSuperAdmin,\n} from '@open-mercato/core/modules/auth/lib/tenantAccess'\nimport { E } from '#generated/entities.ids.generated'\nimport type { CrudEmitContext, CrudEventsConfig, CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n diffCustomFieldChanges,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { extractUndoPayload, reviveSnapshotDates } from '@open-mercato/shared/lib/commands/undo'\nimport { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n buildChanges,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { toOptionalString } from '@open-mercato/shared/lib/string/coerce'\nimport { slugify } from '@open-mercato/shared/lib/slugify'\n\nexport const organizationCrudEvents: CrudEventsConfig = {\n module: 'directory',\n entity: 'organization',\n persistent: true,\n buildPayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n id: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n organizationId: orgCtx.identifiers.id,\n }\n },\n}\n\nexport const organizationCrudIndexer: CrudIndexerConfig = {\n entityType: E.directory.organization,\n buildUpsertPayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n entityType: E.directory.organization,\n recordId: orgCtx.identifiers.id,\n organizationId: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n }\n },\n buildDeletePayload: (ctx) => {\n const orgCtx = ctx as CrudEmitContext<Organization>\n return {\n entityType: E.directory.organization,\n recordId: orgCtx.identifiers.id,\n organizationId: orgCtx.identifiers.id,\n tenantId: tenantIdFromContext(orgCtx),\n }\n },\n}\n\ntype OrganizationTenantShape = {\n __tenantId?: unknown\n tenant?: string | { id?: unknown; getEntity?: () => { id?: unknown } }\n tenantId?: unknown\n tenant_id?: unknown\n}\n\ntype SerializedOrganization = ReturnType<typeof serializeOrganization>\n\ntype ChildParentSnapshot = {\n childId: string\n parentId: string | null\n}\n\ntype OrganizationUndoSnapshot = {\n id: string\n tenantId: string | null\n createdAt?: string | null\n name: string\n slug?: string | null\n logoUrl?: string | null\n logoPreserveAspectRatio?: boolean\n isActive: boolean\n parentId: string | null\n childParents: ChildParentSnapshot[]\n custom?: Record<string, unknown>\n}\n\ntype OrganizationSnapshots = {\n view: SerializedOrganization\n undo: OrganizationUndoSnapshot\n}\n\ntype OrganizationActorScope = {\n isUnrestricted: boolean\n tenantId: string | null\n}\n\ntype AuthorizedOrganizationTarget = {\n organization: Organization\n tenantId: string\n}\n\nexport function resolveTenantIdFromEntity(entity: Organization): string | null {\n const shape = entity as unknown as OrganizationTenantShape\n const cached = toOptionalString(shape.__tenantId)\n if (cached) return cached\n const tenantRef = shape.tenant\n if (typeof tenantRef === 'string') return tenantRef\n if (tenantRef && typeof tenantRef === 'object') {\n const direct = toOptionalString(tenantRef.id)\n if (direct) return direct\n if (typeof tenantRef.getEntity === 'function') {\n const nested = tenantRef.getEntity()\n const nestedId = nested ? toOptionalString(nested.id) : null\n if (nestedId) return nestedId\n }\n }\n const fallback = toOptionalString(shape.tenantId) || toOptionalString(shape.tenant_id)\n return fallback\n}\n\nasync function resolveOrganizationActorScope(ctx: CommandRuntimeContext): Promise<OrganizationActorScope> {\n if (ctx.systemActor === true) return { isUnrestricted: true, tenantId: null }\n const tenantId = normalizeTenantId(ctx.auth?.tenantId ?? null) ?? null\n const isSuperAdmin = await resolveIsSuperAdmin(ctx)\n return { isUnrestricted: isSuperAdmin, tenantId }\n}\n\nfunction buildOrganizationTargetFilter(\n id: string,\n scope: OrganizationActorScope,\n): FilterQuery<Organization> | null {\n if (!scope.isUnrestricted && !scope.tenantId) return null\n return {\n id,\n deletedAt: null,\n ...(scope.isUnrestricted ? {} : { tenant: scope.tenantId }),\n } as FilterQuery<Organization>\n}\n\nasync function loadAuthorizedOrganizationTarget(\n em: EntityManager,\n id: string,\n ctx: CommandRuntimeContext,\n): Promise<AuthorizedOrganizationTarget> {\n const scope = await resolveOrganizationActorScope(ctx)\n const filter = buildOrganizationTargetFilter(id, scope)\n if (!filter) throw new CrudHttpError(404, { error: 'Not found' })\n const organization = await em.findOne(Organization, filter)\n if (!organization) throw new CrudHttpError(404, { error: 'Not found' })\n const tenantId = resolveTenantIdFromEntity(organization)\n if (!tenantId || (!scope.isUnrestricted && tenantId !== scope.tenantId)) {\n throw new CrudHttpError(404, { error: 'Not found' })\n }\n return { organization, tenantId }\n}\n\nfunction buildOrganizationMutationFilter(\n id: string,\n tenantId: string,\n): FilterQuery<Organization> {\n return {\n id,\n deletedAt: null,\n tenant: tenantId,\n } as FilterQuery<Organization>\n}\n\nasync function assertOrganizationUndoTenantAccess(\n ctx: CommandRuntimeContext,\n targetTenantId: string,\n): Promise<void> {\n const scope = await resolveOrganizationActorScope(ctx)\n if (!scope.isUnrestricted && scope.tenantId !== targetTenantId) {\n throw new CrudHttpError(404, { error: 'Not found' })\n }\n}\n\nfunction buildOrganizationUndoTargetFilter(\n id: string,\n tenantId: string,\n): FilterQuery<Organization> {\n return { id, tenant: tenantId } as FilterQuery<Organization>\n}\n\nfunction serializeOrganization(entity: Organization, custom?: Record<string, unknown> | null) {\n return {\n id: String(entity.id),\n tenantId: resolveTenantIdFromEntity(entity),\n name: entity.name,\n slug: entity.slug ?? null,\n logoUrl: entity.logoUrl ?? null,\n logoPreserveAspectRatio: !!entity.logoPreserveAspectRatio,\n isActive: !!entity.isActive,\n parentId: entity.parentId ?? null,\n ancestorIds: Array.isArray(entity.ancestorIds) ? [...entity.ancestorIds] : [],\n childIds: Array.isArray(entity.childIds) ? [...entity.childIds] : [],\n descendantIds: Array.isArray(entity.descendantIds) ? [...entity.descendantIds] : [],\n createdAt: entity.createdAt ? entity.createdAt.toISOString() : null,\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n }\n}\n\nfunction captureOrganizationSnapshots(\n entity: Organization,\n childParents: ChildParentSnapshot[],\n custom?: Record<string, unknown> | null\n): OrganizationSnapshots {\n const tenantId = resolveTenantIdFromEntity(entity)\n return {\n view: serializeOrganization(entity, custom),\n undo: {\n id: String(entity.id),\n tenantId,\n createdAt: entity.createdAt ? entity.createdAt.toISOString() : null,\n name: entity.name,\n slug: entity.slug ?? null,\n logoUrl: entity.logoUrl ?? null,\n logoPreserveAspectRatio: !!entity.logoPreserveAspectRatio,\n isActive: !!entity.isActive,\n parentId: entity.parentId ?? null,\n childParents: (childParents ?? []).map((entry) => ({\n childId: String(entry.childId),\n parentId: entry.parentId,\n })),\n ...(custom && Object.keys(custom).length ? { custom } : {}),\n },\n }\n}\n\nasync function loadChildParentSnapshots(\n em: EntityManager,\n tenantId: string | null,\n childIds: Iterable<string>\n): Promise<ChildParentSnapshot[]> {\n if (!tenantId) return []\n const ids = Array.from(new Set(Array.from(childIds ?? []).map((id) => String(id)).filter(Boolean)))\n if (!ids.length) return []\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: ids },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, filter)\n if (!children.length) return []\n const map = new Map(children.map((child) => [String(child.id), child.parentId ? String(child.parentId) : null]))\n return ids\n .filter((id) => map.has(id))\n .map((id) => ({\n childId: id,\n parentId: map.get(id) ?? null,\n }))\n}\n\nasync function restoreChildParents(em: EntityManager, tenantId: string, snapshots: ChildParentSnapshot[]) {\n if (!snapshots?.length) return\n const ids = Array.from(new Set(snapshots.map((entry) => entry.childId).filter(Boolean)))\n if (!ids.length) return\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: ids },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, filter)\n if (!children.length) return\n const desired = new Map(snapshots.map((entry) => [entry.childId, entry.parentId ?? null]))\n const toPersist: Organization[] = []\n for (const child of children) {\n const id = String(child.id)\n if (!desired.has(id)) continue\n const nextParent = desired.get(id) ?? null\n if (child.parentId !== nextParent) {\n child.parentId = nextParent\n toPersist.push(child)\n }\n }\n if (toPersist.length) await em.persist(toPersist).flush()\n}\n\nconst REPLAY_CYCLE_ERROR_KEY = 'directory.organizations.errors.replayCycle'\n\nasync function assertReplayKeepsHierarchyAcyclic(\n em: EntityManager,\n tenantId: string,\n organizationIds: Iterable<string>,\n): Promise<void> {\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n deletedAt: null,\n } as unknown as FilterQuery<Organization>\n const organizations = await findWithDecryption(em, Organization, filter, undefined, {\n tenantId,\n organizationId: null,\n })\n if (!findOrganizationParentCycle(organizations, organizationIds)) return\n const { translate } = await resolveTranslations()\n throw new CrudHttpError(409, {\n error: translate(\n REPLAY_CYCLE_ERROR_KEY,\n \"The organization hierarchy changed since this action, so it can't be reverted without making an organization its own ancestor.\",\n ),\n code: REPLAY_CYCLE_ERROR_KEY,\n })\n}\n\nfunction normalizeChildIds(ids: readonly string[], exclude: string[]): string[] {\n const excludeSet = new Set(exclude)\n return Array.from(new Set(ids)).filter((id) => !excludeSet.has(id))\n}\n\nasync function ensureParentExists(em: EntityManager, tenantId: string, parentId: string | null): Promise<void> {\n if (!parentId) return\n const parentFilter: FilterQuery<Organization> = { id: parentId, tenant: tenantId, deletedAt: null }\n const parent = await em.findOne(Organization, parentFilter)\n if (!parent) throw new CrudHttpError(400, { error: 'Parent not found' })\n}\n\nasync function ensureChildrenValid(em: EntityManager, tenantId: string, childIds: string[]): Promise<void> {\n if (!childIds.length) return\n const childFilter: FilterQuery<Organization> = { id: { $in: childIds }, tenant: tenantId, deletedAt: null }\n const children = await em.find(Organization, childFilter)\n if (children.length !== childIds.length) throw new CrudHttpError(400, { error: 'Invalid child assignment' })\n}\n\nasync function assignChildren(\n em: EntityManager,\n tenantId: string,\n recordId: string,\n desiredChildIds: Iterable<string>\n): Promise<void> {\n const targetIds = Array.from(new Set(desiredChildIds)).filter((id) => id !== recordId)\n if (!targetIds.length) return\n const filter: FilterQuery<Organization> = { tenant: tenantId, deletedAt: null, id: { $in: targetIds } }\n const children = await em.find(Organization, filter)\n const toPersist: Organization[] = []\n for (const child of children) {\n if (String(child.id) === recordId) continue\n if (child.parentId !== recordId) {\n child.parentId = recordId\n toPersist.push(child)\n }\n }\n if (toPersist.length) await em.persist(toPersist).flush()\n}\n\nasync function clearRemovedChildren(em: EntityManager, tenantId: string, recordId: string, desiredChildIds: Set<string>): Promise<void> {\n const currentFilter: FilterQuery<Organization> = { tenant: tenantId, parentId: recordId, deletedAt: null }\n const current = await em.find(Organization, currentFilter)\n const toPersist = current.filter((child) => !desiredChildIds.has(String(child.id)))\n if (!toPersist.length) return\n for (const child of toPersist) child.parentId = null\n await em.persist(toPersist).flush()\n}\n\nasync function resolveUniqueSlug(em: EntityManager, tenantId: string, baseSlug: string, excludeId?: string): Promise<string> {\n let candidate = baseSlug\n let suffix = 0\n const maxAttempts = 50\n while (suffix < maxAttempts) {\n const filter: FilterQuery<Organization> = {\n tenant: tenantId,\n slug: candidate,\n } as unknown as FilterQuery<Organization>\n const existing = await em.findOne(Organization, filter)\n if (!existing || (excludeId && String(existing.id) === excludeId)) return candidate\n suffix += 1\n candidate = `${baseSlug}-${suffix}`\n }\n return `${baseSlug}-${Date.now()}`\n}\n\nconst createOrganizationCommand: CommandHandler<Record<string, unknown>, Organization> = {\n id: 'directory.organizations.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(organizationCreateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const tenantId = await enforceTenantSelection(ctx, parsed.tenantId)\n if (!tenantId) throw new CrudHttpError(400, { error: 'Tenant scope required' })\n\n const parentId = parsed.parentId ?? null\n const childIds = normalizeChildIds(parsed.childIds ?? [], parentId ? [parentId] : [])\n if (parentId && childIds.includes(parentId)) throw new CrudHttpError(400, { error: 'Child cannot equal parent' })\n\n const tenantRef = em.getReference(Tenant, tenantId)\n const baseSlug = parsed.slug ? parsed.slug : slugify(parsed.name)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let organization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n if (parentId) {\n await ensureParentExists(em, tenantId, parentId)\n }\n await ensureChildrenValid(em, tenantId, childIds)\n const childParentsBefore = await loadChildParentSnapshots(em, tenantId, childIds)\n const slug = baseSlug ? await resolveUniqueSlug(em, tenantId, baseSlug) : null\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n tenant: tenantRef,\n name: parsed.name,\n slug,\n logoUrl: parsed.logoUrl ?? null,\n logoPreserveAspectRatio: parsed.logoPreserveAspectRatio ?? false,\n isActive: parsed.isActive ?? true,\n parentId,\n },\n })\n setInternalTenantId(organization, tenantId)\n const recordId = String(organization.id)\n\n if (childIds.length) {\n await assignChildren(em, tenantId, recordId, childIds)\n }\n const childParentsAfter = await loadChildParentSnapshots(em, tenantId, childIds)\n setUndoMeta(organization, { childParentsBefore, childParentsAfter })\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.directory.organization,\n recordId,\n tenantId,\n organizationId: recordId,\n values: custom,\n })\n\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const recordId = String(organization.id)\n const identifiers = { id: recordId, organizationId: recordId, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: organization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return organization\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n return serializeOrganization(result, custom)\n },\n buildLog: async ({ result, ctx }) => {\n const { translate } = await resolveTranslations()\n const meta = getUndoMeta(result)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n const afterSnapshots = captureOrganizationSnapshots(result, meta.childParentsAfter ?? [], custom)\n return {\n actionLabel: translate('directory.audit.organizations.create', 'Create organization'),\n resourceKind: 'directory.organization',\n resourceId: String(result.id),\n tenantId,\n snapshotAfter: afterSnapshots.view,\n payload: {\n undo: {\n after: afterSnapshots.undo,\n childrenBefore: meta.childParentsBefore ?? [],\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const after = payload?.after\n const childrenBefore = payload?.childrenBefore ?? []\n if (!after) return\n const tenantId = after.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n await restoreChildParents(em, tenantId, childrenBefore)\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(undefined, after.custom)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: after.id,\n tenantId,\n organizationId: after.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n organization = await de.deleteOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(after.id, tenantId),\n soft: true,\n softDeleteField: 'deletedAt',\n })\n if (organization) {\n organization.isActive = false\n organization.parentId = null\n await em.flush()\n }\n await assertReplayKeepsHierarchyAcyclic(\n em,\n tenantId,\n childrenBefore.map((entry) => entry.childId).filter((childId) => childId !== after.id),\n )\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: organization,\n identifiers: { id: after.id, tenantId, organizationId: after.id },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n redo: async ({ logEntry, ctx }) => {\n const after = resolveRedoSnapshot<OrganizationUndoSnapshot>(logEntry)\n if (!after) throw new CrudHttpError(400, { error: '[internal] redo snapshot unavailable for organization create' })\n const tenantId = after.tenantId\n if (!tenantId) throw new CrudHttpError(400, { error: '[internal] redo snapshot missing tenant for organization create' })\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const existing = await em.findOne(Organization, buildOrganizationUndoTargetFilter(after.id, tenantId))\n if (existing) {\n existing.deletedAt = null\n existing.name = after.name\n if (after.slug !== undefined) existing.slug = after.slug ?? null\n if (after.logoUrl !== undefined) existing.logoUrl = after.logoUrl ?? null\n if (after.logoPreserveAspectRatio !== undefined) existing.logoPreserveAspectRatio = !!after.logoPreserveAspectRatio\n existing.isActive = after.isActive\n existing.parentId = after.parentId\n await em.flush()\n organization = existing\n } else {\n const snapshotAfter = logEntry.snapshotAfter\n const createdAt = after.createdAt ?? (\n snapshotAfter && typeof snapshotAfter === 'object' && 'createdAt' in snapshotAfter\n ? snapshotAfter.createdAt\n : undefined\n )\n const creationTime = typeof createdAt === 'string' || createdAt instanceof Date\n ? reviveSnapshotDates({ createdAt }, ['createdAt'])\n : {}\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n id: after.id,\n ...creationTime,\n name: after.name,\n slug: after.slug ?? null,\n logoUrl: after.logoUrl ?? null,\n logoPreserveAspectRatio: after.logoPreserveAspectRatio ?? false,\n tenant: em.getReference(Tenant, tenantId),\n isActive: after.isActive,\n parentId: after.parentId,\n },\n })\n }\n setInternalTenantId(organization, tenantId)\n\n if (after.custom && Object.keys(after.custom).length) {\n const reset = buildCustomFieldResetMap(after.custom, undefined)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: after.id,\n tenantId,\n organizationId: after.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n\n await assignChildren(em, tenantId, after.id, after.childParents.map((entry) => entry.childId))\n await assertReplayKeepsHierarchyAcyclic(em, tenantId, [\n after.id,\n ...after.childParents.map((entry) => entry.childId),\n ])\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const identifiers = { id: after.id, organizationId: after.id, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: organization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return organization\n },\n}\n\nconst updateOrganizationCommand: CommandHandler<Record<string, unknown>, Organization> = {\n id: 'directory.organizations.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(organizationUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: current, tenantId } = await loadAuthorizedOrganizationTarget(em, parsed.id, ctx)\n const currentChildIds = Array.isArray(current.childIds) ? current.childIds : []\n const requestedChildIds = Array.isArray(parsed.childIds) ? parsed.childIds : []\n const combinedChildIds = new Set<string>([...currentChildIds.map(String), ...requestedChildIds.map(String)])\n const childParentsBefore = tenantId\n ? await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n : []\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(current.id),\n tenantId,\n organizationId: String(current.id),\n })\n return { before: captureOrganizationSnapshots(current, childParentsBefore, custom) }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(organizationUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const { tenantId } = await loadAuthorizedOrganizationTarget(em, parsed.id, ctx)\n\n const parentProvided = parsed.parentId !== undefined\n const childrenProvided = parsed.childIds !== undefined\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let resolvedOrganization!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const existing = await em.findOne(\n Organization,\n buildOrganizationMutationFilter(parsed.id, tenantId),\n { refresh: true },\n )\n if (!existing) throw new CrudHttpError(404, { error: 'Not found' })\n\n const parentId = parentProvided ? parsed.parentId ?? null : existing.parentId ?? null\n if (parentProvided && parentId) {\n if (parentId === parsed.id) throw new CrudHttpError(400, { error: 'Organization cannot be its own parent' })\n if (Array.isArray(existing.descendantIds) && existing.descendantIds.includes(parentId)) {\n throw new CrudHttpError(400, { error: 'Cannot assign descendant as parent' })\n }\n await ensureParentExists(em, tenantId, parentId)\n }\n\n const normalizedChildIds = normalizeChildIds(parsed.childIds ?? [], [parsed.id, parentProvided ? parentId ?? '' : ''])\n if (normalizedChildIds.some((id) => id === parentId)) throw new CrudHttpError(400, { error: 'Child cannot equal parent' })\n if (Array.isArray(existing.ancestorIds) && normalizedChildIds.some((id) => existing.ancestorIds.includes(id))) {\n throw new CrudHttpError(400, { error: 'Cannot assign ancestor as child' })\n }\n\n if (normalizedChildIds.length) {\n await ensureChildrenValid(em, tenantId, normalizedChildIds)\n const childFilter = {\n tenant: tenantId,\n deletedAt: null,\n id: { $in: normalizedChildIds },\n } as unknown as FilterQuery<Organization>\n const children = await em.find(Organization, childFilter)\n for (const child of children) {\n if (Array.isArray(child.descendantIds) && child.descendantIds.includes(parsed.id)) {\n throw new CrudHttpError(400, { error: 'Cannot assign descendant cycle' })\n }\n }\n }\n\n const combinedChildIds = new Set<string>([\n ...normalizedChildIds.map(String),\n ...(Array.isArray(existing.childIds) ? existing.childIds.map(String) : []),\n ])\n const childParentsBefore = await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n\n let resolvedSlug: string | null | undefined\n if (parsed.slug !== undefined) {\n resolvedSlug = parsed.slug ? await resolveUniqueSlug(em, tenantId, parsed.slug, parsed.id) : parsed.slug\n }\n\n const organization = await de.updateOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(parsed.id, tenantId),\n apply: (entity) => {\n if (parsed.name !== undefined) entity.name = parsed.name\n if (resolvedSlug !== undefined) entity.slug = resolvedSlug\n if (parsed.logoUrl !== undefined) entity.logoUrl = parsed.logoUrl ?? null\n if (parsed.logoPreserveAspectRatio !== undefined) entity.logoPreserveAspectRatio = parsed.logoPreserveAspectRatio\n if (parsed.isActive !== undefined) entity.isActive = parsed.isActive\n if (parentProvided) entity.parentId = parentId\n },\n })\n if (!organization) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(organization, tenantId)\n\n const recordId = String(organization.id)\n const desiredChildIds = new Set(normalizedChildIds.filter((id) => id !== recordId))\n if (childrenProvided) {\n await clearRemovedChildren(em, tenantId, recordId, desiredChildIds)\n await assignChildren(em, tenantId, recordId, desiredChildIds)\n }\n const childParentsAfter = await loadChildParentSnapshots(em, tenantId, combinedChildIds)\n setUndoMeta(organization, { childParentsBefore, childParentsAfter })\n\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.directory.organization,\n recordId,\n tenantId,\n organizationId: recordId,\n values: custom,\n })\n\n await rebuildHierarchyForTenant(em, tenantId)\n resolvedOrganization = organization\n },\n ], { transaction: true })\n\n const recordId = String(resolvedOrganization.id)\n const identifiers = { id: recordId, organizationId: recordId, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: resolvedOrganization,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return resolvedOrganization\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n return serializeOrganization(result, custom)\n },\n buildLog: async ({ snapshots, result, ctx }) => {\n const { translate } = await resolveTranslations()\n const meta = getUndoMeta(result)\n const beforeSnapshots = snapshots.before as OrganizationSnapshots | undefined\n const beforeRecord = beforeSnapshots?.view ?? null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const tenantId = resolveTenantIdFromEntity(result)\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(result.id),\n tenantId,\n organizationId: String(result.id),\n })\n const after = serializeOrganization(result, custom)\n const changes = buildChanges(beforeRecord, after as Record<string, unknown>, ['name', 'slug', 'logoUrl', 'logoPreserveAspectRatio', 'isActive', 'parentId'])\n const customDiff = diffCustomFieldChanges(beforeRecord?.custom, custom)\n for (const [key, diff] of Object.entries(customDiff)) {\n changes[`cf_${key}`] = diff\n }\n return {\n actionLabel: translate('directory.audit.organizations.update', 'Update organization'),\n resourceKind: 'directory.organization',\n resourceId: String(result.id),\n changes,\n tenantId: after.tenantId,\n payload: {\n undo: {\n before: beforeSnapshots?.undo ?? null,\n after: captureOrganizationSnapshots(result, meta.childParentsAfter ?? [], custom).undo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const before = payload?.before\n const after = payload?.after\n if (!before) return\n const tenantId = before.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let updated: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n updated = await de.updateOrmEntity({\n entity: Organization,\n where: buildOrganizationUndoTargetFilter(before.id, tenantId),\n apply: (entity) => {\n entity.name = before.name\n if (before.slug !== undefined) entity.slug = before.slug\n if (before.logoUrl !== undefined) entity.logoUrl = before.logoUrl ?? null\n if (before.logoPreserveAspectRatio !== undefined) entity.logoPreserveAspectRatio = !!before.logoPreserveAspectRatio\n entity.isActive = before.isActive\n entity.parentId = before.parentId\n },\n })\n if (!updated) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(updated, tenantId)\n const reset = buildCustomFieldResetMap(before.custom, after?.custom)\n if (Object.keys(reset).length) {\n const resetValues = reset as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: before.id,\n tenantId,\n organizationId: before.id,\n values: resetValues,\n notify: false,\n })\n }\n const childSnapshots = before.childParents\n await restoreChildParents(em, tenantId, childSnapshots)\n await assertReplayKeepsHierarchyAcyclic(em, tenantId, [\n before.id,\n ...(childSnapshots ?? []).map((entry) => entry.childId),\n ])\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: updated,\n identifiers: {\n id: before.id,\n tenantId,\n organizationId: before.id,\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n}\n\nconst deleteOrganizationCommand: CommandHandler<{ body: any; query: Record<string, string> }, Organization> = {\n id: 'directory.organizations.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Organization id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: existing, tenantId } = await loadAuthorizedOrganizationTarget(em, id, ctx)\n const childParentsBefore = tenantId\n ? await loadChildParentSnapshots(em, tenantId, Array.isArray(existing.childIds) ? existing.childIds : [])\n : []\n const custom = await loadCustomFieldSnapshot(em, {\n entityId: E.directory.organization,\n recordId: String(existing.id),\n tenantId,\n organizationId: String(existing.id),\n })\n return { before: captureOrganizationSnapshots(existing, childParentsBefore, custom) }\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Organization id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const { organization: existing, tenantId } = await loadAuthorizedOrganizationTarget(em, id, ctx)\n\n const parentId = existing.parentId ?? null\n const childSnapshotsBefore = await loadChildParentSnapshots(\n em,\n tenantId,\n Array.isArray(existing.childIds) ? existing.childIds : [],\n )\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n\n let resolvedDeleted!: Organization\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n const deleted = await de.deleteOrmEntity({\n entity: Organization,\n where: buildOrganizationMutationFilter(id, tenantId),\n soft: true,\n softDeleteField: 'deletedAt',\n })\n if (!deleted) throw new CrudHttpError(404, { error: 'Not found' })\n setInternalTenantId(deleted, tenantId)\n deleted.isActive = false\n deleted.parentId = null\n resolvedDeleted = deleted\n },\n async () => {\n const deleted = resolvedDeleted\n const childrenFilter: FilterQuery<Organization> = { tenant: tenantId, parentId: id, deletedAt: null }\n const children = await em.find(Organization, childrenFilter)\n const toPersist: Organization[] = []\n for (const child of children) {\n child.parentId = parentId\n toPersist.push(child)\n }\n toPersist.push(deleted)\n if (toPersist.length) em.persist(toPersist)\n setUndoMeta(deleted, { childParentsBefore: childSnapshotsBefore })\n },\n async () => {\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n\n const identifiers = { id, organizationId: id, tenantId }\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: resolvedDeleted,\n identifiers,\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n\n return resolvedDeleted\n },\n buildLog: async ({ snapshots, input }) => {\n const { translate } = await resolveTranslations()\n const beforeSnapshots = snapshots.before as OrganizationSnapshots | undefined\n const beforeSnapshot = beforeSnapshots?.view ?? null\n const beforeUndo = beforeSnapshots?.undo ?? null\n const id = String(input?.body?.id ?? input?.query?.id ?? '')\n const fallbackId = beforeSnapshot?.id ?? null\n const fallbackTenant = beforeSnapshot?.tenantId ?? null\n return {\n actionLabel: translate('directory.audit.organizations.delete', 'Delete organization'),\n resourceKind: 'directory.organization',\n resourceId: id || fallbackId || null,\n snapshotBefore: beforeSnapshot ?? null,\n tenantId: beforeUndo?.tenantId ?? fallbackTenant,\n payload: {\n undo: {\n before: beforeUndo,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<OrganizationUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const tenantId = before.tenantId\n if (!tenantId) return\n await assertOrganizationUndoTenantAccess(ctx, tenantId)\n const em = (ctx.container.resolve('em') as EntityManager)\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n let organization: Organization | null = null\n await withAtomicFlush(em, [\n async () => {\n await lockOrganizationHierarchyForTenant(em, tenantId)\n organization = await em.findOne(\n Organization,\n buildOrganizationUndoTargetFilter(before.id, tenantId),\n )\n if (organization) {\n organization.deletedAt = null\n organization.isActive = before.isActive\n organization.name = before.name\n if (before.slug !== undefined) organization.slug = before.slug\n organization.parentId = before.parentId\n await em.flush()\n if (tenantId) setInternalTenantId(organization, tenantId)\n } else {\n organization = await de.createOrmEntity({\n entity: Organization,\n data: {\n id: before.id,\n name: before.name,\n slug: before.slug ?? null,\n tenant: tenantId ? em.getReference(Tenant, tenantId) : undefined,\n isActive: before.isActive,\n parentId: before.parentId,\n },\n })\n if (tenantId) setInternalTenantId(organization, tenantId)\n }\n if (tenantId) {\n const customValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(customValues).length) {\n const resetValues = customValues as Parameters<DataEngine['setCustomFields']>[0]['values']\n await de.setCustomFields({\n entityId: E.directory.organization,\n recordId: before.id,\n tenantId,\n organizationId: before.id,\n values: resetValues,\n notify: false,\n })\n }\n }\n await restoreChildParents(em, tenantId, before.childParents)\n await assertReplayKeepsHierarchyAcyclic(em, tenantId, [\n before.id,\n ...(before.childParents ?? []).map((entry) => entry.childId),\n ])\n await rebuildHierarchyForTenant(em, tenantId)\n },\n ], { transaction: true })\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: organization,\n identifiers: {\n id: before.id,\n tenantId,\n organizationId: before.id,\n },\n events: organizationCrudEvents,\n indexer: organizationCrudIndexer,\n })\n },\n}\n\ntype OrganizationUndoPayload = {\n before?: OrganizationUndoSnapshot | null\n after?: OrganizationUndoSnapshot | null\n childrenBefore?: ChildParentSnapshot[] | null\n}\n\ntype OrganizationUndoMeta = {\n childParentsBefore?: ChildParentSnapshot[]\n childParentsAfter?: ChildParentSnapshot[]\n}\n\nconst UNDO_META_KEY: unique symbol = Symbol('directory.organization.undoMeta')\n\nfunction getUndoMeta(entity: Organization): OrganizationUndoMeta {\n return (Reflect.get(entity, UNDO_META_KEY) as OrganizationUndoMeta | undefined) ?? {}\n}\n\nfunction setUndoMeta(entity: Organization, meta: Partial<OrganizationUndoMeta>) {\n const current = getUndoMeta(entity)\n Reflect.set(entity, UNDO_META_KEY, { ...current, ...meta })\n}\n\nregisterCommand(createOrganizationCommand)\nregisterCommand(updateOrganizationCommand)\nregisterCommand(deleteOrganizationCommand)\n\nfunction setInternalTenantId(entity: Organization, tenantId: string) {\n Reflect.set(entity, '__tenantId', tenantId)\n}\n\nfunction tenantIdFromContext(ctx: CrudEmitContext<Organization>): string | null {\n return resolveTenantIdFromEntity(ctx.entity) ?? ctx.identifiers.tenantId ?? null\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["recordId"]
|
|
7
7
|
}
|
|
@@ -22,6 +22,21 @@ function normalizeUuid(value) {
|
|
|
22
22
|
if (!v || v.toLowerCase() === "null" || v.toLowerCase() === "undefined") return null;
|
|
23
23
|
return v;
|
|
24
24
|
}
|
|
25
|
+
function findOrganizationParentCycle(organizations, organizationIds) {
|
|
26
|
+
const parents = /* @__PURE__ */ new Map();
|
|
27
|
+
for (const org of organizations) parents.set(String(org.id), normalizeUuid(org.parentId));
|
|
28
|
+
for (const startId of organizationIds) {
|
|
29
|
+
const seen = /* @__PURE__ */ new Set([startId]);
|
|
30
|
+
let currentId = parents.get(startId) ?? null;
|
|
31
|
+
while (currentId && parents.has(currentId)) {
|
|
32
|
+
if (currentId === startId) return startId;
|
|
33
|
+
if (seen.has(currentId)) break;
|
|
34
|
+
seen.add(currentId);
|
|
35
|
+
currentId = parents.get(currentId) ?? null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
25
40
|
function computeHierarchyForOrganizations(organizations, tenantId) {
|
|
26
41
|
const nodes = /* @__PURE__ */ new Map();
|
|
27
42
|
for (const org of organizations) {
|
|
@@ -123,9 +138,25 @@ function computeHierarchyForOrganizations(organizations, tenantId) {
|
|
|
123
138
|
walk(id, []);
|
|
124
139
|
}
|
|
125
140
|
}
|
|
141
|
+
function findCycleCutId(startId) {
|
|
142
|
+
const positions = /* @__PURE__ */ new Map();
|
|
143
|
+
const path = [];
|
|
144
|
+
let currentId = startId;
|
|
145
|
+
while (currentId && nodes.has(currentId) && !visited.has(currentId) && !positions.has(currentId)) {
|
|
146
|
+
positions.set(currentId, path.length);
|
|
147
|
+
path.push(currentId);
|
|
148
|
+
currentId = nodes.get(currentId).parentId;
|
|
149
|
+
}
|
|
150
|
+
if (!currentId || !positions.has(currentId)) return null;
|
|
151
|
+
return path.slice(positions.get(currentId)).reduce((smallest, candidate) => candidate < smallest ? candidate : smallest);
|
|
152
|
+
}
|
|
126
153
|
for (const id of nodes.keys()) {
|
|
127
|
-
|
|
128
|
-
|
|
154
|
+
while (!visited.has(id)) {
|
|
155
|
+
const cutId = findCycleCutId(id) ?? id;
|
|
156
|
+
const cutNode = nodes.get(cutId);
|
|
157
|
+
if (cutNode.parentId) nodes.get(cutNode.parentId)?.children.delete(cutId);
|
|
158
|
+
cutNode.parentId = null;
|
|
159
|
+
walk(cutId, []);
|
|
129
160
|
}
|
|
130
161
|
}
|
|
131
162
|
const ordered = orderedIds.map((id) => computed.get(id)).filter((node) => !!node);
|
|
@@ -162,6 +193,7 @@ async function rebuildHierarchyForTenant(em, tenantId) {
|
|
|
162
193
|
}
|
|
163
194
|
export {
|
|
164
195
|
computeHierarchyForOrganizations,
|
|
196
|
+
findOrganizationParentCycle,
|
|
165
197
|
lockOrganizationHierarchyForTenant,
|
|
166
198
|
rebuildHierarchyForTenant
|
|
167
199
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/directory/lib/hierarchy.ts"],
|
|
4
|
-
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { LockMode } from '@mikro-orm/core'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\n\nexport type ComputedOrganizationNode = {\n id: string\n tenantId: string\n name: string\n pathLabel: string\n parentId: string | null\n depth: number\n rootId: string\n treePath: string\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n}\n\nexport type ComputedHierarchy = {\n map: Map<string, ComputedOrganizationNode>\n ordered: ComputedOrganizationNode[]\n}\n\nexport async function lockOrganizationHierarchyForTenant(\n em: EntityManager,\n tenantId: string,\n): Promise<Organization[]> {\n await em.findOne(\n Tenant,\n { id: tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE, refresh: true },\n )\n return em.find(\n Organization,\n { tenant: tenantId as never, deletedAt: null },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n orderBy: { id: 'ASC' },\n refresh: true,\n },\n )\n}\n\ntype InternalNode = {\n org: Organization\n parentId: string | null\n children: Set<string>\n}\n\nfunction normalizeUuid(value: unknown): string | null {\n if (!value) return null\n const v = String(value).trim()\n if (!v || v.toLowerCase() === 'null' || v.toLowerCase() === 'undefined') return null\n return v\n}\n\nexport function computeHierarchyForOrganizations(organizations: Organization[], tenantId: string): ComputedHierarchy {\n const nodes = new Map<string, InternalNode>()\n\n for (const org of organizations) {\n const id = String(org.id)\n const node: InternalNode = {\n org,\n parentId: normalizeUuid(org.parentId),\n children: new Set<string>(),\n }\n nodes.set(id, node)\n }\n\n // Establish child relationships (ignore missing parents or self-references)\n for (const [id, node] of nodes) {\n const parentId = node.parentId\n if (!parentId || parentId === id) {\n node.parentId = null\n continue\n }\n const parent = nodes.get(parentId)\n if (!parent) {\n node.parentId = null\n continue\n }\n parent.children.add(id)\n }\n\n const computed = new Map<string, ComputedOrganizationNode>()\n const orderedIds: string[] = []\n const orderedSet = new Set<string>()\n const visited = new Set<string>()\n\n function walk(nodeId: string, ancestors: string[]): string[] {\n if (ancestors.includes(nodeId)) {\n // Cycle detected; break by treating as root\n const orgName = nodes.get(nodeId)?.org.name || ''\n computed.set(nodeId, {\n id: nodeId,\n tenantId,\n name: orgName,\n pathLabel: orgName,\n parentId: null,\n depth: 0,\n rootId: nodeId,\n treePath: nodeId,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n isActive: nodes.get(nodeId)?.org.isActive ?? true,\n })\n if (!orderedSet.has(nodeId)) {\n orderedIds.push(nodeId)\n orderedSet.add(nodeId)\n }\n visited.add(nodeId)\n return []\n }\n\n const node = nodes.get(nodeId)\n if (!node) return []\n\n visited.add(nodeId)\n const org = node.org\n const id = String(org.id)\n const nextAncestors = [...ancestors, id]\n if (!orderedSet.has(id)) {\n orderedIds.push(id)\n orderedSet.add(id)\n }\n const childIds = Array.from(node.children)\n .filter((childId) => nodes.has(childId))\n .sort((a, b) => {\n const an = nodes.get(a)!.org.name.toLowerCase()\n const bn = nodes.get(b)!.org.name.toLowerCase()\n if (an === bn) return a.localeCompare(b)\n return an.localeCompare(bn)\n })\n\n const descendantIds: string[] = []\n for (const childId of childIds) {\n const desc = walk(childId, nextAncestors)\n descendantIds.push(childId, ...desc)\n }\n\n const ancestorIds = ancestors\n const depth = ancestorIds.length\n const rootId = ancestorIds.length ? ancestorIds[0] : id\n const treePath = nextAncestors.join('/')\n const ancestorNames = ancestors\n .map((ancestorId) => nodes.get(ancestorId)?.org.name)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n const pathLabel = [...ancestorNames, org.name].join(' / ')\n\n const computedNode: ComputedOrganizationNode = {\n id,\n tenantId,\n name: org.name,\n pathLabel,\n parentId: node.parentId,\n depth,\n rootId,\n treePath,\n ancestorIds,\n childIds,\n descendantIds,\n isActive: !!org.isActive,\n }\n computed.set(id, computedNode)\n return descendantIds\n }\n\n // Walk roots first (nodes without parent or whose parent is missing)\n for (const [id, node] of nodes) {\n if (!node.parentId || !nodes.has(node.parentId)) {\n walk(id, [])\n }\n }\n // Handle orphaned nodes or cycles not reached above\n for (const id of nodes.keys()) {\n
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { LockMode } from '@mikro-orm/core'\nimport { Organization, Tenant } from '@open-mercato/core/modules/directory/data/entities'\n\nexport type ComputedOrganizationNode = {\n id: string\n tenantId: string\n name: string\n pathLabel: string\n parentId: string | null\n depth: number\n rootId: string\n treePath: string\n ancestorIds: string[]\n childIds: string[]\n descendantIds: string[]\n isActive: boolean\n}\n\nexport type ComputedHierarchy = {\n map: Map<string, ComputedOrganizationNode>\n ordered: ComputedOrganizationNode[]\n}\n\nexport async function lockOrganizationHierarchyForTenant(\n em: EntityManager,\n tenantId: string,\n): Promise<Organization[]> {\n await em.findOne(\n Tenant,\n { id: tenantId },\n { lockMode: LockMode.PESSIMISTIC_WRITE, refresh: true },\n )\n return em.find(\n Organization,\n { tenant: tenantId as never, deletedAt: null },\n {\n lockMode: LockMode.PESSIMISTIC_WRITE,\n orderBy: { id: 'ASC' },\n refresh: true,\n },\n )\n}\n\ntype InternalNode = {\n org: Organization\n parentId: string | null\n children: Set<string>\n}\n\nfunction normalizeUuid(value: unknown): string | null {\n if (!value) return null\n const v = String(value).trim()\n if (!v || v.toLowerCase() === 'null' || v.toLowerCase() === 'undefined') return null\n return v\n}\n\nexport function findOrganizationParentCycle(\n organizations: ReadonlyArray<Pick<Organization, 'id' | 'parentId'>>,\n organizationIds: Iterable<string>,\n): string | null {\n const parents = new Map<string, string | null>()\n for (const org of organizations) parents.set(String(org.id), normalizeUuid(org.parentId))\n for (const startId of organizationIds) {\n const seen = new Set<string>([startId])\n let currentId = parents.get(startId) ?? null\n while (currentId && parents.has(currentId)) {\n if (currentId === startId) return startId\n if (seen.has(currentId)) break\n seen.add(currentId)\n currentId = parents.get(currentId) ?? null\n }\n }\n return null\n}\n\nexport function computeHierarchyForOrganizations(organizations: Organization[], tenantId: string): ComputedHierarchy {\n const nodes = new Map<string, InternalNode>()\n\n for (const org of organizations) {\n const id = String(org.id)\n const node: InternalNode = {\n org,\n parentId: normalizeUuid(org.parentId),\n children: new Set<string>(),\n }\n nodes.set(id, node)\n }\n\n // Establish child relationships (ignore missing parents or self-references)\n for (const [id, node] of nodes) {\n const parentId = node.parentId\n if (!parentId || parentId === id) {\n node.parentId = null\n continue\n }\n const parent = nodes.get(parentId)\n if (!parent) {\n node.parentId = null\n continue\n }\n parent.children.add(id)\n }\n\n const computed = new Map<string, ComputedOrganizationNode>()\n const orderedIds: string[] = []\n const orderedSet = new Set<string>()\n const visited = new Set<string>()\n\n function walk(nodeId: string, ancestors: string[]): string[] {\n if (ancestors.includes(nodeId)) {\n // Cycle detected; break by treating as root\n const orgName = nodes.get(nodeId)?.org.name || ''\n computed.set(nodeId, {\n id: nodeId,\n tenantId,\n name: orgName,\n pathLabel: orgName,\n parentId: null,\n depth: 0,\n rootId: nodeId,\n treePath: nodeId,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n isActive: nodes.get(nodeId)?.org.isActive ?? true,\n })\n if (!orderedSet.has(nodeId)) {\n orderedIds.push(nodeId)\n orderedSet.add(nodeId)\n }\n visited.add(nodeId)\n return []\n }\n\n const node = nodes.get(nodeId)\n if (!node) return []\n\n visited.add(nodeId)\n const org = node.org\n const id = String(org.id)\n const nextAncestors = [...ancestors, id]\n if (!orderedSet.has(id)) {\n orderedIds.push(id)\n orderedSet.add(id)\n }\n const childIds = Array.from(node.children)\n .filter((childId) => nodes.has(childId))\n .sort((a, b) => {\n const an = nodes.get(a)!.org.name.toLowerCase()\n const bn = nodes.get(b)!.org.name.toLowerCase()\n if (an === bn) return a.localeCompare(b)\n return an.localeCompare(bn)\n })\n\n const descendantIds: string[] = []\n for (const childId of childIds) {\n const desc = walk(childId, nextAncestors)\n descendantIds.push(childId, ...desc)\n }\n\n const ancestorIds = ancestors\n const depth = ancestorIds.length\n const rootId = ancestorIds.length ? ancestorIds[0] : id\n const treePath = nextAncestors.join('/')\n const ancestorNames = ancestors\n .map((ancestorId) => nodes.get(ancestorId)?.org.name)\n .filter((value): value is string => typeof value === 'string' && value.length > 0)\n const pathLabel = [...ancestorNames, org.name].join(' / ')\n\n const computedNode: ComputedOrganizationNode = {\n id,\n tenantId,\n name: org.name,\n pathLabel,\n parentId: node.parentId,\n depth,\n rootId,\n treePath,\n ancestorIds,\n childIds,\n descendantIds,\n isActive: !!org.isActive,\n }\n computed.set(id, computedNode)\n return descendantIds\n }\n\n // Walk roots first (nodes without parent or whose parent is missing)\n for (const [id, node] of nodes) {\n if (!node.parentId || !nodes.has(node.parentId)) {\n walk(id, [])\n }\n }\n\n function findCycleCutId(startId: string): string | null {\n const positions = new Map<string, number>()\n const path: string[] = []\n let currentId: string | null = startId\n while (currentId && nodes.has(currentId) && !visited.has(currentId) && !positions.has(currentId)) {\n positions.set(currentId, path.length)\n path.push(currentId)\n currentId = nodes.get(currentId)!.parentId\n }\n if (!currentId || !positions.has(currentId)) return null\n return path\n .slice(positions.get(currentId))\n .reduce((smallest, candidate) => (candidate < smallest ? candidate : smallest))\n }\n\n // Handle orphaned nodes or cycles not reached above\n for (const id of nodes.keys()) {\n while (!visited.has(id)) {\n const cutId = findCycleCutId(id) ?? id\n const cutNode = nodes.get(cutId)!\n if (cutNode.parentId) nodes.get(cutNode.parentId)?.children.delete(cutId)\n cutNode.parentId = null\n walk(cutId, [])\n }\n }\n\n const ordered = orderedIds\n .map((id) => computed.get(id))\n .filter((node): node is ComputedOrganizationNode => !!node)\n\n return { map: computed, ordered }\n}\n\nexport async function rebuildHierarchyForTenant(em: EntityManager, tenantId: string): Promise<ComputedHierarchy> {\n const organizations = await em.find(Organization, { tenant: tenantId as any, deletedAt: null }, { orderBy: { name: 'ASC' } })\n const hierarchy = computeHierarchyForOrganizations(organizations, tenantId)\n const now = new Date()\n\n for (const org of organizations) {\n const computed = hierarchy.map.get(String(org.id))\n if (!computed) {\n org.parentId = null\n org.rootId = String(org.id)\n org.treePath = String(org.id)\n org.depth = 0\n org.ancestorIds = []\n org.childIds = []\n org.descendantIds = []\n org.updatedAt = now\n continue\n }\n org.parentId = computed.parentId\n org.rootId = computed.rootId\n org.treePath = computed.treePath\n org.depth = computed.depth\n org.ancestorIds = computed.ancestorIds\n org.childIds = computed.childIds\n org.descendantIds = computed.descendantIds\n org.updatedAt = now\n }\n\n await em.flush()\n return hierarchy\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -9,6 +9,7 @@ import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/er
|
|
|
9
9
|
import { parseScopedCommandInput } from "@open-mercato/shared/lib/api/scoped";
|
|
10
10
|
import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
11
11
|
import { plannerAvailabilityDateSpecificReplaceSchema } from "../data/validators.js";
|
|
12
|
+
import { zonedDateKey } from "../lib/availabilityTimezone.js";
|
|
12
13
|
import { serializeOperationMetadata } from "@open-mercato/shared/lib/commands/operationMetadata";
|
|
13
14
|
import {
|
|
14
15
|
runCrudMutationGuardAfterSuccess,
|
|
@@ -80,7 +81,7 @@ async function POST(req) {
|
|
|
80
81
|
const blocked = rules.some((rule) => {
|
|
81
82
|
const window = parseAvailabilityRuleWindow(rule);
|
|
82
83
|
if (window.repeat !== "once") return false;
|
|
83
|
-
return dateSet.has(
|
|
84
|
+
return dateSet.has(zonedDateKey(window.startAt, rule.timezone));
|
|
84
85
|
});
|
|
85
86
|
if (blocked) {
|
|
86
87
|
throw new CrudHttpError(403, { error: translate("planner.availability.errors.unauthorized", "Unauthorized") });
|
|
@@ -190,12 +191,6 @@ function resolveDateSet(input) {
|
|
|
190
191
|
}
|
|
191
192
|
return dates;
|
|
192
193
|
}
|
|
193
|
-
function formatDateKey(value) {
|
|
194
|
-
const year = value.getFullYear();
|
|
195
|
-
const month = String(value.getMonth() + 1).padStart(2, "0");
|
|
196
|
-
const day = String(value.getDate()).padStart(2, "0");
|
|
197
|
-
return `${year}-${month}-${day}`;
|
|
198
|
-
}
|
|
199
194
|
export {
|
|
200
195
|
POST,
|
|
201
196
|
metadata,
|