Class: Shipping::TrackingNumberRepair
- Inherits:
-
Object
- Object
- Shipping::TrackingNumberRepair
- Defined in:
- app/services/shipping/tracking_number_repair.rb
Overview
Suggests the number a hand-keyed tracking number was meant to be.
Every mistake we see in production is one keystroke away from a valid
number: 1Z typed as 12, a stray leading digit (14Z07EH…), a
trailing +, an O for a 0. Rather than guess at intent, generate
the small set of numbers those slips could have come from and let the
carrier's own check digit arbitrate.
The safety property that makes this usable on a shipping identifier:
a repair is offered only when exactly one candidate validates. The
carriers we repair (UPS, FedEx Ground, USPS IMpb, Canada Post,
Purolator) all carry a mod-10 check digit, so a wrong candidate passes
only ~1 time in 10; requiring a unique survivor removes the case where
two plausible readings both check out. Ambiguous input yields nil and
the operator retypes it.
Nothing here rewrites data on its own — TrackingNumberFormatValidator
puts the suggestion in the error message and the operator decides.
Carriers with no check digit (Canpar, Spee-Dee) are format-only, so a
repair there is a weaker claim; the unique-survivor rule still applies
but the operator is the one confirming against the label.
Constant Summary collapse
- CONFUSIONS =
Digit/letter pairs that get confused reading a label or a screen.
{ '0' => %w[O D], 'O' => %w[0], 'D' => %w[0], '1' => %w[I L], 'I' => %w[1], 'L' => %w[1], '2' => %w[Z], 'Z' => %w[2], '5' => %w[S], 'S' => %w[5], '6' => %w[G], 'G' => %w[6], '8' => %w[B], 'B' => %w[8] }.freeze
- MAX_LENGTH =
Longest input we'll try to repair. Above this the candidate set stops
being worth generating and the input isn't a parcel number anyway. 40- MARKETPLACE_REPAIR_CARRIERS =
Last-mile carriers a marketplace label may actually be.
['UPS', 'FedEx', 'USPS', 'Amazon Shipping'].freeze
Instance Method Summary collapse
-
#initialize(carrier, value) ⇒ TrackingNumberRepair
constructor
A new instance of TrackingNumberRepair.
-
#suggestion ⇒ String?
The unique valid number this was probably meant to be, or nil when there's no candidate or more than one.
Constructor Details
#initialize(carrier, value) ⇒ TrackingNumberRepair
Returns a new instance of TrackingNumberRepair.
49 50 51 52 |
# File 'app/services/shipping/tracking_number_repair.rb', line 49 def initialize(carrier, value) @carrier = Heatwave::Normalizers.shipping_carrier(carrier.to_s) @value = Heatwave::Normalizers.tracking_number(value.to_s).to_s end |
Instance Method Details
#suggestion ⇒ String?
Returns the unique valid number this was probably meant
to be, or nil when there's no candidate or more than one.
56 57 58 59 60 61 62 |
# File 'app/services/shipping/tracking_number_repair.rb', line 56 def suggestion return nil if @value.empty? || @value.length > MAX_LENGTH return unique_survivor(MARKETPLACE_REPAIR_CARRIERS.flat_map { |carrier| survivors_for(carrier) }) if TrackingNumberFormatValidator.marketplace_carrier?(@carrier) unique_survivor(survivors_for(@carrier)) end |