mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-15 04:14:24 +00:00
Add new 'Checkout options' step to the edit order cycle form so people can attach shipping methods
This commit is contained in:
committed by
Filipe
parent
1e817af5aa
commit
855ec1a708
@@ -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])
|
||||
|
||||
17
app/helpers/admin/order_cycles_helper.rb
Normal file
17
app/helpers/admin/order_cycles_helper.rb
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
29
app/services/order_available_shipping_methods.rb
Normal file
29
app/services/order_available_shipping_methods.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
83
app/views/admin/order_cycles/checkout_options.html.haml
Normal file
83
app/views/admin/order_cycles/checkout_options.html.haml
Normal 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
|
||||
= "—<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
|
||||
= "—<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')
|
||||
@@ -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
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
h5 {
|
||||
color: $spree-blue;
|
||||
|
||||
&.error {
|
||||
color: $red-500;
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user