mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge branch 'master' into laura_and_will
Conflicts: db/schema.rb
This commit is contained in:
@@ -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
|
||||
|
||||
26
app/controllers/admin/producer_properties_controller.rb
Normal file
26
app/controllers/admin/producer_properties_controller.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
20
app/helpers/spree/admin/base_helper_decorator.rb
Normal file
20
app/helpers/spree/admin/base_helper_decorator.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
17
app/models/producer_property.rb
Normal file
17
app/models/producer_property.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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})
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
remove "div[data-hook='admin_shipping_method_form_availability_fields']"
|
||||
@@ -0,0 +1 @@
|
||||
remove "div[data-hook='admin_shipping_method_form_calculator_fields']"
|
||||
@@ -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 }
|
||||
@@ -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 }
|
||||
@@ -0,0 +1 @@
|
||||
remove "code[erb-loud]:contains(\"render :partial => 'spree/admin/shared/configuration_menu'\")"
|
||||
@@ -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 }
|
||||
@@ -0,0 +1 @@
|
||||
remove "code[erb-loud]:contains(\"render :partial => 'spree/admin/shared/configuration_menu'\")"
|
||||
@@ -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?
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
<% content_for :page_title do %>
|
||||
Enterprises
|
||||
<% end %>
|
||||
|
||||
<% content_for :page_actions do %>
|
||||
<li id="new_product_link">
|
||||
<%= button_link_to "New Enterprise", main_app.new_admin_enterprise_path, :icon => 'add', :id => 'admin_new_enterprise_link' %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<%= render 'admin/shared/enterprises_sub_menu' %>
|
||||
|
||||
|
||||
<%= form_for @enterprise_set, :url => main_app.bulk_update_admin_enterprises_path do |f| %>
|
||||
<table class="index" id="listing_enterprises">
|
||||
<colgroup>
|
||||
<col style="width: 20%;">
|
||||
<col style="width: 10%;">
|
||||
<col style="width: 5%;">
|
||||
<col>
|
||||
<col style="width: 20%;">
|
||||
</colgroup>
|
||||
|
||||
<thead>
|
||||
<tr data-hook="enterprises_header">
|
||||
<th>Name</th>
|
||||
<th>Role</th>
|
||||
<th>Visible?</th>
|
||||
<th>Description</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<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>
|
||||
<td><% if enterprise.is_primary_producer && enterprise.is_distributor %> Producer & Distributor
|
||||
<% elsif enterprise.is_distributor %> Distributor
|
||||
<% elsif enterprise.is_primary_producer %> Producer
|
||||
<% else %>
|
||||
<h1 class = "icon-exclamation-sign with-tip" style = "text-align: center;color: #DA5354" data-powertip = "This enterprise does not have any roles"></h1>
|
||||
<% end %>
|
||||
</td>
|
||||
<td><%= enterprise.visible ? 'Visible' : 'Invisible' %></td>
|
||||
<td><%= enterprise.description %></td>
|
||||
<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_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 class = "icon-exclamation-sign with-tip" style = "font-size: 16px;color: #DA5354" data-powertip = "This enterprise has no payment methods"></span>
|
||||
<% end %><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 class = "icon-exclamation-sign with-tip" style = "font-size: 16px;color: #DA5354" data-powertip = "This enterprise has shipping methods"></span>
|
||||
<% end %><br />
|
||||
<% 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 %>
|
||||
<span class = "icon-warning-sign with-tip" style = "font-size: 16px;color: orange" data-powertip = "This enterprise has no fees"></span>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @enterprises.empty? %>
|
||||
<tr><td colspan="4"><%= t(:none) %></td></tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= f.submit 'Update' %>
|
||||
<% end %>
|
||||
68
app/views/admin/enterprises/index.html.haml
Normal file
68
app/views/admin/enterprises/index.html.haml
Normal file
@@ -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'
|
||||
@@ -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))
|
||||
40
app/views/admin/producer_properties/index.html.haml
Normal file
40
app/views/admin/producer_properties/index.html.haml
Normal file
@@ -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();
|
||||
}
|
||||
});
|
||||
21
app/views/spree/admin/shared/_hubs_sidebar.html.haml
Normal file
21
app/views/spree/admin/shared/_hubs_sidebar.html.haml
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
18
db/migrate/20140613004344_create_producer_properties.rb
Normal file
18
db/migrate/20140613004344_create_producer_properties.rb
Normal file
@@ -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
|
||||
18
db/schema.rb
18
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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user