Commit f7a1b20d4dfae99665483b4ff862329bb0400c85
Committed by
Daniela Feitosa
1 parent
97c04098
Exists in
master
and in
29 other branches
Units of measurement are in the database now
- Product::UNITS was removed; and - We lost the power of gettext to translate units (ActionItem1859)
Showing
18 changed files
with
175 additions
and
44 deletions
Show diff stats
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
app/models/input.rb
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 | ... | ... |
... | ... | @@ -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 => 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 => 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 => 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 < 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 | ... | ... |
... | ... | @@ -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 | ... | ... |