rate-card 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/rate-card +9 -3
- data/lib/rate_card/constants/addresses.rb +34 -0
- data/lib/rate_card/constants/carriers.rb +9 -0
- data/lib/rate_card/run_spec.rb +38 -3
- data/lib/rate_card/table_renderer.rb +1 -1
- data/lib/rate_card/tui/app.rb +129 -27
- data/lib/rate_card/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccc684b0241775fa979051ffd3b9aeed1b08e9eaf8a5bb40bc8560d8f0e2ab39
|
|
4
|
+
data.tar.gz: e3fe60187c6db2cf746a7adabe90a139da79cd655a2b0445e92060db23db2d35
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67bb66aab90c7942ec5cf6d29ce62b23240dd347fdd27c8665d4c1d191c398f97d75ec2b2ddaad989ee21c0645ab5120c00dfa9c2a953d7f176298850aa635bc
|
|
7
|
+
data.tar.gz: 6997aabfddff427e90ecfb38153c3262513d31160af889109da5fe729cfd00b239d63c62137a9f733b47c8d5199bee4e7593b91dc29fefe36291d8b608a584ba
|
data/exe/rate-card
CHANGED
|
@@ -102,7 +102,13 @@ else
|
|
|
102
102
|
exit 1
|
|
103
103
|
end
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
# Usually one pass. UPS rural mode with more than one surcharge type checked
|
|
106
|
+
# produces several - each is its own card with its own files, run and
|
|
107
|
+
# reported independently so one failing does not stop the others from
|
|
108
|
+
# writing. The process exit code is the worst of all of them.
|
|
109
|
+
exit_codes = app.results.map do |result|
|
|
110
|
+
result[:spec].show_table = options[:show_table]
|
|
111
|
+
RateCard::Runner.new(spec: result[:spec], grid: result[:grid], ui: ui).run
|
|
112
|
+
end
|
|
107
113
|
|
|
108
|
-
exit
|
|
114
|
+
exit exit_codes.max
|
|
@@ -72,6 +72,40 @@ module RateCard
|
|
|
72
72
|
|
|
73
73
|
BY_CARRIER = { 'USPS' => USPS, 'UPS' => UPS, 'FedEx' => FEDEX, 'DHL' => DHL_ECOMMERCE, 'OSM' => OSM }.freeze
|
|
74
74
|
|
|
75
|
+
# Rural/remote-area surcharge test addresses. These aren't zone charts
|
|
76
|
+
# (rural surcharge eligibility is a property of the destination zip on
|
|
77
|
+
# a carrier's rural list, not something for_carrier's zone lookup
|
|
78
|
+
# models), so they live outside BY_CARRIER and are looked up directly
|
|
79
|
+
# by callers that need them.
|
|
80
|
+
#
|
|
81
|
+
# Ported from ../rate_table_builder/constants.rb. USPS_RURAL_DAS zones
|
|
82
|
+
# 4-8 were tagged 'maybe' or unverified in the source file - re-verify
|
|
83
|
+
# against USPS's rural lookup before relying on them for a real card.
|
|
84
|
+
USPS_RURAL_DAS = {
|
|
85
|
+
0 => { address1: '12078 W 4000 N', city: 'Bluebell', state: 'UT', postal_code: '84007', country: 'US' },
|
|
86
|
+
1 => { address1: '6074 N 4700 W', city: 'Bear River City', state: 'UT', postal_code: '84301', country: 'US' },
|
|
87
|
+
2 => { address1: '25670 Buffalo Run', city: 'Moran', state: 'WY', postal_code: '83013', country: 'US' },
|
|
88
|
+
3 => { address1: '17 Texs Loop', city: 'Alder', state: 'MT', postal_code: '59710', country: 'US' },
|
|
89
|
+
4 => { address1: '1250 153rd St SE', city: 'Norwich', state: 'ND', postal_code: '58768', country: 'US' },
|
|
90
|
+
5 => { address1: '103 Stonegate Ct', city: 'Gurdon', state: 'AR', postal_code: '71743', country: 'US' },
|
|
91
|
+
6 => { address1: '31 Edsel Rd', city: 'Webbville', state: 'KY', postal_code: '41180', country: 'US' },
|
|
92
|
+
7 => { address1: '295 Old Waterford Road', city: 'Littleton', state: 'NH', postal_code: '03561', country: 'US' },
|
|
93
|
+
8 => { address1: '77 Main Street', city: 'Mars Hill', state: 'ME', postal_code: '04758', country: 'US' }
|
|
94
|
+
}.freeze
|
|
95
|
+
|
|
96
|
+
# UPS has no per-zone rural chart - just one known address per DAS
|
|
97
|
+
# variant. EDAS = Extended Delivery Area Surcharge, RDAS = Remote
|
|
98
|
+
# Delivery Area Surcharge.
|
|
99
|
+
UPS_EDAS_EXCEPTION = { address1: '149 Pheasant Runn Road', city: 'Goshen', state: 'NH', postal_code: '03752',
|
|
100
|
+
country: 'US' }.freeze
|
|
101
|
+
|
|
102
|
+
UPS_RDAS_EXCEPTION = { address1: '106 Yellow Hammer Rd', city: 'Tyner', state: 'NC', postal_code: '27980',
|
|
103
|
+
country: 'US' }.freeze
|
|
104
|
+
|
|
105
|
+
# Looked up by surcharge-type symbol rather than zone, since UPS rural
|
|
106
|
+
# mode sweeps surcharge types instead of zones — see RunSpec#address_for.
|
|
107
|
+
UPS_RURAL = { edas: UPS_EDAS_EXCEPTION, rdas: UPS_RDAS_EXCEPTION }.freeze
|
|
108
|
+
|
|
75
109
|
module_function
|
|
76
110
|
|
|
77
111
|
# Raises rather than falling back. The old USPS default meant asking for
|
|
@@ -30,6 +30,11 @@ module RateCard
|
|
|
30
30
|
'dhl' => 'DHL Express', 'dhl_ecommerce' => 'DHL', 'osm' => 'OSM', 'amazon' => 'Amazon'
|
|
31
31
|
}.freeze
|
|
32
32
|
|
|
33
|
+
# Carriers with a rural/DAS surcharge test address in Constants::Addresses.
|
|
34
|
+
# Independent of zone-chart support - a carrier can have a verified zone
|
|
35
|
+
# chart and no rural chart at all.
|
|
36
|
+
RURAL_AWARE = %w[USPS UPS].freeze
|
|
37
|
+
|
|
33
38
|
module_function
|
|
34
39
|
|
|
35
40
|
# OTHER is only for a malformed entry with no code at all, so a service is
|
|
@@ -44,6 +49,10 @@ module RateCard
|
|
|
44
49
|
def display_order
|
|
45
50
|
DISPLAY_ORDER
|
|
46
51
|
end
|
|
52
|
+
|
|
53
|
+
def rural_aware?(carrier)
|
|
54
|
+
RURAL_AWARE.include?(carrier.to_s)
|
|
55
|
+
end
|
|
47
56
|
end
|
|
48
57
|
end
|
|
49
58
|
end
|
data/lib/rate_card/run_spec.rb
CHANGED
|
@@ -16,7 +16,7 @@ module RateCard
|
|
|
16
16
|
class RunSpec < Struct.new(
|
|
17
17
|
:token, :customer_name, :customer_id, :carrier, :services, :zones,
|
|
18
18
|
:weight_unit, :weights, :package_type, :rate_keys, :output_base,
|
|
19
|
-
:show_table, :started_at, :rate_mode, :cubic_tiers,
|
|
19
|
+
:show_table, :started_at, :rate_mode, :cubic_tiers, :rural,
|
|
20
20
|
keyword_init: true
|
|
21
21
|
)
|
|
22
22
|
# Our rate-key name => the field it arrives as in service_rates. Getting
|
|
@@ -44,10 +44,26 @@ module RateCard
|
|
|
44
44
|
self.class.compact_range(zones)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
def zone_label(zone)
|
|
48
|
+
zone.is_a?(Symbol) ? zone.to_s.upcase : "Z#{zone}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# true for USPS with rural mode on, or any UPS surcharge type/combination.
|
|
52
|
+
# nil/false (rural mode off, or a non-rural-aware carrier) is falsy here.
|
|
53
|
+
def rural?
|
|
54
|
+
!!rural
|
|
55
|
+
end
|
|
56
|
+
|
|
47
57
|
# [1,2,3,5] => "1-3,5". Runs of three or more collapse; a pair stays listed,
|
|
48
58
|
# since "4,5" is no longer than "4-5" and reads as what the user typed.
|
|
59
|
+
#
|
|
60
|
+
# UPS rural mode sweeps surcharge-type symbols (:edas, :rdas) instead of
|
|
61
|
+
# numbered zones - those aren't a range at all, so they're just listed.
|
|
49
62
|
def self.compact_range(numbers)
|
|
50
|
-
|
|
63
|
+
array = numbers.to_a
|
|
64
|
+
return array.join(',') if array.any? { |n| n.is_a?(Symbol) }
|
|
65
|
+
|
|
66
|
+
sorted = array.sort.uniq
|
|
51
67
|
runs = sorted.slice_when { |a, b| b != a + 1 }.to_a
|
|
52
68
|
runs.map { |run| run.length >= 3 ? "#{run.first}-#{run.last}" : run.join(',') }.join(',')
|
|
53
69
|
end
|
|
@@ -104,7 +120,14 @@ module RateCard
|
|
|
104
120
|
end
|
|
105
121
|
end
|
|
106
122
|
|
|
123
|
+
# A Symbol zone (:edas, :rdas) only ever comes from UPS rural mode, so it
|
|
124
|
+
# disambiguates from a real zone number without needing to check carrier
|
|
125
|
+
# or rural separately. USPS rural mode keeps integer zones, just against
|
|
126
|
+
# the rural chart instead of the normal one.
|
|
107
127
|
def address_for(zone)
|
|
128
|
+
return Constants::Addresses::UPS_RURAL[zone] if zone.is_a?(Symbol)
|
|
129
|
+
return Constants::Addresses::USPS_RURAL_DAS[zone] if carrier == 'USPS' && rural?
|
|
130
|
+
|
|
108
131
|
Constants::Addresses.for_carrier(carrier)[zone]
|
|
109
132
|
end
|
|
110
133
|
|
|
@@ -136,7 +159,19 @@ module RateCard
|
|
|
136
159
|
end
|
|
137
160
|
|
|
138
161
|
def run_dir
|
|
139
|
-
Pathname.new(output_base).join("#{slug}_#{customer_id}_#{timestamp}")
|
|
162
|
+
Pathname.new(output_base).join("#{slug}_#{customer_id}_#{timestamp}#{rural_suffix}")
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# UPS rural mode runs one pass per selected surcharge type (see
|
|
166
|
+
# TUI::App#build_specs), so a single spec's zones is exactly one symbol -
|
|
167
|
+
# the suffix names it, so two same-second passes don't collide on
|
|
168
|
+
# run_dir. USPS rural mode sweeps real zones as usual, so it just gets
|
|
169
|
+
# the generic suffix.
|
|
170
|
+
def rural_suffix
|
|
171
|
+
return '' unless rural?
|
|
172
|
+
|
|
173
|
+
surcharge = zones.find { |zone| zone.is_a?(Symbol) }
|
|
174
|
+
surcharge ? "_#{surcharge}" : '_rural'
|
|
140
175
|
end
|
|
141
176
|
|
|
142
177
|
def validate!
|
|
@@ -47,7 +47,7 @@ module RateCard
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def render(service, rate_key)
|
|
50
|
-
header = [spec.weight_label, *spec.zones.map { |zone|
|
|
50
|
+
header = [spec.weight_label, *spec.zones.map { |zone| spec.zone_label(zone) }]
|
|
51
51
|
body = rows(service, rate_key)
|
|
52
52
|
|
|
53
53
|
Lipgloss::Table.new
|
data/lib/rate_card/tui/app.rb
CHANGED
|
@@ -24,11 +24,14 @@ module RateCard
|
|
|
24
24
|
|
|
25
25
|
# No :token stage — see TokenPrompt for why it cannot live in the loop.
|
|
26
26
|
STAGES = %i[
|
|
27
|
-
loading rate_mode carrier services zones unit weights
|
|
28
|
-
rate_keys confirm fetching
|
|
27
|
+
loading rate_mode carrier rural rural_surcharges services zones unit weights
|
|
28
|
+
package_type rate_keys confirm fetching
|
|
29
29
|
].freeze
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
# #spec/#grid hold the most recently finished pass, for every caller that
|
|
32
|
+
# only ever produced one (every carrier except UPS rural mode with more
|
|
33
|
+
# than one surcharge type checked). #results holds every pass.
|
|
34
|
+
attr_reader :spec, :grid, :error, :notifier, :results
|
|
32
35
|
|
|
33
36
|
# notifier is set by the caller to the Bubbletea::Runner, whose #send is
|
|
34
37
|
# the only way a worker thread can get a message onto the event loop.
|
|
@@ -54,6 +57,7 @@ module RateCard
|
|
|
54
57
|
@failure_sparkline = Ntcharts::Sparkline.new(32, 1)
|
|
55
58
|
@failure_sparkline.style = Lipgloss::Style.new.foreground(Theme::WARNING)
|
|
56
59
|
@log = []
|
|
60
|
+
@results = []
|
|
57
61
|
end
|
|
58
62
|
|
|
59
63
|
def cancelled? = @cancelled
|
|
@@ -69,7 +73,7 @@ module RateCard
|
|
|
69
73
|
when ServicesLoaded then services_loaded(message.services)
|
|
70
74
|
when LoadFailed then return fail_with(message.error)
|
|
71
75
|
when ProgressAdvanced then progress_advanced(message)
|
|
72
|
-
when FetchFinished then return
|
|
76
|
+
when FetchFinished then return fetch_finished(message.grid)
|
|
73
77
|
when FetchFailed then return fail_with(message.error)
|
|
74
78
|
else
|
|
75
79
|
return [self, spinner_or_field(message)]
|
|
@@ -175,9 +179,11 @@ module RateCard
|
|
|
175
179
|
|
|
176
180
|
def field_for(stage)
|
|
177
181
|
case stage
|
|
178
|
-
when :rate_mode
|
|
179
|
-
when :carrier
|
|
180
|
-
when :
|
|
182
|
+
when :rate_mode then rate_mode_field
|
|
183
|
+
when :carrier then carrier_field
|
|
184
|
+
when :rural then rural_field
|
|
185
|
+
when :rural_surcharges then rural_surcharges_field
|
|
186
|
+
when :services then services_field
|
|
181
187
|
when :zones then zones_field
|
|
182
188
|
when :unit then unit_field
|
|
183
189
|
when :weights then weights_field
|
|
@@ -238,8 +244,40 @@ module RateCard
|
|
|
238
244
|
)
|
|
239
245
|
end
|
|
240
246
|
|
|
247
|
+
# Only USPS and UPS have a rural/DAS chart (Addresses::USPS_RURAL_DAS,
|
|
248
|
+
# Addresses::UPS_RURAL); every other carrier is decided :normal (nil)
|
|
249
|
+
# and skips this stage, same as any other single-answer stage. Same
|
|
250
|
+
# Normal/Rural toggle for both carriers - which surcharge type(s) UPS
|
|
251
|
+
# means by "rural" is a separate question, :rural_surcharges below.
|
|
252
|
+
def rural_field
|
|
253
|
+
return nil unless Constants::Carriers.rural_aware?(carrier)
|
|
254
|
+
|
|
255
|
+
choices = [['Normal', false], ['Rural (DAS)', true]]
|
|
256
|
+
Fields::Select.new(label: 'Rural / DAS', choices: choices,
|
|
257
|
+
selected: choices.index { |_, v| v == @answers[:rural] } || 0)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# UPS has no per-zone rural chart - each surcharge type is one fixed
|
|
261
|
+
# address, not a zone sweep - so this replaces the zones question for
|
|
262
|
+
# UPS rural mode. Checking both produces two separate rate cards (see
|
|
263
|
+
# #build_specs), one per surcharge type, rather than one card that
|
|
264
|
+
# conflates two different addresses under one "zone" axis.
|
|
265
|
+
def rural_surcharges_field
|
|
266
|
+
return nil unless ups_rural?
|
|
267
|
+
|
|
268
|
+
choices = [['EDAS', :edas], ['RDAS', :rdas]]
|
|
269
|
+
answered = @answers[:rural_surcharges]
|
|
270
|
+
Fields::MultiSelect.new(
|
|
271
|
+
label: 'Surcharge types',
|
|
272
|
+
choices: choices,
|
|
273
|
+
checked: answered ? checked_indexes(choices.map(&:last), answered) : (0...choices.length)
|
|
274
|
+
)
|
|
275
|
+
end
|
|
276
|
+
|
|
241
277
|
def zones_field
|
|
242
|
-
|
|
278
|
+
return nil if ups_rural?
|
|
279
|
+
|
|
280
|
+
available = usps_rural? ? Constants::Addresses::USPS_RURAL_DAS.keys.sort : Constants::Addresses.available_zones(carrier)
|
|
243
281
|
full = "#{available.first}-#{available.last}"
|
|
244
282
|
answered = @answers[:zones]
|
|
245
283
|
|
|
@@ -255,6 +293,14 @@ module RateCard
|
|
|
255
293
|
)
|
|
256
294
|
end
|
|
257
295
|
|
|
296
|
+
def usps_rural?
|
|
297
|
+
carrier == 'USPS' && @answers[:rural] == true
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def ups_rural?
|
|
301
|
+
carrier == 'UPS' && @answers[:rural] == true
|
|
302
|
+
end
|
|
303
|
+
|
|
258
304
|
# Weight is fixed per cubic tier, so asking for a display unit is
|
|
259
305
|
# meaningless in cubic mode — decided as :oz (unused) and skipped.
|
|
260
306
|
def unit_field
|
|
@@ -373,18 +419,39 @@ module RateCard
|
|
|
373
419
|
|
|
374
420
|
# ---------------------------------------------------------------- fetch
|
|
375
421
|
|
|
422
|
+
# UPS rural mode with more than one surcharge type checked runs as
|
|
423
|
+
# several independent passes (see #build_specs) - each one calls
|
|
424
|
+
# Grid.build, feeds the same progress bar, and lands its own {spec:,
|
|
425
|
+
# grid:} in #results before the next pass starts. Every other carrier
|
|
426
|
+
# and mode has exactly one pass, same as before this existed.
|
|
376
427
|
def start_fetch
|
|
377
|
-
@
|
|
428
|
+
@pending_specs = build_specs
|
|
378
429
|
# Before the first call, so a bad path is not discovered after 128 of them.
|
|
379
430
|
begin
|
|
380
|
-
CsvWriter.ensure_writable!(
|
|
431
|
+
@pending_specs.each { |spec| CsvWriter.ensure_writable!(spec.output_base) }
|
|
381
432
|
rescue OutputNotWritable => e
|
|
382
433
|
return fail_with(e).last
|
|
383
434
|
end
|
|
384
435
|
|
|
436
|
+
@results = []
|
|
437
|
+
@total_passes = @pending_specs.length
|
|
438
|
+
@pass_index = 0
|
|
439
|
+
next_pass
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
def next_pass
|
|
443
|
+
@spec = @pending_specs.shift
|
|
444
|
+
return Bubbletea.quit if @spec.nil?
|
|
445
|
+
|
|
446
|
+
@pass_index += 1
|
|
447
|
+
@completed = 0
|
|
448
|
+
@failed = 0
|
|
449
|
+
fetch_command(@spec)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def fetch_command(spec)
|
|
385
453
|
client = @client_factory.call(@token)
|
|
386
454
|
notifier = @notifier
|
|
387
|
-
spec = @spec
|
|
388
455
|
provider = @provider
|
|
389
456
|
|
|
390
457
|
lambda do
|
|
@@ -408,9 +475,10 @@ module RateCard
|
|
|
408
475
|
@failure_sparkline.push(message.failed)
|
|
409
476
|
end
|
|
410
477
|
|
|
411
|
-
def
|
|
478
|
+
def fetch_finished(grid)
|
|
412
479
|
@grid = grid
|
|
413
|
-
|
|
480
|
+
@results << { spec: @spec, grid: grid }
|
|
481
|
+
[self, next_pass]
|
|
414
482
|
end
|
|
415
483
|
|
|
416
484
|
def fail_with(error)
|
|
@@ -418,7 +486,23 @@ module RateCard
|
|
|
418
486
|
[self, Bubbletea.quit]
|
|
419
487
|
end
|
|
420
488
|
|
|
489
|
+
# One RunSpec per pass. UPS rural mode runs one pass per checked
|
|
490
|
+
# surcharge type (each is a fixed single address, not a zone sweep -
|
|
491
|
+
# see Addresses::UPS_RURAL) rather than folding both into one card's
|
|
492
|
+
# zone axis. Every other carrier/mode is the single pass it always was.
|
|
493
|
+
def build_specs
|
|
494
|
+
if ups_rural?
|
|
495
|
+
(@answers[:rural_surcharges] || []).map { |surcharge| run_spec(zones: [surcharge]) }
|
|
496
|
+
else
|
|
497
|
+
[run_spec(zones: @answers[:zones])]
|
|
498
|
+
end
|
|
499
|
+
end
|
|
500
|
+
|
|
421
501
|
def build_spec
|
|
502
|
+
build_specs.first
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def run_spec(zones:)
|
|
422
506
|
cubic = @answers[:rate_mode] == :cubic
|
|
423
507
|
RunSpec.new(
|
|
424
508
|
token: @token,
|
|
@@ -426,11 +510,12 @@ module RateCard
|
|
|
426
510
|
customer_id: identity[:customer_id],
|
|
427
511
|
carrier: carrier,
|
|
428
512
|
services: @answers[:services],
|
|
429
|
-
zones:
|
|
513
|
+
zones: zones,
|
|
430
514
|
weight_unit: @answers[:unit] || :oz,
|
|
431
515
|
weights: cubic ? [] : @answers[:weights],
|
|
432
516
|
cubic_tiers: cubic ? @answers[:weights] : [],
|
|
433
517
|
rate_mode: @answers[:rate_mode] || :weight,
|
|
518
|
+
rural: @answers[:rural],
|
|
434
519
|
package_type: @answers[:package_type],
|
|
435
520
|
rate_keys: @answers[:rate_keys],
|
|
436
521
|
output_base: @output_base,
|
|
@@ -457,15 +542,28 @@ module RateCard
|
|
|
457
542
|
# Everything the run will do, gathered in one block. The answers are also
|
|
458
543
|
# in the transcript above, but they arrived one at a time over eight
|
|
459
544
|
# screens; this is the only place they can be read against each other.
|
|
545
|
+
#
|
|
546
|
+
# Built from real RunSpecs (build_specs) rather than raw @answers, so a
|
|
547
|
+
# UPS rural run with both surcharge types checked recaps as the two
|
|
548
|
+
# separate cards it will actually produce, one line each.
|
|
460
549
|
def recap_view
|
|
550
|
+
specs = build_specs
|
|
551
|
+
carrier_line = " #{Theme.bold(carrier)}#{rural_recap} · #{@answers[:services].map(&:name).join(', ')}"
|
|
461
552
|
[
|
|
462
|
-
|
|
463
|
-
" zones #{
|
|
553
|
+
carrier_line,
|
|
554
|
+
*specs.map { |spec| " zones #{spec.zone_summary} · #{rows_recap} · #{@answers[:package_type]}" },
|
|
464
555
|
" columns: #{@answers[:rate_keys].map { |k| RunSpec::RATE_KEY_LABELS.fetch(k) }.join(', ')}",
|
|
465
|
-
" #{Theme.bold(call_count.to_s)} rate calls against #{Theme.danger('production')}"
|
|
556
|
+
" #{Theme.bold(specs.sum(&:call_count).to_s)} rate calls against #{Theme.danger('production')}" \
|
|
557
|
+
"#{specs.length > 1 ? " (#{specs.length} separate cards)" : ''}"
|
|
466
558
|
].join("\n")
|
|
467
559
|
end
|
|
468
560
|
|
|
561
|
+
def rural_recap
|
|
562
|
+
return '' unless @answers[:rural]
|
|
563
|
+
|
|
564
|
+
" (#{rural_label(@answers[:rural])})"
|
|
565
|
+
end
|
|
566
|
+
|
|
469
567
|
def rows_recap
|
|
470
568
|
if @answers[:rate_mode] == :cubic
|
|
471
569
|
"cubic tiers #{RunSpec.compact_range(@answers[:weights])}"
|
|
@@ -474,16 +572,13 @@ module RateCard
|
|
|
474
572
|
end
|
|
475
573
|
end
|
|
476
574
|
|
|
477
|
-
def call_count
|
|
478
|
-
@answers[:weights].length * @answers[:zones].length
|
|
479
|
-
end
|
|
480
|
-
|
|
481
575
|
def fetch_view
|
|
482
576
|
total = @spec.call_count
|
|
483
577
|
percent = total.zero? ? 0.0 : @completed.to_f / total
|
|
578
|
+
title = @total_passes > 1 ? "fetching rates (pass #{@pass_index}/#{@total_passes})" : 'fetching rates'
|
|
484
579
|
line = " #{@progress.view_as(percent)} #{@completed}/#{total}"
|
|
485
580
|
line += " #{Theme.warning("#{Theme::ALERT} #{@failed} failed")}" if @failed.positive?
|
|
486
|
-
view = "#{Theme.bold(
|
|
581
|
+
view = "#{Theme.bold(" #{title}")}\n#{line}"
|
|
487
582
|
view += "\n#{failure_sparkline_view}" if @failed.positive?
|
|
488
583
|
view
|
|
489
584
|
end
|
|
@@ -500,7 +595,8 @@ module RateCard
|
|
|
500
595
|
# transcript of the run stays on screen — the recap is then a summary of
|
|
501
596
|
# what is already visible rather than the first chance to check it.
|
|
502
597
|
def answered_line(stage, value)
|
|
503
|
-
label = { rate_mode: 'rate by', carrier: 'carrier',
|
|
598
|
+
label = { rate_mode: 'rate by', carrier: 'carrier', rural: 'rural / DAS',
|
|
599
|
+
rural_surcharges: 'surcharge types', services: 'services', zones: 'zones',
|
|
504
600
|
unit: 'unit', weights: 'weights', package_type: 'package',
|
|
505
601
|
rate_keys: 'columns' }[stage]
|
|
506
602
|
label = 'cubic tiers' if stage == :weights && @answers[:rate_mode] == :cubic
|
|
@@ -511,13 +607,19 @@ module RateCard
|
|
|
511
607
|
|
|
512
608
|
def describe(stage, value)
|
|
513
609
|
case stage
|
|
514
|
-
when :services
|
|
515
|
-
when :zones
|
|
516
|
-
when :weights
|
|
517
|
-
when :
|
|
610
|
+
when :services then value.map(&:name).join(', ')
|
|
611
|
+
when :zones then RunSpec.compact_range(value)
|
|
612
|
+
when :weights then RunSpec.compact_range(value)
|
|
613
|
+
when :rural then rural_label(value)
|
|
614
|
+
when :rural_surcharges then value.map { |v| v.to_s.upcase }.join(', ')
|
|
615
|
+
when :rate_keys then value.map { |k| RunSpec::RATE_KEY_LABELS.fetch(k) }.join(', ')
|
|
518
616
|
else value.to_s
|
|
519
617
|
end
|
|
520
618
|
end
|
|
619
|
+
|
|
620
|
+
def rural_label(value)
|
|
621
|
+
value ? 'rural (DAS)' : 'normal'
|
|
622
|
+
end
|
|
521
623
|
end
|
|
522
624
|
end
|
|
523
625
|
end
|
data/lib/rate_card/version.rb
CHANGED