Commit f7a1b20d4dfae99665483b4ff862329bb0400c85

Authored by Joenio Costa
Committed by Daniela Feitosa
1 parent 97c04098

Units of measurement are in the database now

- Product::UNITS was removed; and
- We lost the power of gettext to translate units

(ActionItem1859)
app/helpers/manage_products_helper.rb
... ... @@ -242,8 +242,7 @@ module ManageProductsHelper
242 242 end
243 243  
244 244 def select_unit(object)
245   - selected = object.unit.nil? ? '' : object.unit
246   - select(object.class.name.downcase, 'unit', Product::UNITS.map{|unit| [_(unit[0]), unit[0]]}, {:selected => selected, :include_blank => _('Select the unit')})
  245 + collection_select(object.class.name.downcase, :unit_id, environment.units, :id, :singular, {:include_blank => _('Select the unit')})
247 246 end
248 247  
249 248 def input_icon(input)
... ... @@ -263,14 +262,13 @@ module ManageProductsHelper
263 262 if product_unit.blank?
264 263 _('Amount used in this product or service')
265 264 else
266   - _('Amount used by %s of this product or service') % _(product_unit)
  265 + _('Amount used by %s of this product or service') % product_unit.singular.downcase
267 266 end
268 267 end
269 268  
270 269 def display_unit(input)
271 270 input_amount_used = content_tag('span', input.formatted_amount, :class => 'input-amount-used')
272 271 return input_amount_used if input.unit.blank?
273   - units = Product::UNITS.find {|unit| unit[0] == input.unit}
274   - n_('1 %{singular_unit}', '%{num} %{plural_unit}', input.amount_used.to_f) % { :num => input_amount_used, :singular_unit => content_tag('span', units[0], :class => 'input-unit'), :plural_unit => content_tag('span', units[1], :class => 'input-unit') }
  272 + n_('1 %{singular_unit}', '%{num} %{plural_unit}', input.amount_used.to_f) % { :num => input_amount_used, :singular_unit => content_tag('span', input.unit.singular, :class => 'input-unit'), :plural_unit => content_tag('span', input.unit.plural, :class => 'input-unit') }
275 273 end
276 274 end
... ...
app/models/environment.rb
... ... @@ -162,6 +162,8 @@ class Environment < ActiveRecord::Base
162 162  
163 163 acts_as_accessible
164 164  
  165 + has_many :units, :order => 'position'
  166 +
165 167 def superior_intances
166 168 [self, nil]
167 169 end
... ...
app/models/input.rb
... ... @@ -7,6 +7,8 @@ class Input < ActiveRecord::Base
7 7  
8 8 acts_as_list :scope => :product
9 9  
  10 + belongs_to :unit
  11 +
10 12 include FloatHelper
11 13  
12 14 def price_per_unit=(value)
... ...
app/models/product.rb
... ... @@ -42,14 +42,9 @@ class Product < ActiveRecord::Base
42 42  
43 43 acts_as_mappable
44 44  
45   - include FloatHelper
  45 + belongs_to :unit
46 46  
47   - UNITS = [
48   - [N_('unit'), _('units')],
49   - [N_('litre'), _('litres')],
50   - [N_('kilo'), _('kilos')],
51   - [N_('meter'), _('meters')],
52   - ]
  47 + include FloatHelper
53 48  
54 49 include WhiteListFilter
55 50 filter_iframes :description, :whitelist => lambda { enterprise && enterprise.environment && enterprise.environment.trusted_sites_for_iframe }
... ... @@ -151,7 +146,7 @@ class Product < ActiveRecord::Base
151 146 end
152 147  
153 148 def name_with_unit
154   - unit.blank? ? name : "#{name} - #{_(unit)}"
  149 + unit.blank? ? name : "#{name} - #{unit.name.downcase}"
155 150 end
156 151  
157 152 end
... ...
app/models/unit.rb 0 → 100644
... ... @@ -0,0 +1,17 @@
  1 +class Unit < ActiveRecord::Base
  2 +
  3 + validates_presence_of :singular
  4 + validates_presence_of :plural
  5 +
  6 + belongs_to :environment
  7 + validates_presence_of :environment_id
  8 + acts_as_list :scope => :environment
  9 +
  10 + def name
  11 + self.singular
  12 + end
  13 + def name=(value)
  14 + self.singular = value
  15 + end
  16 +
  17 +end
