Class: MailActivity
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- MailActivity
- Includes:
- Models::Auditable
- Defined in:
- app/models/mail_activity.rb
Overview
== Schema Information
Table name: mail_activities
Database name: primary
id :integer not null, primary key
actual_shipping_cost :decimal(, )
postage_rates :hstore is an Array
service_code :string
state :string
activity_id :integer
address_id :integer
mailing_id :integer
Indexes
index_mail_activities_on_activity_id (activity_id)
index_mail_activities_on_address_id (address_id)
index_mail_activities_on_mailing_id (mailing_id)
index_mail_activities_on_state (state)
Foreign Keys
fk_rails_... (activity_id => activities.id) ON DELETE => cascade
fk_rails_... (address_id => addresses.id)
fk_rails_... (mailing_id => mailings.id)
Constant Summary
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Belongs to collapse
Methods included from Models::Auditable
Has many collapse
-
#shipments ⇒ ActiveRecord::Relation<Shipment>
belongs_to :address, optional: true.
- #uploads ⇒ ActiveRecord::Relation<Upload>
Class Method Summary collapse
-
.complete ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are complete.
-
.open ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are open.
-
.packaged ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are packaged.
-
.postage_labeled ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are postage labeled.
-
.postage_rated ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are postage rated.
Instance Method Summary collapse
- #address ⇒ Object
- #all_labels_pdf ⇒ Object
- #calculate_postage_rates ⇒ Object
- #carrier ⇒ Object (also: #reported_carrier)
-
#company_name ⇒ Object
Sanitized name for mailing.
-
#default_carrier ⇒ Object
The default postal carrier for the store's country (used when no rate has been selected yet).
- #formatted_address(separator: '<br>') ⇒ Object
- #generate_all_labels_pdf ⇒ Object
- #generate_labels ⇒ Object
- #manually_complete? ⇒ Boolean
- #name ⇒ Object
- #ok_to_delete? ⇒ Boolean
-
#person_name ⇒ Object
Sanitized name for mailing.
- #ready_to_complete? ⇒ Boolean
- #ready_to_label? ⇒ Boolean
- #ready_to_manually_complete? ⇒ Boolean
- #ready_to_print_labels? ⇒ Boolean
- #ready_to_print_postage_label? ⇒ Boolean
- #ready_to_rate? ⇒ Boolean
- #ready_to_reset? ⇒ Boolean
-
#selected_carrier ⇒ Object
Resolve the carrier from a composite service_code like "UPS::03" or "FedEx::FEDEX_GROUND".
-
#selected_service_code ⇒ Object
Extract the raw carrier service code from a composite service_code.
- #send_canada_post_manual_void_email(tracking_numbers) ⇒ Object
- #store ⇒ Object
- #store_country_iso3 ⇒ Object
- #void_shipments ⇒ Object
Methods included from Models::Auditable
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::EventPublishable
Class Method Details
.complete ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are complete. Active Record Scope
50 |
# File 'app/models/mail_activity.rb', line 50 scope :complete, -> { where("mail_activities.state = 'complete'") } |
.open ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are open. Active Record Scope
46 |
# File 'app/models/mail_activity.rb', line 46 scope :open, -> { where("mail_activities.state = 'open'") } |
.packaged ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are packaged. Active Record Scope
47 |
# File 'app/models/mail_activity.rb', line 47 scope :packaged, -> { where("mail_activities.state = 'packaged'") } |
.postage_labeled ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are postage labeled. Active Record Scope
49 |
# File 'app/models/mail_activity.rb', line 49 scope :postage_labeled, -> { where("mail_activities.state = 'postage_labeled'") } |
.postage_rated ⇒ ActiveRecord::Relation<MailActivity>
A relation of MailActivities that are postage rated. Active Record Scope
48 |
# File 'app/models/mail_activity.rb', line 48 scope :postage_rated, -> { where("mail_activities.state = 'postage_rated'") } |
Instance Method Details
#activity ⇒ Activity
Validations:
31 |
# File 'app/models/mail_activity.rb', line 31 belongs_to :activity, optional: true |
#address ⇒ Object
302 303 304 |
# File 'app/models/mail_activity.rb', line 302 def address activity.party.main_address end |
#all_labels_pdf ⇒ Object
286 287 288 |
# File 'app/models/mail_activity.rb', line 286 def all_labels_pdf uploads.find_by(category: 'all_labels_pdf') end |
#calculate_postage_rates ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'app/models/mail_activity.rb', line 172 def calculate_postage_rates res = WyShipping.find_mail_activity_shipping_rates(self) rate_hashes = [] rate_hashes = (res[:request_response][:rates] || []).sort_by { |r| r[:total_charges].to_f } if res[:request_response] if res[:status_code] == :ok and rate_hashes.any? self.postage_rates = rate_hashes # this will stringify the keys in the hash array self.service_code = rate_hashes.first[:service_code] if rate_hashes.any? # @mail_activity.service_code = "MediaMail" if rate_hashes.detect{|rh| rh[:service_code] == "MediaMail"} postage_rate_mail_activity! reload end res end |
#carrier ⇒ Object Also known as: reported_carrier
167 168 169 |
# File 'app/models/mail_activity.rb', line 167 def carrier selected_carrier end |
#company_name ⇒ Object
Sanitized name for mailing
92 93 94 95 96 97 98 |
# File 'app/models/mail_activity.rb', line 92 def company_name cn = activity&.party&.full_name unless activity&.party&.is_person? cn ||= address&.party&.full_name unless address&.party&.is_person? return unless cn cn.to_s.gsub(/[^0-9a-z\s]/i, '')[0..34] end |
#default_carrier ⇒ Object
The default postal carrier for the store's country (used when no rate has been selected yet)
147 148 149 |
# File 'app/models/mail_activity.rb', line 147 def default_carrier store&.country_iso3 == 'CAN' ? 'Canadapost' : 'USPS' end |
#formatted_address(separator: '<br>') ⇒ Object
296 297 298 299 300 |
# File 'app/models/mail_activity.rb', line 296 def formatted_address(separator: '<br>') return unless a = address a.full_address(true, separator, person_name) end |
#generate_all_labels_pdf ⇒ Object
248 249 250 251 252 253 254 255 256 257 258 |
# File 'app/models/mail_activity.rb', line 248 def generate_all_labels_pdf all_labels = shipments.completed.map(&:ship_label_pdf) file_name = "#{id}_all_labels_#{Time.current.strftime('%m_%d_%Y_%I_%M%p')}.pdf".downcase all_labels_path = Rails.application.config.x.temp_storage_path.join(file_name) Rails.logger.debug { "self.generate_all_labels_pdf: all_labels_path: #{all_labels_path}, all_labels: #{all_labels.inspect}" } PdfTools.combine(all_labels, output_file_path: all_labels_path) upload = Upload.uploadify(all_labels_path, 'all_labels_pdf') raise 'Combo label was not generated' unless upload uploads << upload end |
#generate_labels ⇒ 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 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 |
# File 'app/models/mail_activity.rb', line 186 def generate_labels shipping_result = WyShipping.ship_mail_activity(self) Rails.logger.info("#{Time.current}: MailActivity ID #{id}, labels generated START LOG $$$$$$$$$$$$$$$$$$$$$$$$$$$$, status_code: #{shipping_result[:status_code]}") if shipping_result[:status_code] == :error Rails.logger.info("#{carrier}, request/response:") Rails.logger.info("#{begin shipping_result[:shipment][:ship_reply_xml] rescue StandardError nil end} ") { status_code: shipping_result[:status_code], status_message: shipping_result[:status_message] } else # only save if labels successfully generated # first pass get tracking numbers and charges Rails.logger.debug("Shipping result received", mail_activity_id: id) self.actual_shipping_cost = shipping_result[:shipment][:total_charges] save # pure hacking to get this to work reload # pure hacking to get this to work shipments.awaiting_label.each_with_index do |shipment, i| ship_result_label = shipping_result.dig(:shipment,:labels,i) Rails.logger.debug "shipment: #{shipment.inspect}" Rails.logger.debug "shipping_result[:shipment][:labels][i]: #{ship_result_label.inspect}" Rails.logger.debug "shipping_result[:shipment][:labels][i][:tracking_number]: #{ship_result_label[:tracking_number] || 'not there'}" shipment.tracking_number = ship_result_label[:tracking_number] shipment.shipengine_label_id = ship_result_label[:shipengine_label_id] shipment.label_generated! end Rails.logger.info("#{Time.current}: MailActivity ID #{id}, labels generated END LOG $$$$$$$$$$$$$$$$$$$$$$$$$$$$") # save this mail_activity save # second pass generate the labels from the temporary paths label_exceptions = [] status_code = :ok shipments.label_complete.each_with_index do |shipment, i| ship_result_label = shipping_result.dig(:shipment,:labels,i) old_label_path = ship_result_label[:image]&.path # skip when label path is nil if old_label_path if shipment.generate_ship_label_pdf(old_label_path, carrier) else label_exceptions << (i + 1) end end end if label_exceptions.empty? && status_code == :ok generate_all_labels_pdf = "Labels generated for #{shipments.completed.length} packages. Actual charge: #{store.catalogs.first.currency_symbol}#{actual_shipping_cost}. #{}" save { status_code: status_code, status_message: } else msg = String.new("Can't generate labels") msg << ", there was an issue with labels #{label_exceptions.map { |l| l + 1 }.join(', ')}" if label_exceptions.any? msg << ", status code returned: #{status_code}" unless status_code == :ok msg << '.' { status_code: :error, status_message: msg } end end end |
#mailing ⇒ Mailing
Validations:
32 |
# File 'app/models/mail_activity.rb', line 32 belongs_to :mailing, optional: true |
#manually_complete? ⇒ Boolean
134 135 136 |
# File 'app/models/mail_activity.rb', line 134 def manually_complete? complete? and !ready_to_print_labels? end |
#name ⇒ Object
100 101 102 |
# File 'app/models/mail_activity.rb', line 100 def name "Mail Activity #{activity.activity_type.task_type}, ID: #{activity.id}, to: #{address.full_address(include_recipient = true, sep = ', ')}" end |
#ok_to_delete? ⇒ Boolean
290 291 292 293 294 |
# File 'app/models/mail_activity.rb', line 290 def ok_to_delete? ok = true ok = false unless open? and shipments.all? { |s| s.ok_to_delete_with_mail_activity? } ok end |
#person_name ⇒ Object
Sanitized name for mailing
83 84 85 86 87 88 89 |
# File 'app/models/mail_activity.rb', line 83 def person_name pn = activity.party.full_name if activity.party.is_person? pn ||= address.party.full_name if address.party&.is_person? return unless pn pn.to_s.gsub(/[^0-9a-z\s]/i, '')[0..34] end |
#ready_to_complete? ⇒ Boolean
122 123 124 |
# File 'app/models/mail_activity.rb', line 122 def ready_to_complete? shipments.any? { |s| s.label_complete? } end |
#ready_to_label? ⇒ Boolean
118 119 120 |
# File 'app/models/mail_activity.rb', line 118 def ready_to_label? postage_rates and postage_rates.any? and shipments.any? { |s| s.awaiting_label? } end |
#ready_to_manually_complete? ⇒ Boolean
126 127 128 |
# File 'app/models/mail_activity.rb', line 126 def ready_to_manually_complete? !shipments.any? { |s| (s.label_complete? or s.awaiting_label?) } end |
#ready_to_print_labels? ⇒ Boolean
130 131 132 |
# File 'app/models/mail_activity.rb', line 130 def ready_to_print_labels? all_labels_pdf.present? and shipments.label_complete.any? end |
#ready_to_print_postage_label? ⇒ Boolean
104 105 106 107 108 |
# File 'app/models/mail_activity.rb', line 104 def ready_to_print_postage_label? (postage_labeled? or complete?) and all_labels_pdf.present? and shipments.label_complete.any? end |
#ready_to_rate? ⇒ Boolean
114 115 116 |
# File 'app/models/mail_activity.rb', line 114 def ready_to_rate? shipments.any? { |s| s.awaiting_label? } end |
#ready_to_reset? ⇒ Boolean
110 111 112 |
# File 'app/models/mail_activity.rb', line 110 def ready_to_reset? shipments.all? { |s| s.ok_to_delete_with_mail_activity? } end |
#selected_carrier ⇒ Object
Resolve the carrier from a composite service_code like "UPS::03" or "FedEx::FEDEX_GROUND".
Falls back to the default postal carrier for legacy service codes without a prefix.
153 154 155 156 157 |
# File 'app/models/mail_activity.rb', line 153 def selected_carrier return default_carrier unless service_code&.include?('::') service_code.split('::').first end |
#selected_service_code ⇒ Object
Extract the raw carrier service code from a composite service_code.
"UPS::03" → "03", "USPS::Priority" → "Priority", "Priority" → "Priority"
161 162 163 164 165 |
# File 'app/models/mail_activity.rb', line 161 def selected_service_code return service_code unless service_code&.include?('::') service_code.split('::').last end |
#send_canada_post_manual_void_email(tracking_numbers) ⇒ Object
282 283 284 |
# File 'app/models/mail_activity.rb', line 282 def send_canada_post_manual_void_email(tracking_numbers) Mailer.canada_post_manual_void_email_for_mail_activity(self, tracking_numbers).deliver end |
#shipments ⇒ ActiveRecord::Relation<Shipment>
belongs_to :address, optional: true
34 |
# File 'app/models/mail_activity.rb', line 34 has_many :shipments, dependent: :destroy |
#store ⇒ Object
138 139 140 |
# File 'app/models/mail_activity.rb', line 138 def store @store ||= mailing.store end |
#store_country_iso3 ⇒ Object
142 143 144 |
# File 'app/models/mail_activity.rb', line 142 def store_country_iso3 store&.mailing_address&.country_iso3 end |
#uploads ⇒ ActiveRecord::Relation<Upload>
35 |
# File 'app/models/mail_activity.rb', line 35 has_many :uploads, as: :resource, dependent: :destroy |
#void_shipments ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'app/models/mail_activity.rb', line 260 def void_shipments if shipments.label_complete.any? tracking_numbers = shipments.label_complete.pluck(:tracking_number) shipping_result = {} shipping_result[:status_code] = :ok shipping_result = WyShipping.void_mail_activity(self) # going to go merrily along but send admin notification if this didn't properly void if shipping_result[:status_code] != :ok Mailer.admin_notification("mail_activity#void_shipments for mail_activity #{id} returned error shipping_result[:status_code]: #{shipping_result[:status_code]}", "mail_activity#void_shipments for mail_activity #{id} returned error shipping_result[:status_code]: #{shipping_result[:status_code]}, shipping_result[:status_message]: #{shipping_result[:status_message]}, shipment tracking numbers: #{tracking_numbers.join(', ')}").deliver_now send_canada_post_manual_void_email(tracking_numbers) if carrier == 'Canadapost' end shipments.label_complete.each(&:label_voided!) self.postage_rates = [] self.service_code = nil reset_mail_activity! { status_code: shipping_result[:status_code], status_message: "Please ensure you manually void manual shipments. Shipments voided. #{shipping_result[:status_message]}" } else { status_code: :error, status_message: "Can't void postage label(s) because the mail activity has no postage label(s)." } end end |