@planning-inspectorate/data-model 1.19.0 → 1.21.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 (39) hide show
  1. package/docs/README.md +27 -1
  2. package/docs/nsip-project-defs-invoice.md +267 -0
  3. package/docs/nsip-project-defs-meeting.md +122 -0
  4. package/docs/nsip-project-defs.md +3 -0
  5. package/docs/nsip-project.md +1889 -7
  6. package/docs/pins-inspector-defs-specialism.md +80 -0
  7. package/docs/pins-inspector-defs.md +3 -0
  8. package/docs/pins-inspector.md +311 -3
  9. package/package.json +2 -2
  10. package/pins_data_model/models/model_appeal_document.py +1 -1
  11. package/pins_data_model/models/model_appeal_event.py +1 -1
  12. package/pins_data_model/models/model_appeal_event_estimate.py +1 -1
  13. package/pins_data_model/models/model_appeal_has.py +1 -1
  14. package/pins_data_model/models/model_appeal_representation.py +1 -1
  15. package/pins_data_model/models/model_appeal_s78.py +1 -1
  16. package/pins_data_model/models/model_dart_response.py +1 -1
  17. package/pins_data_model/models/model_entraid.py +1 -1
  18. package/pins_data_model/models/model_folder.py +1 -1
  19. package/pins_data_model/models/model_gettimesheets_response.py +1 -1
  20. package/pins_data_model/models/model_listed_building.py +1 -1
  21. package/pins_data_model/models/model_listed_buildings.py +1 -1
  22. package/pins_data_model/models/model_nsip_document.py +1 -1
  23. package/pins_data_model/models/model_nsip_exam_timetable.py +1 -1
  24. package/pins_data_model/models/model_nsip_project.py +535 -3
  25. package/pins_data_model/models/model_nsip_project_update.py +1 -1
  26. package/pins_data_model/models/model_nsip_representation.py +1 -1
  27. package/pins_data_model/models/model_nsip_subscription.py +1 -1
  28. package/pins_data_model/models/model_pins_inspector.py +75 -6
  29. package/pins_data_model/models/model_pins_lpa.py +1 -1
  30. package/pins_data_model/models/model_s51_advice.py +1 -1
  31. package/pins_data_model/models/model_service_user.py +1 -1
  32. package/schemas/nsip-project.schema.json +420 -2
  33. package/schemas/pins-inspector.schema.json +108 -3
  34. package/src/enums.cjs +678 -581
  35. package/src/enums.d.ts +668 -583
  36. package/src/enums.js +668 -583
  37. package/src/index.cjs +678 -581
  38. package/src/lib/gen-enums.js +1 -1
  39. package/src/schemas.d.ts +353 -6
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-project.schema.json
3
- # timestamp: 2025-08-29T10:40:44+00:00
3
+ # timestamp: 2025-11-04T12:34:00+00:00
4
4
 
5
5
  from __future__ import annotations
6
6
 
@@ -12,12 +12,17 @@ from pydantic import AwareDatetime, BaseModel, ConfigDict, Field
12
12
 
13
13
  class Decision(Enum):
14
14
  """
15
- Decision: approved/refused/split-decision
15
+ Decision outcome: approved/refused/split-decision/granted/partially_consented/quashed/redetermination/withdrawn
16
16
  """
17
17
 
18
18
  approved = "approved"
19
19
  refused = "refused"
20
20
  split_decision = "split-decision"
21
+ granted = "granted"
22
+ partially_consented = "partially_consented"
23
+ quashed = "quashed"
24
+ redetermination = "redetermination"
25
+ withdrawn = "withdrawn"
21
26
  NoneType_None = None
22
27
 
23
28
 
@@ -136,6 +141,254 @@ class MapZoomLevel(Enum):
136
141
  NoneType_None = None
137
142
 
138
143
 
