Repository: Sundhedsdatastyrelsen/ehdsi
Pull request #183: 174: add hp specializations to CDA
Author: login: jakobvase
Created: 2025-04-02T09:07:07Z | Merged: 2025-04-03T11:29:01Z

Closes #174 .

Will test the resulting documents in the validator before merging.

Linked issue #174: Feedback: Specialization required
One piece of feedback from the apothecaries is that we should include the health professional's specialization in the prescription.

This is available in the authorization registry, see for example here: https://autregweb.sst.dk/Authorization.aspx?id=006R5. I have not looked into how to get it out of the request yet.

It should be put into the prescriber field here: https://art-decor.ehdsi.eu/publication/epsos-html-20240422T073854/tmp-2.16.840.1.113883.3.1937.777.11.10.103-2020-10-07T082031.html, xpath n1:assignedAuthor/n1:code/@displayName.

There might be a problem if the hp has more than one specialty, I don't think we can send that. But I haven't looked deeply into it.
Linked issue comments: user: login: jakobvase
created_at: 2025-04-01T12:05:08Z
body: I was apparently wrong. It is instead available in the "yderregister". I'll post links here.
author_association: COLLABORATOR
user: login: jakobvase
created_at: 2025-04-01T12:50:26Z
body: https://www.nspop.dk/display/public/web/SDM+-+Guide+til+anvendere#SDMGuidetilanvendere-5.5Enkeltopslagiyderregistret

