@planning-inspectorate/data-model 1.20.0 → 1.22.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 (57) hide show
  1. package/docs/README.md +11 -1
  2. package/docs/appeal-has.md +30 -49
  3. package/docs/appeal-s78.md +241 -144
  4. package/docs/pins-inspector-defs-specialism.md +80 -0
  5. package/docs/pins-inspector-defs.md +3 -0
  6. package/docs/pins-inspector.md +311 -3
  7. package/package.json +1 -1
  8. package/pins_data_model/models/model_appeal_document.py +1 -1
  9. package/pins_data_model/models/model_appeal_event.py +1 -1
  10. package/pins_data_model/models/model_appeal_event_estimate.py +1 -1
  11. package/pins_data_model/models/model_appeal_has.py +72 -27
  12. package/pins_data_model/models/model_appeal_representation.py +1 -1
  13. package/pins_data_model/models/model_appeal_s78.py +95 -8
  14. package/pins_data_model/models/model_dart_response.py +1 -1
  15. package/pins_data_model/models/model_entraid.py +1 -1
  16. package/pins_data_model/models/model_folder.py +1 -1
  17. package/pins_data_model/models/model_gettimesheets_response.py +1 -1
  18. package/pins_data_model/models/model_listed_building.py +1 -1
  19. package/pins_data_model/models/model_listed_buildings.py +1 -1
  20. package/pins_data_model/models/model_nsip_document.py +1 -1
  21. package/pins_data_model/models/model_nsip_exam_timetable.py +1 -1
  22. package/pins_data_model/models/model_nsip_project.py +1 -1
  23. package/pins_data_model/models/model_nsip_project_update.py +1 -1
  24. package/pins_data_model/models/model_nsip_representation.py +1 -1
  25. package/pins_data_model/models/model_nsip_subscription.py +1 -1
  26. package/pins_data_model/models/model_pins_inspector.py +75 -6
  27. package/pins_data_model/models/model_pins_lpa.py +1 -1
  28. package/pins_data_model/models/model_s51_advice.py +1 -1
  29. package/pins_data_model/models/model_service_user.py +1 -1
  30. package/schemas/appeal-has.schema.json +52 -21
  31. package/schemas/appeal-s78.schema.json +62 -7
  32. package/schemas/commands/appeals-components/appeal-advert.submission.schema.json +53 -0
  33. package/schemas/commands/{appeal-common-submission.schema.json → appeals-components/appeal-common-submission.schema.json} +8 -8
  34. package/schemas/commands/{appeal-has-submission.schema.json → appeals-components/appeal-has-submission.schema.json} +2 -2
  35. package/schemas/commands/{appeal-s78-submission.schema.json → appeals-components/appeal-s78-submission.schema.json} +2 -2
  36. package/schemas/commands/appeals-components/appellant-procedure-preference.schema.json +37 -0
  37. package/schemas/commands/appeals-components/changed-listed-building-number.schema.json +23 -0
  38. package/schemas/commands/appeals-components/lpa-procedure-preference.schema.json +28 -0
  39. package/schemas/commands/{lpa-questionnaire-cas-advert.schema.json → appeals-components/lpa-questionnaire-advert.schema.json} +8 -33
  40. package/schemas/commands/{lpa-questionnaire-common.schema.json → appeals-components/lpa-questionnaire-common.schema.json} +1 -1
  41. package/schemas/commands/{lpa-questionnaire-has.schema.json → appeals-components/lpa-questionnaire-has.schema.json} +1 -1
  42. package/schemas/commands/{lpa-questionnaire-s78.schema.json → appeals-components/lpa-questionnaire-s78.schema.json} +2 -21
  43. package/schemas/commands/appellant-submission.schema.json +21 -10
  44. package/schemas/commands/lpa-questionnaire.schema.json +24 -10
  45. package/schemas/pins-inspector.schema.json +108 -3
  46. package/src/index.cjs +6 -2
  47. package/src/index.d.ts +4 -0
  48. package/src/index.js +5 -2
  49. package/src/schemas.d.ts +385 -802
  50. package/tests/appeals/appeal-has.test.js +30 -5
  51. package/tests/appeals/appeal-s78.test.js +17 -3
  52. package/tests/appeals/commands/adverts-questionnaire.test.js +1 -0
  53. package/tests/appeals/commands/adverts-submission.test.js +13 -13
  54. package/tests/appeals/commands/cas-adverts-submission.test.js +184 -0
  55. package/tests/appeals/commands/has-submission.test.js +2 -2
  56. package/tests/appeals/commands/s78-submission.test.js +2 -2
  57. package/schemas/commands/appeal-advert.submission.schema.json +0 -23
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: appeal-s78.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-07T15:19:29+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -298,6 +298,38 @@ class DevelopmentType(Enum):
298
298
  NoneType_None = None
