@pdtf/schemas 3.6.0-17 → 3.6.0-19

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.
@@ -49,7 +49,8 @@
49
49
  "Bash(claude --version)",
50
50
  "Bash(gh pr list --head ta6ed6 --json number,title,url)",
51
51
  "Bash(gh pr:*)",
52
- "Bash(sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n)"
52
+ "Bash(sort -t'.' -k1,1n -k2,2n -k3,3n -k4,4n)",
53
+ "Bash(wc -l /Users/ed/Code/schemas/src/schemas/v3/combined.json /Users/ed/Code/schemas/src/schemas/v3/overlays/*.json)"
53
54
  ],
54
55
  "deny": []
55
56
  }
@@ -0,0 +1,146 @@
1
+ # SEF25 Extension Overlays — Front-End UI Spec
2
+
3
+ ## Overview
4
+
5
+ Three new extension overlays add follow-up questions to existing form sections. Each overlay is loaded by passing its key to `getTransactionSchema(schemaId, overlays)`.
6
+
7
+ | Overlay Key | Name | Section | Fields Added |
8
+ |-------------|------|---------|-------------|
9
+ | `sc` | Supply Costs | Water & Drainage | 2 cost fields (private water, private sewerage) |
10
+ | `pc` | Parking Permit Cost | Parking | 1 frequency field |
11
+ | `ph` | Property Hazards | Specialist Issues | 4 Yes/No + details fields |
12
+
13
+ All fields use `sef25Ref` for reference codes.
14
+
15
+ ---
16
+
17
+ ## 1. Supply Costs (`sc`)
18
+
19
+ ### 1a. Private Water Cost
20
+
21
+ **Trigger:** Show when `propertyPack.waterAndDrainage.water.mainsWater.yesNo` = `"No"`
22
+
23
+ **Path:** `propertyPack.waterAndDrainage.water.mainsWater.associatedCost`
24
+
25
+ **UI:** Render alongside the existing "How is water supplied?" details field.
26
+
27
+ | Field | Path (relative) | Type | Validation | UI Element |
28
+ |-------|-----------------|------|------------|------------|
29
+ | Cost (£) | `associatedCost.amount` | `number` | Required | Numeric input |
30
+ | Payment frequency | `associatedCost.frequency` | `string` | Required, enum | Dropdown |
31
+
32
+ **Frequency enum values:** `"Per month"`, `"Per year"`
33
+
34
+ **Ref:** `U1.1` (amount: `U1.1.1`, frequency: `U1.1.2`)
35
+
36
+ ### 1b. Private Sewerage Cost
37
+
38
+ **Trigger:** Show when `propertyPack.waterAndDrainage.drainage.mainsFoulDrainage.yesNo` = `"No"` or `"Not known"`
39
+
40
+ **Path:** `propertyPack.waterAndDrainage.drainage.mainsFoulDrainage.associatedCost`
41
+
42
+ **UI:** Render alongside the existing off-mains drainage system questions.
43
+
44
+ | Field | Path (relative) | Type | Validation | UI Element |
45
+ |-------|-----------------|------|------------|------------|
46
+ | Cost (£) | `associatedCost.amount` | `number` | Required | Numeric input |
47
+ | Payment frequency | `associatedCost.frequency` | `string` | Required, enum | Dropdown |
48
+
49
+ **Frequency enum values:** `"Per month"`, `"Per year"`
50
+
51
+ **Ref:** `U1.2` (amount: `U1.2.1`, frequency: `U1.2.2`)
52
+
53
+ ---
54
+
55
+ ## 2. Parking Permit Cost (`pc`)
56
+
57
+ **Trigger:** Show when `propertyPack.parking.controlledParking.yesNo` = `"Yes"`
58
+
59
+ **Path:** `propertyPack.parking.controlledParking.costOfPermitFrequency`
60
+
61
+ **UI:** Render alongside the existing cost of permit field (previously titled "Annual cost of permit (£)", now retitled to "Cost of permit (£)"). The frequency dropdown clarifies whether the cost amount is monthly or annual.
62
+
63
+ | Field | Path (relative) | Type | Validation | UI Element |
64
+ |-------|-----------------|------|------------|------------|
65
+ | Payment frequency | `costOfPermitFrequency` | `string` | Enum | Dropdown |
66
+
67
+ **Frequency enum values:** `"Per month"`, `"Per year"`
68
+
69
+ **Note:** The existing `annualCostOfPermit` numeric field remains unchanged. The new frequency field sits beside it to indicate whether the entered amount is per month or per year.
70
+
71
+ **Ref:** `P1.1`
72
+
73
+ ---
74
+
75
+ ## 3. Property Hazards (`ph`)
76
+
77
+ **Trigger:** Always shown (no conditional trigger — these are standalone questions within Specialist Issues).
78
+
79
+ **Path prefix:** `propertyPack.specialistIssues`
80
+
81
+ All 4 fields follow the same pattern:
82
+
83
+ - **Initial question:** Yes/No radio/toggle
84
+ - **If "Yes":** Show a required free-text "Give details" field
85
+
86
+ ### Fields
87
+
88
+ | Property | Title | sef25Ref |
89
+ |----------|-------|----------|
90
+ | `wellsDitchesShaft` | Are there any wells, ditches, or shafts at the property? | H1.1 |
91
+ | `damagedOrExposedElectrics` | Are there any damaged or exposed electrics at the property? | H1.2 |
92
+ | `damageToFlooringOrStaircases` | Is there any damage to flooring and/or staircases? | H1.3 |
93
+ | `knownAreasInPoorCondition` | Are there any known areas in poor condition (internal or external)? | H1.4 |
94
+
95
+ ### Data shape per field
96
+
97
+ ```json
98
+ // When "No":
99
+ { "yesNo": "No" }
100
+
101
+ // When "Yes":
102
+ { "yesNo": "Yes", "details": "Free text description..." }
103
+ ```
104
+
105
+ ### Validation
106
+
107
+ - `yesNo` is required (enum: `["Yes", "No"]`)
108
+ - When `yesNo` = `"Yes"`, `details` is required (string, minLength: 1)
109
+ - When `yesNo` = `"No"`, `details` should not be shown or submitted
110
+
111
+ ### UI pattern
112
+
113
+ These follow the identical pattern to existing specialist issues (dry rot, asbestos, subsidence, health & safety). Render them the same way — group them under "Hazards and Known Issues" within the Specialist Issues section.
114
+
115
+ ---
116
+
117
+ ## Loading the Extensions
118
+
119
+ ```js
120
+ import { getTransactionSchema, getValidator } from "@pdtf/schemas";
121
+
122
+ const schemaId = "https://trust.propdata.org.uk/schemas/v3/pdtf-transaction.json";
123
+
124
+ // Load with one or more SEF25 extensions
125
+ const schema = getTransactionSchema(schemaId, ["sc", "pc", "ph"]);
126
+
127
+ // Or combine with other overlays
128
+ const schema = getTransactionSchema(schemaId, ["baspiV5", "sc", "pc", "ph"]);
129
+
130
+ // Validate data against the merged schema
131
+ const validator = getValidator(schemaId, ["sc", "pc", "ph"]);
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Summary of Trigger Conditions
137
+
138
+ | Field | Visible when... |
139
+ |-------|----------------|
140
+ | Water cost | `mainsWater.yesNo` = `"No"` |
141
+ | Sewerage cost | `mainsFoulDrainage.yesNo` = `"No"` or `"Not known"` |
142
+ | Parking permit frequency | `controlledParking.yesNo` = `"Yes"` |
143
+ | Wells/ditches/shaft | Always (within Specialist Issues) |
144
+ | Damaged electrics | Always (within Specialist Issues) |
145
+ | Flooring/staircase damage | Always (within Specialist Issues) |
146
+ | Areas in poor condition | Always (within Specialist Issues) |
package/index.js CHANGED
@@ -52,6 +52,11 @@ const extensionOverlays = {
52
52
 
53
53
  // Transaction Extensions
54
54
  oc: require("./src/schemas/v3/overlays/extensions/oc.json"),
55
+
56
+ // SEF25 Extensions
57
+ sc: require("./src/schemas/v3/overlays/extensions/sc.json"),
58
+ pc: require("./src/schemas/v3/overlays/extensions/pc.json"),
59
+ ph: require("./src/schemas/v3/overlays/extensions/ph.json"),
55
60
  };
56
61
 
57
62
  const overlaysMap = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdtf/schemas",
3
- "version": "3.6.0-17",
3
+ "version": "3.6.0-19",
4
4
  "description": "Property Data Trust Framework Schemas and Utilities",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -6243,6 +6243,13 @@
6243
6243
  "ta7ed5Title": "Who collects the ground rent?",
6244
6244
  "type": "string",
6245
6245
  "enum": [
6246
+ "Landlord",
6247
+ "Management Company",
6248
+ "Managing Agent",
6249
+ "Not applicable",
6250
+ "Other"
6251
+ ],
6252
+ "lpe1Enum": [
6246
6253
  "Landlord",
6247
6254
  "Management Company",
6248
6255
  "Managing Agent",
@@ -6250,7 +6257,7 @@
6250
6257
  ],
6251
6258
  "ta7ed5Enum": [
6252
6259
  "Landlord",
6253
- "Management company",
6260
+ "Management Company",
6254
6261
  "Other"
6255
6262
  ]
6256
6263
  }
@@ -6267,10 +6274,6 @@
6267
6274
  "Management Company",
6268
6275
  "Managing Agent",
6269
6276
  "Not applicable"
6270
- ],
6271
- "ta7ed5Enum": [
6272
- "Landlord",
6273
- "Management company"
6274
6277
  ]
6275
6278
  }
6276
6279
  }
@@ -6278,8 +6281,7 @@
6278
6281
  {
6279
6282
  "properties": {
6280
6283
  "collector": {
6281
- "enum": ["Other"],
6282
- "ta7ed5Enum": ["Other"]
6284
+ "enum": ["Other"]
6283
6285
  },
6284
6286
  "otherCollector": {
6285
6287
  "ta7ed5Ref": "4.3.3",
@@ -6317,6 +6319,16 @@
6317
6319
  "title": "Who collects the building insurance premiums?",
6318
6320
  "type": "string",
6319
6321
  "enum": [
6322
+ "Freeholder",
6323
+ "Landlord",
6324
+ "Management Company",
6325
+ "Managing Agent",
6326
+ "Head Leaseholder",
6327
+ "Seller",
6328
+ "Not applicable",
6329
+ "Other"
6330
+ ],
6331
+ "lpe1Enum": [
6320
6332
  "Landlord",
6321
6333
  "Management Company",
6322
6334
  "Managing Agent",
@@ -6325,8 +6337,8 @@
6325
6337
  "ta7ed5Enum": [
6326
6338
  "Freeholder",
6327
6339
  "Landlord",
6328
- "Management company",
6329
- "Head leaseholder",
6340
+ "Management Company",
6341
+ "Head Leaseholder",
6330
6342
  "Seller",
6331
6343
  "Other"
6332
6344
  ]
@@ -6340,17 +6352,13 @@
6340
6352
  "properties": {
6341
6353
  "collector": {
6342
6354
  "enum": [
6355
+ "Freeholder",
6343
6356
  "Landlord",
6344
6357
  "Management Company",
6345
6358
  "Managing Agent",
6359
+ "Head Leaseholder",
6360
+ "Seller",
6346
6361
  "Not applicable"
6347
- ],
6348
- "ta7ed5Enum": [
6349
- "Freeholder",
6350
- "Landlord",
6351
- "Management company",
6352
- "Head leaseholder",
6353
- "Seller"
6354
6362
  ]
6355
6363
  }
6356
6364
  }
@@ -6358,8 +6366,7 @@
6358
6366
  {
6359
6367
  "properties": {
6360
6368
  "collector": {
6361
- "enum": ["Other"],
6362
- "ta7ed5Enum": ["Other"]
6369
+ "enum": ["Other"]
6363
6370
  },
6364
6371
  "otherCollector": {
6365
6372
  "ta7ed5Ref": "4.2.3",
@@ -10355,8 +10362,14 @@
10355
10362
  },
10356
10363
  "annualCostOfPermit": {
10357
10364
  "baspi5Ref": "A1.6.0.2.2",
10358
- "title": "Annual cost of permit (£)",
10365
+ "title": "Cost of permit (£)",
10359
10366
  "type": "number"
10367
+ },
10368
+ "costOfPermitFrequency": {
10369
+ "sef25Ref": "P1.1",
10370
+ "title": "Payment frequency",
10371
+ "type": "string",
10372
+ "enum": ["Per month", "Per year"]
10360
10373
  }
10361
10374
  },
10362
10375
  "baspi5Required": ["annualCostOfPermit"]
@@ -16001,6 +16014,166 @@
16001
16014
  "ntsl2Required": ["details"]
16002
16015
  }
16003
16016
  ]
16017
+ },
16018
+ "wellsDitchesShaft": {
16019
+ "sef25Ref": "H1.1",
16020
+ "title": "Are there any wells, ditches, or shafts at the property?",
16021
+ "type": "object",
16022
+ "sef25Required": ["yesNo"],
16023
+ "properties": {
16024
+ "yesNo": {
16025
+ "sef25Ref": "H1.1.1",
16026
+ "type": "string",
16027
+ "title": "",
16028
+ "enum": ["Yes", "No"]
16029
+ }
16030
+ },
16031
+ "discriminator": {
16032
+ "propertyName": "yesNo"
16033
+ },
16034
+ "oneOf": [
16035
+ {
16036
+ "properties": {
16037
+ "yesNo": {
16038
+ "enum": ["No"]
16039
+ }
16040
+ }
16041
+ },
16042
+ {
16043
+ "sef25Required": ["details"],
16044
+ "properties": {
16045
+ "yesNo": {
16046
+ "enum": ["Yes"]
16047
+ },
16048
+ "details": {
16049
+ "sef25Ref": "H1.1.2",
16050
+ "title": "Give details",
16051
+ "type": "string",
16052
+ "minLength": 1
16053
+ }
16054
+ }
16055
+ }
16056
+ ]
16057
+ },
16058
+ "damagedOrExposedElectrics": {
16059
+ "sef25Ref": "H1.2",
16060
+ "title": "Are there any damaged or exposed electrics at the property?",
16061
+ "type": "object",
16062
+ "sef25Required": ["yesNo"],
16063
+ "properties": {
16064
+ "yesNo": {
16065
+ "sef25Ref": "H1.2.1",
16066
+ "type": "string",
16067
+ "title": "",
16068
+ "enum": ["Yes", "No"]
16069
+ }
16070
+ },
16071
+ "discriminator": {
16072
+ "propertyName": "yesNo"
16073
+ },
16074
+ "oneOf": [
16075
+ {
16076
+ "properties": {
16077
+ "yesNo": {
16078
+ "enum": ["No"]
16079
+ }
16080
+ }
16081
+ },
16082
+ {
16083
+ "sef25Required": ["details"],
16084
+ "properties": {
16085
+ "yesNo": {
16086
+ "enum": ["Yes"]
16087
+ },
16088
+ "details": {
16089
+ "sef25Ref": "H1.2.2",
16090
+ "title": "Give details",
16091
+ "type": "string",
16092
+ "minLength": 1
16093
+ }
16094
+ }
16095
+ }
16096
+ ]
16097
+ },
16098
+ "damageToFlooringOrStaircases": {
16099
+ "sef25Ref": "H1.3",
16100
+ "title": "Is there any damage to flooring and/or staircases?",
16101
+ "type": "object",
16102
+ "sef25Required": ["yesNo"],
16103
+ "properties": {
16104
+ "yesNo": {
16105
+ "sef25Ref": "H1.3.1",
16106
+ "type": "string",
16107
+ "title": "",
16108
+ "enum": ["Yes", "No"]
16109
+ }
16110
+ },
16111
+ "discriminator": {
16112
+ "propertyName": "yesNo"
16113
+ },
16114
+ "oneOf": [
16115
+ {
16116
+ "properties": {
16117
+ "yesNo": {
16118
+ "enum": ["No"]
16119
+ }
16120
+ }
16121
+ },
16122
+ {
16123
+ "sef25Required": ["details"],
16124
+ "properties": {
16125
+ "yesNo": {
16126
+ "enum": ["Yes"]
16127
+ },
16128
+ "details": {
16129
+ "sef25Ref": "H1.3.2",
16130
+ "title": "Give details",
16131
+ "type": "string",
16132
+ "minLength": 1
16133
+ }
16134
+ }
16135
+ }
16136
+ ]
16137
+ },
16138
+ "knownAreasInPoorCondition": {
16139
+ "sef25Ref": "H1.4",
16140
+ "title": "Are there any known areas in poor condition (internal or external)?",
16141
+ "type": "object",
16142
+ "sef25Required": ["yesNo"],
16143
+ "properties": {
16144
+ "yesNo": {
16145
+ "sef25Ref": "H1.4.1",
16146
+ "type": "string",
16147
+ "title": "",
16148
+ "enum": ["Yes", "No"]
16149
+ }
16150
+ },
16151
+ "discriminator": {
16152
+ "propertyName": "yesNo"
16153
+ },
16154
+ "oneOf": [
16155
+ {
16156
+ "properties": {
16157
+ "yesNo": {
16158
+ "enum": ["No"]
16159
+ }
16160
+ }
16161
+ },
16162
+ {
16163
+ "sef25Required": ["details"],
16164
+ "properties": {
16165
+ "yesNo": {
16166
+ "enum": ["Yes"]
16167
+ },
16168
+ "details": {
16169
+ "sef25Ref": "H1.4.2",
16170
+ "title": "Give details",
16171
+ "type": "string",
16172
+ "minLength": 1
16173
+ }
16174
+ }
16175
+ }
16176
+ ]
16004
16177
  }
16005
16178
  }
16006
16179
  },
@@ -22136,6 +22309,25 @@
22136
22309
  "description": "e.g. Private well, borehole, springs etc.",
22137
22310
  "type": "string",
22138
22311
  "minLength": 1
22312
+ },
22313
+ "associatedCost": {
22314
+ "sef25Ref": "U1.1",
22315
+ "title": "Associated costs for water",
22316
+ "type": "object",
22317
+ "sef25Required": ["amount", "frequency"],
22318
+ "properties": {
22319
+ "amount": {
22320
+ "sef25Ref": "U1.1.1",
22321
+ "title": "Cost (£)",
22322
+ "type": "number"
22323
+ },
22324
+ "frequency": {
22325
+ "sef25Ref": "U1.1.2",
22326
+ "title": "Payment frequency",
22327
+ "type": "string",
22328
+ "enum": ["Per month", "Per year"]
22329
+ }
22330
+ }
22139
22331
  }
22140
22332
  },
22141
22333
  "ntsRequired": ["details"],
@@ -23149,6 +23341,25 @@
23149
23341
  "ntsl2Required": ["details"]
23150
23342
  }
23151
23343
  ]
23344
+ },
23345
+ "associatedCost": {
23346
+ "sef25Ref": "U1.2",
23347
+ "title": "Associated costs for sewerage",
23348
+ "type": "object",
23349
+ "sef25Required": ["amount", "frequency"],
23350
+ "properties": {
23351
+ "amount": {
23352
+ "sef25Ref": "U1.2.1",
23353
+ "title": "Cost (£)",
23354
+ "type": "number"
23355
+ },
23356
+ "frequency": {
23357
+ "sef25Ref": "U1.2.2",
23358
+ "title": "Payment frequency",
23359
+ "type": "string",
23360
+ "enum": ["Per month", "Per year"]
23361
+ }
23362
+ }
23152
23363
  }
23153
23364
  },
23154
23365
  "ntsRequired": ["offMainsDrainageSystem"],
@@ -951,6 +951,7 @@
951
951
  controlledParking
952
952
  yesNo
953
953
  annualCostOfPermit
954
+ costOfPermitFrequency
954
955
  vehicleTypeRestriction
955
956
  yesNo
956
957
  details
@@ -1390,6 +1391,18 @@
1390
1391
  yesNo
1391
1392
  details
1392
1393
  attachments
1394
+ wellsDitchesShaft
1395
+ yesNo
1396
+ details
1397
+ damagedOrExposedElectrics
1398
+ yesNo
1399
+ details
1400
+ damageToFlooringOrStaircases
1401
+ yesNo
1402
+ details
1403
+ knownAreasInPoorCondition
1404
+ yesNo
1405
+ details
1393
1406
  fixturesAndFittings
1394
1407
  itemsToRemove
1395
1408
  yesNo
@@ -1910,6 +1923,9 @@
1910
1923
  mainsWater
1911
1924
  yesNo
1912
1925
  details
1926
+ associatedCost
1927
+ amount
1928
+ frequency
1913
1929
  supplier
1914
1930
  stopcock
1915
1931
  location
@@ -1965,6 +1981,9 @@
1965
1981
  dateLastServiced
1966
1982
  attachments
1967
1983
  details
1984
+ associatedCost
1985
+ amount
1986
+ frequency
1968
1987
  surfaceDrainageCharge
1969
1988
  yesNo
1970
1989
  details
@@ -33,6 +33,9 @@
33
33
  "required": [
34
34
  "managementPlanInPlace"
35
35
  ],
36
+ "discriminator": {
37
+ "propertyName": "managementPlanInPlace"
38
+ },
36
39
  "properties": {
37
40
  "managementPlanInPlace": {
38
41
  "ntsRef": "A5.3.2",
@@ -47,14 +50,29 @@
47
50
  "enum": [
48
51
  "Yes"
49
52
  ]
53
+ }
54
+ },
55
+ "oneOf": [
56
+ {
57
+ "properties": {
58
+ "managementPlanInPlace": {
59
+ "enum": [
60
+ "No",
61
+ "Not known"
62
+ ]
63
+ }
64
+ }
50
65
  },
51
- "attachments": {
52
- "enum": [
53
- "Attached",
54
- "To follow"
55
- ]
66
+ {
67
+ "properties": {
68
+ "managementPlanInPlace": {
69
+ "enum": [
70
+ "Yes"
71
+ ]
72
+ }
73
+ }
56
74
  }
57
- }
75
+ ]
58
76
  }
59
77
  ],
60
78
  "type": "object"
@@ -0,0 +1,28 @@
1
+ {
2
+ "properties": {
3
+ "propertyPack": {
4
+ "properties": {
5
+ "parking": {
6
+ "properties": {
7
+ "controlledParking": {
8
+ "oneOf": [
9
+ null,
10
+ {
11
+ "properties": {
12
+ "costOfPermitFrequency": {
13
+ "sef25Ref": "P1.1",
14
+ "type": "string"
15
+ }
16
+ }
17
+ }
18
+ ]
19
+ }
20
+ }
21
+ }
22
+ }
23
+ }
24
+ },
25
+ "$schema": "http://json-schema.org/draft-07/schema#",
26
+ "$id": "https://trust.propdata.org.uk/schemas/v3/overlays/extensions/pc.json",
27
+ "$comment": "Parking permit cost and frequency"
28
+ }