placementt-core 1.400.1187 → 1.400.1188
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/lib/callables/destinationsConfig.d.ts +2 -2
- package/lib/callables/registry.d.ts +4 -4
- package/lib/kcsie.d.ts +4 -2
- package/lib/kcsie.js +14 -6
- package/lib/kcsie.js.map +1 -1
- package/lib/kcsie.test.js +23 -7
- package/lib/kcsie.test.js.map +1 -1
- package/lib/typeDefinitions.d.ts +3 -2
- package/lib/typeDefinitions.js.map +1 -1
- package/package.json +1 -1
- package/src/kcsie.test.ts +26 -8
- package/src/kcsie.ts +15 -6
- package/src/typeDefinitions.ts +4 -2
|
@@ -37,12 +37,12 @@ export declare const destinationsConfigCallables: {
|
|
|
37
37
|
academicYear: z.ZodString;
|
|
38
38
|
}, "strip", z.ZodTypeAny, {
|
|
39
39
|
created: number;
|
|
40
|
-
academicYear: string;
|
|
41
40
|
provisioned: boolean;
|
|
41
|
+
academicYear: string;
|
|
42
42
|
}, {
|
|
43
43
|
created: number;
|
|
44
|
-
academicYear: string;
|
|
45
44
|
provisioned: boolean;
|
|
45
|
+
academicYear: string;
|
|
46
46
|
}>;
|
|
47
47
|
};
|
|
48
48
|
};
|
|
@@ -2645,12 +2645,12 @@ export declare const allCallables: {
|
|
|
2645
2645
|
academicYear: z.ZodString;
|
|
2646
2646
|
}, "strip", z.ZodTypeAny, {
|
|
2647
2647
|
created: number;
|
|
2648
|
-
academicYear: string;
|
|
2649
2648
|
provisioned: boolean;
|
|
2649
|
+
academicYear: string;
|
|
2650
2650
|
}, {
|
|
2651
2651
|
created: number;
|
|
2652
|
-
academicYear: string;
|
|
2653
2652
|
provisioned: boolean;
|
|
2653
|
+
academicYear: string;
|
|
2654
2654
|
}>;
|
|
2655
2655
|
};
|
|
2656
2656
|
};
|
|
@@ -2690,12 +2690,12 @@ export declare const callableGroups: {
|
|
|
2690
2690
|
academicYear: z.ZodString;
|
|
2691
2691
|
}, "strip", z.ZodTypeAny, {
|
|
2692
2692
|
created: number;
|
|
2693
|
-
academicYear: string;
|
|
2694
2693
|
provisioned: boolean;
|
|
2694
|
+
academicYear: string;
|
|
2695
2695
|
}, {
|
|
2696
2696
|
created: number;
|
|
2697
|
-
academicYear: string;
|
|
2698
2697
|
provisioned: boolean;
|
|
2698
|
+
academicYear: string;
|
|
2699
2699
|
}>;
|
|
2700
2700
|
};
|
|
2701
2701
|
};
|
package/lib/kcsie.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { StudentPlacementData, WorkflowStage } from "./typeDefinitions";
|
|
1
|
+
import { PlacementQuestions, StudentPlacementData, WorkflowStage } from "./typeDefinitions";
|
|
2
2
|
type KcsiePerson = NonNullable<StudentPlacementData["kcsiePeople"]>[string];
|
|
3
3
|
export declare const KCSIE_BARRED_LIST_URL = "https://check-the-childrens-barred-list.education.gov.uk/";
|
|
4
4
|
export declare const KCSIE_STATUS_LABELS: Record<NonNullable<StudentPlacementData["kcsie"]>, string>;
|
|
5
5
|
export declare const KCSIE_NOT_REQUESTED: Pick<StudentPlacementData, "kcsie" | "kcsieStatuses">;
|
|
6
6
|
export declare const kcsiePersonId: ({ surname, dob }: Pick<KcsiePerson, "surname" | "dob">) => string;
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const kcsieCheckedOverAYearAgo: (person: Pick<KcsiePerson, "status" | "reviewed">, now?: Date) => boolean;
|
|
8
|
+
export declare const kcsiePeopleDetails: (people?: StudentPlacementData["kcsiePeople"]) => NonNullable<PlacementQuestions["kcsie"]>["people"];
|
|
9
|
+
export declare const matchingKcsiePeople: (previous: NonNullable<PlacementQuestions["kcsie"]>["people"], surname: string) => NonNullable<PlacementQuestions["kcsie"]>["people"];
|
|
8
10
|
export declare const kcsieOutstanding: (status?: StudentPlacementData["kcsie"]) => boolean;
|
|
9
11
|
export declare const workflowRequiresKcsie: (workflow?: WorkflowStage[]) => boolean;
|
|
10
12
|
export declare const placementKcsieFields: (people: NonNullable<StudentPlacementData["kcsiePeople"]>) => Pick<StudentPlacementData, "kcsie" | "kcsieStatuses">;
|
package/lib/kcsie.js
CHANGED
|
@@ -3,9 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getKcsieCohortCounts = exports.reviewKcsiePerson = exports.kcsieRowsForPlacement = exports.placementKcsieFields = exports.workflowRequiresKcsie = exports.kcsieOutstanding = exports.
|
|
6
|
+
exports.getKcsieCohortCounts = exports.reviewKcsiePerson = exports.kcsieRowsForPlacement = exports.placementKcsieFields = exports.workflowRequiresKcsie = exports.kcsieOutstanding = exports.matchingKcsiePeople = exports.kcsiePeopleDetails = exports.kcsieCheckedOverAYearAgo = exports.kcsiePersonId = exports.KCSIE_NOT_REQUESTED = exports.KCSIE_STATUS_LABELS = exports.KCSIE_BARRED_LIST_URL = void 0;
|
|
7
7
|
const firestore_1 = require("firebase/firestore");
|
|
8
|
-
const benchmarkEvidenceRules_1 = require("./benchmarkEvidenceRules");
|
|
9
8
|
const firebaseQuery_1 = __importDefault(require("./firebase/firebaseQuery"));
|
|
10
9
|
const firebaseQuery = new firebaseQuery_1.default();
|
|
11
10
|
exports.KCSIE_BARRED_LIST_URL = "https://check-the-childrens-barred-list.education.gov.uk/";
|
|
@@ -21,9 +20,18 @@ exports.KCSIE_NOT_REQUESTED = { kcsie: "notRequested", kcsieStatuses: ["notReque
|
|
|
21
20
|
// Surname and DOB are what the DfE search uses, so they identify a person across placements.
|
|
22
21
|
const kcsiePersonId = ({ surname, dob }) => `${surname.trim().toLowerCase().replace(/[^a-z]/g, "")}_${dob}`;
|
|
23
22
|
exports.kcsiePersonId = kcsiePersonId;
|
|
24
|
-
// Outcomes
|
|
25
|
-
const
|
|
26
|
-
exports.
|
|
23
|
+
// Outcomes carry over indefinitely; the school is just told when one is over a year old.
|
|
24
|
+
const kcsieCheckedOverAYearAgo = (person, now = new Date()) => person.status !== "pending" && Boolean(person.reviewed) && now.getTime() - new Date(person.reviewed).getTime() > 365 * 24 * 60 * 60 * 1000;
|
|
25
|
+
exports.kcsieCheckedOverAYearAgo = kcsieCheckedOverAYearAgo;
|
|
26
|
+
// Just the details the employer enters, e.g. to import people from another placement.
|
|
27
|
+
const kcsiePeopleDetails = (people) => Object.values(people || {}).map(({ forename, surname, dob, previousSurnames }) => ({ forename, surname, dob, ...(previousSurnames?.length ? { previousSurnames } : {}) }));
|
|
28
|
+
exports.kcsiePeopleDetails = kcsiePeopleDetails;
|
|
29
|
+
// Previous individuals whose surname starts with what's been typed, for the employer to pick from.
|
|
30
|
+
const matchingKcsiePeople = (previous, surname) => {
|
|
31
|
+
const typed = surname.trim().toLowerCase();
|
|
32
|
+
return typed.length < 2 ? [] : previous.filter((p) => p.surname.toLowerCase().startsWith(typed));
|
|
33
|
+
};
|
|
34
|
+
exports.matchingKcsiePeople = matchingKcsiePeople;
|
|
27
35
|
const kcsieOutstanding = (status) => status === "pending" || status === "flagged" || status === "rejected";
|
|
28
36
|
exports.kcsieOutstanding = kcsieOutstanding;
|
|
29
37
|
const workflowRequiresKcsie = (workflow) => Boolean(workflow?.some((s) => s.kcsie && s.userType === "Provider"));
|
|
@@ -47,7 +55,7 @@ exports.kcsieRowsForPlacement = kcsieRowsForPlacement;
|
|
|
47
55
|
// Applies the outcome to every placement at the school with this employer naming the person, and saves it on the employer for future placements.
|
|
48
56
|
const reviewKcsiePerson = async ({ oId, providerContactId, personId, dob, previousSurnames, status, note, reviewedBy, reviewedByName }) => {
|
|
49
57
|
const now = new Date();
|
|
50
|
-
const outcome = { status,
|
|
58
|
+
const outcome = { status, reviewed: now.toISOString(), reviewedBy, reviewedByName, ...(note?.trim() ? { note: note.trim() } : {}) };
|
|
51
59
|
await firebaseQuery.update(["providerContacts", providerContactId], { [`savedBy.${oId}.kcsie.${personId}`]: { ...outcome, ...(previousSurnames?.length ? { previousSurnames } : {}) } });
|
|
52
60
|
const placements = await firebaseQuery.getDocsWhere(["placements"], [
|
|
53
61
|
(0, firestore_1.where)("oId", "==", oId),
|
package/lib/kcsie.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kcsie.js","sourceRoot":"","sources":["../src/kcsie.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAyC;AACzC,
|
|
1
|
+
{"version":3,"file":"kcsie.js","sourceRoot":"","sources":["../src/kcsie.ts"],"names":[],"mappings":"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"}
|
package/lib/kcsie.test.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
jest.mock("firebase/firestore", () => ({ where: jest.fn() }));
|
|
4
4
|
jest.mock("./firebase/firebaseQuery", () => jest.fn());
|
|
5
5
|
const kcsie_1 = require("./kcsie");
|
|
6
|
-
const person = (status, surname = "Smith",
|
|
7
|
-
forename: "Jane", surname, dob: "1980-02-03", status,
|
|
6
|
+
const person = (status, surname = "Smith", extra = {}) => ({
|
|
7
|
+
forename: "Jane", surname, dob: "1980-02-03", status, submitted: "2026-09-01T00:00:00.000Z", ...extra,
|
|
8
8
|
});
|
|
9
9
|
describe("kcsiePersonId", () => {
|
|
10
10
|
it("matches the same surname and DOB however it is typed", () => {
|
|
@@ -12,11 +12,27 @@ describe("kcsiePersonId", () => {
|
|
|
12
12
|
expect((0, kcsie_1.kcsiePersonId)({ surname: "Smith", dob: "1980-02-03" })).not.toBe((0, kcsie_1.kcsiePersonId)({ surname: "Smith", dob: "1981-02-03" }));
|
|
13
13
|
});
|
|
14
14
|
});
|
|
15
|
-
describe("
|
|
16
|
-
const
|
|
17
|
-
it("
|
|
18
|
-
expect((0, kcsie_1.
|
|
19
|
-
expect((0, kcsie_1.
|
|
15
|
+
describe("kcsieCheckedOverAYearAgo", () => {
|
|
16
|
+
const now = new Date("2026-10-08T12:00:00Z");
|
|
17
|
+
it("flags outcomes over a year old without resetting them", () => {
|
|
18
|
+
expect((0, kcsie_1.kcsieCheckedOverAYearAgo)(person("approved", "Smith", { reviewed: "2025-09-01T00:00:00Z" }), now)).toBe(true);
|
|
19
|
+
expect((0, kcsie_1.kcsieCheckedOverAYearAgo)(person("approved", "Smith", { reviewed: "2026-01-01T00:00:00Z" }), now)).toBe(false);
|
|
20
|
+
expect((0, kcsie_1.kcsieCheckedOverAYearAgo)(person("pending", "Smith", { reviewed: "2025-09-01T00:00:00Z" }), now)).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
describe("kcsiePeopleDetails", () => {
|
|
24
|
+
it("imports names and DOBs from another placement, not its outcomes", () => {
|
|
25
|
+
expect((0, kcsie_1.kcsiePeopleDetails)({ smith: person("approved", "Smith", { previousSurnames: ["Jones"], reviewedBy: "uid1" }) }))
|
|
26
|
+
.toEqual([{ forename: "Jane", surname: "Smith", dob: "1980-02-03", previousSurnames: ["Jones"] }]);
|
|
27
|
+
expect((0, kcsie_1.kcsiePeopleDetails)(undefined)).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe("matchingKcsiePeople", () => {
|
|
31
|
+
const previous = [{ forename: "Jane", surname: "Smith", dob: "1980-02-03" }, { forename: "Bob", surname: "Smythe", dob: "1975-05-05" }, { forename: "Al", surname: "Lee", dob: "1990-01-01" }];
|
|
32
|
+
it("suggests previous individuals by surname once two letters are typed", () => {
|
|
33
|
+
expect((0, kcsie_1.matchingKcsiePeople)(previous, "S")).toEqual([]);
|
|
34
|
+
expect((0, kcsie_1.matchingKcsiePeople)(previous, "sm").map((p) => p.forename)).toEqual(["Jane", "Bob"]);
|
|
35
|
+
expect((0, kcsie_1.matchingKcsiePeople)(previous, "Smi").map((p) => p.forename)).toEqual(["Jane"]);
|
|
20
36
|
});
|
|
21
37
|
});
|
|
22
38
|
describe("kcsieOutstanding", () => {
|
package/lib/kcsie.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kcsie.test.js","sourceRoot":"","sources":["../src/kcsie.test.ts"],"names":[],"mappings":";;AAAA,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAC,KAAK,EAAE,IAAI,CAAC,EAAE,EAAE,EAAC,CAAC,CAAC,CAAC;AAC5D,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AAGvD,
|
|
1
|
+
{"version":3,"file":"kcsie.test.js","sourceRoot":"","sources":["../src/kcsie.test.ts"],"names":[],"mappings":"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"}
|
package/lib/typeDefinitions.d.ts
CHANGED
|
@@ -139,7 +139,6 @@ export type StudentPlacementData = {
|
|
|
139
139
|
kcsiePeople?: {
|
|
140
140
|
[personId: string]: NonNullable<PlacementQuestions["kcsie"]>["people"][number] & {
|
|
141
141
|
status: "pending" | "approved" | "flagged" | "rejected";
|
|
142
|
-
academicYear: string;
|
|
143
142
|
submitted: string;
|
|
144
143
|
reviewed?: string;
|
|
145
144
|
reviewedBy?: string;
|
|
@@ -1087,7 +1086,7 @@ export type ProviderContactData = {
|
|
|
1087
1086
|
[key: string]: unknown;
|
|
1088
1087
|
};
|
|
1089
1088
|
kcsie?: {
|
|
1090
|
-
[personId: string]: Pick<NonNullable<StudentPlacementData["kcsiePeople"]>[string], "status" | "
|
|
1089
|
+
[personId: string]: Pick<NonNullable<StudentPlacementData["kcsiePeople"]>[string], "status" | "reviewed" | "reviewedBy" | "reviewedByName" | "note" | "previousSurnames">;
|
|
1091
1090
|
};
|
|
1092
1091
|
status: "uploaded" | "approved" | "rejected" | "providerReviewed" | "blocked";
|
|
1093
1092
|
};
|
|
@@ -1678,6 +1677,7 @@ export type PlacementReviewDetails = {
|
|
|
1678
1677
|
dbsCheckData?: {
|
|
1679
1678
|
[key: string]: unknown;
|
|
1680
1679
|
} | string;
|
|
1680
|
+
kcsiePeople?: NonNullable<PlacementQuestions["kcsie"]>["people"];
|
|
1681
1681
|
};
|
|
1682
1682
|
};
|
|
1683
1683
|
requireELI?: boolean;
|
|
@@ -1685,6 +1685,7 @@ export type PlacementReviewDetails = {
|
|
|
1685
1685
|
requireDBS?: boolean;
|
|
1686
1686
|
requireKCSIE?: boolean;
|
|
1687
1687
|
kcsiePeople?: NonNullable<PlacementQuestions["kcsie"]>["people"];
|
|
1688
|
+
kcsiePrevious?: NonNullable<PlacementQuestions["kcsie"]>["people"];
|
|
1688
1689
|
kcsie?: StudentPlacementData["kcsie"];
|
|
1689
1690
|
importedProviderForms: boolean;
|
|
1690
1691
|
currentStage: WorkflowStage & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typeDefinitions.js","sourceRoot":"","sources":["../src/typeDefinitions.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"typeDefinitions.js","sourceRoot":"","sources":["../src/typeDefinitions.ts"],"names":[],"mappings":";;;AAysIA,sDASC;AAeD,oDAKC;AAaD,0CAEC;AA9pED;;;;;kFAKkF;AACrE,QAAA,qBAAqB,GAAG,SAAS,CAAC;AAClC,QAAA,iBAAiB,GAAG,OAAO,CAAC;AA0kEzC;yEACyE;AAC5D,QAAA,0BAA0B,GAA2C;IAC9E,gBAAgB,EAAE,2BAA2B;IAC7C,mBAAmB,EAAE,sBAAsB;IAC3C,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,qBAAqB;IACzC,UAAU,EAAE,oCAAoC;IAChD,aAAa,EAAE,yBAAyB;IACxC,aAAa,EAAE,wBAAwB;IACvC,KAAK,EAAE,OAAO;CACjB,CAAC;AAEW,QAAA,0BAA0B,GAA+C;IAClF,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,SAAgB,qBAAqB,CAAC,SAAsC;IACxE,QAAQ,SAAS,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC;QAC5B,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,KAAK,WAAW,CAAC;QACjB,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,OAAO,CAAC,CAAC,OAAO,UAAU,CAAC;IAC3B,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,oBAAoB,CAChC,IAAwC,EACxC,MAA6C;IAE7C,OAAO,IAAI,EAAE,WAAW,IAAI,MAAM,EAAE,YAAY,IAAI,KAAK,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,KAA6D;IACzF,OAAO,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE,IAAI,KAAK,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAC/E,CAAC"}
|
package/package.json
CHANGED
package/src/kcsie.test.ts
CHANGED
|
@@ -2,12 +2,12 @@ jest.mock("firebase/firestore", () => ({where: jest.fn()}));
|
|
|
2
2
|
jest.mock("./firebase/firebaseQuery", () => jest.fn());
|
|
3
3
|
|
|
4
4
|
import {StudentPlacementData} from "./typeDefinitions";
|
|
5
|
-
import {
|
|
5
|
+
import {kcsieCheckedOverAYearAgo, kcsieOutstanding, kcsiePeopleDetails, matchingKcsiePeople, kcsiePersonId, kcsieRowsForPlacement, placementKcsieFields, workflowRequiresKcsie} from "./kcsie";
|
|
6
6
|
|
|
7
7
|
type KcsiePerson = NonNullable<StudentPlacementData["kcsiePeople"]>[string];
|
|
8
8
|
|
|
9
|
-
const person = (status: KcsiePerson["status"], surname = "Smith",
|
|
10
|
-
forename: "Jane", surname, dob: "1980-02-03", status,
|
|
9
|
+
const person = (status: KcsiePerson["status"], surname = "Smith", extra: Partial<KcsiePerson> = {}): KcsiePerson => ({
|
|
10
|
+
forename: "Jane", surname, dob: "1980-02-03", status, submitted: "2026-09-01T00:00:00.000Z", ...extra,
|
|
11
11
|
});
|
|
12
12
|
|
|
13
13
|
describe("kcsiePersonId", () => {
|
|
@@ -17,11 +17,29 @@ describe("kcsiePersonId", () => {
|
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
|
|
20
|
-
describe("
|
|
21
|
-
const
|
|
22
|
-
it("
|
|
23
|
-
expect(
|
|
24
|
-
expect(
|
|
20
|
+
describe("kcsieCheckedOverAYearAgo", () => {
|
|
21
|
+
const now = new Date("2026-10-08T12:00:00Z");
|
|
22
|
+
it("flags outcomes over a year old without resetting them", () => {
|
|
23
|
+
expect(kcsieCheckedOverAYearAgo(person("approved", "Smith", {reviewed: "2025-09-01T00:00:00Z"}), now)).toBe(true);
|
|
24
|
+
expect(kcsieCheckedOverAYearAgo(person("approved", "Smith", {reviewed: "2026-01-01T00:00:00Z"}), now)).toBe(false);
|
|
25
|
+
expect(kcsieCheckedOverAYearAgo(person("pending", "Smith", {reviewed: "2025-09-01T00:00:00Z"}), now)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe("kcsiePeopleDetails", () => {
|
|
30
|
+
it("imports names and DOBs from another placement, not its outcomes", () => {
|
|
31
|
+
expect(kcsiePeopleDetails({smith: person("approved", "Smith", {previousSurnames: ["Jones"], reviewedBy: "uid1"})}))
|
|
32
|
+
.toEqual([{forename: "Jane", surname: "Smith", dob: "1980-02-03", previousSurnames: ["Jones"]}]);
|
|
33
|
+
expect(kcsiePeopleDetails(undefined)).toEqual([]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("matchingKcsiePeople", () => {
|
|
38
|
+
const previous = [{forename: "Jane", surname: "Smith", dob: "1980-02-03"}, {forename: "Bob", surname: "Smythe", dob: "1975-05-05"}, {forename: "Al", surname: "Lee", dob: "1990-01-01"}];
|
|
39
|
+
it("suggests previous individuals by surname once two letters are typed", () => {
|
|
40
|
+
expect(matchingKcsiePeople(previous, "S")).toEqual([]);
|
|
41
|
+
expect(matchingKcsiePeople(previous, "sm").map((p) => p.forename)).toEqual(["Jane", "Bob"]);
|
|
42
|
+
expect(matchingKcsiePeople(previous, "Smi").map((p) => p.forename)).toEqual(["Jane"]);
|
|
25
43
|
});
|
|
26
44
|
});
|
|
27
45
|
|
package/src/kcsie.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import {where} from "firebase/firestore";
|
|
2
|
-
import {academicYearForDate} from "./benchmarkEvidenceRules";
|
|
3
2
|
import FirebaseQuery from "./firebase/firebaseQuery";
|
|
4
|
-
import {StudentPlacementData, WorkflowStage} from "./typeDefinitions";
|
|
3
|
+
import {PlacementQuestions, StudentPlacementData, WorkflowStage} from "./typeDefinitions";
|
|
5
4
|
|
|
6
5
|
const firebaseQuery = new FirebaseQuery();
|
|
7
6
|
|
|
@@ -24,9 +23,19 @@ export const KCSIE_NOT_REQUESTED: Pick<StudentPlacementData, "kcsie"|"kcsieStatu
|
|
|
24
23
|
export const kcsiePersonId = ({surname, dob}: Pick<KcsiePerson, "surname"|"dob">): string =>
|
|
25
24
|
`${surname.trim().toLowerCase().replace(/[^a-z]/g, "")}_${dob}`;
|
|
26
25
|
|
|
27
|
-
// Outcomes
|
|
28
|
-
export const
|
|
29
|
-
person.
|
|
26
|
+
// Outcomes carry over indefinitely; the school is just told when one is over a year old.
|
|
27
|
+
export const kcsieCheckedOverAYearAgo = (person: Pick<KcsiePerson, "status"|"reviewed">, now = new Date()): boolean =>
|
|
28
|
+
person.status !== "pending" && Boolean(person.reviewed) && now.getTime() - new Date(person.reviewed as string).getTime() > 365 * 24 * 60 * 60 * 1000;
|
|
29
|
+
|
|
30
|
+
// Just the details the employer enters, e.g. to import people from another placement.
|
|
31
|
+
export const kcsiePeopleDetails = (people?: StudentPlacementData["kcsiePeople"]): NonNullable<PlacementQuestions["kcsie"]>["people"] =>
|
|
32
|
+
Object.values(people || {}).map(({forename, surname, dob, previousSurnames}) => ({forename, surname, dob, ...(previousSurnames?.length ? {previousSurnames} : {})}));
|
|
33
|
+
|
|
34
|
+
// Previous individuals whose surname starts with what's been typed, for the employer to pick from.
|
|
35
|
+
export const matchingKcsiePeople = (previous: NonNullable<PlacementQuestions["kcsie"]>["people"], surname: string): NonNullable<PlacementQuestions["kcsie"]>["people"] => {
|
|
36
|
+
const typed = surname.trim().toLowerCase();
|
|
37
|
+
return typed.length < 2 ? [] : previous.filter((p) => p.surname.toLowerCase().startsWith(typed));
|
|
38
|
+
};
|
|
30
39
|
|
|
31
40
|
export const kcsieOutstanding = (status?: StudentPlacementData["kcsie"]): boolean =>
|
|
32
41
|
status === "pending" || status === "flagged" || status === "rejected";
|
|
@@ -53,7 +62,7 @@ export const kcsieRowsForPlacement = (placementId: string, placement: StudentPla
|
|
|
53
62
|
// Applies the outcome to every placement at the school with this employer naming the person, and saves it on the employer for future placements.
|
|
54
63
|
export const reviewKcsiePerson = async ({oId, providerContactId, personId, dob, previousSurnames, status, note, reviewedBy, reviewedByName}: {oId: string, providerContactId: string, personId: string, dob: string, previousSurnames?: string[], status: KcsiePerson["status"], note?: string, reviewedBy: string, reviewedByName: string}): Promise<void> => {
|
|
55
64
|
const now = new Date();
|
|
56
|
-
const outcome = {status,
|
|
65
|
+
const outcome = {status, reviewed: now.toISOString(), reviewedBy, reviewedByName, ...(note?.trim() ? {note: note.trim()} : {})};
|
|
57
66
|
|
|
58
67
|
await firebaseQuery.update(["providerContacts", providerContactId], {[`savedBy.${oId}.kcsie.${personId}`]: {...outcome, ...(previousSurnames?.length ? {previousSurnames} : {})}});
|
|
59
68
|
|
package/src/typeDefinitions.ts
CHANGED
|
@@ -127,7 +127,6 @@ export type StudentPlacementData = {
|
|
|
127
127
|
// Keyed by kcsiePersonId (surname and DOB).
|
|
128
128
|
kcsiePeople?: {[personId: string]: NonNullable<PlacementQuestions["kcsie"]>["people"][number] & {
|
|
129
129
|
status: "pending"|"approved"|"flagged"|"rejected",
|
|
130
|
-
academicYear: string,
|
|
131
130
|
submitted: string,
|
|
132
131
|
reviewed?: string,
|
|
133
132
|
reviewedBy?: string, // uid
|
|
@@ -1130,7 +1129,7 @@ export type ProviderContactData = {
|
|
|
1130
1129
|
sharing?: EmployerSharing,
|
|
1131
1130
|
additionalData?: {[key: string]: unknown},
|
|
1132
1131
|
// This school's KCSIE outcomes, so new placements pick them up.
|
|
1133
|
-
kcsie?: {[personId: string]: Pick<NonNullable<StudentPlacementData["kcsiePeople"]>[string], "status"|"
|
|
1132
|
+
kcsie?: {[personId: string]: Pick<NonNullable<StudentPlacementData["kcsiePeople"]>[string], "status"|"reviewed"|"reviewedBy"|"reviewedByName"|"note"|"previousSurnames">},
|
|
1134
1133
|
status: "uploaded"|"approved"|"rejected"|"providerReviewed"|"blocked"}},
|
|
1135
1134
|
}&Address
|
|
1136
1135
|
|
|
@@ -1706,6 +1705,7 @@ export type PlacementReviewDetails = {
|
|
|
1706
1705
|
dbsCheck: boolean|"awaitingReview",
|
|
1707
1706
|
dbsCheckType: "form"|"file",
|
|
1708
1707
|
dbsCheckData?: {[key: string]: unknown}|string,
|
|
1708
|
+
kcsiePeople?: NonNullable<PlacementQuestions["kcsie"]>["people"],
|
|
1709
1709
|
}
|
|
1710
1710
|
},
|
|
1711
1711
|
requireELI?: boolean,
|
|
@@ -1713,6 +1713,8 @@ export type PlacementReviewDetails = {
|
|
|
1713
1713
|
requireDBS?: boolean,
|
|
1714
1714
|
requireKCSIE?: boolean,
|
|
1715
1715
|
kcsiePeople?: NonNullable<PlacementQuestions["kcsie"]>["people"],
|
|
1716
|
+
// Everyone the employer has named to this school before, offered as suggestions.
|
|
1717
|
+
kcsiePrevious?: NonNullable<PlacementQuestions["kcsie"]>["people"],
|
|
1716
1718
|
kcsie?: StudentPlacementData["kcsie"],
|
|
1717
1719
|
importedProviderForms: boolean,
|
|
1718
1720
|
currentStage: WorkflowStage&{files: {[fileId: string]: {name: string, url: string}}},
|