@pdtf/schemas 3.6.0-40 → 3.6.0-41
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/.claude/plans/not-seeing-associated-costs.md +99 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/schemas/v3/combined.json +3 -0
- package/src/schemas/v3/overlays/extensions/lc.json +12 -1
- package/src/schemas/v3/overlays/extensions/sc.json +24 -2
- package/src/schemas/v3/overlays/sef25.json +78 -27
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Plan: associatedCost amount field not appearing for water/drainage
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
**Reported symptom**: even with the relevant SEF25 overlay extension loaded, the `amount` input does not appear under the water and drainage *associated costs* sections when a payment frequency like "Per month" or "Per year" is selected.
|
|
6
|
+
|
|
7
|
+
**Are the fields correctly ref'd?** Yes — the `sef25Ref` / `ntsRef` codes line up between base and overlay:
|
|
8
|
+
|
|
9
|
+
| Field path | base `combined.json` | `sef25.json` | `extensions/sc.json` |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| water `associatedCost` | `sef25Ref U1.1` | `U1.1` | `ntsRef U1.1` |
|
|
12
|
+
| water `frequency` | `sef25Ref U1.1.2` | `U1.1.2` | `ntsRef U1.1.2` |
|
|
13
|
+
| water `amount` (in oneOf branch 1) | `sef25Ref U1.1.1` | `U1.1.1` | `ntsRef U1.1.1` |
|
|
14
|
+
| drainage `associatedCost` | `sef25Ref U1.2` | `U1.2` | `ntsRef U1.2` |
|
|
15
|
+
| drainage `frequency` | `sef25Ref U1.2.2` | `U1.2.2` | `ntsRef U1.2.2` |
|
|
16
|
+
| drainage `amount` | `sef25Ref U1.2.1` | `U1.2.1` | `ntsRef U1.2.1` |
|
|
17
|
+
|
|
18
|
+
There are no `$ref` indirections involved — these are inline definitions, and they all match.
|
|
19
|
+
|
|
20
|
+
## Root cause — missing `discriminator` keyword
|
|
21
|
+
|
|
22
|
+
The three `associatedCost` blocks (leased solar `S1.1`, mains water `U1.1`, mains foul drainage `U1.2`) follow the project's standard *discriminated oneOf* pattern: a child enum field selects which `oneOf` branch is active. Branch 0 (`Not applicable`) leaves `amount` out; branch 1 (`Per month`/`Per year`) requires `amount`.
|
|
23
|
+
|
|
24
|
+
In commit [`188809f`](../../../) ("use frequency as discriminator for associatedCost") this pattern was correctly modelled with both `oneOf` **and** `"discriminator": { "propertyName": "frequency" }`. The block was later flattened, then re‑introduced in commit [`6317499`](../../../) ("re-introduce frequency discriminator on associatedCost (lenient)"). Despite the title, that commit added the `oneOf` branches but **did not put the `discriminator` keyword back**. The current state of all three blocks is therefore `oneOf` without a discriminator hint.
|
|
25
|
+
|
|
26
|
+
Every other oneOf in `combined.json` carries an explicit `discriminator` (`grep -c '"discriminator"'` on the file confirms this is the universal convention here). Both AJV (configured with `discriminator: true` in [index.js:8](../../index.js#L8)) and the schema‑driven UI generator that consumes the merged schema rely on it to know which oneOf branch is active for a given form value. Without it, picking `Per month` does not switch the active branch, so the `amount` property never becomes visible.
|
|
27
|
+
|
|
28
|
+
The overlay files (`sef25.json`, `extensions/sc.json`) themselves do not need a discriminator added — the overlay extractor at [src/utils/extractOverlay.js:143-167](../../src/utils/extractOverlay.js#L143) already propagates `discriminator` from base into the generated overlays, so re‑running it after the base fix will pick the discriminator up automatically.
|
|
29
|
+
|
|
30
|
+
## Fix
|
|
31
|
+
|
|
32
|
+
Three identical edits to **`src/schemas/v3/combined.json`** — add the missing `discriminator` to each `associatedCost` block. After the existing `"properties": { "frequency": { ... } }` line and before `"oneOf": [ ... ]`, insert:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
"discriminator": { "propertyName": "frequency" },
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Locations
|
|
39
|
+
|
|
40
|
+
1. Leased solar panel `associatedCost` (`sef25Ref: "S1.1"`) — [src/schemas/v3/combined.json:21605](../../src/schemas/v3/combined.json#L21605) (insert before line ~21618 `oneOf`)
|
|
41
|
+
2. Water `mainsWater` → `oneOf[0]` (No / private supply) → `associatedCost` (`U1.1`) — [src/schemas/v3/combined.json:22425](../../src/schemas/v3/combined.json#L22425) (insert before line 22438 `oneOf`)
|
|
42
|
+
3. Drainage `mainsFoulDrainage` → `oneOf[2]` (off-mains) → `associatedCost` (`U1.2`) — [src/schemas/v3/combined.json:23547](../../src/schemas/v3/combined.json#L23547) (insert before line 23560 `oneOf`)
|
|
43
|
+
|
|
44
|
+
Note the leased-solar block has the same bug. The user only mentioned water and drainage, but since the structure is identical and the fix is one line each, fixing all three keeps the codebase consistent and pre‑empts the same report for solar panels later. (Confirm with user — see Open Questions.)
|
|
45
|
+
|
|
46
|
+
### Regenerate
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run extract-overlays # regenerates pdtf-transaction.json + sef25.json etc.
|
|
50
|
+
npm run extract-extension-overlays # regenerates sc.json and other extension overlays
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`extractOverlay.js` already detects `element.discriminator` and writes both the discriminator and the per‑branch enum into the generated overlays, so the regenerated `pdtf-transaction.json`, `overlays/sef25.json`, and `overlays/extensions/sc.json` will all carry the discriminator without manual edits.
|
|
54
|
+
|
|
55
|
+
### Version bump
|
|
56
|
+
|
|
57
|
+
Bump `package.json` from `3.6.0-40` to `3.6.0-41`. This is a non‑breaking schema change (existing payloads still validate; only the UI hint is restored).
|
|
58
|
+
|
|
59
|
+
## Verification
|
|
60
|
+
|
|
61
|
+
1. **Validate the schema fix locally:**
|
|
62
|
+
```bash
|
|
63
|
+
npm test
|
|
64
|
+
```
|
|
65
|
+
The existing test suite must still pass. The change is purely additive (adding a discriminator keyword on top of an existing oneOf), so no current test is expected to break.
|
|
66
|
+
|
|
67
|
+
2. **Spot‑check with a small AJV/UI smoke test (optional but recommended):**
|
|
68
|
+
```js
|
|
69
|
+
const { getTransactionSchema } = require("./index");
|
|
70
|
+
const schema = getTransactionSchema(
|
|
71
|
+
"https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json",
|
|
72
|
+
["nts2025", "sc"] // or ["nts2025", "sef25"-style stack you actually use
|
|
73
|
+
);
|
|
74
|
+
// Walk to schema.properties.propertyPack.properties.waterAndDrainage.properties.water.properties.mainsWater.oneOf[0].properties.associatedCost
|
|
75
|
+
// and confirm BOTH of these are present:
|
|
76
|
+
// .discriminator === { propertyName: "frequency" }
|
|
77
|
+
// .oneOf[1].properties.amount.type === "number"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
3. **End-to-end check in the consuming UI:** load the form with the SEF25 / `sc` extension stack, pick `Per month` under water and under drainage, and confirm the `amount (£)` input appears. Repeat for `Per year` (should appear) and `Not applicable` (should hide).
|
|
81
|
+
|
|
82
|
+
4. **Confirm overlays were regenerated cleanly:**
|
|
83
|
+
```bash
|
|
84
|
+
git diff src/schemas/v3/pdtf-transaction.json src/schemas/v3/overlays/sef25.json src/schemas/v3/overlays/extensions/sc.json
|
|
85
|
+
```
|
|
86
|
+
The diff should show `discriminator: { propertyName: "frequency" }` added in each of those three generated files alongside the existing oneOf for water/drainage (and solar, if included).
|
|
87
|
+
|
|
88
|
+
## Critical files
|
|
89
|
+
|
|
90
|
+
- `src/schemas/v3/combined.json` — three edits, the source of truth
|
|
91
|
+
- `src/schemas/v3/pdtf-transaction.json` — regenerated, do not hand-edit
|
|
92
|
+
- `src/schemas/v3/overlays/sef25.json` — regenerated
|
|
93
|
+
- `src/schemas/v3/overlays/extensions/sc.json` — regenerated
|
|
94
|
+
- `src/utils/extractOverlay.js` — read-only reference; already handles discriminator propagation
|
|
95
|
+
- `package.json` — version bump
|
|
96
|
+
|
|
97
|
+
## Open questions
|
|
98
|
+
|
|
99
|
+
- Include the leased solar panel `S1.1` block in the same fix? (Identical bug, one extra one-line edit, keeps the codebase consistent — recommended yes.)
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ The Property Data Trust Framework (PDTF) Schemas provide standardized JSON Schem
|
|
|
7
7
|
|
|
8
8
|
## Project Goals & Status
|
|
9
9
|
|
|
10
|
-
**Current Version:** 3.5.0 (3.6.0-
|
|
10
|
+
**Current Version:** 3.5.0 (3.6.0-41 available as a pre-release on branch/package-tag `next`)
|
|
11
11
|
|
|
12
12
|
This schema framework aims to support the [Home Buying and Selling Group](https://homebuyingandsellinggroup.co.uk) 'Property Pack' initiative, encompassing all requirements starting with the Buyers and Sellers Property Information set ([BASPI v4.0](https://homebuyingandsellinggroup.co.uk/baspi/)).
|
|
13
13
|
|
package/package.json
CHANGED
|
@@ -21610,6 +21610,7 @@
|
|
|
21610
21610
|
"enum": ["Per month", "Per year", "Not applicable"]
|
|
21611
21611
|
}
|
|
21612
21612
|
},
|
|
21613
|
+
"discriminator": { "propertyName": "frequency" },
|
|
21613
21614
|
"oneOf": [
|
|
21614
21615
|
{
|
|
21615
21616
|
"properties": {
|
|
@@ -22435,6 +22436,7 @@
|
|
|
22435
22436
|
"enum": ["Per month", "Per year", "Not applicable"]
|
|
22436
22437
|
}
|
|
22437
22438
|
},
|
|
22439
|
+
"discriminator": { "propertyName": "frequency" },
|
|
22438
22440
|
"oneOf": [
|
|
22439
22441
|
{
|
|
22440
22442
|
"properties": {
|
|
@@ -23557,6 +23559,7 @@
|
|
|
23557
23559
|
"enum": ["Per month", "Per year", "Not applicable"]
|
|
23558
23560
|
}
|
|
23559
23561
|
},
|
|
23562
|
+
"discriminator": { "propertyName": "frequency" },
|
|
23560
23563
|
"oneOf": [
|
|
23561
23564
|
{
|
|
23562
23565
|
"properties": {
|
|
@@ -19,6 +19,9 @@
|
|
|
19
19
|
"required": [
|
|
20
20
|
"frequency"
|
|
21
21
|
],
|
|
22
|
+
"discriminator": {
|
|
23
|
+
"propertyName": "frequency"
|
|
24
|
+
},
|
|
22
25
|
"properties": {
|
|
23
26
|
"frequency": {
|
|
24
27
|
"ntsRef": "S1.1.2",
|
|
@@ -26,7 +29,15 @@
|
|
|
26
29
|
}
|
|
27
30
|
},
|
|
28
31
|
"oneOf": [
|
|
29
|
-
{
|
|
32
|
+
{
|
|
33
|
+
"properties": {
|
|
34
|
+
"frequency": {
|
|
35
|
+
"enum": [
|
|
36
|
+
"Not applicable"
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
30
41
|
{
|
|
31
42
|
"properties": {
|
|
32
43
|
"amount": {
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
"required": [
|
|
16
16
|
"frequency"
|
|
17
17
|
],
|
|
18
|
+
"discriminator": {
|
|
19
|
+
"propertyName": "frequency"
|
|
20
|
+
},
|
|
18
21
|
"properties": {
|
|
19
22
|
"frequency": {
|
|
20
23
|
"ntsRef": "U1.1.2",
|
|
@@ -22,7 +25,15 @@
|
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
27
|
"oneOf": [
|
|
25
|
-
{
|
|
28
|
+
{
|
|
29
|
+
"properties": {
|
|
30
|
+
"frequency": {
|
|
31
|
+
"enum": [
|
|
32
|
+
"Not applicable"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
},
|
|
26
37
|
{
|
|
27
38
|
"properties": {
|
|
28
39
|
"amount": {
|
|
@@ -62,6 +73,9 @@
|
|
|
62
73
|
"required": [
|
|
63
74
|
"frequency"
|
|
64
75
|
],
|
|
76
|
+
"discriminator": {
|
|
77
|
+
"propertyName": "frequency"
|
|
78
|
+
},
|
|
65
79
|
"properties": {
|
|
66
80
|
"frequency": {
|
|
67
81
|
"ntsRef": "U1.2.2",
|
|
@@ -69,7 +83,15 @@
|
|
|
69
83
|
}
|
|
70
84
|
},
|
|
71
85
|
"oneOf": [
|
|
72
|
-
{
|
|
86
|
+
{
|
|
87
|
+
"properties": {
|
|
88
|
+
"frequency": {
|
|
89
|
+
"enum": [
|
|
90
|
+
"Not applicable"
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
},
|
|
73
95
|
{
|
|
74
96
|
"properties": {
|
|
75
97
|
"amount": {
|
|
@@ -350,24 +350,41 @@
|
|
|
350
350
|
},
|
|
351
351
|
"associatedCost": {
|
|
352
352
|
"sef25Ref": "S1.1",
|
|
353
|
-
"
|
|
354
|
-
"frequency"
|
|
355
|
-
],
|
|
356
|
-
"properties": {
|
|
357
|
-
"frequency": {
|
|
358
|
-
"sef25Ref": "S1.1.2"
|
|
359
|
-
}
|
|
353
|
+
"discriminator": {
|
|
354
|
+
"propertyName": "frequency"
|
|
360
355
|
},
|
|
361
356
|
"oneOf": [
|
|
362
|
-
null,
|
|
363
357
|
{
|
|
364
358
|
"properties": {
|
|
359
|
+
"frequency": {
|
|
360
|
+
"enum": [
|
|
361
|
+
"Not applicable"
|
|
362
|
+
]
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"properties": {
|
|
368
|
+
"frequency": {
|
|
369
|
+
"enum": [
|
|
370
|
+
"Per month",
|
|
371
|
+
"Per year"
|
|
372
|
+
]
|
|
373
|
+
},
|
|
365
374
|
"amount": {
|
|
366
375
|
"sef25Ref": "S1.1.1"
|
|
367
376
|
}
|
|
368
377
|
}
|
|
369
378
|
}
|
|
370
|
-
]
|
|
379
|
+
],
|
|
380
|
+
"required": [
|
|
381
|
+
"frequency"
|
|
382
|
+
],
|
|
383
|
+
"properties": {
|
|
384
|
+
"frequency": {
|
|
385
|
+
"sef25Ref": "S1.1.2"
|
|
386
|
+
}
|
|
387
|
+
}
|
|
371
388
|
}
|
|
372
389
|
}
|
|
373
390
|
}
|
|
@@ -401,24 +418,41 @@
|
|
|
401
418
|
"properties": {
|
|
402
419
|
"associatedCost": {
|
|
403
420
|
"sef25Ref": "U1.1",
|
|
404
|
-
"
|
|
405
|
-
"frequency"
|
|
406
|
-
],
|
|
407
|
-
"properties": {
|
|
408
|
-
"frequency": {
|
|
409
|
-
"sef25Ref": "U1.1.2"
|
|
410
|
-
}
|
|
421
|
+
"discriminator": {
|
|
422
|
+
"propertyName": "frequency"
|
|
411
423
|
},
|
|
412
424
|
"oneOf": [
|
|
413
|
-
null,
|
|
414
425
|
{
|
|
415
426
|
"properties": {
|
|
427
|
+
"frequency": {
|
|
428
|
+
"enum": [
|
|
429
|
+
"Not applicable"
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
"properties": {
|
|
436
|
+
"frequency": {
|
|
437
|
+
"enum": [
|
|
438
|
+
"Per month",
|
|
439
|
+
"Per year"
|
|
440
|
+
]
|
|
441
|
+
},
|
|
416
442
|
"amount": {
|
|
417
443
|
"sef25Ref": "U1.1.1"
|
|
418
444
|
}
|
|
419
445
|
}
|
|
420
446
|
}
|
|
421
|
-
]
|
|
447
|
+
],
|
|
448
|
+
"required": [
|
|
449
|
+
"frequency"
|
|
450
|
+
],
|
|
451
|
+
"properties": {
|
|
452
|
+
"frequency": {
|
|
453
|
+
"sef25Ref": "U1.1.2"
|
|
454
|
+
}
|
|
455
|
+
}
|
|
422
456
|
}
|
|
423
457
|
}
|
|
424
458
|
}
|
|
@@ -439,24 +473,41 @@
|
|
|
439
473
|
"properties": {
|
|
440
474
|
"associatedCost": {
|
|
441
475
|
"sef25Ref": "U1.2",
|
|
442
|
-
"
|
|
443
|
-
"frequency"
|
|
444
|
-
],
|
|
445
|
-
"properties": {
|
|
446
|
-
"frequency": {
|
|
447
|
-
"sef25Ref": "U1.2.2"
|
|
448
|
-
}
|
|
476
|
+
"discriminator": {
|
|
477
|
+
"propertyName": "frequency"
|
|
449
478
|
},
|
|
450
479
|
"oneOf": [
|
|
451
|
-
null,
|
|
452
480
|
{
|
|
453
481
|
"properties": {
|
|
482
|
+
"frequency": {
|
|
483
|
+
"enum": [
|
|
484
|
+
"Not applicable"
|
|
485
|
+
]
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
"properties": {
|
|
491
|
+
"frequency": {
|
|
492
|
+
"enum": [
|
|
493
|
+
"Per month",
|
|
494
|
+
"Per year"
|
|
495
|
+
]
|
|
496
|
+
},
|
|
454
497
|
"amount": {
|
|
455
498
|
"sef25Ref": "U1.2.1"
|
|
456
499
|
}
|
|
457
500
|
}
|
|
458
501
|
}
|
|
459
|
-
]
|
|
502
|
+
],
|
|
503
|
+
"required": [
|
|
504
|
+
"frequency"
|
|
505
|
+
],
|
|
506
|
+
"properties": {
|
|
507
|
+
"frequency": {
|
|
508
|
+
"sef25Ref": "U1.2.2"
|
|
509
|
+
}
|
|
510
|
+
}
|
|
460
511
|
}
|
|
461
512
|
}
|
|
462
513
|
}
|