Commit 8f69c31b892b8e522b2f006c2b19d36b1c3b5284

Authored by Rodrigo Souto
2 parents ddb64469 9e203e4c

Merge branch 'redemoinho-improvements'

Conflicts:
	plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
	plugins/shopping_cart/lib/shopping_cart_plugin.rb
	plugins/shopping_cart/lib/shopping_cart_plugin/mailer.rb
	plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
	plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb
	plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb
Showing 36 changed files with 726 additions and 111 deletions   Show diff stats
app/controllers/public/catalog_controller.rb
1 class CatalogController < PublicController 1 class CatalogController < PublicController
2 needs_profile 2 needs_profile
  3 + no_design_blocks
3 4
4 before_filter :check_enterprise_and_environment 5 before_filter :check_enterprise_and_environment
5 6
6 def index 7 def index
7 - @products = @profile.products.paginate(:order => 'name asc', :per_page => 9, :page => params[:page]) 8 + @category = params[:level] ? ProductCategory.find(params[:level]) : nil
  9 + @products = @profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => params[:page])
  10 + @categories = ProductCategory.on_level(params[:level])
8 end 11 end
9 12
10 protected 13 protected
app/helpers/catalog_helper.rb
@@ -3,4 +3,28 @@ module CatalogHelper @@ -3,4 +3,28 @@ module CatalogHelper
3 include DisplayHelper 3 include DisplayHelper
4 include ManageProductsHelper 4 include ManageProductsHelper
5 5
  6 + def breadcrumb(category)
  7 + start = link_to(_('Start'), {:action => 'index'})
  8 + ancestors = category.ancestors.map { |c| link_to(c.name, {:action => 'index', :level => c.id}) }.reverse
  9 + current_level = content_tag('strong', category.name)
  10 + all_items = [start] + ancestors + [current_level]
  11 + content_tag('div', all_items.join(' &rarr; '), :id => 'breadcrumb')
  12 + end
  13 +
  14 + def category_link(category, sub = false)
  15 + count = profile.products.from_category(category).count
  16 + name = truncate(category.name, :length => 22 - count.to_s.size)
  17 + link_name = sub ? name : content_tag('strong', name)
  18 + link = link_to(link_name, {:action => 'index', :level => category.id}, :title => category.name)
  19 + content_tag('li', "#{link} (#{count})") if count > 0
  20 + end
  21 +
  22 + def category_sub_links(category)
  23 + sub_categories = []
  24 + category.children.each do |sub_category|
  25 + sub_categories << category_link(sub_category, true)
  26 + end
  27 + content_tag('ul', sub_categories) if sub_categories.size > 1
  28 + end
  29 +
6 end 30 end
app/helpers/display_helper.rb
@@ -8,6 +8,14 @@ module DisplayHelper @@ -8,6 +8,14 @@ module DisplayHelper
8 opts 8 opts
9 end 9 end
10 10
  11 + def themed_path(file)
  12 + if File.exists?(File.join(Rails.root, 'public', theme_path, file))
  13 + File.join(theme_path, file)
  14 + else
  15 + file
  16 + end
  17 + end
  18 +
11 def image_link_to_product(product, opts={}) 19 def image_link_to_product(product, opts={})
12 return _('No product') unless product 20 return _('No product') unless product
13 target = product_path(product) 21 target = product_path(product)
app/models/category.rb
@@ -13,6 +13,16 @@ class Category &lt; ActiveRecord::Base @@ -13,6 +13,16 @@ class Category &lt; ActiveRecord::Base
13 {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} 13 {:conditions => ['parent_id is null and environment_id = ?', environment.id ]}
14 } 14 }
15 15
  16 + named_scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} }
  17 +
  18 + named_scope :sub_categories, lambda { |category|
  19 + {:conditions => ['categories.path LIKE ? AND categories.id != ?', "%#{category.slug}%", category.id]}
  20 + }
  21 +
  22 + named_scope :sub_tree, lambda { |category|
  23 + {:conditions => ['categories.path LIKE ?', "%#{category.slug}%"]}
  24 + }
  25 +
16 acts_as_filesystem 26 acts_as_filesystem
17 27
18 has_many :article_categorizations, :dependent => :destroy 28 has_many :article_categorizations, :dependent => :destroy
app/models/organization.rb
@@ -78,6 +78,8 @@ class Organization &lt; Profile @@ -78,6 +78,8 @@ class Organization &lt; Profile
78 country 78 country
79 tag_list 79 tag_list
80 template_id 80 template_id
  81 + district
  82 + address_reference
81 ] 83 ]
82 84
83 def self.fields 85 def self.fields
@@ -96,8 +98,8 @@ class Organization &lt; Profile @@ -96,8 +98,8 @@ class Organization &lt; Profile
96 [] 98 []
97 end 99 end
98 100
99 - N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list')  
100 - settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information 101 + N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list'); N_('District'); N_('Address reference')
  102 + settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information, :district, :address_reference
101 103
102 validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT 104 validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT
103 validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) 105 validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? })
app/models/person.rb
@@ -147,6 +147,9 @@ class Person &lt; Profile @@ -147,6 +147,9 @@ class Person &lt; Profile
147 contact_phone 147 contact_phone
148 contact_information 148 contact_information
149 description 149 description
  150 + image
  151 + district
  152 + address_reference
150 ] 153 ]
151 154
152 validates_multiparameter_assignments 155 validates_multiparameter_assignments
@@ -201,8 +204,8 @@ class Person &lt; Profile @@ -201,8 +204,8 @@ class Person &lt; Profile
201 N_('Education'); N_('Custom education'); N_('Custom area of study'); 204 N_('Education'); N_('Custom education'); N_('Custom area of study');
202 settings_items :formation, :custom_formation, :custom_area_of_study 205 settings_items :formation, :custom_formation, :custom_area_of_study
203 206
204 - N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code')  
205 - settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code 207 + N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code'); N_('District'); N_('Address reference')
  208 + settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code, :district, :address_reference
206 209
207 extend SetProfileRegionFromCityState::ClassMethods 210 extend SetProfileRegionFromCityState::ClassMethods
208 set_profile_region_from_city_state 211 set_profile_region_from_city_state
app/models/product.rb
@@ -23,6 +23,10 @@ class Product &lt; ActiveRecord::Base @@ -23,6 +23,10 @@ class Product &lt; ActiveRecord::Base
23 23
24 named_scope :more_recent, :order => "created_at DESC" 24 named_scope :more_recent, :order => "created_at DESC"
25 25
  26 + named_scope :from_category, lambda { |category|
  27 + {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category
  28 + }
  29 +
26 after_update :save_image 30 after_update :save_image
27 31
28 def lat 32 def lat
app/models/profile.rb
@@ -141,6 +141,10 @@ class Profile &lt; ActiveRecord::Base @@ -141,6 +141,10 @@ class Profile &lt; ActiveRecord::Base
141 141
142 acts_as_having_settings :field => :data 142 acts_as_having_settings :field => :data
143 143
  144 + def settings
  145 + data
  146 + end
  147 +
144 settings_items :redirect_l10n, :type => :boolean, :default => false 148 settings_items :redirect_l10n, :type => :boolean, :default => false
145 settings_items :public_content, :type => :boolean, :default => true 149 settings_items :public_content, :type => :boolean, :default => true
146 settings_items :description 150 settings_items :description
@@ -229,7 +233,7 @@ class Profile &lt; ActiveRecord::Base @@ -229,7 +233,7 @@ class Profile &lt; ActiveRecord::Base
229 if myregion 233 if myregion
230 myregion.hierarchy.reverse.first(2).map(&:name).join(separator) 234 myregion.hierarchy.reverse.first(2).map(&:name).join(separator)
231 else 235 else
232 - %w[address city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) 236 + %w[address district city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator)
233 end 237 end
234 end 238 end
235 239
@@ -698,7 +702,7 @@ private :generate_url, :url_options @@ -698,7 +702,7 @@ private :generate_url, :url_options
698 def custom_footer_expanded 702 def custom_footer_expanded
699 footer = custom_footer 703 footer = custom_footer
700 if footer 704 if footer
701 - %w[contact_person contact_email contact_phone location address economic_activity city state country zip_code].each do |att| 705 + %w[contact_person contact_email contact_phone location address district address_reference economic_activity city state country zip_code].each do |att|
702 if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/) 706 if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/)
703 if !self.send(att).nil? && !self.send(att).blank? 707 if !self.send(att).nil? && !self.send(att).blank?
704 footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att)) 708 footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att))
app/views/catalog/index.rhtml
1 <% extra_content = [] %> 1 <% extra_content = [] %>
2 <% extra_content_list = [] %> 2 <% extra_content_list = [] %>
3 3
4 -<ul id="product-list">  
5 - <li><h1><%= _('Products/Services') %></h1></li> 4 +<h1><%= _('Products/Services') %></h1>
6 5
  6 +<%= breadcrumb(@category) if params[:level] %>
  7 +
  8 +<div class='l-sidebar-left-bar'>
  9 + <ul>
  10 + <% if @categories.size > 0 %>
  11 + <% @categories.each do |category| %>
  12 + <%= category_link(category) %>
  13 + <%= category_sub_links(category) %>
  14 + <% end %>
  15 + <% else %>
  16 + <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :style => 'color: #555753; padding-bottom: 0.5em;') %>
  17 + <% end %>
  18 + </ul>
  19 +</div>
  20 +
  21 +<ul id="product-list" class="l-sidebar-left-content">
