Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DT-637 + DT-638: UC9 + UC10 - Request / Process Surrender of Transport Document for Amendment #28

Merged
merged 2 commits into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private EblScenarioListBuilder thenAllPathsFrom(
.thenHappyPathFrom(SI_RECEIVED)),
uc4d_carrier_declineUpdatedShippingInstructions()
.then(shipper_GetShippingInstructions(SI_RECEIVED, SI_DECLINED, TD_START)
.thenAllPathsFrom(SI_DECLINED)));
.thenHappyPathFrom(SI_DECLINED)));
case SI_DECLINED -> thenEither(
uc6_carrier_publishDraftTransportDocument()
.then(shipper_GetShippingInstructions(SI_RECEIVED, TD_DRAFT, true)
Expand All @@ -79,7 +79,13 @@ private EblScenarioListBuilder thenAllPathsFrom(
.thenHappyPathFrom(SI_PENDING_UPDATE)),
uc3_shipper_submitUpdatedShippingInstructions()
.then(shipper_GetShippingInstructions(SI_UPDATE_RECEIVED, TD_START)
.thenAllPathsFrom(SI_UPDATE_RECEIVED)));
case SI_PENDING_UPDATE -> then(uc3_shipper_submitUpdatedShippingInstructions()
.then(
shipper_GetShippingInstructions(SI_RECEIVED, SI_UPDATE_RECEIVED, TD_START)
.thenHappyPathFrom(SI_UPDATE_RECEIVED)));
case SI_ANY -> throw new AssertionError("Not a real/reachable state");
case SI_COMPLETED -> then(noAction());
default -> then(noAction()); // TODO
};
}
Expand All @@ -100,6 +106,8 @@ private EblScenarioListBuilder thenHappyPathFrom(
.then(shipper_GetShippingInstructions(SI_RECEIVED, TD_START)
.thenHappyPathFrom(SI_RECEIVED))
);
case SI_COMPLETED -> then(noAction());
case SI_START, SI_ANY -> throw new AssertionError("Not a real/reachable state");
default -> then(noAction()); // TODO
};
}
Expand All @@ -111,23 +119,39 @@ private EblScenarioListBuilder thenAllPathsFrom(TransportDocumentStatus transpor
.then(
shipper_GetTransportDocument(TD_ISSUED)
.thenAllPathsFrom(TD_ISSUED)));
case TD_ISSUED -> then(
case TD_ISSUED -> thenEither(
uc9_carrier_awaitSurrenderRequestForAmendment()
.then(shipper_GetTransportDocument(TD_PENDING_SURRENDER_FOR_AMENDMENT)
.thenAllPathsFrom(TD_PENDING_SURRENDER_FOR_AMENDMENT)),
uc12_carrier_awaitSurrenderRequestForDelivery()
.then(shipper_GetTransportDocument(TD_PENDING_SURRENDER_FOR_DELIVERY)
.thenAllPathsFrom(TD_PENDING_SURRENDER_FOR_DELIVERY))
);
case TD_PENDING_SURRENDER_FOR_AMENDMENT -> thenEither(
uc10a_carrier_acceptSurrenderRequestForAmendment().then(
shipper_GetTransportDocument(TD_SURRENDERED_FOR_AMENDMENT)
.thenAllPathsFrom(TD_SURRENDERED_FOR_AMENDMENT)
),
uc10r_carrier_rejectSurrenderRequestForAmendment().then(
shipper_GetTransportDocument(TD_ISSUED)
.thenHappyPathFrom(TD_ISSUED)
)
);
case TD_SURRENDERED_FOR_AMENDMENT -> then(noAction()); // TODO: Implement
case TD_PENDING_SURRENDER_FOR_DELIVERY -> thenEither(
uc13a_carrier_acceptSurrenderRequestForDelivery().then(
shipper_GetTransportDocument(TD_SURRENDERED_FOR_DELIVERY)
.thenAllPathsFrom(TD_SURRENDERED_FOR_DELIVERY)
),
uc13r_carrier_rejectSurrenderRequestForDelivery().then(
shipper_GetTransportDocument(TD_SURRENDERED_FOR_DELIVERY)
shipper_GetTransportDocument(TD_ISSUED)
.thenHappyPathFrom(TD_ISSUED)
)
);
case TD_SURRENDERED_FOR_DELIVERY -> thenHappyPathFrom(transportDocumentStatus);
default -> then(noAction()); // TODO
case TD_START, TD_ANY -> throw new AssertionError("Not a real/reachable state");
case TD_VOIDED -> then(noAction());
default -> throw new AssertionError("Not implemented: " + transportDocumentStatus.name());
};
}

