@open-mercato/core 0.6.8-develop.7012.1.1dbd6f5fbd → 0.6.8-develop.7015.1.af90a2ddc7

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.
Files changed (31) hide show
  1. package/dist/modules/customers/api/companies/[id]/people/route.js +19 -63
  2. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  3. package/dist/modules/customers/api/companies/[id]/route.js +9 -85
  4. package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
  5. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +4 -3
  6. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
  7. package/dist/modules/customers/commands/personCompanyLinks.js +131 -2
  8. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  9. package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -1
  10. package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
  11. package/dist/modules/customers/components/detail/PersonCompaniesSection.js +3 -1
  12. package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
  13. package/dist/modules/customers/data/validators.js +10 -2
  14. package/dist/modules/customers/data/validators.js.map +2 -2
  15. package/dist/modules/customers/events.js +5 -0
  16. package/dist/modules/customers/events.js.map +2 -2
  17. package/dist/modules/customers/lib/personCompanies.js +100 -2
  18. package/dist/modules/customers/lib/personCompanies.js.map +2 -2
  19. package/dist/modules/query_index/lib/search-tokens.js +79 -3
  20. package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
  21. package/package.json +7 -7
  22. package/src/modules/customers/api/companies/[id]/people/route.ts +20 -72
  23. package/src/modules/customers/api/companies/[id]/route.ts +11 -97
  24. package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +12 -4
  25. package/src/modules/customers/commands/personCompanyLinks.ts +224 -8
  26. package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -1
  27. package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +8 -1
  28. package/src/modules/customers/data/validators.ts +18 -3
  29. package/src/modules/customers/events.ts +5 -0
  30. package/src/modules/customers/lib/personCompanies.ts +136 -1
  31. package/src/modules/query_index/lib/search-tokens.ts +135 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/data/validators.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport { isValidPhoneNumber } from '@open-mercato/shared/lib/phone'\nimport { COORDINATE_RANGES } from '@open-mercato/shared/lib/location/coordinates'\nimport { dictionaryEntrySortModeSchema } from '@open-mercato/core/modules/dictionaries/lib/entrySort'\n\nconst uuid = () => z.string().uuid()\n\nexport const CUSTOMER_PHONE_INVALID_MESSAGE_KEY = 'customers.people.form.primaryPhone.invalid'\nexport const ACTIVITY_DATE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.dateRequired'\nexport const ACTIVITY_TIME_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.timeRequired'\nexport const ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.phoneRequired'\nexport const ACTIVITY_PHONE_INVALID_MESSAGE_KEY = 'customers.activities.errors.phoneInvalid'\n\n// customer_deals.description is an unbounded `text` column; this cap only exists to keep\n// request bodies, fulltext search documents and query-index documents from growing without limit.\nexport const DEAL_DESCRIPTION_MAX_LENGTH = 50_000\n\nconst emptyStringToNull = (value: unknown): unknown => {\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nconst phoneSchema = z.preprocess(\n emptyStringToNull,\n z\n .string()\n .trim()\n .max(50)\n .refine((val) => isValidPhoneNumber(val), { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY })\n .nullable()\n .optional(),\n)\n\nconst clearableEmailSchema = z.preprocess(\n emptyStringToNull,\n z.string().email().max(320).nullable().optional(),\n)\n\nconst clearableUrlSchema = z.preprocess(\n emptyStringToNull,\n z.string().url().max(300).nullable().optional(),\n)\n\n// Domain is a plain (non-URL) string that maps to a nullable column, so blanking\n// a previously-set value on edit must transmit null to clear it. See #2529.\nconst clearableDomainSchema = z.preprocess(\n emptyStringToNull,\n z.string().trim().max(200).nullable().optional(),\n)\n\n// Plain optional string fields that map to nullable columns: blanking a previously-set\n// value on edit must transmit null to clear it, not be silently dropped. See #3050.\nconst clearableStringSchema = (max: number) =>\n z.preprocess(emptyStringToNull, z.string().trim().max(max).nullable().optional())\n\n// Annual revenue maps to a nullable numeric column. `''`/whitespace/null all clear it;\n// `.nullable()` short-circuits before coercion so null does not coerce to 0. See #3050.\nconst clearableRevenueSchema = z.preprocess(\n (value) => {\n if (typeof value === 'string' && value.trim().length === 0) return null\n return value\n },\n z.coerce.number().min(0).nullable().optional(),\n)\n\nconst interactionPhoneNumberSchema = z.string().trim().max(50).optional().nullable()\n\nconst scopedSchema = z.object({\n organizationId: uuid(),\n tenantId: uuid(),\n})\n\nconst nextInteractionSchema = z\n .object({\n at: z.coerce.date(),\n name: z.string().trim().min(1).max(200),\n refId: z.string().trim().max(191).optional().nullable(),\n icon: z.string().trim().max(100).optional().nullable(),\n color: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n })\n .strict()\n\nconst displayNameSchema = z.string().trim().min(1).max(200)\n\nconst baseEntitySchema = {\n displayName: displayNameSchema,\n // Nullable so a blanked description on edit clears the column instead of being dropped. See #3050.\n description: clearableStringSchema(4000),\n ownerUserId: uuid().optional(),\n primaryEmail: clearableEmailSchema,\n primaryPhone: phoneSchema,\n status: z.string().trim().max(100).optional(),\n lifecycleStage: z.string().trim().max(100).optional(),\n source: z.string().trim().max(150).optional(),\n temperature: z.string().trim().max(100).optional(),\n renewalQuarter: z.string().trim().max(100).optional(),\n isActive: z.boolean().optional(),\n nextInteraction: nextInteractionSchema.nullable().optional(),\n tags: z.array(uuid()).optional(),\n}\n\nconst personDetailsSchema = {\n preferredName: z.string().trim().max(120).optional(),\n jobTitle: z.string().trim().max(150).optional(),\n department: z.string().trim().max(150).optional(),\n seniority: z.string().trim().max(100).optional(),\n timezone: z.string().trim().max(120).optional(),\n linkedInUrl: clearableUrlSchema,\n twitterUrl: clearableUrlSchema,\n companyEntityId: uuid().nullable().optional(),\n}\n\nconst personFirstNameSchema = z.string().trim().min(1).max(120)\nconst personLastNameSchema = z.string().trim().min(1).max(120)\n\nconst companyDetailsSchema = {\n // Nullable so blanked values on edit clear the columns instead of being dropped. See #3050.\n legalName: clearableStringSchema(200),\n brandName: clearableStringSchema(200),\n domain: clearableDomainSchema,\n websiteUrl: clearableUrlSchema,\n industry: z.string().trim().max(150).optional(),\n sizeBucket: clearableStringSchema(100),\n annualRevenue: clearableRevenueSchema,\n}\n\nexport const personCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema.optional(),\n firstName: personFirstNameSchema,\n lastName: personLastNameSchema,\n ...personDetailsSchema,\n})\n\nexport const personUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(\n scopedSchema.extend({\n ...baseEntitySchema,\n ...personDetailsSchema,\n firstName: personFirstNameSchema.optional(),\n lastName: personLastNameSchema.optional(),\n }).partial()\n )\n\nexport const companyCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema,\n ...companyDetailsSchema,\n})\n\nexport const companyUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(companyCreateSchema.partial())\n\nexport const dealCreateSchema = scopedSchema.extend({\n title: z.string().min(1).max(200),\n description: z.string().max(DEAL_DESCRIPTION_MAX_LENGTH).optional(),\n status: z.string().max(50).optional(),\n pipelineStage: z.string().max(100).optional(),\n pipelineId: uuid().optional(),\n pipelineStageId: uuid().optional(),\n valueAmount: z.coerce.number().min(0).optional(),\n valueCurrency: z.string().min(3).max(3).optional(),\n probability: z.number().min(0).max(100).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n // Nullable: the bulk owner-update worker passes `null` to clear ownership.\n // Without `.nullable()`, dealUpdateSchema.parse({ ownerUserId: null }) throws\n // ZodError \"expected string, received null\" inside the queue worker (TC-CRM-069).\n ownerUserId: uuid().optional().nullable(),\n source: z.string().max(150).optional(),\n closureOutcome: z.enum(['won', 'lost']).optional(),\n lossReasonId: uuid().optional(),\n lossNotes: z.string().max(4000).optional(),\n companyIds: z.array(uuid()).optional(),\n personIds: z.array(uuid()).optional(),\n primaryPersonEntityId: uuid().nullable().optional(),\n})\n\nexport const dealUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(dealCreateSchema.partial())\n\n// Bulk update schemas \u2014 used by `api/deals/bulk-update-{owner,stage}/route.ts`. Kept here\n// so all deal-write contracts live next to `dealCreateSchema` / `dealUpdateSchema`.\nexport const dealsBulkUpdateOwnerSchema = z.object({\n ids: z.array(uuid()).min(1).max(10000),\n ownerUserId: uuid().nullable(),\n})\n\nexport const dealsBulkUpdateStageSchema = z.object({\n ids: z.array(uuid()).min(1).max(10000),\n pipelineStageId: uuid(),\n})\n\nexport const dealsBulkUpdateResponseSchema = z.object({\n ok: z.boolean(),\n progressJobId: uuid().nullable(),\n message: z.string(),\n})\n\nexport const activityCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n occurredAt: z.coerce.date().optional(),\n dealId: uuid().optional(),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const activityUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(activityCreateSchema.partial())\n\nexport const commentCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n dealId: uuid().optional(),\n body: z.string().min(1).max(8000),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const commentUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(commentCreateSchema.partial())\n\nexport const addressCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce\n .number()\n .min(COORDINATE_RANGES.latitude.min)\n .max(COORDINATE_RANGES.latitude.max)\n .nullable()\n .optional(),\n longitude: z.coerce\n .number()\n .min(COORDINATE_RANGES.longitude.min)\n .max(COORDINATE_RANGES.longitude.max)\n .nullable()\n .optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const addressUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(addressCreateSchema.partial())\n\nexport const tagCreateSchema = scopedSchema.extend({\n slug: z\n .string()\n .min(1)\n .max(80)\n .regex(/^[a-z0-9_-]+$/, 'Slug must be lowercase and may contain dashes or underscores'),\n label: z.string().min(1).max(120),\n color: z.string().max(30).optional(),\n description: z.string().max(400).optional(),\n})\n\nexport const tagUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(tagCreateSchema.partial())\n\nconst KNOWN_DICTIONARY_KINDS = [\n 'status',\n 'source',\n 'lifecycle_stage',\n 'address_type',\n 'activity_type',\n 'deal_status',\n 'pipeline_stage',\n 'job_title',\n 'industry',\n 'temperature',\n 'renewal_quarter',\n 'person_company_role',\n] as const\nconst CUSTOM_DICTIONARY_KIND_PATTERN = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/\nconst dictionaryKindEnum = z.string().trim().refine(\n (value) =>\n (KNOWN_DICTIONARY_KINDS as readonly string[]).includes(value) ||\n CUSTOM_DICTIONARY_KIND_PATTERN.test(value),\n { message: 'Unsupported dictionary kind' },\n)\n\nconst dictionaryValueSchema = z.string().trim().min(1).max(150)\nconst dictionaryLabelSchema = z.string().trim().max(150)\n// Pipeline-stage rows migrated to semantic tone identifiers in\n// Migration20260519120000_pipeline_stage_color_tones; AddStageDialog now writes those\n// directly. Other dictionary kinds still store hex. Accept either format so round-tripping\n// a migrated pipeline-stage entry through the dictionary edit UI doesn't fail validation.\nconst DICTIONARY_COLOR_TONES = ['success', 'warning', 'info', 'error', 'neutral', 'brand', 'pink'] as const\nconst dictionaryColorSchema = z\n .string()\n .trim()\n .regex(\n new RegExp(`^(#[0-9a-fA-F]{6}|${DICTIONARY_COLOR_TONES.join('|')})$`),\n 'Color must be a six-digit hex code (e.g. #3366ff) or a semantic tone identifier',\n )\nconst dictionaryIconSchema = z.string().trim().max(48)\n\nexport const customerDictionaryEntryCreateSchema = scopedSchema.extend({\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema,\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n})\n\nexport type CustomerDictionaryEntryCreateInput = z.infer<typeof customerDictionaryEntryCreateSchema>\n\nexport const customerDictionaryEntryUpdateSchema = scopedSchema\n .extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema.optional(),\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n })\n .refine(\n (payload) =>\n payload.value !== undefined ||\n payload.label !== undefined ||\n payload.color !== undefined ||\n payload.icon !== undefined,\n {\n message: 'Provide at least one field to update.',\n path: ['value'],\n }\n )\n\nexport type CustomerDictionaryEntryUpdateInput = z.infer<typeof customerDictionaryEntryUpdateSchema>\n\nexport const customerDictionaryEntryDeleteSchema = scopedSchema.extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n})\n\nexport type CustomerDictionaryEntryDeleteInput = z.infer<typeof customerDictionaryEntryDeleteSchema>\n\nexport const tagAssignmentSchema = scopedSchema.extend({\n tagId: uuid(),\n entityId: uuid(),\n})\n\nexport const todoLinkCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n todoId: uuid(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n})\n\nexport const todoLinkWithTodoCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n title: z.string().min(1).max(200),\n isDone: z.boolean().optional(),\n is_done: z.boolean().optional(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n todoCustom: z.record(z.string(), z.any()).optional(),\n custom: z.record(z.string(), z.any()).optional(),\n})\n\n// --- Interaction schemas ---\n\n/**\n * @deprecated Interaction statuses are now dictionary-backed and tenant-configurable\n * (the `interaction-statuses` dictionary). This frozen 3-value list is kept only for\n * backward compatibility; it is no longer the validation source (the API accepts any\n * `z.string().max(50)`). For open/terminal semantics use `lib/interactionStatus.ts`\n * (`isOpenInteractionStatus` / `isTerminalInteractionStatus` / `INTERACTION_STATUS_*`);\n * for the seeded default set use `INTERACTION_STATUS_DEFAULTS` in `cli.ts`. Do not expand\n * this list \u2014 adding members would break exhaustive consumers.\n */\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\n/** @deprecated See {@link interactionStatusValues}. */\nexport type InteractionStatus = typeof interactionStatusValues[number]\n\nconst interactionParticipantSchema = z.object({\n userId: z.string().uuid(),\n name: z.string().trim().max(200).optional(),\n email: z.string().trim().max(320).optional(),\n status: z.string().trim().max(50).optional(),\n})\n\nconst interactionLinkedEntitySchema = z.object({\n id: z.string().uuid(),\n // 'resource' links calendar events to bookable resources (rooms, cars,\n // equipment) from the optional resources module (#3552).\n type: z.enum(['company', 'deal', 'offer', 'resource']),\n label: z.string().trim().max(500),\n})\n\nconst interactionGuestPermissionsSchema = z\n .object({\n canInviteOthers: z.boolean().optional(),\n canModify: z.boolean().optional(),\n canSeeList: z.boolean().optional(),\n })\n .strict()\n\nconst interactionExtendedFields = {\n durationMinutes: z.number().int().min(0).optional().nullable(),\n location: z.string().trim().max(500).optional().nullable(),\n allDay: z.boolean().optional().nullable(),\n recurrenceRule: z.string().trim().max(500).optional().nullable(),\n recurrenceEnd: z.coerce.date().optional().nullable(),\n participants: z.array(interactionParticipantSchema).optional().nullable(),\n reminderMinutes: z.number().int().min(0).optional().nullable(),\n visibility: z.string().trim().max(50).optional().nullable(),\n linkedEntities: z.array(interactionLinkedEntitySchema).optional().nullable(),\n guestPermissions: interactionGuestPermissionsSchema.optional().nullable(),\n} as const\n\nconst interactionCreateBaseSchema = scopedSchema.extend({\n id: z.string().uuid().optional(),\n entityId: z.string().uuid(),\n interactionType: z.string().trim().min(1).max(100),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n // Lenient like `deal_status` (status: z.string().max(50)). The `interaction-statuses`\n // dictionary drives the UI dropdown; the API accepts any string <=50 chars so existing\n // rows, external writers, and the dispatch-crm MCP keep working. Open/terminal semantics\n // live in lib/interactionStatus.ts, not in this validator.\n status: z.string().max(50).optional().default('planned'),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n source: z.string().trim().max(100).optional().nullable(),\n ...interactionExtendedFields,\n})\n\nfunction deriveScheduledAtFromDateTime(date?: string, time?: string): Date | null {\n if (!date || typeof date !== 'string') return null\n const trimmedDate = date.trim()\n if (!trimmedDate) return null\n const trimmedTime = typeof time === 'string' ? time.trim() : ''\n const iso = trimmedTime ? `${trimmedDate}T${trimmedTime}:00` : `${trimmedDate}T00:00:00`\n const parsed = new Date(iso)\n return Number.isNaN(parsed.getTime()) ? null : parsed\n}\n\nexport const interactionCreateSchema = interactionCreateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined && value.phoneNumber !== null) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Derive `scheduledAt` from `date+time` when only the latter are sent so\n // external API consumers don't silently persist `scheduled_at: null` after\n // the validator already enforced non-empty date/time. The form already\n // computes `scheduledAt` itself, so this branch is a no-op for the form path.\n .transform((value) => {\n if (value.scheduledAt) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionCreateInput = z.infer<typeof interactionCreateSchema>\n\nconst interactionUpdateBaseSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(\n scopedSchema\n .extend({\n interactionType: z.string().trim().min(1).max(100).optional(),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.string().max(50).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n pinned: z.boolean().optional(),\n ...interactionExtendedFields,\n })\n .partial(),\n )\n\nexport const interactionUpdateSchema = interactionUpdateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Mirror the create-schema derivation for partial updates: when an external\n // caller supplies `date+time` without `scheduledAt`, derive the timestamp so\n // the update doesn't silently leave `scheduled_at` stale.\n .transform((value) => {\n if (value.scheduledAt !== undefined) return value\n if (!value.date && !value.time) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionUpdateInput = z.infer<typeof interactionUpdateSchema>\n\nexport const interactionCompleteSchema = z.object({\n id: z.string().uuid(),\n occurredAt: z.coerce.date().optional(),\n})\n\nexport const interactionCancelSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const customerAddressFormatSchema = z.enum(['line_first', 'street_first'])\n\nexport const customerSettingsUpsertSchema = scopedSchema.extend({\n addressFormat: customerAddressFormatSchema,\n})\n\nexport const customerStuckThresholdUpsertSchema = scopedSchema.extend({\n stuckThresholdDays: z.number().int().min(1).max(365),\n})\n\nexport const customerDictionarySortModesSchema = z.record(z.string(), dictionaryEntrySortModeSchema)\n\nexport const customerDictionarySortModesUpsertSchema = scopedSchema.extend({\n dictionarySortModes: customerDictionarySortModesSchema,\n})\n\nexport type PersonCreateInput = z.infer<typeof personCreateSchema>\nexport type PersonUpdateInput = z.infer<typeof personUpdateSchema>\nexport type CompanyCreateInput = z.infer<typeof companyCreateSchema>\nexport type CompanyUpdateInput = z.infer<typeof companyUpdateSchema>\nexport type DealCreateInput = z.infer<typeof dealCreateSchema>\nexport type DealUpdateInput = z.infer<typeof dealUpdateSchema>\nexport type ActivityCreateInput = z.infer<typeof activityCreateSchema>\nexport type ActivityUpdateInput = z.infer<typeof activityUpdateSchema>\nexport type CommentCreateInput = z.infer<typeof commentCreateSchema>\nexport type CommentUpdateInput = z.infer<typeof commentUpdateSchema>\nexport type AddressCreateInput = z.infer<typeof addressCreateSchema>\nexport type AddressUpdateInput = z.infer<typeof addressUpdateSchema>\nexport type TagCreateInput = z.infer<typeof tagCreateSchema>\nexport type TagUpdateInput = z.infer<typeof tagUpdateSchema>\nexport type TagAssignmentInput = z.infer<typeof tagAssignmentSchema>\nexport type TodoLinkCreateInput = z.infer<typeof todoLinkCreateSchema>\nexport type TodoLinkWithTodoCreateInput = z.infer<typeof todoLinkWithTodoCreateSchema>\nexport type CustomerSettingsUpsertInput = z.infer<typeof customerSettingsUpsertSchema>\nexport type CustomerStuckThresholdUpsertInput = z.infer<typeof customerStuckThresholdUpsertSchema>\nexport type CustomerDictionarySortModesUpsertInput = z.infer<typeof customerDictionarySortModesUpsertSchema>\nexport type CustomerAddressFormatInput = z.infer<typeof customerAddressFormatSchema>\nexport type InteractionCompleteInput = z.infer<typeof interactionCompleteSchema>\nexport type InteractionCancelInput = z.infer<typeof interactionCancelSchema>\n\n// --- Pipeline schemas ---\n\nexport const pipelineCreateSchema = scopedSchema.extend({\n name: z.string().trim().min(1).max(200),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineUpdateSchema = z.object({\n id: uuid(),\n name: z.string().trim().min(1).max(200).optional(),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport type PipelineCreateInput = z.infer<typeof pipelineCreateSchema>\nexport type PipelineUpdateInput = z.infer<typeof pipelineUpdateSchema>\nexport type PipelineDeleteInput = z.infer<typeof pipelineDeleteSchema>\n\n// --- Pipeline Stage schemas ---\n\nexport const pipelineStageCreateSchema = scopedSchema.extend({\n pipelineId: uuid(),\n label: z.string().trim().min(1).max(200),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).nullish(),\n icon: z.string().trim().max(100).nullish(),\n})\n\nexport const pipelineStageUpdateSchema = z.object({\n id: uuid(),\n label: z.string().trim().min(1).max(200).optional(),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).nullish(),\n icon: z.string().trim().max(100).nullish(),\n})\n\nexport const pipelineStageDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport const pipelineStageReorderSchema = scopedSchema.extend({\n stages: z.array(z.object({\n id: uuid(),\n order: z.number().int().min(0),\n })).min(1),\n})\n\nexport type PipelineStageCreateInput = z.infer<typeof pipelineStageCreateSchema>\nexport type PipelineStageUpdateInput = z.infer<typeof pipelineStageUpdateSchema>\nexport type PipelineStageDeleteInput = z.infer<typeof pipelineStageDeleteSchema>\nexport type PipelineStageReorderInput = z.infer<typeof pipelineStageReorderSchema>\n\nexport const entityRoleCreateSchema = scopedSchema.extend({\n entityType: z.enum(['company', 'person']),\n entityId: uuid(),\n roleType: z.string().trim().min(1).max(100),\n userId: uuid(),\n})\n\nexport const entityRoleUpdateSchema = scopedSchema.extend({\n id: uuid(),\n userId: uuid(),\n})\n\nexport const entityRoleDeleteSchema = scopedSchema.extend({\n id: uuid(),\n})\n\nexport type EntityRoleCreateInput = z.infer<typeof entityRoleCreateSchema>\nexport type EntityRoleUpdateInput = z.infer<typeof entityRoleUpdateSchema>\nexport type EntityRoleDeleteInput = z.infer<typeof entityRoleDeleteSchema>\n\nexport const updateKindSettingSchema = z.object({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type UpdateKindSettingInput = z.infer<typeof updateKindSettingSchema>\n\nexport const customerKindSettingsUpsertSchema = scopedSchema.extend({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type CustomerKindSettingsUpsertInput = z.infer<typeof customerKindSettingsUpsertSchema>\n\nexport const labelCreateSchema = z.object({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/).optional(),\n})\n\nexport type LabelCreateInput = z.infer<typeof labelCreateSchema>\n\nexport const labelCreateCommandSchema = scopedSchema.extend({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/),\n userId: uuid(),\n})\n\nexport type LabelCreateCommandInput = z.infer<typeof labelCreateCommandSchema>\n\nexport const labelAssignmentSchema = z.object({\n labelId: z.string().uuid(),\n entityId: z.string().uuid(),\n})\n\nexport type LabelAssignmentInput = z.infer<typeof labelAssignmentSchema>\n\nexport const labelAssignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport const labelUnassignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport type LabelAssignCommandInput = z.infer<typeof labelAssignCommandSchema>\nexport type LabelUnassignCommandInput = z.infer<typeof labelUnassignCommandSchema>\n\nexport const personCompanyLinkCreateSchema = scopedSchema.extend({\n personEntityId: uuid(),\n companyEntityId: uuid(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const personCompanyLinkUpdateSchema = scopedSchema.extend({\n linkId: uuid(),\n isPrimary: z.boolean(),\n})\n\nexport const personCompanyLinkDeleteSchema = scopedSchema.extend({\n linkId: uuid(),\n})\n\nexport type PersonCompanyLinkCreateInput = z.infer<typeof personCompanyLinkCreateSchema>\nexport type PersonCompanyLinkUpdateInput = z.infer<typeof personCompanyLinkUpdateSchema>\nexport type PersonCompanyLinkDeleteInput = z.infer<typeof personCompanyLinkDeleteSchema>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { isValidPhoneNumber } from '@open-mercato/shared/lib/phone'\nimport { COORDINATE_RANGES } from '@open-mercato/shared/lib/location/coordinates'\nimport { dictionaryEntrySortModeSchema } from '@open-mercato/core/modules/dictionaries/lib/entrySort'\n\nconst uuid = () => z.string().uuid()\n\nexport const CUSTOMER_PHONE_INVALID_MESSAGE_KEY = 'customers.people.form.primaryPhone.invalid'\nexport const ACTIVITY_DATE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.dateRequired'\nexport const ACTIVITY_TIME_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.timeRequired'\nexport const ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY = 'customers.activities.errors.phoneRequired'\nexport const ACTIVITY_PHONE_INVALID_MESSAGE_KEY = 'customers.activities.errors.phoneInvalid'\n\n// customer_deals.description is an unbounded `text` column; this cap only exists to keep\n// request bodies, fulltext search documents and query-index documents from growing without limit.\nexport const DEAL_DESCRIPTION_MAX_LENGTH = 50_000\n\nconst emptyStringToNull = (value: unknown): unknown => {\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n return trimmed.length ? trimmed : null\n}\n\nconst phoneSchema = z.preprocess(\n emptyStringToNull,\n z\n .string()\n .trim()\n .max(50)\n .refine((val) => isValidPhoneNumber(val), { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY })\n .nullable()\n .optional(),\n)\n\nconst clearableEmailSchema = z.preprocess(\n emptyStringToNull,\n z.string().email().max(320).nullable().optional(),\n)\n\nconst clearableUrlSchema = z.preprocess(\n emptyStringToNull,\n z.string().url().max(300).nullable().optional(),\n)\n\n// Domain is a plain (non-URL) string that maps to a nullable column, so blanking\n// a previously-set value on edit must transmit null to clear it. See #2529.\nconst clearableDomainSchema = z.preprocess(\n emptyStringToNull,\n z.string().trim().max(200).nullable().optional(),\n)\n\n// Plain optional string fields that map to nullable columns: blanking a previously-set\n// value on edit must transmit null to clear it, not be silently dropped. See #3050.\nconst clearableStringSchema = (max: number) =>\n z.preprocess(emptyStringToNull, z.string().trim().max(max).nullable().optional())\n\n// Annual revenue maps to a nullable numeric column. `''`/whitespace/null all clear it;\n// `.nullable()` short-circuits before coercion so null does not coerce to 0. See #3050.\nconst clearableRevenueSchema = z.preprocess(\n (value) => {\n if (typeof value === 'string' && value.trim().length === 0) return null\n return value\n },\n z.coerce.number().min(0).nullable().optional(),\n)\n\nconst interactionPhoneNumberSchema = z.string().trim().max(50).optional().nullable()\n\nconst scopedSchema = z.object({\n organizationId: uuid(),\n tenantId: uuid(),\n})\n\nconst nextInteractionSchema = z\n .object({\n at: z.coerce.date(),\n name: z.string().trim().min(1).max(200),\n refId: z.string().trim().max(191).optional().nullable(),\n icon: z.string().trim().max(100).optional().nullable(),\n color: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n })\n .strict()\n\nconst displayNameSchema = z.string().trim().min(1).max(200)\n\nconst baseEntitySchema = {\n displayName: displayNameSchema,\n // Nullable so a blanked description on edit clears the column instead of being dropped. See #3050.\n description: clearableStringSchema(4000),\n ownerUserId: uuid().optional(),\n primaryEmail: clearableEmailSchema,\n primaryPhone: phoneSchema,\n status: z.string().trim().max(100).optional(),\n lifecycleStage: z.string().trim().max(100).optional(),\n source: z.string().trim().max(150).optional(),\n temperature: z.string().trim().max(100).optional(),\n renewalQuarter: z.string().trim().max(100).optional(),\n isActive: z.boolean().optional(),\n nextInteraction: nextInteractionSchema.nullable().optional(),\n tags: z.array(uuid()).optional(),\n}\n\nconst personDetailsSchema = {\n preferredName: z.string().trim().max(120).optional(),\n jobTitle: z.string().trim().max(150).optional(),\n department: z.string().trim().max(150).optional(),\n seniority: z.string().trim().max(100).optional(),\n timezone: z.string().trim().max(120).optional(),\n linkedInUrl: clearableUrlSchema,\n twitterUrl: clearableUrlSchema,\n companyEntityId: uuid().nullable().optional(),\n}\n\nconst personFirstNameSchema = z.string().trim().min(1).max(120)\nconst personLastNameSchema = z.string().trim().min(1).max(120)\n\nconst companyDetailsSchema = {\n // Nullable so blanked values on edit clear the columns instead of being dropped. See #3050.\n legalName: clearableStringSchema(200),\n brandName: clearableStringSchema(200),\n domain: clearableDomainSchema,\n websiteUrl: clearableUrlSchema,\n industry: z.string().trim().max(150).optional(),\n sizeBucket: clearableStringSchema(100),\n annualRevenue: clearableRevenueSchema,\n}\n\nexport const personCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema.optional(),\n firstName: personFirstNameSchema,\n lastName: personLastNameSchema,\n ...personDetailsSchema,\n})\n\nexport const personUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(\n scopedSchema.extend({\n ...baseEntitySchema,\n ...personDetailsSchema,\n firstName: personFirstNameSchema.optional(),\n lastName: personLastNameSchema.optional(),\n }).partial()\n )\n\nexport const companyCreateSchema = scopedSchema.extend({\n ...baseEntitySchema,\n displayName: displayNameSchema,\n ...companyDetailsSchema,\n})\n\nexport const companyUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(companyCreateSchema.partial())\n\nexport const dealCreateSchema = scopedSchema.extend({\n title: z.string().min(1).max(200),\n description: z.string().max(DEAL_DESCRIPTION_MAX_LENGTH).optional(),\n status: z.string().max(50).optional(),\n pipelineStage: z.string().max(100).optional(),\n pipelineId: uuid().optional(),\n pipelineStageId: uuid().optional(),\n valueAmount: z.coerce.number().min(0).optional(),\n valueCurrency: z.string().min(3).max(3).optional(),\n probability: z.number().min(0).max(100).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n // Nullable: the bulk owner-update worker passes `null` to clear ownership.\n // Without `.nullable()`, dealUpdateSchema.parse({ ownerUserId: null }) throws\n // ZodError \"expected string, received null\" inside the queue worker (TC-CRM-069).\n ownerUserId: uuid().optional().nullable(),\n source: z.string().max(150).optional(),\n closureOutcome: z.enum(['won', 'lost']).optional(),\n lossReasonId: uuid().optional(),\n lossNotes: z.string().max(4000).optional(),\n companyIds: z.array(uuid()).optional(),\n personIds: z.array(uuid()).optional(),\n primaryPersonEntityId: uuid().nullable().optional(),\n})\n\nexport const dealUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(dealCreateSchema.partial())\n\n// Bulk update schemas \u2014 used by `api/deals/bulk-update-{owner,stage}/route.ts`. Kept here\n// so all deal-write contracts live next to `dealCreateSchema` / `dealUpdateSchema`.\nexport const dealsBulkUpdateOwnerSchema = z.object({\n ids: z.array(uuid()).min(1).max(10000),\n ownerUserId: uuid().nullable(),\n})\n\nexport const dealsBulkUpdateStageSchema = z.object({\n ids: z.array(uuid()).min(1).max(10000),\n pipelineStageId: uuid(),\n})\n\nexport const dealsBulkUpdateResponseSchema = z.object({\n ok: z.boolean(),\n progressJobId: uuid().nullable(),\n message: z.string(),\n})\n\nexport const activityCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n activityType: z.string().min(1).max(100),\n subject: z.string().max(200).optional(),\n body: z.string().max(8000).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n occurredAt: z.coerce.date().optional(),\n dealId: uuid().optional(),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const activityUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(activityCreateSchema.partial())\n\nexport const commentCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n dealId: uuid().optional(),\n body: z.string().min(1).max(8000),\n authorUserId: uuid().optional(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/)\n .optional()\n .nullable(),\n})\n\nexport const commentUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(commentCreateSchema.partial())\n\nexport const addressCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n name: z.string().max(150).optional(),\n purpose: z.string().max(150).optional(),\n companyName: z.string().max(200).optional(),\n addressLine1: z.string().min(1).max(300),\n addressLine2: z.string().max(300).optional(),\n buildingNumber: z.string().max(50).optional(),\n flatNumber: z.string().max(50).optional(),\n city: z.string().max(150).optional(),\n region: z.string().max(150).optional(),\n postalCode: z.string().max(30).optional(),\n country: z.string().max(150).optional(),\n latitude: z.coerce\n .number()\n .min(COORDINATE_RANGES.latitude.min)\n .max(COORDINATE_RANGES.latitude.max)\n .nullable()\n .optional(),\n longitude: z.coerce\n .number()\n .min(COORDINATE_RANGES.longitude.min)\n .max(COORDINATE_RANGES.longitude.max)\n .nullable()\n .optional(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const addressUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(addressCreateSchema.partial())\n\nexport const tagCreateSchema = scopedSchema.extend({\n slug: z\n .string()\n .min(1)\n .max(80)\n .regex(/^[a-z0-9_-]+$/, 'Slug must be lowercase and may contain dashes or underscores'),\n label: z.string().min(1).max(120),\n color: z.string().max(30).optional(),\n description: z.string().max(400).optional(),\n})\n\nexport const tagUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(tagCreateSchema.partial())\n\nconst KNOWN_DICTIONARY_KINDS = [\n 'status',\n 'source',\n 'lifecycle_stage',\n 'address_type',\n 'activity_type',\n 'deal_status',\n 'pipeline_stage',\n 'job_title',\n 'industry',\n 'temperature',\n 'renewal_quarter',\n 'person_company_role',\n] as const\nconst CUSTOM_DICTIONARY_KIND_PATTERN = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/\nconst dictionaryKindEnum = z.string().trim().refine(\n (value) =>\n (KNOWN_DICTIONARY_KINDS as readonly string[]).includes(value) ||\n CUSTOM_DICTIONARY_KIND_PATTERN.test(value),\n { message: 'Unsupported dictionary kind' },\n)\n\nconst dictionaryValueSchema = z.string().trim().min(1).max(150)\nconst dictionaryLabelSchema = z.string().trim().max(150)\n// Pipeline-stage rows migrated to semantic tone identifiers in\n// Migration20260519120000_pipeline_stage_color_tones; AddStageDialog now writes those\n// directly. Other dictionary kinds still store hex. Accept either format so round-tripping\n// a migrated pipeline-stage entry through the dictionary edit UI doesn't fail validation.\nconst DICTIONARY_COLOR_TONES = ['success', 'warning', 'info', 'error', 'neutral', 'brand', 'pink'] as const\nconst dictionaryColorSchema = z\n .string()\n .trim()\n .regex(\n new RegExp(`^(#[0-9a-fA-F]{6}|${DICTIONARY_COLOR_TONES.join('|')})$`),\n 'Color must be a six-digit hex code (e.g. #3366ff) or a semantic tone identifier',\n )\nconst dictionaryIconSchema = z.string().trim().max(48)\n\nexport const customerDictionaryEntryCreateSchema = scopedSchema.extend({\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema,\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n})\n\nexport type CustomerDictionaryEntryCreateInput = z.infer<typeof customerDictionaryEntryCreateSchema>\n\nexport const customerDictionaryEntryUpdateSchema = scopedSchema\n .extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n value: dictionaryValueSchema.optional(),\n label: dictionaryLabelSchema.optional(),\n color: dictionaryColorSchema.nullable().optional(),\n icon: dictionaryIconSchema.nullable().optional(),\n })\n .refine(\n (payload) =>\n payload.value !== undefined ||\n payload.label !== undefined ||\n payload.color !== undefined ||\n payload.icon !== undefined,\n {\n message: 'Provide at least one field to update.',\n path: ['value'],\n }\n )\n\nexport type CustomerDictionaryEntryUpdateInput = z.infer<typeof customerDictionaryEntryUpdateSchema>\n\nexport const customerDictionaryEntryDeleteSchema = scopedSchema.extend({\n id: uuid(),\n kind: dictionaryKindEnum,\n})\n\nexport type CustomerDictionaryEntryDeleteInput = z.infer<typeof customerDictionaryEntryDeleteSchema>\n\nexport const tagAssignmentSchema = scopedSchema.extend({\n tagId: uuid(),\n entityId: uuid(),\n})\n\nexport const todoLinkCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n todoId: uuid(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n})\n\nexport const todoLinkWithTodoCreateSchema = scopedSchema.extend({\n entityId: uuid(),\n title: z.string().min(1).max(200),\n isDone: z.boolean().optional(),\n is_done: z.boolean().optional(),\n todoSource: z.string().min(1).max(120).default('customers:interaction'),\n createdByUserId: uuid().optional(),\n todoCustom: z.record(z.string(), z.any()).optional(),\n custom: z.record(z.string(), z.any()).optional(),\n})\n\n// --- Interaction schemas ---\n\n/**\n * @deprecated Interaction statuses are now dictionary-backed and tenant-configurable\n * (the `interaction-statuses` dictionary). This frozen 3-value list is kept only for\n * backward compatibility; it is no longer the validation source (the API accepts any\n * `z.string().max(50)`). For open/terminal semantics use `lib/interactionStatus.ts`\n * (`isOpenInteractionStatus` / `isTerminalInteractionStatus` / `INTERACTION_STATUS_*`);\n * for the seeded default set use `INTERACTION_STATUS_DEFAULTS` in `cli.ts`. Do not expand\n * this list \u2014 adding members would break exhaustive consumers.\n */\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\n/** @deprecated See {@link interactionStatusValues}. */\nexport type InteractionStatus = typeof interactionStatusValues[number]\n\nconst interactionParticipantSchema = z.object({\n userId: z.string().uuid(),\n name: z.string().trim().max(200).optional(),\n email: z.string().trim().max(320).optional(),\n status: z.string().trim().max(50).optional(),\n})\n\nconst interactionLinkedEntitySchema = z.object({\n id: z.string().uuid(),\n // 'resource' links calendar events to bookable resources (rooms, cars,\n // equipment) from the optional resources module (#3552).\n type: z.enum(['company', 'deal', 'offer', 'resource']),\n label: z.string().trim().max(500),\n})\n\nconst interactionGuestPermissionsSchema = z\n .object({\n canInviteOthers: z.boolean().optional(),\n canModify: z.boolean().optional(),\n canSeeList: z.boolean().optional(),\n })\n .strict()\n\nconst interactionExtendedFields = {\n durationMinutes: z.number().int().min(0).optional().nullable(),\n location: z.string().trim().max(500).optional().nullable(),\n allDay: z.boolean().optional().nullable(),\n recurrenceRule: z.string().trim().max(500).optional().nullable(),\n recurrenceEnd: z.coerce.date().optional().nullable(),\n participants: z.array(interactionParticipantSchema).optional().nullable(),\n reminderMinutes: z.number().int().min(0).optional().nullable(),\n visibility: z.string().trim().max(50).optional().nullable(),\n linkedEntities: z.array(interactionLinkedEntitySchema).optional().nullable(),\n guestPermissions: interactionGuestPermissionsSchema.optional().nullable(),\n} as const\n\nconst interactionCreateBaseSchema = scopedSchema.extend({\n id: z.string().uuid().optional(),\n entityId: z.string().uuid(),\n interactionType: z.string().trim().min(1).max(100),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n // Lenient like `deal_status` (status: z.string().max(50)). The `interaction-statuses`\n // dictionary drives the UI dropdown; the API accepts any string <=50 chars so existing\n // rows, external writers, and the dispatch-crm MCP keep working. Open/terminal semantics\n // live in lib/interactionStatus.ts, not in this validator.\n status: z.string().max(50).optional().default('planned'),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n source: z.string().trim().max(100).optional().nullable(),\n ...interactionExtendedFields,\n})\n\nfunction deriveScheduledAtFromDateTime(date?: string, time?: string): Date | null {\n if (!date || typeof date !== 'string') return null\n const trimmedDate = date.trim()\n if (!trimmedDate) return null\n const trimmedTime = typeof time === 'string' ? time.trim() : ''\n const iso = trimmedTime ? `${trimmedDate}T${trimmedTime}:00` : `${trimmedDate}T00:00:00`\n const parsed = new Date(iso)\n return Number.isNaN(parsed.getTime()) ? null : parsed\n}\n\nexport const interactionCreateSchema = interactionCreateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined && value.phoneNumber !== null) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Derive `scheduledAt` from `date+time` when only the latter are sent so\n // external API consumers don't silently persist `scheduled_at: null` after\n // the validator already enforced non-empty date/time. The form already\n // computes `scheduledAt` itself, so this branch is a no-op for the form path.\n .transform((value) => {\n if (value.scheduledAt) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionCreateInput = z.infer<typeof interactionCreateSchema>\n\nconst interactionUpdateBaseSchema = z\n .object({\n id: z.string().uuid(),\n })\n .merge(\n scopedSchema\n .extend({\n interactionType: z.string().trim().min(1).max(100).optional(),\n title: z.string().trim().max(500).optional().nullable(),\n body: z.string().trim().max(10000).optional().nullable(),\n status: z.string().max(50).optional(),\n date: z.string().trim().min(1, ACTIVITY_DATE_REQUIRED_MESSAGE_KEY).optional(),\n time: z.string().trim().min(1, ACTIVITY_TIME_REQUIRED_MESSAGE_KEY).optional(),\n phoneNumber: interactionPhoneNumberSchema,\n scheduledAt: z.coerce.date().optional().nullable(),\n occurredAt: z.coerce.date().optional().nullable(),\n priority: z.number().int().min(0).max(100).optional().nullable(),\n authorUserId: z.string().uuid().optional().nullable(),\n ownerUserId: z.string().uuid().optional().nullable(),\n dealId: z.string().uuid().optional().nullable(),\n appearanceIcon: z.string().trim().max(100).optional().nullable(),\n appearanceColor: z.string().trim().regex(/^#([0-9a-fA-F]{6})$/).optional().nullable(),\n pinned: z.boolean().optional(),\n ...interactionExtendedFields,\n })\n .partial(),\n )\n\nexport const interactionUpdateSchema = interactionUpdateBaseSchema\n .superRefine((value, ctx) => {\n if (value.interactionType === 'call' && value.phoneNumber !== undefined) {\n const phone = typeof value.phoneNumber === 'string' ? value.phoneNumber.trim() : ''\n if (!phone) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_REQUIRED_MESSAGE_KEY,\n })\n } else if (!isValidPhoneNumber(phone)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['phoneNumber'],\n message: ACTIVITY_PHONE_INVALID_MESSAGE_KEY,\n })\n }\n }\n })\n // Mirror the create-schema derivation for partial updates: when an external\n // caller supplies `date+time` without `scheduledAt`, derive the timestamp so\n // the update doesn't silently leave `scheduled_at` stale.\n .transform((value) => {\n if (value.scheduledAt !== undefined) return value\n if (!value.date && !value.time) return value\n const derived = deriveScheduledAtFromDateTime(value.date, value.time)\n return derived ? { ...value, scheduledAt: derived } : value\n })\n\nexport type InteractionUpdateInput = z.infer<typeof interactionUpdateSchema>\n\nexport const interactionCompleteSchema = z.object({\n id: z.string().uuid(),\n occurredAt: z.coerce.date().optional(),\n})\n\nexport const interactionCancelSchema = z.object({\n id: z.string().uuid(),\n})\n\nexport const customerAddressFormatSchema = z.enum(['line_first', 'street_first'])\n\nexport const customerSettingsUpsertSchema = scopedSchema.extend({\n addressFormat: customerAddressFormatSchema,\n})\n\nexport const customerStuckThresholdUpsertSchema = scopedSchema.extend({\n stuckThresholdDays: z.number().int().min(1).max(365),\n})\n\nexport const customerDictionarySortModesSchema = z.record(z.string(), dictionaryEntrySortModeSchema)\n\nexport const customerDictionarySortModesUpsertSchema = scopedSchema.extend({\n dictionarySortModes: customerDictionarySortModesSchema,\n})\n\nexport type PersonCreateInput = z.infer<typeof personCreateSchema>\nexport type PersonUpdateInput = z.infer<typeof personUpdateSchema>\nexport type CompanyCreateInput = z.infer<typeof companyCreateSchema>\nexport type CompanyUpdateInput = z.infer<typeof companyUpdateSchema>\nexport type DealCreateInput = z.infer<typeof dealCreateSchema>\nexport type DealUpdateInput = z.infer<typeof dealUpdateSchema>\nexport type ActivityCreateInput = z.infer<typeof activityCreateSchema>\nexport type ActivityUpdateInput = z.infer<typeof activityUpdateSchema>\nexport type CommentCreateInput = z.infer<typeof commentCreateSchema>\nexport type CommentUpdateInput = z.infer<typeof commentUpdateSchema>\nexport type AddressCreateInput = z.infer<typeof addressCreateSchema>\nexport type AddressUpdateInput = z.infer<typeof addressUpdateSchema>\nexport type TagCreateInput = z.infer<typeof tagCreateSchema>\nexport type TagUpdateInput = z.infer<typeof tagUpdateSchema>\nexport type TagAssignmentInput = z.infer<typeof tagAssignmentSchema>\nexport type TodoLinkCreateInput = z.infer<typeof todoLinkCreateSchema>\nexport type TodoLinkWithTodoCreateInput = z.infer<typeof todoLinkWithTodoCreateSchema>\nexport type CustomerSettingsUpsertInput = z.infer<typeof customerSettingsUpsertSchema>\nexport type CustomerStuckThresholdUpsertInput = z.infer<typeof customerStuckThresholdUpsertSchema>\nexport type CustomerDictionarySortModesUpsertInput = z.infer<typeof customerDictionarySortModesUpsertSchema>\nexport type CustomerAddressFormatInput = z.infer<typeof customerAddressFormatSchema>\nexport type InteractionCompleteInput = z.infer<typeof interactionCompleteSchema>\nexport type InteractionCancelInput = z.infer<typeof interactionCancelSchema>\n\n// --- Pipeline schemas ---\n\nexport const pipelineCreateSchema = scopedSchema.extend({\n name: z.string().trim().min(1).max(200),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineUpdateSchema = z.object({\n id: uuid(),\n name: z.string().trim().min(1).max(200).optional(),\n isDefault: z.boolean().optional(),\n})\n\nexport const pipelineDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport type PipelineCreateInput = z.infer<typeof pipelineCreateSchema>\nexport type PipelineUpdateInput = z.infer<typeof pipelineUpdateSchema>\nexport type PipelineDeleteInput = z.infer<typeof pipelineDeleteSchema>\n\n// --- Pipeline Stage schemas ---\n\nexport const pipelineStageCreateSchema = scopedSchema.extend({\n pipelineId: uuid(),\n label: z.string().trim().min(1).max(200),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).nullish(),\n icon: z.string().trim().max(100).nullish(),\n})\n\nexport const pipelineStageUpdateSchema = z.object({\n id: uuid(),\n label: z.string().trim().min(1).max(200).optional(),\n order: z.number().int().min(0).optional(),\n color: z.string().trim().max(20).nullish(),\n icon: z.string().trim().max(100).nullish(),\n})\n\nexport const pipelineStageDeleteSchema = z.object({\n id: uuid(),\n})\n\nexport const pipelineStageReorderSchema = scopedSchema.extend({\n stages: z.array(z.object({\n id: uuid(),\n order: z.number().int().min(0),\n })).min(1),\n})\n\nexport type PipelineStageCreateInput = z.infer<typeof pipelineStageCreateSchema>\nexport type PipelineStageUpdateInput = z.infer<typeof pipelineStageUpdateSchema>\nexport type PipelineStageDeleteInput = z.infer<typeof pipelineStageDeleteSchema>\nexport type PipelineStageReorderInput = z.infer<typeof pipelineStageReorderSchema>\n\nexport const entityRoleCreateSchema = scopedSchema.extend({\n entityType: z.enum(['company', 'person']),\n entityId: uuid(),\n roleType: z.string().trim().min(1).max(100),\n userId: uuid(),\n})\n\nexport const entityRoleUpdateSchema = scopedSchema.extend({\n id: uuid(),\n userId: uuid(),\n})\n\nexport const entityRoleDeleteSchema = scopedSchema.extend({\n id: uuid(),\n})\n\nexport type EntityRoleCreateInput = z.infer<typeof entityRoleCreateSchema>\nexport type EntityRoleUpdateInput = z.infer<typeof entityRoleUpdateSchema>\nexport type EntityRoleDeleteInput = z.infer<typeof entityRoleDeleteSchema>\n\nexport const updateKindSettingSchema = z.object({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type UpdateKindSettingInput = z.infer<typeof updateKindSettingSchema>\n\nexport const customerKindSettingsUpsertSchema = scopedSchema.extend({\n kind: z.string().trim().min(1).max(100),\n selectionMode: z.enum(['single', 'multi']).optional(),\n visibleInTags: z.boolean().optional(),\n sortOrder: z.number().int().min(0).optional(),\n})\n\nexport type CustomerKindSettingsUpsertInput = z.infer<typeof customerKindSettingsUpsertSchema>\n\nexport const labelCreateSchema = z.object({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/).optional(),\n})\n\nexport type LabelCreateInput = z.infer<typeof labelCreateSchema>\n\nexport const labelCreateCommandSchema = scopedSchema.extend({\n label: z.string().trim().min(1).max(120),\n slug: z.string().trim().min(1).max(80).regex(/^[a-z0-9_-]+$/),\n userId: uuid(),\n})\n\nexport type LabelCreateCommandInput = z.infer<typeof labelCreateCommandSchema>\n\nexport const labelAssignmentSchema = z.object({\n labelId: z.string().uuid(),\n entityId: z.string().uuid(),\n})\n\nexport type LabelAssignmentInput = z.infer<typeof labelAssignmentSchema>\n\nexport const labelAssignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport const labelUnassignCommandSchema = scopedSchema.extend({\n labelId: uuid(),\n entityId: uuid(),\n})\n\nexport type LabelAssignCommandInput = z.infer<typeof labelAssignCommandSchema>\nexport type LabelUnassignCommandInput = z.infer<typeof labelUnassignCommandSchema>\n\nexport const personCompanyLinkCreateSchema = scopedSchema.extend({\n personEntityId: uuid(),\n companyEntityId: uuid(),\n isPrimary: z.boolean().optional(),\n})\n\nexport const personCompanyLinkUpdateSchema = scopedSchema.extend({\n linkId: uuid(),\n isPrimary: z.boolean(),\n})\n\n// Two shapes are accepted, because a person can belong to a company in two ways:\n// through a `customer_person_company_links` row (`linkId`), or through a legacy\n// profile-only assignment where `customer_person_profiles.company_id` is set and no\n// link row was ever created (migrated CRM data, #5114). Both detaches go through the\n// same command so audit, undo and cache invalidation stay consistent.\nexport const personCompanyLinkDeleteSchema = scopedSchema\n .extend({\n linkId: uuid().optional(),\n personEntityId: uuid().optional(),\n companyEntityId: uuid().optional(),\n })\n .refine(\n (payload) => Boolean(payload.linkId) || Boolean(payload.personEntityId && payload.companyEntityId),\n {\n message: 'Provide either linkId or both personEntityId and companyEntityId.',\n path: ['linkId'],\n }\n )\n\nexport type PersonCompanyLinkCreateInput = z.infer<typeof personCompanyLinkCreateSchema>\nexport type PersonCompanyLinkUpdateInput = z.infer<typeof personCompanyLinkUpdateSchema>\nexport type PersonCompanyLinkDeleteInput = z.infer<typeof personCompanyLinkDeleteSchema>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -60,6 +60,11 @@ const events = [
