Class: Pdf::Document::PriceList
- Inherits:
-
Object
- Object
- Pdf::Document::PriceList
- 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
-
#renderer ⇒ Object
readonly
Returns the value of attribute renderer.
Class Method Summary collapse
-
.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).
- .item_conditions_for_select ⇒ Object
Instance Method Summary collapse
- #call ⇒ Object
- #catalog ⇒ Object
-
#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.
- #file_name ⇒ Object
-
#initialize(options = {}) ⇒ PriceList
constructor
A new instance of PriceList.
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( = {}) super end |
Instance Attribute Details
#renderer ⇒ Object (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_select ⇒ Object
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
#call ⇒ Object
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) (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 |
#catalog ⇒ Object
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_name ⇒ Object
214 215 216 |
# File 'app/services/pdf/document/price_list.rb', line 214 def file_name 'price_list.pdf' end |