mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-01 02:03:22 +00:00
Auto-merge from CI [skip ci]
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
angular.module("admin.orders").controller "ordersCtrl", ($scope, $compile, $attrs, shops, orderCycles) ->
|
||||
$scope.$compile = $compile
|
||||
$scope.shops = shops
|
||||
$scope.orderCycles = orderCycles
|
||||
for oc in $scope.orderCycles
|
||||
oc.name_and_status = "#{oc.name} (#{oc.status})"
|
||||
|
||||
$scope.distributor_id = $attrs.ofnDistributorId
|
||||
$scope.order_cycle_id = $attrs.ofnOrderCycleId
|
||||
|
||||
$scope.validOrderCycle = (oc, index, array) ->
|
||||
$scope.orderCycleHasDistributor oc, parseInt($scope.distributor_id)
|
||||
|
||||
$scope.distributorHasOrderCycles = (distributor) ->
|
||||
(oc for oc in orderCycles when @orderCycleHasDistributor(oc, distributor.id)).length > 0
|
||||
|
||||
$scope.orderCycleHasDistributor = (oc, distributor_id) ->
|
||||
distributor_ids = (d.id for d in oc.distributors)
|
||||
distributor_ids.indexOf(distributor_id) != -1
|
||||
|
||||
$scope.distributionChosen = ->
|
||||
$scope.distributor_id && $scope.order_cycle_id
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/last_used_address'
|
||||
|
||||
class CheckoutController < Spree::CheckoutController
|
||||
layout 'darkswarm'
|
||||
|
||||
@@ -129,7 +131,11 @@ class CheckoutController < Spree::CheckoutController
|
||||
|
||||
def before_address
|
||||
associate_user
|
||||
last_used_bill_address, last_used_ship_address = find_last_used_addresses(@order.email)
|
||||
|
||||
lua = OpenFoodNetwork::LastUsedAddress.new(@order.email)
|
||||
last_used_bill_address = lua.last_used_bill_address.andand.clone
|
||||
last_used_ship_address = lua.last_used_ship_address.andand.clone
|
||||
|
||||
preferred_bill_address, preferred_ship_address = spree_current_user.bill_address, spree_current_user.ship_address if spree_current_user.respond_to?(:bill_address) && spree_current_user.respond_to?(:ship_address)
|
||||
@order.bill_address ||= preferred_bill_address || last_used_bill_address || Spree::Address.default
|
||||
@order.ship_address ||= preferred_ship_address || last_used_ship_address || Spree::Address.default
|
||||
|
||||
@@ -17,6 +17,24 @@ Spree::Admin::LineItemsController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
variant = Spree::Variant.find(params[:line_item][:variant_id])
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
|
||||
|
||||
@line_item = @order.add_variant(variant, params[:line_item][:quantity].to_i)
|
||||
|
||||
if @order.save
|
||||
respond_with(@line_item) do |format|
|
||||
format.html { render :partial => 'spree/admin/orders/form', :locals => { :order => @order.reload } }
|
||||
end
|
||||
else
|
||||
respond_with(@line_item) do |format|
|
||||
format.js { render :action => 'create', :locals => { :order => @order.reload } }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def load_order
|
||||
|
||||
@@ -10,6 +10,8 @@ Spree::Admin::OrdersController.class_eval do
|
||||
# in an auth failure as the @order object is nil for collection actions
|
||||
before_filter :check_authorization, except: [:bulk_management, :managed]
|
||||
|
||||
before_filter :load_distribution_choices, only: [:new, :edit, :update]
|
||||
|
||||
# After updating an order, the fees should be updated as well
|
||||
# Currently, adding or deleting line items does not trigger updating the
|
||||
# fees! This is a quick fix for that.
|
||||
@@ -19,6 +21,7 @@ Spree::Admin::OrdersController.class_eval do
|
||||
|
||||
before_filter :require_distributor_abn, only: :invoice
|
||||
|
||||
|
||||
respond_to :html, :json
|
||||
|
||||
# Mostly the original Spree method, tweaked to allow us to ransack with completed_at in a sane way
|
||||
@@ -112,4 +115,14 @@ Spree::Admin::OrdersController.class_eval do
|
||||
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
|
||||
end
|
||||
end
|
||||
|
||||
def load_distribution_choices
|
||||
@shops = Enterprise.is_distributor.managed_by(spree_current_user).by_name
|
||||
|
||||
ocs = OrderCycle.managed_by(spree_current_user)
|
||||
@order_cycles = ocs.soonest_closing +
|
||||
ocs.soonest_opening +
|
||||
ocs.closed +
|
||||
ocs.undated
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,14 @@ Spree::Admin::SearchController.class_eval do
|
||||
:bill_address_lastname_start => params[:q]
|
||||
}).result.limit(10)
|
||||
end
|
||||
render :users
|
||||
|
||||
render :users
|
||||
end
|
||||
|
||||
|
||||
def users_with_ams
|
||||
users_without_ams
|
||||
render json: @users, each_serializer: Api::Admin::UserSerializer
|
||||
end
|
||||
alias_method_chain :users, :ams
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/last_used_address'
|
||||
|
||||
Spree::CheckoutController.class_eval do
|
||||
|
||||
include CheckoutHelper
|
||||
@@ -19,7 +21,10 @@ Spree::CheckoutController.class_eval do
|
||||
def before_address
|
||||
associate_user
|
||||
|
||||
last_used_bill_address, last_used_ship_address = find_last_used_addresses(@order.email)
|
||||
lua = OpenFoodNetwork::LastUsedAddress.new(@order.email)
|
||||
last_used_bill_address = lua.last_used_bill_address.andand.clone
|
||||
last_used_ship_address = lua.last_used_ship_address.andand.clone
|
||||
|
||||
preferred_bill_address, preferred_ship_address = spree_current_user.bill_address, spree_current_user.ship_address if spree_current_user.respond_to?(:bill_address) && spree_current_user.respond_to?(:ship_address)
|
||||
|
||||
@order.bill_address ||= preferred_bill_address || last_used_bill_address || Spree::Address.default
|
||||
@@ -29,14 +34,4 @@ Spree::CheckoutController.class_eval do
|
||||
def after_complete
|
||||
reset_order
|
||||
end
|
||||
|
||||
def find_last_used_addresses(email)
|
||||
past = Spree::Order.order("id desc").where(:email => email).where("state != 'cart'").limit(8)
|
||||
if order = past.detect(&:bill_address)
|
||||
bill_address = order.bill_address.clone if order.bill_address
|
||||
ship_address = order.ship_address.clone if order.ship_address and order.shipping_method.andand.require_ship_address
|
||||
end
|
||||
|
||||
[bill_address, ship_address]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,8 +25,8 @@ module Admin
|
||||
admin_inject_json_ams_array "admin.shipping_methods", "shippingMethods", @shipping_methods, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_shops
|
||||
admin_inject_json_ams_array "admin.customers", "shops", @shops, Api::Admin::IdNameSerializer
|
||||
def admin_inject_shops(ngModule='admin.customers')
|
||||
admin_inject_json_ams_array ngModule, "shops", @shops, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_hubs
|
||||
@@ -74,6 +74,10 @@ module Admin
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'admin.orderCycles', name: 'ocInstance', json: "{coordinator_id: '#{@order_cycle.coordinator.id}'}"}
|
||||
end
|
||||
|
||||
def admin_inject_order_cycles
|
||||
admin_inject_json_ams_array "admin.orders", "orderCycles", @order_cycles, Api::Admin::BasicOrderCycleSerializer, current_user: spree_current_user
|
||||
end
|
||||
|
||||
def admin_inject_spree_api_key
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'ofn.admin', name: 'SpreeApiKey', json: "'#{@spree_api_key.to_s}'"}
|
||||
end
|
||||
|
||||
@@ -24,6 +24,8 @@ class OrderCycle < ActiveRecord::Base
|
||||
|
||||
scope :soonest_opening, lambda { upcoming.order('order_cycles.orders_open_at ASC') }
|
||||
|
||||
scope :by_name, order('name')
|
||||
|
||||
scope :distributing_product, lambda { |product|
|
||||
joins(:exchanges).
|
||||
merge(Exchange.outgoing).
|
||||
|
||||
@@ -26,18 +26,15 @@ Spree::Variant.class_eval do
|
||||
after_save :update_units
|
||||
|
||||
scope :with_order_cycles_inner, joins(exchanges: :order_cycle)
|
||||
scope :with_order_cycles_outer, joins('LEFT OUTER JOIN exchange_variants AS o_exchange_variants ON (o_exchange_variants.variant_id = spree_variants.id)').
|
||||
joins('LEFT OUTER JOIN exchanges AS o_exchanges ON (o_exchanges.id = o_exchange_variants.exchange_id)').
|
||||
joins('LEFT OUTER JOIN order_cycles AS o_order_cycles ON (o_order_cycles.id = o_exchanges.order_cycle_id)')
|
||||
|
||||
scope :not_deleted, where(deleted_at: nil)
|
||||
scope :in_stock, where('spree_variants.count_on_hand > 0 OR spree_variants.on_demand=?', true)
|
||||
scope :in_distributor, lambda { |distributor|
|
||||
with_order_cycles_outer.
|
||||
where('o_exchanges.incoming = ? AND o_exchanges.receiver_id = ?', false, distributor).
|
||||
select('DISTINCT spree_variants.*')
|
||||
where(id: ExchangeVariant.select(:variant_id).
|
||||
joins(:exchange).
|
||||
where('exchanges.incoming = ? AND exchanges.receiver_id = ?', false, distributor)
|
||||
)
|
||||
}
|
||||
|
||||
scope :in_order_cycle, lambda { |order_cycle|
|
||||
with_order_cycles_inner.
|
||||
merge(Exchange.outgoing).
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/ insert_before "[data-hook='admin_order_form_buttons']"
|
||||
|
||||
%fieldset.no-border-bottom
|
||||
%legend{align => 'center'} Distribution
|
||||
%legend{align: 'center'} Distribution
|
||||
|
||||
- if @order.complete?
|
||||
.alpha.six.columns
|
||||
@@ -18,9 +18,12 @@
|
||||
- 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
|
||||
%label{for: "order_distributor_id"} Distributor
|
||||
%select.fullwidth{id: "order_distributor_id", name: "order[distributor_id]", 'ng-model' => 'distributor_id'}
|
||||
%option{"ng-repeat" => "shop in shops", "ng-value" => "shop.id", "ng-selected" => "distributor_id == shop.id", "ng-disabled" => "!distributorHasOrderCycles(shop)", "ng-bind" => "shop.name"}
|
||||
|
||||
.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
|
||||
.field{"ng-show" => "distributor_id"}
|
||||
%label{for: "order_order_cycle_id"} Order Cycle
|
||||
%select.select2.fullwidth{id: "order_order_cycle_id", name: "order[order_cycle_id]", 'ng-model' => 'order_cycle_id'}
|
||||
%option{"ng-repeat" => "oc in orderCycles | filter:validOrderCycle", "ng-value" => "oc.id", "ng-selected" => "order_cycle_id == oc.id", "ng-bind" => "oc.name_and_status"}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
add_to_attributes "table.index, [data-hook='admin_order_form_buttons']"
|
||||
attributes "ng-show" => "distributionChosen()"
|
||||
@@ -1,14 +1,24 @@
|
||||
class Api::Admin::BasicOrderCycleSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :first_order, :last_order
|
||||
include OrderCyclesHelper
|
||||
|
||||
attributes :id, :name, :status, :first_order, :last_order
|
||||
|
||||
has_many :suppliers, serializer: Api::Admin::IdNameSerializer
|
||||
has_many :distributors, serializer: Api::Admin::IdNameSerializer
|
||||
|
||||
def status
|
||||
order_cycle_status_class object
|
||||
end
|
||||
|
||||
def first_order
|
||||
object.orders_open_at.strftime("%F")
|
||||
object.orders_open_at.andand.strftime("%F")
|
||||
end
|
||||
|
||||
def last_order
|
||||
(object.orders_close_at + 1.day).strftime("%F")
|
||||
if object.orders_close_at.present?
|
||||
(object.orders_close_at + 1.day).strftime("%F")
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/order_cycle_permissions'
|
||||
|
||||
class Api::Admin::OrderCycleSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :orders_open_at, :orders_close_at, :coordinator_id, :exchanges
|
||||
attributes :editable_variants_for_incoming_exchanges, :editable_variants_for_outgoing_exchanges
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
require 'open_food_network/last_used_address'
|
||||
|
||||
class Api::Admin::UserSerializer < ActiveModel::Serializer
|
||||
attributes :id, :email
|
||||
|
||||
has_one :ship_address, serializer: Api::AddressSerializer
|
||||
has_one :bill_address, serializer: Api::AddressSerializer
|
||||
|
||||
def ship_address
|
||||
object.ship_address ||
|
||||
OpenFoodNetwork::LastUsedAddress.new(object.email).last_used_ship_address
|
||||
end
|
||||
|
||||
def bill_address
|
||||
object.bill_address ||
|
||||
OpenFoodNetwork::LastUsedAddress.new(object.email).last_used_bill_address
|
||||
end
|
||||
end
|
||||
|
||||
6
app/views/spree/admin/line_items/create.js.erb
Normal file
6
app/views/spree/admin/line_items/create.js.erb
Normal file
@@ -0,0 +1,6 @@
|
||||
// The admin order form contains angular directives, so it needs to be
|
||||
// compiled before insertion into the DOM
|
||||
var scope = angular.element("#order-form-wrapper").scope();
|
||||
$("#order-form-wrapper").html(scope.$compile('<%= escape_javascript(render :partial => "spree/admin/orders/form") %>')(scope));
|
||||
scope.$apply();
|
||||
$('select.select2').select2({allowClear: true});
|
||||
24
app/views/spree/admin/orders/edit.html.haml
Normal file
24
app/views/spree/admin/orders/edit.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
= csrf_meta_tags
|
||||
|
||||
- content_for :page_actions do
|
||||
%li= event_links
|
||||
%li= button_link_to t(:resend), resend_admin_order_url(@order), method: :post, icon: 'icon-email'
|
||||
%li= button_link_to t(:back_to_orders_list), admin_orders_path, icon: 'icon-arrow-left'
|
||||
|
||||
= admin_inject_shops 'admin.orders'
|
||||
= admin_inject_order_cycles
|
||||
|
||||
= render 'spree/admin/shared/order_tabs', current: 'Order Details'
|
||||
|
||||
%div{"data-hook" => "admin_order_edit_header"}
|
||||
= render 'spree/shared/error_messages', target: @order
|
||||
|
||||
%div{"ng-app" => "admin.orders", "ng-controller" => "ordersCtrl", "ofn-distributor-id" => @order.distributor_id, "ofn-order-cycle-id" => @order.order_cycle_id}
|
||||
= render 'add_product'
|
||||
|
||||
%div{"data-hook" => "admin_order_edit_form"}
|
||||
#order-form-wrapper
|
||||
= render 'form', order: @order
|
||||
|
||||
- content_for :head do
|
||||
= javascript_tag 'var expand_variants = true;'
|
||||
27
app/views/spree/admin/orders/new.html.haml
Normal file
27
app/views/spree/admin/orders/new.html.haml
Normal file
@@ -0,0 +1,27 @@
|
||||
- content_for :page_title do
|
||||
= t(:new)
|
||||
|
||||
- content_for :page_actions do
|
||||
%li= button_link_to t(:back_to_orders_list), spree.admin_orders_path, :icon => 'icon-arrow-left'
|
||||
|
||||
= admin_inject_shops 'admin.orders'
|
||||
= admin_inject_order_cycles
|
||||
|
||||
= render 'spree/admin/shared/order_tabs', :current => 'Order Details'
|
||||
|
||||
= csrf_meta_tags
|
||||
|
||||
%div{"data-hook" => "admin_order_new_header"}
|
||||
= render 'spree/shared/error_messages', :target => @order
|
||||
|
||||
%div{"ng-app" => "admin.orders", "ng-controller" => "ordersCtrl"}
|
||||
%div{"ng-show" => "distributionChosen()"}
|
||||
= render 'add_product'
|
||||
|
||||
- unless @order.line_items.any?
|
||||
%div{"data-hook" => "admin_order_new_form"}
|
||||
#order-form-wrapper
|
||||
= render 'form'
|
||||
|
||||
- content_for :head do
|
||||
= javascript_tag 'var expand_variants = true;'
|
||||
28
lib/open_food_network/last_used_address.rb
Normal file
28
lib/open_food_network/last_used_address.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
module OpenFoodNetwork
|
||||
class LastUsedAddress
|
||||
def initialize(email)
|
||||
@email = email
|
||||
end
|
||||
|
||||
def last_used_bill_address
|
||||
recent_orders.detect(&:bill_address).andand.bill_address
|
||||
end
|
||||
|
||||
def last_used_ship_address
|
||||
recent_orders.detect { |o|
|
||||
o.ship_address && o.shipping_method.andand.require_ship_address
|
||||
}.andand.ship_address
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def recent_orders
|
||||
Spree::Order.
|
||||
order("id DESC").
|
||||
where(email: @email).
|
||||
where("state != 'cart'").
|
||||
limit(8)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,6 +6,7 @@ module OpenFoodNetwork
|
||||
[
|
||||
"PRODUCT",
|
||||
"Description",
|
||||
"SKU",
|
||||
"Qty",
|
||||
"Pack Size",
|
||||
"Unit",
|
||||
@@ -18,15 +19,23 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def table
|
||||
variants.map do |variant|
|
||||
variants = variants()
|
||||
if params[:distributor_id].to_i > 0
|
||||
distributor = Enterprise.find(params[:distributor_id])
|
||||
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
|
||||
variants.each { |v| scoper.scope(v) }
|
||||
end
|
||||
variants.select { |v| v.in_stock? }
|
||||
.map do |variant|
|
||||
[
|
||||
variant.product.name,
|
||||
variant.full_name,
|
||||
variant.sku,
|
||||
'',
|
||||
OptionValueNamer.new(variant).value,
|
||||
OptionValueNamer.new(variant).unit,
|
||||
variant.price - gst(variant),
|
||||
variant.price,
|
||||
'',
|
||||
gst(variant),
|
||||
grower_and_method(variant),
|
||||
variant.product.primary_taxon.name
|
||||
|
||||
@@ -28,8 +28,6 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def filter(variants)
|
||||
# NOTE: Ordering matters.
|
||||
# filter_to_order_cycle and filter_to_distributor return arrays not relations
|
||||
filter_to_distributor filter_to_order_cycle filter_on_hand filter_to_supplier filter_not_deleted variants
|
||||
end
|
||||
|
||||
@@ -56,9 +54,7 @@ module OpenFoodNetwork
|
||||
def filter_to_distributor(variants)
|
||||
if params[:distributor_id].to_i > 0
|
||||
distributor = Enterprise.find params[:distributor_id]
|
||||
variants.select do |v|
|
||||
Enterprise.distributing_product(v.product_id).include? distributor
|
||||
end
|
||||
variants.in_distributor(distributor)
|
||||
else
|
||||
variants
|
||||
end
|
||||
@@ -67,7 +63,7 @@ module OpenFoodNetwork
|
||||
def filter_to_order_cycle(variants)
|
||||
if params[:order_cycle_id].to_i > 0
|
||||
order_cycle = OrderCycle.find params[:order_cycle_id]
|
||||
variants.select { |v| order_cycle.variants.include? v }
|
||||
variants.where(id: order_cycle.variants)
|
||||
else
|
||||
variants
|
||||
end
|
||||
|
||||
@@ -52,12 +52,6 @@ describe CheckoutController do
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it "doesn't copy the previous shipping address from a pickup order" do
|
||||
old_order = create(:order, bill_address: create(:address), ship_address: create(:address))
|
||||
Spree::Order.stub_chain(:order, :where, :where, :limit, :detect).and_return(old_order)
|
||||
controller.send(:find_last_used_addresses, "email").last.should == nil
|
||||
end
|
||||
|
||||
describe "building the order" do
|
||||
before do
|
||||
controller.stub(:current_distributor).and_return(distributor)
|
||||
|
||||
@@ -126,6 +126,23 @@ describe Spree::Admin::LineItemsController do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#create" do
|
||||
let!(:variant) { create(:variant, price: 88) }
|
||||
let!(:vo) { create(:variant_override, hub: distributor, variant: variant, price: 11.11) }
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], variants: [variant]) }
|
||||
let!(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) }
|
||||
let(:params) { { order_id: order.number, line_item: { variant_id: variant.id, quantity: 1 } } }
|
||||
|
||||
before { login_as_admin }
|
||||
|
||||
it "takes variant overrides into account for price" do
|
||||
spree_post :create, params
|
||||
|
||||
order.line_items(:reload).last.price.should == 11.11
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:distributor1) { create(:distributor_enterprise) }
|
||||
|
||||
@@ -3,7 +3,7 @@ require "spec_helper"
|
||||
feature %q{
|
||||
As an administrator
|
||||
I want to manage orders
|
||||
} do
|
||||
}, js: true do
|
||||
include AuthenticationWorkflow
|
||||
include WebHelper
|
||||
|
||||
@@ -11,7 +11,7 @@ feature %q{
|
||||
@user = create(:user)
|
||||
@product = create(:simple_product)
|
||||
@distributor = create(:distributor_enterprise, charges_sales_tax: true)
|
||||
@order_cycle = create(:simple_order_cycle, distributors: [@distributor], variants: [@product.variants.first])
|
||||
@order_cycle = create(:simple_order_cycle, name: 'One', distributors: [@distributor], variants: [@product.variants.first])
|
||||
|
||||
@order = create(:order_with_totals_and_distribution, user: @user, distributor: @distributor, order_cycle: @order_cycle, state: 'complete', payment_state: 'balance_due')
|
||||
|
||||
@@ -21,33 +21,39 @@ feature %q{
|
||||
create :check_payment, order: @order, amount: @order.total
|
||||
end
|
||||
|
||||
scenario "creating an order with distributor and order cycle", js: true, retry: 3 do
|
||||
order_cycle = create(:order_cycle)
|
||||
distributor = order_cycle.distributors.first
|
||||
product = order_cycle.products.first
|
||||
scenario "creating an order with distributor and order cycle", retry: 3 do
|
||||
distributor_disabled = create(:distributor_enterprise)
|
||||
create(:simple_order_cycle, name: 'Two')
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/orders'
|
||||
click_link 'New Order'
|
||||
|
||||
# Distributors without an order cycle should be shown as disabled
|
||||
page.should have_selector "option[value='#{distributor_disabled.id}'][disabled='disabled']"
|
||||
|
||||
# When we select a distributor, it should limit order cycle selection to those for that distributor
|
||||
page.should_not have_select2 'order_order_cycle_id'
|
||||
select @distributor.name, from: 'order_distributor_id'
|
||||
page.should have_select2 'order_order_cycle_id', options: ['', 'One (open)']
|
||||
select2_select @order_cycle.name, from: 'order_order_cycle_id'
|
||||
|
||||
page.should have_content 'ADD PRODUCT'
|
||||
targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
|
||||
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
|
||||
page.should have_selector 'td', text: @product.name
|
||||
|
||||
select distributor.name, from: 'order_distributor_id'
|
||||
select order_cycle.name, from: 'order_order_cycle_id'
|
||||
click_button 'Update'
|
||||
|
||||
page.should have_selector 'h1', text: 'Customer Details'
|
||||
o = Spree::Order.last
|
||||
o.distributor.should == distributor
|
||||
o.order_cycle.should == order_cycle
|
||||
o.distributor.should == @distributor
|
||||
o.order_cycle.should == @order_cycle
|
||||
end
|
||||
|
||||
scenario "can add a product to an existing order", js: true, retry: 3 do
|
||||
scenario "can add a product to an existing order", retry: 3 do
|
||||
login_to_admin_section
|
||||
visit '/admin/orders'
|
||||
|
||||
@@ -61,7 +67,29 @@ feature %q{
|
||||
@order.line_items(true).map(&:product).should include @product
|
||||
end
|
||||
|
||||
scenario "can't add products to an order outside the order's hub and order cycle", js: true do
|
||||
scenario "displays error when incorrect distribution for products is chosen" do
|
||||
d = create(:distributor_enterprise)
|
||||
oc = create(:simple_order_cycle, distributors: [d])
|
||||
|
||||
@order.state = 'cart'; @order.completed_at = nil; @order.save
|
||||
|
||||
login_to_admin_section
|
||||
visit '/admin/orders'
|
||||
uncheck 'Only show complete orders'
|
||||
click_button 'Filter Results'
|
||||
|
||||
click_edit
|
||||
|
||||
select d.name, from: 'order_distributor_id'
|
||||
select2_select oc.name, from: 'order_order_cycle_id'
|
||||
|
||||
click_button 'Update And Recalculate Fees'
|
||||
|
||||
page.should have_content "Distributor or order cycle cannot supply the products in your cart"
|
||||
end
|
||||
|
||||
|
||||
scenario "can't add products to an order outside the order's hub and order cycle" do
|
||||
product = create(:simple_product)
|
||||
|
||||
login_to_admin_section
|
||||
@@ -79,12 +107,42 @@ feature %q{
|
||||
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_not have_select2 '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 "filling customer details" do
|
||||
# Given a customer with an order, which includes their shipping and billing address
|
||||
@order.ship_address = create(:address, lastname: 'Ship')
|
||||
@order.bill_address = create(:address, lastname: 'Bill')
|
||||
@order.shipping_method = create(:shipping_method, require_ship_address: true)
|
||||
@order.save!
|
||||
|
||||
# When I create a new order
|
||||
login_to_admin_section
|
||||
visit '/admin/orders'
|
||||
click_link 'New Order'
|
||||
select @distributor.name, from: 'order_distributor_id'
|
||||
select2_select @order_cycle.name, from: 'order_order_cycle_id'
|
||||
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
|
||||
click_button 'Update'
|
||||
within('h1.page-title') { page.should have_content "Customer Details" }
|
||||
|
||||
# And I select that customer's email address and save the order
|
||||
targetted_select2_search @order.user.email, from: '#customer_search', dropdown_css: '.select2-drop'
|
||||
click_button 'Continue'
|
||||
within('h1.page-title') { page.should have_content "Shipments" }
|
||||
|
||||
# Then their addresses should be associated with the order
|
||||
order = Spree::Order.last
|
||||
order.ship_address.lastname.should == 'Ship'
|
||||
order.bill_address.lastname.should == 'Bill'
|
||||
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.
|
||||
|
||||
@@ -127,10 +185,13 @@ feature %q{
|
||||
login_to_admin_as @enterprise_user
|
||||
end
|
||||
|
||||
scenario "creating an order with distributor and order cycle", js: true do
|
||||
scenario "creating an order with distributor and order cycle" do
|
||||
visit '/admin/orders'
|
||||
click_link 'New Order'
|
||||
|
||||
select distributor1.name, from: 'order_distributor_id'
|
||||
select2_select order_cycle1.name, from: 'order_order_cycle_id'
|
||||
|
||||
expect(page).to have_content 'ADD PRODUCT'
|
||||
targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
|
||||
|
||||
@@ -141,11 +202,9 @@ feature %q{
|
||||
expect(page).to have_select 'order_distributor_id', with_options: [distributor1.name]
|
||||
expect(page).to_not have_select 'order_distributor_id', with_options: [distributor2.name]
|
||||
|
||||
expect(page).to have_select 'order_order_cycle_id', with_options: [order_cycle1.name]
|
||||
expect(page).to_not have_select 'order_order_cycle_id', with_options: [order_cycle2.name]
|
||||
expect(page).to have_select2 'order_order_cycle_id', with_options: ["#{order_cycle1.name} (open)"]
|
||||
expect(page).to_not have_select2 'order_order_cycle_id', with_options: ["#{order_cycle2.name} (open)"]
|
||||
|
||||
select distributor1.name, from: 'order_distributor_id'
|
||||
select order_cycle1.name, from: 'order_order_cycle_id'
|
||||
click_button 'Update'
|
||||
|
||||
expect(page).to have_selector 'h1', text: 'Customer Details'
|
||||
|
||||
@@ -323,8 +323,8 @@ feature %q{
|
||||
click_link 'Reports'
|
||||
click_link 'LettuceShare'
|
||||
|
||||
page.should have_table_row ['PRODUCT', 'Description', 'Qty', 'Pack Size', 'Unit', 'Unit Price', 'Total', 'GST incl.', 'Grower and growing method', 'Taxon'].map(&:upcase)
|
||||
page.should have_table_row ['Product 2', '100g', '', '100', 'g', '99.0', '99.0', '0', 'Supplier Name (Organic - NASAA 12345)', 'Taxon Name']
|
||||
page.should have_table_row ['PRODUCT', 'Description', 'SKU', 'Qty', 'Pack Size', 'Unit', 'Unit Price', 'Total', 'GST incl.', 'Grower and growing method', 'Taxon'].map(&:upcase)
|
||||
page.should have_table_row ['Product 2', '100g', 'ABC', '', '100', 'g', '99.0', '', '0', 'Supplier Name (Organic - NASAA 12345)', 'Taxon Name']
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
describe "ordersCtrl", ->
|
||||
ctrl = null
|
||||
scope = {}
|
||||
attrs = {}
|
||||
shops = []
|
||||
orderCycles = [
|
||||
{id: 10, name: 'Ten', status: 'open', distributors: [{id: 1, name: 'One'}]}
|
||||
{id: 20, name: 'Twenty', status: 'closed', distributors: [{id: 2, name: 'Two', status: 'closed'}]}
|
||||
]
|
||||
|
||||
beforeEach ->
|
||||
scope = {}
|
||||
|
||||
module('admin.orders')
|
||||
inject ($controller) ->
|
||||
ctrl = $controller 'ordersCtrl', {$scope: scope, $attrs: attrs, shops: shops, orderCycles: orderCycles}
|
||||
|
||||
it "initialises name_and_status", ->
|
||||
expect(scope.orderCycles[0].name_and_status).toEqual "Ten (open)"
|
||||
expect(scope.orderCycles[1].name_and_status).toEqual "Twenty (closed)"
|
||||
|
||||
describe "finding valid order cycles for a distributor", ->
|
||||
order_cycle = {id: 10, distributors: [{id: 1, name: 'One'}]}
|
||||
|
||||
it "returns true when the order cycle includes the distributor", ->
|
||||
scope.distributor_id = '1'
|
||||
expect(scope.validOrderCycle(order_cycle, 1, [order_cycle])).toBe true
|
||||
|
||||
it "returns false otherwise", ->
|
||||
scope.distributor_id = '2'
|
||||
expect(scope.validOrderCycle(order_cycle, 1, [order_cycle])).toBe false
|
||||
|
||||
describe "checking if a distributor has order cycles", ->
|
||||
it "returns true when it does", ->
|
||||
distributor = {id: 1}
|
||||
expect(scope.distributorHasOrderCycles(distributor)).toBe true
|
||||
|
||||
it "returns false otherwise", ->
|
||||
distributor = {id: 3}
|
||||
expect(scope.distributorHasOrderCycles(distributor)).toBe false
|
||||
58
spec/lib/open_food_network/last_used_address_spec.rb
Normal file
58
spec/lib/open_food_network/last_used_address_spec.rb
Normal file
@@ -0,0 +1,58 @@
|
||||
require 'open_food_network/last_used_address'
|
||||
|
||||
module OpenFoodNetwork
|
||||
describe LastUsedAddress do
|
||||
let(:email) { 'test@example.com' }
|
||||
let(:address) { 'address' }
|
||||
|
||||
describe "last used bill address" do
|
||||
let(:lua) { LastUsedAddress.new(email) }
|
||||
let(:order_with_bill_address) { double(:order, bill_address: address) }
|
||||
let(:order_without_bill_address) { double(:order, bill_address: nil) }
|
||||
|
||||
it "returns the bill address when present" do
|
||||
lua.stub(:recent_orders) { [order_with_bill_address] }
|
||||
lua.last_used_bill_address.should == address
|
||||
end
|
||||
|
||||
it "returns nil when there's no order with a bill address" do
|
||||
lua.stub(:recent_orders) { [order_without_bill_address] }
|
||||
lua.last_used_bill_address.should be_nil
|
||||
end
|
||||
|
||||
it "returns nil when there are no recent orders" do
|
||||
lua.stub(:recent_orders) { [] }
|
||||
lua.last_used_bill_address.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "last used ship address" do
|
||||
let(:lua) { LastUsedAddress.new(email) }
|
||||
let(:pickup) { double(:shipping_method, require_ship_address: false) }
|
||||
let(:delivery) { double(:shipping_method, require_ship_address: true) }
|
||||
let(:order_with_ship_address) { double(:order, ship_address: address, shipping_method: delivery) }
|
||||
let(:order_with_unrequired_ship_address) { double(:order, ship_address: address, shipping_method: pickup) }
|
||||
let(:order_without_ship_address) { double(:order, ship_address: nil) }
|
||||
|
||||
it "returns the ship address when present" do
|
||||
lua.stub(:recent_orders) { [order_with_ship_address] }
|
||||
lua.last_used_ship_address.should == address
|
||||
end
|
||||
|
||||
it "returns nil when the order doesn't require a ship address" do
|
||||
lua.stub(:recent_orders) { [order_with_unrequired_ship_address] }
|
||||
lua.last_used_ship_address.should be_nil
|
||||
end
|
||||
|
||||
it "returns nil when there's no order with a ship address" do
|
||||
lua.stub(:recent_orders) { [order_without_ship_address] }
|
||||
lua.last_used_ship_address.should be_nil
|
||||
end
|
||||
|
||||
it "returns nil when there are no recent orders" do
|
||||
lua.stub(:recent_orders) { [] }
|
||||
lua.last_used_ship_address.should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -27,5 +27,44 @@ module OpenFoodNetwork
|
||||
report.send(:gst, v).should == 0
|
||||
end
|
||||
end
|
||||
|
||||
describe "table" do
|
||||
it "handles no items" do
|
||||
report.send(:table).should eq []
|
||||
end
|
||||
|
||||
describe "lists" do
|
||||
let(:v2) { create(:variant) }
|
||||
let(:v3) { create(:variant) }
|
||||
let(:v4) { create(:variant, count_on_hand: 0, on_demand: true) }
|
||||
let(:hub_address) { create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") }
|
||||
let(:hub) { create(:distributor_enterprise, :address => hub_address) }
|
||||
let(:v2o) { create(:variant_override, hub: hub, variant: v2) }
|
||||
let(:v3o) { create(:variant_override, hub: hub, variant: v3, count_on_hand: 0) }
|
||||
|
||||
it "all items" do
|
||||
report.stub(:variants) { [v, v2, v3] }
|
||||
report.send(:table).count.should eq 3
|
||||
end
|
||||
|
||||
it "only available items" do
|
||||
report.stub(:variants) { [v, v2, v3, v4] }
|
||||
v.count_on_hand = 0
|
||||
report.send(:table).count.should eq 3
|
||||
end
|
||||
|
||||
it "only available items considering overrides" do
|
||||
# create the overrides
|
||||
v2o
|
||||
v3o
|
||||
report.stub(:variants) { [v, v2, v3] }
|
||||
report.stub(:params) { {distributor_id: hub.id} }
|
||||
rows = report.send(:table)
|
||||
rows.count.should eq 2
|
||||
rows[1][0].should eq v2.product.name
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -124,15 +124,16 @@ module OpenFoodNetwork
|
||||
it "filters to a specific distributor" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product2.variants.first])
|
||||
|
||||
subject.stub(:params).and_return(distributor_id: distributor.id)
|
||||
subject.filter(variants).should == [product2.variants.first]
|
||||
end
|
||||
it "filters to a specific order cycle" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.variants.first])
|
||||
|
||||
subject.stub(:params).and_return(order_cycle_id: order_cycle.id)
|
||||
@@ -141,8 +142,8 @@ module OpenFoodNetwork
|
||||
|
||||
it "should do all the filters at once" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.variants.first])
|
||||
|
||||
subject.stub(:params).and_return(
|
||||
|
||||
@@ -28,15 +28,43 @@ RSpec::Matchers.define :have_select2 do |id, options={}|
|
||||
end
|
||||
|
||||
failure_message_for_should do |actual|
|
||||
message = "expected to find select2 ##{@id}"
|
||||
message = "expected to find select2 ##{@id}"
|
||||
message += " with #{@options.inspect}" if @options.any?
|
||||
message
|
||||
end
|
||||
|
||||
match_for_should_not do |node|
|
||||
raise "Not yet implemented"
|
||||
@id, @options, @node = id, options, node
|
||||
|
||||
#id = find_label_by_text(locator)
|
||||
from = "#s2id_#{id}"
|
||||
|
||||
results = []
|
||||
|
||||
results << node.has_no_selector?(from, wait: 1)
|
||||
|
||||
# if results.all?
|
||||
# results << selected_option_is(from, options[:selected]) if options.key? :selected
|
||||
# end
|
||||
|
||||
if results.none?
|
||||
results << all_options_absent(from, options[:with_options]) if options.key? :with_options
|
||||
#results << exact_options_present(from, options[:options]) if options.key? :options
|
||||
#results << no_options_present(from, options[:without_options]) if options.key? :without_options
|
||||
end
|
||||
|
||||
if (options.keys & %i(selected options without_options)).any?
|
||||
raise "Not yet implemented"
|
||||
end
|
||||
|
||||
results.any?
|
||||
end
|
||||
|
||||
failure_message_for_should_not do |actual|
|
||||
message = "expected not to find select2 ##{@id}"
|
||||
message += " with #{@options.inspect}" if @options.any?
|
||||
message
|
||||
end
|
||||
|
||||
def all_options_present(from, options)
|
||||
with_select2_open(from) do
|
||||
@@ -46,6 +74,14 @@ RSpec::Matchers.define :have_select2 do |id, options={}|
|
||||
end
|
||||
end
|
||||
|
||||
def all_options_absent(from, options)
|
||||
with_select2_open(from) do
|
||||
options.all? do |option|
|
||||
@node.has_no_selector? "div.select2-drop-active ul.select2-results li", text: option
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def exact_options_present(from, options)
|
||||
with_select2_open(from) do
|
||||
@node.all("div.select2-drop-active ul.select2-results li").map(&:text) == options
|
||||
|
||||
Reference in New Issue
Block a user