Another page describing the Danish registries. I don't know which one we should use yet.
author_association: COLLABORATOR
user: login: jakobvase
created_at: 2025-04-01T13:59:50Z
body: Turns out it _is_ part of the authorization registry, we were just using the wrong version. MR coming up.
author_association: COLLABORATOR
user: login: jakobvase
created_at: 2025-04-03T08:48:35Z
body: The CDA format used by eHDSI does not have a coding system for health professional specializations. In the FHIR documentation (https://build.fhir.org/ig/HL7/CDA-core-2.0/StructureDefinition-AssignedAuthor.html), they recommend using the code system `RoleCode` (https://terminology.hl7.org/5.2.0/ValueSet-v3-RoleCode.html), which does not have any health professional specializations, but instead has values like "brother", "blind", and "attorney". It does include mentions of hospital sections like "Pediatric unit" and "Sleep disorders unit", but they are not meant for specializations, so I can't use those either. It also includes things like "Meat" and "Breeder", roles of farm animals.
author_association: COLLABORATOR
user: login: jakobvase
created_at: 2025-04-03T08:53:20Z
body: We will use a temporary code system in order to get the Danish text across in the CDA format. This may bite us later, but the information is important to apothecaries, so we will take the hit.
author_association: COLLABORATOR

Diff:
diff --git a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Input.java b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Input.java
index ee09c9e1..aa37add0 100644
--- a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Input.java
+++ b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Input.java
@@ -2,7 +2,7 @@
 
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e2.GetDrugMedicationResponseType;
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.GetPrescriptionResponseType;
-import dk.nsi.__.stamdata._3.AuthorizationType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationType;
 import lombok.NonNull;
 
 import java.util.List;
diff --git a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
index 61a246f4..9e1d4a49 100644
--- a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
+++ b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
@@ -9,7 +9,7 @@
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e2.DrugMedicationType;
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.GetPrescriptionResponseType;
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.PrescriptionType;
-import dk.nsi.__.stamdata._3.AuthorizationType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationType;
 import dk.sundhedsdatastyrelsen.ncpeh.cda.model.ActiveIngredient;
 import dk.sundhedsdatastyrelsen.ncpeh.cda.model.Address;
 import dk.sundhedsdatastyrelsen.ncpeh.cda.model.Author;
@@ -40,6 +40,7 @@
 public class EPrescriptionL3Mapper {
     private EPrescriptionL3Mapper() {
     }
+
     /**
      * Map a prescription response from FMK to a CDA data model.
      */
@@ -228,13 +229,14 @@ private static Organization authorOrganization(PrescriptionType prescription) th
         return new Organization(id, org.getName(), org.getTelephoneNumber(), address);
     }
 
-    private static Author author(PrescriptionType prescription, List<AuthorizationType> authorizationTypes) throws MapperException {
+    private static Author author(PrescriptionType prescription, List<AuthorizationType> authorizations) throws MapperException {
+        var firstValidAuthorization = authorizations.stream()
+            .filter(a -> "1".equals(a.getAutorisationGyldig()))
+            .findFirst();
         // https://www.nspop.dk/display/public/web/Autorisation has the list of education codes
         // We should use the translation layer for these codes, but they are also used in L1, which isn't mapped in
         // OpenNCP, so we have to map it in the code.
-        var functionCode = FunctionCodeMapper.mapToFunctionCode(authorizationTypes.stream()
-            .findFirst()
-            .map(AuthorizationType::getEducationCode)
+        var functionCode = FunctionCodeMapper.mapToFunctionCode(firstValidAuthorization.map(AuthorizationType::getUddannelsesKode)
             // 0000 means 'Erstatningsautorisation' replacement authorization
             .orElse("0000"));
         var cdaFunctionCode = CdaCode.builder()
@@ -245,6 +247,7 @@ private static Author author(PrescriptionType prescription, List<AuthorizationTy
 
         return Author.builder()
             .functionCode(cdaFunctionCode)
+            .specialization(getSpecialization(firstValidAuthorization.orElse(null)))
             .time(offsetDateTime(prescription.getCreated().getDateTime()))
             .id(new CdaId(Oid.DK_AUTHORIZATION_REGISTRY, creator.getAuthorisationIdentifier()))
             .name(Name.fromFullName(creator.getName()))
@@ -252,6 +255,31 @@ private static Author author(PrescriptionType prescription, List<AuthorizationTy
             .build();
     }
 
+    private static CdaCode getSpecialization(AuthorizationType authorization) {
+        if (authorization == null) {
+            return null;
+        }
+
+        var specializations = Stream.of(
+                Optional.ofNullable(authorization.getSpeciale1()),
+                Optional.ofNullable(authorization.getSpeciale2()),
+                Optional.ofNullable(authorization.getSpeciale3()))
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .toList();
+
+        // There is no specified coded format for specializations in eHDSI CDA, and no way to send more than one
+        // specialization. So we send it over in an uncoded format. However, in order to display it on the receiver
+        // side, we do need to specify a code system. So we make one up. This is not the ideal way of doing this, we
+        // should ask for a code system from the EU and change the CDA format to support more than one specialization,
+        // but that could take years, so we do this for now.
+        return specializations.isEmpty() ? null : CdaCode.builder()
+            .codeSystem(Oid.DK_AUTHORIZATION_REGISTRY_SPECIALIZATION)
+            .code(String.join(", ", specializations))
+            .displayName(String.join(", ", specializations))
+            .build();
+    }
+
     /**
      * Converts an XML date (xs:date) to a LocalDate.
      */
diff --git a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/Oid.java b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/Oid.java
index 1c792a5c..aa426300 100644
--- a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/Oid.java
+++ b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/Oid.java
@@ -3,6 +3,7 @@
 public enum Oid {
     /**
      * EPrescription document repository id. For now, we use the DK home OID.
+     * TODO Once the spring 2025 test is over, we should update this to 1.2.208.176.7.2.3.
      * <a href="https://oid-base.com/get/1.2.208">Registered.</a>
      */
     DK_EPRESCRIPTION_REPOSITORY_ID("1.2.208"),
@@ -32,6 +33,17 @@ public enum Oid {
      * <a href="https://oid-base.com/get/1.2.208.176.1.3.1">Registered.</a>
      */
     DK_AUTHORIZATION_REGISTRY_EDUCATION_CODE("1.2.208.176.1.3.1"),
+    /**
+     * Made up OID for the specializations in the authorization registry.
+     * If the information does become coded at some point, we should update this.
+     * <p>
+     * There is no specified coded format for specializations in eHDSI CDA, and no way to send more than one
+     * specialization. So we send it over in an uncoded format. However, in order to display it on the receiver
+     * side, we do need to specify a code system. So we make one up. This is not the ideal way of doing this, we
+     * should ask for a code system from the EU and change the CDA format to support more than one specialization,
+     * but that could take years, so we do this for now.
+     */
+    DK_AUTHORIZATION_REGISTRY_SPECIALIZATION("1.2.208.176.1.3.51648"),
     /**
      * Danske ydernumre.
      * <a href="https://oid-base.com/get/1.2.208.176.1.4">Registered.</a>
diff --git a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/model/Author.java b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/model/Author.java
index 8b2d6e4d..4964f958 100644
--- a/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/model/Author.java
+++ b/country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/model/Author.java
@@ -12,6 +12,7 @@
 public class Author {
     @NonNull CdaCode functionCode;
     @NonNull CdaId id;
+    CdaCode specialization;
 
     /**
      * "The author/time element represents the start time of the author’s participation in
diff --git a/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l1.ftlx b/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l1.ftlx
index 8cd5f6ac..68f38cd3 100644
--- a/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l1.ftlx
+++ b/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l1.ftlx
@@ -33,6 +33,9 @@
         <time value="${ l3.author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs l3.author.id /> />
+<#if l3.author.specialization??>
+            <code <@common.cdaCodeAttrs l3.author.specialization />/>
+</#if>
             <#-- TODO: Er det nødvendigt med addr og telecom?  -->
             <addr nullFlavor="NI"/>
             <telecom nullFlavor="NI"/>
diff --git a/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx b/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
index 2696d4a6..7d6738a3 100644
--- a/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
+++ b/country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
@@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specialization??>
+            <code <@common.cdaCodeAttrs author.specialization />/>
+</#if>
             <#-- TODO: Er det nødvendigt med addr og telecom?  -->
             <addr nullFlavor="NI"/>
             <telecom nullFlavor="NI"/>
diff --git a/country-a-service/cda-generator/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3GeneratorTest.java b/country-a-service/cda-generator/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3GeneratorTest.java
index 5013ae95..73c072a7 100644
--- a/country-a-service/cda-generator/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3GeneratorTest.java
+++ b/country-a-service/cda-generator/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3GeneratorTest.java
@@ -1,5 +1,6 @@
 package dk.sundhedsdatastyrelsen.ncpeh.cda;
 
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationType;
 import dk.sundhedsdatastyrelsen.ncpeh.cda.model.Product;
 import dk.sundhedsdatastyrelsen.ncpeh.testing.shared.FmkResponseStorage;
 import freemarker.template.TemplateException;
@@ -69,7 +70,12 @@ public void testCdaValidity(String cpr) throws Exception {
         Assertions.assertFalse(prescription.getPrescription().isEmpty());
         var prescriptions = prescription.getPrescription();
         for (int prescriptionindex = 0; prescriptionindex < prescriptions.size(); prescriptionindex++) {
-            var input = new EPrescriptionL3Input(prescription, prescriptionindex, medication, "FIN", "Manufacturer");
+            var input = new EPrescriptionL3Input(
+                prescription, prescriptionindex, medication, List.of(AuthorizationType.builder()
+                .withSpeciale1("Kirurgi")
+                .withUddannelsesKode("7170")
+                .withAutorisationGyldig("1")
+                .build()), "FIN", "Manufacturer");
             var xmlString = EPrescriptionL3Generator.generate(input);
 
             // 1. Test if well-formed XML (can be parsed)
diff --git a/country-a-service/config/application.yml b/country-a-service/config/application.yml
index e745e478..56773591 100644
--- a/country-a-service/config/application.yml
+++ b/country-a-service/config/application.yml
@@ -16,7 +16,7 @@ spring:
 app:
   fmk.endpoint.url: "https://test2-cnsp.ekstern-test.nspop.dk:8443/decoupling"
   cpr.endpoint.url: "https://test2.ekstern-test.nspop.dk:8443/stamdata-cpr-ws/service/DetGodeCPROpslag-1.0.4"
-  authorization-registry.endpoint.url: "https://test2.ekstern-test.nspop.dk:8443/stamdata-authorization-lookup-ws/service/AuthorizationCodeService"
+  authorization-registry.endpoint.url: "https://test2.ekstern-test.nspop.dk:8443/stamdata-authorization-lookup-ws/service/AuthorizationCodeService-20240105"
 
 management:
   endpoint:
diff --git a/country-a-service/epps-api/autorisationsregister-model/pom.xml b/country-a-service/epps-api/autorisationsregister-model/pom.xml
index 005e55c9..8272e0fd 100644
--- a/country-a-service/epps-api/autorisationsregister-model/pom.xml
+++ b/country-a-service/epps-api/autorisationsregister-model/pom.xml
@@ -59,7 +59,7 @@
                         <arg>-B-Xfluent-builder</arg>
                     </args>
                     <wsdlUrls>
-                        <wsdlUrl>./src/main/resources/authorization-registry.wsdl</wsdlUrl>
+                        <wsdlUrl>./src/main/resources/AuthorizationService-20240105.wsdl</wsdlUrl>
                     </wsdlUrls>
                     <sourceDestDir>${sourcesDir}</sourceDestDir>
                     <destDir>${classesDir}</destDir>
diff --git a/country-a-service/epps-api/autorisationsregister-model/readme.md b/country-a-service/epps-api/autorisationsregister-model/readme.md
new file mode 100644
index 00000000..8a9405e9
--- /dev/null
+++ b/country-a-service/epps-api/autorisationsregister-model/readme.md
@@ -0,0 +1,6 @@
+# Authorization registry integration
+
+The interface is documented at https://www.nspop.dk/display/public/web/SDM+-+Guide+til+anvendere#SDMGuidetilanvendere-5.5Enkeltopslagiyderregistret,
+where they also link to the wsdl which is at http://test1-cnsp.ekstern-test.nspop.dk:8080/stamdata-authorization-lookup-ws/service/AuthorizationService-20240105?wsdl.
+
+Remark that we need the 2024-01-05 version, as we also need the specializations of the health personnel.
diff --git a/country-a-service/epps-api/autorisationsregister-model/src/main/resources/AuthorizationService-20240105.wsdl b/country-a-service/epps-api/autorisationsregister-model/src/main/resources/AuthorizationService-20240105.wsdl
new file mode 100644
index 00000000..76efab35
--- /dev/null
+++ b/country-a-service/epps-api/autorisationsregister-model/src/main/resources/AuthorizationService-20240105.wsdl
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.7-b01-. -->
+<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://nsi.dk/2024/01/05/StamdataAuthorization" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:dgws="http://www.medcom.dk/dgws/2006/04/dgws-1.0.xsd" targetNamespace="http://nsi.dk/2024/01/05/StamdataAuthorization">
+  <wsdl:types>
+    <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sd="http://nsi.dk/2024/01/05/StamdataAuthorization" targetNamespace="http://nsi.dk/2024/01/05/StamdataAuthorization" elementFormDefault="qualified" attributeFormDefault="unqualified">
+      <element name="AuthorizationRequestStructure" type="sd:AuthorizationRequestType">
+        <annotation>
+          <documentation>Request element with a CPR-number.</documentation>
+        </annotation>
+      </element>
+      <complexType name="AuthorizationRequestType">
+        <sequence>
+          <element name="cpr" type="string"/>
+        </sequence>
+      </complexType>
+       <element name="AuthorizationCodeRequestStructure" type="sd:AuthorizationCodeRequestType">
+        <annotation>
+          <documentation>Request element with an authorization code.</documentation>
+        </annotation>
+      </element>
+      <complexType name="AuthorizationCodeRequestType">
+      	<sequence>
+      		<element name="authorizationCode" type="string"/>
+      	</sequence>
+      </complexType>
+      <complexType name="AuthorizationType">
+        <sequence>
+          <element name="autorisationsNummer" type="string"/>
+          <element name="uddannelsesKode" type="string"/>
+          <element name="uddannelsesNavn" type="string" minOccurs="0"/>
+          <element name="uddannelsesLand" type="string" minOccurs="0"/>
+          <element name="tidsbegraenset" type="string" minOccurs="0"/>
+          <element name="tilsyn" type="string" minOccurs="0"/>
+          <element name="tilsynsBemaerkninger" type="string" minOccurs="0"/>
+          <element name="sanktionsType" type="string" minOccurs="0"/>
+          <element name="dispensation75Aarsreglen" type="string" minOccurs="0"/>
+          <element name="selvstaendigVirkeDato" type="string" minOccurs="0"/>
+          <element name="selvstaendigtVirke" type="string" minOccurs="0"/>
+          <element name="selvstaendigVirkeUddLand" type="string" minOccurs="0"/>
+          <element name="speciale1" type="string" minOccurs="0"/>
+          <element name="specialeDato1" type="string" minOccurs="0"/>
+          <element name="specialeUddLand1" type="string" minOccurs="0"/>
+          <element name="speciale2" type="string" minOccurs="0"/>
+          <element name="specialeDato2" type="string" minOccurs="0"/>
+          <element name="specialeUddLand2" type="string" minOccurs="0"/>
+          <element name="speciale3" type="string" minOccurs="0"/>
+          <element name="specialeDato3" type="string" minOccurs="0"/>
+          <element name="specialeUddLand3" type="string" minOccurs="0"/>
+          <element name="autorisationGyldig" type="string" minOccurs="0"/>
+          <element name="autorisationsDato" type="string" minOccurs="0"/>
+        </sequence>
+      </complexType>
+      <element name="AuthorizationResponseStructure" type="sd:AuthorizationResponseType">
+        <annotation>
+          <documentation>Response element for a authorization number.</documentation>
+        </annotation>
+      </element>
+      <complexType name="AuthorizationResponseType">
+        <sequence minOccurs="0">
+          <element name="cpr" type="string"/>
+          <element name="fornavn" type="string" minOccurs="0"/>
+          <element name="efternavn" type="string" minOccurs="0"/>
+          <element name="autorisation" type="sd:AuthorizationType" minOccurs="0" maxOccurs="unbounded"/>
+        </sequence>
+      </complexType>
+    </xsd:schema>
+
+    <!-- Den gode webservice schemas. -->
+    <xsd:schema targetNamespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+    <xsd:include schemaLocation="http://test1-cnsp.ekstern-test.nspop.dk:8080/stamdata-authorization-lookup-ws/service/AuthorizationService-20240105?xsd=4"/>
+  </xsd:schema>
+  <xsd:schema targetNamespace="http://www.medcom.dk/dgws/2006/04/dgws-1.0.xsd">
+    <xsd:include schemaLocation="http://test1-cnsp.ekstern-test.nspop.dk:8080/stamdata-authorization-lookup-ws/service/AuthorizationService-20240105?xsd=2"/>
+  </xsd:schema>
+  
+    <!-- NB: This is added to avoid JAX-WS mapping date to XMLGregorialCalendar, which does not play nice with SEAL. -->
+    <xsd:schema xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://nsi.dk/2024/01/05/StamdataAuthorization" jaxb:version="2.1" elementFormDefault="qualified">
+    <xsd:annotation>
+      <xsd:appinfo>
+        <jaxb:globalBindings>
+          <jaxb:javaType name="java.util.Calendar" xmlType="xsd:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime"/>
+        </jaxb:globalBindings>
+      </xsd:appinfo>
+    </xsd:annotation>
+  </xsd:schema>
+  </wsdl:types>
+
+  <wsdl:message name="AuthorizationRequestMessage">
+    <wsdl:part name="wsseHeader" element="wsse:Security"/>
+    <wsdl:part name="medcomHeader" element="dgws:Header"/>
+    <wsdl:part element="tns:AuthorizationRequestStructure" name="parameters"/>
+  </wsdl:message>
+  
+  <wsdl:message name="AuthorizationCodeRequestMessage">
+    <wsdl:part name="wsseHeader" element="wsse:Security"/>
+    <wsdl:part name="medcomHeader" element="dgws:Header"/>
+    <wsdl:part element="tns:AuthorizationCodeRequestStructure" name="parameters"/>
+  </wsdl:message>
+
+  <wsdl:message name="AuthorizationResponseMessage">
+    <wsdl:part name="wsseHeader" element="wsse:Security"/>
+    <wsdl:part name="medcomHeader" element="dgws:Header"/>
+    <wsdl:part element="tns:AuthorizationResponseStructure" name="parameters"/>
+  </wsdl:message>
+
+  <wsdl:message name="DGWSFault">
+    <wsdl:part name="fault" element="dgws:FaultCode"/>
+  </wsdl:message>
+
+  <wsdl:portType name="AuthorizationPortType">
+    <wsdl:operation name="Authorization">
+      <wsdl:input message="tns:AuthorizationRequestMessage" name="AuthorizationRequestStructureInput"/>
+      <wsdl:output message="tns:AuthorizationResponseMessage" name="AuthorizationResponseStructureOutput"/>
+      <wsdl:fault message="tns:DGWSFault" name="DGWSFault"/>
+    </wsdl:operation>
+  </wsdl:portType>
+  
+  <wsdl:portType name="AuthorizationCodePortType">
+    <wsdl:operation name="Authorization">
+      <wsdl:input message="tns:AuthorizationCodeRequestMessage" name="AuthorizationCodeRequestStructureInput"/>
+      <wsdl:output message="tns:AuthorizationResponseMessage" name="AuthorizationCodeResponseStructureOutput"/>
+      <wsdl:fault message="tns:DGWSFault" name="DGWSFault"/>
+    </wsdl:operation>
+  </wsdl:portType>
+
+  <wsdl:binding name="AuthorizationBinding" type="tns:AuthorizationPortType">
+    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="Authorization">
+      <soap:operation soapAction="http://nsi.dk/sdm/Gateway"/>
+      <wsdl:input name="AuthorizationRequestStructureInput">
+        <soap:body use="literal" parts="parameters"/>
+        <soap:header message="tns:AuthorizationRequestMessage" part="wsseHeader" use="literal"/>
+        <soap:header message="tns:AuthorizationRequestMessage" part="medcomHeader" use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="AuthorizationResponseStructureOutput">
+        <soap:body use="literal" parts="parameters"/>
+        <soap:header message="tns:AuthorizationResponseMessage" part="wsseHeader" use="literal"/>
+        <soap:header message="tns:AuthorizationResponseMessage" part="medcomHeader" use="literal"/>
+      </wsdl:output>
+      <wsdl:fault name="DGWSFault">
+        <soap:fault name="DGWSFault" use="literal"/>
+      </wsdl:fault>
+    </wsdl:operation>
+  </wsdl:binding>
+  
+  <wsdl:binding name="AuthorizationCodeBinding" type="tns:AuthorizationCodePortType">
+    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
+    <wsdl:operation name="Authorization">
+      <soap:operation soapAction="http://nsi.dk/sdm/Gateway"/>
+      <wsdl:input name="AuthorizationCodeRequestStructureInput">
+        <soap:body use="literal" parts="parameters"/>
+        <soap:header message="tns:AuthorizationCodeRequestMessage" part="wsseHeader" use="literal"/>
+        <soap:header message="tns:AuthorizationCodeRequestMessage" part="medcomHeader" use="literal"/>
+      </wsdl:input>
+      <wsdl:output name="AuthorizationCodeResponseStructureOutput">
+        <soap:body use="literal" parts="parameters"/>
+        <soap:header message="tns:AuthorizationResponseMessage" part="wsseHeader" use="literal"/>
+        <soap:header message="tns:AuthorizationResponseMessage" part="medcomHeader" use="literal"/>
+      </wsdl:output>
+      <wsdl:fault name="DGWSFault">
+        <soap:fault name="DGWSFault" use="literal"/>
+      </wsdl:fault>
+    </wsdl:operation>
+  </wsdl:binding>
+
+  <wsdl:service name="AuthorizationService">
+    <wsdl:port binding="tns:AuthorizationBinding" name="AuthorizationPort">
+      <!-- The following is required in the wsdl, but the actual url is defined 
+        elsewhere -->
+      <soap:address location="http://test1-cnsp.ekstern-test.nspop.dk:8080/stamdata-authorization-lookup-ws/service/AuthorizationService-20240105"/>
+    </wsdl:port>
+  </wsdl:service>
+  <wsdl:service name="AuthorizationCodeService">
+    <wsdl:port binding="tns:AuthorizationCodeBinding" name="AuthorizationCodePort">
+      <!-- The following is required in the wsdl, but the actual url is defined 
+        elsewhere -->
+      <soap:address location="http://test1-cnsp.ekstern-test.nspop.dk:8080/stamdata-authorization-lookup-ws/service/AuthorizationCodeService-20240105"/>
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
diff --git a/country-a-service/epps-api/autorisationsregister-model/src/main/resources/authorization-registry.wsdl b/country-a-service/epps-api/autorisationsregister-model/src/main/resources/authorization-registry.wsdl
deleted file mode 100644
index ca7b9a90..00000000
--- a/country-a-service/epps-api/autorisationsregister-model/src/main/resources/authorization-registry.wsdl
+++ /dev/null
@@ -1,158 +0,0 @@
-<?xml version='1.0' encoding='UTF-8'?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.7-b01-. --><wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://nsi.dk/-/stamdata/3.0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:dgws="http://www.medcom.dk/dgws/2006/04/dgws-1.0.xsd" targetNamespace="http://nsi.dk/-/stamdata/3.0">
-    <wsdl:types>
-        <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:sd="http://nsi.dk/-/stamdata/3.0" targetNamespace="http://nsi.dk/-/stamdata/3.0" elementFormDefault="qualified" attributeFormDefault="unqualified">
-            <element name="AuthorizationRequestStructure" type="sd:AuthorizationRequestType">
-                <annotation>
-                    <documentation>Request element with a CPR-number.</documentation>
-                </annotation>
-            </element>
-            <complexType name="AuthorizationRequestType">
-                <sequence>
-                    <element name="cpr" type="string"/>
-                </sequence>
-            </complexType>
-            <element name="AuthorizationCodeRequestStructure" type="sd:AuthorizationCodeRequestType">
-                <annotation>
-                    <documentation>Request element with an authorization code.</documentation>
-                </annotation>
-            </element>
-            <complexType name="AuthorizationCodeRequestType">
-                <sequence>
-                    <element name="authorizationCode" type="string"/>
-                </sequence>
-            </complexType>
-            <complexType name="AuthorizationType">
-                <sequence>
-                    <element name="authorizationCode" type="string"/>
-                    <element name="educationCode" type="string"/>
-                    <element name="educationName" type="string" minOccurs="0"/>
-                </sequence>
-            </complexType>
-            <element name="AuthorizationResponseStructure" type="sd:AuthorizationResponseType">
-                <annotation>
-                    <documentation>Response element for a authorization number.</documentation>
-                </annotation>
-            </element>
-            <complexType name="AuthorizationResponseType">
-                <sequence minOccurs="0">
-                    <element name="cpr" type="string"/>
-                    <element name="firstName" type="string" minOccurs="0"/>
-                    <element name="lastName" type="string" minOccurs="0"/>
-                    <element name="authorization" type="sd:AuthorizationType" minOccurs="0" maxOccurs="unbounded"/>
-                </sequence>
-            </complexType>
-        </xsd:schema>
-
-        <!-- Den gode webservice schemas. -->
-        <xsd:schema targetNamespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
-            <xsd:include schemaLocation="https://wsdl.nspop.dk/stamdata-authorization-lookup-ws/service/AuthorizationService?xsd=4"/>
-        </xsd:schema>
-        <xsd:schema targetNamespace="http://www.medcom.dk/dgws/2006/04/dgws-1.0.xsd">
-            <xsd:include schemaLocation="https://wsdl.nspop.dk/stamdata-authorization-lookup-ws/service/AuthorizationService?xsd=2"/>
-        </xsd:schema>
-
-        <!-- NB: This is added to avoid JAX-WS mapping date to XMLGregorialCalendar, which does not play nice with SEAL. -->
-        <xsd:schema xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://nsi.dk/-/stamdata/3.0" jaxb:version="2.1" elementFormDefault="qualified">
-            <xsd:annotation>
-                <xsd:appinfo>
-                    <jaxb:globalBindings>
-                        <jaxb:javaType name="java.util.Calendar" xmlType="xsd:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime"/>
-                    </jaxb:globalBindings>
-                </xsd:appinfo>
-            </xsd:annotation>
-        </xsd:schema>
-    </wsdl:types>
-
-    <wsdl:message name="AuthorizationRequestMessage">
-        <wsdl:part name="wsseHeader" element="wsse:Security"/>
-        <wsdl:part name="medcomHeader" element="dgws:Header"/>
-        <wsdl:part element="tns:AuthorizationRequestStructure" name="parameters"/>
-    </wsdl:message>
-
-    <wsdl:message name="AuthorizationCodeRequestMessage">
-        <wsdl:part name="wsseHeader" element="wsse:Security"/>
-        <wsdl:part name="medcomHeader" element="dgws:Header"/>
-        <wsdl:part element="tns:AuthorizationCodeRequestStructure" name="parameters"/>
-    </wsdl:message>
-
-    <wsdl:message name="AuthorizationResponseMessage">
-        <wsdl:part name="wsseHeader" element="wsse:Security"/>
-        <wsdl:part name="medcomHeader" element="dgws:Header"/>
-        <wsdl:part element="tns:AuthorizationResponseStructure" name="parameters"/>
-    </wsdl:message>
-
-    <wsdl:message name="DGWSFault">
-        <wsdl:part name="fault" element="dgws:FaultCode"/>
-    </wsdl:message>
-
-    <wsdl:portType name="AuthorizationPortType">
-        <wsdl:operation name="Authorization">
-            <wsdl:input message="tns:AuthorizationRequestMessage" name="AuthorizationRequestStructureInput"/>
-            <wsdl:output message="tns:AuthorizationResponseMessage" name="AuthorizationResponseStructureOutput"/>
-            <wsdl:fault message="tns:DGWSFault" name="DGWSFault"/>
-        </wsdl:operation>
-    </wsdl:portType>
-
-    <wsdl:portType name="AuthorizationCodePortType">
-        <wsdl:operation name="Authorization">
-            <wsdl:input message="tns:AuthorizationCodeRequestMessage" name="AuthorizationCodeRequestStructureInput"/>
-            <wsdl:output message="tns:AuthorizationResponseMessage" name="AuthorizationCodeResponseStructureOutput"/>
-            <wsdl:fault message="tns:DGWSFault" name="DGWSFault"/>
-        </wsdl:operation>
-    </wsdl:portType>
-
-    <wsdl:binding name="AuthorizationBinding" type="tns:AuthorizationPortType">
-        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
-        <wsdl:operation name="Authorization">
-            <soap:operation soapAction="http://nsi.dk/sdm/Gateway"/>
-            <wsdl:input name="AuthorizationRequestStructureInput">
-                <soap:body use="literal" parts="parameters"/>
-                <soap:header message="tns:AuthorizationRequestMessage" part="wsseHeader" use="literal"/>
-                <soap:header message="tns:AuthorizationRequestMessage" part="medcomHeader" use="literal"/>
-            </wsdl:input>
-            <wsdl:output name="AuthorizationResponseStructureOutput">
-                <soap:body use="literal" parts="parameters"/>
-                <soap:header message="tns:AuthorizationResponseMessage" part="wsseHeader" use="literal"/>
-                <soap:header message="tns:AuthorizationResponseMessage" part="medcomHeader" use="literal"/>
-            </wsdl:output>
-            <wsdl:fault name="DGWSFault">
-                <soap:fault name="DGWSFault" use="literal"/>
-            </wsdl:fault>
-        </wsdl:operation>
-    </wsdl:binding>
-
-    <wsdl:binding name="AuthorizationCodeBinding" type="tns:AuthorizationCodePortType">
-        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
-        <wsdl:operation name="Authorization">
-            <soap:operation soapAction="http://nsi.dk/sdm/Gateway"/>
-            <wsdl:input name="AuthorizationCodeRequestStructureInput">
-                <soap:body use="literal" parts="parameters"/>
-                <soap:header message="tns:AuthorizationCodeRequestMessage" part="wsseHeader" use="literal"/>
-                <soap:header message="tns:AuthorizationCodeRequestMessage" part="medcomHeader" use="literal"/>
-            </wsdl:input>
-            <wsdl:output name="AuthorizationCodeResponseStructureOutput">
-                <soap:body use="literal" parts="parameters"/>
-                <soap:header message="tns:AuthorizationResponseMessage" part="wsseHeader" use="literal"/>
-                <soap:header message="tns:AuthorizationResponseMessage" part="medcomHeader" use="literal"/>
-            </wsdl:output>
-            <wsdl:fault name="DGWSFault">
-                <soap:fault name="DGWSFault" use="literal"/>
-            </wsdl:fault>
-        </wsdl:operation>
-    </wsdl:binding>
-
-    <wsdl:service name="AuthorizationService">
-        <wsdl:port binding="tns:AuthorizationBinding" name="AuthorizationPort">
-            <!-- The following is required in the wsdl, but the actual url is defined
-              elsewhere -->
-            <soap:address location="https://wsdl.nspop.dk/stamdata-authorization-lookup-ws/service/AuthorizationService"/>
-        </wsdl:port>
-    </wsdl:service>
-    <wsdl:service name="AuthorizationCodeService">
-        <wsdl:port binding="tns:AuthorizationCodeBinding" name="AuthorizationCodePort">
-            <!-- The following is required in the wsdl, but the actual url is defined
-              elsewhere -->
-            <soap:address location="https://wsdl.nspop.dk/stamdata-authorization-lookup-ws/service/AuthorizationCodeService"/>
-        </wsdl:port>
-    </wsdl:service>
-</wsdl:definitions>
diff --git a/country-a-service/epps-service/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/service/PrescriptionService.java b/country-a-service/epps-service/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/service/PrescriptionService.java
index f0d8272c..c0a0fcf3 100644
--- a/country-a-service/epps-service/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/service/PrescriptionService.java
+++ b/country-a-service/epps-service/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/service/PrescriptionService.java
@@ -11,8 +11,8 @@
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.GetPrescriptionResponseType;
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.PrescriptionType;
 import dk.dkma.medicinecard.xml_schema._2015._06._01.e6.StartEffectuationResponseType;
-import dk.nsi.__.stamdata._3.AuthorizationResponseType;
-import dk.nsi.__.stamdata._3.AuthorizationType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationResponseType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationType;
 import dk.nsp.test.idp.OrganizationIdentities;
 import dk.nsp.test.idp.model.Identity;
 import dk.sundhedsdatastyrelsen.ncpeh.cda.EPrescriptionDocumentIdMapper;
@@ -157,7 +157,7 @@ private Stream<EPrescriptionL3Input> assembleEPrescriptionInput(String patientId
                         EPrescriptionL3Mapper.getAuthorizedHealthcareProfessional(prescription)
                             .getAuthorisationIdentifier(),
                         id -> getAuthorizationByIdentifierCode(id, OrganizationIdentities.sundhedsdatastyrelsen())
-                            .getAuthorization());
+                            .getAutorisation());
 
                     return new EPrescriptionL3Input(
                         fmkResponse,
diff --git a/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/AuthorizationRegistryIT.java b/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/AuthorizationRegistryIT.java
index 6fc9c637..54b65926 100644
--- a/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/AuthorizationRegistryIT.java
+++ b/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/AuthorizationRegistryIT.java
@@ -9,7 +9,7 @@
 import static org.hamcrest.Matchers.is;
 
 class AuthorizationRegistryIT {
-    private final String serviceUrl = "https://test2.ekstern-test.nspop.dk:8443/stamdata-authorization-lookup-ws/service/AuthorizationCodeService";
+    private final String serviceUrl = "https://test2.ekstern-test.nspop.dk:8443/stamdata-authorization-lookup-ws/service/AuthorizationCodeService-20240105";
 
     @Test
     void authorizationLookup() throws JAXBException {
@@ -17,9 +17,9 @@ void authorizationLookup() throws JAXBException {
         // 6QF17 is the authorisation code of Charles Babbage
         var response = client.requestByAuthorizationCode("6QF17", OrganizationIdentities.sundhedsdatastyrelsen());
 
-        assertThat(response.getAuthorization().size(), is(1));
+        assertThat(response.getAutorisation().size(), is(1));
         // For codes: https://www.nspop.dk/display/public/web/Autorisation
-        assertThat(response.getAuthorization().getFirst().getEducationCode(), is("7170"));
-        assertThat(response.getAuthorization().getFirst().getEducationName(), is("Læge"));
+        assertThat(response.getAutorisation().getFirst().getUddannelsesKode(), is("7170"));
+        assertThat(response.getAutorisation().getFirst().getUddannelsesNavn(), is("Læge"));
     }
 }
diff --git a/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/mocks/AuthorizationRegistryClientMock.java b/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/mocks/AuthorizationRegistryClientMock.java
index 36bdcad9..f11933f6 100644
--- a/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/mocks/AuthorizationRegistryClientMock.java
+++ b/country-a-service/integration-tests/src/test/java/dk/sundhedsdatastyrelsen/ncpeh/mocks/AuthorizationRegistryClientMock.java
@@ -1,7 +1,7 @@
 package dk.sundhedsdatastyrelsen.ncpeh.mocks;
 
-import dk.nsi.__.stamdata._3.AuthorizationResponseType;
-import dk.nsi.__.stamdata._3.AuthorizationType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationResponseType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationType;
 import dk.nsp.test.idp.model.Identity;
 import dk.sundhedsdatastyrelsen.ncpeh.client.AuthorizationRegistryClient;
 import jakarta.xml.bind.JAXBException;
@@ -15,7 +15,10 @@ public AuthorizationRegistryClientMock() {
     public AuthorizationResponseType requestByAuthorizationCode(String authorizationCode, Identity caller) throws JAXBException {
         // 7170 is "Læge", doctor.
         return AuthorizationResponseType.builder()
-            .withAuthorization(AuthorizationType.builder().withAuthorizationCode("7170").build())
+            .withAutorisation(AuthorizationType.builder()
+                .withUddannelsesKode("7170")
+                .withSpeciale1("Radiologi")
+                .build())
             .build();
     }
 }
diff --git a/country-a-service/nsp-client/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/client/AuthorizationRegistryClient.java b/country-a-service/nsp-client/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/client/AuthorizationRegistryClient.java
index f38340b6..3ab71d24 100644
--- a/country-a-service/nsp-client/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/client/AuthorizationRegistryClient.java
+++ b/country-a-service/nsp-client/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/client/AuthorizationRegistryClient.java
@@ -1,6 +1,6 @@
 package dk.sundhedsdatastyrelsen.ncpeh.client;
 
-import dk.nsi.__.stamdata._3.AuthorizationResponseType;
+import dk.nsi._2024._01._05.stamdataauthorization.AuthorizationResponseType;
 import dk.nsp.test.idp.model.Identity;
 import dk.sosi.seal.model.Reply;
 import jakarta.xml.bind.JAXBContext;
@@ -32,7 +32,7 @@ private Element authorizationCodeRequestType(String authorizationCode) throws Ex
         factory.setNamespaceAware(true);
         var builder = factory.newDocumentBuilder();
         var document = builder.newDocument();
-        var ns = "http://nsi.dk/-/stamdata/3.0";
+        var ns = "http://nsi.dk/2024/01/05/StamdataAuthorization";
         var rootElement = document.createElementNS(ns, "AuthorizationCodeRequestStructure");
         var authCodeElement = document.createElementNS(ns, "authorizationCode");
         authCodeElement.appendChild(document.createTextNode(authorizationCode));


Reviews:
user: login: CBrams
body: Looks good. Thanks for writing why we needed to change the endpoint, it made me delete a whole comment :D
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-02T12:15:11Z
user: login: hansbugge
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-02T12:24:16Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-02T13:18:18Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-02T13:36:28Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-02T14:34:27Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T10:21:15Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T10:21:35Z
user: login: hansbugge
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T10:56:30Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T11:03:47Z
user: login: jakobvase
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-03T11:28:48Z

Review comments:
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
+            <code displayName="${ author.specializationString }"/>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: hansbugge
body: I don't think this is valid?  Don't we need some combination of nullFlavor, translation, and originalText?
created_at: 2025-04-02T12:24:16Z
author_association: COLLABORATOR
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
+            <code displayName="${ author.specializationString }"/>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: jakobvase
body: I'm testing that :)
created_at: 2025-04-02T13:18:18Z
author_association: COLLABORATOR
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: jakobvase
body: Need to also add this to L1
created_at: 2025-04-02T13:36:28Z
author_association: COLLABORATOR
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
+            <code displayName="${ author.specializationString }"/>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: jakobvase
body: Correct, it is not valid. Will fix
created_at: 2025-04-02T14:34:27Z
author_association: COLLABORATOR
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
+            <code displayName="${ author.specializationString }"/>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: jakobvase
body: Done, please have another look
created_at: 2025-04-03T10:21:15Z
author_association: COLLABORATOR
diff_hunk: @@ -53,6 +53,9 @@
         <time value="${ author.time }"/>
         <assignedAuthor classCode="ASSIGNED">
             <id <@common.cdaIdAttrs author.id /> />
+<#if author.specializationString??>
path: country-a-service/cda-generator/src/main/resources/templates/eprescription-cda-l3.ftlx
user: login: jakobvase
body: Done
created_at: 2025-04-03T10:21:35Z
author_association: COLLABORATOR
diff_hunk: @@ -245,13 +247,39 @@ private static Author author(PrescriptionType prescription, List<AuthorizationTy
 
         return Author.builder()
             .functionCode(cdaFunctionCode)
+            .specialization(getSpecialization(firstValidAuthorization.orElse(null)))
             .time(offsetDateTime(prescription.getCreated().getDateTime()))
             .id(new CdaId(Oid.DK_AUTHORIZATION_REGISTRY, creator.getAuthorisationIdentifier()))
             .name(Name.fromFullName(creator.getName()))
             .organization(authorOrganization(prescription))
             .build();
     }
 
+    private static CdaCode getSpecialization(AuthorizationType authorization) {
+        if (authorization == null) {
+            return null;
+        }
+
+        var specializations = Stream.of(
+                Optional.ofNullable(authorization.getSpeciale1()),
+                Optional.ofNullable(authorization.getSpeciale2()),
+                Optional.ofNullable(authorization.getSpeciale3()))
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .toList();
+
+        // There is no specified coded format for specializations in eHDSI CDA, and no way to send more than one
+        // specialization. So we send it over in an uncoded format. However, in order to display it on the receiver
+        // side, we do need to specify a code system. So we make one up. This is not the ideal way of doing this, we
+        // should ask for a code system from the EU and change the CDA format to support more than one specialization,
+        // but that could take years, so we do this for now.
+        return specializations.isEmpty() ? null : CdaCode.builder()
+            .codeSystem(Oid.DK_AUTHORIZATION_REGISTRY_SPECIALIZATION)
+            .code("not-coded")
path: country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
user: login: hansbugge
body: I think we *should* put a code, that way we would go less against the grain.  One code cannot have multiple display names, so some consumers could potentially balk at this data.  But if we use `String.join(", ", specializations)` for the code then there'd be a 1-1 mapping between code and displayName (trivially so).
created_at: 2025-04-03T10:56:30Z
author_association: COLLABORATOR
diff_hunk: @@ -245,13 +247,39 @@ private static Author author(PrescriptionType prescription, List<AuthorizationTy
 
         return Author.builder()
             .functionCode(cdaFunctionCode)
+            .specialization(getSpecialization(firstValidAuthorization.orElse(null)))
             .time(offsetDateTime(prescription.getCreated().getDateTime()))
             .id(new CdaId(Oid.DK_AUTHORIZATION_REGISTRY, creator.getAuthorisationIdentifier()))
             .name(Name.fromFullName(creator.getName()))
             .organization(authorOrganization(prescription))
             .build();
     }
 
+    private static CdaCode getSpecialization(AuthorizationType authorization) {
+        if (authorization == null) {
+            return null;
+        }
+
+        var specializations = Stream.of(
+                Optional.ofNullable(authorization.getSpeciale1()),
+                Optional.ofNullable(authorization.getSpeciale2()),
+                Optional.ofNullable(authorization.getSpeciale3()))
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .toList();
+
+        // There is no specified coded format for specializations in eHDSI CDA, and no way to send more than one
+        // specialization. So we send it over in an uncoded format. However, in order to display it on the receiver
+        // side, we do need to specify a code system. So we make one up. This is not the ideal way of doing this, we
+        // should ask for a code system from the EU and change the CDA format to support more than one specialization,
+        // but that could take years, so we do this for now.
+        return specializations.isEmpty() ? null : CdaCode.builder()
+            .codeSystem(Oid.DK_AUTHORIZATION_REGISTRY_SPECIALIZATION)
+            .code("not-coded")
path: country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
user: login: jakobvase
body: I'm afraid there are some validations on what these codes can look like. Assumptions like "it doesn't have spaces". So I don't want to use the text directly. But we could use a URL-encoded or base64 encoded version.
created_at: 2025-04-03T11:03:47Z
author_association: COLLABORATOR
diff_hunk: @@ -245,13 +247,39 @@ private static Author author(PrescriptionType prescription, List<AuthorizationTy
 
         return Author.builder()
             .functionCode(cdaFunctionCode)
+            .specialization(getSpecialization(firstValidAuthorization.orElse(null)))
             .time(offsetDateTime(prescription.getCreated().getDateTime()))
             .id(new CdaId(Oid.DK_AUTHORIZATION_REGISTRY, creator.getAuthorisationIdentifier()))
             .name(Name.fromFullName(creator.getName()))
             .organization(authorOrganization(prescription))
             .build();
     }
 
+    private static CdaCode getSpecialization(AuthorizationType authorization) {
+        if (authorization == null) {
+            return null;
+        }
+
+        var specializations = Stream.of(
+                Optional.ofNullable(authorization.getSpeciale1()),
+                Optional.ofNullable(authorization.getSpeciale2()),
+                Optional.ofNullable(authorization.getSpeciale3()))
+            .filter(Optional::isPresent)
+            .map(Optional::get)
+            .toList();
+
+        // There is no specified coded format for specializations in eHDSI CDA, and no way to send more than one
+        // specialization. So we send it over in an uncoded format. However, in order to display it on the receiver
+        // side, we do need to specify a code system. So we make one up. This is not the ideal way of doing this, we
+        // should ask for a code system from the EU and change the CDA format to support more than one specialization,
+        // but that could take years, so we do this for now.
+        return specializations.isEmpty() ? null : CdaCode.builder()
+            .codeSystem(Oid.DK_AUTHORIZATION_REGISTRY_SPECIALIZATION)
+            .code("not-coded")
path: country-a-service/cda-generator/src/main/java/dk/sundhedsdatastyrelsen/ncpeh/cda/EPrescriptionL3Mapper.java
user: login: jakobvase
body: I'll do what you suggest and write the code, and never let you hear the end of it if it doesn't work.
created_at: 2025-04-03T11:28:47Z
author_association: COLLABORATOR

PR comments:
user: login: sonarqubecloud[bot]
created_at: 2025-04-03T11:20:07Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [2 New issues](https://sonarcloud.io/project/issues?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [88.5% Coverage on New Code](https://sonarcloud.io/component_measures?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=Sundhedsdatastyrelsen_ehdsi&pullRequest=183)


author_association: NONE