Module: DeliveriesHelper
- Defined in:
- app/helpers/deliveries_helper.rb
Overview
View helper: deliveries.
Instance Method Summary collapse
- #add_delivery_shipment_link(name) ⇒ Object
- #add_shipment_link(name) ⇒ Object
- #address_hash_to_s(address_hash) ⇒ Object
- #already_pre_packed?(delivery) ⇒ Boolean
-
#amz_bs_badge ⇒ String
Get a badge for Amazon Buy Shipping carrier type.
- #delivery_request_estimated_packaging_form(delivery, return_path = nil) ⇒ Object
- #delivery_request_estimated_packaging_link(delivery, return_path = nil) ⇒ Object
- #delivery_tab_options(delivery_presenter) ⇒ Object
- #edit_delivery_packing_link(delivery = @delivery, return_path: nil) ⇒ Object
- #electronic_commercial_invoice_message ⇒ Object
- #fields_for_shipment(shipment) ⇒ Object
-
#format_shipping_rate_with_marketplace_badge(shipping_cost, show_price: true) ⇒ String
(also: #format_shipping_rate_with_sww_badge)
Format a shipping rate with appropriate badge if it's a marketplace rate (Ship with Walmart or Amazon Buy Shipping).
-
#freight_event_status_icons(delivery, size: nil) ⇒ ActiveSupport::SafeBuffer?
Render the inline freight-event status icon row for a Freightquote LTL delivery — one icon each for load / pickup appointment / delivery, appearing only when at least one event in that bucket has landed.
-
#is_amz_bs_rate?(shipping_cost) ⇒ Boolean
Check if a shipping cost is an Amazon Buy Shipping rate.
-
#is_sww_rate?(shipping_cost) ⇒ Boolean
Check if a shipping cost is a Ship with Walmart rate.
- #pack_shipment_delete_button(f) ⇒ Object
- #render_ship_quotable_command_options(ship_quotable) ⇒ Object
-
#render_tracking_status_badge(badge, size: nil) ⇒ ActiveSupport::SafeBuffer?
Shared markup for a single tracking-status badge (parcel + LTL).
- #setup_delivery_for_packing(delivery) ⇒ Object
- #ship_quotable_command_options(ship_quotable) ⇒ Object
-
#shipengine_ltl_status_icon(delivery, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Render the ShipEngine LTL freight tracking status icon for a delivery — ONE badge per delivery (LTL is a single freight shipment under one PRO, unlike parcel which is per-package).
-
#shipment_event_status_icon(shipment, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Render the inline ShipEngine tracking status icon for a parcel shipment — at most one badge per shipment, reflecting its most- advanced scan (delivered > exception > delivery attempt > in transit > accepted).
-
#shipment_event_status_icons_for_delivery(delivery, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Aggregate variant of #shipment_event_status_icon for the delivery- level heading on the show page.
- #show_delivery_pre_pack_option(delivery) ⇒ Object
-
#sww_badge ⇒ String
Get a badge for Walmart SWW carrier type Can be used inline in any view to identify Walmart rates.
Instance Method Details
#add_delivery_shipment_link(name) ⇒ Object
190 191 192 |
# File 'app/helpers/deliveries_helper.rb', line 190 def add_delivery_shipment_link(name) link_to name, '#', onclick: "$('#shipments').append('#{j(render(partial: 'shipment', locals: { remove_link: true, package: WarehousePackage.new, shipment: Shipment.new }))}');return false", class: 'btn btn-outline-primary me-3' end |
#add_shipment_link(name) ⇒ Object
186 187 188 |
# File 'app/helpers/deliveries_helper.rb', line 186 def add_shipment_link(name) link_to name, '#', onclick: "$('#shipments').append('#{j(render(partial: 'shipment', object: Shipment.new))}')" end |
#address_hash_to_s(address_hash) ⇒ Object
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 |
# File 'app/helpers/deliveries_helper.rb', line 306 def address_hash_to_s(address_hash) freight_fields_text = if address_hash[:is_residential] '(Residential' else '(Commercial' end freight_fields_text += (address_hash[:require_signature_by_default] ? ', require signature by default' : '') freight_fields_text += (address_hash[:has_loading_dock] ? ', has loading dock' : '') freight_fields_text += (address_hash[:requires_inside_delivery] ? ', requires inside delivery' : '') freight_fields_text += (address_hash[:requires_liftgate] ? ', requires lift-gate' : '') freight_fields_text += (address_hash[:is_construction_site] ? ', is construction site' : '') freight_fields_text += (address_hash[:limited_access] ? ', limited access' : '') freight_fields_text += (address_hash[:requires_appointment] ? ', requires delivery appointment' : '') freight_fields_text += (address_hash[:timezone_name].present? ? ", TZ: #{address_hash[:timezone_name]}" : '') freight_fields_text += ')' "#{[address_hash[:street1], address_hash[:street2], address_hash[:city], address_hash[:state_code], address_hash[:country_iso]].compact.join(', ')} #{freight_fields_text}" end |
#already_pre_packed?(delivery) ⇒ Boolean
221 222 223 |
# File 'app/helpers/deliveries_helper.rb', line 221 def already_pre_packed?(delivery) delivery.shipments.all?(&:packed_or_pre_packed?) && !(current_user.has_role?('warehouse_rep') || current_user.is_manager?) # don't allow pre-pack if already pre-packed, unless warehouse staff or admin end |
#amz_bs_badge ⇒ String
Get a badge for Amazon Buy Shipping carrier type
401 402 403 |
# File 'app/helpers/deliveries_helper.rb', line 401 def amz_bs_badge content_tag(:span, 'Amazon Buy Shipping', class: 'badge bg-warning text-dark', title: 'Amazon Buy Shipping rate with A-to-Z protections') end |
#delivery_request_estimated_packaging_form(delivery, return_path = nil) ⇒ Object
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'app/helpers/deliveries_helper.rb', line 225 def delivery_request_estimated_packaging_form(delivery, return_path = nil) return unless show_delivery_pre_pack_option(delivery) pp_disabled = already_pre_packed?(delivery) simple_form_for delivery, url: request_estimated_packaging_delivery_path(delivery, return_path: return_path || polymorphic_url(delivery.resource, tab: 'shipping')), html: { data: { turbo_frame: '_top' } } do |f| content_tag(:div, class: 'btn-group') do concat f.input_field(:suggested_packaging_text, as: :string, placeholder: 'Packaging directions (optional)', size: 40, class: 'form-control rounded-0 rounded-start') concat f.(:submit, (pp_disabled ? 'Already packaged, contact Warehouse to request repackaging' : 'Request Estimated Packaging').to_s, class: 'btn btn-outline-primary', disabled: pp_disabled) end end end |
#delivery_request_estimated_packaging_link(delivery, return_path = nil) ⇒ Object
242 243 244 245 246 247 248 |
# File 'app/helpers/deliveries_helper.rb', line 242 def delivery_request_estimated_packaging_link(delivery, return_path = nil) return unless show_delivery_pre_pack_option(delivery) pp_disabled = already_pre_packed?(delivery) link_to((pp_disabled ? 'Already packaged, contact Warehouse to request repackaging' : 'Request Estimated Packaging').to_s, (pp_disabled ? 'javascript:void(0);' : workflow_action_delivery_path(delivery, return_path: return_path || polymorphic_url(delivery.resource, tab: 'shipping'), wf_action: 'request_estimated_packaging')), data: { turbo_method: :post, turbo_frame: '_top' }, class: 'btn btn-outline-primary') end |
#delivery_tab_options(delivery_presenter) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'app/helpers/deliveries_helper.rb', line 256 def (delivery_presenter) delivery = delivery_presenter.delivery tab_panels = { main: { remote_href: tab_main_delivery_path(delivery) }, shipping: { remote_href: tab_shipping_delivery_path(delivery) }, line_items: { remote_href: tab_line_items_delivery_path(delivery) }, activities: { counter: delivery_presenter.open_activities_counter, remote_href: delivery_activities_path(delivery, selected_activity: params[:selected_activity]) }, attachments: { counter: delivery_presenter.uploads.size, remote_href: delivery_uploads_path(delivery) } } if delivery.order tab_panels.merge!({ invoices: { remote_href: tab_invoices_delivery_path(delivery) }, item_ledger: { remote_href: tab_item_ledger_delivery_path(delivery) }, account_ledger: { remote_href: tab_account_ledger_delivery_path(delivery) } }) end log_size = Array(delivery.shipping_api_log).size if log_size.positive? tab_panels[:shipping_api_log] = { title: 'Shipping API Log', counter: log_size, remote_href: tab_shipping_api_log_delivery_path(delivery) } end freight_events_count = delivery.freight_events.size if freight_events_count.positive? tab_panels[:freight_events] = { title: 'Freight Events', counter: freight_events_count, remote_href: tab_freight_events_delivery_path(delivery) } end # Surface the Tracking Events tab whenever the delivery has accumulated # ShipEngine scan history. Counts events by tracking_number(s), not by # shipment_id — offbook ST shipments legitimately share a tracking number # across multiple Shipment rows, and ShipEngine LTL keys off the delivery's # PRO (no per-pallet tracking_number). `shipment_event_tracking_numbers` # unifies both. Matches the partial's query shape. tracking_numbers = delivery.shipment_event_tracking_numbers tracking_events_count = tracking_numbers.any? ? ShipmentEvent.where(tracking_number: tracking_numbers).count : 0 if tracking_events_count.positive? tab_panels[:tracking_events] = { title: 'Tracking Events', counter: tracking_events_count, remote_href: tab_tracking_events_delivery_path(delivery) } end tab_panels end |
#edit_delivery_packing_link(delivery = @delivery, return_path: nil) ⇒ Object
152 153 154 155 156 157 158 159 160 161 |
# File 'app/helpers/deliveries_helper.rb', line 152 def edit_delivery_packing_link(delivery = @delivery, return_path: nil) return unless delivery.shipment_contents_editable?(current_user) data_hsh = if current_user.has_role?('warehouse_rep') nil else { turbo_confirm: "Are you sure? Packaging is usually defined by the warehouse, but if you know what you're doing, please go ahead." } end link_to 'Edit Packing', picked_delivery_path(delivery, return_path:), data: (data_hsh || {}).merge(turbo_frame: '_top'), class: 'btn btn-outline-primary m-2' end |
#electronic_commercial_invoice_message ⇒ Object
324 325 326 327 328 |
# File 'app/helpers/deliveries_helper.rb', line 324 def return unless @delivery.electronic_ship_ci_pdf || @delivery.should_have_electronic_commercial_invoice? 'DO NOT PRINT COMMERCIAL INVOICE WHEN UPS OR FEDEX LABEL INDICATES EDI, EDI-PULL or ETD: IT IS HANDLED ELECTRONICALLY.' end |
#fields_for_shipment(shipment) ⇒ Object
181 182 183 184 |
# File 'app/helpers/deliveries_helper.rb', line 181 def fields_for_shipment(shipment, &) prefix = shipment.new_record? ? 'new' : 'existing' fields_for("delivery[#{prefix}_shipment_attributes][]", shipment, &) end |
#format_shipping_rate_with_marketplace_badge(shipping_cost, show_price: true) ⇒ String Also known as: format_shipping_rate_with_sww_badge
Format a shipping rate with appropriate badge if it's a marketplace rate
(Ship with Walmart or Amazon Buy Shipping)
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'app/helpers/deliveries_helper.rb', line 336 def format_shipping_rate_with_marketplace_badge(shipping_cost, show_price: true) return '' unless shipping_cost carrier = shipping_cost.respond_to?(:carrier) ? shipping_cost.carrier : shipping_cost.shipping_option&.carrier rd = shipping_cost.rate_data&.with_indifferent_access || {} parts = [] if carrier == 'WalmartSeller' || is_sww_rate?(shipping_cost) parts << content_tag(:span, 'Ship with Walmart', class: 'badge bg-primary me-1') parts << [rd[:sww_carrier_name] || 'Unknown', rd[:sww_service_name].presence].compact.join(' - ') elsif carrier == 'AmazonSeller' || is_amz_bs_rate?(shipping_cost) parts << content_tag(:span, 'Amazon Buy Shipping', class: 'badge bg-warning text-dark me-1') parts << [rd[:amz_carrier_name] || 'Unknown', rd[:amz_service_name].presence].compact.join(' - ') else parts << (shipping_cost.try(:description) || shipping_cost.shipping_option&.name) end # Add price if requested if show_price && shipping_cost.cost.present? parts << ' - ' parts << number_to_currency(shipping_cost.cost) end safe_join(parts) end |
#freight_event_status_icons(delivery, size: nil) ⇒ ActiveSupport::SafeBuffer?
Render the inline freight-event status icon row for a Freightquote LTL
delivery — one icon each for load / pickup appointment / delivery,
appearing only when at least one event in that bucket has landed.
Returns +nil+ (no markup) when the delivery is not Freightquote or has
no relevant events yet, so callers can splat this into any cell without
adding stray whitespace.
Used in two places:
- app/views/crm/warehouses/_delivery.html.erb — beside the shipping
description cell on the warehouse dashboard - app/views/deliveries/show.html.erb — beside the delivery heading
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'app/helpers/deliveries_helper.rb', line 20 def freight_event_status_icons(delivery, size: nil) return nil unless delivery&.carrier == 'Freightquote' badges = FreightEventStatusSummary.for(delivery) return nil if badges.empty? # Wrap in `data-controller="tooltip"` so the project's tooltip # Stimulus controller initialises the Bootstrap tooltips inside # this scope, even when the surrounding view doesn't already. icons = safe_join( badges.map do |badge| icon_class = ["text-#{badge.color}", 'ms-2'] icon_class << "fa-#{size}" if size.present? fa_icon( badge.icon, family: :solid, class: icon_class.compact.join(' '), 'data-bs-toggle': 'tooltip', title: badge.tooltip, 'aria-label': badge.tooltip ) end ) tag.span(icons, class: 'freight-event-status-icons', data: { controller: 'tooltip' }) end |
#is_amz_bs_rate?(shipping_cost) ⇒ Boolean
Check if a shipping cost is an Amazon Buy Shipping rate
381 382 383 384 385 386 387 388 |
# File 'app/helpers/deliveries_helper.rb', line 381 def is_amz_bs_rate?(shipping_cost) return false unless shipping_cost rate_data = shipping_cost.rate_data return false unless rate_data.is_a?(Hash) rate_data['amz_carrier_id'].present? || rate_data[:amz_carrier_id].present? end |
#is_sww_rate?(shipping_cost) ⇒ Boolean
Check if a shipping cost is a Ship with Walmart rate
368 369 370 371 372 373 374 375 |
# File 'app/helpers/deliveries_helper.rb', line 368 def is_sww_rate?(shipping_cost) return false unless shipping_cost rate_data = shipping_cost.rate_data return false unless rate_data.is_a?(Hash) rate_data['sww_carrier_id'].present? || rate_data[:sww_carrier_id].present? end |
#pack_shipment_delete_button(f) ⇒ Object
169 170 171 172 173 174 175 176 177 178 179 |
# File 'app/helpers/deliveries_helper.rb', line 169 def (f) if f.object.persisted? capture do concat f.hidden_field '_destroy' concat f.label '_destroy', fa_icon('trash'), class: 'inline' concat f.check_box '_destroy', class: 'destroy' end else (fa_icon('trash'), type: 'button', class: 'btn pack-shipment-remove', data: { action: 'delivery-nested-form#remove' }) end end |
#render_ship_quotable_command_options(ship_quotable) ⇒ Object
250 251 252 253 254 |
# File 'app/helpers/deliveries_helper.rb', line 250 def (ship_quotable) content_tag(:ul, class: 'list-inline') do (ship_quotable).map { |o| content_tag(:li, o, class: 'list-inline-item') }.join.html_safe end end |
#render_tracking_status_badge(badge, size: nil) ⇒ ActiveSupport::SafeBuffer?
Shared markup for a single tracking-status badge (parcel + LTL). Returns
+nil+ for a nil badge so callers can splat without stray whitespace.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'app/helpers/deliveries_helper.rb', line 136 def render_tracking_status_badge(badge, size: nil) return nil unless badge icon_class = ["text-#{badge.color}", 'ms-2'] icon_class << "fa-#{size}" if size.present? icon = fa_icon( badge.icon, family: :solid, class: icon_class.compact.join(' '), 'data-bs-toggle': 'tooltip', title: badge.tooltip, 'aria-label': badge.tooltip ) tag.span(icon, class: 'shipment-event-status-icon', data: { controller: 'tooltip' }) end |
#setup_delivery_for_packing(delivery) ⇒ Object
163 164 165 166 167 |
# File 'app/helpers/deliveries_helper.rb', line 163 def setup_delivery_for_packing(delivery) delivery.tap do |d| d.shipments.build(state: 'suggested') unless d.shipments.any? { |s| s.suggested? || s.packed? || s.awaiting_label? } end end |
#ship_quotable_command_options(ship_quotable) ⇒ Object
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'app/helpers/deliveries_helper.rb', line 194 def (ship_quotable) opts = [] unless ship_quotable.is_warehouse_pickup? || (ship_quotable.try(:order_type) == Order::CREDIT_ORDER) # Use data attributes to pass ship dates when recalculating opts << link_to('Recalculate Shipping for all Deliveries', recalculate_shipping_all_deliveries_path(ship_quotable_type: @ship_quotable.class.to_s, ship_quotable_id: @ship_quotable.id, return_path: @return_path), class: 'btn btn-outline-primary', data: { controller: 'recalculate-shipping', action: 'click->recalculate-shipping#recalculate', turbo_frame: 'shipping_services' }) if ship_quotable.single_origin opts << link_to('Allow multiple deliveries (drop ships)', multiple_origin_deliveries_path(ship_quotable_type: @ship_quotable.class.to_s, ship_quotable_id: @ship_quotable.id, return_path: @return_path), class: 'btn btn-outline-primary', data: { turbo_frame: 'shipping_services' }) elsif can?( :change_delivery_origin, @ship_quotable ) opts << link_to('Force one delivery from our warehouse', single_origin_deliveries_path(ship_quotable_type: @ship_quotable.class.to_s, ship_quotable_id: @ship_quotable.id, return_path: @return_path), class: 'btn btn-outline-primary', data: { turbo_frame: 'shipping_services' }) end end opts end |
#shipengine_ltl_status_icon(delivery, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Render the ShipEngine LTL freight tracking status icon for a delivery —
ONE badge per delivery (LTL is a single freight shipment under one PRO,
unlike parcel which is per-package). Reuses ShipmentEventStatusSummary
off the delivery's ltl_pro_number, so the icon/color/tooltip are
identical to the ShipEngine package badge. Returns +nil+ when the delivery
isn't ShipEngine LTL, has no PRO, or has no scans yet — so callers can
splat it into any cell without stray whitespace.
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'app/helpers/deliveries_helper.rb', line 117 def shipengine_ltl_status_icon(delivery, size: nil, events_by_number: nil) return nil unless delivery return nil unless ShippingOption::SHIPENGINE_LTL_CARRIERS.include?(delivery.shipping_option&.carrier) return nil if delivery.ltl_pro_number.blank? badge = if events_by_number ShipmentEventStatusSummary.from_events(events_by_number[delivery.ltl_pro_number]) else ShipmentEventStatusSummary.for_tracking_number(delivery.ltl_pro_number) end render_tracking_status_badge(badge, size: size) end |
#shipment_event_status_icon(shipment, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Render the inline ShipEngine tracking status icon for a parcel
shipment — at most one badge per shipment, reflecting its most-
advanced scan (delivered > exception > delivery attempt > in transit
accepted). Returns +nil+ when the shipment has no scans yet so
callers can splat into any cell without adding stray whitespace.
59 60 61 62 63 64 65 66 67 68 |
# File 'app/helpers/deliveries_helper.rb', line 59 def shipment_event_status_icon(shipment, size: nil, events_by_number: nil) return nil if shipment.blank? badge = if events_by_number ShipmentEventStatusSummary.from_events(events_by_number[shipment.tracking_number]) else ShipmentEventStatusSummary.for(shipment) end render_tracking_status_badge(badge, size: size) end |
#shipment_event_status_icons_for_delivery(delivery, size: nil, events_by_number: nil) ⇒ ActiveSupport::SafeBuffer?
Aggregate variant of #shipment_event_status_icon for the delivery-
level heading on the show page. Renders one icon per parcel shipment
under the delivery, in shipment-creation order, mirroring
#freight_event_status_icons's inline placement next to the delivery
title. Returns +nil+ when none of the shipments have any scans yet.
Scope: every shipment with a tracking_number. We do NOT filter by
PARCEL_CARRIER_INTERNAL_TO_SHIPENGINE_CODE here — shipments.carrier
often holds a service-level name ("UPS Standard", "FedEx Ground")
rather than the canonical carrier, and an exact-match filter
silently drops those shipments from the heading even when their
ShipmentEvent rows are populated. The per-shipment
shipment_event_status_icon already short-circuits to nil when no
events exist, so any shipment without scans contributes nothing.
91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/helpers/deliveries_helper.rb', line 91 def shipment_event_status_icons_for_delivery(delivery, size: nil, events_by_number: nil) return nil unless delivery shipments = if events_by_number delivery.shipments.select { |s| s.tracking_number.present? }.sort_by(&:id) else delivery.shipments.where.not(tracking_number: [nil, '']).order(:id) end return nil if shipments.empty? icons = shipments.filter_map { |s| shipment_event_status_icon(s, size: size, events_by_number: events_by_number) } safe_join(icons).presence end |
#show_delivery_pre_pack_option(delivery) ⇒ Object
217 218 219 |
# File 'app/helpers/deliveries_helper.rb', line 217 def show_delivery_pre_pack_option(delivery) !delivery.pre_pack? && delivery.resource&.can_request_estimated_packaging? && delivery.can_request_estimated_packaging? && !delivery.has_dropship_items? # don't allow pre-pack on custom or dropship items end |
#sww_badge ⇒ String
Get a badge for Walmart SWW carrier type
Can be used inline in any view to identify Walmart rates
394 395 396 |
# File 'app/helpers/deliveries_helper.rb', line 394 def sww_badge content_tag(:span, 'Ship with Walmart', class: 'badge bg-primary', title: 'Discounted shipping rate from Walmart marketplace') end |