Merge pull request #7623 from Matt-Yorkley/order-contents

Use OrderContents to update line items
This commit is contained in:
Matt-Yorkley
2021-06-05 17:11:45 +02:00
committed by GitHub
30 changed files with 526 additions and 427 deletions

View File

@@ -1,9 +1,5 @@
Darkswarm.controller "ShopVariantCtrl", ($scope, $modal, Cart) ->
$scope.$watchGroup [
'variant.line_item.quantity',
'variant.line_item.max_quantity'
], (new_value, old_value) ->
return if old_value[0] == null && new_value[0] == null
$scope.updateCart = (line_item) ->
Cart.adjust($scope.variant.line_item)
$scope.variant.line_item.quantity ||= 0
@@ -44,10 +40,12 @@ Darkswarm.controller "ShopVariantCtrl", ($scope, $modal, Cart) ->
$scope.add = (quantity) ->
item = $scope.variant.line_item
item.quantity = $scope.sanitizedQuantity() + quantity
$scope.updateCart(item)
$scope.addMax = (quantity) ->
item = $scope.variant.line_item
item.max_quantity = $scope.sanitizedMaxQuantity() + quantity
$scope.updateCart(item)
$scope.canAdd = (quantity) ->
wantedQuantity = $scope.sanitizedQuantity() + quantity

View File

@@ -32,10 +32,7 @@ module Admin
# See https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/locking/pessimistic.rb#L69
# and https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE
order.with_lock do
if @line_item.update(line_item_params)
order.update_line_item_fees! @line_item
order.update_order_fees!
order.update_order!
if order.contents.update_item(@line_item, line_item_params)
render body: nil, status: :no_content # No Content, does not trigger ng resource auto-update
else
render json: { errors: @line_item.errors }, status: :precondition_failed
@@ -49,7 +46,7 @@ module Admin
load_line_item
authorize! :update, order
@line_item.destroy
order.contents.remove(@line_item.variant)
render body: nil, status: :no_content # No Content, does not trigger ng resource auto-update
end
@@ -63,16 +60,9 @@ module Admin
Spree::LineItem
end
# Returns the appropriate serializer for this controller
#
# @return [Api::Admin::LineItemSerializer]
def serializer(_ams_prefix)
Api::Admin::LineItemSerializer
end
def serialized_line_items
ActiveModel::ArraySerializer.new(
@line_items, each_serializer: serializer(nil)
@line_items, each_serializer: Api::Admin::LineItemSerializer
)
end

View File

@@ -81,7 +81,6 @@ module Api
quantity = params[:quantity].to_i
@order.contents.remove(variant, quantity, @shipment)
@order.recreate_all_fees!
@shipment.reload if @shipment.persisted?
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok

View File

@@ -3,33 +3,28 @@ class CartController < BaseController
def populate
order = current_order(true)
cart_service = CartService.new(order)
cart_service.populate(params.slice(:variants, :quantity), true)
if cart_service.valid?
if cart_service.populate(params.slice(:variants, :quantity))
order.cap_quantity_at_stock!
order.recreate_all_fees!
variant_ids = variant_ids_in(cart_service.variants_h)
render json: { error: false,
stock_levels: VariantsStockLevels.new.call(order, variant_ids) },
status: :ok
render json: { error: false, stock_levels: stock_levels(order) }, status: :ok
else
render json: { error: cart_service.errors.full_messages.join(",") },
status: :precondition_failed
end
populate_variant_attributes
end
def variant_ids_in(variants_h)
variants_h.map { |v| v[:variant_id].to_i }
end
private
def stock_levels(order)
variants_in_cart = order.line_items.pluck(:variant_id)
variants_in_request = raw_params[:variants]&.map(&:first) || []
VariantsStockLevels.new.call(order, (variants_in_cart + variants_in_request).uniq)
end
def check_authorization
session[:access_token] ||= params[:token]
order = Spree::Order.find_by(number: params[:id]) || current_order
@@ -40,26 +35,4 @@ class CartController < BaseController
authorize! :create, Spree::Order
end
end
def populate_variant_attributes
order = current_order.reload
populate_variant_attributes_from_variant(order) if params.key? :variant_attributes
populate_variant_attributes_from_product(order) if params.key? :quantity
end
def populate_variant_attributes_from_variant(order)
params[:variant_attributes].each do |variant_id, attributes|
permitted = attributes.permit(:quantity, :max_quantity).to_h.with_indifferent_access
order.set_variant_attributes(Spree::Variant.find(variant_id), permitted)
end
end
def populate_variant_attributes_from_product(order)
params[:products].each do |_product_id, variant_id|
max_quantity = params[:max_quantity].to_i
order.set_variant_attributes(Spree::Variant.find(variant_id),
max_quantity: max_quantity)
end
end
end

View File

@@ -39,12 +39,8 @@ class LineItemsController < BaseController
def destroy_with_lock(item)
order = item.order
order.with_lock do
item.destroy
order.update_shipping_fees!
order.contents.remove(item.variant)
order.update_payment_fees!
order.update_order_fees!
order.update_order!
order.create_tax_charge!
end
end
end

View File

@@ -38,17 +38,6 @@ module Spree
redirect_to main_app.cart_path
end
def check_authorization
session[:access_token] ||= params[:token]
order = Spree::Order.find_by(number: params[:id]) || current_order
if order
authorize! :edit, order, session[:access_token]
else
authorize! :create, Spree::Order
end
end
# Patching to redirect to shop if order is empty
def edit
@order = current_order(true)
@@ -77,14 +66,10 @@ module Spree
# This action is called either from the cart page when the order is not yet complete, or from
# the edit order page (frontoffice) if the hub allows users to update completed orders.
# This line item updating logic should probably be handled through CartService#populate.
if @order.update(order_params)
discard_empty_line_items
if @order.contents.update_cart(order_params)
@order.recreate_all_fees! # Enterprise fees on line items and on the order itself
if @order.complete?
@order.update_shipping_fees!
@order.update_payment_fees!
@order.create_tax_charge!
end
@@ -109,23 +94,6 @@ module Spree
end
end
def set_current_order
@order = current_order(true)
end
def filter_order_params
if params[:order] && params[:order][:line_items_attributes]
params[:order][:line_items_attributes] =
remove_missing_line_items(params[:order][:line_items_attributes])
end
end
def remove_missing_line_items(attrs)
attrs.select do |_i, line_item|
Spree::LineItem.find_by(id: line_item[:id])
end
end
def cancel
@order = Spree::Order.find_by!(number: params[:id])
authorize! :cancel, @order
@@ -140,6 +108,21 @@ module Spree
private
def set_current_order
@order = current_order(true)
end
def check_authorization
session[:access_token] ||= params[:token]
order = Spree::Order.find_by(number: params[:id]) || current_order
if order
authorize! :edit, order, session[:access_token]
else
authorize! :create, Spree::Order
end
end
# Stripe can redirect here after a payment is processed in the backoffice.
# We verify if it was successful here and persist the changes.
def handle_stripe_response
@@ -153,6 +136,19 @@ module Spree
@order.reload
end
def filter_order_params
if params[:order] && params[:order][:line_items_attributes]
params[:order][:line_items_attributes] =
remove_missing_line_items(params[:order][:line_items_attributes])
end
end
def remove_missing_line_items(attrs)
attrs.select do |_i, line_item|
Spree::LineItem.find_by(id: line_item[:id])
end
end
def discard_empty_line_items
@order.line_items = @order.line_items.select { |li| li.quantity > 0 }
end

