mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge branch 'master' of https://github.com/eaterprises/openfoodweb
Conflicts: Gemfile.lock
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
.bundle
|
||||
.rbenv-version
|
||||
.ruby-version
|
||||
.ruby-gemset
|
||||
.swp
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
1
.ruby-gemset
Normal file
1
.ruby-gemset
Normal file
@@ -0,0 +1 @@
|
||||
openfoodweb
|
||||
1
.ruby-version
Normal file
1
.ruby-version
Normal file
@@ -0,0 +1 @@
|
||||
ruby-1.9.3-p392
|
||||
48
.rvmrc
48
.rvmrc
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This is an RVM Project .rvmrc file, used to automatically load the ruby
|
||||
# development environment upon cd'ing into the directory
|
||||
|
||||
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
|
||||
# Only full ruby name is supported here, for short names use:
|
||||
# echo "rvm use 1.9.3" > .rvmrc
|
||||
environment_id="ruby-1.9.3-p392@openfoodweb"
|
||||
|
||||
# Uncomment the following lines if you want to verify rvm version per project
|
||||
# rvmrc_rvm_version="1.18.21 (stable)" # 1.10.1 seams as a safe start
|
||||
# eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
|
||||
# echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
|
||||
# return 1
|
||||
# }
|
||||
|
||||
# First we attempt to load the desired environment directly from the environment
|
||||
# file. This is very fast and efficient compared to running through the entire
|
||||
# CLI and selector. If you want feedback on which environment was used then
|
||||
# insert the word 'use' after --create as this triggers verbose mode.
|
||||
if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
|
||||
&& -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
|
||||
then
|
||||
\. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
|
||||
[[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
|
||||
\. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
|
||||
else
|
||||
# If the environment file has not yet been created, use the RVM CLI to select.
|
||||
rvm --create "$environment_id" || {
|
||||
echo "Failed to create RVM environment '${environment_id}'."
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
# If you use bundler, this might be useful to you:
|
||||
# if [[ -s Gemfile ]] && {
|
||||
# ! builtin command -v bundle >/dev/null ||
|
||||
# builtin command -v bundle | GREP_OPTIONS= \grep $rvm_path/bin/bundle >/dev/null
|
||||
# }
|
||||
# then
|
||||
# printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
|
||||
# gem install bundler
|
||||
# fi
|
||||
# if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
|
||||
# then
|
||||
# bundle install | GREP_OPTIONS= \grep -vE '^Using|Your bundle is complete'
|
||||
# fi
|
||||
14
Gemfile.lock
14
Gemfile.lock
@@ -16,7 +16,7 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: git://github.com/eaterprises/spree-last-address.git
|
||||
revision: f93ea5a6b06e4605ea9c3fc5ef8e71f8e6aa0ffc
|
||||
revision: 39653f38429546f6367e376e823d2b5482d1cd8d
|
||||
branch: 1-3-stable
|
||||
specs:
|
||||
spree_last_address (1.1.0)
|
||||
@@ -24,7 +24,7 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: git://github.com/eaterprises/spree.git
|
||||
revision: 4fa1f51ba70519bfd3be0975e5b71f2ea73bbbd6
|
||||
revision: 1c133672652e1ee8b6c8d694efe258e62378062e
|
||||
branch: 1-3-stable
|
||||
specs:
|
||||
spree (1.3.3)
|
||||
@@ -256,6 +256,7 @@ GEM
|
||||
faye-websocket (0.4.7)
|
||||
eventmachine (>= 0.12.0)
|
||||
ffaker (1.15.0)
|
||||
ffi (1.9.0)
|
||||
fog (1.14.0)
|
||||
builder
|
||||
excon (~> 0.25.0)
|
||||
@@ -277,7 +278,7 @@ GEM
|
||||
httparty (0.11.0)
|
||||
multi_json (~> 1.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.6.4)
|
||||
i18n (0.6.5)
|
||||
journey (1.0.4)
|
||||
jquery-rails (2.2.2)
|
||||
railties (>= 3.0, < 5.0)
|
||||
@@ -400,6 +401,11 @@ GEM
|
||||
tilt (~> 1.3)
|
||||
select2-rails (3.2.1)
|
||||
thor (~> 0.14)
|
||||
selenium-webdriver (2.35.0)
|
||||
childprocess (>= 0.2.5)
|
||||
multi_json (~> 1.0)
|
||||
rubyzip
|
||||
websocket (~> 1.0.4)
|
||||
shoulda-matchers (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
simplecov (0.7.1)
|
||||
@@ -421,7 +427,7 @@ GEM
|
||||
thor (0.18.1)
|
||||
tilt (1.4.1)
|
||||
timecop (0.6.2.2)
|
||||
treetop (1.4.14)
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
truncate_html (0.5.5)
|
||||
|
||||
@@ -154,10 +154,10 @@ productsApp.controller('AdminBulkProductsCtrl', ["$scope", "$timeout", "$http",
|
||||
$scope.spree_api_key_ok = data.hasOwnProperty("success") && data["success"] == "Use of API Authorised";
|
||||
if ($scope.spree_api_key_ok){
|
||||
$http.defaults.headers.common['X-Spree-Token'] = spree_api_key;
|
||||
dataFetcher('/api/enterprises?template=bulk_index;q[is_primary_producer_eq]=true').then(function(data){
|
||||
dataFetcher('/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true').then(function(data){
|
||||
$scope.suppliers = data;
|
||||
// Need to have suppliers before we get products so we can match suppliers to product.supplier
|
||||
dataFetcher('/api/products?template=bulk_index').then(function(data){
|
||||
dataFetcher('/api/products/managed?template=bulk_index').then(function(data){
|
||||
$scope.resetProducts(data);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,7 +24,11 @@ module Admin
|
||||
end
|
||||
|
||||
def collection
|
||||
super.managed_by(spree_current_user).order('is_primary_producer DESC, is_distributor ASC, name')
|
||||
Enterprise.managed_by(spree_current_user).order('is_primary_producer DESC, is_distributor ASC, name')
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :bulk_update]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,6 +61,13 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def clone
|
||||
@order_cycle = OrderCycle.find params[:id]
|
||||
@order_cycle.clone!
|
||||
redirect_to main_app.admin_order_cycles_path, :notice => "Your order cycle #{@order_cycle.name} has been cloned."
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
def collection
|
||||
OrderCycle.managed_by(spree_current_user)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
Spree::Admin::Orders::CustomerDetailsController.class_eval do
|
||||
#Override BaseController.authorize_admin to inherit CanCan permissions for the current order
|
||||
def authorize_admin
|
||||
load_order unless @order
|
||||
authorize! :admin, @order
|
||||
authorize! params[:action].to_sym, @order
|
||||
# Inherit CanCan permissions for the current order
|
||||
def model_class
|
||||
load_order unless @order
|
||||
@order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ Spree::Admin::ProductsController.class_eval do
|
||||
product_set = Spree::ProductSet.new({:collection_attributes => collection_hash})
|
||||
|
||||
if product_set.save
|
||||
redirect_to "/api/products?template=bulk_index"
|
||||
redirect_to "/api/products/managed?template=bulk_index"
|
||||
else
|
||||
render :nothing => true
|
||||
end
|
||||
@@ -37,7 +37,7 @@ Spree::Admin::ProductsController.class_eval do
|
||||
|
||||
params[:q][:s] ||= "name asc"
|
||||
|
||||
@search = super.ransack(params[:q])
|
||||
@search = Spree::Product.ransack(params[:q]) # this line is modified - hit Spree::Product instead of super, avoiding cancan error for fetching records with block permissions via accessible_by
|
||||
@collection = @search.result.
|
||||
managed_by(spree_current_user). # this line is added to the original spree code!!!!!
|
||||
group_by_products_id.
|
||||
@@ -52,10 +52,15 @@ Spree::Admin::ProductsController.class_eval do
|
||||
@collection
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :bulk_edit, :bulk_update]
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def load_spree_api_key
|
||||
current_user.generate_spree_api_key! unless spree_current_user.spree_api_key
|
||||
@spree_api_key = spree_current_user.spree_api_key
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,6 +11,11 @@ Spree::Admin::ReportsController.class_eval do
|
||||
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:payments => {:name => "Payment Reports", :description => "Reports for Payments"}})
|
||||
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:order_cycles => {:name => "Order Cycle Reports", :description => "Reports for Order Cycles"}})
|
||||
|
||||
# Equivalent to CanCan's "authorize_resource :class => false" (see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146)
|
||||
def model_class
|
||||
self.class.to_s.sub("Controller", "").underscore.split('/').last.singularize.to_sym
|
||||
end
|
||||
|
||||
def orders_and_distributors
|
||||
params[:q] = {} unless params[:q]
|
||||
|
||||
|
||||
@@ -3,15 +3,10 @@ module Spree
|
||||
class EnterprisesController < Spree::Api::BaseController
|
||||
respond_to :json
|
||||
|
||||
def bulk_show
|
||||
@enterprise = Enterprise.find(params[:id])
|
||||
respond_with(@enterprise)
|
||||
end
|
||||
|
||||
def bulk_index
|
||||
@enterprises = Enterprise.ransack(params[:q]).result
|
||||
def managed
|
||||
@enterprises = Enterprise.ransack(params[:q]).result.managed_by(current_api_user)
|
||||
respond_with(@enterprises)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
Spree::Api::ProductsController.class_eval do
|
||||
def managed
|
||||
@products = product_scope.ransack(params[:q]).result.managed_by(current_api_user).page(params[:page]).per(params[:per_page])
|
||||
respond_with(@products, default_template: :index)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -21,7 +21,32 @@ class Exchange < ActiveRecord::Base
|
||||
scope :to_enterprises, lambda { |enterprises| where('exchanges.receiver_id IN (?)', enterprises) }
|
||||
scope :with_variant, lambda { |variant| joins(:exchange_variants).where('exchange_variants.variant_id = ?', variant) }
|
||||
|
||||
def clone!(new_order_cycle)
|
||||
exchange = self.dup
|
||||
exchange.order_cycle = new_order_cycle
|
||||
exchange.enterprise_fee_ids = self.enterprise_fee_ids
|
||||
exchange.variant_ids = self.variant_ids
|
||||
exchange.save!
|
||||
exchange
|
||||
end
|
||||
|
||||
def incoming?
|
||||
receiver == order_cycle.coordinator
|
||||
end
|
||||
|
||||
def to_h(core=false)
|
||||
h = attributes.merge({ 'variant_ids' => variant_ids, 'enterprise_fee_ids' => enterprise_fee_ids })
|
||||
h.reject! { |k| %w(id order_cycle_id created_at updated_at).include? k } if core
|
||||
h
|
||||
end
|
||||
|
||||
def eql?(e)
|
||||
if e.respond_to? :to_h
|
||||
self.to_h(true) == e.to_h(true)
|
||||
else
|
||||
super e
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -28,6 +28,17 @@ class OrderCycle < ActiveRecord::Base
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
def clone!
|
||||
oc = self.dup
|
||||
oc.name = "COPY OF #{oc.name}"
|
||||
oc.orders_open_at = oc.orders_close_at = nil
|
||||
oc.coordinator_fee_ids = self.coordinator_fee_ids
|
||||
oc.save!
|
||||
self.exchanges.each { |e| e.clone!(oc) }
|
||||
oc.reload
|
||||
end
|
||||
|
||||
def suppliers
|
||||
self.exchanges.where(:receiver_id => self.coordinator).map(&:sender).uniq
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class AbilityDecorator
|
||||
|
||||
#Enterprise User can only access products that they are a supplier for
|
||||
can [:create], Spree::Product
|
||||
can [:admin, :read, :update, :bulk_edit, :clone, :destroy], Spree::Product do |product|
|
||||
can [:admin, :read, :update, :bulk_edit, :bulk_update, :clone, :destroy], Spree::Product do |product|
|
||||
user.enterprises.include? product.supplier
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ class AbilityDecorator
|
||||
can [:admin, :index, :read, :search], Spree::Taxon
|
||||
can [:admin, :index, :read, :create, :edit], Spree::Classification
|
||||
|
||||
#User can only access orders that they are a distributor for
|
||||
#Enterprise User can only access orders that they are a distributor for
|
||||
can [:index, :create], Spree::Order
|
||||
can [:admin, :read, :update, :fire, :resend ], Spree::Order do |order|
|
||||
user.enterprises.include? order.distributor
|
||||
@@ -34,7 +34,7 @@ class AbilityDecorator
|
||||
user.enterprises.include? payment_method.distributor
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :edit, :update], OrderCycle do |order_cycle|
|
||||
can [:admin, :index, :read, :edit, :update, :clone], OrderCycle do |order_cycle|
|
||||
user.enterprises.include? order_cycle.coordinator
|
||||
end
|
||||
|
||||
@@ -47,11 +47,14 @@ class AbilityDecorator
|
||||
can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant
|
||||
can [:admin, :index, :read, :create, :edit, :update], Exchange
|
||||
can [:admin, :index, :read, :create, :edit, :update], ExchangeFee
|
||||
|
||||
can [:admin, :index], Enterprise
|
||||
can [:read, :edit, :update], Enterprise do |enterprise|
|
||||
can [:read, :edit, :update, :bulk_update], Enterprise do |enterprise|
|
||||
user.enterprises.include? enterprise
|
||||
end
|
||||
|
||||
#Enterprise User can access reports page
|
||||
can [:admin, :index, :orders_and_distributors, :group_buys, :bulk_coop, :payments, :order_cycles], :report
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,11 +4,11 @@ Spree::Address.class_eval do
|
||||
geocoded_by :full_address
|
||||
after_validation :geocode
|
||||
|
||||
delegate :name, :to => :state, :prefix => true
|
||||
delegate :name, :to => :state, :prefix => true, :allow_nil => true
|
||||
|
||||
def full_address
|
||||
full_address = [address1, address2, zipcode, city, country.name, state.name]
|
||||
full_address = [address1, address2, zipcode, city, country.name, state.andand.name]
|
||||
filtered_address = full_address.select{ |field| !field.nil? && field != '' }
|
||||
filtered_address.compact.join(', ')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/ insert_before "[data-hook='admin_order_form_buttons']"
|
||||
|
||||
%fieldset.no-border-bottom
|
||||
%legend{align => 'center'} Distribution
|
||||
|
||||
- if @order.complete?
|
||||
.alpha.six.columns
|
||||
%p
|
||||
%b Distributor:
|
||||
= f.object.distributor.andand.name || "None"
|
||||
.omega.six.columns
|
||||
%p
|
||||
%b Order cycle:
|
||||
= f.object.order_cycle.andand.name || "None"
|
||||
|
||||
- else
|
||||
.alpha.six.columns
|
||||
.field
|
||||
= f.label :distributor_id
|
||||
= f.collection_select :distributor_id, Enterprise.is_distributor.managed_by(spree_current_user), :id, :name, include_blank: true
|
||||
.omega.six.columns
|
||||
.field
|
||||
= f.label :order_cycle_id
|
||||
= f.collection_select :order_cycle_id, OrderCycle.managed_by(spree_current_user), :id, :name, include_blank: true
|
||||
@@ -42,7 +42,7 @@
|
||||
%legend Address
|
||||
%table
|
||||
= f.fields_for :address do |address_form|
|
||||
= render 'spree/admin/shared/address_form', :f => address_form
|
||||
= render 'spree/admin/shared/address_form_simple', :f => address_form
|
||||
%fieldset
|
||||
%legend Pickup details
|
||||
%table{"data-hook" => "distributors_pickup_details"}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
%th Suppliers
|
||||
%th Distributors
|
||||
%th Products
|
||||
%th
|
||||
%th.actions
|
||||
%tbody
|
||||
= f.fields_for :collection do |order_cycle_form|
|
||||
- order_cycle = order_cycle_form.object
|
||||
@@ -37,5 +37,6 @@
|
||||
%td.products
|
||||
- order_cycle.variants.each do |v|
|
||||
= image_tag(v.images.first.attachment.url(:mini)) if v.images.present?
|
||||
%td
|
||||
%td.actions
|
||||
= link_to '', main_app.clone_admin_order_cycle_path(order_cycle), class: 'clone-order-cycle icon-copy no-text'
|
||||
= f.submit 'Update'
|
||||
|
||||
@@ -9,7 +9,7 @@ Openfoodweb::Application.routes.draw do
|
||||
end
|
||||
|
||||
member do
|
||||
get :shop_front #new world
|
||||
get :shop_front # new world
|
||||
get :shop # old world
|
||||
end
|
||||
end
|
||||
@@ -19,6 +19,7 @@ Openfoodweb::Application.routes.draw do
|
||||
namespace :admin do
|
||||
resources :order_cycles do
|
||||
post :bulk_update, :on => :collection, :as => :bulk_update
|
||||
get :clone, on: :member
|
||||
end
|
||||
|
||||
resources :enterprises do
|
||||
@@ -52,9 +53,20 @@ Spree::Core::Engine.routes.prepend do
|
||||
match '/admin/reports/order_cycles' => 'admin/reports#order_cycles', :as => "order_cycles_admin_reports", :via => [:get, :post]
|
||||
match '/admin/products/bulk_edit' => 'admin/products#bulk_edit', :as => "bulk_edit_admin_products"
|
||||
|
||||
match '/api/users/authorise_api' => 'api/users#authorise_api', :via => :get, :defaults => { :format => 'json' }
|
||||
match '/api/enterprises' => 'api/enterprises#bulk_index', :via => :get, :defaults => { :format => 'json' }
|
||||
match '/api/enterprises/:id' => 'api/enterprises#bulk_show', :via => :get, :defaults => { :format => 'json' }
|
||||
|
||||
namespace :api, :defaults => { :format => 'json' } do
|
||||
resources :users do
|
||||
get :authorise_api, on: :collection
|
||||
end
|
||||
|
||||
resources :products do
|
||||
get :managed, on: :collection
|
||||
end
|
||||
|
||||
resources :enterprises do
|
||||
get :managed, on: :collection
|
||||
end
|
||||
end
|
||||
|
||||
namespace :admin do
|
||||
resources :products do
|
||||
|
||||
@@ -21,7 +21,7 @@ module OpenFoodWeb
|
||||
order_and_distributor_details << [order.created_at, order.id,
|
||||
order.bill_address.full_name, order.email, order.bill_address.phone, order.bill_address.city,
|
||||
line_item.product.sku, line_item.product.name, line_item.variant.options_text, line_item.quantity, line_item.max_quantity, line_item.price * line_item.quantity, line_item.distribution_fee,
|
||||
order.payments.first.payment_method.andand.name,
|
||||
order.payments.first.andand.payment_method.andand.name,
|
||||
order.distributor.andand.name, order.distributor.address.address1, order.distributor.address.city, order.distributor.address.zipcode, order.special_instructions ]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -31,7 +31,7 @@ feature %q{
|
||||
page.should have_field "product_name", with: p2.name
|
||||
end
|
||||
|
||||
it "displays a select box for suppliers, with the appropriate supplier selected" do
|
||||
it "displays a select box for suppliers, with the appropriate supplier selected" do
|
||||
s1 = FactoryGirl.create(:supplier_enterprise)
|
||||
s2 = FactoryGirl.create(:supplier_enterprise)
|
||||
s3 = FactoryGirl.create(:supplier_enterprise)
|
||||
@@ -421,4 +421,66 @@ feature %q{
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "as an enterprise manager" do
|
||||
let(:s1) { create(:supplier_enterprise, name: 'First Supplier') }
|
||||
let(:s2) { create(:supplier_enterprise, name: 'Another Supplier') }
|
||||
let(:s3) { create(:supplier_enterprise, name: 'Yet Another Supplier') }
|
||||
let(:d1) { create(:distributor_enterprise, name: 'First Distributor') }
|
||||
let(:d2) { create(:distributor_enterprise, name: 'Another Distributor') }
|
||||
let!(:product_supplied) { create(:product, supplier: s1, price: 10.0, on_hand: 6) }
|
||||
let!(:product_not_supplied) { create(:product, supplier: s3) }
|
||||
|
||||
before(:each) do
|
||||
@enterprise_user = create_enterprise_user
|
||||
@enterprise_user.enterprise_roles.build(enterprise: s1).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: s2).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: d1).save
|
||||
|
||||
login_to_admin_as @enterprise_user
|
||||
end
|
||||
|
||||
it "shows only products that I supply" do
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
page.should have_field 'product_name', with: product_supplied.name
|
||||
page.should_not have_field 'product_name', with: product_not_supplied.name
|
||||
end
|
||||
|
||||
it "shows only suppliers that I manage" do
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
page.should have_select 'supplier', with_options: [s1.name, s2.name], selected: s1.name
|
||||
page.should_not have_select 'supplier', with_options: [s3.name]
|
||||
end
|
||||
|
||||
it "allows me to update a product" do
|
||||
p = product_supplied
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
page.should have_field "product_name", with: p.name
|
||||
page.should have_select "supplier", selected: s1.name
|
||||
page.should have_field "available_on", with: p.available_on.strftime("%F %T")
|
||||
page.should have_field "price", with: "10.0"
|
||||
page.should have_field "on_hand", with: "6"
|
||||
|
||||
fill_in "product_name", with: "Big Bag Of Potatoes"
|
||||
select s2.name, from: 'supplier'
|
||||
fill_in "available_on", with: (Date.today-3).strftime("%F %T")
|
||||
fill_in "price", with: "20"
|
||||
fill_in "on_hand", with: "18"
|
||||
|
||||
click_button 'Update'
|
||||
page.find("span#update-status-message").should have_content "Update complete"
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
page.should have_field "product_name", with: "Big Bag Of Potatoes"
|
||||
page.should have_select "supplier", selected: s2.name
|
||||
page.should have_field "available_on", with: (Date.today-3).strftime("%F %T")
|
||||
page.should have_field "price", with: "20.0"
|
||||
page.should have_field "on_hand", with: "18"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -105,6 +105,7 @@ feature %q{
|
||||
click_button 'Update'
|
||||
|
||||
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
|
||||
page.should have_selector '#listing_enterprises a', text: 'Eaterprises'
|
||||
end
|
||||
|
||||
|
||||
@@ -128,7 +129,6 @@ feature %q{
|
||||
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') }
|
||||
@@ -153,5 +153,31 @@ feature %q{
|
||||
page.should_not have_content supplier2.name
|
||||
page.should_not have_content distributor2.name
|
||||
end
|
||||
|
||||
scenario "can edit enterprises I have permission to" do
|
||||
click_link 'Enterprises'
|
||||
within('#listing_enterprises tbody tr:first') { click_link 'Edit' }
|
||||
|
||||
fill_in 'enterprise_name', :with => 'Eaterprises'
|
||||
click_button 'Update'
|
||||
|
||||
flash_message.should == 'Enterprise "Eaterprises" has been successfully updated!'
|
||||
page.should have_selector '#listing_enterprises a', text: 'Eaterprises'
|
||||
end
|
||||
|
||||
scenario "can bulk edit enterprise collection dates/times for enterprises I have permission to" do
|
||||
click_link 'Enterprises'
|
||||
|
||||
fill_in 'enterprise_set_collection_attributes_0_next_collection_at', :with => 'One'
|
||||
fill_in 'enterprise_set_collection_attributes_1_next_collection_at', :with => 'Two'
|
||||
click_button 'Update'
|
||||
|
||||
flash_message.should == 'Distributor collection times updated.'
|
||||
|
||||
supplier1.reload.next_collection_at.should == 'One'
|
||||
distributor1.reload.next_collection_at.should == 'Two'
|
||||
supplier2.reload.next_collection_at.should be_nil
|
||||
distributor2.reload.next_collection_at.should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -343,6 +343,22 @@ feature %q{
|
||||
OrderCycle.all.map { |oc| oc.orders_close_at.sec }.should == [1, 3, 5]
|
||||
end
|
||||
|
||||
scenario "cloning an order cycle" do
|
||||
# Given an order cycle
|
||||
oc = create(:order_cycle)
|
||||
|
||||
# When I clone it
|
||||
login_to_admin_section
|
||||
click_link 'Order Cycles'
|
||||
first('a.clone-order-cycle').click
|
||||
flash_message.should == "Your order cycle #{oc.name} has been cloned."
|
||||
|
||||
# Then I should have clone of the order cycle
|
||||
occ = OrderCycle.last
|
||||
occ.name.should == "COPY OF #{oc.name}"
|
||||
end
|
||||
|
||||
|
||||
context 'as an Enterprise user' do
|
||||
|
||||
let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') }
|
||||
@@ -410,6 +426,18 @@ feature %q{
|
||||
order_cycle.coordinator.should == distributor1
|
||||
end
|
||||
|
||||
scenario "cloning an order cycle" do
|
||||
oc = create(:simple_order_cycle)
|
||||
|
||||
click_link "Order Cycles"
|
||||
first('a.clone-order-cycle').click
|
||||
flash_message.should == "Your order cycle #{oc.name} has been cloned."
|
||||
|
||||
# Then I should have clone of the order cycle
|
||||
occ = OrderCycle.last
|
||||
occ.name.should == "COPY OF #{oc.name}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -17,26 +17,62 @@ feature %q{
|
||||
create :check_payment, order: @order, amount: @order.total
|
||||
end
|
||||
|
||||
context "managing orders" do
|
||||
scenario "capture multiple payments from the orders index page" do
|
||||
# d.cook: could also test for an order that has had payment voided, then a new check payment created but not yet captured. But it's not critical and I know it works anyway.
|
||||
scenario "creating an order with distributor and order cycle", js: true do
|
||||
order_cycle = create(:order_cycle)
|
||||
distributor = order_cycle.distributors.first
|
||||
product = order_cycle.products.first
|
||||
|
||||
login_to_admin_section
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Orders'
|
||||
current_path.should == spree.admin_orders_path
|
||||
click_link 'Orders'
|
||||
click_link 'New Order'
|
||||
|
||||
# click the 'capture' link for the order
|
||||
page.find("[data-action=capture][href*=#{@order.number}]").click
|
||||
page.should have_content 'ADD PRODUCT'
|
||||
targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
|
||||
click_link 'Add'
|
||||
page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS
|
||||
page.should have_selector 'td', text: product.name
|
||||
|
||||
flash_message.should == "Payment Updated"
|
||||
select distributor.name, from: 'order_distributor_id'
|
||||
select order_cycle.name, from: 'order_order_cycle_id'
|
||||
click_button 'Update'
|
||||
|
||||
# check the order was captured
|
||||
@order.reload
|
||||
@order.payment_state.should == "paid"
|
||||
page.should have_selector 'h1', text: 'Customer Details'
|
||||
o = Spree::Order.last
|
||||
o.distributor.should == distributor
|
||||
o.order_cycle.should == order_cycle
|
||||
end
|
||||
|
||||
# we should still be on the same page
|
||||
current_path.should == spree.admin_orders_path
|
||||
end
|
||||
scenario "can't change distributor or order cycle once order has been finalized" do
|
||||
login_to_admin_section
|
||||
click_link 'Orders'
|
||||
page.find('td.actions a.icon-edit').click
|
||||
|
||||
page.should have_no_select 'order_distributor_id'
|
||||
page.should have_no_select 'order_order_cycle_id'
|
||||
|
||||
page.should have_selector 'p', text: "Distributor: #{@order.distributor.name}"
|
||||
page.should have_selector 'p', text: 'Order cycle: None'
|
||||
end
|
||||
|
||||
scenario "capture multiple payments from the orders index page" do
|
||||
# d.cook: could also test for an order that has had payment voided, then a new check payment created but not yet captured. But it's not critical and I know it works anyway.
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Orders'
|
||||
current_path.should == spree.admin_orders_path
|
||||
|
||||
# click the 'capture' link for the order
|
||||
page.find("[data-action=capture][href*=#{@order.number}]").click
|
||||
|
||||
flash_message.should == "Payment Updated"
|
||||
|
||||
# check the order was captured
|
||||
@order.reload
|
||||
@order.payment_state.should == "paid"
|
||||
|
||||
# we should still be on the same page
|
||||
current_path.should == spree.admin_orders_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -202,8 +202,8 @@ describe("AdminBulkProductsCtrl", function(){
|
||||
|
||||
it("gets a list of suppliers and then resets products with a list of data", function(){
|
||||
httpBackend.expectGET('/api/users/authorise_api?token=api_key').respond( { "success": "Use of API Authorised" } );
|
||||
httpBackend.expectGET('/api/enterprises?template=bulk_index;q[is_primary_producer_eq]=true').respond("list of suppliers");
|
||||
httpBackend.expectGET('/api/products?template=bulk_index').respond("list of products");
|
||||
httpBackend.expectGET('/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true').respond("list of suppliers");
|
||||
httpBackend.expectGET('/api/products/managed?template=bulk_index').respond("list of products");
|
||||
spyOn(scope, "resetProducts");
|
||||
scope.initialise('api_key');
|
||||
httpBackend.flush();
|
||||
|
||||
@@ -32,11 +32,11 @@ module Spree
|
||||
let (:order) {create(:order, )}
|
||||
|
||||
it "should be able to read/write their enterprises' products" do
|
||||
should have_ability([:admin, :read, :update, :bulk_edit, :clone, :destroy], for: p1)
|
||||
should have_ability([:admin, :read, :update, :bulk_edit, :bulk_update, :clone, :destroy], for: p1)
|
||||
end
|
||||
|
||||
it "should not be able to read/write other enterprises' products" do
|
||||
should_not have_ability([:admin, :read, :update, :bulk_edit, :clone, :destroy], for: p2)
|
||||
should_not have_ability([:admin, :read, :update, :bulk_edit, :bulk_update, :clone, :destroy], for: p2)
|
||||
end
|
||||
|
||||
it "should be able to create a new product" do
|
||||
@@ -126,11 +126,11 @@ module Spree
|
||||
let(:oc2) { create(:simple_order_cycle) }
|
||||
|
||||
it "should be able to read/write OrderCycles they are the co-ordinator of" do
|
||||
should have_ability([:admin, :index, :read, :edit], for: oc1)
|
||||
should have_ability([:admin, :index, :read, :edit, :update, :clone], for: oc1)
|
||||
end
|
||||
|
||||
it "should not be able to read/write OrderCycles they are not the co-ordinator of" do
|
||||
should_not have_ability([:admin, :index, :read, :create, :edit], for: oc2)
|
||||
should_not have_ability([:admin, :index, :read, :create, :edit, :update, :clone], for: oc2)
|
||||
end
|
||||
|
||||
it "should be able to create OrderCycles" do
|
||||
@@ -151,11 +151,11 @@ module Spree
|
||||
end
|
||||
|
||||
it 'should have the ability to read and edit enterprises that I manage' do
|
||||
should have_ability([:read, :edit, :update], for: s1)
|
||||
should have_ability([:read, :edit, :update, :bulk_update], for: s1)
|
||||
end
|
||||
|
||||
it 'should not have the ability to read and edit enterprises that I do not manage' do
|
||||
should_not have_ability([:read, :edit, :update], for: s2)
|
||||
should_not have_ability([:read, :edit, :update, :bulk_update], for: s2)
|
||||
end
|
||||
|
||||
it 'should have the ability administrate enterpises' do
|
||||
|
||||
@@ -97,4 +97,61 @@ describe Exchange do
|
||||
Exchange.with_variant(v).should == [ex]
|
||||
end
|
||||
end
|
||||
|
||||
it "clones itself" do
|
||||
oc = create(:order_cycle)
|
||||
new_oc = create(:simple_order_cycle)
|
||||
|
||||
ex1 = oc.exchanges.last
|
||||
ex2 = ex1.clone! new_oc
|
||||
|
||||
ex1.eql?(ex2).should be_true
|
||||
end
|
||||
|
||||
describe "converting to hash" do
|
||||
let(:oc) { create(:order_cycle) }
|
||||
let(:exchange) do
|
||||
exchange = oc.exchanges.last
|
||||
exchange.payment_enterprise = Enterprise.last
|
||||
exchange.save!
|
||||
exchange
|
||||
end
|
||||
|
||||
it "converts to a hash" do
|
||||
exchange.to_h.should ==
|
||||
{'id' => exchange.id, 'order_cycle_id' => oc.id,
|
||||
'sender_id' => exchange.sender_id, 'receiver_id' => exchange.receiver_id,
|
||||
'payment_enterprise_id' => exchange.payment_enterprise_id, 'variant_ids' => exchange.variant_ids,
|
||||
'enterprise_fee_ids' => exchange.enterprise_fee_ids,
|
||||
'pickup_time' => exchange.pickup_time, 'pickup_instructions' => exchange.pickup_instructions,
|
||||
'created_at' => exchange.created_at, 'updated_at' => exchange.updated_at}
|
||||
end
|
||||
|
||||
it "converts to a hash of core attributes only" do
|
||||
exchange.to_h(true).should ==
|
||||
{'sender_id' => exchange.sender_id, 'receiver_id' => exchange.receiver_id,
|
||||
'payment_enterprise_id' => exchange.payment_enterprise_id, 'variant_ids' => exchange.variant_ids,
|
||||
'enterprise_fee_ids' => exchange.enterprise_fee_ids,
|
||||
'pickup_time' => exchange.pickup_time, 'pickup_instructions' => exchange.pickup_instructions}
|
||||
end
|
||||
end
|
||||
|
||||
describe "comparing equality" do
|
||||
it "compares Exchanges using to_h" do
|
||||
e1 = Exchange.new
|
||||
e2 = Exchange.new
|
||||
|
||||
e1.stub(:to_h) { {'sender_id' => 456} }
|
||||
e2.stub(:to_h) { {'sender_id' => 456} }
|
||||
|
||||
e1.eql?(e2).should be_true
|
||||
end
|
||||
|
||||
it "compares other objects using super" do
|
||||
exchange = Exchange.new
|
||||
exchange_fee = ExchangeFee.new
|
||||
|
||||
exchange.eql?(exchange_fee).should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,6 +141,21 @@ describe OrderCycle do
|
||||
end
|
||||
end
|
||||
|
||||
it "clones itself" do
|
||||
oc = create(:order_cycle)
|
||||
occ = oc.clone!
|
||||
|
||||
occ = OrderCycle.last
|
||||
occ.name.should == "COPY OF #{oc.name}"
|
||||
occ.orders_open_at.should be_nil
|
||||
occ.orders_close_at.should be_nil
|
||||
occ.coordinator.should == oc.coordinator
|
||||
|
||||
occ.coordinator_fee_ids.should == oc.coordinator_fee_ids
|
||||
|
||||
(0..occ.exchanges.count).all? { |i| occ.exchanges[i].eql? oc.exchanges[i] }.should be_true
|
||||
end
|
||||
|
||||
describe "creating adjustments for a line item" do
|
||||
let(:oc) { OrderCycle.new }
|
||||
let(:line_item) { double(:line_item, variant: 123) }
|
||||
|
||||
@@ -22,6 +22,7 @@ WebMock.disable_net_connect!(:allow_localhost => true)
|
||||
# in spec/support/ and its subdirectories.
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
||||
require 'spree/core/testing_support/controller_requests'
|
||||
require 'spree/core/testing_support/capybara_ext'
|
||||
|
||||
require 'active_record/fixtures'
|
||||
fixtures_dir = File.expand_path('../../db/default', __FILE__)
|
||||
|
||||
Reference in New Issue
Block a user