Class: Pdf::Document::PriceList

Inherits:
Object
  • Object
show all
Includes:
ActionView::Helpers::NumberHelper, ActiveModel::API, ActiveModel::Attributes, ActiveModel::Validations, ActiveModel::Validations::Callbacks, Normalizr::Concern, Base, StripAttributes
Defined in:
app/services/pdf/document/price_list.rb

Constant Summary collapse

SECTIONS =
{
  'Floor Heating': {
    fh_tempzone_flex_twin_120: 'TempZone Flex 120V',
    fh_tempzone_flex_twin_240: 'TempZone Flex 240V',
    fh_tempzone_cable_120: 'TempZone Cable 120V',
    fh_tempzone_cable_240: 'TempZone Cable 240V',
    fh_tempzone_ruler_cable_120: 'TempZone Ruler Cable 120V',
    fh_tempzone_ruler_cable_240: 'TempZone Ruler Cable 240V',
    fh_tempzone_easy_twin_120: 'TempZone Easy Mat 120V',
    fh_tempzone_shower_bench: 'TempZone Shower Bench Mat',
    fh_tempzone_shower_floor: 'TempZone Shower Floor Mat',
    fh_tempzone_custom: 'TempZone Custom Mat',
    fh_environ_flex_120: 'Environ Flex 120V',
    fh_environ_flex_240: 'Environ Flex 240V',
    fh_environ_easy_120: 'Environ Easy Mat 120V',
    fh_environ_easy_240: 'Environ Easy Mat 240V',
    fh_slab_cable: 'Slab Heating Cable',
    fh_slab_mat: 'Slab Heating Mat',
    fh_controls: 'Controls',
    fh_power_modules: 'Power Modules',
    fh_relay_panels: 'Relay Panels',
    fh_underlayment: 'Underlayment',
    fh_rough_in_kits: 'Rough-in Kits',
    fh_installation_kits: 'Installation Kits',
    fh_accessories: 'Accessories',
    fh_spare_parts: 'Spare Parts'
  },
  'Towel Warmers': {
    tw_classic_plugin: 'Classic Plug-in',
    tw_classic_hardwired: 'Classic Hardwired',
    tw_classic_dual: 'Classic Dual Connection (Plug-in or Hardwired)',
    tw_cosmopolitan_hardwired: 'Cosmopolitan Hardwired',
    tw_controls: 'Towel Warmer Controls'
  },
  'Radiant Panels': {
    rp_lava_glass: 'Lava Glass',
    rp_lava_mirror: 'Lava Mirror',
    rp_lava_crystal: 'Lava Crystal',
    rp_lava_light: 'Lava Light',
    rp_lava_accessories: 'Lava Accessories',
    rp_ember_flex: 'Ember Flex',
    rp_ember_glass: 'Ember Glass',
    rp_ember_mirror: 'Ember Mirror',
    rp_ember_accessories: 'Ember Accessories',
    rp_controls: 'Controls'
  },
  Mirrors: {
    mirror_led_marquee: 'Marquee LED Mirrors',
    mirror_defoggers: 'Mirror Defoggers'
  },
  'FeelsWarm® Countertop Heating': {
    ch_standard: 'Standard Kit',
    ch_custom: 'Custom Kit',
    ch_controls: 'Controls'
  },
  'Shower Kits': {
    sk_shower_pan_kit: 'Shower Pan Kit',
    sk_drain_assembly_kit: 'Drain Assembly Kit',
    sk_drain_grate_covers: 'Drain Grate Covers',
    sk_shower_floor_heating_kits: 'Shower Floor Heating Kits',
    sk_accessories: 'Accessories',
    sk_drain_assemblies: 'Drain Assemblies'
  },
  'Snow Melting': {
    sm_mat_120: 'Mat 120V',
    sm_mat_240: 'Mat 240V',
    sm_cable_120: 'Cable 120V',
    sm_cable_240: 'Cable 240V',
    sm_cable_208: 'Cable 208V',
    sm_cable_277: 'Cable 277V',
    sm_controls: 'Controls',
    sm_sensors: 'Sensors',
    sm_relay_panels: 'Relay Panels',
    sm_accessories: 'Accessories'
  },
  'Roof & Gutter Deicing': {
    rgd_self_regulating_cable_120: 'Self Regulating Cable 120V',
    rgd_self_regulating_cable_240: 'Self Regulating Cable 240V',
    rgd_constant_wattage_kit: 'Constant Wattage Kit',
    rgd_controls: 'Controls',
    rgd_sensors: 'Sensors',
    rgd_relay_panels: 'Relay Panels',
    rgd_accessories: 'Accessories'
  },
  'Pipe Freeze Protection': {
    pfp_self_regulating_cable_120: 'Self Regulating Cable 120V',
    pfp_self_regulating_cable_240: 'Self Regulating Cable 240V',
    pfp_constant_wattage_cable: 'Constant Wattage Cable',
    pfp_controls: 'Controls',
    pfp_accessories: 'Accessories'
  }
}
SECTION_SPEC_COLUMNS =