View File

@@ -230,7 +230,6 @@ module Spree
# update the order totals, etc.
order.create_tax_charge!
order.update_order!
end
def update_inventory_before_destroy

View File

@@ -35,7 +35,7 @@ module Spree
alias_attribute :shipping_address, :ship_address
has_many :state_changes, as: :stateful
has_many :line_items, -> { order('created_at ASC') }, dependent: :destroy
has_many :line_items, -> { order('created_at ASC') }, class_name: "Spree::LineItem", dependent: :destroy
has_many :payments, dependent: :destroy
has_many :return_authorizations, dependent: :destroy, inverse_of: :order
has_many :adjustments, -> { order "#{Spree::Adjustment.table_name}.created_at ASC" },
@@ -243,63 +243,11 @@ module Spree
return_authorizations.any?(&:authorized?)
end
# This is currently used when adding a variant to an order in the BackOffice.
# Spree::OrderContents#add is equivalent but slightly different from add_variant below.
# OrderContents should always be used when modifying an order's line items
def contents
@contents ||= Spree::OrderContents.new(self)
end
# This is currently used when adding a variant to an order in the FrontOffice.
# This add_variant is equivalent but slightly different from Spree::OrderContents#add above.
# Spree::OrderContents#add is the more modern version in Spree history
# but this add_variant has been customized for OFN FrontOffice.
def add_variant(variant, quantity = 1, max_quantity = nil, currency = nil)
line_items.reload
current_item = find_line_item_by_variant(variant)
# Notify bugsnag if we get line items with a quantity of zero
if quantity == 0
Bugsnag.notify(RuntimeError.new("Zero Quantity Line Item"),
current_item: current_item.as_json,
line_items: line_items.map(&:id),
variant: variant.as_json)
end
if current_item
current_item.quantity = quantity
current_item.max_quantity = max_quantity
current_item.currency = currency unless currency.nil?
current_item.save
else
current_item = Spree::LineItem.new(quantity: quantity, max_quantity: max_quantity)
current_item.variant = variant
if currency
current_item.currency = currency unless currency.nil?
current_item.price = variant.price_in(currency).amount
else
current_item.price = variant.price
end
line_items << current_item
end
reload
current_item
end
def set_variant_attributes(variant, attributes)
line_item = find_line_item_by_variant(variant)
return unless line_item
if attributes.key?(:max_quantity) && attributes[:max_quantity].to_i < line_item.quantity
attributes[:max_quantity] = line_item.quantity
end
line_item.assign_attributes(attributes)
line_item.save!
end
# Associates the specified user with the order.
def associate_user!(user)
self.user = user
@@ -517,6 +465,16 @@ module Spree
shipments
end
# Clear shipments and move order back to address state unless compete. This is relevant where
# an order is part-way through checkout and the user changes items in the cart; in that case
# we need to reset the checkout flow to ensure the order is processed correctly.
def ensure_updated_shipments
if !self.completed? && shipments.any?
shipments.destroy_all
restart_checkout_flow
end
end
def refresh_shipment_rates
shipments.map(&:refresh_rates)
end
@@ -580,12 +538,6 @@ module Spree
save!
end
def remove_variant(variant)
line_items.reload
current_item = find_line_item_by_variant(variant)
current_item.andand.destroy
end
def cap_quantity_at_stock!
line_items.includes(variant: :stock_items).find_each(&:cap_quantity_at_stock!)
end
@@ -749,7 +701,7 @@ module Spree
return if adjustment.finalized?
adjustment.update_adjustment!(force: true)
update_order!
updater.update_totals_and_states
end
# object_params sets the payment amount to the order total, but it does this

View File

@@ -130,6 +130,13 @@ module Spree
steps << "complete" unless steps.include?("complete")
steps
end
def restart_checkout_flow
update_columns(
state: checkout_steps.first,
updated_at: Time.zone.now,
)
end
end
end
end

View File

@@ -11,25 +11,79 @@ module Spree
# Get current line item for variant if exists
# Add variant qty to line_item
def add(variant, quantity = 1, shipment = nil)
line_item = order.find_line_item_by_variant(variant)
add_to_line_item(line_item, variant, quantity, shipment)
line_item = add_to_line_item(variant, quantity, shipment)
update_shipment(shipment)
update_order
line_item
end
# Get current line item for variant
# Remove variant qty from line_item
def remove(variant, quantity = 1, shipment = nil)
line_item = order.find_line_item_by_variant(variant)
def remove(variant, quantity = nil, shipment = nil)
line_item = remove_from_line_item(variant, quantity, shipment)
update_shipment(shipment)
order.update_order_fees! if order.completed?
update_order
line_item
end
unless line_item
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
def update_or_create(variant, attributes)
line_item = find_line_item_by_variant(variant)
if line_item
line_item.update(attributes)
else
line_item = Spree::LineItem.new(attributes)
line_item.variant = variant
line_item.price = variant.price
order.line_items << line_item
end
remove_from_line_item(line_item, variant, quantity, shipment)
order.reload
line_item
end
def update_cart(params)
if order.update_attributes(params)
discard_empty_line_items
update_shipment
update_order
true
else
false
end
end
def update_item(line_item, params)
if line_item.update_attributes(params)
discard_empty_line_items
order.update_line_item_fees! line_item
order.update_order_fees! if order.completed?
update_shipment
update_order
true
else
false
end
end
private
def add_to_line_item(line_item, variant, quantity, shipment = nil)
def discard_empty_line_items
order.line_items = order.line_items.select {|li| li.quantity.positive? }
end
def update_shipment(target_shipment = nil)
if order.completed? || target_shipment.present?
order.update_shipping_fees!
else
order.ensure_updated_shipments
end
end
def add_to_line_item(variant, quantity, shipment = nil)
line_item = find_line_item_by_variant(variant)
if line_item
line_item.target_shipment = shipment
line_item.quantity += quantity.to_i
@@ -40,23 +94,37 @@ module Spree
end
line_item.save
order.reload
line_item
end
def remove_from_line_item(line_item, _variant, quantity, shipment = nil)
line_item.quantity += -quantity
def remove_from_line_item(variant, quantity, shipment = nil)
line_item = find_line_item_by_variant(variant, true)
quantity.present? ? line_item.quantity += -quantity : line_item.quantity = 0
line_item.target_shipment = shipment
if line_item.quantity == 0
Spree::OrderInventory.new(order).verify(line_item, shipment)
line_item.destroy
else
line_item.save!
end
order.reload
line_item
end
def find_line_item_by_variant(variant, raise_error = false)
line_item = order.find_line_item_by_variant(variant)
if !line_item.present? && raise_error
raise ActiveRecord::RecordNotFound, "Line item not found for variant #{variant.sku}"
end
line_item
end
def update_order
order.update_order!
order.reload
end
end
end

