From e4ce8ad75d8cdf3bd7783a01ecae3a74d995a252 Mon Sep 17 00:00:00 2001 From: "J. Koster" Date: Thu, 28 Nov 2024 13:01:00 +0100 Subject: [PATCH] Add content check on Planned needs to match Required. Adopted some code for that. * Also update to latest JIT schema version --- .../core/check/ConformanceCheck.java | 3 +- .../standards/jit/JitScenarioListBuilder.java | 8 +- .../standards/jit/action/JitAction.java | 4 +- .../jit/action/JitPortCallServiceAction.java | 1 + .../jit/action/JitTimestampAction.java | 20 +- .../standards/jit/checks/JitChecks.java | 42 ++- .../standards/jit/model/JitSchema.java | 7 +- .../jit/party/DynamicScenarioParameters.java | 1 + .../standards/jit/party/JitConsumer.java | 2 +- .../standards/jit/party/JitProvider.java | 15 +- .../standards/jit/schemas/JIT_v2.0.0.yaml | 354 +++++++++++++++--- 11 files changed, 368 insertions(+), 89 deletions(-) diff --git a/core/src/main/java/org/dcsa/conformance/core/check/ConformanceCheck.java b/core/src/main/java/org/dcsa/conformance/core/check/ConformanceCheck.java index 5b9c7f67..e1490d15 100644 --- a/core/src/main/java/org/dcsa/conformance/core/check/ConformanceCheck.java +++ b/core/src/main/java/org/dcsa/conformance/core/check/ConformanceCheck.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.UUID; import java.util.function.Consumer; import java.util.function.Function; @@ -25,7 +26,7 @@ protected ConformanceCheck(String title) { private synchronized List getSubChecks() { if (_subChecks == null) { - this._subChecks = this.createSubChecks().collect(Collectors.toList()); + _subChecks = createSubChecks().filter(Objects::nonNull).collect(Collectors.toList()); } return _subChecks; } diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/JitScenarioListBuilder.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/JitScenarioListBuilder.java index be708674..89c8b21b 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/JitScenarioListBuilder.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/JitScenarioListBuilder.java @@ -37,7 +37,7 @@ public static LinkedHashMap createModuleScenario .then( sendTimestamp(context, JitTimestampType.ESTIMATED) .then( - sendTimestampConsumer(context, JitTimestampType.REQUESTED) + sendRequestedTimestamp(context) .then( sendTimestamp(context, JitTimestampType.PLANNED) .then( @@ -52,10 +52,10 @@ private static JitScenarioListBuilder sendTimestamp( previousAction -> new JitTimestampAction(context, previousAction, timestampType, true)); } - private static JitScenarioListBuilder sendTimestampConsumer( - JitScenarioContext context, JitTimestampType timestampType) { + private static JitScenarioListBuilder sendRequestedTimestamp( + JitScenarioContext context) { return new JitScenarioListBuilder( - previousAction -> new JitTimestampAction(context, previousAction, timestampType, false)); + previousAction -> new JitTimestampAction(context, previousAction, JitTimestampType.REQUESTED, false)); } private JitScenarioListBuilder(Function actionBuilder) { diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitAction.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitAction.java index 019a190a..8bc9acab 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitAction.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitAction.java @@ -35,7 +35,7 @@ public void reset() { public ObjectNode exportJsonState() { ObjectNode jsonState = super.exportJsonState(); if (dsp != null) { - jsonState.set("currentDsp", dsp.toJson()); + jsonState.set("dsp", dsp.toJson()); } return jsonState; } @@ -43,7 +43,7 @@ public ObjectNode exportJsonState() { @Override public void importJsonState(JsonNode jsonState) { super.importJsonState(jsonState); - JsonNode dspNode = jsonState.get("currentDsp"); + JsonNode dspNode = jsonState.get("dsp"); if (dspNode != null) { dsp = DynamicScenarioParameters.fromJson(dspNode); } diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitPortCallServiceAction.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitPortCallServiceAction.java index fd61f560..1bca28ee 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitPortCallServiceAction.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitPortCallServiceAction.java @@ -59,6 +59,7 @@ protected void doHandleExchange(ConformanceExchange exchange) { // Update DSP with the Port Call Service response from the provider dsp = new DynamicScenarioParameters( + null, null, null, PortCallServiceType.fromName( diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitTimestampAction.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitTimestampAction.java index 58c81ecf..090e2440 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitTimestampAction.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/action/JitTimestampAction.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; +import org.dcsa.conformance.core.check.ActionCheck; import org.dcsa.conformance.core.check.ConformanceCheck; import org.dcsa.conformance.core.check.HttpMethodCheck; import org.dcsa.conformance.core.check.JsonSchemaCheck; @@ -13,6 +14,7 @@ import org.dcsa.conformance.core.traffic.ConformanceExchange; import org.dcsa.conformance.core.traffic.HttpMessageType; import org.dcsa.conformance.standards.jit.JitScenarioContext; +import org.dcsa.conformance.standards.jit.checks.JitChecks; import org.dcsa.conformance.standards.jit.model.JitTimestamp; import org.dcsa.conformance.standards.jit.model.JitTimestampType; import org.dcsa.conformance.standards.jit.party.JitRole; @@ -51,7 +53,8 @@ protected void doHandleExchange(ConformanceExchange exchange) { JitTimestamp receivedTimestamp = JitTimestamp.fromJson(requestJsonNode); dsp = - dsp.withPreviousTimestamp(receivedTimestamp) + dsp.withPreviousTimestamp(dsp.currentTimestamp()) + .withCurrentTimestamp(receivedTimestamp) .withTimestampDateTime(receivedTimestamp.dateTime()) .withTimestampType( JitTimestampType.fromClassifierCode(receivedTimestamp.classifierCode())); @@ -76,9 +79,8 @@ public ConformanceCheck createCheck(String expectedApiVersion) { return new ConformanceCheck(getActionTitle()) { @Override protected Stream createSubChecks() { -// ActionCheck checksForTimestamp = -// JitChecks.createChecksForTimestamp( -// JitRole::isProvider, getMatchedExchangeUuid(), expectedApiVersion, dsp); + ActionCheck checksForTimestamp = + JitChecks.createChecksForTimestamp(getMatchedExchangeUuid(), expectedApiVersion, dsp); if (sendByProvider) { return Stream.of( new HttpMethodCheck(JitRole::isProvider, getMatchedExchangeUuid(), "PUT"), @@ -87,9 +89,8 @@ protected Stream createSubChecks() { JitRole::isProvider, getMatchedExchangeUuid(), HttpMessageType.REQUEST, - responseSchemaValidator) -// checksForTimestamp - ); + responseSchemaValidator), + checksForTimestamp); } // Consumer sends requested timestamp return Stream.of( @@ -99,9 +100,8 @@ protected Stream createSubChecks() { JitRole::isConsumer, getMatchedExchangeUuid(), HttpMessageType.REQUEST, - responseSchemaValidator) -// checksForTimestamp - ); + responseSchemaValidator), + checksForTimestamp); } }; } diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/checks/JitChecks.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/checks/JitChecks.java index 3982329a..945a58d4 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/checks/JitChecks.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/checks/JitChecks.java @@ -1,5 +1,6 @@ package org.dcsa.conformance.standards.jit.checks; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; @@ -10,6 +11,8 @@ import org.dcsa.conformance.core.check.JsonAttribute; import org.dcsa.conformance.core.check.JsonContentCheck; import org.dcsa.conformance.core.traffic.HttpMessageType; +import org.dcsa.conformance.standards.jit.model.JitClassifierCode; +import org.dcsa.conformance.standards.jit.model.JitTimestamp; import org.dcsa.conformance.standards.jit.model.PortCallServiceType; import org.dcsa.conformance.standards.jit.party.DynamicScenarioParameters; @@ -46,20 +49,35 @@ private static JsonContentCheck checkPortCallService(PortCallServiceType service } public static ActionCheck createChecksForTimestamp( - Predicate isRelevantForRoleName, - UUID matchedExchangeUuid, - String expectedApiVersion, - DynamicScenarioParameters dsp) { + UUID matchedExchangeUuid, + String expectedApiVersion, + DynamicScenarioParameters dsp) { + List checks = new ArrayList<>(); + if (dsp != null && dsp.currentTimestamp().classifierCode().equals(JitClassifierCode.PLN)) { + checks.add(checkPlannedMatchesRequestedTimestamp(dsp)); + } + if (checks.isEmpty()) return null; return JsonAttribute.contentChecks( - isRelevantForRoleName, - matchedExchangeUuid, - HttpMessageType.REQUEST, - expectedApiVersion, - List.of(checkPlannedMatchesRequestedTimestamp(dsp))); + x -> true, + matchedExchangeUuid, + HttpMessageType.REQUEST, + expectedApiVersion, + checks); } - private static JsonContentCheck checkPlannedMatchesRequestedTimestamp(DynamicScenarioParameters dsp) { - // TODO: Implement this check - return null; + private static JsonContentCheck checkPlannedMatchesRequestedTimestamp( + DynamicScenarioParameters dsp) { + return JsonAttribute.customValidator( + "Check if the Planned timestamp matches the Requested timestamp.", + body -> { + JitTimestamp receivedTimestamp = JitTimestamp.fromJson(body); + if (dsp.previousTimestamp().classifierCode().equals(JitClassifierCode.REQ) + && !dsp.previousTimestamp().dateTime().equals(receivedTimestamp.dateTime())) { + return Set.of( + "Expected matching timestamp: '%s' but got Planned timestamp: '%s'" + .formatted(dsp.previousTimestamp().dateTime(), receivedTimestamp.dateTime())); + } + return Collections.emptySet(); + }); } } diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/model/JitSchema.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/model/JitSchema.java index c5983da4..f86dc6d1 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/model/JitSchema.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/model/JitSchema.java @@ -1,5 +1,8 @@ package org.dcsa.conformance.standards.jit.model; +import lombok.Getter; + +@Getter public enum JitSchema { PORT_CALL_SERVICE("PortCallService"), ESTIMATED_TIMESTAMP(Constants.TIMESTAMP), @@ -15,10 +18,6 @@ public enum JitSchema { this.schemaName = schemaName; } - public String getSchemaName() { - return schemaName; - } - private static class Constants { public static final String TIMESTAMP = "Timestamp"; } diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/DynamicScenarioParameters.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/DynamicScenarioParameters.java index ba37d95b..29ec397a 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/DynamicScenarioParameters.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/DynamicScenarioParameters.java @@ -15,6 +15,7 @@ public record DynamicScenarioParameters( JitTimestampType timestampType, JitTimestamp previousTimestamp, + JitTimestamp currentTimestamp, PortCallServiceType portCallServiceType, String timestampDateTime, String portCallID, diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitConsumer.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitConsumer.java index f041b484..ab0a3af6 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitConsumer.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitConsumer.java @@ -86,7 +86,7 @@ private void timestampRequest(JsonNode actionPrompt) { DynamicScenarioParameters dsp = DynamicScenarioParameters.fromJson(actionPrompt.path("dsp")); JitTimestamp timestamp = - JitProvider.getTimestampForType(timestampType, dsp.previousTimestamp()); + JitProvider.getTimestampForType(timestampType, dsp.currentTimestamp()); syncCounterpartPut( JitStandard.PORT_CALL_SERVICES_URL + timestamp.portCallServiceID() + "/timestamp", diff --git a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitProvider.java b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitProvider.java index ab9a0fbb..81472ea8 100644 --- a/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitProvider.java +++ b/jit/src/main/java/org/dcsa/conformance/standards/jit/party/JitProvider.java @@ -83,14 +83,12 @@ private void timestampRequest(JsonNode actionPrompt) { JitTimestampType.valueOf(actionPrompt.required("timestampType").asText()); DynamicScenarioParameters dsp = DynamicScenarioParameters.fromJson(actionPrompt.path("dsp")); - JitTimestamp previousTimestamp = dsp.previousTimestamp(); + JitTimestamp previousTimestamp = + dsp.currentTimestamp(); // currentTimestamp is still the value from the previous action. // Create values for the first timestamp in the sequence. if (previousTimestamp == null) { previousTimestamp = getTimestampForType(JitTimestampType.ESTIMATED, null); - if (dsp.portCallServiceID() != null) { - previousTimestamp = previousTimestamp.withPortCallServiceID(dsp.portCallServiceID()); - } } JitTimestamp timestamp = getTimestampForType(timestampType, previousTimestamp); sendTimestampPutRequest(timestampType, timestamp); @@ -110,8 +108,7 @@ static JitTimestamp getTimestampForType( false, "Port closed due to strike"); case PLANNED, ACTUAL -> - previousTimestamp - .withClassifierCode(timestampType.getClassifierCode()); + previousTimestamp.withClassifierCode(timestampType.getClassifierCode()); case REQUESTED -> previousTimestamp .withClassifierCode(timestampType.getClassifierCode()) @@ -131,8 +128,7 @@ private void sendTimestampPutRequest( timestamp.toJson()); addOperatorLogEntry( - "Submitted %s timestamp for: %s" - .formatted(timestampType, timestamp.dateTime())); + "Submitted %s timestamp for: %s".formatted(timestampType, timestamp.dateTime())); } private JsonNode replacePlaceHolders( @@ -158,7 +154,8 @@ public ConformanceResponse handleRequest(ConformanceRequest request) { "Handled %s timestamp accepted for date/time: %s and remark: %s" .formatted( JitTimestampType.fromClassifierCode(timestamp.classifierCode()), - timestamp.dateTime(), timestamp.remark())); + timestamp.dateTime(), + timestamp.remark())); return request.createResponse( 204, diff --git a/jit/src/main/resources/standards/jit/schemas/JIT_v2.0.0.yaml b/jit/src/main/resources/standards/jit/schemas/JIT_v2.0.0.yaml index 66a8bb2e..b2cb5e02 100644 --- a/jit/src/main/resources/standards/jit/schemas/JIT_v2.0.0.yaml +++ b/jit/src/main/resources/standards/jit/schemas/JIT_v2.0.0.yaml @@ -174,59 +174,55 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' + '/v2/port-call-services': get: parameters: - - $ref: '#/components/parameters/portCallServiceIDPathParam' + - $ref: '#/components/parameters/portCallIDQueryParam' + - $ref: '#/components/parameters/transportCallIDQueryParam' + - $ref: '#/components/parameters/portCallServiceIDQueryParam' + + - $ref: '#/components/parameters/startDateTimeQueryParam' + - $ref: '#/components/parameters/endDateTimeQueryParam' + + - $ref: '#/components/parameters/UNLocationCodeQueryParameter' + - $ref: '#/components/parameters/portVisitReferenceQueryParam' + - $ref: '#/components/parameters/carrierServiceNameQueryParam' + - $ref: '#/components/parameters/carrierServiceCodeQueryParam' + - $ref: '#/components/parameters/universalServiceReferenceQueryParam' + + - $ref: '#/components/parameters/transportCallReferenceQueryParam' + - $ref: '#/components/parameters/transportCallSequenceNumberQueryParam' + - $ref: '#/components/parameters/carrierImportVoyageNumberQueryParam' + - $ref: '#/components/parameters/carrierExportVoyageNumberQueryParam' + - $ref: '#/components/parameters/universalImportVoyageReferenceQueryParam' + - $ref: '#/components/parameters/universalExportVoyageReferenceQueryParam' + - $ref: '#/components/parameters/portCallServiceTypeQueryParam' + - $ref: '#/components/parameters/portCallServiceEventTypeCodeQueryParam' + + - $ref: '#/components/parameters/vesselIMONumberQueryParam' + - $ref: '#/components/parameters/vesselNameQueryParam' + - $ref: '#/components/parameters/MMSINumberQueryParam' + + - $ref: '#/components/parameters/limitQueryParam' + - $ref: '#/components/parameters/cursorQueryParam' - $ref: '#/components/parameters/Api-Version-Major' tags: - Port Call Service - operationId: get-port-call-service - summary: Retrieves a Port Call Service + operationId: get-port-call-services + summary: Retrieve a list of Port Call Services. description: | - Retrieves a Port Call Service + Retrieve a list of Port Call Services. responses: '200': description: | - Get the Port Call Service - headers: - API-Version: - $ref: '#/components/headers/API-Version' - content: - application/json: - schema: - $ref: '#/components/schemas/PortCallService' - '404': - description: | - In case the provider does not know of the `portCallServiceID` used in the request (this could be because of a `PUT` request that has not finished processing or simply because the resource does not exist) - it is possible for the provider to reject the requests by returning a `404` (Not Found). + Get the list of Port Call Services matching the specified filter(s). headers: API-Version: $ref: '#/components/headers/API-Version' content: application/json: schema: - $ref: '#/components/schemas/ErrorResponse' - examples: - notFoundExample: - summary: | - Not Found request - description: | - The provided `portCallServiceID` cannot be found. This can be because a `PUT` request has not been finished processing or because the `portCallServiceID` does not exist in the provider system. - - **NB**: `errorCode` not yet standardized by DCSA. Value `7006` is just a "random example" - value: - httpMethod: GET - requestUri: /v2/port-call-services/085a3207-5e45-49cf-8e1b-f8442beaf545 - statusCode: 404 - statusCodeText: Not Found - statusCodeMessage: | - portCallServiceID not found - providerCorrelationReference: 4426d965-0dd8-4005-8c63-dc68b01c4962 - errorDateTime: '2024-09-04T09:41:00Z' - errors: - - errorCode: 7006 - errorCodeText: portCallServiceID Not Found - errorCodeMessage: | - The Port Call Service does not exist + $ref: '#/components/schemas/PortCallServices' '500': description: | In case a server error occurs in provider system a `500` (Internal Server Error) is returned @@ -940,6 +936,263 @@ components: example: '2' description: | An API-Version header **MAY** be added to the request (optional); if added it **MUST** only contain **MAJOR** version. API-Version header **MUST** be aligned with the URI version. + ############## + # Query params + ############## + + # Technical query parameters + + portCallIDQueryParam: + in: query + name: portCallID + description: | + The **Port Call Identifier** to filter by. Specifying this filter will only return **Port Call Service** objects including the `portCallID`. + schema: + type: string + format: uuid + example: 0342254a-5927-4856-b9c9-aa12e7c00563 + transportCallIDQueryParam: + in: query + name: transportCallID + description: | + The **Transport Call Identifier** to filter by. Specifying this filter will only return **Port Call Service** objects including the `transportCallID`. + schema: + type: string + format: uuid + example: 0342254a-5927-4856-b9c9-aa12e7c00563 + portCallServiceIDQueryParam: + in: query + name: portCallServiceID + description: | + The **Port Call Service Identifier** to filter by. Specifying this filter will (at most) return a single **Port Call Service** object including the `portCallServiceID` (if the `portCallServiceID` exists). + schema: + type: string + format: uuid + example: 0342254a-5927-4856-b9c9-aa12e7c00563 + + # Timestamp query parameters + + startDateTimeQueryParam: + in: query + name: startDateTime + description: | + The **Start Date Time** of the period for which **Port Call Service** information is requested. If a date and time of any **Timestamp** inside a **Port Call Service** matches a date and time on or after (≥) the `startDateTime`, the **Port Call Service** will be included in the result. All matching is done towards local Date and time at the place of the **Port Call Service**. The matched **Timestamp** in the timestamps of the **Port Call Service** must be included in the **Port Call Service** objects returned. + If this filter is not provided the default value is `3 months` prior to request time. The value is populated in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) date format. + schema: + type: string + format: date-time + example: '2020-04-06T07:41:00+08:30' + endDateTimeQueryParam: + in: query + name: endDateTime + description: | + The **End Date Time** of the period for which **Port Call Service** information is requested. If a date and time of any **Timestamp** inside a **Port Call Service** matches a date and time on or before (≤) the `endDateTime`, the **Port Call Service** will be included in the result. All matching is done towards local Date and time at the place of the **Port Call Service**. The matched **Timestamp** in the timestamps of the **Port Call Service** must be included in the **Port Call Service** objects returned. + If this filter is not provided the default value is `6 months` after request time. The value is populated in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) date format. + schema: + type: string + format: date-time + example: '2020-04-10T07:41:00+08:30' + + # Port Call query parameters + + UNLocationCodeQueryParameter: + in: query + name: UNLocationCode + description: | + The **UN Location Code** specifying where a port is located. Specifying this filter will only return **Port Call Service** objects including the `UNLocationCode`. + schema: + type: string + pattern: ^[A-Z]{2}[A-Z2-9]{3}$ + minLength: 5 + maxLength: 5 + example: NLAMS + portVisitReferenceQueryParam: + in: query + name: portVisitReference + description: | + The **Port Visit Reference** to filter by. The result will only return **Port Call Service** objects including the `portVisitReference`. + schema: + type: string + maxLength: 50 + example: NLAMS1234589 + carrierServiceNameQueryParam: + in: query + name: carrierServiceName + description: | + The **Carrier specific Service Name** to filter by. The result will only return **Port Call Service** objects including the `carrierServiceName`. + schema: + type: string + maxLength: 50 + pattern: ^\S(?:.*\S)?$ + example: Great Lion Service + carrierServiceCodeQueryParam: + in: query + name: carrierServiceCode + description: | + The **Carrier specific Service Code** to filter by. The result will only return **Port Call Service** objects including the `carrierServiceCode`. + schema: + type: string + maxLength: 11 + pattern: ^\S(?:.*\S)?$ + example: FE1 + universalServiceReferenceQueryParam: + in: query + name: universalServiceReference + description: | + The **Universal Service Reference** (`USR`) as defined by DCSA to filter by. The result will only return **Port Call Service** objects including the `universalServiceReference`. + schema: + type: string + pattern: ^SR\d{5}[A-Z]$ + maxLength: 8 + minLength: 8 + example: SR12345A + + # Transport Call query parameters + + transportCallReferenceQueryParam: + in: query + name: transportCallReference + description: | + The **Transport Call Reference** to filter by. The result will only return **Port Call Service** objects including the `transportCallReference`. + schema: + type: string + maxLength: 100 + example: '15063401' + transportCallSequenceNumberQueryParam: + in: query + name: transportCallSequenceNumber + description: | + The **Transport Call Sequence Number** to filter by. The result will only return **Port Call Service** objects including the `transportCallSequenceNumber`. + schema: + type: integer + format: int32 + example: 2 + carrierImportVoyageNumberQueryParam: + in: query + name: carrierImportVoyageNumber + description: | + The **Carrier Import Voyage Number** to filter by. The result will only return **Port Call Service** objects including the `carrierImportVoyageNumber`. + schema: + type: string + maxLength: 50 + pattern: ^\S(?:.*\S)?$ + example: 2103N + carrierExportVoyageNumberQueryParam: + in: query + name: carrierExportVoyageNumber + description: | + The **Carrier Export Voyage Number** to filter by. The result will only return **Port Call Service** objects including the `carrierExportVoyageNumber`. + schema: + type: string + maxLength: 50 + pattern: ^\S(?:.*\S)?$ + example: 2103S + universalImportVoyageReferenceQueryParam: + in: query + name: universalImportVoyageReference + description: | + The **Universal Import Voyage Reference** to filter by. The result will only return **Port Call Service** objects including the `universalImportVoyageReference`. + schema: + type: string + pattern: ^\d{2}[0-9A-Z]{2}[NEWSR]$ + minLength: 5 + maxLength: 5 + example: 2103N + universalExportVoyageReferenceQueryParam: + in: query + name: universalExportVoyageReference + description: | + The **Universal Export Voyage Reference** to filter by. The result will only return **Port Call Service** objects including the `universalExportVoyageReference`. + schema: + type: string + pattern: ^\d{2}[0-9A-Z]{2}[NEWSR]$ + minLength: 5 + maxLength: 5 + example: 2103N + + # Port Call Service query parameters + + portCallServiceTypeQueryParam: + in: query + name: portCallServiceType + description: | + The **Port Call Service Type** to filter by. The result will only return **Port Call Service** objects including the `portCallServiceType`. + schema: + type: string + maxLength: 50 + pattern: ^\S(?:.*\S)?$ + example: BERTH + portCallServiceEventTypeCodeQueryParam: + in: query + name: portCallServiceEventTypeCode + description: | + The **Port Call Service Event Type Code** to filter by. The result will only return **Port Call Service** objects including the `portCallServiceEventTypeCode`. + schema: + type: string + enum: + - STRT + - CMPL + - ARRI + - DEPA + example: STRT + + # Vessel query parameters + + vesselIMONumberQueryParam: + in: query + name: vesselIMONumber + description: | + The **Vessel IMO Number** to filter by. The result will only return **Port Call Service** objects including the `vesselIMONumber`. + schema: + type: string + pattern: ^\d{7,8}$ + minLength: 7 + maxLength: 8 + example: '9321483' + vesselNameQueryParam: + in: query + name: vesselName + description: | + The **Vessel Name** to filter by. The result will only return **Port Call Service** objects including the `vesselName`. + schema: + type: string + pattern: ^\S(?:.*\S)?$ + maxLength: 50 + example: King of the Seas + MMSINumberQueryParam: + in: query + name: MMSINumber + description: | + The **MMSI Number** to filter by. The result will only return **Port Call Service** objects including the `MMSINumber`. + schema: + type: string + pattern: ^\d{9}$ + minLength: 9 + maxLength: 9 + example: '278111222' + + # Pagination query parameters + + limitQueryParam: + in: query + name: limit + description: | + Specifies the maximum number of `Port Call Service` objects to return. + schema: + type: integer + format: int32 + minimum: 1 + default: 100 + example: 100 + cursorQueryParam: + in: query + name: cursor + description: | + A server generated value to specify a specific point in a collection result, used for pagination. + schema: + type: string + maxLength: 1024 + example: fE9mZnNldHw9MTAmbGltaXQ9MTA ############# # Path params @@ -975,6 +1228,15 @@ components: example: 0342254a-5927-4856-b9c9-aa12e7c00563 required: true schemas: + #################### + # Port Call Services + #################### + PortCallServices: + type: array + description: | + An array of **Port Call Services** matching the specified filter. + items: + $ref: '#/components/schemas/PortCallService' ################### # Port Call Service @@ -1015,7 +1277,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true required: - portCall @@ -1256,7 +1518,7 @@ components: type: number format: float description: | - The actual draft of the vessel. + The vertical distance between the waterline and the bottom of the hull (keel) of a ship. The depth to which a ship is immersed in water. If the draft is specified in feet (`FOT`) then the decimal part should be considered as a fraction of a foot and **not** as a number of inches. E.g. 120.5 feet means 120 and a half foot (which would be 120'6") example: 12.5 @@ -1553,7 +1815,7 @@ components: title: Timestamp type: object description: | - Date and time for a `ERPA` Timestamp when a **Port Call Service** should be provided (for `ERP`) or has been provided (for `A`). + Date and time for an `ERP-A` Timestamp when a **Port Call Service** should be provided (for `ERP`) or has been provided (for `A`). properties: timestampID: type: string @@ -1614,7 +1876,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true remark: type: string @@ -1640,7 +1902,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true reason: type: string @@ -1661,7 +1923,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true reason: type: string @@ -1682,7 +1944,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true reason: type: string @@ -1700,7 +1962,7 @@ components: isFYI: type: boolean description: | - If set to `true` it indicates that this message is meant for another party - but is sent as a FYI (for your information). + If set to `true` it indicates that this message is primarily meant for another party - but is sent as a FYI (for your information). example: true reason: type: string