299
299
 
300
300
 
301
+ class AdvertType(Enum):
302
+ field_4_6_Sheet_Non_Illuminated = "4-6 Sheet Non-Illuminated"
303
+ field_4_6_Sheet_Illuminated = "4-6 Sheet Illuminated"
304
+ field_12_16_32_Sheet_Non_Illuminated = "12/16/32 Sheet Non-Illuminated"
305
+ field_12_16_32_Sheet_Illuminated = "12/16/32 Sheet Illuminated"
306
+ field_48_64_96_Sheet_Non_Illuminated = "48/64/96 Sheet Non-Illuminated"
307
+ field_48_64_96_Sheet_Illuminated = "48/64/96 Sheet Illuminated"
308
+ Fascia_Projecting_Signs_Non_Illuminated = "Fascia Projecting Signs Non-Illuminated"
309
+ Fascia_Projecting_Signs_Illuminated = "Fascia Projecting Signs Illuminated"
310
+ Directional___Others_Non_Illuminated = "Directional & Others Non-Illuminated"
311
+ Directional___Others_Illuminated = "Directional & Others Illuminated"
312
+ Monolith_Totem_Signs_Non_Illuminated = "Monolith/Totem Signs Non-Illuminated"
313
+ Monolith_Totem_Signs_Illuminated = "Monolith/Totem Signs Illuminated"
314
+ Other = "Other"
315
+ NoneType_None = None
316
+
317
+
318
+ class AdvertDetail(BaseModel):
319
+ model_config = ConfigDict(
320
+ extra="allow",
321
+ )
322
+ advertType: AdvertType
323
+ isAdvertInPosition: bool | None = None
324
+ """
325
+ Is the advertisement in position?
326
+ """
327
+ isSiteOnHighwayLand: bool | None = None
328
+ """
329
+ Is the site on highway land?
330
+ """
331
+
332
+
301
333
  class AppealS78Case1(BaseModel):
302
334
  """
303
335
  Group B - Schema defining the metadata for an appeal
@@ -848,10 +880,10 @@ class AppealS78Case1(BaseModel):
848
880
  """
849
881
  The net gain in residences of the proposed development
850
882
  """
851
- siteGridReferenceEasting: constr(pattern=r"^\d{6}$") | None = Field(
883
+ siteGridReferenceEasting: constr(pattern=r"^\d{6,7}$") = Field(
852
884
  ..., examples=["357144"]
853
885
  )
854
- siteGridReferenceNorthing: constr(pattern=r"^\d{6}$") | None = Field(
886
+ siteGridReferenceNorthing: constr(pattern=r"^\d{6,7}$") = Field(
855
887
  ..., examples=["400534"]
856
888
  )
857
889
  siteViewableFromRoad: bool | None = None
@@ -864,6 +896,41 @@ class AppealS78Case1(BaseModel):
864
896
  planningObligationDueDate: AwareDatetime | None = Field(
865
897
  None, examples=["2023-07-27T20:30:00.000Z"]
866
898
  )
899
+ hasLandownersPermission: bool | None = None
900
+ """
901
+ Does the appellant have the landowners permission
902
+ """
903
+ wasApplicationRefusedDueToHighwayOrTraffic: bool | None = None
904
+ """
905
+ Did the LPA refuse the application because of highway or traffic public safety?
906
+ """
907
+ didAppellantSubmitCompletePhotosAndPlans: bool | None = None
908
+ """
909
+ Did the appellant submit complete photos and plans?
910
+ """
911
+ isSiteInAreaOfSpecialControlAdverts: bool | None = None
912
+ """
913
+ Is the site in an area of special control of advertisements?
914
+ """
915
+ advertDetails: list[AdvertDetail] | None = None
916
+ """
917
+ A list of advertisements for the appeal
918
+ """
919
+
920
+
921
+ class AdvertDetail1(BaseModel):
922
+ model_config = ConfigDict(
923
+ extra="allow",
924
+ )
925
+ advertType: AdvertType
926
+ isAdvertInPosition: bool | None = None
927
+ """
928
+ Is the advertisement in position?
929
+ """
930
+ isSiteOnHighwayLand: bool | None = None
931
+ """
932
+ Is the site on highway land?
933
+ """
867
934
 
868
935
 
869
936
  class AppealS78Case2(BaseModel):
@@ -1100,7 +1167,7 @@ class AppealS78Case2(BaseModel):
1100
1167
  """
