Class: SpeedeeManifestShipment

Inherits:
ApplicationRecord show all
Defined in:
app/models/speedee_manifest_shipment.rb

Overview

== Schema Information

Table name: speedee_manifest_shipments
Database name: primary

id :integer not null, primary key
aod :boolean default(FALSE)
aod_code :integer
apply_package_handling :boolean default(FALSE)
barcode :string not null
bill_to_shipper_number :string default("029692"), not null
cod :boolean default(FALSE)
cod_no_check :boolean default(FALSE)
cod_value :float default(0.0)
declared_value :float default(0.0)
file_version_number :string default("1"), not null
hazardous :boolean default(FALSE)
height :integer
length :integer
oversized :boolean default(FALSE)
package_handling_amount :float default(0.0)
pickup_tag :boolean default(FALSE)
reference_1 :string
reference_2 :string
reference_3 :string
reference_4 :string
ship_date :date not null
ship_from_city :string default("Lake Zurich"), not null
ship_from_company_name :string default("WarmlyYours US Warehouse"), not null
ship_from_contact_name :string default("Shipping Department")
ship_from_country :string default("US")
ship_from_email :string default("warehouseusa@warmlyyours.com")
ship_from_phone :string default("8008755285")
ship_from_shipper_number :string default("001234"), not null
ship_from_state :string default("IL"), not null
ship_from_street_1 :string default("590 Telser Rd"), not null
ship_from_street_2 :string default("Suite B")
ship_from_zip :string default("60047"), not null
ship_to_city :string not null
ship_to_company_name :string not null
ship_to_contact_name :string
ship_to_country :string
ship_to_email :string
ship_to_phone :string
ship_to_shipper_number :string
ship_to_state :string not null
ship_to_street_1 :string not null
ship_to_street_2 :string
ship_to_zip :string not null
weight :integer not null
width :integer
created_at :datetime not null
updated_at :datetime not null
ship_to_company_id :string
shipment_id :integer not null
speedee_manifest_id :integer

Indexes

index_speedee_manifest_shipments_on_aod (aod)
index_speedee_manifest_shipments_on_aod_code (aod_code)
index_speedee_manifest_shipments_on_apply_package_handling (apply_package_handling)
index_speedee_manifest_shipments_on_barcode (barcode)
index_speedee_manifest_shipments_on_bill_to_shipper_number (bill_to_shipper_number)
index_speedee_manifest_shipments_on_cod (cod)
index_speedee_manifest_shipments_on_cod_no_check (cod_no_check)
index_speedee_manifest_shipments_on_file_version_number (file_version_number)
index_speedee_manifest_shipments_on_hazardous (hazardous)
index_speedee_manifest_shipments_on_oversized (oversized)
index_speedee_manifest_shipments_on_pickup_tag (pickup_tag)
index_speedee_manifest_shipments_on_ship_date (ship_date)
index_speedee_manifest_shipments_on_ship_from_city (ship_from_city)
index_speedee_manifest_shipments_on_ship_from_shipper_number (ship_from_shipper_number)
index_speedee_manifest_shipments_on_ship_from_state (ship_from_state)
index_speedee_manifest_shipments_on_ship_from_zip (ship_from_zip)
index_speedee_manifest_shipments_on_ship_to_city (ship_to_city)
index_speedee_manifest_shipments_on_ship_to_state (ship_to_state)
index_speedee_manifest_shipments_on_ship_to_zip (ship_to_zip)
index_speedee_manifest_shipments_on_shipment_id (shipment_id)
speedee_manifest_id_aod (speedee_manifest_id,aod)
speedee_manifest_id_cod (speedee_manifest_id,cod)
speedee_manifest_id_dv (speedee_manifest_id,declared_value)
speedee_manifest_id_hazardous (speedee_manifest_id,hazardous)
speedee_manifest_id_oversized (speedee_manifest_id,oversized)
speedee_manifest_id_pickup_tag (speedee_manifest_id,pickup_tag)
speedee_manifest_id_ship_from_zip (speedee_manifest_id,ship_from_zip)

Constant Summary collapse

