@open-mercato/core 0.6.3-develop.3635.1.e4a05c16e8 → 0.6.3-develop.3653.1.b8558737ae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_settings/index.js +2 -0
- package/dist/generated/entities/customer_settings/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +1 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +332 -0
- package/dist/modules/customers/api/deals/aggregate/route.js.map +7 -0
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js +188 -0
- package/dist/modules/customers/api/deals/bulk-update-owner/route.js.map +7 -0
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js +188 -0
- package/dist/modules/customers/api/deals/bulk-update-stage/route.js.map +7 -0
- package/dist/modules/customers/api/deals/route.js +255 -122
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/settings/stuck-threshold/route.js +169 -0
- package/dist/modules/customers/api/settings/stuck-threshold/route.js.map +7 -0
- package/dist/modules/customers/backend/config/customers/deals/page.js +181 -0
- package/dist/modules/customers/backend/config/customers/deals/page.js.map +7 -0
- package/dist/modules/customers/backend/config/customers/deals/page.meta.js +38 -0
- package/dist/modules/customers/backend/config/customers/deals/page.meta.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/create/page.js +17 -6
- package/dist/modules/customers/backend/customers/deals/create/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +2 -0
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js +217 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js +335 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js +29 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js +160 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js +157 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js +114 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js +36 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ChipButton.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js +199 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js +71 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js +233 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js +126 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js +31 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js +389 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCard.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js +181 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js +199 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js +44 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js +70 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +278 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js +135 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js +83 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js +155 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js +318 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js +138 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +126 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js +71 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/constants.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +2330 -415
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +3 -3
- package/dist/modules/customers/commands/deals.js +6 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +48 -13
- package/dist/modules/customers/commands/pipeline-stages.js.map +3 -3
- package/dist/modules/customers/commands/settings.js +45 -5
- package/dist/modules/customers/commands/settings.js.map +2 -2
- package/dist/modules/customers/data/enrichers.js +130 -1
- package/dist/modules/customers/data/enrichers.js.map +2 -2
- package/dist/modules/customers/data/entities.js +4 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +29 -2
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/lib/bulkDeals.js +150 -0
- package/dist/modules/customers/lib/bulkDeals.js.map +7 -0
- package/dist/modules/customers/lib/kysely.js +12 -0
- package/dist/modules/customers/lib/kysely.js.map +7 -0
- package/dist/modules/customers/lib/stuckDeals.js +32 -0
- package/dist/modules/customers/lib/stuckDeals.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260513203311_customers.js +13 -0
- package/dist/modules/customers/migrations/Migration20260513203311_customers.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js +52 -0
- package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map +7 -0
- package/dist/modules/customers/workers/deals-bulk-update-owner.js +41 -0
- package/dist/modules/customers/workers/deals-bulk-update-owner.js.map +7 -0
- package/dist/modules/customers/workers/deals-bulk-update-stage.js +41 -0
- package/dist/modules/customers/workers/deals-bulk-update-stage.js.map +7 -0
- package/generated/entities/customer_settings/index.ts +1 -0
- package/generated/entity-fields-registry.ts +1 -0
- package/package.json +7 -7
- package/src/modules/customers/api/deals/aggregate/route.ts +438 -0
- package/src/modules/customers/api/deals/bulk-update-owner/route.ts +216 -0
- package/src/modules/customers/api/deals/bulk-update-stage/route.ts +228 -0
- package/src/modules/customers/api/deals/route.ts +330 -135
- package/src/modules/customers/api/settings/stuck-threshold/route.ts +195 -0
- package/src/modules/customers/backend/config/customers/deals/page.meta.ts +36 -0
- package/src/modules/customers/backend/config/customers/deals/page.tsx +205 -0
- package/src/modules/customers/backend/customers/deals/create/page.tsx +25 -6
- package/src/modules/customers/backend/customers/deals/page.tsx +2 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ActivityComposerDialog.tsx +277 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageDialog.tsx +425 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/AddStageLane.tsx +31 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/BulkActionsBar.tsx +171 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeOwnerDialog.tsx +196 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChangeStageDialog.tsx +138 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ChipButton.tsx +47 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CloseDateFilterPopover.tsx +232 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyBreakdownTable.tsx +110 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CurrencyFilterPopover.tsx +310 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/CustomizeViewDialog.tsx +169 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DashedTileButton.tsx +54 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DealCard.tsx +562 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/DealCardMenu.tsx +214 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/EntityFilterPopover.tsx +257 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/FilterBarRow.tsx +62 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/FilterPopoverShell.tsx +101 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +378 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/LaneCurrencyBreakdown.tsx +192 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/LaneResizeHandle.tsx +107 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/PipelineFilterPopover.tsx +196 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/QuickDealDialog.tsx +408 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/SortByPopover.tsx +164 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +171 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/ViewTabsRow.tsx +84 -0
- package/src/modules/customers/backend/customers/deals/pipeline/components/constants.ts +16 -0
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +2841 -550
- package/src/modules/customers/commands/deals.ts +19 -0
- package/src/modules/customers/commands/pipeline-stages.ts +68 -13
- package/src/modules/customers/commands/settings.ts +64 -5
- package/src/modules/customers/data/enrichers.ts +209 -2
- package/src/modules/customers/data/entities.ts +4 -1
- package/src/modules/customers/data/validators.ts +36 -2
- package/src/modules/customers/i18n/de.json +244 -0
- package/src/modules/customers/i18n/en.json +244 -0
- package/src/modules/customers/i18n/es.json +244 -0
- package/src/modules/customers/i18n/pl.json +244 -0
- package/src/modules/customers/lib/bulkDeals.ts +231 -0
- package/src/modules/customers/lib/kysely.ts +60 -0
- package/src/modules/customers/lib/stuckDeals.ts +88 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customers/migrations/Migration20260513203311_customers.ts +13 -0
- package/src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts +71 -0
- package/src/modules/customers/workers/deals-bulk-update-owner.ts +46 -0
- package/src/modules/customers/workers/deals-bulk-update-stage.ts +46 -0
|
@@ -94,7 +94,10 @@ const dealCreateSchema = scopedSchema.extend({
|
|
|
94
94
|
valueCurrency: z.string().min(3).max(3).optional(),
|
|
95
95
|
probability: z.number().min(0).max(100).optional(),
|
|
96
96
|
expectedCloseAt: z.coerce.date().optional(),
|
|
97
|
-
|
|
97
|
+
// Nullable: the bulk owner-update worker passes `null` to clear ownership.
|
|
98
|
+
// Without `.nullable()`, dealUpdateSchema.parse({ ownerUserId: null }) throws
|
|
99
|
+
// ZodError "expected string, received null" inside the queue worker (TC-CRM-069).
|
|
100
|
+
ownerUserId: uuid().optional().nullable(),
|
|
98
101
|
source: z.string().max(150).optional(),
|
|
99
102
|
closureOutcome: z.enum(["won", "lost"]).optional(),
|
|
100
103
|
lossReasonId: uuid().optional(),
|
|
@@ -105,6 +108,19 @@ const dealCreateSchema = scopedSchema.extend({
|
|
|
105
108
|
const dealUpdateSchema = z.object({
|
|
106
109
|
id: uuid()
|
|
107
110
|
}).merge(dealCreateSchema.partial());
|
|
111
|
+
const dealsBulkUpdateOwnerSchema = z.object({
|
|
112
|
+
ids: z.array(uuid()).min(1).max(1e4),
|
|
113
|
+
ownerUserId: uuid().nullable()
|
|
114
|
+
});
|
|
115
|
+
const dealsBulkUpdateStageSchema = z.object({
|
|
116
|
+
ids: z.array(uuid()).min(1).max(1e4),
|
|
117
|
+
pipelineStageId: uuid()
|
|
118
|
+
});
|
|
119
|
+
const dealsBulkUpdateResponseSchema = z.object({
|
|
120
|
+
ok: z.boolean(),
|
|
121
|
+
progressJobId: uuid().nullable(),
|
|
122
|
+
message: z.string()
|
|
123
|
+
});
|
|
108
124
|
const activityCreateSchema = scopedSchema.extend({
|
|
109
125
|
entityId: uuid(),
|
|
110
126
|
activityType: z.string().min(1).max(100),
|
|
@@ -183,7 +199,11 @@ const dictionaryKindEnum = z.string().trim().refine(
|
|
|
183
199
|
);
|
|
184
200
|
const dictionaryValueSchema = z.string().trim().min(1).max(150);
|
|
185
201
|
const dictionaryLabelSchema = z.string().trim().max(150);
|
|
186
|
-
const
|
|
202
|
+
const DICTIONARY_COLOR_TONES = ["success", "warning", "info", "error", "neutral", "brand", "pink"];
|
|
203
|
+
const dictionaryColorSchema = z.string().trim().regex(
|
|
204
|
+
new RegExp(`^(#[0-9a-fA-F]{6}|${DICTIONARY_COLOR_TONES.join("|")})$`),
|
|
205
|
+
"Color must be a six-digit hex code (e.g. #3366ff) or a semantic tone identifier"
|
|
206
|
+
);
|
|
187
207
|
const dictionaryIconSchema = z.string().trim().max(48);
|
|
188
208
|
const customerDictionaryEntryCreateSchema = scopedSchema.extend({
|
|
189
209
|
kind: dictionaryKindEnum,
|
|
@@ -368,6 +388,9 @@ const customerAddressFormatSchema = z.enum(["line_first", "street_first"]);
|
|
|
368
388
|
const customerSettingsUpsertSchema = scopedSchema.extend({
|
|
369
389
|
addressFormat: customerAddressFormatSchema
|
|
370
390
|
});
|
|
391
|
+
const customerStuckThresholdUpsertSchema = scopedSchema.extend({
|
|
392
|
+
stuckThresholdDays: z.number().int().min(1).max(365)
|
|
393
|
+
});
|
|
371
394
|
const pipelineCreateSchema = scopedSchema.extend({
|
|
372
395
|
name: z.string().trim().min(1).max(200),
|
|
373
396
|
isDefault: z.boolean().optional()
|
|
@@ -481,8 +504,12 @@ export {
|
|
|
481
504
|
customerDictionaryEntryUpdateSchema,
|
|
482
505
|
customerKindSettingsUpsertSchema,
|
|
483
506
|
customerSettingsUpsertSchema,
|
|
507
|
+
customerStuckThresholdUpsertSchema,
|
|
484
508
|
dealCreateSchema,
|
|
485
509
|
dealUpdateSchema,
|
|
510
|
+
dealsBulkUpdateOwnerSchema,
|
|
511
|
+
dealsBulkUpdateResponseSchema,
|
|
512
|
+
dealsBulkUpdateStageSchema,
|
|
486
513
|
entityRoleCreateSchema,
|
|
487
514
|
entityRoleDeleteSchema,
|
|
488
515
|
entityRoleUpdateSchema,
|
|
@@ -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'\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\nconst phoneSchema = z.string().trim().max(50).refine((val) => {\n return isValidPhoneNumber(val)\n}, { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional()\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 description: z.string().trim().max(4000).optional(),\n ownerUserId: uuid().optional(),\n primaryEmail: z\n .string()\n .trim()\n .email()\n .max(320)\n .optional(),\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: z.string().trim().url().max(300).optional(),\n twitterUrl: z.string().trim().url().max(300).optional(),\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 legalName: z.string().trim().max(200).optional(),\n brandName: z.string().trim().max(200).optional(),\n domain: z.string().trim().max(200).optional(),\n websiteUrl: z.string().trim().url().max(300).optional(),\n industry: z.string().trim().max(150).optional(),\n sizeBucket: z.string().trim().max(100).optional(),\n annualRevenue: z.coerce.number().min(0).optional(),\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(4000).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 ownerUserId: uuid().optional(),\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})\n\nexport const dealUpdateSchema = z\n .object({\n id: uuid(),\n })\n .merge(dealCreateSchema.partial())\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.number().optional(),\n longitude: z.coerce.number().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)\nconst dictionaryColorSchema = z\n .string()\n .trim()\n .regex(/^#([0-9a-fA-F]{6})$/, 'Color must be a valid six-digit hex code like #3366ff')\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\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\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 type: z.enum(['company', 'deal', 'offer']),\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 status: z.enum(interactionStatusValues).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.enum(interactionStatusValues).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 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 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).optional(),\n icon: z.string().trim().max(100).optional(),\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).optional(),\n icon: z.string().trim().max(100).optional(),\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'\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\nconst phoneSchema = z.string().trim().max(50).refine((val) => {\n return isValidPhoneNumber(val)\n}, { message: CUSTOMER_PHONE_INVALID_MESSAGE_KEY }).optional()\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 description: z.string().trim().max(4000).optional(),\n ownerUserId: uuid().optional(),\n primaryEmail: z\n .string()\n .trim()\n .email()\n .max(320)\n .optional(),\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: z.string().trim().url().max(300).optional(),\n twitterUrl: z.string().trim().url().max(300).optional(),\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 legalName: z.string().trim().max(200).optional(),\n brandName: z.string().trim().max(200).optional(),\n domain: z.string().trim().max(200).optional(),\n websiteUrl: z.string().trim().url().max(300).optional(),\n industry: z.string().trim().max(150).optional(),\n sizeBucket: z.string().trim().max(100).optional(),\n annualRevenue: z.coerce.number().min(0).optional(),\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(4000).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})\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.number().optional(),\n longitude: z.coerce.number().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\nexport const interactionStatusValues = ['planned', 'done', 'canceled'] as const\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 type: z.enum(['company', 'deal', 'offer']),\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 status: z.enum(interactionStatusValues).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.enum(interactionStatusValues).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 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 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).optional(),\n icon: z.string().trim().max(100).optional(),\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).optional(),\n icon: z.string().trim().max(100).optional(),\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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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { invalidateCrudCache } from "@open-mercato/shared/lib/crud/cache";
|
|
2
|
+
import { runWithCacheTenant } from "@open-mercato/cache";
|
|
3
|
+
import { createModuleQueue } from "@open-mercato/queue";
|
|
4
|
+
const CUSTOMERS_DEALS_BULK_UPDATE_STAGE_QUEUE = "customers-deals-bulk-update-stage";
|
|
5
|
+
const CUSTOMERS_DEALS_BULK_UPDATE_OWNER_QUEUE = "customers-deals-bulk-update-owner";
|
|
6
|
+
const queues = /* @__PURE__ */ new Map();
|
|
7
|
+
function getCustomersQueue(queueName) {
|
|
8
|
+
const existing = queues.get(queueName);
|
|
9
|
+
if (existing) return existing;
|
|
10
|
+
const concurrency = Math.max(
|
|
11
|
+
1,
|
|
12
|
+
Number.parseInt(process.env.CUSTOMERS_QUEUE_CONCURRENCY ?? "3", 10) || 3
|
|
13
|
+
);
|
|
14
|
+
const created = createModuleQueue(queueName, { concurrency });
|
|
15
|
+
queues.set(queueName, created);
|
|
16
|
+
return created;
|
|
17
|
+
}
|
|
18
|
+
class BulkDealsPreflightError extends Error {
|
|
19
|
+
constructor(code, message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "BulkDealsPreflightError";
|
|
22
|
+
this.code = code;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function verifyPipelineStageExists(em, stageId, scope) {
|
|
26
|
+
const rows = await em.getConnection().execute(
|
|
27
|
+
`SELECT id FROM customer_pipeline_stages
|
|
28
|
+
WHERE id = ?
|
|
29
|
+
AND tenant_id = ?
|
|
30
|
+
AND organization_id = ?
|
|
31
|
+
LIMIT 1`,
|
|
32
|
+
[stageId, scope.tenantId, scope.organizationId]
|
|
33
|
+
);
|
|
34
|
+
if (rows.length === 0) {
|
|
35
|
+
throw new BulkDealsPreflightError(
|
|
36
|
+
"pipeline_stage_not_found",
|
|
37
|
+
`Pipeline stage ${stageId} does not exist in this tenant`
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const BULK_CACHE_ALIASES = ["customers.deals"];
|
|
42
|
+
function buildCommandContext(scope, container) {
|
|
43
|
+
return {
|
|
44
|
+
container,
|
|
45
|
+
auth: null,
|
|
46
|
+
organizationScope: {
|
|
47
|
+
selectedId: scope.organizationId,
|
|
48
|
+
filterIds: [scope.organizationId],
|
|
49
|
+
allowedIds: [scope.organizationId],
|
|
50
|
+
tenantId: scope.tenantId
|
|
51
|
+
},
|
|
52
|
+
selectedOrganizationId: scope.organizationId,
|
|
53
|
+
organizationIds: [scope.organizationId]
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
async function runBulkDealUpdate(params) {
|
|
57
|
+
const { container, progressJobId, ids, scope, cacheSource, buildBody, logTag } = params;
|
|
58
|
+
const commandBus = container.resolve("commandBus");
|
|
59
|
+
const progressService = container.resolve("progressService");
|
|
60
|
+
const progressContext = {
|
|
61
|
+
tenantId: scope.tenantId,
|
|
62
|
+
organizationId: scope.organizationId,
|
|
63
|
+
userId: scope.userId
|
|
64
|
+
};
|
|
65
|
+
await progressService.startJob(progressJobId, progressContext);
|
|
66
|
+
await progressService.updateProgress(
|
|
67
|
+
progressJobId,
|
|
68
|
+
{ totalCount: ids.length, processedCount: 0 },
|
|
69
|
+
progressContext
|
|
70
|
+
);
|
|
71
|
+
const commandContext = buildCommandContext(scope, container);
|
|
72
|
+
const updatedIds = /* @__PURE__ */ new Set();
|
|
73
|
+
const failedItems = [];
|
|
74
|
+
let affectedCount = 0;
|
|
75
|
+
for (const [index, id] of ids.entries()) {
|
|
76
|
+
try {
|
|
77
|
+
await commandBus.execute(
|
|
78
|
+
"customers.deals.update",
|
|
79
|
+
{
|
|
80
|
+
input: buildBody(id),
|
|
81
|
+
ctx: commandContext,
|
|
82
|
+
skipCacheInvalidation: true
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
affectedCount += 1;
|
|
86
|
+
updatedIds.add(id);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
89
|
+
failedItems.push({ id, message });
|
|
90
|
+
console.warn(`[${logTag}] failed to update deal`, { jobId: progressJobId, id, error });
|
|
91
|
+
}
|
|
92
|
+
await progressService.updateProgress(
|
|
93
|
+
progressJobId,
|
|
94
|
+
{ totalCount: ids.length, processedCount: index + 1 },
|
|
95
|
+
progressContext
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
await runWithCacheTenant(scope.tenantId, async () => {
|
|
99
|
+
for (const id of updatedIds) {
|
|
100
|
+
await invalidateCrudCache(
|
|
101
|
+
container,
|
|
102
|
+
"customers.deal",
|
|
103
|
+
{ id, organizationId: scope.organizationId, tenantId: scope.tenantId },
|
|
104
|
+
scope.tenantId,
|
|
105
|
+
cacheSource,
|
|
106
|
+
BULK_CACHE_ALIASES
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
const summary = {
|
|
111
|
+
affectedCount,
|
|
112
|
+
failedCount: failedItems.length,
|
|
113
|
+
failedItems
|
|
114
|
+
};
|
|
115
|
+
await progressService.completeJob(progressJobId, { resultSummary: summary }, progressContext);
|
|
116
|
+
return summary;
|
|
117
|
+
}
|
|
118
|
+
async function bulkUpdateDealStageWithProgress(params) {
|
|
119
|
+
const em = params.container.resolve("em");
|
|
120
|
+
await verifyPipelineStageExists(em, params.pipelineStageId, params.scope);
|
|
121
|
+
return runBulkDealUpdate({
|
|
122
|
+
container: params.container,
|
|
123
|
+
progressJobId: params.progressJobId,
|
|
124
|
+
ids: params.ids,
|
|
125
|
+
scope: params.scope,
|
|
126
|
+
cacheSource: "bulk-update-stage:customers.deals",
|
|
127
|
+
logTag: "customers.deals.bulk-update-stage",
|
|
128
|
+
buildBody: (id) => ({ id, pipelineStageId: params.pipelineStageId })
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function bulkUpdateDealOwnerWithProgress(params) {
|
|
132
|
+
return runBulkDealUpdate({
|
|
133
|
+
container: params.container,
|
|
134
|
+
progressJobId: params.progressJobId,
|
|
135
|
+
ids: params.ids,
|
|
136
|
+
scope: params.scope,
|
|
137
|
+
cacheSource: "bulk-update-owner:customers.deals",
|
|
138
|
+
logTag: "customers.deals.bulk-update-owner",
|
|
139
|
+
buildBody: (id) => ({ id, ownerUserId: params.ownerUserId })
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
BulkDealsPreflightError,
|
|
144
|
+
CUSTOMERS_DEALS_BULK_UPDATE_OWNER_QUEUE,
|
|
145
|
+
CUSTOMERS_DEALS_BULK_UPDATE_STAGE_QUEUE,
|
|
146
|
+
bulkUpdateDealOwnerWithProgress,
|
|
147
|
+
bulkUpdateDealStageWithProgress,
|
|
148
|
+
getCustomersQueue
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=bulkDeals.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/lib/bulkDeals.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { EntityManager as CoreEntityManager } from '@mikro-orm/core'\nimport type { CommandBus, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'\nimport { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'\nimport { runWithCacheTenant } from '@open-mercato/cache'\nimport { createModuleQueue, type Queue } from '@open-mercato/queue'\nimport type { ProgressService, ProgressServiceContext } from '../../progress/lib/progressService'\n\nexport const CUSTOMERS_DEALS_BULK_UPDATE_STAGE_QUEUE = 'customers-deals-bulk-update-stage'\nexport const CUSTOMERS_DEALS_BULK_UPDATE_OWNER_QUEUE = 'customers-deals-bulk-update-owner'\n\nconst queues = new Map<string, Queue<Record<string, unknown>>>()\n\nexport function getCustomersQueue(queueName: string): Queue<Record<string, unknown>> {\n const existing = queues.get(queueName)\n if (existing) return existing\n const concurrency = Math.max(\n 1,\n Number.parseInt(process.env.CUSTOMERS_QUEUE_CONCURRENCY ?? '3', 10) || 3,\n )\n const created = createModuleQueue<Record<string, unknown>>(queueName, { concurrency })\n queues.set(queueName, created)\n return created\n}\n\nexport type CustomersDealsBulkScope = {\n organizationId: string\n tenantId: string\n userId?: string | null\n}\n\nexport type CustomersDealsBulkUpdateStageJobPayload = {\n progressJobId: string\n ids: string[]\n pipelineStageId: string\n scope: CustomersDealsBulkScope\n}\n\nexport type CustomersDealsBulkUpdateOwnerJobPayload = {\n progressJobId: string\n ids: string[]\n ownerUserId: string | null\n scope: CustomersDealsBulkScope\n}\n\nexport type CustomersDealsBulkFailedItem = {\n id: string\n message: string\n}\n\nexport type CustomersDealsBulkSummary = {\n affectedCount: number\n failedCount: number\n failedItems: CustomersDealsBulkFailedItem[]\n}\n\nexport class BulkDealsPreflightError extends Error {\n readonly code: string\n constructor(code: string, message: string) {\n super(message)\n this.name = 'BulkDealsPreflightError'\n this.code = code\n }\n}\n\nasync function verifyPipelineStageExists(\n em: CoreEntityManager,\n stageId: string,\n scope: CustomersDealsBulkScope,\n): Promise<void> {\n // The `pipelineStageId` posted from the kanban is a `customer_pipeline_stages.id`\n // (the per-pipeline stage definition that `commands/deals.ts:loadPipelineStageSnapshot`\n // also reads). It is NOT a `customer_dictionary_entries.id` \u2014 those entries are a\n // per-tenant dictionary used to centralize stage colours/icons by normalized label.\n const rows = await em.getConnection().execute<Array<{ id: string }>>(\n `SELECT id FROM customer_pipeline_stages\n WHERE id = ?\n AND tenant_id = ?\n AND organization_id = ?\n LIMIT 1`,\n [stageId, scope.tenantId, scope.organizationId],\n )\n if (rows.length === 0) {\n throw new BulkDealsPreflightError(\n 'pipeline_stage_not_found',\n `Pipeline stage ${stageId} does not exist in this tenant`,\n )\n }\n}\n\nconst BULK_CACHE_ALIASES = ['customers.deals']\n\nfunction buildCommandContext(\n scope: CustomersDealsBulkScope,\n container: AwilixContainer,\n): CommandRuntimeContext {\n return {\n container,\n auth: null,\n organizationScope: {\n selectedId: scope.organizationId,\n filterIds: [scope.organizationId],\n allowedIds: [scope.organizationId],\n tenantId: scope.tenantId,\n },\n selectedOrganizationId: scope.organizationId,\n organizationIds: [scope.organizationId],\n }\n}\n\nasync function runBulkDealUpdate(params: {\n container: AwilixContainer\n progressJobId: string\n ids: string[]\n scope: CustomersDealsBulkScope\n cacheSource: string\n buildBody: (id: string) => Record<string, unknown>\n logTag: string\n}): Promise<CustomersDealsBulkSummary> {\n const { container, progressJobId, ids, scope, cacheSource, buildBody, logTag } = params\n const commandBus = container.resolve('commandBus') as CommandBus\n const progressService = container.resolve('progressService') as ProgressService\n const progressContext: ProgressServiceContext = {\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n userId: scope.userId,\n }\n\n await progressService.startJob(progressJobId, progressContext)\n await progressService.updateProgress(\n progressJobId,\n { totalCount: ids.length, processedCount: 0 },\n progressContext,\n )\n\n const commandContext = buildCommandContext(scope, container)\n const updatedIds = new Set<string>()\n const failedItems: CustomersDealsBulkFailedItem[] = []\n let affectedCount = 0\n\n for (const [index, id] of ids.entries()) {\n try {\n // `customers.deals.update` parses its input with `parseWithCustomFields(dealUpdateSchema, rawInput)`\n // and reads `parsed.id` at the top level (see commands/deals.ts). Wrapping the body in\n // `{ body: ... }` made `id` undefined and every per-deal call ZodError'd in the bulk\n // worker, so the job completed with affectedCount=0 in CI (TC-CRM-068/069).\n await commandBus.execute<Record<string, unknown>, { dealId: string }>(\n 'customers.deals.update',\n {\n input: buildBody(id),\n ctx: commandContext,\n skipCacheInvalidation: true,\n },\n )\n affectedCount += 1\n updatedIds.add(id)\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n failedItems.push({ id, message })\n console.warn(`[${logTag}] failed to update deal`, { jobId: progressJobId, id, error })\n }\n\n await progressService.updateProgress(\n progressJobId,\n { totalCount: ids.length, processedCount: index + 1 },\n progressContext,\n )\n }\n\n await runWithCacheTenant(scope.tenantId, async () => {\n for (const id of updatedIds) {\n await invalidateCrudCache(\n container,\n 'customers.deal',\n { id, organizationId: scope.organizationId, tenantId: scope.tenantId },\n scope.tenantId,\n cacheSource,\n BULK_CACHE_ALIASES,\n )\n }\n })\n\n const summary: CustomersDealsBulkSummary = {\n affectedCount,\n failedCount: failedItems.length,\n failedItems,\n }\n await progressService.completeJob(progressJobId, { resultSummary: summary }, progressContext)\n return summary\n}\n\nexport async function bulkUpdateDealStageWithProgress(params: {\n container: AwilixContainer\n progressJobId: string\n ids: string[]\n pipelineStageId: string\n scope: CustomersDealsBulkScope\n}): Promise<CustomersDealsBulkSummary> {\n // Pre-flight check: verify the target stage exists in the caller's tenant scope before\n // doing N per-deal command calls. An invalid stage would otherwise produce N identical\n // failures in `runBulkDealUpdate` and a noisy `failedItems` list.\n const em = params.container.resolve('em') as CoreEntityManager\n await verifyPipelineStageExists(em, params.pipelineStageId, params.scope)\n return runBulkDealUpdate({\n container: params.container,\n progressJobId: params.progressJobId,\n ids: params.ids,\n scope: params.scope,\n cacheSource: 'bulk-update-stage:customers.deals',\n logTag: 'customers.deals.bulk-update-stage',\n buildBody: (id) => ({ id, pipelineStageId: params.pipelineStageId }),\n })\n}\n\nexport async function bulkUpdateDealOwnerWithProgress(params: {\n container: AwilixContainer\n progressJobId: string\n ids: string[]\n ownerUserId: string | null\n scope: CustomersDealsBulkScope\n}): Promise<CustomersDealsBulkSummary> {\n return runBulkDealUpdate({\n container: params.container,\n progressJobId: params.progressJobId,\n ids: params.ids,\n scope: params.scope,\n cacheSource: 'bulk-update-owner:customers.deals',\n logTag: 'customers.deals.bulk-update-owner',\n buildBody: (id) => ({ id, ownerUserId: params.ownerUserId }),\n })\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function resolveKyselyClient(em) {
|
|
2
|
+
if (em == null || typeof em !== "object") return null;
|
|
3
|
+
const candidate = em.getKysely;
|
|
4
|
+
if (typeof candidate !== "function") return null;
|
|
5
|
+
const db = candidate.call(em);
|
|
6
|
+
if (db == null) return null;
|
|
7
|
+
return db;
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
resolveKyselyClient
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=kysely.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/lib/kysely.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Kysely } from 'kysely'\n\n/**\n * Narrow Kysely schema for the customers-module tables used by the kanban helpers\n * (`stuckDeals`, `enrichers`). Defining the schema locally keeps the queries strongly\n * typed without forcing a project-wide DB schema declaration. Add columns/tables here\n * when new customer-module queries need typed access.\n */\nexport interface CustomerKyselyDb {\n customer_settings: {\n organization_id: string\n tenant_id: string\n stuck_threshold_days: number | string | null\n }\n customer_deals: {\n id: string\n organization_id: string\n tenant_id: string\n deleted_at: Date | string | null\n created_at: Date | string | null\n }\n customer_deal_stage_transitions: {\n deal_id: string\n organization_id: string\n tenant_id: string\n deleted_at: Date | string | null\n transitioned_at: Date | string | null\n }\n customer_interactions: {\n deal_id: string | null\n organization_id: string\n tenant_id: string\n deleted_at: Date | string | null\n status: string | null\n }\n}\n\nexport type CustomerKysely = Kysely<CustomerKyselyDb>\n\n/**\n * Narrows an EntityManager-like value to a MikroORM v7 PG EntityManager and returns its\n * Kysely client, or `null` when the value doesn't expose `getKysely`.\n *\n * MikroORM v7's `@mikro-orm/postgresql` EntityManager ships `getKysely<TDb>()`, but the\n * shared `EnricherContext` types `em` as `unknown` to keep the contract DB-agnostic. The\n * kanban helpers (`stuckDeals`, `enrichers`) both need the typed client \u2014 this helper\n * centralizes the runtime check so neither call site has to repeat `(em as any).getKysely`.\n *\n * Returns `null` (rather than throwing) on purpose: callers fall back to a sensible default\n * (empty stuck-id list, un-enriched records) when the env doesn't have Kysely available\n * (e.g. unit tests with a stub EntityManager).\n */\nexport function resolveKyselyClient<TDb = CustomerKyselyDb>(em: unknown): Kysely<TDb> | null {\n if (em == null || typeof em !== 'object') return null\n const candidate = (em as { getKysely?: unknown }).getKysely\n if (typeof candidate !== 'function') return null\n const db = (candidate as () => unknown).call(em)\n if (db == null) return null\n return db as Kysely<TDb>\n}\n"],
|
|
5
|
+
"mappings": "AAoDO,SAAS,oBAA4C,IAAiC;AAC3F,MAAI,MAAM,QAAQ,OAAO,OAAO,SAAU,QAAO;AACjD,QAAM,YAAa,GAA+B;AAClD,MAAI,OAAO,cAAc,WAAY,QAAO;AAC5C,QAAM,KAAM,UAA4B,KAAK,EAAE;AAC/C,MAAI,MAAM,KAAM,QAAO;AACvB,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolveKyselyClient } from "./kysely.js";
|
|
2
|
+
const STUCK_DEFAULT_THRESHOLD_DAYS = 14;
|
|
3
|
+
const DAY_MS = 24 * 60 * 60 * 1e3;
|
|
4
|
+
async function fetchStuckThresholdDays(db, organizationId, tenantId) {
|
|
5
|
+
const row = await db.selectFrom("customer_settings").select(["stuck_threshold_days"]).where("organization_id", "=", organizationId).where("tenant_id", "=", tenantId).executeTakeFirst();
|
|
6
|
+
const raw = row?.stuck_threshold_days;
|
|
7
|
+
const value = typeof raw === "number" ? raw : typeof raw === "string" ? Number(raw) : null;
|
|
8
|
+
if (value !== null && Number.isFinite(value) && value > 0) return value;
|
|
9
|
+
return STUCK_DEFAULT_THRESHOLD_DAYS;
|
|
10
|
+
}
|
|
11
|
+
async function fetchStuckDealIds(em, organizationId, tenantId) {
|
|
12
|
+
const db = resolveKyselyClient(em);
|
|
13
|
+
if (!db) return [];
|
|
14
|
+
const threshold = await fetchStuckThresholdDays(db, organizationId, tenantId);
|
|
15
|
+
const cutoff = new Date(Date.now() - threshold * DAY_MS);
|
|
16
|
+
const oldTransitionRows = await db.selectFrom("customer_deal_stage_transitions").select(["deal_id"]).select((eb) => eb.fn.max("transitioned_at").as("last_transition")).where("organization_id", "=", organizationId).where("tenant_id", "=", tenantId).where("deleted_at", "is", null).groupBy("deal_id").having((eb) => eb(eb.fn.max("transitioned_at"), "<", cutoff)).execute();
|
|
17
|
+
const transitionedDealIds = await db.selectFrom("customer_deal_stage_transitions").select(["deal_id"]).distinct().where("organization_id", "=", organizationId).where("tenant_id", "=", tenantId).where("deleted_at", "is", null).execute();
|
|
18
|
+
const transitionedSet = new Set(transitionedDealIds.map((r) => r.deal_id));
|
|
19
|
+
const oldUntransitionedDeals = await db.selectFrom("customer_deals").select(["id"]).where("organization_id", "=", organizationId).where("tenant_id", "=", tenantId).where("deleted_at", "is", null).where("created_at", "<", cutoff).execute();
|
|
20
|
+
const result = /* @__PURE__ */ new Set();
|
|
21
|
+
oldTransitionRows.forEach((row) => result.add(row.deal_id));
|
|
22
|
+
oldUntransitionedDeals.forEach((row) => {
|
|
23
|
+
if (!transitionedSet.has(row.id)) result.add(row.id);
|
|
24
|
+
});
|
|
25
|
+
return Array.from(result);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
STUCK_DEFAULT_THRESHOLD_DAYS,
|
|
29
|
+
fetchStuckDealIds,
|
|
30
|
+
fetchStuckThresholdDays
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=stuckDeals.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/lib/stuckDeals.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CustomerKysely } from './kysely'\nimport { resolveKyselyClient } from './kysely'\n\n/**\n * Default number of days a deal can sit in a stage before it counts as \"stuck\".\n * Tenants can override by writing a row into `customer_settings.stuck_threshold_days`.\n */\nexport const STUCK_DEFAULT_THRESHOLD_DAYS = 14\nconst DAY_MS = 24 * 60 * 60 * 1000\n\n/**\n * Resolves the configured stuck-threshold for the tenant scope. Falls back to\n * `STUCK_DEFAULT_THRESHOLD_DAYS` when no setting row is present or the value is invalid.\n */\nexport async function fetchStuckThresholdDays(\n db: CustomerKysely,\n organizationId: string,\n tenantId: string,\n): Promise<number> {\n const row = await db\n .selectFrom('customer_settings')\n .select(['stuck_threshold_days'])\n .where('organization_id', '=', organizationId)\n .where('tenant_id', '=', tenantId)\n .executeTakeFirst()\n const raw = row?.stuck_threshold_days\n const value = typeof raw === 'number' ? raw : typeof raw === 'string' ? Number(raw) : null\n if (value !== null && Number.isFinite(value) && value > 0) return value\n return STUCK_DEFAULT_THRESHOLD_DAYS\n}\n\n/**\n * Returns the set of deal IDs (in scope) that are currently considered \"stuck\":\n * - deals whose last stage transition was earlier than (now - threshold), OR\n * - deals that never transitioned but were created earlier than (now - threshold).\n *\n * The list endpoint and the lane-aggregate endpoint MUST share this query so the kanban\n * lane headers, lane counts, and the rendered cards agree on which deals count as stuck.\n */\nexport async function fetchStuckDealIds(\n em: EntityManager,\n organizationId: string,\n tenantId: string,\n): Promise<string[]> {\n const db = resolveKyselyClient(em)\n if (!db) return []\n\n const threshold = await fetchStuckThresholdDays(db, organizationId, tenantId)\n const cutoff = new Date(Date.now() - threshold * DAY_MS)\n\n const oldTransitionRows = await db\n .selectFrom('customer_deal_stage_transitions')\n .select(['deal_id'])\n .select((eb) => eb.fn.max('transitioned_at').as('last_transition'))\n .where('organization_id', '=', organizationId)\n .where('tenant_id', '=', tenantId)\n .where('deleted_at', 'is', null)\n .groupBy('deal_id')\n .having((eb) => eb(eb.fn.max('transitioned_at'), '<', cutoff))\n .execute()\n\n const transitionedDealIds = await db\n .selectFrom('customer_deal_stage_transitions')\n .select(['deal_id'])\n .distinct()\n .where('organization_id', '=', organizationId)\n .where('tenant_id', '=', tenantId)\n .where('deleted_at', 'is', null)\n .execute()\n const transitionedSet = new Set(transitionedDealIds.map((r) => r.deal_id))\n\n const oldUntransitionedDeals = await db\n .selectFrom('customer_deals')\n .select(['id'])\n .where('organization_id', '=', organizationId)\n .where('tenant_id', '=', tenantId)\n .where('deleted_at', 'is', null)\n .where('created_at', '<', cutoff)\n .execute()\n\n const result = new Set<string>()\n oldTransitionRows.forEach((row) => result.add(row.deal_id))\n oldUntransitionedDeals.forEach((row) => {\n if (!transitionedSet.has(row.id)) result.add(row.id)\n })\n return Array.from(result)\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,2BAA2B;AAM7B,MAAM,+BAA+B;AAC5C,MAAM,SAAS,KAAK,KAAK,KAAK;AAM9B,eAAsB,wBACpB,IACA,gBACA,UACiB;AACjB,QAAM,MAAM,MAAM,GACf,WAAW,mBAAmB,EAC9B,OAAO,CAAC,sBAAsB,CAAC,EAC/B,MAAM,mBAAmB,KAAK,cAAc,EAC5C,MAAM,aAAa,KAAK,QAAQ,EAChC,iBAAiB;AACpB,QAAM,MAAM,KAAK;AACjB,QAAM,QAAQ,OAAO,QAAQ,WAAW,MAAM,OAAO,QAAQ,WAAW,OAAO,GAAG,IAAI;AACtF,MAAI,UAAU,QAAQ,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,QAAO;AAClE,SAAO;AACT;AAUA,eAAsB,kBACpB,IACA,gBACA,UACmB;AACnB,QAAM,KAAK,oBAAoB,EAAE;AACjC,MAAI,CAAC,GAAI,QAAO,CAAC;AAEjB,QAAM,YAAY,MAAM,wBAAwB,IAAI,gBAAgB,QAAQ;AAC5E,QAAM,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,YAAY,MAAM;AAEvD,QAAM,oBAAoB,MAAM,GAC7B,WAAW,iCAAiC,EAC5C,OAAO,CAAC,SAAS,CAAC,EAClB,OAAO,CAAC,OAAO,GAAG,GAAG,IAAI,iBAAiB,EAAE,GAAG,iBAAiB,CAAC,EACjE,MAAM,mBAAmB,KAAK,cAAc,EAC5C,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,cAAc,MAAM,IAAI,EAC9B,QAAQ,SAAS,EACjB,OAAO,CAAC,OAAO,GAAG,GAAG,GAAG,IAAI,iBAAiB,GAAG,KAAK,MAAM,CAAC,EAC5D,QAAQ;AAEX,QAAM,sBAAsB,MAAM,GAC/B,WAAW,iCAAiC,EAC5C,OAAO,CAAC,SAAS,CAAC,EAClB,SAAS,EACT,MAAM,mBAAmB,KAAK,cAAc,EAC5C,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,cAAc,MAAM,IAAI,EAC9B,QAAQ;AACX,QAAM,kBAAkB,IAAI,IAAI,oBAAoB,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AAEzE,QAAM,yBAAyB,MAAM,GAClC,WAAW,gBAAgB,EAC3B,OAAO,CAAC,IAAI,CAAC,EACb,MAAM,mBAAmB,KAAK,cAAc,EAC5C,MAAM,aAAa,KAAK,QAAQ,EAChC,MAAM,cAAc,MAAM,IAAI,EAC9B,MAAM,cAAc,KAAK,MAAM,EAC/B,QAAQ;AAEX,QAAM,SAAS,oBAAI,IAAY;AAC/B,oBAAkB,QAAQ,CAAC,QAAQ,OAAO,IAAI,IAAI,OAAO,CAAC;AAC1D,yBAAuB,QAAQ,CAAC,QAAQ;AACtC,QAAI,CAAC,gBAAgB,IAAI,IAAI,EAAE,EAAG,QAAO,IAAI,IAAI,EAAE;AAAA,EACrD,CAAC;AACD,SAAO,MAAM,KAAK,MAAM;AAC1B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260513203311_customers extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`alter table "customer_settings" add "stuck_threshold_days" int not null default 14;`);
|
|
5
|
+
}
|
|
6
|
+
down() {
|
|
7
|
+
this.addSql(`alter table "customer_settings" drop column "stuck_threshold_days";`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
Migration20260513203311_customers
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=Migration20260513203311_customers.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/migrations/Migration20260513203311_customers.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260513203311_customers extends Migration {\n\n override up(): void | Promise<void> {\n this.addSql(`alter table \"customer_settings\" add \"stuck_threshold_days\" int not null default 14;`);\n }\n\n override down(): void | Promise<void> {\n this.addSql(`alter table \"customer_settings\" drop column \"stuck_threshold_days\";`);\n }\n\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,0CAA0C,UAAU;AAAA,EAEtD,KAA2B;AAClC,SAAK,OAAO,qFAAqF;AAAA,EACnG;AAAA,EAES,OAA6B;AACpC,SAAK,OAAO,qEAAqE;AAAA,EACnF;AAEF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Migration } from "@mikro-orm/migrations";
|
|
2
|
+
class Migration20260519120000_pipeline_stage_color_tones extends Migration {
|
|
3
|
+
up() {
|
|
4
|
+
this.addSql(`
|
|
5
|
+
update "customer_dictionary_entries"
|
|
6
|
+
set "color" = case lower("color")
|
|
7
|
+
when '#16a34a' then 'success'
|
|
8
|
+
when '#22c55e' then 'success'
|
|
9
|
+
when '#15803d' then 'success'
|
|
10
|
+
when '#10b981' then 'success'
|
|
11
|
+
when '#059669' then 'success'
|
|
12
|
+
when '#f59e0b' then 'warning'
|
|
13
|
+
when '#eab308' then 'warning'
|
|
14
|
+
when '#d97706' then 'warning'
|
|
15
|
+
when '#f97316' then 'warning'
|
|
16
|
+
when '#ea580c' then 'warning'
|
|
17
|
+
when '#dc2626' then 'error'
|
|
18
|
+
when '#ef4444' then 'error'
|
|
19
|
+
when '#b91c1c' then 'error'
|
|
20
|
+
when '#991b1b' then 'error'
|
|
21
|
+
when '#2563eb' then 'info'
|
|
22
|
+
when '#3b82f6' then 'info'
|
|
23
|
+
when '#0ea5e9' then 'info'
|
|
24
|
+
when '#1d4ed8' then 'info'
|
|
25
|
+
when '#6366f1' then 'info'
|
|
26
|
+
when '#6b7280' then 'neutral'
|
|
27
|
+
when '#9ca3af' then 'neutral'
|
|
28
|
+
when '#4b5563' then 'neutral'
|
|
29
|
+
when '#374151' then 'neutral'
|
|
30
|
+
when '#1f2937' then 'neutral'
|
|
31
|
+
when '#7c3aed' then 'brand'
|
|
32
|
+
when '#8b5cf6' then 'brand'
|
|
33
|
+
when '#a855f7' then 'brand'
|
|
34
|
+
when '#9333ea' then 'brand'
|
|
35
|
+
when '#ec4899' then 'pink'
|
|
36
|
+
when '#f472b6' then 'pink'
|
|
37
|
+
when '#db2777' then 'pink'
|
|
38
|
+
when '#be185d' then 'pink'
|
|
39
|
+
when '' then ''
|
|
40
|
+
else 'neutral'
|
|
41
|
+
end
|
|
42
|
+
where "kind" = 'pipeline_stage'
|
|
43
|
+
and "color" is not null;
|
|
44
|
+
`);
|
|
45
|
+
}
|
|
46
|
+
down() {
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
Migration20260519120000_pipeline_stage_color_tones
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=Migration20260519120000_pipeline_stage_color_tones.js.map
|
package/dist/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.js.map
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/customers/migrations/Migration20260519120000_pipeline_stage_color_tones.ts"],
|
|
4
|
+
"sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\n/**\n * Migrate `customer_dictionary_entries.color` for `kind = 'pipeline_stage'` rows from the\n * legacy hex chip values stored by AddStageDialog to canonical semantic tone identifiers\n * matching Lane.tsx's `ACCENT_TONE_CLASS` map.\n *\n * Before this migration:\n * AddStageDialog stored a hex value like '#16a34a' / '#f59e0b' / '#dc2626' / '#2563eb' /\n * '#6b7280' / '#7c3aed', and Lane.tsx implicitly fell through to gray on every other hex\n * because no explicit hex\u2192tone map existed at render time.\n *\n * After this migration:\n * `color` stores one of: 'success', 'warning', 'info', 'error', 'neutral', 'brand',\n * 'pink', '', or NULL. Lane.tsx now reads the value directly as a tone identifier.\n *\n * Unknown / unmappable hex values collapse to 'neutral'. Forward-only \u2014 reverting tones to\n * the original hex is lossy and not supported. See `.ai/specs/2026-05-19-customers-deals-kanban-ux-review-fixes.md`.\n */\nexport class Migration20260519120000_pipeline_stage_color_tones extends Migration {\n override up(): void | Promise<void> {\n this.addSql(`\n update \"customer_dictionary_entries\"\n set \"color\" = case lower(\"color\")\n when '#16a34a' then 'success'\n when '#22c55e' then 'success'\n when '#15803d' then 'success'\n when '#10b981' then 'success'\n when '#059669' then 'success'\n when '#f59e0b' then 'warning'\n when '#eab308' then 'warning'\n when '#d97706' then 'warning'\n when '#f97316' then 'warning'\n when '#ea580c' then 'warning'\n when '#dc2626' then 'error'\n when '#ef4444' then 'error'\n when '#b91c1c' then 'error'\n when '#991b1b' then 'error'\n when '#2563eb' then 'info'\n when '#3b82f6' then 'info'\n when '#0ea5e9' then 'info'\n when '#1d4ed8' then 'info'\n when '#6366f1' then 'info'\n when '#6b7280' then 'neutral'\n when '#9ca3af' then 'neutral'\n when '#4b5563' then 'neutral'\n when '#374151' then 'neutral'\n when '#1f2937' then 'neutral'\n when '#7c3aed' then 'brand'\n when '#8b5cf6' then 'brand'\n when '#a855f7' then 'brand'\n when '#9333ea' then 'brand'\n when '#ec4899' then 'pink'\n when '#f472b6' then 'pink'\n when '#db2777' then 'pink'\n when '#be185d' then 'pink'\n when '' then ''\n else 'neutral'\n end\n where \"kind\" = 'pipeline_stage'\n and \"color\" is not null;\n `);\n }\n\n override down(): void | Promise<void> {\n // Forward-only migration. Reverting tone identifiers to their original hex values is\n // lossy (we only kept the closest tone, not the source hex) and would not restore the\n // pre-migration state. Operators wanting to change a stage color should reopen the\n // AddStageDialog tone picker.\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,iBAAiB;AAmBnB,MAAM,2DAA2D,UAAU;AAAA,EACvE,KAA2B;AAClC,SAAK,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAwCX;AAAA,EACH;AAAA,EAES,OAA6B;AAAA,EAKtC;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|