... ...
db/migrate/20110221195242_create_units_and_add_reference_to_it_at_products_and_inputs.rb 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +class CreateUnitsAndAddReferenceToItAtProductsAndInputs < ActiveRecord::Migration
  2 + def self.up
  3 + create_table :units do |t|
  4 + t.string :singular, :null => false
  5 + t.string :plural, :null => false
  6 + t.integer :position
  7 + t.references :environment, :null => false
  8 + end
  9 + [:products, :inputs].each do |table_name|
  10 + change_table table_name do |t|
  11 + t.remove :unit
  12 + t.references :unit
  13 + end
  14 + end
  15 + end
  16 +
  17 + def self.down
  18 + drop_table :units
  19 + [:products, :inputs].each do |table_name|
  20 + change_table table_name do |t|
  21 + t.string :unit
  22 + t.remove_references :unit
  23 + end
  24 + end
  25 + end
  26 +end
... ...
db/schema.rb
... ... @@ -9,7 +9,7 @@
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11  
12   -ActiveRecord::Schema.define(:version => 20110215153624) do
  12 +ActiveRecord::Schema.define(:version => 20110221195242) do
13 13  
14 14 create_table "action_tracker", :force => true do |t|
15 15 t.integer "user_id"
... ... @@ -289,11 +289,11 @@ ActiveRecord::Schema.define(:version =&gt; 20110215153624) do
289 289 t.datetime "created_at"
290 290 t.datetime "updated_at"
291 291 t.integer "position"
292   - t.string "unit"
293 292 t.decimal "price_per_unit"
294 293 t.decimal "amount_used"
295 294 t.boolean "relevant_to_price", :default => true
296 295 t.boolean "is_from_solidarity_economy", :default => false
  296 + t.integer "unit_id"
297 297 end
298 298  
299 299 create_table "mailing_sents", :force => true do |t|
... ... @@ -345,10 +345,10 @@ ActiveRecord::Schema.define(:version =&gt; 20110215153624) do
345 345 t.datetime "updated_at"
346 346 t.float "lat"
347 347 t.float "lng"
348   - t.string "unit"
349 348 t.float "discount"
350 349 t.boolean "available", :default => true
351 350 t.boolean "highlighted"
  351 + t.integer "unit_id"
352 352 end
353 353  
354 354 add_index "products", ["enterprise_id"], :name => "index_products_on_enterprise_id"
... ... @@ -469,6 +469,13 @@ ActiveRecord::Schema.define(:version =&gt; 20110215153624) do
469 469 t.string "thumbnail"
470 470 end
471 471  
  472 + create_table "units", :force => true do |t|
  473 + t.string "singular", :null => false
  474 + t.string "plural", :null => false
  475 + t.integer "position"
  476 + t.integer "environment_id", :null => false
  477 + end
  478 +
472 479 create_table "users", :force => true do |t|
473 480 t.string "login"
474 481 t.string "email"
... ...
features/manage_inputs.feature
... ... @@ -20,6 +20,10 @@ Feature: manage inputs
20 20 | owner | category | name |
21 21 | redemoinho | rock | Abbey Road |
22 22 And feature "disable_products_for_enterprises" is disabled on environment
  23 + And the following units
  24 + | singular | plural |
  25 + | Meter | Meters |
  26 + | Litre | Litres |
23 27  
24 28 @selenium
25 29 Scenario: add first input to a product
... ... @@ -110,9 +114,9 @@ Feature: manage inputs
110 114 And I am logged in as "joaosilva"
111 115 When I go to Rede Moinho's page of product Abbey Road
112 116 And I follow "Inputs"
113   - And I should see "Music"
  117 + Then I should see "Music"
114 118 When I follow "Click here to add price and the amount used"
115   - And I should see "Price ($)"
  119 + And I should see "Price"