7 <% @products.each do |product| %> 22 <% @products.each do |product| %>
8 <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> 23 <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %>
9 <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> 24 <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %>
10 25
11 - <li class="product <%= "not-available" unless product.available %>"> 26 + <% status = [] %>
  27 + <% status << 'not-available' if !product.available %>
  28 + <% status << 'highlighted' if product.highlighted %>
  29 +
  30 + <li id="product-<%= product.id %>" class="product <%= status.join(' ') %>">
12 <ul> 31 <ul>
13 <li class="product-image-link"> 32 <li class="product-image-link">
  33 + <% if product.highlighted? %>
  34 + <%= link_to image_tag(themed_path('/images/star.png'), :class => 'star', :alt => _('Highlighted product')), product_path(product) %>
  35 + <% end %>
14 <% if product.image %> 36 <% if product.image %>
15 <div class="zoomable-image"> 37 <div class="zoomable-image">
16 <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> 38 <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %>
app/views/profile_editor/_person_form.rhtml
@@ -21,6 +21,8 @@ @@ -21,6 +21,8 @@
21 <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> 21 <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %>
22 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> 22 <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %>
23 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> 23 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
  24 +<%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference, :rel => _('Address reference')))) %>
  25 +<%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %>
24 26
25 <% optional_field(@person, 'schooling') do %> 27 <% optional_field(@person, 'schooling') do %>
26 <div class="formfieldline"> 28 <div class="formfieldline">
app/views/search/_product.rhtml
1 <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> 1 <% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %>
2 <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> 2 <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%>
3 3
4 -<li class="search-product-item"> 4 +<li class="search-product-item <%= 'highlighted' if product.highlighted? %>">
5 5
6 <div class="search-product-item-first-column"> 6 <div class="search-product-item-first-column">
7 <%= render :partial => 'search/image', :object => product %> 7 <%= render :partial => 'search/image', :object => product %>
app/views/shared/_organization_custom_fields.rhtml
@@ -10,6 +10,8 @@ @@ -10,6 +10,8 @@
10 <%= optional_field(profile, 'economic_activity', f.text_field(:economic_activity)) %> 10 <%= optional_field(profile, 'economic_activity', f.text_field(:economic_activity)) %>
11 <%= optional_field(profile, 'management_information', f.text_area(:management_information, :rows => 5)) %> 11 <%= optional_field(profile, 'management_information', f.text_area(:management_information, :rows => 5)) %>
12 <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(object_name, :address))) %> 12 <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(object_name, :address))) %>
  13 +<%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %>
  14 +<%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %>
13 <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> 15 <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %>
14 <%= optional_field(profile, 'city', f.text_field(:city)) %> 16 <%= optional_field(profile, 'city', f.text_field(:city)) %>
15 <%= optional_field(profile, 'state', f.text_field(:state)) %> 17 <%= optional_field(profile, 'state', f.text_field(:state)) %>
lib/noosfero/plugin/settings.rb
1 class Noosfero::Plugin::Settings 1 class Noosfero::Plugin::Settings
2 2
3 - def initialize(environment, plugin, attributes = nil)  
4 - @environment = environment 3 + def initialize(base, plugin, attributes = nil)
  4 + @base = base
5 @plugin = plugin 5 @plugin = plugin
6 attributes ||= {} 6 attributes ||= {}
7 attributes.each do |k,v| 7 attributes.each do |k,v|
@@ -10,7 +10,7 @@ class Noosfero::Plugin::Settings @@ -10,7 +10,7 @@ class Noosfero::Plugin::Settings
10 end 10 end
11 11
12 def settings 12 def settings
13 - @environment.settings["#{@plugin.public_name}_plugin".to_sym] ||= {} 13 + @base.settings["#{@plugin.public_name}_plugin".to_sym] ||= {}
14 end 14 end
15 15
16 def method_missing(method, *args, &block) 16 def method_missing(method, *args, &block)
@@ -38,7 +38,7 @@ class Noosfero::Plugin::Settings @@ -38,7 +38,7 @@ class Noosfero::Plugin::Settings
38 end 38 end
39 39
40 def save! 40 def save!
41 - @environment.save! 41 + @base.save!
42 end 42 end
43 43
44 end 44 end
plugins/shopping_cart/controllers/shopping_cart_plugin_controller.rb
@@ -100,15 +100,16 @@ class ShoppingCartPluginController &lt; PublicController @@ -100,15 +100,16 @@ class ShoppingCartPluginController &lt; PublicController
100 def buy 100 def buy
101 @cart = cart 101 @cart = cart
102 @enterprise = environment.enterprises.find(cart[:enterprise_id]) 102 @enterprise = environment.enterprises.find(cart[:enterprise_id])
  103 + @settings = Noosfero::Plugin::Settings.new(@enterprise, ShoppingCartPlugin)
103 render :layout => false 104 render :layout => false
104 end 105 end
105 106
106 def send_request 107 def send_request
107 register_order(params[:customer], self.cart[:items]) 108 register_order(params[:customer], self.cart[:items])
108 begin 109 begin
109 - enterprise = Enterprise.find(cart[:enterprise_id])  
110 - ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], enterprise, self.cart[:items])  
111 - ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], enterprise, self.cart[:items]) 110 + enterprise = environment.enterprises.find(cart[:enterprise_id])
  111 + ShoppingCartPlugin::Mailer.deliver_customer_notification(params[:customer], enterprise, self.cart[:items], params[:delivery_option])
  112 + ShoppingCartPlugin::Mailer.deliver_supplier_notification(params[:customer], enterprise, self.cart[:items], params[:delivery_option])
112 self.cart = nil 113 self.cart = nil
113 render :text => { 114 render :text => {
114 :ok => true, 115 :ok => true,
@@ -168,6 +169,25 @@ class ShoppingCartPluginController &lt; PublicController @@ -168,6 +169,25 @@ class ShoppingCartPluginController &lt; PublicController
168 end 169 end
169 end 170 end
170 171
  172 + def update_delivery_option
  173 + enterprise = environment.enterprises.find(cart[:enterprise_id])
  174 + settings = Noosfero::Plugin::Settings.new(enterprise, ShoppingCartPlugin)
  175 + delivery_price = settings.delivery_options[params[:delivery_option]]
  176 + delivery = Product.new(:name => params[:delivery_option], :price => delivery_price)
  177 + delivery.save(false)
  178 + items = self.cart[:items].clone
  179 + items[delivery.id] = 1
  180 + total_price = get_total_on_currency(items, environment)
  181 + delivery.destroy
  182 + render :text => {
  183 + :ok => true,
  184 + :delivery_price => float_to_currency_cart(delivery_price, environment),
  185 + :total_price => total_price,
  186 + :message => _('Delivery option updated.'),
  187 + :error => {:code => 0}
  188 + }.to_json
  189 + end
  190 +
171 private 191 private
172 192
173 def validate_same_enterprise(product) 193 def validate_same_enterprise(product)
plugins/shopping_cart/controllers/shopping_cart_plugin_myprofile_controller.rb
@@ -4,9 +4,12 @@ class ShoppingCartPluginMyprofileController &lt; MyProfileController @@ -4,9 +4,12 @@ class ShoppingCartPluginMyprofileController &lt; MyProfileController
4 append_view_path File.join(File.dirname(__FILE__) + '/../views') 4 append_view_path File.join(File.dirname(__FILE__) + '/../views')
5 5
6 def edit 6 def edit
  7 + params[:settings] = treat_cart_options(params[:settings])
  8 +
  9 + @settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin, params[:settings])
7 if request.post? 10 if request.post?
8 begin 11 begin
9 - profile.update_attributes!(params[:profile_attr]) 12 + @settings.save!
10 session[:notice] = _('Option updated successfully.') 13 session[:notice] = _('Option updated successfully.')
11 rescue Exception => exception 14 rescue Exception => exception
12 session[:notice] = _('Option wasn\'t updated successfully.') 15 session[:notice] = _('Option wasn\'t updated successfully.')
@@ -46,4 +49,25 @@ class ShoppingCartPluginMyprofileController &lt; MyProfileController @@ -46,4 +49,25 @@ class ShoppingCartPluginMyprofileController &lt; MyProfileController
46 order.save! 49 order.save!
47 redirect_to :action => 'reports', :from => params[:context_from], :to => params[:context_to], :filter_status => params[:context_status] 50 redirect_to :action => 'reports', :from => params[:context_from], :to => params[:context_to], :filter_status => params[:context_status]
48 end 51 end
  52 +
  53 + private
  54 +
  55 + def treat_cart_options(settings)
  56 + return if settings.blank?
  57 + settings[:enabled] = settings[:enabled] == '1'
  58 + settings[:delivery] = settings[:delivery] == '1'
  59 + settings[:free_delivery_price] = settings[:free_delivery_price].blank? ? nil : settings[:free_delivery_price].to_d
  60 + settings[:delivery_options] = treat_delivery_options(settings[:delivery_options])
  61 + settings
  62 + end
  63 +
  64 + def treat_delivery_options(params)
  65 + result = {}
  66 + params[:options].size.times do |counter|
  67 + if params[:options][counter].present? && params[:prices][counter].present?
  68 + result[params[:options][counter]] = params[:prices][counter]
  69 + end
  70 + end
  71 + result
  72 + end
49 end 73 end
plugins/shopping_cart/db/migrate/20121022190819_move_fields_included_on_profiles_table_to_settings.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class MoveFieldsIncludedOnProfilesTableToSettings < ActiveRecord::Migration
  2 + def self.up
  3 + Profile.find_each do |profile|
  4 + settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin)
  5 + settings.enabled = profile.shopping_cart
  6 + settings.delivery = profile.shopping_cart_delivery
  7 + settings.delivery_price = profile.shopping_cart_delivery_price
  8 + settings.save!
  9 + end
  10 +
  11 + remove_column :profiles, :shopping_cart
  12 + remove_column :profiles, :shopping_cart_delivery
  13 + remove_column :profiles, :shopping_cart_delivery_price
  14 + end
  15 +
  16 + def self.down
  17 + say "This migration can not be reverted!"
  18 + end
  19 +end
