@open-mercato/core 0.10.1-develop.7833.1.d6cbf0e3ab → 0.10.1-develop.7841.1.af87ac614d

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 (136) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/cart/api/current/lines/bulk/route.js +1 -1
  3. package/dist/modules/cart/api/current/lines/bulk/route.js.map +2 -2
  4. package/dist/modules/cart/api/current/lines/route.js +1 -1
  5. package/dist/modules/cart/api/current/lines/route.js.map +2 -2
  6. package/dist/modules/cart/commands/lines.js +5 -10
  7. package/dist/modules/cart/commands/lines.js.map +2 -2
  8. package/dist/modules/cart/lib/currentCartRoute.js +8 -0
  9. package/dist/modules/cart/lib/currentCartRoute.js.map +3 -3
  10. package/dist/modules/cart/lib/lineMutationLock.js +52 -0
  11. package/dist/modules/cart/lib/lineMutationLock.js.map +7 -0
  12. package/dist/modules/customer_accounts/api/admin/roles.js +25 -2
  13. package/dist/modules/customer_accounts/api/admin/roles.js.map +2 -2
  14. package/dist/modules/customer_accounts/api/admin/users.js +24 -7
  15. package/dist/modules/customer_accounts/api/admin/users.js.map +2 -2
  16. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +77 -15
  17. package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
  18. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +12 -1
  19. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  20. package/dist/modules/customer_accounts/data/validators.js +2 -1
  21. package/dist/modules/customer_accounts/data/validators.js.map +2 -2
  22. package/dist/modules/customer_accounts/lib/adminOrganizationScope.js +46 -0
  23. package/dist/modules/customer_accounts/lib/adminOrganizationScope.js.map +7 -0
  24. package/dist/modules/customers/api/customer-dictionary-entries/route.js +86 -0
  25. package/dist/modules/customers/api/customer-dictionary-entries/route.js.map +7 -0
  26. package/dist/modules/customers/api/dictionaries/[kind]/route.js +29 -7
  27. package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
  28. package/dist/modules/customers/cli.js +28 -110
  29. package/dist/modules/customers/cli.js.map +3 -3
  30. package/dist/modules/customers/components/DictionarySettings.js +1 -1
  31. package/dist/modules/customers/components/DictionarySettings.js.map +1 -1
  32. package/dist/modules/customers/components/detail/ManageTagsDialog.js +1 -1
  33. package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +2 -2
  34. package/dist/modules/customers/components/detail/TaskDialog.js +14 -1
  35. package/dist/modules/customers/components/detail/TaskDialog.js.map +2 -2
  36. package/dist/modules/customers/components/detail/TaskForm.js +1 -16
  37. package/dist/modules/customers/components/detail/TaskForm.js.map +2 -2
  38. package/dist/modules/customers/components/detail/TasksSection.js +38 -10
  39. package/dist/modules/customers/components/detail/TasksSection.js.map +2 -2
  40. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +12 -5
  41. package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +2 -2
  42. package/dist/modules/customers/components/detail/hooks/useInteractions.js +3 -13
  43. package/dist/modules/customers/components/detail/hooks/useInteractions.js.map +2 -2
  44. package/dist/modules/customers/lib/dictionaryDefaults.js +134 -0
  45. package/dist/modules/customers/lib/dictionaryDefaults.js.map +7 -0
  46. package/dist/modules/customers/lib/dictionaryLabels.js +59 -0
  47. package/dist/modules/customers/lib/dictionaryLabels.js.map +7 -0
  48. package/dist/modules/customers/lib/interactionCompatibility.js +1 -0
  49. package/dist/modules/customers/lib/interactionCompatibility.js.map +2 -2
  50. package/dist/modules/customers/translations.js +9 -0
  51. package/dist/modules/customers/translations.js.map +7 -0
  52. package/dist/modules/eudr/index.js +13 -0
  53. package/dist/modules/eudr/index.js.map +2 -2
  54. package/dist/modules/sales/commands/documents.js +3 -3
  55. package/dist/modules/sales/commands/documents.js.map +2 -2
  56. package/dist/modules/sales/components/documents/ItemsSection.js +75 -21
  57. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  58. package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
  59. package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
  60. package/dist/modules/staff/api/timesheets/access-requests/route.js +11 -5
  61. package/dist/modules/staff/api/timesheets/access-requests/route.js.map +2 -2
  62. package/dist/modules/staff/api/timesheets/time-projects/route.js +19 -12
  63. package/dist/modules/staff/api/timesheets/time-projects/route.js.map +2 -2
  64. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js +21 -12
  65. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.js.map +2 -2
  66. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js +14 -9
  67. package/dist/modules/staff/backend/staff/time-tracking/projects/[id]/page.js.map +2 -2
  68. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js +31 -10
  69. package/dist/modules/staff/lib/time-tracking-ui/NoProjectAccess.js.map +2 -2
  70. package/dist/modules/staff/lib/time-tracking-ui/projectAccessScope.js +64 -0
  71. package/dist/modules/staff/lib/time-tracking-ui/projectAccessScope.js.map +7 -0
  72. package/dist/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.js +13 -0
  73. package/dist/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.js.map +7 -0
  74. package/dist/modules/sync_excel/index.js +11 -1
  75. package/dist/modules/sync_excel/index.js.map +2 -2
  76. package/dist/modules/translations/di.js +2 -0
  77. package/dist/modules/translations/di.js.map +2 -2
  78. package/package.json +7 -7
  79. package/src/modules/cart/api/current/lines/bulk/route.ts +1 -1
  80. package/src/modules/cart/api/current/lines/route.ts +1 -1
  81. package/src/modules/cart/commands/lines.ts +5 -10
  82. package/src/modules/cart/i18n/de.json +1 -0
  83. package/src/modules/cart/i18n/en.json +1 -0
  84. package/src/modules/cart/i18n/es.json +1 -0
  85. package/src/modules/cart/i18n/ko.json +1 -0
  86. package/src/modules/cart/i18n/pl.json +1 -0
  87. package/src/modules/cart/lib/currentCartRoute.ts +8 -0
  88. package/src/modules/cart/lib/lineMutationLock.ts +59 -0
  89. package/src/modules/customer_accounts/api/admin/roles.ts +26 -2
  90. package/src/modules/customer_accounts/api/admin/users.ts +26 -7
  91. package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +96 -13
  92. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +9 -1
  93. package/src/modules/customer_accounts/data/validators.ts +1 -0
  94. package/src/modules/customer_accounts/i18n/de.json +10 -0
  95. package/src/modules/customer_accounts/i18n/en.json +10 -0
  96. package/src/modules/customer_accounts/i18n/es.json +10 -0
  97. package/src/modules/customer_accounts/i18n/ko.json +10 -0
  98. package/src/modules/customer_accounts/i18n/pl.json +10 -0
  99. package/src/modules/customer_accounts/lib/adminOrganizationScope.ts +71 -0
  100. package/src/modules/customers/api/customer-dictionary-entries/route.ts +82 -0
  101. package/src/modules/customers/api/dictionaries/[kind]/route.ts +29 -6
  102. package/src/modules/customers/cli.ts +23 -124
  103. package/src/modules/customers/components/DictionarySettings.tsx +1 -1
  104. package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1 -1
  105. package/src/modules/customers/components/detail/TaskDialog.tsx +15 -1
  106. package/src/modules/customers/components/detail/TaskForm.tsx +1 -17
  107. package/src/modules/customers/components/detail/TasksSection.tsx +44 -14
  108. package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +14 -8
  109. package/src/modules/customers/components/detail/hooks/useInteractions.ts +3 -4
  110. package/src/modules/customers/i18n/de.json +81 -0
  111. package/src/modules/customers/i18n/en.json +81 -0
  112. package/src/modules/customers/i18n/es.json +81 -0
  113. package/src/modules/customers/i18n/ko.json +81 -0
  114. package/src/modules/customers/i18n/pl.json +81 -0
  115. package/src/modules/customers/lib/dictionaryDefaults.ts +137 -0
  116. package/src/modules/customers/lib/dictionaryLabels.ts +73 -0
  117. package/src/modules/customers/lib/interactionCompatibility.ts +1 -0
  118. package/src/modules/customers/translations.ts +5 -0
  119. package/src/modules/eudr/index.ts +13 -0
  120. package/src/modules/sales/commands/documents.ts +3 -3
  121. package/src/modules/sales/components/documents/ItemsSection.tsx +82 -23
  122. package/src/modules/sales/components/documents/lineItemUtils.ts +2 -2
  123. package/src/modules/sales/i18n/de.json +1 -0
  124. package/src/modules/sales/i18n/en.json +1 -0
  125. package/src/modules/sales/i18n/es.json +1 -0
  126. package/src/modules/sales/i18n/ko.json +1 -0
  127. package/src/modules/sales/i18n/pl.json +1 -0
  128. package/src/modules/staff/api/timesheets/access-requests/route.ts +13 -14
  129. package/src/modules/staff/api/timesheets/time-projects/route.ts +22 -13
  130. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/edit/page.tsx +25 -14
  131. package/src/modules/staff/backend/staff/time-tracking/projects/[id]/page.tsx +14 -13
  132. package/src/modules/staff/lib/time-tracking-ui/NoProjectAccess.tsx +30 -8
  133. package/src/modules/staff/lib/time-tracking-ui/projectAccessScope.ts +102 -0
  134. package/src/modules/staff/lib/time-tracking-ui/projectAccessScopeHeaders.ts +15 -0
  135. package/src/modules/sync_excel/index.ts +10 -0
  136. package/src/modules/translations/di.ts +2 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/customers/components/detail/hooks/useInteractions.ts"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary } from '../types'\n\ntype InteractionsListResponse = {\n items: InteractionSummary[]\n nextCursor?: string\n}\n\nexport type InteractionCreatePayload = {\n entityId: string\n interactionType: string\n title?: string | null\n body?: string | null\n status?: string\n scheduledAt?: string | null\n priority?: number | null\n customValues?: Record<string, unknown>\n ownerUserId?: string | null\n dealId?: string | null\n}\n\nexport type InteractionUpdatePayload = {\n interactionType?: string\n title?: string | null\n body?: string | null\n status?: string\n scheduledAt?: string | null\n occurredAt?: string | null\n priority?: number | null\n customValues?: Record<string, unknown>\n ownerUserId?: string | null\n dealId?: string | null\n}\n\nexport type UseInteractionsOptions = {\n entityId: string | null\n statusFilter?: string\n typeFilter?: string\n excludeTypeFilter?: string\n pageSize?: number\n}\n\nexport type UseInteractionsResult = {\n interactions: InteractionSummary[]\n isInitialLoading: boolean\n isLoadingMore: boolean\n isMutating: boolean\n hasMore: boolean\n loadMore: () => Promise<void>\n refresh: () => Promise<void>\n createInteraction: (payload: InteractionCreatePayload) => Promise<void>\n updateInteraction: (id: string, payload: InteractionUpdatePayload) => Promise<void>\n completeInteraction: (id: string) => Promise<void>\n cancelInteraction: (id: string) => Promise<void>\n deleteInteraction: (id: string) => Promise<void>\n pendingId: string | null\n totalCount: number\n error: string | null\n}\n\nfunction mergeUnique(existing: InteractionSummary[], incoming: InteractionSummary[]): InteractionSummary[] {\n if (!existing.length) return incoming\n if (!incoming.length) return existing\n const byId = new Map<string, InteractionSummary>()\n const result: InteractionSummary[] = []\n for (const item of existing) {\n byId.set(item.id, item)\n result.push(item)\n }\n for (const item of incoming) {\n if (byId.has(item.id)) {\n const index = result.findIndex((entry) => entry.id === item.id)\n if (index !== -1) result[index] = item\n } else {\n byId.set(item.id, item)\n result.push(item)\n }\n }\n return result\n}\n\nexport function useInteractions({\n entityId,\n statusFilter,\n typeFilter,\n excludeTypeFilter,\n pageSize = 25,\n}: UseInteractionsOptions): UseInteractionsResult {\n const t = useT()\n const [interactions, setInteractions] = React.useState<InteractionSummary[]>([])\n const [nextCursor, setNextCursor] = React.useState<string | null>(null)\n const [isInitialLoading, setIsInitialLoading] = React.useState<boolean>(() => Boolean(entityId))\n const [isLoadingMore, setIsLoadingMore] = React.useState(false)\n const [isMutating, setIsMutating] = React.useState(false)\n const [pendingId, setPendingId] = React.useState<string | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n\n const mapResponse = React.useCallback((payload: InteractionsListResponse) => {\n const mapped = Array.isArray(payload.items) ? payload.items : []\n setNextCursor(typeof payload.nextCursor === 'string' && payload.nextCursor.trim().length > 0 ? payload.nextCursor : null)\n setError(null)\n return mapped\n }, [])\n\n const fetchPage = React.useCallback(\n async (cursor?: string | null): Promise<InteractionsListResponse> => {\n if (!entityId) {\n return { items: [], nextCursor: undefined }\n }\n const params = new URLSearchParams({\n limit: String(pageSize),\n entityId,\n sortField: 'scheduledAt',\n sortDir: 'asc',\n })\n if (cursor) params.set('cursor', cursor)\n if (statusFilter) params.set('status', statusFilter)\n if (typeFilter) params.set('interactionType', typeFilter)\n if (excludeTypeFilter) params.set('excludeInteractionType', excludeTypeFilter)\n\n return readApiResultOrThrow<InteractionsListResponse>(\n `/api/customers/interactions?${params.toString()}`,\n undefined,\n { errorMessage: t('customers.interactions.load.error', 'Failed to load interactions.') },\n )\n },\n [entityId, excludeTypeFilter, pageSize, statusFilter, typeFilter, t],\n )\n\n const refresh = React.useCallback(async () => {\n if (!entityId) {\n setInteractions([])\n setNextCursor(null)\n return\n }\n setIsInitialLoading(true)\n try {\n const payload = await fetchPage(null)\n const mapped = mapResponse(payload)\n setInteractions(mapped)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n throw err\n } finally {\n setIsInitialLoading(false)\n }\n }, [entityId, fetchPage, mapResponse, t])\n\n const loadMore = React.useCallback(async () => {\n if (!entityId) return\n if (isLoadingMore) return\n if (!nextCursor) return\n setIsLoadingMore(true)\n try {\n const payload = await fetchPage(nextCursor)\n const mapped = mapResponse(payload)\n setInteractions((prev) => mergeUnique(prev, mapped))\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n throw err\n } finally {\n setIsLoadingMore(false)\n }\n }, [entityId, fetchPage, isLoadingMore, mapResponse, nextCursor, t])\n\n React.useEffect(() => {\n if (!entityId) {\n setInteractions([])\n setNextCursor(null)\n setError(null)\n setIsInitialLoading(false)\n return\n }\n setInteractions([])\n setNextCursor(null)\n setError(null)\n let cancelled = false\n setIsInitialLoading(true)\n fetchPage(null)\n .then((payload) => {\n if (cancelled) return\n const mapped = mapResponse(payload)\n setInteractions(mapped)\n })\n .catch((err) => {\n if (cancelled) return\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n })\n .finally(() => {\n if (!cancelled) setIsInitialLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [entityId, excludeTypeFilter, statusFilter, typeFilter, fetchPage, mapResponse, t])\n\n const createInteraction = React.useCallback(\n async (payload: InteractionCreatePayload) => {\n if (!entityId) throw new Error('Interaction creation requires an entity id')\n setIsMutating(true)\n try {\n await apiCallOrThrow(\n '/api/customers/interactions',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.interactions.create.error', 'Failed to create interaction.') },\n )\n await refresh()\n } finally {\n setIsMutating(false)\n }\n },\n [entityId, refresh, t],\n )\n\n const updateInteraction = React.useCallback(\n async (id: string, payload: InteractionUpdatePayload) => {\n setIsMutating(true)\n // Send the optimistic-lock header (target's loaded `updatedAt`) so a stale\n // edit \u2014 including a task/activity edited from another tab \u2014 surfaces the\n // conflict bar instead of silently overwriting (#2055). A stale edit after\n // the record was deleted elsewhere maps to the same 409 via the server's\n // enforceRecordGoneIsConflict, instead of a bare \"Interaction not found\" 404.\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id, ...payload }),\n },\n { errorMessage: t('customers.interactions.update.error', 'Failed to update interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) { await refresh(); return }\n throw err\n } finally {\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const completeInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n setPendingId(id)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions/complete',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.interactions.complete.error', 'Failed to complete interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) { await refresh(); return }\n throw err\n } finally {\n setPendingId(null)\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const cancelInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n setPendingId(id)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions/cancel',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.interactions.cancel.error', 'Failed to cancel interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) { await refresh(); return }\n throw err\n } finally {\n setPendingId(null)\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const deleteInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () =>\n apiCallOrThrow(\n `/api/customers/interactions?id=${encodeURIComponent(id)}`,\n {\n method: 'DELETE',\n },\n { errorMessage: t('customers.interactions.delete.error', 'Failed to delete interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n // A stale delete (the record was changed/deleted in another tab) surfaces\n // the unified conflict bar and re-syncs the list instead of a raw error (#2055).\n if (surfaceRecordConflict(err, t)) {\n await refresh()\n return\n }\n throw err\n } finally {\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const hasMore = entityId != null && nextCursor != null\n\n return {\n interactions,\n isInitialLoading,\n isLoadingMore,\n isMutating,\n hasMore,\n loadMore,\n refresh,\n createInteraction,\n updateInteraction,\n completeInteraction,\n cancelInteraction,\n deleteInteraction,\n pendingId,\n totalCount: interactions.length,\n error,\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCallOrThrow, readApiResultOrThrow, withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { InteractionSummary } from '../types'\n\ntype InteractionsListResponse = {\n items: InteractionSummary[]\n nextCursor?: string\n}\n\nexport type InteractionCreatePayload = {\n entityId: string\n interactionType: string\n title?: string | null\n body?: string | null\n status?: string\n scheduledAt?: string | null\n priority?: number | null\n customValues?: Record<string, unknown>\n ownerUserId?: string | null\n dealId?: string | null\n}\n\nexport type InteractionUpdatePayload = {\n interactionType?: string\n title?: string | null\n body?: string | null\n status?: string\n scheduledAt?: string | null\n occurredAt?: string | null\n priority?: number | null\n customValues?: Record<string, unknown>\n ownerUserId?: string | null\n dealId?: string | null\n}\n\nexport type UseInteractionsOptions = {\n entityId: string | null\n statusFilter?: string\n typeFilter?: string\n excludeTypeFilter?: string\n pageSize?: number\n}\n\nexport type UseInteractionsResult = {\n interactions: InteractionSummary[]\n isInitialLoading: boolean\n isLoadingMore: boolean\n isMutating: boolean\n hasMore: boolean\n loadMore: () => Promise<void>\n refresh: () => Promise<void>\n createInteraction: (payload: InteractionCreatePayload) => Promise<void>\n updateInteraction: (id: string, payload: InteractionUpdatePayload) => Promise<void>\n completeInteraction: (id: string) => Promise<void>\n cancelInteraction: (id: string) => Promise<void>\n deleteInteraction: (id: string) => Promise<void>\n pendingId: string | null\n totalCount: number\n error: string | null\n}\n\nfunction mergeUnique(existing: InteractionSummary[], incoming: InteractionSummary[]): InteractionSummary[] {\n if (!existing.length) return incoming\n if (!incoming.length) return existing\n const byId = new Map<string, InteractionSummary>()\n const result: InteractionSummary[] = []\n for (const item of existing) {\n byId.set(item.id, item)\n result.push(item)\n }\n for (const item of incoming) {\n if (byId.has(item.id)) {\n const index = result.findIndex((entry) => entry.id === item.id)\n if (index !== -1) result[index] = item\n } else {\n byId.set(item.id, item)\n result.push(item)\n }\n }\n return result\n}\n\nexport function useInteractions({\n entityId,\n statusFilter,\n typeFilter,\n excludeTypeFilter,\n pageSize = 25,\n}: UseInteractionsOptions): UseInteractionsResult {\n const t = useT()\n const [interactions, setInteractions] = React.useState<InteractionSummary[]>([])\n const [nextCursor, setNextCursor] = React.useState<string | null>(null)\n const [isInitialLoading, setIsInitialLoading] = React.useState<boolean>(() => Boolean(entityId))\n const [isLoadingMore, setIsLoadingMore] = React.useState(false)\n const [isMutating, setIsMutating] = React.useState(false)\n const [pendingId, setPendingId] = React.useState<string | null>(null)\n const [error, setError] = React.useState<string | null>(null)\n\n const mapResponse = React.useCallback((payload: InteractionsListResponse) => {\n const mapped = Array.isArray(payload.items) ? payload.items : []\n setNextCursor(typeof payload.nextCursor === 'string' && payload.nextCursor.trim().length > 0 ? payload.nextCursor : null)\n setError(null)\n return mapped\n }, [])\n\n const fetchPage = React.useCallback(\n async (cursor?: string | null): Promise<InteractionsListResponse> => {\n if (!entityId) {\n return { items: [], nextCursor: undefined }\n }\n const params = new URLSearchParams({\n limit: String(pageSize),\n entityId,\n sortField: 'scheduledAt',\n sortDir: 'asc',\n })\n if (cursor) params.set('cursor', cursor)\n if (statusFilter) params.set('status', statusFilter)\n if (typeFilter) params.set('interactionType', typeFilter)\n if (excludeTypeFilter) params.set('excludeInteractionType', excludeTypeFilter)\n\n return readApiResultOrThrow<InteractionsListResponse>(\n `/api/customers/interactions?${params.toString()}`,\n undefined,\n { errorMessage: t('customers.interactions.load.error', 'Failed to load interactions.') },\n )\n },\n [entityId, excludeTypeFilter, pageSize, statusFilter, typeFilter, t],\n )\n\n const refresh = React.useCallback(async () => {\n if (!entityId) {\n setInteractions([])\n setNextCursor(null)\n return\n }\n setIsInitialLoading(true)\n try {\n const payload = await fetchPage(null)\n const mapped = mapResponse(payload)\n setInteractions(mapped)\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n throw err\n } finally {\n setIsInitialLoading(false)\n }\n }, [entityId, fetchPage, mapResponse, t])\n\n const loadMore = React.useCallback(async () => {\n if (!entityId) return\n if (isLoadingMore) return\n if (!nextCursor) return\n setIsLoadingMore(true)\n try {\n const payload = await fetchPage(nextCursor)\n const mapped = mapResponse(payload)\n setInteractions((prev) => mergeUnique(prev, mapped))\n } catch (err) {\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n throw err\n } finally {\n setIsLoadingMore(false)\n }\n }, [entityId, fetchPage, isLoadingMore, mapResponse, nextCursor, t])\n\n React.useEffect(() => {\n if (!entityId) {\n setInteractions([])\n setNextCursor(null)\n setError(null)\n setIsInitialLoading(false)\n return\n }\n setInteractions([])\n setNextCursor(null)\n setError(null)\n let cancelled = false\n setIsInitialLoading(true)\n fetchPage(null)\n .then((payload) => {\n if (cancelled) return\n const mapped = mapResponse(payload)\n setInteractions(mapped)\n })\n .catch((err) => {\n if (cancelled) return\n const message = err instanceof Error ? err.message : t('customers.interactions.load.error', 'Failed to load interactions.')\n setError(message)\n })\n .finally(() => {\n if (!cancelled) setIsInitialLoading(false)\n })\n return () => {\n cancelled = true\n }\n }, [entityId, excludeTypeFilter, statusFilter, typeFilter, fetchPage, mapResponse, t])\n\n const createInteraction = React.useCallback(\n async (payload: InteractionCreatePayload) => {\n if (!entityId) throw new Error('Interaction creation requires an entity id')\n setIsMutating(true)\n try {\n await apiCallOrThrow(\n '/api/customers/interactions',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { errorMessage: t('customers.interactions.create.error', 'Failed to create interaction.') },\n )\n await refresh()\n } finally {\n setIsMutating(false)\n }\n },\n [entityId, refresh, t],\n )\n\n const updateInteraction = React.useCallback(\n async (id: string, payload: InteractionUpdatePayload) => {\n setIsMutating(true)\n // Send the optimistic-lock header (target's loaded `updatedAt`) so a stale\n // edit \u2014 including a task/activity edited from another tab \u2014 surfaces the\n // conflict bar instead of silently overwriting (#2055). A stale edit after\n // the record was deleted elsewhere maps to the same 409 via the server's\n // enforceRecordGoneIsConflict, instead of a bare \"Interaction not found\" 404.\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions',\n {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id, ...payload }),\n },\n { errorMessage: t('customers.interactions.update.error', 'Failed to update interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) await refresh()\n throw err\n } finally {\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const completeInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n setPendingId(id)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions/complete',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.interactions.complete.error', 'Failed to complete interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) await refresh()\n throw err\n } finally {\n setPendingId(null)\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const cancelInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n setPendingId(id)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () => apiCallOrThrow(\n '/api/customers/interactions/cancel',\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ id }),\n },\n { errorMessage: t('customers.interactions.cancel.error', 'Failed to cancel interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n if (surfaceRecordConflict(err, t)) await refresh()\n throw err\n } finally {\n setPendingId(null)\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const deleteInteraction = React.useCallback(\n async (id: string) => {\n setIsMutating(true)\n const target = interactions.find((entry) => entry.id === id)\n try {\n await withScopedApiRequestHeaders(\n buildOptimisticLockHeader(target?.updatedAt ?? null),\n () =>\n apiCallOrThrow(\n `/api/customers/interactions?id=${encodeURIComponent(id)}`,\n {\n method: 'DELETE',\n },\n { errorMessage: t('customers.interactions.delete.error', 'Failed to delete interaction.') },\n ),\n )\n await refresh()\n } catch (err) {\n // A stale delete (the record was changed/deleted in another tab) surfaces\n // the unified conflict bar and re-syncs the list instead of a raw error (#2055).\n if (surfaceRecordConflict(err, t)) {\n await refresh()\n }\n throw err\n } finally {\n setIsMutating(false)\n }\n },\n [interactions, refresh, t],\n )\n\n const hasMore = entityId != null && nextCursor != null\n\n return {\n interactions,\n isInitialLoading,\n isLoadingMore,\n isMutating,\n hasMore,\n loadMore,\n refresh,\n createInteraction,\n updateInteraction,\n completeInteraction,\n cancelInteraction,\n deleteInteraction,\n pendingId,\n totalCount: interactions.length,\n error,\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,134 @@