1101
1168
  The statutory deadline for submitting an appeal from the original LPA decision date
1102
1169
  """
1103
- siteAddressLine1: str | None = Field(..., examples=["96 The Avenue"])
1170
+ siteAddressLine1: str = Field(..., examples=["96 The Avenue"])
1104
1171
  """
1105
1172
  First line of address for the appeal site
1106
1173
  """
@@ -1108,7 +1175,7 @@ class AppealS78Case2(BaseModel):
1108
1175
  """
1109
1176
  Second line of address for the appeal site
1110
1177
  """
1111
- siteAddressTown: str | None = Field(..., examples=["Maidstone"])
1178
+ siteAddressTown: str = Field(..., examples=["Maidstone"])
1112
1179
  """
1113
1180
  Town / City of the site address
1114
1181
  """
@@ -1116,7 +1183,7 @@ class AppealS78Case2(BaseModel):
1116
1183
  """
1117
1184
  County of the site address
1118
1185
  """
1119
- siteAddressPostcode: str | None = Field(..., examples=["MD21 5XY"])
1186
+ siteAddressPostcode: str = Field(..., examples=["MD21 5XY"])
1120
1187
  """
1121
1188
  Postal code of the site address
1122
1189
  """
@@ -1416,10 +1483,10 @@ class AppealS78Case2(BaseModel):
1416
1483
  """
1417
1484
  The net gain in residences of the proposed development
1418
1485
  """
1419
- siteGridReferenceEasting: constr(pattern=r"^\d{6}$") | None = Field(
1486
+ siteGridReferenceEasting: constr(pattern=r"^\d{6,7}$") | None = Field(
1420
1487
  None, examples=["357144"]
1421
1488
  )
1422
- siteGridReferenceNorthing: constr(pattern=r"^\d{6}$") | None = Field(
1489
+ siteGridReferenceNorthing: constr(pattern=r"^\d{6,7}$") | None = Field(
1423
1490
  None, examples=["400534"]
1424
1491
  )
1425
1492
  siteViewableFromRoad: bool | None = None
@@ -1432,6 +1499,26 @@ class AppealS78Case2(BaseModel):
1432
1499
  planningObligationDueDate: AwareDatetime | None = Field(
1433
1500
  None, examples=["2023-07-27T20:30:00.000Z"]
1434
1501
  )
1502
+ hasLandownersPermission: bool | None = None
1503
+ """
1504
+ Does the appellant have the landowners permission
1505
+ """
1506
+ wasApplicationRefusedDueToHighwayOrTraffic: bool | None = None
1507
+ """
1508
+ Did the LPA refuse the application because of highway or traffic public safety?
1509
+ """
1510
+ didAppellantSubmitCompletePhotosAndPlans: bool | None = None
1511
+ """
1512
+ Did the appellant submit complete photos and plans?
1513
+ """
1514
+ isSiteInAreaOfSpecialControlAdverts: bool | None = None
1515
+ """
1516
+ Is the site in an area of special control of advertisements?
1517
+ """
1518
+ advertDetails: list[AdvertDetail1] | None = None
1519
+ """
1520
+ A list of advertisements for the appeal
1521
+ """
1435
1522
 
1436
1523
 
1437
1524
  class AppealS78Case(RootModel[AppealS78Case1 | AppealS78Case2]):
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: dart-response.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: entraid.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: folder.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: gettimesheets-response.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: listed-building.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: listed-buildings.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-document.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-exam-timetable.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-project.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-project-update.schema.json
3
- # timestamp: 2025-10-30T20:02:31+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-representation.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-subscription.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,21 +1,58 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: pins-inspector.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- from pydantic import BaseModel, ConfigDict
7
+ from pydantic import AwareDatetime, BaseModel, ConfigDict, EmailStr, Field
8
+
9
+
10
+ class Address(BaseModel):
11
+ model_config = ConfigDict(
12
+ extra="allow",
13
+ )
14
+ addressLine1: str | None = None
15
+ addressLine2: str | None = None
16
+ townCity: str | None = None
17
+ county: str | None = None
18
+ postcode: str | None = None
19
+
20
+
21
+ class Specialism(BaseModel):
22
+ model_config = ConfigDict(
23
+ extra="allow",
24
+ )
25
+ name: str = Field(..., examples=["S62A Casework Major"])
26
+ """
27
+ Working above band is stored as a specialism
28
+ """
29
+ proficiency: str | None = Field(..., examples=["trained"])
30
+ """
31
+ trained or in-training
32
+ """
33
+ validFrom: AwareDatetime | None = Field(..., examples=["2023-07-27T20:30:00.000Z"])
34
+ """
35
+ Date training started or date training was completed.
36
+ """
8
37
 
9
38
 
10
39
  class PinsInspector(BaseModel):
11
40
  """
