Class: Item::Materials::Checks::SnowMelting

Inherits:
BaseService
  • Object
show all
Defined in:
app/services/item/materials/checks/snow_melting.rb

Defined Under Namespace

Classes: Result

Constant Summary collapse

SCV_DUAL_AMPS_THRESHOLD =
16.0

Instance Method Summary collapse

Instance Method Details

#economy_paver_check(container, options) ⇒ Object (protected)

Test if we are looking at a room and if so if we have economy sm control group with paver, which is not recommended because economy uses slab sensor



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'app/services/item/materials/checks/snow_melting.rb', line 161

def economy_paver_check(container, options)
  return [] unless (container.class.to_s == "RoomConfiguration" and container.floor_type.seo_key == "paver" and (economy_sm_control_lis = container.line_items.select{|li| ItemConstants::SNOWMELT_CONTROL_BUNDLES_BY_GROUP["SCE"].include?(li.sku)}).any?)
  material_alerts = []
  Rails.logger.debug "#{container.class.name}:#{container.id}: get_snow_melting_material_alerts, container.floor_type.name: #{container.floor_type.name}, economy_sm_control_lis: #{economy_sm_control_lis.map{|li| [li.quantity, li.sku]}.inspect}"
  items = economy_sm_control_lis.map{|li| li.item}
  if items.any? and items.all?{|item| container.catalog.catalog_items.by_skus(item.sku).first.present?}
    ma_options = {}.merge(options)
    ma_options[:room] = container
    ma_options[:recommended_qty] = 0
    ma_options[:actual_qty] = 1
    ma_options[:items] = items
    ma_options[:unmaskable] = true
    ma_options[:name] = "Using the economy snow melting control with a paver surface is not recommended."
    material_alerts << Item::Materials::Alert.new(ma_options)
  end
  return material_alerts
end

#get_sm_heating_elements(container) ⇒ Object (protected)



134
135
136
# File 'app/services/item/materials/checks/snow_melting.rb', line 134

def get_sm_heating_elements(container)
  container.line_items.heating_elements.select{|li| li.item&.is_snow_melting_product? }
end

#locality_check(container, options) ⇒ Object (protected)

Test if we are looking at a room and if so if we are installing in RI or NY because they require an OT sensor on the pavement ie we require SCP sm control group



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'app/services/item/materials/checks/snow_melting.rb', line 139

def locality_check(container, options)
  return [] unless (container.respond_to?(:installation_state_code) and (container.installation_state_code.present? and ["RI", "NY"].include?(container.installation_state_code)) and container.line_items.select{|li| ["SCP-120", "SCE-120", "SCPM-CO-120-3"].include?(li.sku)}.empty?)
  material_alerts = []
  items = [Item.find_by(sku: "SCP-120")]
  items << Item.find_by(sku: "SCE-120") unless (container.class.to_s == "RoomConfiguration" and container.floor_type.seo_key == "paver")
  if items.any? and items.all?{|item| container.catalog.catalog_items.by_skus(item.sku).first.present?}
    ma_options = {}.merge(options)
    ma_options[:room] = container
    ma_options[:group_type] = "snow_melting_controls"
    ma_options[:group_name] = "Snow Melting Controls"
    ma_options[:recommended_qty] = 1
    ma_options[:actual_qty] = 0
    ma_options[:items] = items
    ma_options[:unmaskable] = true
    names_arr = items.map{|it| it.public_name}
    ma_options[:name] = "Using the #{names_arr.join(' or ')} is strongly recommended because of state building and electrical codes in #{container.installation_state_code}, which require shutting off the system when the surface temperature exceeds a certain threshhold. The #{names_arr.join(' and ')} #{names_arr.length > 1 ? 'are' : 'is'} capable of sensing the surface temperature."
    material_alerts << Item::Materials::Alert.new(ma_options)
  end
  return material_alerts
end

#process(container:, options: {}) ⇒ Object



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
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
# File 'app/services/item/materials/checks/snow_melting.rb', line 15

