Class: Item::CustomMatCreator

Inherits:
Object
  • Object
show all
Includes:
ActionView::Helpers::NumberHelper, ActiveModel::Attributes, ActiveModel::Model, ActiveModel::Validations
Defined in:
app/services/item/custom_mat_creator.rb

Overview

Service object: custom mat creator.

Constant Summary collapse

CUSTOM_MAT_PRODUCT_GROUP_ID =

Custom mat product group id.

60
COST_FACTOR_US =

Cost factor us.

2.75
COST_FACTOR_CA =

Cost factor ca.

3.7
CUSTOM_MAT_VOLTAGES =

Custom mat voltages.

[120, 208, 240].freeze

Instance Attribute Summary collapse

Delegated Instance Attributes collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#catalog_idObject (readonly)



35
# File 'app/services/item/custom_mat_creator.rb', line 35

validates :catalog_id, presence: true

#cold_lead_lengthObject (readonly)



37
# File 'app/services/item/custom_mat_creator.rb', line 37

validates :cold_lead_length, presence: true, numericality: { greater_than: 0 }

#installation_plan_numberObject (readonly)



38
# File 'app/services/item/custom_mat_creator.rb', line 38

validates :installation_plan_number, presence: true

#mat_numberObject (readonly)



39
# File 'app/services/item/custom_mat_creator.rb', line 39

validates :mat_number, presence: true

#original_custom_mat_itemObject (readonly)

Returns the value of attribute original_custom_mat_item.



10
11
12
# File 'app/services/item/custom_mat_creator.rb', line 10

def original_custom_mat_item
  @original_custom_mat_item
end

#sqftObject (readonly)



40
# File 'app/services/item/custom_mat_creator.rb', line 40

validates :sqft, presence: true, numericality: { greater_than_or_equal_to: 7 }

#voltsObject (readonly)



41
# File 'app/services/item/custom_mat_creator.rb', line 41

validates :volts, presence: true, numericality: { only_integer: true, greater_than: 0 }

#widthObject (readonly)



42
# File 'app/services/item/custom_mat_creator.rb', line 42

validates :width, presence: true, numericality: { only_integer: true, greater_than: 0 }

#wy_costObject (readonly)



36
# File 'app/services/item/custom_mat_creator.rb', line 36

validates :wy_cost, presence: true, numericality: { greater_than: 0 }

Class Method Details

.calculate_pricing(cost:, sqft:, currency: 'USD') ⇒ Object

rubocop:disable Lint/UnusedMethodArgument



178
179
180
181
182
183
184
185
# File 'app/services/item/custom_mat_creator.rb', line 178

def self.calculate_pricing(cost:, sqft:, currency: 'USD') # rubocop:disable Lint/UnusedMethodArgument
  # `sqft` is part of the public signature (callers pass it) even though the
  # current pricing formula doesn't reference it. Don't let rubocop prefix
  # with `_` — that breaks the kwarg API.
  _ = sqft
  p = cost * get_currency_factor(currency)
  up_to_nearest_5(p)
end

.get_currency_factor(currency) ⇒ Object



170
171
172
173
174
175
176
# File 'app/services/item/custom_mat_creator.rb', line 170

def self.get_currency_factor(currency)
  if currency == 'CAD'
    COST_FACTOR_CA
  else
    COST_FACTOR_US
  end
end

.up_to_nearest_5(n) ⇒ Object



163
164
165
166
167
168
# File 'app/services/item/custom_mat_creator.rb', line 163

def self.up_to_nearest_5(n)
  return n if n % 5 == 0

  rounded = n.round(-1)
  rounded > n ? rounded : rounded + 5
end

Instance Method Details

#catalogObject



66
67
68
# File 'app/services/item/custom_mat_creator.rb', line 66

def catalog
  Catalog.find(catalog_id)
end

#check_for_minimum_electrical_specsObject



187
188
189
190
191
# File 'app/services/item/custom_mat_creator.rb', line 187

def check_for_minimum_electrical_specs
  return if [volts, watts, amps, ohms].filter_map(&:presence).size > 1

  errors.add(:base, 'At least two electrical specs must be present (volts, watts, amps, ohms)')
end

#cold_lead_strObject



155
156
157
# File 'app/services/item/custom_mat_creator.rb', line 155

def cold_lead_str
  "0#{cold_lead_length.round}".last(2) # two digits for this
end

#generate_nameObject



159
160
161
# File 'app/services/item/custom_mat_creator.rb', line 159

def generate_name
  "TempZone Mat Custom Single #{volts.round}V - #{number_with_precision(amps, precision: 2, strip_insignificant_zeros: true)}A - #{number_with_precision(sqft, precision: 1, strip_insignificant_zeros: true)} sq.ft. - #{cold_lead_str} ft. Cold Lead"
end

#generate_skuObject



142
143
144
145
146
147
148
149
150
151
152
153
# File 'app/services/item/custom_mat_creator.rb', line 142