Expand All @@ -137,12 +161,19 @@ private EblScenarioListBuilder thenHappyPathFrom(TransportDocumentStatus transpo
uc8_carrier_issueTransportDocument()
.then(
shipper_GetTransportDocument(TD_ISSUED)
.thenAllPathsFrom(TD_ISSUED)));
.thenHappyPathFrom(TD_ISSUED)));
case TD_ISSUED -> then(
uc12_carrier_awaitSurrenderRequestForDelivery()
.then(shipper_GetTransportDocument(TD_PENDING_SURRENDER_FOR_DELIVERY)
.thenHappyPathFrom(TD_PENDING_SURRENDER_FOR_DELIVERY))
);
case TD_PENDING_SURRENDER_FOR_AMENDMENT -> then(
uc10a_carrier_acceptSurrenderRequestForAmendment().then(
shipper_GetTransportDocument(TD_SURRENDERED_FOR_AMENDMENT)
.thenHappyPathFrom(TD_SURRENDERED_FOR_AMENDMENT)
)
);
case TD_SURRENDERED_FOR_AMENDMENT -> then(noAction()); // TODO: Implement
case TD_PENDING_SURRENDER_FOR_DELIVERY -> then(
uc13a_carrier_acceptSurrenderRequestForDelivery().then(
shipper_GetTransportDocument(TD_SURRENDERED_FOR_DELIVERY)
Expand All @@ -154,7 +185,9 @@ private EblScenarioListBuilder thenHappyPathFrom(TransportDocumentStatus transpo
shipper_GetShippingInstructions(SI_COMPLETED, TD_SURRENDERED_FOR_DELIVERY)
)
);
default -> then(noAction()); // TODO
case TD_START, TD_ANY -> throw new AssertionError("Not a real/reachable state");
case TD_VOIDED -> then(noAction());
default -> throw new AssertionError("Not implemented: " + transportDocumentStatus.name());
};
}

Expand Down Expand Up @@ -330,6 +363,50 @@ private static EblScenarioListBuilder uc8_carrier_issueTransportDocument() {
EBL_NOTIFICATIONS_API, EBL_TD_NOTIFICATION_SCHEMA_NAME)));
}

private static EblScenarioListBuilder uc9_carrier_awaitSurrenderRequestForAmendment() {
EblComponentFactory componentFactory = threadLocalComponentFactory.get();
String carrierPartyName = threadLocalCarrierPartyName.get();
String shipperPartyName = threadLocalShipperPartyName.get();
return new EblScenarioListBuilder(
previousAction ->
new UC9_Carrier_AwaitSurrenderRequestForAmendmentAction(
carrierPartyName,
shipperPartyName,
(EblAction) previousAction,
componentFactory.getMessageSchemaValidator(
EBL_NOTIFICATIONS_API, EBL_TD_NOTIFICATION_SCHEMA_NAME)));
}

private static EblScenarioListBuilder uc10a_carrier_acceptSurrenderRequestForAmendment() {
EblComponentFactory componentFactory = threadLocalComponentFactory.get();
String carrierPartyName = threadLocalCarrierPartyName.get();
String shipperPartyName = threadLocalShipperPartyName.get();
return new EblScenarioListBuilder(
previousAction ->
new UC10_Carrier_ProcessSurrenderRequestForAmendmentAction(
carrierPartyName,
shipperPartyName,
(EblAction) previousAction,
componentFactory.getMessageSchemaValidator(
EBL_NOTIFICATIONS_API, EBL_TD_NOTIFICATION_SCHEMA_NAME),
true));
}

private static EblScenarioListBuilder uc10r_carrier_rejectSurrenderRequestForAmendment() {
EblComponentFactory componentFactory = threadLocalComponentFactory.get();
String carrierPartyName = threadLocalCarrierPartyName.get();
String shipperPartyName = threadLocalShipperPartyName.get();
return new EblScenarioListBuilder(
previousAction ->
new UC10_Carrier_ProcessSurrenderRequestForAmendmentAction(
carrierPartyName,
shipperPartyName,
(EblAction) previousAction,
componentFactory.getMessageSchemaValidator(
EBL_NOTIFICATIONS_API, EBL_TD_NOTIFICATION_SCHEMA_NAME),
false));
}

