1010 CATEGORY_ATTRIBUTES ,
1111 ODS_SYSTEM ,
1212 REQUIRED_CREATE_FIELDS ,
13+ TYPE_ATTRIBUTES ,
14+ TYPE_CATEGORIES ,
1315 Categories ,
1416)
1517from nrlf .core .errors import ParseError
@@ -134,8 +136,10 @@ def validate(self, data: Dict[str, Any] | DocumentReference):
134136 self ._validate_identifiers (resource )
135137 self ._validate_relates_to (resource )
136138 self ._validate_ssp_asid (resource )
139+ self ._validate_type (resource )
137140 self ._validate_category (resource )
138141 self ._validate_author (resource )
142+ self ._validate_type_category_mapping (resource )
139143 if resource .content [0 ].extension :
140144 self ._validate_content_extension (resource )
141145
@@ -354,6 +358,40 @@ def _validate_ssp_asid(self, model: DocumentReference):
354358 )
355359 return
356360
361+ def _validate_type (self , model : DocumentReference ):
362+ """
363+ Validate the type field contains an appropriate coding system, code and display.
364+ """
365+ logger .log (LogReference .VALIDATOR001 , step = "type" )
366+
367+ if len (model .type .coding ) > 1 :
368+ self .result .add_error (
369+ issue_code = "invalid" ,
370+ error_code = "INVALID_RESOURCE" ,
371+ diagnostics = f"Invalid type coding length: { len (model .type [0 ].coding )} Type Coding must only contain a single value" ,
372+ field = f"type.coding" ,
373+ )
374+ return
375+
376+ coding = model .type .coding [0 ]
377+ if coding .system != "http://snomed.info/sct" :
378+ self .result .add_error (
379+ issue_code = "value" ,
380+ error_code = "INVALID_RESOURCE" ,
381+ diagnostics = f"Invalid type system: { coding .system } Type system must be 'http://snomed.info/sct'" ,
382+ field = "type.coding[0].system" ,
383+ )
384+ return
385+
386+ type_attributes = TYPE_ATTRIBUTES .get (type_id , {})
387+ if coding .display != type_attributes .get ("display" ):
388+ self .result .add_error (
389+ issue_code = "value" ,
390+ error_code = "INVALID_RESOURCE" ,
391+ diagnostics = f"type code '{ coding .code } ' must have a display value of '{ type_attributes .get ('display' )} '" ,
392+ field = "type.coding[0].display" ,
393+ )
394+
357395 def _validate_category (self , model : DocumentReference ):
358396 """
359397 Validate the category field contains an appropriate coding system, code and display.
@@ -386,17 +424,17 @@ def _validate_category(self, model: DocumentReference):
386424 issue_code = "value" ,
387425 error_code = "INVALID_RESOURCE" ,
388426 diagnostics = f"Invalid category system: { coding .system } Category system must be 'http://snomed.info/sct'" ,
389- field = f "category[0].coding[{ 0 } ].system" ,
427+ field = "category[0].coding[0 ].system" ,
390428 )
391429 return
392430
393- category_id = f"http://snomed.info/sct |{ coding .code } "
431+ category_id = f"{ coding . system } |{ coding .code } "
394432 if category_id not in CATEGORY_ATTRIBUTES .keys ():
395433 self .result .add_error (
396434 issue_code = "value" ,
397435 error_code = "INVALID_RESOURCE" ,
398436 diagnostics = f"Invalid category code: { coding .code } Category must be a member of the England-NRLRecordCategory value set (https://fhir.nhs.uk/England/CodeSystem/England-NRLRecordCategory)" ,
399- field = f "category[0].coding[{ 0 } ].code" ,
437+ field = "category[0].coding[0 ].code" ,
400438 )
401439 return
402440
@@ -406,7 +444,26 @@ def _validate_category(self, model: DocumentReference):
406444 issue_code = "value" ,
407445 error_code = "INVALID_RESOURCE" ,
408446 diagnostics = f"category code '{ coding .code } ' must have a display value of '{ category_attributes .get ('display' )} '" ,
409- field = f"category[0].coding[{ 0 } ].display" ,
447+ field = "category[0].coding[0].display" ,
448+ )
449+
450+ def _validate_type_category_mapping (self , model : DocumentReference ):
451+ """
452+ Validate the type field contains an appropriate coding system, code and display.
453+ """
454+ logger .log (LogReference .VALIDATOR001 , step = "type_category_mapping" )
455+
456+ type_coding = model .type .coding [0 ]
457+ type_id = f"{ type_coding .system } |{ type_coding .code } "
458+ category_coding = model .category [0 ].coding [0 ]
459+ category_id = f"{ category_coding .system } |{ category_coding .code } "
460+
461+ if not TYPE_CATEGORIES .get (type_id ):
462+ self .result .add_error (
463+ issue_code = "value" ,
464+ error_code = "INVALID_RESOURCE" ,
465+ diagnostics = f"type ({ type_id } ) does not map to the category: { category_id } " ,
466+ field = f"type.coding[0].display" ,
410467 )
411468
412469 def _validate_content_extension (self , model : DocumentReference ):
0 commit comments