Class: RoomConfiguration::Copier
- Inherits:
-
Object
- Object
- RoomConfiguration::Copier
- Defined in:
- app/services/room_configuration/copier.rb
Instance Attribute Summary collapse
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#results ⇒ Object
readonly
Returns the value of attribute results.
-
#room_configurations ⇒ Object
readonly
Returns the value of attribute room_configurations.
Class Method Summary collapse
Instance Method Summary collapse
- #copy_to(opportunity) ⇒ Object
-
#initialize(room_configurations, options = {}) ⇒ Copier
constructor
A new instance of Copier.
Constructor Details
#initialize(room_configurations, options = {}) ⇒ Copier
Returns a new instance of Copier.
9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'app/services/room_configuration/copier.rb', line 9 def initialize(room_configurations, = {}) @logger = [:logger] || Rails.logger @options = @room_configurations = room_configurations.to_a @skip_room_plan_generation = [:skip_room_plan_generation] controller_rooms = @room_configurations.filter_map(&:controlled_by).uniq missing_rooms = controller_rooms - @room_configurations if missing_rooms.present? logger.info "#{missing_rooms.size} controller rooms were added" @room_configurations += missing_rooms end logger.info "#{@room_configurations.size} total rooms loaded into copier" end |
Instance Attribute Details
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
3 4 5 |
# File 'app/services/room_configuration/copier.rb', line 3 def logger @logger end |
#results ⇒ Object (readonly)
Returns the value of attribute results.
3 4 5 |
# File 'app/services/room_configuration/copier.rb', line 3 def results @results end |
#room_configurations ⇒ Object (readonly)
Returns the value of attribute room_configurations.
3 4 5 |
# File 'app/services/room_configuration/copier.rb', line 3 def room_configurations @room_configurations end |
Class Method Details
.generate_all_plans(copied_rooms) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'app/services/room_configuration/copier.rb', line 128 def self.generate_all_plans(copied_rooms) copied_rooms.each do |new_rc| # Since this non critical, we want to log errors but not explode without returning the result if Rails.env.development? new_rc.generate_all_plans else GenerateRoomPlansWorker.perform_async(new_rc.id) end rescue StandardError => e msg = "Error in room copy when generating floorplans for #{new_rc.id}, you might need to call generate_all_plans manually" logger.error msg ErrorReporting.error(e, message: msg) end end |
Instance Method Details
#copy_to(opportunity) ⇒ 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 |
# File 'app/services/room_configuration/copier.rb', line 23 def copy_to(opportunity, &) room_map = {} # old_room_id => new_room_id, this is used for the controller portion # Take each room that is not already present in the target opportunity target_rooms = @room_configurations.reject { |rc| rc.opportunity == opportunity } if (rejected_rooms = @room_configurations - target_rooms).present? logger.warn "#{rejected_rooms.map(&:reference_number).join(', ')} were rejected because they already belong in the target opportunity #{opportunity.reference_number}" end logger.error "There are no valid rooms left to copy" if target_rooms.empty? # We are going to process those that are not controlled first, since those are likely the controller # rooms and we will need their id in the room_map when we process their subordinates # We're also going to process the parent room if they're specified for the same reason so we # can preserve their hierarchy target_rooms = target_rooms.sort_by { |rc| [rc.controlled_by_id.to_i, rc.parent_id.to_i] } # nils are first since they convert to 0 total_rooms_to_copy = target_rooms.size copied_rooms = [] RoomConfiguration.transaction do all_rooms_in_opportunity = opportunity.room_configurations.to_a target_rooms.each_with_index do |rc, index| yield(index + 1, total_rooms_to_copy, "Copying #{rc}") if block_given? new_rc = rc.deep_dup new_rc.reference_number = nil new_rc.opportunity_id = opportunity.id new_rc.set_reference_number new_rc.quoted_heating_system_pl_id = rc.quoted_heating_system_pl_id # if rc.legacy_vignette_plan_image_id.present? # new_rc.vignette = true # new_rc.legacy_vignette_plan_image_id = rc.legacy_vignette_plan_image_id # new_rc.legacy_vignette_room_layout_image_id = rc.legacy_vignette_room_layout_image_id # end new_rc.parent_id = room_map[rc.id] # Only will be a value if the parent room was included in the copy new_rc.controlled_by_id = room_map[rc.id] old_name = new_rc.name # If the name already exists in this opportunity, we can rename if all_rooms_in_opportunity.find { |r| r.name == new_rc.name } new_rc.name = opportunity.next_room_name(room_type: new_rc.room_type, heating_system_product_line: new_rc.heating_system_product_line) end new_rc.save! new_rc.reload # Now fix the catalog if needed, with strict mode an exception will be raised if there's no match in the target catalog CatalogItem::Remapper.new(new_rc, { strict_mode: true, target_catalog: opportunity.customer.catalog, logger: logger }) # We keep track of all the rooms copied thus far and combine with the existing rooms from the opportunity # Mostly for name collision detection all_rooms_in_opportunity << new_rc # Keep track of the new room id, this is important we return this as a result room_map[rc.id] = new_rc.id # The line items are cloned and reset. # A room owns its lines (resource_type='RoomConfiguration'); its quotes/orders hold # *mirrors* of the same lines (resource_type='Quote'/'Order' + room_configuration_id), # kept in step by Pickable#synchronize_lines. Copying both sets doubles every line, so # the room's own lines win and the mirrors are only a fallback for the rare room that # owns none. items_to_copy = rc.line_items.parents_only.to_a if items_to_copy.empty? items_to_copy = LineItem.where(room_configuration_id: rc.id) .where.not(resource_type: 'RoomConfiguration') .parents_only.to_a end items_to_copy.each do |li| new_li = li.deep_dup new_li.room_configuration_id = nil new_li.resource = nil # Ensure discounted_price is set if it was incorrectly left at 0 new_li.discounted_price = new_li.price if new_li.discounted_price.to_f.zero? && new_li.price.to_f.positive? new_rc.line_items << new_li end # Keep references of old pdf which have inaccurate info now new_rc.uploads.where(category: %w[electrical_plan_pdf installation_plan_pdf]).find_each { |u| u.update(category: 'archive', note: "Was #{u.category}") } clone_upload_for_copy(rc.installation_plan_image, new_rc) clone_upload_for_copy(rc.room_layout_image, new_rc) new_rc.quick_note "This room was copied from #{rc.reference_number}. Its original name was #{old_name}" copied_rooms << new_rc end end # Generate the plans again, we do this outside transaction this ensures that our rooms are persisted to the db self.class.generate_all_plans(copied_rooms) unless @skip_room_plan_generation OpenStruct.new(room_copy_results: room_map).freeze end |