1
+ const DEAL_STATUS_DEFAULTS = [
2
+ { value: "open", label: "Open", color: "#2563eb", icon: "lucide:circle" },
3
+ { value: "closed", label: "Closed", color: "#6b7280", icon: "lucide:check-circle" },
4
+ { value: "win", label: "Win", color: "#22c55e", icon: "lucide:trophy" },
5
+ { value: "lost", label: "Lost", color: "#ef4444", icon: "lucide:flag" },
6
+ { value: "in_progress", label: "In progress", color: "#f59e0b", icon: "lucide:activity" }
7
+ ];
8
+ const PIPELINE_STAGE_DEFAULTS = [
9
+ { value: "opportunity", label: "Opportunity", color: "#38bdf8", icon: "lucide:target" },
10
+ { value: "marketing_qualified_lead", label: "Marketing Qualified Lead", color: "#a855f7", icon: "lucide:sparkles" },
11
+ { value: "sales_qualified_lead", label: "Sales Qualified Lead", color: "#f97316", icon: "lucide:users" },
12
+ { value: "offering", label: "Offering", color: "#22c55e", icon: "lucide:package" },
13
+ { value: "negotiations", label: "Negotiations", color: "#facc15", icon: "lucide:handshake" },
14
+ { value: "win", label: "Win", color: "#16a34a", icon: "lucide:award" },
15
+ { value: "lost", label: "Lost", color: "#ef4444", icon: "lucide:flag" },
16
+ { value: "stalled", label: "Stalled", color: "#6b7280", icon: "lucide:alert-circle" }
17
+ ];
18
+ const ENTITY_STATUS_DEFAULTS = [
19
+ { value: "active", label: "Active", color: "#22c55e", icon: "lucide:user-check" },
20
+ { value: "inactive", label: "Inactive", color: "#94a3b8", icon: "lucide:pause-circle" },
21
+ { value: "pending", label: "Pending", color: "#f59e0b", icon: "lucide:clock" },
22
+ { value: "archived", label: "Archived", color: "#64748b", icon: "lucide:archive" }
23
+ ];
24
+ const ENTITY_LIFECYCLE_STAGE_DEFAULTS = [
25
+ { value: "lead", label: "Lead", color: "#3b82f6", icon: "lucide:sparkles" },
26
+ { value: "prospect", label: "Prospect", color: "#8b5cf6", icon: "lucide:eye" },
27
+ { value: "customer", label: "Customer", color: "#22c55e", icon: "lucide:handshake" },
28
+ { value: "subscriber", label: "Subscriber", color: "#10b981", icon: "lucide:bell" },
29
+ { value: "churned", label: "Churned", color: "#ef4444", icon: "lucide:user-x" },
30
+ { value: "other", label: "Other", color: "#94a3b8", icon: "lucide:circle" }
31
+ ];
32
+ const ENTITY_SOURCE_DEFAULTS = [
33
+ { value: "linkedin", label: "LinkedIn", color: "#0a66c2", icon: "lucide:linkedin" },
34
+ { value: "email", label: "Email", color: "#3b82f6", icon: "lucide:mail" },
35
+ { value: "web_form", label: "Web form", color: "#22c55e", icon: "lucide:globe" },
36
+ { value: "referral", label: "Referral", color: "#8b5cf6", icon: "lucide:users" },
37
+ { value: "customer_referral", label: "Customer referral", color: "#22c55e", icon: "lucide:thumbs-up" },
38
+ { value: "partner_referral", label: "Partner referral", color: "#3b82f6", icon: "lucide:handshake" },
39
+ { value: "event", label: "Conference / Event", color: "#f59e0b", icon: "lucide:calendar" },
40
+ { value: "cold_outreach", label: "Cold outreach", color: "#94a3b8", icon: "lucide:phone" },
41
+ { value: "facebook", label: "Facebook", color: "#1877f2", icon: "lucide:facebook" },
42
+ { value: "typeform", label: "Typeform", color: "#262627", icon: "lucide:file-text" },
43
+ { value: "other", label: "Other", color: "#64748b", icon: "lucide:circle" }
44
+ ];
45
+ const ADDRESS_TYPE_DEFAULTS = [
46
+ { value: "office", label: "Office", color: "#3b82f6", icon: "lucide:building" },
47
+ { value: "work", label: "Work", color: "#6366f1", icon: "lucide:briefcase" },
48
+ { value: "billing", label: "Billing", color: "#f97316", icon: "lucide:wallet" },
49
+ { value: "shipping", label: "Shipping", color: "#22c55e", icon: "lucide:truck" },
50
+ { value: "home", label: "Home", color: "#10b981", icon: "lucide:map-pin" }
51
+ ];
52
+ const ACTIVITY_TYPE_DEFAULTS = [
53
+ { value: "call", label: "Call", color: "#2563eb", icon: "lucide:phone-call" },
54
+ { value: "email", label: "Email", color: "#16a34a", icon: "lucide:mail" },
55
+ { value: "event", label: "Event", color: "#6366f1", icon: "lucide:calendar" },
56
+ { value: "meeting", label: "Meeting", color: "#f59e0b", icon: "lucide:users" },
57
+ { value: "note", label: "Note", color: "#a855f7", icon: "lucide:notebook" },
58
+ { value: "task", label: "Task", color: "#ef4444", icon: "lucide:check-square" }
59
+ ];
60
+ const INTERACTION_STATUS_DEFAULTS = [
61
+ { value: "planned", label: "Planned", color: "#2563eb", icon: "lucide:circle" },
62
+ { value: "in_progress", label: "In progress", color: "#f59e0b", icon: "lucide:activity" },
63
+ { value: "waiting", label: "Waiting / blocked", color: "#a855f7", icon: "lucide:pause-circle" },
64
+ { value: "done", label: "Done", color: "#22c55e", icon: "lucide:check-circle" },
65
+ { value: "canceled", label: "Canceled", color: "#6b7280", icon: "lucide:x-circle" }
66
+ ];
67
+ const JOB_TITLE_DEFAULTS = [
68
+ { value: "Director of Operations", label: "Director of Operations", color: "#f97316", icon: "lucide:settings" },
69
+ { value: "VP of Partnerships", label: "VP of Partnerships", color: "#6366f1", icon: "lucide:users" },
70
+ { value: "Founder & Principal", label: "Founder & Principal", color: "#ec4899", icon: "lucide:star" },
71
+ { value: "Senior Project Manager", label: "Senior Project Manager", color: "#0ea5e9", icon: "lucide:clipboard-list" },
72
+ { value: "Chief Revenue Officer", label: "Chief Revenue Officer", color: "#8b5cf6", icon: "lucide:bar-chart-3" },
73
+ { value: "Director of Retail Partnerships", label: "Director of Retail Partnerships", color: "#f59e0b", icon: "lucide:shopping-bag" }
74
+ ];
75
+ const INDUSTRY_DEFAULTS = [
76
+ { value: "Renewable Energy", label: "Renewable Energy" },
77
+ { value: "Software", label: "Software" },
78
+ { value: "Interior Design", label: "Interior Design" },
79
+ { value: "SaaS", label: "SaaS" },
80
+ { value: "E-commerce", label: "E-commerce" },
81
+ { value: "Healthcare", label: "Healthcare" },
82
+ { value: "Manufacturing", label: "Manufacturing" },
83
+ { value: "Logistics", label: "Logistics" },
84
+ { value: "Financial Services", label: "Financial Services" },
85
+ { value: "Retail", label: "Retail" },
86
+ { value: "Hospitality", label: "Hospitality" },
87
+ { value: "Energy", label: "Energy" },
88
+ { value: "Media", label: "Media" }
89
+ ];
90
+ const TEMPERATURE_DEFAULTS = [
91
+ { value: "hot", label: "Hot", color: "#ef4444", icon: "lucide:flame" },
92
+ { value: "high", label: "High", color: "#f59e0b", icon: "lucide:trending-up" },
93
+ { value: "medium", label: "Medium", color: "#8b5cf6", icon: "lucide:sparkles" },
94
+ { value: "low", label: "Low", color: "#64748b", icon: "lucide:clock" },
95
+ { value: "cold", label: "Cold", color: "#94a3b8", icon: "lucide:snowflake" }
96
+ ];
97
+ const PERSON_COMPANY_ROLE_DEFAULTS = [
98
+ { value: "decision_maker", label: "Decision maker", color: "#f59e0b", icon: "lucide:crown" },
99
+ { value: "influencer", label: "Influencer", color: "#8b5cf6", icon: "lucide:sparkles" },
100
+ { value: "budget_holder", label: "Budget holder", color: "#3b82f6", icon: "lucide:wallet" },
101
+ { value: "technical_evaluator", label: "Technical evaluator", color: "#22c55e", icon: "lucide:wrench" },
102
+ { value: "primary_contact", label: "Primary contact", color: "#0ea5e9", icon: "lucide:star" },
103
+ { value: "end_user", label: "End user", color: "#64748b", icon: "lucide:user" }
104
+ ];
105
+ const CUSTOMER_DICTIONARY_DEFAULTS = {
106
+ status: ENTITY_STATUS_DEFAULTS,
107
+ source: ENTITY_SOURCE_DEFAULTS,
108
+ lifecycle_stage: ENTITY_LIFECYCLE_STAGE_DEFAULTS,
109
+ address_type: ADDRESS_TYPE_DEFAULTS,
110
+ activity_type: ACTIVITY_TYPE_DEFAULTS,
111
+ interaction_status: INTERACTION_STATUS_DEFAULTS,
112
+ job_title: JOB_TITLE_DEFAULTS,
113
+ deal_status: DEAL_STATUS_DEFAULTS,
114
+ pipeline_stage: PIPELINE_STAGE_DEFAULTS,
115
+ industry: INDUSTRY_DEFAULTS,
116
+ temperature: TEMPERATURE_DEFAULTS,
117
+ person_company_role: PERSON_COMPANY_ROLE_DEFAULTS
118
+ };
119
+ export {
120
+ ACTIVITY_TYPE_DEFAULTS,
121
+ ADDRESS_TYPE_DEFAULTS,
122
+ CUSTOMER_DICTIONARY_DEFAULTS,
123
+ DEAL_STATUS_DEFAULTS,
124
+ ENTITY_LIFECYCLE_STAGE_DEFAULTS,
125
+ ENTITY_SOURCE_DEFAULTS,
126
+ ENTITY_STATUS_DEFAULTS,
127
+ INDUSTRY_DEFAULTS,
128
+ INTERACTION_STATUS_DEFAULTS,
129
+ JOB_TITLE_DEFAULTS,
130
+ PERSON_COMPANY_ROLE_DEFAULTS,
131
+ PIPELINE_STAGE_DEFAULTS,
132
+ TEMPERATURE_DEFAULTS
133
+ };
134
+ //# sourceMappingURL=dictionaryDefaults.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/customers/lib/dictionaryDefaults.ts"],
4
+ "sourcesContent": ["type DictionaryDefault = {\n value: string\n label: string\n color?: string\n icon?: string\n}\n\nexport const DEAL_STATUS_DEFAULTS: DictionaryDefault[] = [\n { value: 'open', label: 'Open', color: '#2563eb', icon: 'lucide:circle' },\n { value: 'closed', label: 'Closed', color: '#6b7280', icon: 'lucide:check-circle' },\n { value: 'win', label: 'Win', color: '#22c55e', icon: 'lucide:trophy' },\n { value: 'lost', label: 'Lost', color: '#ef4444', icon: 'lucide:flag' },\n { value: 'in_progress', label: 'In progress', color: '#f59e0b', icon: 'lucide:activity' },\n]\n\nexport const PIPELINE_STAGE_DEFAULTS: DictionaryDefault[] = [\n { value: 'opportunity', label: 'Opportunity', color: '#38bdf8', icon: 'lucide:target' },\n { value: 'marketing_qualified_lead', label: 'Marketing Qualified Lead', color: '#a855f7', icon: 'lucide:sparkles' },\n { value: 'sales_qualified_lead', label: 'Sales Qualified Lead', color: '#f97316', icon: 'lucide:users' },\n { value: 'offering', label: 'Offering', color: '#22c55e', icon: 'lucide:package' },\n { value: 'negotiations', label: 'Negotiations', color: '#facc15', icon: 'lucide:handshake' },\n { value: 'win', label: 'Win', color: '#16a34a', icon: 'lucide:award' },\n { value: 'lost', label: 'Lost', color: '#ef4444', icon: 'lucide:flag' },\n { value: 'stalled', label: 'Stalled', color: '#6b7280', icon: 'lucide:alert-circle' },\n]\n\nexport const ENTITY_STATUS_DEFAULTS: DictionaryDefault[] = [\n { value: 'active', label: 'Active', color: '#22c55e', icon: 'lucide:user-check' },\n { value: 'inactive', label: 'Inactive', color: '#94a3b8', icon: 'lucide:pause-circle' },\n { value: 'pending', label: 'Pending', color: '#f59e0b', icon: 'lucide:clock' },\n { value: 'archived', label: 'Archived', color: '#64748b', icon: 'lucide:archive' },\n]\n\nexport const ENTITY_LIFECYCLE_STAGE_DEFAULTS: DictionaryDefault[] = [\n { value: 'lead', label: 'Lead', color: '#3b82f6', icon: 'lucide:sparkles' },\n { value: 'prospect', label: 'Prospect', color: '#8b5cf6', icon: 'lucide:eye' },\n { value: 'customer', label: 'Customer', color: '#22c55e', icon: 'lucide:handshake' },\n { value: 'subscriber', label: 'Subscriber', color: '#10b981', icon: 'lucide:bell' },\n { value: 'churned', label: 'Churned', color: '#ef4444', icon: 'lucide:user-x' },\n { value: 'other', label: 'Other', color: '#94a3b8', icon: 'lucide:circle' },\n]\n\nexport const ENTITY_SOURCE_DEFAULTS: DictionaryDefault[] = [\n { value: 'linkedin', label: 'LinkedIn', color: '#0a66c2', icon: 'lucide:linkedin' },\n { value: 'email', label: 'Email', color: '#3b82f6', icon: 'lucide:mail' },\n { value: 'web_form', label: 'Web form', color: '#22c55e', icon: 'lucide:globe' },\n { value: 'referral', label: 'Referral', color: '#8b5cf6', icon: 'lucide:users' },\n { value: 'customer_referral', label: 'Customer referral', color: '#22c55e', icon: 'lucide:thumbs-up' },\n { value: 'partner_referral', label: 'Partner referral', color: '#3b82f6', icon: 'lucide:handshake' },\n { value: 'event', label: 'Conference / Event', color: '#f59e0b', icon: 'lucide:calendar' },\n { value: 'cold_outreach', label: 'Cold outreach', color: '#94a3b8', icon: 'lucide:phone' },\n { value: 'facebook', label: 'Facebook', color: '#1877f2', icon: 'lucide:facebook' },\n { value: 'typeform', label: 'Typeform', color: '#262627', icon: 'lucide:file-text' },\n { value: 'other', label: 'Other', color: '#64748b', icon: 'lucide:circle' },\n]\n\nexport const ADDRESS_TYPE_DEFAULTS: DictionaryDefault[] = [\n { value: 'office', label: 'Office', color: '#3b82f6', icon: 'lucide:building' },\n { value: 'work', label: 'Work', color: '#6366f1', icon: 'lucide:briefcase' },\n { value: 'billing', label: 'Billing', color: '#f97316', icon: 'lucide:wallet' },\n { value: 'shipping', label: 'Shipping', color: '#22c55e', icon: 'lucide:truck' },\n { value: 'home', label: 'Home', color: '#10b981', icon: 'lucide:map-pin' },\n]\n\nexport const ACTIVITY_TYPE_DEFAULTS: DictionaryDefault[] = [\n { value: 'call', label: 'Call', color: '#2563eb', icon: 'lucide:phone-call' },\n { value: 'email', label: 'Email', color: '#16a34a', icon: 'lucide:mail' },\n { value: 'event', label: 'Event', color: '#6366f1', icon: 'lucide:calendar' },\n { value: 'meeting', label: 'Meeting', color: '#f59e0b', icon: 'lucide:users' },\n { value: 'note', label: 'Note', color: '#a855f7', icon: 'lucide:notebook' },\n { value: 'task', label: 'Task', color: '#ef4444', icon: 'lucide:check-square' },\n]\n\nexport const INTERACTION_STATUS_DEFAULTS: DictionaryDefault[] = [\n { value: 'planned', label: 'Planned', color: '#2563eb', icon: 'lucide:circle' },\n { value: 'in_progress', label: 'In progress', color: '#f59e0b', icon: 'lucide:activity' },\n { value: 'waiting', label: 'Waiting / blocked', color: '#a855f7', icon: 'lucide:pause-circle' },\n { value: 'done', label: 'Done', color: '#22c55e', icon: 'lucide:check-circle' },\n { value: 'canceled', label: 'Canceled', color: '#6b7280', icon: 'lucide:x-circle' },\n]\n\nexport const JOB_TITLE_DEFAULTS: DictionaryDefault[] = [\n { value: 'Director of Operations', label: 'Director of Operations', color: '#f97316', icon: 'lucide:settings' },\n { value: 'VP of Partnerships', label: 'VP of Partnerships', color: '#6366f1', icon: 'lucide:users' },\n { value: 'Founder & Principal', label: 'Founder & Principal', color: '#ec4899', icon: 'lucide:star' },\n { value: 'Senior Project Manager', label: 'Senior Project Manager', color: '#0ea5e9', icon: 'lucide:clipboard-list' },\n { value: 'Chief Revenue Officer', label: 'Chief Revenue Officer', color: '#8b5cf6', icon: 'lucide:bar-chart-3' },\n { value: 'Director of Retail Partnerships', label: 'Director of Retail Partnerships', color: '#f59e0b', icon: 'lucide:shopping-bag' },\n]\n\nexport const INDUSTRY_DEFAULTS: DictionaryDefault[] = [\n { value: 'Renewable Energy', label: 'Renewable Energy' },\n { value: 'Software', label: 'Software' },\n { value: 'Interior Design', label: 'Interior Design' },\n { value: 'SaaS', label: 'SaaS' },\n { value: 'E-commerce', label: 'E-commerce' },\n { value: 'Healthcare', label: 'Healthcare' },\n { value: 'Manufacturing', label: 'Manufacturing' },\n { value: 'Logistics', label: 'Logistics' },\n { value: 'Financial Services', label: 'Financial Services' },\n { value: 'Retail', label: 'Retail' },\n { value: 'Hospitality', label: 'Hospitality' },\n { value: 'Energy', label: 'Energy' },\n { value: 'Media', label: 'Media' },\n]\n\nexport const TEMPERATURE_DEFAULTS: DictionaryDefault[] = [\n { value: 'hot', label: 'Hot', color: '#ef4444', icon: 'lucide:flame' },\n { value: 'high', label: 'High', color: '#f59e0b', icon: 'lucide:trending-up' },\n { value: 'medium', label: 'Medium', color: '#8b5cf6', icon: 'lucide:sparkles' },\n { value: 'low', label: 'Low', color: '#64748b', icon: 'lucide:clock' },\n { value: 'cold', label: 'Cold', color: '#94a3b8', icon: 'lucide:snowflake' },\n]\n\nexport const PERSON_COMPANY_ROLE_DEFAULTS = [\n { value: 'decision_maker', label: 'Decision maker', color: '#f59e0b', icon: 'lucide:crown' },\n { value: 'influencer', label: 'Influencer', color: '#8b5cf6', icon: 'lucide:sparkles' },\n { value: 'budget_holder', label: 'Budget holder', color: '#3b82f6', icon: 'lucide:wallet' },\n { value: 'technical_evaluator', label: 'Technical evaluator', color: '#22c55e', icon: 'lucide:wrench' },\n { value: 'primary_contact', label: 'Primary contact', color: '#0ea5e9', icon: 'lucide:star' },\n { value: 'end_user', label: 'End user', color: '#64748b', icon: 'lucide:user' },\n]\n\nexport const CUSTOMER_DICTIONARY_DEFAULTS: Record<string, readonly DictionaryDefault[]> = {\n status: ENTITY_STATUS_DEFAULTS,\n source: ENTITY_SOURCE_DEFAULTS,\n lifecycle_stage: ENTITY_LIFECYCLE_STAGE_DEFAULTS,\n address_type: ADDRESS_TYPE_DEFAULTS,\n activity_type: ACTIVITY_TYPE_DEFAULTS,\n interaction_status: INTERACTION_STATUS_DEFAULTS,\n job_title: JOB_TITLE_DEFAULTS,\n deal_status: DEAL_STATUS_DEFAULTS,\n pipeline_stage: PIPELINE_STAGE_DEFAULTS,\n industry: INDUSTRY_DEFAULTS,\n temperature: TEMPERATURE_DEFAULTS,\n person_company_role: PERSON_COMPANY_ROLE_DEFAULTS,\n}\n"],
5
+ "mappings": "AAOO,MAAM,uBAA4C;AAAA,EACvD,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,gBAAgB;AAAA,EACxE,EAAE,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,MAAM,sBAAsB;AAAA,EAClF,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,WAAW,MAAM,gBAAgB;AAAA,EACtE,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,cAAc;AAAA,EACtE,EAAE,OAAO,eAAe,OAAO,eAAe,OAAO,WAAW,MAAM,kBAAkB;AAC1F;AAEO,MAAM,0BAA+C;AAAA,EAC1D,EAAE,OAAO,eAAe,OAAO,eAAe,OAAO,WAAW,MAAM,gBAAgB;AAAA,EACtF,EAAE,OAAO,4BAA4B,OAAO,4BAA4B,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAClH,EAAE,OAAO,wBAAwB,OAAO,wBAAwB,OAAO,WAAW,MAAM,eAAe;AAAA,EACvG,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,iBAAiB;AAAA,EACjF,EAAE,OAAO,gBAAgB,OAAO,gBAAgB,OAAO,WAAW,MAAM,mBAAmB;AAAA,EAC3F,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,WAAW,MAAM,eAAe;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,cAAc;AAAA,EACtE,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,sBAAsB;AACtF;AAEO,MAAM,yBAA8C;AAAA,EACzD,EAAE,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,MAAM,oBAAoB;AAAA,EAChF,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,sBAAsB;AAAA,EACtF,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,eAAe;AAAA,EAC7E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,iBAAiB;AACnF;AAEO,MAAM,kCAAuD;AAAA,EAClE,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC1E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,aAAa;AAAA,EAC7E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,mBAAmB;AAAA,EACnF,EAAE,OAAO,cAAc,OAAO,cAAc,OAAO,WAAW,MAAM,cAAc;AAAA,EAClF,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,gBAAgB;AAAA,EAC9E,EAAE,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,MAAM,gBAAgB;AAC5E;AAEO,MAAM,yBAA8C;AAAA,EACzD,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAClF,EAAE,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,MAAM,cAAc;AAAA,EACxE,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,eAAe;AAAA,EAC/E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,eAAe;AAAA,EAC/E,EAAE,OAAO,qBAAqB,OAAO,qBAAqB,OAAO,WAAW,MAAM,mBAAmB;AAAA,EACrG,EAAE,OAAO,oBAAoB,OAAO,oBAAoB,OAAO,WAAW,MAAM,mBAAmB;AAAA,EACnG,EAAE,OAAO,SAAS,OAAO,sBAAsB,OAAO,WAAW,MAAM,kBAAkB;AAAA,EACzF,EAAE,OAAO,iBAAiB,OAAO,iBAAiB,OAAO,WAAW,MAAM,eAAe;AAAA,EACzF,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAClF,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,mBAAmB;AAAA,EACnF,EAAE,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,MAAM,gBAAgB;AAC5E;AAEO,MAAM,wBAA6C;AAAA,EACxD,EAAE,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC9E,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,mBAAmB;AAAA,EAC3E,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,gBAAgB;AAAA,EAC9E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,eAAe;AAAA,EAC/E,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,iBAAiB;AAC3E;AAEO,MAAM,yBAA8C;AAAA,EACzD,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,oBAAoB;AAAA,EAC5E,EAAE,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,MAAM,cAAc;AAAA,EACxE,EAAE,OAAO,SAAS,OAAO,SAAS,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC5E,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,eAAe;AAAA,EAC7E,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC1E,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,sBAAsB;AAChF;AAEO,MAAM,8BAAmD;AAAA,EAC9D,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,MAAM,gBAAgB;AAAA,EAC9E,EAAE,OAAO,eAAe,OAAO,eAAe,OAAO,WAAW,MAAM,kBAAkB;AAAA,EACxF,EAAE,OAAO,WAAW,OAAO,qBAAqB,OAAO,WAAW,MAAM,sBAAsB;AAAA,EAC9F,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,sBAAsB;AAAA,EAC9E,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,kBAAkB;AACpF;AAEO,MAAM,qBAA0C;AAAA,EACrD,EAAE,OAAO,0BAA0B,OAAO,0BAA0B,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC9G,EAAE,OAAO,sBAAsB,OAAO,sBAAsB,OAAO,WAAW,MAAM,eAAe;AAAA,EACnG,EAAE,OAAO,uBAAuB,OAAO,uBAAuB,OAAO,WAAW,MAAM,cAAc;AAAA,EACpG,EAAE,OAAO,0BAA0B,OAAO,0BAA0B,OAAO,WAAW,MAAM,wBAAwB;AAAA,EACpH,EAAE,OAAO,yBAAyB,OAAO,yBAAyB,OAAO,WAAW,MAAM,qBAAqB;AAAA,EAC/G,EAAE,OAAO,mCAAmC,OAAO,mCAAmC,OAAO,WAAW,MAAM,sBAAsB;AACtI;AAEO,MAAM,oBAAyC;AAAA,EACpD,EAAE,OAAO,oBAAoB,OAAO,mBAAmB;AAAA,EACvD,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,EACvC,EAAE,OAAO,mBAAmB,OAAO,kBAAkB;AAAA,EACrD,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,EAC/B,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,EAC3C,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,EAC3C,EAAE,OAAO,iBAAiB,OAAO,gBAAgB;AAAA,EACjD,EAAE,OAAO,aAAa,OAAO,YAAY;AAAA,EACzC,EAAE,OAAO,sBAAsB,OAAO,qBAAqB;AAAA,EAC3D,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,EACnC,EAAE,OAAO,eAAe,OAAO,cAAc;AAAA,EAC7C,EAAE,OAAO,UAAU,OAAO,SAAS;AAAA,EACnC,EAAE,OAAO,SAAS,OAAO,QAAQ;AACnC;AAEO,MAAM,uBAA4C;AAAA,EACvD,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,WAAW,MAAM,eAAe;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,qBAAqB;AAAA,EAC7E,EAAE,OAAO,UAAU,OAAO,UAAU,OAAO,WAAW,MAAM,kBAAkB;AAAA,EAC9E,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,WAAW,MAAM,eAAe;AAAA,EACrE,EAAE,OAAO,QAAQ,OAAO,QAAQ,OAAO,WAAW,MAAM,mBAAmB;AAC7E;AAEO,MAAM,+BAA+B;AAAA,EAC1C,EAAE,OAAO,kBAAkB,OAAO,kBAAkB,OAAO,WAAW,MAAM,eAAe;AAAA,EAC3F,EAAE,OAAO,cAAc,OAAO,cAAc,OAAO,WAAW,MAAM,kBAAkB;AAAA,EACtF,EAAE,OAAO,iBAAiB,OAAO,iBAAiB,OAAO,WAAW,MAAM,gBAAgB;AAAA,EAC1F,EAAE,OAAO,uBAAuB,OAAO,uBAAuB,OAAO,WAAW,MAAM,gBAAgB;AAAA,EACtG,EAAE,OAAO,mBAAmB,OAAO,mBAAmB,OAAO,WAAW,MAAM,cAAc;AAAA,EAC5F,EAAE,OAAO,YAAY,OAAO,YAAY,OAAO,WAAW,MAAM,cAAc;AAChF;AAEO,MAAM,+BAA6E;AAAA,EACxF,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,aAAa;AAAA,EACb,qBAAqB;AACvB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,59 @@
1
+ import { loadDictionary } from "@open-mercato/shared/lib/i18n/server";
2
+ import { createFallbackTranslator } from "@open-mercato/shared/lib/i18n/translate";
3
+ import { getTranslationOverlayPlugin } from "@open-mercato/shared/lib/localization/overlay-plugin";
4
+ import { createLogger } from "@open-mercato/shared/lib/logger";
5
+ import { getTelemetryRuntime } from "@open-mercato/shared/lib/telemetry/runtime";
6
+ import { CUSTOMER_DICTIONARY_DEFAULTS } from "./dictionaryDefaults.js";
7
+ const logger = createLogger("customers").child({ component: "dictionary-labels" });
8
+ function customerDictionaryLabelKey(kind, value) {
9
+ const token = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
10
+ return `customers.dictionaries.defaults.${kind}.${token}`;
11
+ }
12
+ async function localizeCustomerDictionaryEntries(entries, options) {
13
+ if (!entries.length) return [];
14
+ const dictionaryLocale = options.locale.toLowerCase().split("-")[0];
15
+ const translate = createFallbackTranslator(await loadDictionary(dictionaryLocale));
16
+ const defaults = Object.prototype.hasOwnProperty.call(CUSTOMER_DICTIONARY_DEFAULTS, options.kind) ? CUSTOMER_DICTIONARY_DEFAULTS[options.kind] : [];
17
+ const localized = entries.map((entry) => {
18
+ const seeded = defaults.find((candidate) => candidate.value === entry.value && candidate.label === entry.label);
19
+ const renewalQuarter = options.kind === "renewal_quarter" ? /^(\d{4})_q([1-4])$/.exec(entry.value) : null;
20
+ const label = renewalQuarter && entry.label === `Q${renewalQuarter[2]} ${renewalQuarter[1]}` ? translate("customers.dictionaries.defaults.renewal_quarter.label", entry.label, {
21
+ year: renewalQuarter[1],
22
+ quarter: renewalQuarter[2]
23
+ }) : seeded ? translate(customerDictionaryLabelKey(options.kind, seeded.value), entry.label) : entry.label;
24
+ return {
25
+ ...entry,
26
+ label
27
+ };
28
+ });
29
+ const { overlay } = getTranslationOverlayPlugin();
30
+ if (!overlay) return localized;
31
+ const organizationIds = new Set(localized.map((entry) => entry.organizationId));
32
+ const labelsById = /* @__PURE__ */ new Map();
33
+ for (const organizationId of organizationIds) {
34
+ const items = localized.filter((entry) => entry.organizationId === organizationId);
35
+ try {
36
+ const translated = await overlay(items.map(({ id, label }) => ({ id, label })), {
37
+ entityType: "customers:customer_dictionary_entry",
38
+ locale: options.locale,
39
+ tenantId: options.tenantId,
40
+ organizationId,
41
+ container: options.container
42
+ });
43
+ for (const item of translated) {
44
+ if (typeof item.id === "string" && typeof item.label === "string" && item.label.trim()) {
45
+ labelsById.set(item.id, item.label);
46
+ }
47
+ }
48
+ } catch (error) {
49
+ getTelemetryRuntime()?.reportError(error, { module: "customers", code: "customers.dictionary_translation_failed" });
50
+ logger.warn("Translation overlay failed", { error });
51
+ }
52
+ }
53
+ return localized.map((entry) => ({ ...entry, label: labelsById.get(entry.id) ?? entry.label }));
54
+ }
55
+ export {
56
+ customerDictionaryLabelKey,
57
+ localizeCustomerDictionaryEntries
58
+ };
59
+ //# sourceMappingURL=dictionaryLabels.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/customers/lib/dictionaryLabels.ts"],
4
+ "sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { Locale } from '@open-mercato/shared/lib/i18n/config'\nimport { loadDictionary } from '@open-mercato/shared/lib/i18n/server'\nimport { createFallbackTranslator } from '@open-mercato/shared/lib/i18n/translate'\nimport { getTranslationOverlayPlugin } from '@open-mercato/shared/lib/localization/overlay-plugin'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\nimport { getTelemetryRuntime } from '@open-mercato/shared/lib/telemetry/runtime'\nimport { CUSTOMER_DICTIONARY_DEFAULTS } from './dictionaryDefaults'\n\nconst logger = createLogger('customers').child({ component: 'dictionary-labels' })\n\ntype DictionaryLabelEntry = {\n id: string\n value: string\n label: string\n organizationId: string\n}\n\nexport function customerDictionaryLabelKey(kind: string, value: string): string {\n const token = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '')\n return `customers.dictionaries.defaults.${kind}.${token}`\n}\n\nexport async function localizeCustomerDictionaryEntries<T extends DictionaryLabelEntry>(\n entries: T[],\n options: { kind: string; locale: string; tenantId: string; container: AwilixContainer },\n): Promise<T[]> {\n if (!entries.length) return []\n const dictionaryLocale = options.locale.toLowerCase().split('-')[0] as Locale\n const translate = createFallbackTranslator(await loadDictionary(dictionaryLocale))\n const defaults = Object.prototype.hasOwnProperty.call(CUSTOMER_DICTIONARY_DEFAULTS, options.kind)\n ? CUSTOMER_DICTIONARY_DEFAULTS[options.kind]\n : []\n const localized = entries.map((entry) => {\n const seeded = defaults.find((candidate) => candidate.value === entry.value && candidate.label === entry.label)\n const renewalQuarter = options.kind === 'renewal_quarter' ? /^(\\d{4})_q([1-4])$/.exec(entry.value) : null\n const label = renewalQuarter && entry.label === `Q${renewalQuarter[2]} ${renewalQuarter[1]}`\n ? translate('customers.dictionaries.defaults.renewal_quarter.label', entry.label, {\n year: renewalQuarter[1], quarter: renewalQuarter[2],\n })\n : seeded ? translate(customerDictionaryLabelKey(options.kind, seeded.value), entry.label) : entry.label\n return {\n ...entry,\n label,\n }\n })\n const { overlay } = getTranslationOverlayPlugin()\n if (!overlay) return localized\n\n const organizationIds = new Set(localized.map((entry) => entry.organizationId))\n const labelsById = new Map<string, string>()\n for (const organizationId of organizationIds) {\n const items = localized.filter((entry) => entry.organizationId === organizationId)\n try {\n const translated = await overlay(items.map(({ id, label }) => ({ id, label })), {\n entityType: 'customers:customer_dictionary_entry',\n locale: options.locale,\n tenantId: options.tenantId,\n organizationId,\n container: options.container,\n })\n for (const item of translated) {\n if (typeof item.id === 'string' && typeof item.label === 'string' && item.label.trim()) {\n labelsById.set(item.id, item.label)\n }\n }\n } catch (error) {\n getTelemetryRuntime()?.reportError(error, { module: 'customers', code: 'customers.dictionary_translation_failed' })\n logger.warn('Translation overlay failed', { error })\n }\n }\n return localized.map((entry) => ({ ...entry, label: labelsById.get(entry.id) ?? entry.label }))\n}\n"],
5
+ "mappings": "AAEA,SAAS,sBAAsB;AAC/B,SAAS,gCAAgC;AACzC,SAAS,mCAAmC;AAC5C,SAAS,oBAAoB;AAC7B,SAAS,2BAA2B;AACpC,SAAS,oCAAoC;AAE7C,MAAM,SAAS,aAAa,WAAW,EAAE,MAAM,EAAE,WAAW,oBAAoB,CAAC;AAS1E,SAAS,2BAA2B,MAAc,OAAuB;AAC9E,QAAM,QAAQ,MAAM,KAAK,EAAE,YAAY,EAAE,QAAQ,eAAe,GAAG,EAAE,QAAQ,UAAU,EAAE;AACzF,SAAO,mCAAmC,IAAI,IAAI,KAAK;AACzD;AAEA,eAAsB,kCACpB,SACA,SACc;AACd,MAAI,CAAC,QAAQ,OAAQ,QAAO,CAAC;AAC7B,QAAM,mBAAmB,QAAQ,OAAO,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAClE,QAAM,YAAY,yBAAyB,MAAM,eAAe,gBAAgB,CAAC;AACjF,QAAM,WAAW,OAAO,UAAU,eAAe,KAAK,8BAA8B,QAAQ,IAAI,IAC5F,6BAA6B,QAAQ,IAAI,IACzC,CAAC;AACL,QAAM,YAAY,QAAQ,IAAI,CAAC,UAAU;AACvC,UAAM,SAAS,SAAS,KAAK,CAAC,cAAc,UAAU,UAAU,MAAM,SAAS,UAAU,UAAU,MAAM,KAAK;AAC9G,UAAM,iBAAiB,QAAQ,SAAS,oBAAoB,qBAAqB,KAAK,MAAM,KAAK,IAAI;AACrG,UAAM,QAAQ,kBAAkB,MAAM,UAAU,IAAI,eAAe,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,KACtF,UAAU,yDAAyD,MAAM,OAAO;AAAA,MAC9E,MAAM,eAAe,CAAC;AAAA,MAAG,SAAS,eAAe,CAAC;AAAA,IACpD,CAAC,IACD,SAAS,UAAU,2BAA2B,QAAQ,MAAM,OAAO,KAAK,GAAG,MAAM,KAAK,IAAI,MAAM;AACpG,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACD,QAAM,EAAE,QAAQ,IAAI,4BAA4B;AAChD,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,kBAAkB,IAAI,IAAI,UAAU,IAAI,CAAC,UAAU,MAAM,cAAc,CAAC;AAC9E,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,kBAAkB,iBAAiB;AAC5C,UAAM,QAAQ,UAAU,OAAO,CAAC,UAAU,MAAM,mBAAmB,cAAc;AACjF,QAAI;AACF,YAAM,aAAa,MAAM,QAAQ,MAAM,IAAI,CAAC,EAAE,IAAI,MAAM,OAAO,EAAE,IAAI,MAAM,EAAE,GAAG;AAAA,QAC9E,YAAY;AAAA,QACZ,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,QAClB;AAAA,QACA,WAAW,QAAQ;AAAA,MACrB,CAAC;AACD,iBAAW,QAAQ,YAAY;AAC7B,YAAI,OAAO,KAAK,OAAO,YAAY,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,GAAG;AACtF,qBAAW,IAAI,KAAK,IAAI,KAAK,KAAK;AAAA,QACpC;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,0BAAoB,GAAG,YAAY,OAAO,EAAE,QAAQ,aAAa,MAAM,0CAA0C,CAAC;AAClH,aAAO,KAAK,8BAA8B,EAAE,MAAM,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,UAAU,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,OAAO,WAAW,IAAI,MAAM,EAAE,KAAK,MAAM,MAAM,EAAE;AAChG;",
6
+ "names": []
7
+ }
@@ -47,6 +47,7 @@ function mapInteractionRecordToTodoSummary(interaction) {
47
47
  todoId: interaction.id,
48
48
  todoSource: CUSTOMER_INTERACTION_TASK_SOURCE,
49
49
  createdAt: interaction.createdAt,
50
+ updatedAt: interaction.updatedAt,
50
51
  title: interaction.title ?? null,
51
52
  isDone: interaction.status === "done",
52
53
  status: interaction.status,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/customers/lib/interactionCompatibility.ts"],
4
- "sourcesContent": ["import type { InteractionSummary, ActivitySummary, TodoLinkSummary } from '../components/detail/types'\n\nexport const CUSTOMER_INTERACTION_ENTITY_ID = 'customers:customer_interaction'\nexport const CUSTOMER_INTERACTION_TASK_SOURCE = 'customers:interaction'\nexport const CUSTOMER_INTERACTION_TASK_TYPE = 'task'\nexport const CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE = 'adapter:activity'\nexport const CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE = 'adapter:todo'\nexport const EXAMPLE_TODO_SOURCE = 'example:todo'\n\nexport type InteractionRecord = InteractionSummary & {\n authorName?: string | null\n authorEmail?: string | null\n dealTitle?: string | null\n customValues?: Record<string, unknown> | null\n _integrations?: Record<string, unknown>\n}\n\nexport function isTaskInteractionType(value: string | null | undefined): boolean {\n return typeof value === 'string' && value.trim().toLowerCase() === CUSTOMER_INTERACTION_TASK_TYPE\n}\n\nexport function isAdapterActivitySource(value: string | null | undefined): boolean {\n return value === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE\n}\n\nexport function isAdapterTodoSource(value: string | null | undefined): boolean {\n return value === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE\n}\n\nexport function mapInteractionRecordToActivitySummary(interaction: InteractionRecord): ActivitySummary {\n return {\n id: interaction.id,\n activityType: interaction.interactionType,\n subject: interaction.title ?? null,\n body: interaction.body ?? null,\n occurredAt: interaction.occurredAt ?? interaction.scheduledAt ?? null,\n createdAt: interaction.createdAt,\n appearanceIcon: interaction.appearanceIcon ?? null,\n appearanceColor: interaction.appearanceColor ?? null,\n entityId: interaction.entityId ?? null,\n authorUserId: interaction.authorUserId ?? null,\n authorName: interaction.authorName ?? null,\n authorEmail: interaction.authorEmail ?? null,\n dealId: interaction.dealId ?? null,\n dealTitle: interaction.dealTitle ?? null,\n customValues: interaction.customValues ?? null,\n }\n}\n\nexport function mapInteractionRecordToTodoSummary(interaction: InteractionRecord): TodoLinkSummary {\n const customValues: Record<string, unknown> = { ...(interaction.customValues ?? {}) }\n const externalHref = resolveExampleIntegrationHref(interaction)\n if (interaction.priority !== undefined) customValues.priority = interaction.priority\n if (interaction.body !== undefined && customValues.description === undefined) {\n customValues.description = interaction.body ?? null\n }\n if (interaction.scheduledAt !== undefined && customValues.due_at === undefined) {\n customValues.due_at = interaction.scheduledAt ?? null\n }\n\n return {\n id: interaction.id,\n todoId: interaction.id,\n todoSource: CUSTOMER_INTERACTION_TASK_SOURCE,\n createdAt: interaction.createdAt,\n title: interaction.title ?? null,\n isDone: interaction.status === 'done',\n status: interaction.status,\n priority: interaction.priority ?? null,\n severity:\n typeof customValues.severity === 'string' && customValues.severity.trim().length\n ? customValues.severity.trim()\n : null,\n description: interaction.body ?? null,\n dueAt: interaction.scheduledAt ?? null,\n todoOrganizationId: null,\n customValues: Object.keys(customValues).length > 0 ? customValues : null,\n externalHref,\n }\n}\n\ntype IntegrationCarrier = {\n _integrations?: {\n example?: { href?: string | null; syncStatus?: string | null; [key: string]: unknown }\n [key: string]: unknown\n }\n}\n\nexport function resolveExampleIntegrationHref(item: IntegrationCarrier): string | null {\n const example = item._integrations?.example\n if (!example || typeof example !== 'object') return null\n return typeof example.href === 'string' && example.href.trim().length > 0 ? example.href : null\n}\n"],
5
- "mappings": "AAEO,MAAM,iCAAiC;AACvC,MAAM,mCAAmC;AACzC,MAAM,iCAAiC;AACvC,MAAM,+CAA+C;AACrD,MAAM,2CAA2C;AACjD,MAAM,sBAAsB;AAU5B,SAAS,sBAAsB,OAA2C;AAC/E,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,YAAY,MAAM;AACrE;AAEO,SAAS,wBAAwB,OAA2C;AACjF,SAAO,UAAU;AACnB;AAEO,SAAS,oBAAoB,OAA2C;AAC7E,SAAO,UAAU;AACnB;AAEO,SAAS,sCAAsC,aAAiD;AACrG,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,cAAc,YAAY;AAAA,IAC1B,SAAS,YAAY,SAAS;AAAA,IAC9B,MAAM,YAAY,QAAQ;AAAA,IAC1B,YAAY,YAAY,cAAc,YAAY,eAAe;AAAA,IACjE,WAAW,YAAY;AAAA,IACvB,gBAAgB,YAAY,kBAAkB;AAAA,IAC9C,iBAAiB,YAAY,mBAAmB;AAAA,IAChD,UAAU,YAAY,YAAY;AAAA,IAClC,cAAc,YAAY,gBAAgB;AAAA,IAC1C,YAAY,YAAY,cAAc;AAAA,IACtC,aAAa,YAAY,eAAe;AAAA,IACxC,QAAQ,YAAY,UAAU;AAAA,IAC9B,WAAW,YAAY,aAAa;AAAA,IACpC,cAAc,YAAY,gBAAgB;AAAA,EAC5C;AACF;AAEO,SAAS,kCAAkC,aAAiD;AACjG,QAAM,eAAwC,EAAE,GAAI,YAAY,gBAAgB,CAAC,EAAG;AACpF,QAAM,eAAe,8BAA8B,WAAW;AAC9D,MAAI,YAAY,aAAa,OAAW,cAAa,WAAW,YAAY;AAC5E,MAAI,YAAY,SAAS,UAAa,aAAa,gBAAgB,QAAW;AAC5E,iBAAa,cAAc,YAAY,QAAQ;AAAA,EACjD;AACA,MAAI,YAAY,gBAAgB,UAAa,aAAa,WAAW,QAAW;AAC9E,iBAAa,SAAS,YAAY,eAAe;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,QAAQ,YAAY;AAAA,IACpB,YAAY;AAAA,IACZ,WAAW,YAAY;AAAA,IACvB,OAAO,YAAY,SAAS;AAAA,IAC5B,QAAQ,YAAY,WAAW;AAAA,IAC/B,QAAQ,YAAY;AAAA,IACpB,UAAU,YAAY,YAAY;AAAA,IAClC,UACE,OAAO,aAAa,aAAa,YAAY,aAAa,SAAS,KAAK,EAAE,SACtE,aAAa,SAAS,KAAK,IAC3B;AAAA,IACN,aAAa,YAAY,QAAQ;AAAA,IACjC,OAAO,YAAY,eAAe;AAAA,IAClC,oBAAoB;AAAA,IACpB,cAAc,OAAO,KAAK,YAAY,EAAE,SAAS,IAAI,eAAe;AAAA,IACpE;AAAA,EACF;AACF;AASO,SAAS,8BAA8B,MAAyC;AACrF,QAAM,UAAU,KAAK,eAAe;AACpC,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,SAAO,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ,OAAO;AAC7F;",
4
+ "sourcesContent": ["import type { InteractionSummary, ActivitySummary, TodoLinkSummary } from '../components/detail/types'\n\nexport const CUSTOMER_INTERACTION_ENTITY_ID = 'customers:customer_interaction'\nexport const CUSTOMER_INTERACTION_TASK_SOURCE = 'customers:interaction'\nexport const CUSTOMER_INTERACTION_TASK_TYPE = 'task'\nexport const CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE = 'adapter:activity'\nexport const CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE = 'adapter:todo'\nexport const EXAMPLE_TODO_SOURCE = 'example:todo'\n\nexport type InteractionRecord = InteractionSummary & {\n authorName?: string | null\n authorEmail?: string | null\n dealTitle?: string | null\n customValues?: Record<string, unknown> | null\n _integrations?: Record<string, unknown>\n}\n\nexport function isTaskInteractionType(value: string | null | undefined): boolean {\n return typeof value === 'string' && value.trim().toLowerCase() === CUSTOMER_INTERACTION_TASK_TYPE\n}\n\nexport function isAdapterActivitySource(value: string | null | undefined): boolean {\n return value === CUSTOMER_INTERACTION_ACTIVITY_ADAPTER_SOURCE\n}\n\nexport function isAdapterTodoSource(value: string | null | undefined): boolean {\n return value === CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE\n}\n\nexport function mapInteractionRecordToActivitySummary(interaction: InteractionRecord): ActivitySummary {\n return {\n id: interaction.id,\n activityType: interaction.interactionType,\n subject: interaction.title ?? null,\n body: interaction.body ?? null,\n occurredAt: interaction.occurredAt ?? interaction.scheduledAt ?? null,\n createdAt: interaction.createdAt,\n appearanceIcon: interaction.appearanceIcon ?? null,\n appearanceColor: interaction.appearanceColor ?? null,\n entityId: interaction.entityId ?? null,\n authorUserId: interaction.authorUserId ?? null,\n authorName: interaction.authorName ?? null,\n authorEmail: interaction.authorEmail ?? null,\n dealId: interaction.dealId ?? null,\n dealTitle: interaction.dealTitle ?? null,\n customValues: interaction.customValues ?? null,\n }\n}\n\nexport function mapInteractionRecordToTodoSummary(interaction: InteractionRecord): TodoLinkSummary {\n const customValues: Record<string, unknown> = { ...(interaction.customValues ?? {}) }\n const externalHref = resolveExampleIntegrationHref(interaction)\n if (interaction.priority !== undefined) customValues.priority = interaction.priority\n if (interaction.body !== undefined && customValues.description === undefined) {\n customValues.description = interaction.body ?? null\n }\n if (interaction.scheduledAt !== undefined && customValues.due_at === undefined) {\n customValues.due_at = interaction.scheduledAt ?? null\n }\n\n return {\n id: interaction.id,\n todoId: interaction.id,\n todoSource: CUSTOMER_INTERACTION_TASK_SOURCE,\n createdAt: interaction.createdAt,\n updatedAt: interaction.updatedAt,\n title: interaction.title ?? null,\n isDone: interaction.status === 'done',\n status: interaction.status,\n priority: interaction.priority ?? null,\n severity:\n typeof customValues.severity === 'string' && customValues.severity.trim().length\n ? customValues.severity.trim()\n : null,\n description: interaction.body ?? null,\n dueAt: interaction.scheduledAt ?? null,\n todoOrganizationId: null,\n customValues: Object.keys(customValues).length > 0 ? customValues : null,\n externalHref,\n }\n}\n\ntype IntegrationCarrier = {\n _integrations?: {\n example?: { href?: string | null; syncStatus?: string | null; [key: string]: unknown }\n [key: string]: unknown\n }\n}\n\nexport function resolveExampleIntegrationHref(item: IntegrationCarrier): string | null {\n const example = item._integrations?.example\n if (!example || typeof example !== 'object') return null\n return typeof example.href === 'string' && example.href.trim().length > 0 ? example.href : null\n}\n"],
5
+ "mappings": "AAEO,MAAM,iCAAiC;AACvC,MAAM,mCAAmC;AACzC,MAAM,iCAAiC;AACvC,MAAM,+CAA+C;AACrD,MAAM,2CAA2C;AACjD,MAAM,sBAAsB;AAU5B,SAAS,sBAAsB,OAA2C;AAC/E,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,YAAY,MAAM;AACrE;AAEO,SAAS,wBAAwB,OAA2C;AACjF,SAAO,UAAU;AACnB;AAEO,SAAS,oBAAoB,OAA2C;AAC7E,SAAO,UAAU;AACnB;AAEO,SAAS,sCAAsC,aAAiD;AACrG,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,cAAc,YAAY;AAAA,IAC1B,SAAS,YAAY,SAAS;AAAA,IAC9B,MAAM,YAAY,QAAQ;AAAA,IAC1B,YAAY,YAAY,cAAc,YAAY,eAAe;AAAA,IACjE,WAAW,YAAY;AAAA,IACvB,gBAAgB,YAAY,kBAAkB;AAAA,IAC9C,iBAAiB,YAAY,mBAAmB;AAAA,IAChD,UAAU,YAAY,YAAY;AAAA,IAClC,cAAc,YAAY,gBAAgB;AAAA,IAC1C,YAAY,YAAY,cAAc;AAAA,IACtC,aAAa,YAAY,eAAe;AAAA,IACxC,QAAQ,YAAY,UAAU;AAAA,IAC9B,WAAW,YAAY,aAAa;AAAA,IACpC,cAAc,YAAY,gBAAgB;AAAA,EAC5C;AACF;AAEO,SAAS,kCAAkC,aAAiD;AACjG,QAAM,eAAwC,EAAE,GAAI,YAAY,gBAAgB,CAAC,EAAG;AACpF,QAAM,eAAe,8BAA8B,WAAW;AAC9D,MAAI,YAAY,aAAa,OAAW,cAAa,WAAW,YAAY;AAC5E,MAAI,YAAY,SAAS,UAAa,aAAa,gBAAgB,QAAW;AAC5E,iBAAa,cAAc,YAAY,QAAQ;AAAA,EACjD;AACA,MAAI,YAAY,gBAAgB,UAAa,aAAa,WAAW,QAAW;AAC9E,iBAAa,SAAS,YAAY,eAAe;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,IAAI,YAAY;AAAA,IAChB,QAAQ,YAAY;AAAA,IACpB,YAAY;AAAA,IACZ,WAAW,YAAY;AAAA,IACvB,WAAW,YAAY;AAAA,IACvB,OAAO,YAAY,SAAS;AAAA,IAC5B,QAAQ,YAAY,WAAW;AAAA,IAC/B,QAAQ,YAAY;AAAA,IACpB,UAAU,YAAY,YAAY;AAAA,IAClC,UACE,OAAO,aAAa,aAAa,YAAY,aAAa,SAAS,KAAK,EAAE,SACtE,aAAa,SAAS,KAAK,IAC3B;AAAA,IACN,aAAa,YAAY,QAAQ;AAAA,IACjC,OAAO,YAAY,eAAe;AAAA,IAClC,oBAAoB;AAAA,IACpB,cAAc,OAAO,KAAK,YAAY,EAAE,SAAS,IAAI,eAAe;AAAA,IACpE;AAAA,EACF;AACF;AASO,SAAS,8BAA8B,MAAyC;AACrF,QAAM,UAAU,KAAK,eAAe;AACpC,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,SAAO,OAAO,QAAQ,SAAS,YAAY,QAAQ,KAAK,KAAK,EAAE,SAAS,IAAI,QAAQ,OAAO;AAC7F;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,9 @@
1
+ const translatableFields = {
2
+ "customers:customer_dictionary_entry": ["label"]
3
+ };
4
+ var translations_default = translatableFields;
5
+ export {
6
+ translations_default as default,
7
+ translatableFields
8
+ };
9
+ //# sourceMappingURL=translations.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/customers/translations.ts"],
4
+ "sourcesContent": ["export const translatableFields: Record<string, string[]> = {\n 'customers:customer_dictionary_entry': ['label'],\n}\n\nexport default translatableFields\n"],
5
+ "mappings": "AAAO,MAAM,qBAA+C;AAAA,EAC1D,uCAAuC,CAAC,OAAO;AACjD;AAEA,IAAO,uBAAQ;",
6
+ "names": []
7
+ }
@@ -5,6 +5,19 @@ const metadata = {
5
5
  description: "EU Deforestation Regulation compliance: product commodity mappings, supplier origin evidence, due diligence statements.",
6
6
  author: "Open Mercato Team",
7
7
  license: "MIT",
8
+ /**
9
+ * `catalog` is a HARD dependency, and saying so is the fix.
10
+ *
11
+ * `data/enrichers.ts` reads `E.catalog.catalog_product` at module scope, so with `catalog` disabled
12
+ * `E.catalog` is undefined and the read throws while the enricher registry is being imported — which takes
13
+ * `/api/auth/login` with it. An installation shaped as a CRM rather than a shop could not reach its own login
14
+ * screen, and the error named a property rather than a module.
15
+ *
16
+ * Declared rather than defended with optional chaining. This module exists to map PRODUCTS to deforestation
17
+ * compliance evidence, so without a catalogue it has nothing to work on at all — the honest answer is that it
18
+ * cannot be enabled, which the generator now says before anybody starts the app rather than after.
19
+ */
20
+ requires: ["catalog"],
8
21
  ejectable: true
9
22
  };
