placementt-core 1.400.1069 → 1.400.1071
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/pricing.d.ts +0 -174
- package/lib/pricing.js +14 -120
- package/lib/pricing.js.map +1 -1
- package/lib/pricing.test.js +13 -11
- package/lib/pricing.test.js.map +1 -1
- package/package.json +1 -1
- package/src/pricing.test.ts +13 -13
- package/src/pricing.ts +16 -206
package/lib/pricing.d.ts
CHANGED
|
@@ -1,62 +1,24 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The 2026 pricing model.
|
|
3
|
-
*
|
|
4
|
-
* A quote is a base fee plus a per-product fee, and every per-product fee is
|
|
5
|
-
* graduated: the tiers are bands, not lookups, so a school with 1,250 students
|
|
6
|
-
* pays the tier 1 rate on its first 1,000 and the tier 2 rate on the next 250.
|
|
7
|
-
* Anything above the final threshold keeps paying the final tier's rate.
|
|
8
|
-
*
|
|
9
|
-
* Work experience is charged per placement (Y10 and Y12 are quoted separately,
|
|
10
|
-
* and a year group left blank is a year group not taking the product); events
|
|
11
|
-
* and destinations are charged per student. Only events and destinations carry
|
|
12
|
-
* a partial-product discount — that is how the pricing sheet has it, and it is
|
|
13
|
-
* why `partialProductDiscount` names those two rather than being one number.
|
|
14
|
-
*
|
|
15
|
-
* A trust is quoted as one account on its combined roll, and earns a discount
|
|
16
|
-
* on the whole quote for the number of schools it brings on — a smaller one
|
|
17
|
-
* below the threshold, a larger one at or above it.
|
|
18
|
-
*
|
|
19
|
-
* Every figure lives in `PricingConfig` so it can be stored in Firestore and
|
|
20
|
-
* adjusted without a deploy. `DEFAULT_PRICING_CONFIG` is the fallback and the
|
|
21
|
-
* seed for that document.
|
|
22
|
-
*/
|
|
23
|
-
/** One band of the graduated fee, with the rate each product charges in it. */
|
|
24
1
|
export type PricingTier = {
|
|
25
|
-
/** Upper bound of the band, in students (events and destinations). */
|
|
26
2
|
students: number;
|
|
27
|
-
/** Upper bound of the band, in placements (work experience). */
|
|
28
3
|
placements: number;
|
|
29
|
-
/** £ per placement. */
|
|
30
4
|
wex: number;
|
|
31
|
-
/** £ per student. */
|
|
32
5
|
events: number;
|
|
33
|
-
/** £ per student. */
|
|
34
6
|
destinations: number;
|
|
35
7
|
};
|
|
36
8
|
export type PricingConfig = {
|
|
37
|
-
/** No school is quoted below this, however little the products come to. */
|
|
38
9
|
minFee: number;
|
|
39
|
-
/** Charged on every quote. Not itemised to the customer. */
|
|
40
10
|
baseFee: number;
|
|
41
|
-
/** In ascending order of threshold. The last band's rate runs to infinity. */
|
|
42
11
|
tiers: PricingTier[];
|
|
43
|
-
/** Taken off a single product's fee, as a fraction (0.2 = 20% off). */
|
|
44
12
|
partialProductDiscount: {
|
|
45
13
|
events: number;
|
|
46
14
|
destinations: number;
|
|
47
15
|
};
|
|
48
|
-
/** Taken off the whole quote when a school takes the full platform. */
|
|
49
16
|
fullPlatformDiscount: number;
|
|
50
|
-
/** Taken off the whole quote for a trust, on how many schools it brings. */
|
|
51
17
|
trust: {
|
|
52
|
-
/** Schools at which the larger discount takes over. */
|
|
53
18
|
threshold: number;
|
|
54
|
-
/** Fraction off a trust below the threshold. */
|
|
55
19
|
discount: number;
|
|
56
|
-
/** Fraction off a trust at or above it. */
|
|
57
20
|
largeDiscount: number;
|
|
58
21
|
};
|
|
59
|
-
/** Careers hubs are a flat platform fee plus a fee for each school. */
|
|
60
22
|
hub: {
|
|
61
23
|
baseFee: number;
|
|
62
24
|
perSchoolFee: number;
|
|
@@ -64,181 +26,93 @@ export type PricingConfig = {
|
|
|
64
26
|
};
|
|
65
27
|
/** The pricing sheet's figures, as agreed for 2026. */
|
|
66
28
|
export declare const DEFAULT_PRICING_CONFIG: PricingConfig;
|
|
67
|
-
/** Where the adjustable copy of the config lives. */
|
|
68
29
|
export declare const PRICING_CONFIG_PATH: string[];
|
|
69
30
|
export type SchoolPricingInput = {
|
|
70
|
-
/** Roll size. Drives the events and destinations fees. */
|
|
71
31
|
students?: number;
|
|
72
|
-
/** Y10 placements. Undefined means the year group isn't taking work experience. */
|
|
73
32
|
wexY10?: number;
|
|
74
|
-
/** Y12 placements. Undefined means the year group isn't taking work experience. */
|
|
75
33
|
wexY12?: number;
|
|
76
34
|
events?: boolean;
|
|
77
|
-
/** Discount the events fee on its own. */
|
|
78
35
|
eventsDiscount?: boolean;
|
|
79
36
|
destinations?: boolean;
|
|
80
|
-
/** Discount the destinations fee on its own. */
|
|
81
37
|
destinationsDiscount?: boolean;
|
|
82
|
-
/** Discount the whole quote, for a school taking the full platform. */
|
|
83
38
|
fullPlatformDiscount?: boolean;
|
|
84
|
-
/** Schools in the trust being quoted. Two or more earns a trust discount. */
|
|
85
39
|
schools?: number;
|
|
86
|
-
/** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off).
|
|
87
|
-
* Taken after the full-platform discount and before the minimum fee. */
|
|
88
40
|
bespokeDiscount?: number;
|
|
89
|
-
/** A price agreed with the customer, which replaces everything above it —
|
|
90
|
-
* the discounts, the minimum fee and the total the products came to. */
|
|
91
41
|
quoteOverride?: number;
|
|
92
42
|
};
|
|
93
43
|
export type PricingLineKey = "base" | "wexY10" | "wexY12" | "events" | "destinations" | "hubBase" | "hubSchools";
|
|
94
44
|
export type PricingLine = {
|
|
95
45
|
key: PricingLineKey;
|
|
96
46
|
label: string;
|
|
97
|
-
/** What the product costs after any partial-product discount. */
|
|
98
47
|
amount: number;
|
|
99
|
-
/** The fee before its partial-product discount, when one was applied. */
|
|
100
48
|
undiscounted?: number;
|
|
101
|
-
/** How the amount was reached, band by band. Empty for the base fee. */
|
|
102
49
|
bands: PricingBand[];
|
|
103
50
|
};
|
|
104
|
-
/** One band's contribution to a product's fee, for showing the working. */
|
|
105
51
|
export type PricingBand = {
|
|
106
|
-
/** 1-indexed, matching the tier's position in the config. */
|
|
107
52
|
tier: number;
|
|
108
|
-
/** Units charged in this band. */
|
|
109
53
|
quantity: number;
|
|
110
54
|
rate: number;
|
|
111
55
|
amount: number;
|
|
112
56
|
};
|
|
113
57
|
export type SchoolPricingResult = {
|
|
114
58
|
lines: PricingLine[];
|
|
115
|
-
/** The lines added up, before the full-platform discount. */
|
|
116
59
|
subtotal: number;
|
|
117
|
-
/** £ taken off the subtotal by the full-platform discount. */
|
|
118
60
|
fullPlatformDiscountApplied: number;
|
|
119
|
-
/** £ taken off by the trust discount, after the full-platform one. */
|
|
120
61
|
trustDiscountApplied: number;
|
|
121
|
-
/** The rate that trust discount was taken at, as a fraction. */
|
|
122
62
|
trustDiscountRate: number;
|
|
123
|
-
/** £ taken off by the negotiated discount, after the trust one. */
|
|
124
63
|
bespokeDiscountApplied: number;
|
|
125
|
-
/** True when the minimum fee, not the products, set the price. */
|
|
126
64
|
minFeeApplied: boolean;
|
|
127
|
-
/** True when an agreed price replaced the calculated one. */
|
|
128
65
|
overrideApplied: boolean;
|
|
129
66
|
total: number;
|
|
130
67
|
};
|
|
131
68
|
export type HubPricingResult = {
|
|
132
69
|
baseFee: number;
|
|
133
|
-
/** The per-school fee multiplied by the number of schools. */
|
|
134
70
|
schoolFees: number;
|
|
135
71
|
total: number;
|
|
136
72
|
};
|
|
137
|
-
/**
|
|
138
|
-
* What a trust comes off its quote for its size.
|
|
139
|
-
*
|
|
140
|
-
* A trust is more than one school, so a count below two is a single school and
|
|
141
|
-
* earns nothing — the discount is for bringing schools with you.
|
|
142
|
-
*
|
|
143
|
-
* @param {number} [schools] schools in the trust.
|
|
144
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
145
|
-
* @return {number} the discount, as a fraction of the quote.
|
|
146
|
-
*/
|
|
147
73
|
export declare function trustDiscountRate(schools?: number, config?: PricingConfig): number;
|
|
148
|
-
/**
|
|
149
|
-
* Price a school, trust or hub-school quote.
|
|
150
|
-
*
|
|
151
|
-
* Products the school isn't taking are left out of `lines` entirely, so the
|
|
152
|
-
* breakdown only ever shows what is being charged for.
|
|
153
|
-
*
|
|
154
|
-
* @param {object} input the roll, the year groups and the products taken.
|
|
155
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
156
|
-
* @return {object} the total, and the working that reached it.
|
|
157
|
-
*/
|
|
158
74
|
export declare function calculateSchoolPrice(input: SchoolPricingInput, config?: PricingConfig): SchoolPricingResult;
|
|
159
|
-
/**
|
|
160
|
-
* Price a careers hub: the platform fee, plus a fee for every school on it.
|
|
161
|
-
*
|
|
162
|
-
* @param {number} schools how many schools the hub brings on.
|
|
163
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
164
|
-
* @return {object} the platform fee, the school fees and the total.
|
|
165
|
-
*/
|
|
166
75
|
export declare function calculateHubPrice(schools: number, config?: PricingConfig): HubPricingResult;
|
|
167
|
-
/**
|
|
168
|
-
* Fill a stored config out with the defaults.
|
|
169
|
-
*
|
|
170
|
-
* The Firestore document is hand-edited, so treat every branch of it as
|
|
171
|
-
* possibly absent — a config saved before a tier was added should still price,
|
|
172
|
-
* rather than throwing on a missing rate.
|
|
173
|
-
*
|
|
174
|
-
* @param {object} [stored] whatever the Firestore document holds.
|
|
175
|
-
* @return {object} a complete config, safe to price with.
|
|
176
|
-
*/
|
|
177
76
|
export declare function mergePricingConfig(stored?: Partial<PricingConfig>): PricingConfig;
|
|
178
|
-
/** The terms agreed with one customer. Stored at `institutes/{oId}.pricing`. */
|
|
179
77
|
export type InstitutePricing = {
|
|
180
|
-
/** The roll we quoted on. Defaults to the institute's own student count. */
|
|
181
78
|
students?: number;
|
|
182
|
-
/** Y10 placements quoted. Undefined means the year group isn't on work experience. */
|
|
183
79
|
wexY10?: number;
|
|
184
|
-
/** Y12 placements quoted. Undefined means the year group isn't on work experience. */
|
|
185
80
|
wexY12?: number;
|
|
186
|
-
/** Take the partial-product discount off the events fee. */
|
|
187
81
|
eventsDiscount?: boolean;
|
|
188
|
-
/** Take the partial-product discount off the destinations fee. */
|
|
189
82
|
destinationsDiscount?: boolean;
|
|
190
|
-
/** Take the full-platform discount off the whole quote. */
|
|
191
83
|
fullPlatformDiscount?: boolean;
|
|
192
|
-
/** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off). */
|
|
193
84
|
bespokeDiscount?: number;
|
|
194
|
-
/** Why the negotiated discount or the agreed price was given. Admin-only. */
|
|
195
85
|
discountReason?: string;
|
|
196
|
-
/** A price agreed with the customer, which replaces the calculated one. */
|
|
197
86
|
quoteOverride?: number;
|
|
198
|
-
/** Schools in the trust, which set its discount. Trust accounts only. */
|
|
199
87
|
schools?: number;
|
|
200
|
-
/** Schools on the hub. Hub accounts only. */
|
|
201
88
|
hubSchools?: number;
|
|
202
|
-
/** The quote as last saved, for the customer to see. */
|
|
203
89
|
quote?: InstituteQuoteSnapshot;
|
|
204
90
|
};
|
|
205
|
-
/** A priced institute: the same shape for a school, a trust and a hub. */
|
|
206
91
|
export type InstituteQuote = {
|
|
207
92
|
kind: "school" | "hub";
|
|
208
|
-
/** Every fee charged, with the working behind it. */
|
|
209
93
|
lines: PricingLine[];
|
|
210
|
-
/** The lines added up, before any whole-quote discount. */
|
|
211
94
|
subtotal: number;
|
|
212
95
|
fullPlatformDiscountApplied: number;
|
|
213
96
|
trustDiscountApplied: number;
|
|
214
|
-
/** The rate the trust discount was taken at, as a fraction. */
|
|
215
97
|
trustDiscountRate: number;
|
|
216
98
|
bespokeDiscountApplied: number;
|
|
217
99
|
minFeeApplied: boolean;
|
|
218
100
|
overrideApplied: boolean;
|
|
219
101
|
total: number;
|
|
220
102
|
};
|
|
221
|
-
/** What the customer is shown: the total, and what makes it up. No rates. */
|
|
222
103
|
export type InstituteQuoteSnapshot = {
|
|
223
104
|
lines: {
|
|
224
105
|
key: PricingLineKey;
|
|
225
106
|
label: string;
|
|
226
107
|
amount: number;
|
|
227
108
|
}[];
|
|
228
|
-
/** The lines added up. */
|
|
229
109
|
subtotal: number;
|
|
230
|
-
/** Everything taken off the lines to reach the total, as one figure. */
|
|
231
110
|
discountTotal: number;
|
|
232
|
-
/** True when the total is a floor or an agreed price above what the lines
|
|
233
|
-
* come to, so the breakdown is shown as an illustration, not a sum. */
|
|
234
111
|
minimum: boolean;
|
|
235
112
|
total: number;
|
|
236
|
-
/** ISO date the quote was last worked out. */
|
|
237
113
|
updated: string;
|
|
238
114
|
};
|
|
239
|
-
/** What the quote needs to know about the institute being priced. */
|
|
240
115
|
export type InstituteQuoteInput = {
|
|
241
|
-
/** What the institute has, as resolved by `resolveProducts`. */
|
|
242
116
|
products: {
|
|
243
117
|
wex?: boolean;
|
|
244
118
|
events?: boolean;
|
|
@@ -246,60 +120,12 @@ export type InstituteQuoteInput = {
|
|
|
246
120
|
isHub?: boolean;
|
|
247
121
|
isTrust?: boolean;
|
|
248
122
|
};
|
|
249
|
-
/** The institute's roll, when the agreed terms don't name one. */
|
|
250
123
|
students?: number;
|
|
251
|
-
/** Schools in the trust, when the agreed terms don't name a number. */
|
|
252
124
|
schools?: number;
|
|
253
|
-
/** Schools on the hub, when the agreed terms don't name a number. */
|
|
254
125
|
hubSchools?: number;
|
|
255
|
-
/** The terms agreed with this customer. */
|
|
256
126
|
pricing?: InstitutePricing;
|
|
257
127
|
};
|
|
258
|
-
/**
|
|
259
|
-
* Price a school and present it as an institute quote.
|
|
260
|
-
*
|
|
261
|
-
* @param {object} input the roll, the year groups, the products and the terms.
|
|
262
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
263
|
-
* @return {object} the quote, ready to render.
|
|
264
|
-
*/
|
|
265
128
|
export declare function schoolQuote(input: SchoolPricingInput, config?: PricingConfig): InstituteQuote;
|
|
266
|
-
/**
|
|
267
|
-
* Price a careers hub as an institute quote: the platform fee, then the schools.
|
|
268
|
-
*
|
|
269
|
-
* Hubs have no products to discount individually and no minimum fee to fall back
|
|
270
|
-
* on, so the only terms that reach them are the negotiated discount and an
|
|
271
|
-
* agreed price.
|
|
272
|
-
*
|
|
273
|
-
* @param {number} schools how many schools the hub brings on.
|
|
274
|
-
* @param {object} [pricing] the terms agreed with this hub.
|
|
275
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
276
|
-
* @return {object} the quote, ready to render.
|
|
277
|
-
*/
|
|
278
129
|
export declare function hubQuote(schools: number, pricing?: InstitutePricing, config?: PricingConfig): InstituteQuote;
|
|
279
|
-
/**
|
|
280
|
-
* Price an institute on what it actually has and what was agreed with it.
|
|
281
|
-
*
|
|
282
|
-
* The products come from `resolveProducts` rather than the raw flags, so a trust
|
|
283
|
-
* is priced on the union of its schools' products the same way it is gated on
|
|
284
|
-
* them, and it is a trust — not any school with a number against it — that earns
|
|
285
|
-
* the trust discount. A year group with no placements agreed is a year group not on work
|
|
286
|
-
* experience — except where the institute has work experience and neither year
|
|
287
|
-
* group has been filled in, which is a quote waiting to be finished rather than
|
|
288
|
-
* a school not taking the product, so Y10 is charged at zero to say so.
|
|
289
|
-
*
|
|
290
|
-
* @param {object} input the institute's products, roll and agreed terms.
|
|
291
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
292
|
-
* @return {object} the quote, ready to render.
|
|
293
|
-
*/
|
|
294
130
|
export declare function instituteQuote(input: InstituteQuoteInput, config?: PricingConfig): InstituteQuote;
|
|
295
|
-
/**
|
|
296
|
-
* Reduce a quote to what the customer sees: the fees, and one discount figure.
|
|
297
|
-
*
|
|
298
|
-
* The base fee isn't itemised to customers, so it is folded into the first fee
|
|
299
|
-
* they are shown — and where there is nothing to fold it into, it stands alone
|
|
300
|
-
* as the platform fee it is.
|
|
301
|
-
*
|
|
302
|
-
* @param {object} quote the priced institute.
|
|
303
|
-
* @return {object} the snapshot to store on the institute.
|
|
304
|
-
*/
|
|
305
131
|
export declare function quoteSnapshot(quote: InstituteQuote): InstituteQuoteSnapshot;
|
package/lib/pricing.js
CHANGED
|
@@ -1,26 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* The 2026 pricing model.
|
|
4
|
-
*
|
|
5
|
-
* A quote is a base fee plus a per-product fee, and every per-product fee is
|
|
6
|
-
* graduated: the tiers are bands, not lookups, so a school with 1,250 students
|
|
7
|
-
* pays the tier 1 rate on its first 1,000 and the tier 2 rate on the next 250.
|
|
8
|
-
* Anything above the final threshold keeps paying the final tier's rate.
|
|
9
|
-
*
|
|
10
|
-
* Work experience is charged per placement (Y10 and Y12 are quoted separately,
|
|
11
|
-
* and a year group left blank is a year group not taking the product); events
|
|
12
|
-
* and destinations are charged per student. Only events and destinations carry
|
|
13
|
-
* a partial-product discount — that is how the pricing sheet has it, and it is
|
|
14
|
-
* why `partialProductDiscount` names those two rather than being one number.
|
|
15
|
-
*
|
|
16
|
-
* A trust is quoted as one account on its combined roll, and earns a discount
|
|
17
|
-
* on the whole quote for the number of schools it brings on — a smaller one
|
|
18
|
-
* below the threshold, a larger one at or above it.
|
|
19
|
-
*
|
|
20
|
-
* Every figure lives in `PricingConfig` so it can be stored in Firestore and
|
|
21
|
-
* adjusted without a deploy. `DEFAULT_PRICING_CONFIG` is the fallback and the
|
|
22
|
-
* seed for that document.
|
|
23
|
-
*/
|
|
24
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
3
|
exports.PRICING_CONFIG_PATH = exports.DEFAULT_PRICING_CONFIG = void 0;
|
|
26
4
|
exports.trustDiscountRate = trustDiscountRate;
|
|
@@ -41,20 +19,11 @@ exports.DEFAULT_PRICING_CONFIG = {
|
|
|
41
19
|
{ students: 2000, placements: 200, wex: 1.5, events: 0.25, destinations: 0.25 },
|
|
42
20
|
],
|
|
43
21
|
partialProductDiscount: { events: 0.2, destinations: 0.2 },
|
|
44
|
-
fullPlatformDiscount: 0.
|
|
22
|
+
fullPlatformDiscount: 0.1,
|
|
45
23
|
trust: { threshold: 10, discount: 0.05, largeDiscount: 0.1 },
|
|
46
24
|
hub: { baseFee: 2000, perSchoolFee: 150 },
|
|
47
25
|
};
|
|
48
|
-
/** Where the adjustable copy of the config lives. */
|
|
49
26
|
exports.PRICING_CONFIG_PATH = ["adminConfig", "pricing"];
|
|
50
|
-
/**
|
|
51
|
-
* Charge `quantity` across the bands, each band at its own rate, with anything
|
|
52
|
-
* above the final threshold staying on the final band's rate.
|
|
53
|
-
*
|
|
54
|
-
* @param {number} quantity students or placements, depending on the product.
|
|
55
|
-
* @param {Array} bands each band's upper threshold and its rate.
|
|
56
|
-
* @return {Array} one entry per band that charged something.
|
|
57
|
-
*/
|
|
58
27
|
function graduated(quantity, bands) {
|
|
59
28
|
if (!(quantity > 0) || !bands.length)
|
|
60
29
|
return [];
|
|
@@ -66,8 +35,6 @@ function graduated(quantity, bands) {
|
|
|
66
35
|
if (inBand > 0)
|
|
67
36
|
lines.push({ tier: index + 1, quantity: inBand, rate: band.rate, amount: inBand * band.rate });
|
|
68
37
|
});
|
|
69
|
-
// Everything past the last threshold keeps paying the last rate, so it belongs
|
|
70
|
-
// in the last band rather than as a second row at the same rate.
|
|
71
38
|
const last = bands[bands.length - 1];
|
|
72
39
|
const overflow = Math.max(quantity - last.limit, 0);
|
|
73
40
|
if (overflow > 0) {
|
|
@@ -85,33 +52,14 @@ function graduated(quantity, bands) {
|
|
|
85
52
|
const sum = (values) => values.reduce((total, value) => total + value, 0);
|
|
86
53
|
const clampFraction = (value) => Math.min(Math.max(value || 0, 0), 1);
|
|
87
54
|
const bandsTotal = (bands) => sum(bands.map((b) => b.amount));
|
|
88
|
-
/**
|
|
89
|
-
* What a trust comes off its quote for its size.
|
|
90
|
-
*
|
|
91
|
-
* A trust is more than one school, so a count below two is a single school and
|
|
92
|
-
* earns nothing — the discount is for bringing schools with you.
|
|
93
|
-
*
|
|
94
|
-
* @param {number} [schools] schools in the trust.
|
|
95
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
96
|
-
* @return {number} the discount, as a fraction of the quote.
|
|
97
|
-
*/
|
|
98
55
|
function trustDiscountRate(schools, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
99
56
|
const count = schools || 0;
|
|
100
57
|
if (count < 2)
|
|
101
58
|
return 0;
|
|
102
59
|
return count >= config.trust.threshold ? config.trust.largeDiscount : config.trust.discount;
|
|
103
60
|
}
|
|
104
|
-
/**
|
|
105
|
-
* Price a school, trust or hub-school quote.
|
|
106
|
-
*
|
|
107
|
-
* Products the school isn't taking are left out of `lines` entirely, so the
|
|
108
|
-
* breakdown only ever shows what is being charged for.
|
|
109
|
-
*
|
|
110
|
-
* @param {object} input the roll, the year groups and the products taken.
|
|
111
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
112
|
-
* @return {object} the total, and the working that reached it.
|
|
113
|
-
*/
|
|
114
61
|
function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
62
|
+
const schoolCount = Math.max(input.schools || 0, 0);
|
|
115
63
|
const students = input.students || 0;
|
|
116
64
|
const tiers = config.tiers;
|
|
117
65
|
const perPlacement = tiers.map((t) => ({ limit: t.placements, rate: t.wex }));
|
|
@@ -135,7 +83,17 @@ function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
|
135
83
|
};
|
|
136
84
|
addPerStudent("events", "Employer events", input.events, input.eventsDiscount);
|
|
137
85
|
addPerStudent("destinations", "Destinations", input.destinations, input.destinationsDiscount);
|
|
138
|
-
const
|
|
86
|
+
const scaledLines = schoolCount > 1 ? lines.map((line) => ({
|
|
87
|
+
...line,
|
|
88
|
+
amount: line.amount * schoolCount,
|
|
89
|
+
...(line.undiscounted !== undefined ? { undiscounted: line.undiscounted * schoolCount } : {}),
|
|
90
|
+
bands: line.bands.map((band) => ({
|
|
91
|
+
...band,
|
|
92
|
+
quantity: band.quantity * schoolCount,
|
|
93
|
+
amount: band.amount * schoolCount,
|
|
94
|
+
})),
|
|
95
|
+
})) : lines;
|
|
96
|
+
const subtotal = sum(scaledLines.map((l) => l.amount));
|
|
139
97
|
const discounted = input.fullPlatformDiscount ? subtotal * (1 - config.fullPlatformDiscount) : subtotal;
|
|
140
98
|
const trustRate = trustDiscountRate(input.schools, config);
|
|
141
99
|
const trusted = discounted * (1 - trustRate);
|
|
@@ -143,7 +101,7 @@ function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
|
143
101
|
const floored = Math.max(negotiated, config.minFee);
|
|
144
102
|
const overridden = input.quoteOverride !== undefined && input.quoteOverride >= 0;
|
|
145
103
|
return {
|
|
146
|
-
lines,
|
|
104
|
+
lines: scaledLines,
|
|
147
105
|
subtotal,
|
|
148
106
|
fullPlatformDiscountApplied: subtotal - discounted,
|
|
149
107
|
trustDiscountApplied: discounted - trusted,
|
|
@@ -156,27 +114,10 @@ function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
|
156
114
|
total: overridden ? input.quoteOverride : floored,
|
|
157
115
|
};
|
|
158
116
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Price a careers hub: the platform fee, plus a fee for every school on it.
|
|
161
|
-
*
|
|
162
|
-
* @param {number} schools how many schools the hub brings on.
|
|
163
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
164
|
-
* @return {object} the platform fee, the school fees and the total.
|
|
165
|
-
*/
|
|
166
117
|
function calculateHubPrice(schools, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
167
118
|
const schoolFees = Math.max(schools || 0, 0) * config.hub.perSchoolFee;
|
|
168
119
|
return { baseFee: config.hub.baseFee, schoolFees, total: config.hub.baseFee + schoolFees };
|
|
169
120
|
}
|
|
170
|
-
/**
|
|
171
|
-
* Fill a stored config out with the defaults.
|
|
172
|
-
*
|
|
173
|
-
* The Firestore document is hand-edited, so treat every branch of it as
|
|
174
|
-
* possibly absent — a config saved before a tier was added should still price,
|
|
175
|
-
* rather than throwing on a missing rate.
|
|
176
|
-
*
|
|
177
|
-
* @param {object} [stored] whatever the Firestore document holds.
|
|
178
|
-
* @return {object} a complete config, safe to price with.
|
|
179
|
-
*/
|
|
180
121
|
function mergePricingConfig(stored) {
|
|
181
122
|
const d = exports.DEFAULT_PRICING_CONFIG;
|
|
182
123
|
if (!stored)
|
|
@@ -191,28 +132,9 @@ function mergePricingConfig(stored) {
|
|
|
191
132
|
hub: { ...d.hub, ...stored.hub },
|
|
192
133
|
};
|
|
193
134
|
}
|
|
194
|
-
/**
|
|
195
|
-
* Price a school and present it as an institute quote.
|
|
196
|
-
*
|
|
197
|
-
* @param {object} input the roll, the year groups, the products and the terms.
|
|
198
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
199
|
-
* @return {object} the quote, ready to render.
|
|
200
|
-
*/
|
|
201
135
|
function schoolQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
202
136
|
return { kind: "school", ...calculateSchoolPrice(input, config) };
|
|
203
137
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Price a careers hub as an institute quote: the platform fee, then the schools.
|
|
206
|
-
*
|
|
207
|
-
* Hubs have no products to discount individually and no minimum fee to fall back
|
|
208
|
-
* on, so the only terms that reach them are the negotiated discount and an
|
|
209
|
-
* agreed price.
|
|
210
|
-
*
|
|
211
|
-
* @param {number} schools how many schools the hub brings on.
|
|
212
|
-
* @param {object} [pricing] the terms agreed with this hub.
|
|
213
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
214
|
-
* @return {object} the quote, ready to render.
|
|
215
|
-
*/
|
|
216
138
|
function hubQuote(schools, pricing, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
217
139
|
const count = Math.max(schools || 0, 0);
|
|
218
140
|
const hub = calculateHubPrice(count, config);
|
|
@@ -243,21 +165,6 @@ function hubQuote(schools, pricing, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
|
243
165
|
total: overridden ? pricing?.quoteOverride : negotiated,
|
|
244
166
|
};
|
|
245
167
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Price an institute on what it actually has and what was agreed with it.
|
|
248
|
-
*
|
|
249
|
-
* The products come from `resolveProducts` rather than the raw flags, so a trust
|
|
250
|
-
* is priced on the union of its schools' products the same way it is gated on
|
|
251
|
-
* them, and it is a trust — not any school with a number against it — that earns
|
|
252
|
-
* the trust discount. A year group with no placements agreed is a year group not on work
|
|
253
|
-
* experience — except where the institute has work experience and neither year
|
|
254
|
-
* group has been filled in, which is a quote waiting to be finished rather than
|
|
255
|
-
* a school not taking the product, so Y10 is charged at zero to say so.
|
|
256
|
-
*
|
|
257
|
-
* @param {object} input the institute's products, roll and agreed terms.
|
|
258
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
259
|
-
* @return {object} the quote, ready to render.
|
|
260
|
-
*/
|
|
261
168
|
function instituteQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
262
169
|
const pricing = input.pricing;
|
|
263
170
|
if (input.products.isHub) {
|
|
@@ -281,16 +188,6 @@ function instituteQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
|
|
|
281
188
|
quoteOverride: pricing?.quoteOverride,
|
|
282
189
|
}, config);
|
|
283
190
|
}
|
|
284
|
-
/**
|
|
285
|
-
* Reduce a quote to what the customer sees: the fees, and one discount figure.
|
|
286
|
-
*
|
|
287
|
-
* The base fee isn't itemised to customers, so it is folded into the first fee
|
|
288
|
-
* they are shown — and where there is nothing to fold it into, it stands alone
|
|
289
|
-
* as the platform fee it is.
|
|
290
|
-
*
|
|
291
|
-
* @param {object} quote the priced institute.
|
|
292
|
-
* @return {object} the snapshot to store on the institute.
|
|
293
|
-
*/
|
|
294
191
|
function quoteSnapshot(quote) {
|
|
295
192
|
const itemised = quote.lines.filter((l) => l.key !== "base");
|
|
296
193
|
const base = quote.lines.find((l) => l.key === "base")?.amount || 0;
|
|
@@ -305,9 +202,6 @@ function quoteSnapshot(quote) {
|
|
|
305
202
|
return {
|
|
306
203
|
lines,
|
|
307
204
|
subtotal,
|
|
308
|
-
// The customer is shown the fees and one discount, so whatever separates
|
|
309
|
-
// the two — the whole-quote discounts, an agreed price below them — is
|
|
310
|
-
// that one figure, and a total above the fees is flagged instead.
|
|
311
205
|
discountTotal: Math.max(subtotal - quote.total, 0),
|
|
312
206
|
minimum: quote.total > subtotal,
|
|
313
207
|
total: quote.total,
|
package/lib/pricing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"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"}
|
package/lib/pricing.test.js
CHANGED
|
@@ -117,17 +117,18 @@ describe("mergePricingConfig", () => {
|
|
|
117
117
|
});
|
|
118
118
|
});
|
|
119
119
|
describe("the trust discount", () => {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
const
|
|
120
|
+
it("prices a trust as one school price multiplied by the trust size before the discount", () => {
|
|
121
|
+
const base = { students: 500, events: true, destinations: true };
|
|
122
|
+
const single = (0, pricing_1.calculateSchoolPrice)(base);
|
|
123
|
+
const result = (0, pricing_1.calculateSchoolPrice)({ ...base, schools: 9 });
|
|
124
124
|
expect(result.trustDiscountRate).toBe(0.05);
|
|
125
|
-
expect(result.total).toBeCloseTo(
|
|
126
|
-
expect(result.trustDiscountApplied).toBeCloseTo(
|
|
125
|
+
expect(result.total).toBeCloseTo(single.total * 9 * 0.95, 6);
|
|
126
|
+
expect(result.trustDiscountApplied).toBeCloseTo(single.total * 9 * 0.05, 6);
|
|
127
127
|
});
|
|
128
128
|
it("gives a trust of ten schools or more 10%", () => {
|
|
129
|
-
|
|
130
|
-
expect((0, pricing_1.calculateSchoolPrice)(
|
|
129
|
+
const base = { students: 500, events: true, destinations: true };
|
|
130
|
+
expect((0, pricing_1.calculateSchoolPrice)({ ...base, schools: 10 }).trustDiscountRate).toBe(0.1);
|
|
131
|
+
expect((0, pricing_1.calculateSchoolPrice)({ ...base, schools: 40 }).trustDiscountRate).toBe(0.1);
|
|
131
132
|
});
|
|
132
133
|
it("gives a single school nothing, however it is counted", () => {
|
|
133
134
|
expect((0, pricing_1.trustDiscountRate)(undefined)).toBe(0);
|
|
@@ -136,13 +137,14 @@ describe("the trust discount", () => {
|
|
|
136
137
|
});
|
|
137
138
|
it("is taken after the full-platform discount and before the negotiated one", () => {
|
|
138
139
|
const input = {
|
|
139
|
-
students:
|
|
140
|
+
students: 500, events: true, destinations: true,
|
|
140
141
|
fullPlatformDiscount: true, schools: 12, bespokeDiscount: 0.1,
|
|
141
142
|
};
|
|
142
143
|
const result = (0, pricing_1.calculateSchoolPrice)(input);
|
|
143
|
-
const
|
|
144
|
+
const single = (0, pricing_1.calculateSchoolPrice)({ students: 500, events: true, destinations: true });
|
|
145
|
+
const expected = single.subtotal * 12 * 0.8 * 0.9 * 0.9;
|
|
144
146
|
expect(result.total).toBeCloseTo(expected, 6);
|
|
145
|
-
expect(result.trustDiscountApplied).toBeCloseTo(
|
|
147
|
+
expect(result.trustDiscountApplied).toBeCloseTo(single.subtotal * 12 * 0.8 * 0.1, 6);
|
|
146
148
|
});
|
|
147
149
|
it("only reaches an institute that is actually a trust", () => {
|
|
148
150
|
const priced = (isTrust) => (0, pricing_1.instituteQuote)({
|
package/lib/pricing.test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.test.js","sourceRoot":"","sources":["../src/pricing.test.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pricing.test.js","sourceRoot":"","sources":["../src/pricing.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/pricing.test.ts
CHANGED
|
@@ -147,21 +147,20 @@ describe("mergePricingConfig", () => {
|
|
|
147
147
|
});
|
|
148
148
|
|
|
149
149
|
describe("the trust discount", () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const result = calculateSchoolPrice(trust(9));
|
|
155
|
-
const plain = calculateSchoolPrice({...trust(9), schools: undefined});
|
|
150
|
+
it("prices a trust as one school price multiplied by the trust size before the discount", () => {
|
|
151
|
+
const base = {students: 500, events: true, destinations: true};
|
|
152
|
+
const single = calculateSchoolPrice(base);
|
|
153
|
+
const result = calculateSchoolPrice({...base, schools: 9});
|
|
156
154
|
|
|
157
155
|
expect(result.trustDiscountRate).toBe(0.05);
|
|
158
|
-
expect(result.total).toBeCloseTo(
|
|
159
|
-
expect(result.trustDiscountApplied).toBeCloseTo(
|
|
156
|
+
expect(result.total).toBeCloseTo(single.total * 9 * 0.95, 6);
|
|
157
|
+
expect(result.trustDiscountApplied).toBeCloseTo(single.total * 9 * 0.05, 6);
|
|
160
158
|
});
|
|
161
159
|
|
|
162
160
|
it("gives a trust of ten schools or more 10%", () => {
|
|
163
|
-
|
|
164
|
-
expect(calculateSchoolPrice(
|
|
161
|
+
const base = {students: 500, events: true, destinations: true};
|
|
162
|
+
expect(calculateSchoolPrice({...base, schools: 10}).trustDiscountRate).toBe(0.1);
|
|
163
|
+
expect(calculateSchoolPrice({...base, schools: 40}).trustDiscountRate).toBe(0.1);
|
|
165
164
|
});
|
|
166
165
|
|
|
167
166
|
it("gives a single school nothing, however it is counted", () => {
|
|
@@ -172,14 +171,15 @@ describe("the trust discount", () => {
|
|
|
172
171
|
|
|
173
172
|
it("is taken after the full-platform discount and before the negotiated one", () => {
|
|
174
173
|
const input: SchoolPricingInput = {
|
|
175
|
-
students:
|
|
174
|
+
students: 500, events: true, destinations: true,
|
|
176
175
|
fullPlatformDiscount: true, schools: 12, bespokeDiscount: 0.1,
|
|
177
176
|
};
|
|
178
177
|
const result = calculateSchoolPrice(input);
|
|
179
|
-
const
|
|
178
|
+
const single = calculateSchoolPrice({students: 500, events: true, destinations: true});
|
|
179
|
+
const expected = single.subtotal * 12 * 0.8 * 0.9 * 0.9;
|
|
180
180
|
|
|
181
181
|
expect(result.total).toBeCloseTo(expected, 6);
|
|
182
|
-
expect(result.trustDiscountApplied).toBeCloseTo(
|
|
182
|
+
expect(result.trustDiscountApplied).toBeCloseTo(single.subtotal * 12 * 0.8 * 0.1, 6);
|
|
183
183
|
});
|
|
184
184
|
|
|
185
185
|
it("only reaches an institute that is actually a trust", () => {
|
package/src/pricing.ts
CHANGED
|
@@ -1,61 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
* The 2026 pricing model.
|
|
3
|
-
*
|
|
4
|
-
* A quote is a base fee plus a per-product fee, and every per-product fee is
|
|
5
|
-
* graduated: the tiers are bands, not lookups, so a school with 1,250 students
|
|
6
|
-
* pays the tier 1 rate on its first 1,000 and the tier 2 rate on the next 250.
|
|
7
|
-
* Anything above the final threshold keeps paying the final tier's rate.
|
|
8
|
-
*
|
|
9
|
-
* Work experience is charged per placement (Y10 and Y12 are quoted separately,
|
|
10
|
-
* and a year group left blank is a year group not taking the product); events
|
|
11
|
-
* and destinations are charged per student. Only events and destinations carry
|
|
12
|
-
* a partial-product discount — that is how the pricing sheet has it, and it is
|
|
13
|
-
* why `partialProductDiscount` names those two rather than being one number.
|
|
14
|
-
*
|
|
15
|
-
* A trust is quoted as one account on its combined roll, and earns a discount
|
|
16
|
-
* on the whole quote for the number of schools it brings on — a smaller one
|
|
17
|
-
* below the threshold, a larger one at or above it.
|
|
18
|
-
*
|
|
19
|
-
* Every figure lives in `PricingConfig` so it can be stored in Firestore and
|
|
20
|
-
* adjusted without a deploy. `DEFAULT_PRICING_CONFIG` is the fallback and the
|
|
21
|
-
* seed for that document.
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/** One band of the graduated fee, with the rate each product charges in it. */
|
|
1
|
+
|
|
25
2
|
export type PricingTier = {
|
|
26
|
-
/** Upper bound of the band, in students (events and destinations). */
|
|
27
3
|
students: number,
|
|
28
|
-
/** Upper bound of the band, in placements (work experience). */
|
|
29
4
|
placements: number,
|
|
30
|
-
/** £ per placement. */
|
|
31
5
|
wex: number,
|
|
32
|
-
/** £ per student. */
|
|
33
6
|
events: number,
|
|
34
|
-
/** £ per student. */
|
|
35
7
|
destinations: number,
|
|
36
8
|
};
|
|
37
9
|
|
|
38
10
|
export type PricingConfig = {
|
|
39
|
-
/** No school is quoted below this, however little the products come to. */
|
|
40
11
|
minFee: number,
|
|
41
|
-
/** Charged on every quote. Not itemised to the customer. */
|
|
42
12
|
baseFee: number,
|
|
43
|
-
/** In ascending order of threshold. The last band's rate runs to infinity. */
|
|
44
13
|
tiers: PricingTier[],
|
|
45
|
-
/** Taken off a single product's fee, as a fraction (0.2 = 20% off). */
|
|
46
14
|
partialProductDiscount: {events: number, destinations: number},
|
|
47
|
-
/** Taken off the whole quote when a school takes the full platform. */
|
|
48
15
|
fullPlatformDiscount: number,
|
|
49
|
-
/** Taken off the whole quote for a trust, on how many schools it brings. */
|
|
50
16
|
trust: {
|
|
51
|
-
/** Schools at which the larger discount takes over. */
|
|
52
17
|
threshold: number,
|
|
53
|
-
/** Fraction off a trust below the threshold. */
|
|
54
18
|
discount: number,
|
|
55
|
-
/** Fraction off a trust at or above it. */
|
|
56
19
|
largeDiscount: number,
|
|
57
20
|
},
|
|
58
|
-
/** Careers hubs are a flat platform fee plus a fee for each school. */
|
|
59
21
|
hub: {baseFee: number, perSchoolFee: number},
|
|
60
22
|
};
|
|
61
23
|
|
|
@@ -69,36 +31,24 @@ export const DEFAULT_PRICING_CONFIG: PricingConfig = {
|
|
|
69
31
|
{students: 2000, placements: 200, wex: 1.5, events: 0.25, destinations: 0.25},
|
|
70
32
|
],
|
|
71
33
|
partialProductDiscount: {events: 0.2, destinations: 0.2},
|
|
72
|
-
fullPlatformDiscount: 0.
|
|
34
|
+
fullPlatformDiscount: 0.1,
|
|
73
35
|
trust: {threshold: 10, discount: 0.05, largeDiscount: 0.1},
|
|
74
36
|
hub: {baseFee: 2000, perSchoolFee: 150},
|
|
75
37
|
};
|
|
76
38
|
|
|
77
|
-
/** Where the adjustable copy of the config lives. */
|
|
78
39
|
export const PRICING_CONFIG_PATH = ["adminConfig", "pricing"];
|
|
79
40
|
|
|
80
41
|
export type SchoolPricingInput = {
|
|
81
|
-
/** Roll size. Drives the events and destinations fees. */
|
|
82
42
|
students?: number,
|
|
83
|
-
/** Y10 placements. Undefined means the year group isn't taking work experience. */
|
|
84
43
|
wexY10?: number,
|
|
85
|
-
/** Y12 placements. Undefined means the year group isn't taking work experience. */
|
|
86
44
|
wexY12?: number,
|
|
87
45
|
events?: boolean,
|
|
88
|
-
/** Discount the events fee on its own. */
|
|
89
46
|
eventsDiscount?: boolean,
|
|
90
47
|
destinations?: boolean,
|
|
91
|
-
/** Discount the destinations fee on its own. */
|
|
92
48
|
destinationsDiscount?: boolean,
|
|
93
|
-
/** Discount the whole quote, for a school taking the full platform. */
|
|
94
49
|
fullPlatformDiscount?: boolean,
|
|
95
|
-
/** Schools in the trust being quoted. Two or more earns a trust discount. */
|
|
96
50
|
schools?: number,
|
|
97
|
-
/** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off).
|
|
98
|
-
* Taken after the full-platform discount and before the minimum fee. */
|
|
99
51
|
bespokeDiscount?: number,
|
|
100
|
-
/** A price agreed with the customer, which replaces everything above it —
|
|
101
|
-
* the discounts, the minimum fee and the total the products came to. */
|
|
102
52
|
quoteOverride?: number,
|
|
103
53
|
};
|
|
104
54
|
|
|
@@ -108,19 +58,13 @@ export type PricingLineKey =
|
|
|
108
58
|
export type PricingLine = {
|
|
109
59
|
key: PricingLineKey,
|
|
110
60
|
label: string,
|
|
111
|
-
/** What the product costs after any partial-product discount. */
|
|
112
61
|
amount: number,
|
|
113
|
-
/** The fee before its partial-product discount, when one was applied. */
|
|
114
62
|
undiscounted?: number,
|
|
115
|
-
/** How the amount was reached, band by band. Empty for the base fee. */
|
|
116
63
|
bands: PricingBand[],
|
|
117
64
|
};
|
|
118
65
|
|
|
119
|
-
/** One band's contribution to a product's fee, for showing the working. */
|
|
120
66
|
export type PricingBand = {
|
|
121
|
-
/** 1-indexed, matching the tier's position in the config. */
|
|
122
67
|
tier: number,
|
|
123
|
-
/** Units charged in this band. */
|
|
124
68
|
quantity: number,
|
|
125
69
|
rate: number,
|
|
126
70
|
amount: number,
|
|
@@ -128,38 +72,22 @@ export type PricingBand = {
|
|
|
128
72
|
|
|
129
73
|
export type SchoolPricingResult = {
|
|
130
74
|
lines: PricingLine[],
|
|
131
|
-
/** The lines added up, before the full-platform discount. */
|
|
132
75
|
subtotal: number,
|
|
133
|
-
/** £ taken off the subtotal by the full-platform discount. */
|
|
134
76
|
fullPlatformDiscountApplied: number,
|
|
135
|
-
/** £ taken off by the trust discount, after the full-platform one. */
|
|
136
77
|
trustDiscountApplied: number,
|
|
137
|
-
/** The rate that trust discount was taken at, as a fraction. */
|
|
138
78
|
trustDiscountRate: number,
|
|
139
|
-
/** £ taken off by the negotiated discount, after the trust one. */
|
|
140
79
|
bespokeDiscountApplied: number,
|
|
141
|
-
/** True when the minimum fee, not the products, set the price. */
|
|
142
80
|
minFeeApplied: boolean,
|
|
143
|
-
/** True when an agreed price replaced the calculated one. */
|
|
144
81
|
overrideApplied: boolean,
|
|
145
82
|
total: number,
|
|
146
83
|
};
|
|
147
84
|
|
|
148
85
|
export type HubPricingResult = {
|
|
149
86
|
baseFee: number,
|
|
150
|
-
/** The per-school fee multiplied by the number of schools. */
|
|
151
87
|
schoolFees: number,
|
|
152
88
|
total: number,
|
|
153
89
|
};
|
|
154
90
|
|
|
155
|
-
/**
|
|
156
|
-
* Charge `quantity` across the bands, each band at its own rate, with anything
|
|
157
|
-
* above the final threshold staying on the final band's rate.
|
|
158
|
-
*
|
|
159
|
-
* @param {number} quantity students or placements, depending on the product.
|
|
160
|
-
* @param {Array} bands each band's upper threshold and its rate.
|
|
161
|
-
* @return {Array} one entry per band that charged something.
|
|
162
|
-
*/
|
|
163
91
|
function graduated(quantity: number, bands: {limit: number, rate: number}[]): PricingBand[] {
|
|
164
92
|
if (!(quantity > 0) || !bands.length) return [];
|
|
165
93
|
|
|
@@ -172,8 +100,6 @@ function graduated(quantity: number, bands: {limit: number, rate: number}[]): Pr
|
|
|
172
100
|
if (inBand > 0) lines.push({tier: index + 1, quantity: inBand, rate: band.rate, amount: inBand * band.rate});
|
|
173
101
|
});
|
|
174
102
|
|
|
175
|
-
// Everything past the last threshold keeps paying the last rate, so it belongs
|
|
176
|
-
// in the last band rather than as a second row at the same rate.
|
|
177
103
|
const last = bands[bands.length - 1];
|
|
178
104
|
const overflow = Math.max(quantity - last.limit, 0);
|
|
179
105
|
if (overflow > 0) {
|
|
@@ -195,16 +121,6 @@ const clampFraction = (value?: number) => Math.min(Math.max(value || 0, 0), 1);
|
|
|
195
121
|
|
|
196
122
|
const bandsTotal = (bands: PricingBand[]) => sum(bands.map((b) => b.amount));
|
|
197
123
|
|
|
198
|
-
/**
|
|
199
|
-
* What a trust comes off its quote for its size.
|
|
200
|
-
*
|
|
201
|
-
* A trust is more than one school, so a count below two is a single school and
|
|
202
|
-
* earns nothing — the discount is for bringing schools with you.
|
|
203
|
-
*
|
|
204
|
-
* @param {number} [schools] schools in the trust.
|
|
205
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
206
|
-
* @return {number} the discount, as a fraction of the quote.
|
|
207
|
-
*/
|
|
208
124
|
export function trustDiscountRate(
|
|
209
125
|
schools?: number,
|
|
210
126
|
config: PricingConfig = DEFAULT_PRICING_CONFIG,
|
|
@@ -214,20 +130,11 @@ export function trustDiscountRate(
|
|
|
214
130
|
return count >= config.trust.threshold ? config.trust.largeDiscount : config.trust.discount;
|
|
215
131
|
}
|
|
216
132
|
|
|
217
|
-
/**
|
|
218
|
-
* Price a school, trust or hub-school quote.
|
|
219
|
-
*
|
|
220
|
-
* Products the school isn't taking are left out of `lines` entirely, so the
|
|
221
|
-
* breakdown only ever shows what is being charged for.
|
|
222
|
-
*
|
|
223
|
-
* @param {object} input the roll, the year groups and the products taken.
|
|
224
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
225
|
-
* @return {object} the total, and the working that reached it.
|
|
226
|
-
*/
|
|
227
133
|
export function calculateSchoolPrice(
|
|
228
134
|
input: SchoolPricingInput,
|
|
229
135
|
config: PricingConfig = DEFAULT_PRICING_CONFIG,
|
|
230
136
|
): SchoolPricingResult {
|
|
137
|
+
const schoolCount = Math.max(input.schools || 0, 0);
|
|
231
138
|
const students = input.students || 0;
|
|
232
139
|
const tiers = config.tiers;
|
|
233
140
|
|
|
@@ -255,7 +162,18 @@ export function calculateSchoolPrice(
|
|
|
255
162
|
addPerStudent("events", "Employer events", input.events, input.eventsDiscount);
|
|
256
163
|
addPerStudent("destinations", "Destinations", input.destinations, input.destinationsDiscount);
|
|
257
164
|
|
|
258
|
-
const
|
|
165
|
+
const scaledLines = schoolCount > 1 ? lines.map((line) => ({
|
|
166
|
+
...line,
|
|
167
|
+
amount: line.amount * schoolCount,
|
|
168
|
+
...(line.undiscounted !== undefined ? {undiscounted: line.undiscounted * schoolCount} : {}),
|
|
169
|
+
bands: line.bands.map((band) => ({
|
|
170
|
+
...band,
|
|
171
|
+
quantity: band.quantity * schoolCount,
|
|
172
|
+
amount: band.amount * schoolCount,
|
|
173
|
+
})),
|
|
174
|
+
})) : lines;
|
|
175
|
+
|
|
176
|
+
const subtotal = sum(scaledLines.map((l) => l.amount));
|
|
259
177
|
const discounted = input.fullPlatformDiscount ? subtotal * (1 - config.fullPlatformDiscount) : subtotal;
|
|
260
178
|
const trustRate = trustDiscountRate(input.schools, config);
|
|
261
179
|
const trusted = discounted * (1 - trustRate);
|
|
@@ -264,7 +182,7 @@ export function calculateSchoolPrice(
|
|
|
264
182
|
const overridden = input.quoteOverride !== undefined && input.quoteOverride >= 0;
|
|
265
183
|
|
|
266
184
|
return {
|
|
267
|
-
lines,
|
|
185
|
+
lines: scaledLines,
|
|
268
186
|
subtotal,
|
|
269
187
|
fullPlatformDiscountApplied: subtotal - discounted,
|
|
270
188
|
trustDiscountApplied: discounted - trusted,
|
|
@@ -278,13 +196,6 @@ export function calculateSchoolPrice(
|
|
|
278
196
|
};
|
|
279
197
|
}
|
|
280
198
|
|
|
281
|
-
/**
|
|
282
|
-
* Price a careers hub: the platform fee, plus a fee for every school on it.
|
|
283
|
-
*
|
|
284
|
-
* @param {number} schools how many schools the hub brings on.
|
|
285
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
286
|
-
* @return {object} the platform fee, the school fees and the total.
|
|
287
|
-
*/
|
|
288
199
|
export function calculateHubPrice(
|
|
289
200
|
schools: number,
|
|
290
201
|
config: PricingConfig = DEFAULT_PRICING_CONFIG,
|
|
@@ -293,16 +204,6 @@ export function calculateHubPrice(
|
|
|
293
204
|
return {baseFee: config.hub.baseFee, schoolFees, total: config.hub.baseFee + schoolFees};
|
|
294
205
|
}
|
|
295
206
|
|
|
296
|
-
/**
|
|
297
|
-
* Fill a stored config out with the defaults.
|
|
298
|
-
*
|
|
299
|
-
* The Firestore document is hand-edited, so treat every branch of it as
|
|
300
|
-
* possibly absent — a config saved before a tier was added should still price,
|
|
301
|
-
* rather than throwing on a missing rate.
|
|
302
|
-
*
|
|
303
|
-
* @param {object} [stored] whatever the Firestore document holds.
|
|
304
|
-
* @return {object} a complete config, safe to price with.
|
|
305
|
-
*/
|
|
306
207
|
export function mergePricingConfig(stored?: Partial<PricingConfig>): PricingConfig {
|
|
307
208
|
const d = DEFAULT_PRICING_CONFIG;
|
|
308
209
|
if (!stored) return d;
|
|
@@ -318,59 +219,27 @@ export function mergePricingConfig(stored?: Partial<PricingConfig>): PricingConf
|
|
|
318
219
|
};
|
|
319
220
|
}
|
|
320
221
|
|
|
321
|
-
/* -------------------------------------------------------------------------
|
|
322
|
-
* An institute's own quote.
|
|
323
|
-
*
|
|
324
|
-
* The calculator above prices a hypothetical school. What an actual customer
|
|
325
|
-
* pays is that calculation plus the terms agreed with them — the year groups
|
|
326
|
-
* and roll we quoted on, which discounts we gave, and any price we simply shook
|
|
327
|
-
* hands on — so those live on the institute, in `InstitutePricing`, and the
|
|
328
|
-
* quote is worked out from the two together.
|
|
329
|
-
*
|
|
330
|
-
* A school never reads the pricing configuration itself (it is admin data, and
|
|
331
|
-
* a school has no business seeing the tiers), so the agreed quote is snapshotted
|
|
332
|
-
* onto the institute as `InstitutePricing.quote` whenever an admin saves. That
|
|
333
|
-
* snapshot is what the school's own billing page shows.
|
|
334
|
-
* ---------------------------------------------------------------------- */
|
|
335
|
-
|
|
336
|
-
/** The terms agreed with one customer. Stored at `institutes/{oId}.pricing`. */
|
|
337
222
|
export type InstitutePricing = {
|
|
338
|
-
/** The roll we quoted on. Defaults to the institute's own student count. */
|
|
339
223
|
students?: number,
|
|
340
|
-
/** Y10 placements quoted. Undefined means the year group isn't on work experience. */
|
|
341
224
|
wexY10?: number,
|
|
342
|
-
/** Y12 placements quoted. Undefined means the year group isn't on work experience. */
|
|
343
225
|
wexY12?: number,
|
|
344
|
-
/** Take the partial-product discount off the events fee. */
|
|
345
226
|
eventsDiscount?: boolean,
|
|
346
|
-
/** Take the partial-product discount off the destinations fee. */
|
|
347
227
|
destinationsDiscount?: boolean,
|
|
348
|
-
/** Take the full-platform discount off the whole quote. */
|
|
349
228
|
fullPlatformDiscount?: boolean,
|
|
350
|
-
/** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off). */
|
|
351
229
|
bespokeDiscount?: number,
|
|
352
|
-
/** Why the negotiated discount or the agreed price was given. Admin-only. */
|
|
353
230
|
discountReason?: string,
|
|
354
|
-
/** A price agreed with the customer, which replaces the calculated one. */
|
|
355
231
|
quoteOverride?: number,
|
|
356
|
-
/** Schools in the trust, which set its discount. Trust accounts only. */
|
|
357
232
|
schools?: number,
|
|
358
|
-
/** Schools on the hub. Hub accounts only. */
|
|
359
233
|
hubSchools?: number,
|
|
360
|
-
/** The quote as last saved, for the customer to see. */
|
|
361
234
|
quote?: InstituteQuoteSnapshot,
|
|
362
235
|
};
|
|
363
236
|
|
|
364
|
-
/** A priced institute: the same shape for a school, a trust and a hub. */
|
|
365
237
|
export type InstituteQuote = {
|
|
366
238
|
kind: "school"|"hub",
|
|
367
|
-
/** Every fee charged, with the working behind it. */
|
|
368
239
|
lines: PricingLine[],
|
|
369
|
-
/** The lines added up, before any whole-quote discount. */
|
|
370
240
|
subtotal: number,
|
|
371
241
|
fullPlatformDiscountApplied: number,
|
|
372
242
|
trustDiscountApplied: number,
|
|
373
|
-
/** The rate the trust discount was taken at, as a fraction. */
|
|
374
243
|
trustDiscountRate: number,
|
|
375
244
|
bespokeDiscountApplied: number,
|
|
376
245
|
minFeeApplied: boolean,
|
|
@@ -378,42 +247,23 @@ export type InstituteQuote = {
|
|
|
378
247
|
total: number,
|
|
379
248
|
};
|
|
380
249
|
|
|
381
|
-
/** What the customer is shown: the total, and what makes it up. No rates. */
|
|
382
250
|
export type InstituteQuoteSnapshot = {
|
|
383
251
|
lines: {key: PricingLineKey, label: string, amount: number}[],
|
|
384
|
-
/** The lines added up. */
|
|
385
252
|
subtotal: number,
|
|
386
|
-
/** Everything taken off the lines to reach the total, as one figure. */
|
|
387
253
|
discountTotal: number,
|
|
388
|
-
/** True when the total is a floor or an agreed price above what the lines
|
|
389
|
-
* come to, so the breakdown is shown as an illustration, not a sum. */
|
|
390
254
|
minimum: boolean,
|
|
391
255
|
total: number,
|
|
392
|
-
/** ISO date the quote was last worked out. */
|
|
393
256
|
updated: string,
|
|
394
257
|
};
|
|
395
258
|
|
|
396
|
-
/** What the quote needs to know about the institute being priced. */
|
|
397
259
|
export type InstituteQuoteInput = {
|
|
398
|
-
/** What the institute has, as resolved by `resolveProducts`. */
|
|
399
260
|
products: {wex?: boolean, events?: boolean, destinations?: boolean, isHub?: boolean, isTrust?: boolean},
|
|
400
|
-
/** The institute's roll, when the agreed terms don't name one. */
|
|
401
261
|
students?: number,
|
|
402
|
-
/** Schools in the trust, when the agreed terms don't name a number. */
|
|
403
262
|
schools?: number,
|
|
404
|
-
/** Schools on the hub, when the agreed terms don't name a number. */
|
|
405
263
|
hubSchools?: number,
|
|
406
|
-
/** The terms agreed with this customer. */
|
|
407
264
|
pricing?: InstitutePricing,
|
|
408
265
|
};
|
|
409
266
|
|
|
410
|
-
/**
|
|
411
|
-
* Price a school and present it as an institute quote.
|
|
412
|
-
*
|
|
413
|
-
* @param {object} input the roll, the year groups, the products and the terms.
|
|
414
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
415
|
-
* @return {object} the quote, ready to render.
|
|
416
|
-
*/
|
|
417
267
|
export function schoolQuote(
|
|
418
268
|
input: SchoolPricingInput,
|
|
419
269
|
config: PricingConfig = DEFAULT_PRICING_CONFIG,
|
|
@@ -421,18 +271,6 @@ export function schoolQuote(
|
|
|
421
271
|
return {kind: "school", ...calculateSchoolPrice(input, config)};
|
|
422
272
|
}
|
|
423
273
|
|
|
424
|
-
/**
|
|
425
|
-
* Price a careers hub as an institute quote: the platform fee, then the schools.
|
|
426
|
-
*
|
|
427
|
-
* Hubs have no products to discount individually and no minimum fee to fall back
|
|
428
|
-
* on, so the only terms that reach them are the negotiated discount and an
|
|
429
|
-
* agreed price.
|
|
430
|
-
*
|
|
431
|
-
* @param {number} schools how many schools the hub brings on.
|
|
432
|
-
* @param {object} [pricing] the terms agreed with this hub.
|
|
433
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
434
|
-
* @return {object} the quote, ready to render.
|
|
435
|
-
*/
|
|
436
274
|
export function hubQuote(
|
|
437
275
|
schools: number,
|
|
438
276
|
pricing?: InstitutePricing,
|
|
@@ -471,21 +309,6 @@ export function hubQuote(
|
|
|
471
309
|
};
|
|
472
310
|
}
|
|
473
311
|
|
|
474
|
-
/**
|
|
475
|
-
* Price an institute on what it actually has and what was agreed with it.
|
|
476
|
-
*
|
|
477
|
-
* The products come from `resolveProducts` rather than the raw flags, so a trust
|
|
478
|
-
* is priced on the union of its schools' products the same way it is gated on
|
|
479
|
-
* them, and it is a trust — not any school with a number against it — that earns
|
|
480
|
-
* the trust discount. A year group with no placements agreed is a year group not on work
|
|
481
|
-
* experience — except where the institute has work experience and neither year
|
|
482
|
-
* group has been filled in, which is a quote waiting to be finished rather than
|
|
483
|
-
* a school not taking the product, so Y10 is charged at zero to say so.
|
|
484
|
-
*
|
|
485
|
-
* @param {object} input the institute's products, roll and agreed terms.
|
|
486
|
-
* @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
|
|
487
|
-
* @return {object} the quote, ready to render.
|
|
488
|
-
*/
|
|
489
312
|
export function instituteQuote(
|
|
490
313
|
input: InstituteQuoteInput,
|
|
491
314
|
config: PricingConfig = DEFAULT_PRICING_CONFIG,
|
|
@@ -516,16 +339,6 @@ export function instituteQuote(
|
|
|
516
339
|
}, config);
|
|
517
340
|
}
|
|
518
341
|
|
|
519
|
-
/**
|
|
520
|
-
* Reduce a quote to what the customer sees: the fees, and one discount figure.
|
|
521
|
-
*
|
|
522
|
-
* The base fee isn't itemised to customers, so it is folded into the first fee
|
|
523
|
-
* they are shown — and where there is nothing to fold it into, it stands alone
|
|
524
|
-
* as the platform fee it is.
|
|
525
|
-
*
|
|
526
|
-
* @param {object} quote the priced institute.
|
|
527
|
-
* @return {object} the snapshot to store on the institute.
|
|
528
|
-
*/
|
|
529
342
|
export function quoteSnapshot(quote: InstituteQuote): InstituteQuoteSnapshot {
|
|
530
343
|
const itemised = quote.lines.filter((l) => l.key !== "base");
|
|
531
344
|
const base = quote.lines.find((l) => l.key === "base")?.amount || 0;
|
|
@@ -543,9 +356,6 @@ export function quoteSnapshot(quote: InstituteQuote): InstituteQuoteSnapshot {
|
|
|
543
356
|
return {
|
|
544
357
|
lines,
|
|
545
358
|
subtotal,
|
|
546
|
-
// The customer is shown the fees and one discount, so whatever separates
|
|
547
|
-
// the two — the whole-quote discounts, an agreed price below them — is
|
|
548
|
-
// that one figure, and a total above the fees is flagged instead.
|
|
549
359
|
discountTotal: Math.max(subtotal - quote.total, 0),
|
|
550
360
|
minimum: quote.total > subtotal,
|
|
551
361
|
total: quote.total,
|