Class: Shipping::LtlShippingInsurance

Inherits:
BaseService show all
Defined in:
app/services/shipping/ltl_shipping_insurance.rb

Overview

Service object: ltl shipping insurance.

Defined Under Namespace

Classes: Result

Constant Summary collapse

LOADSURE_API_HASH =

Loadsurance integration is currently disabled. When re-enabled, fetch
credentials from Heatwave::Configuration.fetch(:loadsurance_api)
rather than re-introducing top-level LOADSURE_* constants.

{}.freeze
INSURED_VALUE_MIN =

Insured value min.

5000.0
INSURANCE_FEE_MAX_PERCENT =

Insurance fee max percent.

0.05
INSURANCE_FEE_MAX_AMOUNT =

Insurance fee max amount.

250.0
INSURANCE_DED_MAX_PERCENT =

Insurance ded max percent.

0.2
INSURANCE_DED_MAX_AMOUNT =

Insurance ded max amount.

1000.0
INSURANCE_FEE_MIN_AMOUNT =

Insurance fee min amount.

5.0
LOADSURANCE_CARRIER_DATA_BY_CARRIER =

here we only populate parcel carriers that we know are covered by our Shipsurance contract
we do not cover freight carriers per Shipsurance contract
see: https://shipsurance-partner-api.readme.io/reference/extcarrierid-lookup

{
  FedExFreight: {
    mode: 'ROAD',
    name: 'FedEx Freight',
    email: 'mark.lackinger@fedex.com',
    carrierId: {
      type: 'SCAC',
      value: 'FXFS'
    },
    phone: '+12242422831',
    address: {
      address1: '5600 9TH ST',
      city: 'Zion',
      state: 'IL',
      postal: '60099',
      country: 'US'
    }
  },
  Freightquote: {
    mode: 'ROAD',
    name: 'Freightquote.com Inc',
    email: 'brian.dougherty@freightquote.com',
    carrierId: {
      type: 'SCAC',
      value: 'FQCI'
    },
    phone: '+18169496250',
    address: {
      address1: '901 West Carondelet Drive',
      city: 'Kansas City',
      state: 'MO',
      postal: '64114',
      country: 'US'
    }
  },
  RlCarriers: {
    mode: 'ROAD',
    name: 'R&L Carriers',
    email: 'scott.brighton@rlcarriers.com',
    carrierId: {
      type: 'SCAC',
      value: 'RLCA'
    },
    phone: '+18476953100',
    address: {
      address1: '375 Second Street',
      city: 'Elgin',
      state: 'IL',
      postal: '60123',
      country: 'US'
    }
  },
  ShipengineRoadrunner: {
    mode: 'ROAD',
    name: 'Roadrunner Freight',
    email: 'robert.provost@rrts.com',
    carrierId: {
      type: 'SCAC',
      value: 'RDFS'
    },
    phone: '+18478007768',
    address: {
      address1: '4801 68th Avenue',
      city: 'Kenosha',
      state: 'WI',
      postal: '53144',
      country: 'US'
    }
  },
  ShipengineSaia: {
    mode: 'ROAD',
    name: 'Saia LTL Freight',
    email: 'ssanti@saia.com',
    carrierId: {
      type: 'SCAC',
      value: 'SAIA'
    },
    phone: '+18474716588',
    address: {
      address1: '2260 Midlothian Road',
      city: 'Grayslake',
      state: 'IL',
      postal: '60030',
      country: 'US'
    }
  }
}.then do |h|
  # Legacy carrier-string aliases for historical shipments.carrier rows
  # (Freightquote-brokered Saia/Roadrunner from before the direct
  # ShipEngine LTL integration). Kept so label regen / insurance lookups
  # by old `delivery.carrier` strings still resolve. Loadsurance
  # integration is currently disabled, so this is defensive only.
  h.merge(Saia: h[:ShipengineSaia], Roadrunner: h[:ShipengineRoadrunner]).freeze
end
COVERAGE_LIMIT =

Limit for coverage.

25_000.0
LTL_SELF_INSURED =

Per Christian Billen and Venu Adepu (1/30/2025): WarmlyYours self-insures all LTL freight
after 25+ years of zero claims or losses. When true this constant drives:

  1. qualifies_for_rating? → false (hides Shipsurance/Loadsure UI section)
  2. do_not_ship_insure_via_carrier? → true (zeros carrier declared value)
  3. shipengine_ltl_base insured_value hardcoded to 0.0
    Cross-border customs/commercial invoice values (calculate_declared_value,
    unit_value_for_commercial_invoice) are NOT affected — those are separate concerns.
true

Instance Attribute Summary

Attributes inherited from BaseService

#options

Instance Method Summary collapse

Methods inherited from BaseService

#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger

Constructor Details

This class inherits a constructor from BaseService

Instance Method Details

#bill_shipping_to_customer_and_not_a_store_transfer?(delivery) ⇒ Boolean