private static EblScenarioListBuilder uc12_carrier_awaitSurrenderRequestForDelivery() {
EblComponentFactory componentFactory = threadLocalComponentFactory.get();
String carrierPartyName = threadLocalCarrierPartyName.get();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.dcsa.conformance.standards.ebl.action;

import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.stream.Stream;
import lombok.Getter;
import org.dcsa.conformance.core.check.*;

@Getter
public class UC10_Carrier_ProcessSurrenderRequestForAmendmentAction extends StateChangingSIAction {
private final JsonSchemaValidator requestSchemaValidator;
private final boolean acceptAmendmentRequest;

public UC10_Carrier_ProcessSurrenderRequestForAmendmentAction(
String carrierPartyName,
String shipperPartyName,
EblAction previousAction,
JsonSchemaValidator requestSchemaValidator,
boolean acceptAmendmentRequest) {
super(carrierPartyName, shipperPartyName, previousAction, acceptAmendmentRequest ? "UC10a" : "UC10r", 204);
this.requestSchemaValidator = requestSchemaValidator;
this.acceptAmendmentRequest = acceptAmendmentRequest;
}

@Override
public String getHumanReadablePrompt() {
if (acceptAmendmentRequest) {
return ("UC10a: Accept surrender request for amendment for transport document with reference %s"
.formatted(getDspSupplier().get().transportDocumentReference()));
}
return ("UC10r: Reject surrender request for amendment for transport document with reference %s"
.formatted(getDspSupplier().get().transportDocumentReference()));
}

@Override
public ObjectNode asJsonNode() {
return super.asJsonNode()
.put("documentReference", getDspSupplier().get().transportDocumentReference())
.put("acceptAmendmentRequest", acceptAmendmentRequest);
}

@Override
public ConformanceCheck createCheck(String expectedApiVersion) {
return new ConformanceCheck(getActionTitle()) {
@Override
protected Stream<? extends ConformanceCheck> createSubChecks() {
return getTDNotificationChecks(
getMatchedExchangeUuid(),
expectedApiVersion,
requestSchemaValidator
);
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.dcsa.conformance.standards.ebl.action;

import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.stream.Stream;
import lombok.Getter;
import org.dcsa.conformance.core.check.*;

@Getter
public class UC9_Carrier_AwaitSurrenderRequestForAmendmentAction extends StateChangingSIAction {
private final JsonSchemaValidator requestSchemaValidator;

public UC9_Carrier_AwaitSurrenderRequestForAmendmentAction(
String carrierPartyName,
String shipperPartyName,
EblAction previousAction,
JsonSchemaValidator requestSchemaValidator) {
super(carrierPartyName, shipperPartyName, previousAction, "UC9", 204);
this.requestSchemaValidator = requestSchemaValidator;
}

@Override
public String getHumanReadablePrompt() {
return ("UC9: Shipper requests surrender for amendment (via the surrender API if applicable) for transport document with reference %s and carrier sends notification that surrender has been requested. Note when the conformance toolkit is acting as carrier, no action is required from the shipper (the action will auto-resolve). When the conformance toolkit is acting like the Shipper, you will have to ensure that the carrier system sees a surrender request (the surrender uses a different API not in scope for this test)."
.formatted(getDspSupplier().get().transportDocumentReference()));
}

@Override
public ObjectNode asJsonNode() {
return super.asJsonNode()
.put("documentReference", getDspSupplier().get().transportDocumentReference());
}

@Override
public ConformanceCheck createCheck(String expectedApiVersion) {
return new ConformanceCheck(getActionTitle()) {
@Override
protected Stream<? extends ConformanceCheck> createSubChecks() {
return getTDNotificationChecks(
getMatchedExchangeUuid(),
expectedApiVersion,
requestSchemaValidator
);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,23 @@ public void confirmShippingInstructionsComplete(String documentReference) {
changeSIState(SI_STATUS, SI_COMPLETED);
}


public void acceptSurrenderForAmendment(String documentReference) {
checkState(documentReference, getTransportDocumentState(), s -> s == TD_PENDING_SURRENDER_FOR_AMENDMENT);
var td = getTransportDocument().orElseThrow();
td.put(TRANSPORT_DOCUMENT_STATUS, TD_SURRENDERED_FOR_AMENDMENT.wireName());
}

public void rejectSurrenderForAmendment(String documentReference) {
checkState(documentReference, getTransportDocumentState(), s -> s == TD_PENDING_SURRENDER_FOR_AMENDMENT);
var td = getTransportDocument().orElseThrow();
td.put(TRANSPORT_DOCUMENT_STATUS, TD_ISSUED.wireName());
}

public void acceptSurrenderForDelivery(String documentReference) {
checkState(documentReference, getTransportDocumentState(), s -> s == TD_PENDING_SURRENDER_FOR_DELIVERY);
var td = getTransportDocument().orElseThrow();
td.put(TRANSPORT_DOCUMENT_STATUS, TD_SURRENDERED_FOR_AMENDMENT.wireName());
td.put(TRANSPORT_DOCUMENT_STATUS, TD_SURRENDERED_FOR_DELIVERY.wireName());
}

public void rejectSurrenderForDelivery(String documentReference) {
Expand Down Expand Up @@ -221,12 +234,19 @@ public void issueTransportDocument(String documentReference) {
.put(shippedDateField, date);
}

public void surrenderForAmendmentRequest(String documentReference) {
checkState(documentReference, getTransportDocumentState(), s -> s == TD_ISSUED);
var td = getTransportDocument().orElseThrow();
td.put(TRANSPORT_DOCUMENT_STATUS, TD_PENDING_SURRENDER_FOR_AMENDMENT.wireName());
}

public void surrenderForDeliveryRequest(String documentReference) {
checkState(documentReference, getTransportDocumentState(), s -> s == TD_ISSUED);
var td = getTransportDocument().orElseThrow();
td.put(TRANSPORT_DOCUMENT_STATUS, TD_PENDING_SURRENDER_FOR_DELIVERY.wireName());
}


private void copyFieldIfPresent(JsonNode source, ObjectNode dest, String field) {
var data = source.get(field);
if (data != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ protected Map<Class<? extends ConformanceAction>, Consumer<JsonNode>> getActionP
Map.entry(UC4_Carrier_ProcessUpdateToShippingInstructionsAction.class, this::processUpdatedShippingInstructions),
Map.entry(UC6_Carrier_PublishDraftTransportDocumentAction.class, this::publishDraftTransportDocument),
Map.entry(UC8_Carrier_IssueTransportDocumentAction.class, this::issueTransportDocument),
Map.entry(UC9_Carrier_AwaitSurrenderRequestForAmendmentAction.class, this::notifyOfSurrenderForAmendment),
Map.entry(UC10_Carrier_ProcessSurrenderRequestForAmendmentAction.class, this::processSurrenderRequestForAmendment),
Map.entry(UC12_Carrier_AwaitSurrenderRequestForDeliveryAction.class, this::notifyOfSurrenderForDelivery),
Map.entry(UC13_Carrier_ProcessSurrenderRequestForDeliveryAction.class, this::processSurrenderRequestForDelivery),
Map.entry(UC14_Carrier_ConfirmShippingInstructionsCompleteAction.class, this::confirmShippingInstructionsComplete)
Expand Down Expand Up @@ -165,6 +167,20 @@ private void issueTransportDocument(JsonNode actionPrompt) {
addOperatorLogEntry("Issued transport document '%s'".formatted(documentReference));
}

private void notifyOfSurrenderForAmendment(JsonNode actionPrompt) {
log.info("Carrier.notifyOfSurrenderForAmendment(%s)".formatted(actionPrompt.toPrettyString()));

var documentReference = actionPrompt.required("documentReference").asText();
var sir = tdrToSir.getOrDefault(documentReference, documentReference);

var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir);
si.surrenderForAmendmentRequest(documentReference);
si.save(persistentMap);
generateAndEmitNotificationFromTransportDocument(actionPrompt, si, true);

addOperatorLogEntry("Sent notification for surrender for amendment of transport document with reference '%s'".formatted(documentReference));
}

private void notifyOfSurrenderForDelivery(JsonNode actionPrompt) {
log.info("Carrier.notifyOfSurrenderForDelivery(%s)".formatted(actionPrompt.toPrettyString()));

Expand All @@ -179,6 +195,24 @@ private void notifyOfSurrenderForDelivery(JsonNode actionPrompt) {
addOperatorLogEntry("Sent notification for surrender for delivery of transport document with reference '%s'".formatted(documentReference));
}

private void processSurrenderRequestForAmendment(JsonNode actionPrompt) {
log.info("Carrier.processSurrenderRequestForAmendment(%s)".formatted(actionPrompt.toPrettyString()));

var documentReference = actionPrompt.required("documentReference").asText();
var sir = tdrToSir.getOrDefault(documentReference, documentReference);
var accept = actionPrompt.required("acceptAmendmentRequest").asBoolean(true);

var si = CarrierShippingInstructions.fromPersistentStore(persistentMap, sir);
if (accept) {
si.acceptSurrenderForAmendment(documentReference);
} else {
si.rejectSurrenderForAmendment(documentReference);
}
si.save(persistentMap);
generateAndEmitNotificationFromTransportDocument(actionPrompt, si, true);

addOperatorLogEntry("Processed surrender request for delivery of transport document with reference '%s'".formatted(documentReference));
}

private void processSurrenderRequestForDelivery(JsonNode actionPrompt) {
log.info("Carrier.processSurrenderRequestForDelivery(%s)".formatted(actionPrompt.toPrettyString()));
Expand Down
Loading