@open-mercato/core 0.5.1-develop.2663.2c29774b5b → 0.5.1-develop.2681.c559bb2bc3
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/action_log/index.js +8 -0
- package/dist/generated/entities/action_log/index.js.map +2 -2
- package/dist/generated/entities/customer_company_billing/index.js +23 -0
- package/dist/generated/entities/customer_company_billing/index.js.map +7 -0
- package/dist/generated/entities/customer_deal/index.js +8 -0
- package/dist/generated/entities/customer_deal/index.js.map +2 -2
- package/dist/generated/entities/customer_deal_stage_transition/index.js +31 -0
- package/dist/generated/entities/customer_deal_stage_transition/index.js.map +7 -0
- package/dist/generated/entities/customer_dictionary_kind_setting/index.js +21 -0
- package/dist/generated/entities/customer_dictionary_kind_setting/index.js.map +7 -0
- package/dist/generated/entities/customer_entity/index.js +8 -0
- package/dist/generated/entities/customer_entity/index.js.map +2 -2
- package/dist/generated/entities/customer_entity_role/index.js +23 -0
- package/dist/generated/entities/customer_entity_role/index.js.map +7 -0
- package/dist/generated/entities/customer_interaction/index.js +23 -1
- package/dist/generated/entities/customer_interaction/index.js.map +2 -2
- package/dist/generated/entities/customer_label/index.js +19 -0
- package/dist/generated/entities/customer_label/index.js.map +7 -0
- package/dist/generated/entities/customer_label_assignment/index.js +17 -0
- package/dist/generated/entities/customer_label_assignment/index.js.map +7 -0
- package/dist/generated/entities/customer_person_company_link/index.js +21 -0
- package/dist/generated/entities/customer_person_company_link/index.js.map +7 -0
- package/dist/generated/entities/customer_person_company_role/index.js +17 -0
- package/dist/generated/entities/customer_person_company_role/index.js.map +7 -0
- package/dist/generated/entities/dictionary_entry/index.js +4 -0
- package/dist/generated/entities/dictionary_entry/index.js.map +2 -2
- package/dist/generated/entities.ids.generated.js +9 -1
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +116 -1
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/attachments/api/route.js +46 -8
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js +208 -0
- package/dist/modules/audit_logs/api/audit-logs/actions/export/route.js.map +7 -0
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js +52 -6
- package/dist/modules/audit_logs/api/audit-logs/actions/route.js.map +2 -2
- package/dist/modules/audit_logs/cli.js +62 -0
- package/dist/modules/audit_logs/cli.js.map +7 -0
- package/dist/modules/audit_logs/data/entities.js +21 -1
- package/dist/modules/audit_logs/data/entities.js.map +2 -2
- package/dist/modules/audit_logs/data/validators.js +9 -1
- package/dist/modules/audit_logs/data/validators.js.map +2 -2
- package/dist/modules/audit_logs/lib/changeRows.js +34 -0
- package/dist/modules/audit_logs/lib/changeRows.js.map +7 -0
- package/dist/modules/audit_logs/lib/display-helpers.js +2 -20
- package/dist/modules/audit_logs/lib/display-helpers.js.map +3 -3
- package/dist/modules/audit_logs/lib/projections.js +58 -0
- package/dist/modules/audit_logs/lib/projections.js.map +7 -0
- package/dist/modules/audit_logs/migrations/Migration20260412160533.js +21 -0
- package/dist/modules/audit_logs/migrations/Migration20260412160533.js.map +7 -0
- package/dist/modules/audit_logs/services/actionLogService.js +313 -79
- package/dist/modules/audit_logs/services/actionLogService.js.map +2 -2
- package/dist/modules/customers/acl.js +3 -1
- package/dist/modules/customers/acl.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +4 -0
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/assignable-staff/route.js +208 -0
- package/dist/modules/customers/api/assignable-staff/route.js.map +7 -0
- package/dist/modules/customers/api/companies/[id]/people/route.js +205 -0
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +7 -0
- package/dist/modules/customers/api/companies/[id]/roles/route.js +22 -0
- package/dist/modules/customers/api/companies/[id]/roles/route.js.map +7 -0
- package/dist/modules/customers/api/companies/[id]/route.js +374 -32
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/companies/route.js +82 -7
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +172 -0
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +7 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js +156 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +7 -0
- package/dist/modules/customers/api/deals/[id]/route.js +459 -53
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +195 -0
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +7 -0
- package/dist/modules/customers/api/deals/route.js +20 -10
- package/dist/modules/customers/api/deals/route.js.map +3 -3
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +105 -4
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/route.js +118 -42
- package/dist/modules/customers/api/dictionaries/[kind]/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/context.js +30 -6
- package/dist/modules/customers/api/dictionaries/context.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js +207 -0
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +7 -0
- package/dist/modules/customers/api/entity-roles-factory.js +471 -0
- package/dist/modules/customers/api/entity-roles-factory.js.map +7 -0
- package/dist/modules/customers/api/interactions/conflicts/route.js +158 -0
- package/dist/modules/customers/api/interactions/conflicts/route.js.map +7 -0
- package/dist/modules/customers/api/interactions/counts/route.js +92 -0
- package/dist/modules/customers/api/interactions/counts/route.js.map +7 -0
- package/dist/modules/customers/api/interactions/route.js +83 -4
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/labels/assign/route.js +189 -0
- package/dist/modules/customers/api/labels/assign/route.js.map +7 -0
- package/dist/modules/customers/api/labels/auth.js +17 -0
- package/dist/modules/customers/api/labels/auth.js.map +7 -0
- package/dist/modules/customers/api/labels/route.js +281 -0
- package/dist/modules/customers/api/labels/route.js.map +7 -0
- package/dist/modules/customers/api/labels/table-errors.js +38 -0
- package/dist/modules/customers/api/labels/table-errors.js.map +7 -0
- package/dist/modules/customers/api/labels/unassign/route.js +184 -0
- package/dist/modules/customers/api/labels/unassign/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +292 -0
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/companies/context.js +66 -0
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +334 -0
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/companies/route.js +205 -0
- package/dist/modules/customers/api/people/[id]/companies/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/roles/route.js +22 -0
- package/dist/modules/customers/api/people/[id]/roles/route.js.map +7 -0
- package/dist/modules/customers/api/people/[id]/route.js +134 -21
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +122 -23
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +4 -0
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/api/utils.js +22 -0
- package/dist/modules/customers/api/utils.js.map +2 -2
- package/dist/modules/customers/backend/config/customers/page.js +2 -6
- package/dist/modules/customers/backend/config/customers/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +37 -26
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +265 -262
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +3 -3
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js +23 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/formatters.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js +1 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/types.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +43 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js +264 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js +88 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +41 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js +66 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js +39 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js +49 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js +43 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js +28 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +556 -503
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +3 -3
- package/dist/modules/customers/backend/customers/deals/page.js +66 -21
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/page.js +36 -28
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +318 -203
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +3 -3
- package/dist/modules/customers/cli.js +105 -13
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/commands/activities.js +6 -0
- package/dist/modules/customers/commands/activities.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +315 -107
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/dictionaries.js +166 -32
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/dictionaryKindSettings.js +208 -0
- package/dist/modules/customers/commands/dictionaryKindSettings.js.map +7 -0
- package/dist/modules/customers/commands/entity-roles.js +415 -0
- package/dist/modules/customers/commands/entity-roles.js.map +7 -0
- package/dist/modules/customers/commands/index.js +4 -0
- package/dist/modules/customers/commands/index.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +108 -21
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/labels.js +539 -0
- package/dist/modules/customers/commands/labels.js.map +7 -0
- package/dist/modules/customers/commands/people.js +560 -463
- package/dist/modules/customers/commands/people.js.map +3 -3
- package/dist/modules/customers/commands/personCompanyLinks.js +568 -0
- package/dist/modules/customers/commands/personCompanyLinks.js.map +7 -0
- package/dist/modules/customers/commands/shared.js +12 -4
- package/dist/modules/customers/commands/shared.js.map +2 -2
- package/dist/modules/customers/commands/todos.js +10 -1
- package/dist/modules/customers/commands/todos.js.map +2 -2
- package/dist/modules/customers/components/AddressEditor.js +1 -1
- package/dist/modules/customers/components/AddressEditor.js.map +2 -2
- package/dist/modules/customers/components/CustomersConfigurationSections.js +31 -0
- package/dist/modules/customers/components/CustomersConfigurationSections.js.map +7 -0
- package/dist/modules/customers/components/DictionarySettings.js +37 -2
- package/dist/modules/customers/components/DictionarySettings.js.map +2 -2
- package/dist/modules/customers/components/detail/ActiveDealCard.js +121 -0
- package/dist/modules/customers/components/detail/ActiveDealCard.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivitiesSection.js +222 -331
- package/dist/modules/customers/components/detail/ActivitiesSection.js.map +3 -3
- package/dist/modules/customers/components/detail/ActivityAiActions.js +36 -0
- package/dist/modules/customers/components/detail/ActivityAiActions.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityCard.js +126 -0
- package/dist/modules/customers/components/detail/ActivityCard.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityHistorySection.js +340 -0
- package/dist/modules/customers/components/detail/ActivityHistorySection.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityLogTab.js +56 -0
- package/dist/modules/customers/components/detail/ActivityLogTab.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityTimeline.js +108 -0
- package/dist/modules/customers/components/detail/ActivityTimeline.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js +139 -0
- package/dist/modules/customers/components/detail/ActivityTimelineFilters.js.map +7 -0
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js +42 -0
- package/dist/modules/customers/components/detail/ActivityTypeSelector.js.map +7 -0
- package/dist/modules/customers/components/detail/AiActionChips.js +38 -0
- package/dist/modules/customers/components/detail/AiActionChips.js.map +7 -0
- package/dist/modules/customers/components/detail/AssignRoleDialog.js +534 -0
- package/dist/modules/customers/components/detail/AssignRoleDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js +79 -0
- package/dist/modules/customers/components/detail/ChangelogEntryRow.js.map +7 -0
- package/dist/modules/customers/components/detail/ChangelogFilters.js +176 -0
- package/dist/modules/customers/components/detail/ChangelogFilters.js.map +7 -0
- package/dist/modules/customers/components/detail/ChangelogKpiCards.js +88 -0
- package/dist/modules/customers/components/detail/ChangelogKpiCards.js.map +7 -0
- package/dist/modules/customers/components/detail/ChangelogTab.js +470 -0
- package/dist/modules/customers/components/detail/ChangelogTab.js.map +7 -0
- package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js +16 -0
- package/dist/modules/customers/components/detail/ComingSoonPlaceholder.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyCard.js +283 -0
- package/dist/modules/customers/components/detail/CompanyCard.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyDashboardTab.js +133 -0
- package/dist/modules/customers/components/detail/CompanyDashboardTab.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyDetailHeader.js +191 -0
- package/dist/modules/customers/components/detail/CompanyDetailHeader.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +123 -0
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +174 -0
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +7 -0
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +514 -230
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyTagsDialog.js +22 -0
- package/dist/modules/customers/components/detail/CompanyTagsDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +159 -0
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/CreatePersonDialog.js +135 -0
- package/dist/modules/customers/components/detail/CreatePersonDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/DealClosureActionBar.js +59 -0
- package/dist/modules/customers/components/detail/DealClosureActionBar.js.map +7 -0
- package/dist/modules/customers/components/detail/DealDetailHeader.js +237 -0
- package/dist/modules/customers/components/detail/DealDetailHeader.js.map +7 -0
- package/dist/modules/customers/components/detail/DealDetailTabs.js +109 -0
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +7 -0
- package/dist/modules/customers/components/detail/DealForm.js +219 -92
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js +295 -0
- package/dist/modules/customers/components/detail/DealLinkedEntitiesTab.js.map +7 -0
- package/dist/modules/customers/components/detail/DealLostSummaryDialog.js +107 -0
- package/dist/modules/customers/components/detail/DealLostSummaryDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/DealWonPopup.js +113 -0
- package/dist/modules/customers/components/detail/DealWonPopup.js.map +7 -0
- package/dist/modules/customers/components/detail/DealsSection.js +206 -193
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DecisionMakersFooter.js +39 -0
- package/dist/modules/customers/components/detail/DecisionMakersFooter.js.map +7 -0
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +1096 -0
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/InlineActivityComposer.js +197 -0
- package/dist/modules/customers/components/detail/InlineActivityComposer.js.map +7 -0
- package/dist/modules/customers/components/detail/ManageTagsDialog.js +1091 -0
- package/dist/modules/customers/components/detail/ManageTagsDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/MiniWeekCalendar.js +272 -0
- package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +7 -0
- package/dist/modules/customers/components/detail/MobilePersonDetail.js +106 -0
- package/dist/modules/customers/components/detail/MobilePersonDetail.js.map +7 -0
- package/dist/modules/customers/components/detail/NextStepCard.js +72 -0
- package/dist/modules/customers/components/detail/NextStepCard.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonCard.js +192 -0
- package/dist/modules/customers/components/detail/PersonCard.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +345 -0
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonDetailHeader.js +220 -0
- package/dist/modules/customers/components/detail/PersonDetailHeader.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +122 -0
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +7 -0
- package/dist/modules/customers/components/detail/PersonTagsDialog.js +24 -0
- package/dist/modules/customers/components/detail/PersonTagsDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/PipelineStepper.js +191 -0
- package/dist/modules/customers/components/detail/PipelineStepper.js.map +7 -0
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +222 -0
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +7 -0
- package/dist/modules/customers/components/detail/RelationshipHealthCard.js +49 -0
- package/dist/modules/customers/components/detail/RelationshipHealthCard.js.map +7 -0
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js +189 -0
- package/dist/modules/customers/components/detail/RoleAssignmentRow.js.map +7 -0
- package/dist/modules/customers/components/detail/RolesSection.js +234 -0
- package/dist/modules/customers/components/detail/RolesSection.js.map +7 -0
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +410 -0
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +7 -0
- package/dist/modules/customers/components/detail/aiActionCatalog.js +41 -0
- package/dist/modules/customers/components/detail/aiActionCatalog.js.map +7 -0
- package/dist/modules/customers/components/detail/assignableStaff.js +48 -0
- package/dist/modules/customers/components/detail/assignableStaff.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js +48 -0
- package/dist/modules/customers/components/detail/dashboard/ActiveDealWidget.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js +86 -0
- package/dist/modules/customers/components/detail/dashboard/OpenTasksWidget.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js +53 -0
- package/dist/modules/customers/components/detail/dashboard/RecentActivityWidget.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js +30 -0
- package/dist/modules/customers/components/detail/dashboard/RelationshipHealthWidget.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js +43 -0
- package/dist/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.js.map +7 -0
- package/dist/modules/customers/components/detail/dashboard/helpers.js +71 -0
- package/dist/modules/customers/components/detail/dashboard/helpers.js.map +7 -0
- package/dist/modules/customers/components/detail/healthScoreUtils.js +69 -0
- package/dist/modules/customers/components/detail/healthScoreUtils.js.map +7 -0
- package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js +5 -5
- package/dist/modules/customers/components/detail/hooks/useCurrencyDictionary.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js +9 -8
- package/dist/modules/customers/components/detail/hooks/useCustomerDictionary.js.map +3 -3
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js +65 -0
- package/dist/modules/customers/components/detail/hooks/useInteractionMutations.js.map +7 -0
- package/dist/modules/customers/components/detail/notesAdapter.js +70 -30
- package/dist/modules/customers/components/detail/notesAdapter.js.map +2 -2
- package/dist/modules/customers/components/detail/pipelineStageUtils.js +26 -0
- package/dist/modules/customers/components/detail/pipelineStageUtils.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js +144 -0
- package/dist/modules/customers/components/detail/schedule/DateTimeFields.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/FooterFields.js +60 -0
- package/dist/modules/customers/components/detail/schedule/FooterFields.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js +216 -0
- package/dist/modules/customers/components/detail/schedule/LinkedEntitiesField.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/LocationField.js +34 -0
- package/dist/modules/customers/components/detail/schedule/LocationField.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +226 -0
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js +69 -0
- package/dist/modules/customers/components/detail/schedule/fieldConfig.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/index.js +21 -0
- package/dist/modules/customers/components/detail/schedule/index.js.map +7 -0
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +172 -0
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +7 -0
- package/dist/modules/customers/components/detail/utils.js +23 -0
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/components/formConfig.js +144 -22
- package/dist/modules/customers/components/formConfig.js.map +2 -2
- package/dist/modules/customers/components/linking/LinkEntityDialog.js +661 -0
- package/dist/modules/customers/components/linking/LinkEntityDialog.js.map +7 -0
- package/dist/modules/customers/components/linking/adapters/companyAdapter.js +252 -0
- package/dist/modules/customers/components/linking/adapters/companyAdapter.js.map +7 -0
- package/dist/modules/customers/components/linking/adapters/dealAdapter.js +384 -0
- package/dist/modules/customers/components/linking/adapters/dealAdapter.js.map +7 -0
- package/dist/modules/customers/components/linking/adapters/personAdapter.js +324 -0
- package/dist/modules/customers/components/linking/adapters/personAdapter.js.map +7 -0
- package/dist/modules/customers/components/list/CollectionPreviewCell.js +53 -0
- package/dist/modules/customers/components/list/CollectionPreviewCell.js.map +7 -0
- package/dist/modules/customers/data/entities.js +407 -1
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +139 -21
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/events.js +19 -1
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/customerRoleTypes.js +19 -0
- package/dist/modules/customers/lib/customerRoleTypes.js.map +7 -0
- package/dist/modules/customers/lib/dealClosureNotification.js +39 -0
- package/dist/modules/customers/lib/dealClosureNotification.js.map +7 -0
- package/dist/modules/customers/lib/dealStageTransitionTable.js +29 -0
- package/dist/modules/customers/lib/dealStageTransitionTable.js.map +7 -0
- package/dist/modules/customers/lib/dictionaries.js +25 -0
- package/dist/modules/customers/lib/dictionaries.js.map +2 -2
- package/dist/modules/customers/lib/interactionReadModel.js +10 -0
- package/dist/modules/customers/lib/interactionReadModel.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +235 -0
- package/dist/modules/customers/lib/personCompanies.js.map +7 -0
- package/dist/modules/customers/lib/personCompanyLinkTable.js +42 -0
- package/dist/modules/customers/lib/personCompanyLinkTable.js.map +7 -0
- package/dist/modules/customers/lib/roleTypeUsage.js +104 -0
- package/dist/modules/customers/lib/roleTypeUsage.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260406214502.js +18 -0
- package/dist/modules/customers/migrations/Migration20260406214502.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260408135736.js +17 -0
- package/dist/modules/customers/migrations/Migration20260408135736.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260408225345.js +21 -0
- package/dist/modules/customers/migrations/Migration20260408225345.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260411075533.js +27 -0
- package/dist/modules/customers/migrations/Migration20260411075533.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260411103551.js +13 -0
- package/dist/modules/customers/migrations/Migration20260411103551.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260411130944.js +26 -0
- package/dist/modules/customers/migrations/Migration20260411130944.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260415095203.js +13 -0
- package/dist/modules/customers/migrations/Migration20260415095203.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260415135056.js +20 -0
- package/dist/modules/customers/migrations/Migration20260415135056.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260417140000.js +15 -0
- package/dist/modules/customers/migrations/Migration20260417140000.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260417160000.js +17 -0
- package/dist/modules/customers/migrations/Migration20260417160000.js.map +7 -0
- package/dist/modules/customers/migrations/Migration20260417235407.js +13 -0
- package/dist/modules/customers/migrations/Migration20260417235407.js.map +7 -0
- package/dist/modules/customers/setup.js +16 -1
- package/dist/modules/customers/setup.js.map +2 -2
- package/dist/modules/customers/subscribers/deal-closure-notification.js +16 -0
- package/dist/modules/customers/subscribers/deal-closure-notification.js.map +7 -0
- package/dist/modules/customers/subscribers/deal-lost-notification.js +16 -0
- package/dist/modules/customers/subscribers/deal-lost-notification.js.map +7 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js +2 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js +154 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.js.map +7 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js +6 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/route.js.map +2 -2
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js +154 -0
- package/dist/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.js.map +7 -0
- package/dist/modules/dictionaries/api/context.js +8 -1
- package/dist/modules/dictionaries/api/context.js.map +2 -2
- package/dist/modules/dictionaries/api/openapi.js +18 -1
- package/dist/modules/dictionaries/api/openapi.js.map +2 -2
- package/dist/modules/dictionaries/commands/entry-operations.js +388 -0
- package/dist/modules/dictionaries/commands/entry-operations.js.map +7 -0
- package/dist/modules/dictionaries/commands/factory.js +24 -3
- package/dist/modules/dictionaries/commands/factory.js.map +2 -2
- package/dist/modules/dictionaries/commands/index.js +1 -0
- package/dist/modules/dictionaries/commands/index.js.map +2 -2
- package/dist/modules/dictionaries/components/DictionaryTable.js +6 -3
- package/dist/modules/dictionaries/components/DictionaryTable.js.map +2 -2
- package/dist/modules/dictionaries/data/entities.js +11 -1
- package/dist/modules/dictionaries/data/entities.js.map +2 -2
- package/dist/modules/dictionaries/data/validators.js +28 -2
- package/dist/modules/dictionaries/data/validators.js.map +2 -2
- package/dist/modules/dictionaries/events.js +18 -0
- package/dist/modules/dictionaries/events.js.map +7 -0
- package/dist/modules/dictionaries/lib/clientEntries.js +43 -0
- package/dist/modules/dictionaries/lib/clientEntries.js.map +7 -0
- package/dist/modules/dictionaries/migrations/Migration20260410171544.js +45 -0
- package/dist/modules/dictionaries/migrations/Migration20260410171544.js.map +7 -0
- package/dist/modules/inbox_ops/api/proposals/[id]/route.js +4 -1
- package/dist/modules/inbox_ops/api/proposals/[id]/route.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +1 -1
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/sales/components/documents/AddressesSection.js +82 -42
- package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
- package/dist/modules/sales/lib/dictionaries.js +16 -0
- package/dist/modules/sales/lib/dictionaries.js.map +2 -2
- package/dist/modules/sales/widgets/injection-table.js +5 -1
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/generated/entities/action_log/index.ts +4 -0
- package/generated/entities/customer_company_billing/index.ts +10 -0
- package/generated/entities/customer_deal/index.ts +4 -0
- package/generated/entities/customer_deal_stage_transition/index.ts +14 -0
- package/generated/entities/customer_dictionary_kind_setting/index.ts +9 -0
- package/generated/entities/customer_entity/index.ts +4 -0
- package/generated/entities/customer_entity_role/index.ts +10 -0
- package/generated/entities/customer_interaction/index.ts +11 -0
- package/generated/entities/customer_label/index.ts +8 -0
- package/generated/entities/customer_label_assignment/index.ts +7 -0
- package/generated/entities/customer_person_company_link/index.ts +9 -0
- package/generated/entities/customer_person_company_role/index.ts +7 -0
- package/generated/entities/dictionary_entry/index.ts +2 -0
- package/generated/entities.ids.generated.ts +9 -1
- package/generated/entity-fields-registry.ts +116 -1
- package/package.json +3 -3
- package/src/modules/attachments/api/route.ts +48 -6
- package/src/modules/attachments/i18n/de.json +4 -0
- package/src/modules/attachments/i18n/en.json +4 -0
- package/src/modules/attachments/i18n/es.json +4 -0
- package/src/modules/attachments/i18n/pl.json +4 -0
- package/src/modules/audit_logs/api/audit-logs/actions/export/route.ts +260 -0
- package/src/modules/audit_logs/api/audit-logs/actions/route.ts +81 -6
- package/src/modules/audit_logs/cli.ts +79 -0
- package/src/modules/audit_logs/data/entities.ts +17 -0
- package/src/modules/audit_logs/data/validators.ts +9 -1
- package/src/modules/audit_logs/lib/changeRows.ts +47 -0
- package/src/modules/audit_logs/lib/display-helpers.tsx +4 -30
- package/src/modules/audit_logs/lib/projections.ts +110 -0
- package/src/modules/audit_logs/migrations/.snapshot-open-mercato.json +325 -2
- package/src/modules/audit_logs/migrations/Migration20260412160533.ts +21 -0
- package/src/modules/audit_logs/services/actionLogService.ts +455 -85
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/customer_accounts/i18n/de.json +2 -0
- package/src/modules/customer_accounts/i18n/en.json +2 -0
- package/src/modules/customer_accounts/i18n/es.json +2 -0
- package/src/modules/customer_accounts/i18n/pl.json +2 -0
- package/src/modules/customers/acl.ts +2 -0
- package/src/modules/customers/api/activities/route.ts +4 -0
- package/src/modules/customers/api/assignable-staff/route.ts +250 -0
- package/src/modules/customers/api/companies/[id]/people/route.ts +244 -0
- package/src/modules/customers/api/companies/[id]/roles/route.ts +15 -0
- package/src/modules/customers/api/companies/[id]/route.ts +458 -40
- package/src/modules/customers/api/companies/route.ts +93 -15
- package/src/modules/customers/api/deals/[id]/companies/route.ts +203 -0
- package/src/modules/customers/api/deals/[id]/people/route.ts +182 -0
- package/src/modules/customers/api/deals/[id]/route.ts +554 -57
- package/src/modules/customers/api/deals/[id]/stats/route.ts +221 -0
- package/src/modules/customers/api/deals/route.ts +35 -46
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +105 -3
- package/src/modules/customers/api/dictionaries/[kind]/route.ts +143 -44
- package/src/modules/customers/api/dictionaries/context.ts +45 -16
- package/src/modules/customers/api/dictionaries/kind-settings/route.ts +232 -0
- package/src/modules/customers/api/entity-roles-factory.ts +520 -0
- package/src/modules/customers/api/interactions/conflicts/route.ts +196 -0
- package/src/modules/customers/api/interactions/counts/route.ts +112 -0
- package/src/modules/customers/api/interactions/route.ts +95 -2
- package/src/modules/customers/api/labels/assign/route.ts +202 -0
- package/src/modules/customers/api/labels/auth.ts +19 -0
- package/src/modules/customers/api/labels/route.ts +310 -0
- package/src/modules/customers/api/labels/table-errors.ts +36 -0
- package/src/modules/customers/api/labels/unassign/route.ts +197 -0
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +331 -0
- package/src/modules/customers/api/people/[id]/companies/context.ts +70 -0
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +384 -0
- package/src/modules/customers/api/people/[id]/companies/route.ts +215 -0
- package/src/modules/customers/api/people/[id]/roles/route.ts +15 -0
- package/src/modules/customers/api/people/[id]/route.ts +153 -26
- package/src/modules/customers/api/people/route.ts +134 -31
- package/src/modules/customers/api/todos/route.ts +4 -0
- package/src/modules/customers/api/utils.ts +36 -0
- package/src/modules/customers/backend/config/customers/page.tsx +2 -6
- package/src/modules/customers/backend/customers/companies/page.tsx +36 -26
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +277 -262
- package/src/modules/customers/backend/customers/deals/[id]/hooks/formatters.ts +19 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +104 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +60 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealAssociations.ts +362 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealClosure.ts +113 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +52 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealFormHandlers.ts +86 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealInjectedTabs.tsx +60 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealMutationContext.ts +76 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealPipeline.ts +56 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useScheduleDialog.ts +38 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +587 -624
- package/src/modules/customers/backend/customers/deals/page.tsx +71 -28
- package/src/modules/customers/backend/customers/people/page.tsx +35 -29
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +343 -209
- package/src/modules/customers/cli.ts +107 -12
- package/src/modules/customers/commands/activities.ts +13 -0
- package/src/modules/customers/commands/deals.ts +386 -114
- package/src/modules/customers/commands/dictionaries.ts +175 -32
- package/src/modules/customers/commands/dictionaryKindSettings.ts +268 -0
- package/src/modules/customers/commands/entity-roles.ts +494 -0
- package/src/modules/customers/commands/index.ts +4 -0
- package/src/modules/customers/commands/interactions.ts +125 -21
- package/src/modules/customers/commands/labels.ts +626 -0
- package/src/modules/customers/commands/people.ts +373 -259
- package/src/modules/customers/commands/personCompanyLinks.ts +654 -0
- package/src/modules/customers/commands/shared.ts +16 -15
- package/src/modules/customers/commands/todos.ts +17 -1
- package/src/modules/customers/components/AddressEditor.tsx +1 -1
- package/src/modules/customers/components/CustomersConfigurationSections.tsx +36 -0
- package/src/modules/customers/components/DictionarySettings.tsx +43 -2
- package/src/modules/customers/components/detail/ActiveDealCard.tsx +175 -0
- package/src/modules/customers/components/detail/ActivitiesSection.tsx +267 -361
- package/src/modules/customers/components/detail/ActivityAiActions.tsx +49 -0
- package/src/modules/customers/components/detail/ActivityCard.tsx +154 -0
- package/src/modules/customers/components/detail/ActivityHistorySection.tsx +412 -0
- package/src/modules/customers/components/detail/ActivityLogTab.tsx +67 -0
- package/src/modules/customers/components/detail/ActivityTimeline.tsx +158 -0
- package/src/modules/customers/components/detail/ActivityTimelineFilters.tsx +163 -0
- package/src/modules/customers/components/detail/ActivityTypeSelector.tsx +53 -0
- package/src/modules/customers/components/detail/AiActionChips.tsx +48 -0
- package/src/modules/customers/components/detail/AssignRoleDialog.tsx +672 -0
- package/src/modules/customers/components/detail/ChangelogEntryRow.tsx +132 -0
- package/src/modules/customers/components/detail/ChangelogFilters.tsx +193 -0
- package/src/modules/customers/components/detail/ChangelogKpiCards.tsx +107 -0
- package/src/modules/customers/components/detail/ChangelogTab.tsx +629 -0
- package/src/modules/customers/components/detail/ComingSoonPlaceholder.tsx +21 -0
- package/src/modules/customers/components/detail/CompanyCard.tsx +419 -0
- package/src/modules/customers/components/detail/CompanyDashboardTab.tsx +161 -0
- package/src/modules/customers/components/detail/CompanyDetailHeader.tsx +243 -0
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +172 -0
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +206 -0
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +582 -288
- package/src/modules/customers/components/detail/CompanyTagsDialog.tsx +23 -0
- package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +210 -0
- package/src/modules/customers/components/detail/CreatePersonDialog.tsx +178 -0
- package/src/modules/customers/components/detail/DealClosureActionBar.tsx +63 -0
- package/src/modules/customers/components/detail/DealDetailHeader.tsx +335 -0
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +154 -0
- package/src/modules/customers/components/detail/DealForm.tsx +253 -101
- package/src/modules/customers/components/detail/DealLinkedEntitiesTab.tsx +349 -0
- package/src/modules/customers/components/detail/DealLostSummaryDialog.tsx +156 -0
- package/src/modules/customers/components/detail/DealWonPopup.tsx +164 -0
- package/src/modules/customers/components/detail/DealsSection.tsx +276 -221
- package/src/modules/customers/components/detail/DecisionMakersFooter.tsx +56 -0
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +1372 -0
- package/src/modules/customers/components/detail/InlineActivityComposer.tsx +239 -0
- package/src/modules/customers/components/detail/ManageTagsDialog.tsx +1331 -0
- package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +338 -0
- package/src/modules/customers/components/detail/MobilePersonDetail.tsx +124 -0
- package/src/modules/customers/components/detail/NextStepCard.tsx +104 -0
- package/src/modules/customers/components/detail/PersonCard.tsx +238 -0
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +426 -0
- package/src/modules/customers/components/detail/PersonDetailHeader.tsx +294 -0
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +172 -0
- package/src/modules/customers/components/detail/PersonTagsDialog.tsx +26 -0
- package/src/modules/customers/components/detail/PipelineStepper.tsx +245 -0
- package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +255 -0
- package/src/modules/customers/components/detail/RelationshipHealthCard.tsx +63 -0
- package/src/modules/customers/components/detail/RoleAssignmentRow.tsx +248 -0
- package/src/modules/customers/components/detail/RolesSection.tsx +311 -0
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +481 -0
- package/src/modules/customers/components/detail/aiActionCatalog.ts +77 -0
- package/src/modules/customers/components/detail/assignableStaff.ts +124 -0
- package/src/modules/customers/components/detail/dashboard/ActiveDealWidget.tsx +63 -0
- package/src/modules/customers/components/detail/dashboard/OpenTasksWidget.tsx +114 -0
- package/src/modules/customers/components/detail/dashboard/RecentActivityWidget.tsx +69 -0
- package/src/modules/customers/components/detail/dashboard/RelationshipHealthWidget.tsx +40 -0
- package/src/modules/customers/components/detail/dashboard/UpcomingMeetingsWidget.tsx +64 -0
- package/src/modules/customers/components/detail/dashboard/helpers.ts +78 -0
- package/src/modules/customers/components/detail/healthScoreUtils.ts +91 -0
- package/src/modules/customers/components/detail/hooks/useCurrencyDictionary.ts +8 -8
- package/src/modules/customers/components/detail/hooks/useCustomerDictionary.ts +10 -6
- package/src/modules/customers/components/detail/hooks/useInteractionMutations.ts +91 -0
- package/src/modules/customers/components/detail/notesAdapter.ts +91 -30
- package/src/modules/customers/components/detail/pipelineStageUtils.ts +29 -0
- package/src/modules/customers/components/detail/schedule/DateTimeFields.tsx +187 -0
- package/src/modules/customers/components/detail/schedule/FooterFields.tsx +79 -0
- package/src/modules/customers/components/detail/schedule/LinkedEntitiesField.tsx +277 -0
- package/src/modules/customers/components/detail/schedule/LocationField.tsx +42 -0
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +255 -0
- package/src/modules/customers/components/detail/schedule/fieldConfig.ts +70 -0
- package/src/modules/customers/components/detail/schedule/index.ts +9 -0
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +221 -0
- package/src/modules/customers/components/detail/types.ts +16 -0
- package/src/modules/customers/components/detail/utils.ts +25 -0
- package/src/modules/customers/components/formConfig.tsx +223 -28
- package/src/modules/customers/components/linking/LinkEntityDialog.tsx +920 -0
- package/src/modules/customers/components/linking/adapters/companyAdapter.tsx +398 -0
- package/src/modules/customers/components/linking/adapters/dealAdapter.tsx +578 -0
- package/src/modules/customers/components/linking/adapters/personAdapter.tsx +512 -0
- package/src/modules/customers/components/list/CollectionPreviewCell.tsx +66 -0
- package/src/modules/customers/data/entities.ts +353 -1
- package/src/modules/customers/data/validators.ts +170 -19
- package/src/modules/customers/events.ts +22 -0
- package/src/modules/customers/i18n/de.json +841 -2
- package/src/modules/customers/i18n/en.json +841 -2
- package/src/modules/customers/i18n/es.json +840 -1
- package/src/modules/customers/i18n/pl.json +841 -2
- package/src/modules/customers/lib/customerRoleTypes.ts +24 -0
- package/src/modules/customers/lib/dealClosureNotification.ts +64 -0
- package/src/modules/customers/lib/dealStageTransitionTable.ts +32 -0
- package/src/modules/customers/lib/dictionaries.ts +26 -10
- package/src/modules/customers/lib/interactionReadModel.ts +10 -0
- package/src/modules/customers/lib/personCompanies.ts +317 -0
- package/src/modules/customers/lib/personCompanyLinkTable.ts +58 -0
- package/src/modules/customers/lib/roleTypeUsage.ts +146 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +2747 -798
- package/src/modules/customers/migrations/Migration20260406214502.ts +19 -0
- package/src/modules/customers/migrations/Migration20260408135736.ts +15 -0
- package/src/modules/customers/migrations/Migration20260408225345.ts +23 -0
- package/src/modules/customers/migrations/Migration20260411075533.ts +30 -0
- package/src/modules/customers/migrations/Migration20260411103551.ts +13 -0
- package/src/modules/customers/migrations/Migration20260411130944.ts +30 -0
- package/src/modules/customers/migrations/Migration20260415095203.ts +13 -0
- package/src/modules/customers/migrations/Migration20260415135056.ts +22 -0
- package/src/modules/customers/migrations/Migration20260417140000.ts +15 -0
- package/src/modules/customers/migrations/Migration20260417160000.ts +17 -0
- package/src/modules/customers/migrations/Migration20260417235407.ts +13 -0
- package/src/modules/customers/setup.ts +15 -0
- package/src/modules/customers/subscribers/deal-closure-notification.ts +22 -0
- package/src/modules/customers/subscribers/deal-lost-notification.ts +22 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/[entryId]/route.ts +2 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/reorder/route.ts +162 -0
- package/src/modules/dictionaries/api/[dictionaryId]/entries/route.ts +6 -2
- package/src/modules/dictionaries/api/[dictionaryId]/entries/set-default/route.ts +162 -0
- package/src/modules/dictionaries/api/context.ts +9 -0
- package/src/modules/dictionaries/api/openapi.ts +17 -0
- package/src/modules/dictionaries/commands/entry-operations.ts +457 -0
- package/src/modules/dictionaries/commands/factory.ts +31 -3
- package/src/modules/dictionaries/commands/index.ts +1 -0
- package/src/modules/dictionaries/components/DictionaryTable.tsx +15 -6
- package/src/modules/dictionaries/data/entities.ts +9 -0
- package/src/modules/dictionaries/data/validators.ts +34 -0
- package/src/modules/dictionaries/events.ts +20 -0
- package/src/modules/dictionaries/i18n/de.json +2 -0
- package/src/modules/dictionaries/i18n/en.json +2 -0
- package/src/modules/dictionaries/i18n/es.json +2 -0
- package/src/modules/dictionaries/i18n/pl.json +2 -0
- package/src/modules/dictionaries/lib/clientEntries.ts +66 -0
- package/src/modules/dictionaries/migrations/.snapshot-open-mercato.json +185 -3
- package/src/modules/dictionaries/migrations/Migration20260410171544.ts +49 -0
- package/src/modules/inbox_ops/api/proposals/[id]/route.ts +4 -1
- package/src/modules/query_index/lib/engine.ts +9 -1
- package/src/modules/sales/components/documents/AddressesSection.tsx +92 -42
- package/src/modules/sales/i18n/de.json +28 -0
- package/src/modules/sales/i18n/en.json +28 -0
- package/src/modules/sales/i18n/es.json +28 -0
- package/src/modules/sales/i18n/pl.json +28 -0
- package/src/modules/sales/lib/dictionaries.ts +18 -0
- package/src/modules/sales/widgets/injection-table.ts +4 -0
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
CustomerActivity,
|
|
13
13
|
CustomerTagAssignment,
|
|
14
14
|
CustomerTag,
|
|
15
|
+
CustomerLabelAssignment,
|
|
16
|
+
CustomerLabel,
|
|
15
17
|
CustomerDealPersonLink,
|
|
16
18
|
CustomerDeal,
|
|
17
19
|
CustomerTodoLink,
|
|
@@ -33,8 +35,9 @@ import { hydrateCanonicalInteractions } from '../../../lib/interactionReadModel'
|
|
|
33
35
|
import type { QueryEngine } from '@open-mercato/shared/lib/query/types'
|
|
34
36
|
import type { EntityId } from '@open-mercato/shared/modules/entities'
|
|
35
37
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
36
|
-
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
38
|
+
import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
37
39
|
import { parseBooleanFromUnknown, parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
40
|
+
import { loadPersonCompanyLinks, summarizePersonCompanies } from '../../../lib/personCompanies'
|
|
38
41
|
|
|
39
42
|
export const metadata = {
|
|
40
43
|
GET: { requireAuth: true, requireFeatures: ['customers.people.view'] },
|
|
@@ -396,6 +399,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
396
399
|
const includeDeals = includeTokens.has('deals')
|
|
397
400
|
const includeInteractions = includeTokens.has('interactions')
|
|
398
401
|
const includeTodos = includeTokens.has('todos') || includeTokens.has('tasks')
|
|
402
|
+
const plannedPreviewLimit = 5
|
|
399
403
|
|
|
400
404
|
let statusCode = 500
|
|
401
405
|
let profileMeta: Record<string, unknown> | undefined
|
|
@@ -410,6 +414,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
410
414
|
let customFields: Record<string, unknown> = {}
|
|
411
415
|
let viewerUserId: string | null = null
|
|
412
416
|
let profile: CustomerPersonProfile | null = null
|
|
417
|
+
let companies: Array<{ linkId: string | null; companyId: string; displayName: string; isPrimary: boolean; synthetic?: boolean }> = []
|
|
413
418
|
|
|
414
419
|
try {
|
|
415
420
|
const parse = paramsSchema.safeParse({ id: ctx.params?.id })
|
|
@@ -446,7 +451,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
446
451
|
})
|
|
447
452
|
const em = (container.resolve('em') as EntityManager)
|
|
448
453
|
|
|
449
|
-
const person = await em
|
|
454
|
+
const person = await findOneWithDecryption(em, CustomerEntity, { id: parse.data.id, kind: 'person', deletedAt: null }, {}, { tenantId: auth.tenantId ?? null, organizationId: auth.orgId ?? null })
|
|
450
455
|
profiler.mark('person_loaded', { found: !!person })
|
|
451
456
|
if (!person) {
|
|
452
457
|
statusCode = 404
|
|
@@ -469,11 +474,12 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
469
474
|
return forbidden('Access denied')
|
|
470
475
|
}
|
|
471
476
|
|
|
472
|
-
profile = await em
|
|
477
|
+
profile = await findOneWithDecryption(em, CustomerPersonProfile, { entity: person }, { populate: ['company'] }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
473
478
|
profiler.mark('profile_loaded', { found: !!profile })
|
|
479
|
+
companies = summarizePersonCompanies(profile, await loadPersonCompanyLinks(em, person))
|
|
474
480
|
|
|
475
481
|
if (includeAddresses) {
|
|
476
|
-
addresses = await em
|
|
482
|
+
addresses = await findWithDecryption(em, CustomerAddress, { entity: person.id }, { orderBy: { isPrimary: 'desc', createdAt: 'desc' } }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
477
483
|
profiler.mark('addresses_loaded', { count: addresses.length })
|
|
478
484
|
}
|
|
479
485
|
|
|
@@ -486,19 +492,30 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
486
492
|
)
|
|
487
493
|
profiler.mark('tags_loaded', { count: tagAssignments.length })
|
|
488
494
|
|
|
495
|
+
const labelAssignments = await findWithDecryption(
|
|
496
|
+
em,
|
|
497
|
+
CustomerLabelAssignment,
|
|
498
|
+
{ entity: person.id },
|
|
499
|
+
{ populate: ['label'] },
|
|
500
|
+
{ tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
|
|
501
|
+
)
|
|
502
|
+
profiler.mark('labels_loaded', { count: labelAssignments.length })
|
|
503
|
+
|
|
489
504
|
if (includeComments) {
|
|
490
|
-
comments = await em
|
|
505
|
+
comments = await findWithDecryption(em, CustomerComment, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
491
506
|
profiler.mark('comments_loaded', { count: comments.length })
|
|
492
507
|
}
|
|
493
508
|
|
|
494
509
|
const shouldLoadCanonicalInteractions = includeInteractions || includeActivities || includeTodos
|
|
495
510
|
const canonicalInteractionRows = shouldLoadCanonicalInteractions
|
|
496
|
-
? await
|
|
511
|
+
? await findWithDecryption(
|
|
512
|
+
em,
|
|
497
513
|
CustomerInteraction,
|
|
498
514
|
interactionFlags.unified
|
|
499
515
|
? { entity: person.id, deletedAt: null }
|
|
500
516
|
: { entity: person.id },
|
|
501
517
|
{ orderBy: { scheduledAt: 'asc', createdAt: 'desc' }, limit: 100 },
|
|
518
|
+
{ tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
|
|
502
519
|
)
|
|
503
520
|
: []
|
|
504
521
|
profiler.mark('canonical_interactions_loaded', { count: canonicalInteractionRows.length })
|
|
@@ -515,8 +532,42 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
515
532
|
: []
|
|
516
533
|
profiler.mark('canonical_interactions_hydrated', { count: canonicalInteractions.length })
|
|
517
534
|
|
|
535
|
+
const plannedPreviewInteractions = shouldLoadCanonicalInteractions
|
|
536
|
+
? (() => {
|
|
537
|
+
const sorted = [...canonicalInteractions]
|
|
538
|
+
.filter((interaction) => interaction.status === 'planned' && interaction.interactionType !== 'task')
|
|
539
|
+
.sort((left, right) => {
|
|
540
|
+
const leftTime = new Date(left.scheduledAt ?? left.createdAt).getTime()
|
|
541
|
+
const rightTime = new Date(right.scheduledAt ?? right.createdAt).getTime()
|
|
542
|
+
if (leftTime === rightTime) return left.id.localeCompare(right.id)
|
|
543
|
+
return leftTime - rightTime
|
|
544
|
+
})
|
|
545
|
+
return sorted.slice(0, plannedPreviewLimit)
|
|
546
|
+
})()
|
|
547
|
+
: await hydrateCanonicalInteractions({
|
|
548
|
+
em,
|
|
549
|
+
container,
|
|
550
|
+
auth,
|
|
551
|
+
selectedOrganizationId: scope?.selectedId ?? auth.orgId ?? null,
|
|
552
|
+
interactions: await findWithDecryption(
|
|
553
|
+
em,
|
|
554
|
+
CustomerInteraction,
|
|
555
|
+
{
|
|
556
|
+
entity: person.id,
|
|
557
|
+
organizationId: person.organizationId,
|
|
558
|
+
tenantId: person.tenantId,
|
|
559
|
+
deletedAt: null,
|
|
560
|
+
status: 'planned',
|
|
561
|
+
interactionType: { $ne: 'task' },
|
|
562
|
+
},
|
|
563
|
+
{ orderBy: { scheduledAt: 'ASC', createdAt: 'ASC' }, limit: plannedPreviewLimit },
|
|
564
|
+
{ tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null },
|
|
565
|
+
),
|
|
566
|
+
enrich: true,
|
|
567
|
+
})
|
|
568
|
+
|
|
518
569
|
if (includeActivities && !interactionFlags.unified) {
|
|
519
|
-
activities = await em
|
|
570
|
+
activities = await findWithDecryption(em, CustomerActivity, { entity: person.id }, { orderBy: { occurredAt: 'desc', createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
520
571
|
profiler.mark('activities_loaded', { count: activities.length })
|
|
521
572
|
}
|
|
522
573
|
|
|
@@ -525,7 +576,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
525
576
|
}
|
|
526
577
|
|
|
527
578
|
if (includeTodos && !interactionFlags.unified) {
|
|
528
|
-
todoLinks = await em
|
|
579
|
+
todoLinks = await findWithDecryption(em, CustomerTodoLink, { entity: person.id }, { orderBy: { createdAt: 'desc' }, limit: 50 }, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
529
580
|
profiler.mark('todo_links_loaded', { count: todoLinks.length })
|
|
530
581
|
if (todoLinks.length) {
|
|
531
582
|
const queryEngine = (container.resolve('queryEngine') as QueryEngine)
|
|
@@ -575,7 +626,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
575
626
|
if (viewerUserId) authorIds.add(viewerUserId)
|
|
576
627
|
|
|
577
628
|
if (authorIds.size) {
|
|
578
|
-
const users = await em
|
|
629
|
+
const users = await findWithDecryption(em, User, { id: { $in: Array.from(authorIds) } }, {}, { tenantId: person.tenantId ?? auth.tenantId ?? null, organizationId: person.organizationId ?? auth.orgId ?? null })
|
|
579
630
|
userMap = new Map(
|
|
580
631
|
users.map((user) => [
|
|
581
632
|
user.id,
|
|
@@ -640,6 +691,56 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
640
691
|
profiler.mark('custom_fields_merged', { keys: Object.keys(customFields).length })
|
|
641
692
|
|
|
642
693
|
const viewerUserIdFinal = viewerUserId
|
|
694
|
+
const counts = {
|
|
695
|
+
tags: tagAssignments.length + labelAssignments.length,
|
|
696
|
+
comments: includeComments
|
|
697
|
+
? comments.length
|
|
698
|
+
: await em.count(CustomerComment, {
|
|
699
|
+
entity: person.id,
|
|
700
|
+
organizationId: person.organizationId,
|
|
701
|
+
tenantId: person.tenantId,
|
|
702
|
+
}),
|
|
703
|
+
activities: await em.count(CustomerInteraction, {
|
|
704
|
+
entity: person.id,
|
|
705
|
+
organizationId: person.organizationId,
|
|
706
|
+
tenantId: person.tenantId,
|
|
707
|
+
deletedAt: null,
|
|
708
|
+
interactionType: { $ne: 'task' },
|
|
709
|
+
}),
|
|
710
|
+
interactions: await em.count(CustomerInteraction, {
|
|
711
|
+
entity: person.id,
|
|
712
|
+
organizationId: person.organizationId,
|
|
713
|
+
tenantId: person.tenantId,
|
|
714
|
+
deletedAt: null,
|
|
715
|
+
}),
|
|
716
|
+
todos: interactionFlags.unified
|
|
717
|
+
? await em.count(CustomerInteraction, {
|
|
718
|
+
entity: person.id,
|
|
719
|
+
organizationId: person.organizationId,
|
|
720
|
+
tenantId: person.tenantId,
|
|
721
|
+
deletedAt: null,
|
|
722
|
+
interactionType: 'task',
|
|
723
|
+
})
|
|
724
|
+
: await em.count(CustomerTodoLink, {
|
|
725
|
+
entity: person.id,
|
|
726
|
+
organizationId: person.organizationId,
|
|
727
|
+
tenantId: person.tenantId,
|
|
728
|
+
}),
|
|
729
|
+
addresses: includeAddresses
|
|
730
|
+
? addresses.length
|
|
731
|
+
: await em.count(CustomerAddress, {
|
|
732
|
+
entity: person.id,
|
|
733
|
+
organizationId: person.organizationId,
|
|
734
|
+
tenantId: person.tenantId,
|
|
735
|
+
}),
|
|
736
|
+
deals: includeDeals
|
|
737
|
+
? deals.length
|
|
738
|
+
: await em.count(CustomerDealPersonLink, {
|
|
739
|
+
person: person.id,
|
|
740
|
+
}),
|
|
741
|
+
companies: companies.length,
|
|
742
|
+
}
|
|
743
|
+
|
|
643
744
|
const response = NextResponse.json({
|
|
644
745
|
interactionMode,
|
|
645
746
|
person: {
|
|
@@ -652,6 +753,8 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
652
753
|
status: person.status,
|
|
653
754
|
lifecycleStage: person.lifecycleStage,
|
|
654
755
|
source: person.source,
|
|
756
|
+
temperature: person.temperature,
|
|
757
|
+
renewalQuarter: person.renewalQuarter,
|
|
655
758
|
nextInteractionAt: person.nextInteractionAt ? person.nextInteractionAt.toISOString() : null,
|
|
656
759
|
nextInteractionName: person.nextInteractionName,
|
|
657
760
|
nextInteractionRefId: person.nextInteractionRefId,
|
|
@@ -680,7 +783,16 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
680
783
|
}
|
|
681
784
|
: null,
|
|
682
785
|
customFields,
|
|
683
|
-
tags:
|
|
786
|
+
tags: [
|
|
787
|
+
...serializeTags(tagAssignments),
|
|
788
|
+
...labelAssignments
|
|
789
|
+
.map((a) => {
|
|
790
|
+
const label = a.label as CustomerLabel | string | null
|
|
791
|
+
if (!label || typeof label === 'string') return null
|
|
792
|
+
return { id: label.id, label: label.label, color: null }
|
|
793
|
+
})
|
|
794
|
+
.filter((t): t is { id: string; label: string; color: null } => t !== null),
|
|
795
|
+
],
|
|
684
796
|
addresses: includeAddresses
|
|
685
797
|
? addresses.map((address) => ({
|
|
686
798
|
id: address.id,
|
|
@@ -762,12 +874,17 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
762
874
|
title: deal.title,
|
|
763
875
|
status: deal.status,
|
|
764
876
|
pipelineStage: deal.pipelineStage,
|
|
877
|
+
pipelineId: deal.pipelineId ?? null,
|
|
878
|
+
pipelineStageId: deal.pipelineStageId ?? null,
|
|
765
879
|
valueAmount: deal.valueAmount,
|
|
766
880
|
valueCurrency: deal.valueCurrency,
|
|
767
881
|
probability: deal.probability,
|
|
768
882
|
expectedCloseAt: deal.expectedCloseAt ? deal.expectedCloseAt.toISOString() : null,
|
|
769
883
|
ownerUserId: deal.ownerUserId,
|
|
770
884
|
source: deal.source,
|
|
885
|
+
closureOutcome: deal.closureOutcome ?? null,
|
|
886
|
+
lossReasonId: deal.lossReasonId ?? null,
|
|
887
|
+
lossNotes: deal.lossNotes ?? null,
|
|
771
888
|
createdAt: deal.createdAt.toISOString(),
|
|
772
889
|
updatedAt: deal.updatedAt.toISOString(),
|
|
773
890
|
}))
|
|
@@ -815,9 +932,20 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
815
932
|
}).slice(0, 50)
|
|
816
933
|
)
|
|
817
934
|
: [],
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
:
|
|
935
|
+
isPrimary: companies.some((entry) => entry.isPrimary),
|
|
936
|
+
companies: companies.map((entry) => ({
|
|
937
|
+
id: entry.companyId,
|
|
938
|
+
displayName: entry.displayName,
|
|
939
|
+
isPrimary: entry.isPrimary,
|
|
940
|
+
})),
|
|
941
|
+
company: (() => {
|
|
942
|
+
const primaryCompany = companies.find((entry) => entry.isPrimary) ?? companies[0] ?? null
|
|
943
|
+
return primaryCompany
|
|
944
|
+
? { id: primaryCompany.companyId, displayName: primaryCompany.displayName }
|
|
945
|
+
: null
|
|
946
|
+
})(),
|
|
947
|
+
plannedActivitiesPreview: plannedPreviewInteractions,
|
|
948
|
+
counts,
|
|
821
949
|
viewer: {
|
|
822
950
|
userId: viewerUserIdFinal,
|
|
823
951
|
name: viewerUserIdFinal ? userMap.get(viewerUserIdFinal)?.name ?? null : null,
|
|
@@ -828,19 +956,7 @@ export async function GET(_req: Request, ctx: { params?: { id?: string } }) {
|
|
|
828
956
|
profileMeta = {
|
|
829
957
|
include: Array.from(includeTokens),
|
|
830
958
|
interactionMode,
|
|
831
|
-
counts
|
|
832
|
-
tags: tagAssignments.length,
|
|
833
|
-
comments: comments.length,
|
|
834
|
-
activities: includeActivities
|
|
835
|
-
? (interactionFlags.unified ? canonicalActivityItems.length : activities.length + canonicalActivityItems.length)
|
|
836
|
-
: 0,
|
|
837
|
-
interactions: canonicalInteractions.length,
|
|
838
|
-
todos: includeTodos
|
|
839
|
-
? (interactionFlags.unified ? canonicalTodoItems.length : todoLinks.length + canonicalTodoItems.length)
|
|
840
|
-
: 0,
|
|
841
|
-
addresses: addresses.length,
|
|
842
|
-
deals: deals.length,
|
|
843
|
-
},
|
|
959
|
+
counts,
|
|
844
960
|
}
|
|
845
961
|
profiler.mark('response_ready', { status: statusCode })
|
|
846
962
|
return response
|
|
@@ -995,6 +1111,9 @@ const personDetailResponseSchema = z.object({
|
|
|
995
1111
|
expectedCloseAt: z.string().nullable().optional(),
|
|
996
1112
|
ownerUserId: z.string().uuid().nullable().optional(),
|
|
997
1113
|
source: z.string().nullable().optional(),
|
|
1114
|
+
closureOutcome: z.string().nullable().optional(),
|
|
1115
|
+
lossReasonId: z.string().uuid().nullable().optional(),
|
|
1116
|
+
lossNotes: z.string().nullable().optional(),
|
|
998
1117
|
createdAt: z.string(),
|
|
999
1118
|
updatedAt: z.string(),
|
|
1000
1119
|
}),
|
|
@@ -1016,6 +1135,14 @@ const personDetailResponseSchema = z.object({
|
|
|
1016
1135
|
customValues: z.record(z.string(), z.unknown()).nullable().optional(),
|
|
1017
1136
|
}),
|
|
1018
1137
|
),
|
|
1138
|
+
isPrimary: z.boolean(),
|
|
1139
|
+
companies: z.array(
|
|
1140
|
+
z.object({
|
|
1141
|
+
id: z.string().uuid(),
|
|
1142
|
+
displayName: z.string(),
|
|
1143
|
+
isPrimary: z.boolean(),
|
|
1144
|
+
}),
|
|
1145
|
+
),
|
|
1019
1146
|
viewer: z.object({
|
|
1020
1147
|
userId: z.string().uuid().nullable(),
|
|
1021
1148
|
name: z.string().nullable(),
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'
|
|
4
4
|
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CustomerDealPersonLink,
|
|
7
|
+
CustomerEntity,
|
|
8
|
+
CustomerPersonCompanyLink,
|
|
9
|
+
CustomerPersonProfile,
|
|
10
|
+
} from '../../data/entities'
|
|
6
11
|
import { E } from '#generated/entities.ids.generated'
|
|
7
12
|
import { personCreateSchema, personUpdateSchema } from '../../data/validators'
|
|
8
13
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
9
14
|
import {
|
|
15
|
+
applyEntityIdExclusion,
|
|
10
16
|
applyEntityIdRestriction,
|
|
11
17
|
consumeAdvancedFilterState,
|
|
12
18
|
findMatchingEntityIdsWithQueryEngine,
|
|
@@ -23,6 +29,7 @@ import {
|
|
|
23
29
|
createPagedListResponseSchema,
|
|
24
30
|
defaultOkResponseSchema,
|
|
25
31
|
} from '../openapi'
|
|
32
|
+
import { withActiveCustomerPersonCompanyLinkFilter } from '../../lib/personCompanyLinkTable'
|
|
26
33
|
import { normalizeProfilePayload } from './payload'
|
|
27
34
|
|
|
28
35
|
const rawBodySchema = z.object({}).passthrough()
|
|
@@ -48,6 +55,9 @@ const listSchema = z
|
|
|
48
55
|
id: z.string().uuid().optional(),
|
|
49
56
|
tagIds: z.string().optional(),
|
|
50
57
|
tagIdsEmpty: z.string().optional(),
|
|
58
|
+
excludeIds: z.string().optional(),
|
|
59
|
+
excludeLinkedCompanyId: z.string().uuid().optional(),
|
|
60
|
+
excludeLinkedDealId: z.string().uuid().optional(),
|
|
51
61
|
})
|
|
52
62
|
.passthrough()
|
|
53
63
|
|
|
@@ -98,10 +108,10 @@ const crud = makeCrudRoute({
|
|
|
98
108
|
createdAt: 'created_at',
|
|
99
109
|
updatedAt: 'updated_at',
|
|
100
110
|
},
|
|
101
|
-
buildFilters: async (query
|
|
111
|
+
buildFilters: async (query, ctx) => {
|
|
102
112
|
const advancedQuery = { ...query }
|
|
103
113
|
const advancedFilterState = consumeAdvancedFilterState(query)
|
|
104
|
-
const filters: Record<string,
|
|
114
|
+
const filters: Record<string, unknown> = { kind: { $eq: 'person' } }
|
|
105
115
|
if (query.id) filters.id = { $eq: query.id }
|
|
106
116
|
if (query.search) {
|
|
107
117
|
const matchingIds = ctx
|
|
@@ -192,6 +202,65 @@ const crud = makeCrudRoute({
|
|
|
192
202
|
} else if (tagIds.length > 0) {
|
|
193
203
|
filters['tag_assignments.tag_id'] = { $in: tagIds }
|
|
194
204
|
}
|
|
205
|
+
const excludedIds = new Set<string>()
|
|
206
|
+
const excludeIdsRaw = typeof query.excludeIds === 'string' ? query.excludeIds : ''
|
|
207
|
+
excludeIdsRaw
|
|
208
|
+
.split(',')
|
|
209
|
+
.map((value: string) => value.trim())
|
|
210
|
+
.filter((value: string) => value.length > 0)
|
|
211
|
+
.forEach((value: string) => excludedIds.add(value))
|
|
212
|
+
if (ctx && query.excludeLinkedCompanyId) {
|
|
213
|
+
try {
|
|
214
|
+
const em = ctx.container.resolve('em') as EntityManager
|
|
215
|
+
const decryptionScope = {
|
|
216
|
+
tenantId: ctx.auth?.tenantId ?? null,
|
|
217
|
+
organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
|
|
218
|
+
}
|
|
219
|
+
const linkWhere = await withActiveCustomerPersonCompanyLinkFilter(
|
|
220
|
+
em,
|
|
221
|
+
{ company: query.excludeLinkedCompanyId },
|
|
222
|
+
'customers.people.GET',
|
|
223
|
+
)
|
|
224
|
+
const links = await findWithDecryption(
|
|
225
|
+
em,
|
|
226
|
+
CustomerPersonCompanyLink,
|
|
227
|
+
linkWhere,
|
|
228
|
+
{ populate: ['person'] },
|
|
229
|
+
decryptionScope,
|
|
230
|
+
)
|
|
231
|
+
links.forEach((link) => {
|
|
232
|
+
const personId = link.person?.id
|
|
233
|
+
if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)
|
|
234
|
+
})
|
|
235
|
+
} catch (err) {
|
|
236
|
+
console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (ctx && query.excludeLinkedDealId) {
|
|
240
|
+
try {
|
|
241
|
+
const em = ctx.container.resolve('em') as EntityManager
|
|
242
|
+
const decryptionScope = {
|
|
243
|
+
tenantId: ctx.auth?.tenantId ?? null,
|
|
244
|
+
organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
|
|
245
|
+
}
|
|
246
|
+
const links = await findWithDecryption(
|
|
247
|
+
em,
|
|
248
|
+
CustomerDealPersonLink,
|
|
249
|
+
{
|
|
250
|
+
deal: query.excludeLinkedDealId,
|
|
251
|
+
},
|
|
252
|
+
{ populate: ['person'] },
|
|
253
|
+
decryptionScope,
|
|
254
|
+
)
|
|
255
|
+
links.forEach((link) => {
|
|
256
|
+
const personId = link.person?.id
|
|
257
|
+
if (typeof personId === 'string' && personId.length > 0) excludedIds.add(personId)
|
|
258
|
+
})
|
|
259
|
+
} catch (err) {
|
|
260
|
+
console.warn('[customers.people.list] exclusion lookup failed; falling back to base result set', err)
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
applyEntityIdExclusion(filters, Array.from(excludedIds))
|
|
195
264
|
const hasEmail = parseBooleanToken(query.hasEmail)
|
|
196
265
|
if (!email && !emailStartsWith && !emailContains && hasEmail !== null) {
|
|
197
266
|
filters.primary_email = { $exists: hasEmail }
|
|
@@ -218,7 +287,7 @@ const crud = makeCrudRoute({
|
|
|
218
287
|
}
|
|
219
288
|
if (ctx) {
|
|
220
289
|
try {
|
|
221
|
-
const em = ctx.container.resolve('em') as
|
|
290
|
+
const em = ctx.container.resolve('em') as EntityManager
|
|
222
291
|
const cfFilters = await buildCustomFieldFiltersFromQuery({
|
|
223
292
|
entityIds: [E.customers.customer_entity, E.customers.customer_person_profile],
|
|
224
293
|
query,
|
|
@@ -226,8 +295,8 @@ const crud = makeCrudRoute({
|
|
|
226
295
|
tenantId: ctx.auth?.tenantId ?? null,
|
|
227
296
|
})
|
|
228
297
|
Object.assign(filters, cfFilters)
|
|
229
|
-
} catch {
|
|
230
|
-
|
|
298
|
+
} catch (err) {
|
|
299
|
+
console.warn('[customers.people.list] custom field filter resolution failed; falling back to base filters', err)
|
|
231
300
|
}
|
|
232
301
|
}
|
|
233
302
|
if (ctx && advancedFilterState) {
|
|
@@ -280,11 +349,12 @@ const crud = makeCrudRoute({
|
|
|
280
349
|
type: 'left',
|
|
281
350
|
},
|
|
282
351
|
],
|
|
283
|
-
transformItem: (item
|
|
284
|
-
if (!item) return item
|
|
285
|
-
const
|
|
352
|
+
transformItem: (item) => {
|
|
353
|
+
if (!item || typeof item !== 'object') return item
|
|
354
|
+
const record = item as Record<string, unknown>
|
|
355
|
+
const normalized: Record<string, unknown> = { ...record }
|
|
286
356
|
delete normalized.kind
|
|
287
|
-
const cfEntries = extractAllCustomFieldEntries(
|
|
357
|
+
const cfEntries = extractAllCustomFieldEntries(record)
|
|
288
358
|
for (const key of Object.keys(normalized)) {
|
|
289
359
|
if (key.startsWith('cf:')) {
|
|
290
360
|
delete normalized[key]
|
|
@@ -351,6 +421,27 @@ const crud = makeCrudRoute({
|
|
|
351
421
|
.filter((id: string | null): id is string => typeof id === 'string' && id.length > 0)
|
|
352
422
|
if (!ids.length) return
|
|
353
423
|
|
|
424
|
+
const em = ctx.container.resolve('em') as EntityManager
|
|
425
|
+
const decryptionScope = {
|
|
426
|
+
tenantId: ctx.auth?.tenantId ?? null,
|
|
427
|
+
organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
|
|
428
|
+
}
|
|
429
|
+
const entities = await findWithDecryption(
|
|
430
|
+
em,
|
|
431
|
+
CustomerEntity,
|
|
432
|
+
{
|
|
433
|
+
id: { $in: ids },
|
|
434
|
+
deletedAt: null,
|
|
435
|
+
kind: 'person',
|
|
436
|
+
} as FilterQuery<CustomerEntity>,
|
|
437
|
+
undefined,
|
|
438
|
+
decryptionScope,
|
|
439
|
+
)
|
|
440
|
+
const entitiesById = new Map<string, CustomerEntity>()
|
|
441
|
+
for (const entity of entities) {
|
|
442
|
+
entitiesById.set(entity.id, entity)
|
|
443
|
+
}
|
|
444
|
+
|
|
354
445
|
const where: Record<string, unknown> = {
|
|
355
446
|
entity: { $in: ids },
|
|
356
447
|
tenantId: ctx.auth?.tenantId ?? null,
|
|
@@ -360,42 +451,54 @@ const crud = makeCrudRoute({
|
|
|
360
451
|
}
|
|
361
452
|
|
|
362
453
|
const profiles = await findWithDecryption(
|
|
363
|
-
|
|
454
|
+
em,
|
|
364
455
|
CustomerPersonProfile,
|
|
365
|
-
where as
|
|
366
|
-
{ populate: ['entity', 'company'] }
|
|
367
|
-
|
|
368
|
-
tenantId: ctx.auth?.tenantId ?? null,
|
|
369
|
-
organizationId: ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null,
|
|
370
|
-
},
|
|
456
|
+
where as FilterQuery<CustomerPersonProfile>,
|
|
457
|
+
{ populate: ['entity', 'company'] },
|
|
458
|
+
decryptionScope,
|
|
371
459
|
)
|
|
372
460
|
|
|
373
461
|
const profilesByEntityId = new Map<string, CustomerPersonProfile>()
|
|
374
462
|
for (const profile of profiles) {
|
|
375
|
-
const
|
|
463
|
+
const profileEntity = (profile as { entity?: { id?: unknown } }).entity
|
|
464
|
+
const entityId = typeof profileEntity?.id === 'string' ? profileEntity.id : null
|
|
376
465
|
if (entityId) profilesByEntityId.set(entityId, profile)
|
|
377
466
|
}
|
|
378
467
|
|
|
379
468
|
payload.items = items.map((item: unknown) => {
|
|
380
469
|
if (!item || typeof item !== 'object') return item
|
|
381
470
|
const record = item as Record<string, unknown>
|
|
471
|
+
const entity = typeof record.id === 'string' ? entitiesById.get(record.id) : undefined
|
|
382
472
|
const profile = typeof record.id === 'string' ? profilesByEntityId.get(record.id) : undefined
|
|
383
|
-
if (!profile) return item
|
|
473
|
+
if (!entity && !profile) return item
|
|
384
474
|
return {
|
|
385
475
|
...record,
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
476
|
+
display_name: entity?.displayName ?? record.display_name ?? null,
|
|
477
|
+
description: entity?.description ?? record.description ?? null,
|
|
478
|
+
owner_user_id: entity?.ownerUserId ?? record.owner_user_id ?? null,
|
|
479
|
+
primary_email: entity?.primaryEmail ?? record.primary_email ?? null,
|
|
480
|
+
primary_phone: entity?.primaryPhone ?? record.primary_phone ?? null,
|
|
481
|
+
status: entity?.status ?? record.status ?? null,
|
|
482
|
+
lifecycle_stage: entity?.lifecycleStage ?? record.lifecycle_stage ?? null,
|
|
483
|
+
source: entity?.source ?? record.source ?? null,
|
|
484
|
+
next_interaction_at: entity?.nextInteractionAt ? entity.nextInteractionAt.toISOString() : record.next_interaction_at ?? null,
|
|
485
|
+
next_interaction_name: entity?.nextInteractionName ?? record.next_interaction_name ?? null,
|
|
486
|
+
next_interaction_ref_id: entity?.nextInteractionRefId ?? record.next_interaction_ref_id ?? null,
|
|
487
|
+
next_interaction_icon: entity?.nextInteractionIcon ?? record.next_interaction_icon ?? null,
|
|
488
|
+
next_interaction_color: entity?.nextInteractionColor ?? record.next_interaction_color ?? null,
|
|
489
|
+
first_name: profile?.firstName ?? null,
|
|
490
|
+
last_name: profile?.lastName ?? null,
|
|
491
|
+
preferred_name: profile?.preferredName ?? null,
|
|
492
|
+
job_title: profile?.jobTitle ?? null,
|
|
493
|
+
department: profile?.department ?? null,
|
|
494
|
+
seniority: profile?.seniority ?? null,
|
|
495
|
+
timezone: profile?.timezone ?? null,
|
|
496
|
+
linked_in_url: profile?.linkedInUrl ?? null,
|
|
497
|
+
twitter_url: profile?.twitterUrl ?? null,
|
|
395
498
|
company_entity_id:
|
|
396
|
-
profile
|
|
499
|
+
profile?.company && typeof profile.company === 'object'
|
|
397
500
|
? profile.company.id
|
|
398
|
-
: profile
|
|
501
|
+
: profile?.company ?? null,
|
|
399
502
|
}
|
|
400
503
|
})
|
|
401
504
|
},
|
|
@@ -181,6 +181,8 @@ async function ensureCanonicalTodoBridge(
|
|
|
181
181
|
await commandBus.execute('customers.interactions.create', {
|
|
182
182
|
input: {
|
|
183
183
|
id: link.todoId,
|
|
184
|
+
tenantId: link.tenantId,
|
|
185
|
+
organizationId: link.organizationId,
|
|
184
186
|
entityId,
|
|
185
187
|
interactionType: 'task',
|
|
186
188
|
title: detail?.title ?? null,
|
|
@@ -344,6 +346,8 @@ export async function POST(request: Request): Promise<Response> {
|
|
|
344
346
|
|
|
345
347
|
const { result } = await commandBus.execute('customers.interactions.create', {
|
|
346
348
|
input: {
|
|
349
|
+
tenantId: auth.tenantId,
|
|
350
|
+
organizationId: selectedOrganizationId ?? auth.orgId,
|
|
347
351
|
entityId: body.entityId,
|
|
348
352
|
interactionType: 'task',
|
|
349
353
|
title: body.title,
|
|
@@ -234,6 +234,42 @@ export function applyEntityIdRestriction(
|
|
|
234
234
|
filters.id = ids.length > 0 ? { $in: ids } : { $eq: NO_MATCH_ID }
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
export function applyEntityIdExclusion(
|
|
238
|
+
filters: Record<string, unknown>,
|
|
239
|
+
ids: string[],
|
|
240
|
+
): void {
|
|
241
|
+
const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.length > 0)))
|
|
242
|
+
if (!uniqueIds.length) return
|
|
243
|
+
|
|
244
|
+
const currentIdFilter =
|
|
245
|
+
filters.id && typeof filters.id === 'object' && !Array.isArray(filters.id)
|
|
246
|
+
? (filters.id as { $eq?: unknown; $in?: unknown; $nin?: unknown })
|
|
247
|
+
: null
|
|
248
|
+
const currentEq = typeof currentIdFilter?.$eq === 'string' ? currentIdFilter.$eq : null
|
|
249
|
+
const currentIn = Array.isArray(currentIdFilter?.$in)
|
|
250
|
+
? currentIdFilter.$in.filter((value): value is string => typeof value === 'string' && value.length > 0)
|
|
251
|
+
: null
|
|
252
|
+
const currentNotIn = Array.isArray(currentIdFilter?.$nin)
|
|
253
|
+
? currentIdFilter.$nin.filter((value): value is string => typeof value === 'string' && value.length > 0)
|
|
254
|
+
: []
|
|
255
|
+
|
|
256
|
+
if (currentEq) {
|
|
257
|
+
filters.id = uniqueIds.includes(currentEq) ? { $eq: NO_MATCH_ID } : { $eq: currentEq }
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (currentIn) {
|
|
262
|
+
const nextIds = currentIn.filter((id) => !uniqueIds.includes(id))
|
|
263
|
+
filters.id = nextIds.length > 0 ? { $in: nextIds } : { $eq: NO_MATCH_ID }
|
|
264
|
+
return
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
filters.id = {
|
|
268
|
+
...(currentIdFilter ?? {}),
|
|
269
|
+
$nin: Array.from(new Set([...currentNotIn, ...uniqueIds])),
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
237
273
|
export function consumeAdvancedFilterState(query: Record<string, unknown>) {
|
|
238
274
|
const state = deserializeAdvancedFilter(query)
|
|
239
275
|
if (!state) return null
|
|
@@ -2,9 +2,7 @@ import Link from 'next/link'
|
|
|
2
2
|
import { Page, PageBody } from '@open-mercato/ui/backend/Page'
|
|
3
3
|
import { Button } from '@open-mercato/ui/primitives/button'
|
|
4
4
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
5
|
-
import
|
|
6
|
-
import AddressFormatSettings from '../../../components/AddressFormatSettings'
|
|
7
|
-
import PipelineSettings from '../../../components/PipelineSettings'
|
|
5
|
+
import CustomersConfigurationSections from '../../../components/CustomersConfigurationSections'
|
|
8
6
|
|
|
9
7
|
export default async function CustomersConfigurationPage({
|
|
10
8
|
searchParams,
|
|
@@ -27,9 +25,7 @@ export default async function CustomersConfigurationPage({
|
|
|
27
25
|
</Link>
|
|
28
26
|
</Button>
|
|
29
27
|
) : null}
|
|
30
|
-
<
|
|
31
|
-
<PipelineSettings />
|
|
32
|
-
<DictionarySettings />
|
|
28
|
+
<CustomersConfigurationSections />
|
|
33
29
|
</div>
|
|
34
30
|
</PageBody>
|
|
35
31
|
</Page>
|