Returns:

  • (Boolean)


163
164
165
166
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 163

def bill_shipping_to_customer_and_not_a_store_transfer?(delivery)
  # if billing to customer, let them pay for declared value via carrier
  delivery.bill_shipping_to_customer && !delivery.order&.is_store_transfer? # this is to be readable to me, a human
end

#book_shipping_insurance_for_delivery(delivery, _options) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 211

def book_shipping_insurance_for_delivery(delivery, _options)
  status = :ok
  status_message = ''
  insurance_result_hash = {}

  quote_hash = HTTP.use(logging: { logger: Rails.logger }).timeout(60).auth("Bearer #{LOADSURE_API_HASH[:token]}").post("#{LOADSURE_API_HASH[:base_url]}/quote", json: quote_data(delivery)).parse.with_indifferent_access
  if quote_hash[:success] == false
    msgs = (quote_hash[:errors] || []).map { |e| e.dig(:message) }
    status = :error
    status_message = msgs.join('. ')
  else
    quote_cost = quote_hash.dig(:insuranceProduct, :premium).to_f + quote_hash.dig(:insuranceProduct, :serviceFee).to_f
    quote_deductible = quote_hash.dig(:insuranceProduct, :deductible).to_f
    threshhold_exceeded_hash = insurance_quote_exceeds_thresholds?(quote_cost, apply_carrier_coverage_limit(delivery), quote_deductible)
    quote_token = quote_hash.dig(:quoteToken)
    if threshhold_exceeded_hash[:status] != :ok
      status = threshhold_exceeded_hash[:status]
      status_message = threshhold_exceeded_hash[:status_message]
    elsif quote_token.present?
      insurance_result_hash = HTTP.use(logging: { logger: Rails.logger }).timeout(60).auth("Bearer #{LOADSURE_API_HASH[:token]}").post("#{LOADSURE_API_HASH[:base_url]}/purchaseQuote",
                                                                                                                                       json: { quoteToken: quote_token,
                                                                                                                                               additionalAuthorizedUsers: [LOADSURE_API_HASH[:additional_user_id]] }).parse.with_indifferent_access
      if insurance_result_hash[:error].present?
        status = :error
        status_message = insurance_result_hash[:error]
      end
    end
  end

  delivery.shipments.update_all(shipping_insurance_data: { shipping_insurance_record_id: insurance_result_hash[:certificateNumber] }.merge(insurance_result_hash)) if status == :ok
  Result.new(status: status, status_message: status_message)
end

#carrier_present?(carrier) ⇒ Boolean

Returns:

  • (Boolean)


173
174
175
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 173

def carrier_present?(carrier)
  LOADSURANCE_CARRIER_DATA_BY_CARRIER[(carrier || 'none').to_sym].present?
end

#carrier_qualifies_for_rating?(carrier) ⇒ Boolean

Returns:

  • (Boolean)


181
182
183
184
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 181

def carrier_qualifies_for_rating?(carrier)
  # here we want to return a simple TRUE/FALSE boolean, this is to see if we can use this
  carrier_present?(carrier)
end

#cross_border_fedex_freight?(delivery) ⇒ Boolean

Returns:

  • (Boolean)


168
169
170
171
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 168

def cross_border_fedex_freight?(delivery)
  # we do not ship insure cross border FedEx Freight via Loadsurance because we need to pass declared value
  delivery.carrier == 'FedExFreight' && delivery.is_cross_border? # this is to be readable to me, a human
end

#delivery_carrier_present?(delivery) ⇒ Boolean

Returns:

  • (Boolean)


177
178
179
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 177

def delivery_carrier_present?(delivery)
  carrier_present?(delivery.carrier)
end

#get_shipping_insurance_cost_for_delivery(delivery) ⇒ Object



259
260
261
262
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 259

def get_shipping_insurance_cost_for_delivery(delivery)
  delivery.shipments.first&.shipping_insurance_data&.dig('premium').to_f
  # cost = delivery.shipments.where("carrier IS NOT NULL").sum{|s| get_shipping_insurance_cost_for_shipment(s)}
end

#get_shipping_insurance_cost_for_shipment(shipment) ⇒ Object



264
265
266
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 264

def get_shipping_insurance_cost_for_shipment(shipment)
  (get_shipping_insurance_cost_for_delivery(shipment.delivery) / [shipment.delivery.shipments.size, 1].max).round(2)
end

#get_shipping_insurance_insured_value_for_delivery(delivery) ⇒ Object



268
269
270
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 268

def get_shipping_insurance_insured_value_for_delivery(delivery)
  delivery.calculate_declared_value.to_f.abs
end

#get_shipping_insurance_insured_value_for_shipment(shipment) ⇒ Object



272
273
274
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 272

def get_shipping_insurance_insured_value_for_shipment(shipment)
  (shipment.delivery.calculate_declared_value.to_f.abs / [shipment.delivery.shipments.size, 1].max).round(2)
