123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- package booking
- import (
- "errors"
- "time"
- shipping "github.com/longjoy/micro-go-course/section19/cargo/model"
- )
- var ErrInvalidArgument = errors.New("invalid argument")
- type Service interface {
-
-
- BookNewCargo(origin shipping.UNLocode, destination shipping.UNLocode, deadline time.Time) (shipping.TrackingID, error)
-
- LoadCargo(id shipping.TrackingID) (Cargo, error)
-
-
- RequestPossibleRoutesForCargo(id shipping.TrackingID) []shipping.Itinerary
-
-
- AssignCargoToRoute(id shipping.TrackingID, itinerary shipping.Itinerary) (bool, error)
-
- ChangeDestination(id shipping.TrackingID, destination shipping.UNLocode) (bool, error)
-
- Cargos() []Cargo
-
- Locations() []Location
- }
- type service struct {
- cargos shipping.CargoRepository
- locations shipping.LocationRepository
- handlingEvents shipping.HandlingEventRepository
- routingService shipping.RoutingService
- }
- func (s *service) AssignCargoToRoute(id shipping.TrackingID, itinerary shipping.Itinerary) (bool, error) {
- if id == "" || len(itinerary.Legs) == 0 {
- return false, ErrInvalidArgument
- }
- c, err := s.cargos.Find(id)
- if err != nil {
- return false, err
- }
- c.AssignToRoute(itinerary)
- return s.cargos.Store(c)
- }
- func (s *service) BookNewCargo(origin, destination shipping.UNLocode, deadline time.Time) (shipping.TrackingID, error) {
- if origin == "" || destination == "" || deadline.IsZero() {
- return "", ErrInvalidArgument
- }
- id := shipping.NextTrackingID()
- rs := shipping.RouteSpecification{
- Origin: origin,
- Destination: destination,
- ArrivalDeadline: deadline,
- }
- c := shipping.NewCargo(id, rs)
- if _, err := s.cargos.Store(c); err != nil {
- return "", err
- }
- return c.TrackingID, nil
- }
- func (s *service) LoadCargo(id shipping.TrackingID) (Cargo, error) {
- if id == "" {
- return Cargo{}, ErrInvalidArgument
- }
- c, err := s.cargos.Find(id)
- if err != nil {
- return Cargo{}, err
- }
- return assemble(c, s.handlingEvents), nil
- }
- func (s *service) ChangeDestination(id shipping.TrackingID, destination shipping.UNLocode) (bool, error) {
- if id == "" || destination == "" {
- return false, ErrInvalidArgument
- }
- c, err := s.cargos.Find(id)
- if err != nil {
- return false, err
- }
- l, err := s.locations.Find(destination)
- if err != nil {
- return false, err
- }
- c.SpecifyNewRoute(shipping.RouteSpecification{
- Origin: c.Origin,
- Destination: l.UNLocode,
- ArrivalDeadline: c.RouteSpecification.ArrivalDeadline,
- })
- if _, err := s.cargos.Store(c); err != nil {
- return false, err
- }
- return true, nil
- }
- func (s *service) RequestPossibleRoutesForCargo(id shipping.TrackingID) []shipping.Itinerary {
- if id == "" {
- return nil
- }
- c, err := s.cargos.Find(id)
- if err != nil {
- return []shipping.Itinerary{}
- }
- return s.routingService.FetchRoutesForSpecification(c.RouteSpecification)
- }
- func (s *service) Cargos() []Cargo {
- var result []Cargo
- for _, c := range s.cargos.FindAll() {
- result = append(result, assemble(c, s.handlingEvents))
- }
- return result
- }
- func (s *service) Locations() []Location {
- var result []Location
- for _, v := range s.locations.FindAll() {
- result = append(result, Location{
- UNLocode: string(v.UNLocode),
- Name: v.Name,
- })
- }
- return result
- }
- func NewService(cargos shipping.CargoRepository, locations shipping.LocationRepository, events shipping.HandlingEventRepository) Service {
- return &service{
- cargos: cargos,
- locations: locations,
- handlingEvents: events,
- }
- }
- type Location struct {
- UNLocode string `json:"locode"`
- Name string `json:"name"`
- }
- type Cargo struct {
- ArrivalDeadline time.Time `json:"arrival_deadline"`
- Destination string `json:"destination"`
- Legs []shipping.Leg `json:"legs,omitempty"`
- Misrouted bool `json:"misrouted"`
- Origin string `json:"origin"`
- Routed bool `json:"routed"`
- TrackingID string `json:"tracking_id"`
- }
- func assemble(c *shipping.Cargo, events shipping.HandlingEventRepository) Cargo {
- return Cargo{
- TrackingID: string(c.TrackingID),
- Origin: string(c.Origin),
- Destination: string(c.RouteSpecification.Destination),
- Misrouted: c.Delivery.RoutingStatus == shipping.Misrouted,
- Routed: !c.Itinerary.IsEmpty(),
- ArrivalDeadline: c.RouteSpecification.ArrivalDeadline,
- Legs: c.Itinerary.Legs,
- }
- }
|