Add new 'Checkout options' step to the edit order cycle form so people can attach shipping methods

This commit is contained in:
Cillian O'Ruanaidh
2022-06-08 21:15:38 +01:00
committed by Filipe
parent 1e817af5aa
commit 855ec1a708
16 changed files with 499 additions and 8 deletions

View File

@@ -2,10 +2,10 @@
module Admin
class OrderCyclesController < Admin::ResourceController
include OrderCyclesHelper
include ::OrderCyclesHelper
include PaperTrailLogging
prepend_before_action :set_order_cycle_id, only: [:incoming, :outgoing]
prepend_before_action :set_order_cycle_id, only: [:incoming, :outgoing, :checkout_options]
before_action :load_data_for_index, only: :index
before_action :require_coordinator, only: :new
before_action :remove_protected_attrs, only: [:update]
@@ -67,10 +67,12 @@ module Admin
update_nil_subscription_line_items_price_estimate(@order_cycle)
respond_to do |format|
flash[:notice] = I18n.t(:order_cycles_update_notice) if params[:reloading] == '1'
format.html { redirect_back(fallback_location: root_path) }
format.html { redirect_to_after_update_path }
format.json { render json: { success: true } }
end
else
elsif request.format.html?
render :checkout_options
elsif request.format.json?
render json: { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity
end
end
@@ -190,6 +192,16 @@ module Admin
end
end
def redirect_to_after_update_path
if params[:context] == "checkout_options" && params[:save]
redirect_to main_app.admin_order_cycle_checkout_options_path(@order_cycle)
elsif params[:context] == "checkout_options" && params[:save_and_back_to_list]
redirect_to main_app.admin_order_cycles_path
else
redirect_back(fallback_location: root_path)
end
end
def require_coordinator
@order_cycle.coordinator =
permitted_coordinating_enterprises_for(@order_cycle).find_by(id: params[:coordinator_id])

View File

@@ -0,0 +1,17 @@
# frozen_string_literal: true
module Admin
module OrderCyclesHelper
def order_cycle_shared_payment_methods(order_cycle)
order_cycle.attachable_payment_methods.select do |payment_method|
(payment_method.distributor_ids & order_cycle.distributor_ids).many?
end
end
def order_cycle_shared_shipping_methods(order_cycle)
order_cycle.attachable_shipping_methods.select do |shipping_method|
(shipping_method.distributor_ids & order_cycle.distributor_ids).many?
end
end
end
end

View File

@@ -156,6 +156,23 @@ class OrderCycle < ApplicationRecord
]
end
def attachable_payment_methods
Spree::PaymentMethod.available(:both).
joins("INNER JOIN distributors_payment_methods
ON payment_method_id = spree_payment_methods.id").
where("distributor_id IN (?)", distributor_ids).
distinct
end
def attachable_shipping_methods
return Spree::ShippingMethod.none if simple? || !shipping_methods_customisable?
Spree::ShippingMethod.frontend.
joins(:distributor_shipping_methods).
where("distributor_id IN (?)", distributor_ids).
distinct
end
def clone!
oc = dup
oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name)

View File

@@ -243,7 +243,9 @@ module Spree
end
def add_order_cycle_management_abilities(user)
can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle|
can [
:admin, :index, :read, :edit, :update, :incoming, :outgoing, :checkout_options
], OrderCycle do |order_cycle|
OrderCycle.visible_by(user).include? order_cycle
end
can [:admin, :index, :create], Schedule

View File

@@ -0,0 +1,29 @@
# frozen_string_literal: true
class OrderAvailableShippingMethods < Struct.new(:order, :customer)
delegate :distributor,
:order_cycle,
to: :order
def to_a
return [] if distributor.blank?
shipping_methods = shipping_methods_before_tag_rules_applied
applicator = OpenFoodNetwork::TagRuleApplicator.new(distributor,
"FilterShippingMethods", customer&.tag_list)
applicator.filter!(shipping_methods)
shipping_methods.uniq
end
private
def shipping_methods_before_tag_rules_applied
if order_cycle.nil? || order_cycle.simple?
distributor.shipping_methods
else
distributor.shipping_methods.where(id: order_cycle.shipping_methods.select(:id))
end.frontend.to_a
end
end

View File

@@ -17,7 +17,7 @@ module PermittedAttributes
:name, :orders_open_at, :orders_close_at, :coordinator_id,
:preferred_product_selection_from_coordinator_inventory_only,
:automatic_notifications,
{ schedule_ids: [], coordinator_fee_ids: [] }
{ schedule_ids: [], shipping_method_ids: [], coordinator_fee_ids: [] }
]
end

View File

