|
1 | 1 | import type { ImportEnricher } from "@scouterna/scoutin-plugin-api/backend"; |
2 | 2 | import { type } from "arktype"; |
| 3 | +import { firstAttendingDate } from "../specialNeeds/attendance.ts"; |
3 | 4 |
|
4 | 5 | // Static per-event config passed via the data source's `enrichWith` entry |
5 | 6 | // (object form): a flat map of metadata field name -> Scoutnet registration |
6 | 7 | // question ID. Question IDs (and which questions exist at all) are specific |
7 | 8 | // to a project's registration form, so they're configured per event rather |
8 | | -// than hardcoded here. This enricher has no domain knowledge of what the |
9 | | -// fields mean (diet vs medical vs absence, checkbox vs multiselect vs text) - |
10 | | -// it just copies each configured question's raw answer under its field name. |
11 | | -// Grouping/interpreting by field name happens in the jamboree26:specialNeeds |
12 | | -// step, which is the code contract these field names must match. |
| 9 | +// than hardcoded here. Beyond the single computed `firstAttendingDay` field |
| 10 | +// (below), this enricher has no domain knowledge of what the fields mean (diet |
| 11 | +// vs medical vs absence, checkbox vs multiselect vs text) - it just copies each |
| 12 | +// configured question's raw answer under its field name. Grouping/interpreting |
| 13 | +// by field name happens in the jamboree26:specialNeeds step, which is the code |
| 14 | +// contract these field names must match. |
| 15 | +// |
| 16 | +// `variant` is the one bit of domain config this enricher takes: it selects the |
| 17 | +// attendance model (see ../specialNeeds/attendance.ts) used to derive the single |
| 18 | +// computed `firstAttendingDay` field (an ISO yyyy-mm-dd string). It mirrors the |
| 19 | +// jamboree26:specialNeeds step's own `variant` input - `adult` for the funktionär |
| 20 | +// form's period-gate/absence model, `child` for the "medföljande barn" form's |
| 21 | +// positive attend-list. Omit it and no firstAttendingDay is written (the raw |
| 22 | +// answer fields are still copied as before), so sources with no attendance data |
| 23 | +// (e.g. groups) stay unaffected. |
13 | 24 | const Options = type({ |
14 | 25 | "questions?": type.Record("string", "string"), |
| 26 | + "variant?": "'adult' | 'child'", |
15 | 27 | }); |
16 | 28 |
|
17 | 29 | // Structural subset of the raw Scoutnet member record this enricher reads. |
@@ -42,6 +54,8 @@ export const specialNeeds: ImportEnricher = { |
42 | 54 | const options = Options(ctx.options ?? {}); |
43 | 55 | const questionMap = |
44 | 56 | options instanceof type.errors ? undefined : options.questions; |
| 57 | + const variant = |
| 58 | + options instanceof type.errors ? undefined : options.variant; |
45 | 59 |
|
46 | 60 | if (!questionMap || Object.keys(questionMap).length === 0) { |
47 | 61 | // No question IDs configured for this event - nothing to enrich, and |
@@ -97,6 +111,20 @@ export const specialNeeds: ImportEnricher = { |
97 | 111 | result[fieldName] = rawAnswer; |
98 | 112 | } |
99 | 113 | } |
| 114 | + |
| 115 | + // Derive the single computed convenience field: the first day this person is |
| 116 | + // actually attending, as an ISO yyyy-mm-dd string, for the roster export's |
| 117 | + // "first attending day" column. Uses the just-resolved labels in `result` |
| 118 | + // (periodsAttending/absence* for adults, attendanceDays for children) so it |
| 119 | + // needs no separate question config or provider lookup. Only written when a |
| 120 | + // `variant` is configured and a first day can be determined - otherwise the |
| 121 | + // key is omitted rather than set to null, keeping it out of the export for |
| 122 | + // sources with no attendance data. |
| 123 | + if (variant) { |
| 124 | + const firstDay = firstAttendingDate(result, variant); |
| 125 | + if (firstDay != null) result.firstAttendingDay = firstDay; |
| 126 | + } |
| 127 | + |
100 | 128 | return result; |
101 | 129 | }, |
102 | 130 | }; |
0 commit comments