10
23
  import { features } from "./acl.js";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/eudr/index.ts"],
4
- "sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'eudr',\n title: 'EUDR Compliance',\n version: '0.1.0',\n description: 'EU Deforestation Regulation compliance: product commodity mappings, supplier origin evidence, due diligence statements.',\n author: 'Open Mercato Team',\n license: 'MIT',\n ejectable: true,\n}\n\nexport { features } from './acl'\n"],
5
- "mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AACb;AAEA,SAAS,gBAAgB;",
4
+ "sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'eudr',\n title: 'EUDR Compliance',\n version: '0.1.0',\n description: 'EU Deforestation Regulation compliance: product commodity mappings, supplier origin evidence, due diligence statements.',\n author: 'Open Mercato Team',\n license: 'MIT',\n /**\n * `catalog` is a HARD dependency, and saying so is the fix.\n *\n * `data/enrichers.ts` reads `E.catalog.catalog_product` at module scope, so with `catalog` disabled\n * `E.catalog` is undefined and the read throws while the enricher registry is being imported \u2014 which takes\n * `/api/auth/login` with it. An installation shaped as a CRM rather than a shop could not reach its own login\n * screen, and the error named a property rather than a module.\n *\n * Declared rather than defended with optional chaining. This module exists to map PRODUCTS to deforestation\n * compliance evidence, so without a catalogue it has nothing to work on at all \u2014 the honest answer is that it\n * cannot be enabled, which the generator now says before anybody starts the app rather than after.\n */\n requires: ['catalog'],\n ejectable: true,\n}\n\nexport { features } from './acl'\n"],
5
+ "mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaT,UAAU,CAAC,SAAS;AAAA,EACpB,WAAW;AACb;AAEA,SAAS,gBAAgB;",
6
6
  "names": []
