Class: Bom::XmlFromZone

Inherits:
Object
  • Object
show all
Includes:
Service
Defined in:
app/services/bom/xml_from_zone.rb

Overview

Service object: xml from zone.

Instance Method Summary collapse

Methods included from Service

#attributes_used, #build_result, call, #logger

Methods included from Service::Initializer

#initialize

Instance Method Details

#callObject



15
16
17
18
19
20
21
22
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
# File 'app/services/bom/xml_from_zone.rb', line 15

def call
  heating_system_type_name = heating_system_pl.heating_system_type_name
  require_expansion_joint = HeatingElementProductLineOption.get_field_array_from_options(:require_expansion_joint, { floor_type_id: floor_type.id, product_line_id: heating_system_pl.id }).first
  ideal_cable_spacing = HeatingElementProductLineOption.get_field_array_from_options(:ideal_cable_spacing, { floor_type_id: floor_type.id, product_line_id: heating_system_pl.id }).first

  est_element = REXML::Element.new "estimate"
  est_element.add_attribute("catalog_id", catalog.id.to_s)
  est_element.add_attribute("floor_type_id", floor_type.id.to_s)
  est_element.add_attribute("product_type", floor_type.product) # legacy product TZ, SM, EV2
  est_element.add_attribute("currency_code", catalog.currency)

  criteria_keys = {}
  criteria_keys[:zones] = zones
  criteria_keys[:room_type] = RoomType.find(HeatingElementProductLineOption.get_default_room_type_id_for_environment(floor_type.environment))
  criteria_keys[:floor_type] = floor_type
  criteria_keys[:sub_floor_type] = sub_floor_type || SubFloorType.find_by(seo_key: "wood")
  criteria_keys[:heating_system_type] = heating_system_type_name
  criteria_keys[:coverage_state] = options[:coverage_state].presence || 'full'
  criteria_keys[:voltage] = options[:voltage]
  legacy_style = false

  if ["TempZone Flex Roll", "TempZone Easy Mat", "Environ Flex Roll", "Environ Easy Mat", "Slab Heat Cable", "Slab Heat Mat"].include?(heating_system_type_name)
    legacy_style = true
    criteria_keys[:cable_spacing] = options[:cable_spacing] ||= ideal_cable_spacing if ["Slab Heat Cable"].include?(heating_system_type_name)
  elsif ["Snow Melt Mat", "Snow Melt PowerMat", "Snow Melt OmniMat", "Snow Melt EcoMat", "Snow Melt Cable"].include?(heating_system_type_name)
    criteria_keys[:expansion_joint_spacing] = options[:expansion_joint_spacing] if require_expansion_joint
    criteria_keys[:expansion_joint_spacing] ||= 20 if require_expansion_joint
    criteria_keys[:cable_spacing] = options[:cable_spacing] ||= ideal_cable_spacing if ["Snow Melt Cable"].include?(heating_system_type_name)
  end
  hsc_bom = HeatingSystemCalculator::BaseCalculator.new(
    criteria_keys.merge(
      catalog: catalog,
      heating_system_product_line: heating_system_pl,
      require_expansion_joint: require_expansion_joint
    )
  ).calculate_system

  if hsc_bom && hsc_bom['found_solution']
    est_element.add_attribute("coverage_percentage", hsc_bom['coverage_percentage'].to_i.to_s)
    est_element.add_attribute("area", hsc_bom['target_area'].to_f.round(1).to_s)
    insert_xml_from_bom_soln_into_element(hsc_bom, est_element, legacy_style, options[:pricing_formula])
    est_element.to_s
  else
    ", from e-tailer iq domain: #{quick_estimator.domain_name}" if quick_estimator
    err_msg = "BOM::XmlFromZone: #{hsc_bom['error_message']}"
    ErrorReporting.warning(err_msg, attributes_used)
    ""
  end
end

#get_pricing(msrp_price, pricing_formula) ⇒ Object (protected)



160
161
162
163
164
# File 'app/services/bom/xml_from_zone.rb', line 160

def get_pricing(msrp_price, pricing_formula)
  pricing = msrp_price
  pricing = eval(pricing_formula.gsub('msrp_price', msrp_price.to_s)) if pricing_formula # rubocop:disable Security/Eval
  pricing
end

#insert_xml_from_bom_soln_into_element(bom, est_element, legacy_style, pricing_formula = nil) ⇒ Object (protected)



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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'app/services/bom/xml_from_zone.rb', line 67