144
+ class Recommendation(Enum):
145
+ """
146
+ Recommendation
147
+ """
148
+
149
+ recommend_consent = "recommend_consent"
150
+ recommend_partial_consent = "recommend_partial_consent"
151
+ recommend_refusal = "recommend_refusal"
152
+ NoneType_None = None
153
+
154
+
155
+ class Tier(Enum):
156
+ """
157
+ Tier
158
+ """
159
+
160
+ basic = "basic"
161
+ standard = "standard"
162
+ enhanced = "enhanced"
163
+ NoneType_None = None
164
+
165
+
166
+ class PrincipalAreaDisagreementSummaryStmt(Enum):
167
+ """
168
+ Principal area disagreement summary statement (PADSS)
169
+ """
170
+
171
+ submitted_by_applicant = "submitted_by_applicant"
172
+ awaiting_submission = "awaiting_submission"
173
+ not_applicable = "not_applicable"
174
+ NoneType_None = None
175
+
176
+
177
+ class PolicyComplianceDocument(Enum):
178
+ """
179
+ Policy compliance document (PCD)
180
+ """
181
+
182
+ submitted_by_applicant = "submitted_by_applicant"
183
+ awaiting_submission = "awaiting_submission"
184
+ not_applicable = "not_applicable"
185
+ NoneType_None = None
186
+
187
+
188
+ class DesignApproachDocument(Enum):
189
+ """
190
+ Design approach document (DAD)
191
+ """
192
+
193
+ submitted_by_applicant = "submitted_by_applicant"
194
+ awaiting_submission = "awaiting_submission"
195
+ not_applicable = "not_applicable"
196
+ NoneType_None = None
197
+
198
+
199
+ class MatureOutlineControlDocument(Enum):
200
+ """
201
+ Mature outline control documents
202
+ """
203
+
204
+ submitted_by_applicant = "submitted_by_applicant"
205
+ awaiting_submission = "awaiting_submission"
206
+ not_applicable = "not_applicable"
207
+ NoneType_None = None
208
+
209
+
210
+ class CaAndTpEvidence(Enum):
211
+ """
212
+ CA and TP evidence
213
+ """
214
+
215
+ submitted_by_applicant = "submitted_by_applicant"
216
+ awaiting_submission = "awaiting_submission"
217
+ not_applicable = "not_applicable"
218
+ NoneType_None = None
219
+
220
+
221
+ class PublicSectorEqualityDuty(Enum):
222
+ """
223
+ Public sector equality duty (PSED)
224
+ """
225
+
226
+ submitted_by_applicant = "submitted_by_applicant"
227
+ awaiting_submission = "awaiting_submission"
228
+ not_applicable = "not_applicable"
229
+ NoneType_None = None
230
+
231
+
232
+ class FastTrackAdmissionDocument(Enum):
233
+ """
234
+ Fast track admission document
235
+ """
236
+
237
+ submitted_by_applicant = "submitted_by_applicant"
238
+ awaiting_submission = "awaiting_submission"
239
+ not_applicable = "not_applicable"
240
+ NoneType_None = None
241
+
242
+
243
+ class MultipartyApplicationCheckDocument(Enum):
244
+ """
245
+ Multiparty application readiness gate-check (trial)
246
+ """
247
+
248
+ submitted_by_applicant = "submitted_by_applicant"
249
+ awaiting_submission = "awaiting_submission"
250
+ not_applicable = "not_applicable"
251
+ NoneType_None = None
252
+
253
+
254
+ class SubProjectType(Enum):
255
+ """
256
+ Project type
257
+ """
258
+
259
+ energy_from_waste = "energy_from_waste"
260
+ gas_power_station = "gas_power_station"
261
+ hydrogen_power_station = "hydrogen_power_station"
262
+ nuclear = "nuclear"
263
+ offshore_wind = "offshore_wind"
264
+ onshore_wind = "onshore_wind"
265
+ solar = "solar"
266
+ NoneType_None = None
267
+
268
+
269
+ class NewMaturity(Enum):
270
+ """
271
+ New maturity
272
+ """
273
+
274
+ a = "a"
275
+ b = "b"
276
+ c = "c"
277
+ d = "d"
278
+ e = "e"
279
+ f = "f"
280
+ g = "g"
281
+ NoneType_None = None
282
+
283
+
284
+ class PlanningInspectorateRole(Enum):
285
+ """
286
+ Planning Inspectorate role
287
+ """
288
+
289
+ facilitator = "facilitator"
290
+ advisor = "advisor"
291
+ observer = "observer"
292
+ NoneType_None = None
293
+
294
+
295
+ class Meeting(BaseModel):
296
+ """
297
+ A meeting related to the project
298
+ """
299
+
300
+ model_config = ConfigDict(
301
+ extra="allow",
302
+ )
303
+ meetingAgenda: str | None = Field(None, examples=["Flood Risk Assessment (FRA)"])
304
+ """
305
+ Meeting agenda
306
+ """
307
+ planningInspectorateRole: PlanningInspectorateRole | None = Field(
308
+ None, examples=["facilitator"]
309
+ )
310
+ """
311
+ Planning Inspectorate role
312
+ """
313
+ meetingDate: AwareDatetime | None = Field(
314
+ None, examples=["2023-07-27T20:30:00.000Z"]
315
+ )
316
+ """
317
+ Meeting date
318
+ """
319
+ meetingType: str | None = None
320
+ """
321
+ Type of Meeting
322
+ """
323
+
324
+
325
+ class InvoiceStage(Enum):
326
+ """
327
+ Invoice stage
328
+ """
329
+
330
+ pre_acceptance = "pre_acceptance"
331
+ acceptance = "acceptance"
332
+ pre_examination = "pre_examination"
333
+ initial_examination = "initial_examination"
334
+ final_examination = "final_examination"
335
+ NoneType_None = None
336
+
337
+
338
+ class Invoice(BaseModel):
339
+ """
340
+ An invoice related to the project
341
+ """
342
+
343
+ model_config = ConfigDict(
344
+ extra="allow",
345
+ )
346
+ invoiceStage: InvoiceStage | None = Field(None, examples=["pre_acceptance"])
347
+ """
348
+ Invoice stage
349
+ """
350
+ invoiceNumber: str = Field(..., examples=["1800004419"])
351
+ """
352
+ Invoice number
353
+ """
354
+ amountDue: float = Field(..., examples=[500])
355
+ """
356
+ Amount due
357
+ """
358
+ paymentDueDate: AwareDatetime | None = Field(
359
+ None, examples=["2023-07-27T20:30:00.000Z"]
360
+ )
361
+ """
362
+ Payment due date
363
+ """
364
+ invoicedDate: AwareDatetime | None = Field(
365
+ None, examples=["2023-07-27T20:30:00.000Z"]
366
+ )
367
+ """
368
+ Invoiced date
369
+ """
370
+ paymentDate: AwareDatetime | None = Field(
371
+ None, examples=["2023-07-27T20:30:00.000Z"]
372
+ )
373
+ """
374
+ Date of payment
375
+ """
376
+ refundCreditNoteNumber: str | None = Field(None, examples=["1800004419"])
377
+ """
378
+ Refund credit note number
379
+ """
380
+ refundAmount: float | None = Field(None, examples=[200])
381
+ """
382
+ Amount refunded
383
+ """
384
+ refundIssueDate: AwareDatetime | None = Field(
385
+ None, examples=["2023-07-27T20:30:00.000Z"]
386
+ )
387
+ """
388
+ Refund issue date
389
+ """
390
+
391
+
139
392
  class NsipProject(BaseModel):