7
7
  }
@@ -186,8 +186,9 @@ const documentUpdateFieldsSchema = z.object({
186
186
  currencyCode: currencyCodeSchema.optional(),
187
187
  // Order-only columns — SalesQuote declares none of them. Declared here
188
188
  // because the create schema declares them and a caller reusing its create
189
- // payload on an update otherwise lost them silently; `applyDocumentUpdate`
190
- // rejects each with a 400 on a quote rather than dropping it.
189
+ // payload on an update otherwise lost them silently. `applyDocumentUpdate`
190
+ // rejects them on a quote, except `totalsMode`, which is ignored to preserve
191
+ // quote-create compatibility without enabling external quote amounts.
191
192
  exchangeRate: z.union([z.null(), exchangeRateSchema]).optional(),
192
193
  paymentStatusEntryId: z.string().uuid().nullable().optional(),
193
194
  fulfillmentStatusEntryId: z.string().uuid().nullable().optional(),
@@ -4110,7 +4111,6 @@ const updateQuoteCommand = {
4110
4111
  },
4111
4112
  async execute(rawInput, ctx) {
4112
4113
  const parsed = documentUpdateSchema.parse(rawInput ?? {});
4113
- await assertAmountsModeUnsupportedOnQuote([parsed]);
4114
4114
  documentEditSchema.parse(rawInput ?? {});
4115
4115
  const em = ctx.container.resolve("em").fork();
4116
4116
  let quote;