def insert_xml_from_bom_soln_into_element(bom, est_element, legacy_style, pricing_formula = nil)
  logger.debug "bom['foundsolution']: #{bom['foundsolution']}"
  logger.debug "bom['controls']: #{bom['controls'].inspect}"
  return if bom['foundsolution'] == false

  # controls
  if legacy_style
    # for backward compatibility do TZ controls as per before
    bom['controls'].sort_by { |i| [i['price'], i['description']] }.each do |control|
      ct_element = REXML::Element.new control['symbol'].downcase
      ct_element.add_attribute("qty", control['qty'].to_s)
      ct_element.add_attribute("price", get_pricing(control['price'].round(2), pricing_formula).to_s)
      ct_element.add_attribute("description", control['description'])
      ct_element.add_attribute("sku", control['sku'])
      ct_element.add_attribute("third_party_part_number", control['third_party_part_number'])
      ct_element.add_attribute("third_party_sku", control['third_party_sku'])
      ct_element.add_attribute("cat_id", control['cat_id'].to_s)
      item = Item.find_by(sku: control['sku'])
      ct_element.add_attribute("image_url", item.thumbnail_url)
      est_element.add_element ct_element
    end
  else
    # otherwise we do control groups to bundle groups of skus in a single control group option
    bom_control_groups = (bom['controls'] || []).group_by { |p| p["bundle_sku"] }
    # here the non optional relay panels (by bom convention in controls) should be added to the non optional products, their bundle sku will be nil
    bom_required_controls = bom_control_groups[nil] || []
    bom_required_controls.sort_by { |i| [i['price'], i['description']] }.each do |control|
      ct_element = REXML::Element.new control['symbol'].downcase
      ct_element.add_attribute("qty", control['qty'].to_s)
      ct_element.add_attribute("price", get_pricing(control['price'].round(2), pricing_formula).to_s)
      ct_element.add_attribute("description", control['description'])
      ct_element.add_attribute("sku", control['sku'])
      ct_element.add_attribute("third_party_part_number", control['third_party_part_number'])
      ct_element.add_attribute("third_party_sku", control['third_party_sku'])
      ct_element.add_attribute("cat_id", control['cat_id'].to_s)
      item = Item.find_by(sku: control['sku'])
      ct_element.add_attribute("image_url", item.thumbnail_url)
      est_element.add_element ct_element
    end
    # get the radio optional control groups
    bom_optional_groups = []
    bom_control_groups.each do |bundle_sku, products|
      bom_optional_groups << products if bundle_sku
    end
    bom_optional_groups.each do |control_group|
      cg_element = REXML::Element.new 'control_group'
      cg_element.add_attribute("description", control_group.first['description'])
      control_group.each do |control|
        ct_element = REXML::Element.new control['symbol'].downcase
        ct_element.add_attribute("qty", control['qty'].to_s)
        ct_element.add_attribute("price", get_pricing(control['price'].round(2), pricing_formula).to_s)
        ct_element.add_attribute("description", control['description'])
        ct_element.add_attribute("sku", control['sku'])
        ct_element.add_attribute("third_party_part_number", control['third_party_part_number'])
        ct_element.add_attribute("third_party_sku", control['third_party_sku'])
        ct_element.add_attribute("cat_id", control['cat_id'].to_s)
        item = Item.find_by(sku: control['sku'])
        ct_element.add_attribute("image_url", item.thumbnail_url)
        cg_element.add_element ct_element
      end
      est_element.add_element cg_element
    end
  end
  # heating elements
  bom['elements'].sort_by { |i| [i['price'], i['description']] }.each do |element|
    he_element = REXML::Element.new "heating_element"
    he_element.add_attribute("qty", element['qty'].to_s)
    he_element.add_attribute("price", get_pricing(element['price'].round(2), pricing_formula).to_s)
    he_element.add_attribute("description", element['description'])
    he_element.add_attribute("sku", element['sku'])
    he_element.add_attribute("third_party_part_number", element['third_party_part_number'])
    he_element.add_attribute("third_party_sku", element['third_party_sku'])
    he_element.add_attribute("cat_id", element['cat_id'].to_s)
    item = Item.find_by(sku: element['sku'])
    he_element.add_attribute("image_url", item.thumbnail_url)
    est_element.add_element he_element
  end
  # accessories
  (bom['accessories'] || []).select { |i| i['exclusive_group_type'].nil? }.sort_by { |i| [i['price'], i['description']] }.each do |element|
    ac_element = REXML::Element.new "accessory"
    ac_element.add_attribute("qty", element['qty'].to_s)
    ac_element.add_attribute("price", get_pricing(element['price'].round(2), pricing_formula).to_s)
    ac_element.add_attribute("description", element['description'])
    ac_element.add_attribute("sku", element['sku'])
    ac_element.add_attribute("third_party_part_number", element['third_party_part_number'])
    ac_element.add_attribute("third_party_sku", element['third_party_sku'])
    ac_element.add_attribute("cat_id", element['cat_id'].to_s)
    item = Item.find_by(sku: element['sku'])
    ac_element.add_attribute("image_url", item.thumbnail_url)
    est_element.add_element ac_element
  end
end