View File

@@ -160,10 +160,6 @@ module Spree
Spree::Money.new(item_cost, currency: currency)
end
def editable_by?(_user)
!shipped?
end
def update_amounts
return unless fee_adjustment&.amount != cost
@@ -187,14 +183,6 @@ module Spree
@scoper ||= OpenFoodNetwork::ScopeVariantToHub.new(order.distributor)
end
def line_items
if order.complete?
order.line_items.select { |li| inventory_units.pluck(:variant_id).include?(li.variant_id) }
else
order.line_items
end
end
def finalize!
InventoryUnit.finalize_units!(inventory_units)
manifest.each { |item| manifest_unstock(item) }
@@ -295,6 +283,15 @@ module Spree
private
def line_items
if order.complete?
inventory_unit_ids = inventory_units.pluck(:variant_id)
order.line_items.select { |li| inventory_unit_ids.include?(li.variant_id) }
else
order.line_items
end
end
def manifest_unstock(item)
stock_location.unstock item.variant, item.quantity, self
end

View File

@@ -3,23 +3,22 @@ require 'open_food_network/scope_variant_to_hub'
# Previously Spree::OrderPopulator. Modified to work with max_quantity and variant overrides.
class CartService
attr_accessor :order, :currency
attr_reader :variants_h
attr_accessor :order
attr_reader :errors
def initialize(order)
@order = order
@currency = order.currency
@errors = ActiveModel::Errors.new(self)
end
def populate(from_hash, overwrite = false)
def populate(from_hash)
@distributor, @order_cycle = distributor_and_order_cycle
variants_data = read_variants_hash(from_hash)
@order.with_lock do
variants_data = read_variants from_hash
attempt_cart_add_variants variants_data
overwrite_variants variants_data if overwrite
overwrite_variants variants_data
end
valid?
end
@@ -34,10 +33,10 @@ class CartService
loaded_variants = indexed_variants(variants_data)
variants_data.each do |variant_data|
loaded_variant = loaded_variants[variant_data[:variant_id].to_i]
loaded_variant = loaded_variants[variant_data[:variant_id]]
if loaded_variant.deleted?
remove_deleted_variant(loaded_variant)
if loaded_variant.deleted? || !variant_data[:quantity].positive?
cart_remove(loaded_variant)
next
end
@@ -57,15 +56,7 @@ class CartService
end
end
def remove_deleted_variant(variant)
line_item_for_variant(variant).andand.destroy
end
def attempt_cart_add(variant, quantity, max_quantity = nil)
quantity = quantity.to_i
max_quantity = max_quantity.to_i if max_quantity
return unless quantity > 0
scoper.scope(variant)
return unless valid_variant?(variant)
@@ -73,27 +64,37 @@ class CartService
end
def cart_add(variant, quantity, max_quantity)
quantity_to_add, max_quantity_to_add = quantities_to_add(variant, quantity, max_quantity)
if quantity_to_add > 0
@order.add_variant(variant, quantity_to_add, max_quantity_to_add, currency)
attributes = final_quantities(variant, quantity, max_quantity)
if attributes[:quantity].positive?
@order.contents.update_or_create(variant, attributes)
else
@order.remove_variant variant
cart_remove(variant)
end
end
def quantities_to_add(variant, quantity, max_quantity)
def cart_remove(variant)
begin
order.contents.remove(variant)
rescue ActiveRecord::RecordNotFound
# Nothing to remove; no line items for this variant were found.
end
end
def final_quantities(variant, quantity, max_quantity)
# If not enough stock is available, add as much as we can to the cart
on_hand = variant.on_hand
on_hand = [quantity, max_quantity].compact.max if variant.on_demand
quantity_to_add = [quantity, on_hand].min
max_quantity_to_add = max_quantity # max_quantity is not capped
final_quantity = [quantity, on_hand].min
final_max_quantity = max_quantity # max_quantity is not capped
[quantity_to_add, max_quantity_to_add]
{ quantity: final_quantity, max_quantity: final_max_quantity }
end
def overwrite_variants(variants)
variants_removed(variants).each do |id|
cart_remove(id)
variants_removed(variants).each do |variant_id|
variant = Spree::Variant.with_deleted.find(variant_id)
cart_remove(variant)
end
end
@@ -101,27 +102,25 @@ class CartService
@scoper ||= OpenFoodNetwork::ScopeVariantToHub.new(@distributor)
end
def read_variants(data)
@variants_h = read_variants_hash(data)
end
def read_variants_hash(data)
variants_array = []
(data[:variants] || []).each do |variant_id, quantity|
if quantity.is_a?(ActionController::Parameters)
variants_array.push({ variant_id: variant_id, quantity: quantity[:quantity], max_quantity: quantity[:max_quantity] })
variants_array.push({
variant_id: variant_id.to_i,
quantity: quantity[:quantity].to_i,
max_quantity: quantity[:max_quantity].to_i
})
else
variants_array.push({ variant_id: variant_id, quantity: quantity })
variants_array.push({
variant_id: variant_id.to_i,
quantity: quantity.to_i
})
end
end
variants_array
end
def cart_remove(variant_id)
variant = Spree::Variant.find(variant_id)
@order.remove_variant(variant)
end
def distributor_and_order_cycle
[@order.distributor, @order.order_cycle]
end
@@ -131,7 +130,7 @@ class CartService
li = line_item_for_variant loaded_variant
li_added = li.nil? && (variant_data[:quantity].to_i > 0 || variant_data[:max_quantity].to_i > 0)
li_quantity_changed = li.present? && li.quantity.to_i != variant_data[:quantity].to_i
li_quantity_changed = li.present? && li.quantity != variant_data[:quantity].to_i
li_max_quantity_changed = li.present? && li.max_quantity.to_i != variant_data[:max_quantity].to_i
li_added || li_quantity_changed || li_max_quantity_changed

