diff --git a/app/models/standing_line_item.rb b/app/models/standing_line_item.rb index 6f4372d4cf..70d0eebf82 100644 --- a/app/models/standing_line_item.rb +++ b/app/models/standing_line_item.rb @@ -1,4 +1,8 @@ +require 'open_food_network/standing_line_item_updater' + class StandingLineItem < ActiveRecord::Base + include OpenFoodNetwork::StandingLineItemUpdater + belongs_to :standing_order, inverse_of: :standing_line_items belongs_to :variant, class_name: 'Spree::Variant' @@ -6,6 +10,8 @@ class StandingLineItem < ActiveRecord::Base validates :variant, presence: true validates :quantity, { presence: true, numericality: { only_integer: true } } + before_save :update_line_items! # In OpenFoodNetwork::StandingLineItemUpdater + def available_from?(shop, schedule) Spree::Variant.joins(exchanges: { order_cycle: :schedules}) .where(id: variant_id, schedules: { id: schedule}, exchanges: { incoming: false, receiver_id: shop }) diff --git a/app/models/standing_order.rb b/app/models/standing_order.rb index e27e8be1fd..29db805d57 100644 --- a/app/models/standing_order.rb +++ b/app/models/standing_order.rb @@ -3,6 +3,8 @@ require 'open_food_network/standing_order_updater' class StandingOrder < ActiveRecord::Base include OpenFoodNetwork::StandingOrderUpdater + before_save :update_orders! + belongs_to :shop, class_name: 'Enterprise' belongs_to :customer belongs_to :schedule @@ -26,8 +28,6 @@ class StandingOrder < ActiveRecord::Base validate :standing_line_items_available validate :check_associations - after_save :update_orders! - def ends_at_after_begins_at if begins_at.present? && ends_at.present? && ends_at <= begins_at errors.add(:ends_at, "must be after begins at") diff --git a/lib/open_food_network/standing_line_item_updater.rb b/lib/open_food_network/standing_line_item_updater.rb new file mode 100644 index 0000000000..1834448bde --- /dev/null +++ b/lib/open_food_network/standing_line_item_updater.rb @@ -0,0 +1,35 @@ +module OpenFoodNetwork + module StandingLineItemUpdater + + attr_accessor :altered_orders + + def update_line_items! + altered_orders ||= [] + attr_names.each do |attr_name| + unaltered_line_items(attr_name).update_all(:"#{attr_name}" => send(attr_name)) + if altered_line_items(attr_name).any? + altered_orders |= altered_line_items(attr_name).map(&:order) + end + end + end + + private + + def attr_names + [:quantity] + end + + def unaltered_line_items(attr_name) + return line_items_from_future_and_undated_orders unless persisted? + line_items_from_future_and_undated_orders.where("#{attr_name} = (?)", send("#{attr_name}_was")) + end + + def altered_line_items(attr_name) + line_items_from_future_and_undated_orders - unaltered_line_items(attr_name) + end + + def line_items_from_future_and_undated_orders + Spree::LineItem.where(order_id: standing_order.future_and_undated_orders, variant_id: variant_id) + end + end +end diff --git a/lib/open_food_network/standing_order_updater.rb b/lib/open_food_network/standing_order_updater.rb index ef090581a7..1c34084614 100644 --- a/lib/open_food_network/standing_order_updater.rb +++ b/lib/open_food_network/standing_order_updater.rb @@ -23,6 +23,10 @@ module OpenFoodNetwork end end + def future_and_undated_orders + orders.joins(:order_cycle).merge(OrderCycle.not_closed) + end + private def create_order_for(order_cycle_id) diff --git a/spec/lib/open_food_network/standing_order_updater_spec.rb b/spec/lib/open_food_network/standing_order_updater_spec.rb index 3b060c161b..35645fef47 100644 --- a/spec/lib/open_food_network/standing_order_updater_spec.rb +++ b/spec/lib/open_food_network/standing_order_updater_spec.rb @@ -111,5 +111,16 @@ module OpenFoodNetwork end end end + + describe "changing the quantity of a line item" do + let(:standing_order) { create(:standing_order_with_items) } + + it "updates the quantity on all orders" do + sli = standing_order.standing_line_items.first + sli.update_attribute(:quantity, 4) + line_items = Spree::LineItem.where(order_id: standing_order.orders, variant_id: sli.variant_id) + expect(line_items.map(&:quantity)).to eq [4] + end + end end end