Move OFN::SubscriptionService to SubscriptionVariantsService

This commit is contained in:
Kristina Lim
2019-01-20 23:18:52 +11:00
parent c23002102c
commit b691d727a7
8 changed files with 170 additions and 180 deletions

View File

@@ -1,7 +1,6 @@
require 'open_food_network/permissions'
require 'open_food_network/order_cycle_permissions'
require 'open_food_network/scope_variant_to_hub'
require "open_food_network/subscription_service"
module Admin
class SubscriptionLineItemsController < ResourceController
@@ -54,7 +53,7 @@ module Admin
end
def variant_if_eligible(variant_id)
OpenFoodNetwork::SubscriptionService.eligible_variants(@shop).find_by_id(variant_id)
SubscriptionVariantsService.eligible_variants(@shop).find_by_id(variant_id)
end
end
end

View File

@@ -13,9 +13,9 @@ module Api
end
def in_open_and_upcoming_order_cycles
OpenFoodNetwork::SubscriptionService
.in_open_and_upcoming_order_cycles?(option_or_assigned_shop, option_or_assigned_schedule,
object.variant)
SubscriptionVariantsService.in_open_and_upcoming_order_cycles?(option_or_assigned_shop,
option_or_assigned_schedule,
object.variant)
end
private

View File

@@ -2,8 +2,6 @@
# Public interface consists of #valid? method provided by ActiveModel::Validations
# and #json_errors which compiles a serializable hash of errors
require "open_food_network/subscription_service"
class SubscriptionValidator
include ActiveModel::Naming
include ActiveModel::Conversion
@@ -103,7 +101,7 @@ class SubscriptionValidator
return @available_variant_ids if @available_variant_ids.present?
subscription_variant_ids = subscription_line_items.map(&:variant_id)
@available_variant_ids = OpenFoodNetwork::SubscriptionService.eligible_variants(shop)
@available_variant_ids = SubscriptionVariantsService.eligible_variants(shop)
.where(id: subscription_variant_ids).pluck(:id)
end

View File

@@ -0,0 +1,34 @@
class SubscriptionVariantsService
# Includes the following variants:
# - Variants of permitted producers
# - Variants of hub
# - Variants that are in outgoing exchanges where the hub is receiver
def self.eligible_variants(distributor)
permitted_order_cycle_enterprise_ids = EnterpriseRelationship.permitting(distributor)
.with_permission(:add_to_order_cycle).pluck(:parent_id)
permitted_producer_ids = Enterprise.is_primary_producer
.where('enterprises.id IN (?)', permitted_order_cycle_enterprise_ids).pluck(:id)
outgoing_exchange_variant_ids = ExchangeVariant
.select("DISTINCT exchange_variants.variant_id")
.joins(:exchange)
.where(exchanges: { incoming: false, receiver_id: distributor.id })
.pluck(:variant_id)
variant_conditions = ["spree_products.supplier_id IN (?)", permitted_producer_ids | [distributor.id]]
if outgoing_exchange_variant_ids.present?
variant_conditions[0] << " OR spree_variants.id IN (?)"
variant_conditions << outgoing_exchange_variant_ids
end
Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions)
end
def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant)
scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules })
.where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor })
.merge(OrderCycle.not_closed)
scope = scope.where(schedules: { id: schedule })
scope.any?
end
end

View File

@@ -5,8 +5,6 @@ require 'open_food_network/scope_variant_to_hub'
# Further restrictions on the schedule, order_cycle or distributor through which the
# products are available are also possible
require "open_food_network/subscription_service"
module OpenFoodNetwork
class ScopeVariantsForSearch
def initialize(params)
@@ -61,7 +59,7 @@ module OpenFoodNetwork
end
def scope_to_eligible_for_subscriptions_in_distributor
eligible_variants_scope = OpenFoodNetwork::SubscriptionService.eligible_variants(distributor)
eligible_variants_scope = SubscriptionVariantsService.eligible_variants(distributor)
@variants = @variants.merge(eligible_variants_scope)
scope_variants_to_distributor(@variants, distributor)
end

View File

@@ -1,36 +0,0 @@
module OpenFoodNetwork
class SubscriptionService
# Includes the following variants:
# - Variants of permitted producers
# - Variants of hub
# - Variants that are in outgoing exchanges where the hub is receiver
def self.eligible_variants(distributor)
permitted_order_cycle_enterprise_ids = EnterpriseRelationship.permitting(distributor)
.with_permission(:add_to_order_cycle).pluck(:parent_id)
permitted_producer_ids = Enterprise.is_primary_producer
.where('enterprises.id IN (?)', permitted_order_cycle_enterprise_ids).pluck(:id)
outgoing_exchange_variant_ids = ExchangeVariant
.select("DISTINCT exchange_variants.variant_id")
.joins(:exchange)
.where(exchanges: { incoming: false, receiver_id: distributor.id })
.pluck(:variant_id)
variant_conditions = ["spree_products.supplier_id IN (?)", permitted_producer_ids | [distributor.id]]
if outgoing_exchange_variant_ids.present?
variant_conditions[0] << " OR spree_variants.id IN (?)"
variant_conditions << outgoing_exchange_variant_ids
end
Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions)
end
def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant)
scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules })
.where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor })
.merge(OrderCycle.not_closed)
scope = scope.where(schedules: { id: schedule })
scope.any?
end
end
end

