require 'spree/core/controller_helpers/order_decorator' require 'spree/core/controller_helpers/auth_decorator' module Spree class OrdersController < Spree::StoreController include OrderCyclesHelper layout 'darkswarm' ssl_required :show before_filter :check_authorization rescue_from ActiveRecord::RecordNotFound, with: :render_404 helper 'spree/products', 'spree/orders' respond_to :html respond_to :json before_filter :update_distribution, only: :update before_filter :filter_order_params, only: :update before_filter :enable_embedded_shopfront prepend_before_filter :require_order_authentication, only: :show prepend_before_filter :require_order_cycle, only: :edit prepend_before_filter :require_distributor_chosen, only: :edit before_filter :check_hub_ready_for_checkout, only: :edit before_filter :check_at_least_one_line_item, only: :update def show @order = Spree::Order.find_by_number!(params[:id]) end def empty if @order = current_order @order.empty! end 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) @insufficient_stock_lines = @order.insufficient_stock_lines @unavailable_order_variants = OrderCycleDistributedVariants. new(current_order_cycle, current_distributor).unavailable_order_variants(@order) if @order.line_items.empty? redirect_to main_app.shop_path else associate_user if @order.insufficient_stock_lines.present? || @unavailable_order_variants.present? flash[:error] = t("spree.orders.error_flash_for_unavailable_items") end end end def update @insufficient_stock_lines = [] @order = order_to_update unless @order flash[:error] = t(:order_not_found) redirect_to(root_path) && return end if @order.update_attributes(params[:order]) discard_empty_line_items with_open_adjustments { update_totals_and_taxes } if @order == current_order fire_event('spree.order.contents_changed') else @order.update_distribution_charge! end respond_with(@order) do |format| format.html do if params.key?(:checkout) @order.next_transition.run_callbacks if @order.cart? redirect_to checkout_state_path(@order.checkout_steps.first) elsif @order.complete? redirect_to order_path(@order) else redirect_to main_app.cart_path end end end else # Show order with original values, not newly entered ones @insufficient_stock_lines = @order.insufficient_stock_lines @order.line_items(true) respond_with(@order) end end def update_distribution @order = current_order(true) if params[:commit] == 'Choose Hub' distributor = Enterprise.is_distributor.find params[:order][:distributor_id] @order.set_distributor! distributor flash[:notice] = I18n.t(:order_choosing_hub_notice) redirect_to request.referer elsif params[:commit] == 'Choose Order Cycle' @order.empty! # empty cart order_cycle = OrderCycle.active.find params[:order][:order_cycle_id] @order.set_order_cycle! order_cycle flash[:notice] = I18n.t(:order_choosing_hub_notice) redirect_to request.referer end 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 clear @order = current_order(true) @order.empty! @order.set_order_cycle! nil redirect_to main_app.enterprise_path(@order.distributor.id) end def order_cycle_expired @order_cycle = OrderCycle.find session[:expired_order_cycle_id] end def cancel @order = Spree::Order.find_by_number!(params[:id]) authorize! :cancel, @order if @order.cancel flash[:success] = I18n.t(:orders_your_order_has_been_cancelled) else flash[:error] = I18n.t(:orders_could_not_cancel) end redirect_to request.referer || order_path(@order) end private # Updates the various denormalized total attributes of the order and # recalculates the shipment taxes def update_totals_and_taxes @order.updater.update_totals @order.shipment.ensure_correct_adjustment_with_included_tax if @order.shipment end # Sets the adjustments to open to perform the block's action and restores # their state to whatever the they had. Note that it does not change any new # adjustments that might get created in the yielded block. def with_open_adjustments previous_states = @order.adjustments.each_with_object({}) do |adjustment, hash| hash[adjustment.id] = adjustment.state end @order.adjustments.each { |adjustment| adjustment.fire_events(:open) } yield @order.adjustments.each do |adjustment| previous_state = previous_states[adjustment.id] adjustment.update_attribute(:state, previous_state) if previous_state end end def discard_empty_line_items @order.line_items = @order.line_items.select { |li| li.quantity > 0 } end def require_order_authentication return if session[:access_token] || params[:token] || spree_current_user flash[:error] = I18n.t("spree.orders.edit.login_to_view_order") require_login_then_redirect_to request.env['PATH_INFO'] end def order_to_update return @order_to_update if defined? @order_to_update return @order_to_update = current_order unless params[:id] @order_to_update = changeable_order_from_number end # If a specific order is requested, return it if it is COMPLETE and # changes are allowed and the user has access. Return nil if not. def changeable_order_from_number order = Spree::Order.complete.find_by_number(params[:id]) return nil unless order.andand.changes_allowed? && can?(:update, order) order end def check_at_least_one_line_item return unless order_to_update.andand.complete? items = params[:order][:line_items_attributes] .andand.select{ |_k, attrs| attrs["quantity"].to_i > 0 } if items.empty? flash[:error] = I18n.t(:orders_cannot_remove_the_final_item) redirect_to order_path(order_to_update) end end end end