METRO_ZIPS =
%w[
  55050 55055 55075 55101 55102 55103 55104 55105 55106 55107 55108 55109 55110 55111 55112 55113 55114 55115 55116 55117 55118 55119 55120 55121 55122 55123 55125 55126 55127 55128 55129 55144 55145 55146 55150 55155 55161 55164 55165 55166 55168 55169 55170 55172 55175 55305 55306 55311 55317 55318 55337 55343 55344 55345 55346 55347 55369 55378 55379 55391 55401 55402 55403 55404 55405 55406 55407 55408 55409 55410 55411 55412 55413 55414 55415 55416 55417 55418 55419 55420 55421 55422 55423 55424 55425 55426 55427 55428 55429 55430 55431 55432 55433 55434 55435 55436 55437 55438 55439 55440 55441 55442 55443 55444 55445 55446 55447 55448 55449 55450 55454 55455 55458 55459 55470 55474 55478 55479 55480 55483 55484 55485 55486 55487 55488 56301 56302 56303 56304 56377 56379 56387
].freeze
CSV_HEADER_FIELD_MAPPING =
{
  file_version_number: 'File Version Number',
  ship_from_shipper_number: 'Ship From Shipper Number',
  ship_from_company_name: 'Ship From Name',
  ship_from_contact_name: 'Ship From Attention',
  ship_from_street_1: 'Ship From Address 1',
  ship_from_street_2: 'Ship From Address 2',
  ship_from_city: 'Ship From City',
  ship_from_state: 'Ship From State',
  ship_from_zip: 'Ship From Zip',
  ship_from_country: 'Ship From Country',
  ship_from_email: 'Ship From Email',
  ship_from_phone: 'Ship From Phone',
  ship_to_company_id: 'Ship To Import Field',
  ship_to_shipper_number: 'Ship To Shipper Number',
  ship_to_company_name: 'Ship To Name',
  ship_to_contact_name: 'Ship To Attention',
  ship_to_street_1: 'Ship To Address 1',
  ship_to_street_2: 'Ship To Address 2',
  ship_to_city: 'Ship To City',
  ship_to_state: 'Ship To State',
  ship_to_zip: 'Ship To Zip',
  ship_to_country: 'Ship To Country',
  ship_to_email: 'Ship To Email',
  ship_to_phone: 'Ship To Phone',
  reference_1: 'Reference 1',
  reference_2: 'Reference 2',
  reference_3: 'Reference 3',
  reference_4: 'Reference 4',
  weight: 'Weight',
  length: 'Length',
  width: 'Width',
  height: 'Height',
  barcode: 'Barcode',
  oversized: 'Oversized',
  pickup_tag: 'PickupTag',
  hazardous: 'Hazardous',
  aod: 'AOD',
  aod_code: 'AOD Option',
  cod: 'COD',
  cod_no_check: 'COD Option',
  cod_value: 'COD Value',
  declared_value: 'Declared Value',
  package_handling_amount: 'Package Handling',
  apply_package_handling: 'Apply Package Handling',
  ship_date: 'Ship Date',
  bill_to_shipper_number: 'Bill To Shipper Number'
}

Belongs to collapse

Delegated Instance Attributes collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Class Method Details

.create_entries_from_shipments_and_transmit_csv(shipments) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'app/models/speedee_manifest_shipment.rb', line 167

