diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb
index 5f4d64a99f..a4f4eea834 100644
--- a/app/controllers/admin/enterprises_controller.rb
+++ b/app/controllers/admin/enterprises_controller.rb
@@ -2,15 +2,17 @@ module Admin
class EnterprisesController < ResourceController
before_filter :load_enterprise_set, :only => :index
before_filter :load_countries, :except => :index
- before_filter :load_methods_and_fees, :only => [:new, :edit]
+ before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create]
create.after :grant_management
helper 'spree/products'
+
def bulk_update
@enterprise_set = EnterpriseSet.new(params[:enterprise_set])
if @enterprise_set.save
- redirect_to main_app.admin_enterprises_path, :notice => 'Distributor collection times updated.'
+ flash[:success] = 'Enterprises updated successfully'
+ redirect_to main_app.admin_enterprises_path
else
render :index
end
@@ -48,5 +50,14 @@ module Admin
@shipping_methods = Spree::ShippingMethod.managed_by(spree_current_user).sort_by!{ |sm| [(@enterprise.shipping_methods.include? sm) ? 0 : 1, sm.name] }
@enterprise_fees = EnterpriseFee.managed_by(spree_current_user).for_enterprise(@enterprise).order(:fee_type, :name).all
end
+
+ # Overriding method on Spree's resource controller
+ def location_after_save
+ if params[:enterprise].key? :producer_properties_attributes
+ main_app.admin_enterprises_path
+ else
+ main_app.edit_admin_enterprise_path(@enterprise)
+ end
+ end
end
end
diff --git a/app/controllers/admin/producer_properties_controller.rb b/app/controllers/admin/producer_properties_controller.rb
new file mode 100644
index 0000000000..b297e74ff2
--- /dev/null
+++ b/app/controllers/admin/producer_properties_controller.rb
@@ -0,0 +1,26 @@
+module Admin
+ class ProducerPropertiesController < ResourceController
+ before_filter :load_enterprise
+ before_filter :load_properties
+ before_filter :setup_property, only: [:index]
+
+
+ private
+
+ def collection_url
+ main_app.admin_enterprise_producer_properties_url(@enterprise)
+ end
+
+ def load_enterprise
+ @enterprise = Enterprise.find params[:enterprise_id]
+ end
+
+ def load_properties
+ @properties = Spree::Property.pluck(:name)
+ end
+
+ def setup_property
+ @enterprise.producer_properties.build
+ end
+ end
+end
diff --git a/app/controllers/spree/admin/shipping_methods_controller_decorator.rb b/app/controllers/spree/admin/shipping_methods_controller_decorator.rb
index a8f3803085..192d044298 100644
--- a/app/controllers/spree/admin/shipping_methods_controller_decorator.rb
+++ b/app/controllers/spree/admin/shipping_methods_controller_decorator.rb
@@ -2,6 +2,7 @@ module Spree
module Admin
ShippingMethodsController.class_eval do
before_filter :do_not_destroy_referenced_shipping_methods, :only => :destroy
+ before_filter :load_hubs, only: [:new, :edit, :create, :update]
# Sort shipping methods by distributor name
# ! Code copied from Spree::Admin::ResourceController with two added lines
@@ -41,6 +42,11 @@ module Spree
redirect_to collection_url and return
end
end
+
+ private
+ def load_hubs
+ @hubs = Enterprise.managed_by(spree_current_user).is_distributor.sort_by!{ |d| [(@shipping_method.has_distributor? d) ? 0 : 1, d.name] }
+ end
end
end
end
diff --git a/app/helpers/spree/admin/base_helper_decorator.rb b/app/helpers/spree/admin/base_helper_decorator.rb
new file mode 100644
index 0000000000..e278626c5c
--- /dev/null
+++ b/app/helpers/spree/admin/base_helper_decorator.rb
@@ -0,0 +1,20 @@
+module Spree
+ module Admin
+ module BaseHelper
+ # Add url option to pass in link URL
+ def link_to_remove_fields(name, f, options = {})
+ name = '' if options[:no_text]
+ options[:class] = '' unless options[:class]
+ options[:class] += 'no-text with-tip' if options[:no_text]
+
+ url = if f.object.persisted?
+ options[:url] || [:admin, f.object]
+ else
+ '#'
+ end
+
+ link_to_with_icon('icon-trash', name, url, :class => "remove_fields #{options[:class]}", :data => {:action => 'remove'}, :title => t(:remove)) + f.hidden_field(:_destroy)
+ end
+ end
+ end
+end
diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb
index 3c851bde45..cc21f866db 100644
--- a/app/models/enterprise.rb
+++ b/app/models/enterprise.rb
@@ -4,6 +4,7 @@ class Enterprise < ActiveRecord::Base
acts_as_gmappable :process_geocoding => false
has_and_belongs_to_many :groups, class_name: 'EnterpriseGroup'
+ has_many :producer_properties, foreign_key: 'producer_id'
has_many :supplied_products, :class_name => 'Spree::Product', :foreign_key => 'supplier_id', :dependent => :destroy
has_many :distributed_orders, :class_name => 'Spree::Order', :foreign_key => 'distributor_id'
belongs_to :address, :class_name => 'Spree::Address'
@@ -19,6 +20,8 @@ class Enterprise < ActiveRecord::Base
delegate :latitude, :longitude, :city, :state_name, :to => :address
accepts_nested_attributes_for :address
+ accepts_nested_attributes_for :producer_properties, allow_destroy: true, reject_if: lambda { |pp| pp[:property_name].blank? }
+
has_attached_file :logo, :styles => { :medium => "300x300>", :thumb => "100x100>" }
has_attached_file :promo_image, :styles => { :large => "1200x260#", :thumb => "100x100>" }
@@ -102,13 +105,6 @@ class Enterprise < ActiveRecord::Base
end
}
-
- # Force a distinct count to work around relation count issue https://github.com/rails/rails/issues/5554
- def self.distinct_count
- count(distinct: true)
- end
-
-
def self.find_near(suburb)
enterprises = []
@@ -120,6 +116,20 @@ class Enterprise < ActiveRecord::Base
enterprises
end
+ # Force a distinct count to work around relation count issue https://github.com/rails/rails/issues/5554
+ def self.distinct_count
+ count(distinct: true)
+ end
+
+ def set_producer_property(property_name, property_value)
+ transaction do
+ property = Spree::Property.where(name: property_name).first_or_create!(presentation: property_name)
+ producer_property = ProducerProperty.where(producer_id: id, property_id: property.id).first_or_initialize
+ producer_property.value = property_value
+ producer_property.save!
+ end
+ end
+
def has_supplied_products_on_hand?
self.supplied_products.where('count_on_hand > 0').present?
end
diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb
new file mode 100644
index 0000000000..178e7646ff
--- /dev/null
+++ b/app/models/producer_property.rb
@@ -0,0 +1,17 @@
+class ProducerProperty < ActiveRecord::Base
+ belongs_to :property, class_name: 'Spree::Property'
+
+ default_scope order("#{self.table_name}.position")
+
+
+ def property_name
+ property.name if property
+ end
+
+ def property_name=(name)
+ unless name.blank?
+ self.property = Spree::Property.find_by_name(name) ||
+ Spree::Property.create(name: name, presentation: name)
+ end
+ end
+end
diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb
index 44e7d5e02e..e6d93f25aa 100644
--- a/app/models/spree/ability_decorator.rb
+++ b/app/models/spree/ability_decorator.rb
@@ -72,6 +72,8 @@ class AbilityDecorator
can [:admin, :index, :read, :create, :edit, :update], Exchange
can [:admin, :index, :read, :create, :edit, :update], ExchangeFee
+ can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], ProducerProperty
+
can [:admin, :index, :create], Enterprise
can [:read, :edit, :update, :bulk_update], Enterprise do |enterprise|
user.enterprises.include? enterprise
diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb
index 37aeb5e3f1..6e116d3e4d 100644
--- a/app/models/spree/product_decorator.rb
+++ b/app/models/spree/product_decorator.rb
@@ -95,6 +95,21 @@ Spree::Product.class_eval do
# -- Methods
+ def properties_h
+ # Product properties override producer properties
+ ps = supplier.producer_properties.inject(product_properties) do |properties, property|
+ if properties.find { |p| p.property.presentation == property.property.presentation }
+ properties
+ else
+ properties + [property]
+ end
+ end
+
+ ps.
+ sort_by { |pp| pp.position }.
+ map { |pp| {presentation: pp.property.presentation, value: pp.value} }
+ end
+
def in_distributor?(distributor)
self.class.in_distributor(distributor).include? self
end
diff --git a/app/models/spree/shipping_method_decorator.rb b/app/models/spree/shipping_method_decorator.rb
index a9628b3c73..303ab7b96f 100644
--- a/app/models/spree/shipping_method_decorator.rb
+++ b/app/models/spree/shipping_method_decorator.rb
@@ -1,6 +1,6 @@
Spree::ShippingMethod.class_eval do
has_and_belongs_to_many :distributors, join_table: 'distributors_shipping_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id'
- attr_accessible :distributor_ids
+ attr_accessible :distributor_ids, :description
attr_accessible :require_ship_address
scope :managed_by, lambda { |user|
@@ -34,6 +34,10 @@ Spree::ShippingMethod.class_eval do
end
end
+ def has_distributor?(distributor)
+ self.distributors.include?(distributor)
+ end
+
def adjustment_label
'Shipping'
end
diff --git a/app/overrides/spree/admin/shipping_methods/_form/add_distributor.html.haml.deface b/app/overrides/spree/admin/shipping_methods/_form/add_distributor.html.haml.deface
deleted file mode 100644
index 0604fd996a..0000000000
--- a/app/overrides/spree/admin/shipping_methods/_form/add_distributor.html.haml.deface
+++ /dev/null
@@ -1,6 +0,0 @@
-/ insert_bottom "[data-hook='admin_shipping_method_form_availability_fields'] > fieldset"
-
-= f.field_container :distributors do
- = f.label :distributor_ids, 'Distributors'
- - distributors = Enterprise.is_distributor.managed_by(spree_current_user) | f.object.distributors
- = f.collection_select(:distributor_ids, distributors, :id, :name, {include_blank: false}, {class: "select2 fullwidth", multiple: true})
diff --git a/app/overrides/spree/admin/shipping_methods/_form/add_require_ship_address.html.haml.deface b/app/overrides/spree/admin/shipping_methods/_form/add_require_ship_address.html.haml.deface
deleted file mode 100644
index b7bffd4c84..0000000000
--- a/app/overrides/spree/admin/shipping_methods/_form/add_require_ship_address.html.haml.deface
+++ /dev/null
@@ -1,5 +0,0 @@
-/ insert_bottom "[data-hook='admin_shipping_method_form_availability_fields'] > fieldset"
-
-= f.field_container :shipping_requirements do
- = f.label :require_ship_address, "Requires shipping address?"
- = f.check_box :require_ship_address
diff --git a/app/overrides/spree/admin/shipping_methods/_form/remove_form_availability_fields.deface b/app/overrides/spree/admin/shipping_methods/_form/remove_form_availability_fields.deface
new file mode 100644
index 0000000000..7ab45439c4
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/_form/remove_form_availability_fields.deface
@@ -0,0 +1 @@
+remove "div[data-hook='admin_shipping_method_form_availability_fields']"
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/_form/remove_form_calculator_fields.deface b/app/overrides/spree/admin/shipping_methods/_form/remove_form_calculator_fields.deface
new file mode 100644
index 0000000000..5063888fed
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/_form/remove_form_calculator_fields.deface
@@ -0,0 +1 @@
+remove "div[data-hook='admin_shipping_method_form_calculator_fields']"
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/_form/replace_form_fields.html.haml.deface b/app/overrides/spree/admin/shipping_methods/_form/replace_form_fields.html.haml.deface
new file mode 100644
index 0000000000..4dcc351981
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/_form/replace_form_fields.html.haml.deface
@@ -0,0 +1,57 @@
+/ replace "div[data-hook='admin_shipping_method_form_fields']"
+
+.alpha.twelve.columns{"data-hook" => "admin_shipping_method_form_fields"}
+ .row
+ .alpha.three.columns
+ = f.label :name, t(:name)
+ .omega.eight.columns
+ = f.text_field :name, :class => 'fullwidth', placeholder: "eg. 'Pick-up from Primary School'"
+ = error_message_on :shipping_method, :name
+ .row
+ .alpha.three.columns
+ = f.label :description, t(:description)
+ .omega.eight.columns
+ = f.text_area :description, class: 'fullwidth', rows: 2, placeholder: "eg. 'Please collect your order from 123 Imaginary St, Northcote, 3070'"
+ = error_message_on :shipping_method, :description
+ - if @available_zones.length == 1
+ = f.hidden_field :zone_id, value: @available_zones.first.id
+ - else
+ .row
+ .alpha.three.columns
+ = f.label :zone_id, t(:zone)
+ .omega.eight.columns
+ = f.collection_select(:zone_id, @available_zones, :id, :name, {}, {:class => 'select2 fullwidth'})
+ = error_message_on :shipping_method, :zone_id
+ - if spree_current_user.admin?
+ .row
+ .alpha.three.columns
+ = f.label :display_on, t(:display)
+ .omega.eight.columns
+ = select(:shipping_method, :display_on, Spree::ShippingMethod::DISPLAY.collect { |display| [t(display), display == :both ? nil : display.to_s] }, {}, {:class => 'select2 fullwidth'})
+ = error_message_on :shipping_method, :display_on
+ .row
+ -# Shipping Category used to be a select field, but we cut it down to two options to simplify the interface and because we thought 'Collection' and
+ -# 'Delivery' pretty much covered it. If we need more categories in the future, suggest reimplementing the select box from spree's code.
+ .three.columns.alpha
+ %label Category
+ = f.hidden_field :shipping_category_id, value: nil
+ - Spree::ShippingCategory.where(name: ['Delivery', 'Collection']).limit(2).each do |shipping_category|
+ .two.columns
+ = f.radio_button :shipping_category_id, shipping_category.id
+
+ = f.label "shipping_category_id_#{shipping_category.id}", t(shipping_category.name)
+ .row
+ .alpha.three.columns
+ = f.label :require_ship_address, "Requires shipping address?"
+ .two.columns
+ = f.radio_button :require_ship_address, true
+
+ = f.label :yes, t(:yes)
+ .six.columns
+ = f.radio_button :require_ship_address, false
+
+ = f.label :no, t(:no)
+
+ .row
+ .alpha.eleven.columns
+ = render :partial => 'spree/admin/shared/calculator_fields', :locals => { :f => f }
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/edit/add_hubs_sidebar.html.haml.deface b/app/overrides/spree/admin/shipping_methods/edit/add_hubs_sidebar.html.haml.deface
new file mode 100644
index 0000000000..74fc957e71
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/edit/add_hubs_sidebar.html.haml.deface
@@ -0,0 +1,3 @@
+/ insert_after "code[erb-loud]:contains(\"render :partial => 'form', :locals => { :f => f }\")"
+
+= render :partial => 'spree/admin/shared/hubs_sidebar', :locals => { :f => f }
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/edit/remove_configuration_sidebar.deface b/app/overrides/spree/admin/shipping_methods/edit/remove_configuration_sidebar.deface
new file mode 100644
index 0000000000..cc3fbcdee1
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/edit/remove_configuration_sidebar.deface
@@ -0,0 +1 @@
+remove "code[erb-loud]:contains(\"render :partial => 'spree/admin/shared/configuration_menu'\")"
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/new/add_hubs_sidebar.html.haml.deface b/app/overrides/spree/admin/shipping_methods/new/add_hubs_sidebar.html.haml.deface
new file mode 100644
index 0000000000..74fc957e71
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/new/add_hubs_sidebar.html.haml.deface
@@ -0,0 +1,3 @@
+/ insert_after "code[erb-loud]:contains(\"render :partial => 'form', :locals => { :f => f }\")"
+
+= render :partial => 'spree/admin/shared/hubs_sidebar', :locals => { :f => f }
\ No newline at end of file
diff --git a/app/overrides/spree/admin/shipping_methods/new/remove_configuration_sidebar.deface b/app/overrides/spree/admin/shipping_methods/new/remove_configuration_sidebar.deface
new file mode 100644
index 0000000000..cc3fbcdee1
--- /dev/null
+++ b/app/overrides/spree/admin/shipping_methods/new/remove_configuration_sidebar.deface
@@ -0,0 +1 @@
+remove "code[erb-loud]:contains(\"render :partial => 'spree/admin/shared/configuration_menu'\")"
\ No newline at end of file
diff --git a/app/views/admin/enterprises/_form.html.haml b/app/views/admin/enterprises/_form.html.haml
index 9bc0fd0355..d8fab90c6b 100644
--- a/app/views/admin/enterprises/_form.html.haml
+++ b/app/views/admin/enterprises/_form.html.haml
@@ -49,6 +49,15 @@
= f.radio_button :visible, false
= f.label :visible, "Not Visible", :value => "false"
+ - if @enterprise.is_distributor
+ - # TODO: Angularise this
+ .row
+ .three.columns.alpha
+ %label Link to shop front
+ .with-tip{'data-powertip' => "A direct link to your shopfront on the Open Food Network."}
+ %a What's this?
+ .eight.columns.omega
+ = main_app.shop_enterprise_url(@enterprise)
= f.fields_for :address do |af|
@@ -173,8 +182,10 @@
.row
.alpha.three.columns
= f.label :promo_image, class: 'with-tip', 'data-powertip' => 'This image is displayed in "About Us"'
- .with-tip{'data-powertip' => 'This image is displayed on the right hand side of the "About Us" section of your public profile.'}
- %a What's this?
+ %br/
+ %span{ style: 'font-weight:bold' } PLEASE NOTE:
+ Any promo image uploaded here will be cropped to 1200 x 260.
+ This image is displayed on the right hand side of the "About Us" section of your public profile.
.omega.eight.columns
= image_tag @object.promo_image(:large) if @object.promo_image.present?
diff --git a/app/views/admin/enterprises/index.html.erb b/app/views/admin/enterprises/index.html.erb
deleted file mode 100644
index 1795b17950..0000000000
--- a/app/views/admin/enterprises/index.html.erb
+++ /dev/null
@@ -1,76 +0,0 @@
-<% content_for :page_title do %>
- Enterprises
-<% end %>
-
-<% content_for :page_actions do %>
-
- <%= button_link_to "New Enterprise", main_app.new_admin_enterprise_path, :icon => 'add', :id => 'admin_new_enterprise_link' %>
-
-<% end %>
-
-<%= render 'admin/shared/enterprises_sub_menu' %>
-
-
-<%= form_for @enterprise_set, :url => main_app.bulk_update_admin_enterprises_path do |f| %>
-
-
-
-
-
-
-
-
-
-
-
- | Name |
- Role |
- Visible? |
- Description |
- |
-
-
-
- <%= f.fields_for :collection do |enterprise_form| %>
- <% enterprise = enterprise_form.object %>
-
- | <%= link_to enterprise.name, main_app.admin_enterprise_path(enterprise) %> |
- <% if enterprise.is_primary_producer && enterprise.is_distributor %> Producer & Distributor
- <% elsif enterprise.is_distributor %> Distributor
- <% elsif enterprise.is_primary_producer %> Producer
- <% else %>
-
- <% end %>
- |
- <%= enterprise.visible ? 'Visible' : 'Invisible' %> |
- <%= enterprise.description %> |
-
-
- <%= link_to_with_icon('icon-edit', 'Edit Profile', main_app.edit_admin_enterprise_path(enterprise), class: 'edit') %>
- <%= link_to_delete_enterprise enterprise %>
-
- <% if enterprise.is_distributor %>
- <%= link_to_with_icon 'icon-chevron-right', 'Payment Methods', spree.admin_payment_methods_path(enterprise_id: enterprise.id) %> (<%= enterprise.payment_methods.count %>)
- <% if enterprise.payment_methods.count == 0 %>
-
- <% end %>
- <%= link_to_with_icon 'icon-plane', 'Shipping Methods', spree.admin_shipping_methods_path(enterprise_id: enterprise.id) %> (<%= enterprise.shipping_methods.count %>)
- <% if enterprise.shipping_methods.count == 0 %>
-
- <% end %>
- <% end %>
- <%= link_to_with_icon 'icon-money', 'Enterprise Fees', main_app.admin_enterprise_fees_path(enterprise_id: enterprise.id) %> (<%= enterprise.enterprise_fees.count %>)
- <% if enterprise.enterprise_fees.count == 0 %>
-
- <% end %>
- |
-
- <% end %>
- <% if @enterprises.empty? %>
- | <%= t(:none) %> |
- <% end %>
-
-
-
- <%= f.submit 'Update' %>
-<% end %>
diff --git a/app/views/admin/enterprises/index.html.haml b/app/views/admin/enterprises/index.html.haml
new file mode 100644
index 0000000000..b358011d89
--- /dev/null
+++ b/app/views/admin/enterprises/index.html.haml
@@ -0,0 +1,68 @@
+- content_for :page_title do
+ Enterprises
+
+- content_for :page_actions do
+ %li#new_product_link
+ = button_link_to "New Enterprise", main_app.new_admin_enterprise_path, :icon => 'add', :id => 'admin_new_enterprise_link'
+
+= render 'admin/shared/enterprises_sub_menu'
+
+= form_for @enterprise_set, :url => main_app.bulk_update_admin_enterprises_path do |f|
+ %table#listing_enterprises.index
+ %colgroup
+ %col{style: "width: 20%;"}/
+ %col{style: "width: 10%;"}/
+ %col{style: "width: 5%;"}/
+ %col/
+ %col{style: "width: 20%;"}/
+ %thead
+ %tr{"data-hook" => "enterprises_header"}
+ %th Name
+ %th Role
+ %th Visible?
+ %th Description
+ %th
+ %tbody
+ = f.fields_for :collection do |enterprise_form|
+ - enterprise = enterprise_form.object
+ %tr{class: "enterprise-#{enterprise.id}"}
+ %td= link_to enterprise.name, main_app.admin_enterprise_path(enterprise)
+ %td
+ - if enterprise.is_primary_producer && enterprise.is_distributor
+ Producer & Distributor
+ - elsif enterprise.is_distributor
+ Distributor
+ - elsif enterprise.is_primary_producer
+ Producer
+ - else
+ %h1.icon-exclamation-sign.with-tip{"data-powertip" => "This enterprise does not have any roles", style: "text-align: center;color: #DA5354"}
+ %td= enterprise_form.check_box :visible
+ %td= enterprise.description
+ %td{"data-hook" => "admin_users_index_row_actions"}
+ = link_to_with_icon('icon-edit', 'Edit Profile', main_app.edit_admin_enterprise_path(enterprise), class: 'edit')
+ %br/
+ = link_to_delete_enterprise enterprise
+ %br/
+ - if enterprise.is_primary_producer
+ = link_to_with_icon 'icon-dashboard', 'Properties', main_app.admin_enterprise_producer_properties_path(enterprise_id: enterprise.id)
+ (#{enterprise.producer_properties.count})
+ %br/
+ - if enterprise.is_distributor
+ = link_to_with_icon 'icon-chevron-right', 'Payment Methods', spree.admin_payment_methods_path(enterprise_id: enterprise.id)
+ (#{enterprise.payment_methods.count})
+ - if enterprise.payment_methods.count == 0
+ %span.icon-exclamation-sign.with-tip{"data-powertip" => "This enterprise has no payment methods", style: "font-size: 16px;color: #DA5354"}
+ %br/
+ = link_to_with_icon 'icon-plane', 'Shipping Methods', spree.admin_shipping_methods_path(enterprise_id: enterprise.id)
+ (#{enterprise.shipping_methods.count})
+ - if enterprise.shipping_methods.count == 0
+ %span.icon-exclamation-sign.with-tip{"data-powertip" => "This enterprise has shipping methods", style: "font-size: 16px;color: #DA5354"}
+ %br/
+ = link_to_with_icon 'icon-money', 'Enterprise Fees', main_app.admin_enterprise_fees_path(enterprise_id: enterprise.id)
+ (#{enterprise.enterprise_fees.count})
+ - if enterprise.enterprise_fees.count == 0
+ %span.icon-warning-sign.with-tip{"data-powertip" => "This enterprise has no fees", style: "font-size: 16px;color: orange"}
+ - if @enterprises.empty?
+ %tr
+ %td{colspan: "4"}= t(:none)
+ = f.submit 'Update'
diff --git a/app/views/admin/producer_properties/_producer_property_fields.html.haml b/app/views/admin/producer_properties/_producer_property_fields.html.haml
new file mode 100644
index 0000000000..79dc815f9d
--- /dev/null
+++ b/app/views/admin/producer_properties/_producer_property_fields.html.haml
@@ -0,0 +1,12 @@
+-# admin/admin.js.erb in spree requires id to start with "spree_" for sortable tables
+%tr.product_property.fields{"data-hook" => "producer_property", id: "spree_#{dom_id(f.object)}"}
+ %td.no-border
+ %span.handle
+ = f.hidden_field :id
+ %td.property_name
+ = f.text_field :property_name, :class => 'autocomplete'
+ %td.value
+ = f.text_field :value, :class => 'autocomplete'
+ %td.actions
+ - unless @enterprise.producer_properties.empty?
+ = link_to_remove_fields t(:remove), f, no_text: true, url: (f.object.persisted? && main_app.admin_enterprise_producer_property_path(@enterprise, f.object))
diff --git a/app/views/admin/producer_properties/index.html.haml b/app/views/admin/producer_properties/index.html.haml
new file mode 100644
index 0000000000..2b4277b08d
--- /dev/null
+++ b/app/views/admin/producer_properties/index.html.haml
@@ -0,0 +1,40 @@
+- content_for :page_title do
+ = "#{@enterprise.name}:"
+ Producer Properties
+
+
+- content_for :page_actions do
+ %ul.tollbar.inline-menu
+ %li
+ = link_to_add_fields 'Add Producer Property', 'tbody#producer_properties', class: 'icon-plus button'
+
+
+= render 'spree/shared/error_messages', target: @enterprise
+
+
+= form_for @enterprise, url: main_app.admin_enterprise_path(@enterprise), method: :put do |f|
+ %fieldset.no-border-top
+ .add_producer_properties{"data-hook" => "add_producer_properties"}
+ = image_tag 'spinner.gif', :plugin => 'spree', :style => 'display:none;', :id => 'busy_indicator'
+ %table.index.sortable{"data-hook" => "", "data-sortable-link" => main_app.update_positions_admin_enterprise_producer_properties_url(@enterprise)}
+ %thead
+ %tr{"data-hook" => "producer_properties_header"}
+ %th{colspan: "2"} Property
+ %th Value
+ %th.actions
+ %tbody#producer_properties{"data-hook" => ""}
+ = f.fields_for :producer_properties do |pp_form|
+ = render 'producer_property_fields', f: pp_form
+ = render 'spree/admin/shared/edit_resource_links', collection_url: main_app.admin_enterprise_producer_properties_path(@enterprise)
+ = hidden_field_tag 'clear_producer_properties', 'true'
+
+:javascript
+ var properties = #{raw(@properties.to_json)};
+
+ $("#producer_properties input.autocomplete").live("keydown", function() {
+ already_auto_completed = $(this).is('ac_input');
+ if (!already_auto_completed) {
+ $(this).autocomplete({source: properties});
+ $(this).focus();
+ }
+ });
diff --git a/app/views/spree/admin/shared/_hubs_sidebar.html.haml b/app/views/spree/admin/shared/_hubs_sidebar.html.haml
new file mode 100644
index 0000000000..8998e6d593
--- /dev/null
+++ b/app/views/spree/admin/shared/_hubs_sidebar.html.haml
@@ -0,0 +1,21 @@
+- hubs_color = @hubs.count > 0 ? "blue" : "red"
+.sidebar_item.omega.four.columns#hubs
+ .four.columns.alpha.header{ class: "#{hubs_color}" }
+ %span.four.columns.alpha.centered Distributors
+ .four.columns.alpha.list{ class: "#{hubs_color}" }
+ - if @hubs.count > 0
+ -# = hidden_field_tag "enterprise[hub_ids][]", []
+ - @hubs.each do |hub|
+ %a.four.columns.alpha.list-item{ class: "#{cycle('odd','even')}", href: "#{main_app.edit_admin_enterprise_path(hub)}" }
+ %span.three.columns.alpha
+ = hub.name
+ %span.one.column.omega
+ = f.check_box :distributor_ids, { multiple: true }, hub.id, nil
+ - else
+ .four.columns.alpha.list-item
+ %span.three.columns.alpha None Available
+ %span.one.column.omega
+ %span.icon-remove-sign
+ %a.four.columns.alpha.button{ href: "#{main_app.admin_enterprises_path}", class: "#{hubs_color}" }
+ MANAGE
+ %span.icon-arrow-right
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 0622acb050..b151e4bae8 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -45,6 +45,10 @@ Openfoodnetwork::Application.routes.draw do
resources :enterprises do
post :bulk_update, :on => :collection, :as => :bulk_update
+
+ resources :producer_properties do
+ post :update_positions, on: :collection
+ end
end
resources :enterprise_relationships
diff --git a/db/migrate/20140613004344_create_producer_properties.rb b/db/migrate/20140613004344_create_producer_properties.rb
new file mode 100644
index 0000000000..b45b3bed5d
--- /dev/null
+++ b/db/migrate/20140613004344_create_producer_properties.rb
@@ -0,0 +1,18 @@
+class CreateProducerProperties < ActiveRecord::Migration
+ def change
+ create_table :producer_properties do |t|
+ t.string :value
+ t.references :producer
+ t.references :property
+ t.integer :position
+ t.timestamps
+ end
+
+ add_index :producer_properties, :producer_id
+ add_index :producer_properties, :property_id
+ add_index :producer_properties, :position
+
+ add_foreign_key :producer_properties, :enterprises, column: :producer_id
+ add_foreign_key :producer_properties, :spree_properties, column: :property_id
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index a40a1414e1..5932749993 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20140612020206) do
+ActiveRecord::Schema.define(:version => 20140613004344) do
create_table "adjustment_metadata", :force => true do |t|
t.integer "adjustment_id"
@@ -312,6 +312,19 @@ ActiveRecord::Schema.define(:version => 20140612020206) do
t.datetime "updated_at", :null => false
end
+ create_table "producer_properties", :force => true do |t|
+ t.string "value"
+ t.integer "producer_id"
+ t.integer "property_id"
+ t.integer "position"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ add_index "producer_properties", ["position"], :name => "index_producer_properties_on_position"
+ add_index "producer_properties", ["producer_id"], :name => "index_producer_properties_on_producer_id"
+ add_index "producer_properties", ["property_id"], :name => "index_producer_properties_on_property_id"
+
create_table "product_distributions", :force => true do |t|
t.integer "product_id"
t.integer "distributor_id"
@@ -1052,6 +1065,9 @@ ActiveRecord::Schema.define(:version => 20140612020206) do
add_foreign_key "order_cycles", "enterprises", name: "order_cycles_coordinator_id_fk", column: "coordinator_id"
+ add_foreign_key "producer_properties", "enterprises", name: "producer_properties_producer_id_fk", column: "producer_id"
+ add_foreign_key "producer_properties", "spree_properties", name: "producer_properties_property_id_fk", column: "property_id"
+
add_foreign_key "product_distributions", "enterprise_fees", name: "product_distributions_enterprise_fee_id_fk"
add_foreign_key "product_distributions", "enterprises", name: "product_distributions_distributor_id_fk", column: "distributor_id"
add_foreign_key "product_distributions", "spree_products", name: "product_distributions_product_id_fk", column: "product_id"
diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb
index 765a6251bf..50ce2aad7f 100644
--- a/spec/features/admin/enterprises_spec.rb
+++ b/spec/features/admin/enterprises_spec.rb
@@ -33,6 +33,23 @@ feature %q{
end
end
+ scenario "editing enterprises in bulk" do
+ s = create(:supplier_enterprise)
+ d = create(:distributor_enterprise)
+
+ login_to_admin_section
+ click_link 'Enterprises'
+
+ within("tr.enterprise-#{d.id}") do
+ page.should have_checked_field "enterprise_set_collection_attributes_0_visible"
+ uncheck "enterprise_set_collection_attributes_0_visible"
+ end
+ click_button "Update"
+ flash_message.should == 'Enterprises updated successfully'
+ distributor = Enterprise.find(d.id)
+ distributor.visible.should == false
+ end
+
scenario "viewing an enterprise" do
e = create(:enterprise)
@@ -136,16 +153,82 @@ feature %q{
click_button 'Update'
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
- page.should have_selector '#listing_enterprises a', text: 'Eaterprises'
-
- click_link 'Edit Profile'
+ page.should have_field 'enterprise_name', :with => 'Eaterprises'
page.should have_checked_field "enterprise_payment_method_ids_#{payment_method.id}"
page.should have_checked_field "enterprise_shipping_method_ids_#{shipping_method.id}"
page.should have_selector "a.list-item", text: enterprise_fee.name
end
- context 'as an Enterprise user' do
+ describe "producer properties" do
+ it "creates producer properties" do
+ # Given a producer enterprise
+ s = create(:supplier_enterprise)
+
+ # When I go to its properties page
+ login_to_admin_section
+ click_link 'Enterprises'
+ within(".enterprise-#{s.id}") { click_link 'Properties' }
+
+ # And I create a property
+ fill_in 'enterprise_producer_properties_attributes_0_property_name', with: "Certified Organic"
+ fill_in 'enterprise_producer_properties_attributes_0_value', with: "NASAA 12345"
+ click_button 'Update'
+
+ # Then I should be returned to the enterprises page
+ page.should have_selector '#listing_enterprises a', text: s.name
+
+ # And the producer should have the property
+ s.producer_properties(true).count.should == 1
+ s.producer_properties.first.property.presentation.should == "Certified Organic"
+ s.producer_properties.first.value.should == "NASAA 12345"
+ end
+
+ it "updates producer properties" do
+ # Given a producer enterprise with a property
+ s = create(:supplier_enterprise)
+ s.producer_properties.create! property_name: 'Certified Organic', value: 'NASAA 12345'
+
+ # When I go to its properties page
+ login_to_admin_section
+ visit main_app.admin_enterprise_producer_properties_path(s)
+
+ # And I update the property
+ fill_in 'enterprise_producer_properties_attributes_0_property_name', with: "Biodynamic"
+ fill_in 'enterprise_producer_properties_attributes_0_value', with: "Shininess"
+ click_button 'Update'
+
+ # Then I should be returned to the enterprises
+ page.should have_selector '#listing_enterprises a', text: s.name
+
+ # And the property should be updated
+ s.producer_properties(true).count.should == 1
+ s.producer_properties.first.property.presentation.should == "Biodynamic"
+ s.producer_properties.first.value.should == "Shininess"
+ end
+
+ it "removes producer properties", js: true do
+ # Given a producer enterprise with a property
+ s = create(:supplier_enterprise)
+ pp = s.producer_properties.create! property_name: 'Certified Organic', value: 'NASAA 12345'
+
+ # When I go to its properties page
+ login_to_admin_section
+ visit main_app.admin_enterprise_producer_properties_path(s)
+
+ # And I remove the property
+ page.should have_field 'enterprise_producer_properties_attributes_0_property_name', with: 'Certified Organic'
+ within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click }
+
+ # Then the property should have been removed
+ page.should_not have_selector '#progress'
+ page.should_not have_field 'enterprise_producer_properties_attributes_0_property_name', with: 'Certified Organic'
+ s.producer_properties(true).should be_empty
+ end
+ end
+
+
+ context "as an Enterprise user" do
let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') }
let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') }
let(:distributor1) { create(:distributor_enterprise, name: 'First Distributor') }
@@ -190,7 +273,7 @@ feature %q{
Enterprise.managed_by(@new_user).should include enterprise
end
- scenario "can edit enterprises I have permission to" do
+ scenario "editing enterprises I have permission to" do
click_link 'Enterprises'
within('#listing_enterprises tbody tr:first') { click_link 'Edit Profile' }
@@ -198,14 +281,34 @@ feature %q{
click_button 'Update'
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
- page.should have_selector '#listing_enterprises a', text: 'Eaterprises'
+ page.should have_field 'enterprise_name', :with => 'Eaterprises'
end
- scenario "Editing images for an enterprise" do
+ scenario "editing images for an enterprise" do
click_link 'Enterprises'
first(".edit").click
page.should have_content "Logo"
page.should have_content "Promo"
end
+
+ scenario "managing producer properties", js: true do
+ click_link 'Enterprises'
+ within(".enterprise-#{supplier1.id}") { click_link 'Properties' }
+
+ # -- Create / update
+ fill_in 'enterprise_producer_properties_attributes_0_property_name', with: "Certified Organic"
+ fill_in 'enterprise_producer_properties_attributes_0_value', with: "NASAA 12345"
+ click_button 'Update'
+ page.should have_selector '#listing_enterprises a', text: supplier1.name
+ supplier1.producer_properties(true).count.should == 1
+
+ # -- Destroy
+ pp = supplier1.producer_properties.first
+ within(".enterprise-#{supplier1.id}") { click_link 'Properties' }
+
+ within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click }
+ page.should_not have_selector '#progress'
+ supplier1.producer_properties(true).should be_empty
+ end
end
end
diff --git a/spec/features/admin/shipping_methods_spec.rb b/spec/features/admin/shipping_methods_spec.rb
index ab7940acc2..94efc2aacf 100644
--- a/spec/features/admin/shipping_methods_spec.rb
+++ b/spec/features/admin/shipping_methods_spec.rb
@@ -17,12 +17,22 @@ feature 'shipping methods' do
# Given some distributors
d1 = create(:distributor_enterprise, name: 'Aeronautical Adventures')
d2 = create(:distributor_enterprise, name: 'Nautical Travels')
+ sc1 = create(:shipping_category, name: 'Delivery')
+ sc2 = create(:shipping_category, name: 'Collection')
+
+ # Shows appropriate fields when logged in as admin
+ visit spree.new_admin_shipping_method_path
+ page.should have_field 'shipping_method_name'
+ page.should have_field 'shipping_method_description'
+ page.should have_select 'shipping_method_display_on'
+ page.should have_field "shipping_method_shipping_category_id_#{sc1.id}"
+ page.should have_field "shipping_method_shipping_category_id_#{sc2.id}"
+ page.should have_field 'shipping_method_require_ship_address_true', checked: true
# When I create a shipping method and set the distributors
- visit spree.new_admin_shipping_method_path
fill_in 'shipping_method_name', with: 'Carrier Pidgeon'
- select 'Aeronautical Adventures', from: 'shipping_method_distributor_ids'
- select 'Nautical Travels', from: 'shipping_method_distributor_ids'
+ check "shipping_method_distributor_ids_#{d1.id}"
+ check "shipping_method_distributor_ids_#{d2.id}"
click_button 'Create'
# Then the shipping method should have its distributor set
@@ -70,22 +80,24 @@ feature 'shipping methods' do
login_to_admin_as enterprise_user
end
- it "lets me choose whether a shipping address is required" do
- click_link "Enterprises"
- within(".enterprise-#{distributor1.id}") { click_link 'Shipping Methods' }
- click_link 'New Shipping Method'
-
- page.should have_content "Requires shipping address?"
- end
-
- it "creates shipping methods" do
+ it "creating a shipping method" do
+ sc1 = create(:shipping_category, name: 'Delivery')
+ sc2 = create(:shipping_category, name: 'Collection')
click_link 'Enterprises'
within(".enterprise-#{distributor1.id}") { click_link 'Shipping Methods' }
click_link 'New Shipping Method'
+ # Show the correct fields
+ page.should have_field 'shipping_method_name'
+ page.should have_field 'shipping_method_description'
+ page.should_not have_select 'shipping_method_display_on'
+ page.should have_field "shipping_method_shipping_category_id_#{sc1.id}"
+ page.should have_field "shipping_method_shipping_category_id_#{sc2.id}"
+ page.should have_field 'shipping_method_require_ship_address_true', checked: true
+
fill_in 'shipping_method_name', :with => 'Teleport'
- select distributor1.name, :from => 'shipping_method_distributor_ids'
+ check "shipping_method_distributor_ids_#{distributor1.id}"
click_button 'Create'
flash_message.should == 'Shipping method "Teleport" has been successfully created!'
diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb
index 542d95a4b0..bdf5574baf 100644
--- a/spec/models/enterprise_spec.rb
+++ b/spec/models/enterprise_spec.rb
@@ -449,14 +449,27 @@ describe Enterprise do
describe "presentation of attributes" do
let(:distributor) {
create(:distributor_enterprise,
- website: "http://www.google.com",
- facebook: "www.facebook.com/roger",
- linkedin: "http://linkedin.com")
+ website: "http://www.google.com",
+ facebook: "www.facebook.com/roger",
+ linkedin: "https://linkedin.com")
}
+
it "strips http and www from url fields" do
distributor.website.should == "google.com"
distributor.facebook.should == "facebook.com/roger"
distributor.linkedin.should == "linkedin.com"
end
end
+
+ describe "producer properties" do
+ let(:supplier) { create(:supplier_enterprise) }
+
+ it "sets producer properties" do
+ supplier.set_producer_property 'Organic Certified', 'NASAA 12345'
+
+ supplier.producer_properties.count.should == 1
+ supplier.producer_properties.first.value.should == 'NASAA 12345'
+ supplier.producer_properties.first.property.presentation.should == 'Organic Certified'
+ end
+ end
end
diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb
index 111c8e5196..9705fee70e 100644
--- a/spec/models/spree/ability_spec.rb
+++ b/spec/models/spree/ability_spec.rb
@@ -75,6 +75,10 @@ module Spree
should have_ability([:admin, :index, :read, :create, :edit], for: Spree::Classification)
end
+ it "should be able to read/write their enterprises' producer properties" do
+ should have_ability([:admin, :index, :read, :create, :edit, :update_positions, :destroy], for: ProducerProperty)
+ end
+
it "should be able to read and create enterprise relationships" do
should have_ability([:admin, :index, :create], for: EnterpriseRelationship)
end
diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb
index 594dfa5d29..bba8a95301 100644
--- a/spec/models/spree/product_spec.rb
+++ b/spec/models/spree/product_spec.rb
@@ -290,6 +290,52 @@ module Spree
end
end
+ describe "properties" do
+ it "returns product properties as a hash" do
+ product = create(:simple_product)
+ product.set_property 'Organic Certified', 'NASAA 12345'
+
+ product.properties_h.should == [{presentation: 'Organic Certified', value: 'NASAA 12345'}]
+ end
+
+ it "returns producer properties as a hash" do
+ supplier = create(:supplier_enterprise)
+ product = create(:simple_product, supplier: supplier)
+
+ supplier.set_producer_property 'Organic Certified', 'NASAA 54321'
+
+ product.properties_h.should == [{presentation: 'Organic Certified', value: 'NASAA 54321'}]
+ end
+
+ it "overrides producer properties with product properties" do
+ supplier = create(:supplier_enterprise)
+ product = create(:simple_product, supplier: supplier)
+
+ product.set_property 'Organic Certified', 'NASAA 12345'
+ supplier.set_producer_property 'Organic Certified', 'NASAA 54321'
+
+ product.properties_h.should == [{presentation: 'Organic Certified', value: 'NASAA 12345'}]
+ end
+
+ it "sorts by position" do
+ supplier = create(:supplier_enterprise)
+ product = create(:simple_product, supplier: supplier)
+
+ pa = Spree::Property.create! name: 'A', presentation: 'A'
+ pb = Spree::Property.create! name: 'B', presentation: 'B'
+ pc = Spree::Property.create! name: 'C', presentation: 'C'
+
+ product.product_properties.create!({property_id: pa.id, value: '1', position: 1}, {without_protection: true})
+ product.product_properties.create!({property_id: pc.id, value: '3', position: 3}, {without_protection: true})
+ supplier.producer_properties.create!({property_id: pb.id, value: '2', position: 2}, {without_protection: true})
+
+ product.properties_h.should ==
+ [{presentation: 'A', value: '1'},
+ {presentation: 'B', value: '2'},
+ {presentation: 'C', value: '3'}]
+ end
+ end
+
describe "membership" do
it "queries its membership of a particular product distribution" do
d1 = create(:distributor_enterprise)