@kelpie/server 0.12.0 → 0.13.0
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/dist/app.d.ts +13 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +8 -1
- package/dist/app.js.map +1 -1
- package/dist/boot.d.ts.map +1 -1
- package/dist/boot.js +1 -0
- package/dist/boot.js.map +1 -1
- package/dist/lib/apiKeyScopes.d.ts.map +1 -1
- package/dist/lib/apiKeyScopes.js +6 -0
- package/dist/lib/apiKeyScopes.js.map +1 -1
- package/dist/lib/columns.d.ts +6 -0
- package/dist/lib/columns.d.ts.map +1 -1
- package/dist/lib/columns.js +5 -3
- package/dist/lib/columns.js.map +1 -1
- package/dist/lib/config.d.ts +17 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +3 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/egress.d.ts.map +1 -1
- package/dist/lib/egress.js +8 -4
- package/dist/lib/egress.js.map +1 -1
- package/dist/lib/errors.d.ts +3 -3
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +13 -5
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/ids.d.ts +11 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +11 -0
- package/dist/lib/ids.js.map +1 -1
- package/dist/lib/kelpieConfigFile.d.ts +15 -1
- package/dist/lib/kelpieConfigFile.d.ts.map +1 -1
- package/dist/lib/kelpieConfigFile.js +33 -1
- package/dist/lib/kelpieConfigFile.js.map +1 -1
- package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
- package/dist/modules/agent-tasks/catalog.js +32 -1
- package/dist/modules/agent-tasks/catalog.js.map +1 -1
- package/dist/modules/agent-tasks/index.d.ts.map +1 -1
- package/dist/modules/agent-tasks/index.js +1 -0
- package/dist/modules/agent-tasks/index.js.map +1 -1
- package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
- package/dist/modules/agent-tasks/resolve.js +5 -0
- package/dist/modules/agent-tasks/resolve.js.map +1 -1
- package/dist/modules/agent-tasks/routes.d.ts +2 -0
- package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
- package/dist/modules/attachedRecords.d.ts +22 -8
- package/dist/modules/attachedRecords.d.ts.map +1 -1
- package/dist/modules/attachedRecords.js +42 -5
- package/dist/modules/attachedRecords.js.map +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +1 -0
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/auth/repository.d.ts +14 -0
- package/dist/modules/auth/repository.d.ts.map +1 -1
- package/dist/modules/auth/repository.js +20 -2
- package/dist/modules/auth/repository.js.map +1 -1
- package/dist/modules/auth/routes.d.ts.map +1 -1
- package/dist/modules/auth/routes.js +30 -0
- package/dist/modules/auth/routes.js.map +1 -1
- package/dist/modules/auth/service.d.ts +28 -0
- package/dist/modules/auth/service.d.ts.map +1 -1
- package/dist/modules/auth/service.js +72 -4
- package/dist/modules/auth/service.js.map +1 -1
- package/dist/modules/companies/repository.d.ts.map +1 -1
- package/dist/modules/companies/repository.js +1 -1
- package/dist/modules/companies/repository.js.map +1 -1
- package/dist/modules/companies/routes.d.ts +2 -4
- package/dist/modules/companies/routes.d.ts.map +1 -1
- package/dist/modules/companies/routes.js +6 -11
- package/dist/modules/companies/routes.js.map +1 -1
- package/dist/modules/companies/schema.d.ts +13 -28
- package/dist/modules/companies/schema.d.ts.map +1 -1
- package/dist/modules/companies/schema.js +2 -2
- package/dist/modules/companies/schema.js.map +1 -1
- package/dist/modules/companies/service.d.ts +2 -3
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +4 -7
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +2 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/custom-fields/repository.d.ts.map +1 -1
- package/dist/modules/custom-fields/repository.js +2 -0
- package/dist/modules/custom-fields/repository.js.map +1 -1
- package/dist/modules/custom-fields/routes.d.ts +1 -0
- package/dist/modules/custom-fields/routes.d.ts.map +1 -1
- package/dist/modules/dashboard/index.d.ts.map +1 -1
- package/dist/modules/dashboard/index.js +1 -0
- package/dist/modules/dashboard/index.js.map +1 -1
- package/dist/modules/dashboard/repository.d.ts +13 -0
- package/dist/modules/dashboard/repository.d.ts.map +1 -1
- package/dist/modules/dashboard/repository.js +36 -0
- package/dist/modules/dashboard/repository.js.map +1 -1
- package/dist/modules/dashboard/routes.d.ts.map +1 -1
- package/dist/modules/dashboard/routes.js +13 -0
- package/dist/modules/dashboard/routes.js.map +1 -1
- package/dist/modules/dashboard/service.d.ts +11 -0
- package/dist/modules/dashboard/service.d.ts.map +1 -1
- package/dist/modules/dashboard/service.js +24 -1
- package/dist/modules/dashboard/service.js.map +1 -1
- package/dist/modules/decisions/repository.d.ts.map +1 -1
- package/dist/modules/decisions/repository.js +2 -0
- package/dist/modules/decisions/repository.js.map +1 -1
- package/dist/modules/decisions/routes.d.ts +2 -0
- package/dist/modules/decisions/routes.d.ts.map +1 -1
- package/dist/modules/events/attendances.d.ts +35 -0
- package/dist/modules/events/attendances.d.ts.map +1 -0
- package/dist/modules/events/attendances.js +157 -0
- package/dist/modules/events/attendances.js.map +1 -0
- package/dist/modules/events/catalog.d.ts +35 -0
- package/dist/modules/events/catalog.d.ts.map +1 -0
- package/dist/modules/events/catalog.js +11 -0
- package/dist/modules/events/catalog.js.map +1 -0
- package/dist/modules/events/index.d.ts +10 -0
- package/dist/modules/events/index.d.ts.map +1 -0
- package/dist/modules/events/index.js +47 -0
- package/dist/modules/events/index.js.map +1 -0
- package/dist/modules/events/repository.d.ts +67 -0
- package/dist/modules/events/repository.d.ts.map +1 -0
- package/dist/modules/events/repository.js +212 -0
- package/dist/modules/events/repository.js.map +1 -0
- package/dist/modules/events/routes.d.ts +136 -0
- package/dist/modules/events/routes.d.ts.map +1 -0
- package/dist/modules/events/routes.js +280 -0
- package/dist/modules/events/routes.js.map +1 -0
- package/dist/modules/events/schema.d.ts +626 -0
- package/dist/modules/events/schema.d.ts.map +1 -0
- package/dist/modules/events/schema.js +93 -0
- package/dist/modules/events/schema.js.map +1 -0
- package/dist/modules/events/service.d.ts +68 -0
- package/dist/modules/events/service.d.ts.map +1 -0
- package/dist/modules/events/service.js +262 -0
- package/dist/modules/events/service.js.map +1 -0
- package/dist/modules/events/tools.d.ts +8 -0
- package/dist/modules/events/tools.d.ts.map +1 -0
- package/dist/modules/events/tools.js +80 -0
- package/dist/modules/events/tools.js.map +1 -0
- package/dist/modules/forms/applySubmissionFields.d.ts.map +1 -1
- package/dist/modules/forms/applySubmissionFields.js +7 -5
- package/dist/modules/forms/applySubmissionFields.js.map +1 -1
- package/dist/modules/forms/fillAddresses.d.ts +4 -0
- package/dist/modules/forms/fillAddresses.d.ts.map +1 -0
- package/dist/modules/forms/fillAddresses.js +93 -0
- package/dist/modules/forms/fillAddresses.js.map +1 -0
- package/dist/modules/forms/repository.d.ts +2 -2
- package/dist/modules/forms/repository.d.ts.map +1 -1
- package/dist/modules/forms/repository.js.map +1 -1
- package/dist/modules/forms/routes.d.ts +2 -0
- package/dist/modules/forms/routes.d.ts.map +1 -1
- package/dist/modules/forms/routes.js +2 -2
- package/dist/modules/forms/routes.js.map +1 -1
- package/dist/modules/forms/schema.js +2 -2
- package/dist/modules/forms/schema.js.map +1 -1
- package/dist/modules/forms/service.js +2 -2
- package/dist/modules/forms/service.js.map +1 -1
- package/dist/modules/forms/submission.d.ts +1 -0
- package/dist/modules/forms/submission.d.ts.map +1 -1
- package/dist/modules/forms/submission.js +27 -4
- package/dist/modules/forms/submission.js.map +1 -1
- package/dist/modules/hiring/roles.d.ts.map +1 -1
- package/dist/modules/hiring/roles.js +2 -1
- package/dist/modules/hiring/roles.js.map +1 -1
- package/dist/modules/import-export/addresses.d.ts +22 -0
- package/dist/modules/import-export/addresses.d.ts.map +1 -0
- package/dist/modules/import-export/addresses.js +83 -0
- package/dist/modules/import-export/addresses.js.map +1 -0
- package/dist/modules/import-export/drafts.d.ts +3 -4
- package/dist/modules/import-export/drafts.d.ts.map +1 -1
- package/dist/modules/import-export/drafts.js +4 -5
- package/dist/modules/import-export/drafts.js.map +1 -1
- package/dist/modules/import-export/exportRows.d.ts.map +1 -1
- package/dist/modules/import-export/exportRows.js +3 -3
- package/dist/modules/import-export/exportRows.js.map +1 -1
- package/dist/modules/import-export/plan.d.ts.map +1 -1
- package/dist/modules/import-export/plan.js +17 -2
- package/dist/modules/import-export/plan.js.map +1 -1
- package/dist/modules/import-export/presets.d.ts.map +1 -1
- package/dist/modules/import-export/presets.js +52 -7
- package/dist/modules/import-export/presets.js.map +1 -1
- package/dist/modules/import-export/repository.d.ts +3 -4
- package/dist/modules/import-export/repository.d.ts.map +1 -1
- package/dist/modules/import-export/repository.js +2 -3
- package/dist/modules/import-export/repository.js.map +1 -1
- package/dist/modules/import-export/writes.d.ts.map +1 -1
- package/dist/modules/import-export/writes.js +8 -4
- package/dist/modules/import-export/writes.js.map +1 -1
- package/dist/modules/lists/routes.d.ts +4 -0
- package/dist/modules/lists/routes.d.ts.map +1 -1
- package/dist/modules/notes/routes.d.ts +2 -0
- package/dist/modules/notes/routes.d.ts.map +1 -1
- package/dist/modules/people/repository.d.ts.map +1 -1
- package/dist/modules/people/repository.js +1 -1
- package/dist/modules/people/repository.js.map +1 -1
- package/dist/modules/people/routes.d.ts +2 -2
- package/dist/modules/people/routes.js +6 -6
- package/dist/modules/people/routes.js.map +1 -1
- package/dist/modules/people/schema.d.ts +17 -14
- package/dist/modules/people/schema.d.ts.map +1 -1
- package/dist/modules/people/schema.js +6 -4
- package/dist/modules/people/schema.js.map +1 -1
- package/dist/modules/people/service.d.ts +2 -2
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +5 -4
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/plans/repository.d.ts +2 -2
- package/dist/modules/plans/repository.d.ts.map +1 -1
- package/dist/modules/plans/routes.d.ts +1 -0
- package/dist/modules/plans/routes.d.ts.map +1 -1
- package/dist/modules/plans/routes.js +4 -4
- package/dist/modules/plans/routes.js.map +1 -1
- package/dist/modules/plans/schema.d.ts +2 -2
- package/dist/modules/plans/schema.d.ts.map +1 -1
- package/dist/modules/plans/schema.js +3 -3
- package/dist/modules/plans/schema.js.map +1 -1
- package/dist/modules/plans/service.d.ts +2 -2
- package/dist/modules/plans/service.d.ts.map +1 -1
- package/dist/modules/plans/service.js.map +1 -1
- package/dist/modules/plans/tools.js +2 -2
- package/dist/modules/plans/tools.js.map +1 -1
- package/dist/modules/recordTargets.d.ts.map +1 -1
- package/dist/modules/recordTargets.js +11 -0
- package/dist/modules/recordTargets.js.map +1 -1
- package/dist/modules/references.d.ts.map +1 -1
- package/dist/modules/references.js +2 -0
- package/dist/modules/references.js.map +1 -1
- package/dist/modules/sample-data/fixture.d.ts +26 -4
- package/dist/modules/sample-data/fixture.d.ts.map +1 -1
- package/dist/modules/sample-data/fixture.js +157 -23
- package/dist/modules/sample-data/fixture.js.map +1 -1
- package/dist/modules/sample-data/index.d.ts +5 -2
- package/dist/modules/sample-data/index.d.ts.map +1 -1
- package/dist/modules/sample-data/index.js +7 -2
- package/dist/modules/sample-data/index.js.map +1 -1
- package/dist/modules/sample-data/routes.d.ts.map +1 -1
- package/dist/modules/sample-data/routes.js +2 -0
- package/dist/modules/sample-data/routes.js.map +1 -1
- package/dist/modules/sample-data/service.d.ts +11 -3
- package/dist/modules/sample-data/service.d.ts.map +1 -1
- package/dist/modules/sample-data/service.js +452 -363
- package/dist/modules/sample-data/service.js.map +1 -1
- package/dist/modules/sample-data/tools.d.ts.map +1 -1
- package/dist/modules/sample-data/tools.js +4 -3
- package/dist/modules/sample-data/tools.js.map +1 -1
- package/dist/modules/search/index.d.ts +1 -1
- package/dist/modules/search/index.d.ts.map +1 -1
- package/dist/modules/search/index.js +2 -1
- package/dist/modules/search/index.js.map +1 -1
- package/dist/modules/search/repository.d.ts +1 -0
- package/dist/modules/search/repository.d.ts.map +1 -1
- package/dist/modules/search/repository.js +22 -0
- package/dist/modules/search/repository.js.map +1 -1
- package/dist/modules/search/service.d.ts +2 -2
- package/dist/modules/search/service.d.ts.map +1 -1
- package/dist/modules/search/service.js +4 -3
- package/dist/modules/search/service.js.map +1 -1
- package/dist/modules/smtp-email/index.d.ts +12 -4
- package/dist/modules/smtp-email/index.d.ts.map +1 -1
- package/dist/modules/smtp-email/index.js +25 -5
- package/dist/modules/smtp-email/index.js.map +1 -1
- package/dist/modules/workspace/repository.d.ts +2 -0
- package/dist/modules/workspace/repository.d.ts.map +1 -1
- package/dist/modules/workspace/repository.js +12 -0
- package/dist/modules/workspace/repository.js.map +1 -1
- package/dist/modules/workspace/routes.d.ts.map +1 -1
- package/dist/modules/workspace/routes.js +13 -0
- package/dist/modules/workspace/routes.js.map +1 -1
- package/dist/modules/workspace/service.d.ts +10 -0
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +34 -10
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/modules/workspace/starters.d.ts +17 -2
- package/dist/modules/workspace/starters.d.ts.map +1 -1
- package/dist/modules/workspace/starters.js +141 -14
- package/dist/modules/workspace/starters.js.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.d.ts.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.js +3 -4
- package/dist/modules/workspace/workspaceAccessMiddleware.js.map +1 -1
- package/dist/runtime/events.d.ts +1 -1
- package/dist/runtime/events.d.ts.map +1 -1
- package/dist/runtime/events.js +2 -0
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/module.d.ts +8 -0
- package/dist/runtime/module.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/registry.js +102 -7
- package/dist/runtime/registry.js.map +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/testing/app.d.ts +8 -0
- package/dist/testing/app.d.ts.map +1 -1
- package/dist/testing/app.js +6 -1
- package/dist/testing/app.js.map +1 -1
- package/dist/testing/client.d.ts.map +1 -1
- package/dist/testing/client.js +9 -1
- package/dist/testing/client.js.map +1 -1
- package/migrations/0044_events.sql +79 -0
- package/migrations/0045_addresses.sql +66 -0
- package/migrations/0046_drop_company_website.sql +66 -0
- package/migrations/meta/_journal.json +21 -0
- package/package.json +3 -3
- package/src/app.ts +25 -1
- package/src/boot.ts +1 -0
- package/src/lib/apiKeyScopes.ts +6 -0
- package/src/lib/columns.ts +12 -3
- package/src/lib/config.ts +21 -0
- package/src/lib/egress.ts +8 -4
- package/src/lib/errors.ts +16 -9
- package/src/lib/ids.ts +11 -0
- package/src/lib/kelpieConfigFile.ts +69 -1
- package/src/modules/agent-tasks/catalog.ts +33 -1
- package/src/modules/agent-tasks/index.ts +1 -0
- package/src/modules/agent-tasks/resolve.ts +11 -0
- package/src/modules/attachedRecords.ts +85 -13
- package/src/modules/auth/index.ts +1 -0
- package/src/modules/auth/repository.ts +34 -3
- package/src/modules/auth/routes.ts +44 -1
- package/src/modules/auth/service.ts +118 -4
- package/src/modules/companies/repository.ts +1 -0
- package/src/modules/companies/routes.ts +6 -11
- package/src/modules/companies/schema.ts +3 -3
- package/src/modules/companies/service.ts +6 -10
- package/src/modules/core.ts +2 -0
- package/src/modules/custom-fields/repository.ts +2 -0
- package/src/modules/dashboard/index.ts +1 -0
- package/src/modules/dashboard/repository.ts +64 -0
- package/src/modules/dashboard/routes.ts +15 -0
- package/src/modules/dashboard/service.ts +48 -0
- package/src/modules/decisions/repository.ts +2 -0
- package/src/modules/events/attendances.ts +245 -0
- package/src/modules/events/catalog.ts +36 -0
- package/src/modules/events/index.ts +54 -0
- package/src/modules/events/repository.ts +396 -0
- package/src/modules/events/routes.ts +405 -0
- package/src/modules/events/schema.ts +148 -0
- package/src/modules/events/service.ts +443 -0
- package/src/modules/events/tools.ts +118 -0
- package/src/modules/forms/applySubmissionFields.ts +7 -5
- package/src/modules/forms/fillAddresses.ts +185 -0
- package/src/modules/forms/repository.ts +3 -3
- package/src/modules/forms/routes.ts +2 -2
- package/src/modules/forms/schema.ts +2 -2
- package/src/modules/forms/service.ts +2 -2
- package/src/modules/forms/submission.ts +34 -4
- package/src/modules/hiring/roles.ts +2 -1
- package/src/modules/import-export/addresses.ts +150 -0
- package/src/modules/import-export/drafts.ts +7 -9
- package/src/modules/import-export/exportRows.ts +3 -3
- package/src/modules/import-export/plan.ts +30 -2
- package/src/modules/import-export/presets.ts +55 -7
- package/src/modules/import-export/repository.ts +5 -7
- package/src/modules/import-export/writes.ts +8 -4
- package/src/modules/people/repository.ts +1 -0
- package/src/modules/people/routes.ts +6 -6
- package/src/modules/people/schema.ts +7 -5
- package/src/modules/people/service.ts +7 -5
- package/src/modules/plans/repository.ts +2 -2
- package/src/modules/plans/routes.ts +6 -6
- package/src/modules/plans/schema.ts +4 -4
- package/src/modules/plans/service.ts +3 -3
- package/src/modules/plans/tools.ts +2 -2
- package/src/modules/recordTargets.ts +14 -0
- package/src/modules/references.ts +2 -0
- package/src/modules/sample-data/fixture.ts +208 -27
- package/src/modules/sample-data/index.ts +7 -2
- package/src/modules/sample-data/routes.ts +2 -0
- package/src/modules/sample-data/service.ts +166 -49
- package/src/modules/sample-data/tools.ts +4 -3
- package/src/modules/search/index.ts +2 -1
- package/src/modules/search/repository.ts +32 -1
- package/src/modules/search/service.ts +6 -4
- package/src/modules/smtp-email/index.ts +32 -10
- package/src/modules/workspace/repository.ts +18 -0
- package/src/modules/workspace/routes.ts +16 -0
- package/src/modules/workspace/service.ts +59 -14
- package/src/modules/workspace/starters.ts +275 -14
- package/src/modules/workspace/workspaceAccessMiddleware.ts +3 -4
- package/src/runtime/events.ts +2 -0
- package/src/runtime/module.ts +8 -0
- package/src/runtime/registry.ts +122 -8
- package/src/schema/index.ts +1 -0
- package/src/testing/app.ts +14 -1
- package/src/testing/client.ts +11 -1
|
@@ -22,8 +22,12 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
22
22
|
name: 'Name',
|
|
23
23
|
domain: 'Company Domain Name',
|
|
24
24
|
industry: 'Industry',
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
hq_line1: 'Address',
|
|
26
|
+
hq_line2: 'Address 2',
|
|
27
|
+
hq_city: 'City',
|
|
28
|
+
hq_region: 'State/Region',
|
|
29
|
+
hq_postal_code: 'Postal Code',
|
|
30
|
+
hq_country: 'Country',
|
|
27
31
|
description: 'Description',
|
|
28
32
|
},
|
|
29
33
|
people: {
|
|
@@ -35,7 +39,12 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
35
39
|
last_name: 'Last Name',
|
|
36
40
|
email: 'Email',
|
|
37
41
|
phones: 'Phone Number',
|
|
38
|
-
|
|
42
|
+
mailing_line1: 'Address',
|
|
43
|
+
mailing_line2: 'Address 2',
|
|
44
|
+
mailing_city: 'City',
|
|
45
|
+
mailing_region: 'State/Region',
|
|
46
|
+
mailing_postal_code: 'Postal Code',
|
|
47
|
+
mailing_country: 'Country',
|
|
39
48
|
company_domain: 'Company Domain Name',
|
|
40
49
|
title: 'Job Title',
|
|
41
50
|
},
|
|
@@ -59,7 +68,16 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
59
68
|
name: 'Account Name',
|
|
60
69
|
domain: 'Website',
|
|
61
70
|
industry: 'Industry',
|
|
62
|
-
|
|
71
|
+
billing_line1: 'Billing Street',
|
|
72
|
+
billing_city: 'Billing City',
|
|
73
|
+
billing_region: 'Billing State/Province',
|
|
74
|
+
billing_postal_code: 'Billing Zip/Postal Code',
|
|
75
|
+
billing_country: 'Billing Country',
|
|
76
|
+
shipping_line1: 'Shipping Street',
|
|
77
|
+
shipping_city: 'Shipping City',
|
|
78
|
+
shipping_region: 'Shipping State/Province',
|
|
79
|
+
shipping_postal_code: 'Shipping Zip/Postal Code',
|
|
80
|
+
shipping_country: 'Shipping Country',
|
|
63
81
|
description: 'Description',
|
|
64
82
|
},
|
|
65
83
|
people: {
|
|
@@ -69,7 +87,16 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
69
87
|
last_name: 'Last Name',
|
|
70
88
|
email: 'Email',
|
|
71
89
|
phones: 'Phone',
|
|
72
|
-
|
|
90
|
+
mailing_line1: 'Mailing Street',
|
|
91
|
+
mailing_city: 'Mailing City',
|
|
92
|
+
mailing_region: 'Mailing State/Province',
|
|
93
|
+
mailing_postal_code: 'Mailing Zip/Postal Code',
|
|
94
|
+
mailing_country: 'Mailing Country',
|
|
95
|
+
other_line1: 'Other Street',
|
|
96
|
+
other_city: 'Other City',
|
|
97
|
+
other_region: 'Other State/Province',
|
|
98
|
+
other_postal_code: 'Other Zip/Postal Code',
|
|
99
|
+
other_country: 'Other Country',
|
|
73
100
|
company_name: 'Account Name',
|
|
74
101
|
// Salesforce's Contact.Title is the job title, and a job title is a
|
|
75
102
|
// Position. It is not this object's `suffix`, which stays unmapped.
|
|
@@ -101,12 +128,22 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
101
128
|
domain: 'Domains',
|
|
102
129
|
industry: 'Categories',
|
|
103
130
|
description: 'Description',
|
|
104
|
-
|
|
131
|
+
hq_line1: 'Primary location > Line 1',
|
|
132
|
+
hq_line2: 'Primary location > Line 2',
|
|
133
|
+
hq_city: 'Primary location > Locality',
|
|
134
|
+
hq_region: 'Primary location > Region',
|
|
135
|
+
hq_postal_code: 'Primary location > Postcode',
|
|
136
|
+
hq_country: 'Primary location > Country',
|
|
105
137
|
},
|
|
106
138
|
people: {
|
|
107
139
|
name: 'Record',
|
|
108
140
|
email: 'Email addresses',
|
|
109
|
-
|
|
141
|
+
mailing_line1: 'Primary location > Line 1',
|
|
142
|
+
mailing_line2: 'Primary location > Line 2',
|
|
143
|
+
mailing_city: 'Primary location > Locality',
|
|
144
|
+
mailing_region: 'Primary location > Region',
|
|
145
|
+
mailing_postal_code: 'Primary location > Postcode',
|
|
146
|
+
mailing_country: 'Primary location > Country',
|
|
110
147
|
company_name: 'Company > Name',
|
|
111
148
|
title: 'Job title',
|
|
112
149
|
},
|
|
@@ -184,6 +221,9 @@ export function aliasedStageSlug(raw: string): string | undefined {
|
|
|
184
221
|
return ALIASES_BY_SQUASHED_NAME.get(squash(raw))
|
|
185
222
|
}
|
|
186
223
|
|
|
224
|
+
/** A file that names a website but not a domain still has a homepage. */
|
|
225
|
+
const DOMAIN_HEADER_ALIASES = new Set(['website', 'website url', 'url'])
|
|
226
|
+
|
|
187
227
|
/**
|
|
188
228
|
* The column map to use when a request sends none.
|
|
189
229
|
*
|
|
@@ -214,5 +254,13 @@ export function defaultColumnMap(
|
|
|
214
254
|
headers.find((header) => header.toLowerCase() === column.key.toLowerCase()) ?? null
|
|
215
255
|
}
|
|
216
256
|
|
|
257
|
+
if (object === 'companies' && map.domain === null) {
|
|
258
|
+
const alias = headers.find((header) => DOMAIN_HEADER_ALIASES.has(header.toLowerCase()))
|
|
259
|
+
|
|
260
|
+
if (alias !== undefined) {
|
|
261
|
+
map.domain = alias
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
217
265
|
return map
|
|
218
266
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { and, asc, eq, gt, inArray, sql } from 'drizzle-orm'
|
|
2
2
|
|
|
3
|
-
import type { CustomFieldValue } from '@kelpie/schemas'
|
|
3
|
+
import type { CompanyAddress, CustomFieldValue, PersonAddress } from '@kelpie/schemas'
|
|
4
4
|
import type { Queryable } from '../../runtime/transaction.ts'
|
|
5
5
|
import { users } from '../auth/schema.ts'
|
|
6
6
|
import { companies } from '../companies/schema.ts'
|
|
@@ -614,8 +614,7 @@ export interface ExportCompanyRow {
|
|
|
614
614
|
readonly description: string
|
|
615
615
|
readonly summary: string
|
|
616
616
|
readonly tags: readonly string[]
|
|
617
|
-
readonly
|
|
618
|
-
readonly hq: string | null
|
|
617
|
+
readonly addresses: readonly CompanyAddress[]
|
|
619
618
|
readonly customFields: Readonly<Record<string, CustomFieldValue>>
|
|
620
619
|
}
|
|
621
620
|
|
|
@@ -637,8 +636,7 @@ export function readCompanies(
|
|
|
637
636
|
description: companies.description,
|
|
638
637
|
summary: companies.summary,
|
|
639
638
|
tags: companies.tags,
|
|
640
|
-
|
|
641
|
-
hq: companies.hq,
|
|
639
|
+
addresses: companies.addresses,
|
|
642
640
|
customFields: companies.customFields,
|
|
643
641
|
})
|
|
644
642
|
.from(companies)
|
|
@@ -656,7 +654,7 @@ export interface ExportPersonRow {
|
|
|
656
654
|
readonly suffix: string | null
|
|
657
655
|
readonly email: string | null
|
|
658
656
|
readonly timezone: string | null
|
|
659
|
-
readonly
|
|
657
|
+
readonly addresses: readonly PersonAddress[]
|
|
660
658
|
readonly preferredChannel: string
|
|
661
659
|
readonly influence: string
|
|
662
660
|
readonly relationship: string
|
|
@@ -687,7 +685,7 @@ export async function readPeople(
|
|
|
687
685
|
suffix: people.suffix,
|
|
688
686
|
email: people.email,
|
|
689
687
|
timezone: people.timezone,
|
|
690
|
-
|
|
688
|
+
addresses: people.addresses,
|
|
691
689
|
preferredChannel: people.preferredChannel,
|
|
692
690
|
influence: people.influence,
|
|
693
691
|
relationship: people.relationship,
|
|
@@ -148,11 +148,12 @@ async function writeCompany(
|
|
|
148
148
|
'company',
|
|
149
149
|
write.draft.customFields,
|
|
150
150
|
)
|
|
151
|
-
const { customFields: _draftCustomFields, tags, ...rest } = write.draft
|
|
151
|
+
const { customFields: _draftCustomFields, tags, addresses, ...rest } = write.draft
|
|
152
152
|
const created = await companyRepository.insertCompany(tx, {
|
|
153
153
|
...NEW_COMPANY_DEFAULTS,
|
|
154
154
|
...rest,
|
|
155
155
|
tags: tags === undefined ? undefined : [...tags],
|
|
156
|
+
addresses: addresses === undefined ? undefined : [...addresses],
|
|
156
157
|
...(customFields === undefined ? {} : { customFields }),
|
|
157
158
|
id: dependencies.createId('company'),
|
|
158
159
|
workspaceId,
|
|
@@ -169,7 +170,7 @@ async function writeCompany(
|
|
|
169
170
|
throw AppError.notFound('Company not found')
|
|
170
171
|
}
|
|
171
172
|
|
|
172
|
-
const { customFields: draftCustomFields, tags, ...rest } = write.draft
|
|
173
|
+
const { customFields: draftCustomFields, tags, addresses, ...rest } = write.draft
|
|
173
174
|
const customMerge = await validatedCustomFieldsForUpdate(
|
|
174
175
|
tx,
|
|
175
176
|
workspaceId,
|
|
@@ -180,6 +181,7 @@ async function writeCompany(
|
|
|
180
181
|
const columns = {
|
|
181
182
|
...rest,
|
|
182
183
|
tags: tags === undefined ? undefined : [...tags],
|
|
184
|
+
addresses: addresses === undefined ? undefined : [...addresses],
|
|
183
185
|
...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
|
|
184
186
|
}
|
|
185
187
|
const changedFields = [
|
|
@@ -298,12 +300,13 @@ async function writePerson(
|
|
|
298
300
|
'person',
|
|
299
301
|
write.draft.customFields,
|
|
300
302
|
)
|
|
301
|
-
const { customFields: _draftCustomFields, phones, tags, ...rest } = write.draft
|
|
303
|
+
const { customFields: _draftCustomFields, phones, tags, addresses, ...rest } = write.draft
|
|
302
304
|
const created = await peopleRepository.insertPerson(tx, {
|
|
303
305
|
...NEW_PERSON_DEFAULTS,
|
|
304
306
|
...rest,
|
|
305
307
|
phones: phones === undefined ? undefined : [...phones],
|
|
306
308
|
tags: tags === undefined ? undefined : [...tags],
|
|
309
|
+
addresses: addresses === undefined ? undefined : [...addresses],
|
|
307
310
|
...(customFields === undefined ? {} : { customFields }),
|
|
308
311
|
id: dependencies.createId('person'),
|
|
309
312
|
workspaceId,
|
|
@@ -332,7 +335,7 @@ async function writePerson(
|
|
|
332
335
|
throw AppError.notFound('Person not found')
|
|
333
336
|
}
|
|
334
337
|
|
|
335
|
-
const { customFields: draftCustomFields, phones, tags, ...rest } = write.draft
|
|
338
|
+
const { customFields: draftCustomFields, phones, tags, addresses, ...rest } = write.draft
|
|
336
339
|
const customMerge = await validatedCustomFieldsForUpdate(
|
|
337
340
|
tx,
|
|
338
341
|
workspaceId,
|
|
@@ -344,6 +347,7 @@ async function writePerson(
|
|
|
344
347
|
...rest,
|
|
345
348
|
phones: phones === undefined ? undefined : [...phones],
|
|
346
349
|
tags: tags === undefined ? undefined : [...tags],
|
|
350
|
+
addresses: addresses === undefined ? undefined : [...addresses],
|
|
347
351
|
...(customMerge === undefined ? {} : { customFields: customMerge.merged }),
|
|
348
352
|
}
|
|
349
353
|
const changedFields = [
|
|
@@ -74,6 +74,7 @@ function matchesTerm(term: string): SQL | undefined {
|
|
|
74
74
|
ilike(people.email, pattern),
|
|
75
75
|
ilike(people.summary, pattern),
|
|
76
76
|
arrayContainsPattern(people.tags, pattern),
|
|
77
|
+
sql`kelpie_addresses_search_text(${people.addresses}) ilike ${pattern}`,
|
|
77
78
|
heldPositionMatches(pattern),
|
|
78
79
|
)
|
|
79
80
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONSENT_STATUSES, composeName, customFieldsPatchShape } from '@kelpie/schemas'
|
|
1
|
+
import { CONSENT_STATUSES, composeName, customFieldsPatchShape, personAddressesSchema, addressBody } from '@kelpie/schemas'
|
|
2
2
|
import type { NameParts } from '@kelpie/schemas'
|
|
3
3
|
import type { Context, Hono } from 'hono'
|
|
4
4
|
import { z } from 'zod'
|
|
@@ -60,7 +60,7 @@ const personShape = {
|
|
|
60
60
|
phones: z.array(z.string().min(1)),
|
|
61
61
|
social_profiles: z.array(socialProfileBody),
|
|
62
62
|
timezone: z.string().nullable(),
|
|
63
|
-
|
|
63
|
+
addresses: personAddressesSchema,
|
|
64
64
|
preferred_channel: z.enum(PREFERRED_CHANNELS),
|
|
65
65
|
influence: z.enum(INFLUENCE_LEVELS),
|
|
66
66
|
relationship: z.enum(RELATIONSHIP_LEVELS),
|
|
@@ -95,7 +95,7 @@ export const createBody = z
|
|
|
95
95
|
phones: personShape.phones.default([]),
|
|
96
96
|
social_profiles: personShape.social_profiles.default([]),
|
|
97
97
|
timezone: personShape.timezone.default(null),
|
|
98
|
-
|
|
98
|
+
addresses: personShape.addresses.default([]),
|
|
99
99
|
preferred_channel: personShape.preferred_channel.default('email'),
|
|
100
100
|
influence: personShape.influence.default('influencer'),
|
|
101
101
|
relationship: personShape.relationship.default('cold'),
|
|
@@ -137,7 +137,7 @@ export function toCreateInput(body: z.infer<typeof createBody>): CreatePersonInp
|
|
|
137
137
|
phones: body.phones,
|
|
138
138
|
socialProfiles: body.social_profiles,
|
|
139
139
|
timezone: body.timezone,
|
|
140
|
-
|
|
140
|
+
addresses: body.addresses,
|
|
141
141
|
preferredChannel: body.preferred_channel,
|
|
142
142
|
influence: body.influence,
|
|
143
143
|
relationship: body.relationship,
|
|
@@ -173,7 +173,7 @@ export function toUpdateInput(body: z.infer<typeof updateBody>): UpdatePersonInp
|
|
|
173
173
|
...(body.phones === undefined ? {} : { phones: body.phones }),
|
|
174
174
|
...(body.social_profiles === undefined ? {} : { socialProfiles: body.social_profiles }),
|
|
175
175
|
...(body.timezone === undefined ? {} : { timezone: body.timezone }),
|
|
176
|
-
...(body.
|
|
176
|
+
...(body.addresses === undefined ? {} : { addresses: body.addresses }),
|
|
177
177
|
...(body.preferred_channel === undefined ? {} : { preferredChannel: body.preferred_channel }),
|
|
178
178
|
...(body.influence === undefined ? {} : { influence: body.influence }),
|
|
179
179
|
...(body.relationship === undefined ? {} : { relationship: body.relationship }),
|
|
@@ -221,7 +221,7 @@ export function personResponse(person: PersonView): Record<string, unknown> {
|
|
|
221
221
|
phones: person.phones,
|
|
222
222
|
social_profiles: person.socialProfiles,
|
|
223
223
|
timezone: person.timezone,
|
|
224
|
-
|
|
224
|
+
addresses: person.addresses.map(addressBody),
|
|
225
225
|
preferred_channel: person.preferredChannel,
|
|
226
226
|
influence: person.influence,
|
|
227
227
|
relationship: person.relationship,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
PREFERRED_CHANNELS,
|
|
6
6
|
RELATIONSHIP_LEVELS,
|
|
7
7
|
} from '@kelpie/schemas'
|
|
8
|
-
import type { CustomFieldValue, SocialProfile } from '@kelpie/schemas'
|
|
8
|
+
import type { CustomFieldValue, PersonAddress, SocialProfile } from '@kelpie/schemas'
|
|
9
9
|
import { boolean, index, jsonb, pgTable, primaryKey, text, unique } from 'drizzle-orm/pg-core'
|
|
10
10
|
|
|
11
11
|
import {
|
|
@@ -48,9 +48,10 @@ export type { SocialProfile }
|
|
|
48
48
|
* Who you know. Job title is not here: it lives on Position, because a person can
|
|
49
49
|
* hold titles at more than one company.
|
|
50
50
|
*
|
|
51
|
-
* `phones` and `
|
|
52
|
-
* They are typed rather than left as `unknown`, and the
|
|
53
|
-
* goes in, so a row read back is the shape it claims
|
|
51
|
+
* `phones`, `social_profiles`, and `addresses` are jsonb because nothing
|
|
52
|
+
* queries into them. They are typed rather than left as `unknown`, and the
|
|
53
|
+
* route layer parses what goes in, so a row read back is the shape it claims
|
|
54
|
+
* to be.
|
|
54
55
|
*/
|
|
55
56
|
export const people = pgTable(
|
|
56
57
|
'people',
|
|
@@ -75,7 +76,7 @@ export const people = pgTable(
|
|
|
75
76
|
.notNull()
|
|
76
77
|
.default([]),
|
|
77
78
|
timezone: text('timezone'),
|
|
78
|
-
|
|
79
|
+
addresses: jsonb('addresses').$type<readonly PersonAddress[]>().notNull().default([]),
|
|
79
80
|
preferredChannel: text('preferred_channel').notNull(),
|
|
80
81
|
influence: text('influence').notNull(),
|
|
81
82
|
relationship: text('relationship').notNull(),
|
|
@@ -110,6 +111,7 @@ export const people = pgTable(
|
|
|
110
111
|
{ column: people.email, weight: 'B' },
|
|
111
112
|
{ column: people.summary, weight: 'B' },
|
|
112
113
|
{ column: people.tags, weight: 'C', array: true },
|
|
114
|
+
{ column: people.addresses, weight: 'C', addresses: true },
|
|
113
115
|
]),
|
|
114
116
|
},
|
|
115
117
|
(table) => [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ConsentStatus, CustomFieldWireValue } from '@kelpie/schemas'
|
|
1
|
+
import type { ConsentStatus, CustomFieldWireValue, PersonAddress } from '@kelpie/schemas'
|
|
2
2
|
|
|
3
3
|
import { changedKeys } from '../../lib/changes.ts'
|
|
4
4
|
import { UNIQUE_VIOLATION, isReferenceViolation, postgresErrorCode } from '../../lib/database.ts'
|
|
@@ -19,6 +19,7 @@ import { requireWorkspaceId } from '../auth/actor.ts'
|
|
|
19
19
|
import './events.ts'
|
|
20
20
|
import {
|
|
21
21
|
deleteRecordsAttachedTo,
|
|
22
|
+
deleteRecordsAttachedToAttendancesOf,
|
|
22
23
|
deleteRecordsAttachedToCandidaciesOf,
|
|
23
24
|
} from '../attachedRecords.ts'
|
|
24
25
|
import type { CustomFieldValuesValidator } from '../custom-fields/values.ts'
|
|
@@ -69,7 +70,7 @@ const PERSON_FIELD_LABELS: FieldLabels = {
|
|
|
69
70
|
phones: 'Phone numbers',
|
|
70
71
|
socialProfiles: 'Social profiles',
|
|
71
72
|
timezone: 'Timezone',
|
|
72
|
-
|
|
73
|
+
addresses: 'Addresses',
|
|
73
74
|
preferredChannel: 'Preferred channel',
|
|
74
75
|
influence: 'Influence',
|
|
75
76
|
relationship: 'Relationship',
|
|
@@ -110,7 +111,7 @@ export interface CreatePersonInput {
|
|
|
110
111
|
readonly phones: readonly string[]
|
|
111
112
|
readonly socialProfiles: readonly SocialProfile[]
|
|
112
113
|
readonly timezone: string | null
|
|
113
|
-
readonly
|
|
114
|
+
readonly addresses: readonly PersonAddress[]
|
|
114
115
|
readonly preferredChannel: PreferredChannel
|
|
115
116
|
readonly influence: Influence
|
|
116
117
|
readonly relationship: Relationship
|
|
@@ -161,7 +162,7 @@ function toStoredColumns(input: UpdatePersonInput): Partial<repository.PersonCol
|
|
|
161
162
|
...(input.phones === undefined ? {} : { phones: input.phones }),
|
|
162
163
|
...(input.socialProfiles === undefined ? {} : { socialProfiles: input.socialProfiles }),
|
|
163
164
|
...(input.timezone === undefined ? {} : { timezone: input.timezone }),
|
|
164
|
-
...(input.
|
|
165
|
+
...(input.addresses === undefined ? {} : { addresses: input.addresses }),
|
|
165
166
|
...(input.preferredChannel === undefined ? {} : { preferredChannel: input.preferredChannel }),
|
|
166
167
|
...(input.influence === undefined ? {} : { influence: input.influence }),
|
|
167
168
|
...(input.relationship === undefined ? {} : { relationship: input.relationship }),
|
|
@@ -241,7 +242,7 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
|
|
|
241
242
|
phones: input.phones,
|
|
242
243
|
socialProfiles: input.socialProfiles,
|
|
243
244
|
timezone: input.timezone,
|
|
244
|
-
|
|
245
|
+
addresses: input.addresses,
|
|
245
246
|
preferredChannel: input.preferredChannel,
|
|
246
247
|
influence: input.influence,
|
|
247
248
|
relationship: input.relationship,
|
|
@@ -421,6 +422,7 @@ export function createPeopleService(dependencies: PeopleDependencies): PeopleSer
|
|
|
421
422
|
// The candidacy rows themselves cascade, which is why their interview
|
|
422
423
|
// notes have to be taken here: no hiring service sees that delete.
|
|
423
424
|
await deleteRecordsAttachedToCandidaciesOf(tx, workspaceId, id)
|
|
425
|
+
await deleteRecordsAttachedToAttendancesOf(tx, workspaceId, { personId: id })
|
|
424
426
|
|
|
425
427
|
// A person delete failing on a foreign key aborts the enclosing
|
|
426
428
|
// transaction, so the follow-up read that names the referring pipeline
|
|
@@ -11,7 +11,7 @@ import type { ListWindow, SortableFields } from '../../lib/pagination.ts'
|
|
|
11
11
|
import type { Queryable } from '../../runtime/transaction.ts'
|
|
12
12
|
import { workspaceMembers } from '../workspace/schema.ts'
|
|
13
13
|
import { planItems } from './schema.ts'
|
|
14
|
-
import type {
|
|
14
|
+
import type { PlanItemStatus, PlanItemTargetType } from './schema.ts'
|
|
15
15
|
|
|
16
16
|
export type PlanItemRecord = typeof planItems.$inferSelect
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ export const DEFAULT_PLAN_ITEM_SORT = 'date'
|
|
|
39
39
|
|
|
40
40
|
export interface PlanItemFilters {
|
|
41
41
|
/** `?target_type=`: one pipeline. The Planning page's type filter. */
|
|
42
|
-
readonly targetType?:
|
|
42
|
+
readonly targetType?: PlanItemTargetType | undefined
|
|
43
43
|
/** `?target_id=`, repeatable: one record's panel, or a page of records' next steps. */
|
|
44
44
|
readonly targetIds?: readonly string[] | undefined
|
|
45
45
|
/** `?status=`, repeatable. Naming the two open ones is how a caller asks for outstanding work. */
|
|
@@ -8,8 +8,8 @@ import type { Actor } from '../auth/actor.ts'
|
|
|
8
8
|
import { resolveActorFrom } from '../auth/credentials.ts'
|
|
9
9
|
import type { CredentialDependencies } from '../auth/credentials.ts'
|
|
10
10
|
import type { PlanItemFilters } from './repository.ts'
|
|
11
|
-
import {
|
|
12
|
-
import type {
|
|
11
|
+
import { PLAN_ITEM_STATUSES, PLAN_ITEM_TARGET_TYPES } from './schema.ts'
|
|
12
|
+
import type { PlanItemStatus, PlanItemTargetType } from './schema.ts'
|
|
13
13
|
import type {
|
|
14
14
|
CreatePlanItemInput,
|
|
15
15
|
PlanItemView,
|
|
@@ -40,7 +40,7 @@ const planItemShape = {
|
|
|
40
40
|
*/
|
|
41
41
|
export const createBody = z.strictObject({
|
|
42
42
|
...planItemShape,
|
|
43
|
-
target_type: z.enum(
|
|
43
|
+
target_type: z.enum(PLAN_ITEM_TARGET_TYPES),
|
|
44
44
|
target_id: z.string().min(1),
|
|
45
45
|
owner_id: planItemShape.owner_id.default(null),
|
|
46
46
|
status: planItemShape.status.default('todo'),
|
|
@@ -94,18 +94,18 @@ export function toUpdateInput(body: z.infer<typeof updateBody>): UpdatePlanItemI
|
|
|
94
94
|
* cannot attach to a Person, so answering the person question with an empty
|
|
95
95
|
* list would read as "none yet" instead of "that is not a thing".
|
|
96
96
|
*/
|
|
97
|
-
function readTargetType(context: Context):
|
|
97
|
+
function readTargetType(context: Context): PlanItemTargetType | undefined {
|
|
98
98
|
const raw = context.req.query('target_type')
|
|
99
99
|
|
|
100
100
|
if (raw === undefined) {
|
|
101
101
|
return undefined
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const parsed = z.enum(
|
|
104
|
+
const parsed = z.enum(PLAN_ITEM_TARGET_TYPES).safeParse(raw)
|
|
105
105
|
|
|
106
106
|
if (!parsed.success) {
|
|
107
107
|
throw AppError.validationFailed('That is not a record type a plan item attaches to', [
|
|
108
|
-
{ field: 'target_type', message: `Use one of: ${
|
|
108
|
+
{ field: 'target_type', message: `Use one of: ${PLAN_ITEM_TARGET_TYPES.join(', ')}` },
|
|
109
109
|
])
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PLAN_ITEM_STATUSES, PLAN_ITEM_TARGET_TYPES } from '@kelpie/schemas'
|
|
2
2
|
import { date, index, pgTable, text } from 'drizzle-orm/pg-core'
|
|
3
3
|
|
|
4
4
|
import { checkOneOf, createdAt, primaryId, searchVector, updatedAt } from '../../lib/columns.ts'
|
|
@@ -6,8 +6,8 @@ import type { SearchVectorPart } from '../../lib/columns.ts'
|
|
|
6
6
|
import { workspaceMembers, workspaces } from '../workspace/schema.ts'
|
|
7
7
|
|
|
8
8
|
/** Re-exported for the routes and service that constrain themselves to this table. */
|
|
9
|
-
export {
|
|
10
|
-
export type {
|
|
9
|
+
export { PLAN_ITEM_STATUSES, PLAN_ITEM_TARGET_TYPES } from '@kelpie/schemas'
|
|
10
|
+
export type { PlanItemStatus, PlanItemTargetType } from '@kelpie/schemas'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Dated action items on the four pipelines. These replace any next-step text
|
|
@@ -39,7 +39,7 @@ export const planItems = pgTable(
|
|
|
39
39
|
index('plan_items_target_idx').on(table.workspaceId, table.targetType, table.targetId),
|
|
40
40
|
index('plan_items_date_idx').on(table.workspaceId, table.date),
|
|
41
41
|
index('plan_items_search_idx').using('gin', table.searchVector),
|
|
42
|
-
checkOneOf('plan_items_target_type_check', table.targetType,
|
|
42
|
+
checkOneOf('plan_items_target_type_check', table.targetType, PLAN_ITEM_TARGET_TYPES),
|
|
43
43
|
checkOneOf('plan_items_status_check', table.status, PLAN_ITEM_STATUSES),
|
|
44
44
|
],
|
|
45
45
|
)
|
|
@@ -13,7 +13,7 @@ import { targetExists } from '../recordTargets.ts'
|
|
|
13
13
|
import * as repository from './repository.ts'
|
|
14
14
|
import { DEFAULT_PLAN_ITEM_SORT, PLAN_ITEM_SORTS } from './repository.ts'
|
|
15
15
|
import type { PlanItemFilters, PlanItemRecord } from './repository.ts'
|
|
16
|
-
import type {
|
|
16
|
+
import type { PlanItemStatus, PlanItemTargetType } from './schema.ts'
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Plan items: the dated next steps on a Deal, Opportunity, Raise or Partnership.
|
|
@@ -39,7 +39,7 @@ export interface PlansDependencies {
|
|
|
39
39
|
export type PlanItemView = Omit<PlanItemRecord, 'workspaceId'>
|
|
40
40
|
|
|
41
41
|
export interface CreatePlanItemInput {
|
|
42
|
-
readonly targetType:
|
|
42
|
+
readonly targetType: PlanItemTargetType
|
|
43
43
|
readonly targetId: string
|
|
44
44
|
/** `YYYY-MM-DD`. Validated as a real calendar date at the boundary. */
|
|
45
45
|
readonly date: string
|
|
@@ -94,7 +94,7 @@ export function createPlansService(dependencies: PlansDependencies): PlansServic
|
|
|
94
94
|
|
|
95
95
|
async function requireTarget(
|
|
96
96
|
workspaceId: string,
|
|
97
|
-
targetType:
|
|
97
|
+
targetType: PlanItemTargetType,
|
|
98
98
|
targetId: string,
|
|
99
99
|
): Promise<void> {
|
|
100
100
|
if (!(await targetExists(dependencies.db, workspaceId, targetType, targetId))) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PLAN_ITEM_STATUSES, PLAN_ITEM_TARGET_TYPES } from '@kelpie/schemas'
|
|
2
2
|
import { isoDateSchema } from '../../lib/dates.ts'
|
|
3
3
|
import { z } from 'zod'
|
|
4
4
|
|
|
@@ -11,7 +11,7 @@ import type { PlansService } from './service.ts'
|
|
|
11
11
|
|
|
12
12
|
const listArgs = z.strictObject({
|
|
13
13
|
...listWindowShape,
|
|
14
|
-
target_type: z.enum(
|
|
14
|
+
target_type: z.enum(PLAN_ITEM_TARGET_TYPES).optional().describe("One target type's plan items."),
|
|
15
15
|
target_id: idSetArg.optional().describe('The plan items on these records.'),
|
|
16
16
|
status: enumSetArg(PLAN_ITEM_STATUSES)
|
|
17
17
|
.optional()
|
|
@@ -5,6 +5,7 @@ import type { Queryable } from '../runtime/transaction.ts'
|
|
|
5
5
|
import { companies } from './companies/schema.ts'
|
|
6
6
|
import { deals } from './deals/schema.ts'
|
|
7
7
|
import { enquiries } from './enquiries/schema.ts'
|
|
8
|
+
import { attendances, events } from './events/schema.ts'
|
|
8
9
|
import { candidates } from './hiring/schema.ts'
|
|
9
10
|
import { RECORD_TARGET_TYPES } from './notes/schema.ts'
|
|
10
11
|
import { opportunities } from './opportunities/schema.ts'
|
|
@@ -67,6 +68,8 @@ const TABLES: Readonly<Record<RecordTargetType, TargetTable>> = {
|
|
|
67
68
|
raise: targetTable(raises, raises.id, raises.workspaceId, raises.name),
|
|
68
69
|
enquiry: targetTable(enquiries, enquiries.id, enquiries.workspaceId, enquiries.name),
|
|
69
70
|
candidate: targetTable(candidates, candidates.id, candidates.workspaceId),
|
|
71
|
+
event: targetTable(events, events.id, events.workspaceId, events.name),
|
|
72
|
+
attendance: targetTable(attendances, attendances.id, attendances.workspaceId),
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
export function isRecordTargetType(value: string): value is RecordTargetType {
|
|
@@ -141,7 +144,18 @@ async function namesOfType(
|
|
|
141
144
|
// A Candidate's label is the person's name. The role it is for is the other
|
|
142
145
|
// half of the answer, but a timeline row already says which record it is on,
|
|
143
146
|
// so repeating the title in the name would read as "Ada Lovelace" twice over.
|
|
147
|
+
// An Attendance is the same shape: Person↔Event, labelled by the person.
|
|
144
148
|
if (target.name === undefined) {
|
|
149
|
+
if (targetType === 'attendance') {
|
|
150
|
+
return db
|
|
151
|
+
.select({ id: attendances.id, name: people.name })
|
|
152
|
+
.from(attendances)
|
|
153
|
+
.innerJoin(people, eq(attendances.personId, people.id))
|
|
154
|
+
.where(
|
|
155
|
+
and(eq(attendances.workspaceId, workspaceId), inArray(attendances.id, [...targetIds])),
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
145
159
|
return db
|
|
146
160
|
.select({ id: candidates.id, name: people.name })
|
|
147
161
|
.from(candidates)
|
|
@@ -23,6 +23,8 @@ import { AppError } from '../lib/errors.ts'
|
|
|
23
23
|
*/
|
|
24
24
|
const REFERENCING_TYPE_BY_TABLE: Readonly<Record<string, string>> = {
|
|
25
25
|
candidates: 'candidate',
|
|
26
|
+
events: 'event',
|
|
27
|
+
attendances: 'attendance',
|
|
26
28
|
deals: 'deal',
|
|
27
29
|
enquiries: 'enquiry',
|
|
28
30
|
form_submissions: 'form submission',
|