60
60
  { id: "customers.person_company_link.created", label: "Person Linked To Company", entity: "person_company_link", category: "crud", clientBroadcast: true },
61
61
  { id: "customers.person_company_link.updated", label: "Person-Company Link Updated", entity: "person_company_link", category: "crud", clientBroadcast: true },
62
62
  { id: "customers.person_company_link.deleted", label: "Person Unlinked From Company", entity: "person_company_link", category: "crud", clientBroadcast: true },
63
+ // Legacy profile-only company assignments (`customer_person_profiles.company_id` set with no
64
+ // backing link row, #5114) have no link entity, so detaching one cannot honestly emit
65
+ // `customers.person_company_link.deleted` — that event's payload promises a link id that never
66
+ // existed. This sibling carries the same live-refresh signal for that shape instead.
67
+ { id: "customers.person.company_assignment.detached", label: "Legacy Company Assignment Detached", entity: "person_company_link", category: "lifecycle", clientBroadcast: true },
63
68
  // ── Email integration (2026-05-27) ────────────────────────────────────────
64
69
  { id: "customers.email.linked", label: "Email Linked To Person", entity: "email_link", category: "lifecycle", clientBroadcast: true },
65
70
  { id: "customers.email.visibility_changed", label: "Email Visibility Changed", entity: "email_link", category: "lifecycle", clientBroadcast: true }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/customers/events.ts"],
