@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.222
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/README.md +2 -1
- package/package.json +13 -13
- package/src/lib/components/activity-list.js +12 -5
- package/src/lib/components/activity-list.js.map +1 -1
- package/src/lib/components/companies-bulk-bar.d.ts +1 -4
- package/src/lib/components/companies-bulk-bar.js +7 -20
- package/src/lib/components/companies-bulk-bar.js.map +1 -1
- package/src/lib/components/companies-section.d.ts +3 -3
- package/src/lib/components/companies-section.js +149 -46
- package/src/lib/components/companies-section.js.map +1 -1
- package/src/lib/components/company-edit-drawer.js +281 -20
- package/src/lib/components/company-edit-drawer.js.map +1 -1
- package/src/lib/components/company-properties-card.js +99 -8
- package/src/lib/components/company-properties-card.js.map +1 -1
- package/src/lib/components/contact-detail-page.js +3 -1
- package/src/lib/components/contact-detail-page.js.map +1 -1
- package/src/lib/components/contact-merge-dialog.js +33 -10
- package/src/lib/components/contact-merge-dialog.js.map +1 -1
- package/src/lib/components/contact-properties-card.d.ts +0 -69
- package/src/lib/components/contact-properties-card.js +350 -60
- package/src/lib/components/contact-properties-card.js.map +1 -1
- package/src/lib/components/contact-reports-to-field.d.ts +46 -0
- package/src/lib/components/contact-reports-to-field.js +67 -0
- package/src/lib/components/contact-reports-to-field.js.map +1 -0
- package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
- package/src/lib/components/contacts-bulk-bar.js +7 -19
- package/src/lib/components/contacts-bulk-bar.js.map +1 -1
- package/src/lib/components/contacts-section.js +46 -33
- package/src/lib/components/contacts-section.js.map +1 -1
- package/src/lib/components/crm-call-actions.d.ts +10 -0
- package/src/lib/components/crm-call-actions.js +26 -9
- package/src/lib/components/crm-call-actions.js.map +1 -1
- package/src/lib/components/crm-record-picker.d.ts +15 -0
- package/src/lib/components/crm-record-picker.js +16 -10
- package/src/lib/components/crm-record-picker.js.map +1 -1
- package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
- package/src/lib/components/crm-transfer-buttons.js +167 -0
- package/src/lib/components/crm-transfer-buttons.js.map +1 -0
- package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
- package/src/lib/components/deal-contact-roles-card.js +368 -0
- package/src/lib/components/deal-contact-roles-card.js.map +1 -0
- package/src/lib/components/deal-detail-page.d.ts +3 -2
- package/src/lib/components/deal-detail-page.js +25 -6
- package/src/lib/components/deal-detail-page.js.map +1 -1
- package/src/lib/components/deal-edit-drawer.d.ts +10 -0
- package/src/lib/components/deal-edit-drawer.js +219 -10
- package/src/lib/components/deal-edit-drawer.js.map +1 -1
- package/src/lib/components/deal-properties-card.d.ts +7 -0
- package/src/lib/components/deal-properties-card.js +34 -3
- package/src/lib/components/deal-properties-card.js.map +1 -1
- package/src/lib/components/deal-stage-card.d.ts +4 -0
- package/src/lib/components/deal-stage-card.js +10 -2
- package/src/lib/components/deal-stage-card.js.map +1 -1
- package/src/lib/components/deals-bulk-bar.d.ts +0 -3
- package/src/lib/components/deals-bulk-bar.js +7 -20
- package/src/lib/components/deals-bulk-bar.js.map +1 -1
- package/src/lib/components/deals-section.d.ts +3 -3
- package/src/lib/components/deals-section.js +123 -63
- package/src/lib/components/deals-section.js.map +1 -1
- package/src/lib/components/fields-section.js +31 -17
- package/src/lib/components/fields-section.js.map +1 -1
- package/src/lib/components/lead-convert-dialog.d.ts +4 -0
- package/src/lib/components/lead-convert-dialog.js +23 -1
- package/src/lib/components/lead-convert-dialog.js.map +1 -1
- package/src/lib/components/lead-detail-page.js +8 -2
- package/src/lib/components/lead-detail-page.js.map +1 -1
- package/src/lib/components/lead-profile-fields.d.ts +71 -0
- package/src/lib/components/lead-profile-fields.js +386 -0
- package/src/lib/components/lead-profile-fields.js.map +1 -0
- package/src/lib/components/lead-properties-card.d.ts +2 -1
- package/src/lib/components/lead-properties-card.js +85 -176
- package/src/lib/components/lead-properties-card.js.map +1 -1
- package/src/lib/components/lead-source-select.d.ts +4 -23
- package/src/lib/components/lead-source-select.js +9 -73
- package/src/lib/components/lead-source-select.js.map +1 -1
- package/src/lib/components/lead-status-chip.d.ts +9 -3
- package/src/lib/components/lead-status-chip.js +8 -4
- package/src/lib/components/lead-status-chip.js.map +1 -1
- package/src/lib/components/lead-status-options.d.ts +20 -0
- package/src/lib/components/lead-status-options.js +51 -0
- package/src/lib/components/lead-status-options.js.map +1 -0
- package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
- package/src/lib/components/lead-unqualify-dialog.js +50 -18
- package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
- package/src/lib/components/leads-bulk-bar.d.ts +0 -3
- package/src/lib/components/leads-bulk-bar.js +29 -29
- package/src/lib/components/leads-bulk-bar.js.map +1 -1
- package/src/lib/components/leads-section.js +120 -68
- package/src/lib/components/leads-section.js.map +1 -1
- package/src/lib/components/linked-deals-card.d.ts +4 -0
- package/src/lib/components/linked-deals-card.js +47 -3
- package/src/lib/components/linked-deals-card.js.map +1 -1
- package/src/lib/components/log-activity-dialog.js +43 -3
- package/src/lib/components/log-activity-dialog.js.map +1 -1
- package/src/lib/components/new-contact-drawer.d.ts +8 -0
- package/src/lib/components/new-contact-drawer.js +108 -6
- package/src/lib/components/new-contact-drawer.js.map +1 -1
- package/src/lib/components/new-lead-drawer.d.ts +9 -2
- package/src/lib/components/new-lead-drawer.js +88 -121
- package/src/lib/components/new-lead-drawer.js.map +1 -1
- package/src/lib/components/picklist-select.d.ts +36 -0
- package/src/lib/components/picklist-select.js +114 -0
- package/src/lib/components/picklist-select.js.map +1 -0
- package/src/lib/components/picklist-values-card.d.ts +34 -0
- package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
- package/src/lib/components/picklist-values-card.js.map +1 -0
- package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
- package/src/lib/components/pipeline-stages-dialog.js +26 -4
- package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
- package/src/lib/components/pipelines-dialog.js +15 -6
- package/src/lib/components/pipelines-dialog.js.map +1 -1
- package/src/lib/components/recent-activity-feed.js +20 -5
- package/src/lib/components/recent-activity-feed.js.map +1 -1
- package/src/lib/components/recipes-card.js +4 -2
- package/src/lib/components/recipes-card.js.map +1 -1
- package/src/lib/components/record-tasks-card.js +15 -8
- package/src/lib/components/record-tasks-card.js.map +1 -1
- package/src/lib/components/reports/forecast-card.d.ts +6 -0
- package/src/lib/components/reports/forecast-card.js +101 -3
- package/src/lib/components/reports/forecast-card.js.map +1 -1
- package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
- package/src/lib/components/reports/lead-funnel-card.js +9 -5
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
- package/src/lib/components/reports/lead-source-card.d.ts +23 -0
- package/src/lib/components/reports/lead-source-card.js +318 -0
- package/src/lib/components/reports/lead-source-card.js.map +1 -0
- package/src/lib/components/reports/report-export.js +1 -1
- package/src/lib/components/reports/report-export.js.map +1 -1
- package/src/lib/components/reports-section.js +8 -0
- package/src/lib/components/reports-section.js.map +1 -1
- package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
- package/src/lib/components/sharing-rule-drawer.js +108 -19
- package/src/lib/components/sharing-rule-drawer.js.map +1 -1
- package/src/lib/components/sharing-rules-card.js +11 -3
- package/src/lib/components/sharing-rules-card.js.map +1 -1
- package/src/lib/components/task-cells.d.ts +9 -1
- package/src/lib/components/task-cells.js +9 -4
- package/src/lib/components/task-cells.js.map +1 -1
- package/src/lib/components/task-edit-drawer.js +111 -43
- package/src/lib/components/task-edit-drawer.js.map +1 -1
- package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
- package/src/lib/components/tasks-bulk-bar.js +7 -20
- package/src/lib/components/tasks-bulk-bar.js.map +1 -1
- package/src/lib/components/tasks-calendar.d.ts +3 -0
- package/src/lib/components/tasks-calendar.js +8 -1
- package/src/lib/components/tasks-calendar.js.map +1 -1
- package/src/lib/components/tasks-section.d.ts +3 -3
- package/src/lib/components/tasks-section.js +58 -43
- package/src/lib/components/tasks-section.js.map +1 -1
- package/src/lib/constants/api-routes.d.ts +2 -9
- package/src/lib/constants/api-routes.js +1 -7
- package/src/lib/constants/api-routes.js.map +1 -1
- package/src/lib/constants/bundle-common.d.ts +6 -0
- package/src/lib/constants/bundle-common.js +11 -0
- package/src/lib/constants/bundle-common.js.map +1 -1
- package/src/lib/constants/company-filters.d.ts +14 -0
- package/src/lib/constants/company-filters.js +51 -1
- package/src/lib/constants/company-filters.js.map +1 -1
- package/src/lib/constants/contact-filters.d.ts +2 -0
- package/src/lib/constants/contact-filters.js +18 -1
- package/src/lib/constants/contact-filters.js.map +1 -1
- package/src/lib/constants/deal-filters.d.ts +22 -1
- package/src/lib/constants/deal-filters.js +67 -4
- package/src/lib/constants/deal-filters.js.map +1 -1
- package/src/lib/declarations.console-server.d.ts +3 -0
- package/src/lib/declarations.console-server.js +35 -0
- package/src/lib/declarations.console-server.js.map +1 -1
- package/src/lib/declarations.d.ts +26 -0
- package/src/lib/declarations.js +35 -0
- package/src/lib/declarations.js.map +1 -0
- package/src/lib/declarations.server.d.ts +11 -0
- package/src/lib/declarations.server.js +92 -1
- package/src/lib/declarations.server.js.map +1 -1
- package/src/lib/hooks/use-company-picklists.d.ts +15 -0
- package/src/lib/hooks/use-company-picklists.js +55 -0
- package/src/lib/hooks/use-company-picklists.js.map +1 -0
- package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
- package/src/lib/hooks/use-crm-picklist.js +53 -0
- package/src/lib/hooks/use-crm-picklist.js.map +1 -0
- package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
- package/src/lib/hooks/use-crm-record-names.js +45 -19
- package/src/lib/hooks/use-crm-record-names.js.map +1 -1
- package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
- package/src/lib/hooks/use-crm-task-picklists.js +45 -0
- package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
- package/src/lib/hooks/use-deals.d.ts +14 -0
- package/src/lib/hooks/use-deals.js +29 -0
- package/src/lib/hooks/use-deals.js.map +1 -1
- package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
- package/src/lib/hooks/use-lead-picklists.js +46 -0
- package/src/lib/hooks/use-lead-picklists.js.map +1 -0
- package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
- package/src/lib/hooks/use-lead-source-picklist.js +12 -22
- package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
- package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
- package/src/lib/hooks/use-lead-status-picklist.js +40 -0
- package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
- package/src/lib/model/companies.d.ts +32 -3
- package/src/lib/model/companies.js +133 -16
- package/src/lib/model/companies.js.map +1 -1
- package/src/lib/model/contact-merge.d.ts +27 -3
- package/src/lib/model/contact-merge.js +81 -7
- package/src/lib/model/contact-merge.js.map +1 -1
- package/src/lib/model/contact-record.d.ts +17 -0
- package/src/lib/model/contact-record.js +15 -1
- package/src/lib/model/contact-record.js.map +1 -1
- package/src/lib/model/contact-update.d.ts +31 -2
- package/src/lib/model/contact-update.js +14 -0
- package/src/lib/model/contact-update.js.map +1 -1
- package/src/lib/model/crm-list-query.d.ts +5 -0
- package/src/lib/model/crm-list-query.js +8 -0
- package/src/lib/model/crm-list-query.js.map +1 -1
- package/src/lib/model/crm-recipes.d.ts +40 -0
- package/src/lib/model/crm-recipes.js +244 -0
- package/src/lib/model/crm-recipes.js.map +1 -0
- package/src/lib/model/crm-record-counts.d.ts +36 -0
- package/src/lib/model/crm-record-counts.js +54 -0
- package/src/lib/model/crm-record-counts.js.map +1 -0
- package/src/lib/model/crm-record-lists.d.ts +23 -0
- package/src/lib/model/crm-record-lists.js +161 -0
- package/src/lib/model/crm-record-lists.js.map +1 -0
- package/src/lib/model/crm-reports.d.ts +73 -3
- package/src/lib/model/crm-reports.js +120 -1
- package/src/lib/model/crm-reports.js.map +1 -1
- package/src/lib/model/crm-sharing.d.ts +21 -3
- package/src/lib/model/crm-sharing.js +27 -6
- package/src/lib/model/crm-sharing.js.map +1 -1
- package/src/lib/model/deal-board-model.d.ts +8 -2
- package/src/lib/model/deal-board-model.js +15 -2
- package/src/lib/model/deal-board-model.js.map +1 -1
- package/src/lib/model/deal-contact-roles.d.ts +45 -0
- package/src/lib/model/deal-contact-roles.js +73 -0
- package/src/lib/model/deal-contact-roles.js.map +1 -0
- package/src/lib/model/deal-form-model.d.ts +56 -0
- package/src/lib/model/deal-form-model.js +79 -7
- package/src/lib/model/deal-form-model.js.map +1 -1
- package/src/lib/model/download-text-file.d.ts +23 -0
- package/src/lib/model/download-text-file.js +34 -0
- package/src/lib/model/download-text-file.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +36 -2
- package/src/lib/model/lead-filters.js +123 -2
- package/src/lib/model/lead-filters.js.map +1 -1
- package/src/lib/model/lead-source-direction.d.ts +38 -0
- package/src/lib/model/lead-source-direction.js +52 -0
- package/src/lib/model/lead-source-direction.js.map +1 -0
- package/src/lib/model/picklist-values.d.ts +119 -0
- package/src/lib/model/picklist-values.js +256 -0
- package/src/lib/model/picklist-values.js.map +1 -0
- package/src/lib/model/record-facts-disclosed.d.ts +81 -0
- package/src/lib/model/record-facts-disclosed.js +281 -0
- package/src/lib/model/record-facts-disclosed.js.map +1 -0
- package/src/lib/model/record-facts.d.ts +215 -34
- package/src/lib/model/record-facts.js +307 -128
- package/src/lib/model/record-facts.js.map +1 -1
- package/src/lib/model/task-picklists.d.ts +52 -0
- package/src/lib/model/task-picklists.js +83 -0
- package/src/lib/model/task-picklists.js.map +1 -0
- package/src/lib/model/task-routes.d.ts +13 -0
- package/src/lib/model/task-routes.js +23 -4
- package/src/lib/model/task-routes.js.map +1 -1
- package/src/lib/plan-entitlements.js +6 -4
- package/src/lib/plan-entitlements.js.map +1 -1
- package/src/lib/plugin.js +17 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/api-v1/contacts.js +220 -14
- package/src/lib/server/api-v1/contacts.js.map +1 -1
- package/src/lib/server/api-v1/crm-activities.js +14 -1
- package/src/lib/server/api-v1/crm-activities.js.map +1 -1
- package/src/lib/server/api-v1/crm-companies.js +123 -14
- package/src/lib/server/api-v1/crm-companies.js.map +1 -1
- package/src/lib/server/api-v1/crm-deals.js +291 -26
- package/src/lib/server/api-v1/crm-deals.js.map +1 -1
- package/src/lib/server/api-v1/crm-leads.js +144 -38
- package/src/lib/server/api-v1/crm-leads.js.map +1 -1
- package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
- package/src/lib/server/api-v1/crm-pipelines.js +8 -2
- package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
- package/src/lib/server/api-v1/crm-tasks.js +75 -33
- package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
- package/src/lib/server/api-v1/openapi.d.ts +0 -11
- package/src/lib/server/api-v1/openapi.js +171 -16
- package/src/lib/server/api-v1/openapi.js.map +1 -1
- package/src/lib/server/assign-contact-owner.d.ts +162 -0
- package/src/lib/server/assign-contact-owner.js +340 -0
- package/src/lib/server/assign-contact-owner.js.map +1 -0
- package/src/lib/server/associate-company-by-domain.d.ts +70 -0
- package/src/lib/server/associate-company-by-domain.js +153 -0
- package/src/lib/server/associate-company-by-domain.js.map +1 -0
- package/src/lib/server/automation-steps.d.ts +139 -0
- package/src/lib/server/automation-steps.js +472 -0
- package/src/lib/server/automation-steps.js.map +1 -0
- package/src/lib/server/capture-contact.js +65 -21
- package/src/lib/server/capture-contact.js.map +1 -1
- package/src/lib/server/capture-host-contact.d.ts +104 -0
- package/src/lib/server/capture-host-contact.js +151 -0
- package/src/lib/server/capture-host-contact.js.map +1 -0
- package/src/lib/server/company-children.d.ts +25 -0
- package/src/lib/server/company-children.js +42 -0
- package/src/lib/server/company-children.js.map +1 -0
- package/src/lib/server/company-delete.d.ts +18 -0
- package/src/lib/server/company-delete.js +44 -21
- package/src/lib/server/company-delete.js.map +1 -1
- package/src/lib/server/contact-email-history.js +21 -19
- package/src/lib/server/contact-email-history.js.map +1 -1
- package/src/lib/server/contact-remove.js +27 -2
- package/src/lib/server/contact-remove.js.map +1 -1
- package/src/lib/server/contact-reports-to.d.ts +61 -0
- package/src/lib/server/contact-reports-to.js +114 -0
- package/src/lib/server/contact-reports-to.js.map +1 -0
- package/src/lib/server/contact-update.d.ts +42 -1
- package/src/lib/server/contact-update.js +204 -23
- package/src/lib/server/contact-update.js.map +1 -1
- package/src/lib/server/convert-host-lead.d.ts +46 -1
- package/src/lib/server/convert-host-lead.js +173 -15
- package/src/lib/server/convert-host-lead.js.map +1 -1
- package/src/lib/server/convert-open-lead.js +12 -5
- package/src/lib/server/convert-open-lead.js.map +1 -1
- package/src/lib/server/crm-record-indexes.d.ts +45 -0
- package/src/lib/server/crm-record-indexes.js +78 -0
- package/src/lib/server/crm-record-indexes.js.map +1 -0
- package/src/lib/server/crm-sharing.d.ts +9 -1
- package/src/lib/server/crm-sharing.js +23 -3
- package/src/lib/server/crm-sharing.js.map +1 -1
- package/src/lib/server/deal-contact-roles.d.ts +27 -0
- package/src/lib/server/deal-contact-roles.js +89 -0
- package/src/lib/server/deal-contact-roles.js.map +1 -0
- package/src/lib/server/lead-convert.d.ts +5 -0
- package/src/lib/server/lead-convert.js +19 -3
- package/src/lib/server/lead-convert.js.map +1 -1
- package/src/lib/server/lead-create.d.ts +17 -2
- package/src/lib/server/lead-create.js +46 -14
- package/src/lib/server/lead-create.js.map +1 -1
- package/src/lib/server/lead-nurturing.d.ts +6 -0
- package/src/lib/server/lead-nurturing.js +57 -20
- package/src/lib/server/lead-nurturing.js.map +1 -1
- package/src/lib/server/lead-picklists.d.ts +35 -0
- package/src/lib/server/lead-picklists.js +52 -0
- package/src/lib/server/lead-picklists.js.map +1 -0
- package/src/lib/server/lead-source-picklist.d.ts +1 -13
- package/src/lib/server/lead-source-picklist.js +6 -33
- package/src/lib/server/lead-source-picklist.js.map +1 -1
- package/src/lib/server/merge-contacts.js +22 -4
- package/src/lib/server/merge-contacts.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +53 -0
- package/src/lib/server/person-eraser.js +149 -0
- package/src/lib/server/person-eraser.js.map +1 -0
- package/src/lib/server/person-records.d.ts +69 -0
- package/src/lib/server/person-records.js +317 -0
- package/src/lib/server/person-records.js.map +1 -0
- package/src/lib/server/person-refund.d.ts +97 -0
- package/src/lib/server/person-refund.js +221 -0
- package/src/lib/server/person-refund.js.map +1 -0
- package/src/lib/server/picklist-values.d.ts +21 -0
- package/src/lib/server/picklist-values.js +308 -0
- package/src/lib/server/picklist-values.js.map +1 -0
- package/src/lib/server/read-picklist.d.ts +44 -0
- package/src/lib/server/read-picklist.js +65 -0
- package/src/lib/server/read-picklist.js.map +1 -0
- package/src/lib/server/recipe-routes.js +15 -7
- package/src/lib/server/recipe-routes.js.map +1 -1
- package/src/lib/server/record-email-state.js +7 -1
- package/src/lib/server/record-email-state.js.map +1 -1
- package/src/lib/server/record-facts.d.ts +3 -0
- package/src/lib/server/record-facts.js +233 -31
- package/src/lib/server/record-facts.js.map +1 -1
- package/src/lib/server/record-origin.d.ts +27 -0
- package/src/lib/server/record-origin.js +104 -0
- package/src/lib/server/record-origin.js.map +1 -0
- package/src/lib/server/record-timeline.js +15 -2
- package/src/lib/server/record-timeline.js.map +1 -1
- package/src/lib/server/suite-gate.js +4 -3
- package/src/lib/server/suite-gate.js.map +1 -1
- package/src/lib/server/task-routes.js +30 -16
- package/src/lib/server/task-routes.js.map +1 -1
- package/src/lib/server-deal-stage.d.ts +5 -1
- package/src/lib/server-deal-stage.js +10 -5
- package/src/lib/server-deal-stage.js.map +1 -1
- package/src/lib/server.d.ts +8 -3
- package/src/lib/server.js +47 -43
- package/src/lib/server.js.map +1 -1
- package/src/lib/testing/memory-firestore.d.ts +55 -0
- package/src/lib/testing/memory-firestore.js +335 -0
- package/src/lib/testing/memory-firestore.js.map +1 -0
- package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
- package/src/lib/testing/stand-in-email-send-index.js +49 -0
- package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
- package/src/lib/transfer/activities.d.ts +30 -0
- package/src/lib/transfer/activities.js +132 -0
- package/src/lib/transfer/activities.js.map +1 -0
- package/src/lib/transfer/aliases.d.ts +22 -0
- package/src/lib/transfer/aliases.js +1342 -0
- package/src/lib/transfer/aliases.js.map +1 -0
- package/src/lib/transfer/common.d.ts +222 -0
- package/src/lib/transfer/common.js +832 -0
- package/src/lib/transfer/common.js.map +1 -0
- package/src/lib/transfer/companies.d.ts +43 -0
- package/src/lib/transfer/companies.js +549 -0
- package/src/lib/transfer/companies.js.map +1 -0
- package/src/lib/transfer/contacts.d.ts +31 -0
- package/src/lib/transfer/contacts.js +727 -0
- package/src/lib/transfer/contacts.js.map +1 -0
- package/src/lib/transfer/deals.d.ts +66 -0
- package/src/lib/transfer/deals.js +698 -0
- package/src/lib/transfer/deals.js.map +1 -0
- package/src/lib/transfer/email-templates-package.d.ts +40 -0
- package/src/lib/transfer/email-templates-package.js +76 -0
- package/src/lib/transfer/email-templates-package.js.map +1 -0
- package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
- package/src/lib/transfer/email-templates-package.server.js +176 -0
- package/src/lib/transfer/email-templates-package.server.js.map +1 -0
- package/src/lib/transfer/fields.d.ts +102 -0
- package/src/lib/transfer/fields.js +1755 -0
- package/src/lib/transfer/fields.js.map +1 -0
- package/src/lib/transfer/leads.d.ts +30 -0
- package/src/lib/transfer/leads.js +582 -0
- package/src/lib/transfer/leads.js.map +1 -0
- package/src/lib/transfer/pipelines.d.ts +21 -0
- package/src/lib/transfer/pipelines.js +172 -0
- package/src/lib/transfer/pipelines.js.map +1 -0
- package/src/lib/transfer/register.d.ts +47 -0
- package/src/lib/transfer/register.js +277 -0
- package/src/lib/transfer/register.js.map +1 -0
- package/src/lib/transfer/tasks.d.ts +30 -0
- package/src/lib/transfer/tasks.js +418 -0
- package/src/lib/transfer/tasks.js.map +1 -0
- package/src/lib/transfer/ui.d.ts +20 -0
- package/src/lib/transfer/ui.js +42 -0
- package/src/lib/transfer/ui.js.map +1 -0
- package/src/lib/components/company-import-drawer.d.ts +0 -42
- package/src/lib/components/company-import-drawer.js +0 -99
- package/src/lib/components/company-import-drawer.js.map +0 -1
- package/src/lib/components/contact-import-drawer.d.ts +0 -46
- package/src/lib/components/contact-import-drawer.js +0 -149
- package/src/lib/components/contact-import-drawer.js.map +0 -1
- package/src/lib/components/crm-export-all-button.d.ts +0 -39
- package/src/lib/components/crm-export-all-button.js +0 -98
- package/src/lib/components/crm-export-all-button.js.map +0 -1
- package/src/lib/components/csv-import-drawer.d.ts +0 -139
- package/src/lib/components/csv-import-drawer.js +0 -757
- package/src/lib/components/csv-import-drawer.js.map +0 -1
- package/src/lib/components/deal-import-drawer.d.ts +0 -24
- package/src/lib/components/deal-import-drawer.js +0 -83
- package/src/lib/components/deal-import-drawer.js.map +0 -1
- package/src/lib/components/lead-import-drawer.d.ts +0 -27
- package/src/lib/components/lead-import-drawer.js +0 -118
- package/src/lib/components/lead-import-drawer.js.map +0 -1
- package/src/lib/components/lead-source-values-card.d.ts +0 -27
- package/src/lib/components/lead-source-values-card.js.map +0 -1
- package/src/lib/components/task-import-drawer.d.ts +0 -24
- package/src/lib/components/task-import-drawer.js +0 -82
- package/src/lib/components/task-import-drawer.js.map +0 -1
- package/src/lib/model/companies-csv.d.ts +0 -36
- package/src/lib/model/companies-csv.js +0 -38
- package/src/lib/model/companies-csv.js.map +0 -1
- package/src/lib/model/contacts-csv.d.ts +0 -54
- package/src/lib/model/contacts-csv.js +0 -67
- package/src/lib/model/contacts-csv.js.map +0 -1
- package/src/lib/model/crm-company-import.d.ts +0 -154
- package/src/lib/model/crm-company-import.js +0 -331
- package/src/lib/model/crm-company-import.js.map +0 -1
- package/src/lib/model/crm-csv.d.ts +0 -239
- package/src/lib/model/crm-csv.js +0 -467
- package/src/lib/model/crm-csv.js.map +0 -1
- package/src/lib/model/crm-deal-import.d.ts +0 -112
- package/src/lib/model/crm-deal-import.js +0 -263
- package/src/lib/model/crm-deal-import.js.map +0 -1
- package/src/lib/model/crm-import.d.ts +0 -250
- package/src/lib/model/crm-import.js +0 -467
- package/src/lib/model/crm-import.js.map +0 -1
- package/src/lib/model/crm-lead-import.d.ts +0 -138
- package/src/lib/model/crm-lead-import.js +0 -446
- package/src/lib/model/crm-lead-import.js.map +0 -1
- package/src/lib/model/crm-task-import.d.ts +0 -94
- package/src/lib/model/crm-task-import.js +0 -275
- package/src/lib/model/crm-task-import.js.map +0 -1
- package/src/lib/model/deals-csv.d.ts +0 -32
- package/src/lib/model/deals-csv.js +0 -36
- package/src/lib/model/deals-csv.js.map +0 -1
- package/src/lib/model/import-column-shapes.d.ts +0 -36
- package/src/lib/model/import-column-shapes.js +0 -76
- package/src/lib/model/import-column-shapes.js.map +0 -1
- package/src/lib/model/lead-source-values.d.ts +0 -82
- package/src/lib/model/lead-source-values.js +0 -149
- package/src/lib/model/lead-source-values.js.map +0 -1
- package/src/lib/model/leads-csv.d.ts +0 -40
- package/src/lib/model/leads-csv.js +0 -40
- package/src/lib/model/leads-csv.js.map +0 -1
- package/src/lib/model/tasks-csv.d.ts +0 -28
- package/src/lib/model/tasks-csv.js +0 -28
- package/src/lib/model/tasks-csv.js.map +0 -1
- package/src/lib/server/companies-import.d.ts +0 -57
- package/src/lib/server/companies-import.js +0 -242
- package/src/lib/server/companies-import.js.map +0 -1
- package/src/lib/server/contacts-import.d.ts +0 -109
- package/src/lib/server/contacts-import.js +0 -393
- package/src/lib/server/contacts-import.js.map +0 -1
- package/src/lib/server/deals-import.d.ts +0 -76
- package/src/lib/server/deals-import.js +0 -248
- package/src/lib/server/deals-import.js.map +0 -1
- package/src/lib/server/export-route.d.ts +0 -60
- package/src/lib/server/export-route.js +0 -447
- package/src/lib/server/export-route.js.map +0 -1
- package/src/lib/server/import-context.d.ts +0 -87
- package/src/lib/server/import-context.js +0 -182
- package/src/lib/server/import-context.js.map +0 -1
- package/src/lib/server/lead-source-values.d.ts +0 -50
- package/src/lib/server/lead-source-values.js +0 -191
- package/src/lib/server/lead-source-values.js.map +0 -1
- package/src/lib/server/leads-import.d.ts +0 -84
- package/src/lib/server/leads-import.js +0 -367
- package/src/lib/server/leads-import.js.map +0 -1
- package/src/lib/server/tasks-import.d.ts +0 -54
- package/src/lib/server/tasks-import.js +0 -160
- package/src/lib/server/tasks-import.js.map +0 -1
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Aglyn LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/ /**
|
|
17
|
-
* BRINGING A SPREADSHEET OF COMPANIES INTO THE CRM — the pure half
|
|
18
|
-
* (AGL-2621).
|
|
19
|
-
*
|
|
20
|
-
* The contact import's three stages (`crm-import.ts`) over the company
|
|
21
|
-
* vocabulary: a header row is matched to a proposed mapping, one line is
|
|
22
|
-
* mapped to a raw row of verbatim strings, and the server normalizes each
|
|
23
|
-
* row through the SAME functions the company drawer runs —
|
|
24
|
-
* `normalizeCompanyDomain` for the key, `normalizeCompanyWebsite` for the
|
|
25
|
-
* link, `normalizePhone` for E.164, `normalizeAddress` for the postal shape
|
|
26
|
-
* — so an imported company and a typed one are the same document.
|
|
27
|
-
*
|
|
28
|
-
* ## The name is the one thing a row must have
|
|
29
|
-
*
|
|
30
|
-
* A company is matched by its DOMAIN first and its name second, because a
|
|
31
|
-
* domain is a key and a name is a spelling: two files calling one business
|
|
32
|
-
* "Acme" and "Acme Inc" meet at `acme.com`. But a row with a domain and no
|
|
33
|
-
* name would create a record the list cannot caption, so the name is
|
|
34
|
-
* required and the domain optional — the opposite of the contact import,
|
|
35
|
-
* where the address is both the key and the caption.
|
|
36
|
-
*
|
|
37
|
-
* ## A bad cell is dropped and named; a bad row is skipped and named
|
|
38
|
-
*
|
|
39
|
-
* The contact import's rule, unchanged: a domain that is not a hostname, a
|
|
40
|
-
* phone that is not a number, a website that is not a URL, a country that
|
|
41
|
-
* is not a code — each is left off the record and REPORTED under
|
|
42
|
-
* {@link CompanyImportRow.dropped}, never silently discarded.
|
|
43
|
-
*/ import { normalizeAddress, normalizePhone } from "@aglyn/aglyn/foundation/definitions/contact.types";
|
|
44
|
-
import { normalizeContactEmail } from "@aglyn/aglyn/app-utils/contacts";
|
|
45
|
-
import { normalizeCompanyDomain, normalizeCompanyWebsite } from "@aglyn/aglyn/app-utils/crm";
|
|
46
|
-
import { parseContactImportCustomValue } from "./crm-import.js";
|
|
47
|
-
import { customImportTarget, CSV_IMPORT_CHUNK_SIZE, CSV_IMPORT_MAX_BODY_BYTES, CSV_IMPORT_MAX_ROWS, CSV_IMPORT_PREVIEW_ROWS, emptyImportResult, guessImportMapping, importAliasKeys, importSkippedCsv, importTextValue, mapImportRow, mergeImportResults, parseImportTags } from "@aglyn/aglyn/app-utils/csv-import";
|
|
48
|
-
import { nameSearchKey } from "@aglyn/aglyn/app-utils/name-search";
|
|
49
|
-
/** The shared ceilings, under this collection's names. */ export const COMPANY_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS;
|
|
50
|
-
export const COMPANY_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE;
|
|
51
|
-
export const COMPANY_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES;
|
|
52
|
-
export const COMPANY_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS;
|
|
53
|
-
/** The most tags one company may carry — the same cap a contact has. */ export const COMPANY_IMPORT_TAGS_MAX = 20;
|
|
54
|
-
const NAME_MAX = 120;
|
|
55
|
-
const INDUSTRY_MAX = 80;
|
|
56
|
-
const NOTES_MAX = 4000;
|
|
57
|
-
/** The fields a column may be mapped to, in the order the mapping menu lists them. */ export const COMPANY_IMPORT_FIELDS = [
|
|
58
|
-
'name',
|
|
59
|
-
'domain',
|
|
60
|
-
'website',
|
|
61
|
-
'phone',
|
|
62
|
-
'industry',
|
|
63
|
-
'ownerEmail',
|
|
64
|
-
'addressLine1',
|
|
65
|
-
'addressLine2',
|
|
66
|
-
'addressCity',
|
|
67
|
-
'addressState',
|
|
68
|
-
'addressPostalCode',
|
|
69
|
-
'addressCountry',
|
|
70
|
-
'tags',
|
|
71
|
-
'notes'
|
|
72
|
-
];
|
|
73
|
-
/** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */ export const COMPANY_IMPORT_FIELD_LABELS = {
|
|
74
|
-
name: 'Company name (required)',
|
|
75
|
-
domain: 'Domain',
|
|
76
|
-
website: 'Website',
|
|
77
|
-
phone: 'Phone',
|
|
78
|
-
industry: 'Industry',
|
|
79
|
-
ownerEmail: 'Owner (team member email)',
|
|
80
|
-
addressLine1: 'Address line 1',
|
|
81
|
-
addressLine2: 'Address line 2',
|
|
82
|
-
addressCity: 'City',
|
|
83
|
-
addressState: 'State or region',
|
|
84
|
-
addressPostalCode: 'Postal code',
|
|
85
|
-
addressCountry: 'Country (two-letter code)',
|
|
86
|
-
tags: 'Tags (comma or | separated)',
|
|
87
|
-
notes: 'Notes'
|
|
88
|
-
};
|
|
89
|
-
/**
|
|
90
|
-
* Header aliases per field, matched after the shared header normalization.
|
|
91
|
-
*
|
|
92
|
-
* The vocabulary of the exports people arrive with, and — first in each
|
|
93
|
-
* list — the header this CRM's own companies export writes, so an export
|
|
94
|
-
* re-imports without a hand mapping.
|
|
95
|
-
*/ const FIELD_ALIASES = {
|
|
96
|
-
name: [
|
|
97
|
-
'company',
|
|
98
|
-
'company name',
|
|
99
|
-
'name',
|
|
100
|
-
'organization',
|
|
101
|
-
'organisation',
|
|
102
|
-
'account',
|
|
103
|
-
'account name'
|
|
104
|
-
],
|
|
105
|
-
domain: [
|
|
106
|
-
'domain',
|
|
107
|
-
'company domain',
|
|
108
|
-
'domain name',
|
|
109
|
-
'web domain',
|
|
110
|
-
'email domain'
|
|
111
|
-
],
|
|
112
|
-
website: [
|
|
113
|
-
'website',
|
|
114
|
-
'web site',
|
|
115
|
-
'url',
|
|
116
|
-
'website url',
|
|
117
|
-
'homepage',
|
|
118
|
-
'web'
|
|
119
|
-
],
|
|
120
|
-
phone: [
|
|
121
|
-
'phone',
|
|
122
|
-
'phone number',
|
|
123
|
-
'telephone',
|
|
124
|
-
'company phone',
|
|
125
|
-
'main phone'
|
|
126
|
-
],
|
|
127
|
-
industry: [
|
|
128
|
-
'industry',
|
|
129
|
-
'sector',
|
|
130
|
-
'vertical',
|
|
131
|
-
'category'
|
|
132
|
-
],
|
|
133
|
-
ownerEmail: [
|
|
134
|
-
'owner',
|
|
135
|
-
'owner email',
|
|
136
|
-
'company owner',
|
|
137
|
-
'account owner',
|
|
138
|
-
'assigned to'
|
|
139
|
-
],
|
|
140
|
-
addressLine1: [
|
|
141
|
-
'address line 1',
|
|
142
|
-
'address',
|
|
143
|
-
'street',
|
|
144
|
-
'street address',
|
|
145
|
-
'address 1'
|
|
146
|
-
],
|
|
147
|
-
addressLine2: [
|
|
148
|
-
'address line 2',
|
|
149
|
-
'address 2',
|
|
150
|
-
'street 2',
|
|
151
|
-
'suite'
|
|
152
|
-
],
|
|
153
|
-
addressCity: [
|
|
154
|
-
'city',
|
|
155
|
-
'town',
|
|
156
|
-
'locality'
|
|
157
|
-
],
|
|
158
|
-
addressState: [
|
|
159
|
-
'state',
|
|
160
|
-
'region',
|
|
161
|
-
'province',
|
|
162
|
-
'county',
|
|
163
|
-
'state/region'
|
|
164
|
-
],
|
|
165
|
-
addressPostalCode: [
|
|
166
|
-
'postal code',
|
|
167
|
-
'postcode',
|
|
168
|
-
'zip',
|
|
169
|
-
'zip code',
|
|
170
|
-
'post code'
|
|
171
|
-
],
|
|
172
|
-
addressCountry: [
|
|
173
|
-
'country',
|
|
174
|
-
'country code',
|
|
175
|
-
'country/region'
|
|
176
|
-
],
|
|
177
|
-
tags: [
|
|
178
|
-
'tags',
|
|
179
|
-
'tag',
|
|
180
|
-
'labels',
|
|
181
|
-
'groups'
|
|
182
|
-
],
|
|
183
|
-
notes: [
|
|
184
|
-
'notes',
|
|
185
|
-
'note',
|
|
186
|
-
'description',
|
|
187
|
-
'comments'
|
|
188
|
-
]
|
|
189
|
-
};
|
|
190
|
-
const FIELD_ALIAS_KEYS = importAliasKeys(COMPANY_IMPORT_FIELDS, FIELD_ALIASES);
|
|
191
|
-
/**
|
|
192
|
-
* A proposed mapping from a file's header row, each field taken at most
|
|
193
|
-
* once. `fields` is the org's COMPANY definitions (AGL-2661): a header
|
|
194
|
-
* matching one's label or key maps onto it, and wins over a standard
|
|
195
|
-
* alias, the contact import's rule.
|
|
196
|
-
*/ export function guessCompanyImportMapping(columns, fields = []) {
|
|
197
|
-
return guessImportMapping(columns, COMPANY_IMPORT_FIELDS, FIELD_ALIAS_KEYS, fields);
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* One parsed line under the mapping. Empty cells are left absent; custom
|
|
201
|
-
* values are gathered under `custom` by definition key (AGL-2661).
|
|
202
|
-
*/ export function mapCompanyImportRow(cells, mapping) {
|
|
203
|
-
return mapImportRow(cells, mapping);
|
|
204
|
-
}
|
|
205
|
-
/** How a skip reason reads on screen and in the downloaded file. */ export const COMPANY_IMPORT_SKIP_LABELS = {
|
|
206
|
-
'missing-name': 'No company name',
|
|
207
|
-
duplicate: 'Appears earlier in the file',
|
|
208
|
-
'records-band': 'CRM records limit reached',
|
|
209
|
-
'write-failed': 'Could not be saved'
|
|
210
|
-
};
|
|
211
|
-
/**
|
|
212
|
-
* One raw row as the values that will be written, or the reason it cannot
|
|
213
|
-
* be. Refused only for a missing name; every other unreadable cell is
|
|
214
|
-
* dropped and named.
|
|
215
|
-
*/ export function normalizeCompanyImportRow(raw, /**
|
|
216
|
-
* The org's live COMPANY definitions (AGL-2661): a value under a key
|
|
217
|
-
* with no definition is dropped and reported, because a value nobody
|
|
218
|
-
* defined a field for is a value no surface will ever show.
|
|
219
|
-
*/ fields = []) {
|
|
220
|
-
var _importTextValue;
|
|
221
|
-
const name = (_importTextValue = importTextValue(raw.name, NAME_MAX)) == null ? void 0 : _importTextValue.replace(/\s+/g, ' ');
|
|
222
|
-
if (!name) {
|
|
223
|
-
var _raw_domain;
|
|
224
|
-
return {
|
|
225
|
-
ok: false,
|
|
226
|
-
reason: 'missing-name',
|
|
227
|
-
input: String((_raw_domain = raw.domain) != null ? _raw_domain : '').trim()
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
const dropped = [];
|
|
231
|
-
const drop = (field, value)=>{
|
|
232
|
-
dropped.push({
|
|
233
|
-
field,
|
|
234
|
-
value: String(value != null ? value : '').trim()
|
|
235
|
-
});
|
|
236
|
-
};
|
|
237
|
-
const row = {
|
|
238
|
-
name,
|
|
239
|
-
tags: parseImportTags(raw.tags, COMPANY_IMPORT_TAGS_MAX),
|
|
240
|
-
dropped,
|
|
241
|
-
custom: {}
|
|
242
|
-
};
|
|
243
|
-
const domainText = importTextValue(raw.domain, 300);
|
|
244
|
-
if (domainText) {
|
|
245
|
-
const domain = normalizeCompanyDomain(domainText);
|
|
246
|
-
if (domain) row.domain = domain;
|
|
247
|
-
else drop('domain', domainText);
|
|
248
|
-
}
|
|
249
|
-
const websiteText = importTextValue(raw.website, 600);
|
|
250
|
-
if (websiteText) {
|
|
251
|
-
const website = normalizeCompanyWebsite(websiteText);
|
|
252
|
-
if (website) row.website = website;
|
|
253
|
-
else drop('website', websiteText);
|
|
254
|
-
}
|
|
255
|
-
const phoneText = importTextValue(raw.phone, 64);
|
|
256
|
-
if (phoneText) {
|
|
257
|
-
const phone = normalizePhone(phoneText);
|
|
258
|
-
if (phone) row.phone = phone;
|
|
259
|
-
else drop('phone', phoneText);
|
|
260
|
-
}
|
|
261
|
-
const industry = importTextValue(raw.industry, INDUSTRY_MAX);
|
|
262
|
-
if (industry) row.industry = industry;
|
|
263
|
-
const ownerText = importTextValue(raw.ownerEmail, 320);
|
|
264
|
-
if (ownerText) {
|
|
265
|
-
const owner = normalizeContactEmail(ownerText);
|
|
266
|
-
if (owner) row.ownerEmail = owner;
|
|
267
|
-
else drop('ownerEmail', ownerText);
|
|
268
|
-
}
|
|
269
|
-
const address = normalizeAddress({
|
|
270
|
-
line1: importTextValue(raw.addressLine1, 200),
|
|
271
|
-
line2: importTextValue(raw.addressLine2, 200),
|
|
272
|
-
city: importTextValue(raw.addressCity, 120),
|
|
273
|
-
state: importTextValue(raw.addressState, 120),
|
|
274
|
-
postalCode: importTextValue(raw.addressPostalCode, 32),
|
|
275
|
-
country: importTextValue(raw.addressCountry, 8)
|
|
276
|
-
});
|
|
277
|
-
if (address) row.address = address;
|
|
278
|
-
// The country is the one address part the normalizer drops silently — a
|
|
279
|
-
// typed name is not a code — so it is the one part the report has to name.
|
|
280
|
-
const countryText = importTextValue(raw.addressCountry, 64);
|
|
281
|
-
if (countryText && !(address == null ? void 0 : address.country)) drop('addressCountry', countryText);
|
|
282
|
-
const notes = importTextValue(raw.notes, NOTES_MAX);
|
|
283
|
-
if (notes) row.notes = notes;
|
|
284
|
-
// The contact import's custom rule, over the company's definitions.
|
|
285
|
-
const custom = raw.custom && typeof raw.custom === 'object' && !Array.isArray(raw.custom) ? raw.custom : {};
|
|
286
|
-
const definitions = new Map(fields.map((field)=>[
|
|
287
|
-
field.key,
|
|
288
|
-
field
|
|
289
|
-
]));
|
|
290
|
-
for (const [key, value] of Object.entries(custom)){
|
|
291
|
-
const definition = definitions.get(key);
|
|
292
|
-
if (!definition) {
|
|
293
|
-
dropped.push({
|
|
294
|
-
field: customImportTarget(key),
|
|
295
|
-
value: String(value != null ? value : '').trim()
|
|
296
|
-
});
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
const parsed = parseContactImportCustomValue(definition, value);
|
|
300
|
-
if (!parsed) {
|
|
301
|
-
dropped.push({
|
|
302
|
-
field: customImportTarget(key),
|
|
303
|
-
value: String(value != null ? value : '').trim()
|
|
304
|
-
});
|
|
305
|
-
} else if (parsed.value !== undefined) {
|
|
306
|
-
row.custom[key] = parsed.value;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
return {
|
|
310
|
-
ok: true,
|
|
311
|
-
row
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* How two rows are recognized as one company: by domain when the row has
|
|
316
|
-
* one, else by the name's search key — the same `nameLower` the companies
|
|
317
|
-
* list searches on, so "Acme" and "ACME " are one key.
|
|
318
|
-
*/ export function companyImportMatchKey(row) {
|
|
319
|
-
return row.domain ? `domain:${row.domain}` : `name:${nameSearchKey(row.name)}`;
|
|
320
|
-
}
|
|
321
|
-
export function emptyCompanyImportResult() {
|
|
322
|
-
return emptyImportResult();
|
|
323
|
-
}
|
|
324
|
-
export function mergeCompanyImportResults(total, chunk, offset = 0) {
|
|
325
|
-
return mergeImportResults(total, chunk, offset);
|
|
326
|
-
}
|
|
327
|
-
/** The skipped rows as a file the operator can fix and re-import. */ export function companyImportSkippedCsv(columns, entries) {
|
|
328
|
-
return importSkippedCsv(columns, entries, COMPANY_IMPORT_SKIP_LABELS);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
//# sourceMappingURL=crm-company-import.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/model/crm-company-import.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * BRINGING A SPREADSHEET OF COMPANIES INTO THE CRM — the pure half\n * (AGL-2621).\n *\n * The contact import's three stages (`crm-import.ts`) over the company\n * vocabulary: a header row is matched to a proposed mapping, one line is\n * mapped to a raw row of verbatim strings, and the server normalizes each\n * row through the SAME functions the company drawer runs —\n * `normalizeCompanyDomain` for the key, `normalizeCompanyWebsite` for the\n * link, `normalizePhone` for E.164, `normalizeAddress` for the postal shape\n * — so an imported company and a typed one are the same document.\n *\n * ## The name is the one thing a row must have\n *\n * A company is matched by its DOMAIN first and its name second, because a\n * domain is a key and a name is a spelling: two files calling one business\n * \"Acme\" and \"Acme Inc\" meet at `acme.com`. But a row with a domain and no\n * name would create a record the list cannot caption, so the name is\n * required and the domain optional — the opposite of the contact import,\n * where the address is both the key and the caption.\n *\n * ## A bad cell is dropped and named; a bad row is skipped and named\n *\n * The contact import's rule, unchanged: a domain that is not a hostname, a\n * phone that is not a number, a website that is not a URL, a country that\n * is not a code — each is left off the record and REPORTED under\n * {@link CompanyImportRow.dropped}, never silently discarded.\n */\n\nimport type { AglynPostalAddress } from '@aglyn/aglyn/foundation/definitions/contact.types'\nimport { normalizeAddress, normalizePhone } from '@aglyn/aglyn/foundation/definitions/contact.types'\nimport { normalizeContactEmail } from '@aglyn/aglyn/app-utils/contacts'\nimport {\n type ContactFieldDefinition,\n type CrmCustomValue,\n normalizeCompanyDomain,\n normalizeCompanyWebsite,\n} from '@aglyn/aglyn/app-utils/crm'\nimport { parseContactImportCustomValue } from './crm-import'\nimport {\n customImportTarget,\n CSV_IMPORT_CHUNK_SIZE,\n CSV_IMPORT_MAX_BODY_BYTES,\n CSV_IMPORT_MAX_ROWS,\n CSV_IMPORT_PREVIEW_ROWS,\n emptyImportResult,\n guessImportMapping,\n importAliasKeys,\n type ImportChunkResult,\n type ImportDroppedValue,\n importSkippedCsv,\n importTextValue,\n mapImportRow,\n mergeImportResults,\n parseImportTags,\n} from '@aglyn/aglyn/app-utils/csv-import'\nimport { nameSearchKey } from '@aglyn/aglyn/app-utils/name-search'\n\n/** The shared ceilings, under this collection's names. */\nexport const COMPANY_IMPORT_MAX_ROWS = CSV_IMPORT_MAX_ROWS\nexport const COMPANY_IMPORT_CHUNK_SIZE = CSV_IMPORT_CHUNK_SIZE\nexport const COMPANY_IMPORT_MAX_BODY_BYTES = CSV_IMPORT_MAX_BODY_BYTES\nexport const COMPANY_IMPORT_PREVIEW_ROWS = CSV_IMPORT_PREVIEW_ROWS\n\n/** The most tags one company may carry — the same cap a contact has. */\nexport const COMPANY_IMPORT_TAGS_MAX = 20\n\nconst NAME_MAX = 120\nconst INDUSTRY_MAX = 80\nconst NOTES_MAX = 4000\n\n/** The fields a column may be mapped to, in the order the mapping menu lists them. */\nexport const COMPANY_IMPORT_FIELDS = [\n 'name',\n 'domain',\n 'website',\n 'phone',\n 'industry',\n 'ownerEmail',\n 'addressLine1',\n 'addressLine2',\n 'addressCity',\n 'addressState',\n 'addressPostalCode',\n 'addressCountry',\n 'tags',\n 'notes',\n] as const\n\nexport type CompanyImportField = (typeof COMPANY_IMPORT_FIELDS)[number]\n\n/** How each field reads in the mapping menu. Typed so a field cannot ship unlabeled. */\nexport const COMPANY_IMPORT_FIELD_LABELS: Record<CompanyImportField, string> = {\n name: 'Company name (required)',\n domain: 'Domain',\n website: 'Website',\n phone: 'Phone',\n industry: 'Industry',\n ownerEmail: 'Owner (team member email)',\n addressLine1: 'Address line 1',\n addressLine2: 'Address line 2',\n addressCity: 'City',\n addressState: 'State or region',\n addressPostalCode: 'Postal code',\n addressCountry: 'Country (two-letter code)',\n tags: 'Tags (comma or | separated)',\n notes: 'Notes',\n}\n\n/**\n * Header aliases per field, matched after the shared header normalization.\n *\n * The vocabulary of the exports people arrive with, and — first in each\n * list — the header this CRM's own companies export writes, so an export\n * re-imports without a hand mapping.\n */\nconst FIELD_ALIASES: Record<CompanyImportField, readonly string[]> = {\n name: ['company', 'company name', 'name', 'organization', 'organisation', 'account', 'account name'],\n domain: ['domain', 'company domain', 'domain name', 'web domain', 'email domain'],\n website: ['website', 'web site', 'url', 'website url', 'homepage', 'web'],\n phone: ['phone', 'phone number', 'telephone', 'company phone', 'main phone'],\n industry: ['industry', 'sector', 'vertical', 'category'],\n ownerEmail: ['owner', 'owner email', 'company owner', 'account owner', 'assigned to'],\n addressLine1: ['address line 1', 'address', 'street', 'street address', 'address 1'],\n addressLine2: ['address line 2', 'address 2', 'street 2', 'suite'],\n addressCity: ['city', 'town', 'locality'],\n addressState: ['state', 'region', 'province', 'county', 'state/region'],\n addressPostalCode: ['postal code', 'postcode', 'zip', 'zip code', 'post code'],\n addressCountry: ['country', 'country code', 'country/region'],\n tags: ['tags', 'tag', 'labels', 'groups'],\n notes: ['notes', 'note', 'description', 'comments'],\n}\n\nconst FIELD_ALIAS_KEYS = importAliasKeys(COMPANY_IMPORT_FIELDS, FIELD_ALIASES)\n\n/**\n * Column index → field, or a company custom field as `custom:<key>` (AGL-2661).\n * A column absent from the map is not imported.\n */\nexport type CompanyImportMapping = Record<number, CompanyImportField | `custom:${string}`>\n\n/**\n * A proposed mapping from a file's header row, each field taken at most\n * once. `fields` is the org's COMPANY definitions (AGL-2661): a header\n * matching one's label or key maps onto it, and wins over a standard\n * alias, the contact import's rule.\n */\nexport function guessCompanyImportMapping(\n columns: readonly string[],\n fields: readonly Pick<ContactFieldDefinition, 'key' | 'label'>[] = [],\n): CompanyImportMapping {\n return guessImportMapping(columns, COMPANY_IMPORT_FIELDS, FIELD_ALIAS_KEYS, fields)\n}\n\n/**\n * What the browser posts for one line: the cells the mapping selected,\n * under the field they were mapped to, verbatim. `unknown` because the\n * server reads this off an untrusted body.\n */\nexport type CompanyImportRawRow = Partial<Record<CompanyImportField, unknown>> & {\n /** Custom values by definition key, verbatim — judged by `normalizeCompanyImportRow`. */\n custom?: unknown\n}\n\n/**\n * One parsed line under the mapping. Empty cells are left absent; custom\n * values are gathered under `custom` by definition key (AGL-2661).\n */\nexport function mapCompanyImportRow(\n cells: readonly string[],\n mapping: CompanyImportMapping,\n): CompanyImportRawRow {\n return mapImportRow(cells, mapping)\n}\n\n/** Why one row was not stored. */\nexport type CompanyImportSkipReason =\n | 'missing-name'\n | 'duplicate'\n | 'records-band'\n | 'write-failed'\n\n/** How a skip reason reads on screen and in the downloaded file. */\nexport const COMPANY_IMPORT_SKIP_LABELS: Record<CompanyImportSkipReason, string> = {\n 'missing-name': 'No company name',\n duplicate: 'Appears earlier in the file',\n 'records-band': 'CRM records limit reached',\n 'write-failed': 'Could not be saved',\n}\n\n/** One row, ready to be written. */\nexport interface CompanyImportRow {\n name: string\n /** Lowercase hostname — the match key when present. */\n domain?: string\n /** An absolute http(s) URL. */\n website?: string\n /** E.164. */\n phone?: string\n industry?: string\n /** Normalized, for the server to resolve against the org's members. */\n ownerEmail?: string\n address?: AglynPostalAddress\n /** Lowercased, deduplicated, capped at {@link COMPANY_IMPORT_TAGS_MAX}. */\n tags: string[]\n notes?: string\n dropped: ImportDroppedValue[]\n /**\n * Custom values under the org's COMPANY definitions (AGL-2661), each\n * coerced by its type the way a contact's are. Empty when the file\n * mapped none, or none survived.\n */\n custom: Record<string, CrmCustomValue>\n}\n\nexport type CompanyImportRowVerdict =\n | { ok: true; row: CompanyImportRow }\n | { ok: false; reason: 'missing-name'; input: string }\n\n/**\n * One raw row as the values that will be written, or the reason it cannot\n * be. Refused only for a missing name; every other unreadable cell is\n * dropped and named.\n */\nexport function normalizeCompanyImportRow(\n raw: CompanyImportRawRow,\n /**\n * The org's live COMPANY definitions (AGL-2661): a value under a key\n * with no definition is dropped and reported, because a value nobody\n * defined a field for is a value no surface will ever show.\n */\n fields: readonly Pick<ContactFieldDefinition, 'key' | 'type' | 'options'>[] = [],\n): CompanyImportRowVerdict {\n const name = importTextValue(raw.name, NAME_MAX)?.replace(/\\s+/g, ' ')\n if (!name) {\n return { ok: false, reason: 'missing-name', input: String(raw.domain ?? '').trim() }\n }\n const dropped: ImportDroppedValue[] = []\n const drop = (field: CompanyImportField, value: unknown) => {\n dropped.push({ field, value: String(value ?? '').trim() })\n }\n const row: CompanyImportRow = {\n name,\n tags: parseImportTags(raw.tags, COMPANY_IMPORT_TAGS_MAX),\n dropped,\n custom: {},\n }\n\n const domainText = importTextValue(raw.domain, 300)\n if (domainText) {\n const domain = normalizeCompanyDomain(domainText)\n if (domain) row.domain = domain\n else drop('domain', domainText)\n }\n\n const websiteText = importTextValue(raw.website, 600)\n if (websiteText) {\n const website = normalizeCompanyWebsite(websiteText)\n if (website) row.website = website\n else drop('website', websiteText)\n }\n\n const phoneText = importTextValue(raw.phone, 64)\n if (phoneText) {\n const phone = normalizePhone(phoneText)\n if (phone) row.phone = phone\n else drop('phone', phoneText)\n }\n\n const industry = importTextValue(raw.industry, INDUSTRY_MAX)\n if (industry) row.industry = industry\n\n const ownerText = importTextValue(raw.ownerEmail, 320)\n if (ownerText) {\n const owner = normalizeContactEmail(ownerText)\n if (owner) row.ownerEmail = owner\n else drop('ownerEmail', ownerText)\n }\n\n const address = normalizeAddress({\n line1: importTextValue(raw.addressLine1, 200),\n line2: importTextValue(raw.addressLine2, 200),\n city: importTextValue(raw.addressCity, 120),\n state: importTextValue(raw.addressState, 120),\n postalCode: importTextValue(raw.addressPostalCode, 32),\n country: importTextValue(raw.addressCountry, 8),\n })\n if (address) row.address = address\n // The country is the one address part the normalizer drops silently — a\n // typed name is not a code — so it is the one part the report has to name.\n const countryText = importTextValue(raw.addressCountry, 64)\n if (countryText && !address?.country) drop('addressCountry', countryText)\n\n const notes = importTextValue(raw.notes, NOTES_MAX)\n if (notes) row.notes = notes\n\n // The contact import's custom rule, over the company's definitions.\n const custom =\n raw.custom && typeof raw.custom === 'object' && !Array.isArray(raw.custom)\n ? (raw.custom as Record<string, unknown>)\n : {}\n const definitions = new Map(fields.map((field) => [field.key, field]))\n for (const [key, value] of Object.entries(custom)) {\n const definition = definitions.get(key)\n if (!definition) {\n dropped.push({ field: customImportTarget(key), value: String(value ?? '').trim() })\n continue\n }\n const parsed = parseContactImportCustomValue(definition, value)\n if (!parsed) {\n dropped.push({ field: customImportTarget(key), value: String(value ?? '').trim() })\n } else if (parsed.value !== undefined) {\n row.custom[key] = parsed.value\n }\n }\n\n return { ok: true, row }\n}\n\n/**\n * How two rows are recognized as one company: by domain when the row has\n * one, else by the name's search key — the same `nameLower` the companies\n * list searches on, so \"Acme\" and \"ACME \" are one key.\n */\nexport function companyImportMatchKey(\n row: Pick<CompanyImportRow, 'name' | 'domain'>,\n): string {\n return row.domain ? `domain:${row.domain}` : `name:${nameSearchKey(row.name)}`\n}\n\n/** One row the server did not store, by its index in the request, named by the company. */\nexport interface CompanyImportSkippedRow {\n index: number\n name: string\n reason: CompanyImportSkipReason\n}\n\n/** What one request did. The drawer sums these across a file. */\nexport type CompanyImportChunkResult = ImportChunkResult<CompanyImportSkippedRow>\n\nexport function emptyCompanyImportResult(): CompanyImportChunkResult {\n return emptyImportResult<CompanyImportSkippedRow>()\n}\n\nexport function mergeCompanyImportResults(\n total: CompanyImportChunkResult,\n chunk: CompanyImportChunkResult,\n offset = 0,\n): CompanyImportChunkResult {\n return mergeImportResults(total, chunk, offset)\n}\n\n/** The skipped rows as a file the operator can fix and re-import. */\nexport function companyImportSkippedCsv(\n columns: readonly string[],\n entries: readonly { cells: readonly string[]; reason: CompanyImportSkipReason }[],\n): string {\n return importSkippedCsv(columns, entries, COMPANY_IMPORT_SKIP_LABELS)\n}\n"],"names":["normalizeAddress","normalizePhone","normalizeContactEmail","normalizeCompanyDomain","normalizeCompanyWebsite","parseContactImportCustomValue","customImportTarget","CSV_IMPORT_CHUNK_SIZE","CSV_IMPORT_MAX_BODY_BYTES","CSV_IMPORT_MAX_ROWS","CSV_IMPORT_PREVIEW_ROWS","emptyImportResult","guessImportMapping","importAliasKeys","importSkippedCsv","importTextValue","mapImportRow","mergeImportResults","parseImportTags","nameSearchKey","COMPANY_IMPORT_MAX_ROWS","COMPANY_IMPORT_CHUNK_SIZE","COMPANY_IMPORT_MAX_BODY_BYTES","COMPANY_IMPORT_PREVIEW_ROWS","COMPANY_IMPORT_TAGS_MAX","NAME_MAX","INDUSTRY_MAX","NOTES_MAX","COMPANY_IMPORT_FIELDS","COMPANY_IMPORT_FIELD_LABELS","name","domain","website","phone","industry","ownerEmail","addressLine1","addressLine2","addressCity","addressState","addressPostalCode","addressCountry","tags","notes","FIELD_ALIASES","FIELD_ALIAS_KEYS","guessCompanyImportMapping","columns","fields","mapCompanyImportRow","cells","mapping","COMPANY_IMPORT_SKIP_LABELS","duplicate","normalizeCompanyImportRow","raw","replace","ok","reason","input","String","trim","dropped","drop","field","value","push","row","custom","domainText","websiteText","phoneText","ownerText","owner","address","line1","line2","city","state","postalCode","country","countryText","Array","isArray","definitions","Map","map","key","Object","entries","definition","get","parsed","undefined","companyImportMatchKey","emptyCompanyImportResult","mergeCompanyImportResults","total","chunk","offset","companyImportSkippedCsv"],"mappings":"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"}
|
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2026 Aglyn LLC
|
|
4
|
-
*
|
|
5
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
-
* you may not use this file except in compliance with the License.
|
|
7
|
-
* You may obtain a copy of the License at
|
|
8
|
-
*
|
|
9
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
-
*
|
|
11
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
-
* See the License for the specific language governing permissions and
|
|
15
|
-
* limitations under the License.
|
|
16
|
-
*/
|
|
17
|
-
/**
|
|
18
|
-
* EVERY CRM CSV, WRITTEN ONCE (AGL-2662).
|
|
19
|
-
*
|
|
20
|
-
* ## Why these moved out of the plugin
|
|
21
|
-
*
|
|
22
|
-
* Each CRM section already wrote a file from the rows it had LOADED, and
|
|
23
|
-
* the whole-collection export writes the same file from the server over
|
|
24
|
-
* every row there is. The console app may not import a feature plugin —
|
|
25
|
-
* plugins reach an app only through the generated loader manifests — so a
|
|
26
|
-
* server route could not have called the plugin's writers, and writing a
|
|
27
|
-
* second set would have given one feature two file formats, discovered by
|
|
28
|
-
* whichever merchant opened both in a spreadsheet.
|
|
29
|
-
*
|
|
30
|
-
* So the columns and the cells live here, in the library both sides may
|
|
31
|
-
* import. The plugin's `contacts-csv.ts`, `companies-csv.ts`,
|
|
32
|
-
* `deals-csv.ts`, `tasks-csv.ts` and `leads-csv.ts` keep their names and
|
|
33
|
-
* delegate: the sections import what they always did, and there is one
|
|
34
|
-
* implementation under all of it. Their specs are unchanged and are the
|
|
35
|
-
* proof that the move changed no byte of any file.
|
|
36
|
-
*
|
|
37
|
-
* ## What a resolver is for, and what an absent one means
|
|
38
|
-
*
|
|
39
|
-
* A stored document holds ids — an owner uid, a pipeline id, a linked
|
|
40
|
-
* record id — and a spreadsheet cannot read an id. Each writer therefore
|
|
41
|
-
* takes optional resolvers, and every one of them degrades the same way:
|
|
42
|
-
* ABSENT resolver writes the id itself rather than an empty cell, because
|
|
43
|
-
* a row whose owner is a uid is still a row whose owner can be found, and
|
|
44
|
-
* a blank is a claim that nobody owns it.
|
|
45
|
-
*
|
|
46
|
-
* The owner columns carry an ADDRESS where they can, which is also what
|
|
47
|
-
* the contacts and companies imports resolve an owner by — so an exported
|
|
48
|
-
* file re-imports without a hand mapping.
|
|
49
|
-
*/
|
|
50
|
-
import type { AglynPostalAddress } from '@aglyn/aglyn';
|
|
51
|
-
import { type ContactCustomValue, type ContactFieldDefinition, type ContactLifecycleStage, type CrmCompany, type CrmLeadFields, type CrmTask } from '@aglyn/aglyn/app-utils/crm';
|
|
52
|
-
/** Cents as a major-unit decimal — `125000` → `1250.00`; `''` for none. */
|
|
53
|
-
export declare function csvAmount(cents: number | null | undefined): string;
|
|
54
|
-
/** An epoch as an ISO timestamp, or `''` for none. */
|
|
55
|
-
export declare function csvInstant(ms: number | null | undefined): string;
|
|
56
|
-
/**
|
|
57
|
-
* An epoch as a local calendar DATE — `YYYY-MM-DD`.
|
|
58
|
-
*
|
|
59
|
-
* For the fields that are a day rather than a moment: an expected close is
|
|
60
|
-
* stored at local noon precisely so the day survives a timezone round trip,
|
|
61
|
-
* and writing it as an instant would hand a spreadsheet a time nobody
|
|
62
|
-
* chose. The same arithmetic the deal drawer's date field uses, so the
|
|
63
|
-
* file and the field read one day.
|
|
64
|
-
*/
|
|
65
|
-
export declare function csvLocalDate(ms: number | null | undefined): string;
|
|
66
|
-
/** Epoch millis or a Firestore timestamp as an ISO instant, or `''`. */
|
|
67
|
-
export declare function csvStoredInstant(value: unknown): string;
|
|
68
|
-
/** As much of a projected contact row as the file reads. */
|
|
69
|
-
export interface ContactCsvRow {
|
|
70
|
-
email?: string;
|
|
71
|
-
name?: string;
|
|
72
|
-
phone?: string;
|
|
73
|
-
jobTitle?: string;
|
|
74
|
-
companyName?: string;
|
|
75
|
-
ownerUid?: string;
|
|
76
|
-
lifecycleStage?: ContactLifecycleStage | '';
|
|
77
|
-
address?: AglynPostalAddress | null;
|
|
78
|
-
tags?: string[];
|
|
79
|
-
sources?: Record<string, unknown>;
|
|
80
|
-
interactions?: Array<{
|
|
81
|
-
atMs: number;
|
|
82
|
-
}>;
|
|
83
|
-
/** The last open or click on one of the site's campaigns (AGL-2616). */
|
|
84
|
-
lastEmailEngagementAtMs?: number;
|
|
85
|
-
notes?: string;
|
|
86
|
-
/** This holder's custom values, keyed by definition key. */
|
|
87
|
-
custom?: Record<string, ContactCustomValue>;
|
|
88
|
-
}
|
|
89
|
-
export interface ContactCsvOptions {
|
|
90
|
-
/**
|
|
91
|
-
* The owner's address for a stored uid — what the import resolves an
|
|
92
|
-
* owner by. Absent, the uid is written as it is.
|
|
93
|
-
*/
|
|
94
|
-
ownerEmail?: (uid: string) => string;
|
|
95
|
-
/** The org's custom fields, one column each, headed by the field's label. */
|
|
96
|
-
customFields?: readonly Pick<ContactFieldDefinition, 'key' | 'label'>[];
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* The standard columns, in order, headed as the import reads them. A
|
|
100
|
-
* custom field's column follows these, headed by its label.
|
|
101
|
-
*/
|
|
102
|
-
export declare const CONTACT_CSV_COLUMNS: readonly ["Email", "Name", "Phone", "Job title", "Company", "Owner", "Lifecycle stage", "Address line 1", "Address line 2", "City", "State", "Postal code", "Country", "Tags", "Sources", "Last interaction", "Last engaged", "Notes"];
|
|
103
|
-
/** The header row, with one column per custom field after the standard ones. */
|
|
104
|
-
export declare function contactCsvHeader(customFields?: ContactCsvOptions['customFields']): string[];
|
|
105
|
-
/** One contact's cells, in the header's order. */
|
|
106
|
-
export declare function contactCsvCells(contact: ContactCsvRow, options?: ContactCsvOptions): unknown[];
|
|
107
|
-
/** The whole file, header first. */
|
|
108
|
-
export declare function contactsCsv(rows: readonly ContactCsvRow[], options?: ContactCsvOptions): string;
|
|
109
|
-
/** As much of a company row as the file reads. */
|
|
110
|
-
export type CompanyCsvRow = Partial<Pick<CrmCompany, 'name' | 'domain' | 'website' | 'phone' | 'industry' | 'ownerUid' | 'tags' | 'notes' | 'contactsCount'>> & {
|
|
111
|
-
address?: AglynPostalAddress | null;
|
|
112
|
-
};
|
|
113
|
-
export interface CompanyCsvOptions {
|
|
114
|
-
/** The owner's address for a stored uid; absent, the uid is written. */
|
|
115
|
-
ownerEmail?: (uid: string) => string;
|
|
116
|
-
}
|
|
117
|
-
/** The columns, in order, headed as the import reads them. */
|
|
118
|
-
export declare const COMPANY_CSV_COLUMNS: readonly ["Company", "Domain", "Website", "Phone", "Industry", "Owner", "Address line 1", "Address line 2", "City", "State", "Postal code", "Country", "Tags", "Notes", "Contacts"];
|
|
119
|
-
/** One company's cells, in the header's order. */
|
|
120
|
-
export declare function companyCsvCells(company: CompanyCsvRow, options?: CompanyCsvOptions): unknown[];
|
|
121
|
-
/** The whole file, header first. */
|
|
122
|
-
export declare function companiesCsv(rows: readonly CompanyCsvRow[], options?: CompanyCsvOptions): string;
|
|
123
|
-
/** The currency a deal with no code of its own is read in. */
|
|
124
|
-
export declare const CSV_DEFAULT_DEAL_CURRENCY = "usd";
|
|
125
|
-
/** How a deal's `status` reads in a file. */
|
|
126
|
-
export declare const CSV_DEAL_STATUS_LABELS: Record<string, string>;
|
|
127
|
-
/** As much of a deal row as the file reads. */
|
|
128
|
-
export interface DealCsvRow {
|
|
129
|
-
title?: string;
|
|
130
|
-
pipelineId?: string;
|
|
131
|
-
stageId?: string;
|
|
132
|
-
status?: string;
|
|
133
|
-
amountCents?: number;
|
|
134
|
-
currency?: string;
|
|
135
|
-
ownerUid?: string;
|
|
136
|
-
expectedCloseAtMs?: number | null;
|
|
137
|
-
closedAtMs?: number | null;
|
|
138
|
-
contactName?: string;
|
|
139
|
-
companyName?: string;
|
|
140
|
-
lostReason?: string;
|
|
141
|
-
notes?: string;
|
|
142
|
-
}
|
|
143
|
-
export interface DealCsvOptions {
|
|
144
|
-
/** The pipeline's name for a stored id; absent, the id is written. */
|
|
145
|
-
pipelineName?: (pipelineId: string) => string | undefined;
|
|
146
|
-
/** The stage's name within its pipeline; absent, the stage id is written. */
|
|
147
|
-
stageName?: (pipelineId: string, stageId: string) => string | undefined;
|
|
148
|
-
/** The owner's address for a stored uid; absent, the uid is written. */
|
|
149
|
-
ownerEmail?: (uid: string) => string;
|
|
150
|
-
}
|
|
151
|
-
export declare const DEAL_CSV_COLUMNS: readonly ["Title", "Pipeline", "Stage", "Amount", "Currency", "Owner", "Expected close", "Status", "Contact", "Company", "Closed", "Lost reason", "Notes"];
|
|
152
|
-
/** One deal's cells, in the header's order. */
|
|
153
|
-
export declare function dealCsvCells(deal: DealCsvRow, options?: DealCsvOptions): unknown[];
|
|
154
|
-
/** The whole file, header first. */
|
|
155
|
-
export declare function dealsCsv(rows: readonly DealCsvRow[], options?: DealCsvOptions): string;
|
|
156
|
-
/** As much of a task row as the file reads. */
|
|
157
|
-
export type TaskCsvRow = Partial<Pick<CrmTask, 'title' | 'kind' | 'priority' | 'status' | 'dueAtMs' | 'completedAtMs' | 'assigneeUid' | 'contactId' | 'companyId' | 'dealId' | 'notes'>>;
|
|
158
|
-
export interface TaskCsvOptions {
|
|
159
|
-
/** The assignee's address for a stored uid; absent, the uid is written. */
|
|
160
|
-
assigneeEmail?: (uid: string) => string;
|
|
161
|
-
/** What a linked record is called; absent, the id is written. */
|
|
162
|
-
recordName?: (kind: 'contact' | 'company' | 'deal', id: string) => string | undefined;
|
|
163
|
-
}
|
|
164
|
-
export declare const TASK_CSV_COLUMNS: readonly ["Title", "Kind", "Priority", "Status", "Due", "Assignee", "Contact", "Company", "Deal", "Completed", "Notes"];
|
|
165
|
-
/** One task's cells, in the header's order. */
|
|
166
|
-
export declare function taskCsvCells(task: TaskCsvRow, options?: TaskCsvOptions): unknown[];
|
|
167
|
-
/** The whole file, header first. */
|
|
168
|
-
export declare function tasksCsv(rows: readonly TaskCsvRow[], options?: TaskCsvOptions): string;
|
|
169
|
-
/** How one capture surface reads in a file. */
|
|
170
|
-
export declare function csvLeadSourceLabel(source: string): string;
|
|
171
|
-
/** Every surface that produced a capture — the array, or the older single field. */
|
|
172
|
-
export declare function csvLeadSources(lead: Record<string, unknown>): string[];
|
|
173
|
-
/** As much of a lead row as the file reads. */
|
|
174
|
-
export type LeadCsvRow = Record<string, unknown> & Pick<CrmLeadFields, 'status' | 'ownerUid' | 'notes' | 'unqualifiedReason' | 'convertedAtMs' | 'company' | 'jobTitle' | 'phone' | 'website' | 'address' | 'tags' | 'leadSource'> & {
|
|
175
|
-
/** The site the lead lives under — what the `Site` column names. */
|
|
176
|
-
hostId?: string;
|
|
177
|
-
};
|
|
178
|
-
export interface LeadCsvOptions {
|
|
179
|
-
/** The owner's address for a stored uid; absent, the uid is written. */
|
|
180
|
-
ownerEmail?: (uid: string) => string;
|
|
181
|
-
/**
|
|
182
|
-
* The site's name for a row's `hostId`. Given, the file carries a `Site`
|
|
183
|
-
* column — the organization-level file; absent, it does not.
|
|
184
|
-
*/
|
|
185
|
-
siteName?: (hostId: string) => string | undefined;
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* The columns every leads file carries, in the list's order.
|
|
189
|
-
*
|
|
190
|
-
* The lead's own profile (AGL-3231) — company, title, phone, website, the
|
|
191
|
-
* address parts, tags and the lead source — sits where the contacts file
|
|
192
|
-
* keeps the same facts, under the same headers, so one spreadsheet of
|
|
193
|
-
* people reads into either import with the same mapping.
|
|
194
|
-
*/
|
|
195
|
-
export declare const LEAD_CSV_COLUMNS: readonly ["Email", "Name", "Company", "Job title", "Phone", "Website", "Status", "Owner", "Lead source", "Sources", "First seen", "Last seen", "Captures", "Address line 1", "Address line 2", "City", "State", "Postal code", "Country", "Tags", "Unqualified reason", "Converted", "Notes"];
|
|
196
|
-
/** The header row: the standard columns, with `Site` after `Owner` at the org level. */
|
|
197
|
-
export declare function leadCsvHeader(options?: LeadCsvOptions): string[];
|
|
198
|
-
/** One lead's cells, in the header's order. */
|
|
199
|
-
export declare function leadCsvCells(lead: LeadCsvRow, options?: LeadCsvOptions): unknown[];
|
|
200
|
-
/** The whole file, header first. */
|
|
201
|
-
export declare function leadsCsv(rows: readonly LeadCsvRow[], options?: LeadCsvOptions): string;
|
|
202
|
-
/** The five tables a whole-collection export can be asked for. */
|
|
203
|
-
export declare const CRM_EXPORT_RESOURCES: readonly ["contacts", "companies", "deals", "tasks", "leads"];
|
|
204
|
-
export type CrmExportResource = (typeof CRM_EXPORT_RESOURCES)[number];
|
|
205
|
-
export declare function isCrmExportResource(value: unknown): value is CrmExportResource;
|
|
206
|
-
/** Every resolver any of the five writers takes, in one bag. */
|
|
207
|
-
export type CrmExportOptions = ContactCsvOptions & DealCsvOptions & TaskCsvOptions & LeadCsvOptions & {
|
|
208
|
-
assigneeEmail?: (uid: string) => string;
|
|
209
|
-
};
|
|
210
|
-
/** The header row one resource's file carries. */
|
|
211
|
-
export declare function crmExportHeader(resource: CrmExportResource, options?: CrmExportOptions): string[];
|
|
212
|
-
/**
|
|
213
|
-
* One stored document's cells for one resource's file.
|
|
214
|
-
*
|
|
215
|
-
* The bridge the server route stands on: it holds a raw document rather
|
|
216
|
-
* than the projected row a list built, and this is the one place that
|
|
217
|
-
* turns the first into the second — so the streamed file and the file the
|
|
218
|
-
* Export button writes are the same columns filled the same way.
|
|
219
|
-
*/
|
|
220
|
-
export declare function crmExportCells(resource: CrmExportResource, document: Record<string, unknown>, options?: CrmExportOptions): unknown[];
|
|
221
|
-
/** What the contacts file needs to know about the holder it is written for. */
|
|
222
|
-
export interface CrmExportContactHolder {
|
|
223
|
-
/** The consent group whose facet the file reads — a facet is per holder. */
|
|
224
|
-
groupId: string;
|
|
225
|
-
/** The sites in that group, which bound the timeline the file reads. */
|
|
226
|
-
hostIds: readonly string[];
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* A stored contact document as the contacts file reads it.
|
|
230
|
-
*
|
|
231
|
-
* The projection the Contacts list makes before it writes its own file,
|
|
232
|
-
* spelled here so the server can make the same one: a contact document
|
|
233
|
-
* holds one facet per HOLDER, and every field the file writes but the
|
|
234
|
-
* address itself — the phone, the company, the tags, the notes, the
|
|
235
|
-
* lifecycle stage, the custom values — lives in the viewing holder's facet.
|
|
236
|
-
* Reading them off the top of the document is how one business's file ends
|
|
237
|
-
* up carrying another's notes.
|
|
238
|
-
*/
|
|
239
|
-
export declare function contactCsvRowFromDoc(document: Record<string, unknown>, holder: CrmExportContactHolder): ContactCsvRow;
|