12
- Inspector attributes as per Horizon. This will be extended with SAP/Entra data
41
+ Inspector Details originating from Horizon, SAP HR and Entra.
13
42
  """
14
43
 
15
44
  model_config = ConfigDict(
16
45
  extra="allow",
17
46
  )
18
- horizonId: str
47
+ entraId: str | None = Field(..., examples=["00000000-0000-0000-0000-000000000000"])
48
+ """
49
+ EntraID of the Inspector if available in ODW.
50
+ """
51
+ sapId: str | None = Field(..., examples=["12345678"])
52
+ """
53
+ SAPID of the Inspector if available in ODW.
54
+ """
55
+ horizonId: str | None = None
19
56
  """
20
57
  The PINS-generated unique horizon ID
21
58
  """
@@ -47,7 +84,39 @@ class PinsInspector(BaseModel):
47
84
  """
48
85
  The qualifications of the inspector
49
86
  """
50
- email: str | None = None
87
+ email: EmailStr | None = Field(
88
+ ..., examples=["example@planninginspectorate.gov.uk"]
89
+ )
90
+ """
91
+ PINS Email address for the Inspector
92
+ """
93
+ grade: str = Field(..., examples=["B1"])
94
+ """
95
+ Grades as a coded value e.g. B1, B2, B3, FTC-B1, FTC-B2, FTC-B3, PL
96
+ """
97
+ fte: float = Field(..., examples=[0.75])
98
+ """
99
+ FTE Decimal value e.g. 1, 0.5 etc
100
+ """
101
+ unit: str = Field(..., examples=["Operations"])
102
+ """
103
+ The personnel area of the Inspector
104
+ """
105
+ service: str = Field(..., examples=["Planning and Environmental Appeals Service"])
106
+ """
107
+ The personnel sub area of the Inspector
108
+ """
109
+ group: str = Field(..., examples=["Enforcement Groups"])
110
+ """
111
+ Group of the Inspector
112
+ """
113
+ inspectorManager: str = Field(..., examples=["Dan Brown"])
114
+ """
115
+ Name of the Inspector's manager.
116
+ """
117
+ validFrom: AwareDatetime | None = Field(None, examples=["2023-07-27T20:30:00.000Z"])
51
118
  """
