Class: Shipping::DeliveryMd5Extractor
- Inherits:
-
BaseService
- Object
- BaseService
- Shipping::DeliveryMd5Extractor
- Defined in:
- app/services/shipping/delivery_md5_extractor.rb
Overview
Takes a delivery, review line items and shipment contents
and create or update records in the Packings table
returns a result object with the packings created if any
Defined Under Namespace
Classes: Result
Instance Attribute Summary collapse
-
#ignore_timestamp ⇒ Object
readonly
Returns the value of attribute ignore_timestamp.
Instance Method Summary collapse
-
#initialize(options = {}) ⇒ DeliveryMd5Extractor
constructor
A new instance of DeliveryMd5Extractor.
- #process(delivery) ⇒ Object
Methods inherited from BaseService
#log_debug, #log_error, #log_info, #log_warning, #logger, #options, #tagged_logger
Constructor Details
#initialize(options = {}) ⇒ DeliveryMd5Extractor
Returns a new instance of DeliveryMd5Extractor.
17 18 19 20 21 |
# File 'app/services/shipping/delivery_md5_extractor.rb', line 17 def initialize(={}) @ignore_timestamp = .delete(:ignore_timestamp).to_b @origin = .delete(:origin) super end |
Instance Attribute Details
#ignore_timestamp ⇒ Object (readonly)
Returns the value of attribute ignore_timestamp.
15 16 17 |
# File 'app/services/shipping/delivery_md5_extractor.rb', line 15 def @ignore_timestamp end |
Instance Method Details
#process(delivery) ⇒ Object
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'app/services/shipping/delivery_md5_extractor.rb', line 23 def process(delivery) result = Result.new(status: :empty) return result unless delivery.has_valid_shipments? && delivery.line_items.goods.present? logger.tagged("Delivery:#{delivery.id}") do shipments = delivery.shipments.packed_or_measured.includes(shipment_contents: :line_item).select(&:has_dimensions?) # Load up the goods in the delivery item_hash = delivery.packable_item_hash # Run these line items through our md5 hasher md5_result = Shipping::Md5HashItem.process(item_hash) logger.info "delivery md5: #{md5_result.md5}, item string: #{md5_result.items_string}" # Store in delivery model (for backward compatibility) delivery.update_column(:packaged_items_md5_hash, md5_result.md5) result.delivery_md5 = md5_result.md5 # Create a packing for the entire delivery and all contents logger.info "Storing completed delivery to packing model: #{md5_result.md5}" # We record packing different for parcel vs ltl service_type = Packing.service_types[(delivery.ltl_freight? ? :freight_service : :parcel_service)] packing = Packing.where(md5: md5_result.md5, service_type: service_type).first_or_initialize # Skip when a newer *delivery-sourced* packing already exists. # A from_calculator packing is just estimated dims from quoting — real # delivery/manual-entry data must always overwrite it. skip_packing_storage = packing.persisted? && ! && packing.created_at && packing.created_at > delivery.created_at && packing.origin != 'from_calculator' # canadian skip! we will only take canadian package data if nothing exists origin_country = delivery.origin_address&.country_iso3 canadian_skip = origin_country == 'CAN' && packing.persisted? if skip_packing_storage result. = warn_msg = "Newer Packing data already available. Existing packing #{packing.id}/#{packing.created_at} > delivery #{delivery.id}/#{delivery.created_at}, skip saving" logger.warn warn_msg result.status = :warning return result elsif canadian_skip result. = warn_msg = "Packing data already exists and since delivery is from canada we are going to ignore it" logger.warn warn_msg result.status = :warning return result else # Map all our packed_or_measured shipments to pack dimensions packing.packdims = shipments.map(&:to_packdims).sort # Create a link to the delivery packing.delivery = delivery packing.origin = @origin || :from_delivery # Store the line items and quantities this md5 represents packing.contents = md5_result.full_item_id_hash # Packing creation date is same as delivery packing.created_at = delivery.created_at if packing.save # No duplicates of item ids by using union packing.item_ids |= md5_result.kit_item_ids # This allows us to search kit parents in the future result.packings << packing # Now see if we can also create/update a packing of relevant items, that is when md5 is not equal to relevant_md5 relevent_items_packing = nil if md5_result.relevant_md5 != md5_result.md5 # Now also find or create a packing of the relevant item md5 relevent_items_packing = Packing.where(md5: md5_result.relevant_md5, service_type: service_type).first_or_initialize relevent_items_packing.packdims = shipments.map(&:to_packdims).sort # Create a link to the delivery relevent_items_packing.delivery = delivery relevent_items_packing.origin = @origin || :from_delivery # Store the line items and quantities this md5 represents relevent_items_packing.contents = md5_result.relevant_full_item_id_hash # Packing creation date is same as delivery relevent_items_packing.created_at = delivery.created_at # No duplicates of item ids by using union relevent_items_packing.item_ids |= md5_result.relevant_kit_item_ids # This allows us to search kit parents in the future if relevent_items_packing.save && packing.update(relevant_md5: relevent_items_packing.md5) result.packings << relevent_items_packing else result. = err_msg = "Ooops, could not save packing or relevent_items_packing: #{packing.errors_to_s}, #{relevent_items_packing.errors_to_s}" logger.error result.status = :error return result end end result.status = :success else result. = err_msg = "Ooops, could not save packing: #{packing.errors_to_s}" logger.error result.status = :error return result end end # Are all our shipment contents defined? in that case we can also # record the md5 of individual shipments for their content in the packdim_contents defined_shipments = shipments.select{|s| s.shipment_contents.present? } if defined_shipments.present? && defined_shipments.length == shipments.length packdim_contents = [] relevant_items_packdim_contents = [] defined_shipments.each do |shp| # Extract the line items contained in this shipment shipment_item_hash = shp.shipment_contents.includes(line_item: :item).each_with_object({}) do |sc, hsh| item = sc.line_item.item hsh[item] ||= 0 hsh[item] += sc.quantity.abs end # Run those through our trusty md5 extractor (which looks at item kits as well) shp_md5_result = Shipping::Md5HashItem.process(shipment_item_hash) shp_md5 = shp_md5_result.md5 logger.info "Multi shipments delivery with content defined, storing shipment id #{shp.id} to packing with: #{shp_md5}" packdim_contents.concat(Packing.format_packdim_contents(md5: shp_md5_result.md5, contents: shp_md5_result.full_item_id_hash, packdims: shp.to_packdims)) relevant_items_packdim_contents.concat(Packing.format_packdim_contents(md5: shp_md5_result.relevant_md5, contents: shp_md5_result.relevant_full_item_id_hash, packdims: shp.to_packdims)) if relevent_items_packing.present? end packing.update_column(:packdim_contents, packdim_contents.to_json) relevent_items_packing.update_column(:packdim_contents, relevant_items_packdim_contents.to_json) if relevent_items_packing.present? else packing.update_column(:packdim_contents, {}.to_json) relevent_items_packing.update_column(:packdim_contents, {}.to_json) if relevent_items_packing.present? end end result end |