def generate_sku
  sku_base = "TMCS#{volts.round}-#{sqft.round(1)}-CL#{cold_lead_str}"
  serial_number = 1
  # last_matching_custom_mat_item = Item.where("items.sku ILIKE '%#{sku_base}%'").order(:created_at).last
  last_matching_custom_mat_item = Item.where("items.sku ILIKE '%#{sku_base}%'").order(:created_at)
  # if last_matching_custom_mat_item && (ser_str = last_matching_custom_mat_item.sku.split('-').last) && ((last_ser_num = ser_str.to_i) > 0)
  if last_matching_custom_mat_item && (ser_str = last_matching_custom_mat_item.map { |r| r[:sku].split('-').last.to_i }.max) && ((last_ser_num = ser_str) > 0)
    serial_number = last_ser_num + 1
  end
  serial_number_str = "00#{serial_number}".last(3) # three digits for this
  "#{sku_base}-#{serial_number_str}"
end

#saveObject



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/services/item/custom_mat_creator.rb', line 70

def save
  return false unless valid?

  unless (original_custom_mat_item = CatalogItem.last_custom_mat_catalog_item(catalog_id, volts)&.item)
    errors.add(:base, 'Could not find existing custom mat catalog item')
    return false
  end

  @original_custom_mat_item = original_custom_mat_item
  new_custom_mat_item = @original_custom_mat_item.deep_dup
  new_custom_mat_item.sqft = nil
  new_custom_mat_item.base_weight = nil
  new_custom_mat_item.gross_weight = nil
  new_custom_mat_item.shipping_weight = nil
  new_custom_mat_item.box2_shipping_weight = nil
  new_custom_mat_item.box3_shipping_weight = nil

  Item.transaction do
    if new_custom_mat_item.sqft
      new_custom_mat_item.base_weight = new_custom_mat_item.sqft * 0.1 # as per Venu
    end

    # new_custom_mat_item.length = nil
    new_custom_mat_item.shipping_length = [width + 2, 44].min # 2" padding and 44" max length box since they can fold them
    new_custom_mat_item.shipping_width = [new_custom_mat_item.shipping_width = (sqft / width).ceil + 2, 14].min # 14" is the max
    new_custom_mat_item.shipping_height = new_custom_mat_item.shipping_width # it's a roll so same diameter
    new_custom_mat_item.sku = generate_sku
    new_custom_mat_item.name = generate_name

    new_custom_mat_item.save!
    # Apply template
    new_custom_mat_item.create_template_specifications

    set_item_specs(new_custom_mat_item)

    msrp_price = self.class.calculate_pricing(cost: wy_cost,
                                              sqft: new_custom_mat_item.sqft,
                                              currency: catalog.currency)

    new_custom_mat_store_item = @original_custom_mat_item.store_items.find_by(store_id: store.id).dup
    new_custom_mat_store_item.item_id = new_custom_mat_item.id
    new_custom_mat_store_item.unit_cogs = wy_cost
    new_custom_mat_store_item.qty_on_hand = 0
    new_custom_mat_store_item.qty_committed = 0
    new_custom_mat_store_item.last_item_ledger_entry_id = nil
    new_custom_mat_store_item.save!

    new_custom_mat_catalog_item = @original_custom_mat_item.catalog_items.find_by(catalog_id: catalog.id).dup
    new_custom_mat_catalog_item.store_item_id = new_custom_mat_store_item.id
    new_custom_mat_catalog_item.max_discount = 40
    new_custom_mat_catalog_item.amount = msrp_price
    new_custom_mat_catalog_item.state = 'active_hidden'
    new_custom_mat_catalog_item.save!

    new_custom_mat_supplier_item = @original_custom_mat_item.supplier_item.dup
    new_custom_mat_supplier_item.item_id = new_custom_mat_item.id
    new_custom_mat_supplier_item.supplier_sku = "Mat # #{mat_number}"
    new_custom_mat_supplier_item.supplier_description = "Plan # #{installation_plan_number}"
    new_custom_mat_supplier_item.supplier_item_prices.build(purchasing_cost: wy_cost,
                                                            unit_cost: wy_cost,
                                                            currency: catalog.currency,
                                                            effective_from: 1.day.ago)
    new_custom_mat_supplier_item.save!

    new_custom_mat_item.supplier_item_id = new_custom_mat_supplier_item.id
    new_custom_mat_item.save!
  end
  return new_custom_mat_item if new_custom_mat_item.persisted?

  false
end

#set_item_specs(item) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'app/services/item/custom_mat_creator.rb', line 45

def set_item_specs(item)
  ohms_attrs = {
    voltage: volts.presence,
    power: watts.presence,
    current: amps.presence,
    resistance: ohms.presence
  }.compact
  res = OhmsLawCalculator.new(ohms_attrs).calc
  item.voltage = res.voltage
  item.watts = res.power
  item.amps = res.current
  item.ohms = res.resistance

  item.width = width
  item.sqft = sqft
  item.cold_lead_length = cold_lead_length * 12
  item.refresh_specs = true
  item.save!
  item
end

#storeObject

Alias for Catalog#store

Returns:

  • (Object)

    Catalog#store

See Also:



12
# File 'app/services/item/custom_mat_creator.rb', line 12

delegate :store, to: :catalog