def self.create_entries_from_shipments_and_transmit_csv(shipments)
  success = false
  message = ''
  speedee_manifest = nil
  ship_datetime = Time.current
  SpeedeeManifestShipment.transaction do
    if shipments.count > 0
      begin
        SpeedeeManifestShipment.ready_to_add_to_manifest.destroy_all # here we start fresh
        shipments.sort_by { |s| s.id }.each do |shipment|
          order = shipment.delivery.order
          ship_to_attributes = order.ship_to_attributes
          value = shipment.compute_shipment_declared_value
          declared_value = value > Shipping::SpeedeeDelivery::DECLARED_VALUE_MIN ? [value, Shipping::SpeedeeDelivery::DECLARED_VALUE_MAX].min : 0.0
          SpeedeeManifestShipment.create!({
                                            ship_from_shipper_number: Heatwave::Configuration.fetch(:speedee_delivery_account_number),
                                            ship_to_company_name: ship_to_attributes[:name],
                                            ship_to_contact_name: ship_to_attributes[:attention_name],
                                            ship_to_street_1: ship_to_attributes[:address].street1,
                                            ship_to_street_2: ship_to_attributes[:address].street2,
                                            ship_to_city: ship_to_attributes[:address].city,
                                            ship_to_state: ship_to_attributes[:address].state_code,
                                            ship_to_zip: ship_to_attributes[:address].zip_5,
                                            ship_to_country: ship_to_attributes[:address].country.iso,
                                            ship_to_email: ship_to_attributes[:email],
                                            ship_to_phone: PhoneNumber.parse_and_format(ship_to_attributes[:phone], display_format: :strict_10),
                                            reference_1: order.reference_number,
                                            reference_2: order.po_number,
                                            weight: shipment.weight.ceil,
                                            length: shipment.length.ceil,
                                            width: shipment.width.ceil,
                                            height: shipment.height.ceil,
                                            barcode: shipment.tracking_number,
                                            oversized: shipment.is_speedee_oversize?,
                                            aod: shipment.delivery.signature_confirmation,
                                            aod_code: shipment.delivery.signature_confirmation ? 3 : nil, # here we only do AOD Direct option, which is code 3
                                            declared_value: declared_value.round(2),
                                            ship_date: ship_datetime.to_date,
                                            bill_to_shipper_number: Heatwave::Configuration.fetch(:speedee_delivery_account_number),
                                            shipment_id: shipment.id
                                          })
        end
        # now generate CSV and transmit via FTP from SpeedeeManifestShipment.ready_to_add_to_manifest
        if SpeedeeManifestShipment.ready_to_add_to_manifest.count == shipments.count
          # The file naming format is as follows: XXXXXX.YYYYMMDDHHMM
          # XXXXXX = 6 digit Shipper number YYYY = 4 digit Year
          # MM = 2 digit Month
          # DD = 2 digit Day
          # HH = 2 digit Hour
          # MM = 2 digit Minute
          # (or 4 unique digits after ‘Day’)
          csv_filename = "#{Heatwave::Configuration.fetch(:speedee_delivery_account_number)}.#{ship_datetime.strftime('%Y%m%d%H%M%S')}.CSV"
          csv_attributes = SpeedeeManifestShipment.new.attributes.keys.map { |k| k.to_sym }.reject { |k| %i[id shipment_id speedee_manifest_id created_at updated_at].include?(k) }
          speedeed_format_csv_header_attributes = csv_attributes.map { |k| CSV_HEADER_FIELD_MAPPING[k] }
          csv_string = CSV.generate(headers: false) do |csv|
            SpeedeeManifestShipment.ready_to_add_to_manifest.each do |sms|
              csv << csv_attributes.map { |k| sms.send(k) }
            end
          end
          # get a file ready, the 'data' directory has already been added in Rails.root
          csv_filepath = Rails.root.join('data', csv_filename).to_s
          File.open(csv_filepath, 'w') do |f|
            f.write(csv_string)
            f.flush
            f.fsync
          end
          if Rails.env.production?
            speedee_delivery_ftp_hsh = Heatwave::Configuration.fetch(:speedee_delivery_ftp)
            remote_path = '/IN'
            # Use feed FTP transmitter
            transmitter = Feed::TransmitFtp.new(
              logger: Rails.logger,
              hostname: speedee_delivery_ftp_hsh[:hostname],
              ftp_passive: true,
              username: speedee_delivery_ftp_hsh[:username],
              password: speedee_delivery_ftp_hsh[:password],
              remote_directory: remote_path
            )
            Rails.logger.info "Sending speedee manifest csv file #{csv_filepath} to #{remote_path} using transporter profile #{speedee_delivery_ftp_hsh}"
            res = transmitter.process(csv_filepath)
            success = res.transmitted?
          else
            success = true
          end
          if success
            speedee_manifest = SpeedeeManifest.create!(transmitted_at: ship_datetime, filename: csv_filename)
            speedee_manifest.upload_manifest_csv(csv_filepath)
            SpeedeeManifestShipment.ready_to_add_to_manifest.update_all(speedee_manifest_id: speedee_manifest.id)
            SpeedeeManifestShipment.ready_to_add_to_manifest.group_by { |sms| sms.delivery }.keys.each do |d|
              d.manifest_completed!
            end
          end
        else
          message = "Number of speedee manifest shipments (#{SpeedeeManifestShipment.ready_to_add_to_manifest.count}) do not match number of shipments for deliveries in pending manifest completion (#{shipments.count})"
        end
      rescue StandardError => e
        success = false
        message = e.to_s
        ErrorReporting.error(e)
      end
    else
      message = 'No additional shipments for deliveries in pending manifest completion to manifest!'
    end
  end
  { success:, speedee_manifest:, message: }
