placementt-core 1.400.921 → 1.400.923

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.
@@ -883,6 +883,7 @@ export type InstituteData = {
883
883
  yearGroupsIncluded?: number[];
884
884
  closeAfterDays?: number;
885
885
  };
886
+ destinationsConfig?: DestinationsConfig;
886
887
  acceptingAlumni?: boolean;
887
888
  approveAlumni?: boolean;
888
889
  shareAlumni?: boolean;
@@ -905,6 +906,7 @@ export type InstituteData = {
905
906
  provider?: string;
906
907
  };
907
908
  skillsAssessments?: boolean;
909
+ assessActivitySkills?: boolean;
908
910
  skills: string[];
909
911
  scheduledSkillsAssessments?: {
910
912
  [key in "yearStart" | "yearEnd" | "eachTerm" | "preWorkExperience" | "postWorkExperience" | "employerInteraction"]?: {
@@ -1982,6 +1984,76 @@ export type AspirationCycle = {
1982
1984
  aggregates?: AspirationAggregates;
1983
1985
  emailTemplateId?: string;
1984
1986
  studentSelection?: string;
1987
+ autoProvisioned?: boolean;
1988
+ resolveRecipientsAtSend?: boolean;
1989
+ };
1990
+ /**
1991
+ * Extra recipient constraints beyond "active student in the target year group".
1992
+ * Same shape as a cohortFilters entry. Empty/absent = every active student in the
1993
+ * year group. Stored on DestinationsConfig and re-resolved at each send so the
1994
+ * cohort always reflects the live roster (students roll up a year each September).
1995
+ */
1996
+ export type DestinationsRecipientFilter = {
1997
+ k: string;
1998
+ e?: WhereFilterOp;
1999
+ v: unknown;
2000
+ }[];
2001
+ /** One scheduled survey in a year's aspiration programme. `sendMMDD` is "MM-DD". */
2002
+ export type AspirationSurveySlot = {
2003
+ sendMMDD: string;
2004
+ label?: string;
2005
+ };
2006
+ /**
2007
+ * One-time Destinations setup, saved on institutes/{oId}.destinationsConfig by the
2008
+ * setup wizard. destinationsProvisionCron reads it each year to auto-create that
2009
+ * year's aspiration cycles and leaver groups. All MM-DD strings are zero-padded
2010
+ * (e.g. "09-15"). Recipients are NOT frozen here — only the filter rule is stored;
2011
+ * the actual student list is resolved when each form's emails fire.
2012
+ */
2013
+ export type DestinationsConfig = {
2014
+ aspirations: {
2015
+ enabled: boolean;
2016
+ yearGroups: number[];
2017
+ /** Shared schedule applied to every selected year group (1–3 sends/year). */
2018
+ surveys: AspirationSurveySlot[];
2019
+ /** Optional per-year-group override. When a year group key is present its
2020
+ * schedule REPLACES `surveys` for that year group only. */
2021
+ surveysByYearGroup?: {
2022
+ [yearGroup: string]: AspirationSurveySlot[];
2023
+ };
2024
+ closeAfterDays: number;
2025
+ /** Extra constraints on top of "active Year-N student". Re-resolved each send. */
2026
+ recipientFilters?: DestinationsRecipientFilter;
2027
+ };
2028
+ leavers: {
2029
+ enabled: boolean;
2030
+ yearGroups: number[];
2031
+ intentionsSendMMDD: string;
2032
+ resultsDay: {
2033
+ enabled: boolean;
2034
+ sendMMDD: string;
2035
+ };
2036
+ christmas: {
2037
+ enabled: boolean;
2038
+ sendMMDD: string;
2039
+ };
2040
+ /** true → every student in these groups leaves (no internal sixth form). */
2041
+ allStudentsLeave?: boolean;
2042
+ recipientFilters?: DestinationsRecipientFilter;
2043
+ };
2044
+ alumni: {
2045
+ acceptingAlumni: boolean;
2046
+ approveAlumni: boolean;
2047
+ alumniConversations: boolean;
2048
+ visibleToStudents: boolean;
2049
+ };
2050
+ /** MM-DD on which each new academic year's objects are created. Default "09-01". */
2051
+ provisionMMDD: string;
2052
+ /** e.g. "2026/27" — last academic year the cron provisioned. Guards double-provisioning. */
2053
+ lastProvisionedYear?: string;
2054
+ setupCompletedAt: string;
2055
+ setupBy: string;
2056
+ updatedAt?: string;
1985
2057
  };
1986
2058
  /**
1987
2059
  * Pre-aggregated leaver response counts on a LeaverGroup — updated atomically via
@@ -2684,6 +2756,7 @@ export type SkillAssessment = {
2684
2756
  externalKey?: string;
2685
2757
  userType: "parents" | "employers" | "students";
2686
2758
  skillRequest?: string;
2759
+ activityId?: string;
2687
2760
  email: string;
2688
2761
  forename: string;
2689
2762
  surname: string;
@@ -2768,6 +2841,10 @@ export type StudentActivity = {
2768
2841
  hoursPerSession?: number;
2769
2842
  careerAreas?: string[];
2770
2843
  skillsDeveloped?: string[];
2844
+ skillScores?: {
2845
+ [skill: string]: number;
2846
+ };
2847
+ skillsAssessmentId?: string;
2771
2848
  reflection?: string;
2772
2849
  evidenceFileIds?: string[];
2773
2850
  };
@@ -3035,6 +3112,11 @@ export type LeaverGroup = {
3035
3112
  * asks "are you staying on?" first, and stayers skip the alumni / consent
3036
3113
  * capture (and aren't seeded as alumni). */
3037
3114
  allStudentsLeave?: boolean;
3115
+ /** Created by destinationsProvisionCron from the institute's DestinationsConfig
3116
+ * (not via the manual New Leaver Group flow). Auto-provisioned groups defer
3117
+ * recipient fan-out: leaverRequests are built from `students` when invite
3118
+ * emails fire, so the cohort is always resolved against the live roster. */
3119
+ autoProvisioned?: boolean;
3038
3120
  /** Post-leaving checkpoint schedule. Absent = checkpoints disabled for this group. */
3039
3121
  checkpointConfig?: {
3040
3122
  resultsDay?: {
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.921",
5
+ "version": "1.400.923",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
8
8
  "scripts": {
@@ -871,12 +871,17 @@ export type InstituteData = {
871
871
  }
872
872
  },
873
873
  // ASPIRATION CYCLE CONFIGURATION (Form A — annual student intent tracking)
874
+ // @deprecated dead config — never read at runtime. Superseded by destinationsConfig.
874
875
  aspirationCycleConfig?: {
875
876
  autoSend?: boolean, // if true, cron fires each year on scheduledSendMMDD
876
877
  scheduledSendMMDD?: string, // e.g. "09-15" — MM-DD of annual auto-send
877
878
  yearGroupsIncluded?: number[], // which year groups receive Form A; default [7,8,9,10,11]
878
879
  closeAfterDays?: number, // default 21 — link validity window
879
880
  },
881
+ // DESTINATIONS SETUP + ANNUAL AUTO-PROVISIONING (Form A + Form B + checkpoints)
882
+ // Written by the setup wizard (aspirations-saveDestinationsConfig); read by
883
+ // destinationsProvisionCron each September to create that year's surveys/groups.
884
+ destinationsConfig?: DestinationsConfig,
880
885
  acceptingAlumni?: boolean,
881
886
  approveAlumni?: boolean,
882
887
  shareAlumni?: boolean
@@ -900,6 +905,7 @@ export type InstituteData = {
900
905
  },
901
906
  // SKILLS ASSESSMENT CONFIGURATION
902
907
  skillsAssessments?: boolean,
908
+ assessActivitySkills?: boolean, // ask students to self-assess skills when logging an extracurricular activity
903
909
  skills: string[]
904
910
  scheduledSkillsAssessments?: {
905
911
  [key in "yearStart" | "yearEnd" | "eachTerm" | "preWorkExperience" | "postWorkExperience" | "employerInteraction"]?: {
@@ -1894,7 +1900,68 @@ export type AspirationCycle = {
1894
1900
  reminderSentAt?: string, // ISO — day-14 reminder fire time
1895
1901
  aggregates?: AspirationAggregates, // pre-aggregated response data for dashboard charts
1896
1902
  emailTemplateId?: string, // optional custom email template; falls back to system default
1897
- studentSelection?: string, // JSON-serialised DataViewerSelectionBackend — audit of staff-picked recipients
1903
+ studentSelection?: string, // JSON-serialised DataViewerSelectionBackend — audit of staff-picked recipients (or the rule to re-resolve when resolveRecipientsAtSend)
1904
+ autoProvisioned?: boolean, // created by destinationsProvisionCron from the institute's DestinationsConfig, not by staff
1905
+ resolveRecipientsAtSend?: boolean, // true on auto-provisioned cycles — aspirationRequests are fanned out from studentSelection when emails fire, not at creation
1906
+ }
1907
+
1908
+ /**
1909
+ * Extra recipient constraints beyond "active student in the target year group".
1910
+ * Same shape as a cohortFilters entry. Empty/absent = every active student in the
1911
+ * year group. Stored on DestinationsConfig and re-resolved at each send so the
1912
+ * cohort always reflects the live roster (students roll up a year each September).
1913
+ */
1914
+ export type DestinationsRecipientFilter = {k: string, e?: WhereFilterOp, v: unknown}[];
1915
+
1916
+ /** One scheduled survey in a year's aspiration programme. `sendMMDD` is "MM-DD". */
1917
+ export type AspirationSurveySlot = {sendMMDD: string, label?: string};
1918
+
1919
+ /**
1920
+ * One-time Destinations setup, saved on institutes/{oId}.destinationsConfig by the
1921
+ * setup wizard. destinationsProvisionCron reads it each year to auto-create that
1922
+ * year's aspiration cycles and leaver groups. All MM-DD strings are zero-padded
1923
+ * (e.g. "09-15"). Recipients are NOT frozen here — only the filter rule is stored;
1924
+ * the actual student list is resolved when each form's emails fire.
1925
+ */
1926
+ export type DestinationsConfig = {
1927
+ // ── Aspirations (Form A) ──
1928
+ aspirations: {
1929
+ enabled: boolean,
1930
+ yearGroups: number[], // e.g. [7,8,9,10,11]
1931
+ /** Shared schedule applied to every selected year group (1–3 sends/year). */
1932
+ surveys: AspirationSurveySlot[],
1933
+ /** Optional per-year-group override. When a year group key is present its
1934
+ * schedule REPLACES `surveys` for that year group only. */
1935
+ surveysByYearGroup?: {[yearGroup: string]: AspirationSurveySlot[]},
1936
+ closeAfterDays: number, // default 21
1937
+ /** Extra constraints on top of "active Year-N student". Re-resolved each send. */
1938
+ recipientFilters?: DestinationsRecipientFilter,
1939
+ },
1940
+ // ── Leavers (Form B + checkpoints) ──
1941
+ leavers: {
1942
+ enabled: boolean,
1943
+ yearGroups: number[], // subset of [11, 13]
1944
+ intentionsSendMMDD: string, // Form B, before they leave — default "06-15"
1945
+ resultsDay: {enabled: boolean, sendMMDD: string}, // default "08-29"
1946
+ christmas: {enabled: boolean, sendMMDD: string}, // default "12-08"
1947
+ /** true → every student in these groups leaves (no internal sixth form). */
1948
+ allStudentsLeave?: boolean,
1949
+ recipientFilters?: DestinationsRecipientFilter,
1950
+ },
1951
+ // ── Alumni (mirrors the institute root flags) ──
1952
+ alumni: {
1953
+ acceptingAlumni: boolean,
1954
+ approveAlumni: boolean,
1955
+ alumniConversations: boolean,
1956
+ visibleToStudents: boolean, // default visibility for new alumni records
1957
+ },
1958
+ /** MM-DD on which each new academic year's objects are created. Default "09-01". */
1959
+ provisionMMDD: string,
1960
+ /** e.g. "2026/27" — last academic year the cron provisioned. Guards double-provisioning. */
1961
+ lastProvisionedYear?: string,
1962
+ setupCompletedAt: string, // ISO — stamped server-side on first save
1963
+ setupBy: string, // staff uid — stamped server-side
1964
+ updatedAt?: string,
1898
1965
  }
1899
1966
 
1900
1967
  /**
@@ -2613,8 +2680,9 @@ export type SkillAssessment = {
2613
2680
  externalKey?: string,
2614
2681
  userType: "parents"|"employers"|"students",
2615
2682
  skillRequest?: string,
2683
+ activityId?: string, // links a self-assessment to the extracurricular activity it came from
2616
2684
  email: string,
2617
- forename: string,
2685
+ forename: string,
2618
2686
  surname: string,
2619
2687
  }
2620
2688
 
@@ -2752,6 +2820,9 @@ export type StudentActivity = {
2752
2820
 
2753
2821
  skillsDeveloped?: string[]; // from skills framework
2754
2822
 
2823
+ skillScores?: { [skill: string]: number }; // student self-assessed 1-10 score per developed skill
2824
+ skillsAssessmentId?: string; // linked skillsAssessments doc created from this activity
2825
+
2755
2826
  reflection?: string;
2756
2827
 
2757
2828
  // -------------------------
@@ -3031,6 +3102,12 @@ export type LeaverGroup = {
3031
3102
  * capture (and aren't seeded as alumni). */
3032
3103
  allStudentsLeave?: boolean,
3033
3104
 
3105
+ /** Created by destinationsProvisionCron from the institute's DestinationsConfig
3106
+ * (not via the manual New Leaver Group flow). Auto-provisioned groups defer
3107
+ * recipient fan-out: leaverRequests are built from `students` when invite
3108
+ * emails fire, so the cohort is always resolved against the live roster. */
3109
+ autoProvisioned?: boolean,
3110
+
3034
3111
  /** Post-leaving checkpoint schedule. Absent = checkpoints disabled for this group. */
3035
3112
  checkpointConfig?: {
3036
3113
  resultsDay?: {enabled: boolean, sendAt: string, emailTemplateId?: string}, // ISO datetime