116 120 And I fill in "Price" with "10.50"
117 121 And I press "Save"
118 122 Then I should not see "Save"
... ... @@ -126,11 +130,9 @@ Feature: manage inputs
126 130 When I go to Rede Moinho's page of product Abbey Road
127 131 And I follow "Inputs"
128 132 And I follow "Click here to add price and the amount used"
129   - Then I should see "Price ($)"
130   - And I should not see "Price by meter ($)"
131   - When I select "meter"
132   - Then I should see "Price by meter ($)"
133   - And I should not see "Price ($)"
  133 + And I should not see "Price by Meter ($)"
  134 + When I select "Meter"
  135 + Then I should see "Price by Meter ($)"
134 136  
135 137 @selenium
136 138 Scenario: Save all price details of input
... ... @@ -143,10 +145,10 @@ Feature: manage inputs
143 145 And I follow "Click here to add price and the amount used"
144 146 And I fill in "Amount used" with "2.5"
145 147 And I fill in "Price" with "11.50"
146   - And I select "meter"
  148 + And I select "Meter"
147 149 And I press "Save"
148 150 Then I should see "2.5"
149   - And I should see "meter"
  151 + And I should see "Meter"
150 152 And I should not see "$ 11.50"
151 153  
152 154 @selenium
... ... @@ -160,17 +162,17 @@ Feature: manage inputs
160 162 And I follow "Click here to add price and the amount used"
161 163 And I fill in "Amount used" with "2.5"
162 164 And I fill in "Price" with "11.50"
163   - And I select "meter"
  165 + And I select "Meter"
164 166 And I press "Save"
165 167 Then I should see "2.5"
166   - And I should see "meter"
  168 + And I should see "Meter"
167 169 When I follow "Edit" within ".input-details"
168 170 And I fill in "Amount used" with "3.0"
169 171 And I fill in "Price" with "23.31"
170   - And I select "litre"
  172 + And I select "Litre"
171 173 And I press "Save"
172 174 Then I should see "3"
173   - And I should see "litre"
  175 + And I should see "Litre"
174 176  
175 177 @selenium
176 178 Scenario: Cancel edition of a input
... ... @@ -192,7 +194,7 @@ Feature: manage inputs
192 194 Scenario: Cancel edition of an input then edit again
193 195 Given the following input
194 196 | product | category | price_per_unit | unit |
195   - | Abbey Road | music | 10.0 | unit |
  197 + | Abbey Road | music | 10.0 | Meter |
196 198 And I am logged in as "joaosilva"
197 199 When I go to Rede Moinho's page of product Abbey Road
198 200 And I follow "Inputs"
... ... @@ -200,7 +202,7 @@ Feature: manage inputs
200 202 And I follow "Cancel"
201 203 And I follow "Edit" within ".input-details"
202 204 Then I should see "Amount used"
203   - And I should see "Price by unit"
  205 + And I should see "Price by Meter"
204 206  
205 207 @selenium
206 208 Scenario: remove input
... ...
features/manage_products.feature
... ... @@ -467,11 +467,14 @@ Feature: manage products
467 467 And the following products
468 468 | owner | category | name |
469 469 | redemoinho | bicycle | Bike |
  470 + And the following units
  471 + | singular | plural |
  472 + | Kilo | Kilos |
470 473 And I am logged in as "joaosilva"
471 474 When I go to Rede Moinho's page of product Bike
472 475 And I follow "Edit name and unit"
473 476 And I fill in "product_name" with "Red bicycle"
474   - And I select "kilo"
  477 + And I select "Kilo"
475 478 And I press "Save"
476 479 Then I should see "Red bicycle - kilo"
477 480  
... ...
features/step_definitions/noosfero_steps.rb
... ... @@ -121,7 +121,8 @@ Given /^the following inputs?$/ do |table|
121 121 data = item.dup
122 122 product = Product.find_by_name(data.delete("product"))
123 123 category = Category.find_by_slug(data.delete("category").to_slug)
124   - input = Input.create!(data.merge(:product => product, :product_category => category))
  124 + unit = Unit.find_by_singular(data.delete("unit"))
  125 + input = Input.create!(data.merge(:product => product, :product_category => category, :unit => unit))
