product.rb
5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
class Product < ActiveRecord::Base
  belongs_to :enterprise
  belongs_to :product_category
  has_many :product_categorizations
  has_many :product_qualifiers
  has_many :qualifiers, :through => :product_qualifiers
  has_many :inputs, :dependent => :destroy, :order => 'position'
  has_many :price_details, :dependent => :destroy
  has_many :production_costs, :through => :price_details
  validates_uniqueness_of :name, :scope => :enterprise_id, :allow_nil => true
  validates_presence_of :product_category_id
  validates_associated :product_category
  validates_numericality_of :price, :allow_nil => true
  validates_numericality_of :discount, :allow_nil => true
  after_update :save_image
  before_create do |p|
    if p.enterprise
      p['lat'] = p.enterprise.lat
      p['lng'] = p.enterprise.lng
    end
  end
  after_save do |p|
    p.enterprise.product_updated if p.enterprise
  end
  after_save do |p|
    if (p.product_category && !ProductCategorization.find(:first, :conditions => {:category_id => p.product_category.id, :product_id => p.id})) || (!p.product_category)
      ProductCategorization.remove_all_for(p)
      if p.product_category
        ProductCategorization.add_category_to_product(p.product_category, p)
      end
    end
  end
  acts_as_searchable :fields => [ :name, :description, :category_full_name ]
  xss_terminate :only => [ :name ], :on => 'validation'
  xss_terminate :only => [ :description ], :with => 'white_list', :on => 'validation'
  acts_as_mappable
  belongs_to :unit
  include FloatHelper
  include WhiteListFilter
  filter_iframes :description, :whitelist => lambda { enterprise && enterprise.environment && enterprise.environment.trusted_sites_for_iframe }
  def name
    self[:name].blank? ? category_name : self[:name]
  end
  def name=(value)
    if (value == category_name)
      self[:name] = nil
    else
      self[:name] = value
    end
  end
  def name_is_blank?
    self[:name].blank?
  end
  def default_image(size='thumb')
    image ? image.public_filename(size) : '/images/icons-app/product-default-pic-%s.png' % size
  end
  def category_full_name
    product_category ? product_category.full_name.split('/') : nil
  end
  acts_as_having_image
  def save_image
    image.save if image
  end
  def category_name
    product_category ? product_category.name : _('Uncategorized product')
  end
  def self.recent(limit = nil)
    self.find(:all, :order => 'id desc', :limit => limit)
  end
  def enterprise_updated(e)
    self.lat = e.lat
    self.lng = e.lng
    save!
  end
  def url
    enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => id)
  end
  def public?
    enterprise.public_profile
  end
  def formatted_value(method)
    value = self[method] || self.send(method)
    ("%.2f" % value).to_s.gsub('.', enterprise.environment.currency_separator) if value
  end
  def price_with_discount
    discount ? (price - discount) : price
  end
  def price=(value)
    if value.is_a?(String)
      super(decimal_to_float(value))
    else
      super(value)
    end
  end
  def discount=(value)
    if value.is_a?(String)
      super(decimal_to_float(value))
    else
      super(value)
    end
  end
  # Note: will probably be completely overhauled for AI1413
  def inputs_prices?
    return false if self.inputs.count <= 0
    self.inputs.each do |input|
      return false if input.has_price_details? == false
    end
    true
  end
  def any_inputs_details?
    return false if self.inputs.count <= 0
    self.inputs.each do |input|
      return true if input.has_all_price_details? == true
    end
    false
  end
  def has_basic_info?
    %w[unit price discount].each do |field|
      return true if !self.send(field).blank?
    end
    false
  end
  def qualifiers_list=(qualifiers)
    self.product_qualifiers.destroy_all
    qualifiers.each do |qualifier_id, certifier_id|
      self.product_qualifiers.create(:qualifier_id => qualifier_id, :certifier_id => certifier_id)
    end
  end
  def order_inputs!(order = [])
    order.each_with_index do |input_id, array_index|
      self.inputs.find(input_id).update_attributes(:position => array_index + 1)
    end
  end
  def name_with_unit
    unit.blank? ? name : "#{name} - #{unit.name.downcase}"
  end
  def display_supplier_on_search?
    true
  end
  def inputs_cost
    return 0 if inputs.empty?
    inputs.map(&:cost).inject { |sum,price| sum + price }
  end
  def total_production_cost
    return inputs_cost if price_details.empty?
    inputs_cost + price_details.map(&:price).inject { |sum,price| sum + price }
  end
  def price_described?
    return false if price.blank? or price == 0
    (price - total_production_cost).zero?
  end
  def update_price_details(price_details)
    self.price_details.destroy_all
    price_details.each do |price_detail|
      self.price_details.create(price_detail)
    end
  end
  def price_description_percentage
    return 0 if price.blank? || price.zero?
    total_production_cost * 100 / price
  end
  def available_production_costs
    self.enterprise.environment.production_costs + self.enterprise.production_costs
  end
  include ActionController::UrlWriter
  def price_composition_bar_display_url
    url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_price_composition_bar', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options))
  end
  def inputs_cost_update_url
    url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_inputs_cost', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options))
  end
end