52
- The email address of the inspector
119
+ Date the Inspector record was first recorded.
53
120
  """
121
+ address: Address
122
+ specialisms: list[Specialism]
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: pins-lpa.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: s51-advice.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: service-user.schema.json
3
- # timestamp: 2025-10-30T20:02:32+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -78,16 +78,16 @@
78
78
  {
79
79
  "required": ["siteGridReferenceEasting", "siteGridReferenceNorthing"],
80
80
  "properties": {
81
- "siteGridReferenceEasting": { "not": { "type": "null" } },
82
- "siteGridReferenceNorthing": { "not": { "type": "null" } }
81
+ "siteGridReferenceEasting": { "type": "string" },
82
+ "siteGridReferenceNorthing": { "type": "string" }
83
83
  }
84
84
  },
85
85
  {
86
86
  "required": ["siteAddressLine1", "siteAddressTown", "siteAddressPostcode"],
87
87
  "properties": {
88
- "siteAddressLine1": { "not": { "type": "null" } },
89
- "siteAddressTown": { "not": { "type": "null" } },
90
- "siteAddressPostcode": { "not": { "type": "null" } }
88
+ "siteAddressLine1": { "type": "string" },
89
+ "siteAddressTown": { "type": "string" },
90
+ "siteAddressPostcode": { "type": "string" }
91
91
  }
92
92
  }
93
93
  ],
@@ -701,37 +701,68 @@
701
701
  },
702
702
  "siteGridReferenceEasting": {
703
703
  "type": ["string", "null"],
704
- "pattern": "^\\d{6}$",
704
+ "pattern": "^\\d{6,7}$",
705
705
  "examples": ["357144"]
706
706
  },
707
707
  "siteGridReferenceNorthing": {
708
708
  "type": ["string", "null"],
709
- "pattern": "^\\d{6}$",
709
+ "pattern": "^\\d{6,7}$",
710
710
  "examples": ["400534"]
711
711
  },
712
712
  "hasLandownersPermission": {
713
713
  "type": ["boolean", "null"],
714
- "description": "Indicates if the appellant has land owners permission"
715
- },
716
- "isAdvertInPosition": {
717
- "type": ["boolean", "null"],
718
- "description": "Indicates if the advert is already in position"
719
- },
720
- "isSiteInAreaOfSpecialControlAdverts": {
721
- "type": ["boolean", "null"],
722
- "description": "Indicates if the site is in an area of special control for adverts"
714
+ "description": "Does the appellant have the landowners permission"
723
715
  },
724
716
  "wasApplicationRefusedDueToHighwayOrTraffic": {
725
717
  "type": ["boolean", "null"],
726
- "description": "Indicates if the application was refused because of highway or traffic public safety?"
718
+ "description": "Did the LPA refuse the application because of highway or traffic public safety?"
727
719
  },
728
720
  "didAppellantSubmitCompletePhotosAndPlans": {
729
721
  "type": ["boolean", "null"],
730
- "description": "Indicates if the appellant submitted complete and accurate photographs and plans"
722
+ "description": "Did the appellant submit complete photos and plans?"
731
723
  },
732
- "advertType": {
733
- "type": ["string", "null"],
734
- "$comment": "Pick from a TBD list of reference data for advert type"
724
+ "isSiteInAreaOfSpecialControlAdverts": {
725
+ "type": ["boolean", "null"],
726
+ "description": "Is the site in an area of special control of advertisements?"
727
+ },
728
+ "advertDetails": {
729
+ "type": ["array", "null"],
730
+ "items": {
731
+ "type": "object",
732
+ "additionalProperties": true,
733
+ "properties": {
734
+ "advertType": {
735
+ "type": ["string", "null"],
736
+ "enum": [
737
+ "4-6 Sheet Non-Illuminated",
738
+ "4-6 Sheet Illuminated",
739
+ "12/16/32 Sheet Non-Illuminated",
740
+ "12/16/32 Sheet Illuminated",
741
+ "48/64/96 Sheet Non-Illuminated",
742
+ "48/64/96 Sheet Illuminated",
743
+ "Fascia Projecting Signs Non-Illuminated",
744
+ "Fascia Projecting Signs Illuminated",
745
+ "Directional & Others Non-Illuminated",
746
+ "Directional & Others Illuminated",
747
+ "Monolith/Totem Signs Non-Illuminated",
748
+ "Monolith/Totem Signs Illuminated",
749
+ "Other",
750
+ null
751
+ ]
752
+ },
753
+ "isAdvertInPosition": {
754
+ "type": ["boolean", "null"],
755
+ "description": "Is the advertisement in position?"
756
+ },
757
+ "isSiteOnHighwayLand": {
758
+ "type": ["boolean", "null"],
759
+ "description": "Is the site on highway land?"
760
+ }
761
+ },
762
+ "required": ["advertType", "isAdvertInPosition", "isSiteOnHighwayLand"]
763
+ },
764
+ "description": "A list of advertisements for the appeal",
765
+ "$comment": "Also available on CAS Adverts (ZA) cases"
735
766
  }
736
767
  }
737
768
  }
@@ -136,16 +136,16 @@
136
136
  {
137
137
  "required": ["siteGridReferenceEasting", "siteGridReferenceNorthing"],
138
138
  "properties": {
139
- "siteGridReferenceEasting": { "not": { "type": "null" } },
140
- "siteGridReferenceNorthing": { "not": { "type": "null" } }
139
+ "siteGridReferenceEasting": { "type": "string" },
140
+ "siteGridReferenceNorthing": { "type": "string" }
141
141
  }
142
142
  },
143
143
  {
144
144
  "required": ["siteAddressLine1", "siteAddressTown", "siteAddressPostcode"],
145
145
  "properties": {
146
- "siteAddressLine1": { "not": { "type": "null" } },
147
- "siteAddressTown": { "not": { "type": "null" } },
148
- "siteAddressPostcode": { "not": { "type": "null" } }
146
+ "siteAddressLine1": { "type": "string" },
147
+ "siteAddressTown": { "type": "string" },
148
+ "siteAddressPostcode": { "type": "string" }
149
149
  }
150
150
  }
151
151
  ],
@@ -973,12 +973,12 @@
973
973
  },
974
974
  "siteGridReferenceEasting": {
975
975
  "type": ["string", "null"],
976
- "pattern": "^\\d{6}$",
976
+ "pattern": "^\\d{6,7}$",
977
977
  "examples": ["357144"]
978
978
  },
979
979
  "siteGridReferenceNorthing": {
980
980
  "type": ["string", "null"],
981
- "pattern": "^\\d{6}$",
981
+ "pattern": "^\\d{6,7}$",
982
982
  "examples": ["400534"]
983
983
  },
984
984
  "siteViewableFromRoad": {
@@ -1032,6 +1032,61 @@
1032
1032
  "type": ["string", "null"],
1033
1033
  "format": "date-time",
1034
1034
  "examples": ["2023-07-27T20:30:00.000Z"]
1035
+ },
1036
+ "hasLandownersPermission": {
1037
+ "type": ["boolean", "null"],
1038
+ "description": "Does the appellant have the landowners permission"
1039
+ },
1040
+ "wasApplicationRefusedDueToHighwayOrTraffic": {
1041
+ "type": ["boolean", "null"],
1042
+ "description": "Did the LPA refuse the application because of highway or traffic public safety?"
1043
+ },
1044
+ "didAppellantSubmitCompletePhotosAndPlans": {
1045
+ "type": ["boolean", "null"],
1046
+ "description": "Did the appellant submit complete photos and plans?"
1047
+ },
1048
+ "isSiteInAreaOfSpecialControlAdverts": {
1049
+ "type": ["boolean", "null"],
1050
+ "description": "Is the site in an area of special control of advertisements?"
1051
+ },
1052
+ "advertDetails": {
1053
+ "type": ["array", "null"],
1054
+ "items": {
1055
+ "type": "object",
1056
+ "additionalProperties": true,
1057
+ "properties": {
1058
+ "advertType": {
1059
+ "type": ["string", "null"],
1060
+ "enum": [
1061
+ "4-6 Sheet Non-Illuminated",
1062
+ "4-6 Sheet Illuminated",
1063
+ "12/16/32 Sheet Non-Illuminated",
1064
+ "12/16/32 Sheet Illuminated",
1065
+ "48/64/96 Sheet Non-Illuminated",
1066
+ "48/64/96 Sheet Illuminated",
1067
+ "Fascia Projecting Signs Non-Illuminated",
1068
+ "Fascia Projecting Signs Illuminated",
1069
+ "Directional & Others Non-Illuminated",
1070
+ "Directional & Others Illuminated",
1071
+ "Monolith/Totem Signs Non-Illuminated",
1072
+ "Monolith/Totem Signs Illuminated",
1073
+ "Other",
1074
+ null
1075
+ ]
1076
+ },
1077
+ "isAdvertInPosition": {
1078
+ "type": ["boolean", "null"],
1079
+ "description": "Is the advertisement in position?"
1080
+ },
1081
+ "isSiteOnHighwayLand": {
1082
+ "type": ["boolean", "null"],
1083
+ "description": "Is the site on highway land?"
1084
+ }
1085
+ },
1086
+ "required": ["advertType", "isAdvertInPosition", "isSiteOnHighwayLand"]
1087
+ },
1088
+ "description": "A list of advertisements for the appeal",
1089
+ "$comment": "Also available on CAS Adverts (ZA) cases"
1035
1090
  }
1036
1091
  }
1037
1092
  }