125 126 input.update_attributes!(:position => data['position'])
126 127 end
127 128 end
... ... @@ -369,4 +370,8 @@ Given /^someone suggested the following article to be published$/ do |table|
369 370 end
370 371 end
371 372  
372   -
  373 +Given /^the following units?$/ do |table|
  374 + table.hashes.each do |row|
  375 + Unit.create!(row.merge(:environment_id => 1))
  376 + end
  377 +end
... ...
script/sample-products
... ... @@ -39,3 +39,10 @@ for certifier in CERTIFIERS
39 39 print '.'
40 40 end
41 41 puts ' done!'
  42 +
  43 +print "Creating units: "
  44 +[['Litre', 'Litres'], ['Kilo', 'Kilos'], ['Meter', 'Meters']].each do |unit|
  45 + Unit.create!(:singular => unit[0], :plural => unit[1], :environment => environment)
  46 + print '.'
  47 +end
  48 +puts ' done!'
... ...
test/factories.rb
... ... @@ -436,4 +436,12 @@ module Noosfero::Factory
436 436 { :title => name, :body => "my own comment", :article_id => 1 }.merge(params)
437 437 end
438 438  
  439 + ###############################################
  440 + # Unit
  441 + ###############################################
  442 +
  443 + def defaults_for_unit
  444 + { :singular => 'Litre', :plural => 'Litres', :environment_id => 1 }
  445 + end
  446 +
439 447 end
... ...
test/functional/manage_products_controller_test.rb
... ... @@ -272,7 +272,7 @@ class ManageProductsControllerTest &lt; Test::Unit::TestCase
272 272 end
273 273  
274 274 should 'show product price when showing product if unit was informed' do
275   - product = fast_create(Product, :name => 'test product', :price => 50.00, :unit => 'unit', :enterprise_id => @enterprise.id, :product_category_id => @product_category.id)
  275 + product = fast_create(Product, :name => 'test product', :price => 50.00, :unit_id => fast_create(Unit).id, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id)
276 276 get :show, :id => product.id, :profile => @enterprise.identifier
277 277  
278 278 assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /Price:/
... ... @@ -280,7 +280,7 @@ class ManageProductsControllerTest &lt; Test::Unit::TestCase
280 280 end
281 281  
282 282 should 'show product price when showing product if discount was informed' do
283   - product = fast_create(Product, :name => 'test product', :price => 50.00, :unit => 'unit', :discount => 3.50, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id)
  283 + product = fast_create(Product, :name => 'test product', :price => 50.00, :unit_id => fast_create(Unit).id, :discount => 3.50, :enterprise_id => @enterprise.id, :product_category_id => @product_category.id)
284 284 get :show, :id => product.id, :profile => @enterprise.identifier
285 285  
286 286 assert_tag :tag => 'span', :attributes => { :class => 'field-name' }, :content => /List price:/
... ...
test/unit/environment_test.rb
... ... @@ -1108,4 +1108,12 @@ class EnvironmentTest &lt; Test::Unit::TestCase
1108 1108 assert_not_includes env.enabled_features.keys, 'feature3'
1109 1109 end
1110 1110  
  1111 + should 'has a list of units ordered by position' do
  1112 + litre = Unit.create!(:singular => 'Litre', :plural => 'Litres', :environment => Environment.default)
  1113 + meter = Unit.create!(:singular => 'Meter', :plural => 'Meters', :environment => Environment.default)
  1114 + kilo = Unit.create!(:singular => 'Kilo', :plural => 'Kilo', :environment => Environment.default)
  1115 + litre.move_to_bottom
  1116 + assert_equal ["Meter", "Kilo", "Litre"], Environment.default.units.map(&:singular)
  1117 + end
  1118 +
1111 1119 end
... ...
test/unit/input_test.rb
... ... @@ -78,7 +78,7 @@ class InputTest &lt; Test::Unit::TestCase
78 78 end
79 79  
80 80 should 'not have price details if only unit is filled' do
81   - input = Input.new(:unit => 'unit')
  81 + input = Input.new(:unit => Unit.new)
