Class: ShipmentEventStatusSummary
- Inherits:
-
Object
- Object
- ShipmentEventStatusSummary
- Defined in:
- app/services/shipment_event_status_summary.rb
Overview
Compresses a Shipment's shipment_events rows into a single status badge
rendered next to the tracking number on the delivery's Shipments table
and (optionally) inline elsewhere. Mirrors FreightEventStatusSummary
in shape and conventions, with ShipEngine's per-scan status codes
(AC / IT / DE / EX / AT / SP / UN / NY) substituted for CHR's typed
event strings.
A parcel shipment has at most one badge at a time — unlike a freight
delivery where load / pickup / delivery are independent buckets, parcel
scans are linear and the most-advanced one wins. Order:
delivered (DE/SP) → green shipping-fast
delivery_attempt (AT) → orange shipping-fast
exception (EX) → red triangle-exclamation
in_transit (IT) → blue truck-fast
accepted (AC) → grey box
nothing → no badge
Defined Under Namespace
Classes: Badge
Class Method Summary collapse
-
.for(shipment) ⇒ Badge?
(also: for_shipment)
One badge, or nil when no relevant event yet.
-
.for_tracking_number(tracking_number) ⇒ Badge?
Compute the badge directly from a tracking number — used for ShipEngine LTL freight, which has one PRO per delivery (no per-pallet Shipment row to hang the events off) but writes to the same
ShipmentEventprojection. -
.from_events(events) ⇒ Badge?
Compute the badge from already-loaded ShipmentEvent rows — for list views (e.g. the warehouse dashboard) that preload every event for the page in one query and hand each row its slice, avoiding a per-row/per-shipment lookup.
Instance Method Summary collapse
- #call ⇒ Badge?
-
#initialize(shipment = nil, tracking_number: nil, events: nil) ⇒ ShipmentEventStatusSummary
constructor
A new instance of ShipmentEventStatusSummary.
Constructor Details
#initialize(shipment = nil, tracking_number: nil, events: nil) ⇒ ShipmentEventStatusSummary
Returns a new instance of ShipmentEventStatusSummary.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'app/services/shipment_event_status_summary.rb', line 69 def initialize(shipment = nil, tracking_number: nil, events: nil) @shipment = shipment # Scope by tracking_number, NOT by shipment_id. Offbook ST shipments # (cross-border back-order fulfillment from an alternate warehouse) # legitimately share a single tracking_number across multiple # Shipment rows — both shipments must surface the same event # history. ShipmentEvent stores tracking_number denormalised for # exactly this reason. Returns [] when tracking_number is blank. @events = if events events.sort_by { |e| e.occurred_at || Time.zone.at(0) } else tn = tracking_number.presence || shipment&.tracking_number if tn.present? ShipmentEvent.where(tracking_number: tn) .to_a.sort_by { |e| e.occurred_at || Time.zone.at(0) } else [] end end end |
Class Method Details
.for(shipment) ⇒ Badge? Also known as: for_shipment
Returns one badge, or nil when no relevant event yet.
32 33 34 |
# File 'app/services/shipment_event_status_summary.rb', line 32 def self.for(shipment) new(shipment).call end |
.for_tracking_number(tracking_number) ⇒ Badge?
Compute the badge directly from a tracking number — used for ShipEngine
LTL freight, which has one PRO per delivery (no per-pallet Shipment row to
hang the events off) but writes to the same ShipmentEvent projection.
Reuses the identical status→icon/tooltip logic so LTL and parcel badges
are indistinguishable.
50 51 52 |
# File 'app/services/shipment_event_status_summary.rb', line 50 def self.for_tracking_number(tracking_number) new(nil, tracking_number: tracking_number).call end |
.from_events(events) ⇒ Badge?
Compute the badge from already-loaded ShipmentEvent rows — for list views
(e.g. the warehouse dashboard) that preload every event for the page in one
query and hand each row its slice, avoiding a per-row/per-shipment lookup.
60 61 62 |
# File 'app/services/shipment_event_status_summary.rb', line 60 def self.from_events(events) new(events: Array(events)).call end |
Instance Method Details
#call ⇒ Badge?
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'app/services/shipment_event_status_summary.rb', line 91 def call delivered = events.reverse.find { |e| ShipmentEvent::DELIVERED_STATUS_CODES.include?(e.status_code) } return badge_for(:delivered, delivered, color: :success, icon: 'shipping-fast', tooltip_verb: 'Delivered') if delivered attempt = events.reverse.find { |e| e.status_code == 'AT' } return badge_for(:delivery_attempt, attempt, color: :warning, icon: 'shipping-fast', tooltip_verb: 'Delivery attempted') if attempt exception = events.reverse.find { |e| e.status_code == 'EX' } return badge_for(:exception, exception, color: :danger, icon: 'triangle-exclamation', tooltip_verb: 'Exception') if exception in_transit = events.reverse.find { |e| e.status_code == 'IT' } return badge_for(:in_transit, in_transit, color: :primary, icon: 'truck-fast', tooltip_verb: 'In transit') if in_transit accepted = events.reverse.find { |e| e.status_code == 'AC' } return badge_for(:accepted, accepted, color: :secondary, icon: 'box', tooltip_verb: 'Accepted by carrier') if accepted nil end |