View File

@@ -19,9 +19,6 @@ class OrderFeesHandler
create_line_item_fees!
create_order_fees!
order.updater.update_totals
order.updater.persist_totals
end
order.update_order!

View File

@@ -15,6 +15,7 @@ class OrderSyncer
distributor_id: shop_id)
update_associations_for(order)
line_item_syncer.sync!(order)
order.update_order!
order.save
end
end

View File

@@ -209,10 +209,10 @@ describe Admin::BulkLineItemsController, type: :controller do
allow(Spree::LineItem)
.to receive(:find).with(line_item1.id.to_s).and_return(line_item1)
expect(line_item1.order).to receive(:reload).with(lock: true)
expect(line_item1.order).to receive(:with_lock).and_call_original
expect(line_item1.order).to receive(:update_line_item_fees!)
expect(line_item1.order).to receive(:update_order_fees!)
expect(line_item1.order).to receive(:update_order!).twice
expect(line_item1.order).to receive(:update_order!).once
spree_put :update, params
end
@@ -349,6 +349,8 @@ describe Admin::BulkLineItemsController, type: :controller do
it "correctly updates order totals and states" do
expect(order.total).to eq 35.0
expect(order.shipment_adjustments.shipping.sum(:amount)).to eq 6.0
expect(order.shipment_adjustments.tax.sum(:amount)).to eq 0.29
expect(order.item_total).to eq 20.0
expect(order.adjustment_total).to eq 15.0
expect(order.included_tax_total).to eq 1.22
@@ -360,10 +362,11 @@ describe Admin::BulkLineItemsController, type: :controller do
spree_put :update, params
order.reload
expect(order.total).to eq 61.0
expect(order.total).to eq 67.0
expect(order.shipment_adjustments.sum(:amount)).to eq 12.57
expect(order.item_total).to eq 40.0
expect(order.adjustment_total).to eq 21.0
expect(order.included_tax_total).to eq 2.65 # Pending: this should be 3.10!
expect(order.adjustment_total).to eq 27.0
expect(order.included_tax_total).to eq 2.93 # Pending: taxes on enterprise fees unchanged
expect(order.payment_state).to eq "balance_due"
end
end
@@ -373,21 +376,22 @@ describe Admin::BulkLineItemsController, type: :controller do
it "correctly updates order totals and states" do
expect(order.total).to eq 35.0
expect(order.shipment_adjustments.shipping.sum(:amount)).to eq 6.0
expect(order.shipment_adjustments.tax.sum(:amount)).to eq 0.29
expect(order.item_total).to eq 20.0
expect(order.adjustment_total).to eq 15.0
expect(order.included_tax_total).to eq 1.22
expect(order.payment_state).to eq "paid"
expect(order).to receive(:update_order!).at_least(:once).and_call_original
expect(order).to receive(:create_tax_charge!).at_least(:once).and_call_original
spree_delete :destroy, params
order.reload
expect(order.total).to eq 22.0
expect(order.total).to eq 19.0
expect(order.shipment_adjustments.shipping.sum(:amount)).to eq 3.0
expect(order.shipment_adjustments.tax.sum(:amount)).to eq 0.14
expect(order.item_total).to eq 10.0
expect(order.adjustment_total).to eq 12.0
expect(order.included_tax_total).to eq 0.99
expect(order.adjustment_total).to eq 9.0
expect(order.included_tax_total).to eq 0.84
expect(order.payment_state).to eq "credit_owed"
end
end

View File

@@ -70,6 +70,7 @@ module Admin
let!(:line_item) { create(:line_item, order: order, price: 10.0) }
it 'includes the customer balance in the response' do
order.update_order!
get :index, params: params
expect(json_response.first["balance"]).to eq("$-10.00")
end
@@ -77,13 +78,16 @@ module Admin
context 'when the customer has canceled orders' do
let(:order) { create(:order, customer: customer) }
let!(:line_item) { create(:line_item, order: order, price: 10.0) }
let!(:payment) { create(:payment, order: order, amount: order.total) }
let!(:variant) { create(:variant, price: 10.0) }
before do
allow_any_instance_of(Spree::Payment).to receive(:completed?).and_return(true)
order.process_payments!
order.contents.add(variant)
order.payments << create(:payment, order: order, amount: order.total)
order.reload
order.process_payments!
order.update_attribute(:state, 'canceled')
end
@@ -104,8 +108,7 @@ module Admin
end
context 'when the customer has an order with a void payment' do
let(:order) { create(:order, customer: customer, state: 'complete') }
let!(:line_item) { create(:line_item, order: order, price: 10.0) }
let(:order) { create(:order_with_totals, customer: customer, state: 'complete') }
let!(:payment) { create(:payment, order: order, amount: order.total) }
before do

View File

@@ -174,6 +174,42 @@ describe Api::V0::ShipmentsController, type: :controller do
}.to_not change { existing_variant.reload.on_hand }
end
end
context "with shipping fees" do
let!(:distributor) { create(:distributor_enterprise) }
let(:fee_amount) { 10 }
let!(:shipping_method_with_fee) {
create(:shipping_method_with, :shipping_fee, distributors: [distributor],
shipping_fee: fee_amount)
}
let!(:order_cycle) { create(:order_cycle, distributors: [distributor]) }
let!(:order) {
create(:completed_order_with_totals, order_cycle: order_cycle, distributor: distributor)
}
let(:shipping_fee) { order.reload.shipment.adjustments.first }
before do
order.shipments.first.shipping_methods = [shipping_method_with_fee]
order.select_shipping_method(shipping_method_with_fee.id)
order.update_order!
end
context "adding item to a shipment" do
it "updates the shipping fee" do
expect {
api_put :add, params.merge(variant_id: new_variant.to_param)
}.to change { order.reload.shipment.adjustments.first.amount }.by(20)
end
end
context "removing item from a shipment" do
it "updates the shipping fee" do
expect {
api_put :remove, params.merge(variant_id: existing_variant.to_param)
}.to change { order.reload.shipment.adjustments.first.amount }.by(-20)
end
end
end
end
describe "#update" do

View File

