mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-26 20:56:48 +00:00
164 lines
5.0 KiB
Ruby
164 lines
5.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'open_food_network/permissions'
|
|
require 'open_food_network/order_cycle_form_applicator'
|
|
require 'order_management/subscriptions/proxy_order_syncer'
|
|
|
|
class OrderCycleForm
|
|
def initialize(order_cycle, order_cycle_params, user)
|
|
@order_cycle = order_cycle
|
|
@order_cycle_params = order_cycle_params
|
|
@specified_params = order_cycle_params.keys
|
|
@user = user
|
|
@permissions = OpenFoodNetwork::Permissions.new(user)
|
|
@schedule_ids = order_cycle_params.delete(:schedule_ids)
|
|
@selected_distributor_payment_method_ids = order_cycle_params.delete(
|
|
:selected_distributor_payment_method_ids
|
|
)
|
|
@selected_distributor_shipping_method_ids = order_cycle_params.delete(
|
|
:selected_distributor_shipping_method_ids
|
|
)
|
|
end
|
|
|
|
def save
|
|
schedule_ids = build_schedule_ids
|
|
order_cycle.assign_attributes(order_cycle_params)
|
|
return false unless order_cycle.valid?
|
|
|
|
order_cycle.transaction do
|
|
order_cycle.save!
|
|
order_cycle.schedule_ids = schedule_ids if parameter_specified?(:schedule_ids)
|
|
order_cycle.save!
|
|
apply_exchange_changes
|
|
attach_selected_distributor_payment_methods
|
|
attach_selected_distributor_shipping_methods
|
|
sync_subscriptions
|
|
true
|
|
end
|
|
rescue ActiveRecord::RecordInvalid => e
|
|
add_exception_to_order_cycle_errors(e)
|
|
false
|
|
end
|
|
|
|
private
|
|
|
|
attr_accessor :order_cycle, :order_cycle_params, :user, :permissions
|
|
|
|
def add_exception_to_order_cycle_errors(exception)
|
|
error = exception.message.split(":").last.strip
|
|
order_cycle.errors.add(:base, error) if order_cycle.errors.to_a.exclude?(error)
|
|
end
|
|
|
|
def apply_exchange_changes
|
|
return if exchanges_unchanged?
|
|
|
|
OpenFoodNetwork::OrderCycleFormApplicator.new(order_cycle, user).go!
|
|
|
|
# reload so outgoing exchanges are up-to-date for shipping/payment method validations
|
|
order_cycle.reload
|
|
end
|
|
|
|
def attach_selected_distributor_payment_methods
|
|
return if @selected_distributor_payment_method_ids.nil?
|
|
|
|
order_cycle.selected_distributor_payment_method_ids = selected_distributor_payment_method_ids
|
|
order_cycle.save!
|
|
end
|
|
|
|
def attach_selected_distributor_shipping_methods
|
|
return if @selected_distributor_shipping_method_ids.nil?
|
|
|
|
order_cycle.selected_distributor_shipping_method_ids = selected_distributor_shipping_method_ids
|
|
order_cycle.save!
|
|
end
|
|
|
|
def attachable_distributor_payment_method_ids
|
|
@attachable_distributor_payment_method_ids ||= order_cycle.attachable_distributor_payment_methods.map(&:id)
|
|
end
|
|
|
|
def attachable_distributor_shipping_method_ids
|
|
@attachable_distributor_shipping_method_ids ||= order_cycle.attachable_distributor_shipping_methods.map(&:id)
|
|
end
|
|
|
|
def exchanges_unchanged?
|
|
[:incoming_exchanges, :outgoing_exchanges].all? do |direction|
|
|
order_cycle_params[direction].nil?
|
|
end
|
|
end
|
|
|
|
def selected_distributor_payment_method_ids
|
|
@selected_distributor_payment_method_ids = (
|
|
attachable_distributor_payment_method_ids &
|
|
@selected_distributor_payment_method_ids.reject(&:blank?).map(&:to_i)
|
|
)
|
|
|
|
if attachable_distributor_payment_method_ids.sort == @selected_distributor_payment_method_ids.sort
|
|
@selected_distributor_payment_method_ids = []
|
|
end
|
|
|
|
@selected_distributor_payment_method_ids
|
|
end
|
|
|
|
def selected_distributor_shipping_method_ids
|
|
@selected_distributor_shipping_method_ids = (
|
|
attachable_distributor_shipping_method_ids &
|
|
@selected_distributor_shipping_method_ids.reject(&:blank?).map(&:to_i)
|
|
)
|
|
|
|
if attachable_distributor_shipping_method_ids.sort == @selected_distributor_shipping_method_ids.sort
|
|
@selected_distributor_shipping_method_ids = []
|
|
end
|
|
|
|
@selected_distributor_shipping_method_ids
|
|
end
|
|
|
|
def build_schedule_ids
|
|
return unless parameter_specified?(:schedule_ids)
|
|
|
|
result = existing_schedule_ids
|
|
result |= (requested_schedule_ids & permitted_schedule_ids) # Add permitted and requested
|
|
result -= ((result & permitted_schedule_ids) - requested_schedule_ids) # Remove permitted but not requested
|
|
result
|
|
end
|
|
|
|
def sync_subscriptions
|
|
return unless parameter_specified?(:schedule_ids)
|
|
return unless schedule_sync_required?
|
|
|
|
OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscriptions_to_sync).sync!
|
|
end
|
|
|
|
def schedule_sync_required?
|
|
removed_schedule_ids.any? || new_schedule_ids.any?
|
|
end
|
|
|
|
def subscriptions_to_sync
|
|
Subscription.where(schedule_id: removed_schedule_ids + new_schedule_ids)
|
|
end
|
|
|
|
def requested_schedule_ids
|
|
@schedule_ids.map(&:to_i)
|
|
end
|
|
|
|
def parameter_specified?(key)
|
|
@specified_params.map(&:to_s).include?(key.to_s)
|
|
end
|
|
|
|
def permitted_schedule_ids
|
|
Schedule.where(id: requested_schedule_ids | existing_schedule_ids)
|
|
.merge(permissions.editable_schedules).pluck(:id)
|
|
end
|
|
|
|
def existing_schedule_ids
|
|
@existing_schedule_ids ||= order_cycle.persisted? ? order_cycle.schedule_ids : []
|
|
end
|
|
|
|
def removed_schedule_ids
|
|
existing_schedule_ids - order_cycle.schedule_ids
|
|
end
|
|
|
|
def new_schedule_ids
|
|
@order_cycle.schedule_ids - existing_schedule_ids
|
|
end
|
|
end
|