mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-19 04:49:15 +00:00
Standing Orders can be edited
This commit is contained in:
@@ -11,7 +11,10 @@ angular.module("admin.standingOrders").controller "StandingOrderController", ($s
|
||||
|
||||
$scope.save = ->
|
||||
$scope.standing_order_form.$setPristine()
|
||||
StandingOrder.save()
|
||||
if $scope.standingOrder.id?
|
||||
StandingOrder.update()
|
||||
else
|
||||
StandingOrder.create()
|
||||
|
||||
$scope.setView = (view) -> $scope.view = view
|
||||
|
||||
@@ -22,7 +25,7 @@ angular.module("admin.standingOrders").controller "StandingOrderController", ($s
|
||||
|
||||
$scope.estimatedSubtotal = ->
|
||||
$scope.standingOrder.standing_line_items.reduce (subtotal, item) ->
|
||||
item.price_estimate * item.quantity
|
||||
subtotal += item.price_estimate * item.quantity
|
||||
, 0
|
||||
|
||||
$scope.estimatedTotal = ->
|
||||
|
||||
@@ -16,7 +16,7 @@ angular.module("admin.standingOrders").factory "StandingOrder", ($injector, $htt
|
||||
, (response) =>
|
||||
InfoDialog.open 'error', response.data.errors[0]
|
||||
|
||||
save: ->
|
||||
create: ->
|
||||
StatusMessage.display 'progress', 'Saving...'
|
||||
delete @errors[k] for k, v of @errors
|
||||
@standingOrder.$save().then (response) =>
|
||||
@@ -24,3 +24,12 @@ angular.module("admin.standingOrders").factory "StandingOrder", ($injector, $htt
|
||||
, (response) =>
|
||||
StatusMessage.display 'failure', 'Oh no! I was unable to save your changes.'
|
||||
angular.extend(@errors, response.data.errors)
|
||||
|
||||
update: ->
|
||||
StatusMessage.display 'progress', 'Saving...'
|
||||
delete @errors[k] for k, v of @errors
|
||||
@standingOrder.$update().then (response) =>
|
||||
StatusMessage.display 'success', 'Saved'
|
||||
, (response) =>
|
||||
StatusMessage.display 'failure', 'Oh no! I was unable to save your changes.'
|
||||
angular.extend(@errors, response.data.errors)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
angular.module("admin.standingOrders").factory 'StandingOrderResource', ($resource) ->
|
||||
$resource('/admin/standing_orders/:action.json', {}, {
|
||||
$resource('/admin/standing_orders/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'create':
|
||||
method: 'POST'
|
||||
'update':
|
||||
method: 'PUT'
|
||||
params:
|
||||
id: '@id'
|
||||
})
|
||||
|
||||
@@ -12,4 +12,8 @@ input[type='button'], input[type='submit'] {
|
||||
|
||||
.select2-container-disabled {
|
||||
pointer-events: none;
|
||||
|
||||
.select2-choice > .select2-chosen {
|
||||
color: #a1a1a1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,17 +2,19 @@ require 'open_food_network/permissions'
|
||||
|
||||
module Admin
|
||||
class StandingOrdersController < ResourceController
|
||||
before_filter :load_shop, only: [:new]
|
||||
before_filter :load_shops, only: [:index]
|
||||
before_filter :wrap_nested_attrs, only: [:create]
|
||||
before_filter :load_form_data, only: [:new, :edit]
|
||||
before_filter :strip_banned_attrs, only: [:update]
|
||||
before_filter :wrap_nested_attrs, only: [:create, :update]
|
||||
respond_to :json
|
||||
|
||||
respond_override create: { json: {
|
||||
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
|
||||
},
|
||||
success: lambda { render_as_json @standing_order, fee_calculator: fee_calculator },
|
||||
failure: lambda { render json: { errors: json_errors }, status: :unprocessable_entity }
|
||||
} }
|
||||
|
||||
respond_override update: { json: {
|
||||
success: lambda { render_as_json @standing_order, fee_calculator: fee_calculator },
|
||||
failure: lambda { render json: { errors: json_errors }, status: :unprocessable_entity }
|
||||
} }
|
||||
|
||||
@@ -24,13 +26,8 @@ module Admin
|
||||
end
|
||||
|
||||
def new
|
||||
@standing_order.shop = @shop
|
||||
@standing_order.bill_address = Spree::Address.new
|
||||
@standing_order.ship_address = Spree::Address.new
|
||||
@customers = Customer.of(@shop)
|
||||
@schedules = Schedule.with_coordinator(@shop)
|
||||
@payment_methods = Spree::PaymentMethod.for_distributor(@shop)
|
||||
@shipping_methods = Spree::ShippingMethod.for_distributor(@shop)
|
||||
end
|
||||
|
||||
private
|
||||
@@ -49,14 +46,24 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def load_shop
|
||||
@shop = Enterprise.find(params[:shop_id])
|
||||
end
|
||||
|
||||
def load_shops
|
||||
@shops = Enterprise.managed_by(spree_current_user).is_distributor
|
||||
end
|
||||
|
||||
def load_form_data
|
||||
@customers = Customer.of(@standing_order.shop)
|
||||
@schedules = Schedule.with_coordinator(@standing_order.shop)
|
||||
@payment_methods = Spree::PaymentMethod.for_distributor(@standing_order.shop)
|
||||
@shipping_methods = Spree::ShippingMethod.for_distributor(@standing_order.shop)
|
||||
@fee_calculator = fee_calculator
|
||||
end
|
||||
|
||||
def fee_calculator
|
||||
shop, next_oc = @standing_order.shop, @standing_order.schedule.andand.current_or_next_order_cycle
|
||||
return nil unless shop && next_oc
|
||||
OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, next_oc)
|
||||
end
|
||||
|
||||
def json_errors
|
||||
@object.errors.messages.inject({}) do |errors, (k,v)|
|
||||
errors[k] = v.map{ |msg| @object.errors.full_message(k,msg) }
|
||||
@@ -80,10 +87,15 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def strip_banned_attrs
|
||||
params[:standing_order].delete :schedule_id
|
||||
params[:standing_order].delete :customer_id
|
||||
end
|
||||
|
||||
# Overriding Spree method to load data from params here so that
|
||||
# we can authorise #create using an object with required attributes
|
||||
def build_resource
|
||||
StandingOrder.new(shop_id: params[:standing_order].andand[:shop_id])
|
||||
StandingOrder.new(params[:standing_order])
|
||||
end
|
||||
|
||||
def ams_prefix_whitelist
|
||||
|
||||
@@ -120,7 +120,7 @@ module Admin
|
||||
end
|
||||
|
||||
def admin_inject_json_ams(ngModule, name, data, serializer, opts = {})
|
||||
json = serializer.new(data, scope: spree_current_user).to_json
|
||||
json = serializer.new(data, {scope: spree_current_user}.merge(opts)).to_json
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: ngModule, name: name, json: json}
|
||||
end
|
||||
|
||||
|
||||
@@ -253,7 +253,7 @@ class AbilityDecorator
|
||||
can [:create], Customer
|
||||
can [:admin, :index, :update, :destroy], Customer, enterprise_id: Enterprise.managed_by(user).pluck(:id)
|
||||
can [:admin, :new, :index], StandingOrder
|
||||
can [:create], StandingOrder do |standing_order|
|
||||
can [:create, :edit, :update], StandingOrder do |standing_order|
|
||||
user.enterprises.include?(standing_order.shop)
|
||||
end
|
||||
can [:admin, :build], StandingLineItem
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Api::Admin::IndexStandingOrderSerializer < ActiveModel::Serializer
|
||||
attributes :id, :item_count, :begins_on, :ends_on
|
||||
attributes :id, :item_count, :begins_on, :ends_on, :edit_path
|
||||
|
||||
has_one :shop, serializer: Api::Admin::IdNameSerializer
|
||||
has_one :customer, serializer: Api::Admin::IdEmailSerializer # Remove IdEmailSerializer if no longer user here
|
||||
@@ -19,4 +19,8 @@ class Api::Admin::IndexStandingOrderSerializer < ActiveModel::Serializer
|
||||
def ends_on
|
||||
object.ends_at.andand.strftime('%a, %b %d, %Y') || I18n.t(:ongoing)
|
||||
end
|
||||
|
||||
def edit_path
|
||||
edit_admin_standing_order_path(object)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= admin_inject_json_ams "admin.standingOrders", "standingOrder", @standing_order, Api::Admin::StandingOrderSerializer if @standing_order
|
||||
= admin_inject_json_ams "admin.standingOrders", "standingOrder", @standing_order, Api::Admin::StandingOrderSerializer, fee_calculator: @fee_calculator if @standing_order
|
||||
= admin_inject_json_ams_array "admin.standingOrders", "shops", @shops, Api::Admin::IdNameSerializer if @shops
|
||||
= admin_inject_json_ams_array "admin.standingOrders", "customers", @customers, Api::Admin::IdEmailSerializer if @customers
|
||||
= admin_inject_json_ams_array "admin.standingOrders", "schedules", @schedules, Api::Admin::IdNameSerializer if @schedules
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
.row
|
||||
.seven.columns.alpha.field
|
||||
%label{ for: 'customer_id'}= t('admin.customer')
|
||||
%input.ofn-select2.fullwidth#customer_id{ name: 'customer_id', type: 'number', data: 'customers', text: 'email', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.customer_id' } }
|
||||
%input.ofn-select2.fullwidth#customer_id{ name: 'customer_id', type: 'number', data: 'customers', text: 'email', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.customer_id', disabled: 'standingOrder.id' } }
|
||||
.error{ ng: { show: 'submitted && standing_order_details_form.customer_id.$error.required' } }= t(:error_required)
|
||||
.error{ ng: { repeat: 'error in errors.customer', show: 'standing_order_details_form.customer_id.$pristine' } } {{ error }}
|
||||
.two.columns
|
||||
.seven.columns.omega.field
|
||||
%label{ for: 'schedule_id'}= t('admin.schedule')
|
||||
%input.ofn-select2.fullwidth#schedule_id{ name: 'schedule_id', type: 'number', data: 'schedules', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.schedule_id' } }
|
||||
%input.ofn-select2.fullwidth#schedule_id{ name: 'schedule_id', type: 'number', data: 'schedules', required: true, placeholder: t('admin.choose'), ng: { model: 'standingOrder.schedule_id', disabled: 'standingOrder.id' } }
|
||||
.error{ ng: { show: 'submitted && standing_order_details_form.schedule_id.$error.required' } }= t(:error_required)
|
||||
.error{ ng: { repeat: 'error in errors.schedule', show: 'standing_order_details_form.schedule_id.$pristine'} } {{ error }}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
%form.margin-bottom-50{ name: 'standing_order_form', novalidate: true, ng: { submit: 'save()' } }
|
||||
%save-bar{ dirty: "standing_order_form.$dirty", persist: 'true', ng: { show: "view == 'review'" } }
|
||||
%input.red{ type: "submit", value: t('admin.standing_orders.create') }
|
||||
%input.red{ type: "submit", ng: { value: "standingOrder.id ? '#{t(:save_changes)}' : '#{t('admin.standing_orders.create')}'" } }
|
||||
|
||||
.details{ ng: { show: "['details','review'].indexOf(view) >= 0" } }
|
||||
%ng-form{ name: 'standing_order_details_form', ng: { controller: 'DetailsController' } }
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
%span= t(:total)
|
||||
%th.orders-actions.actions
|
||||
%tbody
|
||||
%tr.item{ ng: { repeat: 'item in standingOrder.standing_line_items', class: { even: 'even', odd: 'odd' } } }
|
||||
%tr.item{ id: "sli_{{$index}}", ng: { repeat: 'item in standingOrder.standing_line_items', class: { even: 'even', odd: 'odd' } } }
|
||||
%td.description {{ item.description }}
|
||||
%td.price.align-center {{ item.price_estimate | currency }}
|
||||
%td.qty
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%col.ends_on{ width: "15%", 'ng-show' => 'columns.ends_on.visible' }
|
||||
%col.payment_method{ width: "20%", 'ng-show' => 'columns.payment_method.visible' }
|
||||
%col.shipping_method{ width: "20%", 'ng-show' => 'columns.shipping_method.visible' }
|
||||
-# %col.actions
|
||||
%col.actions{ width: "5%" }
|
||||
%thead
|
||||
%tr
|
||||
-# %th.bulk
|
||||
@@ -25,8 +25,8 @@
|
||||
= t('admin.payment_method')
|
||||
%th.shipping_method{ ng: { show: 'columns.shipping_method.visible', } }
|
||||
= t('admin.shipping_method')
|
||||
-# %th.actions
|
||||
-#
|
||||
%th.actions
|
||||
|
||||
%tr.standing_order{ :id => "so_{{standingOrder.id}}", ng: { repeat: "standingOrder in standingOrders | filter:query", class: { even: "'even'", odd: "'odd'" } } }
|
||||
%td.customer.text-center{ ng: { show: 'columns.customer.visible', bind: '::standingOrder.customer.email' } }
|
||||
%td.schedule.text-center{ ng: { show: 'columns.schedule.visible', bind: '::standingOrder.schedule.name' } }
|
||||
@@ -35,6 +35,6 @@
|
||||
%td.ends_on.text-center{ ng: { show: 'columns.ends_on.visible', bind: '::standingOrder.ends_on' } }
|
||||
%td.payment_method{ ng: { show: 'columns.payment_method.visible', bind: '::standingOrder.payment_method.name' } }
|
||||
%td.shipping_method{ ng: { show: 'columns.shipping_method.visible', bind: '::standingOrder.shipping_method.name' } }
|
||||
-# %td.actions
|
||||
-# %a.edit-standing-order.icon-edit.no-text{ ng: { href: '{{standingOrder.edit_path}}'} }
|
||||
%td.actions
|
||||
%a.edit-standing-order.icon-edit.no-text{ ng: { href: '{{standingOrder.edit_path}}'} }
|
||||
-# %a.delete-standing-order.icon-trash.no-text{ ng: { href: '{{standingOrder.delete_path}}'}, data: { method: 'delete', confirm: "Are you sure?" } }
|
||||
|
||||
9
app/views/admin/standing_orders/edit.html.haml
Normal file
9
app/views/admin/standing_orders/edit.html.haml
Normal file
@@ -0,0 +1,9 @@
|
||||
- content_for :page_title do
|
||||
=t('admin.standing_orders.edit')
|
||||
|
||||
-# - content_for :page_actions do
|
||||
-# %li= button_link_to "Back to standing orders list", main_app.admin_standing_orders_path, icon: 'icon-arrow-left'
|
||||
|
||||
%div{ ng: { app: 'admin.standingOrders', controller: 'StandingOrderController', cloak: true } }
|
||||
= render 'data'
|
||||
= render 'form'
|
||||
@@ -177,7 +177,7 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resources :schedules, only: [:index, :create, :update, :destroy], format: :json
|
||||
|
||||
resources :standing_orders, only: [:index, :new, :create]
|
||||
resources :standing_orders, only: [:index, :new, :create, :edit, :update]
|
||||
|
||||
resources :standing_line_items, only: [], format: :json do
|
||||
post :build, on: :collection
|
||||
|
||||
@@ -87,8 +87,7 @@ describe Admin::StandingOrdersController, type: :controller do
|
||||
end
|
||||
|
||||
it 'loads the preloads the necessary data' do
|
||||
spree_get :new, shop_id: shop.id
|
||||
expect(assigns(:shop)).to eq shop
|
||||
spree_get :new, standing_order: { shop_id: shop.id }
|
||||
expect(assigns(:standing_order)).to be_a_new StandingOrder
|
||||
expect(assigns(:standing_order).shop).to eq shop
|
||||
expect(assigns(:customers)).to include customer1, customer2
|
||||
@@ -214,4 +213,163 @@ describe Admin::StandingOrdersController, type: :controller do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'edit' do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:shop) { create(:distributor_enterprise, owner: user) }
|
||||
let!(:customer1) { create(:customer, enterprise: shop) }
|
||||
let!(:customer2) { create(:customer, enterprise: shop) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
let!(:standing_order) { create(:standing_order,
|
||||
shop: shop,
|
||||
customer: customer1,
|
||||
schedule: schedule,
|
||||
payment_method: payment_method,
|
||||
shipping_method: shipping_method
|
||||
) }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
it 'loads the preloads the necessary data' do
|
||||
spree_get :edit, id: standing_order.id
|
||||
expect(assigns(:standing_order)).to eq standing_order
|
||||
expect(assigns(:customers)).to include customer1, customer2
|
||||
expect(assigns(:schedules)).to eq [schedule]
|
||||
expect(assigns(:payment_methods)).to eq [payment_method]
|
||||
expect(assigns(:shipping_methods)).to eq [shipping_method]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'update' do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:shop) { create(:distributor_enterprise, owner: user) }
|
||||
let!(:customer) { create(:customer, enterprise: shop) }
|
||||
let!(:product1) { create(:product, supplier: shop) }
|
||||
let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
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: [variant1], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
let!(:standing_order) { create(:standing_order,
|
||||
shop: shop,
|
||||
customer: customer,
|
||||
schedule: schedule,
|
||||
payment_method: payment_method,
|
||||
shipping_method: shipping_method,
|
||||
standing_line_items: [create(:standing_line_item, variant: variant1, quantity: 2)]
|
||||
) }
|
||||
let(:standing_line_item1) { standing_order.standing_line_items.first}
|
||||
let(:params) { { format: :json, id: standing_order.id, standing_order: {} } }
|
||||
|
||||
context 'as an non-manager of the standing order shop' do
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { create(:user, enterprises: [create(:enterprise)]) }
|
||||
end
|
||||
|
||||
it 'redirects to unauthorized' do
|
||||
spree_post :update, params
|
||||
expect(response).to redirect_to spree.unauthorized_path
|
||||
end
|
||||
end
|
||||
|
||||
context 'as a manager of the standing_order shop' do
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { user }
|
||||
end
|
||||
|
||||
context 'when I submit params containing a new customer or schedule id' do
|
||||
let!(:new_customer) { create(:customer, enterprise: shop) }
|
||||
let!(:new_schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
|
||||
before do
|
||||
params[:standing_order].merge!({ schedule_id: new_schedule.id, customer_id: new_customer.id})
|
||||
end
|
||||
|
||||
it 'does not alter customer_id or schedule_id' do
|
||||
spree_post :update, params
|
||||
standing_order.reload
|
||||
expect(standing_order.customer).to eq customer
|
||||
expect(standing_order.schedule).to eq schedule
|
||||
end
|
||||
end
|
||||
|
||||
context 'when I submit params containing ids of inaccessible objects' do
|
||||
# As 'user' I shouldnt be able to associate a standing_order with any of these.
|
||||
let(:unmanaged_enterprise) { create(:enterprise) }
|
||||
let(:unmanaged_payment_method) { create(:payment_method, distributors: [unmanaged_enterprise]) }
|
||||
let(:unmanaged_shipping_method) { create(:shipping_method, distributors: [unmanaged_enterprise]) }
|
||||
|
||||
before do
|
||||
params[:standing_order].merge!({
|
||||
payment_method_id: unmanaged_payment_method.id,
|
||||
shipping_method_id: unmanaged_shipping_method.id,
|
||||
})
|
||||
end
|
||||
|
||||
it 'returns errors' do
|
||||
expect{ spree_post :update, params }.to_not change{StandingOrder.count}
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['errors'].keys).to include 'payment_method', 'shipping_method'
|
||||
standing_order.reload
|
||||
expect(standing_order.payment_method).to eq payment_method
|
||||
expect(standing_order.shipping_method).to eq shipping_method
|
||||
end
|
||||
end
|
||||
|
||||
context 'when I submit valid params' do
|
||||
let!(:new_payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:new_shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
|
||||
before do
|
||||
params[:standing_order].merge!({payment_method_id: new_payment_method.id, shipping_method_id: new_shipping_method.id})
|
||||
end
|
||||
|
||||
it 'updates the standing order' do
|
||||
spree_post :update, params
|
||||
standing_order.reload
|
||||
expect(standing_order.schedule).to eq schedule
|
||||
expect(standing_order.customer).to eq customer
|
||||
expect(standing_order.payment_method).to eq new_payment_method
|
||||
expect(standing_order.shipping_method).to eq new_shipping_method
|
||||
end
|
||||
|
||||
context 'with standing_line_items params' do
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
|
||||
before do
|
||||
params[:standing_line_items] = [{id: standing_line_item1.id, quantity: 1, variant_id: variant1.id}, { quantity: 2, variant_id: variant2.id}]
|
||||
end
|
||||
|
||||
context 'where the specified variants are not available from the shop' do
|
||||
it 'returns an error' do
|
||||
expect{ spree_post :update, params }.to_not change{standing_order.standing_line_items.count}
|
||||
json_response = JSON.parse(response.body)
|
||||
expect(json_response['errors']['base']).to eq ["#{product2.name} - #{variant2.full_name} is not available from the selected schedule"]
|
||||
end
|
||||
end
|
||||
|
||||
context 'where the specified variants are available from the shop' do
|
||||
before { outgoing_exchange.update_attributes(variants: [variant1, variant2]) }
|
||||
|
||||
it 'creates standing line items for the standing order' do
|
||||
expect{ spree_post :update, params }.to change{standing_order.standing_line_items.count}.by(1)
|
||||
standing_order.reload
|
||||
expect(standing_order.standing_line_items.count).to be 2
|
||||
standing_line_item = standing_order.standing_line_items.last
|
||||
expect(standing_line_item.quantity).to be 2
|
||||
expect(standing_line_item.variant).to eq variant2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -149,6 +149,12 @@ FactoryGirl.define do
|
||||
begins_at { 1.month.ago }
|
||||
end
|
||||
|
||||
factory :standing_line_item, :class => StandingLineItem do
|
||||
standing_order
|
||||
variant
|
||||
quantity 1
|
||||
end
|
||||
|
||||
factory :variant_override, :class => VariantOverride do
|
||||
price 77.77
|
||||
count_on_hand 11111
|
||||
|
||||
@@ -72,7 +72,7 @@ feature 'Standing Orders' do
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
|
||||
it "passes the smoke test" do
|
||||
visit new_admin_standing_order_path(shop_id: shop.id)
|
||||
visit new_admin_standing_order_path(standing_order: { shop_id: shop.id })
|
||||
|
||||
select2_select customer.email, from: 'customer_id'
|
||||
select2_select schedule.name, from: 'schedule_id'
|
||||
@@ -148,6 +148,62 @@ feature 'Standing Orders' do
|
||||
expect(standing_line_item.variant).to eq variant
|
||||
expect(standing_line_item.quantity).to eq 2
|
||||
end
|
||||
|
||||
context 'editing an existing standing order' do
|
||||
let!(:customer) { create(:customer, enterprise: shop) }
|
||||
let!(:product1) { create(:product, supplier: shop) }
|
||||
let!(:product2) { create(:product, supplier: shop) }
|
||||
let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) }
|
||||
let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) }
|
||||
let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) }
|
||||
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: [variant1, variant2], enterprise_fees: [enterprise_fee]) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [shop]) }
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [shop]) }
|
||||
let!(:standing_order) { create(:standing_order,
|
||||
shop: shop,
|
||||
customer: customer,
|
||||
schedule: schedule,
|
||||
payment_method: payment_method,
|
||||
shipping_method: shipping_method,
|
||||
standing_line_items: [create(:standing_line_item, variant: variant1, quantity: 2)]
|
||||
) }
|
||||
|
||||
it "passes the smoke test" do
|
||||
visit edit_admin_standing_order_path(standing_order)
|
||||
|
||||
# Customer and Schedule cannot be edited
|
||||
expect(page).to have_selector '#s2id_customer_id.select2-container-disabled'
|
||||
expect(page).to have_selector '#s2id_schedule_id.select2-container-disabled'
|
||||
|
||||
# Existing products should be visible
|
||||
within "#sli_0" do
|
||||
expect(page).to have_selector 'td.description', text: "#{product1.name} - #{variant1.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
|
||||
|
||||
# Add variant2 to the standing order
|
||||
targetted_select2_search product2.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
|
||||
fill_in 'add_quantity', with: 1
|
||||
click_link 'Add'
|
||||
within "#sli_1" do
|
||||
expect(page).to have_selector 'td.description', text: "#{product2.name} - #{variant2.full_name}"
|
||||
expect(page).to have_selector 'td.price', text: "$7.75"
|
||||
expect(page).to have_input 'quantity', with: "1"
|
||||
expect(page).to have_selector 'td.total', text: "$7.75"
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page).to have_content 'Saved'
|
||||
|
||||
# Total should be $35.25
|
||||
expect(page).to have_selector '#order_form_total', text: "$35.25"
|
||||
expect(standing_order.reload.standing_line_items.length).to eq 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user