140
393
  """
141
394
  Subset of Pins Data Model [Case]
@@ -168,7 +421,7 @@ class NsipProject(BaseModel):
168
421
  projectDescriptionWelsh: str | None = None
169
422
  decision: Decision
170
423
  """
171
- Decision: approved/refused/split-decision
424
+ Decision outcome: approved/refused/split-decision/granted/partially_consented/quashed/redetermination/withdrawn
172
425
  """
173
426
  publishStatus: PublishStatus
174
427
  sector: Sector
@@ -486,3 +739,282 @@ class NsipProject(BaseModel):
486
739
  """
487
740
  Is this an application for a material change?
488
741
  """
742
+ courtDecisionDate: AwareDatetime | None = Field(
743
+ None, examples=["2023-07-27T20:30:00.000Z"]
744
+ )
745
+ """
746
+ Date of court decision
747
+ """
748
+ courtDecisionOutcomeText: str | None = Field(None, examples=["upheld"])
749
+ """
750
+ Court decision outcome text; values include 'upheld','partially_upheld','quashed','other:<Text>'
751
+ """
752
+ decisionChallengeSubmissionDate: AwareDatetime | None = Field(
753
+ None, examples=["2023-07-27T20:30:00.000Z"]
754
+ )
755
+ """
756
+ Date of decision challenge submission
757
+ """
758
+ recommendation: Recommendation | None = Field(None, examples=["recommend_consent"])
759
+ """
760
+ Recommendation
761
+ """
762
+ inceptionMeetingDate: AwareDatetime | None = Field(
763
+ None, examples=["2023-07-27T20:30:00.000Z"]
764
+ )
765
+ """
766
+ Date of inception meeting
767
+ """
768
+ draftDocumentSubmissionDate: AwareDatetime | None = Field(
769
+ None, examples=["2023-07-27T20:30:00.000Z"]
770
+ )
771
+ """
772
+ Date for submission of draft documents
773
+ """
774
+ programmeDocumentSubmissionDate: AwareDatetime | None = Field(
775
+ None, examples=["2023-07-27T20:30:00.000Z"]
776
+ )
777
+ """
778
+ Programme document submission date
779
+ """
780
+ tier: Tier | None = Field(None, examples=["basic"])
781
+ """
782
+ Tier
783
+ """
784
+ s61SummaryURI: str | None = Field(None, examples=["s61.sharepoint.com/"])
785
+ """
786
+ Link to s61 summary
787
+ """
788
+ estimatedScopingSubmissionDate: AwareDatetime | None = Field(
789
+ None, examples=["2023-07-27T20:30:00.000Z"]
790
+ )
791
+ """
792
+ Estimated scoping submission date
793
+ """
794
+ consultationMilestoneAdequacyDate: AwareDatetime | None = Field(
795
+ None, examples=["2023-07-27T20:30:00.000Z"]
796
+ )
797
+ """
798
+ Adequacy of Consultation Milestone
799
+ """
800
+ planProcessEvidence: bool | None = Field(None, examples=[True])
801
+ """
802
+ Evidence plan process
803
+ """
804
+ issuesTracker: str | None = Field(None, examples=["tracker.sharepoint.com/"])
805
+ """
806
+ Issues tracker
807
+ """
808
+ essentialFastTrackComponents: bool | None = Field(None, examples=[True])
809
+ """
810
+ Essential fast track components
811
+ """
812
+ principalAreaDisagreementSummaryStmt: (
813
+ PrincipalAreaDisagreementSummaryStmt | None
814
+ ) = Field(None, examples=["submitted_by_applicant"])
815
+ """
816
+ Principal area disagreement summary statement (PADSS)
817
+ """
818
+ principalAreaDisagreementSummaryStmtSubmittedDate: AwareDatetime | None = Field(
819
+ None, examples=["2023-07-27T20:30:00.000Z"]
820
+ )
821
+ """
822
+ Principal area disagreement summary statement (PADSS) Submitted date
823
+ """
824
+ policyComplianceDocument: PolicyComplianceDocument | None = Field(
825
+ None, examples=["submitted_by_applicant"]
826
+ )
827
+ """
828
+ Policy compliance document (PCD)
829
+ """
830
+ policyComplianceDocumentSubmittedDate: AwareDatetime | None = Field(
831
+ None, examples=["2023-07-27T20:30:00.000Z"]
832
+ )
833
+ """
834
+ Policy compliance document (PCD) Submitted Date
835
+ """
836
+ designApproachDocument: DesignApproachDocument | None = Field(
837
+ None, examples=["submitted_by_applicant"]
838
+ )
839
+ """
840
+ Design approach document (DAD)
841
+ """
842
+ designApproachDocumentSubmittedDate: AwareDatetime | None = Field(
843
+ None, examples=["2023-07-27T20:30:00.000Z"]
844
+ )
845
+ """
846
+ Design approach document (DAD) Submitted Date
847
+ """
848
+ matureOutlineControlDocument: MatureOutlineControlDocument | None = Field(
849
+ None, examples=["submitted_by_applicant"]
850
+ )
851
+ """
852
+ Mature outline control documents
853
+ """
854
+ matureOutlineControlDocumentSubmittedDate: AwareDatetime | None = Field(
855
+ None, examples=["2023-07-27T20:30:00.000Z"]
856
+ )
857
+ """
858
+ Mature outline control documents Submitted Date
859
+ """
860
+ caAndTpEvidence: CaAndTpEvidence | None = Field(
861
+ None, examples=["submitted_by_applicant"]
862
+ )
863
+ """
864
+ CA and TP evidence
865
+ """
866
+ caAndTpEvidenceSubmittedDate: AwareDatetime | None = Field(
867
+ None, examples=["2023-07-27T20:30:00.000Z"]
868
+ )
869
+ """
870
+ CA and TP evidence Submitted Date
871
+ """
872
+ publicSectorEqualityDuty: PublicSectorEqualityDuty | None = Field(
873
+ None, examples=["submitted_by_applicant"]
874
+ )
875
+ """
876
+ Public sector equality duty (PSED)
877
+ """
878
+ publicSectorEqualityDutySubmittedDate: AwareDatetime | None = Field(
879
+ None, examples=["2023-07-27T20:30:00.000Z"]
880
+ )
881
+ """
882
+ Public sector equality duty (PSED) Submitted Date
883
+ """
884
+ fastTrackAdmissionDocument: FastTrackAdmissionDocument | None = Field(
885
+ None, examples=["submitted_by_applicant"]
886
+ )
887
+ """
888
+ Fast track admission document
889
+ """
890
+ fastTrackAdmissionDocumentSubmittedDate: AwareDatetime | None = Field(
891
+ None, examples=["2023-07-27T20:30:00.000Z"]
892
+ )
893
+ """
894
+ Fast track admission document Submitted Date
895
+ """
896
+ multipartyApplicationCheckDocument: MultipartyApplicationCheckDocument | None = (
897
+ Field(None, examples=["submitted_by_applicant"])
898
+ )
899
+ """
900
+ Multiparty application readiness gate-check (trial)
901
+ """
902
+ multipartyApplicationCheckDocumentSubmittedDate: AwareDatetime | None = Field(
903
+ None, examples=["2023-07-27T20:30:00.000Z"]
904
+ )
905
+ """
906
+ Multiparty application readiness gate-check Submitted Date (trial)
907
+ """
908
+ programmeDocumentURI: str | None = Field(None, examples=["progdoc.sharepoint.com/"])
909
+ """
910
+ Link to programme document
911
+ """
912
+ updatedProgrammeDocumentReceivedDate: AwareDatetime | None = Field(
913
+ None, examples=["2023-07-27T20:30:00.000Z"]
914
+ )
915
+ """
916
+ Date updated programme document is received
917
+ """
918
+ programmeDocumentReviewedByEstDate: AwareDatetime | None = Field(
919
+ None, examples=["2023-07-27T20:30:00.000Z"]
920
+ )
921
+ """
922
+ Date programme document reviewed by EST
923
+ """
924
+ caseTeamIssuedCommentsDate: AwareDatetime | None = Field(
925
+ None, examples=["2023-07-27T20:30:00.000Z"]
926
+ )
927
+ """
928
+ Date case team issued comments on programme document
929
+ """
930
+ subProjectType: SubProjectType | None = Field(None, examples=["solar"])
931
+ """
932
+ Project type
933
+ """
934
+ newMaturity: NewMaturity | None = Field(None, examples=["a"])
935
+ """
936
+ New maturity
937
+ """
938
+ statutoryConsultationPeriodEndDate: AwareDatetime | None = Field(
939
+ None, examples=["2023-07-27T20:30:00.000Z"]
940
+ )
941
+ """
942
+ Statutory consultation period end date
943
+ """
944
+ submissionOfDraftDocumentsDate: AwareDatetime | None = Field(
945
+ None, examples=["2023-07-27T20:30:00.000Z"]
946
+ )
947
+ """
948
+ Date for submission of draft documents
949
+ """
950
+ numberBand2Inspectors: float | None = Field(None, examples=[1])
951
+ """
952
+ Number of band 2 inspectors
953
+ """
954
+ numberBand3Inspectors: float | None = Field(None, examples=[2])
955
+ """
956
+ Number of band 3 inspectors
957
+ """
958
+ memLastUpdated: AwareDatetime | None = Field(
959
+ None, examples=["2023-07-27T20:30:00.000Z"]
960
+ )
961
+ """
962
+ MEM (last updated)
963
+ """
964
+ additionalComments: str | None = Field(
965
+ None,
966
+ examples=["Very likely to change tier from standard to basic after April 2025"],
967
+ )
968
+ """
969
+ Additional comments
970
+ """
971
+ operationsLeadIds: list[str] | None = Field(
972
+ None,
973
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
974
+ )
975
+ """
976
+ Maps to [Employee].[EmployeeID].
977
+ """
978
+ operationsManagerIds: list[str] | None = Field(
979
+ None,
980
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
981
+ )
982
+ """
983
+ New NSIP role, Maps to [Employee].[EmployeeID]
984
+ """
985
+ caseManagerIds: list[str] | None = Field(
986
+ None,
987
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
988
+ )
989
+ """
990
+ Maps to [Employee].[EmployeeID].
991
+ """
992
+ leadInspectorIds: list[str] | None = Field(
993
+ None,
994
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
995
+ )
996
+ """
997
+ Maps to [Employee].[EmployeeID].
998
+ """
999
+ environmentalServicesOfficerIds: list[str] | None = Field(
1000
+ None,
1001
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
1002
+ )
1003
+ """
1004
+ Maps to [Employee].[EmployeeID].
1005
+ """
1006
+ legalOfficerIds: list[str] | None = Field(
1007
+ None,
1008
+ examples=[["9bee96d2-00fe-4269-9d01-8c66", "9bee96d2-00fe-4269-9d01-8c22"]],
1009
+ )
1010
+ """
1011
+ Maps to [Employee].[EmployeeID].
1012
+ """
1013
+ meetings: list[Meeting] | None = None
1014
+ """
1015
+ Collection of meetings associated with this project
1016
+ """
1017
+ invoices: list[Invoice] | None = None
1018
+ """
1019
+ Collection of invoices associated with this project
1020
+ """
@@ -1,6 +1,6 @@
1
1
  # generated by datamodel-codegen:
2
2
  # filename: nsip-project-update.schema.json
3
- # timestamp: 2025-08-29T10:40:44+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-08-29T10:40:44+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-08-29T10:40:44+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-08-29T10:40:44+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]