@planning-inspectorate/data-model 2.10.3 → 2.12.0

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.
Files changed (27) hide show
  1. package/docs/appeal-document.md +2 -0
  2. package/docs/appeal-has.md +1 -0
  3. package/docs/appeal-s78.md +118 -0
  4. package/package.json +1 -1
  5. package/pins_data_model/models/model_appeal_document.py +3 -1
  6. package/pins_data_model/models/model_appeal_has.py +2 -1
  7. package/pins_data_model/models/model_appeal_s78.py +38 -1
  8. package/schemas/appeal-document.schema.json +2 -0
  9. package/schemas/appeal-has.schema.json +1 -0
  10. package/schemas/appeal-s78.schema.json +20 -0
  11. package/schemas/commands/appeal-representation-submission.schema.json +1 -0
  12. package/schemas/commands/appeals-components/appeal-common-planning.schema.json +3 -3
  13. package/schemas/commands/appeals-components/appeal-common-submission.schema.json +1 -0
  14. package/schemas/commands/appeals-components/appeal-ldc.submission.schema.json +19 -0
  15. package/schemas/commands/appeals-components/lpa-questionnaire-common.schema.json +6 -1
  16. package/schemas/commands/appeals-components/lpa-questionnaire-has.schema.json +0 -5
  17. package/schemas/commands/appeals-components/lpa-questionnaire-ldc.schema.json +31 -0
  18. package/schemas/commands/appellant-submission.schema.json +10 -0
  19. package/schemas/commands/lpa-questionnaire.schema.json +13 -1
  20. package/src/enums.cjs +17 -0
  21. package/src/enums.d.ts +15 -0
  22. package/src/enums.js +15 -0
  23. package/src/index.cjs +17 -0
  24. package/src/schemas.d.ts +78 -9
  25. package/tests/appeals/appeal-s78.test.js +16 -1
  26. package/tests/appeals/commands/ldc-questionnaire.test.js +83 -0
  27. package/tests/appeals/commands/ldc-submission.test.js +172 -0
@@ -620,6 +620,8 @@ The type of document, used for exchange, migrations and consumption from the app
620
620
  | `"groundGSupporting"` | |
621
621
  | `"groundAFeeReceipt"` | |
622
622
  | `"delegatedReport"` | |
623
+ | `"relatedApplications"` | |
624
+ | `"otherRelevantMatters"` | |
623
625
  | `null` | |
624
626
 
625
627
  ## sourceSystem
@@ -2462,6 +2462,7 @@ Indicates if the appellant has applied for costs
2462
2462
  | `"listed-building"` | |
2463
2463
  | `"minor-commercial-development"` | |
2464
2464
  | `"advertisement"` | |
2465
+ | `"lawful-development-certificate"` | |
2465
2466
  | `null` | |
2466
2467
 
2467
2468
  ## siteGridReferenceEasting