plugins/shopping_cart/lib/shopping_cart_plugin.rb
@@ -3,17 +3,36 @@ require_dependency &#39;shopping_cart_plugin/ext/person&#39; @@ -3,17 +3,36 @@ require_dependency &#39;shopping_cart_plugin/ext/person&#39;
3 3
4 class ShoppingCartPlugin < Noosfero::Plugin 4 class ShoppingCartPlugin < Noosfero::Plugin
5 5
6 - def self.plugin_name 6 + class << self
  7 + def plugin_name
7 "Shopping Basket" 8 "Shopping Basket"
8 - end 9 + end
  10 +
  11 + def plugin_description
  12 + _("A shopping basket feature for enterprises")
  13 + end
  14 +
  15 + def enabled_default_setting
  16 + true
  17 + end
9 18
10 - def self.plugin_description  
11 - _("A shopping basket feature for enterprises") 19 + def delivery_default_setting
  20 + false
  21 + end
  22 +
  23 + def delivery_price_default_setting
  24 + 0
  25 + end
  26 +
  27 + def delivery_options_default_setting
  28 + {}
  29 + end
12 end 30 end
13 31
14 def add_to_cart_button(item) 32 def add_to_cart_button(item)
15 enterprise = item.enterprise 33 enterprise = item.enterprise
16 - if enterprise.shopping_cart && item.available 34 + settings = Noosfero::Plugin::Settings.new(enterprise, ShoppingCartPlugin)
  35 + if settings.enabled && item.available
17 lambda { 36 lambda {
18 link_to(_('Add to basket'), "add:#{item.name}", 37 link_to(_('Add to basket'), "add:#{item.name}",
19 :class => 'cart-add-item', 38 :class => 'cart-add-item',
@@ -40,11 +59,12 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin @@ -40,11 +59,12 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
40 end 59 end
41 60
42 def control_panel_buttons 61 def control_panel_buttons
  62 + settings = Noosfero::Plugin::Settings.new(context.profile, ShoppingCartPlugin)
43 buttons = [] 63 buttons = []
44 if context.profile.enterprise? 64 if context.profile.enterprise?
45 buttons << { :title => _('Shopping basket'), :icon => 'shopping-cart-icon', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'edit'} } 65 buttons << { :title => _('Shopping basket'), :icon => 'shopping-cart-icon', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'edit'} }
46 end 66 end
47 - if context.profile.enterprise? && context.profile.shopping_cart 67 + if context.profile.enterprise? && settings.enabled
48 buttons << { :title => _('Purchase reports'), :icon => 'shopping-cart-purchase-report', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'reports'} } 68 buttons << { :title => _('Purchase reports'), :icon => 'shopping-cart-purchase-report', :url => {:controller => 'shopping_cart_plugin_myprofile', :action => 'reports'} }
49 end 69 end
50 70
plugins/shopping_cart/lib/shopping_cart_plugin/cart_helper.rb
@@ -8,46 +8,69 @@ module ShoppingCartPlugin::CartHelper @@ -8,46 +8,69 @@ module ShoppingCartPlugin::CartHelper
8 product.discount ? product.price_with_discount : product.price 8 product.discount ? product.price_with_discount : product.price
9 end 9 end
10 10
11 - def get_price(product, environment)  
12 - float_to_currency_cart(sell_price(product), environment) 11 + def get_price(product, environment, quantity=1)
  12 + float_to_currency_cart(price_with_quantity(product,quantity), environment)
13 end 13 end
14 14
15 - def get_total(items, environment)  
16 - float_to_currency_cart(items.map { |id, quantity| sell_price(Product.find(id)) * quantity}.sum, environment) 15 + def price_with_quantity(product, quantity=1)
  16 + quantity = 1 if !quantity.kind_of?(Numeric)
  17 + sell_price(product)*quantity
17 end 18 end
18 19
19 - def items_table(items, profile, by_mail = false) 20 + def get_total(items)
  21 + items.map { |id, quantity| price_with_quantity(Product.find(id),quantity)}.sum
  22 + end
  23 +
  24 + def get_total_on_currency(items, environment)
  25 + float_to_currency_cart(get_total(items), environment)
  26 + end
  27 +
  28 + def items_table(items, profile, delivery_option = nil, by_mail = false)
20 environment = profile.environment 29 environment = profile.environment
  30 + settings = Noosfero::Plugin::Settings.new(profile, ShoppingCartPlugin)
21 items = items.to_a 31 items = items.to_a
22 - if profile.shopping_cart_delivery  
23 - delivery = Product.create!(:name => _('Delivery'), :price => profile.shopping_cart_delivery_price, :product_category => ProductCategory.last)  
24 - items << [delivery.id, 1]  
25 - end  
26 32
27 quantity_opts = { :class => 'cart-table-quantity' } 33 quantity_opts = { :class => 'cart-table-quantity' }
28 quantity_opts.merge!({:align => 'center'}) if by_mail 34 quantity_opts.merge!({:align => 'center'}) if by_mail
29 price_opts = {:class => 'cart-table-price'} 35 price_opts = {:class => 'cart-table-price'}
30 price_opts.merge!({:align => 'right'}) if by_mail 36 price_opts.merge!({:align => 'right'}) if by_mail
  37 + items.sort! {|a, b| Product.find(a.first).name <=> Product.find(b.first).name}
  38 +
  39 + if settings.delivery
  40 + if settings.free_delivery_price && get_total(items) >= settings.free_delivery_price
  41 + delivery = Product.new(:name => _('Free delivery'), :price => 0)
  42 + else
  43 + delivery = Product.new(:name => delivery_option || _('Delivery'), :price => settings.delivery_options[delivery_option])
  44 + end
  45 + delivery.save(false)
  46 + items << [delivery.id, '']
  47 + end
31 48
32 table = '<table id="cart-items-table" cellpadding="2" cellspacing="0" 49 table = '<table id="cart-items-table" cellpadding="2" cellspacing="0"
33 border="'+(by_mail ? '1' : '0')+'" 50 border="'+(by_mail ? '1' : '0')+'"
34 style="'+(by_mail ? 'border-collapse:collapse' : '')+'">' + 51 style="'+(by_mail ? 'border-collapse:collapse' : '')+'">' +
35 content_tag('tr', 52 content_tag('tr',
36 - content_tag('th', _('Item name')) +  
37 - content_tag('th', by_mail ? '&nbsp;#&nbsp;' : '#') +  
38 - content_tag('th', _('Price')) 53 + content_tag('th', _('Item name')) +
  54 + content_tag('th', by_mail ? '&nbsp;#&nbsp;' : '#') +
  55 + content_tag('th', _('Price'))
39 ) + 56 ) +
40 items.map do |id, quantity| 57 items.map do |id, quantity|
41 product = Product.find(id) 58 product = Product.find(id)
  59 + name_opts = {}
  60 + is_delivery = quantity.kind_of?(String)
  61 + if is_delivery
  62 + price_opts.merge!({:id => 'delivery-price'})
  63 + name_opts.merge!({:id => 'delivery-name'})
  64 + end
42 content_tag('tr', 65 content_tag('tr',
43 - content_tag('td', product.name) +  
44 - content_tag('td', quantity, quantity_opts ) +  
45 - content_tag('td', get_price(product, environment), price_opts )  
46 - ) 66 + content_tag('td', product.name, name_opts) +
  67 + content_tag('td', quantity, quantity_opts ) +
  68 + content_tag('td', get_price(product, environment, quantity), price_opts)
  69 + )
47 end.join("\n") 70 end.join("\n")
48 71
49 - total = get_total(items, environment)  
50 - delivery.destroy if profile.shopping_cart_delivery 72 + total = get_total_on_currency(items, environment)
  73 + delivery.destroy if settings.delivery
51 74
52 table + 75 table +
53 content_tag('th', _('Total:'), :colspan => 2, :class => 'cart-table-total-label') + 76 content_tag('th', _('Total:'), :colspan => 2, :class => 'cart-table-total-label') +
@@ -56,6 +79,14 @@ module ShoppingCartPlugin::CartHelper @@ -56,6 +79,14 @@ module ShoppingCartPlugin::CartHelper
56 end 79 end
57 80
58 def float_to_currency_cart(value, environment) 81 def float_to_currency_cart(value, environment)
59 - number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :precision => 2, :format => "%u %n") 82 + number_to_currency(value, :unit => environment.currency_unit, :separator => environment.currency_separator, :delimiter => environment.currency_delimiter, :precision => 2, :format => "%u%n")
  83 + end
  84 +
  85 + def select_delivery_options(options, environment)
  86 + result = options.map do |option, price|
  87 + ["#{option} (#{float_to_currency_cart(price, environment)})", option]
  88 + end
  89 + result << ["#{_('Delivery')} (#{float_to_currency_cart(0, environment)})", 'delivery'] if result.empty?
  90 + result
