placementt-core 1.400.1071 → 1.400.1073

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 CHANGED
@@ -1,24 +1,64 @@
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 priced as one school — its own lines, its own discounts and its own
16
+ * minimum fee — and that one school's price is then multiplied by the number of
17
+ * schools it brings on, which earns a discount on the whole quote: a smaller one
18
+ * below the threshold, a larger one at or above it. Everything the breakdown
19
+ * shows above that multiplication is therefore one school's, not the trust's.
20
+ *
21
+ * Every figure lives in `PricingConfig` so it can be stored in Firestore and
22
+ * adjusted without a deploy. `DEFAULT_PRICING_CONFIG` is the fallback and the
23
+ * seed for that document.
24
+ */
25
+ /** One band of the graduated fee, with the rate each product charges in it. */
1
26
  export type PricingTier = {
27
+ /** Upper bound of the band, in students (events and destinations). */
2
28
  students: number;
29
+ /** Upper bound of the band, in placements (work experience). */
3
30
  placements: number;
31
+ /** £ per placement. */
4
32
  wex: number;
33
+ /** £ per student. */
5
34
  events: number;
35
+ /** £ per student. */
6
36
  destinations: number;
7
37
  };
8
38
  export type PricingConfig = {
39
+ /** No school is quoted below this, however little the products come to. */
9
40
  minFee: number;
41
+ /** Charged on every quote. Not itemised to the customer. */
10
42
  baseFee: number;
43
+ /** In ascending order of threshold. The last band's rate runs to infinity. */
11
44
  tiers: PricingTier[];
45
+ /** Taken off a single product's fee, as a fraction (0.2 = 20% off). */
12
46
  partialProductDiscount: {
13
47
  events: number;
14
48
  destinations: number;
15
49
  };
50
+ /** Taken off the whole quote when a school takes the full platform. */
16
51
  fullPlatformDiscount: number;
52
+ /** Taken off the whole quote for a trust, on how many schools it brings. */
17
53
  trust: {
54
+ /** Schools at which the larger discount takes over. */
18
55
  threshold: number;
56
+ /** Fraction off a trust below the threshold. */
19
57
  discount: number;
58
+ /** Fraction off a trust at or above it. */
20
59
  largeDiscount: number;
21
60
  };
61
+ /** Careers hubs are a flat platform fee plus a fee for each school. */
22
62
  hub: {
23
63
  baseFee: number;
24
64
  perSchoolFee: number;
@@ -26,93 +66,195 @@ export type PricingConfig = {
26
66
  };
27
67
  /** The pricing sheet's figures, as agreed for 2026. */
28
68
  export declare const DEFAULT_PRICING_CONFIG: PricingConfig;
69
+ /** Where the adjustable copy of the config lives. */
29
70
  export declare const PRICING_CONFIG_PATH: string[];
30
71
  export type SchoolPricingInput = {
72
+ /** Roll size. Drives the events and destinations fees. */
31
73
  students?: number;
74
+ /** Y10 placements. Undefined means the year group isn't taking work experience. */
32
75
  wexY10?: number;
76
+ /** Y12 placements. Undefined means the year group isn't taking work experience. */
33
77
  wexY12?: number;
34
78
  events?: boolean;
79
+ /** Discount the events fee on its own. */
35
80
  eventsDiscount?: boolean;
36
81
  destinations?: boolean;
82
+ /** Discount the destinations fee on its own. */
37
83
  destinationsDiscount?: boolean;
84
+ /** Discount the whole quote, for a school taking the full platform. */
38
85
  fullPlatformDiscount?: boolean;
86
+ /** Schools in the trust being quoted. The roll and the placements above are
87
+ * one school's, and the price they come to is multiplied by this count. */
39
88
  schools?: number;
89
+ /** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off).
90
+ * Taken after the full-platform discount and before the minimum fee. */
40
91
  bespokeDiscount?: number;
92
+ /** A price agreed with the customer, which replaces everything above it —
93
+ * the discounts, the minimum fee and the total the products came to. */
41
94
  quoteOverride?: number;
42
95
  };
43
96
  export type PricingLineKey = "base" | "wexY10" | "wexY12" | "events" | "destinations" | "hubBase" | "hubSchools";
44
97
  export type PricingLine = {
45
98
  key: PricingLineKey;
46
99
  label: string;
100
+ /** What the product costs after any partial-product discount. */
47
101
  amount: number;
102
+ /** The fee before its partial-product discount, when one was applied. */
48
103
  undiscounted?: number;
104
+ /** How the amount was reached, band by band. Empty for the base fee. */
49
105
  bands: PricingBand[];
50
106
  };
107
+ /** One band's contribution to a product's fee, for showing the working. */
51
108
  export type PricingBand = {
109
+ /** 1-indexed, matching the tier's position in the config. */
52
110
  tier: number;
111
+ /** Units charged in this band. */
53
112
  quantity: number;
54
113
  rate: number;
55
114
  amount: number;
56
115
  };
57
116
  export type SchoolPricingResult = {
117
+ /** One school's fees. A trust's lines are a single school's, not the sum. */
58
118
  lines: PricingLine[];
119
+ /** One school's lines added up, before the full-platform discount. */
59
120
  subtotal: number;
121
+ /** £ taken off one school's subtotal by the full-platform discount. */
60
122
  fullPlatformDiscountApplied: number;
123
+ /** One school's price, after its discount and the minimum fee. */
124
+ perSchoolTotal: number;
125
+ /** Schools the per-school price is charged for. 1 for a single school. */
126
+ schools: number;
127
+ /** `perSchoolTotal` multiplied out, before the trust discount. */
128
+ schoolsSubtotal: number;
129
+ /** £ taken off `schoolsSubtotal` by the trust discount. */
61
130
  trustDiscountApplied: number;
131
+ /** The rate that trust discount was taken at, as a fraction. */
62
132
  trustDiscountRate: number;
133
+ /** £ taken off by the negotiated discount, after the trust one. */
63
134
  bespokeDiscountApplied: number;
135
+ /** True when the minimum fee, not the products, set the price. */
64
136
  minFeeApplied: boolean;
137
+ /** True when an agreed price replaced the calculated one. */
65
138
  overrideApplied: boolean;
66
139
  total: number;
67
140
  };
68
141
  export type HubPricingResult = {
69
142
  baseFee: number;
143
+ /** The per-school fee multiplied by the number of schools. */
70
144
  schoolFees: number;
71
145
  total: number;
72
146
  };
147
+ /**
148
+ * What a trust comes off its quote for its size.
149
+ *
150
+ * A trust is more than one school, so a count below two is a single school and
151
+ * earns nothing — the discount is for bringing schools with you.
152
+ *
153
+ * @param {number} [schools] schools in the trust.
154
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
155
+ * @return {number} the discount, as a fraction of the quote.
156
+ */
73
157
  export declare function trustDiscountRate(schools?: number, config?: PricingConfig): number;
158
+ /**
159
+ * Price a school, trust or hub-school quote.
160
+ *
161
+ * Products the school isn't taking are left out of `lines` entirely, so the
162
+ * breakdown only ever shows what is being charged for.
163
+ *
164
+ * @param {object} input the roll, the year groups and the products taken.
165
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
166
+ * @return {object} the total, and the working that reached it.
167
+ */
74
168
  export declare function calculateSchoolPrice(input: SchoolPricingInput, config?: PricingConfig): SchoolPricingResult;
169
+ /**
170
+ * Price a careers hub: the platform fee, plus a fee for every school on it.
171
+ *
172
+ * @param {number} schools how many schools the hub brings on.
173
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
174
+ * @return {object} the platform fee, the school fees and the total.
175
+ */
75
176
  export declare function calculateHubPrice(schools: number, config?: PricingConfig): HubPricingResult;
177
+ /**
178
+ * Fill a stored config out with the defaults.
179
+ *
180
+ * The Firestore document is hand-edited, so treat every branch of it as
181
+ * possibly absent — a config saved before a tier was added should still price,
182
+ * rather than throwing on a missing rate.
183
+ *
184
+ * @param {object} [stored] whatever the Firestore document holds.
185
+ * @return {object} a complete config, safe to price with.
186
+ */
76
187
  export declare function mergePricingConfig(stored?: Partial<PricingConfig>): PricingConfig;
188
+ /** The terms agreed with one customer. Stored at `institutes/{oId}.pricing`. */
77
189
  export type InstitutePricing = {
190
+ /** The roll we quoted on. Defaults to the institute's own student count. */
78
191
  students?: number;
192
+ /** Y10 placements quoted. Undefined means the year group isn't on work experience. */
79
193
  wexY10?: number;
194
+ /** Y12 placements quoted. Undefined means the year group isn't on work experience. */
80
195
  wexY12?: number;
196
+ /** Take the partial-product discount off the events fee. */
81
197
  eventsDiscount?: boolean;
198
+ /** Take the partial-product discount off the destinations fee. */
82
199
  destinationsDiscount?: boolean;
200
+ /** Take the full-platform discount off the whole quote. */
83
201
  fullPlatformDiscount?: boolean;
202
+ /** A negotiated discount off the whole quote, as a fraction (0.1 = 10% off). */
84
203
  bespokeDiscount?: number;
204
+ /** Why the negotiated discount or the agreed price was given. Admin-only. */
85
205
  discountReason?: string;
206
+ /** A price agreed with the customer, which replaces the calculated one. */
86
207
  quoteOverride?: number;
208
+ /** Schools in the trust, which set its discount. Trust accounts only. */
87
209
  schools?: number;
210
+ /** Schools on the hub. Hub accounts only. */
88
211
  hubSchools?: number;
212
+ /** The quote as last saved, for the customer to see. */
89
213
  quote?: InstituteQuoteSnapshot;
90
214
  };
215
+ /** A priced institute: the same shape for a school, a trust and a hub. */
91
216
  export type InstituteQuote = {
92
217
  kind: "school" | "hub";
218
+ /** Every fee charged, with the working behind it. One school's, for a trust. */
93
219
  lines: PricingLine[];
220
+ /** The lines added up, before any whole-quote discount. */
94
221
  subtotal: number;
95
222
  fullPlatformDiscountApplied: number;
223
+ /** One school's price, after its discount and the minimum fee. */
224
+ perSchoolTotal: number;
225
+ /** Schools the per-school price is charged for. 1 for a school or a hub. */
226
+ schools: number;
227
+ /** `perSchoolTotal` multiplied out, before the trust discount. */
228
+ schoolsSubtotal: number;
96
229
  trustDiscountApplied: number;
230
+ /** The rate the trust discount was taken at, as a fraction. */
97
231
  trustDiscountRate: number;
98
232
  bespokeDiscountApplied: number;
99
233
  minFeeApplied: boolean;
100
234
  overrideApplied: boolean;
101
235
  total: number;
102
236
  };
237
+ /** What the customer is shown: the total, and what makes it up. No rates. */
103
238
  export type InstituteQuoteSnapshot = {
104
239
  lines: {
105
240
  key: PricingLineKey;
106
241
  label: string;
107
242
  amount: number;
108
243
  }[];
244
+ /** The lines added up. */
109
245
  subtotal: number;
246
+ /** Everything taken off the lines to reach the total, as one figure. */
110
247
  discountTotal: number;
248
+ /** True when the total is a floor or an agreed price above what the lines
249
+ * come to, so the breakdown is shown as an illustration, not a sum. */
111
250
  minimum: boolean;
112
251
  total: number;
252
+ /** ISO date the quote was last worked out. */
113
253
  updated: string;
114
254
  };
255
+ /** What the quote needs to know about the institute being priced. */
115
256
  export type InstituteQuoteInput = {
257
+ /** What the institute has, as resolved by `resolveProducts`. */
116
258
  products: {
117
259
  wex?: boolean;
118
260
  events?: boolean;
@@ -120,12 +262,64 @@ export type InstituteQuoteInput = {
120
262
  isHub?: boolean;
121
263
  isTrust?: boolean;
122
264
  };
265
+ /** The institute's roll, when the agreed terms don't name one. */
123
266
  students?: number;
267
+ /** Schools in the trust, when the agreed terms don't name a number. */
124
268
  schools?: number;
269
+ /** Schools on the hub, when the agreed terms don't name a number. */
125
270
  hubSchools?: number;
271
+ /** The terms agreed with this customer. */
126
272
  pricing?: InstitutePricing;
127
273
  };
274
+ /**
275
+ * Price a school and present it as an institute quote.
276
+ *
277
+ * @param {object} input the roll, the year groups, the products and the terms.
278
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
279
+ * @return {object} the quote, ready to render.
280
+ */
128
281
  export declare function schoolQuote(input: SchoolPricingInput, config?: PricingConfig): InstituteQuote;
282
+ /**
283
+ * Price a careers hub as an institute quote: the platform fee, then the schools.
284
+ *
285
+ * Hubs have no products to discount individually and no minimum fee to fall back
286
+ * on, so the only terms that reach them are the negotiated discount and an
287
+ * agreed price.
288
+ *
289
+ * @param {number} schools how many schools the hub brings on.
290
+ * @param {object} [pricing] the terms agreed with this hub.
291
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
292
+ * @return {object} the quote, ready to render.
293
+ */
129
294
  export declare function hubQuote(schools: number, pricing?: InstitutePricing, config?: PricingConfig): InstituteQuote;
295
+ /**
296
+ * Price an institute on what it actually has and what was agreed with it.
297
+ *
298
+ * The products come from `resolveProducts` rather than the raw flags, so a trust
299
+ * is priced on the union of its schools' products the same way it is gated on
300
+ * them, and it is a trust — not any school with a number against it — that earns
301
+ * the trust discount. A year group with no placements agreed is a year group not on work
302
+ * experience — except where the institute has work experience and neither year
303
+ * group has been filled in, which is a quote waiting to be finished rather than
304
+ * a school not taking the product, so Y10 is charged at zero to say so.
305
+ *
306
+ * @param {object} input the institute's products, roll and agreed terms.
307
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
308
+ * @return {object} the quote, ready to render.
309
+ */
130
310
  export declare function instituteQuote(input: InstituteQuoteInput, config?: PricingConfig): InstituteQuote;
311
+ /**
312
+ * Reduce a quote to what the customer sees: the fees, and one discount figure.
313
+ *
314
+ * The base fee isn't itemised to customers, so it is folded into the first fee
315
+ * they are shown — and where there is nothing to fold it into, it stands alone
316
+ * as the platform fee it is.
317
+ *
318
+ * A trust's lines are one school's, and what a trust pays is every school's, so
319
+ * the fees are multiplied out here: the customer is shown what their account
320
+ * costs, not what one of their schools would have cost on its own.
321
+ *
322
+ * @param {object} quote the priced institute.
323
+ * @return {object} the snapshot to store on the institute.
324
+ */
131
325
  export declare function quoteSnapshot(quote: InstituteQuote): InstituteQuoteSnapshot;
package/lib/pricing.js CHANGED
@@ -1,4 +1,28 @@
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 priced as one school — its own lines, its own discounts and its own
17
+ * minimum fee — and that one school's price is then multiplied by the number of
18
+ * schools it brings on, which earns a discount on the whole quote: a smaller one
19
+ * below the threshold, a larger one at or above it. Everything the breakdown
20
+ * shows above that multiplication is therefore one school's, not the trust's.
21
+ *
22
+ * Every figure lives in `PricingConfig` so it can be stored in Firestore and
23
+ * adjusted without a deploy. `DEFAULT_PRICING_CONFIG` is the fallback and the
24
+ * seed for that document.
25
+ */
2
26
  Object.defineProperty(exports, "__esModule", { value: true });
3
27
  exports.PRICING_CONFIG_PATH = exports.DEFAULT_PRICING_CONFIG = void 0;
4
28
  exports.trustDiscountRate = trustDiscountRate;
@@ -23,7 +47,16 @@ exports.DEFAULT_PRICING_CONFIG = {
23
47
  trust: { threshold: 10, discount: 0.05, largeDiscount: 0.1 },
24
48
  hub: { baseFee: 2000, perSchoolFee: 150 },
25
49
  };
50
+ /** Where the adjustable copy of the config lives. */
26
51
  exports.PRICING_CONFIG_PATH = ["adminConfig", "pricing"];
52
+ /**
53
+ * Charge `quantity` across the bands, each band at its own rate, with anything
54
+ * above the final threshold staying on the final band's rate.
55
+ *
56
+ * @param {number} quantity students or placements, depending on the product.
57
+ * @param {Array} bands each band's upper threshold and its rate.
58
+ * @return {Array} one entry per band that charged something.
59
+ */
27
60
  function graduated(quantity, bands) {
28
61
  if (!(quantity > 0) || !bands.length)
29
62
  return [];
@@ -35,6 +68,8 @@ function graduated(quantity, bands) {
35
68
  if (inBand > 0)
36
69
  lines.push({ tier: index + 1, quantity: inBand, rate: band.rate, amount: inBand * band.rate });
37
70
  });
71
+ // Everything past the last threshold keeps paying the last rate, so it belongs
72
+ // in the last band rather than as a second row at the same rate.
38
73
  const last = bands[bands.length - 1];
39
74
  const overflow = Math.max(quantity - last.limit, 0);
40
75
  if (overflow > 0) {
@@ -52,14 +87,36 @@ function graduated(quantity, bands) {
52
87
  const sum = (values) => values.reduce((total, value) => total + value, 0);
53
88
  const clampFraction = (value) => Math.min(Math.max(value || 0, 0), 1);
54
89
  const bandsTotal = (bands) => sum(bands.map((b) => b.amount));
90
+ /**
91
+ * What a trust comes off its quote for its size.
92
+ *
93
+ * A trust is more than one school, so a count below two is a single school and
94
+ * earns nothing — the discount is for bringing schools with you.
95
+ *
96
+ * @param {number} [schools] schools in the trust.
97
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
98
+ * @return {number} the discount, as a fraction of the quote.
99
+ */
55
100
  function trustDiscountRate(schools, config = exports.DEFAULT_PRICING_CONFIG) {
56
101
  const count = schools || 0;
57
102
  if (count < 2)
58
103
  return 0;
59
104
  return count >= config.trust.threshold ? config.trust.largeDiscount : config.trust.discount;
60
105
  }
106
+ /**
107
+ * Price a school, trust or hub-school quote.
108
+ *
109
+ * Products the school isn't taking are left out of `lines` entirely, so the
110
+ * breakdown only ever shows what is being charged for.
111
+ *
112
+ * @param {object} input the roll, the year groups and the products taken.
113
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
114
+ * @return {object} the total, and the working that reached it.
115
+ */
61
116
  function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
62
- const schoolCount = Math.max(input.schools || 0, 0);
117
+ // A trust is priced as one school, so everything below the multiplication is
118
+ // one school's — the roll and the placements included.
119
+ const schools = Math.max(input.schools || 1, 1);
63
120
  const students = input.students || 0;
64
121
  const tiers = config.tiers;
65
122
  const perPlacement = tiers.map((t) => ({ limit: t.placements, rate: t.wex }));
@@ -83,41 +140,60 @@ function calculateSchoolPrice(input, config = exports.DEFAULT_PRICING_CONFIG) {
83
140
  };
84
141
  addPerStudent("events", "Employer events", input.events, input.eventsDiscount);
85
142
  addPerStudent("destinations", "Destinations", input.destinations, input.destinationsDiscount);
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));
143
+ const subtotal = sum(lines.map((l) => l.amount));
97
144
  const discounted = input.fullPlatformDiscount ? subtotal * (1 - config.fullPlatformDiscount) : subtotal;
145
+ // The floor is held against the school, not the trust: a trust of twenty
146
+ // small schools owes twenty minimum fees, not one.
147
+ const perSchoolTotal = Math.max(discounted, config.minFee);
148
+ const schoolsSubtotal = perSchoolTotal * schools;
98
149
  const trustRate = trustDiscountRate(input.schools, config);
99
- const trusted = discounted * (1 - trustRate);
150
+ const trusted = schoolsSubtotal * (1 - trustRate);
100
151
  const negotiated = trusted * (1 - clampFraction(input.bespokeDiscount));
101
- const floored = Math.max(negotiated, config.minFee);
152
+ // The floor holds against a negotiated discount, but not against the trust
153
+ // discount the account has earned: a trust's minimum is a minimum fee for
154
+ // each of its schools, on the terms its size gets.
155
+ const floored = Math.max(negotiated, config.minFee * schools * (1 - trustRate));
102
156
  const overridden = input.quoteOverride !== undefined && input.quoteOverride >= 0;
103
157
  return {
104
- lines: scaledLines,
158
+ lines,
105
159
  subtotal,
106
160
  fullPlatformDiscountApplied: subtotal - discounted,
107
- trustDiscountApplied: discounted - trusted,
161
+ perSchoolTotal,
162
+ schools,
163
+ schoolsSubtotal,
164
+ trustDiscountApplied: schoolsSubtotal - trusted,
108
165
  trustDiscountRate: trustRate,
109
166
  bespokeDiscountApplied: trusted - negotiated,
110
167
  // An agreed price is the price, so neither the floor nor the discounts
111
168
  // are what set it — they are only reported when the calculation stands.
112
- minFeeApplied: !overridden && floored > negotiated,
169
+ // The floor bites in two places: on the school, and on what a discount
170
+ // took the trust below.
171
+ minFeeApplied: !overridden && (perSchoolTotal > discounted || floored > negotiated),
113
172
  overrideApplied: overridden,
114
173
  total: overridden ? input.quoteOverride : floored,
115
174
  };
116
175
  }
176
+ /**
177
+ * Price a careers hub: the platform fee, plus a fee for every school on it.
178
+ *
179
+ * @param {number} schools how many schools the hub brings on.
180
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
181
+ * @return {object} the platform fee, the school fees and the total.
182
+ */
117
183
  function calculateHubPrice(schools, config = exports.DEFAULT_PRICING_CONFIG) {
118
184
  const schoolFees = Math.max(schools || 0, 0) * config.hub.perSchoolFee;
119
185
  return { baseFee: config.hub.baseFee, schoolFees, total: config.hub.baseFee + schoolFees };
120
186
  }
187
+ /**
188
+ * Fill a stored config out with the defaults.
189
+ *
190
+ * The Firestore document is hand-edited, so treat every branch of it as
191
+ * possibly absent — a config saved before a tier was added should still price,
192
+ * rather than throwing on a missing rate.
193
+ *
194
+ * @param {object} [stored] whatever the Firestore document holds.
195
+ * @return {object} a complete config, safe to price with.
196
+ */
121
197
  function mergePricingConfig(stored) {
122
198
  const d = exports.DEFAULT_PRICING_CONFIG;
123
199
  if (!stored)
@@ -132,9 +208,28 @@ function mergePricingConfig(stored) {
132
208
  hub: { ...d.hub, ...stored.hub },
133
209
  };
134
210
  }
211
+ /**
212
+ * Price a school and present it as an institute quote.
213
+ *
214
+ * @param {object} input the roll, the year groups, the products and the terms.
215
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
216
+ * @return {object} the quote, ready to render.
217
+ */
135
218
  function schoolQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
136
219
  return { kind: "school", ...calculateSchoolPrice(input, config) };
137
220
  }
221
+ /**
222
+ * Price a careers hub as an institute quote: the platform fee, then the schools.
223
+ *
224
+ * Hubs have no products to discount individually and no minimum fee to fall back
225
+ * on, so the only terms that reach them are the negotiated discount and an
226
+ * agreed price.
227
+ *
228
+ * @param {number} schools how many schools the hub brings on.
229
+ * @param {object} [pricing] the terms agreed with this hub.
230
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
231
+ * @return {object} the quote, ready to render.
232
+ */
138
233
  function hubQuote(schools, pricing, config = exports.DEFAULT_PRICING_CONFIG) {
139
234
  const count = Math.max(schools || 0, 0);
140
235
  const hub = calculateHubPrice(count, config);
@@ -156,6 +251,11 @@ function hubQuote(schools, pricing, config = exports.DEFAULT_PRICING_CONFIG) {
156
251
  lines,
157
252
  subtotal: hub.total,
158
253
  fullPlatformDiscountApplied: 0,
254
+ // A hub is one account, however many schools it brings, so there is
255
+ // nothing to multiply and its per-school figures are the quote itself.
256
+ perSchoolTotal: hub.total,
257
+ schools: 1,
258
+ schoolsSubtotal: hub.total,
159
259
  // A hub is already priced on its schools, so it has no trust discount.
160
260
  trustDiscountApplied: 0,
161
261
  trustDiscountRate: 0,
@@ -165,6 +265,21 @@ function hubQuote(schools, pricing, config = exports.DEFAULT_PRICING_CONFIG) {
165
265
  total: overridden ? pricing?.quoteOverride : negotiated,
166
266
  };
167
267
  }
268
+ /**
269
+ * Price an institute on what it actually has and what was agreed with it.
270
+ *
271
+ * The products come from `resolveProducts` rather than the raw flags, so a trust
272
+ * is priced on the union of its schools' products the same way it is gated on
273
+ * them, and it is a trust — not any school with a number against it — that earns
274
+ * the trust discount. A year group with no placements agreed is a year group not on work
275
+ * experience — except where the institute has work experience and neither year
276
+ * group has been filled in, which is a quote waiting to be finished rather than
277
+ * a school not taking the product, so Y10 is charged at zero to say so.
278
+ *
279
+ * @param {object} input the institute's products, roll and agreed terms.
280
+ * @param {object} [config] the figures to price with. Defaults to the 2026 sheet.
281
+ * @return {object} the quote, ready to render.
282
+ */
168
283
  function instituteQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
169
284
  const pricing = input.pricing;
170
285
  if (input.products.isHub) {
@@ -188,20 +303,38 @@ function instituteQuote(input, config = exports.DEFAULT_PRICING_CONFIG) {
188
303
  quoteOverride: pricing?.quoteOverride,
189
304
  }, config);
190
305
  }
306
+ /**
307
+ * Reduce a quote to what the customer sees: the fees, and one discount figure.
308
+ *
309
+ * The base fee isn't itemised to customers, so it is folded into the first fee
310
+ * they are shown — and where there is nothing to fold it into, it stands alone
311
+ * as the platform fee it is.
312
+ *
313
+ * A trust's lines are one school's, and what a trust pays is every school's, so
314
+ * the fees are multiplied out here: the customer is shown what their account
315
+ * costs, not what one of their schools would have cost on its own.
316
+ *
317
+ * @param {object} quote the priced institute.
318
+ * @return {object} the snapshot to store on the institute.
319
+ */
191
320
  function quoteSnapshot(quote) {
192
321
  const itemised = quote.lines.filter((l) => l.key !== "base");
193
322
  const base = quote.lines.find((l) => l.key === "base")?.amount || 0;
323
+ const schools = Math.max(quote.schools || 1, 1);
194
324
  const lines = itemised.length ?
195
325
  itemised.map((line, index) => ({
196
326
  key: line.key,
197
327
  label: line.label,
198
- amount: index === 0 ? line.amount + base : line.amount,
328
+ amount: (index === 0 ? line.amount + base : line.amount) * schools,
199
329
  })) :
200
- [{ key: "base", label: "Platform fee", amount: base }];
330
+ [{ key: "base", label: "Platform fee", amount: base * schools }];
201
331
  const subtotal = sum(lines.map((l) => l.amount));
202
332
  return {
203
333
  lines,
204
334
  subtotal,
335
+ // The customer is shown the fees and one discount, so whatever separates
336
+ // the two — the whole-quote discounts, an agreed price below them — is
337
+ // that one figure, and a total above the fees is flagged instead.
205
338
  discountTotal: Math.max(subtotal - quote.total, 0),
206
339
  minimum: quote.total > subtotal,
207
340
  total: quote.total,
@@ -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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"}