@open-mercato/core 0.4.6-develop-2ba4e02ffb → 0.4.6-develop-96c36a4b2a
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/dist/modules/customers/api/people/[id]/route.js +4 -2
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/commands/people.js +15 -0
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/package.json +2 -2
- package/src/modules/customers/api/people/[id]/route.ts +2 -0
- package/src/modules/customers/commands/people.ts +9 -0
|
@@ -524,7 +524,8 @@ async function GET(_req, ctx) {
|
|
|
524
524
|
timezone: profile.timezone,
|
|
525
525
|
linkedInUrl: profile.linkedInUrl,
|
|
526
526
|
twitterUrl: profile.twitterUrl,
|
|
527
|
-
companyEntityId: profile.company ? typeof profile.company === "string" ? profile.company : profile.company.id : null
|
|
527
|
+
companyEntityId: profile.company ? typeof profile.company === "string" ? profile.company : profile.company.id : null,
|
|
528
|
+
updatedAt: profile.updatedAt.toISOString()
|
|
528
529
|
} : null,
|
|
529
530
|
customFields,
|
|
530
531
|
tags: serializeTags(tagAssignments),
|
|
@@ -672,7 +673,8 @@ const personDetailResponseSchema = z.object({
|
|
|
672
673
|
timezone: z.string().nullable().optional(),
|
|
673
674
|
linkedInUrl: z.string().nullable().optional(),
|
|
674
675
|
twitterUrl: z.string().nullable().optional(),
|
|
675
|
-
companyEntityId: z.string().uuid().nullable().optional()
|
|
676
|
+
companyEntityId: z.string().uuid().nullable().optional(),
|
|
677
|
+
updatedAt: z.string()
|
|
676
678
|
}).nullable(),
|
|
677
679
|
customFields: z.record(z.string(), z.unknown()),
|
|
678
680
|
tags: z.array(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/customers/api/people/%5Bid%5D/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerPersonProfile,\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerTagAssignment,\n CustomerTag,\n CustomerDealPersonLink,\n CustomerDeal,\n CustomerTodoLink,\n} from '../../../data/entities'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport { mergePersonCustomFieldValues, resolvePersonCustomFieldRouting } from '../../../lib/customFieldRouting'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanFromUnknown, parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nfunction parseIncludeParams(request: Request): Set<string> {\n const url = new URL(request.url)\n const raw = url.searchParams.getAll('include')\n const tokens = new Set<string>()\n raw.forEach((entry) => {\n if (!entry) return\n entry\n .split(',')\n .map((part) => part.trim().toLowerCase())\n .filter((part) => part.length > 0)\n .forEach((part) => tokens.add(part))\n })\n return tokens\n}\n\nfunction forbidden(message: string) {\n return NextResponse.json({ error: message }, { status: 403 })\n}\n\nfunction notFound(message: string) {\n return NextResponse.json({ error: message }, { status: 404 })\n}\n\nfunction serializeTags(assignments: CustomerTagAssignment[]): Array<{ id: string; label: string; color: string | null }> {\n return assignments\n .map((assignment) => {\n const tag = assignment.tag as CustomerTag | string | null\n if (!tag || typeof tag === 'string') return null\n return {\n id: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }\n })\n .filter(\n (tag: { id: string; label: string; color: string | null } | null): tag is {\n id: string\n label: string\n color: string | null\n } => tag !== null,\n )\n}\n\ntype TodoDetail = {\n title: string | null\n isDone: boolean | null\n priority: number | null\n severity: string | null\n description: string | null\n dueAt: string | null\n organizationId: string | null\n customValues: Record<string, unknown> | null\n}\n\nfunction extractTodoTitle(record: Record<string, unknown>): string | null {\n const candidates = ['title', 'subject', 'name', 'summary', 'text', 'description']\n for (const key of candidates) {\n const value = record[key]\n if (typeof value === 'string' && value.trim().length > 0) {\n return value.trim()\n }\n }\n return null\n}\n\nfunction parseNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = Number(trimmed)\n if (!Number.isNaN(parsed)) return parsed\n }\n return null\n}\n\nfunction parseDateValue(value: unknown): string | null {\n if (value instanceof Date) {\n const ts = value.getTime()\n return Number.isNaN(ts) ? null : value.toISOString()\n }\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const candidate = new Date(trimmed)\n if (!Number.isNaN(candidate.getTime())) return candidate.toISOString()\n }\n return null\n}\n\nfunction readCustomField(record: Record<string, unknown>, key: string): unknown {\n const custom = record.custom ?? record.customFields ?? record.cf\n if (custom && typeof custom === 'object') {\n const bucket = custom as Record<string, unknown>\n if (key in bucket) return bucket[key]\n }\n return undefined\n}\n\ntype RouteProfilerMark = { label: string; time: bigint; extra?: Record<string, unknown> }\ntype RouteProfiler = { enabled: boolean; mark: (label: string, extra?: Record<string, unknown>) => void; end: (extra?: Record<string, unknown>) => void }\n\nfunction normalizeProfilerTokens(input: string | null | undefined): string[] {\n if (!input) return []\n return input\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter((token) => token.length > 0)\n}\n\nfunction profilerMatches(scope: string, tokens: string[]): boolean {\n if (!tokens.length) return false\n const lower = scope.toLowerCase()\n return tokens.some((token) => {\n if (token === '*' || token === 'all' || parseBooleanToken(token) === true) return true\n if (token.endsWith('*')) {\n const prefix = token.slice(0, -1)\n return prefix.length === 0 ? true : lower.startsWith(prefix)\n }\n return token === lower\n })\n}\n\nfunction isRouteProfilingEnabled(scope: string): boolean {\n const candidates = [\n process.env.OM_CRUD_PROFILE,\n process.env.NEXT_PUBLIC_OM_CRUD_PROFILE,\n process.env.OM_ROUTE_PROFILE,\n process.env.NEXT_PUBLIC_OM_ROUTE_PROFILE,\n ]\n for (const raw of candidates) {\n if (!raw) continue\n const tokens = normalizeProfilerTokens(raw)\n if (profilerMatches(scope, tokens)) return true\n }\n return false\n}\n\nfunction createRouteProfiler(scope: string): RouteProfiler {\n if (!isRouteProfilingEnabled(scope)) {\n return { enabled: false, mark: () => {}, end: () => {} }\n }\n const marks: RouteProfilerMark[] = [{ label: 'start', time: process.hrtime.bigint() }]\n const round = (value: number) => Math.round(value * 1000) / 1000\n return {\n enabled: true,\n mark(label, extra) {\n marks.push({ label, time: process.hrtime.bigint(), extra })\n },\n end(extra) {\n marks.push({ label: 'end', time: process.hrtime.bigint(), extra })\n const segments: Array<{ step: string; durationMs: number; extra?: Record<string, unknown> }> = []\n for (let idx = 1; idx < marks.length; idx += 1) {\n const current = marks[idx]\n const previous = marks[idx - 1]\n if (current.label === 'end') continue\n const durationMs = Number(current.time - previous.time) / 1_000_000\n segments.push({\n step: current.label,\n durationMs: round(durationMs),\n ...(current.extra ? { extra: current.extra } : {}),\n })\n }\n const totalNs = marks[marks.length - 1].time - marks[0].time\n const payload: Record<string, unknown> = {\n scope,\n totalMs: round(Number(totalNs) / 1_000_000),\n steps: segments,\n }\n const tail = marks[marks.length - 1]\n if (tail.extra && Object.keys(tail.extra).length > 0) payload.meta = tail.extra\n else if (extra && Object.keys(extra).length > 0) payload.meta = extra\n try {\n console.info('[route:profile]', payload)\n } catch {\n // ignore logging failures\n }\n },\n }\n}\n\nasync function resolveTodoDetails(\n queryEngine: QueryEngine,\n links: CustomerTodoLink[],\n tenantId: string | null,\n organizationIds: Array<string | null>,\n profiler?: RouteProfiler,\n): Promise<Map<string, TodoDetail>> {\n const details = new Map<string, TodoDetail>()\n if (!links.length || !tenantId) return details\n\n const scopedOrgIds = organizationIds\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n\n const idsBySource = new Map<string, Set<string>>()\n for (const link of links) {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : 'example:todo'\n const id = typeof link.todoId === 'string' && link.todoId.trim().length > 0 ? link.todoId : String(link.todoId ?? '')\n if (!id) continue\n if (!idsBySource.has(source)) idsBySource.set(source, new Set<string>())\n idsBySource.get(source)!.add(id)\n }\n\n profiler?.mark('todo_links_grouped', { sourceCount: idsBySource.size, linkCount: links.length })\n\n for (const [source, idSet] of idsBySource.entries()) {\n const ids = Array.from(idSet)\n if (!ids.length) continue\n profiler?.mark('todo_query_start', { source, count: ids.length })\n try {\n const result = await queryEngine.query<Record<string, unknown>>(source as EntityId, {\n tenantId,\n organizationIds: scopedOrgIds.length > 0 ? scopedOrgIds : undefined,\n filters: { id: { $in: ids } },\n includeCustomFields: ['priority', 'due_at', 'severity', 'description'],\n page: { page: 1, pageSize: Math.max(ids.length, 1) },\n })\n const itemCount = Array.isArray(result.items) ? result.items.length : 0\n profiler?.mark('todo_query_complete', { source, itemCount })\n let enriched = 0\n for (const item of result.items ?? []) {\n if (!item || typeof item !== 'object') continue\n const record = item as Record<string, unknown>\n const rawId = typeof record.id === 'string' && record.id.trim().length > 0 ? record.id : String(record.id ?? '')\n if (!rawId) continue\n const title = extractTodoTitle(record)\n const isDone = (() => {\n const direct = parseBooleanFromUnknown(record.is_done)\n if (direct !== null) return direct\n const custom = parseBooleanFromUnknown(readCustomField(record, 'is_done'))\n if (custom !== null) return custom\n const generic = parseBooleanFromUnknown(record.isDone)\n if (generic !== null) return generic\n return parseBooleanFromUnknown(readCustomField(record, 'isDone'))\n })()\n const priority = (() => {\n const candidates = [\n record['cf:priority'],\n record['cf_priority'],\n record.priority,\n readCustomField(record, 'priority'),\n ]\n for (const candidate of candidates) {\n const parsed = parseNumber(candidate)\n if (parsed !== null) return parsed\n }\n return null\n })()\n const severity = (() => {\n const candidates = [\n record['cf:severity'],\n record['cf_severity'],\n readCustomField(record, 'severity'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string') {\n const trimmed = candidate.trim()\n if (trimmed.length) return trimmed\n }\n }\n return null\n })()\n const descriptionValue = (() => {\n const candidates = [\n record.description,\n record['cf:description'],\n record['cf_description'],\n readCustomField(record, 'description'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string') {\n const trimmed = candidate.trim()\n if (trimmed.length) return trimmed\n }\n }\n return null\n })()\n const dueAt = (() => {\n const candidates = [\n record.due_at,\n record.dueAt,\n record['cf:due_at'],\n record['cf_due_at'],\n readCustomField(record, 'due_at'),\n readCustomField(record, 'dueAt'),\n ]\n for (const candidate of candidates) {\n const parsed = parseDateValue(candidate)\n if (parsed) return parsed\n }\n return null\n })()\n const organizationId = typeof record.organization_id === 'string' && record.organization_id.trim().length > 0\n ? record.organization_id\n : (typeof record.organizationId === 'string' && record.organizationId.trim().length > 0 ? record.organizationId : null)\n const customValues: Record<string, unknown> = {}\n const assignCustomValue = (key: unknown, value: unknown) => {\n if (typeof key !== 'string') return\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n customValues[trimmedKey] = value === undefined ? null : value\n }\n for (const [rawKey, rawValue] of Object.entries(record)) {\n if (rawKey.startsWith('cf:')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n } else if (rawKey.startsWith('cf_')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n }\n }\n const nestedCustom = record.custom ?? record.customFields ?? record.cf\n if (nestedCustom && typeof nestedCustom === 'object') {\n for (const [nestedKey, nestedValue] of Object.entries(nestedCustom as Record<string, unknown>)) {\n assignCustomValue(nestedKey, nestedValue)\n }\n }\n\n details.set(`${source}:${rawId}`, {\n title,\n isDone,\n priority,\n severity,\n description: descriptionValue,\n dueAt,\n organizationId,\n customValues: Object.keys(customValues).length ? customValues : null,\n })\n enriched += 1\n }\n profiler?.mark('todo_items_processed', { source, enriched })\n } catch (err) {\n profiler?.mark('todo_query_failed', { source, error: err instanceof Error ? err.message : String(err) })\n console.warn(`customers.people.detail: failed to resolve todos for source ${source}`, err)\n }\n }\n\n profiler?.mark('todo_details_ready', { enrichedCount: details.size })\n return details\n}\n\nexport async function GET(_req: Request, ctx: { params?: { id?: string } }) {\n const profiler = createRouteProfiler('customers.people.detail')\n profiler.mark('request_received')\n\n const includeTokens = parseIncludeParams(_req)\n profiler.mark('includes_parsed', { include: Array.from(includeTokens) })\n\n const includeActivities = includeTokens.has('activities')\n const includeAddresses = includeTokens.has('addresses')\n const includeComments = includeTokens.has('comments') || includeTokens.has('notes')\n const includeDeals = includeTokens.has('deals')\n const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')\n\n let statusCode = 500\n let profileMeta: Record<string, unknown> | undefined\n let addresses: CustomerAddress[] = []\n let comments: CustomerComment[] = []\n let activities: CustomerActivity[] = []\n let todoLinks: CustomerTodoLink[] = []\n let todoDetails = new Map<string, TodoDetail>()\n let deals: CustomerDeal[] = []\n let tagAssignments: CustomerTagAssignment[] = []\n let userMap = new Map<string, { name: string | null; email: string | null }>()\n let customFields: Record<string, unknown> = {}\n let viewerUserId: string | null = null\n let profile: CustomerPersonProfile | null = null\n\n try {\n const parse = paramsSchema.safeParse({ id: ctx.params?.id })\n if (!parse.success) {\n statusCode = 400\n profileMeta = { reason: 'invalid_person_id' }\n return NextResponse.json({ error: 'Invalid person id' }, { status: 400 })\n }\n profiler.mark('params_resolved', { id: parse.data.id })\n\n const auth = await getAuthFromRequest(_req)\n if (!auth) {\n profiler.mark('auth_missing')\n statusCode = 401\n profileMeta = { reason: 'unauthorized' }\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n profiler.mark('auth_resolved', {\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n userId: auth.sub ?? null,\n isApiKey: !!auth.isApiKey,\n })\n viewerUserId = auth.isApiKey ? null : auth.sub ?? null\n\n const container = await createRequestContainer()\n profiler.mark('container_resolved')\n\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: _req })\n profiler.mark('scope_resolved', {\n scopedOrganizations: Array.isArray(scope?.filterIds) ? scope.filterIds.length : 0,\n })\n const em = (container.resolve('em') as EntityManager)\n\n const person = await em.findOne(CustomerEntity, { id: parse.data.id, kind: 'person', deletedAt: null })\n profiler.mark('person_loaded', { found: !!person })\n if (!person) {\n statusCode = 404\n profileMeta = { reason: 'person_not_found' }\n return notFound('Person not found')\n }\n\n if (auth.tenantId && person.tenantId !== auth.tenantId) {\n statusCode = 404\n profileMeta = { reason: 'person_tenant_mismatch' }\n return notFound('Person not found')\n }\n const allowedOrgIds = new Set<string>()\n if (scope?.filterIds?.length) scope.filterIds.forEach((id) => allowedOrgIds.add(id))\n else if (auth.orgId) allowedOrgIds.add(auth.orgId)\n\n if (allowedOrgIds.size && person.organizationId && !allowedOrgIds.has(person.organizationId)) {\n statusCode = 403\n profileMeta = { reason: 'organization_forbidden' }\n return forbidden('Access denied')\n }\n\n profile = await em.findOne(CustomerPersonProfile, { entity: person })\n profiler.mark('profile_loaded', { found: !!profile })\n\n if (includeAddresses) {\n addresses = await em.find(CustomerAddress, { entity: person.id }, { orderBy: { isPrimary: 'desc', createdAt: 'desc' } })\n profiler.mark('addresses_loaded', { count: addresses.length })\n }\n\n tagAssignments = await findWithDecryption(\n em,\n CustomerTagAssignment,\n { entity: person.id },\n { populate: ['tag'] },\n { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },\n )\n profiler.mark('tags_loaded', { count: tagAssignments.length })\n\n if (includeComments) {\n comments = await em.find(CustomerComment, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })\n profiler.mark('comments_loaded', { count: comments.length })\n }\n\n if (includeActivities) {\n activities = await em.find(CustomerActivity, { entity: person.id }, { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 })\n profiler.mark('activities_loaded', { count: activities.length })\n }\n\n if (includeTodos) {\n todoLinks = await em.find(CustomerTodoLink, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })\n profiler.mark('todo_links_loaded', { count: todoLinks.length })\n if (todoLinks.length) {\n const queryEngine = (container.resolve('queryEngine') as QueryEngine)\n try {\n todoDetails = await resolveTodoDetails(\n queryEngine,\n todoLinks,\n person.tenantId ?? auth.tenantId ?? null,\n [person.organizationId ?? null, ...(scope?.filterIds ?? [])],\n profiler,\n )\n } catch (err) {\n console.warn('customers.people.detail: failed to enrich todo links', err)\n }\n profiler.mark('todo_details_enriched', { count: todoDetails.size, links: todoLinks.length })\n }\n }\n\n const authorIds = new Set<string>()\n if (includeActivities) {\n for (const activity of activities) {\n if (activity.authorUserId) authorIds.add(activity.authorUserId)\n }\n }\n if (includeComments) {\n for (const comment of comments) {\n if (comment.authorUserId) authorIds.add(comment.authorUserId)\n }\n }\n if (viewerUserId) authorIds.add(viewerUserId)\n\n if (authorIds.size) {\n const users = await em.find(User, { id: { $in: Array.from(authorIds) } })\n userMap = new Map(\n users.map((user) => [\n user.id,\n {\n name: user.name ?? null,\n email: user.email ?? null,\n },\n ])\n )\n profiler.mark('authors_loaded', { count: userMap.size })\n }\n\n if (includeDeals) {\n const dealLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { person: person.id },\n { populate: ['deal'] },\n { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },\n )\n deals = dealLinks\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter((deal): deal is CustomerDeal => !!deal && typeof deal !== 'string')\n profiler.mark('deals_loaded', { count: deals.length })\n }\n\n const entityCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_entity,\n recordIds: [person.id],\n tenantIdByRecord: { [person.id]: person.tenantId ?? null },\n organizationIdByRecord: { [person.id]: person.organizationId ?? null },\n tenantFallbacks: [\n person.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n profiler.mark('entity_custom_fields_loaded', { keys: Object.keys(entityCustomFieldValues?.[person.id] ?? {}).length })\n\n let profileCustomFieldValues: Record<string, Record<string, unknown>> = {}\n const profileId = profile?.id ?? null\n if (profileId) {\n profileCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_person_profile,\n recordIds: [profileId],\n tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },\n organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },\n tenantFallbacks: [\n profile?.tenantId ?? person.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n profiler.mark('profile_custom_fields_loaded', { keys: Object.keys(profileCustomFieldValues?.[profileId] ?? {}).length })\n }\n\n const routing = await resolvePersonCustomFieldRouting(em, person.tenantId ?? null, person.organizationId ?? null)\n profiler.mark('custom_field_routing_resolved', { keys: routing.size })\n customFields = mergePersonCustomFieldValues(\n routing,\n entityCustomFieldValues?.[person.id] ?? {},\n profileId ? profileCustomFieldValues?.[profileId] ?? {} : {},\n )\n profiler.mark('custom_fields_merged', { keys: Object.keys(customFields).length })\n\n const viewerUserIdFinal = viewerUserId\n const response = NextResponse.json({\n person: {\n id: person.id,\n displayName: person.displayName,\n description: person.description,\n ownerUserId: person.ownerUserId,\n primaryEmail: person.primaryEmail,\n primaryPhone: person.primaryPhone,\n status: person.status,\n lifecycleStage: person.lifecycleStage,\n source: person.source,\n nextInteractionAt: person.nextInteractionAt ? person.nextInteractionAt.toISOString() : null,\n nextInteractionName: person.nextInteractionName,\n nextInteractionRefId: person.nextInteractionRefId,\n nextInteractionIcon: person.nextInteractionIcon,\n nextInteractionColor: person.nextInteractionColor,\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n isActive: person.isActive,\n createdAt: person.createdAt.toISOString(),\n updatedAt: person.updatedAt.toISOString(),\n },\n profile: profile\n ? {\n id: profile.id,\n firstName: profile.firstName,\n lastName: profile.lastName,\n preferredName: profile.preferredName,\n jobTitle: profile.jobTitle,\n department: profile.department,\n seniority: profile.seniority,\n timezone: profile.timezone,\n linkedInUrl: profile.linkedInUrl,\n twitterUrl: profile.twitterUrl,\n companyEntityId: profile.company ? (typeof profile.company === 'string' ? profile.company : profile.company.id) : null,\n }\n : null,\n customFields,\n tags: serializeTags(tagAssignments),\n addresses: includeAddresses\n ? addresses.map((address) => ({\n id: address.id,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n buildingNumber: address.buildingNumber,\n flatNumber: address.flatNumber,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n createdAt: address.createdAt.toISOString(),\n }))\n : [],\n comments: includeComments\n ? comments.map((comment) => {\n const authorInfo = comment.authorUserId ? userMap.get(comment.authorUserId) : null\n return {\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId,\n authorName: authorInfo?.name ?? null,\n authorEmail: authorInfo?.email ?? null,\n dealId: comment.deal ? (typeof comment.deal === 'string' ? comment.deal : comment.deal.id) : null,\n createdAt: comment.createdAt.toISOString(),\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n })\n : [],\n activities: includeActivities\n ? activities.map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt ? activity.occurredAt.toISOString() : null,\n dealId: activity.deal ? (typeof activity.deal === 'string' ? activity.deal : activity.deal.id) : null,\n authorUserId: activity.authorUserId,\n authorName: activity.authorUserId ? userMap.get(activity.authorUserId)?.name ?? null : null,\n authorEmail: activity.authorUserId ? userMap.get(activity.authorUserId)?.email ?? null : null,\n createdAt: activity.createdAt.toISOString(),\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n }))\n : [],\n deals: includeDeals\n ? deals.map((deal) => ({\n id: deal.id,\n title: deal.title,\n status: deal.status,\n pipelineStage: deal.pipelineStage,\n valueAmount: deal.valueAmount,\n valueCurrency: deal.valueCurrency,\n probability: deal.probability,\n expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,\n ownerUserId: deal.ownerUserId,\n source: deal.source,\n createdAt: deal.createdAt.toISOString(),\n updatedAt: deal.updatedAt.toISOString(),\n }))\n : [],\n todos: includeTodos\n ? todoLinks.map((link) => {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : 'example:todo'\n const key = `${source}:${link.todoId}`\n const detail = todoDetails.get(key)\n return {\n id: link.id,\n todoId: link.todoId,\n todoSource: source,\n createdAt: link.createdAt.toISOString(),\n createdByUserId: link.createdByUserId,\n title: detail?.title ?? null,\n isDone: detail?.isDone ?? null,\n priority: detail?.priority ?? null,\n severity: detail?.severity ?? null,\n description: detail?.description ?? null,\n dueAt: detail?.dueAt ?? null,\n todoOrganizationId: detail?.organizationId ?? null,\n customValues: detail?.customValues ?? null,\n }\n })\n : [],\n viewer: {\n userId: viewerUserIdFinal,\n name: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.name ?? null : null,\n email: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.email ?? auth.email ?? null : auth.email ?? null,\n },\n })\n statusCode = 200\n profileMeta = {\n include: Array.from(includeTokens),\n counts: {\n tags: tagAssignments.length,\n comments: comments.length,\n activities: activities.length,\n todos: todoLinks.length,\n addresses: addresses.length,\n deals: deals.length,\n },\n }\n profiler.mark('response_ready', { status: statusCode })\n return response\n } catch (err) {\n if (statusCode < 400) statusCode = 500\n const message = err instanceof Error ? err.message : String(err)\n profileMeta = { ...(profileMeta ?? {}), error: message }\n throw err\n } finally {\n profiler.end({ status: statusCode, ...(profileMeta ?? {}) })\n }\n}\nconst personDetailQuerySchema = z.object({\n include: z\n .string()\n .optional()\n .describe('Comma-separated list of relations to include (addresses, comments, activities, deals, todos).'),\n}).passthrough()\n\nconst personDetailResponseSchema = z.object({\n person: z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n nextInteractionAt: z.string().nullable().optional(),\n nextInteractionName: z.string().nullable().optional(),\n nextInteractionRefId: z.string().nullable().optional(),\n nextInteractionIcon: z.string().nullable().optional(),\n nextInteractionColor: z.string().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n isActive: z.boolean().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n profile: z\n .object({\n id: z.string().uuid(),\n firstName: z.string().nullable().optional(),\n lastName: z.string().nullable().optional(),\n preferredName: z.string().nullable().optional(),\n jobTitle: z.string().nullable().optional(),\n department: z.string().nullable().optional(),\n seniority: z.string().nullable().optional(),\n timezone: z.string().nullable().optional(),\n linkedInUrl: z.string().nullable().optional(),\n twitterUrl: z.string().nullable().optional(),\n companyEntityId: z.string().uuid().nullable().optional(),\n })\n .nullable(),\n customFields: z.record(z.string(), z.unknown()),\n tags: z.array(\n z.object({\n id: z.string().uuid(),\n label: z.string(),\n color: z.string().nullable().optional(),\n }),\n ),\n addresses: z.array(\n z.object({\n id: z.string().uuid(),\n name: z.string().nullable().optional(),\n purpose: z.string().nullable().optional(),\n addressLine1: z.string().nullable().optional(),\n addressLine2: z.string().nullable().optional(),\n buildingNumber: z.string().nullable().optional(),\n flatNumber: z.string().nullable().optional(),\n city: z.string().nullable().optional(),\n region: z.string().nullable().optional(),\n postalCode: z.string().nullable().optional(),\n country: z.string().nullable().optional(),\n latitude: z.number().nullable().optional(),\n longitude: z.number().nullable().optional(),\n isPrimary: z.boolean().nullable().optional(),\n createdAt: z.string(),\n }),\n ),\n comments: z.array(\n z.object({\n id: z.string().uuid(),\n body: z.string().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n activities: z.array(\n z.object({\n id: z.string().uuid(),\n activityType: z.string(),\n subject: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n deals: z.array(\n z.object({\n id: z.string().uuid(),\n title: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipelineStage: z.string().nullable().optional(),\n valueAmount: z.number().nullable().optional(),\n valueCurrency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expectedCloseAt: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n todos: z.array(\n z.object({\n id: z.string().uuid(),\n todoId: z.string().uuid(),\n todoSource: z.string(),\n createdAt: z.string(),\n createdByUserId: z.string().uuid().nullable().optional(),\n title: z.string().nullable().optional(),\n isDone: z.boolean().nullable().optional(),\n priority: z.number().nullable().optional(),\n severity: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n dueAt: z.string().nullable().optional(),\n todoOrganizationId: z.string().uuid().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n }),\n ),\n viewer: z.object({\n userId: z.string().uuid().nullable(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n }),\n})\n\nconst personDetailErrorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Customers',\n summary: 'Fetch person detail',\n methods: {\n GET: {\n summary: 'Fetch person with related data',\n description: 'Returns a person customer record with optional related resources such as addresses, comments, activities, deals, and todos.',\n query: personDetailQuerySchema,\n responses: [\n { status: 200, description: 'Person detail payload', schema: personDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: personDetailErrorSchema },\n { status: 401, description: 'Unauthorized', schema: personDetailErrorSchema },\n { status: 403, description: 'Forbidden for tenant/organization scope', schema: personDetailErrorSchema },\n { status: 404, description: 'Person not found', schema: personDetailErrorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerEntity,\n CustomerPersonProfile,\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerTagAssignment,\n CustomerTag,\n CustomerDealPersonLink,\n CustomerDeal,\n CustomerTodoLink,\n} from '../../../data/entities'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'\nimport { E } from '#generated/entities.ids.generated'\nimport { mergePersonCustomFieldValues, resolvePersonCustomFieldRouting } from '../../../lib/customFieldRouting'\nimport type { QueryEngine } from '@open-mercato/shared/lib/query/types'\nimport type { EntityId } from '@open-mercato/shared/modules/entities'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanFromUnknown, parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst paramsSchema = z.object({\n id: z.string().uuid(),\n})\n\nfunction parseIncludeParams(request: Request): Set<string> {\n const url = new URL(request.url)\n const raw = url.searchParams.getAll('include')\n const tokens = new Set<string>()\n raw.forEach((entry) => {\n if (!entry) return\n entry\n .split(',')\n .map((part) => part.trim().toLowerCase())\n .filter((part) => part.length > 0)\n .forEach((part) => tokens.add(part))\n })\n return tokens\n}\n\nfunction forbidden(message: string) {\n return NextResponse.json({ error: message }, { status: 403 })\n}\n\nfunction notFound(message: string) {\n return NextResponse.json({ error: message }, { status: 404 })\n}\n\nfunction serializeTags(assignments: CustomerTagAssignment[]): Array<{ id: string; label: string; color: string | null }> {\n return assignments\n .map((assignment) => {\n const tag = assignment.tag as CustomerTag | string | null\n if (!tag || typeof tag === 'string') return null\n return {\n id: tag.id,\n label: tag.label,\n color: tag.color ?? null,\n }\n })\n .filter(\n (tag: { id: string; label: string; color: string | null } | null): tag is {\n id: string\n label: string\n color: string | null\n } => tag !== null,\n )\n}\n\ntype TodoDetail = {\n title: string | null\n isDone: boolean | null\n priority: number | null\n severity: string | null\n description: string | null\n dueAt: string | null\n organizationId: string | null\n customValues: Record<string, unknown> | null\n}\n\nfunction extractTodoTitle(record: Record<string, unknown>): string | null {\n const candidates = ['title', 'subject', 'name', 'summary', 'text', 'description']\n for (const key of candidates) {\n const value = record[key]\n if (typeof value === 'string' && value.trim().length > 0) {\n return value.trim()\n }\n }\n return null\n}\n\nfunction parseNumber(value: unknown): number | null {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const parsed = Number(trimmed)\n if (!Number.isNaN(parsed)) return parsed\n }\n return null\n}\n\nfunction parseDateValue(value: unknown): string | null {\n if (value instanceof Date) {\n const ts = value.getTime()\n return Number.isNaN(ts) ? null : value.toISOString()\n }\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return null\n const candidate = new Date(trimmed)\n if (!Number.isNaN(candidate.getTime())) return candidate.toISOString()\n }\n return null\n}\n\nfunction readCustomField(record: Record<string, unknown>, key: string): unknown {\n const custom = record.custom ?? record.customFields ?? record.cf\n if (custom && typeof custom === 'object') {\n const bucket = custom as Record<string, unknown>\n if (key in bucket) return bucket[key]\n }\n return undefined\n}\n\ntype RouteProfilerMark = { label: string; time: bigint; extra?: Record<string, unknown> }\ntype RouteProfiler = { enabled: boolean; mark: (label: string, extra?: Record<string, unknown>) => void; end: (extra?: Record<string, unknown>) => void }\n\nfunction normalizeProfilerTokens(input: string | null | undefined): string[] {\n if (!input) return []\n return input\n .split(',')\n .map((token) => token.trim().toLowerCase())\n .filter((token) => token.length > 0)\n}\n\nfunction profilerMatches(scope: string, tokens: string[]): boolean {\n if (!tokens.length) return false\n const lower = scope.toLowerCase()\n return tokens.some((token) => {\n if (token === '*' || token === 'all' || parseBooleanToken(token) === true) return true\n if (token.endsWith('*')) {\n const prefix = token.slice(0, -1)\n return prefix.length === 0 ? true : lower.startsWith(prefix)\n }\n return token === lower\n })\n}\n\nfunction isRouteProfilingEnabled(scope: string): boolean {\n const candidates = [\n process.env.OM_CRUD_PROFILE,\n process.env.NEXT_PUBLIC_OM_CRUD_PROFILE,\n process.env.OM_ROUTE_PROFILE,\n process.env.NEXT_PUBLIC_OM_ROUTE_PROFILE,\n ]\n for (const raw of candidates) {\n if (!raw) continue\n const tokens = normalizeProfilerTokens(raw)\n if (profilerMatches(scope, tokens)) return true\n }\n return false\n}\n\nfunction createRouteProfiler(scope: string): RouteProfiler {\n if (!isRouteProfilingEnabled(scope)) {\n return { enabled: false, mark: () => {}, end: () => {} }\n }\n const marks: RouteProfilerMark[] = [{ label: 'start', time: process.hrtime.bigint() }]\n const round = (value: number) => Math.round(value * 1000) / 1000\n return {\n enabled: true,\n mark(label, extra) {\n marks.push({ label, time: process.hrtime.bigint(), extra })\n },\n end(extra) {\n marks.push({ label: 'end', time: process.hrtime.bigint(), extra })\n const segments: Array<{ step: string; durationMs: number; extra?: Record<string, unknown> }> = []\n for (let idx = 1; idx < marks.length; idx += 1) {\n const current = marks[idx]\n const previous = marks[idx - 1]\n if (current.label === 'end') continue\n const durationMs = Number(current.time - previous.time) / 1_000_000\n segments.push({\n step: current.label,\n durationMs: round(durationMs),\n ...(current.extra ? { extra: current.extra } : {}),\n })\n }\n const totalNs = marks[marks.length - 1].time - marks[0].time\n const payload: Record<string, unknown> = {\n scope,\n totalMs: round(Number(totalNs) / 1_000_000),\n steps: segments,\n }\n const tail = marks[marks.length - 1]\n if (tail.extra && Object.keys(tail.extra).length > 0) payload.meta = tail.extra\n else if (extra && Object.keys(extra).length > 0) payload.meta = extra\n try {\n console.info('[route:profile]', payload)\n } catch {\n // ignore logging failures\n }\n },\n }\n}\n\nasync function resolveTodoDetails(\n queryEngine: QueryEngine,\n links: CustomerTodoLink[],\n tenantId: string | null,\n organizationIds: Array<string | null>,\n profiler?: RouteProfiler,\n): Promise<Map<string, TodoDetail>> {\n const details = new Map<string, TodoDetail>()\n if (!links.length || !tenantId) return details\n\n const scopedOrgIds = organizationIds\n .filter((value): value is string => typeof value === 'string' && value.trim().length > 0)\n\n const idsBySource = new Map<string, Set<string>>()\n for (const link of links) {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : 'example:todo'\n const id = typeof link.todoId === 'string' && link.todoId.trim().length > 0 ? link.todoId : String(link.todoId ?? '')\n if (!id) continue\n if (!idsBySource.has(source)) idsBySource.set(source, new Set<string>())\n idsBySource.get(source)!.add(id)\n }\n\n profiler?.mark('todo_links_grouped', { sourceCount: idsBySource.size, linkCount: links.length })\n\n for (const [source, idSet] of idsBySource.entries()) {\n const ids = Array.from(idSet)\n if (!ids.length) continue\n profiler?.mark('todo_query_start', { source, count: ids.length })\n try {\n const result = await queryEngine.query<Record<string, unknown>>(source as EntityId, {\n tenantId,\n organizationIds: scopedOrgIds.length > 0 ? scopedOrgIds : undefined,\n filters: { id: { $in: ids } },\n includeCustomFields: ['priority', 'due_at', 'severity', 'description'],\n page: { page: 1, pageSize: Math.max(ids.length, 1) },\n })\n const itemCount = Array.isArray(result.items) ? result.items.length : 0\n profiler?.mark('todo_query_complete', { source, itemCount })\n let enriched = 0\n for (const item of result.items ?? []) {\n if (!item || typeof item !== 'object') continue\n const record = item as Record<string, unknown>\n const rawId = typeof record.id === 'string' && record.id.trim().length > 0 ? record.id : String(record.id ?? '')\n if (!rawId) continue\n const title = extractTodoTitle(record)\n const isDone = (() => {\n const direct = parseBooleanFromUnknown(record.is_done)\n if (direct !== null) return direct\n const custom = parseBooleanFromUnknown(readCustomField(record, 'is_done'))\n if (custom !== null) return custom\n const generic = parseBooleanFromUnknown(record.isDone)\n if (generic !== null) return generic\n return parseBooleanFromUnknown(readCustomField(record, 'isDone'))\n })()\n const priority = (() => {\n const candidates = [\n record['cf:priority'],\n record['cf_priority'],\n record.priority,\n readCustomField(record, 'priority'),\n ]\n for (const candidate of candidates) {\n const parsed = parseNumber(candidate)\n if (parsed !== null) return parsed\n }\n return null\n })()\n const severity = (() => {\n const candidates = [\n record['cf:severity'],\n record['cf_severity'],\n readCustomField(record, 'severity'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string') {\n const trimmed = candidate.trim()\n if (trimmed.length) return trimmed\n }\n }\n return null\n })()\n const descriptionValue = (() => {\n const candidates = [\n record.description,\n record['cf:description'],\n record['cf_description'],\n readCustomField(record, 'description'),\n ]\n for (const candidate of candidates) {\n if (typeof candidate === 'string') {\n const trimmed = candidate.trim()\n if (trimmed.length) return trimmed\n }\n }\n return null\n })()\n const dueAt = (() => {\n const candidates = [\n record.due_at,\n record.dueAt,\n record['cf:due_at'],\n record['cf_due_at'],\n readCustomField(record, 'due_at'),\n readCustomField(record, 'dueAt'),\n ]\n for (const candidate of candidates) {\n const parsed = parseDateValue(candidate)\n if (parsed) return parsed\n }\n return null\n })()\n const organizationId = typeof record.organization_id === 'string' && record.organization_id.trim().length > 0\n ? record.organization_id\n : (typeof record.organizationId === 'string' && record.organizationId.trim().length > 0 ? record.organizationId : null)\n const customValues: Record<string, unknown> = {}\n const assignCustomValue = (key: unknown, value: unknown) => {\n if (typeof key !== 'string') return\n const trimmedKey = key.trim()\n if (!trimmedKey.length) return\n customValues[trimmedKey] = value === undefined ? null : value\n }\n for (const [rawKey, rawValue] of Object.entries(record)) {\n if (rawKey.startsWith('cf:')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n } else if (rawKey.startsWith('cf_')) {\n assignCustomValue(rawKey.slice(3), rawValue)\n }\n }\n const nestedCustom = record.custom ?? record.customFields ?? record.cf\n if (nestedCustom && typeof nestedCustom === 'object') {\n for (const [nestedKey, nestedValue] of Object.entries(nestedCustom as Record<string, unknown>)) {\n assignCustomValue(nestedKey, nestedValue)\n }\n }\n\n details.set(`${source}:${rawId}`, {\n title,\n isDone,\n priority,\n severity,\n description: descriptionValue,\n dueAt,\n organizationId,\n customValues: Object.keys(customValues).length ? customValues : null,\n })\n enriched += 1\n }\n profiler?.mark('todo_items_processed', { source, enriched })\n } catch (err) {\n profiler?.mark('todo_query_failed', { source, error: err instanceof Error ? err.message : String(err) })\n console.warn(`customers.people.detail: failed to resolve todos for source ${source}`, err)\n }\n }\n\n profiler?.mark('todo_details_ready', { enrichedCount: details.size })\n return details\n}\n\nexport async function GET(_req: Request, ctx: { params?: { id?: string } }) {\n const profiler = createRouteProfiler('customers.people.detail')\n profiler.mark('request_received')\n\n const includeTokens = parseIncludeParams(_req)\n profiler.mark('includes_parsed', { include: Array.from(includeTokens) })\n\n const includeActivities = includeTokens.has('activities')\n const includeAddresses = includeTokens.has('addresses')\n const includeComments = includeTokens.has('comments') || includeTokens.has('notes')\n const includeDeals = includeTokens.has('deals')\n const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')\n\n let statusCode = 500\n let profileMeta: Record<string, unknown> | undefined\n let addresses: CustomerAddress[] = []\n let comments: CustomerComment[] = []\n let activities: CustomerActivity[] = []\n let todoLinks: CustomerTodoLink[] = []\n let todoDetails = new Map<string, TodoDetail>()\n let deals: CustomerDeal[] = []\n let tagAssignments: CustomerTagAssignment[] = []\n let userMap = new Map<string, { name: string | null; email: string | null }>()\n let customFields: Record<string, unknown> = {}\n let viewerUserId: string | null = null\n let profile: CustomerPersonProfile | null = null\n\n try {\n const parse = paramsSchema.safeParse({ id: ctx.params?.id })\n if (!parse.success) {\n statusCode = 400\n profileMeta = { reason: 'invalid_person_id' }\n return NextResponse.json({ error: 'Invalid person id' }, { status: 400 })\n }\n profiler.mark('params_resolved', { id: parse.data.id })\n\n const auth = await getAuthFromRequest(_req)\n if (!auth) {\n profiler.mark('auth_missing')\n statusCode = 401\n profileMeta = { reason: 'unauthorized' }\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n profiler.mark('auth_resolved', {\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n userId: auth.sub ?? null,\n isApiKey: !!auth.isApiKey,\n })\n viewerUserId = auth.isApiKey ? null : auth.sub ?? null\n\n const container = await createRequestContainer()\n profiler.mark('container_resolved')\n\n const scope = await resolveOrganizationScopeForRequest({ container, auth, request: _req })\n profiler.mark('scope_resolved', {\n scopedOrganizations: Array.isArray(scope?.filterIds) ? scope.filterIds.length : 0,\n })\n const em = (container.resolve('em') as EntityManager)\n\n const person = await em.findOne(CustomerEntity, { id: parse.data.id, kind: 'person', deletedAt: null })\n profiler.mark('person_loaded', { found: !!person })\n if (!person) {\n statusCode = 404\n profileMeta = { reason: 'person_not_found' }\n return notFound('Person not found')\n }\n\n if (auth.tenantId && person.tenantId !== auth.tenantId) {\n statusCode = 404\n profileMeta = { reason: 'person_tenant_mismatch' }\n return notFound('Person not found')\n }\n const allowedOrgIds = new Set<string>()\n if (scope?.filterIds?.length) scope.filterIds.forEach((id) => allowedOrgIds.add(id))\n else if (auth.orgId) allowedOrgIds.add(auth.orgId)\n\n if (allowedOrgIds.size && person.organizationId && !allowedOrgIds.has(person.organizationId)) {\n statusCode = 403\n profileMeta = { reason: 'organization_forbidden' }\n return forbidden('Access denied')\n }\n\n profile = await em.findOne(CustomerPersonProfile, { entity: person })\n profiler.mark('profile_loaded', { found: !!profile })\n\n if (includeAddresses) {\n addresses = await em.find(CustomerAddress, { entity: person.id }, { orderBy: { isPrimary: 'desc', createdAt: 'desc' } })\n profiler.mark('addresses_loaded', { count: addresses.length })\n }\n\n tagAssignments = await findWithDecryption(\n em,\n CustomerTagAssignment,\n { entity: person.id },\n { populate: ['tag'] },\n { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },\n )\n profiler.mark('tags_loaded', { count: tagAssignments.length })\n\n if (includeComments) {\n comments = await em.find(CustomerComment, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })\n profiler.mark('comments_loaded', { count: comments.length })\n }\n\n if (includeActivities) {\n activities = await em.find(CustomerActivity, { entity: person.id }, { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 })\n profiler.mark('activities_loaded', { count: activities.length })\n }\n\n if (includeTodos) {\n todoLinks = await em.find(CustomerTodoLink, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 })\n profiler.mark('todo_links_loaded', { count: todoLinks.length })\n if (todoLinks.length) {\n const queryEngine = (container.resolve('queryEngine') as QueryEngine)\n try {\n todoDetails = await resolveTodoDetails(\n queryEngine,\n todoLinks,\n person.tenantId ?? auth.tenantId ?? null,\n [person.organizationId ?? null, ...(scope?.filterIds ?? [])],\n profiler,\n )\n } catch (err) {\n console.warn('customers.people.detail: failed to enrich todo links', err)\n }\n profiler.mark('todo_details_enriched', { count: todoDetails.size, links: todoLinks.length })\n }\n }\n\n const authorIds = new Set<string>()\n if (includeActivities) {\n for (const activity of activities) {\n if (activity.authorUserId) authorIds.add(activity.authorUserId)\n }\n }\n if (includeComments) {\n for (const comment of comments) {\n if (comment.authorUserId) authorIds.add(comment.authorUserId)\n }\n }\n if (viewerUserId) authorIds.add(viewerUserId)\n\n if (authorIds.size) {\n const users = await em.find(User, { id: { $in: Array.from(authorIds) } })\n userMap = new Map(\n users.map((user) => [\n user.id,\n {\n name: user.name ?? null,\n email: user.email ?? null,\n },\n ])\n )\n profiler.mark('authors_loaded', { count: userMap.size })\n }\n\n if (includeDeals) {\n const dealLinks = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { person: person.id },\n { populate: ['deal'] },\n { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },\n )\n deals = dealLinks\n .map((link) => (link.deal as CustomerDeal | string | null) ?? null)\n .filter((deal): deal is CustomerDeal => !!deal && typeof deal !== 'string')\n profiler.mark('deals_loaded', { count: deals.length })\n }\n\n const entityCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_entity,\n recordIds: [person.id],\n tenantIdByRecord: { [person.id]: person.tenantId ?? null },\n organizationIdByRecord: { [person.id]: person.organizationId ?? null },\n tenantFallbacks: [\n person.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n profiler.mark('entity_custom_fields_loaded', { keys: Object.keys(entityCustomFieldValues?.[person.id] ?? {}).length })\n\n let profileCustomFieldValues: Record<string, Record<string, unknown>> = {}\n const profileId = profile?.id ?? null\n if (profileId) {\n profileCustomFieldValues = await loadCustomFieldValues({\n em,\n entityId: E.customers.customer_person_profile,\n recordIds: [profileId],\n tenantIdByRecord: { [profileId]: profile?.tenantId ?? null },\n organizationIdByRecord: { [profileId]: profile?.organizationId ?? null },\n tenantFallbacks: [\n profile?.tenantId ?? person.tenantId ?? auth.tenantId ?? null,\n ].filter((v): v is string => !!v),\n })\n profiler.mark('profile_custom_fields_loaded', { keys: Object.keys(profileCustomFieldValues?.[profileId] ?? {}).length })\n }\n\n const routing = await resolvePersonCustomFieldRouting(em, person.tenantId ?? null, person.organizationId ?? null)\n profiler.mark('custom_field_routing_resolved', { keys: routing.size })\n customFields = mergePersonCustomFieldValues(\n routing,\n entityCustomFieldValues?.[person.id] ?? {},\n profileId ? profileCustomFieldValues?.[profileId] ?? {} : {},\n )\n profiler.mark('custom_fields_merged', { keys: Object.keys(customFields).length })\n\n const viewerUserIdFinal = viewerUserId\n const response = NextResponse.json({\n person: {\n id: person.id,\n displayName: person.displayName,\n description: person.description,\n ownerUserId: person.ownerUserId,\n primaryEmail: person.primaryEmail,\n primaryPhone: person.primaryPhone,\n status: person.status,\n lifecycleStage: person.lifecycleStage,\n source: person.source,\n nextInteractionAt: person.nextInteractionAt ? person.nextInteractionAt.toISOString() : null,\n nextInteractionName: person.nextInteractionName,\n nextInteractionRefId: person.nextInteractionRefId,\n nextInteractionIcon: person.nextInteractionIcon,\n nextInteractionColor: person.nextInteractionColor,\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n isActive: person.isActive,\n createdAt: person.createdAt.toISOString(),\n updatedAt: person.updatedAt.toISOString(),\n },\n profile: profile\n ? {\n id: profile.id,\n firstName: profile.firstName,\n lastName: profile.lastName,\n preferredName: profile.preferredName,\n jobTitle: profile.jobTitle,\n department: profile.department,\n seniority: profile.seniority,\n timezone: profile.timezone,\n linkedInUrl: profile.linkedInUrl,\n twitterUrl: profile.twitterUrl,\n companyEntityId: profile.company ? (typeof profile.company === 'string' ? profile.company : profile.company.id) : null,\n updatedAt: profile.updatedAt.toISOString(),\n }\n : null,\n customFields,\n tags: serializeTags(tagAssignments),\n addresses: includeAddresses\n ? addresses.map((address) => ({\n id: address.id,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n buildingNumber: address.buildingNumber,\n flatNumber: address.flatNumber,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n createdAt: address.createdAt.toISOString(),\n }))\n : [],\n comments: includeComments\n ? comments.map((comment) => {\n const authorInfo = comment.authorUserId ? userMap.get(comment.authorUserId) : null\n return {\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId,\n authorName: authorInfo?.name ?? null,\n authorEmail: authorInfo?.email ?? null,\n dealId: comment.deal ? (typeof comment.deal === 'string' ? comment.deal : comment.deal.id) : null,\n createdAt: comment.createdAt.toISOString(),\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n }\n })\n : [],\n activities: includeActivities\n ? activities.map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt ? activity.occurredAt.toISOString() : null,\n dealId: activity.deal ? (typeof activity.deal === 'string' ? activity.deal : activity.deal.id) : null,\n authorUserId: activity.authorUserId,\n authorName: activity.authorUserId ? userMap.get(activity.authorUserId)?.name ?? null : null,\n authorEmail: activity.authorUserId ? userMap.get(activity.authorUserId)?.email ?? null : null,\n createdAt: activity.createdAt.toISOString(),\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n }))\n : [],\n deals: includeDeals\n ? deals.map((deal) => ({\n id: deal.id,\n title: deal.title,\n status: deal.status,\n pipelineStage: deal.pipelineStage,\n valueAmount: deal.valueAmount,\n valueCurrency: deal.valueCurrency,\n probability: deal.probability,\n expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,\n ownerUserId: deal.ownerUserId,\n source: deal.source,\n createdAt: deal.createdAt.toISOString(),\n updatedAt: deal.updatedAt.toISOString(),\n }))\n : [],\n todos: includeTodos\n ? todoLinks.map((link) => {\n const source = typeof link.todoSource === 'string' && link.todoSource.trim().length > 0 ? link.todoSource : 'example:todo'\n const key = `${source}:${link.todoId}`\n const detail = todoDetails.get(key)\n return {\n id: link.id,\n todoId: link.todoId,\n todoSource: source,\n createdAt: link.createdAt.toISOString(),\n createdByUserId: link.createdByUserId,\n title: detail?.title ?? null,\n isDone: detail?.isDone ?? null,\n priority: detail?.priority ?? null,\n severity: detail?.severity ?? null,\n description: detail?.description ?? null,\n dueAt: detail?.dueAt ?? null,\n todoOrganizationId: detail?.organizationId ?? null,\n customValues: detail?.customValues ?? null,\n }\n })\n : [],\n viewer: {\n userId: viewerUserIdFinal,\n name: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.name ?? null : null,\n email: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.email ?? auth.email ?? null : auth.email ?? null,\n },\n })\n statusCode = 200\n profileMeta = {\n include: Array.from(includeTokens),\n counts: {\n tags: tagAssignments.length,\n comments: comments.length,\n activities: activities.length,\n todos: todoLinks.length,\n addresses: addresses.length,\n deals: deals.length,\n },\n }\n profiler.mark('response_ready', { status: statusCode })\n return response\n } catch (err) {\n if (statusCode < 400) statusCode = 500\n const message = err instanceof Error ? err.message : String(err)\n profileMeta = { ...(profileMeta ?? {}), error: message }\n throw err\n } finally {\n profiler.end({ status: statusCode, ...(profileMeta ?? {}) })\n }\n}\nconst personDetailQuerySchema = z.object({\n include: z\n .string()\n .optional()\n .describe('Comma-separated list of relations to include (addresses, comments, activities, deals, todos).'),\n}).passthrough()\n\nconst personDetailResponseSchema = z.object({\n person: z.object({\n id: z.string().uuid(),\n displayName: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n primaryEmail: z.string().nullable().optional(),\n primaryPhone: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n lifecycleStage: z.string().nullable().optional(),\n source: z.string().nullable().optional(),\n nextInteractionAt: z.string().nullable().optional(),\n nextInteractionName: z.string().nullable().optional(),\n nextInteractionRefId: z.string().nullable().optional(),\n nextInteractionIcon: z.string().nullable().optional(),\n nextInteractionColor: z.string().nullable().optional(),\n organizationId: z.string().uuid().nullable().optional(),\n tenantId: z.string().uuid().nullable().optional(),\n isActive: z.boolean().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n profile: z\n .object({\n id: z.string().uuid(),\n firstName: z.string().nullable().optional(),\n lastName: z.string().nullable().optional(),\n preferredName: z.string().nullable().optional(),\n jobTitle: z.string().nullable().optional(),\n department: z.string().nullable().optional(),\n seniority: z.string().nullable().optional(),\n timezone: z.string().nullable().optional(),\n linkedInUrl: z.string().nullable().optional(),\n twitterUrl: z.string().nullable().optional(),\n companyEntityId: z.string().uuid().nullable().optional(),\n updatedAt: z.string(),\n })\n .nullable(),\n customFields: z.record(z.string(), z.unknown()),\n tags: z.array(\n z.object({\n id: z.string().uuid(),\n label: z.string(),\n color: z.string().nullable().optional(),\n }),\n ),\n addresses: z.array(\n z.object({\n id: z.string().uuid(),\n name: z.string().nullable().optional(),\n purpose: z.string().nullable().optional(),\n addressLine1: z.string().nullable().optional(),\n addressLine2: z.string().nullable().optional(),\n buildingNumber: z.string().nullable().optional(),\n flatNumber: z.string().nullable().optional(),\n city: z.string().nullable().optional(),\n region: z.string().nullable().optional(),\n postalCode: z.string().nullable().optional(),\n country: z.string().nullable().optional(),\n latitude: z.number().nullable().optional(),\n longitude: z.number().nullable().optional(),\n isPrimary: z.boolean().nullable().optional(),\n createdAt: z.string(),\n }),\n ),\n comments: z.array(\n z.object({\n id: z.string().uuid(),\n body: z.string().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n activities: z.array(\n z.object({\n id: z.string().uuid(),\n activityType: z.string(),\n subject: z.string().nullable().optional(),\n body: z.string().nullable().optional(),\n occurredAt: z.string().nullable().optional(),\n dealId: z.string().uuid().nullable().optional(),\n authorUserId: z.string().uuid().nullable().optional(),\n authorName: z.string().nullable().optional(),\n authorEmail: z.string().nullable().optional(),\n createdAt: z.string(),\n appearanceIcon: z.string().nullable().optional(),\n appearanceColor: z.string().nullable().optional(),\n }),\n ),\n deals: z.array(\n z.object({\n id: z.string().uuid(),\n title: z.string().nullable().optional(),\n status: z.string().nullable().optional(),\n pipelineStage: z.string().nullable().optional(),\n valueAmount: z.number().nullable().optional(),\n valueCurrency: z.string().nullable().optional(),\n probability: z.number().nullable().optional(),\n expectedCloseAt: z.string().nullable().optional(),\n ownerUserId: z.string().uuid().nullable().optional(),\n source: z.string().nullable().optional(),\n createdAt: z.string(),\n updatedAt: z.string(),\n }),\n ),\n todos: z.array(\n z.object({\n id: z.string().uuid(),\n todoId: z.string().uuid(),\n todoSource: z.string(),\n createdAt: z.string(),\n createdByUserId: z.string().uuid().nullable().optional(),\n title: z.string().nullable().optional(),\n isDone: z.boolean().nullable().optional(),\n priority: z.number().nullable().optional(),\n severity: z.string().nullable().optional(),\n description: z.string().nullable().optional(),\n dueAt: z.string().nullable().optional(),\n todoOrganizationId: z.string().uuid().nullable().optional(),\n customValues: z.record(z.string(), z.unknown()).nullable().optional(),\n }),\n ),\n viewer: z.object({\n userId: z.string().uuid().nullable(),\n name: z.string().nullable(),\n email: z.string().nullable(),\n }),\n})\n\nconst personDetailErrorSchema = z.object({\n error: z.string(),\n})\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Customers',\n summary: 'Fetch person detail',\n methods: {\n GET: {\n summary: 'Fetch person with related data',\n description: 'Returns a person customer record with optional related resources such as addresses, comments, activities, deals, and todos.',\n query: personDetailQuerySchema,\n responses: [\n { status: 200, description: 'Person detail payload', schema: personDetailResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: personDetailErrorSchema },\n { status: 401, description: 'Unauthorized', schema: personDetailErrorSchema },\n { status: 403, description: 'Forbidden for tenant/organization scope', schema: personDetailErrorSchema },\n { status: 404, description: 'Person not found', schema: personDetailErrorSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -493,6 +493,21 @@ const updatePersonCommand = {
|
|
|
493
493
|
if (parsed.companyEntityId !== void 0) {
|
|
494
494
|
profile.company = await resolveCompanyReference(em, parsed.companyEntityId, record.organizationId, record.tenantId);
|
|
495
495
|
}
|
|
496
|
+
const profileFieldsUpdated = [
|
|
497
|
+
parsed.firstName,
|
|
498
|
+
parsed.lastName,
|
|
499
|
+
parsed.preferredName,
|
|
500
|
+
parsed.jobTitle,
|
|
501
|
+
parsed.department,
|
|
502
|
+
parsed.seniority,
|
|
503
|
+
parsed.timezone,
|
|
504
|
+
parsed.linkedInUrl,
|
|
505
|
+
parsed.twitterUrl,
|
|
506
|
+
parsed.companyEntityId
|
|
507
|
+
].some((v) => v !== void 0);
|
|
508
|
+
if (profileFieldsUpdated) {
|
|
509
|
+
record.updatedAt = /* @__PURE__ */ new Date();
|
|
510
|
+
}
|
|
496
511
|
if (parsed.displayName !== void 0) {
|
|
497
512
|
const nextDisplayName = parsed.displayName.trim();
|
|
498
513
|
if (!nextDisplayName) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/customers/commands/people.ts"],
|
|
4
|
-
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerTodoLink,\n CustomerEntity,\n CustomerPersonProfile,\n CustomerTagAssignment,\n} from '../data/entities'\nimport { resolvePersonCustomFieldRouting, CUSTOMER_ENTITY_ID, PERSON_ENTITY_ID } from '../lib/customFieldRouting'\nimport {\n personCreateSchema,\n personUpdateSchema,\n type PersonCreateInput,\n type PersonUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n assertFound,\n syncEntityTags,\n loadEntityTagIds,\n ensureDictionaryEntry,\n emitQueryIndexDeleteEvents,\n emitQueryIndexUpsertEvents,\n type QueryIndexEventEntry,\n} from './shared'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype PersonAddressSnapshot = {\n id: string\n name: string | null\n purpose: string | null\n addressLine1: string\n addressLine2: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n isPrimary: boolean\n}\n\ntype PersonCommentSnapshot = {\n id: string\n body: string\n authorUserId: string | null\n dealId: string | null\n createdAt: Date\n updatedAt: Date\n deletedAt: Date | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype PersonActivitySnapshot = {\n id: string\n activityType: string\n subject: string | null\n body: string | null\n occurredAt: Date | null\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n dealId: string | null\n createdAt: Date\n updatedAt: Date\n}\n\ntype PersonTodoSnapshot = {\n id: string\n todoId: string\n todoSource: string\n createdAt: Date\n createdByUserId: string | null\n}\n\ntype PersonSnapshot = {\n entity: {\n id: string\n organizationId: string\n tenantId: string\n displayName: string\n description: string | null\n ownerUserId: string | null\n primaryEmail: string | null\n primaryPhone: string | null\n status: string | null\n lifecycleStage: string | null\n source: string | null\n nextInteractionAt: Date | null\n nextInteractionName: string | null\n nextInteractionRefId: string | null\n nextInteractionIcon: string | null\n nextInteractionColor: string | null\n isActive: boolean\n }\n profile: {\n id: string\n firstName: string | null\n lastName: string | null\n preferredName: string | null\n jobTitle: string | null\n department: string | null\n seniority: string | null\n timezone: string | null\n linkedInUrl: string | null\n twitterUrl: string | null\n companyEntityId: string | null\n }\n tagIds: string[]\n addresses: PersonAddressSnapshot[]\n comments: PersonCommentSnapshot[]\n custom?: Record<string, unknown>\n deals: Array<{\n id: string\n dealId: string\n participantRole: string | null\n createdAt: Date\n }>\n activities: PersonActivitySnapshot[]\n todos: PersonTodoSnapshot[]\n}\n\ntype PersonUndoPayload = {\n before?: PersonSnapshot | null\n after?: PersonSnapshot | null\n}\n\nconst personCrudIndexer: CrudIndexerConfig<CustomerEntity> = {\n entityType: E.customers.customer_person_profile,\n}\n\nconst personCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'person',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nfunction normalizeOptionalString(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nfunction normalizeHexColor(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim().toLowerCase()\n return /^#([0-9a-f]{6})$/.test(trimmed) ? trimmed : null\n}\n\nfunction normalizeEmail(value: string | null | undefined): string | null {\n const normalized = normalizeOptionalString(value)\n return normalized ? normalized.toLowerCase() : null\n}\n\nfunction serializePersonSnapshot(\n entity: CustomerEntity,\n profile: CustomerPersonProfile,\n tagIds: string[],\n addresses: CustomerAddress[],\n comments: CustomerComment[],\n deals: CustomerDealPersonLink[],\n activities: CustomerActivity[],\n todoLinks: CustomerTodoLink[],\n custom?: Record<string, unknown>\n): PersonSnapshot {\n return {\n entity: {\n id: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n displayName: entity.displayName,\n description: entity.description ?? null,\n ownerUserId: entity.ownerUserId ?? null,\n primaryEmail: entity.primaryEmail ?? null,\n primaryPhone: entity.primaryPhone ?? null,\n status: entity.status ?? null,\n lifecycleStage: entity.lifecycleStage ?? null,\n source: entity.source ?? null,\n nextInteractionAt: entity.nextInteractionAt ?? null,\n nextInteractionName: entity.nextInteractionName ?? null,\n nextInteractionRefId: entity.nextInteractionRefId ?? null,\n nextInteractionIcon: entity.nextInteractionIcon ?? null,\n nextInteractionColor: entity.nextInteractionColor ?? null,\n isActive: entity.isActive,\n },\n profile: {\n id: profile.id,\n firstName: profile.firstName ?? null,\n lastName: profile.lastName ?? null,\n preferredName: profile.preferredName ?? null,\n jobTitle: profile.jobTitle ?? null,\n department: profile.department ?? null,\n seniority: profile.seniority ?? null,\n timezone: profile.timezone ?? null,\n linkedInUrl: profile.linkedInUrl ?? null,\n twitterUrl: profile.twitterUrl ?? null,\n companyEntityId: profile.company\n ? typeof profile.company === 'string'\n ? profile.company\n : profile.company.id\n : null,\n },\n tagIds,\n addresses: addresses.map((address) => ({\n id: address.id,\n name: address.name ?? null,\n purpose: address.purpose ?? null,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? null,\n city: address.city ?? null,\n region: address.region ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n latitude: address.latitude ?? null,\n longitude: address.longitude ?? null,\n isPrimary: address.isPrimary,\n })),\n comments: comments.map((comment) => ({\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n dealId: comment.deal\n ? typeof comment.deal === 'string'\n ? comment.deal\n : comment.deal.id\n : null,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n deletedAt: comment.deletedAt ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n })),\n deals: deals\n .filter((link) => link.deal)\n .map((link) => ({\n id: link.id,\n dealId: link.deal.id,\n participantRole: link.participantRole ?? null,\n createdAt: link.createdAt,\n })),\n activities: activities.map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject ?? null,\n body: activity.body ?? null,\n occurredAt: activity.occurredAt ?? null,\n authorUserId: activity.authorUserId ?? null,\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n dealId: activity.deal\n ? typeof activity.deal === 'string'\n ? activity.deal\n : activity.deal.id\n : null,\n createdAt: activity.createdAt,\n updatedAt: activity.updatedAt,\n })),\n todos: todoLinks.map((todo) => ({\n id: todo.id,\n todoId: todo.todoId,\n todoSource: todo.todoSource,\n createdAt: todo.createdAt,\n createdByUserId: todo.createdByUserId ?? null,\n })),\n custom,\n }\n}\n\nasync function loadPersonSnapshot(em: EntityManager, entityId: string): Promise<PersonSnapshot | null> {\n const entity = await em.findOne(CustomerEntity, { id: entityId, deletedAt: null })\n if (!entity || entity.kind !== 'person') return null\n const profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: entity },\n { populate: ['company'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n if (!profile) return null\n const tagIds = await loadEntityTagIds(em, entity)\n const addresses = await em.find(CustomerAddress, { entity }, { orderBy: { createdAt: 'asc' } })\n const comments = await findWithDecryption(\n em,\n CustomerComment,\n { entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const deals = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { person: entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const activities = await findWithDecryption(\n em,\n CustomerActivity,\n { entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const todoLinks = await em.find(CustomerTodoLink, { entity }, { orderBy: { createdAt: 'asc' } })\n const entityCustom = await loadCustomFieldSnapshot(em, {\n entityId: CUSTOMER_ENTITY_ID,\n recordId: entity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n const profileCustom = await loadCustomFieldSnapshot(em, {\n entityId: PERSON_ENTITY_ID,\n recordId: profile.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n const routing = await resolvePersonCustomFieldRouting(em, entity.tenantId, entity.organizationId)\n const custom: Record<string, unknown> = { ...entityCustom }\n for (const [key, value] of Object.entries(profileCustom)) {\n const target = routing.get(key)\n if (target === CUSTOMER_ENTITY_ID && Object.prototype.hasOwnProperty.call(custom, key)) continue\n custom[key] = value\n }\n return serializePersonSnapshot(entity, profile, tagIds, addresses, comments, deals, activities, todoLinks, custom)\n}\n\nasync function resolveCompanyReference(\n em: EntityManager,\n companyId: string | null | undefined,\n organizationId: string,\n tenantId: string\n): Promise<CustomerEntity | null> {\n if (!companyId) return null\n const company = await em.findOne(CustomerEntity, { id: companyId, kind: 'company', deletedAt: null })\n if (!company) {\n throw new CrudHttpError(400, { error: 'Company not found' })\n }\n if (company.organizationId !== organizationId || company.tenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Cannot link person to company outside current scope' })\n }\n return company\n}\n\nasync function setCustomFieldsForPerson(\n ctx: CommandRuntimeContext,\n entityId: string,\n profileId: string,\n organizationId: string,\n tenantId: string,\n values: Record<string, unknown>\n): Promise<void> {\n if (!values || !Object.keys(values).length) return\n const em = (ctx.container.resolve('em') as EntityManager)\n const routing = await resolvePersonCustomFieldRouting(em, tenantId, organizationId)\n const entityScoped: Record<string, unknown> = {}\n const profileScoped: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n const target = routing.get(key) ?? PERSON_ENTITY_ID\n if (target === CUSTOMER_ENTITY_ID) entityScoped[key] = value\n else profileScoped[key] = value\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (Object.keys(entityScoped).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: CUSTOMER_ENTITY_ID,\n recordId: entityId,\n organizationId,\n tenantId,\n values: entityScoped,\n notify: true,\n })\n }\n if (Object.keys(profileScoped).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: PERSON_ENTITY_ID,\n recordId: profileId,\n organizationId,\n tenantId,\n values: profileScoped,\n notify: true,\n })\n }\n}\n\nconst createPersonCommand: CommandHandler<PersonCreateInput, { entityId: string; personId: string }> = {\n id: 'customers.people.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(personCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const firstName = parsed.firstName?.trim() ?? ''\n const lastName = parsed.lastName?.trim() ?? ''\n const description = normalizeOptionalString(parsed.description)\n const primaryEmail = normalizeEmail(parsed.primaryEmail)\n const primaryPhone = normalizeOptionalString(parsed.primaryPhone)\n const status = normalizeOptionalString(parsed.status)\n const lifecycleStage = normalizeOptionalString(parsed.lifecycleStage)\n const source = normalizeOptionalString(parsed.source)\n const preferredName = normalizeOptionalString(parsed.preferredName)\n const jobTitle = normalizeOptionalString(parsed.jobTitle)\n const department = normalizeOptionalString(parsed.department)\n const seniority = normalizeOptionalString(parsed.seniority)\n const timezone = normalizeOptionalString(parsed.timezone)\n const linkedInUrl = normalizeOptionalString(parsed.linkedInUrl)\n const twitterUrl = normalizeOptionalString(parsed.twitterUrl)\n const displayName = parsed.displayName?.trim() ?? ''\n const nextInteractionName = parsed.nextInteraction?.name ? parsed.nextInteraction.name.trim() : null\n const nextInteractionRefId = normalizeOptionalString(parsed.nextInteraction?.refId)\n const nextInteractionIcon = normalizeOptionalString(parsed.nextInteraction?.icon)\n const nextInteractionColor = normalizeHexColor(parsed.nextInteraction?.color)\n if (!firstName || !lastName) {\n throw new CrudHttpError(400, { error: 'First and last name are required' })\n }\n if (!displayName) {\n throw new CrudHttpError(400, { error: 'Display name is required' })\n }\n\n const entity = em.create(CustomerEntity, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n kind: 'person',\n displayName,\n description,\n ownerUserId: parsed.ownerUserId ?? null,\n primaryEmail,\n primaryPhone,\n status,\n lifecycleStage,\n source,\n nextInteractionAt: parsed.nextInteraction?.at ?? null,\n nextInteractionName,\n nextInteractionRefId,\n nextInteractionIcon,\n nextInteractionColor,\n isActive: parsed.isActive ?? true,\n })\n\n const company = await resolveCompanyReference(em, parsed.companyEntityId ?? null, parsed.organizationId, parsed.tenantId)\n\n const profile = em.create(CustomerPersonProfile, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n entity,\n firstName,\n lastName,\n preferredName,\n jobTitle,\n department,\n seniority,\n timezone,\n linkedInUrl,\n twitterUrl,\n company,\n })\n\n em.persist(entity)\n em.persist(profile)\n if (status) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'status',\n value: status,\n })\n }\n if (jobTitle) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'job_title',\n value: jobTitle,\n })\n }\n if (source) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'source',\n value: source,\n })\n }\n await em.flush()\n\n const tenantId = entity.tenantId\n const organizationId = entity.organizationId\n await syncEntityTags(em, entity, parsed.tags)\n await em.flush()\n await setCustomFieldsForPerson(ctx, entity.id, profile.id, organizationId, tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity,\n identifiers: {\n id: profile.id ?? entity.id,\n tenantId,\n organizationId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n return { entityId: entity.id, personId: profile.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadPersonSnapshot(em, result.entityId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as PersonSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.people.create', 'Create person'),\n resourceKind: 'customers.person',\n resourceId: result.entityId,\n tenantId: snapshot?.entity.tenantId ?? null,\n organizationId: snapshot?.entity.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry) ?? null\n const entityId = logEntry?.resourceId ?? payload?.after?.entity.id ?? null\n if (!entityId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: entityId })\n if (!entity) return\n const profile = await em.findOne(CustomerPersonProfile, { entity })\n await em.nativeDelete(CustomerTagAssignment, { entity })\n if (profile) {\n await em.remove(profile).flush()\n }\n await em.remove(entity).flush()\n },\n}\n\nconst updatePersonCommand: CommandHandler<PersonUpdateInput, { entityId: string }> = {\n id: 'customers.people.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(personUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPersonSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(personUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: parsed.id, deletedAt: null })\n const record = assertFound(entity, 'Person not found')\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const profile = await em.findOne(CustomerPersonProfile, { entity: record })\n if (!profile) throw new CrudHttpError(404, { error: 'Person profile not found' })\n\n if (parsed.description !== undefined) record.description = normalizeOptionalString(parsed.description)\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.primaryEmail !== undefined) record.primaryEmail = normalizeEmail(parsed.primaryEmail)\n if (parsed.primaryPhone !== undefined) record.primaryPhone = normalizeOptionalString(parsed.primaryPhone)\n if (parsed.status !== undefined) {\n const normalizedStatus = normalizeOptionalString(parsed.status)\n record.status = normalizedStatus\n if (normalizedStatus) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'status',\n value: normalizedStatus,\n })\n }\n }\n if (parsed.lifecycleStage !== undefined) record.lifecycleStage = normalizeOptionalString(parsed.lifecycleStage)\n if (parsed.source !== undefined) {\n const normalizedSource = normalizeOptionalString(parsed.source)\n record.source = normalizedSource\n if (normalizedSource) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'source',\n value: normalizedSource,\n })\n }\n }\n if (parsed.isActive !== undefined) record.isActive = parsed.isActive\n if (parsed.nextInteraction) {\n record.nextInteractionAt = parsed.nextInteraction.at\n record.nextInteractionName = parsed.nextInteraction.name.trim()\n record.nextInteractionRefId = normalizeOptionalString(parsed.nextInteraction.refId) ?? null\n record.nextInteractionIcon = normalizeOptionalString(parsed.nextInteraction.icon)\n record.nextInteractionColor = normalizeHexColor(parsed.nextInteraction.color)\n } else if (parsed.nextInteraction === null) {\n record.nextInteractionAt = null\n record.nextInteractionName = null\n record.nextInteractionRefId = null\n record.nextInteractionIcon = null\n record.nextInteractionColor = null\n }\n\n if (parsed.firstName !== undefined) profile.firstName = normalizeOptionalString(parsed.firstName)\n if (parsed.lastName !== undefined) profile.lastName = normalizeOptionalString(parsed.lastName)\n if (parsed.preferredName !== undefined) profile.preferredName = normalizeOptionalString(parsed.preferredName)\n if (parsed.jobTitle !== undefined) {\n const normalizedJobTitle = normalizeOptionalString(parsed.jobTitle)\n profile.jobTitle = normalizedJobTitle\n if (normalizedJobTitle) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'job_title',\n value: normalizedJobTitle,\n })\n }\n }\n if (parsed.department !== undefined) profile.department = normalizeOptionalString(parsed.department)\n if (parsed.seniority !== undefined) profile.seniority = normalizeOptionalString(parsed.seniority)\n if (parsed.timezone !== undefined) profile.timezone = normalizeOptionalString(parsed.timezone)\n if (parsed.linkedInUrl !== undefined) profile.linkedInUrl = normalizeOptionalString(parsed.linkedInUrl)\n if (parsed.twitterUrl !== undefined) profile.twitterUrl = normalizeOptionalString(parsed.twitterUrl)\n\n if (parsed.companyEntityId !== undefined) {\n profile.company = await resolveCompanyReference(em, parsed.companyEntityId, record.organizationId, record.tenantId)\n }\n\n if (parsed.displayName !== undefined) {\n const nextDisplayName = parsed.displayName.trim()\n if (!nextDisplayName) {\n throw new CrudHttpError(400, { error: 'Display name is required' })\n }\n record.displayName = nextDisplayName\n }\n\n await em.flush()\n await syncEntityTags(em, record, parsed.tags)\n await em.flush()\n\n await setCustomFieldsForPerson(ctx, record.id, profile.id, record.organizationId, record.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: profile.id ?? record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n return { entityId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadPersonSnapshot(em, result.entityId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as PersonSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.people.update', 'Update person'),\n resourceKind: 'customers.person',\n resourceId: before.entity.id,\n tenantId: before.entity.tenantId,\n organizationId: before.entity.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies PersonUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: before.entity.id })\n if (!entity) {\n const newEntity = em.create(CustomerEntity, {\n id: before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n kind: 'person',\n displayName: before.entity.displayName,\n description: before.entity.description,\n ownerUserId: before.entity.ownerUserId,\n primaryEmail: before.entity.primaryEmail,\n primaryPhone: before.entity.primaryPhone,\n status: before.entity.status,\n lifecycleStage: before.entity.lifecycleStage,\n source: before.entity.source,\n nextInteractionAt: before.entity.nextInteractionAt,\n nextInteractionName: before.entity.nextInteractionName,\n nextInteractionRefId: before.entity.nextInteractionRefId,\n nextInteractionIcon: before.entity.nextInteractionIcon,\n nextInteractionColor: before.entity.nextInteractionColor,\n isActive: before.entity.isActive,\n })\n em.persist(newEntity)\n const profile = em.create(CustomerPersonProfile, {\n id: before.profile.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n entity: newEntity,\n firstName: before.profile.firstName,\n lastName: before.profile.lastName,\n preferredName: before.profile.preferredName,\n jobTitle: before.profile.jobTitle,\n department: before.profile.department,\n seniority: before.profile.seniority,\n timezone: before.profile.timezone,\n linkedInUrl: before.profile.linkedInUrl,\n twitterUrl: before.profile.twitterUrl,\n })\n em.persist(profile)\n if (before.profile.companyEntityId) {\n profile.company = await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n }\n await em.flush()\n await syncEntityTags(em, newEntity, before.tagIds)\n await em.flush()\n } else {\n entity.displayName = before.entity.displayName\n entity.description = before.entity.description\n entity.ownerUserId = before.entity.ownerUserId\n entity.primaryEmail = before.entity.primaryEmail\n entity.primaryPhone = before.entity.primaryPhone\n entity.status = before.entity.status\n entity.lifecycleStage = before.entity.lifecycleStage\n entity.source = before.entity.source\n entity.nextInteractionAt = before.entity.nextInteractionAt\n entity.nextInteractionName = before.entity.nextInteractionName\n entity.nextInteractionRefId = before.entity.nextInteractionRefId\n entity.nextInteractionIcon = before.entity.nextInteractionIcon\n entity.nextInteractionColor = before.entity.nextInteractionColor\n entity.isActive = before.entity.isActive\n await em.flush()\n const profile = await em.findOne(CustomerPersonProfile, { entity })\n if (profile) {\n profile.firstName = before.profile.firstName\n profile.lastName = before.profile.lastName\n profile.preferredName = before.profile.preferredName\n profile.jobTitle = before.profile.jobTitle\n profile.department = before.profile.department\n profile.seniority = before.profile.seniority\n profile.timezone = before.profile.timezone\n profile.linkedInUrl = before.profile.linkedInUrl\n profile.twitterUrl = before.profile.twitterUrl\n profile.company = before.profile.companyEntityId\n ? await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n : null\n }\n await syncEntityTags(em, entity, before.tagIds)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: await em.findOne(CustomerEntity, { id: before.entity.id }),\n identifiers: {\n id: before.profile.id ?? before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsForPerson(ctx, before.entity.id, before.profile.id, before.entity.organizationId, before.entity.tenantId, resetValues)\n }\n },\n}\n\nconst deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { entityId: string }> =\n {\n id: 'customers.people.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Person id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPersonSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Person id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonSnapshot(em, id)\n const entity = await em.findOne(CustomerEntity, { id, deletedAt: null })\n const record = assertFound(entity, 'Person not found')\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const profile = await em.findOne(CustomerPersonProfile, { entity: record })\n if (profile) em.remove(profile)\n await em.nativeDelete(CustomerAddress, { entity: record })\n await em.nativeDelete(CustomerComment, { entity: record })\n await em.nativeDelete(CustomerActivity, { entity: record })\n await em.nativeDelete(CustomerTodoLink, { entity: record })\n await em.nativeDelete(CustomerTagAssignment, { entity: record })\n await em.nativeDelete(CustomerDealPersonLink, { person: record })\n em.remove(record)\n await em.flush()\n\n const indexDeletes: QueryIndexEventEntry[] = []\n const dealUpserts: QueryIndexEventEntry[] = []\n if (snapshot) {\n for (const activity of snapshot.activities ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_activity,\n recordId: activity.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const comment of snapshot.comments ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_comment,\n recordId: comment.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const address of snapshot.addresses ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_address,\n recordId: address.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const todo of snapshot.todos ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_todo_link,\n recordId: todo.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const deal of snapshot.deals ?? []) {\n if (deal.dealId) {\n dealUpserts.push({\n entityType: E.customers.customer_deal,\n recordId: deal.dealId,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n }\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: profile?.id ?? record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n await emitQueryIndexDeleteEvents(ctx, indexDeletes)\n await emitQueryIndexUpsertEvents(ctx, dealUpserts)\n return { entityId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PersonSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.people.delete', 'Delete person'),\n resourceKind: 'customers.person',\n resourceId: before.entity.id,\n tenantId: before.entity.tenantId,\n organizationId: before.entity.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies PersonUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entity = await em.findOne(CustomerEntity, { id: before.entity.id })\n if (!entity) {\n entity = em.create(CustomerEntity, {\n id: before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n kind: 'person',\n displayName: before.entity.displayName,\n description: before.entity.description,\n ownerUserId: before.entity.ownerUserId,\n primaryEmail: before.entity.primaryEmail,\n primaryPhone: before.entity.primaryPhone,\n status: before.entity.status,\n lifecycleStage: before.entity.lifecycleStage,\n source: before.entity.source,\n nextInteractionAt: before.entity.nextInteractionAt,\n nextInteractionName: before.entity.nextInteractionName,\n nextInteractionRefId: before.entity.nextInteractionRefId,\n nextInteractionIcon: before.entity.nextInteractionIcon,\n nextInteractionColor: before.entity.nextInteractionColor,\n isActive: before.entity.isActive,\n })\n em.persist(entity)\n }\n\n entity.displayName = before.entity.displayName\n entity.description = before.entity.description\n entity.ownerUserId = before.entity.ownerUserId\n entity.primaryEmail = before.entity.primaryEmail\n entity.primaryPhone = before.entity.primaryPhone\n entity.status = before.entity.status\n entity.lifecycleStage = before.entity.lifecycleStage\n entity.source = before.entity.source\n entity.nextInteractionAt = before.entity.nextInteractionAt\n entity.nextInteractionName = before.entity.nextInteractionName\n entity.nextInteractionRefId = before.entity.nextInteractionRefId\n entity.nextInteractionIcon = before.entity.nextInteractionIcon\n entity.nextInteractionColor = before.entity.nextInteractionColor\n entity.isActive = before.entity.isActive\n\n let profile = await em.findOne(CustomerPersonProfile, { entity })\n if (!profile) {\n profile = em.create(CustomerPersonProfile, {\n id: before.profile.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n entity,\n firstName: before.profile.firstName,\n lastName: before.profile.lastName,\n preferredName: before.profile.preferredName,\n jobTitle: before.profile.jobTitle,\n department: before.profile.department,\n seniority: before.profile.seniority,\n timezone: before.profile.timezone,\n linkedInUrl: before.profile.linkedInUrl,\n twitterUrl: before.profile.twitterUrl,\n })\n } else {\n profile.firstName = before.profile.firstName\n profile.lastName = before.profile.lastName\n profile.preferredName = before.profile.preferredName\n profile.jobTitle = before.profile.jobTitle\n profile.department = before.profile.department\n profile.seniority = before.profile.seniority\n profile.timezone = before.profile.timezone\n profile.linkedInUrl = before.profile.linkedInUrl\n profile.twitterUrl = before.profile.twitterUrl\n }\n\n if (before.profile.companyEntityId) {\n profile.company = await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n } else {\n profile.company = null\n }\n\n await em.flush()\n await syncEntityTags(em, entity, before.tagIds)\n await em.flush()\n\n const beforeActivities = (before as { activities?: PersonActivitySnapshot[] }).activities ?? []\n const beforeTodos = (before as { todos?: PersonTodoSnapshot[] }).todos ?? []\n\n const relatedDealIds = new Set<string>()\n for (const link of before.deals) relatedDealIds.add(link.dealId)\n for (const activity of beforeActivities) {\n if (activity.dealId) relatedDealIds.add(activity.dealId)\n }\n for (const comment of before.comments) {\n if (comment.dealId) relatedDealIds.add(comment.dealId)\n }\n let dealMap = new Map<string, CustomerDeal>()\n if (relatedDealIds.size) {\n const deals = await em.find(CustomerDeal, {\n id: { $in: Array.from(relatedDealIds) },\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n })\n dealMap = new Map(deals.map((deal) => [deal.id, deal]))\n }\n\n await em.nativeDelete(CustomerDealPersonLink, { person: entity })\n for (const link of before.deals) {\n const deal = dealMap.get(link.dealId)\n if (!deal) continue\n const restoredLink = em.create(CustomerDealPersonLink, {\n id: link.id,\n deal,\n person: entity,\n participantRole: link.participantRole,\n createdAt: link.createdAt,\n })\n em.persist(restoredLink)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerActivity, { entity })\n for (const activity of beforeActivities) {\n const restoredActivity = em.create(CustomerActivity, {\n id: activity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt,\n authorUserId: activity.authorUserId,\n appearanceIcon: activity.appearanceIcon,\n appearanceColor: activity.appearanceColor,\n deal: activity.dealId ? dealMap.get(activity.dealId) ?? null : null,\n createdAt: activity.createdAt,\n updatedAt: activity.updatedAt,\n })\n em.persist(restoredActivity)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerComment, { entity })\n for (const comment of before.comments) {\n const restoredComment = em.create(CustomerComment, {\n id: comment.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n body: comment.body,\n authorUserId: comment.authorUserId,\n appearanceIcon: comment.appearanceIcon,\n appearanceColor: comment.appearanceColor,\n deal: comment.dealId ? dealMap.get(comment.dealId) ?? null : null,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n deletedAt: comment.deletedAt,\n })\n em.persist(restoredComment)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerAddress, { entity })\n for (const address of before.addresses) {\n const restoredAddress = em.create(CustomerAddress, {\n id: address.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n })\n em.persist(restoredAddress)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerTodoLink, { entity })\n for (const todo of beforeTodos) {\n const restoredTodo = em.create(CustomerTodoLink, {\n id: todo.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n todoId: todo.todoId,\n todoSource: todo.todoSource,\n createdAt: todo.createdAt,\n createdByUserId: todo.createdByUserId,\n })\n em.persist(restoredTodo)\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity,\n identifiers: {\n id: profile.id ?? entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n const upsertEntries: QueryIndexEventEntry[] = []\n for (const activity of before.activities ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_activity,\n recordId: activity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const comment of before.comments ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_comment,\n recordId: comment.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const address of before.addresses ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_address,\n recordId: address.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const todo of beforeTodos ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_todo_link,\n recordId: todo.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n const dealUpserts: QueryIndexEventEntry[] = []\n for (const deal of before.deals ?? []) {\n if (deal.dealId) {\n dealUpserts.push({\n entityType: E.customers.customer_deal,\n recordId: deal.dealId,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n }\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsForPerson(ctx, entity.id, profile.id, entity.organizationId, entity.tenantId, resetValues)\n }\n await emitQueryIndexUpsertEvents(ctx, upsertEntries)\n await emitQueryIndexUpsertEvents(ctx, dealUpserts)\n },\n }\n\nregisterCommand(createPersonCommand)\nregisterCommand(updatePersonCommand)\nregisterCommand(deletePersonCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport {\n parseWithCustomFields,\n setCustomFieldsIfAny,\n emitCrudSideEffects,\n emitCrudUndoSideEffects,\n requireId,\n} from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport {\n CustomerAddress,\n CustomerComment,\n CustomerActivity,\n CustomerDeal,\n CustomerDealPersonLink,\n CustomerTodoLink,\n CustomerEntity,\n CustomerPersonProfile,\n CustomerTagAssignment,\n} from '../data/entities'\nimport { resolvePersonCustomFieldRouting, CUSTOMER_ENTITY_ID, PERSON_ENTITY_ID } from '../lib/customFieldRouting'\nimport {\n personCreateSchema,\n personUpdateSchema,\n type PersonCreateInput,\n type PersonUpdateInput,\n} from '../data/validators'\nimport {\n ensureOrganizationScope,\n ensureTenantScope,\n extractUndoPayload,\n assertFound,\n syncEntityTags,\n loadEntityTagIds,\n ensureDictionaryEntry,\n emitQueryIndexDeleteEvents,\n emitQueryIndexUpsertEvents,\n type QueryIndexEventEntry,\n} from './shared'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport {\n loadCustomFieldSnapshot,\n buildCustomFieldResetMap,\n} from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'\nimport { E } from '#generated/entities.ids.generated'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\n\ntype PersonAddressSnapshot = {\n id: string\n name: string | null\n purpose: string | null\n addressLine1: string\n addressLine2: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n isPrimary: boolean\n}\n\ntype PersonCommentSnapshot = {\n id: string\n body: string\n authorUserId: string | null\n dealId: string | null\n createdAt: Date\n updatedAt: Date\n deletedAt: Date | null\n appearanceIcon: string | null\n appearanceColor: string | null\n}\n\ntype PersonActivitySnapshot = {\n id: string\n activityType: string\n subject: string | null\n body: string | null\n occurredAt: Date | null\n authorUserId: string | null\n appearanceIcon: string | null\n appearanceColor: string | null\n dealId: string | null\n createdAt: Date\n updatedAt: Date\n}\n\ntype PersonTodoSnapshot = {\n id: string\n todoId: string\n todoSource: string\n createdAt: Date\n createdByUserId: string | null\n}\n\ntype PersonSnapshot = {\n entity: {\n id: string\n organizationId: string\n tenantId: string\n displayName: string\n description: string | null\n ownerUserId: string | null\n primaryEmail: string | null\n primaryPhone: string | null\n status: string | null\n lifecycleStage: string | null\n source: string | null\n nextInteractionAt: Date | null\n nextInteractionName: string | null\n nextInteractionRefId: string | null\n nextInteractionIcon: string | null\n nextInteractionColor: string | null\n isActive: boolean\n }\n profile: {\n id: string\n firstName: string | null\n lastName: string | null\n preferredName: string | null\n jobTitle: string | null\n department: string | null\n seniority: string | null\n timezone: string | null\n linkedInUrl: string | null\n twitterUrl: string | null\n companyEntityId: string | null\n }\n tagIds: string[]\n addresses: PersonAddressSnapshot[]\n comments: PersonCommentSnapshot[]\n custom?: Record<string, unknown>\n deals: Array<{\n id: string\n dealId: string\n participantRole: string | null\n createdAt: Date\n }>\n activities: PersonActivitySnapshot[]\n todos: PersonTodoSnapshot[]\n}\n\ntype PersonUndoPayload = {\n before?: PersonSnapshot | null\n after?: PersonSnapshot | null\n}\n\nconst personCrudIndexer: CrudIndexerConfig<CustomerEntity> = {\n entityType: E.customers.customer_person_profile,\n}\n\nconst personCrudEvents: CrudEventsConfig = {\n module: 'customers',\n entity: 'person',\n persistent: true,\n buildPayload: (ctx) => ({\n id: ctx.identifiers.id,\n organizationId: ctx.identifiers.organizationId,\n tenantId: ctx.identifiers.tenantId,\n }),\n}\n\nfunction normalizeOptionalString(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nfunction normalizeHexColor(value: string | null | undefined): string | null {\n if (typeof value !== 'string') return null\n const trimmed = value.trim().toLowerCase()\n return /^#([0-9a-f]{6})$/.test(trimmed) ? trimmed : null\n}\n\nfunction normalizeEmail(value: string | null | undefined): string | null {\n const normalized = normalizeOptionalString(value)\n return normalized ? normalized.toLowerCase() : null\n}\n\nfunction serializePersonSnapshot(\n entity: CustomerEntity,\n profile: CustomerPersonProfile,\n tagIds: string[],\n addresses: CustomerAddress[],\n comments: CustomerComment[],\n deals: CustomerDealPersonLink[],\n activities: CustomerActivity[],\n todoLinks: CustomerTodoLink[],\n custom?: Record<string, unknown>\n): PersonSnapshot {\n return {\n entity: {\n id: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n displayName: entity.displayName,\n description: entity.description ?? null,\n ownerUserId: entity.ownerUserId ?? null,\n primaryEmail: entity.primaryEmail ?? null,\n primaryPhone: entity.primaryPhone ?? null,\n status: entity.status ?? null,\n lifecycleStage: entity.lifecycleStage ?? null,\n source: entity.source ?? null,\n nextInteractionAt: entity.nextInteractionAt ?? null,\n nextInteractionName: entity.nextInteractionName ?? null,\n nextInteractionRefId: entity.nextInteractionRefId ?? null,\n nextInteractionIcon: entity.nextInteractionIcon ?? null,\n nextInteractionColor: entity.nextInteractionColor ?? null,\n isActive: entity.isActive,\n },\n profile: {\n id: profile.id,\n firstName: profile.firstName ?? null,\n lastName: profile.lastName ?? null,\n preferredName: profile.preferredName ?? null,\n jobTitle: profile.jobTitle ?? null,\n department: profile.department ?? null,\n seniority: profile.seniority ?? null,\n timezone: profile.timezone ?? null,\n linkedInUrl: profile.linkedInUrl ?? null,\n twitterUrl: profile.twitterUrl ?? null,\n companyEntityId: profile.company\n ? typeof profile.company === 'string'\n ? profile.company\n : profile.company.id\n : null,\n },\n tagIds,\n addresses: addresses.map((address) => ({\n id: address.id,\n name: address.name ?? null,\n purpose: address.purpose ?? null,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2 ?? null,\n city: address.city ?? null,\n region: address.region ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n latitude: address.latitude ?? null,\n longitude: address.longitude ?? null,\n isPrimary: address.isPrimary,\n })),\n comments: comments.map((comment) => ({\n id: comment.id,\n body: comment.body,\n authorUserId: comment.authorUserId ?? null,\n dealId: comment.deal\n ? typeof comment.deal === 'string'\n ? comment.deal\n : comment.deal.id\n : null,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n deletedAt: comment.deletedAt ?? null,\n appearanceIcon: comment.appearanceIcon ?? null,\n appearanceColor: comment.appearanceColor ?? null,\n })),\n deals: deals\n .filter((link) => link.deal)\n .map((link) => ({\n id: link.id,\n dealId: link.deal.id,\n participantRole: link.participantRole ?? null,\n createdAt: link.createdAt,\n })),\n activities: activities.map((activity) => ({\n id: activity.id,\n activityType: activity.activityType,\n subject: activity.subject ?? null,\n body: activity.body ?? null,\n occurredAt: activity.occurredAt ?? null,\n authorUserId: activity.authorUserId ?? null,\n appearanceIcon: activity.appearanceIcon ?? null,\n appearanceColor: activity.appearanceColor ?? null,\n dealId: activity.deal\n ? typeof activity.deal === 'string'\n ? activity.deal\n : activity.deal.id\n : null,\n createdAt: activity.createdAt,\n updatedAt: activity.updatedAt,\n })),\n todos: todoLinks.map((todo) => ({\n id: todo.id,\n todoId: todo.todoId,\n todoSource: todo.todoSource,\n createdAt: todo.createdAt,\n createdByUserId: todo.createdByUserId ?? null,\n })),\n custom,\n }\n}\n\nasync function loadPersonSnapshot(em: EntityManager, entityId: string): Promise<PersonSnapshot | null> {\n const entity = await em.findOne(CustomerEntity, { id: entityId, deletedAt: null })\n if (!entity || entity.kind !== 'person') return null\n const profile = await findOneWithDecryption(\n em,\n CustomerPersonProfile,\n { entity: entity },\n { populate: ['company'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n if (!profile) return null\n const tagIds = await loadEntityTagIds(em, entity)\n const addresses = await em.find(CustomerAddress, { entity }, { orderBy: { createdAt: 'asc' } })\n const comments = await findWithDecryption(\n em,\n CustomerComment,\n { entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const deals = await findWithDecryption(\n em,\n CustomerDealPersonLink,\n { person: entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const activities = await findWithDecryption(\n em,\n CustomerActivity,\n { entity },\n { orderBy: { createdAt: 'asc' }, populate: ['deal'] },\n { tenantId: entity.tenantId, organizationId: entity.organizationId },\n )\n const todoLinks = await em.find(CustomerTodoLink, { entity }, { orderBy: { createdAt: 'asc' } })\n const entityCustom = await loadCustomFieldSnapshot(em, {\n entityId: CUSTOMER_ENTITY_ID,\n recordId: entity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n const profileCustom = await loadCustomFieldSnapshot(em, {\n entityId: PERSON_ENTITY_ID,\n recordId: profile.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n const routing = await resolvePersonCustomFieldRouting(em, entity.tenantId, entity.organizationId)\n const custom: Record<string, unknown> = { ...entityCustom }\n for (const [key, value] of Object.entries(profileCustom)) {\n const target = routing.get(key)\n if (target === CUSTOMER_ENTITY_ID && Object.prototype.hasOwnProperty.call(custom, key)) continue\n custom[key] = value\n }\n return serializePersonSnapshot(entity, profile, tagIds, addresses, comments, deals, activities, todoLinks, custom)\n}\n\nasync function resolveCompanyReference(\n em: EntityManager,\n companyId: string | null | undefined,\n organizationId: string,\n tenantId: string\n): Promise<CustomerEntity | null> {\n if (!companyId) return null\n const company = await em.findOne(CustomerEntity, { id: companyId, kind: 'company', deletedAt: null })\n if (!company) {\n throw new CrudHttpError(400, { error: 'Company not found' })\n }\n if (company.organizationId !== organizationId || company.tenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Cannot link person to company outside current scope' })\n }\n return company\n}\n\nasync function setCustomFieldsForPerson(\n ctx: CommandRuntimeContext,\n entityId: string,\n profileId: string,\n organizationId: string,\n tenantId: string,\n values: Record<string, unknown>\n): Promise<void> {\n if (!values || !Object.keys(values).length) return\n const em = (ctx.container.resolve('em') as EntityManager)\n const routing = await resolvePersonCustomFieldRouting(em, tenantId, organizationId)\n const entityScoped: Record<string, unknown> = {}\n const profileScoped: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(values)) {\n const target = routing.get(key) ?? PERSON_ENTITY_ID\n if (target === CUSTOMER_ENTITY_ID) entityScoped[key] = value\n else profileScoped[key] = value\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (Object.keys(entityScoped).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: CUSTOMER_ENTITY_ID,\n recordId: entityId,\n organizationId,\n tenantId,\n values: entityScoped,\n notify: true,\n })\n }\n if (Object.keys(profileScoped).length) {\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: PERSON_ENTITY_ID,\n recordId: profileId,\n organizationId,\n tenantId,\n values: profileScoped,\n notify: true,\n })\n }\n}\n\nconst createPersonCommand: CommandHandler<PersonCreateInput, { entityId: string; personId: string }> = {\n id: 'customers.people.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(personCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const firstName = parsed.firstName?.trim() ?? ''\n const lastName = parsed.lastName?.trim() ?? ''\n const description = normalizeOptionalString(parsed.description)\n const primaryEmail = normalizeEmail(parsed.primaryEmail)\n const primaryPhone = normalizeOptionalString(parsed.primaryPhone)\n const status = normalizeOptionalString(parsed.status)\n const lifecycleStage = normalizeOptionalString(parsed.lifecycleStage)\n const source = normalizeOptionalString(parsed.source)\n const preferredName = normalizeOptionalString(parsed.preferredName)\n const jobTitle = normalizeOptionalString(parsed.jobTitle)\n const department = normalizeOptionalString(parsed.department)\n const seniority = normalizeOptionalString(parsed.seniority)\n const timezone = normalizeOptionalString(parsed.timezone)\n const linkedInUrl = normalizeOptionalString(parsed.linkedInUrl)\n const twitterUrl = normalizeOptionalString(parsed.twitterUrl)\n const displayName = parsed.displayName?.trim() ?? ''\n const nextInteractionName = parsed.nextInteraction?.name ? parsed.nextInteraction.name.trim() : null\n const nextInteractionRefId = normalizeOptionalString(parsed.nextInteraction?.refId)\n const nextInteractionIcon = normalizeOptionalString(parsed.nextInteraction?.icon)\n const nextInteractionColor = normalizeHexColor(parsed.nextInteraction?.color)\n if (!firstName || !lastName) {\n throw new CrudHttpError(400, { error: 'First and last name are required' })\n }\n if (!displayName) {\n throw new CrudHttpError(400, { error: 'Display name is required' })\n }\n\n const entity = em.create(CustomerEntity, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n kind: 'person',\n displayName,\n description,\n ownerUserId: parsed.ownerUserId ?? null,\n primaryEmail,\n primaryPhone,\n status,\n lifecycleStage,\n source,\n nextInteractionAt: parsed.nextInteraction?.at ?? null,\n nextInteractionName,\n nextInteractionRefId,\n nextInteractionIcon,\n nextInteractionColor,\n isActive: parsed.isActive ?? true,\n })\n\n const company = await resolveCompanyReference(em, parsed.companyEntityId ?? null, parsed.organizationId, parsed.tenantId)\n\n const profile = em.create(CustomerPersonProfile, {\n organizationId: parsed.organizationId,\n tenantId: parsed.tenantId,\n entity,\n firstName,\n lastName,\n preferredName,\n jobTitle,\n department,\n seniority,\n timezone,\n linkedInUrl,\n twitterUrl,\n company,\n })\n\n em.persist(entity)\n em.persist(profile)\n if (status) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'status',\n value: status,\n })\n }\n if (jobTitle) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'job_title',\n value: jobTitle,\n })\n }\n if (source) {\n await ensureDictionaryEntry(em, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n kind: 'source',\n value: source,\n })\n }\n await em.flush()\n\n const tenantId = entity.tenantId\n const organizationId = entity.organizationId\n await syncEntityTags(em, entity, parsed.tags)\n await em.flush()\n await setCustomFieldsForPerson(ctx, entity.id, profile.id, organizationId, tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity,\n identifiers: {\n id: profile.id ?? entity.id,\n tenantId,\n organizationId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n return { entityId: entity.id, personId: profile.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadPersonSnapshot(em, result.entityId)\n },\n buildLog: async ({ result, snapshots }) => {\n const { translate } = await resolveTranslations()\n const snapshot = snapshots.after as PersonSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.people.create', 'Create person'),\n resourceKind: 'customers.person',\n resourceId: result.entityId,\n tenantId: snapshot?.entity.tenantId ?? null,\n organizationId: snapshot?.entity.organizationId ?? null,\n snapshotAfter: snapshot ?? null,\n payload: {\n undo: {\n after: snapshot,\n },\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry) ?? null\n const entityId = logEntry?.resourceId ?? payload?.after?.entity.id ?? null\n if (!entityId) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: entityId })\n if (!entity) return\n const profile = await em.findOne(CustomerPersonProfile, { entity })\n await em.nativeDelete(CustomerTagAssignment, { entity })\n if (profile) {\n await em.remove(profile).flush()\n }\n await em.remove(entity).flush()\n },\n}\n\nconst updatePersonCommand: CommandHandler<PersonUpdateInput, { entityId: string }> = {\n id: 'customers.people.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(personUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPersonSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(personUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: parsed.id, deletedAt: null })\n const record = assertFound(entity, 'Person not found')\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const profile = await em.findOne(CustomerPersonProfile, { entity: record })\n if (!profile) throw new CrudHttpError(404, { error: 'Person profile not found' })\n\n if (parsed.description !== undefined) record.description = normalizeOptionalString(parsed.description)\n if (parsed.ownerUserId !== undefined) record.ownerUserId = parsed.ownerUserId ?? null\n if (parsed.primaryEmail !== undefined) record.primaryEmail = normalizeEmail(parsed.primaryEmail)\n if (parsed.primaryPhone !== undefined) record.primaryPhone = normalizeOptionalString(parsed.primaryPhone)\n if (parsed.status !== undefined) {\n const normalizedStatus = normalizeOptionalString(parsed.status)\n record.status = normalizedStatus\n if (normalizedStatus) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'status',\n value: normalizedStatus,\n })\n }\n }\n if (parsed.lifecycleStage !== undefined) record.lifecycleStage = normalizeOptionalString(parsed.lifecycleStage)\n if (parsed.source !== undefined) {\n const normalizedSource = normalizeOptionalString(parsed.source)\n record.source = normalizedSource\n if (normalizedSource) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'source',\n value: normalizedSource,\n })\n }\n }\n if (parsed.isActive !== undefined) record.isActive = parsed.isActive\n if (parsed.nextInteraction) {\n record.nextInteractionAt = parsed.nextInteraction.at\n record.nextInteractionName = parsed.nextInteraction.name.trim()\n record.nextInteractionRefId = normalizeOptionalString(parsed.nextInteraction.refId) ?? null\n record.nextInteractionIcon = normalizeOptionalString(parsed.nextInteraction.icon)\n record.nextInteractionColor = normalizeHexColor(parsed.nextInteraction.color)\n } else if (parsed.nextInteraction === null) {\n record.nextInteractionAt = null\n record.nextInteractionName = null\n record.nextInteractionRefId = null\n record.nextInteractionIcon = null\n record.nextInteractionColor = null\n }\n\n if (parsed.firstName !== undefined) profile.firstName = normalizeOptionalString(parsed.firstName)\n if (parsed.lastName !== undefined) profile.lastName = normalizeOptionalString(parsed.lastName)\n if (parsed.preferredName !== undefined) profile.preferredName = normalizeOptionalString(parsed.preferredName)\n if (parsed.jobTitle !== undefined) {\n const normalizedJobTitle = normalizeOptionalString(parsed.jobTitle)\n profile.jobTitle = normalizedJobTitle\n if (normalizedJobTitle) {\n await ensureDictionaryEntry(em, {\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n kind: 'job_title',\n value: normalizedJobTitle,\n })\n }\n }\n if (parsed.department !== undefined) profile.department = normalizeOptionalString(parsed.department)\n if (parsed.seniority !== undefined) profile.seniority = normalizeOptionalString(parsed.seniority)\n if (parsed.timezone !== undefined) profile.timezone = normalizeOptionalString(parsed.timezone)\n if (parsed.linkedInUrl !== undefined) profile.linkedInUrl = normalizeOptionalString(parsed.linkedInUrl)\n if (parsed.twitterUrl !== undefined) profile.twitterUrl = normalizeOptionalString(parsed.twitterUrl)\n\n if (parsed.companyEntityId !== undefined) {\n profile.company = await resolveCompanyReference(em, parsed.companyEntityId, record.organizationId, record.tenantId)\n }\n\n const profileFieldsUpdated = [\n parsed.firstName, parsed.lastName, parsed.preferredName, parsed.jobTitle,\n parsed.department, parsed.seniority, parsed.timezone, parsed.linkedInUrl,\n parsed.twitterUrl, parsed.companyEntityId,\n ].some((v) => v !== undefined)\n if (profileFieldsUpdated) {\n record.updatedAt = new Date()\n }\n\n if (parsed.displayName !== undefined) {\n const nextDisplayName = parsed.displayName.trim()\n if (!nextDisplayName) {\n throw new CrudHttpError(400, { error: 'Display name is required' })\n }\n record.displayName = nextDisplayName\n }\n\n await em.flush()\n await syncEntityTags(em, record, parsed.tags)\n await em.flush()\n\n await setCustomFieldsForPerson(ctx, record.id, profile.id, record.organizationId, record.tenantId, custom)\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: record,\n identifiers: {\n id: profile.id ?? record.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n return { entityId: record.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return await loadPersonSnapshot(em, result.entityId)\n },\n buildLog: async ({ snapshots }) => {\n const { translate } = await resolveTranslations()\n const before = snapshots.before as PersonSnapshot | undefined\n if (!before) return null\n const afterSnapshot = snapshots.after as PersonSnapshot | undefined\n return {\n actionLabel: translate('customers.audit.people.update', 'Update person'),\n resourceKind: 'customers.person',\n resourceId: before.entity.id,\n tenantId: before.entity.tenantId,\n organizationId: before.entity.organizationId,\n snapshotBefore: before,\n snapshotAfter: afterSnapshot ?? null,\n payload: {\n undo: {\n before,\n after: afterSnapshot ?? null,\n } satisfies PersonUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await em.findOne(CustomerEntity, { id: before.entity.id })\n if (!entity) {\n const newEntity = em.create(CustomerEntity, {\n id: before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n kind: 'person',\n displayName: before.entity.displayName,\n description: before.entity.description,\n ownerUserId: before.entity.ownerUserId,\n primaryEmail: before.entity.primaryEmail,\n primaryPhone: before.entity.primaryPhone,\n status: before.entity.status,\n lifecycleStage: before.entity.lifecycleStage,\n source: before.entity.source,\n nextInteractionAt: before.entity.nextInteractionAt,\n nextInteractionName: before.entity.nextInteractionName,\n nextInteractionRefId: before.entity.nextInteractionRefId,\n nextInteractionIcon: before.entity.nextInteractionIcon,\n nextInteractionColor: before.entity.nextInteractionColor,\n isActive: before.entity.isActive,\n })\n em.persist(newEntity)\n const profile = em.create(CustomerPersonProfile, {\n id: before.profile.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n entity: newEntity,\n firstName: before.profile.firstName,\n lastName: before.profile.lastName,\n preferredName: before.profile.preferredName,\n jobTitle: before.profile.jobTitle,\n department: before.profile.department,\n seniority: before.profile.seniority,\n timezone: before.profile.timezone,\n linkedInUrl: before.profile.linkedInUrl,\n twitterUrl: before.profile.twitterUrl,\n })\n em.persist(profile)\n if (before.profile.companyEntityId) {\n profile.company = await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n }\n await em.flush()\n await syncEntityTags(em, newEntity, before.tagIds)\n await em.flush()\n } else {\n entity.displayName = before.entity.displayName\n entity.description = before.entity.description\n entity.ownerUserId = before.entity.ownerUserId\n entity.primaryEmail = before.entity.primaryEmail\n entity.primaryPhone = before.entity.primaryPhone\n entity.status = before.entity.status\n entity.lifecycleStage = before.entity.lifecycleStage\n entity.source = before.entity.source\n entity.nextInteractionAt = before.entity.nextInteractionAt\n entity.nextInteractionName = before.entity.nextInteractionName\n entity.nextInteractionRefId = before.entity.nextInteractionRefId\n entity.nextInteractionIcon = before.entity.nextInteractionIcon\n entity.nextInteractionColor = before.entity.nextInteractionColor\n entity.isActive = before.entity.isActive\n await em.flush()\n const profile = await em.findOne(CustomerPersonProfile, { entity })\n if (profile) {\n profile.firstName = before.profile.firstName\n profile.lastName = before.profile.lastName\n profile.preferredName = before.profile.preferredName\n profile.jobTitle = before.profile.jobTitle\n profile.department = before.profile.department\n profile.seniority = before.profile.seniority\n profile.timezone = before.profile.timezone\n profile.linkedInUrl = before.profile.linkedInUrl\n profile.twitterUrl = before.profile.twitterUrl\n profile.company = before.profile.companyEntityId\n ? await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n : null\n }\n await syncEntityTags(em, entity, before.tagIds)\n await em.flush()\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: await em.findOne(CustomerEntity, { id: before.entity.id }),\n identifiers: {\n id: before.profile.id ?? before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n const resetValues = buildCustomFieldResetMap(before.custom, payload?.after?.custom)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsForPerson(ctx, before.entity.id, before.profile.id, before.entity.organizationId, before.entity.tenantId, resetValues)\n }\n },\n}\n\nconst deletePersonCommand: CommandHandler<{ body?: Record<string, unknown>; query?: Record<string, unknown> }, { entityId: string }> =\n {\n id: 'customers.people.delete',\n async prepare(input, ctx) {\n const id = requireId(input, 'Person id required')\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadPersonSnapshot(em, id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(input, ctx) {\n const id = requireId(input, 'Person id required')\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadPersonSnapshot(em, id)\n const entity = await em.findOne(CustomerEntity, { id, deletedAt: null })\n const record = assertFound(entity, 'Person not found')\n ensureTenantScope(ctx, record.tenantId)\n ensureOrganizationScope(ctx, record.organizationId)\n const profile = await em.findOne(CustomerPersonProfile, { entity: record })\n if (profile) em.remove(profile)\n await em.nativeDelete(CustomerAddress, { entity: record })\n await em.nativeDelete(CustomerComment, { entity: record })\n await em.nativeDelete(CustomerActivity, { entity: record })\n await em.nativeDelete(CustomerTodoLink, { entity: record })\n await em.nativeDelete(CustomerTagAssignment, { entity: record })\n await em.nativeDelete(CustomerDealPersonLink, { person: record })\n em.remove(record)\n await em.flush()\n\n const indexDeletes: QueryIndexEventEntry[] = []\n const dealUpserts: QueryIndexEventEntry[] = []\n if (snapshot) {\n for (const activity of snapshot.activities ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_activity,\n recordId: activity.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const comment of snapshot.comments ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_comment,\n recordId: comment.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const address of snapshot.addresses ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_address,\n recordId: address.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const todo of snapshot.todos ?? []) {\n indexDeletes.push({\n entityType: E.customers.customer_todo_link,\n recordId: todo.id,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n for (const deal of snapshot.deals ?? []) {\n if (deal.dealId) {\n dealUpserts.push({\n entityType: E.customers.customer_deal,\n recordId: deal.dealId,\n tenantId: record.tenantId,\n organizationId: record.organizationId,\n })\n }\n }\n }\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: record,\n identifiers: {\n id: profile?.id ?? record.id,\n organizationId: record.organizationId,\n tenantId: record.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n await emitQueryIndexDeleteEvents(ctx, indexDeletes)\n await emitQueryIndexUpsertEvents(ctx, dealUpserts)\n return { entityId: record.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as PersonSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('customers.audit.people.delete', 'Delete person'),\n resourceKind: 'customers.person',\n resourceId: before.entity.id,\n tenantId: before.entity.tenantId,\n organizationId: before.entity.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n } satisfies PersonUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<PersonUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let entity = await em.findOne(CustomerEntity, { id: before.entity.id })\n if (!entity) {\n entity = em.create(CustomerEntity, {\n id: before.entity.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n kind: 'person',\n displayName: before.entity.displayName,\n description: before.entity.description,\n ownerUserId: before.entity.ownerUserId,\n primaryEmail: before.entity.primaryEmail,\n primaryPhone: before.entity.primaryPhone,\n status: before.entity.status,\n lifecycleStage: before.entity.lifecycleStage,\n source: before.entity.source,\n nextInteractionAt: before.entity.nextInteractionAt,\n nextInteractionName: before.entity.nextInteractionName,\n nextInteractionRefId: before.entity.nextInteractionRefId,\n nextInteractionIcon: before.entity.nextInteractionIcon,\n nextInteractionColor: before.entity.nextInteractionColor,\n isActive: before.entity.isActive,\n })\n em.persist(entity)\n }\n\n entity.displayName = before.entity.displayName\n entity.description = before.entity.description\n entity.ownerUserId = before.entity.ownerUserId\n entity.primaryEmail = before.entity.primaryEmail\n entity.primaryPhone = before.entity.primaryPhone\n entity.status = before.entity.status\n entity.lifecycleStage = before.entity.lifecycleStage\n entity.source = before.entity.source\n entity.nextInteractionAt = before.entity.nextInteractionAt\n entity.nextInteractionName = before.entity.nextInteractionName\n entity.nextInteractionRefId = before.entity.nextInteractionRefId\n entity.nextInteractionIcon = before.entity.nextInteractionIcon\n entity.nextInteractionColor = before.entity.nextInteractionColor\n entity.isActive = before.entity.isActive\n\n let profile = await em.findOne(CustomerPersonProfile, { entity })\n if (!profile) {\n profile = em.create(CustomerPersonProfile, {\n id: before.profile.id,\n organizationId: before.entity.organizationId,\n tenantId: before.entity.tenantId,\n entity,\n firstName: before.profile.firstName,\n lastName: before.profile.lastName,\n preferredName: before.profile.preferredName,\n jobTitle: before.profile.jobTitle,\n department: before.profile.department,\n seniority: before.profile.seniority,\n timezone: before.profile.timezone,\n linkedInUrl: before.profile.linkedInUrl,\n twitterUrl: before.profile.twitterUrl,\n })\n } else {\n profile.firstName = before.profile.firstName\n profile.lastName = before.profile.lastName\n profile.preferredName = before.profile.preferredName\n profile.jobTitle = before.profile.jobTitle\n profile.department = before.profile.department\n profile.seniority = before.profile.seniority\n profile.timezone = before.profile.timezone\n profile.linkedInUrl = before.profile.linkedInUrl\n profile.twitterUrl = before.profile.twitterUrl\n }\n\n if (before.profile.companyEntityId) {\n profile.company = await resolveCompanyReference(\n em,\n before.profile.companyEntityId,\n before.entity.organizationId,\n before.entity.tenantId\n )\n } else {\n profile.company = null\n }\n\n await em.flush()\n await syncEntityTags(em, entity, before.tagIds)\n await em.flush()\n\n const beforeActivities = (before as { activities?: PersonActivitySnapshot[] }).activities ?? []\n const beforeTodos = (before as { todos?: PersonTodoSnapshot[] }).todos ?? []\n\n const relatedDealIds = new Set<string>()\n for (const link of before.deals) relatedDealIds.add(link.dealId)\n for (const activity of beforeActivities) {\n if (activity.dealId) relatedDealIds.add(activity.dealId)\n }\n for (const comment of before.comments) {\n if (comment.dealId) relatedDealIds.add(comment.dealId)\n }\n let dealMap = new Map<string, CustomerDeal>()\n if (relatedDealIds.size) {\n const deals = await em.find(CustomerDeal, {\n id: { $in: Array.from(relatedDealIds) },\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n })\n dealMap = new Map(deals.map((deal) => [deal.id, deal]))\n }\n\n await em.nativeDelete(CustomerDealPersonLink, { person: entity })\n for (const link of before.deals) {\n const deal = dealMap.get(link.dealId)\n if (!deal) continue\n const restoredLink = em.create(CustomerDealPersonLink, {\n id: link.id,\n deal,\n person: entity,\n participantRole: link.participantRole,\n createdAt: link.createdAt,\n })\n em.persist(restoredLink)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerActivity, { entity })\n for (const activity of beforeActivities) {\n const restoredActivity = em.create(CustomerActivity, {\n id: activity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n activityType: activity.activityType,\n subject: activity.subject,\n body: activity.body,\n occurredAt: activity.occurredAt,\n authorUserId: activity.authorUserId,\n appearanceIcon: activity.appearanceIcon,\n appearanceColor: activity.appearanceColor,\n deal: activity.dealId ? dealMap.get(activity.dealId) ?? null : null,\n createdAt: activity.createdAt,\n updatedAt: activity.updatedAt,\n })\n em.persist(restoredActivity)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerComment, { entity })\n for (const comment of before.comments) {\n const restoredComment = em.create(CustomerComment, {\n id: comment.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n body: comment.body,\n authorUserId: comment.authorUserId,\n appearanceIcon: comment.appearanceIcon,\n appearanceColor: comment.appearanceColor,\n deal: comment.dealId ? dealMap.get(comment.dealId) ?? null : null,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n deletedAt: comment.deletedAt,\n })\n em.persist(restoredComment)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerAddress, { entity })\n for (const address of before.addresses) {\n const restoredAddress = em.create(CustomerAddress, {\n id: address.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n name: address.name,\n purpose: address.purpose,\n addressLine1: address.addressLine1,\n addressLine2: address.addressLine2,\n city: address.city,\n region: address.region,\n postalCode: address.postalCode,\n country: address.country,\n latitude: address.latitude,\n longitude: address.longitude,\n isPrimary: address.isPrimary,\n })\n em.persist(restoredAddress)\n }\n await em.flush()\n\n await em.nativeDelete(CustomerTodoLink, { entity })\n for (const todo of beforeTodos) {\n const restoredTodo = em.create(CustomerTodoLink, {\n id: todo.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n entity,\n todoId: todo.todoId,\n todoSource: todo.todoSource,\n createdAt: todo.createdAt,\n createdByUserId: todo.createdByUserId,\n })\n em.persist(restoredTodo)\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity,\n identifiers: {\n id: profile.id ?? entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n },\n indexer: personCrudIndexer,\n events: personCrudEvents,\n })\n\n const upsertEntries: QueryIndexEventEntry[] = []\n for (const activity of before.activities ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_activity,\n recordId: activity.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const comment of before.comments ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_comment,\n recordId: comment.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const address of before.addresses ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_address,\n recordId: address.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n for (const todo of beforeTodos ?? []) {\n upsertEntries.push({\n entityType: E.customers.customer_todo_link,\n recordId: todo.id,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n const dealUpserts: QueryIndexEventEntry[] = []\n for (const deal of before.deals ?? []) {\n if (deal.dealId) {\n dealUpserts.push({\n entityType: E.customers.customer_deal,\n recordId: deal.dealId,\n tenantId: entity.tenantId,\n organizationId: entity.organizationId,\n })\n }\n }\n const resetValues = buildCustomFieldResetMap(before.custom, undefined)\n if (Object.keys(resetValues).length) {\n await setCustomFieldsForPerson(ctx, entity.id, profile.id, entity.organizationId, entity.tenantId, resetValues)\n }\n await emitQueryIndexUpsertEvents(ctx, upsertEntries)\n await emitQueryIndexUpsertEvents(ctx, dealUpserts)\n },\n }\n\nregisterCommand(createPersonCommand)\nregisterCommand(updatePersonCommand)\nregisterCommand(deletePersonCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/core",
|
|
3
|
-
"version": "0.4.6-develop-
|
|
3
|
+
"version": "0.4.6-develop-96c36a4b2a",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
"dependencies": {
|
|
210
|
-
"@open-mercato/shared": "0.4.6-develop-
|
|
210
|
+
"@open-mercato/shared": "0.4.6-develop-96c36a4b2a",
|
|
211
211
|
"@types/html-to-text": "^9.0.4",
|
|
212
212
|
"@types/semver": "^7.5.8",
|
|
213
213
|
"@xyflow/react": "^12.6.0",
|
|
@@ -613,6 +613,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
613
613
|
linkedInUrl: profile.linkedInUrl,
|
|
614
614
|
twitterUrl: profile.twitterUrl,
|
|
615
615
|
companyEntityId: profile.company ? (typeof profile.company === 'string' ? profile.company : profile.company.id) : null,
|
|
616
|
+
updatedAt: profile.updatedAt.toISOString(),
|
|
616
617
|
}
|
|
617
618
|
: null,
|
|
618
619
|
customFields,
|
|
@@ -777,6 +778,7 @@ const personDetailResponseSchema = z.object({
|
|
|
777
778
|
linkedInUrl: z.string().nullable().optional(),
|
|
778
779
|
twitterUrl: z.string().nullable().optional(),
|
|
779
780
|
companyEntityId: z.string().uuid().nullable().optional(),
|
|
781
|
+
updatedAt: z.string(),
|
|
780
782
|
})
|
|
781
783
|
.nullable(),
|
|
782
784
|
customFields: z.record(z.string(), z.unknown()),
|
|
@@ -662,6 +662,15 @@ const updatePersonCommand: CommandHandler<PersonUpdateInput, { entityId: string
|
|
|
662
662
|
profile.company = await resolveCompanyReference(em, parsed.companyEntityId, record.organizationId, record.tenantId)
|
|
663
663
|
}
|
|
664
664
|
|
|
665
|
+
const profileFieldsUpdated = [
|
|
666
|
+
parsed.firstName, parsed.lastName, parsed.preferredName, parsed.jobTitle,
|
|
667
|
+
parsed.department, parsed.seniority, parsed.timezone, parsed.linkedInUrl,
|
|
668
|
+
parsed.twitterUrl, parsed.companyEntityId,
|
|
669
|
+
].some((v) => v !== undefined)
|
|
670
|
+
if (profileFieldsUpdated) {
|
|
671
|
+
record.updatedAt = new Date()
|
|
672
|
+
}
|
|
673
|
+
|
|
665
674
|
if (parsed.displayName !== undefined) {
|
|
666
675
|
const nextDisplayName = parsed.displayName.trim()
|
|
667
676
|
if (!nextDisplayName) {
|