View File

@@ -1,133 +0,0 @@
require "spec_helper"
require "open_food_network/subscription_service"
module OpenFoodNetwork
describe SubscriptionService do
describe "variant eligibility for subscription" do
let!(:shop) { create(:distributor_enterprise) }
let!(:producer) { create(:supplier_enterprise) }
let!(:product) { create(:product, supplier: producer) }
let!(:variant) { product.variants.first }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) }
let!(:subscription_line_item) do
create(:subscription_line_item, subscription: subscription, variant: variant)
end
let(:current_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago,
orders_close_at: 1.week.from_now)
end
let(:future_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now,
orders_close_at: 2.weeks.from_now)
end
let(:past_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago,
orders_close_at: 1.week.ago)
end
let!(:order_cycle) { current_order_cycle }
context "if the shop is the supplier for the product" do
let!(:producer) { shop }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the supplier is permitted for the shop" do
let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, parent: product.supplier, permissions_list: [:add_to_order_cycle]) }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the variant is involved in an exchange" do
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
context "if it is an incoming exchange where the shop is the receiver" do
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
it "is not eligible" do
expect(described_class.eligible_variants(shop)).to_not include(variant)
end
end
context "if it is an outgoing exchange where the shop is the receiver" do
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
context "if the order cycle is currently open" do
let!(:order_cycle) { current_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the order cycle opens in the future" do
let!(:order_cycle) { future_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the order cycle closed in the past" do
let!(:order_cycle) { past_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
end
end
context "if the variant is unrelated" do
it "is not eligible" do
expect(described_class.eligible_variants(shop)).to_not include(variant)
end
end
end
describe "checking if variant in open and upcoming order cycles" do
let!(:shop) { create(:enterprise) }
let!(:product) { create(:product) }
let!(:variant) { product.variants.first }
let!(:schedule) { create(:schedule) }
context "if the variant is involved in an exchange" do
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
context "if it is an incoming exchange where the shop is the receiver" do
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
it "is is false" do
expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
context "if it is an outgoing exchange where the shop is the receiver" do
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
it "is true" do
expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
end
context "if the variant is unrelated" do
it "is false" do
expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
end
end
end

View File

@@ -0,0 +1,130 @@
require "spec_helper"
describe SubscriptionVariantsService do
describe "variant eligibility for subscription" do
let!(:shop) { create(:distributor_enterprise) }
let!(:producer) { create(:supplier_enterprise) }
let!(:product) { create(:product, supplier: producer) }
let!(:variant) { product.variants.first }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) }
let!(:subscription_line_item) do
create(:subscription_line_item, subscription: subscription, variant: variant)
end
let(:current_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago,
orders_close_at: 1.week.from_now)
end
let(:future_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now,
orders_close_at: 2.weeks.from_now)
end
let(:past_order_cycle) do
create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago,
orders_close_at: 1.week.ago)
end
let!(:order_cycle) { current_order_cycle }
context "if the shop is the supplier for the product" do
let!(:producer) { shop }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the supplier is permitted for the shop" do
let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, parent: product.supplier, permissions_list: [:add_to_order_cycle]) }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the variant is involved in an exchange" do
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
context "if it is an incoming exchange where the shop is the receiver" do
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
it "is not eligible" do
expect(described_class.eligible_variants(shop)).to_not include(variant)
end
end
context "if it is an outgoing exchange where the shop is the receiver" do
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
context "if the order cycle is currently open" do
let!(:order_cycle) { current_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the order cycle opens in the future" do
let!(:order_cycle) { future_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
context "if the order cycle closed in the past" do
let!(:order_cycle) { past_order_cycle }
it "is eligible" do
expect(described_class.eligible_variants(shop)).to include(variant)
end
end
end
end
context "if the variant is unrelated" do
it "is not eligible" do
expect(described_class.eligible_variants(shop)).to_not include(variant)
end
end
end
describe "checking if variant in open and upcoming order cycles" do
let!(:shop) { create(:enterprise) }
let!(:product) { create(:product) }
let!(:variant) { product.variants.first }
let!(:schedule) { create(:schedule) }
context "if the variant is involved in an exchange" do
let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) }
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
context "if it is an incoming exchange where the shop is the receiver" do
let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) }
it "is is false" do
expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
context "if it is an outgoing exchange where the shop is the receiver" do
let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) }
it "is true" do
expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
end
context "if the variant is unrelated" do
it "is false" do
expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant)
end
end
end
end