From 411388040149fcac506d9b0dfd0db0784b6c8242 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 26 Feb 2024 20:53:27 +1100 Subject: [PATCH] Move supplier to variant part 2 Variant model and specs --- app/models/spree/variant.rb | 19 +++++++-- spec/factories/order_cycle_factory.rb | 6 ++- spec/factories/variant_factory.rb | 5 ++- spec/models/spree/variant_spec.rb | 57 ++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 32f04ac651..7ab19c21da 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -13,8 +13,8 @@ module Spree acts_as_paranoid - searchable_attributes :sku, :display_as, :display_name, :primary_taxon_id - searchable_associations :product, :default_price, :primary_taxon + searchable_attributes :sku, :display_as, :display_name, :primary_taxon_id, :supplier_id + searchable_associations :product, :default_price, :primary_taxon, :supplier searchable_scopes :active, :deleted NAME_FIELDS = ["display_name", "display_as", "weight", "unit_value", "unit_description"].freeze @@ -29,6 +29,7 @@ module Spree belongs_to :tax_category, class_name: 'Spree::TaxCategory' belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', optional: false belongs_to :primary_taxon, class_name: 'Spree::Taxon', touch: true, optional: false + belongs_to :supplier, class_name: 'Enterprise', optional: false, touch: true delegate :name, :name=, :description, :description=, :meta_keywords, to: :product @@ -58,6 +59,7 @@ module Spree has_many :variant_overrides, dependent: :destroy has_many :inventory_items, dependent: :destroy has_many :semantic_links, dependent: :delete_all + has_many :supplier_properties, through: :supplier, source: :properties localize_number :price, :weight @@ -142,8 +144,17 @@ module Spree scope :stockable_by, lambda { |enterprise| return where("1=0") if enterprise.blank? - joins(:product). - where(spree_products: { id: Spree::Product.stockable_by(enterprise).select(:id) }) + permitted_producer_ids = EnterpriseRelationship.joins(:parent).permitting(enterprise.id) + .with_permission(:add_to_order_cycle) + .where(enterprises: { is_primary_producer: true }) + .pluck(:parent_id) + + where(supplier: [enterprise.id].union(permitted_producer_ids)) + } + + scope :with_properties, lambda { |property_ids| + left_outer_joins(:supplier_properties). + where(producer_properties: { property_id: property_ids }) } # Define sope as class method to allow chaining with other scopes filtering id. diff --git a/spec/factories/order_cycle_factory.rb b/spec/factories/order_cycle_factory.rb index 18c1fd7181..6693ece689 100644 --- a/spec/factories/order_cycle_factory.rb +++ b/spec/factories/order_cycle_factory.rb @@ -30,7 +30,11 @@ FactoryBot.define do # Products with images proxy.exchanges.incoming.each do |exchange| - product = create(:product, supplier: exchange.sender) + product = create(:product).tap do |p| + variant = p.variants.first + variant.supplier = exchange.sender + variant.save! + end Spree::Image.create( viewable_id: product.id, viewable_type: 'Spree::Product', diff --git a/spec/factories/variant_factory.rb b/spec/factories/variant_factory.rb index 3cb44c6344..3d134c73c4 100644 --- a/spec/factories/variant_factory.rb +++ b/spec/factories/variant_factory.rb @@ -12,7 +12,9 @@ FactoryBot.define do depth { generate(:random_float) } primary_taxon { Spree::Taxon.first || FactoryBot.create(:taxon) } - product { |p| p.association(:product) } + supplier { Enterprise.is_primary_producer.first || FactoryBot.create(:supplier_enterprise) } + + product { |p| p.association(:base_product) } # ensure stock item will be created for this variant before(:create) { create(:stock_location) if Spree::StockLocation.count.zero? } @@ -23,6 +25,7 @@ FactoryBot.define do on_hand { 5 } end + product { |p| p.association(:product) } unit_value { 1 } unit_description { '' } diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 3cea5ba96f..5e39aea27e 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -7,7 +7,24 @@ RSpec.describe Spree::Variant do subject(:variant) { build(:variant) } it { is_expected.to have_many :semantic_links } + it { is_expected.to belong_to(:supplier).required } + it { is_expected.to have_many(:supplier_properties) } + # TODO add test for the other associations + describe "supplier properties" do + subject { create(:variant) } + + it "has no supplier properties to start with" do + expect(subject.supplier_properties).to eq [] + end + + it "includes the supplier's properties" do + subject.supplier.set_producer_property("certified", "yes") + expect(subject.supplier_properties.map(&:presentation)).to eq ["certified"] + end + end + + # add test for the other validation context "validations" do it "should validate price is greater than 0" do variant.price = -1 @@ -266,6 +283,7 @@ RSpec.describe Spree::Variant do end describe "scopes" do + # TODO rename describer below with scope names describe "finding variants in a distributor" do let!(:d1) { create(:distributor_enterprise) } let!(:d2) { create(:distributor_enterprise) } @@ -410,15 +428,15 @@ RSpec.describe Spree::Variant do end end - describe 'stockable_by' do + describe '.stockable_by' do let(:shop) { create(:distributor_enterprise) } let(:add_to_oc_producer) { create(:supplier_enterprise) } let(:other_producer) { create(:supplier_enterprise) } - let!(:v1) { create(:variant, product: create(:simple_product, supplier: shop ) ) } + let!(:v1) { create(:variant, product: create(:simple_product), supplier: shop ) } let!(:v2) { - create(:variant, product: create(:simple_product, supplier: add_to_oc_producer ) ) + create(:variant, product: create(:simple_product), supplier: add_to_oc_producer ) } - let!(:v3) { create(:variant, product: create(:simple_product, supplier: other_producer ) ) } + let!(:v3) { create(:variant, product: create(:simple_product), supplier: other_producer ) } before do create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, @@ -433,6 +451,33 @@ RSpec.describe Spree::Variant do expect(stockable_variants).not_to include v3 end end + + describe ".with_properties" do + let!(:variant_without_wanted_property_on_supplier) { + create(:variant, supplier: supplier_without_wanted_property) + } + let!(:variant_with_wanted_property_on_supplier) { + create(:variant, supplier: supplier_with_wanted_property) + } + let(:supplier_with_wanted_property) { + create(:supplier_enterprise, properties: [wanted_property]) + } + let(:supplier_without_wanted_property) { + create(:supplier_enterprise, properties: [unwanted_property]) + } + let(:wanted_property) { create(:property, presentation: 'Certified Organic') } + let(:unwanted_property) { create(:property, presentation: 'Latest Hype') } + + it "returns no products without a property id" do + expect(Spree::Variant.with_properties([])).to eq [] + end + + it "returns only variants with the wanted property set on supplier" do + expect( + Spree::Variant.with_properties([wanted_property.id]) + ).to match_array [variant_with_wanted_property_on_supplier] + end + end end describe "indexing variants by id" do @@ -771,8 +816,8 @@ RSpec.describe Spree::Variant do let(:variant1) { create(:variant) } let(:variant2) { create(:variant) } let!(:order_cycle) do - enterprise1.supplied_products << variant1.product - enterprise2.supplied_products << variant2.product + enterprise1.supplied_variants << variant1 + enterprise2.supplied_variants << variant2 create( :simple_order_cycle, coordinator: enterprise1,