60 end 91 end
61 end 92 end
plugins/shopping_cart/lib/shopping_cart_plugin/mailer.rb
@@ -2,7 +2,7 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -2,7 +2,7 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
2 2
3 include ShoppingCartPlugin::CartHelper 3 include ShoppingCartPlugin::CartHelper
4 4
5 - def customer_notification(customer, supplier, items) 5 + def customer_notification(customer, supplier, items, delivery_option)
6 domain = supplier.hostname || supplier.environment.default_hostname 6 domain = supplier.hostname || supplier.environment.default_hostname
7 recipients customer[:email] 7 recipients customer[:email]
8 from 'no-reply@' + domain 8 from 'no-reply@' + domain
@@ -13,10 +13,11 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -13,10 +13,11 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
13 :supplier => supplier, 13 :supplier => supplier,
14 :items => items, 14 :items => items,
15 :environment => supplier.environment, 15 :environment => supplier.environment,
16 - :helper => self 16 + :helper => self,
  17 + :delivery_option => delivery_option
17 end 18 end
18 19
19 - def supplier_notification(customer, supplier, items) 20 + def supplier_notification(customer, supplier, items, delivery_option)
20 domain = supplier.environment.default_hostname 21 domain = supplier.environment.default_hostname
21 recipients supplier.contact_email 22 recipients supplier.contact_email
22 from 'no-reply@' + domain 23 from 'no-reply@' + domain
@@ -27,7 +28,7 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase @@ -27,7 +28,7 @@ class ShoppingCartPlugin::Mailer &lt; Noosfero::Plugin::MailerBase
27 :supplier => supplier, 28 :supplier => supplier,
28 :items => items, 29 :items => items,
29 :environment => supplier.environment, 30 :environment => supplier.environment,
30 - :helper => self  
31 - 31 + :helper => self,
  32 + :delivery_option => delivery_option
32 end 33 end
33 end 34 end
plugins/shopping_cart/public/buy.js 0 → 100644
@@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
  1 +jQuery(document).ready(function(){
  2 + jQuery("#cart-request-form").validate({
  3 + submitHandler: function(form) {
  4 + jQuery(form).find('input.submit').attr('disabled', true);
  5 + jQuery('#cboxLoadingOverlay').show().addClass('loading');
  6 + jQuery('#cboxLoadingGraphic').show().addClass('loading');
  7 + }
  8 + });
  9 +});
  10 +
  11 +jQuery('#delivery_option').change(function(){
  12 + jQuery('#cboxLoadingGraphic').show();
  13 + me = this;
  14 + enterprise = jQuery(me).attr('data-profile-identifier');
  15 + option = jQuery(me).val();
  16 + jQuery.ajax({
  17 + url: '/plugin/shopping_cart/update_delivery_option',
  18 + dataType: "json",
  19 + data: 'delivery_option='+option,
  20 + success: function(data, st, ajax) {
  21 + jQuery('#delivery-price').text(data.delivery_price);
  22 + jQuery('.cart-table-total-value').text(data.total_price);
  23 + jQuery('#delivery-name').text(option);
  24 + jQuery('#cboxLoadingGraphic').hide();
  25 + },
  26 + error: function(ajax, st, errorThrown) {
  27 + alert('Update delivery option - HTTP '+st+': '+errorThrown);
  28 + },
  29 + });
  30 +});
  31 +
  32 +jQuery('#customer_payment').change(function(){
  33 + jQuery(this).closest('.formfieldline').next().slideToggle('fast');
  34 +});
plugins/shopping_cart/public/edit.js 0 → 100644
@@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
  1 +jQuery('#settings_delivery').click(function(){
  2 + jQuery('#delivery_settings').toggle('fast');
  3 +});
  4 +
  5 +jQuery('#add-new-option').click(function(){
  6 + new_option = jQuery('#empty-option').clone();
  7 + new_option.removeAttr('id');
  8 + jQuery('#add-new-option-row').before(new_option);
  9 + new_option.show();
  10 + return false;
  11 +});
  12 +
  13 +jQuery('.remove-option').live('click', function(){
  14 + jQuery(this).closest('tr').remove();
  15 + return false;
  16 +});
plugins/shopping_cart/test/functional/shopping_cart_plugin_myprofile_controller_test.rb
@@ -13,46 +13,42 @@ class ShoppingCartPluginMyprofileControllerTest &lt; ActionController::TestCase @@ -13,46 +13,42 @@ class ShoppingCartPluginMyprofileControllerTest &lt; ActionController::TestCase
13 attr_reader :enterprise 13 attr_reader :enterprise
14 14
15 should 'be able to enable shopping cart' do 15 should 'be able to enable shopping cart' do
16 - enterprise.shopping_cart = false  
17 - enterprise.save  
18 - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart => '1'}  
19 - enterprise.reload 16 + settings.enabled = false
  17 + settings.save!
  18 + post :edit, :profile => enterprise.identifier, :settings => {:enabled => '1'}
20 19
21 - assert enterprise.shopping_cart 20 + assert settings.enabled
22 end 21 end
23 22
24 should 'be able to disable shopping cart' do 23 should 'be able to disable shopping cart' do
25 - enterprise.shopping_cart = true  
26 - enterprise.save  
27 - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart => '0'}  
28 - enterprise.reload 24 + settings.enabled = true
  25 + settings.save!
  26 + post :edit, :profile => enterprise.identifier, :settings => {:enabled => '0'}
29 27
30 - assert !enterprise.shopping_cart 28 + assert !settings.enabled
31 end 29 end
32 30
33 should 'be able to enable shopping cart delivery' do 31 should 'be able to enable shopping cart delivery' do
34 - enterprise.shopping_cart_delivery = false  
35 - enterprise.save  
36 - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery => '1'}  
37 - enterprise.reload 32 + settings.delivery = false
  33 + settings.save!
  34 + post :edit, :profile => enterprise.identifier, :settings => {:delivery => '1'}
38 35
39 - assert enterprise.shopping_cart_delivery 36 + assert settings.delivery
40 end 37 end
41 38
42 should 'be able to disable shopping cart delivery' do 39 should 'be able to disable shopping cart delivery' do
43 - enterprise.shopping_cart_delivery = true  
44 - enterprise.save  
45 - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery => '0'}  
46 - enterprise.reload 40 + settings.delivery = true
  41 + settings.save!
  42 + post :edit, :profile => enterprise.identifier, :settings => {:delivery => '0'}