Maps section key prefix → [extra spec symbols] shown between NAME and PRICE

{
  'fh_tempzone_flex'      => { extra: %i[width length coverage watts amps] },
  'fh_tempzone_cable'     => { extra: %i[width length coverage watts amps] },
  'fh_tempzone_ruler'     => { extra: %i[width length coverage watts amps] },
  'fh_tempzone_easy'      => { extra: %i[coverage watts amps] },
  'fh_tempzone_shower'    => { extra: %i[coverage watts] },
  'fh_tempzone_custom'    => { extra: %i[coverage watts] },
  'fh_environ_flex'       => { extra: %i[width length coverage watts amps] },
  'fh_environ_easy'       => { extra: %i[coverage watts amps] },
  'fh_slab'               => { extra: %i[length watts amps] },
  'fh_controls'           => { extra: %i[maximum_current], name_col: true },
  'fh_power_modules'      => { extra: %i[maximum_current], name_col: true },
  'fh_relay_panels'       => { name_col: true },
  'fh_underlayment'       => { extra: %i[width length], name_col: true },
  'fh_rough_in_kits'      => { name_col: true },
  'fh_installation_kits'  => { name_col: true },
  'fh_accessories'        => { name_col: true },
  'fh_spare_parts'        => { name_col: true },
  'tw_'                   => { extra: %i[finish width height depth], name_col: true },
  'rp_'                   => { name_col: true },
  'mirror_'               => { name_col: true },
  'ch_'                   => { name_col: true },
  'sk_'                   => { name_col: true },
  'sm_mat'                => { extra: %i[width length coverage watts amps] },
  'sm_cable'              => { extra: %i[length watts amps] },
  'sm_controls'           => { extra: %i[maximum_current], name_col: true },
  'sm_sensors'            => { name_col: true },
  'sm_relay_panels'       => { name_col: true },
  'sm_accessories'        => { name_col: true },
  'rgd_'                  => { name_col: true },
  'pfp_'                  => { name_col: true }
}.freeze
GROUP_HEADINGS =

Maps section key → group heading shown before first section in that family

{
  'fh_' => 'FLOOR HEATING',
  'tw_' => 'TOWEL WARMERS',
  'rp_' => 'RADIANT PANELS',
  'mirror_' => 'MIRRORS',
  'ch_' => "FEELSWARM\u00AE COUNTERTOP HEATING",
  'sk_' => 'SHOWER KITS',
  'sm_' => 'SNOW MELTING',
  'rgd_' => 'ROOF & GUTTER DEICING',
  'pfp_' => 'PIPE FREEZE PROTECTION'
}.freeze
DIMENSION_SPECS =
%i[width length height depth].freeze
SPEC_UNIT_LABELS =
{
  'in' => 'in.', 'ft' => 'ft', 'mm' => 'mm', 'cm' => 'cm', 'm' => 'm'
}.freeze

Constants included from Base