def process(container:, options:{})
  sm_heating_elements = get_sm_heating_elements(container)
  return Result.new(status: :skipped) unless qualify?(container) && sm_heating_elements.present?

  material_alerts = []
  # first test if we have any snow melt products
  # get actual sm controls in the line items
  all_bundled_sm_skus = ItemConstants::SNOWMELT_CONTROL_SKUS
  all_controls_sm_skus = ItemConstants::SNOWMELT_CONTROL_TSTAT_SKUS
  controls = container.line_items.select{|li| all_controls_sm_skus.include?(li.sku)}
  # get actual relay panels
  relay_panels = container.line_items.relay_panels
  # get current of the sm heating system
  current = sm_heating_elements.to_a.sum{|li| li.item.amps*li.quantity.to_f}
  # next test if we have more sm controls than we have sm heating elements
  num_controls = controls.sum{|li| li.quantity}
  num_heating_elements = sm_heating_elements.sum{|li| li.quantity}
  if num_controls > num_heating_elements
    ma_options = {}.merge(options)
    ma_options[:room] = container
    ma_options[:recommended_qty] = num_heating_elements
    ma_options[:actual_qty] = num_controls
    ma_options[:items] = controls.map{|li| li.item}.compact
    ma_options[:unmaskable] = true
    ma_options[:name] = "At least one heating element per control is recommended."
    material_alerts << Item::Materials::Alert.new(ma_options)
  end
  if (num_controls == 0) and (num_heating_elements > 0)
    ma_options = {}.merge(options)
    ma_options[:room] = container
    ma_options[:recommended_qty] = 1
    ma_options[:actual_qty] = num_controls
    ma_options[:items] = Item.where(sku: all_controls_sm_skus).to_a
    ma_options[:unmaskable] = true
    ma_options[:name] = "At least one Snow Melting control is recommended."
    material_alerts << Item::Materials::Alert.new(ma_options)
  end

  material_alerts += locality_check(container, options)

  material_alerts += economy_paver_check(container, options)

  # next test for each sm control we have
  ItemConstants::SNOWMELT_CONTROL_BUNDLES_BY_GROUP.select{|k,v| controls.any?{|li| v.include?(li.sku)}}.each do |group_sku, bundled_sm_skus|
    # if we have sm control group items in both the bundled group and outside the bundled group, it is not recommended
    sm_control = Item.find_by(sku: ItemConstants::SNOWMELT_CONTROL_BUNDLES_BY_GROUP[group_sku].first)
    if (non_group_bundle_lis = container.line_items.select{|li| (all_bundled_sm_skus - bundled_sm_skus).include?(li.sku)}).any?
      # we do, so set up the alert
      ma_options = {}.merge(options)
      ma_options[:room] = container
      ma_options[:recommended_qty] = 0
      ma_options[:actual_qty] = 1
      ma_options[:unmaskable] = true
      items = non_group_bundle_lis.map{|li| li.item}.compact
      ma_options[:name] = "Using the following items is not recommended with the #{ItemConstants::SNOWMELT_CONTROL_BUNDLE_SKU_NAME_HASH[group_sku]} snow melting control:"
      ma_options[:items] = items
      material_alerts << Item::Materials::Alert.new(ma_options)
    end
    # if we have sm controls but not the other group items, it is not recommended
    bundled_skus_not_in_lis = bundled_sm_skus.select{|sku| container.line_items.detect{|li| li.sku == sku}.nil?}
    if bundled_skus_not_in_lis.any?
      # we are missing some skus, so set up the alert
      items = bundled_skus_not_in_lis.map{|sku| Item.find_by(sku: sku)}
      if items.any? and items.all?{|item| container.catalog.catalog_items.by_skus(item.sku).first.present?}
        ma_options = {}.merge(options)
        ma_options[:room] = container
        ma_options[:recommended_qty] = controls.select{|li| li.sku == sm_control.sku}.sum{|li| li.quantity}
        ma_options[:actual_qty] = 0
        ma_options[:unmaskable] = true
        ma_options[:name] = "The following items are recommended with the #{ItemConstants::SNOWMELT_CONTROL_BUNDLE_SKU_NAME_HASH[group_sku]} snow melting control:"
        ma_options[:items] = items
        material_alerts << Item::Materials::Alert.new(ma_options)
      end
    end
  end
  # check relay panels and RCO if we have controls
  if controls.any?
    # set minimum recommended relay panels, unless SCV control only and current under 16 amps
    if controls.length == 1 and controls.first.sku == "SCV-DUAL" and current < SCV_DUAL_AMPS_THRESHOLD
      poles = 0
    else
      # get number of poles in the sm heating system
      poles = sm_heating_elements.to_a.sum{|li| ( (Item::DOUBLE_POLE_VOLTAGES.include?(li.item.voltage) || li.item.amps > 15.0) ? 2 : 1).round*li.quantity}
    end
    # get relay_panels required from poles
    # first test if we have enough
    actual_poles = relay_panels.to_a.sum{|li| li.num_poles.to_i*li.quantity}
    if actual_poles != poles
      relay_panels_sku_qty = HeatingElementProductLineOption.get_relay_panels_from_poles(poles)
      relay_panels_sku_qty.each do |sku, qty|
        actual_qty = relay_panels.select{|li| li.sku == sku}.sum{|li| li.quantity}
        if qty != actual_qty and container.catalog.catalog_items.by_skus(sku).first.present? and (item = Item.find_by(sku: sku)).present?
          ma_options = {}.merge(options)
          ma_options[:room] = container
          ma_options[:recommended_qty] = qty
          ma_options[:actual_qty] = actual_qty
          ma_options[:items] = [item]
          ma_options[:unmaskable] = true
          material_alerts << Item::Materials::Alert.new(ma_options)
        end
      end
    end
    rcos = container.line_items.select{|li| li.sku == "RCO"}
    if rcos.any? and controls.detect{|li| ["SCP-120","SCA-DUAL"].include?(li.sku)}.nil? and (item = Item.find_by(sku: "RCO")).present?
      ma_options = {}.merge(options)
      ma_options[:room] = container
      ma_options[:recommended_qty] = 0
      ma_options[:actual_qty] = rcos.sum{|li| li.quantity}
      ma_options[:items] = [item]
      ma_options[:unmaskable] = true
      ma_options[:name] = "The RCO is only compatible with Premium and Advanced snow melting controls."
      material_alerts << Item::Materials::Alert.new(ma_options)
    end
  end
  return Result.new(status: :ok, alerts: material_alerts)
end

#qualify?(container) ⇒ Boolean

Returns:

  • (Boolean)


10
11
12
13
# File 'app/services/item/materials/checks/snow_melting.rb', line 10

def qualify?(container)
  # we only apply this test when a container is a room or is a quote or order with no rooms, ie a single system
  container.is_a?(RoomConfiguration) || (container.respond_to?(:room_configurations) && container.room_configurations.empty?)
end