@@ -16,7 +16,6 @@ describe CartController, type: :controller do
it "returns HTTP success when successful" do
allow(cart_service).to receive(:populate) { true }
allow(cart_service).to receive(:valid?) { true }
allow(cart_service).to receive(:variants_h) { {} }
post :populate, xhr: true, params: { use_route: :spree }, as: :json
expect(response.status).to eq(200)
end
@@ -30,32 +29,17 @@ describe CartController, type: :controller do
expect(response.status).to eq(412)
end
it "tells cart_service to overwrite" do
allow(cart_service).to receive(:variants_h) { {} }
allow(cart_service).to receive(:valid?) { true }
expect(cart_service).to receive(:populate).with({}, true)
post :populate, xhr: true, params: { use_route: :spree }, as: :json
end
it "returns stock levels as JSON on success" do
allow(controller).to receive(:variant_ids_in) { [123] }
allow_any_instance_of(VariantsStockLevels).to receive(:call).and_return("my_stock_levels")
allow(cart_service).to receive(:populate) { true }
allow(cart_service).to receive(:valid?) { true }
allow(cart_service).to receive(:variants_h) { {} }
post :populate, xhr: true, params: { use_route: :spree }, as: :json
data = JSON.parse(response.body)
expect(data['stock_levels']).to eq('my_stock_levels')
end
it "extracts variant ids from the cart service" do
variants_h = [{ variant_id: "900", quantity: 2, max_quantity: nil },
{ variant_id: "940", quantity: 3, max_quantity: 3 }]
expect(controller.variant_ids_in(variants_h)).to eq([900, 940])
end
end
context "handling variant overrides correctly" do
@@ -110,7 +94,6 @@ describe CartController, type: :controller do
order = subject.current_order(true)
allow(order).to receive(:distributor) { distributor }
allow(order).to receive(:order_cycle) { order_cycle }
expect(order).to receive(:set_variant_attributes).with(variant, max_quantity: "3")
allow(controller).to receive(:current_order).and_return(order)
expect do

View File

