Merge branch 'master' of github.com:eaterprises/openfoodweb

This commit is contained in:
alexs
2013-08-16 12:13:47 +10:00
21 changed files with 364 additions and 85 deletions

View File

@@ -21,6 +21,9 @@ angular.module('order_cycle', ['ngResource'])
$scope.incomingExchangesVariants = ->
OrderCycle.incomingExchangesVariants()
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.participatingEnterprises = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds()
@@ -82,6 +85,9 @@ angular.module('order_cycle', ['ngResource'])
$scope.incomingExchangesVariants = ->
OrderCycle.incomingExchangesVariants()
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.participatingEnterprises = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds()
@@ -141,6 +147,9 @@ angular.module('order_cycle', ['ngResource'])
numActiveVariants++ for id, active of exchange.variants when active
numActiveVariants
exchangeDirection: (exchange) ->
if this.order_cycle.incoming_exchanges.indexOf(exchange) == -1 then 'outgoing' else 'incoming'
toggleProducts: (exchange) ->
exchange.showProducts = !exchange.showProducts
@@ -234,6 +243,7 @@ angular.module('order_cycle', ['ngResource'])
data = angular.extend({}, this.order_cycle)
data = this.removeInactiveExchanges(data)
data = this.translateCoordinatorFees(data)
data = this.translateExchangeFees(data)
data
removeInactiveExchanges: (order_cycle) ->
@@ -247,6 +257,15 @@ angular.module('order_cycle', ['ngResource'])
order_cycle.coordinator_fee_ids = (fee.id for fee in order_cycle.coordinator_fees)
delete order_cycle.coordinator_fees
order_cycle
translateExchangeFees: (order_cycle) ->
for exchange in order_cycle.incoming_exchanges
exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees)
delete exchange.enterprise_fees
for exchange in order_cycle.outgoing_exchanges
exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees)
delete exchange.enterprise_fees
order_cycle
}])
.factory('Enterprise', ['$resource', ($resource) ->

View File

@@ -32,6 +32,12 @@ form.order_cycle {
float: left;
margin-right: 3em;
}
ol {
list-style-type: none;
li {
margin-bottom: 0.5em;
}
}
table.exchanges {
tr td.active {
width: 20px;
@@ -68,6 +74,7 @@ form.order_cycle {
.coordinator-fees {
margin-top: 1em;
}
.actions {
margin-top: 3em;
}

View File

@@ -61,6 +61,10 @@ module Admin
end
end
protected
def collection
OrderCycle.managed_by(spree_current_user)
end
private
def load_order_cycle_set

View File

@@ -4,7 +4,7 @@ module OrderCyclesHelper
end
def coordinating_enterprises
Enterprise.is_distributor.order('name')
Enterprise.is_distributor.managed_by(spree_current_user).order('name')
end
def order_cycle_local_remote_class(distributor, order_cycle)

View File

@@ -14,4 +14,7 @@ class Exchange < ActiveRecord::Base
validates_uniqueness_of :sender_id, :scope => [:order_cycle_id, :receiver_id]
accepts_nested_attributes_for :variants
scope :incoming, joins(:order_cycle).where('exchanges.receiver_id = order_cycles.coordinator_id')
scope :outgoing, joins(:order_cycle).where('exchanges.sender_id = order_cycles.coordinator_id')
end

View File

@@ -20,6 +20,14 @@ class OrderCycle < ActiveRecord::Base
where('spree_variants.id IN (?)', product.variants_including_master.map(&:id)).
select('DISTINCT order_cycles.*') }
scope :managed_by, lambda { |user|
if user.has_spree_role?('admin')
scoped
else
where('coordinator_id IN (?)', user.enterprises.map {|enterprise| enterprise.id })
end
}
def suppliers
self.exchanges.where(:receiver_id => self.coordinator).map(&:sender).uniq
end

View File

@@ -23,7 +23,7 @@ class AbilityDecorator
user.enterprises.include? order.distributor
end
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Shipment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Adjustment
can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::ReturnAuthorization
@@ -33,6 +33,13 @@ class AbilityDecorator
can [:admin, :read, :update, :fire, :resend ], Spree::PaymentMethod do |payment_method|
user.enterprises.include? payment_method.distributor
end
can [:admin, :index, :read, :edit, :update], OrderCycle do |order_cycle|
user.enterprises.include? order_cycle.coordinator
end
can [:create], OrderCycle
end
end
end

View File

@@ -1,5 +1,6 @@
%table.coordinator-fees
%tr{'ng-repeat' => 'enterprise_fee in order_cycle.coordinator_fees'}
%td= select_tag 'order_cycle_coordinator_fee_{{ $index }}_id', nil, {'ng-model' => 'enterprise_fee.id', 'ng-options' => 'enterprise_fee.id as enterprise_fee.name for enterprise_fee in enterpriseFeesForEnterprise(order_cycle.coordinator_id)'}
%td= link_to 'Remove', '#', {'id' => 'order_cycle_coordinator_fee_{{ $index }}_remove', 'ng-click' => 'removeCoordinatorFee($event, $index)'}
%ol.coordinator-fees
%li{'ng-repeat' => 'enterprise_fee in order_cycle.coordinator_fees'}
= select_tag 'order_cycle_coordinator_fee_{{ $index }}_id', nil, {'ng-model' => 'enterprise_fee.id', 'ng-options' => 'enterprise_fee.id as enterprise_fee.name for enterprise_fee in enterpriseFeesForEnterprise(order_cycle.coordinator_id)'}
= link_to 'Remove', '#', {'id' => 'order_cycle_coordinator_fee_{{ $index }}_remove', 'ng-click' => 'removeCoordinatorFee($event, $index)'}
= f.submit 'Add coordinator fee', 'ng-click' => 'addCoordinatorFee($event)'

View File

@@ -13,3 +13,13 @@
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'placeholder' => 'Pickup time / date', 'ng-model' => 'exchange.pickup_time'
%br/
= text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => 'Delivery instructions', 'ng-model' => 'exchange.pickup_instructions'
%td.fees
%ol
%li{'ng-repeat' => 'enterprise_fee in exchange.enterprise_fees'}
= select_tag 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_id', nil, {'id' => 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_id', 'ng-model' => 'enterprise_fee.enterprise_id', 'ng-options' => 'enterprise.id as enterprise.name for enterprise in participatingEnterprises()'}
= select_tag 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_fee_id', nil, {'id' => 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_enterprise_fee_id', 'ng-model' => 'enterprise_fee.id', 'ng-options' => 'enterprise_fee.id as enterprise_fee.name for enterprise_fee in enterpriseFeesForEnterprise(enterprise_fee.enterprise_id)'}
= link_to 'Remove', '#', {'id' => 'order_cycle_{{ exchangeDirection(exchange) }}_exchange_{{ $parent.$index }}_enterprise_fees_{{ $index }}_remove', 'ng-click' => 'removeExchangeFee($event, exchange, $index)'}
= f.submit 'Add fee', 'ng-click' => 'addExchangeFee($event, exchange)'

View File

@@ -18,13 +18,14 @@
%th
%th Supplier
%th Products
%th Fees
%tbody{'ng-repeat' => 'exchange in order_cycle.incoming_exchanges'}
%tr.supplier
%tr{'class' => "supplier supplier-{{ exchange.enterprise_id }}"}
= render 'exchange_form', :f => f, :type => 'supplier'
%tr.products{'ng-show' => 'exchange.showProducts'}
= render 'exchange_supplied_products_form'
= select_tag :new_supplier_id, options_from_collection_for_select(Enterprise.is_primary_producer, :id, :name), {'ng-model' => 'new_supplier_id'}
= select_tag :new_supplier_id, options_from_collection_for_select(Enterprise.is_primary_producer.managed_by(spree_current_user), :id, :name), {'ng-model' => 'new_supplier_id'}
= f.submit 'Add supplier', 'ng-click' => 'addSupplier($event)'
@@ -42,13 +43,14 @@
%th Distributor
%th Products
%th Collection details
%th Fees
%tbody{'ng-repeat' => 'exchange in order_cycle.outgoing_exchanges'}
%tr.distributor
%tr{'class' => "distributor distributor-{{ exchange.enterprise_id }}"}
= render 'exchange_form', :f => f, :type => 'distributor'
%tr.products{'ng-show' => 'exchange.showProducts'}
= render 'exchange_distributed_products_form'
= select_tag :new_distributor_id, options_from_collection_for_select(Enterprise.is_distributor, :id, :name), {'ng-model' => 'new_distributor_id'}
= select_tag :new_distributor_id, options_from_collection_for_select(Enterprise.is_distributor.managed_by(spree_current_user), :id, :name), {'ng-model' => 'new_distributor_id'}
= f.submit 'Add distributor', 'ng-click' => 'addDistributor($event)'
.actions

View File

@@ -18,6 +18,7 @@ r.element :order_cycle, @order_cycle do
r.list_of :enterprise_fees do |fee|
r.element :id
r.element :enterprise_id
end
r.element :pickup_time

View File

@@ -1,4 +1,9 @@
module OpenFoodWeb
# There are two translator classes on the boundary between Angular and Rails: On the Angular side,
# there is the OrderCycle#dataForSubmit method, and on the Rails side is this class. I think data
# translation is more a responsibility of Angular, so I'd be inclined to refactor this class to move
# as much as possible (if not all) of its logic into Angular.
class OrderCycleFormApplicator
def initialize(order_cycle)
@order_cycle = order_cycle
@@ -10,22 +15,30 @@ module OpenFoodWeb
@order_cycle.incoming_exchanges ||= []
@order_cycle.incoming_exchanges.each do |exchange|
variant_ids = exchange_variant_ids(exchange)
enterprise_fee_ids = exchange[:enterprise_fee_ids]
if exchange_exists?(exchange[:enterprise_id], @order_cycle.coordinator_id)
update_exchange(exchange[:enterprise_id], @order_cycle.coordinator_id, {variant_ids: variant_ids})
update_exchange(exchange[:enterprise_id], @order_cycle.coordinator_id,
{variant_ids: variant_ids, enterprise_fee_ids: enterprise_fee_ids})
else
add_exchange(exchange[:enterprise_id], @order_cycle.coordinator_id, {variant_ids: variant_ids})
add_exchange(exchange[:enterprise_id], @order_cycle.coordinator_id,
{variant_ids: variant_ids, enterprise_fee_ids: enterprise_fee_ids})
end
end
@order_cycle.outgoing_exchanges ||= []
@order_cycle.outgoing_exchanges.each do |exchange|
variant_ids = exchange_variant_ids(exchange)
enterprise_fee_ids = exchange[:enterprise_fee_ids]
if exchange_exists?(@order_cycle.coordinator_id, exchange[:enterprise_id])
update_exchange(@order_cycle.coordinator_id, exchange[:enterprise_id], {variant_ids: variant_ids, pickup_time: exchange[:pickup_time], pickup_instructions: exchange[:pickup_instructions]})
update_exchange(@order_cycle.coordinator_id, exchange[:enterprise_id],
{variant_ids: variant_ids, enterprise_fee_ids: enterprise_fee_ids,
pickup_time: exchange[:pickup_time], pickup_instructions: exchange[:pickup_instructions]})
else
add_exchange(@order_cycle.coordinator_id, exchange[:enterprise_id], {variant_ids: variant_ids, pickup_time: exchange[:pickup_time], pickup_instructions: exchange[:pickup_instructions]})
add_exchange(@order_cycle.coordinator_id, exchange[:enterprise_id],
{variant_ids: variant_ids, enterprise_fee_ids: enterprise_fee_ids,
pickup_time: exchange[:pickup_time], pickup_instructions: exchange[:pickup_instructions]})
end
end

View File

@@ -1,11 +0,0 @@
@echo off
REM Windows script for running e2e tests
REM You have to run server and capture some browser first
REM
REM Requirements:
REM - NodeJS (http://nodejs.org/)
REM - Testacular (npm install -g testacular)
set BASE_DIR=%~dp0
testacular start "%BASE_DIR%\..\config\testacular-e2e.conf.js" %*

View File

@@ -1,9 +0,0 @@
#!/bin/bash
BASE_DIR=`dirname $0`
echo ""
echo "Starting Testacular Server (http://vojtajina.github.com/testacular)"
echo "-------------------------------------------------------------------"
testacular start $BASE_DIR/../config/testacular-e2e.conf.js $*

View File

@@ -1,13 +0,0 @@
#!/bin/bash
###
# This scripts updates the local repo with the latest changes from github.
#
# The master branch will be REPLACED with what's in github and all local changes
# will be LOST.
###
git checkout master
git fetch -f origin
git fetch --tags origin
git reset --hard origin/master

View File

@@ -9,10 +9,18 @@ FactoryGirl.define do
# Suppliers
ex1 = create(:exchange, :order_cycle => oc, :receiver => oc.coordinator)
ex2 = create(:exchange, :order_cycle => oc, :receiver => oc.coordinator)
ExchangeFee.create!(exchange: ex1,
enterprise_fee: create(:enterprise_fee, enterprise: ex1.sender))
ExchangeFee.create!(exchange: ex2,
enterprise_fee: create(:enterprise_fee, enterprise: ex2.sender))
# Distributors
create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 0', :pickup_instructions => 'instructions 0')
create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 1', :pickup_instructions => 'instructions 1')
ex3 = create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 0', :pickup_instructions => 'instructions 0')
ex4 = create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 1', :pickup_instructions => 'instructions 1')
ExchangeFee.create!(exchange: ex3,
enterprise_fee: create(:enterprise_fee, enterprise: ex3.receiver))
ExchangeFee.create!(exchange: ex4,
enterprise_fee: create(:enterprise_fee, enterprise: ex4.receiver))
# Products with images
[ex1, ex2].each do |exchange|

View File

@@ -6,7 +6,7 @@ feature %q{
}, js: true do
include AuthenticationWorkflow
include WebHelper
before :all do
@orig_default_wait_time = Capybara.default_wait_time
Capybara.default_wait_time = 5
@@ -50,7 +50,9 @@ feature %q{
distributor = create(:distributor_enterprise, name: 'My distributor')
# And some enterprise fees
supplier_fee = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee')
coordinator_fee = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee')
distributor_fee = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee')
# When I go to the new order cycle page
login_to_admin_section
@@ -74,6 +76,11 @@ feature %q{
check 'order_cycle_incoming_exchange_0_variants_2'
check 'order_cycle_incoming_exchange_0_variants_3'
# And I add a supplier fee
within("tr.supplier-#{supplier.id}") { click_button 'Add fee' }
select 'My supplier', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id'
select 'Supplier fee', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id'
# And I add a distributor with the same products
select 'My distributor', from: 'new_distributor_id'
click_button 'Add distributor'
@@ -85,6 +92,11 @@ feature %q{
check 'order_cycle_outgoing_exchange_0_variants_2'
check 'order_cycle_outgoing_exchange_0_variants_3'
# And I add a distributor fee
within("tr.distributor-#{distributor.id}") { click_button 'Add fee' }
select 'My distributor', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id'
select 'Distributor fee', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id'
# And I click Create
click_button 'Create'
@@ -100,8 +112,10 @@ feature %q{
page.should have_selector 'td.suppliers', text: 'My supplier'
page.should have_selector 'td.distributors', text: 'My distributor'
# And it should have a coordinator fee
OrderCycle.last.coordinator_fees.should == [coordinator_fee]
# And it should have some fees
OrderCycle.last.exchanges.first.enterprise_fees.should == [supplier_fee]
OrderCycle.last.coordinator_fees.should == [coordinator_fee]
OrderCycle.last.exchanges.last.enterprise_fees.should == [distributor_fee]
# And it should have some variants selected
OrderCycle.last.exchanges.first.variants.count.should == 2
@@ -132,10 +146,11 @@ feature %q{
page.find('#order_cycle_coordinator_id').value.to_i.should == oc.coordinator_id
page.should have_selector "select[name='order_cycle_coordinator_fee_0_id']"
# And I should see the suppliers with products
# And I should see the suppliers
page.should have_selector 'td.supplier_name', :text => oc.suppliers.first.name
page.should have_selector 'td.supplier_name', :text => oc.suppliers.last.name
# And the suppliers should have products
page.all('table.exchanges tbody tr.supplier').each do |row|
row.find('td.products input').click
@@ -145,7 +160,18 @@ feature %q{
row.find('td.products input').click
end
# And I should see the distributors with products
# And the suppliers should have fees
page.find('#order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id option[selected=selected]').
text.should == oc.suppliers.first.name
page.find('#order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id option[selected=selected]').
text.should == oc.suppliers.first.enterprise_fees.first.name
page.find('#order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_id option[selected=selected]').
text.should == oc.suppliers.last.name
page.find('#order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_fee_id option[selected=selected]').
text.should == oc.suppliers.last.enterprise_fees.first.name
# And I should see the distributors
page.should have_selector 'td.distributor_name', :text => oc.distributors.first.name
page.should have_selector 'td.distributor_name', :text => oc.distributors.last.name
@@ -154,6 +180,7 @@ feature %q{
page.find('#order_cycle_outgoing_exchange_1_pickup_time').value.should == 'time 1'
page.find('#order_cycle_outgoing_exchange_1_pickup_instructions').value.should == 'instructions 1'
# And the distributors should have products
page.all('table.exchanges tbody tr.distributor').each do |row|
row.find('td.products input').click
@@ -162,6 +189,17 @@ feature %q{
row.find('td.products input').click
end
# And the distributors should have fees
page.find('#order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id option[selected=selected]').
text.should == oc.distributors.first.name
page.find('#order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id option[selected=selected]').
text.should == oc.distributors.first.enterprise_fees.first.name
page.find('#order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_id option[selected=selected]').
text.should == oc.distributors.last.name
page.find('#order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_fee_id option[selected=selected]').
text.should == oc.distributors.last.enterprise_fees.first.name
end
@@ -178,8 +216,12 @@ feature %q{
v2 = create(:variant, product: product)
# And some enterprise fees
supplier_fee1 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 1')
supplier_fee2 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 2')
coordinator_fee1 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 1')
coordinator_fee2 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 2')
distributor_fee1 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 1')
distributor_fee2 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 2')
# When I go to its edit page
login_to_admin_section
@@ -210,6 +252,16 @@ feature %q{
check "order_cycle_incoming_exchange_2_variants_#{v1.id}"
check "order_cycle_incoming_exchange_2_variants_#{v2.id}"
# And I configure some supplier fees
within("tr.supplier-#{supplier.id}") { click_button 'Add fee' }
select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id'
select 'Supplier fee 1', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id'
within("tr.supplier-#{supplier.id}") { click_button 'Add fee' }
within("tr.supplier-#{supplier.id}") { click_button 'Add fee' }
click_link 'order_cycle_incoming_exchange_2_enterprise_fees_0_remove'
select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id'
select 'Supplier fee 2', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id'
# And I add a distributor and some products
select 'My distributor', from: 'new_distributor_id'
click_button 'Add distributor'
@@ -224,6 +276,16 @@ feature %q{
uncheck "order_cycle_outgoing_exchange_2_variants_#{v1.id}"
check "order_cycle_outgoing_exchange_2_variants_#{v2.id}"
# And I configure some distributor fees
within("tr.distributor-#{distributor.id}") { click_button 'Add fee' }
select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id'
select 'Distributor fee 1', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id'
within("tr.distributor-#{distributor.id}") { click_button 'Add fee' }
within("tr.distributor-#{distributor.id}") { click_button 'Add fee' }
click_link 'order_cycle_outgoing_exchange_2_enterprise_fees_0_remove'
select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id'
select 'Distributor fee 2', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id'
# And I click Update
click_button 'Update'
@@ -242,6 +304,12 @@ feature %q{
# And my coordinator fees should have been configured
OrderCycle.last.coordinator_fee_ids.sort.should == [coordinator_fee1.id, coordinator_fee2.id].sort
# And my supplier fees should have been configured
OrderCycle.last.exchanges.incoming.last.enterprise_fee_ids.should == [supplier_fee2.id]
# And my distributor fees should have been configured
OrderCycle.last.exchanges.outgoing.last.enterprise_fee_ids.should == [distributor_fee2.id]
# And it should have some variants selected
OrderCycle.last.variants.map { |v| v.id }.sort.should == [1, v1.id, v2.id].sort
@@ -274,4 +342,71 @@ feature %q{
OrderCycle.all.map { |oc| oc.orders_close_at.sec }.should == [1, 3, 5]
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') }
let(:distributor2) { create(:distributor_enterprise, name: 'Another Distributor') }
before(:each) do
product = create(:product, supplier: supplier1)
product.distributors << distributor1
product.save!
@new_user = create_enterprise_user
@new_user.enterprise_roles.build(enterprise: supplier1).save
@new_user.enterprise_roles.build(enterprise: distributor1).save
login_to_admin_as @new_user
end
scenario "can view products I am coordinating" do
oc_user_coordinating = create(:simple_order_cycle, { coordinator: supplier1, name: 'Order Cycle 1' } )
oc_for_other_user = create(:simple_order_cycle, { coordinator: supplier2, name: 'Order Cycle 2' } )
click_link "Order Cycles"
page.should have_content oc_user_coordinating.name
page.should_not have_content oc_for_other_user.name
end
scenario "can create a new order cycle" do
click_link "Order Cycles"
click_link 'New Order Cycle'
fill_in 'order_cycle_name', with: 'My order cycle'
fill_in 'order_cycle_orders_open_at', with: '2012-11-06 06:00:00'
fill_in 'order_cycle_orders_close_at', with: '2012-11-13 17:00:00'
select 'First Supplier', from: 'new_supplier_id'
click_button 'Add supplier'
select 'First Distributor', from: 'order_cycle_coordinator_id'
select 'First Distributor', from: 'new_distributor_id'
click_button 'Add distributor'
# Should only have suppliers / distributors listed which the user can manage
within "#new_supplier_id" do
page.should_not have_content supplier2.name
end
within "#new_distributor_id" do
page.should_not have_content distributor2.name
end
within "#order_cycle_coordinator_id" do
page.should_not have_content distributor2.name
page.should_not have_content supplier1.name
page.should_not have_content supplier2.name
end
click_button 'Create'
flash_message.should == "Your order cycle has been created."
order_cycle = OrderCycle.find_by_name('My order cycle')
order_cycle.coordinator.should == distributor1
end
end
end

View File

@@ -17,6 +17,7 @@ describe 'OrderCycle controllers', ->
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').andReturn('variants selected')
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').andReturn('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').andReturn('variant supplied')
exchangeDirection: jasmine.createSpy('exchangeDirection').andReturn('exchange direction')
toggleProducts: jasmine.createSpy('toggleProducts')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
@@ -66,6 +67,10 @@ describe 'OrderCycle controllers', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')
it 'Delegates exchangeDirection to OrderCycle', ->
expect(scope.exchangeDirection('exchange')).toEqual('exchange direction')
expect(OrderCycle.exchangeDirection).toHaveBeenCalledWith('exchange')
it 'Finds enterprises participating in the order cycle', ->
scope.enterprises =
1: {id: 1, name: 'Eaterprises'}
@@ -141,6 +146,7 @@ describe 'OrderCycle controllers', ->
exchangeSelectedVariants: jasmine.createSpy('exchangeSelectedVariants').andReturn('variants selected')
productSuppliedToOrderCycle: jasmine.createSpy('productSuppliedToOrderCycle').andReturn('product supplied')
variantSuppliedToOrderCycle: jasmine.createSpy('variantSuppliedToOrderCycle').andReturn('variant supplied')
exchangeDirection: jasmine.createSpy('exchangeDirection').andReturn('exchange direction')
toggleProducts: jasmine.createSpy('toggleProducts')
addSupplier: jasmine.createSpy('addSupplier')
addDistributor: jasmine.createSpy('addDistributor')
@@ -189,6 +195,10 @@ describe 'OrderCycle controllers', ->
expect(scope.variantSuppliedToOrderCycle('variant')).toEqual('variant supplied')
expect(OrderCycle.variantSuppliedToOrderCycle).toHaveBeenCalledWith('variant')
it 'Delegates exchangeDirection to OrderCycle', ->
expect(scope.exchangeDirection('exchange')).toEqual('exchange direction')
expect(OrderCycle.exchangeDirection).toHaveBeenCalledWith('exchange')
it 'Finds enterprises participating in the order cycle', ->
scope.enterprises =
1: {id: 1, name: 'Eaterprises'}
@@ -350,6 +360,19 @@ describe 'OrderCycle services', ->
result = OrderCycle.exchangeSelectedVariants({variants: {1: true, 2: false, 3: true}})
expect(result).toEqual(2)
describe 'fetching the direction for an exchange', ->
it 'returns "incoming" for incoming exchanges', ->
exchange = {id: 1}
OrderCycle.order_cycle.incoming_exchanges = [exchange]
OrderCycle.order_cycle.outgoing_exchanges = []
expect(OrderCycle.exchangeDirection(exchange)).toEqual 'incoming'
it 'returns "outgoing" for outgoing exchanges', ->
exchange = {id: 1}
OrderCycle.order_cycle.incoming_exchanges = []
OrderCycle.order_cycle.outgoing_exchanges = [exchange]
expect(OrderCycle.exchangeDirection(exchange)).toEqual 'outgoing'
describe 'toggling products', ->
exchange = null
@@ -568,9 +591,11 @@ describe 'OrderCycle services', ->
OrderCycle.order_cycle = {foo: 'bar'}
spyOn(OrderCycle, 'removeInactiveExchanges')
spyOn(OrderCycle, 'translateCoordinatorFees')
spyOn(OrderCycle, 'translateExchangeFees')
OrderCycle.dataForSubmit()
expect(OrderCycle.removeInactiveExchanges).toHaveBeenCalled()
expect(OrderCycle.translateCoordinatorFees).toHaveBeenCalled()
expect(OrderCycle.translateExchangeFees).toHaveBeenCalled()
it 'removes inactive exchanges', ->
data =
@@ -605,5 +630,26 @@ describe 'OrderCycle services', ->
data = OrderCycle.translateCoordinatorFees(data)
expect(data.coordinator_fees).toBeUndefined()
expect(data.coordinator_fee_ids).toEqual([1, 2])
expect(data.coordinator_fee_ids).toEqual [1, 2]
it 'converts exchange fees into a list of ids', ->
data =
incoming_exchanges: [
enterprise_fees: [
{id: 1}
{id: 2}
]
]
outgoing_exchanges: [
enterprise_fees: [
{id: 3}
{id: 4}
]
]
data = OrderCycle.translateExchangeFees(data)
expect(data.incoming_exchanges[0].enterprise_fees).toBeUndefined()
expect(data.outgoing_exchanges[0].enterprise_fees).toBeUndefined()
expect(data.incoming_exchanges[0].enterprise_fee_ids).toEqual [1, 2]
expect(data.outgoing_exchanges[0].enterprise_fee_ids).toEqual [3, 4]

View File

@@ -7,7 +7,7 @@ module OpenFoodWeb
coordinator_id = 123
supplier_id = 456
incoming_exchange = {:enterprise_id => supplier_id, :variants => {'1' => true, '2' => false, '3' => true}}
incoming_exchange = {:enterprise_id => supplier_id, :variants => {'1' => true, '2' => false, '3' => true}, :enterprise_fee_ids => [1, 2]}
oc = double(:order_cycle, :coordinator_id => coordinator_id, :exchanges => [], :incoming_exchanges => [incoming_exchange], :outgoing_exchanges => [])
@@ -15,7 +15,7 @@ module OpenFoodWeb
applicator.should_receive(:exchange_variant_ids).with(incoming_exchange).and_return([1, 3])
applicator.should_receive(:exchange_exists?).with(supplier_id, coordinator_id).and_return(false)
applicator.should_receive(:add_exchange).with(supplier_id, coordinator_id, {:variant_ids => [1, 3]})
applicator.should_receive(:add_exchange).with(supplier_id, coordinator_id, {:variant_ids => [1, 3], :enterprise_fee_ids => [1, 2]})
applicator.should_receive(:destroy_untouched_exchanges)
applicator.go!
@@ -25,7 +25,7 @@ module OpenFoodWeb
coordinator_id = 123
distributor_id = 456
outgoing_exchange = {:enterprise_id => distributor_id, :variants => {'1' => true, '2' => false, '3' => true}, :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'}
outgoing_exchange = {:enterprise_id => distributor_id, :variants => {'1' => true, '2' => false, '3' => true}, :enterprise_fee_ids => [1, 2], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'}
oc = double(:order_cycle, :coordinator_id => coordinator_id, :exchanges => [], :incoming_exchanges => [], :outgoing_exchanges => [outgoing_exchange])
@@ -33,7 +33,7 @@ module OpenFoodWeb
applicator.should_receive(:exchange_variant_ids).with(outgoing_exchange).and_return([1, 3])
applicator.should_receive(:exchange_exists?).with(coordinator_id, distributor_id).and_return(false)
applicator.should_receive(:add_exchange).with(coordinator_id, distributor_id, {:variant_ids => [1, 3], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'})
applicator.should_receive(:add_exchange).with(coordinator_id, distributor_id, {:variant_ids => [1, 3], :enterprise_fee_ids => [1, 2], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'})
applicator.should_receive(:destroy_untouched_exchanges)
applicator.go!
@@ -43,7 +43,7 @@ module OpenFoodWeb
coordinator_id = 123
supplier_id = 456
incoming_exchange = {:enterprise_id => supplier_id, :variants => {'1' => true, '2' => false, '3' => true}}
incoming_exchange = {:enterprise_id => supplier_id, :variants => {'1' => true, '2' => false, '3' => true}, :enterprise_fee_ids => [1, 2]}
oc = double(:order_cycle,
:coordinator_id => coordinator_id,
@@ -55,7 +55,7 @@ module OpenFoodWeb
applicator.should_receive(:exchange_variant_ids).with(incoming_exchange).and_return([1, 3])
applicator.should_receive(:exchange_exists?).with(supplier_id, coordinator_id).and_return(true)
applicator.should_receive(:update_exchange).with(supplier_id, coordinator_id, {:variant_ids => [1, 3]})
applicator.should_receive(:update_exchange).with(supplier_id, coordinator_id, {:variant_ids => [1, 3], :enterprise_fee_ids => [1, 2]})
applicator.should_receive(:destroy_untouched_exchanges)
applicator.go!
@@ -65,7 +65,7 @@ module OpenFoodWeb
coordinator_id = 123
distributor_id = 456
outgoing_exchange = {:enterprise_id => distributor_id, :variants => {'1' => true, '2' => false, '3' => true}, :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'}
outgoing_exchange = {:enterprise_id => distributor_id, :variants => {'1' => true, '2' => false, '3' => true}, :enterprise_fee_ids => [1, 2], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'}
oc = double(:order_cycle,
:coordinator_id => coordinator_id,
@@ -77,7 +77,7 @@ module OpenFoodWeb
applicator.should_receive(:exchange_variant_ids).with(outgoing_exchange).and_return([1, 3])
applicator.should_receive(:exchange_exists?).with(coordinator_id, distributor_id).and_return(true)
applicator.should_receive(:update_exchange).with(coordinator_id, distributor_id, {:variant_ids => [1, 3], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'})
applicator.should_receive(:update_exchange).with(coordinator_id, distributor_id, {:variant_ids => [1, 3], :enterprise_fee_ids => [1, 2], :pickup_time => 'pickup time', :pickup_instructions => 'pickup instructions'})
applicator.should_receive(:destroy_untouched_exchanges)
applicator.go!
@@ -133,14 +133,17 @@ module OpenFoodWeb
receiver = FactoryGirl.create(:enterprise)
variant1 = FactoryGirl.create(:variant)
variant2 = FactoryGirl.create(:variant)
enterprise_fee1 = FactoryGirl.create(:enterprise_fee)
enterprise_fee2 = FactoryGirl.create(:enterprise_fee)
applicator.send(:touched_exchanges=, [])
applicator.send(:add_exchange, sender.id, receiver.id, {:variant_ids => [variant1.id, variant2.id]})
applicator.send(:add_exchange, sender.id, receiver.id, {:variant_ids => [variant1.id, variant2.id], :enterprise_fee_ids => [enterprise_fee1.id, enterprise_fee2.id]})
exchange = Exchange.last
exchange.sender.should == sender
exchange.receiver.should == receiver
exchange.variants.sort.should == [variant1, variant2].sort
exchange.enterprise_fees.sort.should == [enterprise_fee1, enterprise_fee2].sort
applicator.send(:touched_exchanges).should == [exchange]
end
@@ -153,14 +156,18 @@ module OpenFoodWeb
variant1 = FactoryGirl.create(:variant)
variant2 = FactoryGirl.create(:variant)
variant3 = FactoryGirl.create(:variant)
enterprise_fee1 = FactoryGirl.create(:enterprise_fee)
enterprise_fee2 = FactoryGirl.create(:enterprise_fee)
enterprise_fee3 = FactoryGirl.create(:enterprise_fee)
exchange = FactoryGirl.create(:exchange, order_cycle: oc, sender: sender, receiver: receiver, variant_ids: [variant1.id, variant2.id])
exchange = FactoryGirl.create(:exchange, order_cycle: oc, sender: sender, receiver: receiver, variant_ids: [variant1.id, variant2.id], enterprise_fee_ids: [enterprise_fee1.id, enterprise_fee2.id])
applicator.send(:touched_exchanges=, [])
applicator.send(:update_exchange, sender.id, receiver.id, {:variant_ids => [variant1.id, variant3.id]})
applicator.send(:update_exchange, sender.id, receiver.id, {:variant_ids => [variant1.id, variant3.id], :enterprise_fee_ids => [enterprise_fee2.id, enterprise_fee3.id]})
exchange.reload
exchange.variant_ids.sort.should == [variant1.id, variant3.id].sort
exchange.variants.sort.should == [variant1, variant3].sort
exchange.enterprise_fees.sort.should == [enterprise_fee2, enterprise_fee3]
applicator.send(:touched_exchanges).should == [exchange]
end
end

View File

@@ -13,22 +13,10 @@ module Spree
let(:s2) { create(:supplier_enterprise) }
let(:d1) { create(:distributor_enterprise) }
let(:d2) { create(:distributor_enterprise) }
# create product for each enterprise
let(:p1) { create(:product, supplier: s1, distributors:[d1, d2]) }
let(:p2) { create(:product, supplier: s2, distributors:[d1, d2]) }
# create order for each enterprise
let(:o1) do
o = create(:order, distributor: d1, bill_address: create(:address))
create(:line_item, order: o, product: p1)
o
end
let(:o2) do
o = create(:order, distributor: d2, bill_address: create(:address))
create(:line_item, order: o, product: p1)
o
end
subject { user }
let(:user){ nil }
@@ -55,7 +43,7 @@ module Spree
should have_ability(:create, for: Spree::Product)
end
it "should be able to read/write their enterprises' product variants" do
it "should be able to read/write their enterprises' product variants" do
should have_ability([:admin, :index, :read, :create, :edit], for: Spree::Variant)
end
@@ -66,7 +54,7 @@ module Spree
it "should be able to read/write their enterprises' product images" do
should have_ability([:admin, :index, :read, :create, :edit], for: Spree::Image)
end
it "should be able to read Taxons (in order to create classifications)" do
should have_ability([:admin, :index, :read, :search], for: Spree::Taxon)
end
@@ -74,6 +62,7 @@ module Spree
it "should be able to read/write Classifications on a product" do
should have_ability([:admin, :index, :read, :create, :edit], for: Spree::Classification)
end
end
context "when is a distributor enterprise user" do
@@ -84,13 +73,24 @@ module Spree
d1.enterprise_roles.build(user: user).save
user
end
# create order for each enterprise
let(:o1) do
o = create(:order, distributor: d1, bill_address: create(:address))
create(:line_item, order: o, product: p1)
o
end
let(:o2) do
o = create(:order, distributor: d2, bill_address: create(:address))
create(:line_item, order: o, product: p1)
o
end
it "should be able to read/write their enterprises' orders" do
should have_ability([:admin, :index, :read, :edit], for: o1)
should have_ability([:admin, :index, :read, :edit], for: o1)
end
it "should not be able to read/write other enterprises' orders" do
should_not have_ability([:admin, :index, :read, :edit], for: o2)
should_not have_ability([:admin, :index, :read, :edit], for: o2)
end
it "should be able to create a new order" do
@@ -114,6 +114,29 @@ module Spree
end
end
context 'Order Cycle co-ordinator' do
let (:user) do
user = create(:user)
user.spree_roles = []
s1.enterprise_roles.build(user: user).save
user
end
let(:oc1) { create(:simple_order_cycle, {coordinator: s1}) }
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)
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)
end
it "should be able to create OrderCycles" do
should have_ability([:create], for: OrderCycle)
end
end
end
end
end

View File

@@ -43,4 +43,22 @@ describe Exchange do
e.exchange_fees.create(:enterprise_fee => f)
e.enterprise_fees.count.should == 1
end
describe "scopes" do
let(:supplier) { create(:supplier_enterprise) }
let(:coordinator) { create(:distributor_enterprise) }
let(:distributor) { create(:distributor_enterprise) }
let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
let!(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator }
let!(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor }
it "finds incoming exchanges" do
Exchange.incoming.should == [incoming_exchange]
end
it "finds outgoing exchanges" do
Exchange.outgoing.should == [outgoing_exchange]
end
end
end