@@ -6,6 +6,8 @@
= t("admin.order_cycles.wizard_progress.incoming")
%li
= t("admin.order_cycles.wizard_progress.outgoing")
%li
= t("admin.order_cycles.wizard_progress.checkout_options")
- else
%li{ class: "#{'current' if action_name == 'edit'}" }
%a{ href: main_app.edit_admin_order_cycle_path(@order_cycle) }
@@ -16,3 +18,6 @@
%li{ class: "#{'current' if action_name == 'outgoing'}" }
%a{ href: main_app.admin_order_cycle_outgoing_path(@order_cycle) }
= t("admin.order_cycles.wizard_progress.outgoing")
%li{ class: "#{'current' if action_name == 'checkout_options'}" }
%a{ href: main_app.admin_order_cycle_checkout_options_path(@order_cycle) }
= t("admin.order_cycles.wizard_progress.checkout_options")

View File

@@ -0,0 +1,83 @@
= render partial: "/admin/order_cycles/order_cycle_top_buttons"
- content_for :page_title do
= t :edit_order_cycle
- shared_payment_methods = order_cycle_shared_payment_methods(@order_cycle)
- shared_shipping_methods = order_cycle_shared_shipping_methods(@order_cycle)
= form_for [main_app, :admin, @order_cycle], html: { class: "order_cycle" } do |f|
= render 'wizard_progress'
%fieldset.no-border-bottom
%legend{ align: 'center'}= t('.checkout_options')
%table.checkout-options
%thead
%tr
%th= t('.distributor')
%th= t('.shipping_methods')
%th= t('.payment_methods')
- @order_cycle.distributors.each do |distributor|
- payment_methods = @order_cycle.attachable_payment_methods.where("distributor_id = ?", distributor.id).reject { |payment_method| shared_payment_methods.include?(payment_method) }
- shipping_methods = @order_cycle.attachable_shipping_methods.where("distributor_id = ?", distributor.id).reject { |shipping_method| shared_shipping_methods.include?(shipping_method) }
%tr
%td= distributor.name
%td
- shipping_methods.each do |shipping_method|
%p
%label
= check_box_tag "order_cycle[preferred_shipping_method_ids][]",
shipping_method.id, @order_cycle.shipping_methods.include?(shipping_method),
id: "order_cycle_preferred_shipping_method_ids_#{shipping_method.id}"
= shipping_method.name
- distributor.shipping_methods.backend.each do |shipping_method|
%label.disabled
= check_box_tag nil, nil, false, disabled: true
= shipping_method.name
= "(#{t('.back_end')})"
- if shipping_methods.none? && distributor.shipping_methods.backend.none?
%p.text-center
= t('.no_shipping_methods')
%td
- if payment_methods.any?
%ul
- payment_methods.each do |payment_method|
%li= payment_method.name
- else
%p.text-center
= t('.no_payment_methods')
- if shared_payment_methods.any? || shared_shipping_methods.any?
%tr
%td= t('.shared')
%td
- if shared_shipping_methods.any?
= f.collection_check_boxes :shipping_method_ids, shared_shipping_methods, :id, :name do |input|
- shared_shipping_method = input.object
%p
= input.check_box
= input.label
%p
= "&mdash;<em>#{shared_shipping_method.distributors.where(id: @order_cycle.distributor_ids).map(&:name).join(", ")}</em>".html_safe
%td
- if shared_payment_methods.any?
%ul
- shared_payment_methods.each do |shared_payment_method|
%li
= shared_payment_method.name
%p
= "&mdash;<em>#{shared_payment_method.distributors.where(id: @order_cycle.distributor_ids).map(&:name).join(", ")}</em>".html_safe
%div#save-bar
%div.container
%div.seven.columns.alpha
- if @order_cycle.errors.any?
%h5#status-message.error
= @order_cycle.errors.to_a.to_sentence
%div.nine.columns.omega.text-right
= hidden_field_tag :context, :checkout_options
= f.submit t('.save'), class: "red", name: :save
= f.submit t('.save_and_back_to_list'), class: "red", name: :save_and_back_to_list
%a.button.cancel{ href: main_app.admin_order_cycles_path }
= t('.cancel')

View File

@@ -10,7 +10,8 @@
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.save_and_back_to_list'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input.red{ type: "button", value: t('.save_and_next'), ng: { click: "submit($event, '#{main_app.admin_order_cycle_checkout_options_path(@order_cycle)}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
%input{ type: "button", value: t('.next'), ng: { click: "cancel('#{main_app.admin_order_cycle_checkout_options_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
%fieldset.no-border-bottom

View File

@@ -11,6 +11,10 @@
h5 {
color: $spree-blue;
&.error {
color: $red-500;
}
}
input {

View File

@@ -96,6 +96,14 @@ form.order_cycle {
.icon-question-sign {
font-size: 18px;
}
table.checkout-options {
ul {
margin-left: 1em;
}
p, li {
margin: 0.5em 0;
}
}
table.exchanges {
tr td.active {
width: 20px;