47 43
48 - assert !enterprise.shopping_cart_delivery 44 + assert !settings.delivery
49 end 45 end
50 46
51 should 'be able to choose the delivery price' do 47 should 'be able to choose the delivery price' do
52 price = 4.35 48 price = 4.35
53 - post :edit, :profile => enterprise.identifier, :profile_attr => {:shopping_cart_delivery_price => price}  
54 - enterprise.reload  
55 - assert enterprise.shopping_cart_delivery_price == price 49 + post :edit, :profile => enterprise.identifier, :settings => {:delivery_price => price}
  50 +
  51 + assert settings.delivery_price == price
56 end 52 end
57 53
58 should 'filter the reports correctly' do 54 should 'filter the reports correctly' do
@@ -112,4 +108,11 @@ class ShoppingCartPluginMyprofileControllerTest &lt; ActionController::TestCase @@ -112,4 +108,11 @@ class ShoppingCartPluginMyprofileControllerTest &lt; ActionController::TestCase
112 po.reload 108 po.reload
113 assert_equal ShoppingCartPlugin::PurchaseOrder::Status::CONFIRMED, po.status 109 assert_equal ShoppingCartPlugin::PurchaseOrder::Status::CONFIRMED, po.status
114 end 110 end
  111 +
  112 + private
  113 +
  114 + def settings
  115 + @enterprise.reload
  116 + Noosfero::Plugin::Settings.new(@enterprise, ShoppingCartPlugin)
  117 + end
115 end 118 end
plugins/shopping_cart/views/shopping_cart_plugin/buy.html.erb
@@ -6,30 +6,26 @@ @@ -6,30 +6,26 @@
6 <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %> 6 <%= labelled_form_field('* ' + _("Name"), f.text_field(:name, :class => 'required') ) %>
7 <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %> 7 <%= labelled_form_field('* ' + _("Email"), f.text_field(:email, :class => 'required email') ) %>
8 <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %> 8 <%= labelled_form_field('* ' + _("Contact phone"), f.text_field(:contact_phone, :class => 'required') ) %>
  9 + <%= labelled_form_field(_('Delivery option'), select_tag(:delivery_option, options_for_select(select_delivery_options(@settings.delivery_options, environment)), 'data-profile-identifier' => @enterprise.identifier)) unless !@settings.delivery || (@settings.free_delivery_price && get_total(@cart[:items]) >= @settings.free_delivery_price) %>
  10 + <%= labelled_form_field(_('Payment'), select_tag('customer[payment]', options_for_select([[_("Money"), :money],[_('Check'), :check]]))) %>
  11 + <%= labelled_form_field(_('Change'), text_field_tag('customer[change]')) %>
9 </div> 12 </div>
10 - <fieldset><legend><%=_('Delivery Address')%></legend>  
11 - <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %>  
12 - <%= labelled_form_field( _("City"), f.text_field(:city)) %>  
13 - <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %>  
14 - </fieldset> 13 + <% if @settings.delivery %>
  14 + <fieldset><legend><%=_('Delivery Address')%></legend>
  15 + <%= labelled_form_field(_('Address (street and number)'), f.text_field(:address)) %>
  16 + <%= labelled_form_field(_('Address reference'), f.text_field(:address_reference)) %>
  17 + <%= labelled_form_field(_('District'), f.text_field(:district)) %>
  18 + <%= labelled_form_field( _("City"), f.text_field(:city)) %>
  19 + <%= labelled_form_field(_('ZIP code'), f.text_field(:zip_code)) %>
  20 + </fieldset>
  21 + <% end %>
15 <div id="cart-form-actions"> 22 <div id="cart-form-actions">
16 <%= submit_button(:send, _('Send buy request')) %> 23 <%= submit_button(:send, _('Send buy request')) %>
17 </div> 24 </div>
18 <% end %> 25 <% end %>
19 - <%= items_table(@cart[:items], @enterprise) %> 26 + <% delivery_option = @settings.delivery_options.first && @settings.delivery_options.first.first %>
  27 + <%= items_table(@cart[:items], @enterprise, delivery_option) %>
20 <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> 28 <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %>
21 </div> 29 </div>
22 30
23 -<script type="text/javascript">  
24 -//<![CDATA[  
25 - jQuery(document).ready(function(){  
26 - jQuery("#cart-request-form").validate({  
27 - submitHandler: function(form) {  
28 - jQuery(form).find('input.submit').attr('disabled', true);  
29 - jQuery('#cboxLoadingOverlay').show().addClass('loading');  
30 - jQuery('#cboxLoadingGraphic').show().addClass('loading');  
31 - }  
32 - });  
33 - });  
34 -//]]>  
35 -</script> 31 +<%= javascript_include_tag '../plugins/shopping_cart/buy' %>
plugins/shopping_cart/views/shopping_cart_plugin/mailer/customer_notification.html.erb
@@ -17,26 +17,35 @@ @@ -17,26 +17,35 @@
17 <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> 17 <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li>
18 <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> 18 <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li>
19 <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> 19 <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li>
20 - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> 20 + <li><b><%= _('Payment') %>: </b><%= @customer[:payment] == 'money' ? _('Money') : _('Check') %></li>
  21 + <% if @customer[:payment] == 'money' %>
  22 + <li><b><%= _('Change') %>: </b><%= @customer[:change] %></li>
  23 + <% end %>
  24 + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %>
21 <li><b><%= _('Address') %>:</b> 25 <li><b><%= _('Address') %>:</b>
22 <% end %> 26 <% end %>
23 <% if !@customer[:address].blank? %> 27 <% if !@customer[:address].blank? %>
24 <%= @customer[:address] %><br \> 28 <%= @customer[:address] %><br \>
25 <% end %> 29 <% end %>
  30 + <% if !@customer[:district].blank? %>
  31 + <%= @customer[:district] %><br \>
  32 + <% end %>
26 <% if !@customer[:city].blank? %> 33 <% if !@customer[:city].blank? %>
27 <%= @customer[:city] %><br \> 34 <%= @customer[:city] %><br \>
28 <% end %> 35 <% end %>
29 <% if !@customer[:zip_code].blank? %> 36 <% if !@customer[:zip_code].blank? %>
30 <%= @customer[:zip_code] %> 37 <%= @customer[:zip_code] %>
31 <% end %> 38 <% end %>
32 - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> 39 + <% if !@customer[:address_reference].blank? %>
  40 + <%= @customer[:address_reference] %><br \>
  41 + <% end %>
  42 + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %>
33 </li> 43 </li>
34 <% end %> 44 <% end %>
35 </ul> 45 </ul>
36 46
37 <p><%=_('Here are the products you bought:')%></p> 47 <p><%=_('Here are the products you bought:')%></p>
38 - <%= @helper.items_table(@items, @supplier, true) %>  
39 - 48 + <%= @helper.items_table(@items, @supplier, @delivery_option, true) %>
40 <p> 49 <p>
41 --<br/> 50 --<br/>
42 <%=_('Thanks for buying with us!')%><br/> 51 <%=_('Thanks for buying with us!')%><br/>
plugins/shopping_cart/views/shopping_cart_plugin/mailer/supplier_notification.html.erb
@@ -15,26 +15,35 @@ @@ -15,26 +15,35 @@
15 <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li> 15 <li><b><%= _('Full name') %>: </b><%= @customer[:name] %></li>
16 <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li> 16 <li><b><%= _('Email') %>: </b><%= @customer[:email] %></li>
17 <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li> 17 <li><b><%= _('Phone number') %>: </b><%= @customer[:contact_phone] %></li>
18 - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> 18 + <li><b><%= _('Payment') %>: </b><%= @customer[:payment] == 'money' ? _('Money') : _('Check') %></li>
  19 + <% if @customer[:payment] == 'money' %>
  20 + <li><b><%= _('Change') %>: </b><%= @customer[:change] %></li>
  21 + <% end %>
  22 + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %>
19 <li><b><%= _('Address') %>:</b> 23 <li><b><%= _('Address') %>:</b>
20 <% end %> 24 <% end %>
21 <% if !@customer[:address].blank? %> 25 <% if !@customer[:address].blank? %>
22 <%= @customer[:address] %><br \> 26 <%= @customer[:address] %><br \>
23 <% end %> 27 <% end %>
  28 + <% if !@customer[:district].blank? %>
  29 + <%= @customer[:district] %><br \>
  30 + <% end %>
