handling.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. package model
  2. // TODO: It would make sense to have this in its own package. Unfortunately,
  3. // then there would be a circular dependency between the cargo and handling
  4. // packages since cargo.Delivery would use handling.HandlingEvent and
  5. // handling.HandlingEvent would use cargo.TrackingID. Also,
  6. // HandlingEventFactory depends on the cargo repository.
  7. //
  8. // It would make sense not having the cargo package depend on handling.
  9. import (
  10. "errors"
  11. "time"
  12. )
  13. // HandlingActivity represents how and where a cargo can be handled, and can
  14. // be used to express predictions about what is expected to happen to a cargo
  15. // in the future.
  16. type HandlingActivity struct {
  17. Type HandlingEventType
  18. Location UNLocode
  19. VoyageNumber VoyageNumber
  20. }
  21. // HandlingEvent is used to register the event when, for instance, a cargo is
  22. // unloaded from a carrier at a some location at a given time.
  23. type HandlingEvent struct {
  24. TrackingID TrackingID
  25. Activity HandlingActivity
  26. }
  27. // HandlingEventType describes type of a handling event.
  28. type HandlingEventType int
  29. // Valid handling event types.
  30. const (
  31. NotHandled HandlingEventType = iota
  32. Load
  33. Unload
  34. Receive
  35. Claim
  36. Customs
  37. )
  38. func (t HandlingEventType) String() string {
  39. switch t {
  40. case NotHandled:
  41. return "Not Handled"
  42. case Load:
  43. return "Load"
  44. case Unload:
  45. return "Unload"
  46. case Receive:
  47. return "Receive"
  48. case Claim:
  49. return "Claim"
  50. case Customs:
  51. return "Customs"
  52. }
  53. return ""
  54. }
  55. // HandlingHistory is the handling history of a cargo.
  56. type HandlingHistory struct {
  57. HandlingEvents []HandlingEvent
  58. }
  59. // MostRecentlyCompletedEvent returns most recently completed handling event.
  60. func (h HandlingHistory) MostRecentlyCompletedEvent() (HandlingEvent, error) {
  61. if len(h.HandlingEvents) == 0 {
  62. return HandlingEvent{}, errors.New("delivery history is empty")
  63. }
  64. return h.HandlingEvents[len(h.HandlingEvents)-1], nil
  65. }
  66. // HandlingEventRepository provides access a handling event store.
  67. type HandlingEventRepository interface {
  68. Store(e HandlingEvent)
  69. QueryHandlingHistory(TrackingID) HandlingHistory
  70. }
  71. // HandlingEventFactory creates handling events.
  72. type HandlingEventFactory struct {
  73. CargoRepository CargoRepository
  74. VoyageRepository VoyageRepository
  75. LocationRepository LocationRepository
  76. }
  77. // CreateHandlingEvent creates a validated handling event.
  78. func (f *HandlingEventFactory) CreateHandlingEvent(registered time.Time, completed time.Time, id TrackingID,
  79. voyageNumber VoyageNumber, unLocode UNLocode, eventType HandlingEventType) (HandlingEvent, error) {
  80. if _, err := f.CargoRepository.Find(id); err != nil {
  81. return HandlingEvent{}, err
  82. }
  83. if _, err := f.VoyageRepository.Find(voyageNumber); err != nil {
  84. // TODO: This is pretty ugly, but when creating a Receive event, the voyage number is not known.
  85. if len(voyageNumber) > 0 {
  86. return HandlingEvent{}, err
  87. }
  88. }
  89. if _, err := f.LocationRepository.Find(unLocode); err != nil {
  90. return HandlingEvent{}, err
  91. }
  92. return HandlingEvent{
  93. TrackingID: id,
  94. Activity: HandlingActivity{
  95. Type: eventType,
  96. Location: unLocode,
  97. VoyageNumber: voyageNumber,
  98. },
  99. }, nil
  100. }