diff --git a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java index 2cc0a26d..eebd2da0 100644 --- a/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java +++ b/ebl-surrender/src/main/java/org/dcsa/conformance/standards/eblsurrender/party/EblSurrenderPlatform.java @@ -3,6 +3,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.time.Instant; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -13,6 +15,7 @@ import org.dcsa.conformance.core.scenario.ConformanceAction; import org.dcsa.conformance.core.state.JsonNodeMap; import org.dcsa.conformance.core.state.StateManagementUtil; +import org.dcsa.conformance.core.toolkit.JsonToolkit; import org.dcsa.conformance.core.traffic.ConformanceMessageBody; import org.dcsa.conformance.core.traffic.ConformanceRequest; import org.dcsa.conformance.core.traffic.ConformanceResponse; @@ -42,13 +45,16 @@ public EblSurrenderPlatform( @Override protected void exportPartyJsonState(ObjectNode targetObjectNode) { - targetObjectNode.set("eblStatesById", StateManagementUtil.storeMap(objectMapper, eblStatesById, EblSurrenderState::name)); + targetObjectNode.set( + "eblStatesById", + StateManagementUtil.storeMap(objectMapper, eblStatesById, EblSurrenderState::name)); targetObjectNode.set("tdrsBySrr", StateManagementUtil.storeMap(objectMapper, tdrsBySrr)); } @Override protected void importPartyJsonState(ObjectNode sourceObjectNode) { - StateManagementUtil.restoreIntoMap(eblStatesById, sourceObjectNode.get("eblStatesById"), EblSurrenderState::valueOf); + StateManagementUtil.restoreIntoMap( + eblStatesById, sourceObjectNode.get("eblStatesById"), EblSurrenderState::valueOf); StateManagementUtil.restoreIntoMap(tdrsBySrr, sourceObjectNode.get("tdrsBySrr")); } @@ -75,40 +81,17 @@ private void requestSurrender(JsonNode actionPrompt) { forAmendment ? EblSurrenderState.AMENDMENT_SURRENDER_REQUESTED : EblSurrenderState.DELIVERY_SURRENDER_REQUESTED); - ObjectNode jsonRequestBody = - objectMapper - .createObjectNode() - .put("surrenderRequestReference", srr) - .put("transportDocumentReference", tdr) - .put("surrenderRequestCode", src); - - jsonRequestBody.set( - "surrenderRequestedBy", - objectMapper - .createObjectNode() - .put("eblPlatformIdentifier", "one@example.com") - .put("legalName", "Legal Name One")); - ObjectNode endorsementChainLink = - objectMapper - .createObjectNode() - .put("action", "ETOF") - .put("actionDateTime", "2023-08-27T19:38:24.342Z"); - endorsementChainLink.set( - "actor", - objectMapper - .createObjectNode() - .put("eblPlatformIdentifier", "two@example.com") - .put("legalName", "Legal Name Two")); - endorsementChainLink.set( - "recipient", - objectMapper - .createObjectNode() - .put("eblPlatformIdentifier", "three@example.com") - .put("legalName", "Legal Name Three")); + JsonNode jsonRequestBody = + JsonToolkit.templateFileToJsonNode( + "/standards/eblsurrender/messages/eblsurrender-api-%s-request.json" + .formatted(apiVersion.startsWith("3") ? "v30" : "v20"), + Map.ofEntries( + Map.entry("SURRENDER_REQUEST_REFERENCE_PLACEHOLDER", srr), + Map.entry("TRANSPORT_DOCUMENT_REFERENCE_PLACEHOLDER", tdr), + Map.entry("SURRENDER_REQUEST_CODE_PLACEHOLDER", src), + Map.entry("ACTION_DATE_TIME_PLACEHOLDER", Instant.now().toString()))); - jsonRequestBody.set( - "endorsementChain", objectMapper.createArrayNode().add(endorsementChainLink)); asyncCounterpartPost( "/%s/ebl-surrender-requests".formatted(apiVersion.startsWith("3") ? "v3" : "v2"), jsonRequestBody); diff --git a/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v20-request.json b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v20-request.json new file mode 100644 index 00000000..33ffb470 --- /dev/null +++ b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v20-request.json @@ -0,0 +1,23 @@ +{ + "surrenderRequestReference": "SURRENDER_REQUEST_REFERENCE_PLACEHOLDER", + "transportDocumentReference": "TRANSPORT_DOCUMENT_REFERENCE_PLACEHOLDER", + "surrenderRequestCode": "SURRENDER_REQUEST_CODE_PLACEHOLDER", + "surrenderRequestedBy": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + }, + "endorsementChain": [ + { + "action": "ETOF", + "actionDateTime": "ACTION_DATE_TIME_PLACEHOLDER", + "actor": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + }, + "recipient": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + } + } + ] +} diff --git a/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v30-request.json b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v30-request.json new file mode 100644 index 00000000..33ffb470 --- /dev/null +++ b/ebl-surrender/src/main/resources/standards/eblsurrender/messages/eblsurrender-api-v30-request.json @@ -0,0 +1,23 @@ +{ + "surrenderRequestReference": "SURRENDER_REQUEST_REFERENCE_PLACEHOLDER", + "transportDocumentReference": "TRANSPORT_DOCUMENT_REFERENCE_PLACEHOLDER", + "surrenderRequestCode": "SURRENDER_REQUEST_CODE_PLACEHOLDER", + "surrenderRequestedBy": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + }, + "endorsementChain": [ + { + "action": "ETOF", + "actionDateTime": "ACTION_DATE_TIME_PLACEHOLDER", + "actor": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + }, + "recipient": { + "eblPlatform": "ASDF", + "legalName": "Legal Name" + } + } + ] +} diff --git a/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v20-carrier.json b/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v20-carrier.json index 68787982..fdbc9398 100644 --- a/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v20-carrier.json +++ b/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v20-carrier.json @@ -103,7 +103,7 @@ "minLength": 2, "pattern": "^[A-Z]+$", "type": "string", - "description": "country code of the location of registration according to ISO 3166-1 alpha-2", + "description": "Country code of the location of registration according to ISO 3166-1 alpha-2", "example": "NL" }, "surrenderRequestReference": { @@ -128,15 +128,17 @@ }, "transactionParty": { "required": [ - "eblPlatformIdentifier", + "eblPlatform", "legalName" ], "type": "object", "properties": { - "eblPlatformIdentifier": { - "pattern": "\\S+@\\S+", + "eblPlatform": { + "maxLength": 4, + "pattern": "\\S+", "type": "string", - "example": "43549850248@exampleplatform.com" + "description": "The EBL platform of the transaction party. Should be a code from https://github.com/dcsaorg/DCSA-Information-Model/blob/master/datamodel/referencedata.d/eblsolutionproviders.csv.", + "example": "BOLE" }, "legalName": { "$ref": "#/components/schemas/legalName" @@ -150,19 +152,19 @@ "taxReference": { "pattern": "^\\S+$", "type": "string", - "description": "tax reference used in the location of registration", + "description": "Tax reference used in the location of registration", "example": "NL859951480B01" }, - "supportingPartyCodes": { - "$ref": "#/components/schemas/supportingPartyCodes" + "partyCodes": { + "$ref": "#/components/schemas/partyCodes" } }, "description": "refers to a company or a legal entity." }, - "supportingPartyCodes": { + "partyCodes": { "type": "array", "items": { - "$ref": "#/components/schemas/supportingPartyCodes_inner" + "$ref": "#/components/schemas/partyCodes_inner" } }, "endorsementChainLink": { @@ -363,7 +365,7 @@ "type": "string", "description": "A unique number allocated by the shipping line to the transport document and the main number used for the tracking of the status of the shipment.\n" }, - "supportingPartyCodes_inner": { + "partyCodes_inner": { "required": [ "partyCode", "partyCodeListProvider" @@ -374,16 +376,22 @@ "maxLength": 100, "minLength": 1, "pattern": "^\\S+(\\s+\\S+)*$", - "type": "string", - "example": "54930084UKLVMY22DS16" + "type": "string" }, "partyCodeListProvider": { "type": "string", - "description": "Describes which party code list the party code is from. Options are:\n\n - `LEI`: The party code is a Legal Entity Identifier (LEI) as issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en\n - `DID`: The party code is a Decentralized Identifier (see https://www.w3.org/TR/did-core/).\n", + "description": "Describes the organisation that provides the party code.\n\n - `EPUI`:The party code is an EBL Platform User Identifier (that is, an identifier provided by a platform, used to transfer eBLs). EPIU should be combined with the `codeListName`, to identify the platform that issued the identifier.\n - `GLEIF`: The party code is issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en. The `codeNameList` (if omitted) defaults to `LEI`.\n - `W3C`: The party code is issued by a standard created by World Wide Web Consortium (W3C). See https://www.w3.org/. The `codeNameList` (if omitted) defaults to `DID`.\n", "enum": [ - "LEI", - "DID" + "GLEIF", + "W3C", + "EPUI" ] + }, + "codeListName": { + "maxLength": 100, + "pattern": "^\\S+(\\s+\\S+)*$", + "type": "string", + "description": "The name of the code list / code generation mechanism / code authority for the party code.\n\nFor `EPUI`:\n * `Wave`: An identifier provided by Wave BL.\n * `CargoX`: An identifier provided by CargoX\n * `EdoxOnline`: An identifier provided by EdoxOnline\n * `IQAX`: An identifier provided by IQAX\n * `EssDOCS`: An identifier provided by essDOCS\n * `Bolero`: An identifier provided by Bolero\n * `TradeGO`: An identifierprovided by TradeGo\n * `Secro`: An identifier provided by Secro\n * `GSBN`: An identifier provided by GSBN\n * `WiseTech`: An identifier provided by WiseTech\n\nFor `W3C`:\n * `DID`: The party code is a Decentralized Identifier (see https://www.w3.org/TR/did-core/).\n\nFor `GLEIF`:\n * `LEI`: The party code is a Legal Entity Identifier (LEI) as issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en\n" } } } diff --git a/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v30-carrier.json b/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v30-carrier.json index 01fd779c..86c359b1 100644 --- a/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v30-carrier.json +++ b/ebl-surrender/src/main/resources/standards/eblsurrender/schemas/eblsurrender-v30-carrier.json @@ -103,7 +103,7 @@ "minLength": 2, "pattern": "^[A-Z]+$", "type": "string", - "description": "country code of the location of registration according to ISO 3166-1 alpha-2", + "description": "Country code of the location of registration according to ISO 3166-1 alpha-2", "example": "NL" }, "surrenderRequestReference": { @@ -128,15 +128,17 @@ }, "transactionParty": { "required": [ - "eblPlatformIdentifier", + "eblPlatform", "legalName" ], "type": "object", "properties": { - "eblPlatformIdentifier": { - "pattern": "\\S+@\\S+", + "eblPlatform": { + "maxLength": 4, + "pattern": "\\S+", "type": "string", - "example": "43549850248@exampleplatform.com" + "description": "The EBL platform of the transaction party. Should be a code from https://github.com/dcsaorg/DCSA-Information-Model/blob/master/datamodel/referencedata.d/eblsolutionproviders.csv.", + "example": "BOLE" }, "legalName": { "$ref": "#/components/schemas/legalName" @@ -150,19 +152,19 @@ "taxReference": { "pattern": "^\\S+$", "type": "string", - "description": "tax reference used in the location of registration", + "description": "Tax reference used in the location of registration", "example": "NL859951480B01" }, - "supportingPartyCodes": { - "$ref": "#/components/schemas/supportingPartyCodes" + "partyCodes": { + "$ref": "#/components/schemas/partyCodes" } }, "description": "refers to a company or a legal entity." }, - "supportingPartyCodes": { + "partyCodes": { "type": "array", "items": { - "$ref": "#/components/schemas/supportingPartyCodes_inner" + "$ref": "#/components/schemas/partyCodes_inner" } }, "endorsementChainLink": { @@ -239,9 +241,6 @@ "items": { "$ref": "#/components/schemas/endorsementChainLink" } - }, - "surrenderToCarrier": { - "$ref": "#/components/schemas/surrenderRequestDetails_surrenderToCarrier" } }, "description": "A concrete surrender request related to a transport document.\n\nThe platform guarantees *all* of the following:\n\n 1) The surrender request was submitted by the sole possessor of the EBL.\n 2) Depending on the eBL type:\n * For non-negoitable (\"straight\") eBLs, the surrender request was submitted by either the original shipper OR the consignee.\n * For negotiable eBLs with a named titleholder, the surrender request was submitted by the named titleholder.\n * For negotiable eBLs without a named titleholder / blank eBLs, possession is sufficient for the entity surrendering the eBL.\n 3) The platform has the EBL in custody while the carrier is evaluating this surrender request. I.e., neither possession nor title holder changes can occur until the carrier responds to this surrender request.\n" @@ -366,7 +365,7 @@ "type": "string", "description": "A unique number allocated by the shipping line to the transport document and the main number used for the tracking of the status of the shipment.\n" }, - "supportingPartyCodes_inner": { + "partyCodes_inner": { "required": [ "partyCode", "partyCodeListProvider" @@ -377,44 +376,24 @@ "maxLength": 100, "minLength": 1, "pattern": "^\\S+(\\s+\\S+)*$", - "type": "string", - "example": "54930084UKLVMY22DS16" + "type": "string" }, "partyCodeListProvider": { "type": "string", - "description": "Describes which party code list the party code is from. Options are:\n\n - `LEI`: The party code is a Legal Entity Identifier (LEI) as issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en\n - `DID`: The party code is a Decentralized Identifier (see https://www.w3.org/TR/did-core/).\n", + "description": "Describes the organisation that provides the party code.\n\n - `EPUI`:The party code is an EBL Platform User Identifier (that is, an identifier provided by a platform, used to transfer eBLs). EPIU should be combined with the `codeListName`, to identify the platform that issued the identifier.\n - `GLEIF`: The party code is issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en. The `codeNameList` (if omitted) defaults to `LEI`.\n - `W3C`: The party code is issued by a standard created by World Wide Web Consortium (W3C). See https://www.w3.org/. The `codeNameList` (if omitted) defaults to `DID`.\n", "enum": [ - "LEI", - "DID" + "GLEIF", + "W3C", + "EPUI" ] - } - } - }, - "surrenderRequestDetails_surrenderToCarrier": { - "required": [ - "partyCode", - "partyCodeListProvider" - ], - "properties": { - "partyCode": { - "maxLength": 4, - "minLength": 3, - "pattern": "^\\S+$", - "type": "string", - "description": "The code containing the NMFTA/SCAC and/or the SMDG code to specify the carrier.\n", - "example": "MSC" }, - "partyCodeListProvider": { + "codeListName": { + "maxLength": 100, + "pattern": "^\\S+(\\s+\\S+)*$", "type": "string", - "description": "Describes which party code list the party code is from. Options are:\n\n - `NMFTA`: The NMFTA (National Motor Freight Traffic Association) includes SPLC (Standard Point Location Code). This is sometimes also refered to as the SCAC code.\n - `SMDG`: The party code is a SMDG code from the Liner Code List.\n", - "example": "SMDG", - "enum": [ - "NMFTA", - "SMDG" - ] + "description": "The name of the code list / code generation mechanism / code authority for the party code.\n\nFor `EPUI`:\n * `Wave`: An identifier provided by Wave BL.\n * `CargoX`: An identifier provided by CargoX\n * `EdoxOnline`: An identifier provided by EdoxOnline\n * `IQAX`: An identifier provided by IQAX\n * `EssDOCS`: An identifier provided by essDOCS\n * `Bolero`: An identifier provided by Bolero\n * `TradeGO`: An identifierprovided by TradeGo\n * `Secro`: An identifier provided by Secro\n * `GSBN`: An identifier provided by GSBN\n * `WiseTech`: An identifier provided by WiseTech\n\nFor `W3C`:\n * `DID`: The party code is a Decentralized Identifier (see https://www.w3.org/TR/did-core/).\n\nFor `GLEIF`:\n * `LEI`: The party code is a Legal Entity Identifier (LEI) as issued by Global Legal Entity Identifier Foundation (GLEIF). See https://www.gleif.org/en\n" } - }, - "description": "Optinally, describe the carrier that the eBL should be surrendered to. " + } } }, "parameters": {