placementt-core 1.400.932 → 1.400.934

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.
@@ -19,7 +19,53 @@ export type ChecklistItem = {
19
19
  oId: string;
20
20
  name: string;
21
21
  status: ChecklistItemStatus;
22
+ packageFormat?: OnboardingPackFormat;
23
+ packageItems?: string[];
24
+ productTypes?: OnboardingProductType[];
25
+ address?: string;
22
26
  };
27
+ export type OnboardingPackFormat = "box" | "A4 letter";
28
+ export type OnboardingProductType = "careersHub" | "careersHubSchool" | "trust" | "workExperience" | "employerEvents" | "destinations";
29
+ export type OnboardingProductPack = {
30
+ format: OnboardingPackFormat;
31
+ /** Product-specific items only — universal items are added automatically. */
32
+ items: string[];
33
+ };
34
+ export declare const ONBOARDING_BOX_UNIVERSAL_ITEMS: string[];
35
+ export declare const ONBOARDING_LETTER_UNIVERSAL_ITEMS: string[];
36
+ export declare const onboardingPackConfig: Record<OnboardingProductType, OnboardingProductPack>;
37
+ export type OnboardingInstituteInput = {
38
+ package?: string;
39
+ workExperience?: boolean;
40
+ employerEvents?: boolean;
41
+ destinationTracking?: boolean;
42
+ careersHubLinks?: {
43
+ [oId: string]: {
44
+ status?: string;
45
+ };
46
+ };
47
+ ["address-line1"]?: string;
48
+ ["address-line2"]?: string;
49
+ locality?: string;
50
+ postal_code?: string;
51
+ country?: string;
52
+ };
53
+ /** Which onboarding product types a given institute holds. */
54
+ export declare function getOnboardingProductTypes(ins: OnboardingInstituteInput): OnboardingProductType[];
55
+ export type OnboardingPackage = {
56
+ format: OnboardingPackFormat;
57
+ productTypes: OnboardingProductType[];
58
+ items: string[];
59
+ };
60
+ /**
61
+ * Build the single onboarding package for an institute.
62
+ * Returns null if the institute holds no relevant products.
63
+ * "Box wins": any box product upgrades the whole package to a box and the A4
64
+ * items (e.g. the hub one-pager) are merged in, de-duplicated.
65
+ */
66
+ export declare function buildOnboardingPackage(ins: OnboardingInstituteInput): OnboardingPackage | null;
67
+ /** Human-readable single-line address from institute fields. */
68
+ export declare function formatInstituteAddress(ins: OnboardingInstituteInput): string;
23
69
  export type PhoneCheckInCategory = "careersHub" | "trust" | "workExperience" | "employerEvents" | null;
