Skip to content

Commit

Permalink
This resolves #5132. The admin manual order cart is much more like th…
Browse files Browse the repository at this point in the history
…e frontend now in that you start off by adding items to the cart(line items). You then add an address, the shipments are calculated based on the frontend rules you have set up but you as an admin can ignore those rules and muck with the shipments on the Shipments tab. You can also skip adding items to the cart altogether by just entering an address and then adding shipments manually, the way the old backend admin did before this patch.

Extracting the advanceOrder function into a function in the Spree namespace so that both the shipmentsJS and line_itemsJS can share it

Advancing the order after we add variants on the cart page. If we have already created shipments, then when we edit a line item the order gets reset to the address state. This call pushes it back to the payment state and destroys the old shipments, recreating them to match the new line item state.

In checkout.rb we first create_proposed_shipments but here we check if addresses are valid. If not we need to destroy_all instead of delete_all so that the inventory_units that were created by create_propsed_shipments will also be destroyed and not clutter up the DB

Fixing the Split tool. IF success we reload the page, else display a generic error. Would like to in the future provide more specific errors. Not allowing splits to the same shipment nor to a shipment or location that does not have the stock and is NOT backorderable. Next commit will have a boatload of automated tests.

Adding appropriate tests for the splitting of shipments.

Fixes #5166
  • Loading branch information
Tyler Smart authored and Jeff Dutil committed Aug 14, 2014
1 parent a9d3ad9 commit b252e9a
Show file tree
Hide file tree
Showing 31 changed files with 713 additions and 156 deletions.
14 changes: 7 additions & 7 deletions api/app/controllers/spree/api/line_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@ def order

def find_line_item
id = params[:id].to_i
order.line_items.detect {|line_item| line_item.id == id} or
raise ActiveRecord::RecordNotFound
order.line_items.detect { |line_item| line_item.id == id } or
raise ActiveRecord::RecordNotFound
end

def line_items_attributes
{ line_items_attributes: {
id: params[:id],
quantity: params[:line_item][:quantity]
} }
{line_items_attributes: {
id: params[:id],
quantity: params[:line_item][:quantity]
}}
end

def line_item_params
params.require(:line_item).permit(:quantity, :variant_id)
end
end
end
end
end
23 changes: 23 additions & 0 deletions api/app/controllers/spree/api/shipments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module Api
class ShipmentsController < Spree::Api::BaseController

before_filter :find_and_update_shipment, only: [:ship, :ready, :add, :remove]
before_filter :load_transfer_params, only: [:transfer_to_location, :transfer_to_shipment]

def create
@order = Spree::Order.find_by!(number: params[:shipment][:order_id])
Expand Down Expand Up @@ -62,8 +63,30 @@ def remove
respond_with(@shipment, default_template: :show)
end

def transfer_to_location
success, message = @original_shipment.transfer_to_location(@variant, @quantity, @stock_location)
status = success ? 201 : 422
render json: {success: success, message: message}, status: status
end

def transfer_to_shipment
success, message = @original_shipment.transfer_to_shipment(@variant, @quantity, @target_shipment)
status = success ? 201 : 422
render json: {success: success, message: message}, status: status
end

private

def load_transfer_params
@original_shipment = Spree::Shipment.where(number: params[:original_shipment_number]).first
@target_shipment = params[:target_shipment_number] ? Spree::Shipment.where(number: params[:target_shipment_number]).first : nil
@variant = Spree::Variant.find(params[:variant_id])
@quantity = params[:quantity].to_i
@stock_location = params[:stock_location_id] ? Spree::StockLocation.find(params[:stock_location_id]) : nil
authorize! :read, @original_shipment
authorize! :create, Shipment
end

def find_and_update_shipment
@shipment = Spree::Shipment.accessible_by(current_ability, :update).readonly(false).find_by!(number: params[:id])
@shipment.update_attributes(shipment_params)
Expand Down
1 change: 0 additions & 1 deletion api/app/controllers/spree/api/variants_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ def destroy
def index
@variants = scope.includes({ option_values: :option_type }, :product, :default_price, :images, { stock_items: :stock_location })
.ransack(params[:q]).result.page(params[:page]).per(params[:per_page])

respond_with(@variants)
end