82 82 assert !input.has_price_details?
83 83 end
84 84  
... ... @@ -157,4 +157,9 @@ class InputTest &lt; Test::Unit::TestCase
157 157 assert_equal '1.00', input.formatted_value(:price_per_unit)
158 158 end
159 159  
  160 + should 'has relation with unit' do
  161 + input = Input.new
  162 + assert_kind_of Unit, input.build_unit
  163 + end
  164 +
160 165 end
... ...
test/unit/manage_products_helper_test.rb
... ... @@ -137,6 +137,18 @@ class ManageProductsHelperTest &lt; Test::Unit::TestCase
137 137 assert_equal 'LINK', edit_ui_button('link to edit', {:action => 'add_input', :id => product.id})
138 138 end
139 139  
  140 + should 'show unit on label of amount selection' do
  141 + input = Input.new()
  142 + input.expects(:product).returns(Product.new(:unit => Unit.new(:singular => 'Meter')))
  143 + assert_equal 'Amount used by meter of this product or service', label_amount_used(input)
  144 + end
  145 +
  146 + should 'not show unit on label of amount selection if product has no unit selected' do
  147 + input = Input.new()
  148 + input.expects(:product).returns(Product.new)
  149 + assert_equal 'Amount used in this product or service', label_amount_used(input)
  150 + end
  151 +
140 152 protected
141 153 include NoosferoTestHelper
142 154 include ActionView::Helpers::TextHelper
... ...
test/unit/product_test.rb
... ... @@ -295,11 +295,6 @@ class ProductTest &lt; Test::Unit::TestCase
295 295 end
296 296 end
297 297  
298   - should 'has a list of units' do
299   - assert_kind_of Array, Product::UNITS
300   - assert_includes Product::UNITS.flatten, 'unit'
301   - end
302   -
303 298 should 'test if name is blank' do
304 299 product = Product.new
305 300 assert product.name_is_blank?
... ... @@ -309,7 +304,7 @@ class ProductTest &lt; Test::Unit::TestCase
309 304 product = Product.new
310 305 assert !product.has_basic_info?
311 306  
312   - product = Product.new(:unit => 'unit')
  307 + product = Product.new(:unit => Unit.new)
313 308 assert product.has_basic_info?
314 309  
315 310 product = Product.new(:price => 1)
... ... @@ -348,8 +343,13 @@ class ProductTest &lt; Test::Unit::TestCase
348 343 should 'format name with unit' do
349 344 product = Product.new(:name => "My product")
350 345 assert_equal "My product", product.name_with_unit
351   - product.unit = 'litre'
  346 + product.unit = Unit.new(:name => 'litre')
352 347 assert_equal "My product - litre", product.name_with_unit
353 348 end
354 349  
  350 + should 'have relation with unit' do
  351 + product = Product.new
  352 + assert_kind_of Unit, product.build_unit
  353 + end
  354 +
355 355 end
... ...
test/unit/unit_test.rb 0 → 100644
... ... @@ -0,0 +1,34 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class UnitTest < Test::Unit::TestCase
  4 +
  5 + should 'require singular name' do
  6 + unit = Unit.new; unit.valid?
  7 + assert_match /can't be blank/, unit.errors["singular"]
  8 + end
  9 +
  10 + should 'require plural name' do
  11 + unit = Unit.new; unit.valid?
  12 + assert_match /can't be blank/, unit.errors["plural"]
  13 + end
  14 +
  15 + should 'belongs and require an environment' do
  16 + unit = Unit.new; unit.valid?
  17 + assert_match /can't be blank/, unit.errors["environment_id"]
  18 + unit.environment = Environment.default; unit.valid?
  19 + assert_nil unit.errors["environment_id"]
  20 + end
  21 +
  22 + should 'increment position automatically' do
  23 + first = Unit.create!(:singular => 'Litre', :plural => 'Litres', :environment => Environment.default)
  24 + second = Unit.create!(:singular => 'Meter', :plural => 'Meters', :environment => Environment.default)
  25 + assert_equal 1, first.position
  26 + assert_equal 2, second.position
  27 + end
  28 +
  29 + should 'has an getter and setter alias to singular field' do
  30 + unit = Unit.new(:name => 'Litre')
  31 + assert_equal 'Litre', unit.singular
  32 + end
  33 +
  34 +end
... ...