24 <% if !@customer[:city].blank? %> 31 <% if !@customer[:city].blank? %>
25 <%= @customer[:city] %><br \> 32 <%= @customer[:city] %><br \>
26 <% end %> 33 <% end %>
27 <% if !@customer[:zip_code].blank? %> 34 <% if !@customer[:zip_code].blank? %>
28 <%= @customer[:zip_code] %> 35 <%= @customer[:zip_code] %>
29 <% end %> 36 <% end %>
30 - <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? %> 37 + <% if !@customer[:address_reference].blank? %>
  38 + <%= @customer[:address_reference] %><br \>
  39 + <% end %>
  40 + <% if !@customer[:address].blank? || !@customer[:city].blank? || !@customer[:zip_code].blank? || !@customer[:district].blank? || !@customer[:address_reference].blank? %>
31 </li> 41 </li>
32 <% end %> 42 <% end %>
33 </ul> 43 </ul>
34 44
35 <p><%=_('And here are the items bought by this customer:')%></p> 45 <p><%=_('And here are the items bought by this customer:')%></p>
36 - <%= @helper.items_table(@items, @supplier, true) %>  
37 - 46 + <%= @helper.items_table(@items, @supplier, @delivery_option, true) %>
38 <p> 47 <p>
39 --<br/> 48 --<br/>
40 <%=_('If there are any problems with this email contact the admin of %s.') % @environment.name %> 49 <%=_('If there are any problems with this email contact the admin of %s.') % @environment.name %>
plugins/shopping_cart/views/shopping_cart_plugin_myprofile/edit.html.erb
1 <h1> <%= _('Basket options') %> </h1> 1 <h1> <%= _('Basket options') %> </h1>
2 2
3 -<% form_for(:profile_attr, profile, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %>  
4 - <%= labelled_form_field(_('Enabled?'), f.check_box(:shopping_cart)) %>  
5 - <%= labelled_form_field(_('Delivery?'), f.check_box(:shopping_cart_delivery)) %>  
6 - <%= labelled_form_field(_('Delivery price:'), f.text_field(:shopping_cart_delivery_price)) %> 3 +<% form_for(:settings, @settings, :url => {:action => 'edit'}, :html => {:method => 'post'}) do |f| %>
  4 + <%= labelled_form_field(_('Enabled?'), f.check_box(:enabled)) %>
  5 + <%= labelled_form_field(_('Delivery?'), f.check_box(:delivery)) %>
  6 + <% display_delivery_settings = @settings.delivery ? 'auto' : 'none' %>
  7 + <fieldset id='delivery_settings' style="display: <%= display_delivery_settings %>"><legend><%=_('Delivery')%></legend>
  8 + <table>
  9 + <tr>
  10 + <th><%= _('Option') %></th>
  11 + <th><%= _('Price') %></th>
  12 + <th>&nbsp;</th>
  13 + </tr>
  14 + <% @settings.delivery_options.each do |option, price| %>
  15 + <tr>
  16 + <td><%= text_field_tag('settings[delivery_options][options][]', option, :style => 'width: 100%') %></td>
  17 + <td><%= text_field_tag('settings[delivery_options][prices][]', price, :style => 'width: 100%') %></td>
  18 + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td>
  19 + </tr>
  20 + <% end %>
  21 + <tr>
  22 + <td><%= text_field_tag('settings[delivery_options][options][]', nil, :style => 'width: 100%') %></td>
  23 + <td><%= text_field_tag('settings[delivery_options][prices][]', nil, :style => 'width: 100%') %></td>
  24 + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td>
  25 + </tr>
  26 + <tr id='add-new-option-row'>
  27 + <td colspan='3' style='background-color: #EEE; text-align: center'><%= link_to(_('ADD NEW OPTION'), '', :id => 'add-new-option') %></td>
  28 + </tr>
  29 + <tr id="empty-option" style='display: none'>
  30 + <td><%= text_field_tag('settings[delivery_options][options][]', nil, :style => 'width: 100%') %></td>
  31 + <td><%= text_field_tag('settings[delivery_options][prices][]', nil, :style => 'width: 100%') %></td>
  32 + <td><%= button_without_text(:close, _('Remove option'), '', :class => 'remove-option') %></td>
  33 + </tr>
  34 + </table>
  35 +
  36 + <%= labelled_form_field(_('Free delivery price:'), f.text_field(:free_delivery_price)) %>
  37 + <%= content_tag('small', _('Empty stands for no free delivery price.')) %>
  38 + </fieldset>
7 <br style='clear: both'/> 39 <br style='clear: both'/>
8 <br style='clear: both'/> 40 <br style='clear: both'/>
9 <div> 41 <div>
@@ -11,3 +43,5 @@ @@ -11,3 +43,5 @@
11 <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %> 43 <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %>
12 </div> 44 </div>
13 <% end%> 45 <% end%>
  46 +
  47 +<%= javascript_include_tag '../plugins/shopping_cart/edit' %>
public/designs/themes/noosfero/images/rails.png 0 → 100644

1.75 KB

public/images/star.png 0 → 100644

3.58 KB

public/stylesheets/application.css
@@ -2681,6 +2681,40 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation @@ -2681,6 +2681,40 @@ div#activation_enterprise label, div#activation_enterprise input, div#activation
2681 .msie #product-list h3 { 2681 .msie #product-list h3 {
2682 margin-top: -15px; 2682 margin-top: -15px;
2683 } 2683 }
  2684 +
  2685 +.l-sidebar-left-bar ul,
  2686 +.l-sidebar-right-bar ul {
  2687 + list-style-type: none;
  2688 + margin-left: 0;
  2689 + padding: 1em 1em 0.5em 1em;
  2690 +}
  2691 +
  2692 +.l-sidebar-left-bar ul ul,
  2693 +.l-sidebar-right-bar ul ul {
  2694 + padding-top: 0;
  2695 +}
  2696 +
  2697 +.l-sidebar-left-bar ul{
  2698 + background-color: #eeeeec;
  2699 + border-radius: 5px;
  2700 +}
  2701 +
  2702 +.l-sidebar-left-bar a,
  2703 +.l-sidebar-right-bar a {
  2704 + text-decoration: none;
  2705 +}
  2706 +
  2707 +.l-sidebar-left-bar a:hover,
  2708 +.l-sidebar-right-bar a:hover {
  2709 + text-decoration: underline;
  2710 +}
  2711 +
  2712 +.l-sidebar-left-bar li,
  2713 +.l-sidebar-right-bar li {
  2714 + margin: 0;
  2715 + padding: 0;
  2716 +}
  2717 +
2684 /* * * Show Product * * * * * * * * * * * * */ 2718 /* * * Show Product * * * * * * * * * * * * */
2685 2719
2686 .controller-catalog #show_product .product-pic { 2720 .controller-catalog #show_product .product-pic {
@@ -6070,6 +6104,35 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -6070,6 +6104,35 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6070 line-height: 1.5; 6104 line-height: 1.5;
6071 } 6105 }
6072 6106
  6107 +/* Sidebar Layout */
  6108 +
  6109 +.l-sidebar-left-bar {
  6110 + float: left;
  6111 + width: 20%;
  6112 +}
  6113 +
  6114 +.l-sidebar-left-content {
  6115 + float: right;
  6116 + width: 78%;
  6117 +}
  6118 +
  6119 +.l-sidebar-right-bar {
  6120 + float: right;
  6121 + width: 20%;
  6122 +}
  6123 +
  6124 +.l-sidebar-right-content {
  6125 + float: left;
  6126 + width: 78%;
  6127 +}
  6128 +
  6129 +/* Breadcrumb */
  6130 +
  6131 +#breadcrumb {
  6132 + font-size: 16px;
  6133 + margin: 15px 0;
  6134 +}
  6135 +
6073 .controller-profile_editor #profile-data { 6136 .controller-profile_editor #profile-data {
6074 display: table; 6137 display: table;
6075 width: auto; 6138 width: auto;
@@ -6118,3 +6181,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img { @@ -6118,3 +6181,10 @@ li.profile-activity-item.upload_image .activity-gallery-images-count-1 img {
6118 width: 100px; 6181 width: 100px;
6119 text-align: center; 6182 text-align: center;
6120 } 6183 }
  6184 +
  6185 +#product-list .highlighted img.star {
  6186 + position: absolute;
  6187 + top: 2px;
  6188 + right: 2px;
  6189 + z-index: 10;
  6190 +}
