func (s proxyService) FetchRoutesForSpecification(rs cargo.RouteSpecification) []cargo.Itinerary { response, err := s.FetchRoutesEndpoint(s.Context, fetchRoutesRequest{ From: string(rs.Origin), To: string(rs.Destination), }) if err != nil { return []cargo.Itinerary{} } resp := response.(fetchRoutesResponse) var itineraries []cargo.Itinerary for _, r := range resp.Paths { var legs []cargo.Leg for _, e := range r.Edges { legs = append(legs, cargo.Leg{ VoyageNumber: voyage.Number(e.Voyage), LoadLocation: location.UNLocode(e.Origin), UnloadLocation: location.UNLocode(e.Destination), LoadTime: e.Departure, UnloadTime: e.Arrival, }) } itineraries = append(itineraries, cargo.Itinerary{Legs: legs}) } return itineraries }
func (s *S) TestCargoFromHongkongToStockholm(chk *C) { dbname := "dddsample_test" var err error session, err := mgo.Dial("127.0.0.1") if err != nil { panic(err) } defer session.Close() session.SetMode(mgo.Monotonic, true) session.DB(dbname).DropDatabase() var ( cargoRepository, _ = repository.NewMongoCargo(dbname, session) locationRepository, _ = repository.NewMongoLocation(dbname, session) voyageRepository, _ = repository.NewMongoVoyage(dbname, session) handlingEventRepository = repository.NewMongoHandlingEvent(dbname, session) ) handlingEventFactory := cargo.HandlingEventFactory{ CargoRepository: cargoRepository, VoyageRepository: voyageRepository, LocationRepository: locationRepository, } routingService := &stubRoutingService{} cargoEventHandler := &stubCargoEventHandler{} cargoInspectionService := inspection.NewService(cargoRepository, handlingEventRepository, cargoEventHandler) handlingEventHandler := &stubHandlingEventHandler{cargoInspectionService} var ( bookingService = booking.NewService(cargoRepository, locationRepository, handlingEventRepository, routingService) handlingEventService = handling.NewService(handlingEventRepository, handlingEventFactory, handlingEventHandler) ) var ( origin = location.CNHKG // Hongkong destination = location.SESTO // Stockholm arrivalDeadline = time.Date(2009, time.March, 18, 12, 00, 00, 00, time.UTC) ) // // Use case 1: booking // trackingID, err := bookingService.BookNewCargo(origin, destination, arrivalDeadline) chk.Assert(err, IsNil) c, err := cargoRepository.Find(trackingID) chk.Assert(err, IsNil) chk.Check(c.Delivery.TransportStatus, Equals, cargo.NotReceived) chk.Check(c.Delivery.RoutingStatus, Equals, cargo.NotRouted) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.Itinerary.IsEmpty(), Equals, true) chk.Check(c.Delivery.ETA, Equals, time.Time{}) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{}) // // Use case 2: routing // itineraries := bookingService.RequestPossibleRoutesForCargo(trackingID) itinerary := selectPreferredItinerary(itineraries) c.AssignToRoute(itinerary) cargoRepository.Store(c) chk.Check(c.Delivery.TransportStatus, Equals, cargo.NotReceived) chk.Check(c.Delivery.RoutingStatus, Equals, cargo.Routed) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.Itinerary.IsEmpty(), Equals, false) chk.Check(c.Delivery.ETA, Not(Equals), time.Time{}) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Receive, Location: location.CNHKG}) // // Use case 3: handling // err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 1), trackingID, "", location.CNHKG, cargo.Receive) chk.Check(err, IsNil) // Ensure we're not working with stale cargo. c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.TransportStatus, Equals, cargo.InPort) chk.Check(c.Delivery.LastKnownLocation, Equals, location.CNHKG) chk.Check(c.Delivery.Itinerary.IsEmpty(), Equals, false) err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 3), trackingID, voyage.V100.Number, location.CNHKG, cargo.Load) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.TransportStatus, Equals, cargo.OnboardCarrier) chk.Check(c.Delivery.LastKnownLocation, Equals, location.CNHKG) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.Itinerary.IsEmpty(), Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.V100.Number) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Unload, Location: location.USNYC, VoyageNumber: voyage.V100.Number}) // // Here's an attempt to register a handling event that's not valid // because there is no voyage with the specified voyage number, // and there's no location with the specified UN Locode either. // noSuchVoyageNumber := voyage.Number("XX000") noSuchUNLocode := location.UNLocode("ZZZZZ") err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 5), trackingID, noSuchVoyageNumber, noSuchUNLocode, cargo.Load) chk.Check(err, NotNil) // // Cargo is incorrectly unloaded in Tokyo // err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 5), trackingID, voyage.V100.Number, location.JNTKO, cargo.Unload) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.JNTKO) chk.Check(c.Delivery.TransportStatus, Equals, cargo.InPort) chk.Check(c.Delivery.Itinerary.IsEmpty(), Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.Number("")) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{}) // Cargo is now misdirected chk.Check(c.Delivery.IsMisdirected, Equals, true) // // Cargo needs to be rerouted // rs := cargo.RouteSpecification{ Origin: location.JNTKO, Destination: location.SESTO, ArrivalDeadline: arrivalDeadline, } // Specify a new route, this time from Tokyo (where it was incorrectly unloaded) to Stockholm c.SpecifyNewRoute(rs) cargoRepository.Store(c) chk.Check(c.Delivery.RoutingStatus, Equals, cargo.Misrouted) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{}) // Repeat procedure of selecting one out of a number of possible routes satisfying the route spec newItineraries := bookingService.RequestPossibleRoutesForCargo(trackingID) newItinerary := selectPreferredItinerary(newItineraries) c.AssignToRoute(newItinerary) cargoRepository.Store(c) chk.Check(c.Delivery.RoutingStatus, Equals, cargo.Routed) // // Cargo has been rerouted, shipping continues // // Load in Tokyo err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 8), trackingID, voyage.V300.Number, location.JNTKO, cargo.Load) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.JNTKO) chk.Check(c.Delivery.TransportStatus, Equals, cargo.OnboardCarrier) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.V300.Number) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Unload, Location: location.DEHAM, VoyageNumber: voyage.V300.Number}) // Unload in Hamburg err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 12), trackingID, voyage.V300.Number, location.DEHAM, cargo.Unload) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.DEHAM) chk.Check(c.Delivery.TransportStatus, Equals, cargo.InPort) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.Number("")) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Load, Location: location.DEHAM, VoyageNumber: voyage.V400.Number}) // Load in Hamburg err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 14), trackingID, voyage.V400.Number, location.DEHAM, cargo.Load) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.DEHAM) chk.Check(c.Delivery.TransportStatus, Equals, cargo.OnboardCarrier) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.V400.Number) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Unload, Location: location.SESTO, VoyageNumber: voyage.V400.Number}) // Unload in Stockholm err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 15), trackingID, voyage.V400.Number, location.SESTO, cargo.Unload) chk.Check(err, IsNil) c, err = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.SESTO) chk.Check(c.Delivery.TransportStatus, Equals, cargo.InPort) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.Number("")) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{Type: cargo.Claim, Location: location.SESTO}) // Finally, cargo is claimed in Stockholm. This ends the cargo lifecycle from our perspective. err = handlingEventService.RegisterHandlingEvent(toDate(2009, time.March, 16), trackingID, voyage.V400.Number, location.SESTO, cargo.Claim) chk.Check(err, IsNil) c, _ = cargoRepository.Find(trackingID) chk.Check(c.Delivery.LastKnownLocation, Equals, location.SESTO) chk.Check(c.Delivery.TransportStatus, Equals, cargo.Claimed) chk.Check(c.Delivery.IsMisdirected, Equals, false) chk.Check(c.Delivery.CurrentVoyage, Equals, voyage.Number("")) chk.Check(c.Delivery.NextExpectedActivity, Equals, cargo.HandlingActivity{}) }