Expand Down
5 changes: 5 additions & 0 deletions api/app/views/spree/api/variants/big.v1.rabl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ cache [I18n.locale, @current_user_roles.include?('admin'), 'big_variant', root_o

extends "spree/api/variants/small"

node :total_on_hand do
root_object.total_on_hand
end


child(:stock_items => :stock_items) do
attributes :id, :count_on_hand, :stock_location_id, :backorderable
attribute :available? => :available
Expand Down
5 changes: 5 additions & 0 deletions api/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
end

resources :shipments, only: [:create, :update] do
collection do
post 'transfer_to_location'
post 'transfer_to_shipment'
end

member do
put :ready
put :ship
Expand Down
10 changes: 10 additions & 0 deletions backend/app/assets/javascripts/spree/backend/admin.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -274,4 +274,14 @@ $(document).ready(function(){
$('a.dismiss').click(function() {
$(this).parent().fadeOut();
});

window.Spree.advanceOrder = function() {
$.ajax({
type: "PUT",
async: false,
url: Spree.url(Spree.routes.checkouts_api + "/" + order_number + "/advance")
}).done(function() {
window.location.reload();
});
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ adjustLineItem = (line_item_id, quantity) ->
line_item:
quantity: quantity
).done (msg) ->
advanceOrder()
window.Spree.advanceOrder()

deleteLineItem = (line_item_id) ->
url = lineItemURL(line_item_id)
Expand All @@ -58,4 +58,4 @@ deleteLineItem = (line_item_id) ->
$('#line-item-' + line_item_id).remove()
if $('.line-items tr.line-item').length == 0
$('.line-items').remove()
advanceOrder()
window.Spree.advanceOrder()
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// This file contains the code for interacting with line items in the manual cart
$(document).ready(function () {
'use strict';

// handle variant selection, show stock level.
$('#add_line_item_variant_id').change(function(){
var variant_id = $(this).val();

var variant = _.find(window.variants, function(variant){
return variant.id == variant_id
})
$('#stock_details').html(variantLineItemTemplate({variant: variant}));
$('#stock_details').show();

$('button.add_variant').click(addVariant);

// Add some tips
$('.with-tip').powerTip({
smartPlacement: true,
fadeInTime: 50,
fadeOutTime: 50,
intentPollInterval: 300
});

});
});

addVariant = function() {
$('#stock_details').hide();

var variant_id = $('input.variant_autocomplete').val();
var quantity = $("input.quantity[data-variant-id='" + variant_id + "']").val();

adjustLineItems(order_number, variant_id, quantity);
return 1
}

adjustLineItems = function(order_number, variant_id, quantity){
var url = Spree.routes.orders_api + "/" + order_number + '/line_items';

$.ajax({
type: "POST",
url: Spree.url(url),
data: { line_item: {variant_id: variant_id, quantity: quantity }}
}).done(function( msg ) {
window.Spree.advanceOrder();
window.location.reload();
});

}
63 changes: 33 additions & 30 deletions backend/app/assets/javascripts/spree/backend/shipments.js.erb
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,13 @@ startItemSplit = function(event){

completeItemSplit = function(event) {
event.preventDefault();

if($('#item_stock_location').val() === ""){
alert('Please select the split destination.');
return false;
}

var link = $(this);
var order_number = link.closest('tbody').data('order-number');
var stock_item_row = link.closest('tr');
var variant_id = stock_item_row.data('variant-id');
var quantity = stock_item_row.find('#item_quantity').val();
Expand All @@ -242,46 +247,44 @@ completeItemSplit = function(event) {
var new_shipment = selected_shipment.data('new-shipment');

if (stock_location_id != 'new_shipment') {
// first remove item(s) from original shipment
$.ajax({
type: "PUT",
async: false,
url: Spree.url(Spree.routes.shipments_api + "/" + original_shipment_number + "/remove.json"),
data: { variant_id: variant_id, quantity: quantity }
});

if (new_shipment != undefined) {
// TRANSFER TO A NEW LOCATION
$.ajax({
type: "POST",
async: false,
url: Spree.url(Spree.routes.shipments_api + "?shipment[order_id]=" + order_number),
data: { variant_id: variant_id, quantity: quantity, stock_location_id: stock_location_id }
url: Spree.url(Spree.routes.shipments_api + "/transfer_to_location"),
data: {
original_shipment_number: original_shipment_number,
variant_id: variant_id,
quantity: quantity,
stock_location_id: stock_location_id
}
}).error(function(msg) {
alert(msg.responseJSON['message']);
}).done(function(msg) {
advanceOrder();
window.Spree.advanceOrder();
});
} else {
$.ajax({
type: "PUT",
async: false,
url: Spree.url(Spree.routes.shipments_api + "/" + target_shipment_number + "/add.json"),
data: { variant_id: variant_id, quantity: quantity }
}).done(function(msg) {
advanceOrder();
});
// TRANSFER TO AN EXISTING SHIPMENT
$.ajax({
type: "POST",
async: false,
url: Spree.url(Spree.routes.shipments_api + "/transfer_to_shipment"),
data: {
original_shipment_number: original_shipment_number,
target_shipment_number: target_shipment_number,
variant_id: variant_id,
quantity: quantity
}
}).error(function(msg) {
alert(msg.responseJSON['message']);
}).done(function(msg) {
window.Spree.advanceOrder();
});
}
}
}

advanceOrder = function() {
$.ajax({
type: "PUT",
async: false,
url: Spree.url(Spree.routes.checkouts_api + "/" + order_number + "/advance")
}).done(function() {
window.location.reload();
});
}

cancelItemSplit = function(event) {
event.preventDefault();
var link = $(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ $(document).ready ->
if $("#variant_autocomplete_template").length > 0
window.variantTemplate = Handlebars.compile($("#variant_autocomplete_template").text())
window.variantStockTemplate = Handlebars.compile($("#variant_autocomplete_stock_template").text())
window.variantLineItemTemplate = Handlebars.compile($("#variant_line_items_autocomplete_stock_template").text())
return

formatVariantResult = (variant) ->
Expand Down
6 changes: 6 additions & 0 deletions backend/app/controllers/spree/admin/base_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ def config_locale
Spree::Backend::Config[:locale]
end

def can_not_transition_without_customer_info
unless @order.billing_address.present?
flash[:notice] = Spree.t(:fill_in_customer_info)
redirect_to edit_admin_order_customer_url(@order)
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def update

@order.refresh_shipment_rates
flash[:success] = Spree.t('customer_details_updated')
redirect_to admin_order_customer_path(@order)
redirect_to edit_admin_order_url(@order)
else
render :action => :edit
end
Expand Down
15 changes: 13 additions & 2 deletions backend/app/controllers/spree/admin/orders_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Spree
module Admin
class OrdersController < Spree::Admin::BaseController
before_filter :initialize_order_events
before_filter :load_order, :only => [:edit, :update, :cancel, :resume, :approve, :resend, :open_adjustments, :close_adjustments]
before_filter :load_order, :only => [:edit, :update, :cancel, :resume, :approve, :resend, :open_adjustments, :close_adjustments, :cart]

respond_to :html

Expand Down Expand Up @@ -49,15 +49,26 @@ def index

def new
@order = Order.create(order_params)
redirect_to edit_admin_order_url(@order)
redirect_to cart_admin_order_url(@order)
end

def edit
can_not_transition_without_customer_info

unless @order.completed?
@order.refresh_shipment_rates
end
end

def cart
unless @order.completed?
@order.refresh_shipment_rates
end
if @order.shipped_shipments.count > 0
redirect_to edit_admin_order_url(@order)
end
end

def update
if @order.update_attributes(params[:order]) && @order.line_items.present?
@order.update!
Expand Down
9 changes: 1 addition & 8 deletions backend/app/controllers/spree/admin/payments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class PaymentsController < Spree::Admin::BaseController
before_filter :load_order, :only => [:create, :new, :index, :fire]
before_filter :load_payment, :except => [:create, :new, :index]
before_filter :load_data
before_filter :can_transition_to_payment
before_filter :can_not_transition_without_customer_info

respond_to :html

Expand Down Expand Up @@ -85,13 +85,6 @@ def load_data
end
end

def can_transition_to_payment
unless @order.billing_address.present?
flash[:notice] = Spree.t(:fill_in_customer_info)
redirect_to edit_admin_order_customer_url(@order)
end
end

def load_order
@order = Order.find_by_number!(params[:order_id])
authorize! action, @order
Expand Down
18 changes: 18 additions & 0 deletions backend/app/views/spree/admin/orders/_add_line_item.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<%= render :partial => "spree/admin/variants/autocomplete", :formats => :js %>

<%= render :partial => "spree/admin/variants/autocomplete_line_items_stock", :formats => :js %>


<div id="add-line-item" data-hook>
<fieldset class="no-border-bottom">
<legend align="center"><%= Spree.t(:add_product) %></legend>

<div data-hook="add_product_name" class="field twelve columns alpha">
<%= label_tag :add_line_item_variant_id, Spree.t(:name_or_sku) %>
<%= hidden_field_tag :add_line_item_variant_id, "", :class => "variant_autocomplete fullwidth" %>
</div>

</fieldset>

<div id="stock_details"></div>
</div>
Loading

0 comments on commit b252e9a

Please sign in to comment.