Class: HeatingElementProductLineOption
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- HeatingElementProductLineOption
- Extended by:
- ActionView::Helpers::NumberHelper
- Includes:
- Models::Auditable
- Defined in:
- app/models/heating_element_product_line_option.rb
Overview
== Schema Information
Table name: heating_element_product_line_options
Database name: primary
id :integer not null, primary key
application_type :string(255)
environment :string(255)
ideal_cable_spacing :float
instant_quotable :boolean
is_public :boolean
membrane_recommended :boolean
membrane_type :string
priority :integer
require_cable_spacing :boolean
require_expansion_joint :boolean
underlayment_r_value :string(255)
underlayment_recommended :boolean
underlayment_type :string(255)
created_at :datetime not null
updated_at :datetime not null
creator_id :integer
floor_type_id :integer
product_line_id :integer
room_type_id :integer
store_id :integer
sub_floor_type_id :integer
updater_id :integer
Indexes
by_env_sid_rtid_ftid (environment,store_id,room_type_id,floor_type_id)
by_env_sid_sftid (environment,store_id,sub_floor_type_id)
by_ftid_plid_sftid (floor_type_id,product_line_id,sub_floor_type_id)
idx_floor_type_sub_floor_type_store (floor_type_id,sub_floor_type_id,store_id)
idx_is_public (is_public)
index_heating_element_product_line_options_on_creator_id (creator_id)
index_heating_element_product_line_options_on_instant_quotable (instant_quotable)
index_heating_element_product_line_options_on_store_id (store_id)
index_heating_element_product_line_options_on_updater_id (updater_id)
pl_id_mem_rec (product_line_id,membrane_recommended)
rt_id_sft_id_ft_id (room_type_id,sub_floor_type_id,floor_type_id)
sft_id_pl_id_mr (sub_floor_type_id,product_line_id,membrane_recommended)
Constant Summary collapse
- ENVIRONMENTS_HASH =
{ 'Indoor' => { key: 'indoor', application_type: 'FH', base_product_line_url: 'floor-heating', default_room_type_seo_key: 'bathroom', default_floor_type_seo_key: 'tile-marble-or-stone' }, 'Outdoor' => { key: 'outdoor', application_type: 'SMRD', base_product_line_url: 'snow-melting', default_room_type_seo_key: 'driveway', default_floor_type_seo_key: 'asphalt' }, 'Countertop' => { key: 'countertop', application_type: 'CH', base_product_line_url: 'countertop-heater', default_room_type_seo_key: 'countertop', default_floor_type_seo_key: 'granite-countertop' }, 'Roof' => { key: 'roof', application_type: 'SMRD', base_product_line_url: 'roof-and-gutter-deicing', default_room_type_seo_key: 'roof', default_floor_type_seo_key: 'asphalt-shingle' }, 'Pipe' => { key: 'pipe', application_type: 'PIPE', base_product_line_url: 'pipe-freeze-protection', default_room_type_seo_key: 'pipe', default_floor_type_seo_key: 'pipe' }, 'Custom Mirror' => { key: 'custom-mirror', application_type: 'CUSTOM_MIRROR', base_product_line_url: 'led-mirror', default_room_type_seo_key: 'custom-mirror', default_floor_type_seo_key: 'custom-mirror' } }
- PUBLIC_ENVIRONMENTS =
%w[Indoor Outdoor]
- PUBLIC_ENVIRONMENT_KEYS =
PUBLIC_ENVIRONMENTS.map { |e| ENVIRONMENTS_HASH[e][:key] }
- PUBLIC_ENVIRONMENTS_HASH =
ENVIRONMENTS_HASH.select { |k, _v| PUBLIC_ENVIRONMENTS.include?(k) }
- APPLICATION_TYPES =
["FH", "SM", "CH", "RD", "PIPE"]
ENVIRONMENTS_HASH.map { |_k, v| v[:application_type] }.uniq
- ENVIRONMENTS =
["Indoor", "Outdoor", "Countertop", "Roof", "Pipe"]
ENVIRONMENTS_HASH.map { |k, _v| k }
- DEFAULT_SUB_FLOOR_TYPE =
'Unconfirmed/Other'- PUBLIC_SUB_FLOOR_TYPE_KEYS =
SubFloorType.active.by_name.map { |sf| sf.seo_key }
- DEFAULT_FLOOR_TYPE_BY_ENVIRONMENT =
{ 'Indoor' => 'Tile, Marble or Stone', 'Outdoor' => 'Asphalt (new)', 'Countertop' => 'Granite countertop', 'Roof' => 'Asphalt shingle', 'Pipe' => 'Pipe', 'Custom Mirror' => 'Custom Mirror' }
- PUBLIC_FLOOR_TYPE_KEYS =
ENVIRONMENTS_HASH.map{|k,v| [k,FloorType.find_by(seo_key: v[:default_floor_type_seo_key])&.name]}.to_h
%w[asphalt existing-asphalt bamboo-floating bamboo-glued bamboo-nailed carpet-glued carpet concrete existing-concrete cork engineered-floating engineered-glued engineered-nailed unfinished-stamped-or-colored-concrete wood-glued wood-nailed heated-balcony heated-bench laminate-click-together-floating laminate-glued-together-floating laminate-nailed other paver resilients-vinyl-and-luxury-vinyl-tile-lvt tile-marble-or-stone]
- UNDERLAYMENT_TYPES =
FloorType.active.by_environment(PUBLIC_ENVIRONMENTS).by_name.map{|f| f.seo_key}
['ThermalSheet']
- MEMBRANE_TYPES =
%w[Prodeso Ditra]
- PRODUCT_LINE_BY_HEATING_SYSTEM_TYPE =
{ 'TempZone Flex Roll' => 'floor-heating-tempzone-flex-roll', 'TempZone Easy Mat' => 'floor-heating-tempzone-easy-mat', 'TempZone Cable' => 'floor-heating-tempzone-cable', 'TempZone Ruler Cable' => 'floor-heating-tempzone-ruler-cable', 'TempZone Thin Cable' => 'floor-heating-tempzone-thin-cable', 'Environ Flex Roll' => 'floor-heating-environ-flex-roll', 'Environ Easy Mat' => 'floor-heating-environ-easy-mat', 'Slab Heat Cable' => 'floor-heating-slab-heat-cable', 'Slab Heat Mat' => 'floor-heating-slab-heat-mat', 'Snow Melt Cable' => 'snow-melting-cable', 'Snow Melt Mat' => 'snow-melting-mat', 'Snow Melt PowerMat' => 'snowmelt-powermat', 'Snow Melt OmniMat' => 'snowmelt-omnimat', 'Snow Melt EcoMat' => 'snowmelt-ecomat' }
- LEGACY_PRODUCT_BY_HEATING_SYSTEM_TYPE =
{ 'TempZone Flex Roll' => 'TZ', 'TempZone Easy Mat' => 'TZEM', 'TempZone Cable' => 'TZC', 'TempZone Thin Cable' => 'TZTC', 'Environ Flex Roll' => 'EVFR', 'Environ Easy Mat' => 'EV2', 'Slab Heat Cable' => 'SHC', 'Slab Heat Mat' => 'SHM', 'Snow Melt Cable' => 'SMC', 'Snow Melt Mat' => 'SMM' }
- HEATING_SYSTEM_TYPE_BY_LEGACY_PRODUCT =
{ 'TZ' => 'TempZone Flex Roll', 'TZEM' => 'TempZone Easy Mat', 'TZC' => 'TempZone Cable', 'TZTC' => 'TempZone Thin Cable', 'EV2' => 'Environ Flex Roll', 'EVFR' => 'Environ Flex Roll', 'SMC' => 'Snow Melt Cable', 'SMM' => 'Snow Melt Mat', 'SHC' => 'Slab Heat Cable', 'SHM' => 'Slab Heat Mat' }
- CALLOUTS_BY_HEATING_SYSTEM =
{ 'TempZone Flex Roll' => ['Full coverage for any size space, such as kitchens, living rooms, or basements', 'Ideal for in-field flexibility', 'Single & twin conductor available', '15 watts per sq. ft., 1/8" thick'], 'TempZone Easy Mat' => ["Floor heating for specific larger areas 'blanket' coverage, such as a family room or bedroom", 'No-cut one piece, rectangular mat', '120 Volt / 240 Volt', '15 watts per sq. ft., 1/8" thick'], 'TempZone Cable' => ['At 3.75 inch spacing: 12 Watts per sq ft. (potentially a primary heat source)', 'At 5 inch spacing: 9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.7 Watts per linear ft'], 'TempZone Cable 3.75' => ['10-12 Watts per sq ft. (potentially a primary heat source)', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.75 Watts per linear ft'], 'TempZone Cable 5' => ['8-9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.75 Watts per linear ft'], 'TempZone Ruler Cable' => ['At 3.75 inch spacing: 12 Watts per sq ft. (potentially a primary heat source)', 'At 5 inch spacing: 9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.7 Watts per linear ft'], 'TempZone Ruler Cable 3.75' => ['10-12 Watts per sq ft. (potentially a primary heat source)', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.75 Watts per linear ft'], 'TempZone Ruler Cable 5' => ['8-9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3.75 Watts per linear ft'], 'TempZone Thin Cable' => ['At 3 inch spacing: 12 Watts per sq ft. (potentially a primary heat source)', 'At 4 inch spacing: 9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3 Watts per linear ft'], 'TempZone Thin Cable 3' => ['10-12 Watts per sq ft. (potentially a primary heat source)', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3 Watts per linear ft'], 'TempZone Thin Cable 4' => ['8-9 Watts per sq ft.', 'Ideal for in-field flexibility', 'Available in 120v or 240v systems', '3 Watts per linear ft'], 'Environ Flex Roll' => ['Ideal for in-field flexibility', 'Full coverage for any size space, commonly installed beneath carpet & laminate', '12 watts per sq. ft.'], 'Environ Easy Mat' => ["Floor heating for specific larger areas 'blanket' coverage, such as a family room", 'No-cut one piece', '12 watts per sq. ft.'], 'Snow Melt Cable' => ['Installs in asphalt, concrete, or under pavers in mortar', 'Perfect for driveways, patios, walkways and stairs', 'Available in 120V or 240V systems', 'Ultimate in flexible installation with free-form cable'], 'Snow Melt Mat' => ['Installs in asphalt, concrete, or under pavers in mortar', 'Perfect for driveways, patios, walkways and stairs', 'Available in 120V or 240V systems', 'Flexible installation with Flex Roll technology'], 'Slab Heat Cable' => ['Installs directly in concrete', 'Available in 120v or 240v systems', '6 Watts per lineal ft / 20 Watts per sq ft.', 'Ultimate in flexible installation with free-form cable'], 'Slab Heat Mat' => ['Installs directly in concrete', 'Available in 120v or 240v systems', '6 Watts per lineal ft / 20 Watts per sq ft.', 'Flexible installation with Flex Roll technology'] }
- CALLOUTS_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => ['25 Year Warranty', '1/8" super-thin mat'], 'TempZone Easy Mat' => ['25 Year Warranty', '1/8" super-thin mat'], 'TempZone Shower Mat' => ['25 Year Warranty', '1/8" super-thin mat'], 'TempZone Custom Mat' => ['25 Year Warranty', '1/8" super-thin mat'], 'TempZone Cable' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Ruler Cable' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Thin Cable' => ['25 Year Warranty', '1/8" super-thin cable'], 'TempZone Thin Cable 3.0' => ['25 Year Warranty', '1/8" super-thin cable'], 'TempZone Cable 3.0' => ['25 Year Warranty', '3/16" robust cable'], # to support legacy 'TempZone Cable 3.5' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Cable 3.75' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Ruler Cable 3.0' => ['25 Year Warranty', '3/16" robust cable'], # to support legacy 'TempZone Ruler Cable 3.5' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Ruler Cable 3.75' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Thin Cable 3.5' => ['25 Year Warranty', '1/8" super-thin cable'], # to support legacy 'TempZone Thin Cable 3.75' => ['25 Year Warranty', '1/8" super-thin cable'], # to support legacy 'TempZone Thin Cable 4.0' => ['25 Year Warranty', '1/8" super-thin cable'], 'TempZone Cable 4.0' => ['25 Year Warranty', '3/16" robust cable'], # to support legacy 'TempZone Cable 4.75' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Cable 5.0' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Ruler Cable 4.0' => ['25 Year Warranty', '3/16" robust cable'], # to support legacy 'TempZone Ruler Cable 4.75' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Ruler Cable 5.0' => ['25 Year Warranty', '3/16" robust cable'], 'TempZone Thin Cable 4.75' => ['25 Year Warranty', '1/8" super-thin cable'], # to support legacy 'TempZone Thin Cable 5.0' => ['25 Year Warranty', '1/8" super-thin cable'], # to support legacy 'Environ Flex Roll' => ['10 Year Warranty under Laminate & Floating Hardwood, 5 Year under Carpet', '1/16" super-thin mat'], 'Environ Easy Mat' => ['10 Year Warranty under Laminate & Floating Hardwood, 5 Year under Carpet', '1/16" super-thin mat'], 'Snow Melt Cable' => ['10 Year Warranty', 'Energy efficient twin-conductor heating cable'], 'Snow Melt Mat' => ['10 Year Warranty', 'Energy efficient twin-conductor heating mat'], 'Slab Heat Cable' => ['10 Year Warranty', 'Energy efficient twin-conductor heating cable'], 'Slab Heat Mat' => ['10 Year Warranty', 'Energy efficient twin-conductor heating cable'] }
- WARRANTY_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => '25 Years', 'TempZone Easy Mat' => '25 Years', 'TempZone Custom Mat' => '25 Years', 'TempZone Shower Mat' => '25 Years', 'TempZone Cable' => '25 Years', 'TempZone Ruler Cable' => '25 Years', 'TempZone Thin Cable' => '25 Years', 'TempZone Thin Cable 3.0' => '25 Years', 'TempZone Cable 3.0' => '25 Years', # to support legacy 'TempZone Cable 3.5' => '25 Years', 'TempZone Cable 3.75' => '25 Years', 'TempZone Thin Cable 3.5' => '25 Years', # to support legacy 'TempZone Thin Cable 3.75' => '25 Years', # to support legacy 'TempZone Thin Cable 4.0' => '25 Years', 'TempZone Cable 4.0' => '25 Years', # to support legacy 'TempZone Cable 4.75' => '25 Years', 'TempZone Cable 5.0' => '25 Years', 'TempZone Thin Cable 4.75' => '25 Years', # to support legacy 'TempZone Thin Cable 5.0' => '25 Years', # to support legacy 'Environ Flex Roll' => '10 Years under Laminate & Floating Hardwood, 5 Years under Carpet', 'Environ Easy Mat' => '10 Years under Laminate & Floating Hardwood, 5 Years under Carpet', 'Snow Melt Cable' => '10 Years', 'Snow Melt Mat' => '10 Years', 'Slab Heat Cable' => '10 Years', 'Slab Heat Mat' => '10 Years' }
- WATTS_PER_SQFT_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => '15', 'TempZone Easy Mat' => '15', 'TempZone Custom Mat' => '15', 'TempZone Shower Mat' => '15', 'TempZone Cable' => '10-12', 'TempZone Ruler Cable' => '10-12', 'TempZone Thin Cable' => '10-12', 'TempZone Thin Cable 3.0' => '10-12', 'TempZone Cable 3.0' => '12-15', # to support legacy 'TempZone Cable 3.5' => '11-14', 'TempZone Cable 3.75' => '10-12', 'TempZone Ruler Cable 3.0' => '12-15', # to support legacy 'TempZone Ruler Cable 3.5' => '11-14', 'TempZone Ruler Cable 3.75' => '10-12', 'TempZone Thin Cable 3.5' => '10-12', # to support legacy 'TempZone Thin Cable 3.75' => '9-11', # to support legacy 'TempZone Thin Cable 4.0' => '8-9', 'TempZone Cable 4.0' => '10-12', # to support legacy 'TempZone Cable 4.75' => '9-10', 'TempZone Cable 5.0' => '7-9', 'TempZone Ruler Cable 4.0' => '10-12', # to support legacy 'TempZone Ruler Cable 4.75' => '9-10', 'TempZone Ruler Cable 5.0' => '7-9', 'TempZone Thin Cable 4.75' => '7-9', # to support legacy 'TempZone Thin Cable 5.0' => '6-8', # to support legacy 'Environ Flex Roll' => '12', 'Environ Easy Mat' => '12', 'Snow Melt Cable' => '50', 'Snow Melt Mat' => '50', 'Slab Heat Cable' => '20', 'Slab Heat Mat' => '20' }
- PRICE_PER_SQFT_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => '$10 - $12 per sq. ft.', 'TempZone Easy Mat' => '$10 - $12 per sq. ft.', 'TempZone Custom Mat' => '$15 - $30 per sq. ft.', 'TempZone Shower Mat' => '$15 - $20 per sq. ft.', 'TempZone Cable' => '$15 - $20 per sq. ft.', 'TempZone Ruler Cable' => '$15 - $20 per sq. ft.', 'TempZone Thin Cable' => '$8 - $10 per sq. ft.', 'TempZone Thin Cable 3.0' => '$8 - $10 per sq. ft.', 'TempZone Cable 3.0' => '$19 - $25 per sq. ft.', # to support legacy 'TempZone Cable 3.5' => '$16 - $22 per sq. ft.', 'TempZone Cable 3.75' => '$15 - $20 per sq. ft.', 'TempZone Ruler Cable 3.0' => '$19 - $25 per sq. ft.', # to support legacy 'TempZone Ruler Cable 3.5' => '$16 - $22 per sq. ft.', 'TempZone Ruler Cable 3.75' => '$15 - $20 per sq. ft.', 'TempZone Thin Cable 3.5' => '$7 - $10 per sq. ft.', # to support legacy 'TempZone Thin Cable 3.75' => '$6 - $8 per sq. ft.', # to support legacy 'TempZone Thin Cable 4.0' => '$6 - $8 per sq. ft.', 'TempZone Cable 4.0' => '$14 - $19 per sq. ft.', # to support legacy 'TempZone Cable 4.75' => '$13 - $18 per sq. ft.', 'TempZone Cable 5.0' => '$12 - $17 per sq. ft.', 'TempZone Ruler Cable 4.0' => '$14 - $19 per sq. ft.', # to support legacy 'TempZone Ruler Cable 4.75' => '$13 - $18 per sq. ft.', 'TempZone Ruler Cable 5.0' => '$12 - $17 per sq. ft.', 'TempZone Thin Cable 4.75' => '$5 - $7 per sq. ft.', # to support legacy 'TempZone Thin Cable 5.0' => '$5 - $7 per sq. ft.', # to support legacy 'Environ Flex Roll' => '$10 - $12 per sq. ft.', 'Environ Easy Mat' => '$10 - $12 per sq. ft.', 'Snow Melt Cable' => '$8 - $16 per sq. ft.', 'Snow Melt Mat' => '$10 - $20 per sq. ft.', 'Slab Heat Cable' => '$8 - $16 per sq. ft.', 'Slab Heat Mat' => '$10 - $20 per sq. ft.' }
- CABLE_SPACING_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => '3.0', 'TempZone Easy Mat' => '3.0', 'TempZone Shower Mat' => '3.0', 'TempZone Custom Mat' => '3.0', 'TempZone Cable' => '3.0" to 5.0', 'TempZone Ruler Cable' => '3.0" to 5.0', 'TempZone Thin Cable' => '3.0" to 5.0', 'TempZone Thin Cable 3.0' => '3.0', 'TempZone Cable 3.0' => '3.0', # to support legacy 'TempZone Cable 3.5' => '3.5', 'TempZone Cable 3.75' => '3.75', 'TempZone Ruler Cable 3.0' => '3.0', # to support legacy 'TempZone Ruler Cable 3.5' => '3.5', 'TempZone Ruler Cable 3.75' => '3.75', 'TempZone Thin Cable 3.5' => '3.5', # to support legacy 'TempZone Thin Cable 3.75' => '3.75', # to support legacy 'TempZone Thin Cable 4.0' => '4.0', 'TempZone Cable 4.0' => '4.0', # to support legacy 'TempZone Cable 4.75' => '4.75', 'TempZone Cable 5.0' => '5.0', 'TempZone Ruler Cable 4.0' => '4.0', # to support legacy 'TempZone Ruler Cable 4.75' => '4.75', 'TempZone Ruler Cable 5.0' => '5.0', 'TempZone Thin Cable 4.75' => '4.75', # to support legacy 'TempZone Thin Cable 5.0' => '5.0', # to support legacy 'Environ Flex Roll' => '3.0', 'Environ Easy Mat' => '3.0', 'Snow Melt Cable' => '3.0', 'Snow Melt Mat' => '3.0', 'Slab Heat Cable' => '3.0', 'Slab Heat Mat' => '3.0' }
- INSTALLATION_BLURB_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => 'Cut/Turn Installation', 'TempZone Easy Mat' => 'Spot Heat Placement', 'TempZone Shower Mat' => 'Spot Heat Placement', 'TempZone Custom Mat' => 'Spot Heat Placement', 'TempZone Cable' => 'Free-Form: Membrane or Fixing Strips', 'TempZone Ruler Cable' => 'Free-Form: Membrane or Fixing Strips', 'TempZone Thin Cable' => 'Free-Form Installation', 'TempZone Thin Cable 3.0' => 'Free-Form Installation', 'TempZone Cable 3.0' => 'Free-Form Installation', # to support legacy 'TempZone Cable 3.5' => 'Free-Form Installation', 'TempZone Cable 3.75' => 'Free-Form Installation', 'TempZone Ruler Cable 3.0' => 'Free-Form Installation', # to support legacy 'TempZone Ruler Cable 3.5' => 'Free-Form Installation', 'TempZone Ruler Cable 3.75' => 'Free-Form Installation', 'TempZone Thin Cable 3.5' => 'Free-Form Installation', # to support legacy 'TempZone Thin Cable 3.75' => 'Free-Form Installation', # to support legacy 'TempZone Thin Cable 4.0' => 'Free-Form Installation', 'TempZone Cable 4.0' => 'Free-Form Installation', # to support legacy 'TempZone Cable 4.75' => 'Free-Form Installation', 'TempZone Cable 5.0' => 'Free-Form Installation', 'TempZone Ruler Cable 4.0' => 'Free-Form Installation', # to support legacy 'TempZone Ruler Cable 4.75' => 'Free-Form Installation', 'TempZone Ruler Cable 5.0' => 'Free-Form Installation', 'TempZone Thin Cable 4.75' => 'Free-Form Installation', # to support legacy 'TempZone Thin Cable 5.0' => 'Free-Form Installation', # to support legacy 'Environ Flex Roll' => 'Cut/Turn Installation', 'Environ Easy Mat' => 'Spot Heat Placement', 'Snow Melt Cable' => 'Free-Form Installation', 'Snow Melt Mat' => 'Cut/Turn Installation', 'Slab Heat Cable' => 'Free-Form Installation', 'Slab Heat Mat' => 'Cut/Turn Installation' }
- INSTALLATION_LEVEL_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => 'medium', 'TempZone Easy Mat' => 'easy', 'TempZone Shower Mat' => 'easy', 'TempZone Custom Mat' => 'easy', 'TempZone Cable' => 'easy', 'TempZone Ruler Cable' => 'easy', 'TempZone Thin Cable' => 'moderate', 'TempZone Cable 3.0' => 'moderate', # to support legacy 'TempZone Ruler Cable 3.0' => 'moderate', # to support legacy 'TempZone Thin Cable 3.0' => 'moderate', 'TempZone Cable 3.5' => 'easy', 'TempZone Cable 3.75' => 'easy', 'TempZone Ruler Cable 3.5' => 'easy', 'TempZone Ruler Cable 3.75' => 'easy', 'TempZone Thin Cable 3.5' => 'easy', # to support legacy 'TempZone Thin Cable 3.75' => 'easy', # to support legacy 'TempZone Cable 4.0' => 'moderate', # to support legacy 'TempZone Ruler Cable 4.0' => 'moderate', # to support legacy 'TempZone Thin Cable 4.0' => 'moderate', 'TempZone Cable 4.75' => 'easy', 'TempZone Cable 5.0' => 'easy', 'TempZone Ruler Cable 4.75' => 'easy', 'TempZone Ruler Cable 5.0' => 'easy', 'TempZone Thin Cable 4.75' => 'easy', # to support legacy 'TempZone Thin Cable 5.0' => 'easy', # to support legacy 'Environ Flex Roll' => 'medium', 'Environ Easy Mat' => 'easy', 'Snow Melt Cable' => 'moderate', 'Snow Melt Mat' => 'medium', 'Slab Heat Cable' => 'moderate', 'Slab Heat Mat' => 'medium' }
- FEATURES_BY_CONTROL_SKU_LIST =
{ 'Indoor' => { 'Programmable' => { 'TH114-AF-GA' => false, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => false, 'UTN5-4999' => false, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, 'Built-In GFCI' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, 'Comes with floor sensor' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, 'Dual Voltage' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, 'Digital Temperature Readout' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UWG5-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG4-4999-B' => true }, 'Touchscreen' => { 'TH114-AF-GA' => false, 'TH115-AF-GA-08' => false, 'TH115-AF-12VDC' => false, 'UTN4-4999' => false, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UWG5-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG4-4999-B' => true }, 'Control via Phone/Web' => { 'TH114-AF-GA' => false, 'TH115-AF-GA-08' => false, 'TH115-AF-12VDC' => false, 'UTN4-4999' => false, 'UTN5-4999' => false, 'UDG4-4999' => false, 'UDG4-4999-WY' => false, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, 'Maximum Load: 15 Amps' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true }, '3 Year Warranty' => { 'TH114-AF-GA' => true, 'TH115-AF-GA-08' => true, 'TH115-AF-12VDC' => true, 'UTN4-4999' => true, 'UTN5-4999' => true, 'UDG4-4999' => true, 'UDG4-4999-WY' => true, 'UDG4-4999-B' => true, 'UWG4-4999' => true, 'UWG5-4999-WY' => true, 'UWG4-4999-B' => true } }, 'Outdoor' => { 'Automatic' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => true, 'SCV-DUAL' => true, 'SCM-120' => false }, 'Outdoor Rated' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => false, 'SCV-DUAL' => true, 'SCM-120' => false }, 'Moisture Sensor' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => true, 'SCV-DUAL' => true, 'SCM-120' => false }, 'Air Temp Sensor' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => true, 'SCV-DUAL' => true, 'SCM-120' => false }, 'Slab Temp Sensor' => { 'SCP-120' => true, 'SCA-DUAL' => false, 'SCE-120' => true, 'SCV-DUAL' => false, 'SCM-120' => false }, 'Digital Temp Readout' => { 'SCP-120' => false, 'SCA-DUAL' => false, 'SCE-120' => true, 'SCV-DUAL' => false, 'SCM-120' => false }, 'Adjust After-Run Time' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => true, 'SCV-DUAL' => true, 'SCM-120' => false }, 'Reliable Manual Control' => { 'SCM-120' => true }, 'Timer Adjustable Up To 12 Hours' => { 'SCM-120' => true }, 'Remote Control via Smart Device' => { 'SCW-120' => true }, 'Works with IFTTT Service' => { 'SCW-120' => true }, 'On/Off Switch for Manual Operation' => { 'SCW-120' => true }, '2 Year Warranty' => { 'SCP-120' => true, 'SCA-DUAL' => true, 'SCE-120' => true, 'SCV-DUAL' => true, 'SCM-120' => true, 'SCW-120' => true } } }
- IQ_PRODUCT_HEADER_IMAGE_URL_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => 'https://ik.warmlyyours.com/img/tempzone-flex-roll-cable-c16e8f.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'TempZone Easy Mat' => 'https://ik.warmlyyours.com/img/iq-tempzone-easy-mat-thumbnail-b412fa.jpeg?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'TempZone Shower Mat' => 'https://ik.warmlyyours.com/img/iq-tempzone-shower-mat-f0bfbc.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'TempZone Cable' => 'https://ik.warmlyyours.com/img/tempzone-cable-with-grip-strips-qcungu?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'TempZone Ruler Cable' => 'https://ik.warmlyyours.com/img/iq-tempzone-ruler-cable-with-grip-strips-vmswnq.jpeg?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'TempZone Thin Cable' => 'https://ik.warmlyyours.com/img/tempzone-cable-with-grip-strips-qcungu?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Environ Flex Roll' => 'https://ik.warmlyyours.com/img/iq-environ-flex-roll-thumbnail-c253e0.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Environ Easy Mat' => 'https://ik.warmlyyours.com/img/iq-environ-easy-mat-thumbnail-b8b7eb.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Snow Melt Cable' => 'https://ik.warmlyyours.com/img/iq-snow-melt-cable-thumbnail-2ff059.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Snow Melt Mat' => 'https://ik.warmlyyours.com/img/iq-snow-melting-mat-thumbnail-a0e07c.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Slab Heat Cable' => 'https://ik.warmlyyours.com/img/iq-slab-heating-cable-thumbnail-aa33fe.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF', 'Slab Heat Mat' => 'https://ik.warmlyyours.com/img/iq-slab-heating-mat-b130ec.png?tr=w-400,h-400,cm-pad_resize,bg-FFFFFF' }
- IQ_PRODUCT_DESCRIPTION_BY_HEATING_SYSTEM_LIST =
{ 'TempZone Flex Roll' => 'Cut-and-Turn Format for Easy Installation', 'TempZone Easy Mat' => 'Targeted Heat Coverage for Small Areas', 'TempZone Shower Mat' => 'Targeted Heat Coverage for Shower Areas', 'TempZone Thin Cable 3.0' => 'Maximum Flexibility at a Minimal Cost', 'TempZone Cable 3.0' => 'Maximum Flexibility at a Minimal Cost', # to support legacy 'TempZone Cable 3.5' => 'Maximum Flexibility with Easy Installation', 'TempZone Cable 3.75' => 'Maximum Flexibility with Easy Installation', 'TempZone Ruler Cable 3.0' => 'Maximum Flexibility at a Minimal Cost', # to support legacy 'TempZone Ruler Cable 3.5' => 'Maximum Flexibility with Easy Installation', 'TempZone Ruler Cable 3.75' => 'Maximum Flexibility with Easy Installation', 'TempZone Thin Cable 3.5' => 'Maximum Flexibility with Easy Installation', # to support legacy 'TempZone Thin Cable 3.75' => 'Maximum Flexibility with Easy Installation', # to support legacy 'TempZone Thin Cable 4.0' => 'Maximum Flexibility at a Minimal Cost', 'TempZone Cable 4.0' => 'Maximum Flexibility at a Minimal Cost', # to support legacy 'TempZone Cable 4.75' => 'Maximum Flexibility with Easy Installation', 'TempZone Cable 5.0' => 'Maximum Flexibility with Easy Installation', 'TempZone Ruler Cable 4.0' => 'Maximum Flexibility at a Minimal Cost', # to support legacy 'TempZone Ruler Cable 4.75' => 'Maximum Flexibility with Easy Installation', 'TempZone Ruler Cable 5.0' => 'Maximum Flexibility with Easy Installation', 'TempZone Thin Cable 4.75' => 'Maximum Flexibility with Easy Installation', # to support legacy 'TempZone Thin Cable 5.0' => 'Maximum Flexibility with Easy Installation', # to support legacy 'Environ Flex Roll' => 'Cut/Turn Installation for Maximum Flexibility', 'Environ Easy Mat' => 'Easy & Quick Installation in Large Spaces', 'Snow Melt Cable' => 'Maximum Flexibility at a Minimal Cost', 'Snow Melt Mat' => 'Cut-and-Turn Format for Easy Installation', 'Slab Heat Cable' => 'Maximum Flexibility at a Minimal Cost', 'Slab Heat Mat' => 'Cut-and-Turn Format for Easy Installation' }
- IQ_IMAGE_NAMES_BY_HEATING_SYSTEM =
{ 'TempZone Flex Roll' => 'tempzone.png', 'TempZone Easy Mat' => 'tempzone.png', 'TempZone Shower Mat' => 'tempzone.png', 'TempZone Cable' => 'tempzone.png', 'TempZone Ruler Cable' => 'tempzone.png', 'TempZone Thin Cable' => 'tempzone.png', 'Environ Flex Roll' => 'environ.png', 'Environ Easy Mat' => 'environ.png', 'Snow Melt Cable' => 'snow-melt-cable.png', 'Snow Melt Mat' => 'snow-melt-mat.png', 'Slab Heat Cable' => 'slab-cable.png', 'Slab Heat Mat' => 'slab-mat.png' }
- DEFAULT_EXPANSION_JOINT_SPACING =
20- CABLE_SPACING_EXTRA_COPY =
{ '3.0' => '(fixing strips)', '3.5' => '(DITRA-HEAT)', '3.75' => '(Prodeso)', '4.0' => '(fixing strips)', '4.75' => '(DITRA-HEAT)', '5.0' => '(fixing strips/Prodeso)' }
- COLDEST_MONTH_AVE_TEMP_THRESHOLD =
40.0
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
- #priority ⇒ Object readonly
Belongs to collapse
- #floor_type ⇒ FloorType
- #product_line ⇒ ProductLine
- #room_type ⇒ RoomType
- #store ⇒ Store
- #sub_floor_type ⇒ SubFloorType
Methods included from Models::Auditable
Delegated Instance Attributes collapse
-
#heating_system_type_name ⇒ Object
Alias for Product_line#heating_system_type_name.
-
#product_line_is_heating_system_type ⇒ Object
Alias for Product_line#is_heating_system_type.
Class Method Summary collapse
- .application_type_select_options ⇒ Object
- .cable_spacing_for_select(cs_options = {}) ⇒ Object
- .compact_priorities ⇒ Object
-
.const_missing(name) ⇒ Object
Keep constant for backward compatibility, but delegate to method.
- .default_cable_spacings(installation_postal_code = nil, sub_floor_type = nil, _floor_type = nil) ⇒ Object
-
.default_room_type_by_environment ⇒ Object
Lazily load room type mappings to avoid N+1 queries at class load time.
- .environment_select_options ⇒ Object
- .get_default_floor_type_id_for_environment(env) ⇒ Object
- .get_default_product_line_by_heating_system_type(system) ⇒ Object
- .get_default_room_type_id_for_environment(env) ⇒ Object
- .get_default_room_type_key_for_environment(env) ⇒ Object
- .get_default_subfloor_type_id ⇒ Object
- .get_field_array_from_options(assoc_sym, options = {}) ⇒ Object
- .get_product_line_for_room(rc) ⇒ Object
- .get_product_line_from_heating_system_type_code(code) ⇒ Object
- .get_product_line_from_heating_system_type_name(name) ⇒ Object
- .get_relay_panels_from_poles(poles) ⇒ Object
- .get_suggested_underlayments(options) ⇒ Object
- .get_suggested_underlayments_for_room(rc) ⇒ Object
- .ideal_cable_spacing_select_options ⇒ Object
-
.instant_quotable_environments ⇒ Object
Cached list of environments that support instant quoting.
- .membrane_type_select_options ⇒ Object
- .next_priority ⇒ Object
- .options_for_select(assoc_sym, assoc_sort_field = 'name', assoc_name_method = 'name', options = {}, include_blank = false, assoc_key = 'id') ⇒ Object
- .options_scope(options = {}) ⇒ Object
-
.populate_options ⇒ Object
DEPRECATED USED ONLY FOR MIGRATION.
-
.prioritized ⇒ ActiveRecord::Relation<HeatingElementProductLineOption>
A relation of HeatingElementProductLineOptions that are prioritized.
- .product_line_is_iq_supported?(pl) ⇒ Boolean
- .product_line_options_for_select ⇒ Object
- .public_environment_select_options ⇒ Object
- .public_room_type_keys ⇒ Object
-
.readable_order ⇒ ActiveRecord::Relation<HeatingElementProductLineOption>
A relation of HeatingElementProductLineOptions that are readable order.
-
.reset_cached_constants! ⇒ Object
Keep constant for backward compatibility.
- .shc_cable_spacing_for_select(cs_options = {}) ⇒ Object
- .smc_cable_spacing_for_select(cs_options = {}) ⇒ Object
- .spacing_to_unit(spacing_in_inches, unit = 'in') ⇒ Object
- .tz_cable_spacing_for_select(cs_options = {}) ⇒ Object
-
.tz_cable_watts_per_sqft(cs, options) ⇒ Object
cs = cable spacing, decimal in inch.
- .underlayment_type_select_options ⇒ Object
-
.valid_membrane_types ⇒ Object
Cached list of valid membrane types to avoid expensive DISTINCT queries on every request.
- .voltage_options_for_select(heating_system_product_line, include_24 = false, environment = nil, use_smc_voltages = nil) ⇒ Object
Instance Method Summary collapse
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
Instance Attribute Details
#priority ⇒ Object (readonly)
58 |
# File 'app/models/heating_element_product_line_option.rb', line 58 validates :priority, :product_line, :floor_type, presence: true |
Class Method Details
.application_type_select_options ⇒ Object
777 778 779 |
# File 'app/models/heating_element_product_line_option.rb', line 777 def self. APPLICATION_TYPES.map { |o| o } end |
.cable_spacing_for_select(cs_options = {}) ⇒ Object
820 821 822 823 |
# File 'app/models/heating_element_product_line_option.rb', line 820 def self.cable_spacing_for_select( = {}) = { unit: 'in' }.merge() tz_cable_spacing_for_select() + shc_cable_spacing_for_select() + smc_cable_spacing_for_select() end |
.compact_priorities ⇒ Object
1168 1169 1170 1171 1172 |
# File 'app/models/heating_element_product_line_option.rb', line 1168 def self.compact_priorities HeatingElementProductLineOption.readable_order.each_with_index do |heplo, i| heplo.update_attribute(:priority, i) end end |
.const_missing(name) ⇒ Object
Keep constant for backward compatibility, but delegate to method
93 94 95 96 97 98 99 |
# File 'app/models/heating_element_product_line_option.rb', line 93 def self.const_missing(name) if name == :DEFAULT_ROOM_TYPE_BY_ENVIRONMENT default_room_type_by_environment else super end end |
.default_cable_spacings(installation_postal_code = nil, sub_floor_type = nil, _floor_type = nil) ⇒ Object
838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
# File 'app/models/heating_element_product_line_option.rb', line 838 def self.default_cable_spacings(installation_postal_code = nil, sub_floor_type = nil, _floor_type = nil) cable_spacings = if sub_floor_type [3.75, 4.0] # these are the default starting TZ cable spacings calculated for the IQ, first is with membrane, second is without else [4.0, 3.0] # these are the default starting SM cable spacings calculated for the IQ, first is default, second is to compete with lower wattage systems out there end if installation_postal_code && sub_floor_type && avg_temp = AverageMonthlyTemperature.get_from_postal_code(installation_postal_code) coldest_month_ave_temp = avg_temp[:average_temperatures]&.min if coldest_month_ave_temp && (coldest_month_ave_temp >= COLDEST_MONTH_AVE_TEMP_THRESHOLD) && (sub_floor_type&.seo_key == 'wood') # 4 " spacing for wood subfloors in these zones cable_spacings = [3.75, 4.0] # these are the default starting TZ cable spacings calculated for the IQ, first is with membrane, second is without end end cable_spacings end |
.default_room_type_by_environment ⇒ Object
Lazily load room type mappings to avoid N+1 queries at class load time
84 85 86 87 88 89 90 |
# File 'app/models/heating_element_product_line_option.rb', line 84 def self.default_room_type_by_environment @default_room_type_by_environment ||= begin seo_keys = ENVIRONMENTS_HASH.values.map { |v| v[:default_room_type_seo_key] } room_types_by_key = RoomType.where(seo_key: seo_keys).index_by(&:seo_key) ENVIRONMENTS_HASH.transform_values { |v| room_types_by_key[v[:default_room_type_seo_key]]&.name } end end |
.environment_select_options ⇒ Object
781 782 783 |
# File 'app/models/heating_element_product_line_option.rb', line 781 def self. ENVIRONMENTS end |
.get_default_floor_type_id_for_environment(env) ⇒ Object
766 767 768 |
# File 'app/models/heating_element_product_line_option.rb', line 766 def self.get_default_floor_type_id_for_environment(env) FloorType.find_by(name: DEFAULT_FLOOR_TYPE_BY_ENVIRONMENT[env]).id end |
.get_default_product_line_by_heating_system_type(system) ⇒ Object
770 771 772 773 774 775 |
# File 'app/models/heating_element_product_line_option.rb', line 770 def self.get_default_product_line_by_heating_system_type(system) pl = nil url = PRODUCT_LINE_BY_HEATING_SYSTEM_TYPE[system] pl = ProductLine.find_by(slug_ltree: LtreePaths.slug_ltree_from_legacy_hyphen_url(url))&.id if url pl end |
.get_default_room_type_id_for_environment(env) ⇒ Object
754 755 756 |
# File 'app/models/heating_element_product_line_option.rb', line 754 def self.get_default_room_type_id_for_environment(env) RoomType.find_by(name: DEFAULT_ROOM_TYPE_BY_ENVIRONMENT[env]).id end |
.get_default_room_type_key_for_environment(env) ⇒ Object
758 759 760 |
# File 'app/models/heating_element_product_line_option.rb', line 758 def self.get_default_room_type_key_for_environment(env) RoomType.find_by(name: DEFAULT_ROOM_TYPE_BY_ENVIRONMENT[env]).seo_key end |
.get_default_subfloor_type_id ⇒ Object
762 763 764 |
# File 'app/models/heating_element_product_line_option.rb', line 762 def self.get_default_subfloor_type_id SubFloorType.find_by(name: DEFAULT_SUB_FLOOR_TYPE).id end |
.get_field_array_from_options(assoc_sym, options = {}) ⇒ Object
930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 |
# File 'app/models/heating_element_product_line_option.rb', line 930 def self.(assoc_sym, = {}) # Check if this is a direct field on the model or an association is_direct_field = !column_names.include?("#{assoc_sym}_id") # Build the base query with filters and prioritized ordering # The .prioritized scope is important because callers often use .first to get the highest-priority value base_query = HeatingElementProductLineOption.joins(:product_line).prioritized .each do |k, v| base_query = base_query.where(k => v) unless k == assoc_sym || v.nil? end if is_direct_field # For direct fields (like :environment, :ideal_cable_spacing), pluck and get unique values # We can't use DISTINCT with ORDER BY on non-selected columns, so we pluck and uniq in Ruby base_query.pluck(assoc_sym).uniq else # For associations, get distinct foreign key values base_query.pluck("#{assoc_sym}_id").uniq end end |
.get_product_line_for_room(rc) ⇒ Object
975 976 977 978 979 980 981 982 |
# File 'app/models/heating_element_product_line_option.rb', line 975 def self.get_product_line_for_room(rc) res = nil opt = HeatingElementProductLineOption.all.where(floor_type_id: rc.floor_type_id) opt = opt.where(sub_floor_type_id: rc.sub_floor_type_id) if rc.sub_floor_type_id opt = opt.prioritized.first res = opt.product_line if opt res end |
.get_product_line_from_heating_system_type_code(code) ⇒ Object
967 968 969 970 971 972 973 |
# File 'app/models/heating_element_product_line_option.rb', line 967 def self.get_product_line_from_heating_system_type_code(code) pl = nil name = HEATING_SYSTEM_TYPE_BY_LEGACY_PRODUCT[code] pl_id = get_default_product_line_by_heating_system_type(name) pl = ProductLine.find(pl_id) if pl_id.present? pl end |
.get_product_line_from_heating_system_type_name(name) ⇒ Object
960 961 962 963 964 965 |
# File 'app/models/heating_element_product_line_option.rb', line 960 def self.get_product_line_from_heating_system_type_name(name) pl = nil pl_id = get_default_product_line_by_heating_system_type(name) pl = ProductLine.find(pl_id) if pl_id.present? pl end |
.get_relay_panels_from_poles(poles) ⇒ Object
1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 |
# File 'app/models/heating_element_product_line_option.rb', line 1116 def self.get_relay_panels_from_poles(poles) # get proper relay panels based on number of poles relay_panels_sku_qty = {} relay_panels_sku_qty['RLY-4PL-CC'] = 0 relay_panels_sku_qty['RLY-8PL-CC'] = 0 relay_panels_sku_qty['RLY-12PL-CC'] = 0 return relay_panels_sku_qty unless poles > 0 if poles <= 4 relay_panels_sku_qty['RLY-4PL-CC'] = 1 elsif poles <= 8 relay_panels_sku_qty['RLY-8PL-CC'] = 1 elsif poles <= 12 relay_panels_sku_qty['RLY-12PL-CC'] = 1 elsif poles <= 16 relay_panels_sku_qty['RLY-8PL-CC'] = 2 elsif poles > 16 relay_panels_sku_qty = {} qty_4 = 0 qty_8 = 0 qty_12 = if (poles % 12) > 8 (poles / 12).ceil else (poles / 12).floor end poles_left = poles - (12 * qty_12) if poles_left > 4 qty_8 = if (poles_left % 8) > 4 (poles_left / 8).ceil else (poles_left / 8).floor end poles_left -= (8 * qty_8) end qty_4 = (poles_left / 4).ceil if poles_left > 0 relay_panels_sku_qty['RLY-12PL-CC'] = qty_12 if qty_12 > 0 relay_panels_sku_qty['RLY-8PL-CC'] = qty_8 if qty_8 > 0 relay_panels_sku_qty['RLY-4PL-CC'] = qty_4 if qty_4 > 0 end relay_panels_sku_qty end |
.get_suggested_underlayments(options) ⇒ Object
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 |
# File 'app/models/heating_element_product_line_option.rb', line 989 def self.get_suggested_underlayments() logger.debug("get_suggested_underlayments, options: #{.inspect}") raise 'Insulation Sqft must be greater than 0' unless [:sqft].to_i > 0 u_lines = {} add_one_extra = [:add_one_extra] add_one_extra = false if add_one_extra.nil? [:product_line_id] ||= HeatingElementProductLineOption.get_product_line_from_heating_system_type_name([:heating_system_type_name]) if [:heating_system_type_name] opt = HeatingElementProductLineOption.all opt = opt.where(floor_type_id: [:floor_type_id]) unless [:floor_type_id].blank? opt = opt.where(product_line_id: [:product_line_id]) unless [:product_line_id].blank? opt = opt.where(sub_floor_type_id: [:sub_floor_type_id]) unless [:sub_floor_type_id].blank? opt = opt.where(ideal_cable_spacing: [:ideal_cable_spacing]) unless [:ideal_cable_spacing].blank? opt = opt.where(membrane_recommended: [:membrane_recommended]) unless [:membrane_recommended].nil? # keep .nil? for boolean - false is a valid value opt = opt.prioritized.first add_thermalsheet = opt && opt.underlayment_recommended && opt.underlayment_type == 'ThermalSheet' add_prodeso = opt && opt.membrane_recommended && opt.membrane_type.index('Prodeso') if add_thermalsheet && (thermalsheet_item = Item.find_by(sku: ItemConstants::THERMALSHEET_SHEET_SKU)) thermalsheet_units = thermalsheet_item.get_quantity_from_sqft([:sqft], add_one_extra) if thermalsheet_units > 0 u_lines[thermalsheet_item.sku] = { quantity: thermalsheet_units, name: thermalsheet_item.name, detailed_description: thermalsheet_item.detailed_description, item_id: thermalsheet_item.id } end end if add_prodeso # Calculate Prodeso membrane quantities - compare rolls-only vs sheets-only, pick cheaper # Rule: never mix rolls and sheets, use whichever option is more cost-effective catalog_id = [:catalog_id] || 1 area_sqft = [:sqft].to_f prodeso_items = Item.membranes.includes(:catalog_items).index_by(&:sku) # Calculate sheets-only cost (use 10.8 sqft sheets) sheet_item = prodeso_items[ItemConstants::MEMBRANE_SHEET_SKU] sheet_sqft = sheet_item&.sqft || 10.8 sheet_price = sheet_item&.catalog_items&.detect { |ci| ci.catalog_id == catalog_id }&.amount || 59.0 sheets_needed = (area_sqft / sheet_sqft).ceil sheets_cost = sheets_needed * sheet_price # Calculate rolls-only cost (use 54 and/or 162 sqft rolls) roll_54 = prodeso_items[ItemConstants::MEMBRANE_SMALL_SKU] roll_162 = prodeso_items[ItemConstants::MEMBRANE_LARGE_SKU] roll_54_sqft = roll_54&.sqft || 54.0 roll_162_sqft = roll_162&.sqft || 162.0 roll_54_price = roll_54&.catalog_items&.detect { |ci| ci.catalog_id == catalog_id }&.amount || 209.0 roll_162_price = roll_162&.catalog_items&.detect { |ci| ci.catalog_id == catalog_id }&.amount || 509.0 # Find optimal roll combination using cost optimization # Try different combinations and pick the cheapest best_rolls_qty = nil best_rolls_cost = Float::INFINITY # Helper: ceiling that's forgiving of tiny remainders (< 1 sqft gap is acceptable) forgiving_ceil = ->(area, unit_sqft) { ratio = area / unit_sqft (ratio - ratio.floor) < 0.02 ? ratio.floor.to_i : ratio.ceil.to_i } # Option 1: Use only 54 sqft rolls qty_54_only = [forgiving_ceil.call(area_sqft, roll_54_sqft), 1].max cost_54_only = qty_54_only * roll_54_price if cost_54_only < best_rolls_cost best_rolls_cost = cost_54_only best_rolls_qty = { ItemConstants::MEMBRANE_SMALL_SKU => qty_54_only } end # Option 2: Use 162 sqft rolls + 54 sqft rolls for remainder if area_sqft > roll_54_sqft qty_162 = (area_sqft / roll_162_sqft).floor remainder = area_sqft - (qty_162 * roll_162_sqft) qty_54 = remainder > 0 ? forgiving_ceil.call(remainder, roll_54_sqft) : 0 cost_mixed = (qty_162 * roll_162_price) + (qty_54 * roll_54_price) if cost_mixed < best_rolls_cost best_rolls_cost = cost_mixed best_rolls_qty = {} best_rolls_qty[ItemConstants::MEMBRANE_LARGE_SKU] = qty_162 if qty_162.positive? best_rolls_qty[ItemConstants::MEMBRANE_SMALL_SKU] = qty_54 if qty_54.positive? end # Option 3: Round up to one more 162 roll (might be cheaper than multiple 54s) qty_162_rounded = forgiving_ceil.call(area_sqft, roll_162_sqft) cost_162_only = qty_162_rounded * roll_162_price if cost_162_only < best_rolls_cost best_rolls_cost = cost_162_only best_rolls_qty = { ItemConstants::MEMBRANE_LARGE_SKU => qty_162_rounded } end end rolls_qty = best_rolls_qty rolls_cost = best_rolls_cost rolls_cost = (rolls_qty[ItemConstants::MEMBRANE_LARGE_SKU] || 0) * roll_162_price + (rolls_qty[ItemConstants::MEMBRANE_SMALL_SKU] || 0) * roll_54_price # Rule: If area >= smallest roll size, always use rolls (more practical for installation) # Otherwise, compare cost and pick cheaper option use_rolls = area_sqft >= roll_54_sqft || rolls_cost < sheets_cost if use_rolls rolls_qty.each do |sku, qty| next unless qty.positive? item = prodeso_items[sku] u_lines[sku] = { quantity: qty, name: item.name, detailed_description: item.detailed_description, item_id: item.id } end elsif sheet_item u_lines[sheet_item.sku] = { quantity: sheets_needed, name: sheet_item.name, detailed_description: sheet_item.detailed_description, item_id: sheet_item.id } end end logger.debug("get_suggested_underlayments, u_lines: #{u_lines.inspect}") u_lines end |
.get_suggested_underlayments_for_room(rc) ⇒ Object
984 985 986 987 |
# File 'app/models/heating_element_product_line_option.rb', line 984 def self.get_suggested_underlayments_for_room(rc) HeatingElementProductLineOption.get_suggested_underlayments({ sqft: rc.insulation_surface, sub_floor_type_id: rc.sub_floor_type_id, floor_type_id: rc.floor_type_id, product_line_id: rc.heating_system_product_line_id, catalog_id: rc.catalog.id }) end |
.ideal_cable_spacing_select_options ⇒ Object
789 790 791 |
# File 'app/models/heating_element_product_line_option.rb', line 789 def self. cable_spacing_for_select end |
.instant_quotable_environments ⇒ Object
Cached list of environments that support instant quoting
111 112 113 |
# File 'app/models/heating_element_product_line_option.rb', line 111 def self.instant_quotable_environments @instant_quotable_environments ||= (:environment, { instant_quotable: true }).uniq end |
.membrane_type_select_options ⇒ Object
797 798 799 |
# File 'app/models/heating_element_product_line_option.rb', line 797 def self. MEMBRANE_TYPES.map { |o| [o] } end |
.next_priority ⇒ Object
1164 1165 1166 |
# File 'app/models/heating_element_product_line_option.rb', line 1164 def self.next_priority (HeatingElementProductLineOption.maximum(:priority) || 0) + 1 end |
.options_for_select(assoc_sym, assoc_sort_field = 'name', assoc_name_method = 'name', options = {}, include_blank = false, assoc_key = 'id') ⇒ Object
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
# File 'app/models/heating_element_product_line_option.rb', line 889 def self.(assoc_sym, assoc_sort_field = 'name', assoc_name_method = 'name', = {}, include_blank = false, assoc_key = 'id') Rails.logger.debug("HeatingElementProductLineOption.options_for_select", assoc_sym: assoc_sym, assoc_sort_field: assoc_sort_field) assoc_fk = "#{assoc_sym}_id" # Build the base query with filters base_query = HeatingElementProductLineOption.all .each do |k, v| base_query = base_query.where(k => v) unless k == assoc_sym || v.nil? end # Get distinct association IDs that match the filters matching_ids = base_query.where.not(assoc_fk => nil).distinct.pluck(assoc_fk) return [] if matching_ids.empty? # Query the association table directly for just the fields we need assoc_class = reflect_on_association(assoc_sym).klass order_clause = assoc_sort_field ? { assoc_sort_field => :asc } : {} # Check if assoc_name_method is a database column or a Ruby method # If it's a method (like heating_system_type_name), we need to load objects and call the method is_column = assoc_class.column_names.include?(assoc_name_method.to_s) is_key_column = assoc_class.column_names.include?(assoc_key.to_s) if is_column && is_key_column # Efficient path: both are columns, use pluck = assoc_class .where(id: matching_ids) .order(order_clause) .pluck(assoc_name_method, assoc_key) else # Fallback path: one or both are methods, load objects records = assoc_class.where(id: matching_ids).order(order_clause) = records.map { |r| [r.public_send(assoc_name_method), r.public_send(assoc_key)] } end .insert(0, ['----', nil]) if .any? && include_blank == true end |
.options_scope(options = {}) ⇒ Object
951 952 953 954 955 956 957 958 |
# File 'app/models/heating_element_product_line_option.rb', line 951 def self.( = {}) Rails.logger.debug("HeatingElementProductLineOption.options_scope") res = HeatingElementProductLineOption.includes(:product_line, :sub_floor_type, :floor_type) ( || {}).each do |k, v| res = res.where(k => v) if v.present? end res end |
.populate_options ⇒ Object
DEPRECATED USED ONLY FOR MIGRATION
1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 |
# File 'app/models/heating_element_product_line_option.rb', line 1184 def self. # DEPRECATED USED ONLY FOR MIGRATION application_types = HeatingElementProductLineOption::APPLICATION_TYPES env_by_app_type = { 'FH' => ['Indoor'], 'SM' => ['Outdoor'], 'CH' => ['Countertop'] } heating_system_types = ['TempZone Flex Roll', 'TempZone Easy Mat', 'Environ Flex Roll', 'Environ Easy Mat', 'Slab Heat Cable', 'Slab Heat Mat', 'Snow Melt Cable', 'Snow Melt Mat'] heating_system_type_pl_ids = [12, 102, 99, 21, 25, 28, 37, 40] priority = 0 application_types.each do |application_type| # puts "application_type: #{application_type}" env_by_app_type[application_type].each do |environment| # puts "environment: #{environment}" sub_floor_type_ids ||= SubFloorType.active.by_name.map { |sf| sf.id } sub_floor_type_ids = [nil] if environment == 'Outdoor' # sub floor only applies to Indoor sub_floor_type_ids.each do |sub_floor_type_id| sub_floor_type = nil sub_floor_type = SubFloorType.find(sub_floor_type_id) if sub_floor_type_id # puts "sub_floor_type: #{sub_floor_type ? sub_floor_type.name : 'nil'}" floor_types = FloorType.active.by_environment(environment) floor_types.each do |floor_type| # puts "floor_type: #{floor_type.name}" # Need to exclude unfinished stamped concrete (id 5) except for newly poured concrete sub floor (id 3) if floor_type.id == 5 and sub_floor_type.id != 3 # puts "skipping floor_type floor_type: #{floor_type.name} and sub_floor_type: #{sub_floor_type ? sub_floor_type.name : 'nil'}" else require_expansion_joint = floor_type.require_expansion_joint? # use floor type to determine this for now # puts "require_expansion_joint: #{require_expansion_joint}" # get all public and not public (by passing for_iq=nil) heating_types for floor_type HeatingSystem.heating_system_types_for_floor_type(floor_type, room_type = nil, for_iq = nil).each do |heating_system_type| # get heating system type's corresponding product line # puts "heating_system_type: #{heating_system_type}" ind = heating_system_types.index(heating_system_type) product_line = ProductLine.find(heating_system_type_pl_ids[ind]) # puts "product_line: #{product_line.name}" # use legacy HeatingSystem to populate various options heating_system = HeatingSystem.new(heating_system_type) require_cable_spacing = heating_system.require_cable_spacing? # puts "require_cable_spacing: #{require_cable_spacing}" ideal_cable_spacing = nil ideal_cable_spacing = heating_system.ideal_cable_spacing(floor_type) if require_cable_spacing # puts "ideal_cable_spacing: #{ideal_cable_spacing}" is_public = false heating_system_types_public = HeatingSystem.heating_system_types_for_floor_type(floor_type, room_type = nil, for_iq = true) # figure out if public by passing in for_iq true and seeing current heating_system_type is in there is_public = true if heating_system_types_public.include?(heating_system_type) # puts "is_public: #{is_public}" # find insulation/underlayment options, here we reproduce some of the logic in floor_type's suggested_underlayment method underlayment_recommended = false add_thermalsheet = false product_type = begin heating_system.code rescue StandardError nil end product_type ||= floor_type.product # default to floor type's recommendation if %w[EV2 TZ EVFR TZEM].include? product_type && !((sub_floor_type and sub_floor_type.name.to_s.downcase.index('wood')) || floor_type.is_carpet?) add_thermalsheet = true end underlayment_recommended = true if add_thermalsheet # puts "underlayment_recommended: #{underlayment_recommended}" underlayment_type = nil underlayment_type = 'ThermalSheet' if add_thermalsheet # puts "underlayment_type: #{underlayment_type}" # for underlayment_r_value, just use this if then else, which is the only sense I can make out from the table produced by Scott here: https://docs.google.com/a/warmlyyours.com/spreadsheet/ccc?key=0AlWFu-aXWRVZdGxxaFBjamVSLVVKaFFiSGt0XzJOamc#gid=1 floor_type_name_lower_case = floor_type.name.downcase if heating_system_type.downcase.index('tempzone') and (floor_type_name_lower_case.index('bamboo') or floor_type_name_lower_case.index('') or floor_type_name_lower_case.index('carpet') or floor_type_name_lower_case.index('engineered') or floor_type_name_lower_case.index('laminate')) 'L' end 'H' if heating_system_type.downcase.index('environ') and floor_type_name_lower_case.index('carpet') # puts "underlayment_r_value: #{underlayment_r_value}" # great, now create the damn thing priority += 1 # puts "priority: #{priority}" attributes = { priority: priority, application_type: application_type, environment: environment, sub_floor_type_id: sub_floor_type_id, floor_type_id: floor_type.id, product_line_id: product_line.id, is_public: is_public, require_expansion_joint: require_expansion_joint, require_cable_spacing: require_cable_spacing, ideal_cable_spacing: ideal_cable_spacing, underlayment_recommended: underlayment_recommended, underlayment_type: underlayment_type } # puts "creating HeatingElementProductLineOption: attributes: #{attributes.inspect}" HeatingElementProductLineOption.create(attributes) end end end end end end end |
.prioritized ⇒ ActiveRecord::Relation<HeatingElementProductLineOption>
A relation of HeatingElementProductLineOptions that are prioritized. Active Record Scope
66 |
# File 'app/models/heating_element_product_line_option.rb', line 66 scope :prioritized, -> { joins(:product_line).order('heating_element_product_line_options.is_public DESC, heating_element_product_line_options.priority, product_lines.priority') } |
.product_line_is_iq_supported?(pl) ⇒ Boolean
1174 1175 1176 1177 1178 |
# File 'app/models/heating_element_product_line_option.rb', line 1174 def self.product_line_is_iq_supported?(pl) res = false res = PRODUCT_LINE_BY_HEATING_SYSTEM_TYPE[pl.heating_system_type_name].present? if pl and pl.heating_system_type_name.present? res end |
.product_line_options_for_select ⇒ Object
1158 1159 1160 |
# File 'app/models/heating_element_product_line_option.rb', line 1158 def self. HeatingElementProductLineOption.joins(:product_line).pluck(Arel.sql('distinct product_lines.lineage_expanded, product_lines.id')).sort end |
.public_environment_select_options ⇒ Object
785 786 787 |
# File 'app/models/heating_element_product_line_option.rb', line 785 def self. PUBLIC_ENVIRONMENTS_HASH.map { |k, _v| k } end |
.public_room_type_keys ⇒ Object
101 102 103 |
# File 'app/models/heating_element_product_line_option.rb', line 101 def self.public_room_type_keys @public_room_type_keys ||= RoomType.by_environment(PUBLIC_ENVIRONMENTS).pluck(:seo_key) end |
.readable_order ⇒ ActiveRecord::Relation<HeatingElementProductLineOption>
A relation of HeatingElementProductLineOptions that are readable order. Active Record Scope
63 64 65 |
# File 'app/models/heating_element_product_line_option.rb', line 63 scope :readable_order, -> { joins(:floor_type).order('heating_element_product_line_options.application_type ASC, heating_element_product_line_options.environment ASC, heating_element_product_line_options.sub_floor_type_id ASC, floor_types.name ASC, heating_element_product_line_options.priority ASC').readonly(false) } |
.reset_cached_constants! ⇒ Object
Keep constant for backward compatibility
116 117 118 119 120 121 |
# File 'app/models/heating_element_product_line_option.rb', line 116 def self.reset_cached_constants! @default_room_type_by_environment = nil @public_room_type_keys = nil @valid_membrane_types = nil @instant_quotable_environments = nil end |
.shc_cable_spacing_for_select(cs_options = {}) ⇒ Object
831 832 833 834 835 836 |
# File 'app/models/heating_element_product_line_option.rb', line 831 def self.shc_cable_spacing_for_select( = {}) = { unit: 'in' }.merge() [["SHC 12 watts/sqft - #{RubyUnits::Unit.new('6.0 in').to_s([:unit])}", 6.0], ["SHC 15 watts/sqft - #{RubyUnits::Unit.new('5.0 in').to_s([:unit])}", 5.0], ["SHC 17 watts/sqft - #{RubyUnits::Unit.new('4.0 in').to_s([:unit])}", 4.0], ["SHC 20 watts/sqft - #{RubyUnits::Unit.new('3.0 in').to_s([:unit])}", 3.0]] end |
.smc_cable_spacing_for_select(cs_options = {}) ⇒ Object
825 826 827 828 829 |
# File 'app/models/heating_element_product_line_option.rb', line 825 def self.smc_cable_spacing_for_select( = {}) = { unit: 'in' }.merge() [["SMC 25 watts/sqft - #{RubyUnits::Unit.new('6.0 in').to_s([:unit])}", 6.0], ["SMC up to 31.5 watts/sqft - #{RubyUnits::Unit.new('5.0 in').to_s([:unit])}", 5.0], ["SMC up to 33 watts/sqft - #{RubyUnits::Unit.new('4.5 in').to_s([:unit])}", 4.5], ["SMC up to 38.5 watts/sqft - #{RubyUnits::Unit.new('4.0 in').to_s([:unit])}", 4.0], ["SMC up to 43 watts/sqft - #{RubyUnits::Unit.new('3.5 in').to_s([:unit])}", 3.5], ["SMC up to 50 watts/sqft - #{RubyUnits::Unit.new('3.0 in').to_s([:unit])}", 3.0], ["SMC up to 60 watts/sqft - #{RubyUnits::Unit.new('2.5 in').to_s([:unit])}", 2.5]] end |
.spacing_to_unit(spacing_in_inches, unit = 'in') ⇒ Object
873 874 875 876 877 878 |
# File 'app/models/heating_element_product_line_option.rb', line 873 def self.spacing_to_unit(spacing_in_inches, unit = 'in') n = RubyUnits::Unit.new(spacing_in_inches, 'in') n = n.convert_to(unit) if unit != 'in' n = number_with_precision(n.scalar, strip_insignificant_zeros: true) "#{n} #{unit}" end |
.tz_cable_spacing_for_select(cs_options = {}) ⇒ Object
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 |
# File 'app/models/heating_element_product_line_option.rb', line 855 def self.tz_cable_spacing_for_select( = {}) = { unit: 'in', tz_cable_pl_url: ProductLineUrls::FLOOR_HEATING_TEMPZONE_CABLE }.merge() opts = if [:sftid] and sft = SubFloorType.find([:sftid]).name and sft.index('Concrete') # disable 4 inch and greater spacing for concrete subfloors [] else [["TZ (Prodeso membrane) #{tz_cable_watts_per_sqft(5.0, )} watts/sqft - #{spacing_to_unit(5.0, [:unit])} spacing", 5.0], ["TZ (DITRA membrane) #{tz_cable_watts_per_sqft(4.75, )} watts/sqft - #{spacing_to_unit(4.75, [:unit])} spacing", 4.75], ["TZ #{tz_cable_watts_per_sqft(4.0, )} watts/sqft - #{spacing_to_unit(4.0, [:unit])} spacing", 4.0]] end opts += [["TZ (Prodeso membrane / Free form) #{tz_cable_watts_per_sqft(3.75, )} watts/sqft - #{spacing_to_unit(3.75, [:unit])} spacing", 3.75]] opts += [["TZ (DITRA membrane / Free form) #{tz_cable_watts_per_sqft(3.5, )} watts/sqft - #{spacing_to_unit(3.5, [:unit])} spacing", 3.5]] opts += [["TZ #{tz_cable_watts_per_sqft(3.0, )} watts/sqft - #{spacing_to_unit(3.0, [:unit])} spacing", 3.0]] opts += [["TZ (Alternating 2/3 stud Prodeso Membrane 2.5/3.75\" Spacing) #{tz_cable_watts_per_sqft(3.125, )} average watts/sqft - average #{spacing_to_unit(3.125, [:unit])} spacing", 3.125]] unless [:is_public] == true opts += [["TZ (Alternating 2/3 stud DITRA Membrane 2.3/3.5\" Spacing) #{tz_cable_watts_per_sqft(2.9, )} average watts/sqft - average #{spacing_to_unit(2.9, [:unit])} spacing", 2.9]] unless [:is_public] == true opts end |
.tz_cable_watts_per_sqft(cs, options) ⇒ Object
cs = cable spacing, decimal in inch. So 3.5 for 3" 1/2
881 882 883 884 885 886 887 |
# File 'app/models/heating_element_product_line_option.rb', line 881 def self.tz_cable_watts_per_sqft(cs, ) slug = LtreePaths.slug_ltree_from_legacy_hyphen_url([:tz_cable_pl_url]) || [:tz_cable_pl_url].to_s tz_cable_pl = ProductLine.find_by(slug_ltree: slug) watts_per_sqft = RoomConfiguration::WATTS_PER_SQUARE_FOOT["#{tz_cable_pl.heating_system_type_name} #{cs}"] watts_per_sqft ||= (RoomConfiguration::WATTS_PER_SQUARE_FOOT["#{tz_cable_pl.heating_system_type_name}"] * 3.0 / cs).round(1) watts_per_sqft end |
.underlayment_type_select_options ⇒ Object
793 794 795 |
# File 'app/models/heating_element_product_line_option.rb', line 793 def self. UNDERLAYMENT_TYPES.map { |o| [o] } end |
.valid_membrane_types ⇒ Object
Cached list of valid membrane types to avoid expensive DISTINCT queries on every request
106 107 108 |
# File 'app/models/heating_element_product_line_option.rb', line 106 def self.valid_membrane_types @valid_membrane_types ||= pluck(Arel.sql('distinct membrane_type')).compact end |
.voltage_options_for_select(heating_system_product_line, include_24 = false, environment = nil, use_smc_voltages = nil) ⇒ Object
801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
# File 'app/models/heating_element_product_line_option.rb', line 801 def self.(heating_system_product_line, include_24 = false, environment = nil, use_smc_voltages = nil) hs_name = heating_system_product_line&.heating_system_type_name if /TempZone Custom Mat/i.match?(hs_name) res = [120, 208, 240] elsif /TempZone/i.match?(hs_name) res = [120, 240] res += [24] if include_24 == true elsif /Countertop Heater/i.match?(hs_name) res = [] elsif (hs_name =~ /Snow/i && hs_name =~ /Cable/i) or hs_name =~ /Pipe Freeze Protection/i or hs_name =~ /Roof & Gutter/i res = [120, 208, 240, 277] else res = [120, 240] res += [24] if include_24 == true res += [208, 277] if environment.to_s.downcase == 'outdoor' and use_smc_voltages end res end |
Instance Method Details
#floor_type ⇒ FloorType
Validations:
53 |
# File 'app/models/heating_element_product_line_option.rb', line 53 belongs_to :floor_type, inverse_of: :heating_element_product_line_options, optional: true |
#heating_system_type_name ⇒ Object
Alias for Product_line#heating_system_type_name
61 |
# File 'app/models/heating_element_product_line_option.rb', line 61 delegate :heating_system_type_name, to: :product_line |
#name_with_cable_spacing ⇒ Object
1268 1269 1270 1271 1272 1273 1274 1275 |
# File 'app/models/heating_element_product_line_option.rb', line 1268 def name_with_cable_spacing extra = '' if ideal_cable_spacing.present? extra = " at #{ideal_cable_spacing} inch spacing" extra += " #{CABLE_SPACING_EXTRA_COPY[ideal_cable_spacing.to_s]}" if product_line.slug_ltree.to_s.include?('tempzone.cable') end "#{product_line.heating_system_type_name}#{extra}" end |
#product_line ⇒ ProductLine
Validations:
54 |
# File 'app/models/heating_element_product_line_option.rb', line 54 belongs_to :product_line, inverse_of: :heating_element_product_line_options, optional: true |
#product_line_is_heating_system_type ⇒ Object
Alias for Product_line#is_heating_system_type
1162 |
# File 'app/models/heating_element_product_line_option.rb', line 1162 delegate :is_heating_system_type, to: :product_line, prefix: true |
#room_type ⇒ RoomType
56 |
# File 'app/models/heating_element_product_line_option.rb', line 56 belongs_to :room_type, inverse_of: :heating_element_product_line_options, optional: true |
#store ⇒ Store
55 |
# File 'app/models/heating_element_product_line_option.rb', line 55 belongs_to :store, inverse_of: :heating_element_product_line_options, optional: true |
#sub_floor_type ⇒ SubFloorType
52 |
# File 'app/models/heating_element_product_line_option.rb', line 52 belongs_to :sub_floor_type, inverse_of: :heating_element_product_line_options, optional: true |
#summary ⇒ Object
1180 1181 1182 |
# File 'app/models/heating_element_product_line_option.rb', line 1180 def summary "#{is_public ? 'Public' : 'Internal'}>#{application_type}>#{environment}>#{sub_floor_type.name + '>' if sub_floor_type}#{floor_type.name}>#{product_line.heating_system_type_name}" end |