4
- "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\n/**\n * Customers Module Events\n *\n * Declares all events that can be emitted by the customers module.\n */\nconst events = [\n // People\n { id: 'customers.person.created', label: 'Customer (Person) Created', entity: 'person', category: 'crud' },\n { id: 'customers.person.updated', label: 'Customer (Person) Updated', entity: 'person', category: 'crud' },\n { id: 'customers.person.deleted', label: 'Customer (Person) Deleted', entity: 'person', category: 'crud' },\n\n // Companies\n { id: 'customers.company.created', label: 'Customer (Company) Created', entity: 'company', category: 'crud' },\n { id: 'customers.company.updated', label: 'Customer (Company) Updated', entity: 'company', category: 'crud' },\n { id: 'customers.company.deleted', label: 'Customer (Company) Deleted', entity: 'company', category: 'crud' },\n\n // Deals\n { id: 'customers.deal.created', label: 'Deal Created', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.updated', label: 'Deal Updated', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.deleted', label: 'Deal Deleted', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.won', label: 'Deal Won', entity: 'deal', category: 'lifecycle' },\n { id: 'customers.deal.lost', label: 'Deal Lost', entity: 'deal', category: 'lifecycle' },\n\n // Comments\n { id: 'customers.comment.created', label: 'Comment Created', entity: 'comment', category: 'crud' },\n { id: 'customers.comment.updated', label: 'Comment Updated', entity: 'comment', category: 'crud' },\n { id: 'customers.comment.deleted', label: 'Comment Deleted', entity: 'comment', category: 'crud' },\n\n // Addresses\n { id: 'customers.address.created', label: 'Address Created', entity: 'address', category: 'crud' },\n { id: 'customers.address.updated', label: 'Address Updated', entity: 'address', category: 'crud' },\n { id: 'customers.address.deleted', label: 'Address Deleted', entity: 'address', category: 'crud' },\n\n // Activities\n { id: 'customers.activity.created', label: 'Activity Created', entity: 'activity', category: 'crud' },\n { id: 'customers.activity.updated', label: 'Activity Updated', entity: 'activity', category: 'crud' },\n { id: 'customers.activity.deleted', label: 'Activity Deleted', entity: 'activity', category: 'crud' },\n\n // Tags\n { id: 'customers.tag.created', label: 'Tag Created', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.updated', label: 'Tag Updated', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.deleted', label: 'Tag Deleted', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.assigned', label: 'Tag Assigned', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.removed', label: 'Tag Removed', entity: 'tag', category: 'crud' },\n\n // Todos\n { id: 'customers.todo.created', label: 'Todo Created', entity: 'todo', category: 'crud' },\n { id: 'customers.todo.updated', label: 'Todo Updated', entity: 'todo', category: 'crud' },\n { id: 'customers.todo.deleted', label: 'Todo Deleted', entity: 'todo', category: 'crud' },\n\n // Interactions (canonical)\n { id: 'customers.interaction.created', label: 'Interaction Created', entity: 'interaction', category: 'crud' },\n { id: 'customers.interaction.updated', label: 'Interaction Updated', entity: 'interaction', category: 'crud' },\n { id: 'customers.interaction.completed', label: 'Interaction Completed', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.canceled', label: 'Interaction Canceled', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.reverted', label: 'Interaction Reverted', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.deleted', label: 'Interaction Deleted', entity: 'interaction', category: 'crud' },\n { id: 'customers.next_interaction.updated', label: 'Next Interaction Updated', entity: 'interaction', category: 'lifecycle' },\n\n // Entity Roles\n { id: 'customers.entity_role.created', label: 'Entity Role Created', entity: 'entity_role', category: 'crud' },\n { id: 'customers.entity_role.updated', label: 'Entity Role Updated', entity: 'entity_role', category: 'crud' },\n { id: 'customers.entity_role.deleted', label: 'Entity Role Deleted', entity: 'entity_role', category: 'crud' },\n\n // Labels\n { id: 'customers.label.created', label: 'Label Created', entity: 'label', category: 'crud' },\n { id: 'customers.label.updated', label: 'Label Updated', entity: 'label', category: 'crud' },\n { id: 'customers.label.deleted', label: 'Label Deleted', entity: 'label', category: 'crud' },\n\n // Label Assignments\n { id: 'customers.label_assignment.created', label: 'Label Assigned', entity: 'label_assignment', category: 'crud' },\n { id: 'customers.label_assignment.updated', label: 'Label Assignment Updated', entity: 'label_assignment', category: 'crud' },\n { id: 'customers.label_assignment.deleted', label: 'Label Unassigned', entity: 'label_assignment', category: 'crud' },\n\n // Person-Company Links\n { id: 'customers.person_company_link.created', label: 'Person Linked To Company', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n { id: 'customers.person_company_link.updated', label: 'Person-Company Link Updated', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n { id: 'customers.person_company_link.deleted', label: 'Person Unlinked From Company', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n\n // \u2500\u2500 Email integration (2026-05-27) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n { id: 'customers.email.linked', label: 'Email Linked To Person', entity: 'email_link', category: 'lifecycle', clientBroadcast: true },\n { id: 'customers.email.visibility_changed', label: 'Email Visibility Changed', entity: 'email_link', category: 'lifecycle', clientBroadcast: true },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'customers',\n events,\n})\n\n/** Type-safe event emitter for customers module */\nexport const emitCustomersEvent = eventsConfig.emit\n\n/** Event IDs that can be emitted by the customers module */\nexport type CustomersEventId = typeof events[number]['id']\n\nexport default eventsConfig\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\n/**\n * Customers Module Events\n *\n * Declares all events that can be emitted by the customers module.\n */\nconst events = [\n // People\n { id: 'customers.person.created', label: 'Customer (Person) Created', entity: 'person', category: 'crud' },\n { id: 'customers.person.updated', label: 'Customer (Person) Updated', entity: 'person', category: 'crud' },\n { id: 'customers.person.deleted', label: 'Customer (Person) Deleted', entity: 'person', category: 'crud' },\n\n // Companies\n { id: 'customers.company.created', label: 'Customer (Company) Created', entity: 'company', category: 'crud' },\n { id: 'customers.company.updated', label: 'Customer (Company) Updated', entity: 'company', category: 'crud' },\n { id: 'customers.company.deleted', label: 'Customer (Company) Deleted', entity: 'company', category: 'crud' },\n\n // Deals\n { id: 'customers.deal.created', label: 'Deal Created', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.updated', label: 'Deal Updated', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.deleted', label: 'Deal Deleted', entity: 'deal', category: 'crud' },\n { id: 'customers.deal.won', label: 'Deal Won', entity: 'deal', category: 'lifecycle' },\n { id: 'customers.deal.lost', label: 'Deal Lost', entity: 'deal', category: 'lifecycle' },\n\n // Comments\n { id: 'customers.comment.created', label: 'Comment Created', entity: 'comment', category: 'crud' },\n { id: 'customers.comment.updated', label: 'Comment Updated', entity: 'comment', category: 'crud' },\n { id: 'customers.comment.deleted', label: 'Comment Deleted', entity: 'comment', category: 'crud' },\n\n // Addresses\n { id: 'customers.address.created', label: 'Address Created', entity: 'address', category: 'crud' },\n { id: 'customers.address.updated', label: 'Address Updated', entity: 'address', category: 'crud' },\n { id: 'customers.address.deleted', label: 'Address Deleted', entity: 'address', category: 'crud' },\n\n // Activities\n { id: 'customers.activity.created', label: 'Activity Created', entity: 'activity', category: 'crud' },\n { id: 'customers.activity.updated', label: 'Activity Updated', entity: 'activity', category: 'crud' },\n { id: 'customers.activity.deleted', label: 'Activity Deleted', entity: 'activity', category: 'crud' },\n\n // Tags\n { id: 'customers.tag.created', label: 'Tag Created', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.updated', label: 'Tag Updated', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.deleted', label: 'Tag Deleted', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.assigned', label: 'Tag Assigned', entity: 'tag', category: 'crud' },\n { id: 'customers.tag.removed', label: 'Tag Removed', entity: 'tag', category: 'crud' },\n\n // Todos\n { id: 'customers.todo.created', label: 'Todo Created', entity: 'todo', category: 'crud' },\n { id: 'customers.todo.updated', label: 'Todo Updated', entity: 'todo', category: 'crud' },\n { id: 'customers.todo.deleted', label: 'Todo Deleted', entity: 'todo', category: 'crud' },\n\n // Interactions (canonical)\n { id: 'customers.interaction.created', label: 'Interaction Created', entity: 'interaction', category: 'crud' },\n { id: 'customers.interaction.updated', label: 'Interaction Updated', entity: 'interaction', category: 'crud' },\n { id: 'customers.interaction.completed', label: 'Interaction Completed', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.canceled', label: 'Interaction Canceled', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.reverted', label: 'Interaction Reverted', entity: 'interaction', category: 'lifecycle' },\n { id: 'customers.interaction.deleted', label: 'Interaction Deleted', entity: 'interaction', category: 'crud' },\n { id: 'customers.next_interaction.updated', label: 'Next Interaction Updated', entity: 'interaction', category: 'lifecycle' },\n\n // Entity Roles\n { id: 'customers.entity_role.created', label: 'Entity Role Created', entity: 'entity_role', category: 'crud' },\n { id: 'customers.entity_role.updated', label: 'Entity Role Updated', entity: 'entity_role', category: 'crud' },\n { id: 'customers.entity_role.deleted', label: 'Entity Role Deleted', entity: 'entity_role', category: 'crud' },\n\n // Labels\n { id: 'customers.label.created', label: 'Label Created', entity: 'label', category: 'crud' },\n { id: 'customers.label.updated', label: 'Label Updated', entity: 'label', category: 'crud' },\n { id: 'customers.label.deleted', label: 'Label Deleted', entity: 'label', category: 'crud' },\n\n // Label Assignments\n { id: 'customers.label_assignment.created', label: 'Label Assigned', entity: 'label_assignment', category: 'crud' },\n { id: 'customers.label_assignment.updated', label: 'Label Assignment Updated', entity: 'label_assignment', category: 'crud' },\n { id: 'customers.label_assignment.deleted', label: 'Label Unassigned', entity: 'label_assignment', category: 'crud' },\n\n // Person-Company Links\n { id: 'customers.person_company_link.created', label: 'Person Linked To Company', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n { id: 'customers.person_company_link.updated', label: 'Person-Company Link Updated', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n { id: 'customers.person_company_link.deleted', label: 'Person Unlinked From Company', entity: 'person_company_link', category: 'crud', clientBroadcast: true },\n // Legacy profile-only company assignments (`customer_person_profiles.company_id` set with no\n // backing link row, #5114) have no link entity, so detaching one cannot honestly emit\n // `customers.person_company_link.deleted` \u2014 that event's payload promises a link id that never\n // existed. This sibling carries the same live-refresh signal for that shape instead.\n { id: 'customers.person.company_assignment.detached', label: 'Legacy Company Assignment Detached', entity: 'person_company_link', category: 'lifecycle', clientBroadcast: true },\n\n // \u2500\u2500 Email integration (2026-05-27) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n { id: 'customers.email.linked', label: 'Email Linked To Person', entity: 'email_link', category: 'lifecycle', clientBroadcast: true },\n { id: 'customers.email.visibility_changed', label: 'Email Visibility Changed', entity: 'email_link', category: 'lifecycle', clientBroadcast: true },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'customers',\n events,\n})\n\n/** Type-safe event emitter for customers module */\nexport const emitCustomersEvent = eventsConfig.emit\n\n/** Event IDs that can be emitted by the customers module */\nexport type CustomersEventId = typeof events[number]['id']\n\nexport default eventsConfig\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -2,7 +2,8 @@ import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
2
2
  import { findWithDecryption, findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
3
3
  import {
4
4
  CustomerEntity,
5
- CustomerPersonCompanyLink
5
+ CustomerPersonCompanyLink,
6
+ CustomerPersonProfile
6
7
  } from "../data/entities.js";
7
8
  import {
8
9
  filterActivePersonCompanyLinks,
@@ -34,6 +35,99 @@ async function requireCompany(em, companyId, organizationId, tenantId) {
34
35
  }
35
36
  return company;
36
37
  }
38
+ async function loadCompanyPeopleUnion(em, company, scope) {
39
+ const decryptionScope = {
40
+ tenantId: scope.tenantId ?? company.tenantId ?? null,
41
+ organizationId: scope.organizationId ?? company.organizationId ?? null
42
+ };
43
+ const relatedPeopleById = /* @__PURE__ */ new Map();
44
+ const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(
45
+ em,
46
+ { company: company.id, organizationId: company.organizationId, tenantId: company.tenantId },
47
+ "customers.companies.loadCompanyPeopleUnion"
48
+ );
49
+ const companyLinks = filterActivePersonCompanyLinks(
50
+ await findWithDecryption(
51
+ em,
52
+ CustomerPersonCompanyLink,
53
+ companyLinkWhere,
54
+ { populate: ["person", "person.personProfile"], orderBy: { isPrimary: "desc", createdAt: "asc" } },
55
+ decryptionScope
56
+ )
57
+ );
58
+ companyLinks.forEach((link) => {
59
+ const entity = typeof link.person === "string" ? null : link.person;
60
+ if (!entity || entity.kind !== "person" || entity.deletedAt) return;
61
+ const personProfile = entity.personProfile && typeof entity.personProfile !== "string" ? entity.personProfile : null;
62
+ relatedPeopleById.set(entity.id, {
63
+ entity,
64
+ profile: personProfile,
65
+ linkedAt: link.createdAt instanceof Date ? link.createdAt.toISOString() : null
66
+ });
67
+ });
68
+ const profiles = await findWithDecryption(
69
+ em,
70
+ CustomerPersonProfile,
71
+ {
72
+ company: company.id,
73
+ tenantId: company.tenantId,
74
+ organizationId: company.organizationId,
75
+ entity: { deletedAt: null }
76
+ },
77
+ { populate: ["entity"] },
78
+ decryptionScope
79
+ );
80
+ profiles.forEach((entry) => {
81
+ const entity = entry.entity;
82
+ if (!entity || entity.kind !== "person" || entity.deletedAt) return;
83
+ if (!relatedPeopleById.has(entity.id)) {
84
+ relatedPeopleById.set(entity.id, {
85
+ entity,
86
+ profile: entry ?? null,
87
+ linkedAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null
88
+ });
89
+ }
90
+ });
91
+ return Array.from(relatedPeopleById.values());
92
+ }
93
+ async function countCompanyPeopleUnion(em, company) {
94
+ const personIds = /* @__PURE__ */ new Set();
95
+ const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(
96
+ em,
97
+ {
98
+ company: company.id,
99
+ organizationId: company.organizationId,
100
+ tenantId: company.tenantId,
101
+ person: { kind: "person", deletedAt: null }
102
+ },
103
+ "customers.companies.countCompanyPeopleUnion"
104
+ );
105
+ const companyLinks = filterActivePersonCompanyLinks(
106
+ await em.find(CustomerPersonCompanyLink, companyLinkWhere, {
107
+ fields: ["person", "deletedAt"]
108
+ })
109
+ );
110
+ companyLinks.forEach((link) => {
111
+ const personId = typeof link.person === "string" ? link.person : link.person?.id;
112
+ if (personId) personIds.add(personId);
113
+ });
114
+ const profiles = await em.find(
115
+ CustomerPersonProfile,
116
+ {
117
+ company: company.id,
118
+ tenantId: company.tenantId,
119
+ organizationId: company.organizationId,
120
+ entity: { kind: "person", deletedAt: null }
121
+ },
122
+ { fields: ["entity"] }
123
+ );
124
+ profiles.forEach((entry) => {
125
+ const entity = entry.entity;
126
+ const entityId = typeof entity === "string" ? entity : entity?.id;
127
+ if (entityId) personIds.add(entityId);
128
+ });
129
+ return personIds.size;
130
+ }
37
131
  async function loadPersonCompanyLinks(em, person) {
38
132
  const where = await withActiveCustomerPersonCompanyLinkFilter(
39
133
  em,
@@ -207,7 +301,9 @@ async function removePersonCompanyLink(em, person, profile, linkId) {
207
301
  const link = existingLinks.find((entry) => entry.id === linkId) ?? existingLinks.find((entry) => (typeof entry.company === "string" ? entry.company : entry.company.id) === linkId) ?? null;
208
302
  if (!link) {
209
303
  if (profile.company && typeof profile.company !== "string" && profile.company.id === linkId) {
210
- profile.company = null;
304
+ const primary = existingLinks.find((entry) => entry.isPrimary) ?? null;
305
+ const primaryCompany = primary ? resolveLinkedCompany(primary) : null;
306
+ profile.company = primaryCompany ?? null;
211
307
  return;
212
308
  }
213
309
  throw notFound("Company link not found");
@@ -229,7 +325,9 @@ async function removePersonCompanyLink(em, person, profile, linkId) {
229
325
  }
230
326
  export {
231
327
  addPersonCompanyLink,
328
+ countCompanyPeopleUnion,
232
329
  findDeletedPersonCompanyLink,
330
+ loadCompanyPeopleUnion,
233
331
  loadPersonCompanyLinks,
234
332
  promoteFallbackPrimaryLink,
235
333
  removePersonCompanyLink,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/lib/personCompanies.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../data/entities'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from './personCompanyLinkTable'\n\nexport type PersonCompanySummary = {\n linkId: string | null\n companyId: string\n displayName: string\n isPrimary: boolean\n synthetic?: boolean\n}\n\nexport async function findDeletedPersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n company: CustomerEntity,\n): Promise<CustomerPersonCompanyLink | null> {\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n person,\n company,\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n deletedAt: { $ne: null },\n } as any,\n {},\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n return link ?? null\n}\n\nasync function requireCompany(\n em: EntityManager,\n companyId: string,\n organizationId: string,\n tenantId: string,\n): Promise<CustomerEntity> {\n const company = await findOneWithDecryption(em, CustomerEntity, { id: companyId, kind: 'company', deletedAt: null }, {}, { tenantId, organizationId })\n if (!company) {\n throw notFound('Company not found')\n }\n if (company.organizationId !== organizationId || company.tenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Cannot link company outside current scope' })\n }\n return company\n}\n\nexport async function loadPersonCompanyLinks(\n em: EntityManager,\n person: CustomerEntity,\n): Promise<CustomerPersonCompanyLink[]> {\n const where = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n { person, organizationId: person.organizationId, tenantId: person.tenantId },\n 'customers.personCompanies.loadPersonCompanyLinks',\n )\n return filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n where,\n { populate: ['company'], orderBy: { isPrimary: 'desc', createdAt: 'asc' } },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n ),\n )\n}\n\nexport function summarizePersonCompanies(\n profile: CustomerPersonProfile | null,\n links: CustomerPersonCompanyLink[],\n): PersonCompanySummary[] {\n if (links.length > 0) {\n const items: PersonCompanySummary[] = []\n links.forEach((link) => {\n const company = typeof link.company === 'string' ? null : link.company\n if (!company) return\n items.push({\n linkId: link.id,\n companyId: company.id,\n displayName: company.displayName,\n isPrimary: Boolean(link.isPrimary),\n })\n })\n return items\n }\n\n const fallbackCompany = profile?.company && typeof profile.company !== 'string' ? profile.company : null\n if (!fallbackCompany) return []\n\n return [\n {\n linkId: fallbackCompany.id,\n companyId: fallbackCompany.id,\n displayName: fallbackCompany.displayName,\n isPrimary: true,\n synthetic: true,\n },\n ]\n}\n\nasync function clearPrimaryFlags(em: EntityManager, person: CustomerEntity): Promise<void> {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, organizationId: person.organizationId, tenantId: person.tenantId, isPrimary: true },\n { isPrimary: false },\n )\n}\n\nfunction resolveLinkedCompany(link: CustomerPersonCompanyLink): CustomerEntity | null {\n return typeof link.company === 'string' ? null : link.company\n}\n\nexport async function promoteFallbackPrimaryLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n links: CustomerPersonCompanyLink[],\n removedCompanyId?: string | null,\n): Promise<void> {\n const nextPrimary = links[0] ?? null\n if (!nextPrimary) {\n if (\n !removedCompanyId\n || (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId)\n || profile.company == null\n ) {\n profile.company = null\n }\n return\n }\n\n await clearPrimaryFlags(em, person)\n nextPrimary.isPrimary = true\n const nextCompany = resolveLinkedCompany(nextPrimary)\n if (nextCompany) {\n profile.company = nextCompany\n }\n}\n\nexport async function syncLegacyPrimaryCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n companyId: string | null | undefined,\n): Promise<void> {\n const normalizedCompanyId = typeof companyId === 'string' && companyId.trim().length > 0 ? companyId.trim() : null\n const existingLinks = await loadPersonCompanyLinks(em, person)\n\n if (!normalizedCompanyId) {\n if (existingLinks.some((link) => link.isPrimary)) {\n await clearPrimaryFlags(em, person)\n }\n profile.company = null\n return\n }\n\n const company = await requireCompany(em, normalizedCompanyId, person.organizationId, person.tenantId)\n const currentLink =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n\n if (currentLink) {\n if (!currentLink.isPrimary) {\n await clearPrimaryFlags(em, person)\n currentLink.isPrimary = true\n } else if (existingLinks.some((link) => link.id !== currentLink.id && link.isPrimary)) {\n await clearPrimaryFlags(em, person)\n currentLink.isPrimary = true\n }\n } else {\n await clearPrimaryFlags(em, person)\n const link = em.create(CustomerPersonCompanyLink, {\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n person,\n company,\n isPrimary: true,\n })\n em.persist(link)\n }\n\n profile.company = company\n}\n\nexport async function addPersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n companyId: string,\n options?: { isPrimary?: boolean },\n): Promise<CustomerPersonCompanyLink> {\n const company = await requireCompany(em, companyId, person.organizationId, person.tenantId)\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const makePrimary = Boolean(options?.isPrimary) || existingLinks.length === 0\n const existing =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n\n if (existing) {\n if (makePrimary && !existing.isPrimary) {\n await clearPrimaryFlags(em, person)\n existing.isPrimary = true\n profile.company = company\n }\n return existing\n }\n\n if (makePrimary) {\n await clearPrimaryFlags(em, person)\n }\n\n const deletedLink = await findDeletedPersonCompanyLink(em, person, company)\n const link = deletedLink ?? em.create(CustomerPersonCompanyLink, {\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n person,\n company,\n isPrimary: makePrimary,\n })\n if (deletedLink) {\n deletedLink.deletedAt = null\n deletedLink.isPrimary = makePrimary\n }\n em.persist(link)\n\n if (makePrimary) {\n profile.company = company\n } else if (!profile.company && existingLinks.length === 0) {\n profile.company = company\n link.isPrimary = true\n }\n\n return link\n}\n\nexport async function updatePersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n linkId: string,\n patch: { isPrimary?: boolean },\n): Promise<CustomerPersonCompanyLink | null> {\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const link = existingLinks.find((entry) => entry.id === linkId)\n ?? existingLinks.find((entry) => (typeof entry.company === 'string' ? entry.company : entry.company.id) === linkId)\n ?? null\n\n if (!link && profile.company && typeof profile.company !== 'string' && profile.company.id === linkId && patch.isPrimary === false) {\n profile.company = null\n return null\n }\n\n if (!link) {\n throw notFound('Company link not found')\n }\n\n if (patch.isPrimary === true) {\n await clearPrimaryFlags(em, person)\n link.isPrimary = true\n const company = resolveLinkedCompany(link)\n if (company) {\n profile.company = company\n }\n } else if (patch.isPrimary === false) {\n const linkWasPrimary = link.isPrimary\n const removedCompanyId = typeof link.company === 'string' ? link.company : link.company.id\n link.isPrimary = false\n if (linkWasPrimary) {\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, removedCompanyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId) {\n profile.company = null\n }\n }\n\n return link\n}\n\nexport async function removePersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n linkId: string,\n): Promise<void> {\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const link = existingLinks.find((entry) => entry.id === linkId)\n ?? existingLinks.find((entry) => (typeof entry.company === 'string' ? entry.company : entry.company.id) === linkId)\n ?? null\n\n if (!link) {\n if (profile.company && typeof profile.company !== 'string' && profile.company.id === linkId) {\n profile.company = null\n return\n }\n throw notFound('Company link not found')\n }\n\n const removedCompanyId = typeof link.company === 'string' ? link.company : link.company.id\n const removedWasPrimary = link.isPrimary\n link.isPrimary = false\n link.deletedAt = new Date()\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n\n if (removedWasPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, removedCompanyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId) {\n const primary = remainingLinks.find((entry) => entry.isPrimary) ?? null\n const primaryCompany = primary ? resolveLinkedCompany(primary) : null\n if (primaryCompany) {\n profile.company = primaryCompany\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport {\n CustomerEntity,\n CustomerPersonCompanyLink,\n CustomerPersonProfile,\n} from '../data/entities'\nimport {\n filterActivePersonCompanyLinks,\n withActiveCustomerPersonCompanyLinkFilter,\n} from './personCompanyLinkTable'\n\nexport type PersonCompanySummary = {\n linkId: string | null\n companyId: string\n displayName: string\n isPrimary: boolean\n synthetic?: boolean\n}\n\nexport async function findDeletedPersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n company: CustomerEntity,\n): Promise<CustomerPersonCompanyLink | null> {\n const link = await findOneWithDecryption(\n em,\n CustomerPersonCompanyLink,\n {\n person,\n company,\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n deletedAt: { $ne: null },\n } as any,\n {},\n { tenantId: person.tenantId, organizationId: person.organizationId },\n )\n return link ?? null\n}\n\nasync function requireCompany(\n em: EntityManager,\n companyId: string,\n organizationId: string,\n tenantId: string,\n): Promise<CustomerEntity> {\n const company = await findOneWithDecryption(em, CustomerEntity, { id: companyId, kind: 'company', deletedAt: null }, {}, { tenantId, organizationId })\n if (!company) {\n throw notFound('Company not found')\n }\n if (company.organizationId !== organizationId || company.tenantId !== tenantId) {\n throw new CrudHttpError(403, { error: 'Cannot link company outside current scope' })\n }\n return company\n}\n\nexport type CompanyPersonUnionEntry = {\n entity: CustomerEntity\n profile: CustomerPersonProfile | null\n linkedAt: string | null\n}\n\n/**\n * Resolve \"people belonging to this company\" as the union of active\n * `CustomerPersonCompanyLink` rows and `CustomerPersonProfile.company`\n * profile-only assignments (data that never got a link row, e.g. from\n * migrated CRM imports). This is the single source of truth for both the\n * company People tab list and its badge count \u2014 see #5114.\n */\nexport async function loadCompanyPeopleUnion(\n em: EntityManager,\n company: CustomerEntity,\n scope: { tenantId?: string | null; organizationId?: string | null },\n): Promise<CompanyPersonUnionEntry[]> {\n const decryptionScope = {\n tenantId: scope.tenantId ?? company.tenantId ?? null,\n organizationId: scope.organizationId ?? company.organizationId ?? null,\n }\n const relatedPeopleById = new Map<string, CompanyPersonUnionEntry>()\n\n const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n { company: company.id, organizationId: company.organizationId, tenantId: company.tenantId },\n 'customers.companies.loadCompanyPeopleUnion',\n )\n const companyLinks = filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n companyLinkWhere,\n { populate: ['person', 'person.personProfile'], orderBy: { isPrimary: 'desc', createdAt: 'asc' } },\n decryptionScope,\n ),\n )\n companyLinks.forEach((link) => {\n const entity = typeof link.person === 'string' ? null : link.person\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n const personProfile =\n entity.personProfile && typeof entity.personProfile !== 'string' ? entity.personProfile : null\n relatedPeopleById.set(entity.id, {\n entity,\n profile: personProfile,\n linkedAt: link.createdAt instanceof Date ? link.createdAt.toISOString() : null,\n })\n })\n\n const profiles = await findWithDecryption(\n em,\n CustomerPersonProfile,\n {\n company: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n entity: { deletedAt: null },\n },\n { populate: ['entity'] },\n decryptionScope,\n )\n profiles.forEach((entry) => {\n const entity = entry.entity as CustomerEntity | null\n if (!entity || entity.kind !== 'person' || entity.deletedAt) return\n if (!relatedPeopleById.has(entity.id)) {\n relatedPeopleById.set(entity.id, {\n entity,\n profile: entry ?? null,\n linkedAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null,\n })\n }\n })\n\n return Array.from(relatedPeopleById.values())\n}\n\n/**\n * Count-only sibling of `loadCompanyPeopleUnion` for the company People badge, which\n * needs the size of the union and nothing else. Both queries project just the foreign\n * key column and push the `kind: 'person'` / `deletedAt: null` predicates into the\n * WHERE clause, so no person row is hydrated and no PII is decrypted to produce a\n * number \u2014 `findWithDecryption` is deliberately not used here because the projections\n * select no encrypted column.\n */\nexport async function countCompanyPeopleUnion(\n em: EntityManager,\n company: CustomerEntity,\n): Promise<number> {\n const personIds = new Set<string>()\n\n const companyLinkWhere = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n {\n company: company.id,\n organizationId: company.organizationId,\n tenantId: company.tenantId,\n person: { kind: 'person', deletedAt: null },\n },\n 'customers.companies.countCompanyPeopleUnion',\n )\n const companyLinks = filterActivePersonCompanyLinks(\n await em.find(CustomerPersonCompanyLink, companyLinkWhere as any, {\n fields: ['person', 'deletedAt'],\n } as any),\n )\n companyLinks.forEach((link) => {\n const personId = typeof link.person === 'string' ? link.person : link.person?.id\n if (personId) personIds.add(personId)\n })\n\n const profiles = await em.find(\n CustomerPersonProfile,\n {\n company: company.id,\n tenantId: company.tenantId,\n organizationId: company.organizationId,\n entity: { kind: 'person', deletedAt: null },\n } as any,\n { fields: ['entity'] } as any,\n )\n profiles.forEach((entry) => {\n const entity = entry.entity as CustomerEntity | string | null\n const entityId = typeof entity === 'string' ? entity : entity?.id\n if (entityId) personIds.add(entityId)\n })\n\n return personIds.size\n}\n\nexport async function loadPersonCompanyLinks(\n em: EntityManager,\n person: CustomerEntity,\n): Promise<CustomerPersonCompanyLink[]> {\n const where = await withActiveCustomerPersonCompanyLinkFilter(\n em,\n { person, organizationId: person.organizationId, tenantId: person.tenantId },\n 'customers.personCompanies.loadPersonCompanyLinks',\n )\n return filterActivePersonCompanyLinks(\n await findWithDecryption(\n em,\n CustomerPersonCompanyLink,\n where,\n { populate: ['company'], orderBy: { isPrimary: 'desc', createdAt: 'asc' } },\n { tenantId: person.tenantId, organizationId: person.organizationId },\n ),\n )\n}\n\nexport function summarizePersonCompanies(\n profile: CustomerPersonProfile | null,\n links: CustomerPersonCompanyLink[],\n): PersonCompanySummary[] {\n if (links.length > 0) {\n const items: PersonCompanySummary[] = []\n links.forEach((link) => {\n const company = typeof link.company === 'string' ? null : link.company\n if (!company) return\n items.push({\n linkId: link.id,\n companyId: company.id,\n displayName: company.displayName,\n isPrimary: Boolean(link.isPrimary),\n })\n })\n return items\n }\n\n const fallbackCompany = profile?.company && typeof profile.company !== 'string' ? profile.company : null\n if (!fallbackCompany) return []\n\n return [\n {\n linkId: fallbackCompany.id,\n companyId: fallbackCompany.id,\n displayName: fallbackCompany.displayName,\n isPrimary: true,\n synthetic: true,\n },\n ]\n}\n\nasync function clearPrimaryFlags(em: EntityManager, person: CustomerEntity): Promise<void> {\n await em.nativeUpdate(\n CustomerPersonCompanyLink,\n { person, organizationId: person.organizationId, tenantId: person.tenantId, isPrimary: true },\n { isPrimary: false },\n )\n}\n\nfunction resolveLinkedCompany(link: CustomerPersonCompanyLink): CustomerEntity | null {\n return typeof link.company === 'string' ? null : link.company\n}\n\nexport async function promoteFallbackPrimaryLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n links: CustomerPersonCompanyLink[],\n removedCompanyId?: string | null,\n): Promise<void> {\n const nextPrimary = links[0] ?? null\n if (!nextPrimary) {\n if (\n !removedCompanyId\n || (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId)\n || profile.company == null\n ) {\n profile.company = null\n }\n return\n }\n\n await clearPrimaryFlags(em, person)\n nextPrimary.isPrimary = true\n const nextCompany = resolveLinkedCompany(nextPrimary)\n if (nextCompany) {\n profile.company = nextCompany\n }\n}\n\nexport async function syncLegacyPrimaryCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n companyId: string | null | undefined,\n): Promise<void> {\n const normalizedCompanyId = typeof companyId === 'string' && companyId.trim().length > 0 ? companyId.trim() : null\n const existingLinks = await loadPersonCompanyLinks(em, person)\n\n if (!normalizedCompanyId) {\n if (existingLinks.some((link) => link.isPrimary)) {\n await clearPrimaryFlags(em, person)\n }\n profile.company = null\n return\n }\n\n const company = await requireCompany(em, normalizedCompanyId, person.organizationId, person.tenantId)\n const currentLink =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n\n if (currentLink) {\n if (!currentLink.isPrimary) {\n await clearPrimaryFlags(em, person)\n currentLink.isPrimary = true\n } else if (existingLinks.some((link) => link.id !== currentLink.id && link.isPrimary)) {\n await clearPrimaryFlags(em, person)\n currentLink.isPrimary = true\n }\n } else {\n await clearPrimaryFlags(em, person)\n const link = em.create(CustomerPersonCompanyLink, {\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n person,\n company,\n isPrimary: true,\n })\n em.persist(link)\n }\n\n profile.company = company\n}\n\nexport async function addPersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n companyId: string,\n options?: { isPrimary?: boolean },\n): Promise<CustomerPersonCompanyLink> {\n const company = await requireCompany(em, companyId, person.organizationId, person.tenantId)\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const makePrimary = Boolean(options?.isPrimary) || existingLinks.length === 0\n const existing =\n existingLinks.find((link) => (typeof link.company === 'string' ? link.company : link.company.id) === company.id) ?? null\n\n if (existing) {\n if (makePrimary && !existing.isPrimary) {\n await clearPrimaryFlags(em, person)\n existing.isPrimary = true\n profile.company = company\n }\n return existing\n }\n\n if (makePrimary) {\n await clearPrimaryFlags(em, person)\n }\n\n const deletedLink = await findDeletedPersonCompanyLink(em, person, company)\n const link = deletedLink ?? em.create(CustomerPersonCompanyLink, {\n organizationId: person.organizationId,\n tenantId: person.tenantId,\n person,\n company,\n isPrimary: makePrimary,\n })\n if (deletedLink) {\n deletedLink.deletedAt = null\n deletedLink.isPrimary = makePrimary\n }\n em.persist(link)\n\n if (makePrimary) {\n profile.company = company\n } else if (!profile.company && existingLinks.length === 0) {\n profile.company = company\n link.isPrimary = true\n }\n\n return link\n}\n\nexport async function updatePersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n linkId: string,\n patch: { isPrimary?: boolean },\n): Promise<CustomerPersonCompanyLink | null> {\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const link = existingLinks.find((entry) => entry.id === linkId)\n ?? existingLinks.find((entry) => (typeof entry.company === 'string' ? entry.company : entry.company.id) === linkId)\n ?? null\n\n if (!link && profile.company && typeof profile.company !== 'string' && profile.company.id === linkId && patch.isPrimary === false) {\n profile.company = null\n return null\n }\n\n if (!link) {\n throw notFound('Company link not found')\n }\n\n if (patch.isPrimary === true) {\n await clearPrimaryFlags(em, person)\n link.isPrimary = true\n const company = resolveLinkedCompany(link)\n if (company) {\n profile.company = company\n }\n } else if (patch.isPrimary === false) {\n const linkWasPrimary = link.isPrimary\n const removedCompanyId = typeof link.company === 'string' ? link.company : link.company.id\n link.isPrimary = false\n if (linkWasPrimary) {\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, removedCompanyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId) {\n profile.company = null\n }\n }\n\n return link\n}\n\nexport async function removePersonCompanyLink(\n em: EntityManager,\n person: CustomerEntity,\n profile: CustomerPersonProfile,\n linkId: string,\n): Promise<void> {\n const existingLinks = await loadPersonCompanyLinks(em, person)\n const link = existingLinks.find((entry) => entry.id === linkId)\n ?? existingLinks.find((entry) => (typeof entry.company === 'string' ? entry.company : entry.company.id) === linkId)\n ?? null\n\n if (!link) {\n if (profile.company && typeof profile.company !== 'string' && profile.company.id === linkId) {\n // Profile-only assignment: no link row backs it, so only the legacy field is\n // cleared. It must keep mirroring the primary link the way every other detach\n // path leaves it, so promote a remaining primary link instead of nulling blindly.\n const primary = existingLinks.find((entry) => entry.isPrimary) ?? null\n const primaryCompany = primary ? resolveLinkedCompany(primary) : null\n profile.company = primaryCompany ?? null\n return\n }\n throw notFound('Company link not found')\n }\n\n const removedCompanyId = typeof link.company === 'string' ? link.company : link.company.id\n const removedWasPrimary = link.isPrimary\n link.isPrimary = false\n link.deletedAt = new Date()\n const remainingLinks = existingLinks.filter((entry) => entry.id !== link.id)\n\n if (removedWasPrimary) {\n await promoteFallbackPrimaryLink(em, person, profile, remainingLinks, removedCompanyId)\n } else if (profile.company && typeof profile.company !== 'string' && profile.company.id === removedCompanyId) {\n const primary = remainingLinks.find((entry) => entry.isPrimary) ?? null\n const primaryCompany = primary ? resolveLinkedCompany(primary) : null\n if (primaryCompany) {\n profile.company = primaryCompany\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["link"]
7
7
  }