Base::FONT, Base::NIMBUS_SANS_PATH, Base::NIMBUS_SANS_PATH_BOLD, Base::WY_LOGO_PATH

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ PriceList

Returns a new instance of PriceList.



152
153
154
# File 'app/services/pdf/document/price_list.rb', line 152

def initialize(options = {})
  super
end

Instance Attribute Details

#rendererObject (readonly)

Returns the value of attribute renderer.



14
15
16
# File 'app/services/pdf/document/price_list.rb', line 14

def renderer
  @renderer
end

Class Method Details

.details_and_prices_for(catalog_id:, product_line_path: nil, product_category_path: nil, available_to_public_only: true, skus: [], sku_regex: nil, exact_product_category: false, item_condition: nil) ⇒ Object

Uses ltree path-based queries (no DB lookup needed)



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'app/services/pdf/document/price_list.rb', line 175

def self.details_and_prices_for(catalog_id:,
                                product_line_path: nil,
                                product_category_path: nil,
                                available_to_public_only: true,
                                skus: [],
                                sku_regex: nil,
                                exact_product_category: false,
                                item_condition: nil)
  if skus.any?
    sku_order_sql = skus.each_with_index.map { |sku, i| "WHEN '#{sku}' THEN #{i}" }.join(' ')
    items = Item.where(sku: skus).order(Arel.sql("CASE sku #{sku_order_sql} END"))
  elsif sku_regex
    items = Item.where('sku ~* ?', sku_regex).order(price: :asc, sku: :asc)
  else
    items = Item.by_product_line_path(product_line_path)
    if product_category_path.present?
      items = exact_product_category ? items.by_product_category_path_exact(product_category_path) : items.by_product_category_path(product_category_path)
    end
    items = items.available_to_public if available_to_public_only
    items = items.order(:price, :sku)
  end
  price_sql = "(select amount from catalog_items left join store_items on store_items.id = catalog_items.store_item_id left join items items2 on items2.id = store_items.item_id where store_items.location = 'AVAILABLE' and catalog_id = #{catalog_id} and items2.id = items.id)"
  items = items.select("items.*,#{price_sql} as price")
  items = items.where("#{price_sql} is not null")
  items = items.where(condition: item_condition) if item_condition.present?
  items
end

.item_conditions_for_selectObject



156
157
158
# File 'app/services/pdf/document/price_list.rb', line 156

def self.item_conditions_for_select
  [['Any', ''], ['New Only', 'new'], ['Refurb/B-stocks', 'refurbished']]
end

Instance Method Details

#callObject



203
204
205
206
207
208
209
210
211
212
# File 'app/services/pdf/document/price_list.rb', line 203

def call
  composer  = build_composer
  draw_body(composer)
  insert_headers_and_footers(composer)
  io = StringIO.new
  composer.write(io, optimize: true)
  file_path = Rails.application.config.x.temp_storage_path.join(file_name)
  File.binwrite(file_path, io.string)
  Upload.uploadify(file_path, 'price_list_pdf', nil, file_name)
end

#catalogObject



218
219
220
# File 'app/services/pdf/document/price_list.rb', line 218

def catalog
  Catalog.find(catalog_id) if catalog_id
end

#details_and_prices_for(product_line_path:, product_category_path: nil, exact_product_category: false, available_to_public_only: true) ⇒ Object

Instance method delegates to class method



161
162
163
164
165
166
167
168
169
170
171
172
# File 'app/services/pdf/document/price_list.rb', line 161

def details_and_prices_for(product_line_path:, product_category_path: nil,
                           exact_product_category: false,
                           available_to_public_only: true)
  Pdf::Document::PriceList.details_and_prices_for(
    catalog_id: catalog.id,
    product_line_path:,
    product_category_path:,
    item_condition:,
    exact_product_category:,
    available_to_public_only:
  )
end

#file_nameObject



214
215
216
# File 'app/services/pdf/document/price_list.rb', line 214

def file_name
  'price_list.pdf'
end