mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-25 20:46:48 +00:00
It allowed introspection of a dynamic state machine. But the only two usages of this method only referred to the first state which is always the same. Our complicated checkout logic needs more clarity and introducing some hardcoded state names here can only help.
197 lines
5.9 KiB
Ruby
197 lines
5.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Spree
|
|
class OrdersController < ::BaseController
|
|
include OrderCyclesHelper
|
|
include Rails.application.routes.url_helpers
|
|
include CablecarResponses
|
|
include WhiteLabel
|
|
|
|
layout 'darkswarm'
|
|
|
|
rescue_from ActiveRecord::RecordNotFound, with: :render_404
|
|
helper 'spree/orders'
|
|
|
|
respond_to :html, :json
|
|
|
|
before_action :check_authorization
|
|
before_action :set_order_from_params, only: :show
|
|
before_action :set_current_order, only: [:edit, :update]
|
|
before_action :filter_order_params, only: :update
|
|
|
|
prepend_before_action :require_order_authentication, only: :show
|
|
prepend_before_action :require_order_cycle, only: :edit
|
|
prepend_before_action :require_distributor_chosen, only: :edit
|
|
before_action :check_hub_ready_for_checkout, only: :edit
|
|
before_action :check_at_least_one_line_item, only: :update
|
|
|
|
before_action only: [:show, :edit] do
|
|
hide_ofn_navigation(@order.distributor)
|
|
end
|
|
|
|
def show; end
|
|
|
|
def empty
|
|
if @order = current_order
|
|
@order.empty!
|
|
end
|
|
|
|
redirect_to main_app.cart_path
|
|
end
|
|
|
|
# Patching to redirect to shop if order is empty
|
|
def edit
|
|
@insufficient_stock_lines = @order.insufficient_stock_lines
|
|
@unavailable_order_variants = OrderCycles::DistributedVariantsService.
|
|
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.now[: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(main_app.root_path) && return
|
|
end
|
|
|
|
# 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.
|
|
if @order.contents.update_cart(order_params)
|
|
@order.recreate_all_fees! # Enterprise fees on line items and on the order itself
|
|
|
|
# Re apply the voucher
|
|
VoucherAdjustmentsService.new(@order).update
|
|
@order.update_totals_and_states
|
|
|
|
if @order.complete?
|
|
@order.update_payment_fees!
|
|
@order.create_tax_charge!
|
|
end
|
|
|
|
respond_with(@order) do |format|
|
|
format.html do
|
|
if params.key?(:checkout)
|
|
@order.next_transition.run_callbacks if @order.cart?
|
|
redirect_to main_app.checkout_step_path("address")
|
|
elsif @order.complete?
|
|
redirect_to main_app.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.reload
|
|
respond_with(@order)
|
|
end
|
|
end
|
|
|
|
def cancel
|
|
@order = Spree::Order.find_by!(number: params[:id])
|
|
authorize! :cancel, @order
|
|
|
|
if Orders::CustomerCancellationService.new(@order).call
|
|
flash[:success] = I18n.t(:orders_your_order_has_been_cancelled)
|
|
else
|
|
flash[:error] = I18n.t(:orders_could_not_cancel)
|
|
end
|
|
render status: :found,
|
|
cable_ready: cable_car.redirect_to(url: request.referer || main_app.order_path(@order))
|
|
end
|
|
|
|
private
|
|
|
|
def set_order_from_params
|
|
@order = Spree::Order.find_by!(number: params[:id])
|
|
end
|
|
|
|
def set_current_order
|
|
@order = current_order(true)
|
|
end
|
|
|
|
def check_authorization
|
|
session[:access_token] ||= params[:order_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
|
|
|
|
def filter_order_params
|
|
return unless params[:order] && params[:order][:line_items_attributes]
|
|
|
|
params[:order][:line_items_attributes] =
|
|
remove_missing_line_items(params[:order][:line_items_attributes])
|
|
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
|
|
|
|
def require_order_authentication
|
|
return if session[:access_token] || params[:order_token] || spree_current_user
|
|
|
|
store_location_for :spree_user, request.original_fullpath
|
|
|
|
flash[:error] = I18n.t("spree.orders.edit.login_to_view_order")
|
|
redirect_to main_app.root_path(anchor: "/login", after_login: request.original_fullpath)
|
|
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&.changes_allowed? && can?(:update, order)
|
|
|
|
order
|
|
end
|
|
|
|
def check_at_least_one_line_item
|
|
return unless order_to_update&.complete?
|
|
|
|
items = params[:order][:line_items_attributes]
|
|
&.select{ |_k, attrs| attrs["quantity"].to_i > 0 }
|
|
|
|
return unless items.empty?
|
|
|
|
flash[:error] = I18n.t(:orders_cannot_remove_the_final_item)
|
|
redirect_to main_app.order_path(order_to_update)
|
|
end
|
|
|
|
def order_params
|
|
params.require(:order).permit(
|
|
:distributor_id, :order_cycle_id,
|
|
line_items_attributes: [:id, :quantity]
|
|
)
|
|
end
|
|
end
|
|
end
|