24
70
  export type CustomerCareConfig = {
25
71
  seasonalTasks: SeasonalTaskConfig[];
@@ -1,9 +1,115 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.customerCareConfig = void 0;
3
+ exports.customerCareConfig = exports.onboardingPackConfig = exports.ONBOARDING_LETTER_UNIVERSAL_ITEMS = exports.ONBOARDING_BOX_UNIVERSAL_ITEMS = void 0;
4
+ exports.getOnboardingProductTypes = getOnboardingProductTypes;
5
+ exports.buildOnboardingPackage = buildOnboardingPackage;
6
+ exports.formatInstituteAddress = formatInstituteAddress;
4
7
  exports.resolveSeasonalDates = resolveSeasonalDates;
5
8
  exports.isInBlackout = isInBlackout;
6
9
  exports.getCheckInCategory = getCheckInCategory;
10
+ // Universal items every BOX contains, regardless of product.
11
+ exports.ONBOARDING_BOX_UNIVERSAL_ITEMS = [
12
+ "Handwritten A6 card",
13
+ "Sticky notes",
14
+ "Highlighter",
15
+ "2 pens",
16
+ "Sticker",
17
+ ];
18
+ // Universal items every A4 LETTER contains, regardless of product.
19
+ exports.ONBOARDING_LETTER_UNIVERSAL_ITEMS = [
20
+ "Handwritten A6 card",
21
+ ];
22
+ // TODO(customer-success): refine the exact leaflet names/contents per product.
23
+ exports.onboardingPackConfig = {
24
+ careersHubSchool: {
25
+ format: "A4 letter",
26
+ // Hub schools are just users of the hub product → information one-pager.
27
+ items: ["Careers Hub platform one-pager"],
28
+ },
29
+ careersHub: {
30
+ format: "box",
31
+ items: ["Careers Hub platform guide leaflet", "New features leaflet"],
32
+ },
33
+ trust: {
34
+ format: "box",
35
+ items: ["Trust platform guide leaflet", "New features leaflet"],
36
+ },
37
+ workExperience: {
38
+ format: "box",
39
+ items: ["Work Experience platform guide leaflet", "New features leaflet"],
40
+ },
41
+ employerEvents: {
42
+ format: "box",
43
+ items: ["Employer Events platform guide leaflet", "New features leaflet"],
44
+ },
45
+ destinations: {
46
+ format: "box",
47
+ items: ["Destinations platform guide leaflet", "New features leaflet"],
48
+ },
49
+ };
50
+ /** Which onboarding product types a given institute holds. */
51
+ function getOnboardingProductTypes(ins) {
52
+ const types = [];
53
+ if (ins.package === "careersHub")
54
+ types.push("careersHub");
55
+ const isHubSchool = ins.package === "careersSchool" ||
56
+ Object.values(ins.careersHubLinks || {}).some((l) => l.status === "approved");
57
+ if (isHubSchool)
58
+ types.push("careersHubSchool");
59
+ if (ins.package === "institutes-two")
60
+ types.push("trust");
61
+ // Add-on products apply whenever the flag is set (institutes-one or trusts).
62
+ if (ins.workExperience)
63
+ types.push("workExperience");
64
+ if (ins.employerEvents)
65
+ types.push("employerEvents");
66
+ if (ins.destinationTracking)
67
+ types.push("destinations");
68
+ return types;
69
+ }
70
+ // Case-insensitive, order-preserving de-duplication.
71
+ function dedupeItems(items) {
72
+ const seen = new Set();
73
+ const out = [];
74
+ for (const item of items) {
75
+ const key = item.trim().toLowerCase();
76
+ if (seen.has(key))
77
+ continue;
78
+ seen.add(key);
79
+ out.push(item);
80
+ }
81
+ return out;
82
+ }
83
+ /**
84
+ * Build the single onboarding package for an institute.
85
+ * Returns null if the institute holds no relevant products.
86
+ * "Box wins": any box product upgrades the whole package to a box and the A4
87
+ * items (e.g. the hub one-pager) are merged in, de-duplicated.
88
+ */
89
+ function buildOnboardingPackage(ins) {
90
+ const productTypes = getOnboardingProductTypes(ins);
91
+ if (productTypes.length === 0)
92
+ return null;
93
+ const isBox = productTypes.some((t) => exports.onboardingPackConfig[t].format === "box");
94
+ const format = isBox ? "box" : "A4 letter";
95
+ const universal = isBox ? exports.ONBOARDING_BOX_UNIVERSAL_ITEMS : exports.ONBOARDING_LETTER_UNIVERSAL_ITEMS;
96
+ const productItems = productTypes.flatMap((t) => exports.onboardingPackConfig[t].items);
97
+ return {
98
+ format,
99
+ productTypes,
100
+ items: dedupeItems([...universal, ...productItems]),
101
+ };
102
+ }
103
+ /** Human-readable single-line address from institute fields. */
104
+ function formatInstituteAddress(ins) {
105
+ return [
106
+ ins["address-line1"],
107
+ ins["address-line2"],
108
+ ins.locality,
109
+ ins.postal_code,
110
+ ins.country,
111
+ ].filter(Boolean).join(", ");
112
+ }
7
113
  exports.customerCareConfig = {
8
114
  seasonalTasks: [
9
115
  {
@@ -21,6 +127,15 @@ exports.customerCareConfig = {
21
127
  createAtMMDD: "03-09",
22
128
  description: "Send Easter eggs to admin staff at every active school.",
23
129
  },
130
+ {
131
+ // Start-of-year onboarding packs. Created at the start of August so
132
+ // there's time to prepare; should be sent by the start of term.
133
+ id: "onboardingPacks",
134
+ name: "Onboarding Packs",
135
+ deadlineMMDD: "09-15",
136
+ createAtMMDD: "08-01",
137
+ description: "Send the start-of-year onboarding pack (box or A4 letter) to every active customer. Each school's exact contents and format are listed against it.",
138
+ },
24
139
  ],
25
140
  phoneCheckIn: {
26
141
  careersHub: { intervalDays: 42, label: "Careers Hub" },
@@ -1 +1 @@
1
- {"version":3,"file":"customerCareConfig.js","sourceRoot":"","sources":["../src/customerCareConfig.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"customerCareConfig.js","sourceRoot":"","sources":["../src/customerCareConfig.ts"],"names":[],"mappings":"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"}
@@ -397,6 +397,7 @@ export type UserData = {
397
397
  groupData?: UserGroupData;
398
398
  staffRoles: string[];
399
399
  flags?: FlagCodes[];
400
+ keyContact?: boolean;
400
401
  cohortRequests: {
401
402
  [oId: string]: string[];
402
403
  };
@@ -2857,6 +2858,8 @@ export type SkillAssessment = {
2857
2858
  email: string;
2858
2859
  forename: string;
2859
2860
  surname: string;
2861
+ completedByStaff?: boolean;
2862
+ completedByStaffId?: string;
2860
2863
  };
2861
2864
  export type SkillAssessmentRequest = {
2862
2865
  dateCreated: Timestamp;
@@ -3035,7 +3038,7 @@ export type SupportTask = {
3035
3038
  assignee: string;
3036
3039
  commId?: string;
3037
3040
  commType?: "leads" | "users";
3038
- source?: "customerQuery" | "general" | "seasonalTask";
3041
+ source?: "customerQuery" | "general" | "seasonalTask" | "onboardingPack";
3039
3042
  dueAt: string;
3040
3043
  inbox?: SupportInbox;
3041
3044
  messageId?: string;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "private": false,
3
3
  "name": "placementt-core",
4
4
  "author": "Placementt",
5
- "version": "1.400.932",
5
+ "version": "1.400.934",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
8
8
  "scripts": {
@@ -25,8 +25,178 @@ export type ChecklistItem = {
25
25
  oId: string;
26
26
  name: string;
27
27
  status: ChecklistItemStatus;
28
+ // ── Onboarding-pack extras (only populated on onboardingPack tasks) ──
29
+ // The package contents are baked in at task-creation time so the
30
+ // customer-success team always sees exactly what to pack, even if the
31
+ // institute's products change later.
32
+ packageFormat?: OnboardingPackFormat;
33
+ packageItems?: string[];
34
+ productTypes?: OnboardingProductType[];
35
+ address?: string;
28
36
  };
29
37
 
38
+ // ─── Onboarding packs ─────────────────────────────────────────────────────────
39
+ // Hardcoded definition of what goes into each customer's onboarding pack.
40
+ // Keyed by product type; each entry declares the package format and the
41
+ // product-specific items (universal items are added by buildOnboardingPackage).
42
+ //
43
+ // Rules (see buildOnboardingPackage):
44
+ // - "box" always wins: if a school holds any box product, it gets a single box
45
+ // and every product's specific items are merged in (de-duplicated).
46
+ // - A school that is *only* a hub-linked school gets an A4 letter. The moment
47
+ // they hold any higher package it becomes a box, and the A4 hub one-pager is
48
+ // folded into the box (de-duplicated).
49
+
50
+ export type OnboardingPackFormat = "box" | "A4 letter";
51
+
52
+ // The six product types a customer can hold for onboarding-pack purposes.
53
+ // (Distinct from CustomerProductType because it also covers "destinations".)
54
+ export type OnboardingProductType =
55
+ | "careersHub" // package === "careersHub" (the hub itself)
56
+ | "careersHubSchool" // careersHubLinks approved (a school using a hub)
57
+ | "trust" // package === "institutes-two"
58
+ | "workExperience" // workExperience flag
59
+ | "employerEvents" // employerEvents flag
60
+ | "destinations"; // destinationTracking flag
61
+
62
+ export type OnboardingProductPack = {
63
+ format: OnboardingPackFormat;
64
+ /** Product-specific items only — universal items are added automatically. */
65
+ items: string[];
66
+ };
67
+
68
+ // Universal items every BOX contains, regardless of product.
69
+ export const ONBOARDING_BOX_UNIVERSAL_ITEMS: string[] = [
70
+ "Handwritten A6 card",
71
+ "Sticky notes",
72
+ "Highlighter",
73
+ "2 pens",
74
+ "Sticker",
75
+ ];
76
+
77
+ // Universal items every A4 LETTER contains, regardless of product.
78
+ export const ONBOARDING_LETTER_UNIVERSAL_ITEMS: string[] = [
79
+ "Handwritten A6 card",
80
+ ];
81
+
82
+ // TODO(customer-success): refine the exact leaflet names/contents per product.
83
+ export const onboardingPackConfig: Record<OnboardingProductType, OnboardingProductPack> = {
84
+ careersHubSchool: {
85
+ format: "A4 letter",
86
+ // Hub schools are just users of the hub product → information one-pager.
87
+ items: ["Careers Hub platform one-pager"],
88
+ },
89
+ careersHub: {
90
+ format: "box",
91
+ items: ["Careers Hub platform guide leaflet", "New features leaflet"],
92
+ },
93
+ trust: {
94
+ format: "box",
95
+ items: ["Trust platform guide leaflet", "New features leaflet"],
96
+ },
97
+ workExperience: {
98
+ format: "box",
99
+ items: ["Work Experience platform guide leaflet", "New features leaflet"],
100
+ },
101
+ employerEvents: {
102
+ format: "box",
103
+ items: ["Employer Events platform guide leaflet", "New features leaflet"],
104
+ },
105
+ destinations: {
106
+ format: "box",
107
+ items: ["Destinations platform guide leaflet", "New features leaflet"],
108
+ },
109
+ };
110
+
111
+ // Minimal shape of the institute fields we read — declared locally to avoid a
112
+ // circular import with typeDefinitions (which imports ChecklistItem from here).
113
+ export type OnboardingInstituteInput = {
114
+ package?: string;
115
+ workExperience?: boolean;
116
+ employerEvents?: boolean;
117
+ destinationTracking?: boolean;
118
+ careersHubLinks?: {[oId: string]: {status?: string}};
119
+ ["address-line1"]?: string;
120
+ ["address-line2"]?: string;
121
+ locality?: string;
122
+ postal_code?: string;
123
+ country?: string;
124
+ };
125
+
126
+ /** Which onboarding product types a given institute holds. */
127
+ export function getOnboardingProductTypes(ins: OnboardingInstituteInput): OnboardingProductType[] {
128
+ const types: OnboardingProductType[] = [];
129
+
130
+ if (ins.package === "careersHub") types.push("careersHub");
131
+
132
+ const isHubSchool =
133
+ ins.package === "careersSchool" ||
134
+ Object.values(ins.careersHubLinks || {}).some((l) => l.status === "approved");
135
+ if (isHubSchool) types.push("careersHubSchool");
136
+
137
+ if (ins.package === "institutes-two") types.push("trust");
138
+
139
+ // Add-on products apply whenever the flag is set (institutes-one or trusts).
140
+ if (ins.workExperience) types.push("workExperience");
141
+ if (ins.employerEvents) types.push("employerEvents");
142
+ if (ins.destinationTracking) types.push("destinations");
143
+
144
+ return types;
145
+ }
146
+
147
+ // Case-insensitive, order-preserving de-duplication.
148
+ function dedupeItems(items: string[]): string[] {
149
+ const seen = new Set<string>();
150
+ const out: string[] = [];
151
+ for (const item of items) {
152
+ const key = item.trim().toLowerCase();
153
+ if (seen.has(key)) continue;
154
+ seen.add(key);
155
+ out.push(item);
156
+ }
157
+ return out;
158
+ }
159
+
160
+ export type OnboardingPackage = {
161
+ format: OnboardingPackFormat;
162
+ productTypes: OnboardingProductType[];
163
+ items: string[];
164
+ };
165
+
166
+ /**
167
+ * Build the single onboarding package for an institute.
168
+ * Returns null if the institute holds no relevant products.
169
+ * "Box wins": any box product upgrades the whole package to a box and the A4
170
+ * items (e.g. the hub one-pager) are merged in, de-duplicated.
171
+ */
172
+ export function buildOnboardingPackage(ins: OnboardingInstituteInput): OnboardingPackage | null {
173
+ const productTypes = getOnboardingProductTypes(ins);
174
+ if (productTypes.length === 0) return null;
175
+
176
+ const isBox = productTypes.some((t) => onboardingPackConfig[t].format === "box");
177
+ const format: OnboardingPackFormat = isBox ? "box" : "A4 letter";
178
+
179
+ const universal = isBox ? ONBOARDING_BOX_UNIVERSAL_ITEMS : ONBOARDING_LETTER_UNIVERSAL_ITEMS;
180
+ const productItems = productTypes.flatMap((t) => onboardingPackConfig[t].items);
181
+
182
+ return {
183
+ format,
184
+ productTypes,
185
+ items: dedupeItems([...universal, ...productItems]),
186
+ };
187
+ }
188
+
189
+ /** Human-readable single-line address from institute fields. */
190
+ export function formatInstituteAddress(ins: OnboardingInstituteInput): string {
191
+ return [
192
+ ins["address-line1"],
193
+ ins["address-line2"],
194
+ ins.locality,
195
+ ins.postal_code,
196
+ ins.country,
197
+ ].filter(Boolean).join(", ");
198
+ }
199
+
30
200
  export type PhoneCheckInCategory = "careersHub" | "trust" | "workExperience" | "employerEvents" | null;
31
201
 
32
202
  export type CustomerCareConfig = {
@@ -57,6 +227,15 @@ export const customerCareConfig: CustomerCareConfig = {
57
227
  createAtMMDD: "03-09",
58
228
  description: "Send Easter eggs to admin staff at every active school.",
59
229
  },
230
+ {
231
+ // Start-of-year onboarding packs. Created at the start of August so
232
+ // there's time to prepare; should be sent by the start of term.
233
+ id: "onboardingPacks",
234
+ name: "Onboarding Packs",
235
+ deadlineMMDD: "09-15",
236
+ createAtMMDD: "08-01",
237
+ description: "Send the start-of-year onboarding pack (box or A4 letter) to every active customer. Each school's exact contents and format are listed against it.",
238
+ },
60
239
  ],
61
240
  phoneCheckIn: {
62
241
  careersHub: {intervalDays: 42, label: "Careers Hub"},
@@ -407,6 +407,7 @@ export type UserData = {
407
407
  groupData?: UserGroupData,
408
408
  staffRoles: string[],
409
409
  flags?: FlagCodes[],
410
+ keyContact?: boolean, // Staff member who should receive customer-success packages (e.g. onboarding packs)
410
411
  cohortRequests: {[oId: string]: string[]},
411
412
  cohorts: {[oId: string]: string[]},
412
413
  analytics?: AnalyticsItem,
@@ -2764,7 +2765,7 @@ export type SkillAssessment = {
2764
2765
  dateCompleted: Timestamp,
2765
2766
  uid: string,
2766
2767
  scores: {
2767
- [skill: string]: number,
2768
+ [skill: string]: number,
2768
2769
  },
2769
2770
  externalKey?: string,
2770
2771
  userType: "parents"|"employers"|"students",
@@ -2773,6 +2774,8 @@ export type SkillAssessment = {
2773
2774
  email: string,
2774
2775
  forename: string,
2775
2776
  surname: string,
2777
+ completedByStaff?: boolean, // true when a staff member submitted scores on the student's behalf
2778
+ completedByStaffId?: string, // uid of the staff member who submitted
2776
2779
  }
2777
2780
 
2778
2781
  export type SkillAssessmentRequest = {
@@ -3015,7 +3018,7 @@ export type SupportTask = {
3015
3018
  assignee: string; // uid of the assigned team member
3016
3019
  commId?: string; // optional link to a Communication doc
3017
3020
  commType?: "leads" | "users"; // collection the comm lives in
3018
- source?: "customerQuery" | "general" | "seasonalTask";
3021
+ source?: "customerQuery" | "general" | "seasonalTask" | "onboardingPack";
3019
3022
  dueAt: string; // ISO string
3020
3023
  inbox?: SupportInbox; // which task inbox triggered this (absent for non-email tasks)
3021
3024
  messageId?: string; // Graph message ID — used to prevent duplicates