end

.metroActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are metro. Active Record Scope

Returns:

See Also:



98
99
100
# File 'app/models/speedee_manifest_shipment.rb', line 98

scope :metro, -> {
  where('speedee_manifest_shipments.ship_from_zip IN (?) AND speedee_manifest_shipments.ship_to_zip IN (?)', METRO_ZIPS.join(','), METRO_ZIPS.join(','))
}

.ready_to_add_to_manifestActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are ready to add to manifest. Active Record Scope

Returns:

See Also:



96
# File 'app/models/speedee_manifest_shipment.rb', line 96

scope :ready_to_add_to_manifest, -> { joins(shipment: :delivery).merge(Delivery.pending_manifest_completion) }

.regularActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are regular. Active Record Scope

Returns:

See Also:



97
# File 'app/models/speedee_manifest_shipment.rb', line 97

scope :regular, -> { where('1=1') }

.weightActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are weight. Active Record Scope

Returns:

See Also:



101
# File 'app/models/speedee_manifest_shipment.rb', line 101

scope :weight, -> { where('1=0') }

.with_aodActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with aod. Active Record Scope

Returns:

See Also:



106
# File 'app/models/speedee_manifest_shipment.rb', line 106

scope :with_aod, -> { where(aod: true) }

.with_codActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with cod. Active Record Scope

Returns:

See Also:



105
# File 'app/models/speedee_manifest_shipment.rb', line 105

scope :with_cod, -> { where(cod: true) }

.with_declared_valueActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with declared value. Active Record Scope

Returns:

See Also:



103
# File 'app/models/speedee_manifest_shipment.rb', line 103

scope :with_declared_value, -> { where('speedee_manifest_shipments.declared_value > 0.0') }

.with_hazardousActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with hazardous. Active Record Scope

Returns:

See Also:



107
# File 'app/models/speedee_manifest_shipment.rb', line 107

scope :with_hazardous, -> { where(hazardous: true) }

.with_oversizedActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with oversized. Active Record Scope

Returns:

See Also:



108
# File 'app/models/speedee_manifest_shipment.rb', line 108

scope :with_oversized, -> { where(oversized: true) }

.with_pickup_tagActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with pickup tag. Active Record Scope

Returns:

See Also:



104
# File 'app/models/speedee_manifest_shipment.rb', line 104

scope :with_pickup_tag, -> { where(pickup_tag: true) }

.with_shipment_codActiveRecord::Relation<SpeedeeManifestShipment>

A relation of SpeedeeManifestShipments that are with shipment cod. Active Record Scope

Returns:

See Also:



109
# File 'app/models/speedee_manifest_shipment.rb', line 109

scope :with_shipment_cod, -> { where('1=0') }

Instance Method Details

#deliveryObject

Alias for Shipment#delivery

Returns:

  • (Object)

    Shipment#delivery

See Also:



111
# File 'app/models/speedee_manifest_shipment.rb', line 111

delegate :delivery, to: :shipment

#mark_delivery_as_manifested!Object



163
164
165
# File 'app/models/speedee_manifest_shipment.rb', line 163

def mark_delivery_as_manifested!
  delivery.manifest_completed!
end

#orderObject

Alias for Shipment#order

Returns:

  • (Object)

    Shipment#order

See Also:



112
# File 'app/models/speedee_manifest_shipment.rb', line 112

delegate :order, to: :shipment

#shipmentShipment

Returns:

See Also:



89
# File 'app/models/speedee_manifest_shipment.rb', line 89

belongs_to :shipment, optional: true

#speed_manifestSpeedManifest

Returns:

  • (SpeedManifest)

See Also:



90
# File 'app/models/speedee_manifest_shipment.rb', line 90

belongs_to :speed_manifest, optional: true