@@ -250,7 +250,7 @@ describe Spree::OrdersController, type: :controller do
before do
order.set_distribution! d, oc
order.add_variant variant, 5
order.contents.add(variant, 5)
end
describe "the page" do
@@ -296,7 +296,7 @@ describe Spree::OrdersController, type: :controller do
describe "when I pass params that includes a line item no longer in our cart" do
it "should silently ignore the missing line item" do
order = subject.current_order(true)
li = order.add_variant(create(:simple_product, on_hand: 110).variants.first)
li = order.contents.add(create(:simple_product, on_hand: 110).variants.first)
get :update, params: { order: { line_items_attributes: {
"0" => { quantity: "0", id: "9999" },
"1" => { quantity: "99", id: li.id }
@@ -308,21 +308,21 @@ describe Spree::OrdersController, type: :controller do
it "filters line items that are missing from params" do
order = subject.current_order(true)
li = order.add_variant(create(:simple_product).master)
li = order.contents.add(create(:simple_product).variants.first)
attrs = {
"0" => { quantity: "0", id: "9999" },
"1" => { quantity: "99", id: li.id }
}
expect(controller.remove_missing_line_items(attrs)).to eq(
expect(controller.__send__(:remove_missing_line_items, attrs)).to eq(
"1" => { quantity: "99", id: li.id }
)
end
it "keeps the adjustments' previous state" do
order = subject.current_order(true)
line_item = order.add_variant(create(:simple_product, on_hand: 110).variants.first)
line_item = order.contents.add(create(:simple_product, on_hand: 110).variants.first)
adjustment = create(:adjustment, adjustable: order)
get :update, params: { order: { line_items_attributes: {

View File

@@ -15,6 +15,7 @@ FactoryBot.define do
after(:create) do |order|
create(:line_item, order: order)
order.line_items.reload # to ensure order.line_items is accessible after
order.updater.update_totals_and_states
end
end

View File

@@ -414,6 +414,7 @@ feature '
let!(:adj_manual2) { create(:adjustment, order: order1, adjustable: order1, originator: nil, label: "Manual adjustment", amount: 40, included_tax: 3) }
before do
order1.update_order!
order1.update_attribute :email, 'customer@email.com'
order1.shipment.update_columns(included_tax_total: 10.06)
Timecop.travel(Time.zone.local(2015, 4, 25, 14, 0, 0)) { order1.finalize! }

View File

@@ -164,7 +164,7 @@ feature "full-page cart", js: true do
let(:variant2) { product_with_fee.variants.first }
before do
add_product_to_cart order, product_with_tax
order.contents.add(product_with_tax.variants.first)
end
describe "when on_hand is zero but variant is on demand" do
@@ -179,7 +179,7 @@ feature "full-page cart", js: true do
describe "with insufficient stock available" do
it "prevents user from entering invalid values" do
add_product_to_cart order, product_with_fee
order.contents.add(product_with_fee.variants.first)
variant.update!(on_hand: 2, on_demand: false)
variant2.update!(on_hand: 3, on_demand: false)

View File

@@ -1,6 +1,7 @@
describe "ShopVariantCtrl", ->
ctrl = null
scope = null
CartMock = null
beforeEach ->
module 'Darkswarm'
@@ -16,7 +17,10 @@ describe "ShopVariantCtrl", ->
max_quantity: undefined
}
}
ctrl = $controller 'ShopVariantCtrl', {$scope: scope, $modal: $modal, Cart: null}
CartMock =
adjust: ->
true
ctrl = $controller 'ShopVariantCtrl', {$scope: scope, $modal: $modal, Cart: CartMock}
it "initializes the quantity for shop display", ->
expect(scope.variant.line_item.quantity).toEqual 0

View File

@@ -11,7 +11,6 @@ module Spree
it 'should update inventory, totals, and tax' do
# Regression check for Spree #1481
expect(line_item.order).to receive(:create_tax_charge!)
expect(line_item.order).to receive(:update_order!)
line_item.quantity = 2
line_item.save
end

View File

@@ -3,12 +3,11 @@
require 'spec_helper'
describe Spree::OrderContents do
let(:order) { Spree::Order.create }
let!(:order) { create(:order) }
let!(:variant) { create(:variant) }
subject { described_class.new(order) }
context "#add" do
let(:variant) { create(:variant) }
context 'given quantity is not explicitly provided' do
it 'should add one line item' do
line_item = subject.add(variant)
@@ -42,8 +41,6 @@ describe Spree::OrderContents do
end
context "#remove" do
let(:variant) { create(:variant) }
context "given an invalid variant" do
it "raises an exception" do
expect {
@@ -53,11 +50,12 @@ describe Spree::OrderContents do
end
context 'given quantity is not explicitly provided' do
it 'should remove one line item' do
line_item = subject.add(variant, 3)
subject.remove(variant)
it 'should remove line item' do
subject.add(variant, 3)
expect(line_item.reload.quantity).to eq 2
expect{
subject.remove(variant)
}.to change(Spree::LineItem, :count).by -1
end
end
@@ -89,4 +87,105 @@ describe Spree::OrderContents do
expect(order.total.to_f).to eq 19.99
end
end
context "#update_cart" do
let!(:line_item) { subject.add variant, 1 }
let(:params) do
{ line_items_attributes: {
"0" => { id: line_item.id, quantity: 3 }
} }
end
it "changes item quantity" do
subject.update_cart params
expect(line_item.reload.quantity).to eq 3
end
it "updates order totals" do
expect {
subject.update_cart params
}.to change { subject.order.total }
end
context "submits item quantity 0" do
let(:params) do
{ line_items_attributes: {
"0" => { id: line_item.id, quantity: 0 }
} }
end
it "removes item from order" do
expect {
subject.update_cart params
}.to change { order.line_items.count }
end
end
it "ensures updated shipments" do
expect(subject.order).to receive(:ensure_updated_shipments)
subject.update_cart params
end
end
describe "#update_item" do
let!(:line_item) { subject.add variant, 1 }
context "updating enterprise fees" do
it "updates the line item's enterprise fees" do
expect(order).to receive(:update_line_item_fees!).with(line_item)
subject.update_item(line_item, { quantity: 3 })
end
it "updates the order's enterprise fees if completed" do
allow(order).to receive(:completed?) { true }
expect(order).to receive(:update_order_fees!)
subject.update_item(line_item, { quantity: 3 })
end
it "does not update the order's enterprise fees if not complete" do
expect(order).to_not receive(:update_order_fees!)
subject.update_item(line_item, { quantity: 3 })
end
end
it "ensures updated shipments" do
expect(order).to receive(:ensure_updated_shipments)
subject.update_item(line_item, { quantity: 3 })
end
it "updates the order" do
expect(order).to receive(:update_order!)
subject.update_item(line_item, { quantity: 3 })
end
end
describe "#update_or_create" do
describe "creating" do
it "creates a new line item with given attributes" do
subject.update_or_create(variant, { quantity: 2, max_quantity: 3 })
line_item = order.line_items.reload.first
expect(line_item.quantity).to eq 2
expect(line_item.max_quantity).to eq 3
expect(line_item.price).to eq variant.price
end
end
describe "updating" do
let!(:line_item) { subject.add variant, 2 }
it "updates existing line item with given attributes" do
subject.update_or_create(variant, { quantity: 3, max_quantity: 4 })
expect(line_item.reload.quantity).to eq 3
expect(line_item.max_quantity).to eq 4
end
end
end
end

View File

@@ -455,26 +455,6 @@ describe Spree::Order do
end
end
describe "setting variant attributes" do
it "sets attributes on line items for variants" do
d = create(:distributor_enterprise)
p = create(:product)
subject.distributor = d
subject.save!
subject.add_variant(p.master, 1, 3)
li = Spree::LineItem.last
expect(li.max_quantity).to eq(3)
end
it "does nothing when the line item is not found" do
p = build_stubbed(:simple_product)
subject.set_variant_attributes(p.master, { 'max_quantity' => '3' }.with_indifferent_access)
end
end
describe "applying enterprise fees" do
subject { create(:order) }
let(:fee_handler) { ::OrderFeesHandler.new(subject) }
@@ -727,59 +707,6 @@ describe Spree::Order do
end
end
describe "removing an item from the order" do
let(:order) { create(:order) }
let(:v1) { create(:variant) }
let(:v2) { create(:variant) }
let(:v3) { create(:variant) }
before do
order.add_variant v1
order.add_variant v2
order.recreate_all_fees!
end
it "removes the variant's line item" do
order.remove_variant v1
expect(order.line_items.reload.map(&:variant)).to eq([v2])
end
it "does nothing when there is no matching line item" do
expect do
order.remove_variant v3
end.to change(order.line_items.reload, :count).by(0)
end
context "when the item has an associated adjustment" do
let(:distributor) { create(:distributor_enterprise) }
let(:order_cycle) do
create(:order_cycle).tap do
create(:exchange, variants: [v1], incoming: true)
create(:exchange, variants: [v1], incoming: false, receiver: distributor)
end
end
let(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) }
it "removes the variant's line item" do
order.remove_variant v1
expect(order.line_items.reload.map(&:variant)).to eq([v2])
end
it "removes the variant's adjustment" do
line_item = order.line_items.where(variant_id: v1.id).first
adjustment_scope = Spree::Adjustment.where(adjustable_type: "Spree::LineItem",
adjustable_id: line_item.id)
expect(adjustment_scope.count).to eq(1)
adjustment = adjustment_scope.first
order.remove_variant v1
expect { adjustment.reload }.to raise_error
end
end
end
describe "emptying the order" do
it "removes shipments" do
subject.shipments << create(:shipment)
@@ -1199,8 +1126,11 @@ describe Spree::Order do
context "when no order has been finalised in this order cycle" do
let(:product) { create(:product) }
before do
order.contents.update_or_create(product.variants.first, { quantity: 1, max_quantity: 3 })
end
it "returns no items even though the cart contains items" do
order.add_variant(product.master, 1, 3)
expect(order.finalised_line_items).to eq []
end
end
@@ -1210,9 +1140,12 @@ describe Spree::Order do
let!(:prev_order2) { create(:completed_order_with_totals, distributor: distributor, order_cycle: order_cycle, user: order.user) }
let(:product) { create(:product) }
it "returns previous items" do
prev_order.add_variant(product.master, 1, 3)
before do
prev_order.contents.update_or_create(product.variants.first, { quantity: 1, max_quantity: 3 })
prev_order2.reload # to get the right response from line_items
end
it "returns previous items" do
expect(order.finalised_line_items.length).to eq 11
expect(order.finalised_line_items).to match_array(prev_order.line_items + prev_order2.line_items)
end
@@ -1380,4 +1313,36 @@ describe Spree::Order do
end
end
end
describe "#ensure_updated_shipments" do
before { Spree::Shipment.create!(order: order) }
context "when the order is not completed" do
it "destroys current shipments" do
order.ensure_updated_shipments
expect(order.shipments).to be_empty
end
it "puts order back in address state" do
order.ensure_updated_shipments
expect(order.state).to eq "address"
end
end
context "when the order is completed" do
before do
allow(order).to receive(:completed?) { true }
end
it "does not change the shipments" do
expect {
order.ensure_updated_shipments
}.not_to change { order.shipments }
expect {
order.ensure_updated_shipments
}.not_to change { order.state }
end
end
end
end

View File

@@ -79,7 +79,7 @@ module Spree
expect(flat_percent_payment_method.compute_amount(order)).to eq 0
product = create(:product)
order.add_variant(product.master)
order.contents.add(product.variants.first)
expect(flat_percent_payment_method.compute_amount(order)).to eq 2.0
end

View File

@@ -52,6 +52,33 @@ module Spree
expect(line_item).not_to be_valid
end
end
context "when the line item's variant has an override" do
let(:hub) { order.distributor }
let(:variant) { line_item.variant }
let(:vo_stock) { 999 }
let!(:variant_override) {
create(:variant_override, variant: variant, hub: hub, count_on_hand: vo_stock)
}
context "when the override has stock" do
it "is valid" do
line_item.quantity = 999
validator.validate(line_item)
expect(line_item).to be_valid
end
end
context "when the override is out of stock" do
let(:vo_stock) { 1 }
it "is not valid" do
line_item.quantity = 999
validator.validate(line_item)
expect(line_item).to_not be_valid
end
end
end
end
end
end

View File

@@ -27,9 +27,9 @@ describe CartService do
describe "#populate" do
it "adds a variant" do
cart_service.populate(
ActionController::Parameters.new({ variants: { variant.id.to_s => { quantity: '1',
max_quantity: '2' } } }),
true
ActionController::Parameters.new(
{ variants: { variant.id.to_s => { quantity: '1', max_quantity: '2' } } }
)
)
li = order.find_line_item_by_variant(variant)
expect(li).to be
@@ -38,28 +38,35 @@ describe CartService do
expect(li.final_weight_volume).to eq(1.0)
end
it "updates a variant's quantity, max quantity and final_weight_volume" do
order.add_variant variant, 1, 2
context "updating an existing variant" do
before do
order.contents.update_or_create(variant, { quantity: 1, max_quantity: 2 })
end
cart_service.populate(
ActionController::Parameters.new({ variants: { variant.id.to_s => { quantity: '2',
max_quantity: '3' } } }),
true
)
li = order.find_line_item_by_variant(variant)
expect(li).to be
expect(li.quantity).to eq(2)
expect(li.max_quantity).to eq(3)
expect(li.final_weight_volume).to eq(2.0)
end
it "updates a variant's quantity, max quantity and final_weight_volume" do
cart_service.populate(
ActionController::Parameters.new(
{ variants: { variant.id.to_s => { quantity: '2', max_quantity: '3' } } }
)
)
it "removes a variant" do
order.add_variant variant, 1, 2
li = order.find_line_item_by_variant(variant)
expect(li).to be
expect(li.quantity).to eq(2)
expect(li.max_quantity).to eq(3)
expect(li.final_weight_volume).to eq(2.0)
end
cart_service.populate(ActionController::Parameters.new({ variants: {} }), true)
order.line_items.reload
li = order.find_line_item_by_variant(variant)
expect(li).not_to be
it "removes a variant" do
cart_service.populate(
ActionController::Parameters.new(
{ variants: { variant.id.to_s => { quantity: '0' } } }
)
)
order.line_items.reload
li = order.find_line_item_by_variant(variant)
expect(li).not_to be
end
end
context "when a variant has been soft-deleted" do
@@ -69,7 +76,11 @@ describe CartService do
it "does not add the deleted variant to the cart" do
variant.delete
cart_service.populate(ActionController::Parameters.new({ variants: { variant.id.to_s => { quantity: '2' } } }), true)
cart_service.populate(
ActionController::Parameters.new(
{ variants: { variant.id.to_s => { quantity: '2' } } }
)
)
expect(relevant_line_item).to be_nil
expect(cart_service.errors.count).to be 0
@@ -84,7 +95,11 @@ describe CartService do
it "removes the line_item from the cart" do
variant.delete
cart_service.populate(ActionController::Parameters.new({ variants: { variant.id.to_s => { quantity: '3' } } }), true)
cart_service.populate(
ActionController::Parameters.new(
{ variants: { variant.id.to_s => { quantity: '3' } } }
)
)
expect(Spree::LineItem.where(id: relevant_line_item).first).to be_nil
expect(cart_service.errors.count).to be 0
@@ -98,28 +113,28 @@ describe CartService do
let!(:variant) { create(:variant) }
it "returns true when item is not in cart and a quantity is specified" do
variant_data = { variant_id: variant.id, quantity: '2' }
variant_data = { variant_id: variant.id, quantity: 2 }
expect(cart_service).to receive(:line_item_for_variant).with(variant).and_return(nil)
expect(cart_service.send(:varies_from_cart, variant_data, variant )).to be true
end
it "returns true when item is not in cart and a max_quantity is specified" do
variant_data = { variant_id: variant.id, quantity: '0', max_quantity: '2' }
variant_data = { variant_id: variant.id, quantity: 0, max_quantity: 2 }
expect(cart_service).to receive(:line_item_for_variant).with(variant).and_return(nil)
expect(cart_service.send(:varies_from_cart, variant_data, variant)).to be true
end
it "returns false when item is not in cart and no quantity or max_quantity are specified" do
variant_data = { variant_id: variant.id, quantity: '0' }
variant_data = { variant_id: variant.id, quantity: 0 }
expect(cart_service).to receive(:line_item_for_variant).with(variant).and_return(nil)
expect(cart_service.send(:varies_from_cart, variant_data, variant)).to be false
end
it "returns true when quantity varies" do
variant_data = { variant_id: variant.id, quantity: '2' }
variant_data = { variant_id: variant.id, quantity: 2 }
line_item = double(:line_item, quantity: 1, max_quantity: nil)
allow(cart_service).to receive(:line_item_for_variant) { line_item }
@@ -127,7 +142,7 @@ describe CartService do
end
it "returns true when max_quantity varies" do
variant_data = { variant_id: variant.id, quantity: '1', max_quantity: '3' }
variant_data = { variant_id: variant.id, quantity: 1, max_quantity: 3 }
line_item = double(:line_item, quantity: 1, max_quantity: nil)
allow(cart_service).to receive(:line_item_for_variant) { line_item }
@@ -135,7 +150,7 @@ describe CartService do
end
it "returns false when max_quantity varies only in nil vs 0" do
variant_data = { variant_id: variant.id, quantity: '1' }
variant_data = { variant_id: variant.id, quantity: 1 }
line_item = double(:line_item, quantity: 1, max_quantity: nil)
allow(cart_service).to receive(:line_item_for_variant) { line_item }
@@ -143,7 +158,7 @@ describe CartService do
end
it "returns false when both are specified and neither varies" do
variant_data = { variant_id: variant.id, quantity: '1', max_quantity: '2' }
variant_data = { variant_id: variant.id, quantity: 1, max_quantity: 2 }
line_item = double(:line_item, quantity: 1, max_quantity: 2)
allow(cart_service).to receive(:line_item_for_variant) { line_item }
@@ -151,30 +166,6 @@ describe CartService do
end
end
describe "variants_removed" do
it "returns the variant ids when one is in the cart but not in those given" do
allow(cart_service).to receive(:variant_ids_in_cart) { [123] }
expect(cart_service.send(:variants_removed, [])).to eq([123])
end
it "returns nothing when all items in the cart are provided" do
allow(cart_service).to receive(:variant_ids_in_cart) { [123] }
expect(cart_service.send(:variants_removed, [{ variant_id: '123' }])).to eq([])
end
it "returns nothing when items are added to cart" do
allow(cart_service).to receive(:variant_ids_in_cart) { [123] }
expect(
cart_service.send(:variants_removed, [{ variant_id: '123' }, { variant_id: '456' }])
).to eq([])
end
it "does not return duplicates" do
allow(cart_service).to receive(:variant_ids_in_cart) { [123, 123] }
expect(cart_service.send(:variants_removed, [])).to eq([123])
end
end
describe "attempt_cart_add" do
let!(:variant) { create(:variant, on_hand: 250) }
let(:quantity) { 123 }
@@ -189,38 +180,40 @@ describe CartService do
expect(cart_service).to receive(:check_variant_available_under_distribution).with(variant).
and_return(true)
expect(variant).to receive(:on_demand).and_return(false)
expect(order).to receive(:add_variant).with(variant, quantity, nil, currency)
expect(order).to receive_message_chain(:contents, :update_or_create).
with(variant, { quantity: quantity, max_quantity: nil })
cart_service.send(:attempt_cart_add, variant, quantity.to_s)
cart_service.send(:attempt_cart_add, variant, quantity)
end
it "filters quantities through #quantities_to_add" do
expect(cart_service).to receive(:quantities_to_add).with(variant, 123, 123).
and_return([5, 5])
it "filters quantities through #final_quantities" do
expect(cart_service).to receive(:final_quantities).with(variant, 123, 123).
and_return({ quantity: 5, max_quantity: 5 })
allow(cart_service).to receive(:check_order_cycle_provided) { true }
allow(cart_service).to receive(:check_variant_available_under_distribution) { true }
expect(order).to receive(:add_variant).with(variant, 5, 5, currency)
expect(order).to receive_message_chain(:contents, :update_or_create).
with(variant, { quantity: 5, max_quantity: 5 })
cart_service.send(:attempt_cart_add, variant, quantity.to_s, quantity.to_s)
cart_service.send(:attempt_cart_add, variant, quantity, quantity)
end
it "removes variants which have become out of stock" do
expect(cart_service).to receive(:quantities_to_add).with(variant, 123, 123).
and_return([0, 0])
expect(cart_service).to receive(:final_quantities).with(variant, 123, 123).
and_return({ quantity: 0, max_quantity: 0 })
allow(cart_service).to receive(:check_order_cycle_provided) { true }
allow(cart_service).to receive(:check_variant_available_under_distribution) { true }
expect(order).to receive(:remove_variant).with(variant)
expect(order).to receive(:add_variant).never
expect(cart_service).to receive(:cart_add).with(variant, 123, 123).and_call_original
expect(order).to receive_message_chain(:contents, :remove).with(variant)
cart_service.send(:attempt_cart_add, variant, quantity.to_s, quantity.to_s)
cart_service.send(:attempt_cart_add, variant, quantity, quantity)
end
end
describe "quantities_to_add" do
describe "#final_quantities" do
let(:v) { double(:variant, on_hand: 10) }
context "when backorders are not allowed" do
@@ -228,23 +221,27 @@ describe CartService do
expect(v).to receive(:on_demand).and_return(false)
end
context "when max_quantity is not provided" do
context "getting quantity and max_quantity" do
it "returns full amount when available" do
expect(cart_service.send(:quantities_to_add, v, 5, nil)).to eq([5, nil])
expect(cart_service.send(:final_quantities, v, 5, nil)).
to eq({ quantity: 5, max_quantity: nil })
end
it "returns a limited amount when not entirely available" do
expect(cart_service.send(:quantities_to_add, v, 15, nil)).to eq([10, nil])
expect(cart_service.send(:final_quantities, v, 15, nil)).
to eq({ quantity: 10, max_quantity: nil })
end
end
context "when max_quantity is provided" do
it "returns full amount when available" do
expect(cart_service.send(:quantities_to_add, v, 5, 6)).to eq([5, 6])
expect(cart_service.send(:final_quantities, v, 5, 6)).
to eq({ quantity: 5, max_quantity: 6 })
end
it "also returns the full amount when not entirely available" do
expect(cart_service.send(:quantities_to_add, v, 15, 16)).to eq([10, 16])
expect(cart_service.send(:final_quantities, v, 15, 16)).
to eq({ quantity: 10, max_quantity: 16 })
end
end
end
@@ -255,11 +252,13 @@ describe CartService do
end
it "does not limit quantity" do
expect(cart_service.send(:quantities_to_add, v, 15, nil)).to eq([15, nil])
expect(cart_service.send(:final_quantities, v, 15, nil)).
to eq({ quantity: 15, max_quantity: nil })
end
it "does not limit max_quantity" do
expect(cart_service.send(:quantities_to_add, v, 15, 16)).to eq([15, 16])
expect(cart_service.send(:final_quantities, v, 15, 16)).
to eq({ quantity: 15, max_quantity: 16 })
end
end
end

View File

@@ -443,7 +443,10 @@ describe OrderSyncer do
before { variant.update_attribute(:on_hand, 3) }
context "when the changed line_item quantity matches the new quantity on the subscription line item" do
before { changed_line_item.update(quantity: 3) }
before do
changed_line_item.update(quantity: 3)
order.update_order!
end
it "does not change the quantity, and doesn't add the order to order_update_issues" do
expect(order.reload.total.to_f).to eq 99.95
@@ -456,7 +459,10 @@ describe OrderSyncer do
end
context "when the changed line_item quantity doesn't match the new quantity on the subscription line item" do
before { changed_line_item.update(quantity: 2) }
before do
changed_line_item.update(quantity: 2)
order.update_order!
end
it "does not change the quantity, and adds the order to order_update_issues" do
expect(order.reload.total.to_f).to eq 79.96