end


276
277
278
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 276

def get_shipping_insurance_link_for_shipment(shipment)
  %(<a href='https://portal.loadsure.net/certificates/details/?certificateNumber=#{shipment.shipping_insurance_record_id}' target='_blank' rel='noopener'>#{shipment.shipping_insurance_record_id}</a> <small>(file claim <a href='https://portal.loadsure.net/claims/file?id=#{shipment.shipping_insurance_record_id}' target='_blank' rel='noopener' onclick='return confirm("Are you sure you want to file a claim?")'>here</a>)</small>).html_safe
end

#process(delivery, _options = {}) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 138

def process(delivery, _options = {})
  status = :ok
  status_message = 'WarmlyYours Self Insures all LTL Shipping'
  qualifies(delivery)
  # 03/18/24 Here we have decided per Venu and Christian to discontinue our Shipping Insurance with Loadsure, and self-insure after seeing no record of any claims or losses for LTL shipments in our history.
  # So we want to qualify all LTL shipments i.e. return TRUE, so we don't pass declared value to the LTL carriers, but then do nothing when it is ship insurance time
  # if qualifies_res.status == :ok
  #   r = book_shipping_insurance_for_delivery(delivery, options)
  #   unless r.status == :ok
  #     status = :error
  #     status_message = "Shipping insurance for delivery #{delivery.name} cannot be booked: #{r.status_message}"
  #   end
  # else
  #   status = qualifies_res.status
  #   status_message = qualifies_res.status_message
  # end
  Result.new(status: status, status_message: status_message)
end

#qualifies(_delivery) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 186

def qualifies(_delivery)
  # status = :ok
  # status_message = ''
  # any_labeled_shipments = delivery.shipments.label_complete.any?
  # all_labeled_shipments_have_tracking_number = delivery.shipments.label_complete.all?{|s| s.tracking_number.present?}
  # unless qualifies_for_rating?(delivery) && any_labeled_shipments && all_labeled_shipments_have_tracking_number
  #   status = :error
  #   status_message_arr = []
  #   status_message_arr << "Order #{delivery.order&.reference_number} does not qualify for Loadsurance shipping insurance"
  #   status_message_arr << "Carrier #{delivery.carrier} is not one of our covered Loadsurance carriers" if !delivery_carrier_present?(delivery)
  #   status_message_arr << "When customer pays for shipping we do not ship insure via Loadsurance" if bill_shipping_to_customer_and_not_a_store_transfer?(delivery)
  #   status_message_arr << "When delivery value is less than $#{INSURED_VALUE_MIN.round(2)} we do not ship insure via Loadsurance" if delivery.calculate_declared_value.to_f.abs < INSURED_VALUE_MIN
  #   status_message_arr << "When delivery is FedExFreight cross-border, we do not ship insure via Loadsurance" if cross_border_fedex_freight?(delivery)
  #   status_message_arr << "Delivery does not have any labeled shipments" if !any_labeled_shipments
  #   status_message_arr << "Not all shipments have tracking numbers" if !all_labeled_shipments_have_tracking_number
  #   status_message = "#{status_message_arr.join('. ')}."
  # end
  ############################################################################
  # Note that we are disabling LTL shipping insurance for all deliveries based on price increases, lack of claims and an executive decision by Christian Billen and Venu Adepu on 1/30/2025
  ############################################################################
  status = :error
  status_message = 'LTL shipping insurance is now disabled.'
  Result.new(status: status, status_message: status_message)
end

#qualifies_for_rating?(delivery) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
160
161
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 157

def qualifies_for_rating?(delivery)
  return false if LTL_SELF_INSURED

  delivery.supported_shipping_carrier? && delivery_carrier_present?(delivery) && (delivery.calculate_declared_value.to_f.abs > INSURED_VALUE_MIN) && !cross_border_fedex_freight?(delivery) && !bill_shipping_to_customer_and_not_a_store_transfer?(delivery)
end

#void_shipping_insurance_for_delivery(delivery) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'app/services/shipping/ltl_shipping_insurance.rb', line 244

def void_shipping_insurance_for_delivery(delivery)
  status = :ok
  status_message = ''

  void_result_hash = HTTP.use(logging: { logger: Rails.logger }).timeout(60).auth("Bearer #{LOADSURE_API_HASH[:token]}").post("#{LOADSURE_API_HASH[:base_url]}/cancelCertificate", json: void_data(delivery)).parse.with_indifferent_access
  if void_result_hash[:success] == false
    msgs = (void_result_hash[:errors] || []).map { |e| e.dig(:message) }
    status = :error
    status_message = msgs.join('. ')
  end

  delivery.shipments.update_all(shipping_insurance_data: {}.merge(void_result_hash)) if status == :ok
  Result.new(status: status, status_message: status_message)
end