mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-10 03:30:22 +00:00
Moving action for estimating standing_line_item prices into StandingLineItemController#build
This commit is contained in:
@@ -17,7 +17,7 @@ angular.module("admin.standingOrders").controller "StandingOrderController", ($s
|
||||
|
||||
$scope.estimatedSubtotal = ->
|
||||
$scope.standingOrder.standing_line_items.reduce (subtotal, item) ->
|
||||
item.price_with_fees * item.quantity
|
||||
item.price_estimate * item.quantity
|
||||
, 0
|
||||
|
||||
$scope.estimatedTotal = ->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.standingOrders").factory "StandingOrder", ($injector, $http, StatusMessage, StandingOrderResource) ->
|
||||
angular.module("admin.standingOrders").factory "StandingOrder", ($injector, $http, StatusMessage, InfoDialog, StandingOrderResource) ->
|
||||
new class StandingOrder
|
||||
standingOrder: new StandingOrderResource()
|
||||
errors: {}
|
||||
@@ -10,13 +10,11 @@ angular.module("admin.standingOrders").factory "StandingOrder", ($injector, $htt
|
||||
buildItem: (item) ->
|
||||
return false unless item.variant_id > 0
|
||||
return false unless item.quantity > 0
|
||||
estimate_query = "/admin/variants/#{item.variant_id}/price_estimate?"
|
||||
estimate_query += "shop_id=#{@standingOrder.shop_id};schedule_id=#{@standingOrder.schedule_id}"
|
||||
$http.get(estimate_query).then (response) =>
|
||||
angular.extend(response.data, item) # Add variant_id and qty
|
||||
data = angular.extend({}, item, { shop_id: @standingOrder.shop_id, schedule_id: @standingOrder.schedule_id })
|
||||
$http.post("/admin/standing_line_items/build", data).then (response) =>
|
||||
@standingOrder.standing_line_items.push response.data
|
||||
, (response) =>
|
||||
alert(response.data.errors)
|
||||
InfoDialog.open 'error', response.data.errors[0]
|
||||
|
||||
save: ->
|
||||
StatusMessage.display 'progress', 'Saving...'
|
||||
|
||||
39
app/controllers/admin/standing_line_items_controller.rb
Normal file
39
app/controllers/admin/standing_line_items_controller.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'open_food_network/order_cycle_permissions'
|
||||
|
||||
module Admin
|
||||
class StandingLineItemsController < ResourceController
|
||||
before_filter :load_build_context, only: [:build]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def build
|
||||
return render json: { errors: ['Unauthorised'] }, status: :unauthorized unless @shop
|
||||
if @variant
|
||||
@standing_line_item.assign_attributes(params[:standing_line_item])
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(@shop, @order_cycle) if @order_cycle
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
render json: @standing_line_item, serializer: Api::Admin::StandingLineItemSerializer, fee_calculator: fee_calculator
|
||||
else
|
||||
render json: { errors: ["#{@shop.name} is not permitted to sell the selected product"] }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def permissions
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
end
|
||||
|
||||
def load_build_context
|
||||
@shop = Enterprise.managed_by(spree_current_user).find_by_id(params[:shop_id])
|
||||
@schedule = permissions.editable_schedules.find_by_id(params[:schedule_id])
|
||||
@order_cycle = @schedule.andand.current_or_next_order_cycle
|
||||
@variant = Spree::Variant.stockable_by(@shop).find_by_id(params[:standing_line_item][:variant_id])
|
||||
end
|
||||
|
||||
def new_actions
|
||||
[:new, :create, :build] # Added build
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,11 @@ module Admin
|
||||
respond_to :json
|
||||
|
||||
respond_override create: { json: {
|
||||
success: lambda { render_as_json @standing_order },
|
||||
success: lambda {
|
||||
shop, next_oc = @standing_order.shop, @standing_order.schedule.current_or_next_order_cycle
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, next_oc) if shop && next_oc
|
||||
render_as_json @standing_order, fee_calculator: fee_calculator
|
||||
},
|
||||
failure: lambda { render json: { errors: json_errors }, status: :unprocessable_entity }
|
||||
} }
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
require 'open_food_network/permissions'
|
||||
|
||||
Spree::Admin::VariantsController.class_eval do
|
||||
helper 'spree/products'
|
||||
before_filter :load_price_estimate_context, only: [:price_estimate]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def search
|
||||
search_params = { :product_name_cont => params[:q], :sku_cont => params[:q] }
|
||||
|
||||
@variants = Spree::Variant.where(is_master: false).ransack(search_params.merge(:m => 'or')).result
|
||||
|
||||
if params[:schedule_id].present?
|
||||
schedule = Schedule.find params[:schedule_id]
|
||||
@variants = @variants.in_schedule(schedule)
|
||||
end
|
||||
|
||||
if params[:order_cycle_id].present?
|
||||
order_cycle = OrderCycle.find params[:order_cycle_id]
|
||||
@variants = @variants.in_order_cycle(order_cycle)
|
||||
@@ -26,16 +26,6 @@ Spree::Admin::VariantsController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def price_estimate
|
||||
if @shop && @schedule && @order_cycle
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(@shop, @order_cycle)
|
||||
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
|
||||
render json: @variant, serializer: Api::Admin::EstimatedVariantSerializer, fee_calculator: fee_calculator
|
||||
else
|
||||
render json: { errors: ["Unauthorized"], status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@variant = Spree::Variant.find(params[:id])
|
||||
@variant.delete # This line changed, as well as removal of following conditional
|
||||
@@ -55,22 +45,4 @@ Spree::Admin::VariantsController.class_eval do
|
||||
option_values.andand.each_value {|id| @object.option_values << OptionValue.find(id)}
|
||||
@object.save
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Allows us to use a variant_id only to look up a price estimate
|
||||
def parent_data
|
||||
return super unless action == :price_estimate
|
||||
nil
|
||||
end
|
||||
|
||||
def permissions
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
end
|
||||
|
||||
def load_price_estimate_context
|
||||
@shop = Enterprise.managed_by(spree_current_user).find_by_id(params[:shop_id])
|
||||
@schedule = permissions.editable_schedules.find_by_id(params[:schedule_id])
|
||||
@order_cycle = @schedule.andand.current_or_next_order_cycle
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,6 +9,6 @@ class Schedule < ActiveRecord::Base
|
||||
scope :with_coordinator, lambda { |enterprise| joins(:order_cycles).where('coordinator_id = ?', enterprise.id).select('DISTINCT schedules.*') }
|
||||
|
||||
def current_or_next_order_cycle
|
||||
order_cycles.order('orders_close_at ASC').first
|
||||
order_cycles.where('orders_close_at > (?)', Time.now).order('orders_close_at ASC').first
|
||||
end
|
||||
end
|
||||
|
||||
@@ -137,9 +137,6 @@ class AbilityDecorator
|
||||
end
|
||||
|
||||
can [:create], Spree::Variant
|
||||
can [:price_estimate], Spree::Variant do |variant|
|
||||
OpenFoodNetwork::Permissions.new(user).visible_products.include? variant.product
|
||||
end
|
||||
can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant|
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier
|
||||
end
|
||||
@@ -255,10 +252,11 @@ class AbilityDecorator
|
||||
|
||||
can [:create], Customer
|
||||
can [:admin, :index, :update, :destroy], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id)
|
||||
can [:admin, :new, :indicative_variant], StandingOrder
|
||||
can [:admin, :new], StandingOrder
|
||||
can [:create], StandingOrder do |standing_order|
|
||||
user.enterprises.include?(standing_order.shop)
|
||||
end
|
||||
can [:admin, :build], StandingLineItem
|
||||
end
|
||||
|
||||
def add_relationship_management_abilities(user)
|
||||
|
||||
@@ -117,6 +117,13 @@ Spree::Product.class_eval do
|
||||
end
|
||||
}
|
||||
|
||||
scope :stockable_by, lambda { |enterprise|
|
||||
return where('1=0') unless enterprise.present?
|
||||
permitted_producer_ids = EnterpriseRelationship.joins(:parent).permitting(enterprise)
|
||||
.with_permission(:add_to_order_cycle).where(enterprises: { is_primary_producer: true }).pluck(:parent_id)
|
||||
return where('spree_products.supplier_id IN (?)', [enterprise.id] | permitted_producer_ids)
|
||||
}
|
||||
|
||||
|
||||
# -- Methods
|
||||
|
||||
|
||||
@@ -42,6 +42,13 @@ Spree::Variant.class_eval do
|
||||
select('DISTINCT spree_variants.*')
|
||||
}
|
||||
|
||||
scope :in_schedule, lambda { |schedule|
|
||||
joins(exchanges: { order_cycle: :schedule}).
|
||||
merge(Exchange.outgoing).
|
||||
where(schedules: { id: schedule}).
|
||||
select('DISTINCT spree_variants.*')
|
||||
}
|
||||
|
||||
scope :for_distribution, lambda { |order_cycle, distributor|
|
||||
where('spree_variants.id IN (?)', order_cycle.variants_distributed_by(distributor))
|
||||
}
|
||||
@@ -58,6 +65,11 @@ Spree::Variant.class_eval do
|
||||
|
||||
localize_number :price, :cost_price, :weight
|
||||
|
||||
scope :stockable_by, lambda { |enterprise|
|
||||
return where("1=0") unless enterprise.present?
|
||||
joins(:product).where(spree_products: { id: Spree::Product.stockable_by(enterprise).pluck(:id) })
|
||||
}
|
||||
|
||||
# Define sope as class method to allow chaining with other scopes filtering id.
|
||||
# In Rails 3, merging two scopes on the same column will consider only the last scope.
|
||||
def self.in_distributor(distributor)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
class Api::Admin::EstimatedVariantSerializer < ActiveModel::Serializer
|
||||
attributes :variant_id, :description, :price_with_fees
|
||||
|
||||
def variant_id
|
||||
object.id
|
||||
end
|
||||
|
||||
def description
|
||||
"#{object.product.name} - #{object.full_name}"
|
||||
end
|
||||
|
||||
def price_with_fees
|
||||
(object.price + options[:fee_calculator].indexed_fees_for(object)).to_f
|
||||
end
|
||||
end
|
||||
15
app/serializers/api/admin/standing_line_item_serializer.rb
Normal file
15
app/serializers/api/admin/standing_line_item_serializer.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
class Api::Admin::StandingLineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :variant_id, :quantity, :description, :price_estimate
|
||||
|
||||
def description
|
||||
"#{object.variant.product.name} - #{object.variant.full_name}"
|
||||
end
|
||||
|
||||
def price_estimate
|
||||
if options[:fee_calculator]
|
||||
(object.variant.price + options[:fee_calculator].indexed_fees_for(object.variant)).to_f
|
||||
else
|
||||
"?"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
class Api::Admin::StandingOrderSerializer < ActiveModel::Serializer
|
||||
attributes :id, :shop_id, :customer_id, :schedule_id, :payment_method_id, :shipping_method_id, :begins_at, :ends_at
|
||||
|
||||
has_many :standing_line_items
|
||||
has_many :standing_line_items, serializer: Api::Admin::StandingLineItemSerializer
|
||||
|
||||
def begins_at
|
||||
object.begins_at.andand.strftime('%F')
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
%tbody
|
||||
%tr.item{ ng: { repeat: 'item in standingOrder.standing_line_items', class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td.price.align-center {{ item.price_with_fees | currency }}
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.qty
|
||||
%input.qty{ name: 'quantity', type: 'number', min: 0, ng: { model: 'item.quantity' } }
|
||||
%td.total.align-center {{ (item.price_with_fees * item.quantity) | currency }}
|
||||
%td.total.align-center {{ (item.price_estimate * item.quantity) | currency }}
|
||||
%td.actions
|
||||
%a.delete-resource.icon_link.with-tip.icon-trash.no-text{ data: { confirm: "Are you sure?" }, :href => "javascript:void(0)" }
|
||||
%tbody#subtotal.no-border-top{"data-hook" => "admin_order_form_subtotal"}
|
||||
|
||||
@@ -177,8 +177,10 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resources :schedules, only: [:index, :create, :update, :destroy], format: :json
|
||||
|
||||
resources :standing_orders, only: [:new, :create] do
|
||||
get :indicative_variant, on: :collection, format: :json
|
||||
resources :standing_orders, only: [:new, :create]
|
||||
|
||||
resources :standing_line_items, only: [], format: :json do
|
||||
post :build, on: :collection
|
||||
end
|
||||
end
|
||||
|
||||
@@ -292,10 +294,6 @@ Spree::Core::Engine.routes.prepend do
|
||||
get :print_ticket, on: :member
|
||||
get :managed, on: :collection
|
||||
end
|
||||
|
||||
resources :variants, only: [], format: :json do
|
||||
get :price_estimate, on: :member
|
||||
end
|
||||
end
|
||||
|
||||
resources :orders do
|
||||
|
||||
@@ -118,7 +118,10 @@ module OpenFoodNetwork
|
||||
return Spree::Variant.where("1=0") unless @order_cycle
|
||||
|
||||
if user_manages_coordinator_or(hub)
|
||||
# TODO: Use variants_stockable_by(hub) for this?
|
||||
|
||||
# Any variants produced by the coordinator, for outgoing exchanges with itself
|
||||
# TODO: isn't this completely redundant given the assignment of hub_variants below?
|
||||
coordinator_variants = []
|
||||
if hub == @coordinator
|
||||
coordinator_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', @coordinator)
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Admin::StandingLineItemsController, type: :controller do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
|
||||
describe "build" do
|
||||
let(:user) { create(:user) }
|
||||
let!(:shop) { create(:enterprise, owner: user) }
|
||||
let(:unmanaged_shop) { create(:enterprise) }
|
||||
let!(:product) { create(:product) }
|
||||
let!(:variant) { create(:variant, product: product, unit_value: '100', price: 15.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 3.50) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: shop, receiver: shop, variants: [variant], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle])}
|
||||
let(:unmanaged_schedule) { create(:schedule, order_cycles: [create(:simple_order_cycle, coordinator: unmanaged_shop)]) }
|
||||
|
||||
context "json" do
|
||||
let(:params) { { format: :json, standing_line_item: { quantity: 2, variant_id: variant.id } } }
|
||||
|
||||
context 'as an enterprise user' do
|
||||
before { allow(controller).to receive(:spree_current_user) { user } }
|
||||
|
||||
context "but no shop_id is provided" do
|
||||
it "returns an error" do
|
||||
spree_post :build, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorised']
|
||||
end
|
||||
end
|
||||
|
||||
context "and an unmanaged shop_id is provided" do
|
||||
before { params.merge!({ shop_id: unmanaged_shop.id }) }
|
||||
|
||||
it "returns an error" do
|
||||
spree_post :build, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorised']
|
||||
end
|
||||
end
|
||||
|
||||
context "where a managed shop_id is provided" do
|
||||
before { params.merge!({ shop_id: shop.id }) }
|
||||
|
||||
context "but the shop doesn't have permission to sell product in question" do
|
||||
it "returns an error" do
|
||||
spree_post :build, params
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['errors']).to eq ["#{shop.name} is not permitted to sell the selected product"]
|
||||
end
|
||||
end
|
||||
|
||||
context "and the shop has permission to sell the product in question" do
|
||||
before do
|
||||
product.update_attribute(:supplier_id, shop.id)
|
||||
end
|
||||
|
||||
context "but no schedule_id is provided" do
|
||||
it "returns a serialized standing line item without a price estimate" do
|
||||
spree_post :build, params
|
||||
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['price_estimate']).to eq '?'
|
||||
expect(json_response['quantity']).to eq 2
|
||||
expect(json_response['description']).to eq "#{variant.product.name} - 100g"
|
||||
end
|
||||
end
|
||||
|
||||
context "but an unmanaged schedule_id is provided" do
|
||||
before { params.merge!({ schedule_id: unmanaged_schedule.id }) }
|
||||
|
||||
it "returns a serialized standing line item without a price estimate" do
|
||||
spree_post :build, params
|
||||
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['price_estimate']).to eq '?'
|
||||
expect(json_response['quantity']).to eq 2
|
||||
expect(json_response['description']).to eq "#{variant.product.name} - 100g"
|
||||
end
|
||||
end
|
||||
|
||||
context "and a managed schedule_id is provided" do
|
||||
before { params.merge!({ schedule_id: schedule.id }) }
|
||||
|
||||
it "returns a serialized standing line item with a price estimate" do
|
||||
spree_post :build, params
|
||||
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['price_estimate']).to eq 18.5
|
||||
expect(json_response['quantity']).to eq 2
|
||||
expect(json_response['description']).to eq "#{variant.product.name} - 100g"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -35,88 +35,6 @@ module Spree
|
||||
assigns(:variants).should match_array [v1, v2]
|
||||
end
|
||||
end
|
||||
|
||||
describe "price_estimate" do
|
||||
let(:user) { create(:user) }
|
||||
let!(:enterprise) { create(:enterprise, owner: user) }
|
||||
let(:unmanaged_enterprise) { create(:enterprise) }
|
||||
let!(:product) { create(:product) }
|
||||
let!(:variant) { create(:variant, product: product, unit_value: '100', price: 15.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 3.50) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: enterprise, orders_open_at: 2.days.from_now, orders_close_at: 7.days.from_now) }
|
||||
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: enterprise, receiver: enterprise, variants: [variant], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle])}
|
||||
let(:unmanaged_schedule) { create(:schedule, order_cycles: [create(:simple_order_cycle, coordinator: unmanaged_enterprise)]) }
|
||||
|
||||
context "json" do
|
||||
let(:params) { { format: :json, id: variant.id } }
|
||||
|
||||
context 'as an enterprise user' do
|
||||
before { allow(controller).to receive(:spree_current_user) { user } }
|
||||
|
||||
context "where I don't have access to the product in question" do
|
||||
it "redirects to unauthorized" do
|
||||
spree_get :price_estimate, params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context "where I have access to the product in question" do
|
||||
before do
|
||||
product.update_attribute(:supplier_id, enterprise.id)
|
||||
end
|
||||
|
||||
context "but no shop_id is provided" do
|
||||
before { params.merge!({ schedule_id: schedule.id }) }
|
||||
|
||||
it "returns an error" do
|
||||
spree_get :price_estimate, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorized']
|
||||
end
|
||||
end
|
||||
|
||||
context "and an unmanaged shop_id is provided" do
|
||||
before { params.merge!({ shop_id: unmanaged_enterprise.id, schedule_id: schedule.id }) }
|
||||
|
||||
it "returns an error" do
|
||||
spree_get :price_estimate, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorized']
|
||||
end
|
||||
end
|
||||
|
||||
context "where no schedule_id is provided" do
|
||||
before { params.merge!({ shop_id: enterprise.id }) }
|
||||
|
||||
it "returns an error" do
|
||||
spree_get :price_estimate, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorized']
|
||||
end
|
||||
end
|
||||
|
||||
context "and an unmanaged schedule_id is provided" do
|
||||
before { params.merge!({ shop_id: enterprise.id, schedule_id: unmanaged_schedule.id }) }
|
||||
|
||||
it "returns an error" do
|
||||
spree_get :price_estimate, params
|
||||
expect(JSON.parse(response.body)['errors']).to eq ['Unauthorized']
|
||||
end
|
||||
end
|
||||
|
||||
context "where a managed shop_id and schedule_id are provided" do
|
||||
before { params.merge!({ shop_id: enterprise.id, schedule_id: schedule.id }) }
|
||||
|
||||
it "returns a price estimate for the variant" do
|
||||
spree_get :price_estimate, params
|
||||
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['price_with_fees']).to eq 18.5
|
||||
expect(json_response['description']).to eq "#{variant.product.name} - 100g"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,7 +141,7 @@ FactoryGirl.define do
|
||||
factory :standing_order, :class => StandingOrder do
|
||||
shop { FactoryGirl.create :enterprise }
|
||||
schedule
|
||||
customer
|
||||
customer { create(:customer, enterprise: shop) }
|
||||
payment_method
|
||||
shipping_method
|
||||
begins_at { 1.month.ago }
|
||||
|
||||
@@ -53,6 +53,14 @@ feature 'Standing Orders' do
|
||||
expect(page).to have_content 'Saved'
|
||||
}.to change(StandingOrder, :count).by(1)
|
||||
|
||||
# Prices are shown
|
||||
within 'table#standing-line-items tr.item', match: :first do
|
||||
expect(page).to have_selector 'td.description', text: "#{product.name} - #{variant.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$13.75"
|
||||
expect(page).to have_input 'quantity', with: "2"
|
||||
expect(page).to have_selector 'td.total', text: "$27.50"
|
||||
end
|
||||
|
||||
# Basic properties of standing order are set
|
||||
standing_order = StandingOrder.last
|
||||
expect(standing_order.customer).to eq customer
|
||||
|
||||
@@ -388,6 +388,26 @@ module Spree
|
||||
expect(products).to_not include new_variant.product, hidden_variant.product
|
||||
end
|
||||
end
|
||||
|
||||
describe 'stockable_by' do
|
||||
let(:shop) { create(:distributor_enterprise) }
|
||||
let(:add_to_oc_producer) { create(:supplier_enterprise) }
|
||||
let(:other_producer) { create(:supplier_enterprise) }
|
||||
let!(:p1) { create(:simple_product, supplier: shop ) }
|
||||
let!(:p2) { create(:simple_product, supplier: add_to_oc_producer ) }
|
||||
let!(:p3) { create(:simple_product, supplier: other_producer ) }
|
||||
|
||||
before do
|
||||
create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, permissions_list: [:add_to_order_cycle])
|
||||
create(:enterprise_relationship, parent: other_producer, child: shop, permissions_list: [:manage_products])
|
||||
end
|
||||
|
||||
it 'shows products produced by the enterprise and any producers granting P-OC' do
|
||||
stockable_products = Spree::Product.stockable_by(shop)
|
||||
expect(stockable_products).to include p1, p2
|
||||
expect(stockable_products).to_not include p3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "finders" do
|
||||
|
||||
@@ -165,6 +165,26 @@ module Spree
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'stockable_by' do
|
||||
let(:shop) { create(:distributor_enterprise) }
|
||||
let(:add_to_oc_producer) { create(:supplier_enterprise) }
|
||||
let(:other_producer) { create(:supplier_enterprise) }
|
||||
let!(:v1) { create(:variant, product: create(:simple_product, supplier: shop ) ) }
|
||||
let!(:v2) { create(:variant, product: create(:simple_product, supplier: add_to_oc_producer ) ) }
|
||||
let!(:v3) { create(:variant, product: create(:simple_product, supplier: other_producer ) ) }
|
||||
|
||||
before do
|
||||
create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, permissions_list: [:add_to_order_cycle])
|
||||
create(:enterprise_relationship, parent: other_producer, child: shop, permissions_list: [:manage_products])
|
||||
end
|
||||
|
||||
it 'shows variants produced by the enterprise and any producers granting P-OC' do
|
||||
stockable_variants = Spree::Variant.stockable_by(shop)
|
||||
expect(stockable_variants).to include v1, v2
|
||||
expect(stockable_variants).to_not include v3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "callbacks" do
|
||||
|
||||
Reference in New Issue
Block a user