blob: 30c91f940fef195a3793974a935d6e85beb68102 [file] [log] [blame]
/*
* Copyright 2011 Marc Grue.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zest.sample.dcicargo.sample_a.context.shipping.booking;
import java.util.Date;
import org.junit.Before;
import org.junit.Test;
import org.apache.zest.api.unitofwork.UnitOfWork;
import org.apache.zest.sample.dcicargo.sample_a.bootstrap.test.TestApplication;
import org.apache.zest.sample.dcicargo.sample_a.data.entity.CargosEntity;
import org.apache.zest.sample.dcicargo.sample_a.data.entity.HandlingEventsEntity;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.Cargo;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.Cargos;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.RouteSpecification;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.cargo.TrackingId;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.Delivery;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.RoutingStatus;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.delivery.TransportStatus;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEvent;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.itinerary.Itinerary;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.location.Location;
import org.apache.zest.sample.dcicargo.sample_a.data.shipping.voyage.Voyage;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.apache.zest.sample.dcicargo.sample_a.data.shipping.handling.HandlingEventType.*;
/**
* Tests of the Build Delivery Snapshot subfunction use case.
*
* All deviations of the use case are tested one by one. The business rules are therefore enforcing the
* structure for the test suite and not arbitrary ideas of the programmer what to test. If the business
* analyst haven't foreseen a deviation in the use case, it's his responsibility that it's not tested.
*
* Test method names describe the test purpose. The prefix refers to the step in the use case.
*
* FIXME: Test methods call each other to allow ordered execution, ie. tests are not indepedants !
*/
public class BuildDeliverySnapshotTest
extends TestApplication
{
final Date TODAY = new Date();
private Location HONGKONG;
private Location STOCKHOLM;
private Location NEWYORK;
private Location DALLAS;
private Location HANGZHOU;
private Location HELSINKI;
private Location TOKYO;
private Location HAMBURG;
private Voyage V100S;
private Voyage V200T;
private Voyage V300A;
private Voyage V400S;
private Voyage V500S;
private Location SHANGHAI;
private TrackingId trackingId;
private Cargo cargo;
private Itinerary itinerary;
@Before
public void prepareTest()
throws Exception
{
super.prepareTest();
UnitOfWork uow = module.currentUnitOfWork();
HONGKONG = uow.get( Location.class, CNHKG.code().get() );
STOCKHOLM = uow.get( Location.class, SESTO.code().get() );
SHANGHAI = uow.get( Location.class, CNSHA.code().get() );
TOKYO = uow.get( Location.class, JNTKO.code().get() );
NEWYORK = uow.get( Location.class, USNYC.code().get() );
DALLAS = uow.get( Location.class, USDAL.code().get() );
HANGZHOU = uow.get( Location.class, CNHGH.code().get() );
HELSINKI = uow.get( Location.class, FIHEL.code().get() );
HAMBURG = uow.get( Location.class, DEHAM.code().get() );
V100S = uow.get( Voyage.class, "V100S" );
V200T = uow.get( Voyage.class, "V200T" );
V300A = uow.get( Voyage.class, "V300A" );
V400S = uow.get( Voyage.class, "V400S" );
V500S = uow.get( Voyage.class, "V500S" );
Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
trackingId = new BookNewCargo( CARGOS, HONGKONG, STOCKHOLM, day( 17 ) ).createCargo( "ABC" );
cargo = uow.get( Cargo.class, trackingId.id().get() );
itinerary = itinerary(
leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
);
}
// DERIVE WITH ROUTE SPECIFICATION ==============================================================================
@Test( expected = RouteException.class )
public void deviation_2a_InvalidRouteSpecification_sameLocations() throws Exception
{
RouteSpecification routeSpec = routeSpecification( HONGKONG, HONGKONG, day( 20 ) );
new BuildDeliverySnapshot( routeSpec ).get();
}
@Test( expected = RouteException.class )
public void deviation_2b_InvalidRouteSpecification_tooEarlyDeadline() throws Exception
{
RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, TODAY );
new BuildDeliverySnapshot( routeSpec ).get();
}
@Test
public void deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification() throws Exception
{
RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
}
// DERIVE WITH NON-ROUTED CARGO ==============================================================================
@Test
public void deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo() throws Exception
{
deviation_2c_ItineraryIsUnknown_buildFromRouteSpecification();
UnitOfWork uow = module.currentUnitOfWork();
RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 20 ) );
Cargos CARGOS = uow.get( Cargos.class, CargosEntity.CARGOS_ID );
Delivery delivery = new BuildDeliverySnapshot( routeSpec ).get();
Cargo cargo = CARGOS.createCargo( routeSpec, delivery, "ABCD" );
// Same as previous test (just build from cargo instead)
assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.NOT_ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
}
// DERIVE WITH ROUTE SPECIFICATION + ITINERARY (Routed cargo) ==============================================
@Test
public void deviation_2d_UnsatisfyingItinerary_wrongOrigin() throws Exception
{
deviation_2c_ItineraryIsUnknown_buildFromNonRoutedCargo();
Itinerary itinerary = itinerary(
leg( V100S, HONGKONG, NEWYORK, day( 1 ), day( 8 ) ),
leg( V200T, NEWYORK, DALLAS, day( 9 ), day( 12 ) ),
leg( V300A, DALLAS, STOCKHOLM, day( 13 ), day( 16 ) )
);
// Hangzhou not in itinerary first leg
RouteSpecification routeSpec = routeSpecification( HANGZHOU, STOCKHOLM, day( 20 ) );
cargo.itinerary().set( itinerary );
cargo.routeSpecification().set( routeSpec );
Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
// Route specification not satisfied by itinerary
assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
}
@Test
public void deviation_2d_UnsatisfyingItinerary_wrongDestination() throws Exception
{
deviation_2d_UnsatisfyingItinerary_wrongOrigin();
// Helsinki not in itinerary last leg
RouteSpecification routeSpec = routeSpecification( HONGKONG, HELSINKI, day( 20 ) );
cargo.routeSpecification().set( routeSpec );
Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
// Route specification not satisfied by itinerary
assertThat( itinerary.lastLeg().unloadLocation().get(), is( not( equalTo( routeSpec.destination().get() ) ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
}
@Test
public void deviation_2d_UnsatisfyingItinerary_missedDeadline() throws Exception
{
deviation_2d_UnsatisfyingItinerary_wrongDestination();
// Arrival on day 12 according to itinerary is not meeting deadline
RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, day( 14 ) );
cargo.routeSpecification().set( routeSpec );
Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
// Route specification not satisfied by itinerary
assertFalse( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
}
@Test
public void deviation_3a_CargoHasNoHandlingHistory() throws Exception
{
deviation_2d_UnsatisfyingItinerary_missedDeadline();
Date arrival = day( 16 );
Date deadline = day( 20 );
// Itinerary will satisfy route specification
RouteSpecification routeSpec = routeSpecification( HONGKONG, STOCKHOLM, deadline );
cargo.routeSpecification().set( routeSpec );
Delivery delivery = new BuildDeliverySnapshot( cargo ).get();
// Route specification satisfied by itinerary
assertThat( itinerary.firstLeg().loadLocation().get(), is( equalTo( routeSpec.origin().get() ) ) );
assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.timestamp().get().after( TODAY ), is( equalTo( true ) ) ); // TODAY is set first
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.NOT_RECEIVED ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( HandlingEventType.RECEIVE ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( null ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
}
// DERIVE WITH ROUTE SPECIFICATION + ITINERARY + LAST HANDLING EVENT ============================================
@Test
public void deviation_4a_RECEIVE_1a_UnexpectedPort() throws Exception
{
deviation_3a_CargoHasNoHandlingHistory();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Unexpected receipt in Shanghai
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, SHANGHAI, null );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
// We don't know what's next for a misdirected cargo
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( SHANGHAI ) ) );
// Cargo is still routed - but it should be re-routed according to new (unexpected) location.
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
}
@Test
public void deviation_4a_RECEIVE_1b_ExpectedPort() throws Exception
{
deviation_4a_RECEIVE_1a_UnexpectedPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Expected receipt in Hong Kong
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, HandlingEventType.RECEIVE, HONGKONG, null );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
// We expect the cargo to be loaded on voyage V100S in Hong Kong
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
}
@Test
public void deviation_4b_LOAD_2a_UnexpectedPort() throws Exception
{
deviation_4a_RECEIVE_1b_ExpectedPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Unexpected load in Tokyo
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, TOKYO, V100S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
}
@Test
public void deviation_4b_LOAD_2b_ExpectedPort() throws Exception
{
deviation_4b_LOAD_2a_UnexpectedPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Expected load in Hong Kong
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V100S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( V100S ) ) );
// We expect the cargo to be unloaded from voyage V100S in New York
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( NEWYORK ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
}
@Test
public void deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary() throws Exception
{
deviation_4b_LOAD_2b_ExpectedPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Load onto unexpected voyage
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 1 ), trackingId, LOAD, HONGKONG, V400S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( HONGKONG ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( V400S ) ) );
}
@Test
public void deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary() throws Exception
{
deviation_4b_LOAD_2c_UnexpectedVoyageNotFromItinerary();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// The system doesn't currently check if handling events happen in the right order, so
// a cargo can now suddenly load in New York, even though it hasn't got there yet.
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, LOAD, NEWYORK, V200T );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
// Should have been true, but we accept it for now...
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.ONBOARD_CARRIER ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( NEWYORK ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( V200T ) ) );
// We expect the cargo to be unloaded from voyage V200T in Dallas
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( DALLAS ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V200T ) ) );
}
@Test
public void deviation_4c_UNLOAD_1a_UnexpectedPort() throws Exception
{
deviation_4b_LOAD_2c_ExpectedButLaterVoyageInItinerary();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Unexpected unload in Tokyo
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 5 ), day( 5 ), trackingId, UNLOAD, TOKYO, V100S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
cargo.delivery().set( delivery );
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
// Cargo needs to be rerouted
// Customer specifies a new route
RouteSpecification routeSpec = routeSpecification( TOKYO, STOCKHOLM, day( 20 ) );
cargo.routeSpecification().set( routeSpec );
delivery = new BuildDeliverySnapshot( cargo ).get();
cargo.delivery().set( delivery );
// Old itinerary will not satisfy new route specification
assertThat( itinerary.firstLeg().loadLocation().get(), is( not( equalTo( routeSpec.origin().get() ) ) ) );
assertThat( itinerary.lastLeg().unloadLocation().get(), is( equalTo( routeSpec.destination().get() ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.MISROUTED ) ) );
// Old planned arrival time is still satisfying new deadline
assertTrue( routeSpec.arrivalDeadline().get().after( itinerary.finalArrivalDate() ) );
// We don't know what's next before a new itinerary has been chosen
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
// Cargo is still misdirected (in unexpected location) according to old itinerary
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
// Last known data
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
// New itinerary that satisfy the new route specification. New origin departure from Tokyo.
Date arrival= day( 19 );
itinerary = itinerary(
leg( V400S, TOKYO, HAMBURG, day( 9 ), day( 16 ) ),
leg( V500S, HAMBURG, STOCKHOLM, day( 17 ), arrival )
);
// Customer reroutes cargo. This is a possible step in the cargo booking process.
new BookNewCargo( cargo, itinerary ).assignCargoToRoute();
delivery = cargo.delivery().get();
// Cargo is on track again
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastHandlingEvent().get().handlingEventType().get(), is( equalTo( UNLOAD ) ) );
assertThat( delivery.lastHandlingEvent().get().voyage().get(), is( equalTo( V100S ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( TOKYO ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( arrival ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
// When a cargo is rerouted the (often misdirected) last handling event is flagged as disregarded
// since it doesn't have to be part of the new itinerary (this isn't in the Citerus version).
// We now expect the cargo to be loaded onto voyage V400S in Tokyo heading to Hamburg
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( TOKYO ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V400S ) ) );
// Cargo is not misdirected anymore according to new itinerary. Cargo location is now expected to be in Tokyo.
}
@Test
public void deviation_4c_UNLOAD_1b_ExpectedMidpointLocation() throws Exception
{
deviation_4c_UNLOAD_1a_UnexpectedPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Unload at midpoint location of itinerary
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 8 ), day( 8 ), trackingId, UNLOAD, HAMBURG, V400S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( HAMBURG ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
// We expect the cargo to be loaded onto voyage V200T in New York heading for Dallas
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( LOAD ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( HAMBURG ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( V500S ) ) );
}
@Test
public void deviation_4c_UNLOAD_1c_Destination() throws Exception
{
deviation_4c_UNLOAD_1b_ExpectedMidpointLocation();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Unload at destination
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, UNLOAD, STOCKHOLM, V500S );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
// Cargo has arrived at destination location
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
// We expect the cargo to be claimed by customer
assertThat( delivery.nextExpectedHandlingEvent().get().handlingEventType().get(), is( equalTo( CLAIM ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().location().get(), is( equalTo( STOCKHOLM ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get().voyage().get(), is( equalTo( null ) ) );
}
@Test
public void deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort() throws Exception
{
deviation_4c_UNLOAD_1c_Destination();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Cargo was handled by the customs authorities
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CUSTOMS, STOCKHOLM, null );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.IN_PORT ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
// Cargo might be at destination, but the last handling event wasn't unloading
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
// Shouldn't we expect the cargo to be claimed by the customer now ?
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
}
@Test
public void deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort() throws Exception
{
deviation_4d_CUSTOMS_1a_CargoIsInDestinationPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Cargo was claimed but not at destination location
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 1 ), day( 16 ), trackingId, CLAIM, HELSINKI, null );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( true ) ) );
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
assertThat( delivery.eta().get(), is( equalTo( null ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( HELSINKI ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
// Cargo is claimed but has not arrived yet in destination port
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( false ) ) );
}
@Test
public void deviation_4e_CLAIM_1b_CargoIsInDestinationPort() throws Exception
{
deviation_4e_CLAIM_1a_CargoIsNotInDestinationPort();
UnitOfWork uow = module.currentUnitOfWork();
HandlingEventsEntity HANDLING_EVENTS = uow.get( HandlingEventsEntity.class, HandlingEventsEntity.HANDLING_EVENTS_ID );
// Cargo was claimed by customer at destination location
HandlingEvent handlingEvent = HANDLING_EVENTS.createHandlingEvent( day( 16 ), day( 16 ), trackingId, CLAIM, STOCKHOLM, null );
Delivery delivery = new BuildDeliverySnapshot( cargo, handlingEvent ).get();
assertThat( delivery.isMisdirected().get(), is( equalTo( false ) ) );
assertThat( delivery.routingStatus().get(), is( equalTo( RoutingStatus.ROUTED ) ) );
assertThat( delivery.transportStatus().get(), is( equalTo( TransportStatus.CLAIMED ) ) );
assertThat( delivery.lastHandlingEvent().get(), is( equalTo( handlingEvent ) ) );
assertThat( delivery.lastKnownLocation().get(), is( equalTo( STOCKHOLM ) ) );
assertThat( delivery.currentVoyage().get(), is( equalTo( null ) ) );
// Cargo is claimed in destination port
assertThat( delivery.isUnloadedAtDestination().get(), is( equalTo( true ) ) );
// No more expected handling events
assertThat( delivery.nextExpectedHandlingEvent().get(), is( equalTo( null ) ) );
}
}