test/functional/catalog_controller_test.rb
@@ -109,4 +109,119 @@ class CatalogControllerTest &lt; ActionController::TestCase @@ -109,4 +109,119 @@ class CatalogControllerTest &lt; ActionController::TestCase
109 assert_tag :tag => 'span', :content => 'This is Plugin2 speaking!', :attributes => {:id => 'plugin2'} 109 assert_tag :tag => 'span', :content => 'This is Plugin2 speaking!', :attributes => {:id => 'plugin2'}
110 end 110 end
111 111
  112 + should 'get categories of the right level' do
  113 + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment)
  114 + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id)
  115 + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id)
  116 + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id)
  117 + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id)
  118 + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id)
  119 + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id)
  120 + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id)
  121 +
  122 + get :index, :profile => @enterprise.identifier, :level => pc1.id
  123 +
  124 + assert_not_includes assigns(:categories), pc1
  125 + assert_includes assigns(:categories), pc2
  126 + assert_includes assigns(:categories), pc3
  127 + assert_not_includes assigns(:categories), pc4
  128 + end
  129 +
  130 + should 'filter products based on level selected' do
  131 + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment)
  132 + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id)
  133 + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id)
  134 + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id)
  135 + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id)
  136 + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id)
  137 + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id)
  138 + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id)
  139 +
  140 + get :index, :profile => @enterprise.identifier, :level => pc2.id
  141 +
  142 + assert_not_includes assigns(:products), p1
  143 + assert_includes assigns(:products), p2
  144 + assert_not_includes assigns(:products), p3
  145 + assert_includes assigns(:products), p4
  146 + end
  147 +
  148 + should 'get products ordered by availability, highlighted and then name' do
  149 + p1 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Zebra', :available => true, :highlighted => true)
  150 + p2 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Car', :available => true)
  151 + p3 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Panda', :available => true)
  152 + p4 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Pen', :available => false, :highlighted => true)
  153 + p5 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Ball', :available => false)
  154 + p6 = fast_create(Product, :enterprise_id => @enterprise.id, :name => 'Medal', :available => false)
  155 +
  156 + get :index, :profile => @enterprise.identifier
  157 +
  158 + assert_equal [p1,p2,p3,p4,p5,p6], assigns(:products)
  159 + end
  160 +
  161 + should 'add highlighted CSS class around a highlighted product' do
  162 + prod = @enterprise.products.create!(:name => 'Highlighted Product', :product_category => @product_category, :highlighted => true)
  163 + get :index, :profile => @enterprise.identifier
  164 + assert_tag :tag => 'li', :attributes => { :class => 'product highlighted' }, :content => /Highlighted Product/
  165 + end
  166 +
  167 + should 'do not add highlighted CSS class around an ordinary product' do
  168 + prod = @enterprise.products.create!(:name => 'Ordinary Product', :product_category => @product_category, :highlighted => false)
  169 + get :index, :profile => @enterprise.identifier
  170 + assert_no_tag :tag => 'li', :attributes => { :class => 'product highlighted' }, :content => /Ordinary Product/
  171 + end
  172 +
  173 + should 'display star image in highlighted product' do
  174 + prod = @enterprise.products.create!(:name => 'The Eyes Are The Light', :product_category => @product_category, :highlighted => true)
  175 + get :index, :profile => @enterprise.identifier
  176 + assert_tag :tag => 'img', :attributes => { :class => 'star', :src => /star.png/ }
  177 + end
  178 +
  179 + should 'display categories and sub-categories link' do
  180 + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment)
  181 + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id)
  182 + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id)
  183 + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id)
  184 + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id)
  185 + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id)
  186 + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id)
  187 + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id)
  188 +
  189 + get :index, :profile => @enterprise.identifier
  190 +
  191 + assert_tag :tag => 'a', :attributes => {:href => /level=#{pc1.id}/}
  192 + assert_tag :tag => 'a', :attributes => {:href => /level=#{pc2.id}/}
  193 + assert_tag :tag => 'a', :attributes => {:href => /level=#{pc3.id}/}
  194 + assert_no_tag :tag => 'a', :attributes => {:href => /level=#{pc4.id}/}
  195 + end
  196 +
  197 +
  198 + should 'display categories on breadcrumb' do
  199 + pc1 = ProductCategory.create!(:name => "PC1", :environment => @enterprise.environment)
  200 + pc2 = ProductCategory.create!(:name => "PC2", :environment => @enterprise.environment, :parent_id => pc1.id)
  201 + pc3 = ProductCategory.create!(:name => "PC3", :environment => @enterprise.environment, :parent_id => pc1.id)
  202 + pc4 = ProductCategory.create!(:name => "PC4", :environment => @enterprise.environment, :parent_id => pc2.id)
  203 + p1 = fast_create(Product, :product_category_id => pc1.id, :enterprise_id => @enterprise.id)
  204 + p2 = fast_create(Product, :product_category_id => pc2.id, :enterprise_id => @enterprise.id)
  205 + p3 = fast_create(Product, :product_category_id => pc3.id, :enterprise_id => @enterprise.id)
  206 + p4 = fast_create(Product, :product_category_id => pc4.id, :enterprise_id => @enterprise.id)
  207 +
  208 + get :index, :profile => @enterprise.identifier, :level => pc4.id
  209 +
  210 + assert_tag :tag => 'div', :attributes => {:id => 'breadcrumb'}, :descendant => {:tag => 'a', :attributes => {:href => /level=#{pc1.id}/}}
  211 + assert_tag :tag => 'div', :attributes => {:id => 'breadcrumb'}, :descendant => {:tag => 'a', :attributes => {:href => /level=#{pc2.id}/}}
  212 + assert_tag :tag => 'div', :attributes => {:id => 'breadcrumb'}, :descendant => {:tag => 'strong', :content => pc4.name}
  213 + assert_no_tag :tag => 'div', :attributes => {:id => 'breadcrumb'}, :descendant => {:tag => 'a', :attributes => {:href => /level=#{pc3.id}/}}
  214 + end
  215 +
  216 + should 'add product status on the class css' do
  217 + category = ProductCategory.create!(:name => "Cateogry", :environment => @enterprise.environment)
  218 + p1 = fast_create(Product, :product_category_id => category.id, :enterprise_id => @enterprise.id, :highlighted => true)
  219 + p2 = fast_create(Product, :product_category_id => category.id, :enterprise_id => @enterprise.id, :available => false)
  220 +
  221 + get :index, :profile => @enterprise.identifier
  222 +
  223 + assert_tag :tag => 'li', :attributes => {:id => "product-#{p1.id}", :class => /highlighted/}
  224 + assert_tag :tag => 'li', :attributes => {:id => "product-#{p2.id}", :class => /not-available/}
  225 + end
  226 +
112 end 227 end
test/functional/search_controller_test.rb
@@ -926,6 +926,20 @@ class SearchControllerTest &lt; ActionController::TestCase @@ -926,6 +926,20 @@ class SearchControllerTest &lt; ActionController::TestCase
926 end 926 end
927 end 927 end
928 928
  929 + should 'add highlighted CSS class around a highlighted product' do
  930 + enterprise = fast_create(Enterprise)
  931 + product = Product.create!(:name => 'Enter Sandman', :enterprise_id => enterprise.id, :product_category_id => @product_category.id, :highlighted => true)
  932 + get :products
  933 + assert_tag :tag => 'li', :attributes => { :class => 'search-product-item highlighted' }, :content => /Enter Sandman/
  934 + end
  935 +
  936 + should 'do not add highlighted CSS class around an ordinary product' do
  937 + enterprise = fast_create(Enterprise)
  938 + product = Product.create!(:name => 'Holier Than Thou', :enterprise_id => enterprise.id, :product_category_id => @product_category.id, :highlighted => false)
  939 + get :products
  940 + assert_no_tag :tag => 'li', :attributes => { :class => 'search-product-item highlighted' }, :content => /Holier Than Thou/
  941 + end
  942 +
929 ################################################################## 943 ##################################################################
930 ################################################################## 944 ##################################################################
931 945
test/unit/category_test.rb
@@ -552,4 +552,62 @@ class CategoryTest &lt; ActiveSupport::TestCase @@ -552,4 +552,62 @@ class CategoryTest &lt; ActiveSupport::TestCase
552 cat.save! 552 cat.save!
553 end 553 end
554 554
  555 + should 'return categories of a level' do
  556 + c1 = fast_create(Category)
  557 + c2 = fast_create(Category)
  558 + c3 = fast_create(Category, :parent_id => c1)
  559 + c4 = fast_create(Category, :parent_id => c1)
  560 + c5 = fast_create(Category, :parent_id => c2)
  561 + c6 = fast_create(Category, :parent_id => c3)
  562 +
  563 + assert_includes Category.on_level(nil), c1
  564 + assert_includes Category.on_level(nil), c2
  565 + assert_includes Category.on_level(c1), c3
  566 + assert_includes Category.on_level(c1), c4
  567 + assert_includes Category.on_level(c2), c5
  568 + assert_includes Category.on_level(c3), c6
  569 + end
  570 +
  571 + should 'on level named_scope must be able to receive parent or parent_id' do
  572 + parent = fast_create(Category)
  573 + category = fast_create(Category, :parent_id => parent)
  574 +
  575 + assert_includes Category.on_level(parent), category
  576 + assert_includes Category.on_level(parent.id), category
  577 + end
  578 +
  579 + should 'list category sub-categories' do
  580 + c1 = Category.create!(:name => 'Category 1', :environment => Environment.default)
  581 + c2 = Category.create!(:name => 'Category 2', :environment => Environment.default)
  582 + c3 = Category.create!(:name => 'Category 3', :environment => Environment.default, :parent_id => c1)
  583 + c4 = Category.create!(:name => 'Category 4', :environment => Environment.default, :parent_id => c1)
  584 + c5 = Category.create!(:name => 'Category 5', :environment => Environment.default, :parent_id => c3)
  585 +
  586 + sub_categories = Category.sub_categories(c1)
  587 +
  588 + assert ActiveRecord::NamedScope::Scope, sub_categories.class
  589 + assert_not_includes sub_categories, c1
  590 + assert_not_includes sub_categories, c2
  591 + assert_includes sub_categories, c3
  592 + assert_includes sub_categories, c4
  593 + assert_includes sub_categories, c5
  594 + end
  595 +
  596 + should 'list category sub-tree' do
  597 + c1 = Category.create!(:name => 'Category 1', :environment => Environment.default)
  598 + c2 = Category.create!(:name => 'Category 2', :environment => Environment.default)
  599 + c3 = Category.create!(:name => 'Category 3', :environment => Environment.default, :parent_id => c1)
  600 + c4 = Category.create!(:name => 'Category 4', :environment => Environment.default, :parent_id => c1)
  601 + c5 = Category.create!(:name => 'Category 5', :environment => Environment.default, :parent_id => c3)
  602 +
  603 + sub_tree = Category.sub_tree(c1)
  604 +
  605 + assert ActiveRecord::NamedScope::Scope, sub_tree.class
  606 + assert_includes sub_tree, c1
  607 + assert_not_includes sub_tree, c2
  608 + assert_includes sub_tree, c3
  609 + assert_includes sub_tree, c4
  610 + assert_includes sub_tree, c5
  611 + end
  612 +
555 end 613 end
test/unit/display_helper_test.rb
@@ -44,4 +44,14 @@ class DisplayHelperTest &lt; ActiveSupport::TestCase @@ -44,4 +44,14 @@ class DisplayHelperTest &lt; ActiveSupport::TestCase
44 assert_equal 'go to <a href="http://www.noosfero.org" onclick="return confirm(\'Are you sure you want to visit this web site?\')" rel="nofolow" target="_blank">www.&#x200B;noos&#x200B;fero&#x200B;.org</a> yeah!', html 44 assert_equal 'go to <a href="http://www.noosfero.org" onclick="return confirm(\'Are you sure you want to visit this web site?\')" rel="nofolow" target="_blank">www.&#x200B;noos&#x200B;fero&#x200B;.org</a> yeah!', html
45 end 45 end
46 46
  47 + should 'return path to file under theme dir if theme has that file' do
  48 + stubs(:theme_path).returns('/designs/themes/noosfero')
  49 + assert_equal '/designs/themes/noosfero/images/rails.png', themed_path('/images/rails.png')
  50 + end
  51 +
  52 + should 'return path to file under public dir if theme hasnt that file' do
  53 + stubs(:theme_path).returns('/designs/themes/noosfero')
  54 + assert_equal '/images/invalid-file.png', themed_path('/images/invalid-file.png')
  55 + end
  56 +
47 end 57 end
test/unit/person_test.rb
@@ -64,7 +64,7 @@ class PersonTest &lt; ActiveSupport::TestCase @@ -64,7 +64,7 @@ class PersonTest &lt; ActiveSupport::TestCase
64 64
65 should "have person info fields" do 65 should "have person info fields" do
66 p = Person.new(:environment => Environment.default) 66 p = Person.new(:environment => Environment.default)
67 - [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code, :image ].each do |i| 67 + [ :name, :photo, :contact_information, :birth_date, :sex, :address, :city, :state, :country, :zip_code, :image, :district, :address_reference ].each do |i|
68 assert_respond_to p, i 68 assert_respond_to p, i
69 end 69 end
70 end 70 end
test/unit/plugin_settings_test.rb
@@ -10,29 +10,41 @@ class PluginSettingsTest &lt; ActiveSupport::TestCase @@ -10,29 +10,41 @@ class PluginSettingsTest &lt; ActiveSupport::TestCase
10 10
11 def setup 11 def setup
12 @environment = Environment.new 12 @environment = Environment.new
  13 + @profile = Profile.new
13 @plugin = SolarSystemPlugin 14 @plugin = SolarSystemPlugin
14 - @settings = Noosfero::Plugin::Settings.new(@environment, @plugin)  
15 end 15 end
16 16
17 - attr_accessor :environment, :plugin, :settings 17 + attr_accessor :environment, :profile, :plugin, :settings
18 18
19 - should 'store setttings in environment' do 19 + should 'store setttings on any model that offers settings' do
  20 + base = environment
  21 + settings = Noosfero::Plugin::Settings.new(base, plugin)
20 settings.star = 'sun' 22 settings.star = 'sun'
21 settings.planets = 8 23 settings.planets = 8
22 - assert_equal 'sun', environment.settings[:solar_system_plugin][:star]  
23 - assert_equal 8, environment.settings[:solar_system_plugin][:planets] 24 + assert_equal 'sun', base.settings[:solar_system_plugin][:star]
  25 + assert_equal 8, base.settings[:solar_system_plugin][:planets]
  26 + assert_equal 'sun', settings.star
  27 + assert_equal 8, settings.planets
  28 +
  29 + base = profile
  30 + settings = Noosfero::Plugin::Settings.new(base, plugin)
  31 + settings.star = 'sun'
  32 + settings.planets = 8
  33 + assert_equal 'sun', base.settings[:solar_system_plugin][:star]
  34 + assert_equal 8, base.settings[:solar_system_plugin][:planets]
24 assert_equal 'sun', settings.star 35 assert_equal 'sun', settings.star
25 assert_equal 8, settings.planets 36 assert_equal 8, settings.planets
26 end 37 end
27 38
28 - should 'save environment on save' do 39 + should 'save base on save' do
29 environment.expects(:save!) 40 environment.expects(:save!)
  41 + settings = Noosfero::Plugin::Settings.new(environment, plugin)
30 settings.save! 42 settings.save!
31 end 43 end
32 44
33 should 'use default value defined on the plugin class' do 45 should 'use default value defined on the plugin class' do
  46 + settings = Noosfero::Plugin::Settings.new(profile, plugin)
34 assert_equal 42, settings.secret 47 assert_equal 42, settings.secret
35 end 48 end
36 49
37 end 50 end
38 -  
test/unit/product_test.rb
@@ -772,4 +772,40 @@ class ProductTest &lt; ActiveSupport::TestCase @@ -772,4 +772,40 @@ class ProductTest &lt; ActiveSupport::TestCase
772 assert_equal [prod3, prod2, prod1], Product.more_recent 772 assert_equal [prod3, prod2, prod1], Product.more_recent
773 end 773 end
774 774
  775 + should 'return products from a category' do
  776 + pc1 = ProductCategory.create!(:name => 'PC1', :environment => Environment.default)
  777 + pc2 = ProductCategory.create!(:name => 'PC2', :environment => Environment.default)
  778 + pc3 = ProductCategory.create!(:name => 'PC3', :environment => Environment.default, :parent => pc1)
  779 + p1 = fast_create(Product, :product_category_id => pc1)
  780 + p2 = fast_create(Product, :product_category_id => pc1)
  781 + p3 = fast_create(Product, :product_category_id => pc2)
  782 + p4 = fast_create(Product, :product_category_id => pc3)
  783 +
  784 + products = Product.from_category(pc1)
  785 +
  786 + assert_includes products, p1
  787 + assert_includes products, p2
  788 + assert_not_includes products, p3
  789 + assert_includes products, p4
  790 + end
  791 +
  792 + should 'not crash if nil is passed to from_category' do
  793 + assert_nothing_raised do
  794 + Product.from_category(nil)
  795 + end
  796 + end
  797 +
  798 + should 'return from_category scope untouched if passed nil' do
  799 + enterprise = fast_create(Enterprise)
  800 + p1 = fast_create(Product, :enterprise_id => enterprise.id)
  801 + p2 = fast_create(Product, :enterprise_id => enterprise.id)
  802 + p3 = fast_create(Product, :enterprise_id => enterprise.id)
  803 +
  804 + products = enterprise.products.from_category(nil)
  805 +
  806 + assert_includes products, p1
  807 + assert_includes products, p2
  808 + assert_includes products, p3
  809 + end
  810 +
775 end 811 end