@@ -191,6 +191,11 @@ any of
191
191
  | [isSiteSubjectToArticle4Direction](#issitesubjecttoarticle4direction) | `boolean` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-issitesubjecttoarticle4direction.md "appeal-s78.schema.json#/properties/isSiteSubjectToArticle4Direction") |
192
192
  | [article4AffectedDevelopmentRights](#article4affecteddevelopmentrights) | `string` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-article4affecteddevelopmentrights.md "appeal-s78.schema.json#/properties/article4AffectedDevelopmentRights") |
193
193
  | [pcnRestrictedDevelopmentRights](#pcnrestricteddevelopmentrights) | `boolean` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-pcnrestricteddevelopmentrights.md "appeal-s78.schema.json#/properties/pcnRestrictedDevelopmentRights") |
194
+ | [applicationMadeUnderActSection](#applicationmadeunderactsection) | `string` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-applicationmadeunderactsection.md "appeal-s78.schema.json#/properties/applicationMadeUnderActSection") |
195
+ | [siteUseAtTimeOfApplication](#siteuseattimeofapplication) | `string` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-siteuseattimeofapplication.md "appeal-s78.schema.json#/properties/siteUseAtTimeOfApplication") |
196
+ | [appealUnderActSection](#appealunderactsection) | `string` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-appealunderactsection.md "appeal-s78.schema.json#/properties/appealUnderActSection") |
197
+ | [lpaConsiderAppealInvalid](#lpaconsiderappealinvalid) | `boolean` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-lpaconsiderappealinvalid.md "appeal-s78.schema.json#/properties/lpaConsiderAppealInvalid") |
198
+ | [lpaAppealInvalidReasons](#lpaappealinvalidreasons) | `string` | Optional | can be null | [Appeal S78 Case](appeal-s78-properties-lpaappealinvalidreasons.md "appeal-s78.schema.json#/properties/lpaAppealInvalidReasons") |
194
199
  | Additional Properties | Any | Optional | can be null | |
195
200
 
196
201
  ## caseId
@@ -3571,6 +3576,7 @@ The net gain in residences of the proposed development
3571
3576
  | `"listed-building"` | |
3572
3577
  | `"minor-commercial-development"` | |
3573
3578
  | `"advertisement"` | |
3579
+ | `"lawful-development-certificate"` | |
3574
3580
  | `null` | |
3575
3581
 
3576
3582
  ## developmentType
@@ -4512,6 +4518,118 @@ Have any development rights been restricted by means of a planning condition?
4512
4518
 
4513
4519
  `boolean`
4514
4520
 
4521
+ ## applicationMadeUnderActSection
4522
+
4523
+
4524
+
4525
+ `applicationMadeUnderActSection`
4526
+
4527
+ * is optional
4528
+
4529
+ * Type: `string`
4530
+
4531
+ * can be null
4532
+
4533
+ * defined in: [Appeal S78 Case](appeal-s78-properties-applicationmadeunderactsection.md "appeal-s78.schema.json#/properties/applicationMadeUnderActSection")
4534
+
4535
+ ### applicationMadeUnderActSection Type
4536
+
4537
+ `string`
4538
+
4539
+ ### applicationMadeUnderActSection Constraints
4540
+
4541
+ **enum**: the value of this property must be equal to one of the following values:
4542
+
4543
+ | Value | Explanation |
4544
+ | :---------------------------------------- | :---------- |
4545
+ | `"existing-development"` | |
4546
+ | `"proposed-use-of-a-development"` | |
4547
+ | `"proposed-changes-to-a-listed-building"` | |
4548
+ | `null` | |
4549
+
4550
+ ## siteUseAtTimeOfApplication
4551
+
4552
+ Site use at time of application
4553
+
4554
+ `siteUseAtTimeOfApplication`
4555
+
4556
+ * is optional
4557
+
4558
+ * Type: `string`
4559
+
4560
+ * can be null
4561
+
4562
+ * defined in: [Appeal S78 Case](appeal-s78-properties-siteuseattimeofapplication.md "appeal-s78.schema.json#/properties/siteUseAtTimeOfApplication")
4563
+
4564
+ ### siteUseAtTimeOfApplication Type
4565
+
4566
+ `string`
4567
+
4568
+ ## appealUnderActSection
4569
+
4570
+
4571
+
4572
+ `appealUnderActSection`
4573
+
4574
+ * is optional
4575
+
4576
+ * Type: `string`
4577
+
4578
+ * can be null
4579
+
4580
+ * defined in: [Appeal S78 Case](appeal-s78-properties-appealunderactsection.md "appeal-s78.schema.json#/properties/appealUnderActSection")
4581
+
4582
+ ### appealUnderActSection Type
4583
+
4584
+ `string`
4585
+
4586
+ ### appealUnderActSection Constraints
4587
+
4588
+ **enum**: the value of this property must be equal to one of the following values:
4589
+
4590
+ | Value | Explanation |
4591
+ | :---------------------------------------- | :---------- |
4592
+ | `"existing-development"` | |
4593
+ | `"proposed-use-of-a-development"` | |
4594
+ | `"proposed-changes-to-a-listed-building"` | |
4595
+ | `null` | |
4596
+
4597
+ ## lpaConsiderAppealInvalid
4598
+
4599
+
4600
+
4601
+ `lpaConsiderAppealInvalid`
4602
+
4603
+ * is optional
4604
+
4605
+ * Type: `boolean`
4606
+
4607
+ * can be null
4608
+
4609
+ * defined in: [Appeal S78 Case](appeal-s78-properties-lpaconsiderappealinvalid.md "appeal-s78.schema.json#/properties/lpaConsiderAppealInvalid")
4610
+
4611
+ ### lpaConsiderAppealInvalid Type
4612
+
4613
+ `boolean`
4614
+
4615
+ ## lpaAppealInvalidReasons
4616
+
4617
+ Reason(s) why LPA consider the appeal invalid
4618
+
4619
+ `lpaAppealInvalidReasons`
4620
+
4621
+ * is optional
4622
+
4623
+ * Type: `string`
4624
+
4625
+ * can be null
4626
+
4627
+ * defined in: [Appeal S78 Case](appeal-s78-properties-lpaappealinvalidreasons.md "appeal-s78.schema.json#/properties/lpaAppealInvalidReasons")
4628
+
4629
+ ### lpaAppealInvalidReasons Type
4630
+
4631
+ `string`
4632
+
4515
4633
  ## Additional Properties
4516
4634
 
4517
4635
  Additional properties are allowed and do not have to follow a specific schema
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planning-inspectorate/data-model",
3
- "version": "2.10.3",
3
+ "version": "2.12.0",
4
4
  "description": "JSON Schemas for the Planning Inspectorate's Data Model",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: appeal-document.schema.json
3
- # timestamp: 2026-01-20T11:57:10+00:00
3
+ # timestamp: 2026-01-21T12:30:03+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -142,6 +142,8 @@ class DocumentType(Enum):
142
142
  groundGSupporting = "groundGSupporting"
143
143
  groundAFeeReceipt = "groundAFeeReceipt"
144
144
  delegatedReport = "delegatedReport"
145
+ relatedApplications = "relatedApplications"
146
+ otherRelevantMatters = "otherRelevantMatters"
145
147
  NoneType_None = None
146
148
 
147
149
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: appeal-has.schema.json
3
- # timestamp: 2026-01-20T11:57:10+00:00
3
+ # timestamp: 2026-01-21T12:30:03+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -229,6 +229,7 @@ class TypeOfPlanningApplication(Enum):
229
229
  listed_building = "listed-building"
230
230
  minor_commercial_development = "minor-commercial-development"
231
231
  advertisement = "advertisement"
232
+ lawful_development_certificate = "lawful-development-certificate"
232
233
  NoneType_None = None
233
234
 
234
235
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: appeal-s78.schema.json
3
- # timestamp: 2026-01-20T11:57:10+00:00
3
+ # timestamp: 2026-01-21T12:30:03+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -281,6 +281,7 @@ class TypeOfPlanningApplication(Enum):
281
281
  listed_building = "listed-building"
282
282
  minor_commercial_development = "minor-commercial-development"
283
283
  advertisement = "advertisement"
284
+ lawful_development_certificate = "lawful-development-certificate"
284
285
  NoneType_None = None
285
286
 
286
287
 
@@ -370,6 +371,20 @@ class ApplicationPartOrWholeDevelopment(Enum):
370
371
  NoneType_None = None
371
372
 
372
373
 
374
+ class ApplicationMadeUnderActSection(Enum):
375
+ existing_development = "existing-development"
376
+ proposed_use_of_a_development = "proposed-use-of-a-development"
377
+ proposed_changes_to_a_listed_building = "proposed-changes-to-a-listed-building"
378
+ NoneType_None = None
379
+
380
+
381
+ class AppealUnderActSection(Enum):
382
+ existing_development = "existing-development"
383
+ proposed_use_of_a_development = "proposed-use-of-a-development"
384
+ proposed_changes_to_a_listed_building = "proposed-changes-to-a-listed-building"
385
+ NoneType_None = None
386
+
387
+
373
388
  class AppealS78Case1(BaseModel):
374
389
  """
375
390
  Group B - Schema defining the metadata for an appeal
@@ -1065,6 +1080,17 @@ class AppealS78Case1(BaseModel):
1065
1080
  """
1066
1081
  Have any development rights been restricted by means of a planning condition?
1067
1082
  """
1083
+ applicationMadeUnderActSection: ApplicationMadeUnderActSection | None = None
1084
+ siteUseAtTimeOfApplication: str | None = None
1085
+ """
1086
+ Site use at time of application
1087
+ """
1088
+ appealUnderActSection: AppealUnderActSection | None = None
1089
+ lpaConsiderAppealInvalid: bool | None = None
1090
+ lpaAppealInvalidReasons: str | None = None
1091
+ """
1092
+ Reason(s) why LPA consider the appeal invalid
1093
+ """
1068
1094
 
1069
1095
 
1070
1096
  class AdvertDetail1(BaseModel):
@@ -1791,6 +1817,17 @@ class AppealS78Case2(BaseModel):
1791
1817
  """
1792
1818
  Have any development rights been restricted by means of a planning condition?
1793
1819
  """
1820
+ applicationMadeUnderActSection: ApplicationMadeUnderActSection | None = None
1821
+ siteUseAtTimeOfApplication: str | None = None
1822
+ """
1823
+ Site use at time of application
1824
+ """
1825
+ appealUnderActSection: AppealUnderActSection | None = None
1826
+ lpaConsiderAppealInvalid: bool | None = None
1827
+ lpaAppealInvalidReasons: str | None = None
1828
+ """
1829
+ Reason(s) why LPA consider the appeal invalid
1830
+ """
1794
1831
 
1795
1832
 
1796
1833
  class AppealS78Case(RootModel[AppealS78Case1 | AppealS78Case2]):
@@ -220,6 +220,8 @@
220
220
  "groundGSupporting",
221
221
  "groundAFeeReceipt",
222
222
  "delegatedReport",
223
+ "relatedApplications",
224
+ "otherRelevantMatters",
223
225
  null
224
226
  ],
225
227
  "description": "The type of document, used for exchange, migrations and consumption from the appeal back-office system"
@@ -696,6 +696,7 @@
696
696
  "listed-building",
697
697
  "minor-commercial-development",
698
698
  "advertisement",
699
+ "lawful-development-certificate",
699
700
  null
700
701
  ]
701
702
  },
@@ -1014,6 +1014,7 @@
1014
1014
  "listed-building",
1015
1015
  "minor-commercial-development",
1016
1016
  "advertisement",
1017
+ "lawful-development-certificate",
1017
1018
  null
1018
1019
  ]
1019
1020
  },
@@ -1265,6 +1266,25 @@
1265
1266
  "pcnRestrictedDevelopmentRights": {
1266
1267
  "type": ["boolean", "null"],
1267
1268
  "description": "Have any development rights been restricted by means of a planning condition?"
1269
+ },
1270
+ "applicationMadeUnderActSection": {
1271
+ "type": ["string", "null"],
1272
+ "enum": ["existing-development", "proposed-use-of-a-development", "proposed-changes-to-a-listed-building", null]
1273
+ },
1274
+ "siteUseAtTimeOfApplication": {
1275
+ "type": ["string", "null"],
1276
+ "description": "Site use at time of application"
1277
+ },
1278
+ "appealUnderActSection": {
1279
+ "type": ["string", "null"],
1280
+ "enum": ["existing-development", "proposed-use-of-a-development", "proposed-changes-to-a-listed-building", null]
1281
+ },
1282
+ "lpaConsiderAppealInvalid": {
1283
+ "type": ["boolean", "null"]
1284
+ },
1285
+ "lpaAppealInvalidReasons": {
1286
+ "type": ["string", "null"],
1287
+ "description": "Reason(s) why LPA consider the appeal invalid"
1268
1288
  }
1269
1289
  }
1270
1290
  }
@@ -87,6 +87,7 @@
87
87
  "lpaWitnessesEvidence",
88
88
  "rule6ProofOfEvidence",
89
89
  "rule6WitnessesEvidence",
90
+ "appellantStatement",
90
91
  null
91
92
  ],
92
93
  "description": "The type of document, used for exchange, migrations and consumption from the appeal back-office system"
@@ -21,14 +21,14 @@
21
21
  "description": "The unique identifier of the LPA application"
22
22
  },
23
23
  "applicationDate": {
24
- "type": "string",
24
+ "type": ["string", "null"],
25
25
  "format": "date-time",
26
26
  "examples": ["2023-07-27T20:30:00.000Z"],
27
27
  "description": "The date of the original LPA application"
28
28
  },
29
29
  "applicationDecision": {
30
- "type": "string",
31
- "enum": ["granted", "refused", "not_received"],
30
+ "type": ["string", "null"],
31
+ "enum": ["granted", "refused", "not_received", null],
32
32
  "description": "The outcome of the original LPA decision"
33
33
  },
34
34
  "applicationDecisionDate": {
@@ -139,6 +139,7 @@
139
139
  "listed-building",
140
140
  "minor-commercial-development",
141
141
  "advertisement",
142
+ "lawful-development-certificate",
142
143
  null
143
144
  ]
144
145
  },
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "commands/appeals-components/appeal-ldc.submission.schema.json",
4
+ "title": "LDC specific properties",
5
+ "description": "Schema defining any properties for ldc appeals",
6
+ "type": "object",
7
+ "additionalProperties": true,
8
+ "required": ["siteUseAtTimeOfApplication", "applicationMadeUnderActSection"],
9
+ "properties": {
10
+ "siteUseAtTimeOfApplication": {
11
+ "type": ["string", "null"],
12
+ "description": "Site use at time of application"
13
+ },
14
+ "applicationMadeUnderActSection": {
15
+ "type": ["string", "null"],
16
+ "enum": ["existing-development", "proposed-use-of-a-development", "proposed-changes-to-a-listed-building", null]
17
+ }
18
+ }
19
+ }
@@ -11,7 +11,8 @@
11
11
  "siteAccessDetails",
12
12
  "siteSafetyDetails",
13
13
  "nearbyCaseReferences",
14
- "neighbouringSiteAddresses"
14
+ "neighbouringSiteAddresses",
15
+ "isCorrectAppealType"
15
16
  ],
16
17
  "properties": {
17
18
  "caseReference": {
@@ -105,6 +106,10 @@
105
106
  "reasonForNeighbourVisits": {
106
107
  "type": ["string", "null"],
107
108
  "description": "A general reason given for the need to visit any neighbours"
109
+ },
110
+ "isCorrectAppealType": {
111
+ "type": ["boolean", "null"],
112
+ "description": "Indicates if the LPA considers the appeal type appropriate"
108
113
  }
109
114
  }
110
115
  }
@@ -6,7 +6,6 @@
6
6
  "type": "object",
7
7
  "additionalProperties": true,
8
8
  "required": [
9
- "isCorrectAppealType",
10
9
  "affectedListedBuildingNumbers",
11
10
  "isGreenBelt",
12
11
  "inConservationArea",
@@ -18,10 +17,6 @@
18
17
  "allOf": [
19
18
  {
20
19
  "properties": {
21
- "isCorrectAppealType": {
22
- "type": ["boolean", "null"],
23
- "description": "Indicates if the LPA considers the appeal type appropriate"
24
- },
25
20
  "affectedListedBuildingNumbers": {
26
21
  "type": ["array", "null"],
27
22
  "items": {
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "commands/appeals-components/lpa-questionnaire-ldc.schema.json",
4
+ "title": "LPAQ LDC submission properties",
5
+ "description": "Schema defining any LDC specific properties for LPAQ submissions",
6
+ "type": "object",
7
+ "additionalProperties": true,
8
+ "required": ["appealUnderActSection", "lpaConsiderAppealInvalid", "lpaAppealInvalidReasons"],
9
+ "allOf": [
10
+ {
11
+ "properties": {
12
+ "appealUnderActSection": {
13
+ "type": ["string", "null"],
14
+ "enum": [
15
+ "existing-development",
16
+ "proposed-use-of-a-development",
17
+ "proposed-changes-to-a-listed-building",
18
+ null
19
+ ]
20
+ },
21
+ "lpaConsiderAppealInvalid": {
22
+ "type": ["boolean", "null"]
23
+ },
24
+ "lpaAppealInvalidReasons": {
25
+ "type": ["string", "null"],
26
+ "description": "Reason(s) why LPA consider the appeal invalid"
27
+ }
28
+ }
29
+ }
30
+ ]
31
+ }
@@ -63,6 +63,16 @@
63
63
  { "$ref": "appeals-components/appeal-enforcement-submission.schema.json" },
64
64
  { "$ref": "appeals-components/appellant-procedure-preference.schema.json" }
65
65
  ]
66
+ },
67
+ {
68
+ "$comment": "Lawful development certificate",
69
+ "allOf": [
70
+ { "properties": { "caseType": { "enum": ["X"] } } },
71
+ { "$ref": "appeals-components/appeal-common-submission.schema.json" },
72
+ { "$ref": "appeals-components/appeal-common-planning.schema.json" },
73
+ { "$ref": "appeals-components/appellant-procedure-preference.schema.json" },
74
+ { "$ref": "appeals-components/appeal-ldc.submission.schema.json" }
75
+ ]
66
76
  }
67
77
  ]
68
78
  },
@@ -83,6 +83,16 @@
83
83
  { "$ref": "appeals-components/site-designations-protection.schema.json" },
84
84
  { "$ref": "appeals-components/lpa-questionnaire-enforcement.schema.json" }
85
85
  ]
86
+ },
87
+ {
88
+ "$comment": "Lawful Development Certificate",
89
+ "allOf": [
90
+ { "properties": { "caseType": { "enum": ["X"] } } },
91
+ { "$ref": "appeals-components/lpa-questionnaire-common.schema.json" },
92
+ { "$ref": "appeals-components/lpa-procedure-preference.schema.json" },
93
+ { "$ref": "appeals-components/infrastructure-levy.schema.json" },
94
+ { "$ref": "appeals-components/lpa-questionnaire-ldc.schema.json" }
95
+ ]
86
96
  }
87
97
  ]
88
98
  },
@@ -168,7 +178,9 @@
168
178
  "planningPermission",
169
179
  "lpaEnforcementNotice",
170
180
  "lpaEnforcementNoticePlan",
171
- "planningContraventionNotice"
181
+ "planningContraventionNotice",
182
+ "relatedApplications",
183
+ "otherRelevantMatters"
172
184
  ],
173
185
  "description": "The type of document, used for exchange, migrations and consumption from the appeal back-office system"
174
186
  }
package/src/enums.cjs CHANGED
@@ -11,6 +11,12 @@ const APPEAL_ALLOCATION_LEVEL = Object.freeze({
11
11
  H: 'H',
12
12
  });
13
13
 
14
+ const APPEAL_APPEAL_UNDER_ACT_SECTION = Object.freeze({
15
+ EXISTING_DEVELOPMENT: 'existing-development',
16
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
17
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
18
+ });
19
+
14
20
  const APPEAL_APPELLANT_PROCEDURE_PREFERENCE = Object.freeze({
15
21
  HEARING: 'hearing',
16
22
  INQUIRY: 'inquiry',
@@ -23,6 +29,12 @@ const APPEAL_APPLICATION_DECISION = Object.freeze({
23
29
  REFUSED: 'refused',
24
30
  });
25
31
 
32
+ const APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = Object.freeze({
33
+ EXISTING_DEVELOPMENT: 'existing-development',
34
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
35
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
36
+ });
37
+
26
38
  const APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = Object.freeze({
27
39
  ALL_OF_THE_DEVELOPMENT: 'all-of-the-development',
28
40
  PART_OF_THE_DEVELOPMENT: 'part-of-the-development',
@@ -183,6 +195,7 @@ const APPEAL_DOCUMENT_TYPE = Object.freeze({
183
195
  ORIGINAL_APPLICATION_FORM: 'originalApplicationForm',
184
196
  OTHER_NEW_DOCUMENTS: 'otherNewDocuments',
185
197
  OTHER_PARTY_REPRESENTATIONS: 'otherPartyRepresentations',
198
+ OTHER_RELEVANT_MATTERS: 'otherRelevantMatters',
186
199
  OTHER_RELEVANT_POLICIES: 'otherRelevantPolicies',
187
200
  OWNERSHIP_CERTIFICATE: 'ownershipCertificate',
188
201
  PLAN_SHOWING_EXTENT_OF_ORDER: 'planShowingExtentOfOrder',
@@ -192,6 +205,7 @@ const APPEAL_DOCUMENT_TYPE = Object.freeze({
192
205
  PLANNING_PERMISSION: 'planningPermission',
193
206
  PLANS_DRAWINGS: 'plansDrawings',
194
207
  PRIOR_CORRESPONDENCE_WITH_PINS: 'priorCorrespondenceWithPINS',
208
+ RELATED_APPLICATIONS: 'relatedApplications',
195
209
  RULE_6_PROOF_OF_EVIDENCE: 'rule6ProofOfEvidence',
196
210
  RULE_6_STATEMENT: 'rule6Statement',
197
211
  RULE_6_WITNESSES_EVIDENCE: 'rule6WitnessesEvidence',
@@ -344,6 +358,7 @@ const APPEAL_TYPE_OF_PLANNING_APPLICATION = Object.freeze({
344
358
  ADVERTISEMENT: 'advertisement',
345
359
  FULL_APPEAL: 'full-appeal',
346
360
  HOUSEHOLDER_PLANNING: 'householder-planning',
361
+ LAWFUL_DEVELOPMENT_CERTIFICATE: 'lawful-development-certificate',
347
362
  LISTED_BUILDING: 'listed-building',
348
363
  MINOR_COMMERCIAL_DEVELOPMENT: 'minor-commercial-development',
349
364
  OUTLINE_PLANNING: 'outline-planning',
@@ -720,8 +735,10 @@ const STATUS = Object.freeze({
720
735
  });
721
736
 
722
737
  exports.APPEAL_ALLOCATION_LEVEL = APPEAL_ALLOCATION_LEVEL;
738
+ exports.APPEAL_APPEAL_UNDER_ACT_SECTION = APPEAL_APPEAL_UNDER_ACT_SECTION;
723
739
  exports.APPEAL_APPELLANT_PROCEDURE_PREFERENCE = APPEAL_APPELLANT_PROCEDURE_PREFERENCE;
724
740
  exports.APPEAL_APPLICATION_DECISION = APPEAL_APPLICATION_DECISION;
741
+ exports.APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION;
725
742
  exports.APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT;
726
743
  exports.APPEAL_CASE_DECISION_OUTCOME = APPEAL_CASE_DECISION_OUTCOME;
727
744
  exports.APPEAL_CASE_PROCEDURE = APPEAL_CASE_PROCEDURE;
package/src/enums.d.ts CHANGED
@@ -9,6 +9,12 @@ export const APPEAL_ALLOCATION_LEVEL = {
9
9
  H: 'H',
10
10
  } as const;
11
11
 
12
+ export const APPEAL_APPEAL_UNDER_ACT_SECTION = {
13
+ EXISTING_DEVELOPMENT: 'existing-development',
14
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
15
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
16
+ } as const;
17
+
12
18
  export const APPEAL_APPELLANT_PROCEDURE_PREFERENCE = {
13
19
  HEARING: 'hearing',
14
20
  INQUIRY: 'inquiry',
@@ -21,6 +27,12 @@ export const APPEAL_APPLICATION_DECISION = {
21
27
  REFUSED: 'refused',
22
28
  } as const;
23
29
 
30
+ export const APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = {
31
+ EXISTING_DEVELOPMENT: 'existing-development',
32
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
33
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
34
+ } as const;
35
+
24
36
  export const APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = {
25
37
  ALL_OF_THE_DEVELOPMENT: 'all-of-the-development',
26
38
  PART_OF_THE_DEVELOPMENT: 'part-of-the-development',
@@ -181,6 +193,7 @@ export const APPEAL_DOCUMENT_TYPE = {
181
193
  ORIGINAL_APPLICATION_FORM: 'originalApplicationForm',
182
194
  OTHER_NEW_DOCUMENTS: 'otherNewDocuments',
183
195
  OTHER_PARTY_REPRESENTATIONS: 'otherPartyRepresentations',
196
+ OTHER_RELEVANT_MATTERS: 'otherRelevantMatters',
184
197
  OTHER_RELEVANT_POLICIES: 'otherRelevantPolicies',
185
198
  OWNERSHIP_CERTIFICATE: 'ownershipCertificate',
186
199
  PLAN_SHOWING_EXTENT_OF_ORDER: 'planShowingExtentOfOrder',
@@ -190,6 +203,7 @@ export const APPEAL_DOCUMENT_TYPE = {
190
203
  PLANNING_PERMISSION: 'planningPermission',
191
204
  PLANS_DRAWINGS: 'plansDrawings',
192
205
  PRIOR_CORRESPONDENCE_WITH_PINS: 'priorCorrespondenceWithPINS',
206
+ RELATED_APPLICATIONS: 'relatedApplications',
193
207
  RULE_6_PROOF_OF_EVIDENCE: 'rule6ProofOfEvidence',
194
208
  RULE_6_STATEMENT: 'rule6Statement',
195
209
  RULE_6_WITNESSES_EVIDENCE: 'rule6WitnessesEvidence',
@@ -342,6 +356,7 @@ export const APPEAL_TYPE_OF_PLANNING_APPLICATION = {
342
356
  ADVERTISEMENT: 'advertisement',
343
357
  FULL_APPEAL: 'full-appeal',
344
358
  HOUSEHOLDER_PLANNING: 'householder-planning',
359
+ LAWFUL_DEVELOPMENT_CERTIFICATE: 'lawful-development-certificate',
345
360
  LISTED_BUILDING: 'listed-building',
346
361
  MINOR_COMMERCIAL_DEVELOPMENT: 'minor-commercial-development',
347
362
  OUTLINE_PLANNING: 'outline-planning',
package/src/enums.js CHANGED
@@ -9,6 +9,12 @@ export const APPEAL_ALLOCATION_LEVEL = Object.freeze({
9
9
  H: 'H',
10
10
  });
11
11
 
12
+ export const APPEAL_APPEAL_UNDER_ACT_SECTION = Object.freeze({
13
+ EXISTING_DEVELOPMENT: 'existing-development',
14
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
15
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
16
+ });
17
+
12
18
  export const APPEAL_APPELLANT_PROCEDURE_PREFERENCE = Object.freeze({
13
19
  HEARING: 'hearing',
14
20
  INQUIRY: 'inquiry',
@@ -21,6 +27,12 @@ export const APPEAL_APPLICATION_DECISION = Object.freeze({
21
27
  REFUSED: 'refused',
22
28
  });
23
29
 
30
+ export const APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = Object.freeze({
31
+ EXISTING_DEVELOPMENT: 'existing-development',
32
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
33
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
34
+ });
35
+
24
36
  export const APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = Object.freeze({
25
37
  ALL_OF_THE_DEVELOPMENT: 'all-of-the-development',
26
38
  PART_OF_THE_DEVELOPMENT: 'part-of-the-development',
@@ -181,6 +193,7 @@ export const APPEAL_DOCUMENT_TYPE = Object.freeze({
181
193
  ORIGINAL_APPLICATION_FORM: 'originalApplicationForm',
182
194
  OTHER_NEW_DOCUMENTS: 'otherNewDocuments',
183
195
  OTHER_PARTY_REPRESENTATIONS: 'otherPartyRepresentations',
196
+ OTHER_RELEVANT_MATTERS: 'otherRelevantMatters',
184
197
  OTHER_RELEVANT_POLICIES: 'otherRelevantPolicies',
185
198
  OWNERSHIP_CERTIFICATE: 'ownershipCertificate',
186
199
  PLAN_SHOWING_EXTENT_OF_ORDER: 'planShowingExtentOfOrder',
@@ -190,6 +203,7 @@ export const APPEAL_DOCUMENT_TYPE = Object.freeze({
190
203
  PLANNING_PERMISSION: 'planningPermission',
191
204
  PLANS_DRAWINGS: 'plansDrawings',
192
205
  PRIOR_CORRESPONDENCE_WITH_PINS: 'priorCorrespondenceWithPINS',
206
+ RELATED_APPLICATIONS: 'relatedApplications',
193
207
  RULE_6_PROOF_OF_EVIDENCE: 'rule6ProofOfEvidence',
194
208
  RULE_6_STATEMENT: 'rule6Statement',
195
209
  RULE_6_WITNESSES_EVIDENCE: 'rule6WitnessesEvidence',
@@ -342,6 +356,7 @@ export const APPEAL_TYPE_OF_PLANNING_APPLICATION = Object.freeze({
342
356
  ADVERTISEMENT: 'advertisement',
343
357
  FULL_APPEAL: 'full-appeal',
344
358
  HOUSEHOLDER_PLANNING: 'householder-planning',
359
+ LAWFUL_DEVELOPMENT_CERTIFICATE: 'lawful-development-certificate',
345
360
  LISTED_BUILDING: 'listed-building',
346
361
  MINOR_COMMERCIAL_DEVELOPMENT: 'minor-commercial-development',
347
362
  OUTLINE_PLANNING: 'outline-planning',
package/src/index.cjs CHANGED
@@ -92,6 +92,12 @@ const APPEAL_ALLOCATION_LEVEL = Object.freeze({
92
92
  H: 'H',
93
93
  });
94
94
 
95
+ const APPEAL_APPEAL_UNDER_ACT_SECTION = Object.freeze({
96
+ EXISTING_DEVELOPMENT: 'existing-development',
97
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
98
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
99
+ });
100
+
95
101
  const APPEAL_APPELLANT_PROCEDURE_PREFERENCE = Object.freeze({
96
102
  HEARING: 'hearing',
97
103
  INQUIRY: 'inquiry',
@@ -104,6 +110,12 @@ const APPEAL_APPLICATION_DECISION = Object.freeze({
104
110
  REFUSED: 'refused',
105
111
  });
106
112
 
113
+ const APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = Object.freeze({
114
+ EXISTING_DEVELOPMENT: 'existing-development',
115
+ PROPOSED_CHANGES_TO_A_LISTED_BUILDING: 'proposed-changes-to-a-listed-building',
116
+ PROPOSED_USE_OF_A_DEVELOPMENT: 'proposed-use-of-a-development',
117
+ });
118
+
107
119
  const APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = Object.freeze({
108
120
  ALL_OF_THE_DEVELOPMENT: 'all-of-the-development',
109
121
  PART_OF_THE_DEVELOPMENT: 'part-of-the-development',
@@ -264,6 +276,7 @@ const APPEAL_DOCUMENT_TYPE = Object.freeze({
264
276
  ORIGINAL_APPLICATION_FORM: 'originalApplicationForm',
265
277
  OTHER_NEW_DOCUMENTS: 'otherNewDocuments',
266
278
  OTHER_PARTY_REPRESENTATIONS: 'otherPartyRepresentations',
279
+ OTHER_RELEVANT_MATTERS: 'otherRelevantMatters',
267
280
  OTHER_RELEVANT_POLICIES: 'otherRelevantPolicies',
268
281
  OWNERSHIP_CERTIFICATE: 'ownershipCertificate',
269
282
  PLAN_SHOWING_EXTENT_OF_ORDER: 'planShowingExtentOfOrder',
@@ -273,6 +286,7 @@ const APPEAL_DOCUMENT_TYPE = Object.freeze({
273
286
  PLANNING_PERMISSION: 'planningPermission',
274
287
  PLANS_DRAWINGS: 'plansDrawings',
275
288
  PRIOR_CORRESPONDENCE_WITH_PINS: 'priorCorrespondenceWithPINS',
289
+ RELATED_APPLICATIONS: 'relatedApplications',
276
290
  RULE_6_PROOF_OF_EVIDENCE: 'rule6ProofOfEvidence',
277
291
  RULE_6_STATEMENT: 'rule6Statement',
278
292
  RULE_6_WITNESSES_EVIDENCE: 'rule6WitnessesEvidence',
@@ -425,6 +439,7 @@ const APPEAL_TYPE_OF_PLANNING_APPLICATION = Object.freeze({
425
439
  ADVERTISEMENT: 'advertisement',
426
440
  FULL_APPEAL: 'full-appeal',
427
441
  HOUSEHOLDER_PLANNING: 'householder-planning',
442
+ LAWFUL_DEVELOPMENT_CERTIFICATE: 'lawful-development-certificate',
428
443
  LISTED_BUILDING: 'listed-building',
429
444
  MINOR_COMMERCIAL_DEVELOPMENT: 'minor-commercial-development',
430
445
  OUTLINE_PLANNING: 'outline-planning',
@@ -833,8 +848,10 @@ function loadAllSchemasSync() {
833
848
  }
834
849
 
835
850
  exports.APPEAL_ALLOCATION_LEVEL = APPEAL_ALLOCATION_LEVEL;
851
+ exports.APPEAL_APPEAL_UNDER_ACT_SECTION = APPEAL_APPEAL_UNDER_ACT_SECTION;
836
852
  exports.APPEAL_APPELLANT_PROCEDURE_PREFERENCE = APPEAL_APPELLANT_PROCEDURE_PREFERENCE;
837
853
  exports.APPEAL_APPLICATION_DECISION = APPEAL_APPLICATION_DECISION;
854
+ exports.APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION = APPEAL_APPLICATION_MADE_UNDER_ACT_SECTION;
838
855
  exports.APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT = APPEAL_APPLICATION_PART_OR_WHOLE_DEVELOPMENT;
839
856
  exports.APPEAL_CASE_DECISION_OUTCOME = APPEAL_CASE_DECISION_OUTCOME;
840
857
  exports.APPEAL_CASE_PROCEDURE = APPEAL_CASE_PROCEDURE;
package/src/schemas.d.ts CHANGED
@@ -168,6 +168,8 @@ export interface AppealDocument {
168
168
  | 'groundGSupporting'
169
169
  | 'groundAFeeReceipt'
170
170
  | 'delegatedReport'
171
+ | 'relatedApplications'
172
+ | 'otherRelevantMatters'
171
173
  | null;
172
174
  /**
173
175
  * The system mastering the metadata for the current document
@@ -772,6 +774,7 @@ export type AppealHASCase = (
772
774
  | 'listed-building'
773
775
  | 'minor-commercial-development'
774
776
  | 'advertisement'
777
+ | 'lawful-development-certificate'
775
778
  | null;
776
779
  siteGridReferenceEasting?: string | null;
777
780
  siteGridReferenceNorthing?: string | null;
@@ -1475,6 +1478,7 @@ export type AppealS78Case = (
1475
1478
  | 'listed-building'
1476
1479
  | 'minor-commercial-development'
1477
1480
  | 'advertisement'
1481
+ | 'lawful-development-certificate'
1478
1482
  | null;
1479
1483
  developmentType:
1480
1484
  | 'householder'
@@ -1642,6 +1646,25 @@ export type AppealS78Case = (
1642
1646
  * Have any development rights been restricted by means of a planning condition?
1643
1647
  */
1644
1648
  pcnRestrictedDevelopmentRights?: boolean | null;
1649
+ applicationMadeUnderActSection?:
1650
+ | 'existing-development'
1651
+ | 'proposed-use-of-a-development'
1652
+ | 'proposed-changes-to-a-listed-building'
1653
+ | null;
1654
+ /**
1655
+ * Site use at time of application
1656
+ */
1657
+ siteUseAtTimeOfApplication?: string | null;
1658
+ appealUnderActSection?:
1659
+ | 'existing-development'
1660
+ | 'proposed-use-of-a-development'
1661
+ | 'proposed-changes-to-a-listed-building'
1662
+ | null;
1663
+ lpaConsiderAppealInvalid?: boolean | null;
1664
+ /**
1665
+ * Reason(s) why LPA consider the appeal invalid
1666
+ */
1667
+ lpaAppealInvalidReasons?: string | null;
1645
1668
  [k: string]: unknown;
1646
1669
  };
1647
1670
 
@@ -3423,6 +3446,7 @@ export type AppealRepresentationSubmission = {
3423
3446
  | 'lpaWitnessesEvidence'
3424
3447
  | 'rule6ProofOfEvidence'
3425
3448
  | 'rule6WitnessesEvidence'
3449
+ | 'appellantStatement'
3426
3450
  | null;
3427
3451
  [k: string]: unknown;
3428
3452
  }[];
@@ -3572,6 +3596,7 @@ export type AppellantCommonSubmissionProperties = (
3572
3596
  | 'listed-building'
3573
3597
  | 'minor-commercial-development'
3574
3598
  | 'advertisement'
3599
+ | 'lawful-development-certificate'
3575
3600
  | null;
3576
3601
  /**
3577
3602
  * Indicates if the appellant has applied for costs
@@ -3955,7 +3980,13 @@ export interface AppellantSubmissionCommand {
3955
3980
  | ({
3956
3981
  caseType?: 'C';
3957
3982
  } & AppellantEnforcementSubmissionProperties &
3958
- AppellantProcedurePreferenceProperties);
3983
+ AppellantProcedurePreferenceProperties)
3984
+ | ({
3985
+ caseType?: 'X';
3986
+ } & AppellantCommonSubmissionProperties &
3987
+ AppellantCommonPlanningProperties &
3988
+ AppellantProcedurePreferenceProperties &
3989
+ LDCSpecificProperties);
3959
3990
  documents: {
3960
3991
  /**
3961
3992
  * The unique identifier for the document
@@ -4104,11 +4135,11 @@ export interface AppellantCommonPlanningProperties {
4104
4135
  /**
4105
4136
  * The date of the original LPA application
4106
4137
  */
4107
- applicationDate: string;
4138
+ applicationDate: string | null;
4108
4139
  /**
4109
4140
  * The outcome of the original LPA decision
4110
4141
  */
4111
- applicationDecision: 'granted' | 'refused' | 'not_received';
4142
+ applicationDecision: 'granted' | 'refused' | 'not_received' | null;
4112
4143
  /**
4113
4144
  * The date of the original LPA decision
4114
4145
  */
@@ -4182,6 +4213,21 @@ export interface AdvertSpecificProperties {
4182
4213
  | null;
4183
4214
  [k: string]: unknown;
4184
4215
  }
4216
+ /**
4217
+ * Schema defining any properties for ldc appeals
4218
+ */
4219
+ export interface LDCSpecificProperties {
4220
+ /**
4221
+ * Site use at time of application
4222
+ */
4223
+ siteUseAtTimeOfApplication: string | null;
4224
+ applicationMadeUnderActSection:
4225
+ | 'existing-development'
4226
+ | 'proposed-use-of-a-development'
4227
+ | 'proposed-changes-to-a-listed-building'
4228
+ | null;
4229
+ [k: string]: unknown;
4230
+ }
4185
4231
 
4186
4232
  export type Name = string;
4187
4233
 
@@ -4214,10 +4260,6 @@ export interface Address {
4214
4260
  * Schema defining any HAS specific properties for LPAQ submissions
4215
4261
  */
4216
4262
  export type LPAQHASSubmissionProperties = {
4217
- /**
4218
- * Indicates if the LPA considers the appeal type appropriate
4219
- */
4220
- isCorrectAppealType?: boolean | null;
4221
4263
  /**
4222
4264
  * A list of affected listed building IDs from Historic England
4223
4265
  */
@@ -4488,6 +4530,21 @@ export type LPAQEnforcementSubmissionProperties = {
4488
4530
  */
4489
4531
  article4AffectedDevelopmentRights?: string | null;
4490
4532
  };
4533
+ /**
4534
+ * Schema defining any LDC specific properties for LPAQ submissions
4535
+ */
4536
+ export type LPAQLDCSubmissionProperties = {
4537
+ appealUnderActSection?:
4538
+ | 'existing-development'
4539
+ | 'proposed-use-of-a-development'
4540
+ | 'proposed-changes-to-a-listed-building'
4541
+ | null;
4542
+ lpaConsiderAppealInvalid?: boolean | null;
4543
+ /**
4544
+ * Reason(s) why LPA consider the appeal invalid
4545
+ */
4546
+ lpaAppealInvalidReasons?: string | null;
4547
+ };
4491
4548
 
4492
4549
  /**
4493
4550
  * Schema defining the data produced by the Front-Office when an LPA Questionnaire is submitted
@@ -4541,7 +4598,13 @@ export interface LPAQuestionnaireCommand {
4541
4598
  InfrastructureLevyProperties &
4542
4599
  EnvironmentalImpactAssessmentProperties &
4543
4600
  SiteDesignationsAndProtectionSpecificProperties &
4544
- LPAQEnforcementSubmissionProperties);
4601
+ LPAQEnforcementSubmissionProperties)
4602
+ | ({
4603
+ caseType?: 'X';
4604
+ } & LPAQCommonSubmissionProperties &
4605
+ LPAProcedurePreferenceProperties &
4606
+ InfrastructureLevyProperties &
4607
+ LPAQLDCSubmissionProperties);
4545
4608
  documents: {
4546
4609
  /**
4547
4610
  * The unique identifier for the document
@@ -4609,7 +4672,9 @@ export interface LPAQuestionnaireCommand {
4609
4672
  | 'planningPermission'
4610
4673
  | 'lpaEnforcementNotice'
4611
4674
  | 'lpaEnforcementNoticePlan'
4612
- | 'planningContraventionNotice';
4675
+ | 'planningContraventionNotice'
4676
+ | 'relatedApplications'
4677
+ | 'otherRelevantMatters';
4613
4678
  [k: string]: unknown;
4614
4679
  }[];
4615
4680
  [k: string]: unknown;
@@ -4678,6 +4743,10 @@ export interface LPAQCommonSubmissionProperties {
4678
4743
  * A general reason given for the need to visit any neighbours
4679
4744
  */
4680
4745
  reasonForNeighbourVisits?: string | null;
4746
+ /**
4747
+ * Indicates if the LPA considers the appeal type appropriate
4748
+ */
4749
+ isCorrectAppealType: boolean | null;
4681
4750
  [k: string]: unknown;
4682
4751
  }
4683
4752
 
@@ -161,7 +161,12 @@ const appealS78 = {
161
161
  advertType: 'Other'
162
162
  }
163
163
  ],
164
- padsSapId: null
164
+ padsSapId: null,
165
+ applicationMadeUnderActSection: 'existing-development',
166
+ siteUseAtTimeOfApplication: 'Site use at time of application',
167
+ appealUnderActSection: 'proposed-use-of-a-development',
168
+ lpaConsiderAppealInvalid: true,
169
+ lpaAppealInvalidReasons: 'Reason(s) why LPA consider the appeal invalid'
165
170
  };
166
171
 
167
172
  describe(schema, () => {
@@ -239,4 +244,14 @@ describe(schema, () => {
239
244
  const validationResult = ajv.validate(schema, test);
240
245
  assert.strictEqual(validationResult, false);
241
246
  });
247
+
248
+ const groupBAppealTypes = ['C', 'F', 'H', 'W', 'X', 'Y', 'Z'];
249
+ groupBAppealTypes.forEach((appealType) => {
250
+ it(`should support group B appeal type ${appealType}`, () => {
251
+ const test = structuredClone(appealS78);
252
+ test.caseType = appealType;
253
+ const validationResult = ajv.validate(schema, test);
254
+ assert.strictEqual(validationResult, true);
255
+ });
256
+ });
242
257
  });
@@ -0,0 +1,83 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import Ajv from 'ajv';
4
+ import addFormats from 'ajv-formats';
5
+ import { loadAllSchemasSync } from '../../../src/index.js';
6
+
7
+ const schema = 'lpa-questionnaire.schema.json';
8
+
9
+ const document = {
10
+ documentId: 'deserunt sint aliqua adipisicing dolore',
11
+ filename: 'ut dolore',
12
+ originalFilename: 'Lorem amet fugiat adipisicing Excepteur',
13
+ size: -90476934,
14
+ mime: 'magna labore exercitation ut',
15
+ documentURI: 'ut reprehenderit',
16
+ dateCreated: '1933-04-03T03:24:38.0Z',
17
+ documentType: 'plansDrawings'
18
+ };
19
+
20
+ const exampleHasQuestionnaireSchema = {
21
+ casedata: {
22
+ caseType: 'X',
23
+ caseReference: 'nisi incididunt cillum',
24
+ lpaQuestionnaireSubmittedDate: '2026-04-03T03:24:38.0Z',
25
+ siteAccessDetails: ['test'],
26
+ siteSafetyDetails: ['test 2'],
27
+ isCorrectAppealType: true,
28
+ nearbyCaseReferences: ['1234567', '7654321'],
29
+ neighbouringSiteAddresses: [
30
+ {
31
+ neighbouringSiteAddressLine1: 'commodo dolore incididunt',
32
+ neighbouringSiteAddressLine2: 'est voluptate irure aliqua elit',
33
+ neighbouringSiteAddressTown: 'labore aliquip ex incididunt nulla',
34
+ neighbouringSiteAddressCounty: 'enim ut Duis ut ex',
35
+ neighbouringSiteAddressPostcode: 'pariatur',
36
+ neighbouringSiteAccessDetails: 'aliqua irure mollit consequat nisi',
37
+ neighbouringSiteSafetyDetails: null
38
+ }
39
+ ],
40
+ reasonForNeighbourVisits: 'adipisicing in voluptate',
41
+ hasInfrastructureLevy: true,
42
+ isInfrastructureLevyFormallyAdopted: true,
43
+ infrastructureLevyAdoptedDate: '1913-06-14T10:40:33.0Z',
44
+ infrastructureLevyExpectedDate: '1912-06-14T10:40:33.0Z',
45
+ lpaProcedurePreference: 'inquiry',
46
+ lpaProcedurePreferenceDetails: 'in reprehenderit',
47
+ lpaProcedurePreferenceDuration: -34480053.16630782,
48
+ appealUnderActSection: 'proposed-use-of-a-development',
49
+ lpaConsiderAppealInvalid: true,
50
+ lpaAppealInvalidReasons: 'Reason(s) why LPA consider the appeal invalid'
51
+ },
52
+ documents: [document]
53
+ };
54
+
55
+ describe('LDC questionnaire command schema', () => {
56
+ const schemas = loadAllSchemasSync();
57
+ const flatSchemas = Object.values(schemas).reduce((a, c) => ({ ...a, ...c }), {});
58
+ const ajv = new Ajv({ schemas: flatSchemas, allErrors: true });
59
+ addFormats(ajv);
60
+
61
+ it('should allow valid schema for LDC', () => {
62
+ const validationResult = ajv.validate(schema, exampleHasQuestionnaireSchema);
63
+ assert.strictEqual(validationResult, true);
64
+ });
65
+
66
+ it('should reject missing caseReference', () => {
67
+ const test = structuredClone(exampleHasQuestionnaireSchema);
68
+ delete test.casedata.caseReference;
69
+ const validationResult = ajv.validate(schema, test);
70
+ assert.strictEqual(validationResult, false);
71
+ assert.strictEqual(
72
+ ajv.errors.some((x) => x.message === "must have required property 'caseReference'"),
73
+ true
74
+ );
75
+ });
76
+
77
+ it('should allow additional props', () => {
78
+ const test = structuredClone(exampleHasQuestionnaireSchema);
79
+ test.test = 1;
80
+ const validationResult = ajv.validate(schema, test);
81
+ assert.strictEqual(validationResult, true);
82
+ });
83
+ });
@@ -0,0 +1,172 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import Ajv from 'ajv';
4
+ import addFormats from 'ajv-formats';
5
+ import { loadAllSchemasSync } from '../../../src/index.js';
6
+
7
+ const schema = 'appellant-submission.schema.json';
8
+
9
+ const user = {
10
+ salutation: 'nisi aute tempor Ut',
11
+ firstName: null,
12
+ lastName: null,
13
+ emailAddress: null,
14
+ telephoneNumber: 'irure',
15
+ organisation: null,
16
+ serviceUserType: 'Appellant'
17
+ };
18
+
19
+ const document = {
20
+ documentId: 'Lorem',
21
+ filename: 'sunt',
22
+ originalFilename: 'dolore fugiat',
23
+ size: 663667,
24
+ mime: 'consequat veniam ipsum ullamco sint',
25
+ documentURI: 'reprehenderit',
26
+ dateCreated: '1904-04-10T14:53:32.0Z',
27
+ documentType: 'appellantCaseWithdrawalLetter'
28
+ };
29
+
30
+ const exampleLDCSubmissionSchema = {
31
+ casedata: {
32
+ submissionId: '072a9b08-0266-a291-ecd0-bb0ded9d7350',
33
+ caseType: 'X',
34
+ caseProcedure: 'written',
35
+ lpaCode: 'in laborum pariatur cupidatat',
36
+ caseSubmittedDate: '1920-12-06T17:37:12.0Z',
37
+ enforcementNotice: false,
38
+ applicationReference: 'voluptate esse Excepteur veniam sunt',
39
+ applicationDate: '1921-01-26T02:05:56.0Z',
40
+ applicationDecision: 'not_received',
41
+ applicationDecisionDate: '1890-12-26T17:09:36.0Z',
42
+ caseSubmissionDueDate: null,
43
+ siteAddressLine1: 'exercitation incididunt laborum',
44
+ siteAddressLine2: 'in Ut voluptate ea',
45
+ siteAddressTown: 'Lorem amet consectetur',
46
+ siteAddressCounty: null,
47
+ siteAddressPostcode: 'sunt nulla aliquip labore',
48
+ siteGridReferenceEasting: '357144',
49
+ siteGridReferenceNorthing: '400534',
50
+ siteAccessDetails: null,
51
+ siteSafetyDetails: ['Duis laboris ex', 'sint Lorem cupidatat commodo'],
52
+ isGreenBelt: null,
53
+ originalDevelopmentDescription: null,
54
+ changedDevelopmentDescription: false,
55
+ nearbyCaseReferences: [
56
+ 'enim consectetur irure ad',
57
+ 'irure ut',
58
+ 'irure eiusmod minim Excepteur id',
59
+ 'aliqua pariatur consectetur eiusmod'
60
+ ],
61
+ appellantCostsAppliedFor: true,
62
+ appellantProcedurePreference: 'hearing',
63
+ appellantProcedurePreferenceDetails: 'eiusmod ex exercitation',
64
+ appellantProcedurePreferenceDuration: 10816414.941069126,
65
+ appellantProcedurePreferenceWitnessCount: -91300569.36444478,
66
+ siteUseAtTimeOfApplication: 'residential',
67
+ applicationMadeUnderActSection: 'existing-development'
68
+ },
69
+ documents: [document],
70
+ users: [user]
71
+ };
72
+
73
+ describe('LDC submission command schema', () => {
74
+ const schemas = loadAllSchemasSync();
75
+ const flatSchemas = Object.values(schemas).reduce((a, c) => ({ ...a, ...c }), {});
76
+ const ajv = new Ajv({ schemas: flatSchemas, allErrors: true });
77
+ addFormats(ajv);
78
+
79
+ it('should allow valid schema for LDC', () => {
80
+ const validationResult = ajv.validate(schema, exampleLDCSubmissionSchema);
81
+ assert.strictEqual(validationResult, true);
82
+ });
83
+
84
+ it('should enforce LDC specific props', () => {
85
+ const test = structuredClone(exampleLDCSubmissionSchema);
86
+ delete test.casedata.siteUseAtTimeOfApplication;
87
+ delete test.casedata.applicationMadeUnderActSection;
88
+
89
+ const validationResult = ajv.validate(schema, test);
90
+
91
+ assert.strictEqual(validationResult, false);
92
+ });
93
+
94
+ it('should enforce eastings-northings pattern', () => {
95
+ const invalidPatterns = [
96
+ { easting: 'abc123', northing: '400534', description: 'easting with letters' },
97
+ { easting: '12345678', northing: '400534', description: 'easting too long' },
98
+ { easting: '12345', northing: '400534', description: 'easting too short' },
99
+ { easting: '357144', northing: 'xyz123', description: 'northing with letters' },
100
+ { easting: '357144', northing: '12345678', description: 'northing too long' },
101
+ { easting: '357144', northing: '12345', description: 'northing too short' },
102
+ { easting: '', northing: '400534', description: 'empty easting' },
103
+ { easting: '357144', northing: '', description: 'empty northing' }
104
+ ];
105
+
106
+ for (const pattern of invalidPatterns) {
107
+ const test = structuredClone(exampleLDCSubmissionSchema);
108
+ test.casedata.siteGridReferenceEasting = pattern.easting;
109
+ test.casedata.siteGridReferenceNorthing = pattern.northing;
110
+
111
+ const validationResult = ajv.validate(schema, test);
112
+ assert.strictEqual(validationResult, false, `Expected validation to fail for ${pattern.description}`);
113
+ }
114
+ });
115
+
116
+ it('should allow only eastings-northings', () => {
117
+ const test = structuredClone(exampleLDCSubmissionSchema);
118
+ test.casedata.siteAddressPostcode = undefined;
119
+ test.casedata.siteAddressLine1 = null;
120
+ test.casedata.siteAddressTown = null;
121
+ const validationResult = ajv.validate(schema, test);
122
+ assert.strictEqual(validationResult, true);
123
+ });
124
+
125
+ it('should allow only site address', () => {
126
+ const test = structuredClone(exampleLDCSubmissionSchema);
127
+ test.casedata.siteGridReferenceEasting = undefined;
128
+ test.casedata.siteGridReferenceNorthing = null;
129
+ const validationResult = ajv.validate(schema, test);
130
+ assert.strictEqual(validationResult, true);
131
+ });
132
+
133
+ it('should enforce either site address or easting-northing', () => {
134
+ const test = structuredClone(exampleLDCSubmissionSchema);
135
+ test.casedata.siteAddressPostcode = undefined;
136
+ test.casedata.siteAddressLine1 = null;
137
+ test.casedata.siteAddressTown = null;
138
+ test.casedata.siteGridReferenceEasting = undefined;
139
+ test.casedata.siteGridReferenceNorthing = null;
140
+ const validationResult = ajv.validate(schema, test);
141
+ assert.strictEqual(validationResult, false);
142
+ });
143
+
144
+ it('should reject missing root property', () => {
145
+ const test = structuredClone(exampleLDCSubmissionSchema);
146
+ delete test.casedata.caseType;
147
+ const validationResult = ajv.validate(schema, test);
148
+ assert.strictEqual(validationResult, false);
149
+ assert.strictEqual(
150
+ ajv.errors.some((x) => x.message === "must have required property 'caseType'"),
151
+ true
152
+ );
153
+ });
154
+
155
+ it('should reject missing nested property', () => {
156
+ const test = structuredClone(exampleLDCSubmissionSchema);
157
+ delete test.casedata.caseProcedure;
158
+ const validationResult = ajv.validate(schema, test);
159
+ assert.strictEqual(validationResult, false);
160
+ assert.strictEqual(
161
+ ajv.errors.some((x) => x.message === "must have required property 'caseProcedure'"),
162
+ true
163
+ );
164
+ });
165
+
166
+ it('should allow additional props', () => {
167
+ const test = structuredClone(exampleLDCSubmissionSchema);
168
+ test.test = 1;
169
+ const validationResult = ajv.validate(schema, test);
170
+ assert.strictEqual(validationResult, true);
171
+ });
172
+ });