From d1dd56372054dbfefa28d65ccca17735d2412ada Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 26 Feb 2024 16:23:09 +1100 Subject: [PATCH 001/145] Move supplier to variant part 1 --- app/models/spree/product.rb | 41 ++- ...20240221060301_add_supplier_to_variants.rb | 5 + db/schema.rb | 3 + spec/factories/product_factory.rb | 2 - spec/models/spree/product_spec.rb | 236 +++++++++--------- 5 files changed, 145 insertions(+), 142 deletions(-) create mode 100644 db/migrate/20240221060301_add_supplier_to_variants.rb diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 1f79ebf95c..7df8c7b357 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -29,12 +29,10 @@ module Spree acts_as_paranoid - searchable_attributes :supplier_id, :meta_keywords, :sku - searchable_associations :supplier, :properties, :variants + searchable_attributes :meta_keywords, :sku + searchable_associations :properties, :variants searchable_scopes :active, :with_properties - belongs_to :supplier, class_name: 'Enterprise', optional: false, touch: true - has_one :image, class_name: "Spree::Image", as: :viewable, dependent: :destroy has_many :product_properties, dependent: :destroy @@ -45,7 +43,6 @@ module Spree has_many :prices, -> { order('spree_variants.id, currency') }, through: :variants has_many :stock_items, through: :variants - has_many :supplier_properties, through: :supplier, source: :properties has_many :variant_images, -> { order(:position) }, source: :images, through: :variants @@ -79,14 +76,11 @@ module Spree around_destroy :destruction after_save :update_units + # -- Scopes scope :with_properties, ->(*property_ids) { left_outer_joins(:product_properties). - left_outer_joins(:supplier_properties). where(inherits_properties: true). - where(producer_properties: { property_id: property_ids }). - or( - where(spree_product_properties: { property_id: property_ids }) - ) + where(spree_product_properties: { property_id: property_ids }) } scope :with_order_cycles_outer, -> { @@ -126,8 +120,9 @@ module Spree distinct } - # -- Scopes - scope :in_supplier, lambda { |supplier| where(supplier_id: supplier) } + scope :in_supplier, lambda { |supplier| + joins(:variants).where(spree_variants: { supplier: }) + } # Products distributed via the given distributor through an OC scope :in_distributor, lambda { |distributor| @@ -149,10 +144,10 @@ module Spree enterprise = enterprise.respond_to?(:id) ? enterprise.id : enterprise.to_i with_order_cycles_outer. - where(" - spree_products.supplier_id = ? - OR (o_exchanges.incoming = ? AND o_exchanges.receiver_id = ?) - ", enterprise, false, enterprise). + in_supplier(enterprise). + or( + where(o_exchanges: { incoming: false, receiver_id: enterprise }) + ). select('distinct spree_products.*') } @@ -170,14 +165,14 @@ module Spree where.not(order_cycles: { id: nil }) } - scope :by_producer, -> { joins(:supplier).order('enterprises.name') } - scope :by_name, -> { order('name') } + scope :by_producer, -> { joins(variants: :supplier).order('enterprises.name') } + scope :by_name, -> { order('spree_products.name') } scope :managed_by, lambda { |user| if user.has_spree_role?('admin') where(nil) else - where(supplier_id: user.enterprises.select("enterprises.id")) + in_supplier(user.enterprises) end } @@ -188,7 +183,8 @@ module Spree .with_permission(:add_to_order_cycle) .where(enterprises: { is_primary_producer: true }) .pluck(:parent_id) - where(spree_products: { supplier_id: [enterprise.id] | permitted_producer_ids }) + + in_supplier([enterprise.id].union(permitted_producer_ids)) } scope :active, lambda { where(spree_products: { deleted_at: nil }) } @@ -236,7 +232,10 @@ module Spree ps = product_properties.all if inherits_properties - ps = OpenFoodNetwork::PropertyMerge.merge(ps, supplier.producer_properties) + # NOTE: Set the supplier as the first variant supplier. If variants have different supplier, + # result might not be correct + supplier = variants.first.supplier + ps = OpenFoodNetwork::PropertyMerge.merge(ps, supplier&.producer_properties || []) end ps. diff --git a/db/migrate/20240221060301_add_supplier_to_variants.rb b/db/migrate/20240221060301_add_supplier_to_variants.rb new file mode 100644 index 0000000000..84eea57fd2 --- /dev/null +++ b/db/migrate/20240221060301_add_supplier_to_variants.rb @@ -0,0 +1,5 @@ +class AddSupplierToVariants < ActiveRecord::Migration[7.0] + def change + add_reference :spree_variants, :supplier, foreign_key: { to_table: :enterprises } + end +end diff --git a/db/schema.rb b/db/schema.rb index ba68c5c4b6..e8b49d884d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -977,10 +977,12 @@ ActiveRecord::Schema[7.0].define(version: 2024_06_25_024328) do t.bigint "tax_category_id" t.bigint "shipping_category_id" t.bigint "primary_taxon_id" + t.bigint "supplier_id" t.index ["primary_taxon_id"], name: "index_spree_variants_on_primary_taxon_id" t.index ["product_id"], name: "index_variants_on_product_id" t.index ["shipping_category_id"], name: "index_spree_variants_on_shipping_category_id" t.index ["sku"], name: "index_spree_variants_on_sku" + t.index ["supplier_id"], name: "index_spree_variants_on_supplier_id" t.index ["tax_category_id"], name: "index_spree_variants_on_tax_category_id" t.check_constraint "unit_value > 0::double precision", name: "positive_unit_value" end @@ -1221,6 +1223,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_06_25_024328) do add_foreign_key "spree_taxons", "spree_taxons", column: "parent_id", name: "spree_taxons_parent_id_fk" add_foreign_key "spree_users", "spree_addresses", column: "bill_address_id", name: "spree_users_bill_address_id_fk" add_foreign_key "spree_users", "spree_addresses", column: "ship_address_id", name: "spree_users_ship_address_id_fk" + add_foreign_key "spree_variants", "enterprises", column: "supplier_id" add_foreign_key "spree_variants", "spree_products", column: "product_id", name: "spree_variants_product_id_fk" add_foreign_key "spree_variants", "spree_shipping_categories", column: "shipping_category_id" add_foreign_key "spree_variants", "spree_tax_categories", column: "tax_category_id" diff --git a/spec/factories/product_factory.rb b/spec/factories/product_factory.rb index 8e1d5e64c7..454a1bd689 100644 --- a/spec/factories/product_factory.rb +++ b/spec/factories/product_factory.rb @@ -14,8 +14,6 @@ FactoryBot.define do sku { 'ABC' } deleted_at { nil } - supplier { Enterprise.is_primary_producer.first || FactoryBot.create(:supplier_enterprise) } - unit_value { 1 } unit_description { '' } diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 26733c8759..0293b27888 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -10,6 +10,10 @@ module Spree context '#duplicate' do it 'duplicates product' do + variant = product.variants.first + variant.supplier = create(:supplier_enterprise) + variant.save! + clone = product.duplicate expect(clone).to be_persisted @@ -84,65 +88,6 @@ module Spree end end - describe "supplier properties" do - subject { create(:product) } - - it "has no supplier properties to start with" do - expect(subject.supplier_properties).to eq [] - end - - it "doesn't include product properties" do - subject.set_property("certified", "organic") - 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 - - describe ".with_properties scope" do - let!(:product_without_wanted_property_on_supplier) { - create(:product, supplier: supplier_without_wanted_property) - } - let!(:product_with_wanted_property_on_supplier) { - create(:product, supplier: supplier_with_wanted_property) - } - let!(:product_with_wanted_property) { create(:product, properties: [wanted_property]) } - let!(:product_without_wanted_property_property) { - create(:product, properties: [unwanted_property]) - } - let!(:product_with_wanted_property_and_on_supplier) { - create(:product, properties: [wanted_property], supplier: supplier_with_wanted_property) - } - let!(:product_ignoring_property) { - create(:product, supplier: supplier_with_wanted_property, inherits_properties: false) - } - 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::Product.with_properties([])).to eq [] - end - - it "returns only products with the wanted property set both on supplier & product itself" do - expect( - Spree::Product.with_properties([wanted_property.id]) - ).to match_array [ - product_with_wanted_property_on_supplier, - product_with_wanted_property, - product_with_wanted_property_and_on_supplier - ] - end - end - describe '#total_on_hand' do it 'returns sum of stock items count_on_hand' do product = build(:product) @@ -162,10 +107,6 @@ module Spree end end - describe "associations" do - it { is_expected.to belong_to(:supplier).required } - end - describe "validations and defaults" do it "is valid when built from factory" do expect(build(:product)).to be_valid @@ -196,10 +137,6 @@ module Spree end end - it "requires a supplier" do - expect(build(:simple_product, supplier: nil)).not_to be_valid - end - context "when the product has variants" do let(:product) do product = create(:simple_product) @@ -238,7 +175,6 @@ module Spree before do create(:stock_location) product.primary_taxon_id = taxon.id - product.supplier = create(:supplier_enterprise) product.name = "Product1" product.variant_unit = "weight" product.variant_unit_scale = 1000 @@ -330,13 +266,16 @@ module Spree let(:product) { create(:simple_product) } describe "touching affected enterprises when the product is deleted" do - let(:product) { create(:simple_product, supplier: distributor) } - let(:supplier) { product.supplier } + let(:product) { create(:simple_product) } + let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [distributor], variants: [product.variants.first]) } + before do + create(:variant, product:, supplier:) + end it "touches the supplier" do expect { product.destroy }.to change { supplier.reload.updated_at } @@ -377,12 +316,37 @@ module Spree end describe "scopes" do + describe ".with_properties" do + let!(:product_with_wanted_property) { create(:product, properties: [wanted_property]) } + let!(:product_without_wanted_property_property) { + create(:product, properties: [unwanted_property]) + } + let!(:product_ignoring_property) { + create(:product, inherits_properties: false) + } + 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::Product.with_properties([])).to eq [] + end + + it "returns only products with the wanted property set both on supplier & product itself" do + expect( + Spree::Product.with_properties([wanted_property.id]) + ).to match_array [product_with_wanted_property] + end + end + describe "in_supplier" do it "shows products in supplier" do s1 = create(:supplier_enterprise) + p1 = create(:product, supplier_id: s1.id) + create(:variant, product: p1, supplier: s1) s2 = create(:supplier_enterprise) - p1 = create(:product, supplier: s1) - p2 = create(:product, supplier: s2) + p2 = create(:product, supplier_id: s2.id) + create(:variant, product: p2, supplier: s2) + expect(Product.in_supplier(s1)).to eq([p1]) end end @@ -461,9 +425,12 @@ module Spree describe "in_supplier_or_distributor" do it "shows products in supplier" do s1 = create(:supplier_enterprise) + p1 = create(:product, supplier_id: s1.id) + create(:variant, product: p1, supplier: s1) s2 = create(:supplier_enterprise) - p1 = create(:product, supplier: s1) - p2 = create(:product, supplier: s2) + p2 = create(:product, supplier_id: s2.id) + create(:variant, product: p2, supplier: s2) + expect(Product.in_supplier_or_distributor(s1)).to eq([p1]) end @@ -483,7 +450,9 @@ module Spree it "shows products in all three without duplicates" do s = create(:supplier_enterprise) d = create(:distributor_enterprise) - p = create(:product, supplier: s) + p = create(:product) + create(:variant, product: p, supplier: s) + create(:simple_order_cycle, suppliers: [s], distributors: [d], variants: [p.variants.first]) [s, d].each { |e| expect(Product.in_supplier_or_distributor(e)).to eq([p]) } @@ -523,31 +492,57 @@ module Spree end end - describe "access roles" do + describe "by_producer" do + it "orders by name" do + producer_z = create(:enterprise, name: "z_cooperative") + producer_a = create(:enterprise, name: "a_cooperative") + producer_g = create(:enterprise, name: "g_cooperative") + + product_1 = create(:product) + create(:variant, product: product_1, supplier: producer_z) + product_2 = create(:product) + create(:variant, product: product_2, supplier: producer_a) + product_3 = create(:product) + create(:variant, product: product_3, supplier: producer_g) + + expect(Product.by_producer).to match_array([ + product_2, + product_3, + product_1, + ]) + end + end + + describe "managed_by" do + let!(:e1) { create(:enterprise) } + let!(:e2) { create(:enterprise) } + let!(:p1) { create(:product) } + let!(:p2) { create(:product) } + before(:each) do - @e1 = create(:enterprise) - @e2 = create(:enterprise) - @p1 = create(:product, supplier: @e1) - @p2 = create(:product, supplier: @e2) + create(:variant, product: p1, supplier: e1) + create(:variant, product: p1, supplier: e2) end it "shows only products for given user" do user = create(:user) user.spree_roles = [] - @e1.enterprise_roles.build(user:).save + e1.enterprise_roles.build(user:).save product = Product.managed_by user + expect(product.count).to eq(1) - expect(product).to include @p1 + expect(product).to include p1 end it "shows all products for admin user" do user = create(:admin_user) product = Product.managed_by user + expect(product.count).to eq(2) - expect(product).to include @p1 - expect(product).to include @p2 + expect(product).to include p1 + expect(product).to include p2 end end @@ -583,11 +578,15 @@ module Spree let(:shop) { create(:distributor_enterprise) } let(:add_to_oc_producer) { create(:supplier_enterprise) } let(:other_producer) { create(:supplier_enterprise) } - let!(:p1) { create(:simple_product, supplier: shop ) } - let!(:p2) { create(:simple_product, supplier: add_to_oc_producer ) } - let!(:p3) { create(:simple_product, supplier: other_producer ) } + let(:p1) { create(:simple_product) } + let(:p2) { create(:simple_product) } + let(:p3) { create(:simple_product) } before do + create(:variant, product: p1, supplier: shop) + create(:variant, product: p2, supplier: add_to_oc_producer) + create(:variant, product: p3, supplier: other_producer) + create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, permissions_list: [:add_to_order_cycle]) create(:enterprise_relationship, parent: other_producer, child: shop, @@ -613,59 +612,54 @@ module Spree end end - describe "properties" do + describe "#properties_including_inherited" do + let(:product) { create(:simple_product) } + let(:supplier) { create(:supplier_enterprise) } + + before do + product.variants = [] + product.variants << create(:variant, product:, supplier:) + end + it "returns product properties as a hash" do - product = create(:simple_product) product.set_property 'Organic Certified', 'NASAA 12345' property = product.properties.last expect(product.properties_including_inherited) - .to eq([{ id: property.id, name: "Organic Certified", - value: 'NASAA 12345' }]) + .to eq([{ id: property.id, name: "Organic Certified", value: 'NASAA 12345' }]) end it "returns producer properties as a hash" do - supplier = create(:supplier_enterprise) - product = create(:simple_product, supplier:) - supplier.set_producer_property 'Organic Certified', 'NASAA 54321' property = supplier.properties.last expect(product.properties_including_inherited) - .to eq([{ id: property.id, name: "Organic Certified", - value: 'NASAA 54321' }]) + .to eq([{ id: property.id, name: "Organic Certified", value: 'NASAA 54321' }]) end it "overrides producer properties with product properties" do - supplier = create(:supplier_enterprise) - product = create(:simple_product, supplier:) - product.set_property 'Organic Certified', 'NASAA 12345' supplier.set_producer_property 'Organic Certified', 'NASAA 54321' property = product.properties.last expect(product.properties_including_inherited) - .to eq([{ id: property.id, name: "Organic Certified", - value: 'NASAA 12345' }]) + .to eq([{ id: property.id, name: "Organic Certified", value: 'NASAA 12345' }]) end context "when product has an inherit_properties value set to true" do - let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier:, inherits_properties: true) } + let(:product) { create(:simple_product, inherits_properties: true) } it "inherits producer properties" do supplier.set_producer_property 'Organic Certified', 'NASAA 54321' property = supplier.properties.last expect(product.properties_including_inherited) - .to eq([{ id: property.id, name: "Organic Certified", - value: 'NASAA 54321' }]) + .to eq([{ id: property.id, name: "Organic Certified", value: 'NASAA 54321' }]) end end context "when product has an inherit_properties value set to false" do - let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier:, inherits_properties: false) } + let(:product) { create(:simple_product, inherits_properties: false) } it "does not inherit producer properties" do supplier.set_producer_property 'Organic Certified', 'NASAA 54321' @@ -675,9 +669,6 @@ module Spree end it "sorts by position" do - supplier = create(:supplier_enterprise) - product = create(:simple_product, supplier:) - pa = Spree::Property.create! name: 'A', presentation: 'A' pb = Spree::Property.create! name: 'B', presentation: 'B' pc = Spree::Property.create! name: 'C', presentation: 'C' @@ -743,18 +734,25 @@ module Spree end describe "deletion" do - let(:p) { create(:simple_product) } - let(:v) { create(:variant, product: p) } - let(:oc) { create(:simple_order_cycle) } - let(:s) { create(:supplier_enterprise) } - let(:e) { - create(:exchange, order_cycle: oc, incoming: true, sender: s, receiver: oc.coordinator) + let(:product) { create(:simple_product) } + let(:variant) { create(:variant, product:) } + let(:order_cycle) { create(:simple_order_cycle) } + let(:supplier) { create(:supplier_enterprise) } + let(:exchange) { + create( + :exchange, + order_cycle:, + incoming: true, + sender: supplier, + receiver: order_cycle.coordinator + ) } it "removes all variants from order cycles" do - e.variants << v - p.destroy - expect(e.variants.reload).to be_empty + exchange.variants << variant + + product.destroy + expect(exchange.variants.reload).to be_empty end end From 411388040149fcac506d9b0dfd0db0784b6c8242 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 26 Feb 2024 20:53:27 +1100 Subject: [PATCH 002/145] 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, From d9d77d2b2555e988b01964288ad11ddec8085b85 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 23 Apr 2024 11:18:09 +1000 Subject: [PATCH 003/145] Migrate supplier to variant --- db/migrate/20240422064305_migrate_product_supplier.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 db/migrate/20240422064305_migrate_product_supplier.rb diff --git a/db/migrate/20240422064305_migrate_product_supplier.rb b/db/migrate/20240422064305_migrate_product_supplier.rb new file mode 100644 index 0000000000..5ab52b4b32 --- /dev/null +++ b/db/migrate/20240422064305_migrate_product_supplier.rb @@ -0,0 +1,11 @@ +class MigrateProductSupplier < ActiveRecord::Migration[7.0] + def up + ActiveRecord::Base.connection.execute(<<-SQL + UPDATE spree_variants + SET supplier_id = spree_products.supplier_id + FROM spree_products + WHERE spree_variants.product_id = spree_products.id + SQL + ) + end +end From 06b0b546854ecce9aab73f395102ae77e5c1f369 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 11:33:42 +1100 Subject: [PATCH 004/145] Update attribute translation --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index fafdc31f2b..d8d47d2423 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -69,7 +69,6 @@ en: name: "Product Name" price: "Price" primary_taxon: "Product Category" - supplier: "Supplier" shipping_category_id: "Shipping Category" variant_unit: "Variant Unit" variant_unit_name: "Variant Unit Name" @@ -77,6 +76,7 @@ en: spree/variant: primary_taxon: "Product Category" shipping_category_id: "Shipping Category" + supplier: "Supplier" spree/credit_card: base: "Credit Card" number: "Number" From 6290e7ad1c2c57c86dee42691be6c5d02a28c26c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 11:32:50 +1100 Subject: [PATCH 005/145] Test the suppliers are touched on destroy --- spec/models/spree/variant_spec.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 5e39aea27e..6a3fac9e13 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -834,11 +834,18 @@ RSpec.describe Spree::Variant do describe "destruction" do it "destroys exchange variants" do - v = create(:variant) - e = create(:exchange, variants: [v]) + variant = create(:variant) + exchange = create(:exchange, variants: [variant]) - v.destroy - expect(e.reload.variant_ids).to be_empty + variant.destroy + expect(exchange.reload.variant_ids).to be_empty + end + + it "touches the supplier" do + supplier = create(:supplier_enterprise) + variant = create(:variant, supplier:) + + expect { variant.destroy }.to change { supplier.reload.updated_at } end end From 7af36510c84f1ab3843a02d82a2c88e834268d71 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 11:44:14 +1100 Subject: [PATCH 006/145] Fix lambda styling It follows Style/Lambda cop : https://docs.rubocop.org/rubocop/1.60/cops_style.html#stylelambda --- app/models/spree/product.rb | 11 +++++------ app/models/spree/variant.rb | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 7df8c7b357..c459ba2b28 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -65,7 +65,7 @@ module Spree accepts_nested_attributes_for :image accepts_nested_attributes_for :product_properties, allow_destroy: true, - reject_if: lambda { |pp| pp[:property_name].blank? } + reject_if: ->(pp) { pp[:property_name].blank? } # Transient attributes used temporarily when creating a new product, # these values are persisted on the product's variant @@ -77,13 +77,13 @@ module Spree after_save :update_units # -- Scopes - scope :with_properties, ->(*property_ids) { + scope :with_properties, lambda { |property_ids| left_outer_joins(:product_properties). where(inherits_properties: true). where(spree_product_properties: { property_id: property_ids }) } - scope :with_order_cycles_outer, -> { + scope :with_order_cycles_outer, lambda { joins(" LEFT OUTER JOIN spree_variants AS o_spree_variants ON (o_spree_variants.product_id = spree_products.id)"). @@ -105,9 +105,7 @@ module Spree where(import_date: import_date.all_day)) } - scope :with_order_cycles_inner, -> { - joins(variants: { exchanges: :order_cycle }) - } + scope :with_order_cycles_inner, -> { joins(variants: { exchanges: :order_cycle }) } scope :visible_for, lambda { |enterprise| joins(' @@ -120,6 +118,7 @@ module Spree distinct } + # TODO rewrite everything with lambda or -> scope :in_supplier, lambda { |supplier| joins(:variants).where(spree_variants: { supplier: }) } diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 7ab19c21da..40370c3c20 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -96,7 +96,7 @@ module Spree after_save :save_default_price # default variant scope only lists non-deleted variants - scope :deleted, lambda { where.not(deleted_at: nil) } + scope :deleted, -> { where.not(deleted_at: nil) } scope :with_order_cycles_inner, -> { joins(exchanges: :order_cycle) } From 5cb59d941a7b4628d8506141f2dcf8412222aded Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 12 Jun 2024 20:46:41 +1000 Subject: [PATCH 007/145] Add transient attribute supplier_id to Spree::Product supplier_id transient attribute will be saved on the variant --- app/models/spree/product.rb | 3 ++- spec/factories/product_factory.rb | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index c459ba2b28..ff5e73aac1 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -70,7 +70,7 @@ module Spree # Transient attributes used temporarily when creating a new product, # these values are persisted on the product's variant attr_accessor :price, :display_as, :unit_value, :unit_description, :tax_category_id, - :shipping_category_id, :primary_taxon_id + :shipping_category_id, :primary_taxon_id, :supplier_id after_create :ensure_standard_variant around_destroy :destruction @@ -283,6 +283,7 @@ module Spree variant.tax_category_id = tax_category_id variant.shipping_category_id = shipping_category_id variant.primary_taxon_id = primary_taxon_id + variant.supplier_id = supplier_id variants << variant end diff --git a/spec/factories/product_factory.rb b/spec/factories/product_factory.rb index 454a1bd689..1095091cf0 100644 --- a/spec/factories/product_factory.rb +++ b/spec/factories/product_factory.rb @@ -4,6 +4,10 @@ FactoryBot.define do factory :base_product, class: Spree::Product do sequence(:name) { |n| "Product ##{n} - #{Kernel.rand(9999)}" } + supplier_id do + Enterprise.is_primary_producer.first&.id || FactoryBot.create(:supplier_enterprise).id + end + transient do primary_taxon { nil } end From 8abea0afcfe16026cddc34a162b02cb1569649e2 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 12:11:02 +1100 Subject: [PATCH 008/145] Add missing associations and validations specs --- spec/models/spree/product_spec.rb | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 0293b27888..155f46fab0 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -107,6 +107,17 @@ module Spree end end + describe "associations" do + it { is_expected.to have_one(:image) } + + it { is_expected.to have_many(:product_properties) } + it { is_expected.to have_many(:properties).through(:product_properties) } + it { is_expected.to have_many(:variants) } + it { is_expected.to have_many(:prices).through(:variants) } + it { is_expected.to have_many(:stock_items).through(:variants) } + it { is_expected.to have_many(:variant_images).through(:variants) } + end + describe "validations and defaults" do it "is valid when built from factory" do expect(build(:product)).to be_valid @@ -144,6 +155,8 @@ module Spree product.reload end + it { is_expected.to validate_numericality_of(:price).is_greater_than_or_equal_to(0) } + it "requires a unit" do product.variant_unit = nil expect(product).not_to be_valid @@ -498,12 +511,9 @@ module Spree producer_a = create(:enterprise, name: "a_cooperative") producer_g = create(:enterprise, name: "g_cooperative") - product_1 = create(:product) - create(:variant, product: product_1, supplier: producer_z) - product_2 = create(:product) - create(:variant, product: product_2, supplier: producer_a) - product_3 = create(:product) - create(:variant, product: product_3, supplier: producer_g) + product_1 = create(:product, supplier_id: producer_z.id) + product_2 = create(:product, supplier_id: producer_a.id) + product_3 = create(:product, supplier_id: producer_g.id) expect(Product.by_producer).to match_array([ product_2, From 22f4ae115a7d7970a86670fcb6839bb49bf17178 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 13:41:03 +1100 Subject: [PATCH 009/145] Add missing associations and validations specs --- app/models/spree/variant.rb | 2 +- spec/models/spree/variant_spec.rb | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 40370c3c20..b2ed204dd6 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -25,7 +25,7 @@ module Spree variants_display_name supplier_name).join('_or_')}_cont".freeze - belongs_to :product, -> { with_deleted }, touch: true, class_name: 'Spree::Product' + belongs_to :product, -> { with_deleted }, required: true, touch: true, class_name: 'Spree::Product' 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 diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 6a3fac9e13..abfea244dd 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -7,9 +7,29 @@ RSpec.describe Spree::Variant do subject(:variant) { build(:variant) } it { is_expected.to have_many :semantic_links } + it { is_expected.to belong_to(:product).required } it { is_expected.to belong_to(:supplier).required } - it { is_expected.to have_many(:supplier_properties) } - # TODO add test for the other associations + it { is_expected.to have_many(:inventory_units) } + it { is_expected.to have_many(:line_items) } + it { is_expected.to have_many(:stock_items) } + it { is_expected.to have_many(:stock_locations).through(:stock_items) } + it { is_expected.to have_many(:images) } + it { is_expected.to have_one(:default_price) } + it { is_expected.to have_many(:prices) } + it { is_expected.to have_many(:exchange_variants) } + it { is_expected.to have_many(:exchanges).through(:exchange_variants) } + it { is_expected.to have_many(:variant_overrides) } + it { is_expected.to have_many(:inventory_items) } + it { is_expected.to have_many(:supplier_properties).through(:supplier) } + + describe "shipping category" do + it "sets a shipping category if none provided" do + variant = build(:variant, shipping_category: nil) + + expect(variant).to be_valid + expect(variant.shipping_category).to_not be_nil + end + end describe "supplier properties" do subject { create(:variant) } From 02b9dfb51786953ac753196a0a5724c204b7c9da Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 15:36:14 +1100 Subject: [PATCH 010/145] Add after update primary taxon call back It updates supplier on primary taxon update. It fixes falling enterprise caching specs. --- app/models/spree/product.rb | 11 +++++++++-- spec/models/enterprise_caching_spec.rb | 19 +++++++++++++------ spec/models/spree/product_spec.rb | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index ff5e73aac1..34707c2658 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'open_food_network/property_merge' +# TODO update description # PRODUCTS # Products represent an entity for sale in a store. @@ -75,6 +76,7 @@ module Spree after_create :ensure_standard_variant around_destroy :destruction after_save :update_units + after_update :touch_supplier, if: :saved_change_to_primary_taxon_id? # -- Scopes scope :with_properties, lambda { |property_ids| @@ -118,9 +120,8 @@ module Spree distinct } - # TODO rewrite everything with lambda or -> scope :in_supplier, lambda { |supplier| - joins(:variants).where(spree_variants: { supplier: }) + distinct.joins(:variants).where(spree_variants: { supplier: }) } # Products distributed via the given distributor through an OC @@ -321,6 +322,12 @@ module Spree variants.each(&:update_units) end + def touch_supplier + # Assume the product supplier is the supplier of the first variant + # Will breack if product has mutiple variants with different supplier + variants.first.supplier.touch + end + def touch_distributors Enterprise.distributing_products(id).each(&:touch) end diff --git a/spec/models/enterprise_caching_spec.rb b/spec/models/enterprise_caching_spec.rb index 5f10a52398..625d92ca9d 100644 --- a/spec/models/enterprise_caching_spec.rb +++ b/spec/models/enterprise_caching_spec.rb @@ -11,12 +11,15 @@ RSpec.describe Enterprise do let(:supplier2) { create(:supplier_enterprise) } describe "with a supplied product" do - let(:product) { create(:simple_product, supplier: enterprise, primary_taxon_id: taxon.id) } - let(:variant) { product.variants.first } + let(:product) { create(:simple_product, primary_taxon_id: taxon.id) } let(:property) { product.product_properties.last } let(:producer_property) { enterprise.producer_properties.last } + let(:variant) { create(:variant, product:, supplier: enterprise) } before do + product.variants = [] + product.variants << variant + product.set_property 'Organic', 'NASAA 12345' enterprise.set_producer_property 'Biodynamic', 'ASDF 4321' end @@ -41,7 +44,7 @@ RSpec.describe Enterprise do it "touches enterprise when the supplier of a product changes" do expect { - later { product.update!(supplier: supplier2) } + later { variant.update!(supplier: supplier2) } }.to change { enterprise.reload.updated_at } end end @@ -53,11 +56,15 @@ RSpec.describe Enterprise do create(:simple_order_cycle, distributors: [enterprise], variants: [product.variants.first]) } - let(:supplier) { product.supplier } + let(:supplier) { variant.supplier } let(:property) { product.product_properties.last } let(:producer_property) { supplier.producer_properties.last } + let(:variant) { create(:variant, product:, supplier: enterprise) } before do + product.variants = [] + product.variants << variant + product.set_property 'Organic', 'NASAA 12345' supplier.set_producer_property 'Biodynamic', 'ASDF 4321' end @@ -83,9 +90,9 @@ RSpec.describe Enterprise do }.to change { enterprise.reload.updated_at } end - it "touches enterprise when the supplier of a product changes" do + it "touches enterprise when the supplier of a variant changes" do expect { - later { product.update!(supplier: supplier2) } + later { variant.update!(supplier: supplier2) } }.to change { enterprise.reload.updated_at } end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 155f46fab0..c98416b4b2 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -303,6 +303,22 @@ module Spree end end + describe "after updating primary taxon" do + let(:product) { create(:simple_product) } + let(:supplier) { create(:supplier_enterprise) } + let(:new_taxon) { create(:taxon) } + + before do + product.variants = [] + product.variants << create(:variant, product:, supplier:) + end + + it "touches the supplier" do + expect { product.update(primary_taxon_id: new_taxon.id) } + .to change { supplier.reload.updated_at } + end + end + it "updates units when saved change to variant unit" do product.variant_unit = 'items' product.variant_unit_scale = nil @@ -356,6 +372,7 @@ module Spree s1 = create(:supplier_enterprise) p1 = create(:product, supplier_id: s1.id) create(:variant, product: p1, supplier: s1) + create(:variant, product: p1, supplier: s1) s2 = create(:supplier_enterprise) p2 = create(:product, supplier_id: s2.id) create(:variant, product: p2, supplier: s2) From d073a181e9bea33eae0836b6b7d2e669dee4a994 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 15:52:17 +1100 Subject: [PATCH 011/145] Fix EnterpriseRelationship --- app/models/enterprise_relationship.rb | 2 +- spec/models/enterprise_relationship_spec.rb | 81 +++++++++------------ 2 files changed, 37 insertions(+), 46 deletions(-) diff --git a/app/models/enterprise_relationship.rb b/app/models/enterprise_relationship.rb index 29cd043f9a..bdc318c08b 100644 --- a/app/models/enterprise_relationship.rb +++ b/app/models/enterprise_relationship.rb @@ -108,6 +108,6 @@ class EnterpriseRelationship < ApplicationRecord def child_variant_overrides VariantOverride.unscoped.for_hubs(child) - .joins(variant: :product).where(spree_products: { supplier_id: parent }) + .joins(:variant).where(spree_variants: { supplier_id: parent } ) end end diff --git a/spec/models/enterprise_relationship_spec.rb b/spec/models/enterprise_relationship_spec.rb index dfdc2df022..d4d9dbd2c7 100644 --- a/spec/models/enterprise_relationship_spec.rb +++ b/spec/models/enterprise_relationship_spec.rb @@ -164,36 +164,31 @@ RSpec.describe EnterpriseRelationship do :create_variant_overrides] ) } let!(:vo1) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: producer - ) - )) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: producer) + ) } let!(:vo2) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: producer - ) - )) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: producer) + ) } let!(:vo3) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: some_other_producer - ) - )) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: some_other_producer) + ) } context "revoking variant override permissions" do context "when the enterprise relationship is destroyed" do before { er.destroy } + it "should set permission_revoked_at to the current time " \ "for all variant overrides of the relationship" do expect(vo1.reload.permission_revoked_at).not_to be_nil @@ -205,6 +200,7 @@ RSpec.describe EnterpriseRelationship do context "and is then removed" do before { er.permissions_list = [:add_to_order_cycles]; er.save! } + it "should set permission_revoked_at to the current time " \ "for all relevant variant overrides" do expect(vo1.reload.permission_revoked_at).not_to be_nil @@ -237,34 +233,28 @@ RSpec.describe EnterpriseRelationship do permissions_list: [:add_to_order_cycles] ) } let!(:vo1) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: producer - ) - ), - permission_revoked_at: Time.now.in_time_zone) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: producer), + permission_revoked_at: Time.now.in_time_zone + ) } let!(:vo2) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: producer - ) - ), - permission_revoked_at: Time.now.in_time_zone) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: producer), + permission_revoked_at: Time.now.in_time_zone + ) } let!(:vo3) { - create(:variant_override, hub:, - variant: create( - :variant, - product: create( - :product, supplier: some_other_producer - ) - ), - permission_revoked_at: Time.now.in_time_zone) + create( + :variant_override, + hub:, + variant: create(:variant, product: create(:product), supplier: some_other_producer), + permission_revoked_at: Time.now.in_time_zone + ) } context "and is then added" do @@ -292,6 +282,7 @@ RSpec.describe EnterpriseRelationship do end end end + describe "updating order cycles" do let(:hub) { create(:distributor_enterprise) } let(:producer) { create(:supplier_enterprise) } From 50bd2747150233bf55f25133d0767460e1ebe869 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 27 Feb 2024 16:32:36 +1100 Subject: [PATCH 012/145] Fix Enterprise --- app/models/enterprise.rb | 10 ++++----- spec/models/enterprise_spec.rb | 39 +++++++++++++++++----------------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 5a1ec12d23..3d6b33fc17 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -39,13 +39,13 @@ class Enterprise < ApplicationRecord class_name: 'EnterpriseGroup' has_many :producer_properties, foreign_key: 'producer_id', dependent: :destroy has_many :properties, through: :producer_properties - has_many :supplied_products, class_name: 'Spree::Product', - foreign_key: 'supplier_id', - dependent: :destroy - has_many :supplied_variants, through: :supplied_products, source: :variants + has_many :supplied_variants, + class_name: 'Spree::Variant', foreign_key: 'supplier_id', dependent: :destroy + has_many :supplied_products, through: :supplied_variants, source: :product has_many :distributed_orders, class_name: 'Spree::Order', foreign_key: 'distributor_id', dependent: :restrict_with_exception + belongs_to :address, class_name: 'Spree::Address' belongs_to :business_address, optional: true, class_name: 'Spree::Address', dependent: :destroy has_many :enterprise_fees, dependent: :restrict_with_exception @@ -167,7 +167,7 @@ class Enterprise < ApplicationRecord scope :is_distributor, -> { where.not(sells: 'none') } scope :is_hub, -> { where(sells: 'any') } scope :supplying_variant_in, lambda { |variants| - joins(supplied_products: :variants). + joins(:supplied_variants). where(spree_variants: { id: variants }). select('DISTINCT enterprises.*') } diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 6b1fd9059c..c0b01822a6 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -37,13 +37,13 @@ RSpec.describe Enterprise do expect(EnterpriseRole.where(id: role.id)).to be_empty end - xit "destroys supplied products upon destroy" do - s = create(:supplier_enterprise) - p = create(:simple_product, supplier: s) + it "destroys supplied variants upon destroy" do + supplier = create(:supplier_enterprise) + variant = create(:variant, supplier:) - s.destroy + variant.destroy - expect(Spree::Product.where(id: p.id)).to be_empty + expect(Spree::Variant.where(id: variant.id)).to be_empty end it "destroys relationships upon destroy" do @@ -567,31 +567,30 @@ RSpec.describe Enterprise do end end - describe "supplying_variant_in" do + describe ".supplying_variant_in" do it "finds producers by supply of variant" do - s = create(:supplier_enterprise) - p = create(:simple_product, supplier: s) - v = create(:variant, product: p) + supplier = create(:supplier_enterprise) + variant = create(:variant, supplier:) - expect(Enterprise.supplying_variant_in([v])).to eq([s]) + expect(Enterprise.supplying_variant_in([variant])).to eq([supplier]) end it "returns multiple enterprises when given multiple variants" do - s1 = create(:supplier_enterprise) - s2 = create(:supplier_enterprise) - p1 = create(:simple_product, supplier: s1) - p2 = create(:simple_product, supplier: s2) + supplier1 = create(:supplier_enterprise) + supplier2 = create(:supplier_enterprise) + variant1 = create(:variant, supplier: supplier1) + variant2 = create(:variant, supplier: supplier2) - expect(Enterprise.supplying_variant_in([p1.variants.first, - p2.variants.first])).to match_array [s1, s2] + expect(Enterprise.supplying_variant_in([variant1, variant2])) + .to match_array([supplier1, supplier2]) end it "does not return duplicates" do - s = create(:supplier_enterprise) - p1 = create(:simple_product, supplier: s) - p2 = create(:simple_product, supplier: s) + supplier = create(:supplier_enterprise) + variant1 = create(:variant, supplier:) + variant2 = create(:variant, supplier:) - expect(Enterprise.supplying_variant_in([p1.variants.first, p2.variants.first])).to eq([s]) + expect(Enterprise.supplying_variant_in([variant1, variant2])).to eq([supplier]) end end From 80112709f33dec7ac02c2918a90fc625f07e372b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 28 Feb 2024 10:25:51 +1100 Subject: [PATCH 013/145] Fix invoice and api serializer --- app/serializers/api/product_serializer.rb | 1 - app/serializers/api/variant_serializer.rb | 2 ++ app/serializers/invoice/product_serializer.rb | 1 - app/serializers/invoice/variant_serializer.rb | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/serializers/api/product_serializer.rb b/app/serializers/api/product_serializer.rb index e25fdaf04a..1a34ece6b2 100644 --- a/app/serializers/api/product_serializer.rb +++ b/app/serializers/api/product_serializer.rb @@ -10,7 +10,6 @@ class Api::ProductSerializer < ActiveModel::Serializer has_many :variants, serializer: Api::VariantSerializer has_one :image, serializer: Api::ImageSerializer - has_one :supplier, serializer: Api::IdSerializer # return an unformatted descripton def description diff --git a/app/serializers/api/variant_serializer.rb b/app/serializers/api/variant_serializer.rb index 1d58eda967..660d45467f 100644 --- a/app/serializers/api/variant_serializer.rb +++ b/app/serializers/api/variant_serializer.rb @@ -9,6 +9,8 @@ class Api::VariantSerializer < ActiveModel::Serializer :tag_list, :thumb_url, :unit_price_price, :unit_price_unit + has_one :supplier, serializer: Api::IdSerializer + delegate :price, to: :object def fees diff --git a/app/serializers/invoice/product_serializer.rb b/app/serializers/invoice/product_serializer.rb index 61f5ecadd0..d5900200c6 100644 --- a/app/serializers/invoice/product_serializer.rb +++ b/app/serializers/invoice/product_serializer.rb @@ -3,6 +3,5 @@ class Invoice class ProductSerializer < ActiveModel::Serializer attributes :name - has_one :supplier, serializer: Invoice::EnterpriseSerializer end end diff --git a/app/serializers/invoice/variant_serializer.rb b/app/serializers/invoice/variant_serializer.rb index 3f0a547b96..ef00becdf4 100644 --- a/app/serializers/invoice/variant_serializer.rb +++ b/app/serializers/invoice/variant_serializer.rb @@ -4,5 +4,6 @@ class Invoice class VariantSerializer < ActiveModel::Serializer attributes :id, :display_name, :options_text has_one :product, serializer: Invoice::ProductSerializer + has_one :supplier, serializer: Invoice::EnterpriseSerializer end end From a87f10b2a6e8c2acf57f15178262613ed957f8b8 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 28 Feb 2024 10:34:03 +1100 Subject: [PATCH 014/145] Fix order cycle spec --- spec/models/order_cycle_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index b673da05e9..5c903f4985 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -151,12 +151,12 @@ RSpec.describe OrderCycle do end it "checks for variants" do - p1 = create(:simple_product) - p2 = create(:simple_product) - oc = create(:simple_order_cycle, suppliers: [p1.supplier], variants: [p1.variants.first]) + variant1 = create(:variant) + variant2 = create(:variant) + order_cycle = create(:simple_order_cycle, suppliers: [variant1.supplier], variants: [variant1]) - expect(oc).to have_variant(p1.variants.first) - expect(oc).not_to have_variant(p2.variants.first) + expect(order_cycle).to have_variant(variant1) + expect(order_cycle).not_to have_variant(variant2) end describe "product exchanges" do From b86d8e1603efd224a59747cfa1848ec369cdc5e3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 28 Feb 2024 10:35:13 +1100 Subject: [PATCH 015/145] Fix product import entry validation --- app/models/product_import/entry_validator.rb | 4 +--- spec/models/product_import/entry_validator_spec.rb | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/app/models/product_import/entry_validator.rb b/app/models/product_import/entry_validator.rb index 34369fe44d..5e7172948b 100644 --- a/app/models/product_import/entry_validator.rb +++ b/app/models/product_import/entry_validator.rb @@ -287,9 +287,7 @@ module ProductImport end def inventory_validation(entry) - products = Spree::Product.where(supplier_id: entry.producer_id, - name: entry.name, - deleted_at: nil) + products = Spree::Product.in_supplier(entry.producer_id).where(name: entry.name) if products.empty? mark_as_invalid(entry, attribute: 'name', diff --git a/spec/models/product_import/entry_validator_spec.rb b/spec/models/product_import/entry_validator_spec.rb index 3f9ef97209..47512e5a78 100644 --- a/spec/models/product_import/entry_validator_spec.rb +++ b/spec/models/product_import/entry_validator_spec.rb @@ -63,12 +63,12 @@ RSpec.describe ProductImport::EntryValidator do let(:potatoes) { create( :simple_product, - supplier: enterprise, on_hand: '100', name: 'Potatoes', unit_value: 1000, variant_unit_scale: 1000, - variant_unit: 'weight' + variant_unit: 'weight', + variants: [create(:variant, supplier: enterprise)] ) } @@ -119,24 +119,24 @@ RSpec.describe ProductImport::EntryValidator do let!(:product_g) { create( :simple_product, - supplier: enterprise, on_hand: '100', name: 'Tomato', unit_value: 500, variant_unit_scale: 1, - variant_unit: 'weight' + variant_unit: 'weight', + variants: [create(:variant, supplier: enterprise, unit_value: 500)] ) } let!(:product_kg) { create( :simple_product, - supplier: enterprise, on_hand: '100', name: 'Potatoes', unit_value: 1000, variant_unit_scale: 1000, - variant_unit: 'weight' + variant_unit: 'weight', + variants: [create(:variant, supplier: enterprise, unit_value: 1000)] ) } From 94faf4cf69e13f125f6de16dfaaaaeb3f42feb1b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 28 Feb 2024 10:37:54 +1100 Subject: [PATCH 016/145] Fix invenrory reset strategy spec --- spec/models/product_import/inventory_reset_strategy_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/models/product_import/inventory_reset_strategy_spec.rb b/spec/models/product_import/inventory_reset_strategy_spec.rb index 86a0b67de4..d7e6a7abc7 100644 --- a/spec/models/product_import/inventory_reset_strategy_spec.rb +++ b/spec/models/product_import/inventory_reset_strategy_spec.rb @@ -7,7 +7,7 @@ RSpec.describe ProductImport::InventoryResetStrategy do describe '#reset' do context 'when there are excluded_items_ids' do - let(:enterprise) { variant.product.supplier } + let(:enterprise) { variant.supplier } let(:variant) { build_stubbed(:variant) } let!(:variant_override) do build_stubbed( @@ -131,7 +131,7 @@ RSpec.describe ProductImport::InventoryResetStrategy do context 'and supplier_ids is set' do let(:supplier_ids) { enterprise.id } - let(:enterprise) { variant.product.supplier } + let(:enterprise) { variant.supplier } let(:variant) { create(:variant) } context "and variant overrides with count on hand" do @@ -202,7 +202,7 @@ RSpec.describe ProductImport::InventoryResetStrategy do context 'and supplier_ids is set' do let(:supplier_ids) { enterprise.id } - let(:enterprise) { variant.product.supplier } + let(:enterprise) { variant.supplier } let(:variant) { create(:variant) } context "and variant overrides with count on hand" do From d5cc60fd3a1052a9373f7ab2b29981bf8946902e Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 4 Mar 2024 16:22:42 +1100 Subject: [PATCH 017/145] Fix ProductImporter and related Class --- app/models/product_import/entry_processor.rb | 2 +- app/models/product_import/entry_validator.rb | 6 +- .../product_import/products_reset_strategy.rb | 7 +- .../products_reset_strategy_spec.rb | 2 +- spec/models/product_importer_spec.rb | 130 ++++++++++-------- 5 files changed, 78 insertions(+), 69 deletions(-) diff --git a/app/models/product_import/entry_processor.rb b/app/models/product_import/entry_processor.rb index 05bc462eff..6308df275c 100644 --- a/app/models/product_import/entry_processor.rb +++ b/app/models/product_import/entry_processor.rb @@ -169,7 +169,6 @@ module ProductImport product.assign_attributes( entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name') ) - product.supplier_id = entry.producer_id if product.save ensure_variant_updated(product, entry) @@ -231,6 +230,7 @@ module ProductImport variant.on_demand = entry.on_demand if entry.on_demand variant.on_hand = entry.on_hand if entry.on_hand variant.import_date = @import_time + variant.supplier_id = entry.producer_id variant.save end end diff --git a/app/models/product_import/entry_validator.rb b/app/models/product_import/entry_validator.rb index 5e7172948b..2705ff1126 100644 --- a/app/models/product_import/entry_validator.rb +++ b/app/models/product_import/entry_validator.rb @@ -73,6 +73,7 @@ module ProductImport # Variant needs a product. Product needs to be assigned first in order for # delegate to work. name= will fail otherwise. new_variant = Spree::Variant.new(product_id:, **variant_attributes) + new_variant.supplier_id = entry.producer_id new_variant.save if new_variant.persisted? @@ -356,9 +357,7 @@ module ProductImport end def product_validation(entry) - products = Spree::Product.where(supplier_id: entry.enterprise_id, - name: entry.name, - deleted_at: nil) + products = Spree::Product.in_supplier(entry.enterprise_id).where(name: entry.name) if products.empty? mark_as_new_product(entry) @@ -382,7 +381,6 @@ module ProductImport new_product.assign_attributes( entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name') ) - new_product.supplier_id = entry.producer_id entry.on_hand = 0 if entry.on_hand.nil? if new_product.valid? diff --git a/engines/catalog/app/services/catalog/product_import/products_reset_strategy.rb b/engines/catalog/app/services/catalog/product_import/products_reset_strategy.rb index ac7dac8de4..f4a8b9a2dd 100644 --- a/engines/catalog/app/services/catalog/product_import/products_reset_strategy.rb +++ b/engines/catalog/app/services/catalog/product_import/products_reset_strategy.rb @@ -20,12 +20,7 @@ module Catalog attr_reader :excluded_items_ids, :enterprise_ids def enterprise_variants_relation - relation = Spree::Variant - .joins(:product) - .where( - spree_products: { supplier_id: enterprise_ids }, - spree_variants: { deleted_at: nil } - ) + relation = Spree::Variant.where(supplier_id: enterprise_ids) return relation if excluded_items_ids.blank? diff --git a/engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb b/engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb index c6d43be45f..d407537e26 100644 --- a/engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb +++ b/engines/catalog/spec/services/catalog/product_import/products_reset_strategy_spec.rb @@ -10,8 +10,8 @@ module Catalog describe '#reset' do let(:supplier_ids) { enterprise.id } let(:product) { create(:product) } - let(:enterprise) { product.supplier } let(:variant) { product.variants.first } + let(:enterprise) { variant.supplier } before { variant.on_hand = 2 } diff --git a/spec/models/product_importer_spec.rb b/spec/models/product_importer_spec.rb index 39b6508575..9ce0dbf83e 100644 --- a/spec/models/product_importer_spec.rb +++ b/spec/models/product_importer_spec.rb @@ -36,67 +36,70 @@ RSpec.describe ProductImport::ProductImporter do let!(:shipping_category) { create(:shipping_category) } let!(:product) { - create(:simple_product, supplier: enterprise2, name: 'Hypothetical Cake', description: nil, - primary_taxon_id: category2.id) + create(:simple_product, name: 'Hypothetical Cake', description: nil, + primary_taxon_id: category2.id, supplier_id: enterprise2.id, + variants: []) } let!(:variant) { create(:variant, product_id: product.id, price: '8.50', on_hand: '100', unit_value: '500', - display_name: 'Preexisting Banana') + display_name: 'Preexisting Banana', supplier: enterprise2) } let!(:variant_with_empty_display_name) { create(:variant, product_id: product.id, price: '8.50', on_hand: '100', unit_value: '500', - display_name: '') + display_name: '', supplier: enterprise2) } let!(:product2) { - create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Beans', unit_value: '500', - primary_taxon_id: category.id, description: nil) + create(:simple_product, on_hand: '100', name: 'Beans', unit_value: '500', + primary_taxon_id: category.id, description: nil, variants: [] ) } let!(:product3) { - create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Sprouts', - unit_value: '500', primary_taxon_id: category.id) + create(:simple_product, on_hand: '100', name: 'Sprouts', unit_value: '500', + primary_taxon_id: category.id, supplier_id: enterprise.id) } let!(:product4) { - create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Cabbage', unit_value: '1', + create(:simple_product, on_hand: '100', name: 'Cabbage', unit_value: '1', variant_unit_scale: nil, variant_unit: "items", - variant_unit_name: "Whole", primary_taxon_id: category.id) + variant_unit_name: "Whole", primary_taxon_id: category.id, + supplier_id: enterprise.id) } let!(:product5) { - create(:simple_product, supplier: enterprise2, on_hand: '100', name: 'Lettuce', - unit_value: '500', primary_taxon_id: category.id) + create(:simple_product, on_hand: '100', name: 'Lettuce', unit_value: '500', + primary_taxon_id: category.id, supplier_id: enterprise2.id) } let!(:product6) { - create(:simple_product, supplier: enterprise3, on_hand: '100', name: 'Beetroot', + create(:simple_product, on_hand: '100', name: 'Beetroot', unit_value: '500', on_demand: true, variant_unit_scale: 1, - variant_unit: 'weight', primary_taxon_id: category.id, description: nil) + variant_unit: 'weight', primary_taxon_id: category.id, description: nil, + supplier_id: enterprise3.id) } let!(:product7) { - create(:simple_product, supplier: enterprise3, on_hand: '100', name: 'Tomato', - unit_value: '500', variant_unit_scale: 1, - variant_unit: 'weight', primary_taxon_id: category.id, - description: nil) + create(:simple_product, on_hand: '100', name: 'Tomato', unit_value: '500', + variant_unit_scale: 1, variant_unit: 'weight', + primary_taxon_id: category.id, description: nil, + supplier_id: enterprise3.id) } let!(:product8) { - create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Oats', description: "", + create(:simple_product, on_hand: '100', name: 'Oats', description: "", unit_value: '500', variant_unit_scale: 1, variant_unit: 'weight', primary_taxon_id: category4.id) } let!(:product9) { - create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Oats', description: "", + create(:simple_product, on_hand: '100', name: 'Oats', description: "", unit_value: '500', variant_unit_scale: 1, variant_unit: 'weight', primary_taxon_id: category4.id) } let!(:variant2) { create(:variant, product_id: product8.id, price: '4.50', on_hand: '100', unit_value: '500', - display_name: 'Porridge Oats') + display_name: 'Porridge Oats', supplier: enterprise) } let!(:variant3) { create(:variant, product_id: product8.id, price: '5.50', on_hand: '100', unit_value: '500', - display_name: 'Rolled Oats') + display_name: 'Rolled Oats', supplier: enterprise) } let!(:variant4) { create(:variant, product_id: product9.id, price: '6.50', on_hand: '100', unit_value: '500', - display_name: 'Flaked Oats') + display_name: 'Flaked Oats', supplier: enterprise) } let!(:variant_override) { @@ -155,54 +158,64 @@ RSpec.describe ProductImport::ProductImporter do expect(importer.updated_ids.count).to eq 5 carrots = Spree::Product.find_by(name: 'Carrots') - expect(carrots.supplier).to eq enterprise + carrots_variant = carrots.variants.first expect(carrots.on_hand).to eq 5 - expect(carrots.variants.first.price).to eq 3.20 - expect(carrots.variants.first.unit_value).to eq 500 expect(carrots.variant_unit).to eq 'weight' expect(carrots.variant_unit_scale).to eq 1 - expect(carrots.variants.first.on_demand).not_to eq true - expect(carrots.variants.first.import_date).to be_within(1.minute).of Time.zone.now + + expect(carrots_variant.supplier).to eq enterprise + expect(carrots_variant.price).to eq 3.20 + expect(carrots_variant.unit_value).to eq 500 + expect(carrots_variant.on_demand).to_not eq true + expect(carrots_variant.import_date).to be_within(1.minute).of Time.zone.now potatoes = Spree::Product.find_by(name: 'Potatoes') - expect(potatoes.supplier).to eq enterprise + potatoes_variant = potatoes.variants.first expect(potatoes.on_hand).to eq 6 - expect(potatoes.variants.first.price).to eq 6.50 - expect(potatoes.variants.first.unit_value).to eq 2000 expect(potatoes.variant_unit).to eq 'weight' expect(potatoes.variant_unit_scale).to eq 1000 - expect(potatoes.variants.first.on_demand).not_to eq true - expect(potatoes.variants.first.import_date).to be_within(1.minute).of Time.zone.now + + expect(potatoes_variant.supplier).to eq enterprise + expect(potatoes_variant.price).to eq 6.50 + expect(potatoes_variant.unit_value).to eq 2000 + expect(potatoes_variant.on_demand).to_not eq true + expect(potatoes_variant.import_date).to be_within(1.minute).of Time.zone.now pea_soup = Spree::Product.find_by(name: 'Pea Soup') - expect(pea_soup.supplier).to eq enterprise + pea_soup_variant = pea_soup.variants.first expect(pea_soup.on_hand).to eq 8 - expect(pea_soup.variants.first.price).to eq 5.50 - expect(pea_soup.variants.first.unit_value).to eq 0.75 expect(pea_soup.variant_unit).to eq 'volume' expect(pea_soup.variant_unit_scale).to eq 0.001 - expect(pea_soup.variants.first.on_demand).not_to eq true - expect(pea_soup.variants.first.import_date).to be_within(1.minute).of Time.zone.now + + expect(pea_soup_variant.supplier).to eq enterprise + expect(pea_soup_variant.price).to eq 5.50 + expect(pea_soup_variant.unit_value).to eq 0.75 + expect(pea_soup_variant.on_demand).to_not eq true + expect(pea_soup_variant.import_date).to be_within(1.minute).of Time.zone.now salad = Spree::Product.find_by(name: 'Salad') - expect(salad.supplier).to eq enterprise + salad_variant = salad.variants.first expect(salad.on_hand).to eq 7 - expect(salad.variants.first.price).to eq 4.50 - expect(salad.variants.first.unit_value).to eq 1 expect(salad.variant_unit).to eq 'items' expect(salad.variant_unit_scale).to eq nil - expect(salad.variants.first.on_demand).not_to eq true - expect(salad.variants.first.import_date).to be_within(1.minute).of Time.zone.now + + expect(salad_variant.supplier).to eq enterprise + expect(salad_variant.price).to eq 4.50 + expect(salad_variant.unit_value).to eq 1 + expect(salad_variant.on_demand).to_not eq true + expect(salad_variant.import_date).to be_within(1.minute).of Time.zone.now buns = Spree::Product.find_by(name: 'Hot Cross Buns') - expect(buns.supplier).to eq enterprise + buns_variant = buns.variants.first expect(buns.on_hand).to eq 7 - expect(buns.variants.first.price).to eq 3.50 - expect(buns.variants.first.unit_value).to eq 1 expect(buns.variant_unit).to eq 'items' expect(buns.variant_unit_scale).to eq nil - expect(buns.variants.first.on_demand).to eq true - expect(buns.variants.first.import_date).to be_within(1.minute).of Time.zone.now + + expect(buns_variant.supplier).to eq enterprise + expect(buns_variant.price).to eq 3.50 + expect(buns_variant.unit_value).to eq 1 + expect(buns_variant.on_demand).to eq true + expect(buns_variant.import_date).to be_within(1.minute).of Time.zone.now end end @@ -236,10 +249,11 @@ RSpec.describe ProductImport::ProductImporter do expect(importer.updated_ids.count).to eq 1 carrots = Spree::Product.find_by(name: 'Good Carrots') - expect(carrots.supplier).to eq enterprise + carrots_variant = carrots.variants.first expect(carrots.on_hand).to eq 5 - expect(carrots.variants.first.price).to eq 3.20 - expect(carrots.variants.first.import_date).to be_within(1.minute).of Time.zone.now + expect(carrots_variant.supplier).to eq enterprise + expect(carrots_variant.price).to eq 3.20 + expect(carrots_variant.import_date).to be_within(1.minute).of Time.zone.now expect(Spree::Product.find_by(name: 'Bad Potatoes')).to eq nil end @@ -282,12 +296,14 @@ RSpec.describe ProductImport::ProductImporter do expect(importer.products_created_count).to eq 1 carrots = Spree::Product.find_by(name: 'Good Carrots') + carrots_variant = carrots.variants.first + expect(carrots.on_hand).to eq 5 - expect(carrots.variants.first.price).to eq 3.20 - expect(carrots.variants.first.primary_taxon.name).to eq "Vegetables" - expect(carrots.variants.first.shipping_category).to eq shipping_category - expect(carrots.supplier).to eq enterprise - expect(carrots.variants.first.unit_presentation).to eq "500g" + expect(carrots.primary_taxon.name).to eq "Vegetables" + expect(carrots_variant.supplier).to eq enterprise + expect(carrots_variant.price).to eq 3.20 + expect(carrots_variant.shipping_category).to eq shipping_category + expect(carrots_variant.unit_presentation).to eq "500g" end end @@ -446,7 +462,7 @@ RSpec.describe ProductImport::ProductImporter do CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Hypothetical Cake", enterprise2.name, "Cake", "5", "5.50", "1", "g", + csv << ["Hypothetical Cake", enterprise2.name, "Cake", "5", "5.50", "500", "g", "", shipping_category.name] end } From 859f7efd020bd346520bde4b3e6b4d2d76dccced Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 4 Mar 2024 16:37:16 +1100 Subject: [PATCH 018/145] Fix Spree:Ability --- app/models/spree/ability.rb | 14 ++++++++------ spec/models/spree/ability_spec.rb | 9 ++++----- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/models/spree/ability.rb b/app/models/spree/ability.rb index 159b56dcc7..4e2a8601be 100644 --- a/app/models/spree/ability.rb +++ b/app/models/spree/ability.rb @@ -189,7 +189,9 @@ module Spree :seo, :group_buy_options, :bulk_update, :clone, :delete, :destroy], Spree::Product do |product| - OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier + OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include?( + product.variants.first.supplier + ) end can [:admin, :index, :bulk_update, :destroy, :destroy_variant, :clone], :products_v3 @@ -198,11 +200,11 @@ module Spree can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant| OpenFoodNetwork::Permissions.new(user). - managed_product_enterprises.include? variant.product.supplier + managed_product_enterprises.include? variant.supplier end can [:admin, :index, :read, :update, :bulk_update, :bulk_reset], VariantOverride do |vo| - next false unless vo.hub.present? && vo.variant&.product&.supplier.present? + next false unless vo.hub.present? && vo.variant&.supplier.present? hub_auth = OpenFoodNetwork::Permissions.new(user). variant_override_hubs. @@ -210,14 +212,14 @@ module Spree producer_auth = OpenFoodNetwork::Permissions.new(user). variant_override_producers. - include? vo.variant.product.supplier + include? vo.variant.supplier hub_auth && producer_auth end can [:admin, :create, :update], InventoryItem do |ii| next false unless ii.enterprise.present? && - ii.variant&.product&.supplier.present? + ii.variant&.supplier.present? hub_auth = OpenFoodNetwork::Permissions.new(user). variant_override_hubs. @@ -225,7 +227,7 @@ module Spree producer_auth = OpenFoodNetwork::Permissions.new(user). variant_override_producers. - include? ii.variant.product.supplier + include? ii.variant.supplier hub_auth && producer_auth end diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 9ff691368e..aa31506e30 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -304,9 +304,9 @@ RSpec.describe Spree::Ability do let(:d1) { create(:distributor_enterprise) } let(:d2) { create(:distributor_enterprise) } - let(:p1) { create(:product, supplier: s1) } - let(:p2) { create(:product, supplier: s2) } - let(:p_related) { create(:product, supplier: s_related) } + let(:p1) { create(:product, supplier_id: s1.id) } + let(:p2) { create(:product, supplier_id: s2.id) } + let(:p_related) { create(:product, supplier_id: s_related.id) } let(:er1) { create(:enterprise_relationship, parent: s1, child: d1) } let(:er2) { create(:enterprise_relationship, parent: d1, child: s1) } @@ -796,8 +796,7 @@ RSpec.describe Spree::Ability do describe "permissions for variant overrides" do let!(:distributor) { create(:distributor_enterprise) } let!(:producer) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier: producer) } - let!(:variant) { create(:variant, product:) } + let!(:variant) { create(:variant, supplier: producer) } let!(:variant_override) { create(:variant_override, hub: distributor, variant:) } subject { user } From 054d967323401bc76a9fcea3b566984956a6d282 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 10:05:29 +1100 Subject: [PATCH 019/145] Fix line items * fix supplier related code * Fix associations + plus spec --- app/models/spree/line_item.rb | 12 +++++------- spec/models/spree/line_item_spec.rb | 30 ++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/app/models/spree/line_item.rb b/app/models/spree/line_item.rb index eed6741b31..fc44eb109a 100644 --- a/app/models/spree/line_item.rb +++ b/app/models/spree/line_item.rb @@ -16,7 +16,7 @@ module Spree belongs_to :variant, -> { with_deleted }, class_name: "Spree::Variant" has_one :product, through: :variant - has_one :supplier, through: :product + has_one :supplier, through: :variant belongs_to :tax_category, class_name: "Spree::TaxCategory", optional: true has_many :adjustments, as: :adjustable, dependent: :destroy @@ -85,13 +85,11 @@ module Spree where(order_cycles: { id: order_cycle }) } - # Here we are simply joining the line item to its variant and product - # We dont use joins here to avoid the default scopes, - # and with that, include deleted variants and deleted products + # Here we are simply joining the line item to its variant + # We dont use joins here to avoid the default scopes, and with that, include deleted variants scope :supplied_by_any, lambda { |enterprises| - product_ids = Spree::Product.unscoped.where(supplier_id: enterprises).select(:id) - variant_ids = Spree::Variant.unscoped.where(product_id: product_ids).select(:id) - where(spree_line_items: { variant_id: variant_ids }) + variant_ids = Spree::Variant.unscoped.where(supplier: enterprises).select(:id) + where(variant_id: variant_ids) } scope :with_tax, -> { diff --git a/spec/models/spree/line_item_spec.rb b/spec/models/spree/line_item_spec.rb index f68e2555d1..d4a757cf99 100644 --- a/spec/models/spree/line_item_spec.rb +++ b/spec/models/spree/line_item_spec.rb @@ -7,6 +7,16 @@ module Spree let(:order) { create :order_with_line_items, line_items_count: 1 } let(:line_item) { order.line_items.first } + describe "associations" do + it { is_expected.to belong_to(:order).required } + it { is_expected.to have_one(:order_cycle).through(:order) } + it { is_expected.to belong_to(:variant).required } + it { is_expected.to have_one(:product).through(:variant) } + it { is_expected.to have_one(:supplier).through(:variant) } + it { is_expected.to belong_to(:tax_category).optional } + it { is_expected.to have_many(:adjustments) } + end + context '#save' do it 'should update inventory, totals, and tax' do # Regression check for Spree #1481 @@ -144,11 +154,11 @@ module Spree let(:s1) { create(:supplier_enterprise) } let(:s2) { create(:supplier_enterprise) } - let(:p1) { create(:simple_product, supplier: s1) } - let(:p2) { create(:simple_product, supplier: s2) } + let(:variant1) { create(:variant, supplier: s1) } + let(:variant2) { create(:variant, supplier: s2) } - let(:li1) { create(:line_item, order: o, product: p1) } - let(:li2) { create(:line_item, order: o, product: p2) } + let(:li1) { create(:line_item, order: o, variant: variant1) } + let(:li2) { create(:line_item, order: o, variant: variant2) } let(:p3) { create(:product, name: 'Clear Honey') } let(:p4) { create(:product, name: 'Apricots') } @@ -806,10 +816,12 @@ module Spree RSpec.describe "searching with ransack" do let(:order_cycle1) { create(:order_cycle) } let(:order_cycle2) { create(:order_cycle) } - let(:product1) { create(:product, supplier: create(:supplier_enterprise)) } - let(:product2) { create(:product, supplier: create(:supplier_enterprise)) } - let!(:line_item1) { create(:line_item, variant: product1.variants.first) } - let!(:line_item2) { create(:line_item, variant: product2.variants.first) } + let(:variant1) { create(:variant, supplier: supplier1) } + let(:variant2) { create(:variant, supplier: supplier2) } + let(:supplier1) { create(:supplier_enterprise) } + let(:supplier2) { create(:supplier_enterprise) } + let!(:line_item1) { create(:line_item, variant: variant1) } + let!(:line_item2) { create(:line_item, variant: variant2) } let(:search_result) { Spree::LineItem.ransack(query).result } @@ -819,7 +831,7 @@ module Spree end context "searching by supplier" do - let(:query) { { supplier_id_eq: line_item1.variant.product.supplier_id } } + let(:query) { { supplier_id_eq: line_item1.variant.supplier_id } } it "filters results" do expect(search_result.to_a).to eq [line_item1] From 612ab097b708b002527bb45523e60b404c8cb3ea Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 10:27:47 +1100 Subject: [PATCH 020/145] Fix order specs --- spec/models/spree/order_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index ec49b695cd..50ef24dc72 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -1459,10 +1459,10 @@ RSpec.describe Spree::Order do let(:aaron) { create(:supplier_enterprise, name: "Aaron the farmer") } let(:zed) { create(:supplier_enterprise, name: "Zed the farmer") } - let(:aaron_apple) { create(:product, name: "Apple", supplier: aaron) } - let(:aaron_banana) { create(:product, name: "Banana", supplier: aaron) } - let(:zed_apple) { create(:product, name: "Apple", supplier: zed) } - let(:zed_banana) { create(:product, name: "Banana", supplier: zed) } + let(:aaron_apple) { create(:product, name: "Apple", supplier_id: aaron.id) } + let(:aaron_banana) { create(:product, name: "Banana", supplier_id: aaron.id) } + let(:zed_apple) { create(:product, name: "Apple", supplier_id: zed.id) } + let(:zed_banana) { create(:product, name: "Banana", supplier_id: zed.id) } let(:distributor) { create(:distributor_enterprise) } let(:order) do From 95ed8063705b1cbff4bccfcf495d065014188fb4 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 10:33:50 +1100 Subject: [PATCH 021/145] Fix shipment specs --- spec/models/spree/shipment_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/models/spree/shipment_spec.rb b/spec/models/spree/shipment_spec.rb index 4b4f70318c..a559d8b855 100644 --- a/spec/models/spree/shipment_spec.rb +++ b/spec/models/spree/shipment_spec.rb @@ -65,8 +65,8 @@ RSpec.describe Spree::Shipment do end describe "with soft-deleted products or variants" do - let!(:product) { create(:product) } - let!(:order) { create(:order, distributor: product.supplier) } + let(:variant) { create(:variant) } + let(:order) { create(:order, distributor: variant.supplier) } context "when the variant is soft-deleted" do it "can still access the variant" do @@ -79,7 +79,7 @@ RSpec.describe Spree::Shipment do context "when the product is soft-deleted" do it "can still access the variant" do - order.line_items.first.variant.delete + order.line_items.first.product.delete variants = shipment.reload.manifest.map(&:variant) expect(variants).to eq [order.line_items.first.variant] From ef298e3b62fddbee2b42e093329ad12f1d82eeeb Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 10:43:44 +1100 Subject: [PATCH 022/145] Fix taxon --- app/models/spree/taxon.rb | 2 +- spec/models/spree/taxon_spec.rb | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/models/spree/taxon.rb b/app/models/spree/taxon.rb index 0ccb9e6499..827551b4d7 100644 --- a/app/models/spree/taxon.rb +++ b/app/models/spree/taxon.rb @@ -57,7 +57,7 @@ module Spree taxons = {} Spree::Taxon. - joins(products: :supplier). + joins(products: { variants: :supplier }). select('spree_taxons.*, enterprises.id AS enterprise_id'). each do |t| taxons[t.enterprise_id.to_i] ||= Set.new diff --git a/spec/models/spree/taxon_spec.rb b/spec/models/spree/taxon_spec.rb index 34bdda4395..282320c206 100644 --- a/spec/models/spree/taxon_spec.rb +++ b/spec/models/spree/taxon_spec.rb @@ -11,7 +11,9 @@ module Spree let(:t2) { create(:taxon) } describe "finding all supplied taxons" do - let!(:p1) { create(:simple_product, supplier: e, primary_taxon_id: t1.id) } + let!(:p1) { + create(:simple_product, primary_taxon_id: t1.id, supplier_id: e.id) + } it "finds taxons" do expect(Taxon.supplied_taxons).to eq(e.id => Set.new([t1.id])) @@ -40,9 +42,10 @@ module Spree describe "touches" do let!(:taxon1) { create(:taxon) } let!(:taxon2) { create(:taxon) } - let!(:product) { create(:simple_product, primary_taxon: taxon1) } + let!(:product) { create(:simple_product, primary_taxon_id: taxon1.id) } let(:variant) { product.variants.first } + it "is touched when assignment of primary_taxon on a variant changes" do expect do variant.update(primary_taxon: taxon2) From 765655ae25633ead5a030bd356c1fe3bddcaad44 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 11:37:46 +1100 Subject: [PATCH 023/145] Fix bulk line items controller specs --- .../admin/bulk_line_items_controller_spec.rb | 52 +++++++++---------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/spec/controllers/admin/bulk_line_items_controller_spec.rb b/spec/controllers/admin/bulk_line_items_controller_spec.rb index 999c39c945..dcca09f313 100644 --- a/spec/controllers/admin/bulk_line_items_controller_spec.rb +++ b/spec/controllers/admin/bulk_line_items_controller_spec.rb @@ -95,29 +95,26 @@ RSpec.describe Admin::BulkLineItemsController, type: :controller do let(:coordinator) { create(:distributor_enterprise) } let(:order_cycle) { create(:simple_order_cycle, coordinator:) } let!(:order1) { - FactoryBot.create(:order, order_cycle:, state: 'complete', - completed_at: Time.zone.now, distributor: distributor1, - billing_address: FactoryBot.create(:address) ) + create(:order, order_cycle:, state: 'complete', + completed_at: Time.zone.now, distributor: distributor1, + billing_address: create(:address) ) } let!(:line_item1) { - FactoryBot.create(:line_item_with_shipment, order: order1, - product: FactoryBot.create(:product, - supplier:)) + create(:line_item_with_shipment, order: order1, + variant: create(:variant, supplier:)) } let!(:line_item2) { - FactoryBot.create(:line_item_with_shipment, order: order1, - product: FactoryBot.create(:product, - supplier:)) + create(:line_item_with_shipment, order: order1, + variant: create(:variant, supplier:)) } let!(:order2) { - FactoryBot.create(:order, order_cycle:, state: 'complete', - completed_at: Time.zone.now, distributor: distributor2, - billing_address: FactoryBot.create(:address) ) + create(:order, order_cycle:, state: 'complete', + completed_at: Time.zone.now, distributor: distributor2, + billing_address: create(:address) ) } let!(:line_item3) { - FactoryBot.create(:line_item_with_shipment, order: order2, - product: FactoryBot.create(:product, - supplier:)) + create(:line_item_with_shipment, order: order2, + variant: create(:variant, supplier:)) } context "producer enterprise" do @@ -189,15 +186,15 @@ RSpec.describe Admin::BulkLineItemsController, type: :controller do let(:coordinator) { create(:distributor_enterprise) } let(:order_cycle) { create(:simple_order_cycle, coordinator:) } let!(:order1) { - FactoryBot.create(:order, order_cycle:, state: 'complete', - completed_at: Time.zone.now, - distributor: distributor1, - billing_address: FactoryBot.create(:address) ) + create(:order, order_cycle:, state: 'complete', + completed_at: Time.zone.now, + distributor: distributor1, + billing_address: create(:address) ) } let!(:line_item1) { - line_item1 = FactoryBot.create(:line_item_with_shipment, - order: order1, - product: FactoryBot.create(:product, supplier:)) + line_item1 = create(:line_item_with_shipment, + order: order1, + variant: create(:variant, supplier:)) # make sure shipment is available through db reloads of this line_item line_item1.tap(&:save!) } @@ -298,14 +295,13 @@ RSpec.describe Admin::BulkLineItemsController, type: :controller do let(:coordinator) { create(:distributor_enterprise) } let(:order_cycle) { create(:simple_order_cycle, coordinator:) } let!(:order1) { - FactoryBot.create(:order, order_cycle:, state: 'complete', - completed_at: Time.zone.now, distributor: distributor1, - billing_address: FactoryBot.create(:address) ) + create(:order, order_cycle:, state: 'complete', + completed_at: Time.zone.now, distributor: distributor1, + billing_address: create(:address) ) } let!(:line_item1) { - FactoryBot.create(:line_item_with_shipment, order: order1, - product: FactoryBot.create(:product, - supplier:)) + create(:line_item_with_shipment, order: order1, + variant: create(:variant, supplier:)) } let(:params) { { id: line_item1.id, order_id: order1.number } } From 1b7a5fdb2c85d25ee9af13ece28940408cb471d4 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 11:59:51 +1100 Subject: [PATCH 024/145] Fix inventory items controller --- spec/controllers/admin/inventory_items_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/admin/inventory_items_controller_spec.rb b/spec/controllers/admin/inventory_items_controller_spec.rb index 8375a89bbd..be33be4871 100644 --- a/spec/controllers/admin/inventory_items_controller_spec.rb +++ b/spec/controllers/admin/inventory_items_controller_spec.rb @@ -44,7 +44,7 @@ RSpec.describe Admin::InventoryItemsController, type: :controller do context "and the producer has granted VO permission" do before do - create(:enterprise_relationship, parent: variant.product.supplier, child: enterprise, + create(:enterprise_relationship, parent: variant.supplier, child: enterprise, permissions_list: [:create_variant_overrides]) end @@ -114,7 +114,7 @@ RSpec.describe Admin::InventoryItemsController, type: :controller do context "and the producer has granted VO permission" do before do - create(:enterprise_relationship, parent: variant.product.supplier, child: enterprise, + create(:enterprise_relationship, parent: variant.supplier, child: enterprise, permissions_list: [:create_variant_overrides]) end From 71e4911b9e79a390dabf6d6cfdc86e0b9bb6e755 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 14:00:51 +1100 Subject: [PATCH 025/145] Fix order cycle permission --- .../order_cycle_permissions.rb | 18 ++++------- .../order_cycle_permissions_spec.rb | 32 +++++++++---------- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/lib/open_food_network/order_cycle_permissions.rb b/lib/open_food_network/order_cycle_permissions.rb index c6c2508112..e4e1fd0d8e 100644 --- a/lib/open_food_network/order_cycle_permissions.rb +++ b/lib/open_food_network/order_cycle_permissions.rb @@ -151,7 +151,7 @@ module OpenFoodNetwork end def all_variants_supplied_by(producer) - Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', producer) + Spree::Variant.where(supplier: producer) end def no_variants @@ -163,9 +163,9 @@ module OpenFoodNetwork user_manages_coordinator_or(enterprise) end.map(&:id) - Spree::Variant.includes(product: :supplier). - select("spree_variants.id, spree_variants.product_id, spree_products.supplier_id"). - joins(:product).where(spree_products: { supplier_id: valid_suppliers }) + Spree::Variant.includes(:supplier). + select(:id, :product_id, :supplier_id). + where(supplier_id: valid_suppliers) end # Find the variants that a user is permitted see within outgoing exchanges @@ -186,12 +186,8 @@ module OpenFoodNetwork # PLUS my incoming producers' variants that are already in an outgoing exchange of this hub, # so things don't break. TODO: Remove this when all P-OC are sorted out - active_variants = Spree::Variant.joins(:exchanges, :product). - where("exchanges.receiver_id = (?) - AND spree_products.supplier_id IN (?) - AND incoming = 'f'", - hub.id, - managed_producer_ids) + active_variants = Spree::Variant.joins(:exchanges). + where(exchanges: { receiver: hub, incoming: "false" }, supplier_id: managed_producer_ids) Spree::Variant.where(id: permitted_variants | active_variants) end @@ -238,7 +234,7 @@ module OpenFoodNetwork end def variants_from_suppliers(supplier_ids) - Spree::Variant.joins(:product).where(spree_products: { supplier_id: supplier_ids }) + Spree::Variant.where(supplier_id: supplier_ids) end def active_outgoing_variants(hub) diff --git a/spec/lib/open_food_network/order_cycle_permissions_spec.rb b/spec/lib/open_food_network/order_cycle_permissions_spec.rb index 72a9ada9e5..11d13debfc 100644 --- a/spec/lib/open_food_network/order_cycle_permissions_spec.rb +++ b/spec/lib/open_food_network/order_cycle_permissions_spec.rb @@ -207,7 +207,7 @@ module OpenFoodNetwork context "and distributes variants distributed by an unmanaged & unpermitted producer" do before { - ex.variants << create(:variant, product: create(:product, supplier: producer)) + ex.variants << create(:variant, supplier: producer) } # TODO: update this when we are confident about P-OCs @@ -338,8 +338,7 @@ module OpenFoodNetwork incoming: false) } before { - ex_outgoing.variants << create(:variant, - product: create(:product, supplier: producer)) + ex_outgoing.variants << create(:variant, supplier: producer) } # TODO: update this when we are confident about P-OCs @@ -423,8 +422,7 @@ module OpenFoodNetwork describe "legacy compatability" do context "where my hub's outgoing exchange contains variants of a producer " \ "I don't manage and has not given my hub P-OC" do - let!(:product) { create(:product, supplier: producer) } - let!(:variant) { create(:variant, product:) } + let!(:variant) { create(:variant, supplier: producer) } let!(:ex_out) { create(:exchange, order_cycle: oc, sender: coordinator, receiver: hub, incoming: true) } @@ -484,8 +482,8 @@ module OpenFoodNetwork # remove when behaviour no longer required describe "legacy compatability" do context "where an outgoing exchange contains variants of a producer I manage" do - let!(:product) { create(:product, supplier: producer) } - let!(:variant) { create(:variant, product:) } + let!(:variant) { create(:variant, supplier: producer) } + before { ex_out.variants << variant } context "where my producer supplies to the order cycle" do @@ -513,8 +511,8 @@ module OpenFoodNetwork "between two enterprises which are visible to a user" do let!(:producer1) { create(:supplier_enterprise) } let!(:producer2) { create(:supplier_enterprise) } - let!(:v1) { create(:variant, product: create(:simple_product, supplier: producer1)) } - let!(:v2) { create(:variant, product: create(:simple_product, supplier: producer2)) } + let!(:v1) { create(:variant, supplier: producer1) } + let!(:v2) { create(:variant, supplier: producer2) } describe "incoming exchanges" do context "as a manager of the coordinator" do @@ -593,7 +591,7 @@ module OpenFoodNetwork end context "where the coordinator produces products" do - let!(:v3) { create(:variant, product: create(:simple_product, supplier: coordinator)) } + let!(:v3) { create(:variant, supplier: coordinator) } it "returns any variants produced by the coordinator itself for exchanges w/ 'self'" do visible = permissions.visible_variants_for_outgoing_exchanges_to(coordinator) @@ -642,7 +640,7 @@ module OpenFoodNetwork context "where the hub produces products" do # NOTE: No relationship to self required - let!(:v3) { create(:variant, product: create(:simple_product, supplier: hub)) } + let!(:v3) { create(:variant, supplier: hub) } it "returns any variants produced by the hub" do visible = permissions.visible_variants_for_outgoing_exchanges_to(hub) @@ -720,7 +718,7 @@ module OpenFoodNetwork incoming: false) } # This one won't be in the exchange, and so shouldn't be visible - let!(:v3) { create(:variant, product: create(:simple_product, supplier: producer2)) } + let!(:v3) { create(:variant, supplier: producer2) } before { ex.variants << v2 } @@ -738,8 +736,8 @@ module OpenFoodNetwork "between two enterprises which are editable by a user" do let!(:producer1) { create(:supplier_enterprise) } let!(:producer2) { create(:supplier_enterprise) } - let!(:v1) { create(:variant, product: create(:simple_product, supplier: producer1)) } - let!(:v2) { create(:variant, product: create(:simple_product, supplier: producer2)) } + let!(:v1) { create(:variant, supplier: producer1) } + let!(:v2) { create(:variant, supplier: producer2) } describe "incoming exchanges" do context "as a manager of the coordinator" do @@ -801,7 +799,7 @@ module OpenFoodNetwork end context "where the coordinator produces products" do - let!(:v3) { create(:variant, product: create(:simple_product, supplier: coordinator)) } + let!(:v3) { create(:variant, supplier: coordinator) } it "returns any variants produced by the coordinator itself for exchanges w/ 'self'" do visible = permissions.editable_variants_for_outgoing_exchanges_to(coordinator) @@ -849,7 +847,7 @@ module OpenFoodNetwork context "where the hub produces products" do # NOTE: No relationship to self required - let!(:v3) { create(:variant, product: create(:simple_product, supplier: hub)) } + let!(:v3) { create(:variant, supplier: hub) } it "returns any variants produced by the hub" do visible = permissions.visible_variants_for_outgoing_exchanges_to(hub) @@ -943,7 +941,7 @@ module OpenFoodNetwork incoming: false) } # This one won't be in the exchange, and so shouldn't be visible - let!(:v3) { create(:variant, product: create(:simple_product, supplier: producer2)) } + let!(:v3) { create(:variant, supplier: producer2) } before { ex.variants << v2 } From b13a1e88435ca7dbd95aafba96524d2a75225f8a Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 15:02:03 +1100 Subject: [PATCH 026/145] Fix order cycle controller spec --- spec/controllers/admin/order_cycles_controller_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/controllers/admin/order_cycles_controller_spec.rb b/spec/controllers/admin/order_cycles_controller_spec.rb index aaeafbd8d7..2a859e7210 100644 --- a/spec/controllers/admin/order_cycles_controller_spec.rb +++ b/spec/controllers/admin/order_cycles_controller_spec.rb @@ -217,8 +217,7 @@ module Admin let(:coordinator) { order_cycle.coordinator } let(:producer) { create(:supplier_enterprise) } let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } - let!(:p) { create(:product) } - let!(:v) { p.variants.first } + let(:v) { create(:variant) } let!(:incoming_exchange) { create(:exchange, order_cycle:, sender: producer, receiver: coordinator, incoming: true, variants: [v]) From 6d1a6c6d0ef3812dfec7429ac5428398f4060f62 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 15:58:26 +1100 Subject: [PATCH 027/145] Fix orders and fulfillment reports Plus specs --- lib/reporting/line_items.rb | 2 +- lib/reporting/reports/orders_and_fulfillment/base.rb | 4 ++-- .../orders_and_fulfillment/order_cycle_customer_totals.rb | 2 +- .../order_cycle_distributor_totals_by_supplier.rb | 2 +- .../orders_and_fulfillment/order_cycle_supplier_totals.rb | 2 +- .../order_cycle_supplier_totals_by_distributor.rb | 2 +- .../order_cycle_customer_totals_report_spec.rb | 2 +- .../order_cycle_distributor_totals_by_supplier_report_spec.rb | 2 +- .../order_cycle_supplier_totals_by_distributor_report_spec.rb | 2 +- .../orders_cycle_supplier_totals_report_spec.rb | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/reporting/line_items.rb b/lib/reporting/line_items.rb index 233c965c2a..01cd726ed0 100644 --- a/lib/reporting/line_items.rb +++ b/lib/reporting/line_items.rb @@ -15,7 +15,7 @@ module Reporting @orders ||= search_orders end - def list(line_item_includes = [variant: [product: :supplier]]) + def list(line_item_includes = [variant: [:supplier, :product]]) line_items = order_permissions.visible_line_items.in_orders(orders.result) .order("supplier.name", "product.name", "variant.display_name") diff --git a/lib/reporting/reports/orders_and_fulfillment/base.rb b/lib/reporting/reports/orders_and_fulfillment/base.rb index 4d223be657..36b6ecf325 100644 --- a/lib/reporting/reports/orders_and_fulfillment/base.rb +++ b/lib/reporting/reports/orders_and_fulfillment/base.rb @@ -49,11 +49,11 @@ module Reporting end def supplier_name - proc { |line_items| line_items.first.variant.product.supplier.name } + proc { |line_items| line_items.first.variant.supplier.name } end def supplier_charges_sales_tax? - proc { |line_items| line_items.first.variant.product.supplier.charges_sales_tax } + proc { |line_items| line_items.first.variant.supplier.charges_sales_tax } end def product_name diff --git a/lib/reporting/reports/orders_and_fulfillment/order_cycle_customer_totals.rb b/lib/reporting/reports/orders_and_fulfillment/order_cycle_customer_totals.rb index 8a538dfe23..b5703dcbda 100644 --- a/lib/reporting/reports/orders_and_fulfillment/order_cycle_customer_totals.rb +++ b/lib/reporting/reports/orders_and_fulfillment/order_cycle_customer_totals.rb @@ -93,7 +93,7 @@ module Reporting end def line_item_includes - [{ variant: { product: :supplier }, + [{ variant: [:product, :supplier], order: [:bill_address, :ship_address, :order_cycle, :adjustments, :payments, :user, :distributor, :shipments] }] end diff --git a/lib/reporting/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier.rb b/lib/reporting/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier.rb index 9e2dcd4d43..f39cae4725 100644 --- a/lib/reporting/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier.rb +++ b/lib/reporting/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier.rb @@ -40,7 +40,7 @@ module Reporting :adjustments, { shipments: { shipping_rates: :shipping_method } } ], - variant: { product: :supplier } + variant: [:product, :supplier] }] end end diff --git a/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals.rb b/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals.rb index 87837d32a0..dedbc9e2d8 100644 --- a/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals.rb +++ b/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals.rb @@ -42,7 +42,7 @@ module Reporting end def line_item_includes - [{ variant: { product: :supplier } }] + [{ variant: [:supplier, :product] }] end def query_result diff --git a/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor.rb b/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor.rb index 3d7c211126..aae3478837 100644 --- a/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor.rb +++ b/lib/reporting/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor.rb @@ -41,7 +41,7 @@ module Reporting def line_item_includes [{ order: :distributor, - variant: { product: :supplier } }] + variant: [:product, :supplier] }] end end end diff --git a/spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb b/spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb index 16511bca45..8ca2d09130 100644 --- a/spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb +++ b/spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb @@ -29,7 +29,7 @@ RSpec.describe Reporting::Reports::OrdersAndFulfillment::OrderCycleCustomerTotal distributor:, completed_at: order_date, ).tap do |order| - order.line_items[0].product.supplier.update(name: "Apple Farmer") + order.line_items[0].variant.supplier.update(name: "Apple Farmer") order.line_items[0].product.update(name: "Apples") order.line_items[0].variant.update(sku: "APP") end diff --git a/spec/lib/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier_report_spec.rb b/spec/lib/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier_report_spec.rb index 9bedefa186..094e9a5c72 100644 --- a/spec/lib/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier_report_spec.rb +++ b/spec/lib/reports/orders_and_fulfillment/order_cycle_distributor_totals_by_supplier_report_spec.rb @@ -30,7 +30,7 @@ module Reporting distributor_name_field = report_table.first[0] expect(distributor_name_field).to eq distributor.name - supplier = order.line_items.first.variant.product.supplier + supplier = order.line_items.first.variant.supplier supplier_name_field = report_table.first[1] expect(supplier_name_field).to eq supplier.name end diff --git a/spec/lib/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor_report_spec.rb b/spec/lib/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor_report_spec.rb index c6cbb733d0..4681387af4 100644 --- a/spec/lib/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor_report_spec.rb +++ b/spec/lib/reports/orders_and_fulfillment/order_cycle_supplier_totals_by_distributor_report_spec.rb @@ -27,7 +27,7 @@ module Reporting end it "has a variant row under the distributor" do - supplier = order.line_items.first.variant.product.supplier + supplier = order.line_items.first.variant.supplier expect(report.rows.first.producer).to eq supplier.name expect(report.rows.first.hub).to eq distributor.name end diff --git a/spec/lib/reports/orders_and_fulfillment/orders_cycle_supplier_totals_report_spec.rb b/spec/lib/reports/orders_and_fulfillment/orders_cycle_supplier_totals_report_spec.rb index c40dcc90db..e81596cbbd 100644 --- a/spec/lib/reports/orders_and_fulfillment/orders_cycle_supplier_totals_report_spec.rb +++ b/spec/lib/reports/orders_and_fulfillment/orders_cycle_supplier_totals_report_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Reporting::Reports::OrdersAndFulfillment::OrderCycleSupplierTotal create(:completed_order_with_totals, line_items_count: 1, distributor:) end let!(:supplier) do - order.line_items.first.variant.product.supplier + order.line_items.first.variant.supplier end let(:current_user) { distributor.owner } let(:params) { { display_summary_row: false, fields_to_hide: [] } } From 3d82309c5f64b6b6cdb26e4f7933e82bcc8360f0 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 16:14:50 +1100 Subject: [PATCH 028/145] Fix order permission and specs --- app/services/permissions/order.rb | 2 +- spec/services/permissions/order_spec.rb | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/services/permissions/order.rb b/app/services/permissions/order.rb index 842e858321..d4c2f4b0ea 100644 --- a/app/services/permissions/order.rb +++ b/app/services/permissions/order.rb @@ -83,7 +83,7 @@ module Permissions Spree::Order.with_line_items_variants_and_products_outer. where( distributor_id: granted_distributor_ids, - spree_products: { supplier_id: enterprises_with_associated_orders } + spree_variants: { supplier_id: enterprises_with_associated_orders } ). where_clause.__send__(:predicates). reduce(:and) diff --git a/spec/services/permissions/order_spec.rb b/spec/services/permissions/order_spec.rb index 385b4a336a..9460445f7d 100644 --- a/spec/services/permissions/order_spec.rb +++ b/spec/services/permissions/order_spec.rb @@ -88,8 +88,8 @@ module Permissions context "which contains my products" do before do - line_item.product.supplier = producer - line_item.product.save + line_item.variant.supplier = producer + line_item.variant.save end it "should let me see the order" do @@ -165,8 +165,8 @@ module Permissions create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle]) - line_item1.product.supplier = producer - line_item1.product.save + line_item1.variant.supplier = producer + line_item1.variant.save end it "should let me see the line_items pertaining to variants I produce" do From 2952ebb05c2eba2b76fa85b9bc84fc95c6ec865b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 16:20:48 +1100 Subject: [PATCH 029/145] Fix admin report controller spec --- spec/controllers/admin/reports_controller_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/controllers/admin/reports_controller_spec.rb b/spec/controllers/admin/reports_controller_spec.rb index 5e80fe5f68..4501adf433 100644 --- a/spec/controllers/admin/reports_controller_spec.rb +++ b/spec/controllers/admin/reports_controller_spec.rb @@ -15,9 +15,9 @@ RSpec.describe Admin::ReportsController, type: :controller do let(:distributor1) { create(:distributor_enterprise) } let(:distributor2) { create(:distributor_enterprise) } let(:distributor3) { create(:distributor_enterprise) } - let(:product1) { create(:product, price: 12.34, supplier: supplier1) } - let(:product2) { create(:product, price: 23.45, supplier: supplier2) } - let(:product3) { create(:product, price: 34.56, supplier: supplier3) } + let(:product1) { create(:product, price: 12.34, supplier_id: supplier1.id) } + let(:product2) { create(:product, price: 23.45, supplier_id: supplier2.id) } + let(:product3) { create(:product, price: 34.56, supplier_id: supplier3.id) } # Given two order cycles with both distributors let(:ocA) { From b5e76e1dabaa7e11843e7c53a3617b1d53d0fb9f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 16:24:30 +1100 Subject: [PATCH 030/145] Fix subscriptions controller specs --- spec/controllers/admin/subscriptions_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/admin/subscriptions_controller_spec.rb b/spec/controllers/admin/subscriptions_controller_spec.rb index 0960e2fc86..a59001731a 100644 --- a/spec/controllers/admin/subscriptions_controller_spec.rb +++ b/spec/controllers/admin/subscriptions_controller_spec.rb @@ -262,9 +262,9 @@ RSpec.describe Admin::SubscriptionsController, type: :controller do let!(:user) { create(:user) } let!(:shop) { create(:distributor_enterprise, owner: user) } let!(:customer) { create(:customer, enterprise: shop) } - let!(:product1) { create(:product, supplier: shop) } + let!(:product1) { create(:product) } let!(:variant1) { - create(:variant, product: product1, unit_value: '100', price: 12.00) + create(:variant, product: product1, unit_value: '100', price: 12.00, supplier: shop) } let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } let!(:order_cycle) { From 04fb49bc253680d3159da3239a34833df0ef2c92 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 16:27:50 +1100 Subject: [PATCH 031/145] Fix admin variant overrides controller specs --- .../admin/variant_overrides_controller_spec.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/controllers/admin/variant_overrides_controller_spec.rb b/spec/controllers/admin/variant_overrides_controller_spec.rb index 7e37e63d60..13848a22d1 100644 --- a/spec/controllers/admin/variant_overrides_controller_spec.rb +++ b/spec/controllers/admin/variant_overrides_controller_spec.rb @@ -52,15 +52,15 @@ RSpec.describe Admin::VariantOverridesController, type: :controller do context "and the producer has granted VO permission" do before do - create(:enterprise_relationship, parent: variant.product.supplier, child: hub, + create(:enterprise_relationship, parent: variant.supplier, child: hub, permissions_list: [:create_variant_overrides]) end it "loads data" do put :bulk_update, as: format, params: { variant_overrides: variant_override_params } expect(assigns[:hubs]).to eq [hub] - expect(assigns[:producers]).to eq [variant.product.supplier] - expect(assigns[:hub_permissions]).to eq Hash[hub.id, [variant.product.supplier.id]] + expect(assigns[:producers]).to eq [variant.supplier] + expect(assigns[:hub_permissions]).to eq Hash[hub.id, [variant.supplier.id]] expect(assigns[:inventory_items]).to eq [inventory_item] end @@ -113,9 +113,9 @@ RSpec.describe Admin::VariantOverridesController, type: :controller do let(:hub) { create(:distributor_enterprise) } let(:producer) { create(:supplier_enterprise) } - let(:product) { create(:product, supplier: producer) } - let(:variant1) { create(:variant, product:) } - let(:variant2) { create(:variant, product:) } + let(:product) { create(:product) } + let(:variant1) { create(:variant, product:, supplier: producer) } + let(:variant2) { create(:variant, product:, supplier: producer) } let!(:variant_override1) { create(:variant_override, hub:, variant: variant1, count_on_hand: 5, default_stock: 7, resettable: true) @@ -179,8 +179,8 @@ RSpec.describe Admin::VariantOverridesController, type: :controller do "to another hub I manage" do before { hub.owner.update_attribute(:enterprise_limit, 2) } let(:hub2) { create(:distributor_enterprise, owner: hub.owner) } - let(:product) { create(:product, supplier: producer) } - let(:variant3) { create(:variant, product:) } + let(:product) { create(:product) } + let(:variant3) { create(:variant, product:, supplier: producer) } let!(:variant_override3) { create(:variant_override, hub: hub2, variant: variant3, count_on_hand: 1, default_stock: 13, resettable: true) From a873fa692b903960934473aa3ce990eadd38a3e7 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 16:53:46 +1100 Subject: [PATCH 032/145] Fix exchange products renderer and specs --- app/services/exchange_products_renderer.rb | 4 ++-- spec/services/exchange_products_renderer_spec.rb | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/services/exchange_products_renderer.rb b/app/services/exchange_products_renderer.rb index c6cfceab22..fc95368af0 100644 --- a/app/services/exchange_products_renderer.rb +++ b/app/services/exchange_products_renderer.rb @@ -30,7 +30,7 @@ class ExchangeProductsRenderer end def supplied_products(enterprises_query_matcher) - products_relation = Spree::Product.where(supplier_id: enterprises_query_matcher).order(:name) + products_relation = Spree::Product.in_supplier(enterprises_query_matcher).order(:name) filter_visible(products_relation) end @@ -95,7 +95,7 @@ class ExchangeProductsRenderer return enterprises if enterprises.empty? enterprises.includes( - supplied_products: [:supplier, :variants, :image] + supplied_products: [{ variants: :supplier }, :image] ) end end diff --git a/spec/services/exchange_products_renderer_spec.rb b/spec/services/exchange_products_renderer_spec.rb index df0e482edc..dd64f43df2 100644 --- a/spec/services/exchange_products_renderer_spec.rb +++ b/spec/services/exchange_products_renderer_spec.rb @@ -14,7 +14,9 @@ RSpec.describe ExchangeProductsRenderer do it "loads products" do products = renderer.exchange_products(true, exchange.sender) - expect(products.first.supplier.name).to eq exchange.variants.first.product.supplier.name + expect(products.first.variants.first.supplier.name).to eq( + exchange.variants.first.supplier.name + ) end it "loads products in order" do @@ -31,10 +33,10 @@ RSpec.describe ExchangeProductsRenderer do it "loads products" do products = renderer.exchange_products(false, exchange.receiver) - suppliers = [exchange.variants[0].product.supplier.name, - exchange.variants[1].product.supplier.name] - expect(suppliers).to include products.first.supplier.name - expect(suppliers).to include products.second.supplier.name + suppliers = [exchange.variants[0].supplier.name, + exchange.variants[1].supplier.name] + expect(suppliers).to include products.first.variants.first.supplier.name + expect(suppliers).to include products.second.variants.first.supplier.name end it "loads products in order" do @@ -74,8 +76,8 @@ RSpec.describe ExchangeProductsRenderer do exchange = order_cycle.exchanges.incoming.first variants = renderer.exchange_variants(true, exchange.sender) - expect(variants.first.product.supplier.name) - .to eq exchange.variants.first.product.supplier.name + expect(variants.first.supplier.name) + .to eq exchange.variants.first.supplier.name end describe "when OC is showing only the coordinators inventory" do From 53e7b024716b0174eeeeedc78d00279d57bf9f35 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 5 Mar 2024 20:33:36 +1100 Subject: [PATCH 033/145] Fix admin api exchange products controller --- .../api/admin/for_order_cycle/supplied_product_serializer.rb | 2 +- spec/controllers/api/v0/exchange_products_controller_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/serializers/api/admin/for_order_cycle/supplied_product_serializer.rb b/app/serializers/api/admin/for_order_cycle/supplied_product_serializer.rb index f135d31dab..7e22751b72 100644 --- a/app/serializers/api/admin/for_order_cycle/supplied_product_serializer.rb +++ b/app/serializers/api/admin/for_order_cycle/supplied_product_serializer.rb @@ -7,7 +7,7 @@ module Api attributes :name, :supplier_name, :image_url, :variants def supplier_name - object.supplier&.name + object.variants.first.supplier&.name end def image_url diff --git a/spec/controllers/api/v0/exchange_products_controller_spec.rb b/spec/controllers/api/v0/exchange_products_controller_spec.rb index ea226a80f1..f290186450 100644 --- a/spec/controllers/api/v0/exchange_products_controller_spec.rb +++ b/spec/controllers/api/v0/exchange_products_controller_spec.rb @@ -39,7 +39,7 @@ module Api api_get :index, exchange_id: exchange.id, order_cycle_id: 666, enterprise_id: 666, incoming: false expect(json_response["products"].first["supplier_name"]) - .to eq exchange.variants.first.product.supplier.name + .to eq exchange.variants.first.supplier.name end end @@ -48,7 +48,7 @@ module Api api_get :index, order_cycle_id: order_cycle.id, enterprise_id: exchange.sender_id, incoming: true expect(json_response["products"].first["supplier_name"]) - .to eq exchange.variants.first.product.supplier.name + .to eq exchange.variants.first.supplier.name end end end From 0c9223809b55b5088dff6dc6918e6002a1e90ede Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 14:03:09 +1100 Subject: [PATCH 034/145] Fix with_properties scope to accept any number of arguments --- app/models/spree/product.rb | 2 +- .../distributed_products_service.rb | 22 +++++++-- app/services/products_renderer.rb | 44 ++++++++++++++---- config/initializers/pagy.rb | 6 +-- spec/models/spree/product_spec.rb | 2 +- .../distributed_products_service_spec.rb | 46 +++++++++++++------ spec/services/products_renderer_spec.rb | 36 +++++++++------ 7 files changed, 110 insertions(+), 48 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 34707c2658..f897c4553d 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -79,7 +79,7 @@ module Spree after_update :touch_supplier, if: :saved_change_to_primary_taxon_id? # -- Scopes - scope :with_properties, lambda { |property_ids| + scope :with_properties, ->(*property_ids) { left_outer_joins(:product_properties). where(inherits_properties: true). where(spree_product_properties: { property_id: property_ids }) diff --git a/app/services/order_cycles/distributed_products_service.rb b/app/services/order_cycles/distributed_products_service.rb index 4da5039e26..6bdde387c8 100644 --- a/app/services/order_cycles/distributed_products_service.rb +++ b/app/services/order_cycles/distributed_products_service.rb @@ -11,11 +11,8 @@ module OrderCycles @customer = customer end - def products_relation - Spree::Product.where(id: stocked_products).group("spree_products.id") - end - - # Joins on the first product variant to allow us to filter product by taxon. This is so + # TODO refactor products_taxons_relation and products_supplier_relation + # Joins on the first product variant to allow us to filter product by taxon. # This is so # enterprise can display product sorted by category in a custom order on their shopfront. # # Caveat, the category sorting won't work properly if there are multiple variant with different @@ -31,6 +28,21 @@ module OrderCycles group("spree_products.id, first_variant.primary_taxon_id") end + # Joins on the first product variant to allow us to filter product by supplier. This is so + # enterprise can display product sorted by supplier in a custom order on their shopfront. + # + # Caveat, the supplier sorting won't work properly if there are multiple variant with different + # supplier for a given product. + # + def products_supplier_relation + Spree::Product.where(id: stocked_products). + joins("LEFT JOIN (SELECT DISTINCT ON(product_id) id, product_id, supplier_id + FROM spree_variants WHERE deleted_at IS NULL) first_variant + ON spree_products.id = first_variant.product_id"). + select("spree_products.*, first_variant.supplier_id"). + group("spree_products.id, first_variant.supplier_id") + end + def variants_relation order_cycle. variants_distributed_by(distributor). diff --git a/app/services/products_renderer.rb b/app/services/products_renderer.rb index 57608f849a..4825d4aa71 100644 --- a/app/services/products_renderer.rb +++ b/app/services/products_renderer.rb @@ -34,12 +34,12 @@ class ProductsRenderer return unless order_cycle @products ||= begin - results = distributed_products. - products_taxons_relation. + results = products_relation. order(Arel.sql(products_order)) - filter_and_paginate(results). - each { |product| product_scoper.scope(product) } # Scope results with variant_overrides + results = filter(results) + # Scope results with variant_overrides + paginate(results).each { |product| product_scoper.scope(product) } end end @@ -51,9 +51,37 @@ class ProductsRenderer OpenFoodNetwork::EnterpriseFeeCalculator.new distributor, order_cycle end - def filter_and_paginate(query) - results = query.ransack(args[:q]).result + # TODO refactor this, distributed_products should be able to give use the relation based + # on the sorting method, same for ordering. It would prevent the SQL implementation from + # leaking here + def products_relation + if distributor.preferred_shopfront_product_sorting_method == "by_category" && + distributor.preferred_shopfront_taxon_order.present? + return distributed_products.products_taxons_relation + end + distributed_products.products_supplier_relation + end + + def filter(query) + property_ids = args[:q]&.dig("with_variants_supplier_properties") + + if property_ids.present? + # We can't search on an association's scope with ransack, a work around is to define + # the a scope on the parent (Spree::Product) but because we are joining on "first_variant" + # it doesn't work, so we do the filtering manually here + results = query.joins('JOIN enterprises ON enterprises.id = first_variant.supplier_id + LEFT OUTER JOIN producer_properties + ON producer_properties.producer_id = enterprises.id'). + where(producer_properties: { property_id: property_ids }) + + return results + end + + query.ransack(args[:q]).result + end + + def paginate(results) _pagy, paginated_results = pagy_arel( results, page: args[:page] || 1, @@ -67,12 +95,13 @@ class ProductsRenderer OrderCycles::DistributedProductsService.new(distributor, order_cycle, customer) end + # TODO refactor, see above def products_order if distributor.preferred_shopfront_product_sorting_method == "by_producer" && distributor.preferred_shopfront_producer_order.present? order_by_producer = distributor .preferred_shopfront_producer_order - .split(",").map { |id| "spree_products.supplier_id=#{id} DESC" } + .split(",").map { |id| "first_variant.supplier_id=#{id} DESC" } .join(", ") "#{order_by_producer}, spree_products.name ASC, spree_products.id ASC" elsif distributor.preferred_shopfront_product_sorting_method == "by_category" && @@ -87,7 +116,6 @@ class ProductsRenderer end end - def variants_for_shop @variants_for_shop ||= begin scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor) diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb index cd18f12b32..572f8c3fd3 100644 --- a/config/initializers/pagy.rb +++ b/config/initializers/pagy.rb @@ -4,12 +4,12 @@ require 'pagy/extras/arel' require 'pagy/extras/items' require 'pagy/extras/overflow' - # Pagy Variables # See https://ddnexus.github.io/pagy/api/pagy#variables -Pagy::DEFAULT[:items] = 100 +Pagy::DEFAULT[:items] = 100 -# Items extra: Allow the client to request a custom number of items per page with an optional selector UI +# Items extra: Allow the client to request a custom number of items per page with an optional +# selector UI # See https://ddnexus.github.io/pagy/extras/items Pagy::DEFAULT[:items_param] = :per_page Pagy::DEFAULT[:max_items] = 100 diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index c98416b4b2..41aa38f8e1 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -362,7 +362,7 @@ module Spree it "returns only products with the wanted property set both on supplier & product itself" do expect( - Spree::Product.with_properties([wanted_property.id]) + Spree::Product.with_properties([wanted_property.id, 99_999]) ).to match_array [product_with_wanted_property] end end diff --git a/spec/services/order_cycles/distributed_products_service_spec.rb b/spec/services/order_cycles/distributed_products_service_spec.rb index 4427c48494..259955d41a 100644 --- a/spec/services/order_cycles/distributed_products_service_spec.rb +++ b/spec/services/order_cycles/distributed_products_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe OrderCycles::DistributedProductsService do - describe "#products_relation" do + describe "#products_supplier_relation" do let(:distributor) { create(:distributor_enterprise) } let(:product) { create(:product) } let(:variant) { product.variants.first } @@ -12,10 +12,20 @@ RSpec.describe OrderCycles::DistributedProductsService do create(:simple_order_cycle, distributors: [distributor], variants: [variant]) end + it "returns de duplicated result" do + supplier = create(:supplier_enterprise) + variant.update(supplier: ) + create(:variant, product:, supplier: ) + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).to eq([product]) + end + describe "product distributed by distributor in the OC" do it "returns products" do - expect(described_class.new(distributor, order_cycle, - customer).products_relation).to eq([product]) + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).to eq([product]) end end @@ -29,8 +39,9 @@ RSpec.describe OrderCycles::DistributedProductsService do end it "does not return product" do - expect(described_class.new(distributor, order_cycle, - customer).products_relation).not_to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).not_to include product end end @@ -41,22 +52,25 @@ RSpec.describe OrderCycles::DistributedProductsService do end it "does not return product" do - expect(described_class.new(distributor, order_cycle, - customer).products_relation).not_to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).not_to include product end end describe "filtering products that are out of stock" do context "with regular variants" do it "returns product when variant is in stock" do - expect(described_class.new(distributor, order_cycle, - customer).products_relation).to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).to include product end it "does not return product when variant is out of stock" do variant.update_attribute(:on_hand, 0) - expect(described_class.new(distributor, order_cycle, - customer).products_relation).not_to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).not_to include product end end @@ -66,15 +80,17 @@ RSpec.describe OrderCycles::DistributedProductsService do } it "does not return product when an override is out of stock" do - expect(described_class.new(distributor, order_cycle, - customer).products_relation).not_to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).not_to include product end it "returns product when an override is in stock" do variant.update_attribute(:on_hand, 0) override.update_attribute(:count_on_hand, 10) - expect(described_class.new(distributor, order_cycle, - customer).products_relation).to include product + expect( + described_class.new(distributor, order_cycle, customer).products_supplier_relation + ).to include product end end end diff --git a/spec/services/products_renderer_spec.rb b/spec/services/products_renderer_spec.rb index 0913c61ee9..1a5291082d 100644 --- a/spec/services/products_renderer_spec.rb +++ b/spec/services/products_renderer_spec.rb @@ -15,12 +15,13 @@ RSpec.describe ProductsRenderer do let(:fruits_supplier) { create(:supplier_enterprise) } let(:cakes_supplier) { create(:supplier_enterprise) } let!(:product_apples) { - create(:product, name: "apples", primary_taxon_id: fruits.id, - supplier_id: fruits_supplier.id) + create(:product, name: "apples", primary_taxon_id: fruits.id, supplier_id: fruits_supplier.id) } let!(:product_banana_bread) { - create(:product, name: "banana bread", primary_taxon_id: cakes.id, - supplier_id: cakes_supplier.id) + create(:product, name: "banana bread", variants: [ + create(:variant, supplier: cakes_supplier, primary_taxon: cakes), + create(:variant, supplier: fruits_supplier, primary_taxon: cakes) + ]) } let!(:product_cherries) { create(:product, name: "cherries", primary_taxon_id: fruits.id, @@ -68,12 +69,17 @@ RSpec.describe ProductsRenderer do context "filtering" do it "filters products by name_or_meta_keywords_or_variants_display_as_or_" \ - "variants_display_name_or_supplier_name_cont" do - products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, { q: { - "#{[:name, :meta_keywords, :variants_display_as, - :variants_display_name, :supplier_name] - .join('_or_')}_cont": "apples", - } }) + "variants_display_name_or_variants_supplier_name_cont" do + params = [:name, :meta_keywords, :variants_display_as, :variants_display_name, + :variants_supplier_name] + ransack_param = "#{params.join('_or_')}_cont" + products_renderer = ProductsRenderer.new( + distributor, + order_cycle, + customer, + { q: { "#{ransack_param}": "apples" } } + ) + products = products_renderer.send(:products) expect(products).to eq([product_apples]) end @@ -89,7 +95,7 @@ RSpec.describe ProductsRenderer do value: '1', position: 1 }) products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, { q: { - with_properties: [property_organic.id] + with_properties: [property_organic.id, 999] } }) products = products_renderer.send(:products) expect(products).to eq([product_apples]) @@ -98,10 +104,10 @@ RSpec.describe ProductsRenderer do it "filters products with a producer property" do fruits_supplier.producer_properties.create!({ property_id: property_organic.id, value: '1', position: 1 }) - products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, - { q: { - with_properties: [property_organic.id] - } }) + + search_param = { q: { "with_variants_supplier_properties" => [property_organic.id] } } + products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, search_param) + products = products_renderer.send(:products) expect(products).to eq([product_apples, product_cherries]) end From 586acad8f1d26c0226dbc09683ac9da9fe4ef69d Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 15:04:30 +1100 Subject: [PATCH 035/145] Fix most of api V0 order cycles controller --- .../api/v0/order_cycles_controller_spec.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/spec/controllers/api/v0/order_cycles_controller_spec.rb b/spec/controllers/api/v0/order_cycles_controller_spec.rb index bb77374986..eb578e56f4 100644 --- a/spec/controllers/api/v0/order_cycles_controller_spec.rb +++ b/spec/controllers/api/v0/order_cycles_controller_spec.rb @@ -52,7 +52,7 @@ module Api it "returns products that were searched for" do ransack_param = "name_or_meta_keywords_or_variants_display_as_or_" \ - "variants_display_name_or_supplier_name_cont" + "variants_display_name_or_variants_supplier_name_cont" api_get :products, id: order_cycle.id, distributor: distributor.id, q: { ransack_param => "Kangaroo" } @@ -241,10 +241,13 @@ module Api context "with producer properties" do let!(:property4) { create(:property) } + let!(:supplier) { create(:supplier_enterprise) } let!(:producer_property) { - create(:producer_property, producer_id: product1.supplier.id, property: property4) + create(:producer_property, producer_id: supplier.id, property: property4) } + before { product1.variants.first.update(supplier: ) } + it "loads producer properties for distributed products in the order cycle" do api_get :properties, id: order_cycle.id, distributor: distributor.id @@ -260,16 +263,16 @@ module Api context "with custom taxon ordering applied and duplicate product names in the order cycle" do let!(:supplier) { create(:supplier_enterprise) } let!(:product5) { - create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier:) + create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier_id: supplier.id) } let!(:product6) { - create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier:) + create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier_id: supplier.id) } let!(:product7) { - create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier:) + create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier_id: supplier.id) } let!(:product8) { - create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier:) + create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier_id: supplier.id) } before do From 71b693896123e207a9225494480ba0d1e83c54f9 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 15:36:52 +1100 Subject: [PATCH 036/145] Fix API V0 order controller spec --- spec/controllers/api/v0/orders_controller_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/controllers/api/v0/orders_controller_spec.rb b/spec/controllers/api/v0/orders_controller_spec.rb index 6755ae0678..a6d15774fa 100644 --- a/spec/controllers/api/v0/orders_controller_spec.rb +++ b/spec/controllers/api/v0/orders_controller_spec.rb @@ -42,19 +42,19 @@ module Api let!(:order5) { create(:order, state: 'cart', completed_at: nil) } let!(:line_item1) do create(:line_item_with_shipment, order: order1, - product: create(:product, supplier:)) + product: create(:product, supplier_id: supplier.id)) end let!(:line_item2) do create(:line_item_with_shipment, order: order2, - product: create(:product, supplier:)) + product: create(:product, supplier_id: supplier.id)) end let!(:line_item3) do create(:line_item_with_shipment, order: order2, - product: create(:product, supplier:)) + product: create(:product, supplier_id: supplier.id)) end let!(:line_item4) do create(:line_item_with_shipment, order: order3, - product: create(:product, supplier:)) + product: create(:product, supplier_id: supplier.id)) end context 'as a regular user' do @@ -235,7 +235,7 @@ module Api it "returns unauthorized, as the order product's supplier owner" do allow(controller).to receive(:spree_current_user) { - order.line_items.first.variant.product.supplier.owner + order.line_items.first.variant.supplier.owner } get :show, params: { id: order.number } assert_unauthorized! From e48cdeba20cc836f1c9ade2d29628635ac126019 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 16:08:57 +1100 Subject: [PATCH 037/145] Fix product related permissions --- lib/open_food_network/permissions.rb | 26 ++++++++++--------- .../lib/open_food_network/permissions_spec.rb | 20 +++++++------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/lib/open_food_network/permissions.rb b/lib/open_food_network/permissions.rb index 27a0312a7f..87f43f052f 100644 --- a/lib/open_food_network/permissions.rb +++ b/lib/open_food_network/permissions.rb @@ -62,28 +62,26 @@ module OpenFoodNetwork def editable_products return Spree::Product.all if admin? - Spree::Product.where(supplier_id: @user.enterprises).or( - Spree::Product.where(supplier_id: related_enterprises_granting(:manage_products)) + product_with_variants.where(spree_variants: { supplier_id: @user.enterprises }).or( + product_with_variants.where( + spree_variants: { supplier_id: related_enterprises_granting(:manage_products) } + ) ) end def visible_products return Spree::Product.all if admin? - Spree::Product.where( - supplier_id: @user.enterprises - ).or( - Spree::Product.where( - supplier_id: related_enterprises_granting(:manage_products) | - related_enterprises_granting(:add_to_order_cycle) + product_with_variants.where(spree_variants: { supplier_id: @user.enterprises }).or( + product_with_variants.where( + spree_variants: { + supplier_id: related_enterprises_granting(:manage_products) | + related_enterprises_granting(:add_to_order_cycle) + } ) ) end - def product_ids_supplied_by(supplier_ids) - Spree::Product.where(supplier_id: supplier_ids).select(:id) - end - def managed_product_enterprises managed_and_related_enterprises_granting :manage_products end @@ -176,5 +174,9 @@ module OpenFoodNetwork def managed_enterprise_products Spree::Product.managed_by(@user) end + + def product_with_variants + Spree::Product.joins(:variants) + end end end diff --git a/spec/lib/open_food_network/permissions_spec.rb b/spec/lib/open_food_network/permissions_spec.rb index 457b1fd98f..d0c678a874 100644 --- a/spec/lib/open_food_network/permissions_spec.rb +++ b/spec/lib/open_food_network/permissions_spec.rb @@ -190,8 +190,8 @@ module OpenFoodNetwork end describe "#editable_products" do - let!(:p1) { create(:simple_product, supplier: create(:supplier_enterprise) ) } - let!(:p2) { create(:simple_product, supplier: create(:supplier_enterprise) ) } + let!(:p1) { create(:simple_product, supplier_id: create(:supplier_enterprise).id ) } + let!(:p2) { create(:simple_product, supplier_id: create(:supplier_enterprise).id ) } before do allow(permissions).to receive(:managed_enterprise_products) { Spree::Product.where('1=0') } @@ -202,7 +202,7 @@ module OpenFoodNetwork it "returns products produced by managed enterprises" do allow(user).to receive(:admin?) { false } - allow(user).to receive(:enterprises) { [p1.supplier] } + allow(user).to receive(:enterprises) { [p1.variants.first.supplier] } expect(permissions.editable_products).to eq([p1]) end @@ -211,7 +211,7 @@ module OpenFoodNetwork allow(user).to receive(:admin?) { false } allow(user).to receive(:enterprises) { [] } allow(permissions).to receive(:related_enterprises_granting). - with(:manage_products) { Enterprise.where(id: p2.supplier) } + with(:manage_products) { Enterprise.where(id: p2.variants.first.supplier) } expect(permissions.editable_products).to eq([p2]) end @@ -226,9 +226,9 @@ module OpenFoodNetwork end describe "finding visible products" do - let!(:p1) { create(:simple_product, supplier: create(:supplier_enterprise) ) } - let!(:p2) { create(:simple_product, supplier: create(:supplier_enterprise) ) } - let!(:p3) { create(:simple_product, supplier: create(:supplier_enterprise) ) } + let!(:p1) { create(:simple_product, supplier_id: create(:supplier_enterprise).id ) } + let!(:p2) { create(:simple_product, supplier_id: create(:supplier_enterprise).id ) } + let!(:p3) { create(:simple_product, supplier_id: create(:supplier_enterprise).id ) } before do allow(permissions).to receive(:managed_enterprise_products) { Spree::Product.where("1=0") } @@ -242,7 +242,7 @@ module OpenFoodNetwork it "returns products produced by managed enterprises" do allow(user).to receive(:admin?) { false } - allow(user).to receive(:enterprises) { Enterprise.where(id: p1.supplier_id) } + allow(user).to receive(:enterprises) { Enterprise.where(id: p1.variants.first.supplier_id) } expect(permissions.visible_products).to eq([p1]) end @@ -251,7 +251,7 @@ module OpenFoodNetwork allow(user).to receive(:admin?) { false } allow(user).to receive(:enterprises) { [] } allow(permissions).to receive(:related_enterprises_granting). - with(:manage_products) { Enterprise.where(id: p2.supplier) } + with(:manage_products) { Enterprise.where(id: p2.variants.first.supplier) } expect(permissions.visible_products).to eq([p2]) end @@ -260,7 +260,7 @@ module OpenFoodNetwork allow(user).to receive(:admin?) { false } allow(user).to receive(:enterprises) { [] } allow(permissions).to receive(:related_enterprises_granting). - with(:add_to_order_cycle) { Enterprise.where(id: p3.supplier).select(:id) } + with(:add_to_order_cycle) { Enterprise.where(id: p3.variants.first.supplier).select(:id) } expect(permissions.visible_products).to eq([p3]) end From e1c3f0a31c62d224ebc93efe88a02ab710e0f942 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 16:18:18 +1100 Subject: [PATCH 038/145] Fix product scope query Plus a small name refactor --- app/controllers/api/v0/products_controller.rb | 2 +- app/queries/product_scope_query.rb | 11 +++--- spec/queries/product_scope_query_spec.rb | 34 ++++++++++++++++--- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/app/controllers/api/v0/products_controller.rb b/app/controllers/api/v0/products_controller.rb index a85b1986d9..6df0356cf5 100644 --- a/app/controllers/api/v0/products_controller.rb +++ b/app/controllers/api/v0/products_controller.rb @@ -54,7 +54,7 @@ module Api end def overridable - @products = product_finder.paged_products_for_producers + @products = product_finder.products_for_producers render_paged_products @products, ::Api::Admin::ProductSimpleSerializer end diff --git a/app/queries/product_scope_query.rb b/app/queries/product_scope_query.rb index 00f4a401e8..1a89711c04 100644 --- a/app/queries/product_scope_query.rb +++ b/app/queries/product_scope_query.rb @@ -31,16 +31,17 @@ class ProductScopeQuery product_scope.find(@params[:product_id]) end - def paged_products_for_producers + def products_for_producers producer_ids = OpenFoodNetwork::Permissions.new(@user). variant_override_producers.by_name.select('enterprises.id') + # Use `order("enterprises.name")` instead of `by_producer scope`, the scope adds a join + # on variants which messes our query Spree::Product.where(nil). merge(product_scope). - includes(variants: [:product, :default_price, :stock_items]). - where(supplier_id: producer_ids). - by_producer.by_name. - ransack(@params[:q]).result + includes(variants: [:product, :default_price, :stock_items, :supplier]). + where(variants: { supplier_id: producer_ids }). + ransack(@params[:q]).result(distinct: true) end def product_scope diff --git a/spec/queries/product_scope_query_spec.rb b/spec/queries/product_scope_query_spec.rb index 197ec23aad..fb72a044a3 100755 --- a/spec/queries/product_scope_query_spec.rb +++ b/spec/queries/product_scope_query_spec.rb @@ -6,14 +6,14 @@ RSpec.describe ProductScopeQuery do let!(:taxon) { create(:taxon) } let(:supplier) { create(:supplier_enterprise) } let(:supplier2) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier:, primary_taxon: taxon) } - let!(:product2) { create(:product, supplier: supplier2, primary_taxon: taxon) } + let!(:product) { create(:product, supplier_id: supplier.id, primary_taxon: taxon) } + let!(:product2) { create(:product, supplier_id: supplier2.id, primary_taxon: taxon) } let!(:current_api_user) { supplier_enterprise_user(supplier) } before { current_api_user.enterprise_roles.create(enterprise: supplier2) } describe '#bulk_products' do - let!(:product3) { create(:product, supplier: supplier2) } + let!(:product3) { create(:product, supplier_id: supplier2.id) } it "returns a list of products" do expect(ProductScopeQuery.new(current_api_user, {}).bulk_products) @@ -22,7 +22,7 @@ RSpec.describe ProductScopeQuery do it "filters results by supplier" do subject = ProductScopeQuery - .new(current_api_user, { q: { supplier_id_eq: supplier.id } }).bulk_products + .new(current_api_user, { q: { variants_supplier_id_eq: supplier.id } }).bulk_products expect(subject).to include(product) expect(subject).not_to include(product2, product3) @@ -82,6 +82,32 @@ RSpec.describe ProductScopeQuery do end end + describe "#products_for_producers" do + subject(:query) { ProductScopeQuery.new(current_api_user, { page: 1, per_page: 20 }) } + + let(:hub) { create(:distributor_enterprise) } + let(:producer) { create(:supplier_enterprise) } + let!(:product3) { create(:product, supplier_id: producer.id) } + let!(:product4) { create(:product, supplier_id: producer.id) } + let!(:product5) { create(:product, supplier_id: supplier.id) } + let!(:er) { + create(:enterprise_relationship, parent: producer, child: hub, + permissions_list: [:create_variant_overrides]) + } + + before do + current_api_user.enterprise_roles.create(enterprise: hub) + end + + it "finds products by producer" do + # Add variants so we can check if we are not returning duplicate products + create(:variant, product: product3, supplier: producer) + create(:variant, product: product3, supplier: producer) + + expect(query.products_for_producers).to eq([product3, product4]) + end + end + private def supplier_enterprise_user(enterprise) From 507fa028c149d8a57dfe7cc8a49e906157ffbc99 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 16:30:31 +1100 Subject: [PATCH 039/145] Fix api admin serializers --- app/serializers/api/admin/product_serializer.rb | 2 -- app/serializers/api/admin/variant_serializer.rb | 3 ++- spec/serializers/api/admin/product_serializer_spec.rb | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/serializers/api/admin/product_serializer.rb b/app/serializers/api/admin/product_serializer.rb index 356c0debdf..836b78bdaa 100644 --- a/app/serializers/api/admin/product_serializer.rb +++ b/app/serializers/api/admin/product_serializer.rb @@ -7,8 +7,6 @@ module Api :inherits_properties, :on_hand, :price, :import_date, :image_url, :thumb_url, :variants - has_one :supplier, key: :producer_id, embed: :id - def variants ActiveModel::ArraySerializer.new( object.variants, diff --git a/app/serializers/api/admin/variant_serializer.rb b/app/serializers/api/admin/variant_serializer.rb index 06732aa7b5..5ccb8347c7 100644 --- a/app/serializers/api/admin/variant_serializer.rb +++ b/app/serializers/api/admin/variant_serializer.rb @@ -9,6 +9,7 @@ module Api :price, :on_demand, :on_hand, :in_stock, :stock_location_id, :stock_location_name has_one :primary_taxon, key: :category_id, embed: :id + has_one :supplier, key: :producer_id, embed: :id def name if object.full_name.present? @@ -31,7 +32,7 @@ module Api end def producer_name - object.product.supplier.name + object.supplier.name end def image diff --git a/spec/serializers/api/admin/product_serializer_spec.rb b/spec/serializers/api/admin/product_serializer_spec.rb index d2c0f25577..8cbb0a63ec 100644 --- a/spec/serializers/api/admin/product_serializer_spec.rb +++ b/spec/serializers/api/admin/product_serializer_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Api::Admin::ProductSerializer do - let(:product) { create(:simple_product) } + let(:product) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } let(:serializer) { described_class.new(product) } it "serializes a product" do From c82444efa91c7d794b5239be0e153b34d3d5045b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 16:34:01 +1100 Subject: [PATCH 040/145] Fix API v0 products controller --- .../api/v0/products_controller_spec.rb | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/spec/controllers/api/v0/products_controller_spec.rb b/spec/controllers/api/v0/products_controller_spec.rb index 3775ed1947..df999c4ab4 100644 --- a/spec/controllers/api/v0/products_controller_spec.rb +++ b/spec/controllers/api/v0/products_controller_spec.rb @@ -8,10 +8,10 @@ RSpec.describe Api::V0::ProductsController, type: :controller do let(:supplier) { create(:supplier_enterprise) } let(:supplier2) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier:) } - let!(:other_product) { create(:product) } - let(:product_other_supplier) { create(:product, supplier: supplier2) } - let(:product_with_image) { create(:product_with_image, supplier:) } + let!(:product) { create(:product, supplier_id: supplier.id) } + let!(:other_product) { create(:product, supplier_id: supplier.id) } + let(:product_other_supplier) { create(:product, supplier_id: supplier2.id) } + let(:product_with_image) { create(:product_with_image, supplier_id: supplier.id) } let(:all_attributes) { ["id", "name", "variants"] } let(:variants_attributes) { ["id", "options_text", "unit_value", "unit_description", "unit_to_display", "on_demand", @@ -36,7 +36,7 @@ RSpec.describe Api::V0::ProductsController, type: :controller do it "gets a single product" do product.create_image!(attachment:) product.variants.create!(unit_value: "1", unit_description: "thing", price: 1, - primary_taxon: taxon) + primary_taxon: taxon, supplier:) product.variants.first.images.create!(attachment:) product.set_property("spree", "rocks") @@ -120,7 +120,7 @@ RSpec.describe Api::V0::ProductsController, type: :controller do expect(response.status).to eq(422) expect(json_response["error"]).to eq("Invalid resource. Please fix errors and try again.") errors = json_response["errors"] - expect(errors.keys).to match_array(["name", "supplier", "variant_unit", "price"]) + expect(errors.keys).to match_array(["name", "variant_unit", "price"]) end it "can update a product" do @@ -228,9 +228,9 @@ RSpec.describe Api::V0::ProductsController, type: :controller do describe '#bulk_products' do context "as an enterprise user" do let!(:taxon) { create(:taxon) } - let!(:product2) { create(:product, supplier:, primary_taxon: taxon) } - let!(:product3) { create(:product, supplier: supplier2, primary_taxon: taxon) } - let!(:product4) { create(:product, supplier: supplier2) } + let!(:product2) { create(:product, supplier_id: supplier.id, primary_taxon: taxon) } + let!(:product3) { create(:product, supplier_id: supplier2.id, primary_taxon: taxon) } + let!(:product4) { create(:product, supplier_id: supplier2.id) } let(:current_api_user) { supplier_enterprise_user(supplier) } before { current_api_user.enterprise_roles.create(enterprise: supplier2) } @@ -262,7 +262,8 @@ RSpec.describe Api::V0::ProductsController, type: :controller do end it "filters results by supplier" do - api_get :bulk_products, { page: 1, per_page: 15, q: { supplier_id_eq: supplier.id } }, + api_get :bulk_products, + { page: 1, per_page: 15, q: { variants_supplier_id_eq: supplier.id } }, format: :json expect(returned_product_ids).to eq [product2.id, other_product.id, product.id] end From 656361c82d23111e39746d93f78497b6e33cc465 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 13 Mar 2024 16:45:07 +1100 Subject: [PATCH 041/145] Fix API v0 packing report --- lib/reporting/queries/joins.rb | 4 ++-- lib/reporting/reports/packing/base.rb | 2 +- spec/controllers/api/v0/reports/packing_report_spec.rb | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/reporting/queries/joins.rb b/lib/reporting/queries/joins.rb index e0097aa3a0..e4ad23e802 100644 --- a/lib/reporting/queries/joins.rb +++ b/lib/reporting/queries/joins.rb @@ -19,8 +19,8 @@ module Reporting reflect query.join(association(Spree::Variant, :product)) end - def joins_product_supplier - reflect query.join(association(Spree::Product, :supplier, supplier_alias)) + def joins_variant_supplier + reflect query.join(association(Spree::Variant, :supplier, supplier_alias)) end def joins_variant_shipping_category diff --git a/lib/reporting/reports/packing/base.rb b/lib/reporting/reports/packing/base.rb index 8fb00736d8..07ac39a59a 100644 --- a/lib/reporting/reports/packing/base.rb +++ b/lib/reporting/reports/packing/base.rb @@ -18,7 +18,7 @@ module Reporting joins_order_bill_address. joins_variant. joins_variant_product. - joins_product_supplier. + joins_variant_supplier. joins_variant_shipping_category. selecting(select_fields). ordered_by(ordering_fields) diff --git a/spec/controllers/api/v0/reports/packing_report_spec.rb b/spec/controllers/api/v0/reports/packing_report_spec.rb index 1b35ddbe66..1dbf9f287d 100644 --- a/spec/controllers/api/v0/reports/packing_report_spec.rb +++ b/spec/controllers/api/v0/reports/packing_report_spec.rb @@ -34,7 +34,7 @@ RSpec.describe Api::V0::ReportsController, type: :controller do context "as an enterprise user with partial order permissions (supplier with P-OC)" do let!(:order) { create(:completed_order_with_totals) } - let(:supplier) { order.line_items.first.product.supplier } + let(:supplier) { order.line_items.first.variant.supplier } let(:current_user) { supplier.owner } let!(:perms) { create(:enterprise_relationship, parent: supplier, child: order.distributor, @@ -62,7 +62,7 @@ RSpec.describe Api::V0::ReportsController, type: :controller do { "hub" => line_item.order.distributor.name, "customer_code" => line_item.order.customer&.code, - "supplier" => line_item.product.supplier.name, + "supplier" => line_item.variant.supplier.name, "product" => line_item.product.name, "variant" => line_item.full_name, "quantity" => line_item.quantity, @@ -80,7 +80,7 @@ RSpec.describe Api::V0::ReportsController, type: :controller do 'first_name' => '< Hidden >', 'last_name' => '< Hidden >', 'phone' => '< Hidden >', - "supplier" => line_item.product.supplier.name, + "supplier" => line_item.variant.supplier.name, "product" => line_item.product.name, "variant" => line_item.full_name, "quantity" => line_item.quantity, From 16709704fd271c7b77440246e3bedab4b85246a3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 10:36:54 +1100 Subject: [PATCH 042/145] Fix API v0 shipments controller --- spec/controllers/api/v0/shipments_controller_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/controllers/api/v0/shipments_controller_spec.rb b/spec/controllers/api/v0/shipments_controller_spec.rb index f7c9584e01..a4400e7cad 100644 --- a/spec/controllers/api/v0/shipments_controller_spec.rb +++ b/spec/controllers/api/v0/shipments_controller_spec.rb @@ -44,8 +44,8 @@ RSpec.describe Api::V0::ShipmentsController, type: :controller do before do order.update_attribute :ship_address_id, order_ship_address.id - order.update_attribute :distributor, variant.product.supplier - shipment.shipping_method.distributors << variant.product.supplier + order.update_attribute :distributor, variant.supplier + shipment.shipping_method.distributors << variant.supplier end context '#create' do @@ -364,7 +364,7 @@ RSpec.describe Api::V0::ShipmentsController, type: :controller do context "when line items have fees" do let(:fee_order) { - instance_double(Spree::Order, number: "123", distributor: variant.product.supplier) + instance_double(Spree::Order, number: "123", distributor: variant.supplier) } let(:contents) { instance_double(Spree::OrderContents) } let(:fee_order_shipment) { From 30decf3f34528a8960652fdef828a4e6b6d4fe42 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 10:40:39 +1100 Subject: [PATCH 043/145] Fix API V0 shops controller spec --- spec/controllers/api/v0/shops_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/api/v0/shops_controller_spec.rb b/spec/controllers/api/v0/shops_controller_spec.rb index 2cd251b762..c00be92165 100644 --- a/spec/controllers/api/v0/shops_controller_spec.rb +++ b/spec/controllers/api/v0/shops_controller_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Api::V0::ShopsController, type: :controller do } let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') } let!(:category) { create(:taxon, name: 'Fruit') } - let!(:product) { create(:product, supplier: producer, primary_taxon: category ) } + let!(:product) { create(:product, supplier_id: producer.id, primary_taxon: category ) } let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) } let!(:closed_hub1) { create(:distributor_enterprise) } let!(:closed_hub2) { create(:distributor_enterprise) } From 2e129eab8f24f7aa6f40e0aa9556af320772cded Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 11:08:10 +1100 Subject: [PATCH 044/145] Fix API V0 variants controller --- app/services/permitted_attributes/product.rb | 2 +- app/services/permitted_attributes/variant.rb | 3 ++- spec/controllers/api/v0/variants_controller_spec.rb | 13 +++++++------ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/app/services/permitted_attributes/product.rb b/app/services/permitted_attributes/product.rb index 1adc8ff7d9..1fd91fcd1a 100644 --- a/app/services/permitted_attributes/product.rb +++ b/app/services/permitted_attributes/product.rb @@ -4,7 +4,7 @@ module PermittedAttributes class Product def self.attributes [ - :id, :name, :description, :supplier_id, :price, + :id, :name, :description, :price, :variant_unit, :variant_unit_scale, :variant_unit_with_scale, :unit_value, :unit_description, :variant_unit_name, :display_as, :sku, :group_buy, :group_buy_unit_size, diff --git a/app/services/permitted_attributes/variant.rb b/app/services/permitted_attributes/variant.rb index 21f0f997b8..4d4fdcea38 100644 --- a/app/services/permitted_attributes/variant.rb +++ b/app/services/permitted_attributes/variant.rb @@ -7,7 +7,8 @@ module PermittedAttributes :id, :sku, :on_hand, :on_demand, :shipping_category_id, :price, :unit_value, :unit_description, :display_name, :display_as, :tax_category_id, - :weight, :height, :width, :depth, :taxon_ids, :primary_taxon_id + :weight, :height, :width, :depth, :taxon_ids, :primary_taxon_id, + :supplier_id ] end end diff --git a/spec/controllers/api/v0/variants_controller_spec.rb b/spec/controllers/api/v0/variants_controller_spec.rb index 496af4d6b4..1f053d0325 100644 --- a/spec/controllers/api/v0/variants_controller_spec.rb +++ b/spec/controllers/api/v0/variants_controller_spec.rb @@ -88,9 +88,9 @@ RSpec.describe Api::V0::VariantsController, type: :controller do context "as an enterprise user" do let(:current_api_user) { create(:user, enterprises: [supplier]) } let(:supplier_other) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier:) } + let!(:product) { create(:product, supplier_id: supplier.id) } let(:variant) { product.variants.first } - let(:product_other) { create(:product, supplier: supplier_other) } + let(:product_other) { create(:product, supplier_id: supplier_other.id) } let(:variant_other) { product_other.variants.first } context "with a single remaining variant" do @@ -102,7 +102,7 @@ RSpec.describe Api::V0::VariantsController, type: :controller do end context "with more than one variants" do - let(:variant_to_delete) { create(:variant, product:) } + let(:variant_to_delete) { create(:variant, product:, supplier:) } it "deletes a variant" do api_delete :destroy, id: variant_to_delete.id @@ -125,7 +125,7 @@ RSpec.describe Api::V0::VariantsController, type: :controller do context "as an administrator" do let(:current_api_user) { create(:admin_user) } - let(:product) { create(:product) } + let(:product) { create(:product, supplier_id: create(:supplier_enterprise).id) } let(:variant) { product.variants.first } let(:taxon) { create(:taxon) } let!(:variant2) { create(:variant, product:) } @@ -144,8 +144,9 @@ RSpec.describe Api::V0::VariantsController, type: :controller do it "can create a new variant" do original_number_of_variants = variant.product.variants.count - api_post :create, variant: { sku: "12345", unit_value: "1", - unit_description: "L", price: "1", primary_taxon_id: taxon.id }, + api_post :create, variant: { sku: "12345", unit_value: "1", unit_description: "L", + price: "1",primary_taxon_id: taxon.id, + supplier_id: variant.supplier.id}, product_id: variant.product.id expect(attributes.all?{ |attr| json_response.include? attr.to_s }).to eq(true) From 5b3e79e6c827196d07f9016eae17e3306e6df8cc Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 11:12:54 +1100 Subject: [PATCH 045/145] Fix Line Items controller specs --- spec/controllers/line_items_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/line_items_controller_spec.rb b/spec/controllers/line_items_controller_spec.rb index a825e77b35..42949bdcc4 100644 --- a/spec/controllers/line_items_controller_spec.rb +++ b/spec/controllers/line_items_controller_spec.rb @@ -168,7 +168,7 @@ RSpec.describe LineItemsController, type: :controller do } let(:enterprise_fee) { create(:enterprise_fee, calculator:) } let!(:exchange) { - create(:exchange, incoming: true, sender: variant1.product.supplier, + create(:exchange, incoming: true, sender: variant1.supplier, receiver: order_cycle.coordinator, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) } From 076200597d294f3bec0b7e289329cd70da5db2bd Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 11:44:13 +1100 Subject: [PATCH 046/145] Fix shop controller spec --- spec/controllers/shops_controller_spec.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/controllers/shops_controller_spec.rb b/spec/controllers/shops_controller_spec.rb index a12a964038..84d639eb13 100644 --- a/spec/controllers/shops_controller_spec.rb +++ b/spec/controllers/shops_controller_spec.rb @@ -30,7 +30,7 @@ RSpec.describe ShopsController, type: :controller do it 'renders distributed producer properties' do producer_property = create(:property, presentation: 'certified') producer = create(:supplier_enterprise, properties: [producer_property]) - product = create(:product) + product = create(:product, supplier_id: producer.id) create( :simple_order_cycle, @@ -53,7 +53,8 @@ RSpec.describe ShopsController, type: :controller do property = create(:property, presentation: 'dairy') product = create(:product, properties: [property]) - producer.supplied_products << product + + producer.supplied_variants << product.variants.first create( :simple_order_cycle, From 6d55f8ef2e3e08d269e161d8b881012fc5f5bc0d Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 11:47:19 +1100 Subject: [PATCH 047/145] Fix admin orders controller spec --- spec/controllers/spree/admin/orders_controller_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/controllers/spree/admin/orders_controller_spec.rb b/spec/controllers/spree/admin/orders_controller_spec.rb index d4dab4e0b2..6011c818db 100644 --- a/spec/controllers/spree/admin/orders_controller_spec.rb +++ b/spec/controllers/spree/admin/orders_controller_spec.rb @@ -75,7 +75,7 @@ RSpec.describe Spree::Admin::OrdersController, type: :controller do let(:order_cycle) { create(:simple_order_cycle, distributors: [distributor]) } let(:enterprise_fee) { create(:enterprise_fee, calculator: build(:calculator_per_item) ) } let!(:exchange) { - create(:exchange, incoming: true, sender: variant1.product.supplier, + create(:exchange, incoming: true, sender: variant1.supplier, receiver: order_cycle.coordinator, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) } @@ -234,7 +234,7 @@ RSpec.describe Spree::Admin::OrdersController, type: :controller do } before do - line_item.product.supplier = distributor + line_item.variant.supplier = distributor order.shipments << shipment order.line_items << line_item distributor.shipping_methods << shipment.shipping_method From 82b630c0c480ed940bf45f18a04306e877bc60fe Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 12:58:55 +1100 Subject: [PATCH 048/145] Partially fix admin product controller spec --- .../spree/admin/products_controller_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/controllers/spree/admin/products_controller_spec.rb b/spec/controllers/spree/admin/products_controller_spec.rb index 2e33fc3926..010e1468e4 100644 --- a/spec/controllers/spree/admin/products_controller_spec.rb +++ b/spec/controllers/spree/admin/products_controller_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do let(:s_managed) { create(:enterprise) } let(:s_unmanaged) { create(:enterprise) } let(:product) do - create(:simple_product, supplier: s_unmanaged, name: 'Peas') + create(:simple_product, supplier_id: s_unmanaged.id, name: 'Peas') end before do @@ -31,7 +31,7 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do let!(:product) do create( :simple_product, - supplier: producer, + supplier_id: producer.id, variant_unit: 'items', variant_unit_scale: nil, variant_unit_name: 'bunches', @@ -76,7 +76,7 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do let!(:product) do create( :simple_product, - supplier: producer, + supplier_id: producer.id, variant_unit: 'items', variant_unit_scale: nil, variant_unit_name: 'bunches', @@ -87,7 +87,7 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do let!(:another_product) do create( :simple_product, - supplier: producer, + supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1000, variant_unit_name: nil @@ -174,7 +174,7 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do describe "updating a product" do let(:producer) { create(:enterprise) } - let!(:product) { create(:simple_product, supplier: producer) } + let!(:product) { create(:simple_product, supplier_id: producer.id) } before do controller_login_as_enterprise_user [producer] From 93922b484ff09c0b95f19f051d5301e25b890f8f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 13:53:20 +1100 Subject: [PATCH 049/145] Fix admin variants controller specs --- spec/controllers/spree/admin/variants_controller_spec.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/spec/controllers/spree/admin/variants_controller_spec.rb b/spec/controllers/spree/admin/variants_controller_spec.rb index 8585415d0e..4ef69d61f7 100644 --- a/spec/controllers/spree/admin/variants_controller_spec.rb +++ b/spec/controllers/spree/admin/variants_controller_spec.rb @@ -12,7 +12,8 @@ module Spree let(:product) { create(:product, name: 'Product A') } let(:deleted_variant) do deleted_variant = product.variants.create( - unit_value: "2", price: 1, primary_taxon: create(:taxon) + unit_value: "2", price: 1, primary_taxon: create(:taxon), + supplier: create(:supplier_enterprise) ) deleted_variant.delete deleted_variant @@ -31,8 +32,9 @@ module Spree end describe "#search" do - let!(:p1) { create(:simple_product, name: 'Product 1') } - let!(:p2) { create(:simple_product, name: 'Product 2') } + let(:supplier) { create(:supplier_enterprise) } + let!(:p1) { create(:simple_product, name: 'Product 1', supplier_id: supplier.id) } + let!(:p2) { create(:simple_product, name: 'Product 2', supplier_id: supplier.id) } let!(:v1) { p1.variants.first } let!(:v2) { p2.variants.first } let!(:vo) { create(:variant_override, variant: v1, hub: d, count_on_hand: 44) } From f38e13b1a0f187220e10dc8028554e2c191272d0 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 13:58:12 +1100 Subject: [PATCH 050/145] Fix orders controller spec --- spec/controllers/spree/orders_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index f1f47762c2..e4eeb84b8c 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -283,7 +283,7 @@ RSpec.describe Spree::OrdersController, type: :controller do let(:order_cycle) { create(:simple_order_cycle, distributors: [distributor]) } let(:enterprise_fee) { create(:enterprise_fee, calculator: build(:calculator_per_item) ) } let!(:exchange) { - create(:exchange, incoming: true, sender: variant1.product.supplier, + create(:exchange, incoming: true, sender: variant1.supplier, receiver: order_cycle.coordinator, variants: [variant1, variant2], enterprise_fees: [enterprise_fee]) } From 80c4d9d03be4f7d1309fb6d3d63d0c57806ce768 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 14:11:16 +1100 Subject: [PATCH 051/145] Fix invoice template --- app/views/spree/admin/orders/_invoice_table.html.haml | 2 +- app/views/spree/admin/orders/_invoice_table2.html.haml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/spree/admin/orders/_invoice_table.html.haml b/app/views/spree/admin/orders/_invoice_table.html.haml index 04ac30e81a..6a83e036b6 100644 --- a/app/views/spree/admin/orders/_invoice_table.html.haml +++ b/app/views/spree/admin/orders/_invoice_table.html.haml @@ -16,7 +16,7 @@ = render 'spree/shared/line_item_name', line_item: item %br %small - %em= item.variant.product.supplier.name + %em= item.variant.supplier.name %td{:align => "right"} = item.quantity %td{:align => "right"} diff --git a/app/views/spree/admin/orders/_invoice_table2.html.haml b/app/views/spree/admin/orders/_invoice_table2.html.haml index 789737bdad..863a301b41 100644 --- a/app/views/spree/admin/orders/_invoice_table2.html.haml +++ b/app/views/spree/admin/orders/_invoice_table2.html.haml @@ -19,7 +19,7 @@ = render 'spree/shared/line_item_name', line_item: item %br %small - %em= item.variant.product.supplier.name + %em= item.variant.supplier.name %td{:align => "right"} = item.quantity %td{:align => "right"} From 1f904a3e2ff69fe967e760f003c6881decccad12 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 14:13:12 +1100 Subject: [PATCH 052/145] Fix orcer cycle form service spec --- spec/services/order_cycles/form_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/order_cycles/form_service_spec.rb b/spec/services/order_cycles/form_service_spec.rb index ca8c5e1b18..b0efb4fcee 100644 --- a/spec/services/order_cycles/form_service_spec.rb +++ b/spec/services/order_cycles/form_service_spec.rb @@ -138,7 +138,7 @@ RSpec.describe OrderCycles::FormService do let(:shipping_method) { create(:shipping_method, distributors: [distributor]) } let(:distributor_payment_method) { payment_method.distributor_payment_methods.first } let(:distributor_shipping_method) { shipping_method.distributor_shipping_methods.first } - let(:variant) { create(:variant, product: create(:product, supplier:)) } + let(:variant) { create(:variant, supplier:) } let(:params) { { name: 'Some new name' } } let(:form) { OrderCycles::FormService.new(order_cycle, params, user) } let(:outgoing_exchange_params) do From df209fdc2b742e5ed12faff53fa7d87eef84c96f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 14:21:08 +1100 Subject: [PATCH 053/145] Fix product tag rules filterer spec --- spec/services/product_tag_rules_filterer_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/services/product_tag_rules_filterer_spec.rb b/spec/services/product_tag_rules_filterer_spec.rb index eafd6d6d38..5fd88f7dfa 100644 --- a/spec/services/product_tag_rules_filterer_spec.rb +++ b/spec/services/product_tag_rules_filterer_spec.rb @@ -5,11 +5,11 @@ require "spec_helper" RSpec.describe ProductTagRulesFilterer do describe "filtering by tag rules" do let!(:distributor) { create(:distributor_enterprise) } - let(:product) { create(:product, supplier: distributor) } - let(:v1) { create(:variant, product:) } - let(:v2) { create(:variant, product:) } - let(:v3) { create(:variant, product:) } - let(:v4) { create(:variant, product:) } + let(:product) { create(:product, ) } + let(:v1) { create(:variant, product:, supplier: distributor) } + let(:v2) { create(:variant, product:, supplier: distributor) } + let(:v3) { create(:variant, product:, supplier: distributor) } + let(:v4) { create(:variant, product:, supplier: distributor) } let(:variant_hidden_by_default) { create(:variant_override, variant: v1, hub: distributor) } let(:variant_hidden_by_rule) { create(:variant_override, variant: v2, hub: distributor) } let(:variant_shown_by_rule) { create(:variant_override, variant: v3, hub: distributor) } @@ -18,7 +18,7 @@ RSpec.describe ProductTagRulesFilterer do } let(:customer) { create(:customer, enterprise: distributor) } let(:variants_relation) { - Spree::Variant.joins(:product).where(spree_products: { supplier_id: distributor.id }) + Spree::Variant.where(supplier: distributor.id) } let(:default_hide_rule) { create(:filter_products_tag_rule, From f8c2dfb3f7c5eb06d8970f434bf1ecfe5d795573 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 14 Mar 2024 14:27:27 +1100 Subject: [PATCH 054/145] Fix variants stock level sevice specs --- spec/services/variants_stock_levels_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/variants_stock_levels_spec.rb b/spec/services/variants_stock_levels_spec.rb index 630fc2c2de..13b2056d96 100644 --- a/spec/services/variants_stock_levels_spec.rb +++ b/spec/services/variants_stock_levels_spec.rb @@ -53,7 +53,7 @@ RSpec.describe VariantsStockLevels do describe "when the variant has an override" do let!(:distributor) { create(:distributor_enterprise) } - let(:supplier) { variant_in_the_order.product.supplier } + let(:supplier) { variant_in_the_order.supplier } let!(:order_cycle) { create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [variant_in_the_order, variant_not_in_the_order]) From c1dc87ae219c2560040d1eddc5fba3ad6fe245a0 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 18 Mar 2024 12:06:26 +1100 Subject: [PATCH 055/145] Fix enterprise fee calculator spec --- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb index 29f96c231a..5478e99934 100644 --- a/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb +++ b/spec/lib/open_food_network/enterprise_fee_calculator_spec.rb @@ -11,8 +11,8 @@ module OpenFoodNetwork let(:coordinator) { create(:distributor_enterprise) } let(:distributor) { create(:distributor_enterprise) } let(:order_cycle) { create(:simple_order_cycle) } - let(:product1) { create(:simple_product, supplier: supplier1, price: 10.00) } - let(:product2) { create(:simple_product, supplier: supplier2, price: 20.00) } + let(:product1) { create(:simple_product, supplier_id: supplier1.id, price: 10.00) } + let(:product2) { create(:simple_product, supplier_id: supplier2.id, price: 20.00) } describe "calculating fees for a variant" do describe "summing all the per-item fees for variant in the specified hub + order cycle" do From fddfd0dbfb3caae2e083471e5577667f207b24af Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 18 Mar 2024 13:33:40 +1100 Subject: [PATCH 056/145] Fix bulk coop report --- lib/reporting/reports/bulk_coop/base.rb | 2 +- spec/lib/reports/bulk_coop_report_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/reporting/reports/bulk_coop/base.rb b/lib/reporting/reports/bulk_coop/base.rb index 5bb079d923..ce4c154e35 100644 --- a/lib/reporting/reports/bulk_coop/base.rb +++ b/lib/reporting/reports/bulk_coop/base.rb @@ -22,7 +22,7 @@ module Reporting [ { order: [:bill_address], - variant: { product: :supplier } + variant: [:product, :supplier] } ] end diff --git a/spec/lib/reports/bulk_coop_report_spec.rb b/spec/lib/reports/bulk_coop_report_spec.rb index 775350d18d..fb6b64a7aa 100644 --- a/spec/lib/reports/bulk_coop_report_spec.rb +++ b/spec/lib/reports/bulk_coop_report_spec.rb @@ -122,7 +122,7 @@ module Reporting ship_address: create(:address)) end let(:li2) do - build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + build(:line_item_with_shipment, variant: create(:variant, supplier: s1)) end before do @@ -144,7 +144,7 @@ module Reporting ship_address: create(:address)) end let(:li2) do - build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + build(:line_item_with_shipment, variant: create(:variant, supplier: s1)) end before do From 323602abbb6de0adbb84fac4029bb3313a38ae08 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 18 Mar 2024 13:41:49 +1100 Subject: [PATCH 057/145] Fix customer report specs --- spec/lib/reports/customers_report_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/reports/customers_report_spec.rb b/spec/lib/reports/customers_report_spec.rb index bdd18d57b6..19f7283a78 100644 --- a/spec/lib/reports/customers_report_spec.rb +++ b/spec/lib/reports/customers_report_spec.rb @@ -209,7 +209,7 @@ module Reporting describe "fetching orders" do let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier:) } + let(:product) { create(:simple_product, supplier_id: supplier.id) } let(:order) { create(:order, completed_at: 1.day.ago) } it "only shows orders managed by the current user" do From 40892580cd0d0f40add97080e7fed052602afb24 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 19 Mar 2024 11:27:37 +1100 Subject: [PATCH 058/145] Fix enterprise fee summary report spec --- .../reports/enterprise_fee_summary/scope.rb | 9 +------- spec/factories/variant_factory.rb | 2 +- .../enterprise_fee_summary_report_spec.rb | 22 +++++++++---------- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/lib/reporting/reports/enterprise_fee_summary/scope.rb b/lib/reporting/reports/enterprise_fee_summary/scope.rb index 7b6ed51425..39e6e20ffd 100644 --- a/lib/reporting/reports/enterprise_fee_summary/scope.rb +++ b/lib/reporting/reports/enterprise_fee_summary/scope.rb @@ -224,13 +224,6 @@ module Reporting JOIN_STRING ) - join_scope( - <<~JOIN_STRING - LEFT OUTER JOIN spree_products - ON (spree_products.id = spree_variants.product_id) - JOIN_STRING - ) - join_scope( <<~JOIN_STRING LEFT OUTER JOIN spree_tax_categories AS product_tax_categories @@ -324,7 +317,7 @@ module Reporting def filter_by_distribution(params) filter_scope(spree_orders: { distributor_id: params.distributor_ids }) \ if params.distributor_ids.present? - filter_scope(spree_products: { supplier_id: params.producer_ids }) \ + filter_scope(spree_variants: { supplier_id: params.producer_ids }) \ if params.producer_ids.present? filter_scope(spree_orders: { order_cycle_id: params.order_cycle_ids }) \ if params.order_cycle_ids.present? diff --git a/spec/factories/variant_factory.rb b/spec/factories/variant_factory.rb index 3d134c73c4..50da2702b0 100644 --- a/spec/factories/variant_factory.rb +++ b/spec/factories/variant_factory.rb @@ -38,7 +38,7 @@ FactoryBot.define do trait :with_order_cycle do transient do order_cycle { create(:order_cycle) } - producer { product.supplier } + producer { supplier } coordinator { create(:distributor_enterprise) } distributor { create(:distributor_enterprise) } incoming_exchange_fees { [] } diff --git a/spec/lib/reports/enterprise_fee_summary/enterprise_fee_summary_report_spec.rb b/spec/lib/reports/enterprise_fee_summary/enterprise_fee_summary_report_spec.rb index a11f40a7ac..ceeb312b5b 100644 --- a/spec/lib/reports/enterprise_fee_summary/enterprise_fee_summary_report_spec.rb +++ b/spec/lib/reports/enterprise_fee_summary/enterprise_fee_summary_report_spec.rb @@ -523,21 +523,21 @@ RSpec.describe Reporting::Reports::EnterpriseFeeSummary::FeeSummary do let!(:producer_c) { create(:supplier_enterprise, name: "Producer C") } let!(:fee_a) { create(:enterprise_fee, name: "Fee A", enterprise: producer_a, amount: 1) } - let!(:fee_b) { create(:enterprise_fee, name: "Fee B", enterprise: producer_b, amount: 1) } - let!(:fee_c) { create(:enterprise_fee, name: "Fee C", enterprise: producer_c, amount: 1) } + let!(:fee_b) { create(:enterprise_fee, name: "Fee B", enterprise: producer_b, amount: 2) } + let!(:fee_c) { create(:enterprise_fee, name: "Fee C", enterprise: producer_c, amount: 3) } - let!(:product_a) { create(:product, supplier: producer_a) } - let!(:product_b) { create(:product, supplier: producer_b) } - let!(:product_c) { create(:product, supplier: producer_c) } + let!(:product_a) { create(:product, supplier_id: producer_a.id) } + let!(:product_b) { create(:product, supplier_id: producer_b.id) } + let!(:product_c) { create(:product, supplier_id: producer_c.id) } let!(:variant_a) do - prepare_variant(product: product_a, producer: producer_a, incoming_exchange_fees: [fee_a]) + prepare_variant(product: product_a, supplier: producer_a, incoming_exchange_fees: [fee_a]) end let!(:variant_b) do - prepare_variant(product: product_b, producer: producer_b, incoming_exchange_fees: [fee_b]) + prepare_variant(product: product_b, supplier: producer_b, incoming_exchange_fees: [fee_b]) end let!(:variant_c) do - prepare_variant(product: product_c, producer: producer_c, incoming_exchange_fees: [fee_c]) + prepare_variant(product: product_c, supplier: producer_c, incoming_exchange_fees: [fee_c]) end let!(:order_a) { prepare_order(variant: variant_a) } @@ -697,8 +697,7 @@ RSpec.describe Reporting::Reports::EnterpriseFeeSummary::FeeSummary do end def default_order_options - { customer:, distributor:, order_cycle:, - shipping_method:, variant: } + { customer:, distributor:, order_cycle:, shipping_method:, variant: } end def prepare_incomplete_order(options = {}) @@ -713,8 +712,7 @@ RSpec.describe Reporting::Reports::EnterpriseFeeSummary::FeeSummary do end def default_variant_options - { product:, producer:, coordinator:, - distributor:, order_cycle: } + { product:, coordinator:, distributor:, order_cycle: } end def prepare_variant(options = {}) From c273c6b15511442d7bb3898edd0380f968922feb Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 19 Mar 2024 11:30:22 +1100 Subject: [PATCH 059/145] Fix enterprise fee with tax report specs --- .../enterprise_fees_with_tax_report_by_producer_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer_spec.rb b/spec/lib/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer_spec.rb index a993becede..ae58f2e211 100644 --- a/spec/lib/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer_spec.rb +++ b/spec/lib/reports/enterprise_fee_summary/enterprise_fees_with_tax_report_by_producer_spec.rb @@ -26,7 +26,7 @@ RSpec.describe Reporting::Reports::EnterpriseFeeSummary::EnterpriseFeesWithTaxRe outgoing.exchange_variants.create(variant:) end } - let(:variant) { create(:product, supplier: enterprise).variants.first } + let(:variant) { create(:variant, supplier: enterprise) } let(:order) { create( :order, :with_line_item, From bfb4997207da95fdb2e4ca4ed21821794657a2c3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 8 Apr 2024 21:19:01 +1000 Subject: [PATCH 060/145] Fix product and inventory report, lettuce share --- lib/reporting/reports/products_and_inventory/lettuce_share.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reporting/reports/products_and_inventory/lettuce_share.rb b/lib/reporting/reports/products_and_inventory/lettuce_share.rb index 366332fd55..7d3fa4a807 100644 --- a/lib/reporting/reports/products_and_inventory/lettuce_share.rb +++ b/lib/reporting/reports/products_and_inventory/lettuce_share.rb @@ -65,7 +65,7 @@ module Reporting end def producer_name(variant) - variant.product.supplier.name + variant.supplier.name end def certification(variant) From 45f43653856986ad7d7c89481ed2513f053ad740 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 8 Apr 2024 21:23:18 +1000 Subject: [PATCH 061/145] Fix order cycle management report --- spec/lib/reports/order_cycle_management_report_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/reports/order_cycle_management_report_spec.rb b/spec/lib/reports/order_cycle_management_report_spec.rb index 65c3a2d86b..17136d5942 100644 --- a/spec/lib/reports/order_cycle_management_report_spec.rb +++ b/spec/lib/reports/order_cycle_management_report_spec.rb @@ -66,7 +66,7 @@ module Reporting describe "fetching orders" do let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier:) } + let(:product) { create(:simple_product, supplier_id: supplier.id) } let(:order) { create(:order, completed_at: 1.day.ago) } it "only shows orders managed by the current user" do From 17793e7b123ee656206cbda27bfff1c208144fd7 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 16 Apr 2024 09:35:19 +1000 Subject: [PATCH 062/145] Fix packing report spec --- .../reports/packing/packing_report_spec.rb | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/spec/lib/reports/packing/packing_report_spec.rb b/spec/lib/reports/packing/packing_report_spec.rb index 624a5dab5a..47553fe65b 100644 --- a/spec/lib/reports/packing/packing_report_spec.rb +++ b/spec/lib/reports/packing/packing_report_spec.rb @@ -3,8 +3,6 @@ require 'spec_helper' RSpec.describe "Packing Reports" do - include AuthenticationHelper - describe "fetching orders" do let(:distributor) { create(:distributor_enterprise) } let(:order_cycle) { create(:simple_order_cycle) } @@ -56,12 +54,20 @@ RSpec.describe "Packing Reports" do ship_address: create(:address)) } let(:line_item2) { - build(:line_item_with_shipment, - product: create(:simple_product, name: "visible", supplier: supplier1)) + build( + :line_item_with_shipment, + variant: create( + :variant, supplier: supplier1, product: create(:simple_product, name: "visible") + ) + ) } let(:line_item3) { - build(:line_item_with_shipment, - product: create(:simple_product, name: "not visible", supplier: supplier2)) + build( + :line_item_with_shipment, + variant: create( + :variant, supplier: supplier2, product: create(:simple_product, name: "not visible") + ) + ) } before do @@ -140,7 +146,7 @@ RSpec.describe "Packing Reports" do before do order4.line_items << line_item4 order4.finalize! - line_item4.variant.product.update(supplier: create(:supplier_enterprise)) + line_item4.variant.update(supplier: create(:supplier_enterprise)) end context "filtering by order cycle" do From 83fa080f7600b93ea6a1efcd370d173c0b41bced Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 17 Apr 2024 15:17:38 +1000 Subject: [PATCH 063/145] Fix product and inventory report --- .../reports/products_and_inventory/base.rb | 9 +- .../products_and_inventory_report_spec.rb | 82 +++++++++---------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/lib/reporting/reports/products_and_inventory/base.rb b/lib/reporting/reports/products_and_inventory/base.rb index 3b58daca76..06b1e9b3f0 100644 --- a/lib/reporting/reports/products_and_inventory/base.rb +++ b/lib/reporting/reports/products_and_inventory/base.rb @@ -13,8 +13,8 @@ module Reporting # rubocop:disable Metrics/AbcSize def columns { - supplier: proc { |variant| variant.product.supplier.name }, - producer_suburb: proc { |variant| variant.product.supplier.address.city }, + supplier: proc { |variant| variant.supplier.name }, + producer_suburb: proc { |variant| variant.supplier.address.city }, product: proc { |variant| variant.product.name }, product_properties: proc { |v| v.product.properties.map(&:name).join(", ") }, taxons: proc { |variant| variant.primary_taxon.name }, @@ -33,9 +33,10 @@ module Reporting def child_variants Spree::Variant. + select("spree_variants.*, spree_products.name"). joins(:product). merge(visible_products). - order('spree_products.name') + order('spree_products.name').distinct end private @@ -59,7 +60,7 @@ module Reporting def filter_to_supplier(variants) if params[:supplier_id].to_i > 0 - variants.where(spree_products: { supplier_id: params[:supplier_id] }) + variants.where(supplier: params[:supplier_id]) else variants end diff --git a/spec/lib/reports/products_and_inventory_report_spec.rb b/spec/lib/reports/products_and_inventory_report_spec.rb index 79b8c6d21c..ff8025d4e6 100644 --- a/spec/lib/reports/products_and_inventory_report_spec.rb +++ b/spec/lib/reports/products_and_inventory_report_spec.rb @@ -36,10 +36,8 @@ module Reporting full_name: "Variant Name", count_on_hand: 10, price: 100) - allow(variant).to receive_message_chain(:product, :supplier, - :name).and_return("Supplier") - allow(variant).to receive_message_chain(:product, :supplier, :address, - :city).and_return("A city") + allow(variant).to receive_message_chain(:supplier, :name).and_return("Supplier") + allow(variant).to receive_message_chain(:supplier, :address, :city).and_return("A city") allow(variant).to receive_message_chain(:product, :name).and_return("Product Name") allow(variant).to receive_message_chain(:product, :properties) .and_return [double(name: "property1"), double(name: "property2")] @@ -85,62 +83,62 @@ module Reporting describe "fetching child variants" do it "returns some variants" do - product1 = create(:simple_product, supplier:) - variant1 = product1.variants.first - variant2 = create(:variant, product: product1) + product1 = create(:simple_product) + variant1 = create(:variant, product: product1, supplier:) + variant2 = create(:variant, product: product1, supplier:) expect(subject.child_variants).to match_array [variant1, variant2] end it "should only return variants managed by the user" do - product1 = create(:simple_product, supplier: create(:supplier_enterprise)) - product2 = create(:simple_product, supplier:) - variant1 = product1.variants.first - variant2 = product2.variants.first + variant1 = create(:variant, supplier: create(:supplier_enterprise)) + variant2 = create(:variant, supplier:) - expect(subject.child_variants).to eq([variant2]) + expect(subject.child_variants).to match_array([variant2]) end end describe "Filtering variants" do - let(:variants) { Spree::Variant.where(nil).joins(:product) } + let(:variants) { Spree::Variant.joins(:product) } describe "based on report type" do it "returns only variants on hand" do - product1 = create(:simple_product, supplier:, on_hand: 99) - product2 = create(:simple_product, supplier:, on_hand: 0) + product1 = create(:simple_product, supplier_id: supplier.id, on_hand: 99) + product2 = create(:simple_product, supplier_id: supplier.id, on_hand: 0) subject = Inventory.new enterprise_user expect(subject.filter(variants)).to eq([product1.variants.first]) end end + it "filters to a specific supplier" do supplier2 = create(:supplier_enterprise) - product1 = create(:simple_product, supplier:) - product2 = create(:simple_product, supplier: supplier2) + variant1 = create(:variant, supplier: ) + variant2 = create(:variant, supplier: supplier2) allow(subject).to receive(:params).and_return(supplier_id: supplier.id) - expect(subject.filter(variants)).to eq([product1.variants.first]) + expect(subject.filter(variants)).to eq([variant1]) end + it "filters to a specific distributor" do distributor = create(:distributor_enterprise) - product1 = create(:simple_product, supplier:) - product2 = create(:simple_product, supplier:) + variant1 = create(:variant, supplier:) + variant2 = create(:variant, supplier:) order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], - variants: [product2.variants.first]) + variants: [variant2]) allow(subject).to receive(:params).and_return(distributor_id: distributor.id) - expect(subject.filter(variants)).to eq([product2.variants.first]) + expect(subject.filter(variants)).to eq([variant2]) end it "ignores variant overrides without filter" do distributor = create(:distributor_enterprise) - product = create(:simple_product, supplier:, price: 5) + product = create(:simple_product, supplier_id: supplier.id, price: 5) variant = product.variants.first order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], - variants: [product.variants.first]) + variants: [variant]) create(:variant_override, hub: distributor, variant:, price: 2) result = subject.filter(variants) @@ -150,11 +148,11 @@ module Reporting it "considers variant overrides with distributor" do distributor = create(:distributor_enterprise) - product = create(:simple_product, supplier:, price: 5) + product = create(:simple_product, supplier_id: supplier.id, price: 5) variant = product.variants.first order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], - variants: [product.variants.first]) + variants: [variant]) create(:variant_override, hub: distributor, variant:, price: 2) allow(subject).to receive(:params).and_return(distributor_id: distributor.id) @@ -165,14 +163,14 @@ module Reporting it "filters to a specific order cycle" do distributor = create(:distributor_enterprise) - product1 = create(:simple_product, supplier:) - product2 = create(:simple_product, supplier:) + variant1 = create(:variant, supplier:) + variant2 = create(:variant, supplier:) order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], - variants: [product1.variants.first]) + variants: [variant1]) allow(subject).to receive(:params).and_return(order_cycle_id: order_cycle.id) - expect(subject.filter(variants)).to eq([product1.variants.first]) + expect(subject.filter(variants)).to eq([variant1]) end it "should do all the filters at once" do @@ -181,15 +179,11 @@ module Reporting distributor = create(:distributor_enterprise) other_distributor = create(:distributor_enterprise) other_supplier = create(:supplier_enterprise) - not_filtered_variant = create(:simple_product, supplier:).variants.first - variant_filtered_by_order_cycle = create(:simple_product, - supplier:).variants.first - variant_filtered_by_distributor = create(:simple_product, - supplier:).variants.first - variant_filtered_by_supplier = create(:simple_product, - supplier: other_supplier).variants.first - variant_filtered_by_stock = create(:simple_product, supplier:, - on_hand: 0).variants.first + not_filtered_variant = create(:variant, supplier:) + variant_filtered_by_order_cycle = create(:variant, supplier:) + variant_filtered_by_distributor = create(:variant, supplier:) + variant_filtered_by_supplier = create(:variant, supplier: other_supplier) + variant_filtered_by_stock = create(:variant, supplier:, on_hand: 0) # This OC contains all products except the one that should be filtered # by order cycle. We create a separate OC further down to proof that @@ -273,6 +267,10 @@ module Reporting let(:report) do AllProducts.new user, { fields_to_hide: [] } end + # Creating a variant directly would create a product with another variant with no supplier + # which breaks the test + let(:variant) { create(:product).variants.first } + let(:supplier) { create(:supplier_enterprise) } it "Should return headers" do expect(report.table_headers).to eq([ @@ -292,10 +290,9 @@ module Reporting end it "Should render 'On demand' when the product is available on demand" do - product = create(:product) - variant = product.variants.first variant.on_demand = true variant.on_hand = 15 + variant.supplier = supplier variant.save! first_row = report.table_rows.first @@ -307,10 +304,9 @@ module Reporting end it "Should render the on hand count when the product is not available on demand" do - product = create(:product) - variant = product.variants.first variant.on_demand = false variant.on_hand = 22 + variant.supplier = supplier variant.save! first_row = report.table_rows.first From 6ee77fa40665bf4919410c4bbc1f813bc3b07d44 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 17 Apr 2024 15:30:07 +1000 Subject: [PATCH 064/145] Fix sales tax totals by order report --- spec/lib/reports/sales_tax_totals_by_order_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/reports/sales_tax_totals_by_order_spec.rb b/spec/lib/reports/sales_tax_totals_by_order_spec.rb index 641bc8030e..7987ddad0b 100644 --- a/spec/lib/reports/sales_tax_totals_by_order_spec.rb +++ b/spec/lib/reports/sales_tax_totals_by_order_spec.rb @@ -55,7 +55,7 @@ RSpec.describe "Reporting::Reports::SalesTax::SalesTaxTotalsByOrder" do end before do - product.update!(supplier_id: supplier.id) + variant.update!(supplier: ) order.update!( number: 'ORDER_NUMBER_1', From 25371ee9d0f98bd852dd12ee7c65dc5103111d86 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 23 Apr 2024 13:55:16 +1000 Subject: [PATCH 065/145] Fix admin pages - move supplier to variant row on Bulk Edit product page - add supplier dropdow on add/update variant page --- .../spree/admin/products_controller.rb | 10 ++-- .../spree/admin/variants_controller.rb | 8 +++ app/reflexes/products_reflex.rb | 2 +- app/services/exchange_variant_deleter.rb | 6 +-- app/services/permitted_attributes/product.rb | 2 +- .../admin/products_v3/_product_row.html.haml | 9 +--- .../admin/products_v3/_variant_row.html.haml | 9 +++- .../spree/admin/products/_form.html.haml | 6 --- .../spree/admin/variants/_form.html.haml | 4 ++ .../spree/admin/products_controller_spec.rb | 19 +------ .../spree/admin/variants_controller_spec.rb | 53 +++++++++++++++++++ spec/models/spree/product_spec.rb | 4 ++ 12 files changed, 87 insertions(+), 45 deletions(-) diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 32099627d8..b8aa975f2f 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -27,6 +27,9 @@ module Spree end def new + @producers = OpenFoodNetwork::Permissions.new(spree_current_user). + managed_product_enterprises.is_primary_producer.by_name + @object.shipping_category_id = DefaultShippingCategory.find_or_create.id end @@ -52,14 +55,9 @@ module Spree def update @url_filters = ::ProductFilters.new.extract(request.query_parameters) - original_supplier_id = @product.supplier_id delete_stock_params_and_set_after do params[:product] ||= {} if params[:clear_product_properties] if @object.update(permitted_resource_params) - if original_supplier_id != @product.supplier_id - ExchangeVariantDeleter.new.delete(@product) - end - flash[:success] = flash_message_for(@object, :successfully_updated) end redirect_to spree.edit_admin_product_url(@object, @url_filters) @@ -157,8 +155,6 @@ module Spree end def load_form_data - @producers = OpenFoodNetwork::Permissions.new(spree_current_user). - managed_product_enterprises.is_primary_producer.by_name @taxons = Spree::Taxon.order(:name) @import_dates = product_import_dates.uniq.to_json end diff --git a/app/controllers/spree/admin/variants_controller.rb b/app/controllers/spree/admin/variants_controller.rb index 47505f7b1d..33f29e1b45 100644 --- a/app/controllers/spree/admin/variants_controller.rb +++ b/app/controllers/spree/admin/variants_controller.rb @@ -46,7 +46,13 @@ module Spree def update @url_filters = ::ProductFilters.new.extract(request.query_parameters) + original_supplier_id = @object.supplier_id + if @object.update(permitted_resource_params) + if original_supplier_id != @object.supplier_id + ExchangeVariantDeleter.new.delete(@object) + end + flash[:success] = flash_message_for(@object, :successfully_updated) redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters) else @@ -113,6 +119,8 @@ module Spree private def load_data + @producers = OpenFoodNetwork::Permissions.new(spree_current_user). + managed_product_enterprises.is_primary_producer.by_name @tax_categories = TaxCategory.order(:name) @shipping_categories = ShippingCategory.order(:name) end diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index a2feef4d28..3816ce88fc 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -108,7 +108,7 @@ class ProductsReflex < ApplicationReflex def ransack_query query = {} - query.merge!(supplier_id_in: @producer_id) if @producer_id.present? + query.merge!(variant_supplier_id_in: @producer_id) if @producer_id.present? if @search_term.present? query.merge!(Spree::Variant::SEARCH_KEY => @search_term) end diff --git a/app/services/exchange_variant_deleter.rb b/app/services/exchange_variant_deleter.rb index 0db1abd884..beb005795b 100644 --- a/app/services/exchange_variant_deleter.rb +++ b/app/services/exchange_variant_deleter.rb @@ -1,9 +1,7 @@ # frozen_string_literal: true class ExchangeVariantDeleter - def delete(product) - ExchangeVariant. - where(variant_id: product.variants.select(:id)). - delete_all + def delete(variant) + ExchangeVariant.where(variant_id: variant.id).delete_all end end diff --git a/app/services/permitted_attributes/product.rb b/app/services/permitted_attributes/product.rb index 1fd91fcd1a..f080f2b730 100644 --- a/app/services/permitted_attributes/product.rb +++ b/app/services/permitted_attributes/product.rb @@ -8,7 +8,7 @@ module PermittedAttributes :variant_unit, :variant_unit_scale, :variant_unit_with_scale, :unit_value, :unit_description, :variant_unit_name, :display_as, :sku, :group_buy, :group_buy_unit_size, - :taxon_ids, :primary_taxon_id, :tax_category_id, + :taxon_ids, :primary_taxon_id, :tax_category_id, :supplier_id, :meta_keywords, :notes, :inherits_properties, { product_properties_attributes: [:id, :property_name, :value], variants_attributes: [PermittedAttributes::Variant.attributes], diff --git a/app/views/admin/products_v3/_product_row.html.haml b/app/views/admin/products_v3/_product_row.html.haml index 375e8ad47a..f5c4fd8b5d 100644 --- a/app/views/admin/products_v3/_product_row.html.haml +++ b/app/views/admin/products_v3/_product_row.html.haml @@ -25,13 +25,8 @@ -# empty %td.col-on_hand.align-right -# empty -%td.col-producer.naked_inputs - = render(SearchableDropdownComponent.new(form: f, - name: :supplier_id, - aria_label: t('.producer_field_name'), - options: producer_options, - selected_option: product.supplier_id, - placeholder_value: t('admin.products_v3.filters.search_for_producers'))) +%td.col-on_hand.align-right + -# empty %td.col-category.align-left -# empty %td.col-tax_category.align-left diff --git a/app/views/admin/products_v3/_variant_row.html.haml b/app/views/admin/products_v3/_variant_row.html.haml index 311b833e04..b137c25de0 100644 --- a/app/views/admin/products_v3/_variant_row.html.haml +++ b/app/views/admin/products_v3/_variant_row.html.haml @@ -39,8 +39,13 @@ = f.label :on_demand do = f.check_box :on_demand, 'data-action': 'change->toggle-control#disableIfPresent change->popout#closeIfChecked' = t(:on_demand) -%td.col-producer.align-left - -# empty producer name +%td.col-producer.naked_inputs + = render(SearchableDropdownComponent.new(form: f, + name: :supplier_id, + aria_label: t('.producer_field_name'), + options: producer_options, + selected_option: variant.supplier_id, + placeholder_value: t('admin.products_v3.filters.search_for_producers'))) %td.col-category.field.naked_inputs = render(SearchableDropdownComponent.new(form: f, name: :primary_taxon_id, diff --git a/app/views/spree/admin/products/_form.html.haml b/app/views/spree/admin/products/_form.html.haml index 1f3492c123..546efeace4 100644 --- a/app/views/spree/admin/products/_form.html.haml +++ b/app/views/spree/admin/products/_form.html.haml @@ -27,12 +27,6 @@ = f.text_field :variant_unit_name, {placeholder: t('admin.products.unit_name_placeholder')} = f.error_message_on :variant_unit_name - = f.field_container :supplier do - = f.label :supplier, t(:spree_admin_supplier) - %br - = f.collection_select(:supplier_id, @producers, :id, :name, {:include_blank => true}, {:class => "select2"}) - = f.error_message_on :supplier - .clear .clear diff --git a/app/views/spree/admin/variants/_form.html.haml b/app/views/spree/admin/variants/_form.html.haml index f90f15c1f7..dcb4d68b6e 100644 --- a/app/views/spree/admin/variants/_form.html.haml +++ b/app/views/spree/admin/variants/_form.html.haml @@ -76,4 +76,8 @@ = f.label :primary_taxon, t('spree.admin.products.primary_taxon_form.product_category') = f.collection_select(:primary_taxon_id, Spree::Taxon.order(:name), :id, :name, { include_blank: true }, { class: "select2 fullwidth" }) + .field + = f.label :supplier, t(:spree_admin_supplier) + = f.collection_select(:supplier_id, @producers, :id, :name, {:include_blank => true}, {:class => "select2 fullwidth"}) + .clear diff --git a/spec/controllers/spree/admin/products_controller_spec.rb b/spec/controllers/spree/admin/products_controller_spec.rb index 010e1468e4..f41c4adfcd 100644 --- a/spec/controllers/spree/admin/products_controller_spec.rb +++ b/spec/controllers/spree/admin/products_controller_spec.rb @@ -113,7 +113,8 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do "unit_value" => 4, "unit_description" => "", "display_name" => "name", - "primary_taxon_id" => taxon.id + "primary_taxon_id" => taxon.id, + "supplier_id" => producer.id } ] } @@ -180,22 +181,6 @@ RSpec.describe Spree::Admin::ProductsController, type: :controller do controller_login_as_enterprise_user [producer] end - describe "change product supplier" do - let(:distributor) { create(:distributor_enterprise) } - let!(:order_cycle) { - create(:simple_order_cycle, variants: [product.variants.first], coordinator: distributor, - distributors: [distributor]) - } - - it "should remove product from existing Order Cycles" do - new_producer = create(:enterprise) - spree_put :update, id: product, product: { supplier_id: new_producer.id } - - expect(product.reload.supplier.id).to eq new_producer.id - expect(order_cycle.reload.distributed_variants).not_to include product.variants.first - end - end - describe "product stock setting with errors" do it "notifies bugsnag and still raise error" do # forces an error in the variant diff --git a/spec/controllers/spree/admin/variants_controller_spec.rb b/spec/controllers/spree/admin/variants_controller_spec.rb index 4ef69d61f7..3ee35450ff 100644 --- a/spec/controllers/spree/admin/variants_controller_spec.rb +++ b/spec/controllers/spree/admin/variants_controller_spec.rb @@ -31,6 +31,59 @@ module Spree end end + describe "#update" do + let!(:variant) { create(:variant, display_name: "Tomatoes", sku: 123, supplier: producer) } + let(:producer) { create(:enterprise) } + + it "updates the variant" do + expect { + spree_put( + :update, + id: variant.id, + product_id: variant.product.id, + variant: { display_name: "Better tomatoes", sku: 456 } + ) + variant.reload + }.to change { variant.display_name }.to("Better tomatoes") + .and change { variant.sku }.to(456.to_s) + end + + context "when updating supplier" do + let(:new_producer) { create(:enterprise) } + + it "updates the supplier" do + expect { + spree_put( + :update, + id: variant.id, + product_id: variant.product.id, + variant: { supplier_id: new_producer.id } + ) + variant.reload + }.to change { variant.supplier_id }.to(new_producer.id) + end + + it "removes associated product from existing Order Cycles" do + distributor = create(:distributor_enterprise) + order_cycle = create( + :simple_order_cycle, + variants: [variant], + coordinator: distributor, + distributors: [distributor] + ) + + spree_put( + :update, + id: variant.id, + product_id: variant.product.id, + variant: { supplier_id: new_producer.id } + ) + + expect(order_cycle.reload.distributed_variants).to_not include variant + end + end + end + describe "#search" do let(:supplier) { create(:supplier_enterprise) } let!(:p1) { create(:simple_product, name: 'Product 1', supplier_id: supplier.id) } diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 41aa38f8e1..b9dce1b3b1 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -184,6 +184,7 @@ module Spree let!(:product){ Spree::Product.new } let!(:shipping_category){ create(:shipping_category) } let!(:taxon){ create(:taxon) } + let(:supplier){ create(:enterprise) } before do create(:stock_location) @@ -194,15 +195,18 @@ module Spree product.unit_value = 1 product.price = 4.27 product.shipping_category_id = shipping_category.id + product.supplier_id = supplier.id product.save! end it "copies properties to the first standard variant" do expect(product.variants.reload.length).to eq 1 standard_variant = product.variants.reload.first + expect(standard_variant).to be_valid expect(standard_variant.price).to eq 4.27 expect(standard_variant.shipping_category).to eq shipping_category expect(standard_variant.primary_taxon).to eq taxon + expect(standard_variant.supplier).to eq supplier end end From 63807f198b2b18dfb5c44604dd8eda8ccf8c4438 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 6 May 2024 15:28:53 +1000 Subject: [PATCH 066/145] Fix product set, to handle updating supplier on the variant --- app/services/sets/product_set.rb | 4 +- spec/services/sets/product_set_spec.rb | 62 +++++++++++++++++--------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/app/services/sets/product_set.rb b/app/services/sets/product_set.rb index 04138eedbc..15ffe47e21 100644 --- a/app/services/sets/product_set.rb +++ b/app/services/sets/product_set.rb @@ -55,8 +55,6 @@ module Sets def update_product(product, attributes) return false unless update_product_only_attributes(product, attributes) - ExchangeVariantDeleter.new.delete(product) if product.saved_change_to_supplier_id? - update_product_variants(product, attributes) end @@ -107,6 +105,8 @@ module Sets if variant.present? variant.assign_attributes(variant_attributes.except(:id)) variant.save if variant.changed? + + ExchangeVariantDeleter.new.delete(variant) if variant.saved_change_to_supplier_id? else variant = create_variant(product, variant_attributes) end diff --git a/spec/services/sets/product_set_spec.rb b/spec/services/sets/product_set_spec.rb index 3d2181c493..f24fefcd76 100644 --- a/spec/services/sets/product_set_spec.rb +++ b/spec/services/sets/product_set_spec.rb @@ -93,8 +93,6 @@ RSpec.describe Sets::ProductSet do end context "when the product is in an order cycle" do - let(:producer) { create(:enterprise) } - let(:distributor) { create(:distributor_enterprise) } let!(:order_cycle) { create(:simple_order_cycle, variants: [product.variants.first], @@ -117,22 +115,6 @@ RSpec.describe Sets::ProductSet do expect(order_cycle.distributed_variants).to include product.variants.first end end - - context 'and a different supplier is passed' do - let(:collection_hash) do - { 0 => { id: product.id, supplier_id: producer.id } } - end - - it 'updates the product and removes the product from order cycles' do - expect { - product_set.save - product.reload - }.to change { product.supplier }.to(producer). - and change { order_cycle.distributed_variants.count }.by(-1) - - expect(order_cycle.distributed_variants).not_to include product.variants.first - end - end end context "when product attributes are not changed" do @@ -158,7 +140,7 @@ RSpec.describe Sets::ProductSet do end describe "updating a product's variants" do - let(:product) { create(:simple_product) } + let(:product) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } let(:variant) { product.variants.first } let(:product_attributes) { {} } let(:variant_attributes) { { sku: "var_sku" } } @@ -228,6 +210,41 @@ RSpec.describe Sets::ProductSet do end end + context "when the variant is in an order cycle" do + let(:distributor) { create(:distributor_enterprise) } + let!(:order_cycle) { + create(:simple_order_cycle, variants: [variant], + coordinator: distributor, + distributors: [distributor]) + } + let(:variant_attributes) { { display_name: "New season variant" } } + + it 'updates the variant and keeps it in order cycles' do + expect { + product_set.save + variant.reload + }.to change { variant.display_name }.to("New season variant"). + and change { order_cycle.distributed_variants.count }.by(0) + + expect(order_cycle.distributed_variants).to include variant + end + + context 'when supplier is updated' do + let(:producer) { create(:supplier_enterprise) } + let(:variant_attributes) { { supplier_id: producer.id } } + + it 'updates the variant and removes the variant from order cycles' do + expect { + product_set.save + variant.reload + }.to change { variant.supplier }.to(producer). + and change { order_cycle.distributed_variants.count }.by(-1) + + expect(order_cycle.distributed_variants).to_not include variant + end + end + end + context "when products attributes are also updated" do let(:product_attributes) { { sku: "prod_sku" } @@ -286,9 +303,11 @@ RSpec.describe Sets::ProductSet do let(:variants_attributes) { [ { id: product.variants.first.id.to_s }, # default variant unchanged - { sku: "new sku", price: "5.00", unit_value: "5" }, # omit ID for new variant + # omit ID for new variant + { sku: "new sku", price: "5.00", unit_value: "5", supplier_id: supplier.id }, ] } + let(:supplier) { create(:supplier_enterprise) } it "creates new variant" do expect { @@ -305,7 +324,8 @@ RSpec.describe Sets::ProductSet do let(:variants_attributes) { [ { id: product.variants.first.id.to_s }, # default variant unchanged - { sku: "new sku", unit_value: "blah" }, # price missing, unit_value should be number + # price missing, unit_value should be number + { sku: "new sku", unit_value: "blah", supplier_id: supplier.id }, ] } From b891a03468876b7b6b05feee8b88dbff7739529b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 6 May 2024 15:43:59 +1000 Subject: [PATCH 067/145] Fix search by producer, BUU product page --- app/models/spree/variant.rb | 2 +- app/reflexes/products_reflex.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index b2ed204dd6..f0198f0171 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -23,7 +23,7 @@ module Spree meta_keywords variants_display_as variants_display_name - supplier_name).join('_or_')}_cont".freeze + variants_supplier_name).join('_or_')}_cont".freeze belongs_to :product, -> { with_deleted }, required: true, touch: true, class_name: 'Spree::Product' belongs_to :tax_category, class_name: 'Spree::TaxCategory' diff --git a/app/reflexes/products_reflex.rb b/app/reflexes/products_reflex.rb index 3816ce88fc..c96f49050e 100644 --- a/app/reflexes/products_reflex.rb +++ b/app/reflexes/products_reflex.rb @@ -108,7 +108,7 @@ class ProductsReflex < ApplicationReflex def ransack_query query = {} - query.merge!(variant_supplier_id_in: @producer_id) if @producer_id.present? + query.merge!(variants_supplier_id_in: @producer_id) if @producer_id.present? if @search_term.present? query.merge!(Spree::Variant::SEARCH_KEY => @search_term) end From 78abe36327828fbd9b1f0537e308a18c7711c5ae Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 6 May 2024 16:47:50 +1000 Subject: [PATCH 068/145] Fix BUU product page specs --- .../admin/products_v3_controller.rb | 4 +-- app/views/admin/products_v3/_table.html.haml | 25 ++++++++++++++++++- config/locales/en.yml | 1 - .../system/admin/products_v3/products_spec.rb | 21 +++++++--------- 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/app/controllers/admin/products_v3_controller.rb b/app/controllers/admin/products_v3_controller.rb index 28f352009f..327a4a4be9 100644 --- a/app/controllers/admin/products_v3_controller.rb +++ b/app/controllers/admin/products_v3_controller.rb @@ -149,7 +149,7 @@ module Admin def ransack_query query = {} - query.merge!(supplier_id_in: @producer_id) if @producer_id.present? + query.merge!(variants_supplier_id_in: @producer_id) if @producer_id.present? if @search_term.present? query.merge!(Spree::Variant::SEARCH_KEY => @search_term) end @@ -163,13 +163,13 @@ module Admin def product_query_includes [ :image, - :supplier, { variants: [ :default_price, :primary_taxon, :product, :stock_items, :tax_category, + :supplier, ] }, ] end diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index e04f33b00a..524b3d6d4a 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -63,4 +63,27 @@ %th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties') %th.align-right= t('admin.products_page.columns.actions') - products.each_with_index do |product, product_index| - = render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: } + = form.fields_for("products", product, index: product_index) do |product_form| + %tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id, + controller: "nested-form product", + action: 'rails-nested-form:add->bulk-form#registerElements rails-nested-form:remove->bulk-form#toggleFormChanged' } } + %tr + = render partial: 'product_row', locals: { f: product_form, product: } + + - product.variants.each_with_index do |variant, variant_index| + = form.fields_for("products][#{product_index}][variants_attributes][", variant, index: variant_index) do |variant_form| + %tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false } + = render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: } + + = form.fields_for("products][#{product_index}][variants_attributes][NEW_RECORD", product.variants.build) do |new_variant_form| + %template{ 'data-nested-form-target': "template" } + %tr.condensed{ 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': "true" } + = render partial: 'variant_row', locals: { variant: new_variant_form.object, f: new_variant_form, category_options:, tax_category_options:, producer_options: } + + %tr{ 'data-nested-form-target': "target" } + %tr.condensed + %td + %td{ colspan: 11 } + %button.secondary.condensed.naked.icon-plus{ 'data-action': "nested-form#add", + 'aria-label': t('.new_variant') } + =t('.new_variant') diff --git a/config/locales/en.yml b/config/locales/en.yml index d8d47d2423..d0764b7a91 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -917,7 +917,6 @@ en: search_for_tax_categories: "Search for tax categories" category_field_name: "Category" tax_category_field_name: "Tax Category" - product_row: producer_field_name: "Producer" clone: success: Successfully cloned the product diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index ca829c2b33..e2293de943 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -97,11 +97,11 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi end it "should not display search input, change the producers, category and tax category" do - producer_to_select = random_producer(product_a) + producer_to_select = random_producer(variant_a1) category_to_select = random_category(variant_a1) tax_category_to_select = random_tax_category - within row_containing_name(product_a.name) do + within row_containing_name(variant_a1.display_name) do validate_tomselect_without_search!( page, "Producer", producer_search_selector @@ -126,10 +126,9 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi click_button "Save changes" expect(page).to have_content "Changes saved" - product_a.reload - variant_a1.reload - expect(product_a.supplier.name).to eq(producer_to_select) + variant_a1.reload + expect(variant_a1.supplier.name).to eq(producer_to_select) expect(variant_a1.primary_taxon.name).to eq(category_to_select) expect(variant_a1.tax_category.name).to eq(tax_category_to_select) end @@ -145,19 +144,17 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi end it "should display search input, change the producer" do - producer_to_select = random_producer(product_a) + producer_to_select = random_producer(variant_a1) category_to_select = random_category(variant_a1) tax_category_to_select = random_tax_category - within row_containing_name(product_a.name) do + within row_containing_name(variant_a1.display_name) do validate_tomselect_with_search!( page, "Producer", producer_search_selector ) tomselect_search_and_select(producer_to_select, from: "Producer") - end - within row_containing_name(variant_a1.display_name) do sleep(0.1) validate_tomselect_with_search!( page, "Category", @@ -176,10 +173,9 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi click_button "Save changes" expect(page).to have_content "Changes saved" - product_a.reload - variant_a1.reload - expect(product_a.supplier.name).to eq(producer_to_select) + variant_a1.reload + expect(variant_a1.supplier.name).to eq(producer_to_select) expect(variant_a1.primary_taxon.name).to eq(category_to_select) expect(variant_a1.tax_category.name).to eq(tax_category_to_select) end @@ -246,6 +242,7 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi describe "Cloning product" do it "shows the cloned product on page when clicked on the cloned option" do + # TODO, variant supplier missing, needs to be copied from variant and not product within "table.products" do # Gather input values, because page.content doesn't include them. input_content = page.find_all('input[type=text]').map(&:value).join From 2ab9ccf73d1a16446da9ccc387123451d7fe63dd Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 7 May 2024 13:04:09 +1000 Subject: [PATCH 069/145] Bulk edit product, move supplier dropdown to variant --- app/views/spree/admin/products/index/_products_product.html.haml | 1 - app/views/spree/admin/products/index/_products_variant.html.haml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/spree/admin/products/index/_products_product.html.haml b/app/views/spree/admin/products/index/_products_product.html.haml index e399d64aa3..b5a778a043 100644 --- a/app/views/spree/admin/products/index/_products_product.html.haml +++ b/app/views/spree/admin/products/index/_products_product.html.haml @@ -6,7 +6,6 @@ %a{class: 'image-modal'} %img{'ng-src' => '{{ product.thumb_url }}'} %td.producer{ 'ng-show' => 'columns.producer.visible' } - %select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'product.producer_id', :name => 'producer_id', 'ofn-track-product' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' } %td.sku{ 'ng-show' => 'columns.sku.visible' } %input{ 'ng-model' => "product.sku", :name => 'product_sku', 'ofn-track-product' => 'sku', :type => 'text' } %td.name{ 'ng-show' => 'columns.name.visible' } diff --git a/app/views/spree/admin/products/index/_products_variant.html.haml b/app/views/spree/admin/products/index/_products_variant.html.haml index 48c732c155..2d1119f8a5 100644 --- a/app/views/spree/admin/products/index/_products_variant.html.haml +++ b/app/views/spree/admin/products/index/_products_variant.html.haml @@ -4,6 +4,7 @@ %a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last", 'ofn-with-tip' => t('.new_variant') } %td{ 'ng-show' => 'columns.image.visible' } %td{ 'ng-show' => 'columns.producer.visible' } + %select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'variant.producer_id', :name => 'producer_id', 'ofn-track-product' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' } %td{ 'ng-show' => 'columns.sku.visible' } %input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' } %td{ 'ng-show' => 'columns.name.visible' } From 9f612270c7fcdc6a1df28ed1cbc10a311c19714b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 8 May 2024 13:52:40 +1000 Subject: [PATCH 070/145] Fix bulk update product page old style and related product pages --- .../admin/bulk_product_update.js.coffee | 10 +-- .../spree/admin/products_controller.rb | 10 ++- .../index/_products_variant.html.haml | 2 +- .../admin/bulk_product_update_spec.js.coffee | 4 +- spec/system/admin/bulk_product_update_spec.rb | 68 +++++++++++-------- 5 files changed, 56 insertions(+), 38 deletions(-) diff --git a/app/assets/javascripts/admin/bulk_product_update.js.coffee b/app/assets/javascripts/admin/bulk_product_update.js.coffee index 5adb65c399..7df51e7711 100644 --- a/app/assets/javascripts/admin/bulk_product_update.js.coffee +++ b/app/assets/javascripts/admin/bulk_product_update.js.coffee @@ -47,7 +47,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout removeClearedValues() params = { 'q[name_cont]': $scope.q.query, - 'q[supplier_id_eq]': $scope.q.producerFilter, + 'q[variants_supplier_id_eq]': $scope.q.producerFilter, 'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter, 'q[s]': $scope.sorting, import_date: $scope.q.importDateFilter, @@ -217,7 +217,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout products: productsToSubmit filters: 'q[name_cont]': $scope.q.query - 'q[supplier_id_eq]': $scope.q.producerFilter + 'q[variants_supplier_id_eq]': $scope.q.producerFilter 'q[variants_primary_taxon_id_eq]': $scope.q.categoryFilter 'q[s]': $scope.sorting import_date: $scope.q.importDateFilter @@ -314,9 +314,6 @@ filterSubmitProducts = (productsToFilter) -> if product.hasOwnProperty("name") filteredProduct.name = product.name hasUpdatableProperty = true - if product.hasOwnProperty("producer_id") - filteredProduct.supplier_id = product.producer_id - hasUpdatableProperty = true if product.hasOwnProperty("price") filteredProduct.price = product.price hasUpdatableProperty = true @@ -379,6 +376,9 @@ filterSubmitVariant = (variant) -> if variant.hasOwnProperty("display_as") filteredVariant.display_as = variant.display_as hasUpdatableProperty = true + if variant.hasOwnProperty("producer_id") + filteredVariant.supplier_id = variant.producer_id + hasUpdatableProperty = true {filteredVariant: filteredVariant, hasUpdatableProperty: hasUpdatableProperty} diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index b8aa975f2f..9071f4e20b 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -12,6 +12,7 @@ module Spree include EnterprisesHelper before_action :load_data + before_action :load_producers, only: [:index, :new] before_action :load_form_data, only: [:index, :new, :create, :edit, :update] before_action :load_spree_api_key, only: [:index, :variant_overrides] before_action :strip_new_properties, only: [:create, :update] @@ -27,9 +28,6 @@ module Spree end def new - @producers = OpenFoodNetwork::Permissions.new(spree_current_user). - managed_product_enterprises.is_primary_producer.by_name - @object.shipping_category_id = DefaultShippingCategory.find_or_create.id end @@ -44,6 +42,7 @@ module Spree flash[:success] = flash_message_for(@object, :successfully_created) redirect_after_save else + load_producers # Re-fill the form with deleted params on product @on_hand = request.params[:product][:on_hand] @on_demand = request.params[:product][:on_demand] @@ -159,6 +158,11 @@ module Spree @import_dates = product_import_dates.uniq.to_json end + def load_producers + @producers = OpenFoodNetwork::Permissions.new(spree_current_user). + managed_product_enterprises.is_primary_producer.by_name + end + def product_import_dates options = [{ id: '0', name: '' }] product_import_dates_query.collect(&:import_date). diff --git a/app/views/spree/admin/products/index/_products_variant.html.haml b/app/views/spree/admin/products/index/_products_variant.html.haml index 2d1119f8a5..8a5c2c0311 100644 --- a/app/views/spree/admin/products/index/_products_variant.html.haml +++ b/app/views/spree/admin/products/index/_products_variant.html.haml @@ -4,7 +4,7 @@ %a{ :class => "add-variant icon-plus-sign", 'ng-click' => "addVariant(product)", 'ng-show' => "$last", 'ofn-with-tip' => t('.new_variant') } %td{ 'ng-show' => 'columns.image.visible' } %td{ 'ng-show' => 'columns.producer.visible' } - %select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'variant.producer_id', :name => 'producer_id', 'ofn-track-product' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' } + %select.fullwidth{ "data-controller": "tom-select", 'ng-model' => 'variant.producer_id', :name => 'producer_id', 'ofn-track-variant' => 'producer_id', 'ng-options' => 'producer.id as producer.name for producer in producers' } %td{ 'ng-show' => 'columns.sku.visible' } %input{ 'ng-model' => "variant.sku", :name => 'variant_sku', 'ofn-track-variant' => 'sku', :type => 'text' } %td{ 'ng-show' => 'columns.name.visible' } diff --git a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee index 57f6225110..77802a3df2 100644 --- a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee +++ b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee @@ -192,7 +192,6 @@ describe "filtering products for submission to database", -> updated_at: null on_hand: 0 on_demand: false - producer_id: 5 group_buy: null group_buy_unit_size: null variants: [ @@ -204,6 +203,7 @@ describe "filtering products for submission to database", -> unit_description: "(bottle)" display_as: "bottle" display_name: "nothing" + producer_id: 5 ] variant_unit: 'volume' variant_unit_scale: 1 @@ -213,7 +213,6 @@ describe "filtering products for submission to database", -> expect(filterSubmitProducts([testProduct])).toEqual [ id: 1 name: "TestProduct" - supplier_id: 5 variant_unit: 'volume' variant_unit_scale: 1 variant_unit_name: 'loaf' @@ -226,6 +225,7 @@ describe "filtering products for submission to database", -> unit_description: "(bottle)" display_as: "bottle" display_name: "nothing" + supplier_id: 5 ] ] diff --git a/spec/system/admin/bulk_product_update_spec.rb b/spec/system/admin/bulk_product_update_spec.rb index b53ff6d819..1bf458bce2 100644 --- a/spec/system/admin/bulk_product_update_spec.rb +++ b/spec/system/admin/bulk_product_update_spec.rb @@ -30,10 +30,12 @@ RSpec.describe ' s1 = FactoryBot.create(:supplier_enterprise) s2 = FactoryBot.create(:supplier_enterprise) s3 = FactoryBot.create(:supplier_enterprise) - p1 = FactoryBot.create(:product, supplier: s2) - p2 = FactoryBot.create(:product, supplier: s3) + p1 = FactoryBot.create(:product, supplier_id: s2.id) + p2 = FactoryBot.create(:product, supplier_id: s3.id) visit spree.admin_products_path + # the supplier dropdown is on the variant row, so we expand all for the dropdown to be visible + click_expand_all expect(page).to have_select "producer_id", with_options: [s1.name, s2.name, s3.name], selected: s2.name @@ -214,7 +216,11 @@ RSpec.describe ' end context "creating new variants" do - let!(:product) { create(:product, variant_unit: 'weight', variant_unit_scale: 1000) } + let(:supplier) { create(:supplier_enterprise) } + let!(:new_supplier) { create(:supplier_enterprise) } + let!(:product) { + create(:product, variant_unit: 'weight', variant_unit_scale: 1000, supplier_id: supplier.id) + } before do login_as_admin @@ -242,6 +248,7 @@ RSpec.describe ' expect(page).to have_selector "tr.variant", count: 1 # When I fill out variant details and hit update + select new_supplier.name, from: 'producer_id' fill_in "variant_display_name", with: "Case of 12 Bottles" fill_in "variant_unit_value_with_description", with: "3 (12x250 mL bottles)" fill_in "variant_display_as", with: "Case" @@ -258,14 +265,15 @@ RSpec.describe ' expect(updated_variant.display_as).to eq "Case" expect(updated_variant.price).to eq 4.0 expect(updated_variant.on_hand).to eq 10 + expect(updated_variant.supplier).to eq new_supplier # Then I should see edit buttons for the new variant expect(page).to have_selector "a.edit-variant" end context "handle the 'on_demand' variant case creation" do - let(:v1) { create(:variant, product:, on_hand: 4) } - let(:v2) { create(:variant, product:, on_demand: true) } + let(:v1) { create(:variant, product:, on_hand: 4, supplier:) } + let(:v2) { create(:variant, product:, on_demand: true, supplier:) } before do product.variants << v1 @@ -281,6 +289,7 @@ RSpec.describe ' end within "tr#v_-1" do + select supplier.name, from: 'producer_id' fill_in "variant_unit_value_with_description", with: "120" fill_in "variant_price", with: "6.66" end @@ -330,7 +339,7 @@ RSpec.describe ' s2 = FactoryBot.create(:supplier_enterprise) t1 = FactoryBot.create(:taxon) t2 = FactoryBot.create(:taxon) - p = FactoryBot.create(:product, supplier: s1, variant_unit: 'volume', + p = FactoryBot.create(:product, supplier_id: s1.id, variant_unit: 'volume', variant_unit_scale: 1, primary_taxon: t2, sku: "OLD SKU") login_as_admin @@ -340,13 +349,11 @@ RSpec.describe ' within "tr#p_#{p.id}" do expect(page).to have_field "product_name", with: p.name - expect(page).to have_select "producer_id", selected: s1.name expect(page).to have_select "variant_unit_with_scale", selected: "Volume (L)" expect(page).to have_checked_field "inherits_properties" expect(page).to have_field "product_sku", with: p.sku fill_in "product_name", with: "Big Bag Of Potatoes" - select s2.name, from: 'producer_id' select "Weight (kg)", from: "variant_unit_with_scale" uncheck "inherits_properties" fill_in "product_sku", with: "NEW SKU" @@ -357,7 +364,6 @@ RSpec.describe ' p.reload expect(p.name).to eq "Big Bag Of Potatoes" - expect(p.supplier).to eq s2 expect(p.variant_unit).to eq "weight" expect(p.variant_unit_scale).to eq 1000 # Kg expect(p.inherits_properties).to be false @@ -387,7 +393,7 @@ RSpec.describe ' it "updating a product with variants" do s1 = create(:supplier_enterprise) s2 = create(:supplier_enterprise) - p = create(:product, supplier: s1, variant_unit: 'volume', variant_unit_scale: 0.001, + p = create(:product, supplier_id: s1.id, variant_unit: 'volume', variant_unit_scale: 0.001, price: 3.0, unit_value: 0.25, unit_description: '(bottle)' ) v = p.variants.first v.update_attribute(:sku, "VARIANTSKU") @@ -510,8 +516,8 @@ RSpec.describe ' it "updating when a filter has been applied" do s1 = create(:supplier_enterprise) s2 = create(:supplier_enterprise) - p1 = FactoryBot.create(:simple_product, name: "product1", supplier: s1) - p2 = FactoryBot.create(:simple_product, name: "product2", supplier: s2) + p1 = FactoryBot.create(:simple_product, name: "product1", supplier_id: s1.id) + p2 = FactoryBot.create(:simple_product, name: "product2", supplier_id: s2.id) login_as_admin visit spree.admin_products_path @@ -610,7 +616,7 @@ RSpec.describe ' expect(page).to have_selector "a.edit-product", count: 2 # Set a filter - select2_select p1.supplier.name, from: "producer_filter" + select2_select v1.supplier.name, from: "producer_filter" apply_filters within "tr#p_#{p1.id}" do @@ -619,7 +625,7 @@ RSpec.describe ' uri = URI.parse(current_url) expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path( - v1.product.id, producerFilter: p1.supplier.id + v1.product.id, producerFilter: v1.supplier.id ) end @@ -647,7 +653,7 @@ RSpec.describe ' expect(page).to have_selector "a.edit-variant", count: 2 # Set a filter - select2_select p1.supplier.name, from: "producer_filter" + select2_select v1.supplier.name, from: "producer_filter" apply_filters within "tr#v_#{v1.id}" do @@ -656,7 +662,7 @@ RSpec.describe ' uri = URI.parse(current_url) expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_variant_path( - v1.product.id, v1.id, producerFilter: p1.supplier.id + v1.product.id, v1.id, producerFilter: v1.supplier.id ) end end @@ -666,6 +672,7 @@ RSpec.describe ' p1 = FactoryBot.create(:product, name: "P1") p2 = FactoryBot.create(:product, name: "P2") p3 = FactoryBot.create(:product, name: "P3") + p1_supplier = p1.variants.first.supplier login_as_admin visit spree.admin_products_path @@ -676,14 +683,16 @@ RSpec.describe ' find("a.clone-product").click end expect(page).to have_selector "a.clone-product", count: 4 + click_expand_all expect(page).to have_field "product_name", with: "COPY OF #{p1.name}" - expect(page).to have_select "producer_id", selected: p1.supplier.name.to_s + expect(page).to have_select "producer_id", selected: p1_supplier.name.to_s visit spree.admin_products_path + click_expand_all expect(page).to have_selector "a.clone-product", count: 4 expect(page).to have_field "product_name", with: "COPY OF #{p1.name}" - expect(page).to have_select "producer_id", selected: p1.supplier.name.to_s + expect(page).to have_select "producer_id", selected: p1_supplier.name.to_s end end end @@ -713,8 +722,8 @@ RSpec.describe ' it "displays basic filtering controls which filter the product list" do s1 = create(:supplier_enterprise) s2 = create(:supplier_enterprise) - p1 = FactoryBot.create(:simple_product, name: "product1", supplier: s1) - p2 = FactoryBot.create(:simple_product, name: "product2", supplier: s2) + p1 = FactoryBot.create(:simple_product, name: "product1", supplier_id: s1.id) + p2 = FactoryBot.create(:simple_product, name: "product2", supplier_id: s2.id) login_as_admin visit spree.admin_products_path @@ -753,13 +762,13 @@ RSpec.describe ' let(:supplier_permitted) { create(:supplier_enterprise, name: 'Supplier Permitted') } let(:distributor_managed) { create(:distributor_enterprise, name: 'Distributor Managed') } let(:distributor_unmanaged) { create(:distributor_enterprise, name: 'Distributor Unmanaged') } - let!(:product_supplied) { create(:product, supplier: supplier_managed1, price: 10.0) } - let!(:product_not_supplied) { create(:product, supplier: supplier_unmanaged) } + let!(:product_supplied) { create(:product, supplier_id: supplier_managed1.id, price: 10.0) } + let!(:product_not_supplied) { create(:product, supplier_id: supplier_unmanaged.id) } let!(:product_supplied_permitted) { - create(:product, name: 'Product Permitted', supplier: supplier_permitted, price: 10.0) + create(:product, name: 'Product Permitted', supplier_id: supplier_permitted.id, price: 10.0) } let(:product_supplied_inactive) { - create(:product, supplier: supplier_managed1, price: 10.0) + create(:product, supplier_id: supplier_managed1.id, price: 10.0) } let!(:supplier_permitted_relationship) do @@ -786,6 +795,7 @@ RSpec.describe ' it "shows only suppliers that I manage or have permission to" do visit spree.admin_products_path + click_expand_all expect(page) .to have_select( @@ -841,16 +851,16 @@ RSpec.describe ' within "tr#p_#{p.id}" do expect(page).to have_field "product_name", with: p.name - expect(page).to have_select "producer_id", selected: supplier_permitted.name fill_in "product_name", with: "Big Bag Of Potatoes" - select supplier_managed2.name, from: 'producer_id' select "Weight (kg)", from: "variant_unit_with_scale" find("a.view-variants").click end within "#v_#{v.id}" do + expect(page).to have_select "producer_id", selected: supplier_permitted.name + select supplier_managed2.name, from: 'producer_id' fill_in "variant_price", with: "20" fill_in "variant_on_hand", with: "18" fill_in "variant_display_as", with: "Big Bag" @@ -862,9 +872,9 @@ RSpec.describe ' p.reload v.reload expect(p.name).to eq "Big Bag Of Potatoes" - expect(p.supplier).to eq supplier_managed2 expect(p.variant_unit).to eq "weight" expect(p.variant_unit_scale).to eq 1000 # Kg + expect(v.supplier).to eq supplier_managed2 expect(v.display_as).to eq "Big Bag" expect(v.price).to eq 20.0 expect(v.on_hand).to eq 18 @@ -922,4 +932,8 @@ RSpec.describe ' def apply_filters page.find('.button.icon-search').click end + + def click_expand_all + find("a", text: "EXPAND ALL").click + end end From ee88e2fdfa000dabc76ba497037d43f9cb290dd5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 8 May 2024 15:49:19 +1000 Subject: [PATCH 071/145] Fix product system spec --- .../admin/product_properties_controller.rb | 1 + .../admin/product_properties/index.html.haml | 4 +- spec/system/admin/products_spec.rb | 67 ++++++++++--------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/app/controllers/spree/admin/product_properties_controller.rb b/app/controllers/spree/admin/product_properties_controller.rb index e5edc8f3d4..aebdff556e 100644 --- a/app/controllers/spree/admin/product_properties_controller.rb +++ b/app/controllers/spree/admin/product_properties_controller.rb @@ -8,6 +8,7 @@ module Spree before_action :setup_property, only: [:index] def index + @supplier = @product.variants.first.supplier @url_filters = ::ProductFilters.new.extract(request.query_parameters) end diff --git a/app/views/spree/admin/product_properties/index.html.haml b/app/views/spree/admin/product_properties/index.html.haml index 12660fc2cd..cd07017706 100644 --- a/app/views/spree/admin/product_properties/index.html.haml +++ b/app/views/spree/admin/product_properties/index.html.haml @@ -27,7 +27,7 @@ = render partial: 'product_property_fields', locals: { f: pp_form } = f.check_box :inherits_properties - = f.label :inherits_properties, t('.inherits_properties_checkbox_hint', supplier: @product.supplier.name) + = f.label :inherits_properties, t('.inherits_properties_checkbox_hint', supplier: @supplier.name) %br %br @@ -39,7 +39,7 @@ %th= t('admin.description') %th.actions %tbody#producer_properties - - @product.supplier.producer_properties.each do |producer_property| + - @supplier.producer_properties.each do |producer_property| %tr %td= producer_property.property.presentation %td= producer_property.value diff --git a/spec/system/admin/products_spec.rb b/spec/system/admin/products_spec.rb index 753dd4e4ba..5a95b93733 100644 --- a/spec/system/admin/products_spec.rb +++ b/spec/system/admin/products_spec.rb @@ -131,7 +131,6 @@ RSpec.describe ' expect(current_path).to eq spree.admin_products_path expect(flash_message).to eq('Product "A new product !!!" has been successfully created!') product = Spree::Product.find_by(name: 'A new product !!!') - expect(product.supplier).to eq(@supplier) expect(product.variant_unit).to eq('weight') expect(product.variant_unit_scale).to eq(1000) expect(product.variants.first.unit_value).to eq(5000) @@ -144,7 +143,10 @@ RSpec.describe ' expect(product.variants.first.shipping_category).to eq(shipping_category) expect(product.description).to eq("
A description...
") expect(product.group_buy).to be_falsey - expect(product.variants.first.unit_presentation).to eq("5kg") + + variant = product.variants.first + expect(variant.unit_presentation).to eq("5kg") + expect(variant.supplier).to eq(@supplier) end it "creating an on-demand product" do @@ -284,11 +286,13 @@ RSpec.describe ' before { Flipper.disable(:admin_style_v3) } describe "deleting" do - let!(:product1) { create(:simple_product, name: 'a product to keep', supplier: @supplier) } + let!(:product1) { + create(:simple_product, name: 'a product to keep', supplier_id: @supplier.id) + } context 'a simple product' do let!(:product2) { - create(:simple_product, name: 'a product to delete', supplier: @supplier) + create(:simple_product, name: 'a product to delete', supplier_id: @supplier.id } before do @@ -339,7 +343,7 @@ RSpec.describe ' describe 'cloning' do let!(:product1) { - create(:simple_product, name: 'a weight product', supplier: @supplier, + create(:simple_product, name: 'a weight product', supplier_id: @supplier.id, variant_unit: "weight") } @@ -403,25 +407,26 @@ RSpec.describe ' expect(flash_message).to eq('Product "A new product !!!" has been successfully created!') product = Spree::Product.find_by(name: 'A new product !!!') - expect(product.supplier).to eq(@supplier2) - expect(product.variants.first.tax_category).to be_nil + variant = product.variants.first + expect(variant.tax_category).to be_nil + expect(variant.supplier).to eq(@supplier2) end end it "editing a product" do - product = create(:simple_product, name: 'a product', supplier: @supplier2) + product = create(:simple_product, name: 'a product', supplier_id: @supplier2.id) visit spree.edit_admin_product_path product - select 'Permitted Supplier', from: 'product_supplier_id' + fill_in_trix_editor 'product_description', with: 'A description...' click_button 'Update' expect(flash_message).to eq('Product "a product" has been successfully updated!') product.reload - expect(product.supplier).to eq(@supplier_permitted) + expect(product.description).to eq("
A description...
") end it "editing a product comming from the bulk product update page with filter" do - product = create(:simple_product, name: 'a product', supplier: @supplier2) + product = create(:simple_product, name: 'a product', supplier_id: @supplier2.id) visit spree.edit_admin_product_path(product, filter) @@ -478,7 +483,7 @@ RSpec.describe ' end it "editing product group buy options" do - product = product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.edit_admin_product_path product within('#sidebar') { click_link 'Group Buy Options' } @@ -494,7 +499,7 @@ RSpec.describe ' end it "loading editing product group buy options with url filters" do - product = product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.group_buy_options_admin_product_path(product, filter) @@ -504,7 +509,7 @@ RSpec.describe ' end it "editing product group buy options with url filter" do - product = product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.group_buy_options_admin_product_path(product, filter) choose('product_group_buy_1') @@ -517,7 +522,7 @@ RSpec.describe ' end it "editing product Search" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.edit_admin_product_path product within('#sidebar') { click_link 'Search' } fill_in 'Product Search Keywords', with: 'Product Search Keywords' @@ -530,7 +535,7 @@ RSpec.describe ' end it "loading editing product Search with url filters" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.seo_admin_product_path(product, filter) @@ -540,7 +545,7 @@ RSpec.describe ' end it "editing product Search with url filter" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.seo_admin_product_path(product, filter) @@ -554,7 +559,7 @@ RSpec.describe ' end it "loading product properties page including url filters" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.admin_product_product_properties_path(product, filter) uri = URI.parse(current_url) @@ -570,7 +575,7 @@ RSpec.describe ' it "deleting product properties" do # Given a product with a property - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) product.set_property('fooprop', 'fooval') # When I navigate to the product properties page @@ -594,7 +599,7 @@ RSpec.describe ' it "deleting product properties including url filters" do # Given a product with a property - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) product.set_property('fooprop', 'fooval') # When I navigate to the product properties page @@ -612,7 +617,7 @@ RSpec.describe ' it "adding product properties including url filters" do # Given a product - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) product.set_property('fooprop', 'fooval') # When I navigate to the product properties page @@ -629,7 +634,7 @@ RSpec.describe ' end it "loading new product image page" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.admin_product_images_path(product) expect(page).to have_selector ".no-objects-found" @@ -639,7 +644,7 @@ RSpec.describe ' end it "loading new product image page including url filters" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.admin_product_images_path(product, filter) @@ -651,7 +656,7 @@ RSpec.describe ' end it "upload a new product image including url filters" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.admin_product_images_path(product, filter) @@ -665,7 +670,7 @@ RSpec.describe ' end it "loading image page including url filter" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) visit spree.admin_product_images_path(product, filter) @@ -676,7 +681,7 @@ RSpec.describe ' end it "loading edit product image page including url filter" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) image = white_logo_file image_object = Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', alt: "position 1", @@ -697,7 +702,7 @@ RSpec.describe ' end it "updating a product image including url filter" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) image = white_logo_file image_object = Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', alt: "position 1", @@ -716,7 +721,7 @@ RSpec.describe ' it "checks error when creating product image with unsupported format" do unsupported_image_file_path = Rails.root.join("README.md").to_s - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) image = white_logo_file Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', @@ -732,7 +737,7 @@ RSpec.describe ' end it "deleting product images" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) image = white_logo_file Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', alt: "position 1", attachment: image, position: 1) @@ -750,7 +755,7 @@ RSpec.describe ' end it "deleting product image including url filter" do - product = create(:simple_product, supplier: @supplier2) + product = create(:simple_product, supplier_id: @supplier2.id) image = white_logo_file Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', alt: "position 1", attachment: image, position: 1) @@ -766,7 +771,7 @@ RSpec.describe ' end context "editing a product's variant unit scale" do - let(:product) { create(:simple_product, name: 'a product', supplier: @supplier2) } + let(:product) { create(:simple_product, name: 'a product', supplier_id: @supplier2.id) } before do allow(Spree::Config).to receive(:available_units).and_return("g,lb,oz,kg,T,mL,L,kL") From 6c4c0ebf6f499eb9d79ea7ec1daa33af2ad5349c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 8 May 2024 16:58:36 +1000 Subject: [PATCH 072/145] Refactor product page system spec Remove some duplication and group related test --- spec/system/admin/products_spec.rb | 698 +++++++++++++---------------- 1 file changed, 323 insertions(+), 375 deletions(-) diff --git a/spec/system/admin/products_spec.rb b/spec/system/admin/products_spec.rb index 5a95b93733..43c808a691 100644 --- a/spec/system/admin/products_spec.rb +++ b/spec/system/admin/products_spec.rb @@ -13,23 +13,18 @@ RSpec.describe ' let!(:taxon) { create(:taxon) } let!(:stock_location) { create(:stock_location, backorderable_default: false) } let!(:shipping_category) { DefaultShippingCategory.find_or_create } - - before do - @supplier = create(:supplier_enterprise, name: 'New supplier') - @distributors = (1..3).map { create(:distributor_enterprise) } - @enterprise_fees = (0..2).map { |i| create(:enterprise_fee, enterprise: @distributors[i]) } - end + let!(:supplier) { create(:supplier_enterprise, name: 'New supplier') } describe "creating a product" do let!(:tax_category) { create(:tax_category, name: 'Test Tax Category') } + before do + login_as_admin + visit spree.new_admin_product_path + end + it "display all attributes when submitting with error: no name" do - login_to_admin_section - - click_link 'Products' - click_link 'New Product' - - select @supplier.name, from: 'product_supplier_id' + select supplier.name, from: 'product_supplier_id' select "Weight (kg)", from: 'product_variant_unit_with_scale' fill_in 'product_unit_value', with: "5.00 g" assert_selector(:field, placeholder: "5kg g") @@ -44,7 +39,7 @@ RSpec.describe ' click_button 'Create' expect(page).to have_content "Name can't be blank" - expect(page).to have_field 'product_supplier_id', with: @supplier.id + expect(page).to have_field 'product_supplier_id', with: supplier.id expect(page).to have_field 'product_unit_value', with: "5.00 g" expect(page).to have_field 'product_display_as', with: "Big Box of Chocolates" expect(page).to have_field 'product_primary_taxon_id', with: taxon.id @@ -60,10 +55,6 @@ RSpec.describe ' end it "display all attributes when submitting with error: Unit Value must be grater than 0" do - login_to_admin_section - - visit spree.new_admin_product_path - select 'New supplier', from: 'product_supplier_id' fill_in 'product_name', with: "new product name" select "Weight (kg)", from: 'product_variant_unit_with_scale' @@ -80,7 +71,7 @@ RSpec.describe ' click_button 'Create' expect(page).to have_field 'product_name', with: "new product name" - expect(page).to have_field 'product_supplier_id', with: @supplier.id + expect(page).to have_field 'product_supplier_id', with: supplier.id expect(page).to have_field 'product_unit_value', with: "0 g" expect(page).to have_field 'product_display_as', with: "Big Box of Chocolates" expect(page).to have_field 'product_primary_taxon_id', with: taxon.id @@ -96,11 +87,6 @@ RSpec.describe ' end it "preserves 'Items' 'Unit Size' selection when submitting with error" do - login_to_admin_section - - click_link 'Products' - click_link 'New Product' - select "Items", from: 'product_variant_unit_with_scale' click_button 'Create' @@ -109,11 +95,6 @@ RSpec.describe ' end it "assigning important attributes" do - login_to_admin_section - - click_link 'Products' - click_link 'New Product' - expect(find_field('product_shipping_category_id').text).to eq(shipping_category.name) select 'New supplier', from: 'product_supplier_id' @@ -146,15 +127,10 @@ RSpec.describe ' variant = product.variants.first expect(variant.unit_presentation).to eq("5kg") - expect(variant.supplier).to eq(@supplier) + expect(variant.supplier).to eq(supplier) end it "creating an on-demand product" do - login_as_admin - visit spree.admin_products_path - - click_link 'New Product' - fill_in 'product_name', with: 'Hot Cakes' select 'New supplier', from: 'product_supplier_id' select "Weight (kg)", from: 'product_variant_unit_with_scale' @@ -177,11 +153,6 @@ RSpec.describe ' end it "creating product with empty unit value" do - login_as_admin - visit spree.admin_products_path - - click_link 'New Product' - fill_in 'product_name', with: 'Hot Cakes' select 'New supplier', from: 'product_supplier_id' select "Weight (kg)", from: 'product_variant_unit_with_scale' @@ -228,9 +199,6 @@ RSpec.describe ' context "when enable_localized_number is set to #{localized_number}" do before do allow(Spree::Config).to receive(:enable_localized_number?).and_return(localized_number) - login_as_admin - visit spree.admin_products_path - click_link 'New Product' end it "and price is #{price}" do @@ -370,23 +338,22 @@ RSpec.describe ' let!(:tax_category) { create(:tax_category) } let(:filter) { { producerFilter: 2 } } let(:image_file_path) { Rails.root.join(file_fixture_path, "thinking-cat.jpg") } + let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') } + let(:supplier_permitted) { create(:supplier_enterprise, name: 'Permitted Supplier') } + let(:new_user) { create(:user) } before do - @new_user = create(:user) - @supplier2 = create(:supplier_enterprise, name: 'Another Supplier') - @supplier_permitted = create(:supplier_enterprise, name: 'Permitted Supplier') - @new_user.enterprise_roles.build(enterprise: @supplier2).save - @new_user.enterprise_roles.build(enterprise: @distributors[0]).save - create(:enterprise_relationship, parent: @supplier_permitted, child: @supplier2, - permissions_list: [:manage_products]) + new_user.enterprise_roles.build(enterprise: supplier2).save - login_as @new_user + login_as new_user end context "products do not require a tax category" do it "creating a new product" do - visit spree.admin_products_path - click_link 'New Product' + create(:enterprise_relationship, parent: supplier_permitted, child: supplier2, + permissions_list: [:manage_products]) + + visit spree.new_admin_product_path fill_in 'product_name', with: 'A new product !!!' fill_in 'product_price', with: '19.99' @@ -400,8 +367,8 @@ RSpec.describe ' # Should only have suppliers listed which the user can manage expect(page).to have_select 'product_supplier_id', - with_options: [@supplier2.name, @supplier_permitted.name] - expect(page).not_to have_select 'product_supplier_id', with_options: [@supplier.name] + with_options: [supplier2.name, supplier_permitted.name] + expect(page).not_to have_select 'product_supplier_id', with_options: [supplier.name] click_button 'Create' @@ -409,369 +376,350 @@ RSpec.describe ' product = Spree::Product.find_by(name: 'A new product !!!') variant = product.variants.first expect(variant.tax_category).to be_nil - expect(variant.supplier).to eq(@supplier2) + expect(variant.supplier).to eq(supplier2) end end - it "editing a product" do - product = create(:simple_product, name: 'a product', supplier_id: @supplier2.id) + describe "editing page" do + let!(:product) { create(:simple_product, name: 'a product', supplier_id: supplier2.id) } - visit spree.edit_admin_product_path product + it "editing a product" do + visit spree.edit_admin_product_path product - fill_in_trix_editor 'product_description', with: 'A description...' - click_button 'Update' - expect(flash_message).to eq('Product "a product" has been successfully updated!') - product.reload - expect(product.description).to eq("
A description...
") - end + fill_in_trix_editor 'product_description', with: 'A description...' + click_button 'Update' + expect(flash_message).to eq('Product "a product" has been successfully updated!') + product.reload + expect(product.description).to eq("
A description...
") + end - it "editing a product comming from the bulk product update page with filter" do - product = create(:simple_product, name: 'a product', supplier_id: @supplier2.id) + it "editing a product comming from the bulk product update page with filter" do + visit spree.edit_admin_product_path(product, filter) - visit spree.edit_admin_product_path(product, filter) + click_button 'Update' + expect(flash_message).to eq('Product "a product" has been successfully updated!') - click_button 'Update' - expect(flash_message).to eq('Product "a product" has been successfully updated!') + # Check the url still includes the filters + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) - # Check the url still includes the filters - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) + # Link back to the bulk product update page should include the filters + expected_admin_product_url = + Regexp.new(Regexp.escape("#{spree.admin_products_path}#?#{filter.to_query}")) + expect(page).to have_link('Back to products list', + href: expected_admin_product_url) + expect(page).to have_link('Cancel', href: expected_admin_product_url) - # Link back to the bulk product update page should include the filters - expected_admin_product_url = - Regexp.new(Regexp.escape("#{spree.admin_products_path}#?#{filter.to_query}")) - expect(page).to have_link('Back to products list', - href: expected_admin_product_url) - expect(page).to have_link('Cancel', href: expected_admin_product_url) + expected_product_url = Regexp.new(Regexp.escape(spree.edit_admin_product_path( + product.id, filter + ))) + expect(page).to have_link('Product Details', + href: expected_product_url) - expected_product_url = Regexp.new(Regexp.escape(spree.edit_admin_product_path( - product.id, filter - ))) - expect(page).to have_link('Product Details', - href: expected_product_url) - - expected_product_image_url = Regexp.new(Regexp.escape(spree.admin_product_images_path( - product.id, filter - ))) - expect(page).to have_link('Images', - href: expected_product_image_url) - - expected_product_variant_url = Regexp.new(Regexp.escape(spree.admin_product_variants_path( + expected_product_image_url = Regexp.new(Regexp.escape(spree.admin_product_images_path( product.id, filter ))) - expect(page).to have_link('Variants', - href: expected_product_variant_url) + expect(page).to have_link('Images', + href: expected_product_image_url) - expected_product_properties_url = - Regexp.new(Regexp.escape(spree.admin_product_product_properties_path( - product.id, filter - ))) - expect(page).to have_link('Product Properties', - href: expected_product_properties_url) + expected_product_variant_url = Regexp.new(Regexp.escape(spree.admin_product_variants_path( + product.id, filter + ))) + expect(page).to have_link('Variants', + href: expected_product_variant_url) - expected_product_group_buy_option_url = - Regexp.new(Regexp.escape(spree.group_buy_options_admin_product_path( - product.id, filter - ))) - expect(page).to have_link('Group Buy Options', - href: expected_product_group_buy_option_url) + expected_product_properties_url = + Regexp.new(Regexp.escape(spree.admin_product_product_properties_path( + product.id, filter + ))) + expect(page).to have_link('Product Properties', + href: expected_product_properties_url) - expected_product_seo_url = Regexp.new(Regexp.escape(spree.seo_admin_product_path( - product.id, filter - ))) - expect(page).to have_link('Search', href: expected_product_seo_url) - end + expected_product_group_buy_option_url = + Regexp.new(Regexp.escape(spree.group_buy_options_admin_product_path( + product.id, filter + ))) + expect(page).to have_link('Group Buy Options', + href: expected_product_group_buy_option_url) - it "editing product group buy options" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.edit_admin_product_path product - within('#sidebar') { click_link 'Group Buy Options' } - choose('product_group_buy_1') - fill_in 'Bulk unit size', with: '10' - - click_button 'Update' - - expect(flash_message).to eq("Product \"#{product.name}\" has been successfully updated!") - product.reload - expect(product.group_buy).to be true - expect(product.group_buy_unit_size).to eq(10.0) - end - - it "loading editing product group buy options with url filters" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.group_buy_options_admin_product_path(product, filter) - - expected_cancel_link = Regexp.new(Regexp.escape(spree.edit_admin_product_path(product, - filter))) - expect(page).to have_link('Cancel', href: expected_cancel_link) - end - - it "editing product group buy options with url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.group_buy_options_admin_product_path(product, filter) - choose('product_group_buy_1') - fill_in 'Bulk unit size', with: '10' - - click_button 'Update' - - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) - end - - it "editing product Search" do - product = create(:simple_product, supplier_id: @supplier2.id) - visit spree.edit_admin_product_path product - within('#sidebar') { click_link 'Search' } - fill_in 'Product Search Keywords', with: 'Product Search Keywords' - fill_in 'Notes', with: 'Just testing Notes' - click_button 'Update' - expect(flash_message).to eq("Product \"#{product.name}\" has been successfully updated!") - product.reload - expect(product.notes).to eq('Just testing Notes') - expect(product.meta_keywords).to eq('Product Search Keywords') - end - - it "loading editing product Search with url filters" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.seo_admin_product_path(product, filter) - - expected_cancel_link = Regexp.new(Regexp.escape(spree.edit_admin_product_path(product, - filter))) - expect(page).to have_link('Cancel', href: expected_cancel_link) - end - - it "editing product Search with url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.seo_admin_product_path(product, filter) - - fill_in 'Product Search Keywords', with: 'Product Search Keywords' - fill_in 'Notes', with: 'Just testing Notes' - - click_button 'Update' - - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) - end - - it "loading product properties page including url filters" do - product = create(:simple_product, supplier_id: @supplier2.id) - visit spree.admin_product_product_properties_path(product, filter) - - uri = URI.parse(current_url) - # we stay on the same url as the new image content is loaded via an ajax call - expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_product_properties_path(product, - filter) - - expected_cancel_link = Regexp.new(Regexp.escape(spree.admin_product_product_properties_path( - product, filter - ))) - expect(page).to have_link('Cancel', href: expected_cancel_link) - end - - it "deleting product properties" do - # Given a product with a property - product = create(:simple_product, supplier_id: @supplier2.id) - product.set_property('fooprop', 'fooval') - - # When I navigate to the product properties page - visit spree.admin_product_product_properties_path(product) - expect(page).to have_select2 'product_product_properties_attributes_0_property_name', - selected: 'fooprop' - expect(page).to have_field 'product_product_properties_attributes_0_value', with: 'fooval' - - # And I delete the property - accept_alert do - page.all('a.delete-resource').first.click - end - click_button 'Update' - - # Then the property should have been deleted - expect(page).not_to have_field 'product_product_properties_attributes_0_property_name', - with: 'fooprop' - expect(page).not_to have_field 'product_product_properties_attributes_0_value', with: 'fooval' - expect(product.reload.property('fooprop')).to be_nil - end - - it "deleting product properties including url filters" do - # Given a product with a property - product = create(:simple_product, supplier_id: @supplier2.id) - product.set_property('fooprop', 'fooval') - - # When I navigate to the product properties page - visit spree.admin_product_product_properties_path(product, filter) - - # And I delete the property - accept_alert do - page.all('a.delete-resource').first.click + expected_product_seo_url = Regexp.new(Regexp.escape(spree.seo_admin_product_path( + product.id, filter + ))) + expect(page).to have_link('Search', href: expected_product_seo_url) end - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_product_properties_path(product, - filter) - end + it "editing product group buy options" do + visit spree.edit_admin_product_path product + within('#sidebar') { click_link 'Group Buy Options' } + choose('product_group_buy_1') + fill_in 'Bulk unit size', with: '10' - it "adding product properties including url filters" do - # Given a product - product = create(:simple_product, supplier_id: @supplier2.id) - product.set_property('fooprop', 'fooval') + click_button 'Update' - # When I navigate to the product properties page - visit spree.admin_product_product_properties_path(product, filter) + expect(flash_message).to eq("Product \"#{product.name}\" has been successfully updated!") + product.reload + expect(product.group_buy).to be true + expect(product.group_buy_unit_size).to eq(10.0) + end - # And I add a property - select 'fooprop', from: 'product_product_properties_attributes_0_property_name' - fill_in 'product_product_properties_attributes_0_value', with: 'fooval2' + it "loading editing product group buy options with url filters" do + visit spree.group_buy_options_admin_product_path(product, filter) - click_button 'Update' - - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) - end - - it "loading new product image page" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.admin_product_images_path(product) - expect(page).to have_selector ".no-objects-found" - - page.find('a#new_image_link').click - expect(page).to have_selector "#image_attachment" - end - - it "loading new product image page including url filters" do - product = create(:simple_product, supplier_id: @supplier2.id) - - visit spree.admin_product_images_path(product, filter) - - page.find('a#new_image_link').click - - expected_cancel_link = Regexp.new(Regexp.escape(spree.admin_product_images_path(product, + expected_cancel_link = Regexp.new(Regexp.escape(spree.edit_admin_product_path(product, filter))) - expect(page).to have_link('Cancel', href: expected_cancel_link) - end + expect(page).to have_link('Cancel', href: expected_cancel_link) + end - it "upload a new product image including url filters" do - product = create(:simple_product, supplier_id: @supplier2.id) + it "editing product group buy options with url filter" do + visit spree.group_buy_options_admin_product_path(product, filter) + choose('product_group_buy_1') + fill_in 'Bulk unit size', with: '10' - visit spree.admin_product_images_path(product, filter) + click_button 'Update' - page.find('a#new_image_link').click + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) + end - attach_file('image_attachment', image_file_path) - click_button "Create" + it "editing product Search" do + visit spree.edit_admin_product_path product - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) - end + within('#sidebar') { click_link 'Search' } + fill_in 'Product Search Keywords', with: 'Product Search Keywords' + fill_in 'Notes', with: 'Just testing Notes' + click_button 'Update' + expect(flash_message).to eq("Product \"#{product.name}\" has been successfully updated!") + product.reload + expect(product.notes).to eq('Just testing Notes') + expect(product.meta_keywords).to eq('Product Search Keywords') + end - it "loading image page including url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) + it "loading editing product Search with url filters" do + visit spree.seo_admin_product_path(product, filter) - visit spree.admin_product_images_path(product, filter) - - expected_new_image_link = Regexp.new(Regexp.escape(spree.new_admin_product_image_path( - product, filter - ))) - expect(page).to have_link('New Image', href: expected_new_image_link) - end - - it "loading edit product image page including url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) - image = white_logo_file - image_object = Spree::Image.create(viewable_id: product.id, - viewable_type: 'Spree::Product', alt: "position 1", - attachment: image, position: 1) - - visit spree.admin_product_images_path(product, filter) - - page.find("a.icon-edit").click - - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}") - .to eq spree.edit_admin_product_image_path(product, image_object, filter) - - expected_cancel_link = Regexp.new(Regexp.escape(spree.admin_product_images_path(product, + expected_cancel_link = Regexp.new(Regexp.escape(spree.edit_admin_product_path(product, filter))) - expect(page).to have_link('Cancel', href: expected_cancel_link) - expect(page).to have_link("Back To Images List", href: expected_cancel_link) - end - - it "updating a product image including url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) - image = white_logo_file - image_object = Spree::Image.create(viewable_id: product.id, - viewable_type: 'Spree::Product', alt: "position 1", - attachment: image, position: 1) - - visit spree.admin_product_images_path(product, filter) - - page.find("a.icon-edit").click - - attach_file('image_attachment', image_file_path) - click_button "Update" - - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) - end - - it "checks error when creating product image with unsupported format" do - unsupported_image_file_path = Rails.root.join("README.md").to_s - product = create(:simple_product, supplier_id: @supplier2.id) - - image = white_logo_file - Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', - alt: "position 1", attachment: image, position: 1) - - visit spree.admin_product_images_path(product) - page.find('a#new_image_link').click - attach_file('image_attachment', unsupported_image_file_path) - click_button "Create" - - expect(page).to have_text "Attachment has an invalid content type" - expect(page).to have_text "Attachment is not a valid image" - end - - it "deleting product images" do - product = create(:simple_product, supplier_id: @supplier2.id) - image = white_logo_file - Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', - alt: "position 1", attachment: image, position: 1) - - visit spree.admin_product_images_path(product) - expect(page).to have_selector "table.index td img" - expect(product.reload.image).not_to be_nil - - accept_alert do - page.find('a.delete-resource').click + expect(page).to have_link('Cancel', href: expected_cancel_link) end - expect(page).not_to have_selector "table.index td img" - expect(product.reload.image).to be_nil - end + it "editing product Search with url filter" do + visit spree.seo_admin_product_path(product, filter) - it "deleting product image including url filter" do - product = create(:simple_product, supplier_id: @supplier2.id) - image = white_logo_file - Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', - alt: "position 1", attachment: image, position: 1) + fill_in 'Product Search Keywords', with: 'Product Search Keywords' + fill_in 'Notes', with: 'Just testing Notes' - visit spree.admin_product_images_path(product, filter) + click_button 'Update' - accept_alert do - page.find('a.delete-resource').click + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) end - uri = URI.parse(current_url) - expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) + it "loading product properties page including url filters" do + visit spree.admin_product_product_properties_path(product, filter) + + uri = URI.parse(current_url) + # we stay on the same url as the new image content is loaded via an ajax call + expect("#{uri.path}?#{uri.query}").to eq( + spree.admin_product_product_properties_path(product, filter) + ) + + expected_cancel_link = Regexp.new( + Regexp.escape(spree.admin_product_product_properties_path(product, filter)) + ) + expect(page).to have_link('Cancel', href: expected_cancel_link) + end + end + + describe "product properties" do + # Given a product with a property + let!(:product) { + create(:simple_product, supplier_id: supplier2.id).tap do |product| + product.set_property('fooprop', 'fooval') + end + } + + it "deleting product properties" do + # When I navigate to the product properties page + visit spree.admin_product_product_properties_path(product) + expect(page).to have_select2 'product_product_properties_attributes_0_property_name', + selected: 'fooprop' + expect(page).to have_field 'product_product_properties_attributes_0_value', with: 'fooval' + + # And I delete the property + accept_alert do + page.all('a.delete-resource').first.click + end + click_button 'Update' + + # Then the property should have been deleted + expect(page).not_to have_field 'product_product_properties_attributes_0_property_name', + with: 'fooprop' + expect(page).not_to have_field 'product_product_properties_attributes_0_value', + with: 'fooval' + expect(product.reload.property('fooprop')).to be_nil + end + + it "deleting product properties including url filters" do + # When I navigate to the product properties page + visit spree.admin_product_product_properties_path(product, filter) + + # And I delete the property + accept_alert do + page.all('a.delete-resource').first.click + end + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq( + spree.admin_product_product_properties_path(product, filter) + ) + end + + it "adding product properties including url filters" do + # When I navigate to the product properties page + visit spree.admin_product_product_properties_path(product, filter) + + # And I add a property + select 'fooprop', from: 'product_product_properties_attributes_0_property_name' + fill_in 'product_product_properties_attributes_0_value', with: 'fooval2' + + click_button 'Update' + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.edit_admin_product_path(product, filter) + end + end + + describe "image page" do + let!(:product) { create(:simple_product, supplier_id: supplier2.id) } + + it "loading new product image page" do + visit spree.admin_product_images_path(product) + expect(page).to have_selector ".no-objects-found" + + page.find('a#new_image_link').click + expect(page).to have_selector "#image_attachment" + end + + it "loading new product image page including url filters" do + visit spree.admin_product_images_path(product, filter) + + page.find('a#new_image_link').click + + expected_cancel_link = Regexp.new(Regexp.escape(spree.admin_product_images_path(product, + filter))) + expect(page).to have_link('Cancel', href: expected_cancel_link) + end + + it "upload a new product image including url filters" do + visit spree.admin_product_images_path(product, filter) + + page.find('a#new_image_link').click + + attach_file('image_attachment', image_file_path) + click_button "Create" + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) + end + + it "loading image page including url filter" do + visit spree.admin_product_images_path(product, filter) + + expected_new_image_link = Regexp.new(Regexp.escape(spree.new_admin_product_image_path( + product, filter + ))) + expect(page).to have_link('New Image', href: expected_new_image_link) + end + + it "loading edit product image page including url filter" do + image = white_logo_file + image_object = Spree::Image.create(viewable_id: product.id, + viewable_type: 'Spree::Product', alt: "position 1", + attachment: image, position: 1) + + visit spree.admin_product_images_path(product, filter) + + page.find("a.icon-edit").click + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}") + .to eq spree.edit_admin_product_image_path(product, image_object, filter) + + expected_cancel_link = Regexp.new(Regexp.escape(spree.admin_product_images_path(product, + filter))) + expect(page).to have_link('Cancel', href: expected_cancel_link) + expect(page).to have_link("Back To Images List", href: expected_cancel_link) + end + + it "updating a product image including url filter" do + image = white_logo_file + image_object = Spree::Image.create(viewable_id: product.id, + viewable_type: 'Spree::Product', alt: "position 1", + attachment: image, position: 1) + + visit spree.admin_product_images_path(product, filter) + + page.find("a.icon-edit").click + + attach_file('image_attachment', image_file_path) + click_button "Update" + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) + end + + it "checks error when creating product image with unsupported format" do + unsupported_image_file_path = Rails.root.join("README.md").to_s + product = create(:simple_product, supplier_id: @supplier2.id) + + image = white_logo_file + Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', + alt: "position 1", attachment: image, position: 1) + + visit spree.admin_product_images_path(product) + page.find('a#new_image_link').click + attach_file('image_attachment', unsupported_image_file_path) + click_button "Create" + + expect(page).to have_text "Attachment has an invalid content type" + expect(page).to have_text "Attachment is not a valid image" + end + + it "deleting product images" do + image = white_logo_file + Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', + alt: "position 1", attachment: image, position: 1) + + visit spree.admin_product_images_path(product) + expect(page).to have_selector "table.index td img" + expect(product.reload.image).not_to be_nil + + accept_alert do + page.find('a.delete-resource').click + end + + expect(page).not_to have_selector "table.index td img" + expect(product.reload.image).to be_nil + end + + it "deleting product image including url filter" do + image = white_logo_file + Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', + alt: "position 1", attachment: image, position: 1) + + visit spree.admin_product_images_path(product, filter) + + accept_alert do + page.find('a.delete-resource').click + end + + uri = URI.parse(current_url) + expect("#{uri.path}?#{uri.query}").to eq spree.admin_product_images_path(product, filter) + end end context "editing a product's variant unit scale" do - let(:product) { create(:simple_product, name: 'a product', supplier_id: @supplier2.id) } + let(:product) { create(:simple_product, name: 'a product', supplier_id: supplier2.id) } before do allow(Spree::Config).to receive(:available_units).and_return("g,lb,oz,kg,T,mL,L,kL") From 07fb7b5b5ebe7f9d5e3f825bef924623ad5e6c88 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Fri, 10 May 2024 14:27:41 +1000 Subject: [PATCH 073/145] Fix variant system spec --- spec/system/admin/variants_spec.rb | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/spec/system/admin/variants_spec.rb b/spec/system/admin/variants_spec.rb index beb164fe1e..7de52b8272 100644 --- a/spec/system/admin/variants_spec.rb +++ b/spec/system/admin/variants_spec.rb @@ -24,6 +24,7 @@ RSpec.describe ' fill_in 'unit_value_human', with: '1' fill_in 'variant_unit_description', with: 'foo' select taxon.name, from: "variant_primary_taxon_id" + select2_select product.variants.first.supplier.name, from: "variant_supplier_id" click_button 'Create' # Then the variant should have been created @@ -65,6 +66,7 @@ RSpec.describe ' fill_in 'variant_weight', with: '1.234' fill_in 'unit_value_human', with: 1 select taxon.name, from: "variant_primary_taxon_id" + select2_select product.variants.first.supplier.name, from: "variant_supplier_id" click_button 'Create' # Then the variant should have been created @@ -236,6 +238,27 @@ RSpec.describe ' end end + describe "editing supplier" do + let(:product) { create(:simple_product) } + let(:variant) { product.variants.first } + + before do + login_as_admin + end + + it "updates the supplier" do + new_supplier = create(:supplier_enterprise) + visit spree.edit_admin_product_variant_path(product, variant) + + select2_select new_supplier.name, from: "variant_supplier_id" + + click_button 'Update' + + expect(page).to have_content %(Variant "#{product.name}" has been successfully updated!) + expect(variant.reload.supplier).to eq(new_supplier) + end + end + describe "editing on hand and on demand values" do let(:product) { create(:simple_product) } let(:variant) { product.variants.first } @@ -331,7 +354,7 @@ RSpec.describe ' fill_in "unit_value_human", with: "1.23" click_button 'Update' - expect(page).not_to have_content %(Variant "#{product.name}" has been successfully updated!) + expect(page).to have_content %(Variant "#{product.name}" has been successfully updated!) # Then the displayed values should have been saved expect(variant.reload.unit_value).to eq(1.23) From b156f722f1dadba1ddcf1a92ef96d8c651374387 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 15 May 2024 14:02:54 +1000 Subject: [PATCH 074/145] Fix variant override spec --- .../index_utils/filters/attr_filter.js.coffee | 18 ++++--- .../directives/track_inheritance.js.coffee | 4 +- .../filters/hub_permissions_filter.js.coffee | 6 ++- .../dirty_variant_overrides.js.coffee | 8 +-- .../services/variant_overrides.js.coffee | 13 ++--- .../api/admin/variant_simple_serializer.rb | 6 ++- .../_products_product.html.haml | 2 +- .../_products_variants.html.haml | 2 +- .../admin/variant_overrides/index.html.haml | 1 + .../services/variant_overrides_spec.js.coffee | 50 +++++++++++-------- spec/system/admin/variant_overrides_spec.rb | 28 +++++++---- 11 files changed, 82 insertions(+), 56 deletions(-) diff --git a/app/assets/javascripts/admin/index_utils/filters/attr_filter.js.coffee b/app/assets/javascripts/admin/index_utils/filters/attr_filter.js.coffee index c645b507f1..14255f3f85 100644 --- a/app/assets/javascripts/admin/index_utils/filters/attr_filter.js.coffee +++ b/app/assets/javascripts/admin/index_utils/filters/attr_filter.js.coffee @@ -1,12 +1,16 @@ # Used like a regular angular filter where an object is passed # Adds the additional special case that a value of 0 for the filter # acts as a bypass for that particular attribute + +# NOTE the name doesn't reflect what the filter does, it only fiters on the variant.producer_id angular.module("admin.indexUtils").filter "attrFilter", ($filter) -> return (objects, filters) -> - Object.keys(filters).reduce (filtered, attr) -> - filter = filters[attr] - return filtered if !filter? || filter == 0 - return $filter('filter')(filtered, (object) -> - object[attr] == filter - ) - , objects + filter = filters["producer_id"] + + return objects if !filter? || filter == 0 + + return $filter('filter')(objects, (product) -> + for variant in product.variants + return true if variant["producer_id"] == filter + false + , true) diff --git a/app/assets/javascripts/admin/variant_overrides/directives/track_inheritance.js.coffee b/app/assets/javascripts/admin/variant_overrides/directives/track_inheritance.js.coffee index ecc1cdac29..6c908ea641 100644 --- a/app/assets/javascripts/admin/variant_overrides/directives/track_inheritance.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/directives/track_inheritance.js.coffee @@ -2,10 +2,10 @@ angular.module("admin.variantOverrides").directive "trackInheritance", (VariantO require: "ngModel" link: (scope, element, attrs, ngModel) -> # This is a bit hacky, but it allows us to load the inherit property on the VO, but then not submit it - scope.inherit = angular.equals scope.variantOverrides[scope.hub_id][scope.variant.id], VariantOverrides.newFor scope.hub_id, scope.variant.id + scope.inherit = angular.equals scope.variantOverrides[scope.hub_id][scope.variant.id], VariantOverrides.newFor scope.hub_id, scope.variant ngModel.$parsers.push (viewValue) -> if ngModel.$dirty && viewValue - DirtyVariantOverrides.inherit scope.hub_id, scope.variant.id, scope.variantOverrides[scope.hub_id][scope.variant.id].id + DirtyVariantOverrides.inherit scope.hub_id, scope.variant, scope.variantOverrides[scope.hub_id][scope.variant.id].id scope.displayDirty() viewValue diff --git a/app/assets/javascripts/admin/variant_overrides/filters/hub_permissions_filter.js.coffee b/app/assets/javascripts/admin/variant_overrides/filters/hub_permissions_filter.js.coffee index b1434fb21e..7818fadc78 100644 --- a/app/assets/javascripts/admin/variant_overrides/filters/hub_permissions_filter.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/filters/hub_permissions_filter.js.coffee @@ -2,4 +2,8 @@ angular.module("admin.variantOverrides").filter "hubPermissions", ($filter) -> return (products, hubPermissions, hub_id) -> return [] if !hub_id return [] if !hubPermissions[hub_id] - return $filter('filter')(products, ((product) -> hubPermissions[hub_id].indexOf(product.producer_id) > -1), true) + + return $filter('filter')(products, ((product) -> + for variant in product.variants + return hubPermissions[hub_id].indexOf(variant.producer_id) > -1 + ), true) diff --git a/app/assets/javascripts/admin/variant_overrides/services/dirty_variant_overrides.js.coffee b/app/assets/javascripts/admin/variant_overrides/services/dirty_variant_overrides.js.coffee index 537fb484dc..0d5512979f 100644 --- a/app/assets/javascripts/admin/variant_overrides/services/dirty_variant_overrides.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/services/dirty_variant_overrides.js.coffee @@ -12,11 +12,11 @@ angular.module("admin.variantOverrides").factory "DirtyVariantOverrides", ($http @add(hub_id, variant_id, vo_id) @dirtyVariantOverrides[hub_id][variant_id][attr] = value - inherit: (hub_id, variant_id, vo_id) -> - @add(hub_id, variant_id, vo_id) - blankVo = angular.copy(VariantOverrides.inherit(hub_id, variant_id)) + inherit: (hub_id, variant, vo_id) -> + @add(hub_id, variant.id, vo_id) + blankVo = angular.copy(VariantOverrides.inherit(hub_id, variant)) delete blankVo[attr] for attr, value of blankVo when attr not in @requiredAttrs() - @dirtyVariantOverrides[hub_id][variant_id] = blankVo + @dirtyVariantOverrides[hub_id][variant.id] = blankVo count: -> count = 0 diff --git a/app/assets/javascripts/admin/variant_overrides/services/variant_overrides.js.coffee b/app/assets/javascripts/admin/variant_overrides/services/variant_overrides.js.coffee index 94a4d093eb..351dbb89f5 100644 --- a/app/assets/javascripts/admin/variant_overrides/services/variant_overrides.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/services/variant_overrides.js.coffee @@ -13,17 +13,18 @@ angular.module("admin.variantOverrides").factory "VariantOverrides", (variantOve @variantOverrides[hub.id] ||= {} for product in products for variant in product.variants - @inherit(hub.id, variant.id) unless @variantOverrides[hub.id][variant.id] + @inherit(hub.id, variant) unless @variantOverrides[hub.id][variant.id] - inherit: (hub_id, variant_id) -> + inherit: (hub_id, variant) -> # This method is called from the trackInheritance directive, to reinstate inheritance - @variantOverrides[hub_id][variant_id] ||= {} - angular.extend @variantOverrides[hub_id][variant_id], @newFor hub_id, variant_id + @variantOverrides[hub_id][variant.id] ||= {} + angular.extend @variantOverrides[hub_id][variant.id], @newFor(hub_id, variant) - newFor: (hub_id, variant_id) -> + newFor: (hub_id, variant) -> # These properties need to match those checked in VariantOverrideSet.deletable? hub_id: hub_id - variant_id: variant_id + variant_id: variant.id + producer_id: variant.producer_id sku: null price: null count_on_hand: null diff --git a/app/serializers/api/admin/variant_simple_serializer.rb b/app/serializers/api/admin/variant_simple_serializer.rb index d94421321f..3a2944aff0 100644 --- a/app/serializers/api/admin/variant_simple_serializer.rb +++ b/app/serializers/api/admin/variant_simple_serializer.rb @@ -6,7 +6,7 @@ module Api attributes :id, :name, :import_date, :options_text, :unit_value, :unit_description, :unit_to_display, :display_as, :display_name, :name_to_display, - :price, :on_demand, :on_hand + :price, :on_demand, :on_hand, :producer_id has_many :variant_overrides @@ -27,6 +27,10 @@ module Api def price object.price.nil? ? 0.to_f : object.price end + + def producer_id + object.supplier_id + end end end end diff --git a/app/views/admin/variant_overrides/_products_product.html.haml b/app/views/admin/variant_overrides/_products_product.html.haml index 188f332e26..30ca0ed176 100644 --- a/app/views/admin/variant_overrides/_products_product.html.haml +++ b/app/views/admin/variant_overrides/_products_product.html.haml @@ -1,5 +1,5 @@ %tr.product.even - %td.producer{ "ng-show": 'columns.producer.visible', "ng-bind-html": '::producersByID[product.producer_id].name' } + %td.producer{ "ng-show": 'columns.producer.visible' } %td.product{ "ng-show": 'columns.product.visible', "ng-bind": '::product.name' } %td.sku{ "ng-show": 'columns.sku.visible' } %td.price{ "ng-show": 'columns.price.visible' } diff --git a/app/views/admin/variant_overrides/_products_variants.html.haml b/app/views/admin/variant_overrides/_products_variants.html.haml index 43decfe33f..c924044c9b 100644 --- a/app/views/admin/variant_overrides/_products_variants.html.haml +++ b/app/views/admin/variant_overrides/_products_variants.html.haml @@ -1,5 +1,5 @@ %tr.variant{ id: "v_{{variant.id}}", "ng-repeat": 'variant in product.variants | inventoryVariants:hub_id:views' } - %td.producer{ "ng-show": 'columns.producer.visible' } + %td.producer{ "ng-show": 'columns.producer.visible', "ng-bind": '::producersByID[variant.producer_id].name' } %td.product{ "ng-show": 'columns.product.visible' } %span{ "ng-bind": '::variant.display_name || ""' } .variant-override-unit{ "ng-bind": '::variant.unit_to_display' } diff --git a/app/views/admin/variant_overrides/index.html.haml b/app/views/admin/variant_overrides/index.html.haml index adfcc8f71c..f80ad3ae04 100644 --- a/app/views/admin/variant_overrides/index.html.haml +++ b/app/views/admin/variant_overrides/index.html.haml @@ -7,6 +7,7 @@ = render 'admin/variant_overrides/loading_flash' = render 'admin/variant_overrides/controls' = render 'admin/variant_overrides/no_results' + // filteredProducts is defined in admin/variant_overrides/products %div{ "ng-cloak": true, "ng-show": 'hub_id && filteredProducts.length > 0' } = render 'admin/variant_overrides/new_products' = render 'admin/variant_overrides/hidden_products' diff --git a/spec/javascripts/unit/admin/services/variant_overrides_spec.js.coffee b/spec/javascripts/unit/admin/services/variant_overrides_spec.js.coffee index 26f6d1ce93..b2a4bcd728 100644 --- a/spec/javascripts/unit/admin/services/variant_overrides_spec.js.coffee +++ b/spec/javascripts/unit/admin/services/variant_overrides_spec.js.coffee @@ -1,9 +1,9 @@ describe "VariantOverrides service", -> VariantOverrides = $httpBackend = null variantOverrides = [ - {id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - {id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - {id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + {id: 1, hub_id: 10, variant_id: 100, producer_id: 500, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + {id: 2, hub_id: 10, variant_id: 200, producer_id: 500, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + {id: 3, hub_id: 20, variant_id: 300, producer_id: 500, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } ] beforeEach -> @@ -19,38 +19,44 @@ describe "VariantOverrides service", -> it "indexes variant overrides by hub_id -> variant_id", -> expect(VariantOverrides.variantOverrides).toEqual 10: - 100: {id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 200: {id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 100: {id: 1, hub_id: 10, variant_id: 100, producer_id: 500, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 200: {id: 2, hub_id: 10, variant_id: 200, producer_id: 500, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } 20: - 300: {id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 300: {id: 3, hub_id: 20, variant_id: 300, producer_id: 500, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } it "ensures blank data available for some products", -> hubs = [{id: 10}, {id: 20}, {id: 30}] products = [ { id: 1 - variants: [{id: 100}, {id: 200}, {id: 300}, {id: 400}, {id: 500}] + variants: [ + {id: 100, producer_id: 1000}, + {id: 200, producer_id: 1000}, + {id: 300, producer_id: 1000}, + {id: 400, producer_id: 1000}, + {id: 500, producer_id: 1001} + ] } ] VariantOverrides.ensureDataFor hubs, products expect(VariantOverrides.variantOverrides[10]).toEqual - 100: { id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 200: { id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 300: { hub_id: 10, variant_id: 300, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 400: { hub_id: 10, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 500: { hub_id: 10, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 100: { id: 1, hub_id: 10, variant_id: 100, producer_id: 500, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 200: { id: 2, hub_id: 10, variant_id: 200, producer_id: 500, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 300: { hub_id: 10, variant_id: 300, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 400: { hub_id: 10, variant_id: 400, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 500: { hub_id: 10, variant_id: 500, producer_id: 1001, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } expect(VariantOverrides.variantOverrides[20]).toEqual - 100: { hub_id: 20, variant_id: 100, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 200: { hub_id: 20, variant_id: 200, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 300: { id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 400: { hub_id: 20, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: []} - 500: { hub_id: 20, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 100: { hub_id: 20, variant_id: 100, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 200: { hub_id: 20, variant_id: 200, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 300: { id: 3, hub_id: 20, variant_id: 300, producer_id: 500, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 400: { hub_id: 20, variant_id: 400, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: []} + 500: { hub_id: 20, variant_id: 500, producer_id: 1001, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } expect(VariantOverrides.variantOverrides[30]).toEqual - 100: { hub_id: 30, variant_id: 100, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 200: { hub_id: 30, variant_id: 200, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 300: { hub_id: 30, variant_id: 300, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: []} - 400: { hub_id: 30, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } - 500: { hub_id: 30, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 100: { hub_id: 30, variant_id: 100, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 200: { hub_id: 30, variant_id: 200, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 300: { hub_id: 30, variant_id: 300, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: []} + 400: { hub_id: 30, variant_id: 400, producer_id: 1000, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } + 500: { hub_id: 30, variant_id: 500, producer_id: 1001, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false, tag_list : '', tags: [] } it "updates the IDs of variant overrides", -> VariantOverrides.variantOverrides[2] = {} diff --git a/spec/system/admin/variant_overrides_spec.rb b/spec/system/admin/variant_overrides_spec.rb index 3f48ae7602..ce81548573 100644 --- a/spec/system/admin/variant_overrides_spec.rb +++ b/spec/system/admin/variant_overrides_spec.rb @@ -48,31 +48,31 @@ RSpec.describe " context "when inventory_items exist for variants" do let!(:product) { - create(:simple_product, supplier: producer, variant_unit: 'weight', variant_unit_scale: 1) + create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1) } let!(:variant) { create(:variant, product:, unit_value: 1, price: 1.23, on_hand: 12) } let!(:inventory_item) { create(:inventory_item, enterprise: hub, variant: ) } let!(:product_managed) { - create(:simple_product, supplier: producer_managed, variant_unit: 'weight', + create(:simple_product, supplier_id: producer_managed.id, variant_unit: 'weight', variant_unit_scale: 1) } let!(:variant_managed) { - create(:variant, product: product_managed, unit_value: 3, price: 3.65, on_hand: 2) + create(:variant, product: product_managed, supplier: producer_managed, unit_value: 3, price: 3.65, on_hand: 2) } let!(:inventory_item_managed) { create(:inventory_item, enterprise: hub, variant: variant_managed ) } - let!(:product_related) { create(:simple_product, supplier: producer_related) } + let!(:product_related) { create(:simple_product, supplier_id: producer_related.id) } let!(:variant_related) { - create(:variant, product: product_related, unit_value: 2, price: 2.34, on_hand: 23) + create(:variant, product: product_related, supplier: producer_related, unit_value: 2, price: 2.34, on_hand: 23) } let!(:inventory_item_related) { create(:inventory_item, enterprise: hub, variant: variant_related ) } - let!(:product_unrelated) { create(:simple_product, supplier: producer_unrelated) } + let!(:product_unrelated) { create(:simple_product, supplier_id: producer_unrelated.id) } context "when a hub is selected" do before do @@ -83,12 +83,18 @@ RSpec.describe " context "with no overrides" do it "displays the list of products with variants" do expect(page).to have_table_row ['Producer', 'Product', 'Price', 'On Hand', 'On Demand?'] - expect(page).to have_table_row [producer.name, product.name, '', '', ''] + expect(page).to have_table_row ['', product.name, '', '', ''] + within "tr#v_#{variant.id}" do |tr| + expect(tr).to have_content(producer.name) + end expect(page).to have_input "variant-overrides-#{variant.id}-price", placeholder: '1.23' expect(page).to have_input "variant-overrides-#{variant.id}-count_on_hand", placeholder: '12' - expect(page).to have_table_row [producer_related.name, product_related.name, '', '', ''] + expect(page).to have_table_row ['', product_related.name, '', '', ''] + within "tr#v_#{variant_related.id}" do |tr| + expect(tr).to have_content(producer_related.name) + end expect(page).to have_input "variant-overrides-#{variant_related.id}-price", placeholder: '2.34' expect(page).to have_input "variant-overrides-#{variant_related.id}-count_on_hand", @@ -253,7 +259,7 @@ RSpec.describe " create(:variant_override, variant:, hub: hub2, price: 1, count_on_hand: 2) } let!(:product2) { - create(:simple_product, supplier: producer, variant_unit: 'weight', + create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1) } let!(:variant2) { @@ -470,7 +476,7 @@ RSpec.describe " describe "when inventory_items do not exist for variants" do let!(:product) { - create(:simple_product, supplier: producer, variant_unit: 'weight', variant_unit_scale: 1) + create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1) } let!(:variant1) { create(:variant, product:, unit_value: 1, price: 1.23, on_hand: 12) @@ -523,7 +529,7 @@ RSpec.describe " it "shows more than 100 products in my inventory" do supplier = create(:supplier_enterprise, sells: "own") inventory_items = (1..101).map do - product = create(:simple_product, supplier:) + product = create(:simple_product, supplier_id: supplier.id) InventoryItem.create!( enterprise: supplier, variant: product.variants.first From f161f51a0ec926a795c667a287ca3bb5230c71f3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 15 May 2024 15:50:18 +1000 Subject: [PATCH 075/145] Fix sales tax by producer report --- .../sales_tax_totals_by_producer_spec.rb | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/spec/system/admin/reports/sales_tax/sales_tax_totals_by_producer_spec.rb b/spec/system/admin/reports/sales_tax/sales_tax_totals_by_producer_spec.rb index 63b4f7f071..3b76817177 100644 --- a/spec/system/admin/reports/sales_tax/sales_tax_totals_by_producer_spec.rb +++ b/spec/system/admin/reports/sales_tax/sales_tax_totals_by_producer_spec.rb @@ -25,41 +25,35 @@ RSpec.describe "Sales Tax Totals By Producer" do ].join(" ") } let!(:state_zone){ create(:zone_with_state_member) } - let!(:country_zone){ create(:zone_with_member) } - let!(:tax_category){ create(:tax_category) } - let!(:state_tax_rate){ create(:tax_rate, zone: state_zone, tax_category:) } - let!(:country_tax_rate){ create(:tax_rate, zone: country_zone, tax_category:) } - let!(:ship_address){ create(:ship_address) } + let!(:country_zone) { create(:zone_with_member) } + let!(:tax_category) { create(:tax_category, name: 'tax_category') } + let!(:state_tax_rate) { + create(:tax_rate, name: 'State', amount: 0.015, zone: state_zone, tax_category:) + } + let!(:country_tax_rate) { + create(:tax_rate, name: 'Country', amount: 0.025, zone: country_zone, tax_category:) + } + let!(:ship_address) { create(:ship_address) } let(:another_state){ create(:state, name: 'Another state', country: ship_address.country) } - let!(:variant){ create(:variant) } - let!(:product){ variant.product } - let!(:supplier){ create(:supplier_enterprise) } - let!(:distributor){ create(:distributor_enterprise_with_tax) } - let!(:payment_method){ create(:payment_method, :flat_rate) } - let!(:shipping_method){ create(:shipping_method, :flat_rate) } + let!(:variant) { create(:variant, supplier:, tax_category:) } + let!(:product) { variant.product } + let!(:supplier) { create(:supplier_enterprise, name: 'Supplier', charges_sales_tax: true) } + let!(:distributor) { create(:distributor_enterprise_with_tax, name: 'Distributor') } + let!(:payment_method) { create(:payment_method, :flat_rate) } + let!(:shipping_method) { create(:shipping_method, :flat_rate) } - let!(:order){ create(:order_with_distributor, distributor:) } - let!(:order_cycle){ - create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], + let!(:order) { create(:order_with_distributor, distributor:) } + let!(:order_cycle) { + create(:simple_order_cycle, name: 'oc1', suppliers: [supplier], distributors: [distributor], variants: [variant]) } - let(:admin){ create(:admin_user) } + let(:admin) { create(:admin_user) } before do - state_tax_rate.update!({ name: 'State', amount: 0.015 }) - country_tax_rate.update!({ name: 'Country', amount: 0.025 }) - tax_category.update!({ name: 'tax_category' }) - order_cycle.update!(name: "oc1") - - distributor.update!({ name: 'Distributor' }) distributor.shipping_methods << shipping_method distributor.payment_methods << payment_method - - supplier.update!(name: 'Supplier', charges_sales_tax: true) - product.update!(supplier_id: supplier.id) - variant.update!(tax_category_id: tax_category.id) end context 'added tax' do From 1ea3160a6a238a4b086bd7be99a21482805affd7 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 15 May 2024 16:17:35 +1000 Subject: [PATCH 076/145] Fic enterprises controller --- app/controllers/admin/enterprises_controller.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb index db67df4406..e5b35473ac 100644 --- a/app/controllers/admin/enterprises_controller.rb +++ b/app/controllers/admin/enterprises_controller.rb @@ -189,10 +189,7 @@ module Admin .visible_enterprises if enterprises.present? - enterprises.includes( - supplied_products: - [:supplier, :variants, :image] - ) + enterprises.includes(supplied_products: [:variants, :image]) end when :index if spree_current_user.admin? From 5884edaa1bda83e8a43ba64d8ccc78e266a33453 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 15 May 2024 21:43:54 +1000 Subject: [PATCH 077/145] Fix product import system spec --- .../spree/admin/products_controller.rb | 8 +++---- app/models/product_import/entry_processor.rb | 6 +++-- app/models/spree/product.rb | 10 ++++++-- spec/models/product_importer_spec.rb | 11 +++++---- spec/system/admin/product_import_spec.rb | 23 +++++++++++-------- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 9071f4e20b..3ae92a38bd 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -173,12 +173,10 @@ module Spree def product_import_dates_query Spree::Variant. - select('DISTINCT spree_variants.import_date'). - joins(:product). - where(spree_products: { supplier_id: editable_enterprises.collect(&:id) }). + select('import_date').distinct. + where(supplier_id: editable_enterprises.collect(&:id)). where.not(spree_variants: { import_date: nil }). - where(spree_variants: { deleted_at: nil }). - order('spree_variants.import_date DESC') + order('import_date DESC') end def strip_new_properties diff --git a/app/models/product_import/entry_processor.rb b/app/models/product_import/entry_processor.rb index 6308df275c..4c585a4b32 100644 --- a/app/models/product_import/entry_processor.rb +++ b/app/models/product_import/entry_processor.rb @@ -227,11 +227,13 @@ module ProductImport # Ensure attributes are correctly copied to a new product's variant variant = product.variants.first variant.display_name = entry.display_name if entry.display_name - variant.on_demand = entry.on_demand if entry.on_demand - variant.on_hand = entry.on_hand if entry.on_hand variant.import_date = @import_time variant.supplier_id = entry.producer_id variant.save + + # on_demand and on_hand require a stock level, which is created after the variant is created + variant.on_demand = entry.on_demand if entry.on_demand + variant.on_hand = entry.on_hand if entry.on_hand end end end diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index f897c4553d..8cb1cfa041 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -74,9 +74,9 @@ module Spree :shipping_category_id, :primary_taxon_id, :supplier_id after_create :ensure_standard_variant + after_update :touch_supplier, if: :saved_change_to_primary_taxon_id? around_destroy :destruction after_save :update_units - after_update :touch_supplier, if: :saved_change_to_primary_taxon_id? # -- Scopes scope :with_properties, ->(*property_ids) { @@ -319,7 +319,13 @@ module Spree def update_units return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name? - variants.each(&:update_units) + variants.each do |v| + if v.persisted? + v.update_units + else + v.assign_units + end + end end def touch_supplier diff --git a/spec/models/product_importer_spec.rb b/spec/models/product_importer_spec.rb index 9ce0dbf83e..4dc3df2199 100644 --- a/spec/models/product_importer_spec.rb +++ b/spec/models/product_importer_spec.rb @@ -166,7 +166,7 @@ RSpec.describe ProductImport::ProductImporter do expect(carrots_variant.supplier).to eq enterprise expect(carrots_variant.price).to eq 3.20 expect(carrots_variant.unit_value).to eq 500 - expect(carrots_variant.on_demand).to_not eq true + expect(carrots_variant.on_demand).not_to eq true expect(carrots_variant.import_date).to be_within(1.minute).of Time.zone.now potatoes = Spree::Product.find_by(name: 'Potatoes') @@ -178,7 +178,7 @@ RSpec.describe ProductImport::ProductImporter do expect(potatoes_variant.supplier).to eq enterprise expect(potatoes_variant.price).to eq 6.50 expect(potatoes_variant.unit_value).to eq 2000 - expect(potatoes_variant.on_demand).to_not eq true + expect(potatoes_variant.on_demand).not_to eq true expect(potatoes_variant.import_date).to be_within(1.minute).of Time.zone.now pea_soup = Spree::Product.find_by(name: 'Pea Soup') @@ -190,7 +190,7 @@ RSpec.describe ProductImport::ProductImporter do expect(pea_soup_variant.supplier).to eq enterprise expect(pea_soup_variant.price).to eq 5.50 expect(pea_soup_variant.unit_value).to eq 0.75 - expect(pea_soup_variant.on_demand).to_not eq true + expect(pea_soup_variant.on_demand).not_to eq true expect(pea_soup_variant.import_date).to be_within(1.minute).of Time.zone.now salad = Spree::Product.find_by(name: 'Salad') @@ -202,7 +202,7 @@ RSpec.describe ProductImport::ProductImporter do expect(salad_variant.supplier).to eq enterprise expect(salad_variant.price).to eq 4.50 expect(salad_variant.unit_value).to eq 1 - expect(salad_variant.on_demand).to_not eq true + expect(salad_variant.on_demand).not_to eq true expect(salad_variant.import_date).to be_within(1.minute).of Time.zone.now buns = Spree::Product.find_by(name: 'Hot Cross Buns') @@ -299,7 +299,8 @@ RSpec.describe ProductImport::ProductImporter do carrots_variant = carrots.variants.first expect(carrots.on_hand).to eq 5 - expect(carrots.primary_taxon.name).to eq "Vegetables" + + expect(carrots_variant.primary_taxon.name).to eq "Vegetables" expect(carrots_variant.supplier).to eq enterprise expect(carrots_variant.price).to eq 3.20 expect(carrots_variant.shipping_category).to eq shipping_category diff --git a/spec/system/admin/product_import_spec.rb b/spec/system/admin/product_import_spec.rb index f7f37d87c3..85555f96bb 100644 --- a/spec/system/admin/product_import_spec.rb +++ b/spec/system/admin/product_import_spec.rb @@ -24,23 +24,26 @@ RSpec.describe "Product Import" do let!(:tax_category2) { create(:tax_category) } let!(:shipping_category) { create(:shipping_category) } - let!(:product) { create(:simple_product, supplier: enterprise2, name: 'Hypothetical Cake') } + let!(:product) { create(:simple_product, supplier_id: enterprise2.id, name: 'Hypothetical Cake') } let!(:variant) { create(:variant, product_id: product.id, price: '8.50', on_hand: 100, unit_value: '500', - display_name: 'Preexisting Banana') + display_name: 'Preexisting Banana', supplier: enterprise2) } let!(:product2) { - create(:simple_product, supplier: enterprise, on_hand: 100, name: 'Beans', unit_value: '500', - description: '', primary_taxon_id: category.id) + create(:simple_product, supplier_id: enterprise.id, on_hand: 100, name: 'Beans', + unit_value: '500', description: '', primary_taxon_id: category.id) } let!(:product3) { - create(:simple_product, supplier: enterprise, on_hand: 100, name: 'Sprouts', unit_value: '500') + create(:simple_product, supplier_id: enterprise.id, on_hand: 100, name: 'Sprouts', + unit_value: '500') } let!(:product4) { - create(:simple_product, supplier: enterprise, on_hand: 100, name: 'Cabbage', unit_value: '500') + create(:simple_product, supplier_id: enterprise.id, on_hand: 100, name: 'Cabbage', + unit_value: '500') } let!(:product5) { - create(:simple_product, supplier: enterprise2, on_hand: 100, name: 'Lettuce', unit_value: '500') + create(:simple_product, supplier_id: enterprise2.id, on_hand: 100, name: 'Lettuce', + unit_value: '500') } let!(:variant_override) { create(:variant_override, variant_id: product4.variants.first.id, hub: enterprise2, @@ -89,7 +92,7 @@ RSpec.describe "Product Import" do carrots = Spree::Product.find_by(name: 'Carrots') potatoes = Spree::Product.find_by(name: 'Potatoes') - expect(potatoes.supplier).to eq enterprise + expect(potatoes.variants.first.supplier).to eq enterprise expect(potatoes.on_hand).to eq 6 expect(potatoes.variants.first.price).to eq 6.50 expect(potatoes.variants.first.import_date).to be_within(1.minute).of Time.zone.now @@ -362,7 +365,7 @@ RSpec.describe "Product Import" do end it "handles a unit of kg for inventory import" do - product = create(:simple_product, supplier: enterprise, on_hand: 100, name: 'Beets', + product = create(:simple_product, supplier_id: enterprise.id, on_hand: 100, name: 'Beets', unit_value: '1000', variant_unit_scale: 1000) csv_data = <<~CSV name, distributor, producer, category, on_hand, price, unit_type, units, on_demand @@ -400,7 +403,7 @@ RSpec.describe "Product Import" do describe "Item type products" do let!(:product) { - create(:simple_product, supplier: enterprise, on_hand: nil, name: 'Aubergine', + create(:simple_product, supplier_id: enterprise.id, on_hand: nil, name: 'Aubergine', unit_value: '1', variant_unit_scale: nil, variant_unit: "items", variant_unit_name: "Bag") } From 03ee9529f168b91319b6161d15b10eabf25cc84c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 20 May 2024 15:57:23 +1000 Subject: [PATCH 078/145] Fix packing report system spec --- spec/system/admin/reports/packing_report_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/system/admin/reports/packing_report_spec.rb b/spec/system/admin/reports/packing_report_spec.rb index fd697b56e2..d3a9d0113b 100644 --- a/spec/system/admin/reports/packing_report_spec.rb +++ b/spec/system/admin/reports/packing_report_spec.rb @@ -34,10 +34,10 @@ RSpec.describe "Packing Reports" do bill_address: bill_address2) } let(:supplier) { create(:supplier_enterprise, name: "Supplier") } - let(:product1) { create(:simple_product, name: "Product 1", supplier: ) } - let(:variant1) { create(:variant, product: product1, unit_description: "Big") } - let(:variant2) { create(:variant, product: product1, unit_description: "Small") } - let(:product2) { create(:simple_product, name: "Product 2", supplier:) } + let(:product1) { create(:simple_product, name: "Product 1", supplier_id: supplier.id ) } + let(:variant1) { create(:variant, product: product1, unit_description: "Big", supplier: ) } + let(:variant2) { create(:variant, product: product1, unit_description: "Small", supplier: ) } + let(:product2) { create(:simple_product, name: "Product 2", supplier_id: supplier.id) } before do order1.finalize! From 93a63c5eb5d5878a5c14be2743babf288ef061f5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 20 May 2024 15:58:49 +1000 Subject: [PATCH 079/145] Fix payment report system spec --- spec/system/admin/reports/payments_report_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/admin/reports/payments_report_spec.rb b/spec/system/admin/reports/payments_report_spec.rb index ad37562c5c..b6819667d8 100644 --- a/spec/system/admin/reports/payments_report_spec.rb +++ b/spec/system/admin/reports/payments_report_spec.rb @@ -23,7 +23,7 @@ RSpec.describe "Payments Reports" do ) end let(:order_cycle) { create(:simple_order_cycle) } - let(:product) { create(:product, supplier:) } + let(:product) { create(:product, supplier_id: supplier.id) } let(:supplier) { create(:supplier_enterprise) } before do From 315f951f8fcf72eab7f90e9bb88c6d270e388492 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 20 May 2024 16:00:34 +1000 Subject: [PATCH 080/145] Fix order cycle complex editing system spec --- .../order_cycles/complex_editing_multiple_product_pages_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb b/spec/system/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb index 993ad50b65..fca4b55f11 100644 --- a/spec/system/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb +++ b/spec/system/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb @@ -13,7 +13,7 @@ RSpec.describe ' describe "editing an order cycle with multiple pages of products" do let(:order_cycle) { create(:order_cycle) } let(:supplier_enterprise) { order_cycle.exchanges.incoming.first.sender } - let!(:new_product) { create(:product, supplier: supplier_enterprise) } + let!(:new_product) { create(:product, supplier_id: supplier_enterprise.id) } before do stub_const("#{Api::V0::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) From e0e78f27987aa97583189425b82e400b8daf41f9 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 20 May 2024 16:10:15 +1000 Subject: [PATCH 081/145] Fix order and fulfillment system spec --- .../admin/reports/orders_and_fulfillment_spec.rb | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/spec/system/admin/reports/orders_and_fulfillment_spec.rb b/spec/system/admin/reports/orders_and_fulfillment_spec.rb index f124dfa2c0..1aa808e2fc 100644 --- a/spec/system/admin/reports/orders_and_fulfillment_spec.rb +++ b/spec/system/admin/reports/orders_and_fulfillment_spec.rb @@ -37,9 +37,9 @@ RSpec.describe "Orders And Fulfillment" do order_cycle_id: order_cycle.id) } let(:supplier) { create(:supplier_enterprise, name: "Supplier Name") } - let(:product) { create(:simple_product, name: "Baked Beans", supplier: ) } - let(:variant1) { create(:variant, product:, unit_description: "Big") } - let(:variant2) { create(:variant, product:, unit_description: "Small") } + let(:product) { create(:simple_product, name: "Baked Beans", supplier_id: supplier.id ) } + let(:variant1) { create(:variant, product:, unit_description: "Big", supplier:) } + let(:variant2) { create(:variant, product:, unit_description: "Small", supplier: ) } before do # order1 has two line items / variants @@ -427,8 +427,12 @@ RSpec.describe "Orders And Fulfillment" do describe "Order Cycle Distributor Totals by Supplier" do context "for an OC supplied by two suppliers" do let(:supplier2) { create(:supplier_enterprise, name: "Another Supplier Name") } - let(:product2) { create(:simple_product, name: "Salted Peanuts", supplier: supplier2 ) } - let(:variant3) { create(:variant, product: product2, unit_description: "Bag") } + let(:product2) { + create(:simple_product, name: "Salted Peanuts", supplier_id: supplier2.id ) + } + let(:variant3) { + create(:variant, product: product2, unit_description: "Bag", supplier: supplier2) + } let(:order4) { create(:completed_order_with_totals, line_items_count: 0, distributor:, bill_address: bill_address1, From 4115b857f7507498271cce8228caa746fbfbab06 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 20 May 2024 16:12:38 +1000 Subject: [PATCH 082/145] Fix revenue by hub system spec --- spec/system/admin/reports/revenues_by_hub_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/system/admin/reports/revenues_by_hub_spec.rb b/spec/system/admin/reports/revenues_by_hub_spec.rb index d0df382ba0..114ec2e411 100644 --- a/spec/system/admin/reports/revenues_by_hub_spec.rb +++ b/spec/system/admin/reports/revenues_by_hub_spec.rb @@ -42,8 +42,7 @@ RSpec.describe "Revenues By Hub Reports" do let(:distributor3) { create(:enterprise, name: "Hub 3", owner:) } let(:owner) { create(:user, email: 'email@email.com') } let(:order_cycle) { create(:simple_order_cycle) } - let(:product) { create(:product, supplier:) } - let(:supplier) { create(:supplier_enterprise) } + let(:product) { create(:product) } let(:voucher2) { create(:voucher_flat_rate, code: 'code', enterprise: distributor2, amount: 10) } let(:voucher3) { create(:voucher_flat_rate, code: 'code', enterprise: distributor3, amount: 10) } From 8937c3395acb02d80ef9cdd963486697bc145956 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 11:14:34 +1000 Subject: [PATCH 083/145] Fix order management subscription variant list --- .../order_management/subscriptions/variants_list.rb | 9 ++++----- .../subscriptions/variants_list_spec.rb | 13 ++++++------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/engines/order_management/app/services/order_management/subscriptions/variants_list.rb b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb index 1807f5154f..fb06ed8829 100644 --- a/engines/order_management/app/services/order_management/subscriptions/variants_list.rb +++ b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb @@ -8,15 +8,14 @@ module OrderManagement # - Variants of hub # - Variants that are in outgoing exchanges where the hub is receiver def self.eligible_variants(distributor) - variant_conditions = ["spree_products.supplier_id IN (?)", - permitted_producer_ids(distributor)] + query = Spree::Variant.where(supplier_id: permitted_producer_ids(distributor)) + exchange_variant_ids = outgoing_exchange_variant_ids(distributor) if exchange_variant_ids.present? - variant_conditions[0] << " OR spree_variants.id IN (?)" - variant_conditions << exchange_variant_ids + query = query.or(Spree::Variant.where(id: exchange_variant_ids)) end - Spree::Variant.joins(:product).where(*variant_conditions) + query end def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant) diff --git a/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb index bb95c0dc77..f932ad36aa 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb @@ -8,8 +8,7 @@ module OrderManagement 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!(:variant) { create(:variant, supplier: producer) } let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } let!(:subscription) { create(:subscription, shop:, schedule:) } @@ -45,7 +44,7 @@ module OrderManagement context "if the supplier is permitted for the shop" do let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, - parent: product.supplier, + parent: variant.supplier, permissions_list: [:add_to_order_cycle]) } @@ -60,7 +59,7 @@ module OrderManagement context "if it is an incoming exchange where the shop is the receiver" do let!(:incoming_exchange) { - order_cycle.exchanges.create(sender: product.supplier, + order_cycle.exchanges.create(sender: variant.supplier, receiver: shop, incoming: true, variants: [variant]) } @@ -72,7 +71,7 @@ module OrderManagement context "if it is an outgoing exchange where the shop is the receiver" do let!(:outgoing_exchange) { - order_cycle.exchanges.create(sender: product.supplier, + order_cycle.exchanges.create(sender: variant.supplier, receiver: shop, incoming: false, variants: [variant]) @@ -123,7 +122,7 @@ module OrderManagement context "if it is an incoming exchange where the shop is the receiver" do let!(:incoming_exchange) { - order_cycle.exchanges.create(sender: product.supplier, + order_cycle.exchanges.create(sender: variant.supplier, receiver: shop, incoming: true, variants: [variant]) @@ -138,7 +137,7 @@ module OrderManagement context "if it is an outgoing exchange where the shop is the receiver" do let!(:outgoing_exchange) { - order_cycle.exchanges.create(sender: product.supplier, + order_cycle.exchanges.create(sender: variant.supplier, receiver: shop, incoming: false, variants: [variant]) From 62efde4c98821a8c33fee23113ce4c26b5b6f847 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 11:56:49 +1000 Subject: [PATCH 084/145] Fix subscription smoke test --- .../admin/subscriptions/smoke_tests_spec.rb | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/spec/system/admin/subscriptions/smoke_tests_spec.rb b/spec/system/admin/subscriptions/smoke_tests_spec.rb index bd49f05c3a..f8d19993f5 100644 --- a/spec/system/admin/subscriptions/smoke_tests_spec.rb +++ b/spec/system/admin/subscriptions/smoke_tests_spec.rb @@ -61,13 +61,13 @@ RSpec.describe 'Subscriptions' do describe "with an inactive order cycle" do let!(:customer) { create(:customer, enterprise: shop) } - let!(:product1) { create(:product, supplier: shop) } - let!(:product2) { create(:product, supplier: shop) } + let!(:product1) { create(:product, supplier_id: shop.id) } + let!(:product2) { create(:product, supplier_id: shop.id) } let!(:variant1) { - create(:variant, product: product1, unit_value: '100', price: 12.00) + create(:variant, product: product1, unit_value: '100', price: 12.00, supplier: shop) } let!(:variant2) { - create(:variant, product: product2, unit_value: '1000', price: 6.00) + create(:variant, product: product2, unit_value: '1000', price: 6.00, supplier: shop) } let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } let!(:order_cycle) { @@ -146,19 +146,24 @@ RSpec.describe 'Subscriptions' do describe "allowed variants" do let!(:customer) { create(:customer, enterprise: shop) } let!(:credit_card) { create(:stored_credit_card, user: customer.user) } - let!(:shop_product) { create(:product, supplier: shop) } - let!(:shop_product2) { create(:product, supplier: shop) } - let!(:shop_variant) { create(:variant, product: shop_product, unit_value: "2000") } - let!(:shop_variant2) { create(:variant, product: shop_product2, unit_value: "1000") } + let!(:shop_product) { create(:product, supplier_id: shop.id) } + let!(:shop_product2) { create(:product, supplier_id: shop.id) } + let!(:shop_variant) { + create(:variant, product: shop_product, unit_value: "2000", supplier: shop) + } + let!(:shop_variant2) { + create(:variant, product: shop_product2, unit_value: "1000", supplier: shop) + } let!(:permitted_supplier) do create(:supplier_enterprise).tap do |supplier| create(:enterprise_relationship, child: shop, parent: supplier, permissions_list: [:add_to_order_cycle]) end end - let!(:permitted_supplier_product) { create(:product, supplier: permitted_supplier) } + let!(:permitted_supplier_product) { create(:product, supplier_id: permitted_supplier.id) } let!(:permitted_supplier_variant) { - create(:variant, product: permitted_supplier_product, unit_value: "2000") + create(:variant, product: permitted_supplier_product, unit_value: "2000", + supplier: permitted_supplier) } let!(:incoming_exchange_product) { create(:product) } let!(:incoming_exchange_variant) do From 07fb607c351d49b27aa9340093f83105efed3a21 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 11:57:46 +1000 Subject: [PATCH 085/145] Small test speed up `select_datetime_from_datepicker` will manually click through the month to find the given date. Setting the date to a month from now speed up the test, and will prevent failing test after 2040 --- spec/system/admin/subscriptions/smoke_tests_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/admin/subscriptions/smoke_tests_spec.rb b/spec/system/admin/subscriptions/smoke_tests_spec.rb index f8d19993f5..33f9b7c31e 100644 --- a/spec/system/admin/subscriptions/smoke_tests_spec.rb +++ b/spec/system/admin/subscriptions/smoke_tests_spec.rb @@ -122,7 +122,7 @@ RSpec.describe 'Subscriptions' do # update orders close find('#order_cycle_orders_close_at').click - select_datetime_from_datepicker Time.zone.at(Time.zone.local(2040, 10, 24, 17, 0o0, 0o0)) + select_datetime_from_datepicker Time.zone.at(1.month.from_now) find("body").send_keys(:escape) click_button 'Save' From 93660efdf7b24a56fbcad8b9595fab4a4157bc85 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 13:27:25 +1000 Subject: [PATCH 086/145] Fix subscription crud spec --- spec/system/admin/subscriptions/crud_spec.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/spec/system/admin/subscriptions/crud_spec.rb b/spec/system/admin/subscriptions/crud_spec.rb index e2871dc450..3e6ca504ad 100644 --- a/spec/system/admin/subscriptions/crud_spec.rb +++ b/spec/system/admin/subscriptions/crud_spec.rb @@ -206,13 +206,13 @@ RSpec.describe 'Subscriptions' do create(:customer, enterprise: shop, bill_address: address, user: customer_user, allow_charges: true) } - let!(:test_product) { create(:product, supplier: shop) } + let!(:test_product) { create(:product) } let!(:test_variant) { - create(:variant, product: test_product, unit_value: "100", price: 12.00) + create(:variant, product: test_product, unit_value: "100", price: 12.00, supplier: shop) } - let!(:shop_product) { create(:product, supplier: shop) } + let!(:shop_product) { create(:product) } let!(:shop_variant) { - create(:variant, product: shop_product, unit_value: "1000", price: 6.00) + create(:variant, product: shop_product, unit_value: "1000", price: 6.00, supplier: shop) } let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } let!(:order_cycle) { @@ -448,17 +448,17 @@ RSpec.describe 'Subscriptions' do context 'editing an existing subscription' do let!(:customer) { create(:customer, enterprise: shop) } - let!(:product1) { create(:product, supplier: shop) } - let!(:product2) { create(:product, supplier: shop) } - let!(:product3) { create(:product, supplier: shop) } + let!(:product1) { create(:product) } + let!(:product2) { create(:product) } + let!(:product3) { create(:product) } let!(:variant1) { - create(:variant, product: product1, unit_value: '100', price: 12.00) + create(:variant, product: product1, unit_value: '100', price: 12.00, supplier: shop) } let!(:variant2) { - create(:variant, product: product2, unit_value: '1000', price: 6.00) + create(:variant, product: product2, unit_value: '1000', price: 6.00, supplier: shop) } let!(:variant3) { - create(:variant, product: product3, unit_value: '10000', price: 22.00) + create(:variant, product: product3, unit_value: '10000', price: 22.00, supplier: shop) } let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } let!(:order_cycle) { From 61750c51b3c851c80b5acfaf9c864b0141c62e80 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 13:37:32 +1000 Subject: [PATCH 087/145] Fix enterprise system spec --- spec/support/request/shop_workflow.rb | 2 +- spec/system/admin/enterprises_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index 1b34f6ab23..3501e15ec9 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -109,7 +109,7 @@ module ShopWorkflow end def add_variant_to_order_cycle(exchange, variant) - ensure_supplier_exchange(exchange, variant.product.supplier) + ensure_supplier_exchange(exchange, variant.supplier) exchange.variants << variant end diff --git a/spec/system/admin/enterprises_spec.rb b/spec/system/admin/enterprises_spec.rb index 6f55ba071e..effdc83c2b 100644 --- a/spec/system/admin/enterprises_spec.rb +++ b/spec/system/admin/enterprises_spec.rb @@ -501,7 +501,7 @@ RSpec.describe ' orders_close_at: 2.days.from_now) } let(:product) { - create(:simple_product, supplier: supplier1, primary_taxon: taxon, + create(:simple_product, supplier_id: supplier1.id, primary_taxon: taxon, properties: [property], name: "Beans") } let(:variant) { product.variants.first } From 0167357f8fcd595d4e2d206607bf3cafaa6c5e98 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 13:55:09 +1000 Subject: [PATCH 088/145] Fic enterprise fee summary report system spec --- ...ry_fee_with_tax_report_by_producer_spec.rb | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb b/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb index 3d16397453..002e0a7247 100644 --- a/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb +++ b/spec/system/admin/reports/enterprise_summary_fees/enterprise_summary_fee_with_tax_report_by_producer_spec.rb @@ -43,10 +43,10 @@ RSpec.describe "Enterprise Summary Fee with Tax Report By Producer" do create(:supplier_enterprise, name: 'Supplier2', charges_sales_tax: true, owner_id: supplier2_owner.id) } - let!(:product){ create(:simple_product, supplier: ) } - let!(:product2){ create(:simple_product, supplier: supplier2 ) } - let!(:variant){ create(:variant, product_id: product.id, tax_category:) } - let!(:variant2){ create(:variant, product_id: product2.id, tax_category:) } + let!(:product){ create(:simple_product) } + let!(:product2){ create(:simple_product) } + let!(:variant){ create(:variant, product_id: product.id, tax_category:, supplier:) } + let!(:variant2){ create(:variant, product_id: product2.id, tax_category:, supplier: supplier2) } let!(:distributor_owner) { create(:user, enterprise_limit: 1) } let!(:distributor){ distributor = create(:distributor_enterprise_with_tax, name: 'Distributor', @@ -169,17 +169,6 @@ RSpec.describe "Enterprise Summary Fee with Tax Report By Producer" do order2 } - before do - product.update!({ - tax_category_id: tax_category.id, - supplier_id: supplier.id - }) - product2.update!({ - tax_category_id: tax_category.id, - supplier_id: supplier2.id - }) - end - context 'added tax' do # 1 order cycle has: # - coordinator fees (20) 1.5% = 0.30, 2.5% = 0.50 From add6d15fc417787d384f303abeb68ea71334c62c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 15:13:28 +1000 Subject: [PATCH 089/145] Fix bulk order management system spec --- .../line_items_controller.js.coffee | 14 +++---- .../api/admin/line_item_serializer.rb | 2 +- .../admin/bulk_order_management_spec.rb | 37 ++++++++++--------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee b/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee index e19c5c7b8b..88479620fa 100644 --- a/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee +++ b/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee @@ -27,7 +27,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, "order_bill_address_full_name_reversed", "order_bill_address_full_name_with_comma", "order_bill_address_full_name_with_comma_reversed", - "variant_product_supplier_name", + "variant_supplier_name", "order_email", "order_number", "product_name"].join("_or_") + "_cont" @@ -81,7 +81,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, "q[order_shipment_state_not_eq]": "shipped", "q[order_completed_at_not_null]": "true", "q[order_distributor_id_eq]": $scope.distributorFilter, - "q[variant_product_supplier_id_eq]": $scope.supplierFilter, + "q[variant_supplier_id_eq]": $scope.supplierFilter, "q[order_order_cycle_id_eq]": $scope.orderCycleFilter, "q[order_completed_at_gteq]": if formattedStartDate then formattedStartDate else undefined, "q[order_completed_at_lt]": if formattedEndDate then formattedEndDate else undefined, @@ -105,7 +105,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, Dereferencer.dereferenceAttr $scope.line_items, "supplier", Enterprises.byID $scope.loadOrders() RequestMonitor.load $q.all([$scope.orders.$promise]).then -> - Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID + Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.byID $scope.bulk_order_form.$setPristine() @@ -133,7 +133,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, return $http( method: 'GET' url: "/admin/orders/#{order.number}/fire?e=cancel&send_cancellation_email=#{sendEmailCancellation}&restock_items=#{restock_items}") - + $scope.deleteLineItem = (lineItem) -> if lineItem.order.item_count == 1 ofnCancelOrderAlert((confirm, sendEmailCancellation, restock_items) -> @@ -167,7 +167,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $scope.cancelOrder(order, sendEmailCancellation, restock_items).then(-> $scope.refreshData()) else Promise.all(LineItems.delete(item) for item in items).then(-> $scope.refreshData()) - , "js.admin.deleting_item_will_cancel_order") + , "js.admin.deleting_item_will_cancel_order") else ofnDeleteLineItemsAlert(() -> Promise.all(LineItems.delete(item) for item in lineItemsToDelete).then(-> $scope.refreshData()) @@ -199,7 +199,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $scope.refreshData() $scope.getLineItemScale = (lineItem) -> - if lineItem.units_product && lineItem.units_variant && (lineItem.units_product.variant_unit == "weight" || lineItem.units_product.variant_unit == "volume") + if lineItem.units_product && lineItem.units_variant && (lineItem.units_product.variant_unit == "weight" || lineItem.units_product.variant_unit == "volume") lineItem.units_product.variant_unit_scale else 1 @@ -252,7 +252,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, scale = $scope.getScale(unitsProduct, unitsVariant) if scale $scope.getFormattedValueWithUnitName(value, unitsProduct, unitsVariant, scale) - else + else '' $scope.fulfilled = (sumOfUnitValues) -> diff --git a/app/serializers/api/admin/line_item_serializer.rb b/app/serializers/api/admin/line_item_serializer.rb index b264e32056..acdb9053ff 100644 --- a/app/serializers/api/admin/line_item_serializer.rb +++ b/app/serializers/api/admin/line_item_serializer.rb @@ -9,7 +9,7 @@ module Api has_one :order, serializer: Api::Admin::IdSerializer def supplier - { id: object.product.supplier_id } + { id: object.supplier.id } end def units_product diff --git a/spec/system/admin/bulk_order_management_spec.rb b/spec/system/admin/bulk_order_management_spec.rb index 4b7eddffa7..e8af8337c9 100644 --- a/spec/system/admin/bulk_order_management_spec.rb +++ b/spec/system/admin/bulk_order_management_spec.rb @@ -174,13 +174,13 @@ RSpec.describe ' let!(:s1) { create(:supplier_enterprise) } let!(:s2) { create(:supplier_enterprise) } let!(:li1) { - create(:line_item_with_shipment, order: o1, product: create(:product, supplier: s1)) + create(:line_item_with_shipment, order: o1, variant: create(:variant, supplier: s1)) } let!(:li2) { - create(:line_item_with_shipment, order: o2, product: create(:product, supplier: s2)) + create(:line_item_with_shipment, order: o2, variant: create(:variant, supplier: s2)) } let!(:li3) { - create(:line_item_with_shipment, order: o2, product: create(:product, supplier: s2)) + create(:line_item_with_shipment, order: o2, variant: create(:variant, supplier: s2)) } before :each do @@ -195,7 +195,7 @@ RSpec.describe ' end it "by supplier name" do - fill_in "quick_filter", with: li1.product.supplier.name + fill_in "quick_filter", with: li1.variant.supplier.name page.find('.filter-actions .button.icon-search').click expect_line_items_results [li1], [li2, li3] @@ -327,8 +327,8 @@ RSpec.describe ' it "displays a column for producer" do expect(page).to have_selector "th.producer", text: "Producer" - expect(page).to have_selector "td.producer", text: li1.product.supplier.name - expect(page).to have_selector "td.producer", text: li2.product.supplier.name + expect(page).to have_selector "td.producer", text: li1.supplier.name + expect(page).to have_selector "td.producer", text: li2.supplier.name end it "displays a column for variant description, which shows only product name " \ @@ -586,10 +586,10 @@ RSpec.describe ' order_cycle: create(:simple_order_cycle) ) } let!(:li1) { - create(:line_item_with_shipment, order: o1, product: create(:product, supplier: s1) ) + create(:line_item_with_shipment, order: o1, variant: create(:variant, supplier: s1) ) } let!(:li2) { - create(:line_item_with_shipment, order: o1, product: create(:product, supplier: s2) ) + create(:line_item_with_shipment, order: o1, variant: create(:variant, supplier: s2) ) } before :each do @@ -743,8 +743,9 @@ RSpec.describe ' let!(:d2) { create(:distributor_enterprise) } let!(:oc1) { create(:simple_order_cycle, suppliers: [s1], distributors: [d1] ) } let!(:oc2) { create(:simple_order_cycle, suppliers: [s2], distributors: [d2] ) } - let!(:p1) { create(:product, supplier: s1) } - let!(:p2) { create(:product, supplier: s2) } + let!(:v1) { create(:variant, supplier: s1) } + let!(:v2) { create(:variant, supplier: s2) } + let!(:o1) { create(:order_with_distributor, state: 'complete', shipment_state: 'ready', completed_at: Time.zone.now, distributor: d1, @@ -755,8 +756,8 @@ RSpec.describe ' completed_at: Time.zone.now, distributor: d2, order_cycle: oc2 ) } - let!(:li1) { create(:line_item_with_shipment, order: o1, product: p1 ) } - let!(:li2) { create(:line_item_with_shipment, order: o2, product: p2 ) } + let!(:li1) { create(:line_item_with_shipment, order: o1, variant: v1 ) } + let!(:li2) { create(:line_item_with_shipment, order: o2, variant: v2 ) } before :each do visit_bulk_order_management @@ -1262,18 +1263,18 @@ RSpec.describe ' completed_at: Time.zone.now, distributor: d2 ) } let!(:line_item_distributed) { - create(:line_item_with_shipment, order: o1, product: create(:product, supplier: s1) ) + create(:line_item_with_shipment, order: o1, variant: create(:variant, supplier: s1) ) } let!(:line_item_not_distributed) { - create(:line_item_with_shipment, order: o2, product: create(:product, supplier: s1) ) + create(:line_item_with_shipment, order: o2, variant: create(:variant, supplier: s1) ) } before(:each) do - @enterprise_user = create(:user) - @enterprise_user.enterprise_roles.build(enterprise: s1).save - @enterprise_user.enterprise_roles.build(enterprise: d1).save + enterprise_user = create(:user) + enterprise_user.enterprise_roles.build(enterprise: s1).save + enterprise_user.enterprise_roles.build(enterprise: d1).save - login_as @enterprise_user + login_as enterprise_user end it "displays a Bulk Management Tab under the Orders item" do From e901886915d8d2fa34d2db89bfc787e4c01f32e3 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 15:36:44 +1000 Subject: [PATCH 090/145] Fix report system spec --- spec/system/admin/reports_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/spec/system/admin/reports_spec.rb b/spec/system/admin/reports_spec.rb index 80839873d2..8902d93461 100644 --- a/spec/system/admin/reports_spec.rb +++ b/spec/system/admin/reports_spec.rb @@ -379,16 +379,16 @@ RSpec.describe ' let(:supplier) { create(:supplier_enterprise, name: 'Supplier Name') } let(:taxon) { create(:taxon, name: 'Taxon Name') } let(:product1) { - create(:simple_product, name: "Product Name", price: 100, supplier:, - primary_taxon_id: taxon.id) + create(:simple_product, name: "Product Name", price: 100, primary_taxon_id: taxon.id, + supplier_id: supplier.id) } let(:product2) { create(:simple_product, name: "Product 2", price: 99.0, variant_unit: 'weight', - variant_unit_scale: 1, unit_value: '100', supplier:, - primary_taxon_id: taxon.id, sku: "product_sku") + variant_unit_scale: 1, unit_value: '100', + primary_taxon_id: taxon.id, sku: "product_sku", supplier_id: supplier.id) } let(:variant1) { product1.variants.first } - let(:variant2) { create(:variant, product: product1, price: 80.0, primary_taxon: taxon) } + let(:variant2) { create(:variant, product: product1, price: 80.0, primary_taxon: taxon, supplier:) } let(:variant3) { product2.variants.first } before do @@ -415,18 +415,18 @@ RSpec.describe ' expect(page).to have_table_row ["Supplier", "Producer Suburb", "Product", "Product Properties", "Taxons", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount", "SKU", - "On Demand?", "On Hand"] - expect(page).to have_table_row [product1.supplier.name, product1.supplier.address.city, + "On Demand?", "On hand"] + expect(page).to have_table_row [supplier.name, supplier.address.city, "Product Name", product1.properties.map(&:presentation).join(", "), taxon.name, "1g", "100.0", "none", "", "sku1", "No", "10"] - expect(page).to have_table_row [product1.supplier.name, product1.supplier.address.city, + expect(page).to have_table_row [supplier.name, supplier.address.city, "Product Name", product1.properties.map(&:presentation).join(", "), taxon.name, "1g", "80.0", "none", "", "sku2", "No", "20"] - expect(page).to have_table_row [product2.supplier.name, product1.supplier.address.city, + expect(page).to have_table_row [supplier.name, supplier.address.city, "Product 2", product1.properties.map(&:presentation).join(", "), taxon.name, "100g", "99.0", From ca801779540a8c12e25b33deeef4d8189b87b827 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 21 May 2024 15:52:04 +1000 Subject: [PATCH 091/145] Fix admin order cycle system spec --- spec/system/admin/order_cycles/simple_spec.rb | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/spec/system/admin/order_cycles/simple_spec.rb b/spec/system/admin/order_cycles/simple_spec.rb index dd10959dd0..74f077de9b 100644 --- a/spec/system/admin/order_cycles/simple_spec.rb +++ b/spec/system/admin/order_cycles/simple_spec.rb @@ -146,10 +146,8 @@ RSpec.describe ' create(:payment_method, distributors: [distributor_managed, distributor_unmanaged, distributor_permitted]) } - let!(:product_managed) { create(:product, supplier: supplier_managed) } - let!(:variant_managed) { product_managed.variants.first } - let!(:product_permitted) { create(:product, supplier: supplier_permitted) } - let!(:variant_permitted) { product_permitted.variants.first } + let!(:variant_managed) { create(:variant, supplier: supplier_managed) } + let!(:variant_permitted) { create(:variant, supplier: supplier_permitted) } let!(:schedule) { create(:schedule, name: 'Schedule1', order_cycles: [ @@ -185,12 +183,12 @@ RSpec.describe ' context "that is a manager of the coordinator" do before do - @new_user = create(:user) - @new_user.enterprise_roles.build(enterprise: supplier_managed).save - @new_user.enterprise_roles.build(enterprise: distributor_managed).save - @new_user.enterprise_roles.build(enterprise: other_distributor_managed).save + new_user = create(:user) + new_user.enterprise_roles.build(enterprise: supplier_managed).save + new_user.enterprise_roles.build(enterprise: distributor_managed).save + new_user.enterprise_roles.build(enterprise: other_distributor_managed).save - login_as @new_user + login_as new_user end it "viewing a list of order cycles I am coordinating" do @@ -375,8 +373,7 @@ RSpec.describe ' distributors: [distributor_managed], name: 'Order Cycle 1' ) end - let(:product) { create(:product, supplier: supplier_managed) } - let(:v1) { create(:variant, product: ) } + let(:v1) { create(:variant, supplier: supplier_managed) } let(:inventory_item_v1) { create(:inventory_item, enterprise: distributor_managed, variant: v1, visible: false) } @@ -413,7 +410,7 @@ RSpec.describe ' # we need this assertion here to assure there is enough time to # toggle the variant box and evaluate the following assertion - expect(page).to have_content product.name + expect(page).to have_content v1.product.name end it "doesn't show a warning when going to 'outgoing products' tab" do @@ -432,7 +429,7 @@ RSpec.describe ' # we need this assertion here to assure there is enough time to # toggle the variant box and evaluate the following assertion - expect(page).to have_content product.name + expect(page).to have_content v1.product.name expect(page).not_to have_content "No variant available for this product" end @@ -469,8 +466,8 @@ RSpec.describe ' distributor_permitted, distributor_unmanaged ], name: 'Order Cycle 1') - v1 = create(:variant, product: create(:product, supplier: supplier_managed) ) - v2 = create(:variant, product: create(:product, supplier: supplier_managed) ) + v1 = create(:variant, supplier: supplier_managed) + v2 = create(:variant, supplier: supplier_managed) # Incoming exchange ex_in = oc.exchanges.where(sender_id: supplier_managed, receiver_id: distributor_managed, @@ -554,8 +551,8 @@ RSpec.describe ' distributor_permitted, distributor_unmanaged ], name: 'Order Cycle 1') - v1 = create(:variant, product: create(:product, supplier: supplier_managed) ) - v2 = create(:variant, product: create(:product, supplier: supplier_managed) ) + v1 = create(:variant, supplier: supplier_managed) + v2 = create(:variant, supplier: supplier_managed) # Incoming exchange ex_in = oc.exchanges.where(sender_id: supplier_managed, receiver_id: distributor_managed, @@ -620,9 +617,9 @@ RSpec.describe ' describe "simplified interface for enterprise users selling only their own produce" do let(:user) { create(:user) } let(:enterprise) { create(:enterprise, is_primary_producer: true, sells: 'own') } - let!(:p1) { create(:simple_product, supplier: enterprise) } - let!(:p2) { create(:simple_product, supplier: enterprise) } - let!(:p3) { create(:simple_product, supplier: enterprise) } + let!(:p1) { create(:product, supplier_id: enterprise.id) } + let!(:p2) { create(:product, supplier_id: enterprise.id) } + let!(:p3) { create(:product, supplier_id: enterprise.id) } let!(:v1) { p1.variants.first } let!(:v2) { p2.variants.first } let!(:v3) { p3.variants.first } From 6538c7adca8fb0c5824d7eaf61c2c7b2abb17c89 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:44:08 +1000 Subject: [PATCH 092/145] Fix shopping system spec --- .../controllers/products_controller.js.coffee | 2 +- .../darkswarm/services/products.js.coffee | 2 +- .../services/products_spec.js.coffee | 25 +++++++++------ .../consumer/shopping/checkout_paypal_spec.rb | 2 +- .../system/consumer/shopping/shopping_spec.rb | 31 +++++++++++++------ 5 files changed, 40 insertions(+), 22 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee index 79f1db42ab..930091bec5 100644 --- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee @@ -66,7 +66,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ id: $scope.order_cycle.order_cycle_id, page: page || $scope.page, per_page: $scope.per_page, - 'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont]': $scope.query, + 'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_variants_supplier_name_cont]': $scope.query, 'q[with_properties][]': $scope.activeProperties, 'q[variants_primary_taxon_id_in_any][]': $scope.activeTaxons } diff --git a/app/assets/javascripts/darkswarm/services/products.js.coffee b/app/assets/javascripts/darkswarm/services/products.js.coffee index 8482c34d57..6334f0cd7f 100644 --- a/app/assets/javascripts/darkswarm/services/products.js.coffee +++ b/app/assets/javascripts/darkswarm/services/products.js.coffee @@ -39,7 +39,7 @@ angular.module('Darkswarm').factory 'Products', (OrderCycleResource, OrderCycle, dereference: -> for product in @fetched_products - product.supplier = Shopfront.producers_by_id[product.supplier.id] + product.supplier = Shopfront.producers_by_id[product.variants[0].supplier.id] Dereferencer.dereference product.taxons, Taxons.taxons_by_id product.properties = angular.copy(product.properties_with_values) diff --git a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee index baea195cf2..7f9ea624a3 100644 --- a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee @@ -19,16 +19,16 @@ describe 'Products service', -> beforeEach -> product = test: "cats" - supplier: - id: 9 price: 11 - master: {} - variants: [] + variants: [ + id: 1000, price: 11, supplier: {id: 9} + ] productWithImage = supplier: id: 9 - master: {} - variants: [] + variants: [ + id: 1000, price: 20, supplier: {id: 9} + ] image: { large_url: 'foo.png' } @@ -79,7 +79,7 @@ describe 'Products service', -> it "dereferences suppliers", -> Shopfront.producers_by_id = {id: 9, name: "test"} - $httpBackend.expectGET(endpoint).respond([{supplier : {id: 9}, master: {}}]) + $httpBackend.expectGET(endpoint).respond([product]) $httpBackend.flush() expect(Products.products[0].supplier).toBe Shopfront.producers_by_id["9"] @@ -96,13 +96,16 @@ describe 'Products service', -> expect(Products.products[0].properties[1]).toBe properties[0] it "registers variants with Variants service", -> - product.variants = [{id: 1}] + product.variants = [{id: 1, supplier: {id: 9}}] $httpBackend.expectGET(endpoint).respond([product]) $httpBackend.flush() expect(Products.products[0].variants[0]).toBe Variants.variants[1] it "stores variant names", -> - product.variants = [{id: 1, name_to_display: "one"}, {id: 2, name_to_display: "two"}] + product.variants = [ + {id: 1, name_to_display: "one", supplier: {id: 9}}, + {id: 2, name_to_display: "two", supplier: {id: 9}} + ] $httpBackend.expectGET(endpoint).respond([product]) $httpBackend.flush() expect(Products.products[0].variant_names).toEqual "one two " @@ -125,7 +128,9 @@ describe 'Products service', -> expect(Products.products[0].price).toEqual 11.00 it "displays the minimum variant price when the product has variants", -> - product.variants = [{price: 22}, {price: 33}] + product.variants = [ + {price: 22, supplier: {id: 9} }, {price: 33, supplier: {id: 9}} + ] $httpBackend.expectGET(endpoint).respond([product]) $httpBackend.flush() expect(Products.products[0].price).toEqual 22 diff --git a/spec/system/consumer/shopping/checkout_paypal_spec.rb b/spec/system/consumer/shopping/checkout_paypal_spec.rb index 8368867e2c..98947d099c 100644 --- a/spec/system/consumer/shopping/checkout_paypal_spec.rb +++ b/spec/system/consumer/shopping/checkout_paypal_spec.rb @@ -10,7 +10,7 @@ RSpec.describe "Check out with Paypal" do let(:distributor) { create(:distributor_enterprise) } let(:supplier) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier:) } + let(:product) { create(:simple_product, supplier_id: supplier.id) } let(:variant) { product.variants.first } let(:order_cycle) { create( diff --git a/spec/system/consumer/shopping/shopping_spec.rb b/spec/system/consumer/shopping/shopping_spec.rb index 7868c73382..becfc90f03 100644 --- a/spec/system/consumer/shopping/shopping_spec.rb +++ b/spec/system/consumer/shopping/shopping_spec.rb @@ -22,7 +22,7 @@ RSpec.describe "As a consumer I want to shop with a distributor" do coordinator: create(:distributor_enterprise), orders_close_at: 3.days.from_now) } - let(:product) { create(:simple_product, supplier:, meta_keywords: "Domestic") } + let(:product) { create(:simple_product, supplier_id: supplier.id, meta_keywords: "Domestic") } let(:variant) { product.variants.first } let(:order) { create(:order, distributor:) } @@ -260,7 +260,7 @@ RSpec.describe "As a consumer I want to shop with a distributor" do context "one having 20 products" do before do 20.times do - product = create(:simple_product, supplier:) + product = create(:simple_product, supplier_id: supplier.id) add_variant_to_order_cycle(exchange1, product.variants.first) end end @@ -275,7 +275,7 @@ RSpec.describe "As a consumer I want to shop with a distributor" do context "another having 5 products" do before do 5.times do - product = create(:simple_product, supplier:) + product = create(:simple_product, supplier_id: supplier.id) add_variant_to_order_cycle(exchange2, product.variants.first) end end @@ -296,9 +296,11 @@ RSpec.describe "As a consumer I want to shop with a distributor" do display_as: 'displayedunderthename') end let(:product2) { - create(:simple_product, supplier:, name: "Meercats", meta_keywords: "Wild Fresh") + create(:simple_product, supplier_id: supplier.id, name: "Meercats", meta_keywords: "Wild Fresh") + } + let(:variant3) { + create(:variant, product: product2, supplier:, price: 40, display_name: "Ferrets") } - let(:variant3) { create(:variant, product: product2, price: 40, display_name: "Ferrets") } let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) } before do @@ -333,39 +335,50 @@ RSpec.describe "As a consumer I want to shop with a distributor" do end context "filtering search results" do - before do - visit shop_path - sleep(2) - end it "returns results when successful" do + visit shop_path + # When we see the Add button, it means product are loaded on the page + expect(page).to have_content("Add", count: 4) + fill_in "search", with: "74576345634XXXXXX" expect(page).to have_content "Sorry, no results found" expect(page).not_to have_content 'Meercats' + click_on "Clear search" # clears search by clicking text expect(page).to have_content("Add", count: 4) + fill_in "search", with: "Meer" # For product named "Meercats" expect(page).to have_content 'Meercats' expect(page).not_to have_content product.name + find("a.clear").click # clears search by clicking the X button expect(page).to have_content("Add", count: 4) end + it "returns results by looking at different columns in DB" do + visit shop_path + # When we see the Add button, it means product are loaded on the page + expect(page).to have_content("Add", count: 4) + # by keyword model: meta_keywords fill_in "search", with: "Wild" # For product named "Meercats" expect(page).to have_content 'Wild' find("a.clear").click + # by variant display name model: variant display_name fill_in "search", with: "Ferrets" # For variants named "Ferrets" within('div.pad-top') do expect(page).to have_content 'Ferrets' expect(page).not_to have_content 'Badgers' end + # model: variant display_as fill_in "search", with: "displayedunder" # "Badgers" within('div.pad-top') do expect(page).not_to have_content 'Ferrets' expect(page).to have_content 'Badgers' end + # model: Enterprise name fill_in "search", with: "Enterp" # Enterprise 1 sells nothing within('p.no-results') do From d53bfe455df03c7892d44980eee0c4eee4c3200c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:47:11 +1000 Subject: [PATCH 093/145] Fix guest checkout system spec --- spec/system/consumer/checkout/guest_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/guest_spec.rb b/spec/system/consumer/checkout/guest_spec.rb index bf24547115..0a90caab66 100644 --- a/spec/system/consumer/checkout/guest_spec.rb +++ b/spec/system/consumer/checkout/guest_spec.rb @@ -12,7 +12,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:product) { - create(:taxed_product, supplier:, price: 10, zone:, tax_rate_amount: 0.1) + create(:taxed_product, supplier_id: supplier.id, price: 10, zone:, tax_rate_amount: 0.1) } let(:variant) { product.variants.first } let!(:order_cycle) { From 4396c39c83de459d73440cdcb8c7af7ea7415651 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:49:31 +1000 Subject: [PATCH 094/145] Fix checkout details system spec --- spec/system/consumer/checkout/details_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/details_spec.rb b/spec/system/consumer/checkout/details_spec.rb index 7c970196be..bb204e3ca7 100644 --- a/spec/system/consumer/checkout/details_spec.rb +++ b/spec/system/consumer/checkout/details_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:product) { - create(:taxed_product, supplier:, price: 10, zone:, tax_rate_amount: 0.1) + create(:taxed_product, supplier_id: supplier.id, price: 10, zone:, tax_rate_amount: 0.1) } let(:variant) { product.variants.first } let!(:order_cycle) { From 8db7352774aed3a4a1eb246cc49ae55645bd12c5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:53:11 +1000 Subject: [PATCH 095/145] Fix tax not incl checkout system spec --- spec/system/consumer/checkout/tax_not_incl_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/tax_not_incl_spec.rb b/spec/system/consumer/checkout/tax_not_incl_spec.rb index 274480300e..a5a0d26f91 100644 --- a/spec/system/consumer/checkout/tax_not_incl_spec.rb +++ b/spec/system/consumer/checkout/tax_not_incl_spec.rb @@ -32,7 +32,7 @@ RSpec.describe "As a consumer, I want to see adjustment breakdown" do let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:supplier) { create(:supplier_enterprise) } let(:product_with_tax) { - create(:product, supplier:, price: 10, tax_category_id: tax_category.id) + create(:product, supplier_id: supplier.id, price: 10, tax_category_id: tax_category.id) } let(:variant_with_tax) { product_with_tax.variants.first } let(:order_cycle) { From 12c017ab99e586cd2e3e5725f66a092c94e58d81 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:55:26 +1000 Subject: [PATCH 096/145] Fix checkout tax incl system spec --- spec/system/consumer/checkout/tax_incl_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/tax_incl_spec.rb b/spec/system/consumer/checkout/tax_incl_spec.rb index b8b9ff5b7e..de0ee1af4a 100644 --- a/spec/system/consumer/checkout/tax_incl_spec.rb +++ b/spec/system/consumer/checkout/tax_incl_spec.rb @@ -29,7 +29,7 @@ RSpec.describe "As a consumer, I want to see adjustment breakdown" do let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:supplier) { create(:supplier_enterprise) } let!(:product_with_tax) { - create(:simple_product, supplier:, price: 10, tax_category_id: tax_category.id) + create(:simple_product, supplier_id: supplier.id, price: 10, tax_category_id: tax_category.id) } let!(:variant_with_tax) { product_with_tax.variants.first } let!(:order_cycle) { From 1061bf50b49c57e75ec682c1b7502c6cad173405 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 10:57:44 +1000 Subject: [PATCH 097/145] Fix shopping unit price system spec --- spec/system/consumer/shopping/unit_price_spec.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/system/consumer/shopping/unit_price_spec.rb b/spec/system/consumer/shopping/unit_price_spec.rb index 85da774add..95432649de 100644 --- a/spec/system/consumer/shopping/unit_price_spec.rb +++ b/spec/system/consumer/shopping/unit_price_spec.rb @@ -15,8 +15,7 @@ RSpec.describe "As a consumer, I want to check unit price information for a prod coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) } - let(:product) { create(:simple_product, supplier:) } - let(:variant) { product.variants.first } + let(:variant) { create(:variant, supplier:) } let(:order) { create(:order, distributor:) } let(:exchange1) { oc1.exchanges.to_enterprises(distributor).outgoing.first } let(:user) { create(:user, password: "password", password_confirmation: "password") } From a8cdca89a18255665fcb29e5fce4f0f063738808 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 11:05:53 +1000 Subject: [PATCH 098/145] Fix shopping variant overrides system spec --- .../shopping/variant_overrides_spec.rb | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/spec/system/consumer/shopping/variant_overrides_spec.rb b/spec/system/consumer/shopping/variant_overrides_spec.rb index cda13c4459..01dd56c349 100644 --- a/spec/system/consumer/shopping/variant_overrides_spec.rb +++ b/spec/system/consumer/shopping/variant_overrides_spec.rb @@ -18,21 +18,33 @@ RSpec.describe "shopping with variant overrides defined" do let(:outgoing_exchange) { oc.exchanges.outgoing.first } let(:sm) { hub.shipping_methods.first } let(:pm) { hub.payment_methods.first } - let(:product1) { create(:simple_product, supplier: producer) } - let(:product2) { create(:simple_product, supplier: producer) } - let(:product3) { create(:simple_product, supplier: producer, on_demand: true) } - let(:product4) { create(:simple_product, supplier: producer) } - let(:product1_variant1) { create(:variant, product: product1, price: 11.11, unit_value: 1) } - let(:product1_variant2) { create(:variant, product: product1, price: 22.22, unit_value: 2) } - let(:product2_variant1) { create(:variant, product: product2, price: 33.33, unit_value: 3) } - let(:product1_variant3) { create(:variant, product: product1, price: 44.44, unit_value: 4) } + let(:product1) { create(:simple_product, supplier_id: producer.id) } + let(:product2) { create(:simple_product, supplier_id: producer.id) } + let(:product3) { create(:simple_product, supplier_id: producer.id, on_demand: true) } + let(:product4) { create(:simple_product, supplier_id: producer.id) } + let(:product1_variant1) { + create(:variant, product: product1, price: 11.11, unit_value: 1, supplier: producer) + } + let(:product1_variant2) { + create(:variant, product: product1, price: 22.22, unit_value: 2, supplier: producer) + } + let(:product2_variant1) { + create(:variant, product: product2, price: 33.33, unit_value: 3, supplier: producer) + } + let(:product1_variant3) { + create(:variant, product: product1, price: 44.44, unit_value: 4, supplier: producer) + } let(:product3_variant1) { - create(:variant, product: product3, price: 55.55, unit_value: 5, on_demand: true) + create(:variant, product: product3, price: 55.55, unit_value: 5, on_demand: true, + supplier: producer) } let(:product3_variant2) { - create(:variant, product: product3, price: 66.66, unit_value: 6, on_demand: true) + create(:variant, product: product3, price: 66.66, unit_value: 6, on_demand: true, + supplier: producer) + } + let(:product4_variant1) { + create(:variant, product: product4, price: 77.77, unit_value: 7, supplier: producer) } - let(:product4_variant1) { create(:variant, product: product4, price: 77.77, unit_value: 7) } let!(:product1_variant1_override) { create(:variant_override, :use_producer_stock_settings, hub:, variant: product1_variant1, price: 55.55, count_on_hand: nil, From 470986dc19f089125ba93c89b494a6376fbcaf62 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 11:52:59 +1000 Subject: [PATCH 099/145] Fix white label system spec --- spec/system/consumer/white_label_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/white_label_spec.rb b/spec/system/consumer/white_label_spec.rb index 73aa8065a9..25d9666c3c 100644 --- a/spec/system/consumer/white_label_spec.rb +++ b/spec/system/consumer/white_label_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'White label setting' do let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) } let!(:shipping_method) { create(:shipping_method, distributors: [distributor]) } let(:product) { - create(:taxed_product, supplier: create(:supplier_enterprise), price: 10, + create(:taxed_product, supplier_id: create(:supplier_enterprise).id, price: 10, zone: create(:zone_with_member), tax_rate_amount: 0.1) } let!(:order_cycle) { From 4c274e0a90b8f51a2e695c2c4eeba4e810aaa462 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 11:55:56 +1000 Subject: [PATCH 100/145] Fix groups system spec --- spec/system/consumer/groups_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/system/consumer/groups_spec.rb b/spec/system/consumer/groups_spec.rb index 6820ad1b9c..563fefc094 100644 --- a/spec/system/consumer/groups_spec.rb +++ b/spec/system/consumer/groups_spec.rb @@ -24,8 +24,8 @@ RSpec.describe 'Groups' do let!(:producer1) { create(:supplier_enterprise) } let!(:producer2) { create(:supplier_enterprise) } - let!(:product1) { create(:simple_product, supplier: producer1) } - let!(:product2) { create(:simple_product, supplier: producer2) } + let!(:product1) { create(:simple_product, supplier_id: producer1.id) } + let!(:product2) { create(:simple_product, supplier_id: producer2.id) } before do product1.set_property 'Organic', 'NASAA 12345' @@ -85,10 +85,10 @@ RSpec.describe 'Groups' do let(:d4) { create(:distributor_enterprise, with_payment_and_shipping: true, visible: "public") } - let(:p1) { create(:simple_product, supplier: producer) } - let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } - let(:p3) { create(:simple_product, supplier: create(:supplier_enterprise)) } - let(:p4) { create(:simple_product, supplier: create(:supplier_enterprise)) } + let(:p1) { create(:simple_product, supplier_id: producer.id) } + let(:p2) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } + let(:p3) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } + let(:p4) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } let(:ex_d3) { order_cycle.exchanges.outgoing.where(receiver_id: d3).first } From 8104d8e37b5fdb9e54a2ecf8881b595738ae83c7 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 11:58:12 +1000 Subject: [PATCH 101/145] Fix checkout auth system spec --- spec/system/consumer/shopping/checkout_auth_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/shopping/checkout_auth_spec.rb b/spec/system/consumer/shopping/checkout_auth_spec.rb index 0e3ea887f7..ed52e3ba19 100644 --- a/spec/system/consumer/shopping/checkout_auth_spec.rb +++ b/spec/system/consumer/shopping/checkout_auth_spec.rb @@ -17,7 +17,7 @@ RSpec.describe "As a consumer I want to check out my cart" do coordinator: create(:distributor_enterprise), variants: [product.variants.first]) } - let(:product) { create(:simple_product, supplier:) } + let(:product) { create(:simple_product, supplier_id: supplier.id) } let(:order) { create(:order, order_cycle:, distributor:) } let(:address) { create(:address, firstname: "Foo", lastname: "Bar") } let(:user) { create(:user, bill_address: address, ship_address: address) } From 0f7f1a5d5c1d9ab9e14e0c54aaac85926f5f9a48 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 12:02:24 +1000 Subject: [PATCH 102/145] Fix shopping system spec --- spec/system/consumer/shopping/shopping_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/system/consumer/shopping/shopping_spec.rb b/spec/system/consumer/shopping/shopping_spec.rb index becfc90f03..ee988330aa 100644 --- a/spec/system/consumer/shopping/shopping_spec.rb +++ b/spec/system/consumer/shopping/shopping_spec.rb @@ -388,8 +388,11 @@ RSpec.describe "As a consumer I want to shop with a distributor" do end context "when supplier uses property" do - let(:product3) { create(:simple_product, supplier:, inherits_properties: false) } + let(:product3) { + create(:simple_product, supplier_id: supplier.id, inherits_properties: false) + } + # TODO properties before do add_variant_to_order_cycle(exchange, product3.variants.first) property = create(:property, presentation: 'certified') From 9b879da61605ee505c18f5f052d2ac97812f179f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 12:05:46 +1000 Subject: [PATCH 103/145] Fix Checkout payment system spec --- spec/system/consumer/checkout/payment_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/payment_spec.rb b/spec/system/consumer/checkout/payment_spec.rb index e9a1c83609..b0bd281ca1 100644 --- a/spec/system/consumer/checkout/payment_spec.rb +++ b/spec/system/consumer/checkout/payment_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:product) { - create(:taxed_product, supplier:, price: 10, zone:, tax_rate_amount: 0.1) + create(:taxed_product, supplier_id: supplier.id, price: 10, zone:, tax_rate_amount: 0.1) } let(:variant) { product.variants.first } let!(:order_cycle) { From a2de846f2c4abee945f2643d3f754447e7a1923f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 12:07:09 +1000 Subject: [PATCH 104/145] Fix darkswarm caching system spec --- spec/system/consumer/caching/darkswarm_caching_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/caching/darkswarm_caching_spec.rb b/spec/system/consumer/caching/darkswarm_caching_spec.rb index 02c2fdad65..f3ae4482c1 100644 --- a/spec/system/consumer/caching/darkswarm_caching_spec.rb +++ b/spec/system/consumer/caching/darkswarm_caching_spec.rb @@ -11,7 +11,7 @@ RSpec.describe "Darkswarm data caching", caching: true do create(:distributor_enterprise, with_payment_and_shipping: true, is_primary_producer: true) } let!(:product) { - create(:simple_product, supplier: producer, primary_taxon: taxon, + create(:simple_product, supplier_id: producer.id, primary_taxon: taxon, properties: [property]) } let!(:order_cycle) { From 725e2bfa48887c29c94b58eb7b70a249ed33f687 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 12:10:23 +1000 Subject: [PATCH 105/145] Fix checkout summary system spec --- spec/system/consumer/checkout/summary_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/checkout/summary_spec.rb b/spec/system/consumer/checkout/summary_spec.rb index 75a1a06487..a15b800528 100644 --- a/spec/system/consumer/checkout/summary_spec.rb +++ b/spec/system/consumer/checkout/summary_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "As a consumer, I want to checkout my order" do let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:product) { - create(:taxed_product, supplier:, price: 10, zone:, tax_rate_amount: 0.1) + create(:taxed_product, supplier_id: supplier.id, price: 10, zone:, tax_rate_amount: 0.1) } let(:variant) { product.variants.first } let!(:order_cycle) { From 7c712f005872c20d197447c6a1afe66ad8eb8257 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 12:12:39 +1000 Subject: [PATCH 106/145] Fix cart system spec --- spec/system/consumer/shopping/cart_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/system/consumer/shopping/cart_spec.rb b/spec/system/consumer/shopping/cart_spec.rb index 5ad9edef83..0e40f3ea97 100644 --- a/spec/system/consumer/shopping/cart_spec.rb +++ b/spec/system/consumer/shopping/cart_spec.rb @@ -24,11 +24,11 @@ RSpec.describe "full-page cart" do create(:enterprise_fee, amount: 11.00, tax_category: product_with_tax.tax_category) } let(:product_with_tax) { - create(:taxed_product, supplier:, zone:, price: 110.00, tax_rate_amount: 0.1, + create(:taxed_product, supplier_id: supplier.id, zone:, price: 110.00, tax_rate_amount: 0.1, included_in_price: true) } let(:product_with_fee) { - create(:simple_product, supplier:, price: 0.86, on_hand: 100) + create(:simple_product, supplier_id: supplier.id, price: 0.86, on_hand: 100) } let(:order) { create(:order, order_cycle:, distributor:) } From 2550f8fd808664976c6f45daebc177e734783554 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 14:16:04 +1000 Subject: [PATCH 107/145] Fix cached enterprise serializer spec --- spec/serializers/api/cached_enterprise_serializer_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/serializers/api/cached_enterprise_serializer_spec.rb b/spec/serializers/api/cached_enterprise_serializer_spec.rb index 584d365e73..c358870149 100644 --- a/spec/serializers/api/cached_enterprise_serializer_spec.rb +++ b/spec/serializers/api/cached_enterprise_serializer_spec.rb @@ -13,7 +13,7 @@ RSpec.describe Api::CachedEnterpriseSerializer do before do product = create(:product, properties: [property]) - enterprise.supplied_products << product + enterprise.supplied_variants << product.variants.first end context "when the enterprise is a producer" do @@ -56,7 +56,7 @@ RSpec.describe Api::CachedEnterpriseSerializer do before do product = create(:product, properties: [property]) - producer.supplied_products << product + producer.supplied_variants << product.variants.first create( :simple_order_cycle, From d61478005992e9832b6648d08e2058f6ec88b517 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 14:20:11 +1000 Subject: [PATCH 108/145] Fix product serializer spec --- spec/serializers/api/product_serializer_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/serializers/api/product_serializer_spec.rb b/spec/serializers/api/product_serializer_spec.rb index af0b1f3bf4..73a6e952f9 100644 --- a/spec/serializers/api/product_serializer_spec.rb +++ b/spec/serializers/api/product_serializer_spec.rb @@ -28,7 +28,7 @@ RSpec.describe Api::ProductSerializer do it "serializes various attributes" do expect(serializer.serializable_hash.keys).to eq [ :id, :name, :meta_keywords, :group_buy, :notes, :description, :description_html, - :properties_with_values, :variants, :image, :supplier + :properties_with_values, :variants, :image ] end From 848144d3780d3036604d438cc5d29c51e1149403 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 14:34:51 +1000 Subject: [PATCH 109/145] Fix DFC engine --- .../dfc_provider/supplied_products_controller.rb | 6 +++++- engines/dfc_provider/app/services/dfc_builder.rb | 2 +- engines/dfc_provider/app/services/offer_builder.rb | 2 +- .../app/services/supplied_product_builder.rb | 7 ++++--- .../dfc_provider/spec/requests/catalog_items_spec.rb | 4 ++-- .../dfc_provider/spec/requests/enterprises_spec.rb | 6 ++++-- engines/dfc_provider/spec/requests/offers_spec.rb | 4 ++-- .../spec/requests/supplied_products_spec.rb | 6 ++++-- .../spec/services/catalog_item_builder_spec.rb | 4 ++-- .../spec/services/enterprise_builder_spec.rb | 4 ++-- .../spec/services/supplied_product_builder_spec.rb | 12 ++++++------ spec/system/admin/dfc_product_import_spec.rb | 2 +- 12 files changed, 34 insertions(+), 25 deletions(-) diff --git a/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb index 57d25c1929..3e5b26ec8d 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb @@ -20,8 +20,12 @@ module DfcProvider ) product = variant.product + if variant.new_record? + variant.supplier = current_enterprise + variant.save! + end + product.save! if product.new_record? - variant.save! if variant.new_record? supplied_product = SuppliedProductBuilder.supplied_product(variant) render json: DfcIo.export(supplied_product) diff --git a/engines/dfc_provider/app/services/dfc_builder.rb b/engines/dfc_provider/app/services/dfc_builder.rb index 5411d8ab28..4f55e301fb 100644 --- a/engines/dfc_provider/app/services/dfc_builder.rb +++ b/engines/dfc_provider/app/services/dfc_builder.rb @@ -3,7 +3,7 @@ class DfcBuilder def self.catalog_item(variant) id = urls.enterprise_catalog_item_url( - enterprise_id: variant.product.supplier_id, + enterprise_id: variant.supplier_id, id: variant.id, ) product = SuppliedProductBuilder.supplied_product(variant) diff --git a/engines/dfc_provider/app/services/offer_builder.rb b/engines/dfc_provider/app/services/offer_builder.rb index b499c1d945..0c3a8b276c 100644 --- a/engines/dfc_provider/app/services/offer_builder.rb +++ b/engines/dfc_provider/app/services/offer_builder.rb @@ -3,7 +3,7 @@ class OfferBuilder < DfcBuilder def self.build(variant) id = urls.enterprise_offer_url( - enterprise_id: variant.product.supplier_id, + enterprise_id: variant.supplier_id, id: variant.id, ) diff --git a/engines/dfc_provider/app/services/supplied_product_builder.rb b/engines/dfc_provider/app/services/supplied_product_builder.rb index bdf069bdfb..9c1e83e8f5 100644 --- a/engines/dfc_provider/app/services/supplied_product_builder.rb +++ b/engines/dfc_provider/app/services/supplied_product_builder.rb @@ -3,11 +3,11 @@ class SuppliedProductBuilder < DfcBuilder def self.supplied_product(variant) id = urls.enterprise_supplied_product_url( - enterprise_id: variant.product.supplier_id, + enterprise_id: variant.supplier_id, id: variant.id, ) product_uri = urls.enterprise_url( - variant.product.supplier_id, + variant.supplier_id, spree_product_id: variant.product_id ) @@ -29,14 +29,15 @@ class SuppliedProductBuilder < DfcBuilder if product Spree::Variant.new( product:, + supplier:, price: 0, ).tap do |variant| apply(supplied_product, variant) end else product = import_product(supplied_product) - product.supplier = supplier product.ensure_standard_variant + product.variants.first.supplier = supplier product.variants.first end.tap do |variant| link = supplied_product.semanticId diff --git a/engines/dfc_provider/spec/requests/catalog_items_spec.rb b/engines/dfc_provider/spec/requests/catalog_items_spec.rb index 1405a5b0a5..03e1ba468a 100644 --- a/engines/dfc_provider/spec/requests/catalog_items_spec.rb +++ b/engines/dfc_provider/spec/requests/catalog_items_spec.rb @@ -15,7 +15,7 @@ RSpec.describe "CatalogItems", type: :request, swagger_doc: "dfc.yaml", let(:product) { create( :base_product, - id: 90_000, supplier: enterprise, name: "Apple", description: "Red", + id: 90_000, name: "Apple", description: "Red", variants: [variant], primary_taxon: non_local_vegetable ) @@ -27,7 +27,7 @@ RSpec.describe "CatalogItems", type: :request, swagger_doc: "dfc.yaml", dfc_id: "https://github.com/datafoodconsortium/taxonomies/releases/latest/download/productTypes.rdf#non-local-vegetable" ) } - let(:variant) { build(:base_variant, id: 10_001, unit_value: 1, sku: "AR") } + let(:variant) { build(:base_variant, id: 10_001, unit_value: 1, sku: "AR", supplier: enterprise) } before { login_as user } diff --git a/engines/dfc_provider/spec/requests/enterprises_spec.rb b/engines/dfc_provider/spec/requests/enterprises_spec.rb index 9785361aa6..13c9f249be 100644 --- a/engines/dfc_provider/spec/requests/enterprises_spec.rb +++ b/engines/dfc_provider/spec/requests/enterprises_spec.rb @@ -27,7 +27,7 @@ RSpec.describe "Enterprises", type: :request, swagger_doc: "dfc.yaml", rswag_aut let!(:product) { create( :product_with_image, - id: 90_000, supplier: enterprise, name: "Apple", description: "Round", + id: 90_000, name: "Apple", description: "Round", variants: [variant], primary_taxon: non_local_vegetable ) @@ -39,7 +39,9 @@ RSpec.describe "Enterprises", type: :request, swagger_doc: "dfc.yaml", rswag_aut dfc_id: "https://github.com/datafoodconsortium/taxonomies/releases/latest/download/productTypes.rdf#non-local-vegetable" ) } - let(:variant) { build(:base_variant, id: 10_001, unit_value: 1, sku: "APP") } + let(:variant) { + build(:base_variant, id: 10_001, unit_value: 1, sku: "APP", supplier: enterprise) + } before { login_as user } diff --git a/engines/dfc_provider/spec/requests/offers_spec.rb b/engines/dfc_provider/spec/requests/offers_spec.rb index f309613c0c..dd5274e1b9 100644 --- a/engines/dfc_provider/spec/requests/offers_spec.rb +++ b/engines/dfc_provider/spec/requests/offers_spec.rb @@ -9,11 +9,11 @@ RSpec.describe "Offers", type: :request, swagger_doc: "dfc.yaml", rswag_autodoc: create( :product, id: 90_000, - supplier: enterprise, name: "Pesto", description: "Basil Pesto", + name: "Pesto", description: "Basil Pesto", variants: [variant], ) } - let(:variant) { build(:base_variant, id: 10_001, unit_value: 1) } + let(:variant) { build(:base_variant, id: 10_001, unit_value: 1, supplier: enterprise) } before { login_as user } diff --git a/engines/dfc_provider/spec/requests/supplied_products_spec.rb b/engines/dfc_provider/spec/requests/supplied_products_spec.rb index e72e13017f..cb707b3fdb 100644 --- a/engines/dfc_provider/spec/requests/supplied_products_spec.rb +++ b/engines/dfc_provider/spec/requests/supplied_products_spec.rb @@ -9,11 +9,13 @@ RSpec.describe "SuppliedProducts", type: :request, swagger_doc: "dfc.yaml", rswa create( :product_with_image, id: 90_000, - supplier: enterprise, name: "Pesto", description: "Basil Pesto", + name: "Pesto", description: "Basil Pesto", variants: [variant] ) } - let(:variant) { build(:base_variant, id: 10_001, unit_value: 1, primary_taxon: taxon) } + let(:variant) { + build(:base_variant, id: 10_001, unit_value: 1, primary_taxon: taxon, supplier: enterprise) + } let(:taxon) { build( :taxon, diff --git a/engines/dfc_provider/spec/services/catalog_item_builder_spec.rb b/engines/dfc_provider/spec/services/catalog_item_builder_spec.rb index 7c1b4d2c0f..6f7d5d42a6 100644 --- a/engines/dfc_provider/spec/services/catalog_item_builder_spec.rb +++ b/engines/dfc_provider/spec/services/catalog_item_builder_spec.rb @@ -8,7 +8,7 @@ RSpec.describe DfcBuilder do describe ".catalog_item" do it "assigns a semantic id" do variant.id = 5 - variant.product.supplier_id = 7 + variant.supplier_id = 7 item = DfcBuilder.catalog_item(variant) @@ -19,7 +19,7 @@ RSpec.describe DfcBuilder do it "refers to a supplied product" do variant.id = 5 - variant.product.supplier_id = 7 + variant.supplier_id = 7 item = DfcBuilder.catalog_item(variant) diff --git a/engines/dfc_provider/spec/services/enterprise_builder_spec.rb b/engines/dfc_provider/spec/services/enterprise_builder_spec.rb index cc26fe767b..05fa5ae17d 100644 --- a/engines/dfc_provider/spec/services/enterprise_builder_spec.rb +++ b/engines/dfc_provider/spec/services/enterprise_builder_spec.rb @@ -5,7 +5,7 @@ require_relative "../spec_helper" RSpec.describe EnterpriseBuilder do subject(:builder) { described_class } let(:enterprise) { - build( + create( :enterprise, id: 10_000, name: "Fabi's Farm", description: "The place where stuff grows", abn: "123 456 789 0", @@ -13,7 +13,7 @@ RSpec.describe EnterpriseBuilder do ) } let(:variant) { - create(:product, supplier: enterprise, name: "Apple").variants.first + create(:product, supplier_id: enterprise.id, name: "Apple").variants.first } describe ".enterprise" do diff --git a/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb b/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb index 3e582a7aa4..c39aab031e 100644 --- a/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb +++ b/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb @@ -7,13 +7,13 @@ RSpec.describe SuppliedProductBuilder do subject(:builder) { described_class } let(:variant) { - build(:variant, id: 5, product: spree_product, primary_taxon: taxon) + create(:variant, id: 5, product: spree_product, primary_taxon: taxon, supplier:) } let(:spree_product) { - create(:product, id: 6, supplier:) + create(:product, id: 6) } let(:supplier) { - build(:supplier_enterprise, id: 7) + create(:supplier_enterprise, id: 7) } let(:taxon) { build( @@ -43,7 +43,7 @@ RSpec.describe SuppliedProductBuilder do variant.product.name = "Apple" product = builder.supplied_product(variant) - expect(product.name).to eq "Apple" + expect(product.name).to match /Apple/ end it "assigns the variant name if present" do @@ -51,7 +51,7 @@ RSpec.describe SuppliedProductBuilder do variant.display_name = "Granny Smith" product = builder.supplied_product(variant) - expect(product.name).to eq "Apple - Granny Smith" + expect(product.name).to match /Apple - Granny Smith/ end context "product_type mapping" do @@ -244,7 +244,7 @@ RSpec.describe SuppliedProductBuilder do it "doesn't return a product of another enterprise" do variant.save! - create(:product, id: 8, supplier: create(:enterprise)) + create(:product, id: 8, supplier_id: create(:enterprise).id) supplied_product.spree_product_uri = "http://test.host/api/dfc/enterprises/7?spree_product_id=8" diff --git a/spec/system/admin/dfc_product_import_spec.rb b/spec/system/admin/dfc_product_import_spec.rb index f02f4b5565..dff70ff168 100644 --- a/spec/system/admin/dfc_product_import_spec.rb +++ b/spec/system/admin/dfc_product_import_spec.rb @@ -8,7 +8,7 @@ RSpec.describe "DFC Product Import" do let(:user) { create(:oidc_user, owned_enterprises: [enterprise]) } let(:enterprise) { create(:supplier_enterprise) } - let(:source_product) { create(:product, supplier: enterprise) } + let(:source_product) { create(:product, supplier_id: enterprise.id) } before do login_as user From 3eae329cc48b85f26d2bea41ff492e971e0bf388 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 14:59:02 +1000 Subject: [PATCH 110/145] Fix shop system spec --- spec/system/consumer/shops_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/spec/system/consumer/shops_spec.rb b/spec/system/consumer/shops_spec.rb index d36a9ca6c1..2fc8ddec4c 100644 --- a/spec/system/consumer/shops_spec.rb +++ b/spec/system/consumer/shops_spec.rb @@ -112,8 +112,8 @@ RSpec.describe 'Shops' do create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } - let!(:p1) { create(:simple_product, supplier: producer) } - let!(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } + let!(:p1) { create(:simple_product, supplier_id: producer.id) } + let!(:p2) { create(:simple_product, supplier_id: create(:supplier_enterprise).id) } let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } let(:ex_d2) { order_cycle.exchanges.outgoing.where(receiver_id: d2).first } @@ -184,7 +184,7 @@ RSpec.describe 'Shops' do variants: [product.variants.first] ) } - let(:product) { create(:simple_product, supplier: producer) } + let(:product) { create(:simple_product, supplier_id: producer.id) } before do product.set_property 'Local', 'XYZ 123' @@ -207,7 +207,7 @@ RSpec.describe 'Shops' do end describe "hub producer modal" do - let!(:product) { create(:simple_product, supplier: producer, primary_taxon: taxon) } + let!(:product) { create(:simple_product, supplier_id: producer.id, primary_taxon: taxon) } let!(:taxon) { create(:taxon, name: 'Fruit') } let!(:order_cycle) { create( From 8244fa7685e3cd2bbbbaabb328695328c04979a7 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 15:01:17 +1000 Subject: [PATCH 111/145] Fix enterprise shopfront serializer spec --- spec/serializers/api/enterprise_shopfront_serializer_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/serializers/api/enterprise_shopfront_serializer_spec.rb b/spec/serializers/api/enterprise_shopfront_serializer_spec.rb index 766995c793..3f0dee41da 100644 --- a/spec/serializers/api/enterprise_shopfront_serializer_spec.rb +++ b/spec/serializers/api/enterprise_shopfront_serializer_spec.rb @@ -12,10 +12,10 @@ RSpec.describe Api::EnterpriseShopfrontSerializer do let!(:taxon1) { create(:taxon, name: 'Meat') } let!(:taxon2) { create(:taxon, name: 'Veg') } let!(:product) { - create(:product, supplier: producer, primary_taxon: taxon1 ) + create(:product, supplier_id: producer.id, primary_taxon: taxon1 ) } let!(:product2) { - create(:product, supplier: producer_hidden, primary_taxon: taxon2 ) + create(:product, supplier_id: producer_hidden.id, primary_taxon: taxon2 ) } let(:close_time) { 2.days.from_now } From 7b6b365c4f749aa9632e589ca6c703028495fd11 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 15:38:30 +1000 Subject: [PATCH 112/145] Fix subscription form spec --- .../order_management/subscriptions/form_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb index c915ff0e99..1533f82df8 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb @@ -8,18 +8,18 @@ module OrderManagement describe "creating a new subscription" do let!(:shop) { create(:distributor_enterprise) } let!(:customer) { create(:customer, enterprise: shop) } - let!(:product1) { create(:product, supplier: shop) } - let!(:product2) { create(:product, supplier: shop) } - let!(:product3) { create(:product, supplier: shop) } + let!(:product1) { create(:product) } + let!(:product2) { create(:product) } + let!(:product3) { create(:product) } let!(:variant1) { - create(:variant, product: product1, unit_value: '100', price: 12.00) + create(:variant, product: product1, unit_value: '100', price: 12.00, supplier: shop) } let!(:variant2) { - create(:variant, product: product2, unit_value: '1000', price: 6.00) + create(:variant, product: product2, unit_value: '1000', price: 6.00, supplier: shop) } let!(:variant3) { create(:variant, product: product2, unit_value: '1000', - price: 2.50, on_hand: 1) + price: 2.50, on_hand: 1, supplier: shop) } let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } let!(:order_cycle1) { From 34aba72dea31716799b0a9ab5db30f259ec07ea4 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 15:45:32 +1000 Subject: [PATCH 113/145] Fix order summary mailer view --- app/views/spree/order_mailer/_order_summary.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/spree/order_mailer/_order_summary.html.haml b/app/views/spree/order_mailer/_order_summary.html.haml index 55e0e67cc3..1c3b4c7480 100644 --- a/app/views/spree/order_mailer/_order_summary.html.haml +++ b/app/views/spree/order_mailer/_order_summary.html.haml @@ -20,7 +20,7 @@ = render 'spree/shared/line_item_name', line_item: item %br %small - %em= item.variant.product.supplier.name + %em= item.variant.supplier.name %td - if item.variant.sku.blank? \- From b5cf47d306b27a2f371568ffdf9f8805f46f9d56 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 20:23:56 +1000 Subject: [PATCH 114/145] Fix producer mailer --- app/mailers/producer_mailer.rb | 11 ++++++----- .../producer_mailer/order_cycle_report.html.haml | 2 +- .../producer_mailer/order_cycle_report.text.haml | 2 +- spec/mailers/producer_mailer_spec.rb | 13 +++++++------ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/mailers/producer_mailer.rb b/app/mailers/producer_mailer.rb index 4752141c42..99c5f0f4f5 100644 --- a/app/mailers/producer_mailer.rb +++ b/app/mailers/producer_mailer.rb @@ -60,11 +60,12 @@ class ProducerMailer < ApplicationMailer def line_items_from(order_cycle, producer) @line_items ||= Spree::LineItem. - includes(variant: [:product]). + includes(variant: :product). + joins(variant: :product). from_order_cycle(order_cycle). - sorted_by_name_and_unit_value. - merge(Spree::Product.with_deleted.in_supplier(producer)). - merge(Spree::Order.by_state(["complete", "resumed"])) + merge(Spree::Variant.with_deleted.where(supplier: producer)). + merge(Spree::Order.by_state(["complete", "resumed"])). + sorted_by_name_and_unit_value end def total_from_line_items(line_items) @@ -81,7 +82,7 @@ class ProducerMailer < ApplicationMailer line_items.map do |line_item| { sku: line_item.variant.sku, - supplier_name: line_item.product.supplier.name, + supplier_name: line_item.variant.supplier.name, product_and_full_name: line_item.product_and_full_name, quantity: line_item.quantity, first_name: line_item.order.billing_address.first_name, diff --git a/app/views/producer_mailer/order_cycle_report.html.haml b/app/views/producer_mailer/order_cycle_report.html.haml index c44742a4b1..4b85b9ce44 100644 --- a/app/views/producer_mailer/order_cycle_report.html.haml +++ b/app/views/producer_mailer/order_cycle_report.html.haml @@ -40,7 +40,7 @@ = line_items.first.variant.sku - if @distributors_pickup_times.many? %td - = line_items.first.product.supplier.name + = line_items.first.variant.supplier.name %td = product_and_full_name %td.text-right diff --git a/app/views/producer_mailer/order_cycle_report.text.haml b/app/views/producer_mailer/order_cycle_report.text.haml index 2cfc55cd76..adf77e8eb8 100644 --- a/app/views/producer_mailer/order_cycle_report.text.haml +++ b/app/views/producer_mailer/order_cycle_report.text.haml @@ -15,7 +15,7 @@ Orders summary = t :producer_mail_order_text \ - @grouped_line_items.each_pair do |product_and_full_name, line_items| - #{line_items.first.variant.sku} - #{raw(line_items.first.product.supplier.name)} - #{raw(product_and_full_name)} (QTY: #{line_items.sum(&:quantity)}) @ #{line_items.first.single_money} = #{Spree::Money.new(line_items.sum(&:total), currency: line_items.first.currency)} + #{line_items.first.variant.sku} - #{raw(line_items.first.variant.supplier.name)} - #{raw(product_and_full_name)} (QTY: #{line_items.sum(&:quantity)}) @ #{line_items.first.single_money} = #{Spree::Money.new(line_items.sum(&:total), currency: line_items.first.currency)} \ \ #{t :total}: #{@total} diff --git a/spec/mailers/producer_mailer_spec.rb b/spec/mailers/producer_mailer_spec.rb index b4e1be284a..fe1bbe2d8b 100644 --- a/spec/mailers/producer_mailer_spec.rb +++ b/spec/mailers/producer_mailer_spec.rb @@ -16,13 +16,14 @@ RSpec.describe ProducerMailer, type: :mailer do let(:d1) { create(:distributor_enterprise, charges_sales_tax: true) } let(:d2) { create(:distributor_enterprise) } let(:p1) { - create(:product, name: "Zebra", price: 12.34, supplier: s1, tax_category_id: tax_category.id) + create(:product, name: "Zebra", price: 12.34, supplier_id: s1.id, + tax_category_id: tax_category.id) } - let(:p2) { create(:product, name: "Aardvark", price: 23.45, supplier: s2) } - let(:p3) { create(:product, name: "Banana", price: 34.56, supplier: s1) } - let(:p4) { create(:product, name: "coffee", price: 45.67, supplier: s1) } - let(:p5) { create(:product, name: "Daffodil", price: 56.78, supplier: s1) } - let(:p6) { create(:product, name: "Eggs", price: 67.89, supplier: s1) } + let(:p2) { create(:product, name: "Aardvark", price: 23.45, supplier_id: s2.id) } + let(:p3) { create(:product, name: "Banana", price: 34.56, supplier_id: s1.id) } + let(:p4) { create(:product, name: "coffee", price: 45.67, supplier_id: s1.id) } + let(:p5) { create(:product, name: "Daffodil", price: 56.78, supplier_id: s1.id) } + let(:p6) { create(:product, name: "Eggs", price: 67.89, supplier_id: s1.id) } let(:order_cycle) { create(:simple_order_cycle) } let!(:incoming_exchange) { order_cycle.exchanges.create! sender: s1, receiver: d1, incoming: true, From 1c6d10d4e78dabf28d1dfa2288d70af95da09a2f Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 20:31:54 +1000 Subject: [PATCH 115/145] Remove supplier_id from simple product serializer --- app/serializers/api/admin/product_simple_serializer.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/serializers/api/admin/product_simple_serializer.rb b/app/serializers/api/admin/product_simple_serializer.rb index 6b968ab8d3..07f66294b6 100644 --- a/app/serializers/api/admin/product_simple_serializer.rb +++ b/app/serializers/api/admin/product_simple_serializer.rb @@ -3,13 +3,9 @@ module Api module Admin class ProductSimpleSerializer < ActiveModel::Serializer - attributes :id, :name, :producer_id + attributes :id, :name has_many :variants, key: :variants, serializer: Api::Admin::VariantSimpleSerializer - - def producer_id - object.supplier_id - end end end end From 564ea0bd4923ffd0d41c6f9dfe945a4a788916ad Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 22:07:22 +1000 Subject: [PATCH 116/145] Fix enterprise touching when associated record updated --- app/models/spree/product.rb | 2 ++ app/models/spree/property.rb | 8 ++++++++ spec/models/enterprise_caching_spec.rb | 9 ++++----- spec/models/spree/product_spec.rb | 27 +++++++++++++++++++------- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 8cb1cfa041..56e6150621 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -329,6 +329,8 @@ module Spree end def touch_supplier + return if variants.empty? + # Assume the product supplier is the supplier of the first variant # Will breack if product has mutiple variants with different supplier variants.first.supplier.touch diff --git a/app/models/spree/property.rb b/app/models/spree/property.rb index 9f45270a78..0aae0d04dd 100644 --- a/app/models/spree/property.rb +++ b/app/models/spree/property.rb @@ -6,6 +6,8 @@ module Spree has_many :products, through: :product_properties has_many :producer_properties, dependent: :destroy + after_touch :touch_producer_properties + validates :name, :presentation, presence: true scope :sorted, -> { order(:name) } @@ -13,5 +15,11 @@ module Spree def property self end + + private + + def touch_producer_properties + producer_properties.each(&:touch) + end end end diff --git a/spec/models/enterprise_caching_spec.rb b/spec/models/enterprise_caching_spec.rb index 625d92ca9d..d2c8321690 100644 --- a/spec/models/enterprise_caching_spec.rb +++ b/spec/models/enterprise_caching_spec.rb @@ -11,15 +11,14 @@ RSpec.describe Enterprise do let(:supplier2) { create(:supplier_enterprise) } describe "with a supplied product" do - let(:product) { create(:simple_product, primary_taxon_id: taxon.id) } + let(:product) { + create(:simple_product, primary_taxon_id: taxon.id, supplier_id: enterprise.id) + } let(:property) { product.product_properties.last } let(:producer_property) { enterprise.producer_properties.last } - let(:variant) { create(:variant, product:, supplier: enterprise) } + let(:variant) { product.variants.first } before do - product.variants = [] - product.variants << variant - product.set_property 'Organic', 'NASAA 12345' enterprise.set_producer_property 'Biodynamic', 'ASDF 4321' end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index b9dce1b3b1..1106ecd92c 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -283,7 +283,6 @@ module Spree let(:product) { create(:simple_product) } describe "touching affected enterprises when the product is deleted" do - let(:product) { create(:simple_product) } let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise) } let!(:oc) { @@ -308,19 +307,33 @@ module Spree end describe "after updating primary taxon" do - let(:product) { create(:simple_product) } + let(:product) { create(:simple_product, supplier_id: supplier.id) } let(:supplier) { create(:supplier_enterprise) } let(:new_taxon) { create(:taxon) } - before do - product.variants = [] - product.variants << create(:variant, product:, supplier:) - end - it "touches the supplier" do expect { product.update(primary_taxon_id: new_taxon.id) } .to change { supplier.reload.updated_at } end + + context "when product has no variant" do + it "doesn't blow up" do + product.variants = [] + product.save! + + expect { product.update(primary_taxon_id: new_taxon.id) }.to_not raise_error + end + end + end + + describe "after touching the product" do + let(:product) { create(:simple_product, supplier_id: supplier.id) } + let(:supplier) { create(:supplier_enterprise) } + + it "touches the supplier" do + expect { product.touch } + .to change { supplier.reload.updated_at } + end end it "updates units when saved change to variant unit" do From dd8f0aafabd6b9e1528ea76ccd2e1fc02f5d9aa5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 22 May 2024 22:09:22 +1000 Subject: [PATCH 117/145] Fix ProductImport::EntryProcessor#count_existing_items Plus spec --- app/models/product_import/entry_processor.rb | 5 +- .../product_import/entry_processor_spec.rb | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/models/product_import/entry_processor.rb b/app/models/product_import/entry_processor.rb index 4c585a4b32..8ce73489a9 100644 --- a/app/models/product_import/entry_processor.rb +++ b/app/models/product_import/entry_processor.rb @@ -54,10 +54,7 @@ module ProductImport if settings.importing_into_inventory? VariantOverride.for_hubs([enterprise_id]).count else - Spree::Variant. - joins(:product). - where(spree_products: { supplier_id: enterprise_id }). - count + Spree::Variant.where(supplier_id: enterprise_id).count end @enterprise_products[enterprise_id] = products_count diff --git a/spec/models/product_import/entry_processor_spec.rb b/spec/models/product_import/entry_processor_spec.rb index 1306080ef8..13022d2207 100644 --- a/spec/models/product_import/entry_processor_spec.rb +++ b/spec/models/product_import/entry_processor_spec.rb @@ -150,4 +150,50 @@ RSpec.describe ProductImport::EntryProcessor do end end end + + describe "#count_existing_items" do + let(:settings) { instance_double(ProductImport::Settings, importing_into_inventory?: false) } + let(:editable_enterprises) do + { + "#{supplier1.name}": supplier1.id, + "#{supplier2.name}": supplier2.id + } + end + let(:supplier1) { create(:supplier_enterprise) } + let(:supplier2) { create(:supplier_enterprise) } + let!(:products) { create_list(:simple_product, 3, supplier_id: supplier1.id) } + + before do + allow(ProductImport::Settings).to receive(:new) { settings } + + enterprises = { + "#{supplier1.name}": { id: supplier1.id }, + "#{supplier2.name}": { id: supplier2.id } + } + allow(spreadsheet_data).to receive(:enterprises_index).and_return(enterprises) + + create_list(:simple_product, 2, supplier_id: supplier2.id) + end + + it "returns the total of existing variants for the given enterprises" do + entry_processor.count_existing_items + + expect(entry_processor.total_enterprise_products).to eq(5) + end + + context "when importing into inventory" do + let(:settings) { instance_double(ProductImport::Settings, importing_into_inventory?: true) } + + it "returns the total of existing variant override for the given enterprises" do + products.each do |p| + variant = p.variants.first + create(:variant_override, variant:, hub: variant.supplier) + end + + entry_processor.count_existing_items + + expect(entry_processor.total_enterprise_products).to eq(3) + end + end + end end From 2d707e8acbe39686409b4cb8302dbe8ac666770b Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Sun, 26 May 2024 13:45:29 +1000 Subject: [PATCH 118/145] Fix consumer producer system spec --- spec/system/consumer/producers_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/system/consumer/producers_spec.rb b/spec/system/consumer/producers_spec.rb index 48832fbd62..5796810156 100644 --- a/spec/system/consumer/producers_spec.rb +++ b/spec/system/consumer/producers_spec.rb @@ -19,10 +19,10 @@ RSpec.describe ' let(:taxon_veg) { create(:taxon, name: 'Vegetables') } let!(:product1) { - create(:simple_product, supplier: producer1, primary_taxon: taxon_fruit) + create(:simple_product, supplier_id: producer1.id, primary_taxon: taxon_fruit) } let!(:product2) { - create(:simple_product, supplier: producer2, primary_taxon: taxon_veg) + create(:simple_product, supplier_id: producer2.id, primary_taxon: taxon_veg) } let(:shop) { create(:distributor_enterprise) } From 3dc7c2bf56c38767c1f98fcf06fecfaad271b7cc Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Sun, 26 May 2024 14:16:38 +1000 Subject: [PATCH 119/145] Fix spree product touch supplier Take into account import product scenario, in this case the variant doesn't have an assigned supplier yet. --- app/models/spree/product.rb | 8 +++++++- spec/models/spree/product_spec.rb | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 56e6150621..5c7d55e1bd 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -77,6 +77,7 @@ module Spree after_update :touch_supplier, if: :saved_change_to_primary_taxon_id? around_destroy :destruction after_save :update_units + after_touch :touch_supplier # -- Scopes scope :with_properties, ->(*property_ids) { @@ -333,7 +334,12 @@ module Spree # Assume the product supplier is the supplier of the first variant # Will breack if product has mutiple variants with different supplier - variants.first.supplier.touch + first_variant = variants.first + + # The variant is invalid if no supplier is present, but this method can be triggered when + # importing product. In this scenario the variant has not been updated with the supplier yet + # hence the check. + first_variant.supplier.touch if first_variant.supplier.present? end def touch_distributors diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 1106ecd92c..fbe396b709 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -334,6 +334,14 @@ module Spree expect { product.touch } .to change { supplier.reload.updated_at } end + + context "when the first variant is missing supplier" do + it "doesn't blow up" do + product.variants.first.update_attribute(:supplier_id, nil) + + expect { product.touch }.to_not raise_error + end + end end it "updates units when saved change to variant unit" do From feb7e173b19f68434bbd75a214112c91c9ca28b0 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 27 May 2024 15:11:37 +1000 Subject: [PATCH 120/145] Fix order cycle controller spec, product properties filtering And fix the underlying product renderer --- .../api/v0/order_cycles_controller.rb | 5 +-- app/services/products_renderer.rb | 3 +- .../api/v0/order_cycles_controller_spec.rb | 21 ++++++++----- spec/services/products_renderer_spec.rb | 31 ++++++++++++++----- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/v0/order_cycles_controller.rb b/app/controllers/api/v0/order_cycles_controller.rb index 7bb56ecc56..1f195b490a 100644 --- a/app/controllers/api/v0/order_cycles_controller.rb +++ b/app/controllers/api/v0/order_cycles_controller.rb @@ -86,8 +86,9 @@ module Api end def distributed_products - OrderCycles::DistributedProductsService.new(distributor, order_cycle, - customer).products_relation + OrderCycles::DistributedProductsService.new( + distributor, order_cycle, customer + ).products_supplier_relation.pluck(:id) end end end diff --git a/app/services/products_renderer.rb b/app/services/products_renderer.rb index 4825d4aa71..2ad240d0c9 100644 --- a/app/services/products_renderer.rb +++ b/app/services/products_renderer.rb @@ -73,7 +73,8 @@ class ProductsRenderer results = query.joins('JOIN enterprises ON enterprises.id = first_variant.supplier_id LEFT OUTER JOIN producer_properties ON producer_properties.producer_id = enterprises.id'). - where(producer_properties: { property_id: property_ids }) + where(producer_properties: { property_id: property_ids }). + where(inherits_properties: true) return results end diff --git a/spec/controllers/api/v0/order_cycles_controller_spec.rb b/spec/controllers/api/v0/order_cycles_controller_spec.rb index eb578e56f4..e3cbe2503d 100644 --- a/spec/controllers/api/v0/order_cycles_controller_spec.rb +++ b/spec/controllers/api/v0/order_cycles_controller_spec.rb @@ -107,14 +107,15 @@ module Api let!(:supplier) { create(:supplier_enterprise, properties: [supplier_property]) } before do - product1.update!(supplier:) - product2.update!(supplier:) - product3.update!(supplier:, inherits_properties: false) + product1.variants.first.update!(supplier:) + product2.variants.first.update!(supplier:) + product3.update!(inherits_properties: false) + product3.variants.first.update!(supplier:) end it "filter out the product that don't inherits from supplier properties" do api_get :products, id: order_cycle.id, distributor: distributor.id, - q: { with_properties: [supplier_property.id] } + q: { with_variants_supplier_properties: [supplier_property.id] } expect(response.status).to eq 200 expect(product_ids).to match_array [product1.id, product2.id] @@ -263,16 +264,20 @@ module Api context "with custom taxon ordering applied and duplicate product names in the order cycle" do let!(:supplier) { create(:supplier_enterprise) } let!(:product5) { - create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier_id: supplier.id) + create(:product, name: "Duplicate name", primary_taxon_id: taxon3.id, + supplier_id: supplier.id) } let!(:product6) { - create(:product, name: "Duplicate name", primary_taxon: taxon3, supplier_id: supplier.id) + create(:product, name: "Duplicate name", primary_taxon_id: taxon3.id, + supplier_id: supplier.id) } let!(:product7) { - create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier_id: supplier.id) + create(:product, name: "Duplicate name", primary_taxon_id: taxon2.id, + supplier_id: supplier.id) } let!(:product8) { - create(:product, name: "Duplicate name", primary_taxon: taxon2, supplier_id: supplier.id) + create(:product, name: "Duplicate name", primary_taxon_id: taxon2.id, + supplier_id: supplier.id) } before do diff --git a/spec/services/products_renderer_spec.rb b/spec/services/products_renderer_spec.rb index 1a5291082d..218f8fb944 100644 --- a/spec/services/products_renderer_spec.rb +++ b/spec/services/products_renderer_spec.rb @@ -15,21 +15,24 @@ RSpec.describe ProductsRenderer do let(:fruits_supplier) { create(:supplier_enterprise) } let(:cakes_supplier) { create(:supplier_enterprise) } let!(:product_apples) { - create(:product, name: "apples", primary_taxon_id: fruits.id, supplier_id: fruits_supplier.id) + create(:product, name: "apples", primary_taxon_id: fruits.id, + supplier_id: fruits_supplier.id, inherits_properties: true) } let!(:product_banana_bread) { - create(:product, name: "banana bread", variants: [ - create(:variant, supplier: cakes_supplier, primary_taxon: cakes), - create(:variant, supplier: fruits_supplier, primary_taxon: cakes) - ]) + create(:product, name: "banana bread", inherits_properties: true, + variants: [ + create(:variant, supplier: cakes_supplier, primary_taxon: cakes), + create(:variant, supplier: fruits_supplier, primary_taxon: cakes) + ] + ) } let!(:product_cherries) { create(:product, name: "cherries", primary_taxon_id: fruits.id, - supplier_id: fruits_supplier.id) + supplier_id: fruits_supplier.id, inherits_properties: true) } let!(:product_doughnuts) { create(:product, name: "doughnuts", primary_taxon_id: cakes.id, - supplier_id: cakes_supplier.id) + supplier_id: cakes_supplier.id, inherits_properties: true) } before do @@ -112,6 +115,20 @@ RSpec.describe ProductsRenderer do expect(products).to eq([product_apples, product_cherries]) end + it "filters out products with inherits_properties set to false" do + product_cherries.update!(inherits_properties: false) + product_banana_bread.update!(inherits_properties: false) + + fruits_supplier.producer_properties.create!({ property_id: property_organic.id, + value: '1', position: 1 }) + + search_param = { q: { "with_variants_supplier_properties" => [property_organic.id] } } + products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, search_param) + + products = products_renderer.send(:products) + expect(products).to eq([product_apples]) + end + it "filters products with property when sorting is enabled" do allow(distributor).to receive(:preferred_shopfront_taxon_order) { "#{fruits.id},#{cakes.id}" From 3704b18952a768ff7fc6093e46160ecb50e59c48 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 27 May 2024 15:46:55 +1000 Subject: [PATCH 121/145] Fix property filtering in shopping system spec --- .../darkswarm/controllers/products_controller.js.coffee | 2 +- spec/system/consumer/shopping/products_spec.rb | 6 +++--- spec/system/consumer/shopping/shopping_spec.rb | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee index 930091bec5..59da50958b 100644 --- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee @@ -67,7 +67,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ page: page || $scope.page, per_page: $scope.per_page, 'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_variants_supplier_name_cont]': $scope.query, - 'q[with_properties][]': $scope.activeProperties, + 'q[with_variants_supplier_properties][]': $scope.activeProperties, 'q[variants_primary_taxon_id_in_any][]': $scope.activeTaxons } diff --git a/spec/system/consumer/shopping/products_spec.rb b/spec/system/consumer/shopping/products_spec.rb index 81a21613be..f2ff5b0d5a 100644 --- a/spec/system/consumer/shopping/products_spec.rb +++ b/spec/system/consumer/shopping/products_spec.rb @@ -25,11 +25,11 @@ RSpec.describe "As a consumer I want to view products" do orders_close_at: 2.days.from_now) } let(:product) { - create(:simple_product, supplier:, primary_taxon: taxon, properties: [property], - name: "Beans") + create(:simple_product, supplier_id: supplier.id, primary_taxon: taxon, + properties: [property], name: "Beans") } let(:product2) { - create(:product, supplier:, primary_taxon: taxon2, properties: [property2], + create(:product, supplier_id: supplier.id, primary_taxon: taxon2, properties: [property2], name: "Chickpeas") } let(:variant) { product.variants.first } diff --git a/spec/system/consumer/shopping/shopping_spec.rb b/spec/system/consumer/shopping/shopping_spec.rb index ee988330aa..fcbdbfc890 100644 --- a/spec/system/consumer/shopping/shopping_spec.rb +++ b/spec/system/consumer/shopping/shopping_spec.rb @@ -392,7 +392,6 @@ RSpec.describe "As a consumer I want to shop with a distributor" do create(:simple_product, supplier_id: supplier.id, inherits_properties: false) } - # TODO properties before do add_variant_to_order_cycle(exchange, product3.variants.first) property = create(:property, presentation: 'certified') From a52401107ab03b1daa0adc1bfa65fa614a51bcf5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 28 May 2024 12:07:21 +1000 Subject: [PATCH 122/145] Order cycle API, separate properties and producer_properties Due to moving the supplier to the variant, we had to add manual search for producer properties instead of using ransack. So we need a way for the frontend to diferenciate between product properties and producer properties. This is the first step towards that --- .../api/v0/order_cycles_controller.rb | 16 ++++++++--- config/routes/api.rb | 1 + .../api/v0/order_cycles_controller_spec.rb | 27 +++++++++---------- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/app/controllers/api/v0/order_cycles_controller.rb b/app/controllers/api/v0/order_cycles_controller.rb index 1f195b490a..ccf6a24dd6 100644 --- a/app/controllers/api/v0/order_cycles_controller.rb +++ b/app/controllers/api/v0/order_cycles_controller.rb @@ -7,9 +7,11 @@ module Api include ApiActionCaching skip_authorization_check - skip_before_action :authenticate_user, :ensure_api_key, only: [:taxons, :properties] + skip_before_action :authenticate_user, :ensure_api_key, only: [ + :taxons, :properties, :producer_properties + ] - caches_action :taxons, :properties, + caches_action :taxons, :properties, :producer_properties, expires_in: CacheService::FILTERS_EXPIRY, cache_path: proc { |controller| controller.request.url } @@ -41,7 +43,13 @@ module Api def properties render plain: ActiveModel::ArraySerializer.new( - product_properties | producer_properties, each_serializer: Api::PropertySerializer + product_properties, each_serializer: Api::PropertySerializer + ).to_json + end + + def producer_properties + render plain: ActiveModel::ArraySerializer.new( + load_producer_properties, each_serializer: Api::PropertySerializer ).to_json end @@ -58,7 +66,7 @@ module Api select('DISTINCT spree_properties.*') end - def producer_properties + def load_producer_properties producers = Enterprise. joins(:supplied_products). where(spree_products: { id: distributed_products }) diff --git a/config/routes/api.rb b/config/routes/api.rb index a661c6f359..74f2ad3652 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -60,6 +60,7 @@ Openfoodnetwork::Application.routes.draw do get :products, on: :member get :taxons, on: :member get :properties, on: :member + get :producer_properties, on: :member end resources :exchanges, only: [:show], to: 'exchange_products#index' do diff --git a/spec/controllers/api/v0/order_cycles_controller_spec.rb b/spec/controllers/api/v0/order_cycles_controller_spec.rb index e3cbe2503d..225b6f22be 100644 --- a/spec/controllers/api/v0/order_cycles_controller_spec.rb +++ b/spec/controllers/api/v0/order_cycles_controller_spec.rb @@ -239,25 +239,24 @@ module Api expect(json_response.length).to be 2 expect(properties).to include property1.presentation, property2.presentation end + end - context "with producer properties" do - let!(:property4) { create(:property) } - let!(:supplier) { create(:supplier_enterprise) } - let!(:producer_property) { - create(:producer_property, producer_id: supplier.id, property: property4) - } + describe "#producer_properties" do + let!(:property4) { create(:property) } + let!(:supplier) { create(:supplier_enterprise) } + let!(:producer_property) { + create(:producer_property, producer_id: supplier.id, property: property4) + } - before { product1.variants.first.update(supplier: ) } + before { product1.variants.first.update(supplier: ) } - it "loads producer properties for distributed products in the order cycle" do - api_get :properties, id: order_cycle.id, distributor: distributor.id + it "loads producer properties for distributed products in the order cycle" do + api_get :producer_properties, id: order_cycle.id, distributor: distributor.id - properties = json_response.pluck(:name) + properties = json_response.pluck(:name) - expect(json_response.length).to be 3 - expect(properties).to include property1.presentation, property2.presentation, - producer_property.property.presentation - end + expect(json_response.length).to be 1 + expect(properties).to include producer_property.property.presentation end end From 9632f42a40d5a1c14713664bf77cd504ff853114 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 28 May 2024 15:35:35 +1000 Subject: [PATCH 123/145] Fix producer property filtering --- .../controllers/products_controller.js.coffee | 22 +++++++++++++++++-- .../services/order_cycle_resource.js.coffee | 7 ++++++ .../products/_applied_filters_feedback.haml | 8 ++++--- app/views/shop/products/_filters.html.haml | 4 ++++ app/views/shop/products/_search_feedback.haml | 2 +- 5 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee index 59da50958b..96f40509df 100644 --- a/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products_controller.js.coffee @@ -4,15 +4,18 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ $scope.query = "" $scope.taxonSelectors = FilterSelectorsService.createSelectors() $scope.propertySelectors = FilterSelectorsService.createSelectors() + $scope.producerPropertySelectors = FilterSelectorsService.createSelectors() $scope.filtersActive = true $scope.page = 1 $scope.per_page = 10 $scope.order_cycle = OrderCycle.order_cycle $scope.supplied_taxons = null $scope.supplied_properties = null + $scope.supplied_producer_properties = null $scope.showFilterSidebar = false $scope.activeTaxons = [] $scope.activeProperties = [] + $scope.activeProducerProperties = [] # Update filters after initial load of shop tab $timeout => @@ -45,6 +48,12 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ $scope.supplied_properties[property.id] = Properties.properties_by_id[property.id] ) + OrderCycleResource.producerProperties params, (data)=> + $scope.supplied_producer_properties = {} + data.map( (property) -> + $scope.supplied_producer_properties[property.id] = Properties.properties_by_id[property.id] + ) + $scope.loadMore = -> if ($scope.page * $scope.per_page) <= Products.products.length $scope.loadMoreProducts() @@ -52,6 +61,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ $scope.$watch 'query', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue $scope.$watchCollection 'activeTaxons', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue $scope.$watchCollection 'activeProperties', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue + $scope.$watchCollection 'activeProducerProperties', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue $scope.loadProducts = -> $scope.page = 1 @@ -67,7 +77,8 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ page: page || $scope.page, per_page: $scope.per_page, 'q[name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_variants_supplier_name_cont]': $scope.query, - 'q[with_variants_supplier_properties][]': $scope.activeProperties, + 'q[with_properties][]': $scope.activeProperties, + 'q[with_variants_supplier_properties][]': $scope.activeProducerProperties, 'q[variants_primary_taxon_id_in_any][]': $scope.activeTaxons } @@ -86,6 +97,12 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ Properties.properties_by_id[property_id].name ).join($scope.filtersJoinWord()) if $scope.activeProperties? + $scope.appliedProducerPropertiesList = -> + $scope.activeProducerProperties.map( (property_id) -> + Properties.properties_by_id[property_id].name + ).join($scope.filtersJoinWord()) if $scope.activeProducerProperties? + + $scope.filtersJoinWord = -> $sce.trustAsHtml(" #{t('products_or')} ") @@ -99,6 +116,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ $scope.clearFilters = -> $scope.taxonSelectors.clearAll() $scope.propertySelectors.clearAll() + $scope.producerPropertySelectors.clearAll() $scope.refreshStaleData = -> # If the products template has already been loaded but the controller is being initialized @@ -109,7 +127,7 @@ angular.module('Darkswarm').controller "ProductsCtrl", ($scope, $sce, $filter, $ $scope.loadProducts() $scope.filtersCount = () -> - $scope.taxonSelectors.totalActive() + $scope.propertySelectors.totalActive() + $scope.taxonSelectors.totalActive() + $scope.propertySelectors.totalActive() + $scope.producerPropertySelectors.totalActive() $scope.toggleFilterSidebar = -> $scope.showFilterSidebar = !$scope.showFilterSidebar diff --git a/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee b/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee index 092ea51345..5eb3e7b420 100644 --- a/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee +++ b/app/assets/javascripts/darkswarm/services/order_cycle_resource.js.coffee @@ -18,4 +18,11 @@ angular.module('Darkswarm').factory 'OrderCycleResource', ($resource) -> url: '/api/v0/order_cycles/:id/properties.json' params: id: '@id' + 'producerProperties': + method: 'GET' + isArray: true + url: '/api/v0/order_cycles/:id/producer_properties.json' + params: + id: '@id' + }) diff --git a/app/views/shop/products/_applied_filters_feedback.haml b/app/views/shop/products/_applied_filters_feedback.haml index 2eb647b3b5..1d21075b38 100644 --- a/app/views/shop/products/_applied_filters_feedback.haml +++ b/app/views/shop/products/_applied_filters_feedback.haml @@ -1,10 +1,12 @@ = cache_with_locale do - %span{ "ng-show" => "query && ( appliedPropertiesList() || appliedTaxonsList() )" } + %span{ "ng-show" => "query && ( appliedPropertiesList() || appliedProducerPropertiesList() || appliedTaxonsList() )" } = t :products_filters_in - %span.applied-properties{'ng-bind-html' => 'appliedPropertiesList()'} + %span{ "ng-show" => "appliedPropertiesList() && appliedProducerPropertiesList()" } + = t :products_or + %span.applied-properties{'ng-bind-html' => 'appliedProducerPropertiesList()'} - %span{ "ng-show" => "appliedPropertiesList() && appliedTaxonsList()" } + %span{ "ng-show" => "(appliedPropertiesList() || appliedProducerPropertiesList()) && appliedTaxonsList()" } = t :products_and %span.applied-taxons{'ng-bind-html' => 'appliedTaxonsList()'} diff --git a/app/views/shop/products/_filters.html.haml b/app/views/shop/products/_filters.html.haml index 8a929af886..c9f5455e95 100644 --- a/app/views/shop/products/_filters.html.haml +++ b/app/views/shop/products/_filters.html.haml @@ -4,3 +4,7 @@ .filter-shopfront.property-selectors{ "ng-show": 'supplied_properties != null' } %filter-selector{ 'selector-set' => "propertySelectors", objects: "supplied_properties", "active-selectors" => "activeProperties"} + + .filter-shopfront.property-selectors{ng: {show: 'supplied_producer_properties != null'}} + %filter-selector{ 'selector-set' => "producerPropertySelectors", objects: "supplied_producer_properties", "active-selectors" => "activeProducerProperties"} + diff --git a/app/views/shop/products/_search_feedback.haml b/app/views/shop/products/_search_feedback.haml index eb71015376..d0511135d8 100644 --- a/app/views/shop/products/_search_feedback.haml +++ b/app/views/shop/products/_search_feedback.haml @@ -1,5 +1,5 @@ = cache_with_locale do - .row.animate-slide{ "ng-show" => "query || appliedPropertiesList() || appliedTaxonsList()" } + .row.animate-slide{ "ng-show" => "query || appliedPropertiesList() || appliedProducerPropertiesList() || appliedTaxonsList()" } .small-12.columns .alert-box.search-alert.ng-scope %div{"ng-show" => "Products.products.length > 0"} From 84197aca195d3c28852417cebdde847761c566e5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 29 May 2024 16:08:32 +1000 Subject: [PATCH 124/145] Fix the filtering by properties/supplier properties - Apply OR when filtering by both product properties and supplier properties - Apply AND when filtering by supplier properties and taxon Filtering by product properties and taxon is handled by ransack, so no change there --- .../distributed_products_service.rb | 7 ++++ app/services/products_renderer.rb | 39 +++++++++++++----- config/initializers/pagy.rb | 1 + spec/services/products_renderer_spec.rb | 40 +++++++++++++++++++ 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/app/services/order_cycles/distributed_products_service.rb b/app/services/order_cycles/distributed_products_service.rb index 6bdde387c8..5f349dae37 100644 --- a/app/services/order_cycles/distributed_products_service.rb +++ b/app/services/order_cycles/distributed_products_service.rb @@ -43,6 +43,13 @@ module OrderCycles group("spree_products.id, first_variant.supplier_id") end + def supplier_property_join(query) + query.joins(" + JOIN enterprises ON enterprises.id = first_variant.supplier_id + LEFT OUTER JOIN producer_properties ON producer_properties.producer_id = enterprises.id + ") + end + def variants_relation order_cycle. variants_distributed_by(distributor). diff --git a/app/services/products_renderer.rb b/app/services/products_renderer.rb index 2ad240d0c9..bebdadf812 100644 --- a/app/services/products_renderer.rb +++ b/app/services/products_renderer.rb @@ -64,26 +64,43 @@ class ProductsRenderer end def filter(query) - property_ids = args[:q]&.dig("with_variants_supplier_properties") + supplier_properties = args[:q]&.slice("with_variants_supplier_properties") - if property_ids.present? + ransack_results = query.ransack(args[:q]).result.to_a + + return ransack_results if supplier_properties.blank? + + with_properties = args[:q]&.dig("with_properties") + supplier_properties_results = [] + + if supplier_properties.present? # We can't search on an association's scope with ransack, a work around is to define # the a scope on the parent (Spree::Product) but because we are joining on "first_variant" - # it doesn't work, so we do the filtering manually here - results = query.joins('JOIN enterprises ON enterprises.id = first_variant.supplier_id - LEFT OUTER JOIN producer_properties - ON producer_properties.producer_id = enterprises.id'). - where(producer_properties: { property_id: property_ids }). + # to get the supplier it doesn't work, so we do the filtering manually here + # see: + # OrderCycleDistributedProducts#products_supplier_relation + # OrderCycleDistributedProducts#supplier_property_join + supplier_property_ids = supplier_properties["with_variants_supplier_properties"] + supplier_properties_results = distributed_products.supplier_property_join(query). + where(producer_properties: { property_id: supplier_property_ids }). where(inherits_properties: true) - - return results end - query.ransack(args[:q]).result + if supplier_properties_results.present? && with_properties.present? + # apply "OR" between property search + return ransack_results | supplier_properties_results + end + + # Intersect the result to apply "AND" with other search criteria + return ransack_results.intersection(supplier_properties_results) \ + unless supplier_properties_results.empty? + + # We should get here but just in case we return the ransack results + ransack_results end def paginate(results) - _pagy, paginated_results = pagy_arel( + _pagy, paginated_results = pagy_array( results, page: args[:page] || 1, items: args[:per_page] || DEFAULT_PER_PAGE diff --git a/config/initializers/pagy.rb b/config/initializers/pagy.rb index 572f8c3fd3..eab7d3a437 100644 --- a/config/initializers/pagy.rb +++ b/config/initializers/pagy.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'pagy/extras/arel' +require 'pagy/extras/array' require 'pagy/extras/items' require 'pagy/extras/overflow' diff --git a/spec/services/products_renderer_spec.rb b/spec/services/products_renderer_spec.rb index 218f8fb944..8ef148c9f0 100644 --- a/spec/services/products_renderer_spec.rb +++ b/spec/services/products_renderer_spec.rb @@ -115,6 +115,46 @@ RSpec.describe ProductsRenderer do expect(products).to eq([product_apples, product_cherries]) end + # TODO this is a bit flaky due to banana bread having two supplier + it "filters products with a product property or a producer property" do + cakes_supplier.producer_properties.create!({ property_id: property_organic.id, + value: '1', position: 1 }) + product_apples.product_properties.create!({ property_id: property_conventional.id, + value: '1', position: 1 }) + + search_param = { q: + { + "with_variants_supplier_properties" => [property_organic.id], + "with_properties" => [property_conventional.id] + } } + products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, search_param) + + products = products_renderer.send(:products) + expect(products).to eq([product_apples, product_banana_bread, product_doughnuts]) + end + + it "filters product with property and taxon set" do + stone_fruit = create(:taxon, name: "Stone fruit") + product_peach = + create(:product, name: "peach", primary_taxon_id: stone_fruit.id, + supplier_id: fruits_supplier.id, inherits_properties: true) + + fruits_supplier.producer_properties.create!({ property_id: property_organic.id, + value: '1', position: 1 }) + exchange.variants << product_peach.variants.first + + search_param = { q: + { + "with_variants_supplier_properties" => [property_organic.id], + "variants_primary_taxon_id_in_any" => [stone_fruit.id], + } } + + products_renderer = ProductsRenderer.new(distributor, order_cycle, customer, search_param) + + products = products_renderer.send(:products) + expect(products).to eq([product_peach]) + end + it "filters out products with inherits_properties set to false" do product_cherries.update!(inherits_properties: false) product_banana_bread.update!(inherits_properties: false) From b6faa43879190e600cc6de9a5f2694d15474ba1d Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 11 Jun 2024 12:21:02 +1000 Subject: [PATCH 125/145] Fix touching distributor callback spec The original spec check if the supplier and distributor where updated after deleting product. In reality, the supplier and the distributor are the same, so no need to test with the supplier --- spec/models/spree/product_spec.rb | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index fbe396b709..0a6e6267cf 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -283,19 +283,13 @@ module Spree let(:product) { create(:simple_product) } describe "touching affected enterprises when the product is deleted" do - let(:supplier) { create(:supplier_enterprise) } + let(:product) { create(:simple_product, supplier_id: distributor.id) } let(:distributor) { create(:distributor_enterprise) } + let(:supplier) { create(:supplier_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [distributor], variants: [product.variants.first]) } - before do - create(:variant, product:, supplier:) - end - - it "touches the supplier" do - expect { product.destroy }.to change { supplier.reload.updated_at } - end it "touches all distributors" do expect { product.destroy }.to change { distributor.reload.updated_at } @@ -321,7 +315,7 @@ module Spree product.variants = [] product.save! - expect { product.update(primary_taxon_id: new_taxon.id) }.to_not raise_error + expect { product.update(primary_taxon_id: new_taxon.id) }.not_to raise_error end end end @@ -339,7 +333,7 @@ module Spree it "doesn't blow up" do product.variants.first.update_attribute(:supplier_id, nil) - expect { product.touch }.to_not raise_error + expect { product.touch }.not_to raise_error end end end From 312c24096835307760b3b55f0a71760d0fdbfa74 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 11 Jun 2024 16:04:06 +1000 Subject: [PATCH 126/145] Fix mutilingual spec --- spec/system/consumer/multilingual_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/consumer/multilingual_spec.rb b/spec/system/consumer/multilingual_spec.rb index 7116c0c1de..16ec57b35c 100644 --- a/spec/system/consumer/multilingual_spec.rb +++ b/spec/system/consumer/multilingual_spec.rb @@ -104,7 +104,7 @@ RSpec.describe 'Multilingual' do let(:supplier) { create(:supplier_enterprise) } let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true) } let(:product) { - create(:taxed_product, supplier:, price: 10, zone:) + create(:taxed_product, supplier_id: supplier.id, price: 10, zone:) } let(:variant) { product.variants.first } let!(:order_cycle) { From 891f79666dd2ffdc34e108fdbba476acc2818c48 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Thu, 13 Jun 2024 14:50:47 +1000 Subject: [PATCH 127/145] Spree::Product remove in_supplier_or_distributor scope It is not used anywhere --- app/models/spree/product.rb | 12 ---------- spec/models/spree/product_spec.rb | 37 ------------------------------- 2 files changed, 49 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 5c7d55e1bd..a59f1240c0 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -140,18 +140,6 @@ module Spree distinct } - # Products supplied by a given enterprise or distributed via that enterprise through an OC - scope :in_supplier_or_distributor, lambda { |enterprise| - enterprise = enterprise.respond_to?(:id) ? enterprise.id : enterprise.to_i - - with_order_cycles_outer. - in_supplier(enterprise). - or( - where(o_exchanges: { incoming: false, receiver_id: enterprise }) - ). - select('distinct spree_products.*') - } - # Products distributed by the given order cycle scope :in_order_cycle, lambda { |order_cycle| with_order_cycles_inner. diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 0a6e6267cf..5b5aaef0b4 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -471,43 +471,6 @@ module Spree end end - describe "in_supplier_or_distributor" do - it "shows products in supplier" do - s1 = create(:supplier_enterprise) - p1 = create(:product, supplier_id: s1.id) - create(:variant, product: p1, supplier: s1) - s2 = create(:supplier_enterprise) - p2 = create(:product, supplier_id: s2.id) - create(:variant, product: p2, supplier: s2) - - expect(Product.in_supplier_or_distributor(s1)).to eq([p1]) - end - - it "shows products in order cycle distribution" do - s = create(:supplier_enterprise) - d1 = create(:distributor_enterprise) - d2 = create(:distributor_enterprise) - p1 = create(:product) - p2 = create(:product) - create(:simple_order_cycle, suppliers: [s], distributors: [d1], - variants: [p1.variants.first]) - create(:simple_order_cycle, suppliers: [s], distributors: [d2], - variants: [p2.variants.first]) - expect(Product.in_supplier_or_distributor(d1)).to eq([p1]) - end - - it "shows products in all three without duplicates" do - s = create(:supplier_enterprise) - d = create(:distributor_enterprise) - p = create(:product) - create(:variant, product: p, supplier: s) - - create(:simple_order_cycle, suppliers: [s], distributors: [d], - variants: [p.variants.first]) - [s, d].each { |e| expect(Product.in_supplier_or_distributor(e)).to eq([p]) } - end - end - describe "in_order_cycle" do it "shows products in order cycle distribution" do s = create(:supplier_enterprise) From 7219f72ac72bf7d68a06e37de8b33b78a186eea4 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 17 Jun 2024 10:12:07 +1000 Subject: [PATCH 128/145] Fix rebase issue --- spec/helpers/admin/orders_helper_spec.rb | 3 ++- spec/system/admin/products_spec.rb | 2 +- spec/system/admin/reports_spec.rb | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/spec/helpers/admin/orders_helper_spec.rb b/spec/helpers/admin/orders_helper_spec.rb index c24f92c471..a9b301af5e 100644 --- a/spec/helpers/admin/orders_helper_spec.rb +++ b/spec/helpers/admin/orders_helper_spec.rb @@ -70,7 +70,8 @@ RSpec.describe Admin::OrdersHelper, type: :helper do } let!(:ship_address){ create(:ship_address) } let!(:product) { - create(:simple_product, supplier: enterprise, price: 10, tax_category_id: tax_category.id) + create(:simple_product, supplier_id: enterprise.id, price: 10, + tax_category_id: tax_category.id) } let!(:variant){ create(:variant, :with_order_cycle, product:, distributor: enterprise, order_cycle:, diff --git a/spec/system/admin/products_spec.rb b/spec/system/admin/products_spec.rb index 43c808a691..cfbe4d3d2b 100644 --- a/spec/system/admin/products_spec.rb +++ b/spec/system/admin/products_spec.rb @@ -670,7 +670,7 @@ RSpec.describe ' it "checks error when creating product image with unsupported format" do unsupported_image_file_path = Rails.root.join("README.md").to_s - product = create(:simple_product, supplier_id: @supplier2.id) + product = create(:simple_product, supplier_id: supplier2.id) image = white_logo_file Spree::Image.create(viewable_id: product.id, viewable_type: 'Spree::Product', diff --git a/spec/system/admin/reports_spec.rb b/spec/system/admin/reports_spec.rb index 8902d93461..cf00d2c2e6 100644 --- a/spec/system/admin/reports_spec.rb +++ b/spec/system/admin/reports_spec.rb @@ -385,7 +385,8 @@ RSpec.describe ' let(:product2) { create(:simple_product, name: "Product 2", price: 99.0, variant_unit: 'weight', variant_unit_scale: 1, unit_value: '100', - primary_taxon_id: taxon.id, sku: "product_sku", supplier_id: supplier.id) + primary_taxon_id: taxon.id, sku: "product_sku", + supplier_id: supplier.id) } let(:variant1) { product1.variants.first } let(:variant2) { create(:variant, product: product1, price: 80.0, primary_taxon: taxon, supplier:) } From 260211cf155b4f5c740cac51ff628893f6354d7d Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 17 Jun 2024 10:39:51 +1000 Subject: [PATCH 129/145] Fix Ruboxop issue --- app/models/enterprise.rb | 2 +- app/models/spree/variant.rb | 4 +++- app/services/products_renderer.rb | 6 ++++-- spec/controllers/api/v0/variants_controller_spec.rb | 4 ++-- .../spree/admin/variants_controller_spec.rb | 2 +- spec/models/spree/product_spec.rb | 12 ++++++------ spec/models/spree/taxon_spec.rb | 1 - spec/models/spree/variant_spec.rb | 2 +- spec/services/products_renderer_spec.rb | 3 +-- spec/services/sets/product_set_spec.rb | 2 +- spec/system/admin/products_v3/products_spec.rb | 8 ++++---- spec/system/admin/reports_spec.rb | 4 +++- spec/system/admin/variant_overrides_spec.rb | 12 ++++++++---- spec/system/consumer/shopping/shopping_spec.rb | 7 ++++--- 14 files changed, 39 insertions(+), 30 deletions(-) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 3d6b33fc17..3d95f20353 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -45,7 +45,7 @@ class Enterprise < ApplicationRecord has_many :distributed_orders, class_name: 'Spree::Order', foreign_key: 'distributor_id', dependent: :restrict_with_exception - + belongs_to :address, class_name: 'Spree::Address' belongs_to :business_address, optional: true, class_name: 'Spree::Address', dependent: :destroy has_many :enterprise_fees, dependent: :restrict_with_exception diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index f0198f0171..5bca9d31df 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -25,7 +25,9 @@ module Spree variants_display_name variants_supplier_name).join('_or_')}_cont".freeze - belongs_to :product, -> { with_deleted }, required: true, touch: true, class_name: 'Spree::Product' + belongs_to :product, -> { + with_deleted + }, touch: true, class_name: 'Spree::Product', optional: false 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 diff --git a/app/services/products_renderer.rb b/app/services/products_renderer.rb index bebdadf812..9db07fa975 100644 --- a/app/services/products_renderer.rb +++ b/app/services/products_renderer.rb @@ -2,7 +2,8 @@ require 'open_food_network/scope_product_to_hub' -class ProductsRenderer + +class ProductsRenderer # rubocop:disable Metrics/ClassLength include Pagy::Backend class NoProducts < RuntimeError; end @@ -63,7 +64,8 @@ class ProductsRenderer distributed_products.products_supplier_relation end - def filter(query) + # TODO: refactor to address CyclomaticComplexity + def filter(query) # rubocop:disable Metrics/CyclomaticComplexity supplier_properties = args[:q]&.slice("with_variants_supplier_properties") ransack_results = query.ransack(args[:q]).result.to_a diff --git a/spec/controllers/api/v0/variants_controller_spec.rb b/spec/controllers/api/v0/variants_controller_spec.rb index 1f053d0325..ce9f486512 100644 --- a/spec/controllers/api/v0/variants_controller_spec.rb +++ b/spec/controllers/api/v0/variants_controller_spec.rb @@ -145,8 +145,8 @@ RSpec.describe Api::V0::VariantsController, type: :controller do it "can create a new variant" do original_number_of_variants = variant.product.variants.count api_post :create, variant: { sku: "12345", unit_value: "1", unit_description: "L", - price: "1",primary_taxon_id: taxon.id, - supplier_id: variant.supplier.id}, + price: "1", primary_taxon_id: taxon.id, + supplier_id: variant.supplier.id }, product_id: variant.product.id expect(attributes.all?{ |attr| json_response.include? attr.to_s }).to eq(true) diff --git a/spec/controllers/spree/admin/variants_controller_spec.rb b/spec/controllers/spree/admin/variants_controller_spec.rb index 3ee35450ff..ba6e1542e5 100644 --- a/spec/controllers/spree/admin/variants_controller_spec.rb +++ b/spec/controllers/spree/admin/variants_controller_spec.rb @@ -79,7 +79,7 @@ module Spree variant: { supplier_id: new_producer.id } ) - expect(order_cycle.reload.distributed_variants).to_not include variant + expect(order_cycle.reload.distributed_variants).not_to include variant end end end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 5b5aaef0b4..cf678c5491 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -510,14 +510,14 @@ module Spree producer_a = create(:enterprise, name: "a_cooperative") producer_g = create(:enterprise, name: "g_cooperative") - product_1 = create(:product, supplier_id: producer_z.id) - product_2 = create(:product, supplier_id: producer_a.id) - product_3 = create(:product, supplier_id: producer_g.id) + product1 = create(:product, supplier_id: producer_z.id) + product2 = create(:product, supplier_id: producer_a.id) + product3 = create(:product, supplier_id: producer_g.id) expect(Product.by_producer).to match_array([ - product_2, - product_3, - product_1, + product2, + product3, + product1, ]) end end diff --git a/spec/models/spree/taxon_spec.rb b/spec/models/spree/taxon_spec.rb index 282320c206..49797f69f4 100644 --- a/spec/models/spree/taxon_spec.rb +++ b/spec/models/spree/taxon_spec.rb @@ -45,7 +45,6 @@ module Spree let!(:product) { create(:simple_product, primary_taxon_id: taxon1.id) } let(:variant) { product.variants.first } - it "is touched when assignment of primary_taxon on a variant changes" do expect do variant.update(primary_taxon: taxon2) diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index abfea244dd..c633bf67da 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -27,7 +27,7 @@ RSpec.describe Spree::Variant do variant = build(:variant, shipping_category: nil) expect(variant).to be_valid - expect(variant.shipping_category).to_not be_nil + expect(variant.shipping_category).not_to be_nil end end diff --git a/spec/services/products_renderer_spec.rb b/spec/services/products_renderer_spec.rb index 8ef148c9f0..2716448ba2 100644 --- a/spec/services/products_renderer_spec.rb +++ b/spec/services/products_renderer_spec.rb @@ -23,8 +23,7 @@ RSpec.describe ProductsRenderer do variants: [ create(:variant, supplier: cakes_supplier, primary_taxon: cakes), create(:variant, supplier: fruits_supplier, primary_taxon: cakes) - ] - ) + ]) } let!(:product_cherries) { create(:product, name: "cherries", primary_taxon_id: fruits.id, diff --git a/spec/services/sets/product_set_spec.rb b/spec/services/sets/product_set_spec.rb index f24fefcd76..068b49a900 100644 --- a/spec/services/sets/product_set_spec.rb +++ b/spec/services/sets/product_set_spec.rb @@ -240,7 +240,7 @@ RSpec.describe Sets::ProductSet do }.to change { variant.supplier }.to(producer). and change { order_cycle.distributed_variants.count }.by(-1) - expect(order_cycle.distributed_variants).to_not include variant + expect(order_cycle.distributed_variants).not_to include variant end end end diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index e2293de943..35dad02d36 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -488,13 +488,13 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi let(:supplier_permitted) { create(:supplier_enterprise, name: 'Supplier Permitted') } let(:distributor_managed) { create(:distributor_enterprise, name: 'Distributor Managed') } let(:distributor_unmanaged) { create(:distributor_enterprise, name: 'Distributor Unmanaged') } - let!(:product_supplied) { create(:product, supplier: supplier_managed1, price: 10.0) } - let!(:product_not_supplied) { create(:product, supplier: supplier_unmanaged) } + let!(:product_supplied) { create(:product, supplier_id: supplier_managed1.id, price: 10.0) } + let!(:product_not_supplied) { create(:product, supplier_id: supplier_unmanaged.id) } let!(:product_supplied_permitted) { - create(:product, name: 'Product Permitted', supplier: supplier_permitted, price: 10.0) + create(:product, name: 'Product Permitted', supplier_id: supplier_permitted.id, price: 10.0) } let(:product_supplied_inactive) { - create(:product, supplier: supplier_managed1, price: 10.0) + create(:product, supplier_id: supplier_managed1.id, price: 10.0) } let!(:supplier_permitted_relationship) do diff --git a/spec/system/admin/reports_spec.rb b/spec/system/admin/reports_spec.rb index cf00d2c2e6..835c6c8a4c 100644 --- a/spec/system/admin/reports_spec.rb +++ b/spec/system/admin/reports_spec.rb @@ -389,7 +389,9 @@ RSpec.describe ' supplier_id: supplier.id) } let(:variant1) { product1.variants.first } - let(:variant2) { create(:variant, product: product1, price: 80.0, primary_taxon: taxon, supplier:) } + let(:variant2) { + create(:variant, product: product1, price: 80.0, primary_taxon: taxon, supplier:) + } let(:variant3) { product2.variants.first } before do diff --git a/spec/system/admin/variant_overrides_spec.rb b/spec/system/admin/variant_overrides_spec.rb index ce81548573..44937c3123 100644 --- a/spec/system/admin/variant_overrides_spec.rb +++ b/spec/system/admin/variant_overrides_spec.rb @@ -48,7 +48,8 @@ RSpec.describe " context "when inventory_items exist for variants" do let!(:product) { - create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1) + create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', + variant_unit_scale: 1) } let!(:variant) { create(:variant, product:, unit_value: 1, price: 1.23, on_hand: 12) } let!(:inventory_item) { create(:inventory_item, enterprise: hub, variant: ) } @@ -58,7 +59,8 @@ RSpec.describe " variant_unit_scale: 1) } let!(:variant_managed) { - create(:variant, product: product_managed, supplier: producer_managed, unit_value: 3, price: 3.65, on_hand: 2) + create(:variant, product: product_managed, supplier: producer_managed, unit_value: 3, + price: 3.65, on_hand: 2) } let!(:inventory_item_managed) { create(:inventory_item, enterprise: hub, variant: variant_managed ) @@ -66,7 +68,8 @@ RSpec.describe " let!(:product_related) { create(:simple_product, supplier_id: producer_related.id) } let!(:variant_related) { - create(:variant, product: product_related, supplier: producer_related, unit_value: 2, price: 2.34, on_hand: 23) + create(:variant, product: product_related, supplier: producer_related, unit_value: 2, + price: 2.34, on_hand: 23) } let!(:inventory_item_related) { create(:inventory_item, enterprise: hub, variant: variant_related ) @@ -476,7 +479,8 @@ RSpec.describe " describe "when inventory_items do not exist for variants" do let!(:product) { - create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', variant_unit_scale: 1) + create(:simple_product, supplier_id: producer.id, variant_unit: 'weight', + variant_unit_scale: 1) } let!(:variant1) { create(:variant, product:, unit_value: 1, price: 1.23, on_hand: 12) diff --git a/spec/system/consumer/shopping/shopping_spec.rb b/spec/system/consumer/shopping/shopping_spec.rb index fcbdbfc890..a7984c6318 100644 --- a/spec/system/consumer/shopping/shopping_spec.rb +++ b/spec/system/consumer/shopping/shopping_spec.rb @@ -296,7 +296,8 @@ RSpec.describe "As a consumer I want to shop with a distributor" do display_as: 'displayedunderthename') end let(:product2) { - create(:simple_product, supplier_id: supplier.id, name: "Meercats", meta_keywords: "Wild Fresh") + create(:simple_product, supplier_id: supplier.id, name: "Meercats", + meta_keywords: "Wild Fresh") } let(:variant3) { create(:variant, product: product2, supplier:, price: 40, display_name: "Ferrets") @@ -338,8 +339,8 @@ RSpec.describe "As a consumer I want to shop with a distributor" do it "returns results when successful" do visit shop_path # When we see the Add button, it means product are loaded on the page - expect(page).to have_content("Add", count: 4) - + expect(page).to have_content("Add", count: 4) + fill_in "search", with: "74576345634XXXXXX" expect(page).to have_content "Sorry, no results found" expect(page).not_to have_content 'Meercats' From 56b58219da5803eeb1646337ad47da0230e919ec Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 17 Jun 2024 11:19:30 +1000 Subject: [PATCH 130/145] Update rubocop TODO --- .rubocop_todo.yml | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e054d5ae51..6e13783512 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -6,13 +6,6 @@ # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. -Layout/EmptyLineBetweenDefs: - Exclude: - - 'app/services/products_renderer.rb' - # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). Layout/EmptyLines: @@ -108,7 +101,7 @@ Lint/UselessMethodDefinition: Exclude: - 'app/models/spree/gateway.rb' -# Offense count: 24 +# Offense count: 23 # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max. Metrics/AbcSize: Exclude: @@ -121,7 +114,6 @@ Metrics/AbcSize: - 'app/helpers/spree/admin/navigation_helper.rb' - 'app/models/enterprise_group.rb' - 'app/models/enterprise_relationship.rb' - - 'app/models/product_import/entry_processor.rb' - 'app/models/spree/ability.rb' - 'app/models/spree/address.rb' - 'app/models/spree/order/checkout.rb' @@ -253,7 +245,7 @@ Metrics/MethodLength: - 'lib/spree/localized_number.rb' - 'lib/tasks/sample_data/product_factory.rb' -# Offense count: 48 +# Offense count: 49 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ModuleLength: Exclude: @@ -283,6 +275,7 @@ Metrics/ModuleLength: - 'spec/controllers/payment_gateways/stripe_controller_spec.rb' - 'spec/controllers/spree/admin/adjustments_controller_spec.rb' - 'spec/controllers/spree/admin/payment_methods_controller_spec.rb' + - 'spec/controllers/spree/admin/variants_controller_spec.rb' - 'spec/lib/open_food_network/address_finder_spec.rb' - 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb' - 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb' @@ -893,7 +886,7 @@ Style/ReturnNilInPredicateMethodDefinition: - 'app/serializers/api/admin/customer_serializer.rb' - 'engines/order_management/app/services/order_management/subscriptions/validator.rb' -# Offense count: 204 +# Offense count: 207 Style/Send: Exclude: - 'spec/controllers/admin/subscriptions_controller_spec.rb' From 117f6d3300b225a9f4a6f2eb7fae754dab7673f9 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 17 Jun 2024 11:39:44 +1000 Subject: [PATCH 131/145] First round of code review change --- lib/open_food_network/order_cycle_permissions.rb | 5 +++-- spec/models/spree/product_spec.rb | 8 ++------ spec/models/spree/variant_spec.rb | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/lib/open_food_network/order_cycle_permissions.rb b/lib/open_food_network/order_cycle_permissions.rb index e4e1fd0d8e..1ab7933938 100644 --- a/lib/open_food_network/order_cycle_permissions.rb +++ b/lib/open_food_network/order_cycle_permissions.rb @@ -185,9 +185,10 @@ module OpenFoodNetwork permitted_variants = variants_from_suppliers(producer_ids) # PLUS my incoming producers' variants that are already in an outgoing exchange of this hub, - # so things don't break. TODO: Remove this when all P-OC are sorted out + # so things don't break. + # TODO: Remove this when all P-OC are sorted out active_variants = Spree::Variant.joins(:exchanges). - where(exchanges: { receiver: hub, incoming: "false" }, supplier_id: managed_producer_ids) + where(exchanges: { receiver: hub, incoming: false }, supplier_id: managed_producer_ids) Spree::Variant.where(id: permitted_variants | active_variants) end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index cf678c5491..0375fcf971 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -505,7 +505,7 @@ module Spree end describe "by_producer" do - it "orders by name" do + it "orders by producer name" do producer_z = create(:enterprise, name: "z_cooperative") producer_a = create(:enterprise, name: "a_cooperative") producer_g = create(:enterprise, name: "g_cooperative") @@ -514,11 +514,7 @@ module Spree product2 = create(:product, supplier_id: producer_a.id) product3 = create(:product, supplier_id: producer_g.id) - expect(Product.by_producer).to match_array([ - product2, - product3, - product1, - ]) + expect(Product.by_producer).to eq([product2, product3, product1]) end end diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index c633bf67da..2252d589e4 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -863,7 +863,7 @@ RSpec.describe Spree::Variant do it "touches the supplier" do supplier = create(:supplier_enterprise) - variant = create(:variant, supplier:) + variant = create(:variant, supplier:, updated_at: 1.hour.ago) expect { variant.destroy }.to change { supplier.reload.updated_at } end From efbec02fb90abb8513a17f9f820d3ecbf2927246 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 18 Jun 2024 10:24:43 +1000 Subject: [PATCH 132/145] Fix rebase issue --- spec/system/admin/products_v3/products_spec.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/system/admin/products_v3/products_spec.rb b/spec/system/admin/products_v3/products_spec.rb index 35dad02d36..a0e35aa41b 100644 --- a/spec/system/admin/products_v3/products_spec.rb +++ b/spec/system/admin/products_v3/products_spec.rb @@ -522,18 +522,19 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi it "shows only suppliers that I manage or have permission to" do visit spree.admin_products_path - within row_containing_name(product_supplied.name) do + + within row_containing_placeholder(product_supplied.name) do expect(page).to have_select( - '_products_0_supplier_id', + '_products_0_variants_attributes_0_supplier_id', options: [ supplier_managed1.name, supplier_managed2.name, supplier_permitted.name ], selected: supplier_managed1.name ) end - within row_containing_name(product_supplied_permitted.name) do + within row_containing_placeholder(product_supplied_permitted.name) do expect(page).to have_select( - '_products_1_supplier_id', + '_products_1_variants_attributes_0_supplier_id', options: [ supplier_managed1.name, supplier_managed2.name, supplier_permitted.name ], selected: supplier_permitted.name From c328ee8087f34965186957c8b44d227994c8fead Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 19 Jun 2024 10:42:24 +1000 Subject: [PATCH 133/145] Remove stockable_by from Product and Variant It's not used anymore --- app/models/spree/product.rb | 11 ----------- app/models/spree/variant.rb | 11 ----------- spec/models/spree/product_spec.rb | 26 -------------------------- spec/models/spree/variant_spec.rb | 24 ------------------------ 4 files changed, 72 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index a59f1240c0..a8ae210631 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -165,17 +165,6 @@ module Spree end } - scope :stockable_by, lambda { |enterprise| - return where('1=0') if enterprise.blank? - - permitted_producer_ids = EnterpriseRelationship.joins(:parent).permitting(enterprise.id) - .with_permission(:add_to_order_cycle) - .where(enterprises: { is_primary_producer: true }) - .pluck(:parent_id) - - in_supplier([enterprise.id].union(permitted_producer_ids)) - } - scope :active, lambda { where(spree_products: { deleted_at: nil }) } def self.group_by_products_id diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 5bca9d31df..45a4e993a2 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -143,17 +143,6 @@ module Spree .where("o_inventory_items.id IS NULL OR o_inventory_items.visible = (?)", true) } - scope :stockable_by, lambda { |enterprise| - return where("1=0") if enterprise.blank? - - 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 }) diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 0375fcf971..208f4bde81 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -579,32 +579,6 @@ module Spree end end - describe 'stockable_by' do - let(:shop) { create(:distributor_enterprise) } - let(:add_to_oc_producer) { create(:supplier_enterprise) } - let(:other_producer) { create(:supplier_enterprise) } - let(:p1) { create(:simple_product) } - let(:p2) { create(:simple_product) } - let(:p3) { create(:simple_product) } - - before do - create(:variant, product: p1, supplier: shop) - create(:variant, product: p2, supplier: add_to_oc_producer) - create(:variant, product: p3, supplier: other_producer) - - create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, - permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: other_producer, child: shop, - permissions_list: [:manage_products]) - end - - it 'shows products produced by the enterprise and any producers granting P-OC' do - stockable_products = Spree::Product.stockable_by(shop) - expect(stockable_products).to include p1, p2 - expect(stockable_products).not_to include p3 - end - end - describe "imported_on" do let!(:v1) { create(:variant, import_date: 1.day.ago) } let!(:v2) { create(:variant, import_date: 2.days.ago) } diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 2252d589e4..c681066ae6 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -448,30 +448,6 @@ RSpec.describe Spree::Variant do end end - 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!(:v2) { - create(:variant, product: create(:simple_product), supplier: add_to_oc_producer ) - } - let!(:v3) { create(:variant, product: create(:simple_product), supplier: other_producer ) } - - before do - create(:enterprise_relationship, parent: add_to_oc_producer, child: shop, - permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: other_producer, child: shop, - permissions_list: [:manage_products]) - end - - it 'shows variants produced by the enterprise and any producers granting P-OC' do - stockable_variants = Spree::Variant.stockable_by(shop) - expect(stockable_variants).to include v1, v2 - 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) From 3788b33eb0d45e6ac894f8d74cf53d1888053eaa Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 17 Jun 2024 11:39:44 +1000 Subject: [PATCH 134/145] First round of code review change --- spec/models/spree/variant_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index c681066ae6..4788cb68a3 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -838,8 +838,8 @@ RSpec.describe Spree::Variant do end it "touches the supplier" do - supplier = create(:supplier_enterprise) - variant = create(:variant, supplier:, updated_at: 1.hour.ago) + supplier = create(:supplier_enterprise, updated_at: 1.hour.ago) + variant = create(:variant, supplier:) expect { variant.destroy }.to change { supplier.reload.updated_at } end From f73745a8039c21e6a7ffe3bb44578b5e85e40c25 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 19 Jun 2024 10:45:34 +1000 Subject: [PATCH 135/145] David's first review changes --- app/models/spree/taxon.rb | 2 +- spec/models/enterprise_spec.rb | 3 ++- spec/models/spree/product_spec.rb | 5 +---- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/models/spree/taxon.rb b/app/models/spree/taxon.rb index 827551b4d7..bc0b85371a 100644 --- a/app/models/spree/taxon.rb +++ b/app/models/spree/taxon.rb @@ -57,7 +57,7 @@ module Spree taxons = {} Spree::Taxon. - joins(products: { variants: :supplier }). + joins(variants: :supplier). select('spree_taxons.*, enterprises.id AS enterprise_id'). each do |t| taxons[t.enterprise_id.to_i] ||= Set.new diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index c0b01822a6..971bea4b0c 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -38,10 +38,11 @@ RSpec.describe Enterprise do end it "destroys supplied variants upon destroy" do + pending "Variant are soft deletable, see: https://github.com/openfoodfoundation/openfoodnetwork/issues/2971" supplier = create(:supplier_enterprise) variant = create(:variant, supplier:) - variant.destroy + supplier.destroy expect(Spree::Variant.where(id: variant.id)).to be_empty end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 208f4bde81..bc6c66ff34 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -10,10 +10,6 @@ module Spree context '#duplicate' do it 'duplicates product' do - variant = product.variants.first - variant.supplier = create(:supplier_enterprise) - variant.save! - clone = product.duplicate expect(clone).to be_persisted @@ -390,6 +386,7 @@ module Spree it "shows products in supplier" do s1 = create(:supplier_enterprise) p1 = create(:product, supplier_id: s1.id) + # We create two variants to let us test we don't get duplicated product create(:variant, product: p1, supplier: s1) create(:variant, product: p1, supplier: s1) s2 = create(:supplier_enterprise) From 448308710a1f4dbfeb35aa9310ab3ddbe526c7d9 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 19 Jun 2024 14:28:37 +1000 Subject: [PATCH 136/145] Per review, distributor are now updated via variant When a product is deleted, it will delete associated variant and in turn will touch the affected distributors --- app/models/enterprise.rb | 8 ++--- app/models/spree/product.rb | 6 ---- app/models/spree/variant.rb | 16 ++++++++-- spec/models/enterprise_spec.rb | 52 +++++++++++++++++++++---------- spec/models/spree/product_spec.rb | 7 +---- spec/models/spree/variant_spec.rb | 14 +++++++++ 6 files changed, 69 insertions(+), 34 deletions(-) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 3d95f20353..03de14c176 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -205,14 +205,14 @@ class Enterprise < ApplicationRecord select('DISTINCT enterprises.*') } - scope :distributing_products, lambda { |product_ids| + scope :distributing_variants, lambda { |variants_ids| exchanges = joins(" INNER JOIN exchanges - ON (exchanges.receiver_id = enterprises.id AND exchanges.incoming = 'f') + ON (exchanges.receiver_id = enterprises.id AND exchanges.incoming = false) "). joins('INNER JOIN exchange_variants ON (exchange_variants.exchange_id = exchanges.id)'). joins('INNER JOIN spree_variants ON (spree_variants.id = exchange_variants.variant_id)'). - where(spree_variants: { product_id: product_ids }).select('DISTINCT enterprises.id') + where(spree_variants: { id: variants_ids }).select('DISTINCT enterprises.id') where(id: exchanges) } @@ -598,7 +598,7 @@ class Enterprise < ApplicationRecord # Touch distributors without them touching their distributors. # We avoid an infinite loop and don't need to touch the whole distributor tree. def touch_distributors - Enterprise.distributing_products(supplied_products.select(:id)). + Enterprise.distributing_variants(supplied_variants.select(:id)). where.not(enterprises: { id: }). update_all(updated_at: Time.zone.now) end diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index a8ae210631..fa906cca83 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -240,8 +240,6 @@ module Spree def destruction transaction do - touch_distributors - ExchangeVariant. where(exchange_variants: { variant_id: variants.with_deleted. select(:id) }).destroy_all @@ -319,10 +317,6 @@ module Spree first_variant.supplier.touch if first_variant.supplier.present? end - def touch_distributors - Enterprise.distributing_products(id).each(&:touch) - end - def validate_image return if image.blank? || !image.changed? || image.valid? diff --git a/app/models/spree/variant.rb b/app/models/spree/variant.rb index 45a4e993a2..00340f49d7 100644 --- a/app/models/spree/variant.rb +++ b/app/models/spree/variant.rb @@ -252,8 +252,16 @@ module Spree end def destruction - exchange_variants.reload.destroy_all - yield + transaction do + # Even tough Enterprise will touch associated variant distributors when touched, + # the variant will be removed from the exchange by the time it's triggered, + # so it won't be able to find the deleted variant's distributors. + # This why we do it here + touch_distributors + + exchange_variants.reload.destroy_all + yield + end end def ensure_unit_value @@ -270,5 +278,9 @@ module Spree def convert_variant_weight_to_decimal self.weight = weight.to_d end + + def touch_distributors + Enterprise.distributing_variants(id).each(&:touch) + end end end diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 971bea4b0c..f69c6f96d2 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -412,12 +412,33 @@ RSpec.describe Enterprise do end describe "callbacks" do - it "restores permalink to original value when it is changed and invalid" do - e1 = create(:enterprise, permalink: "taken") - e2 = create(:enterprise, permalink: "not_taken") - e2.permalink = "taken" - e2.save - expect(e2.reload.permalink).to eq "not_taken" + describe "restore_permalink" do + it "restores permalink to original value when it is changed and invalid" do + e1 = create(:enterprise, permalink: "taken") + e2 = create(:enterprise, permalink: "not_taken") + e2.permalink = "taken" + e2.save + expect(e2.reload.permalink).to eq "not_taken" + end + end + + describe "touch_distributors" do + it "touches supplied variant distributors" do + enterprise = create(:enterprise) + variant = create(:variant) + enterprise.supplied_variants << variant + + updated_at = 1.hour.ago + distributor1 = create(:distributor_enterprise, updated_at:) + distributor2 = create(:distributor_enterprise, updated_at:) + + create(:simple_order_cycle, distributors: [distributor1], variants: [variant]) + create(:simple_order_cycle, distributors: [distributor2], variants: [variant]) + + expect { enterprise.touch } + .to change { distributor1.reload.updated_at } + .and change { distributor2.reload.updated_at } + end end end @@ -595,23 +616,22 @@ RSpec.describe Enterprise do end end - describe "distributing_products" do + describe "distributing_variants" do let(:distributor) { create(:distributor_enterprise) } - let(:product) { create(:product) } + let(:variant) { create(:variant) } it "returns enterprises distributing via an order cycle" do - order_cycle = create(:simple_order_cycle, distributors: [distributor], - variants: [product.variants.first]) - expect(Enterprise.distributing_products(product.id)).to eq([distributor]) + order_cycle = create(:simple_order_cycle, distributors: [distributor], variants: [variant]) + expect(Enterprise.distributing_variants(variant.id)).to eq([distributor]) end it "does not return duplicate enterprises" do - another_product = create(:product) + another_variant = create(:variant) order_cycle = create(:simple_order_cycle, distributors: [distributor], - variants: [product.variants.first, - another_product.variants.first]) - expect(Enterprise.distributing_products([product.id, - another_product.id])).to eq([distributor]) + variants: [variant, another_variant]) + expect(Enterprise.distributing_variants( + [variant.id, another_variant.id] + )).to eq([distributor]) end end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index bc6c66ff34..385588538d 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -278,19 +278,14 @@ module Spree describe "callbacks" do let(:product) { create(:simple_product) } - describe "touching affected enterprises when the product is deleted" do + describe "destroy product" do let(:product) { create(:simple_product, supplier_id: distributor.id) } let(:distributor) { create(:distributor_enterprise) } - let(:supplier) { create(:supplier_enterprise) } let!(:oc) { create(:simple_order_cycle, distributors: [distributor], variants: [product.variants.first]) } - it "touches all distributors" do - expect { product.destroy }.to change { distributor.reload.updated_at } - end - it "removes variants from order cycles" do expect { product.destroy }.to change { ExchangeVariant.count } end diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 4788cb68a3..ef1f22fcdf 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -843,6 +843,20 @@ RSpec.describe Spree::Variant do expect { variant.destroy }.to change { supplier.reload.updated_at } end + + it "touches distributors" do + variant = create(:variant) + updated_at = 1.hour.ago + distributor1 = create(:distributor_enterprise, updated_at:) + distributor2 = create(:distributor_enterprise, updated_at:) + + create(:simple_order_cycle, distributors: [distributor1], variants: [variant]) + create(:simple_order_cycle, distributors: [distributor2], variants: [variant]) + + expect { variant.destroy } + .to change { distributor1.reload.updated_at } + .and change { distributor2.reload.updated_at } + end end describe "#ensure_unit_value" do From 9549f4e5067ac6581d4dea65690994edc5dbf8ff Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 19 Jun 2024 11:11:36 +1000 Subject: [PATCH 137/145] Update product description --- app/models/spree/product.rb | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index fa906cca83..92ce6c202c 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -1,24 +1,19 @@ # frozen_string_literal: true require 'open_food_network/property_merge' -# TODO update description # PRODUCTS # Products represent an entity for sale in a store. # Products can have variations, called variants -# Products properties include description, permalink, availability, -# shipping category, etc. that do not change by variant. -# -# MASTER VARIANT -# Every product has one master variant, which stores master price and sku, size and weight, etc. -# Price, SKU, size, weight, etc. are all delegated to the master variant. -# Contains on_hand inventory levels only when there are no variants for the product. +# Products properties include description, meta_keywork, etc. that do not change by variant. # # VARIANTS -# All variants can access the product properties directly (via reverse delegation). +# Every product has at least one variant (standard variant), which stores price and availability, +# shipping category, sku, size and weight, etc. +# All variants can access the product name, description, and meta_keyword directly (via reverse +# delegation). # Inventory units are tied to Variant. -# The master variant can have inventory units, but not option values. -# All other variants have option values and may have inventory units. +# All variants have option values and may have inventory units. # Sum of on_hand each variant's inventory level determine "on_hand" level for the product. # module Spree From f79691e4bfbad455791a8cd226846c69af3445b8 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 26 Jun 2024 09:54:57 +1000 Subject: [PATCH 138/145] Ignore supplier_id for Spree::Product --- app/models/spree/product.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 92ce6c202c..2aa558a5ad 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -22,6 +22,7 @@ module Spree include LogDestroyPerformer self.belongs_to_required_by_default = false + self.ignored_columns += [:supplier_id] acts_as_paranoid From f60a79437e3429a543487f1b7195c16560ec1faf Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 26 Jun 2024 10:56:15 +1000 Subject: [PATCH 139/145] Reworked the test to use variant factory Creating a variant actually create an extra one via the associated product, as it will create a "standard variant". As far as I can see there is no way around it, but it should be fixed once the Product refactor is finished, and product becomes product group. Added a comment on the variant factory to explain the problem. It's not ideal as it will slow down the test suite a little, but I think it's better to write the code the way you would expect it, and it will eventually get fixed. --- spec/factories/variant_factory.rb | 9 +++++-- .../products_and_inventory_report_spec.rb | 24 ++++++++----------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/spec/factories/variant_factory.rb b/spec/factories/variant_factory.rb index 50da2702b0..dc729a29e6 100644 --- a/spec/factories/variant_factory.rb +++ b/spec/factories/variant_factory.rb @@ -14,7 +14,13 @@ FactoryBot.define do primary_taxon { Spree::Taxon.first || FactoryBot.create(:taxon) } supplier { Enterprise.is_primary_producer.first || FactoryBot.create(:supplier_enterprise) } - product { |p| p.association(:base_product) } + # createing a product here will end up creating an extra variant, as creating product will + # create a "standard variant" by default. We could try to pass the variant instance we + # are creating but it fails because then the variant instance gets saved and it fails because + # the product isn't associated yet. It's a chicken and egg problem. + # It will be fixed once we finish the product refactor, and we don't need the product to + # create a "standard variant" + product { association :base_product } # ensure stock item will be created for this variant before(:create) { create(:stock_location) if Spree::StockLocation.count.zero? } @@ -25,7 +31,6 @@ FactoryBot.define do on_hand { 5 } end - product { |p| p.association(:product) } unit_value { 1 } unit_description { '' } diff --git a/spec/lib/reports/products_and_inventory_report_spec.rb b/spec/lib/reports/products_and_inventory_report_spec.rb index ff8025d4e6..19a7024bb1 100644 --- a/spec/lib/reports/products_and_inventory_report_spec.rb +++ b/spec/lib/reports/products_and_inventory_report_spec.rb @@ -267,12 +267,10 @@ module Reporting let(:report) do AllProducts.new user, { fields_to_hide: [] } end - # Creating a variant directly would create a product with another variant with no supplier - # which breaks the test - let(:variant) { create(:product).variants.first } + let(:variant) { create(:variant, supplier:) } let(:supplier) { create(:supplier_enterprise) } - it "Should return headers" do + it "returns headers" do expect(report.table_headers).to eq([ "Supplier", "Producer Suburb", @@ -289,29 +287,27 @@ module Reporting ]) end - it "Should render 'On demand' when the product is available on demand" do + it "renders 'On demand' when the product is available on demand" do variant.on_demand = true variant.on_hand = 15 - variant.supplier = supplier variant.save! - first_row = report.table_rows.first - on_demand_column = first_row[-2] - on_hand_column = first_row[-1] + last_row = report.table_rows.last + on_demand_column = last_row[-2] + on_hand_column = last_row[-1] expect(on_demand_column).to eq("Yes") expect(on_hand_column).to eq("On demand") end - it "Should render the on hand count when the product is not available on demand" do + it "renders the on hand count when the product is not available on demand" do variant.on_demand = false variant.on_hand = 22 - variant.supplier = supplier variant.save! - first_row = report.table_rows.first - on_demand_column = first_row[-2] - on_hand_column = first_row[-1] + last_row = report.table_rows.last + on_demand_column = last_row[-2] + on_hand_column = last_row[-1] expect(on_demand_column).to eq("No") expect(on_hand_column).to eq(22) From 1d86315108ac29999414fad4d79c776999184150 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 26 Jun 2024 11:23:29 +1000 Subject: [PATCH 140/145] Per review, update comment to match code --- lib/reporting/reports/enterprise_fee_summary/scope.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/reporting/reports/enterprise_fee_summary/scope.rb b/lib/reporting/reports/enterprise_fee_summary/scope.rb index 39e6e20ffd..5aa518f5c4 100644 --- a/lib/reporting/reports/enterprise_fee_summary/scope.rb +++ b/lib/reporting/reports/enterprise_fee_summary/scope.rb @@ -201,7 +201,6 @@ module Reporting # Includes: # * Line item # * Variant - # * Product # * Tax category of product, if enterprise fee tells to inherit def include_line_item_source_details join_scope( From 1ead9208eebb4048a3e9b8f2aa391aa4db9eac8c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 26 Jun 2024 12:03:49 +1000 Subject: [PATCH 141/145] Fix rebase issue Fix test by creating a variant instead of relying on some random data from the database. --- spec/services/orders/compare_invoice_service_spec.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/spec/services/orders/compare_invoice_service_spec.rb b/spec/services/orders/compare_invoice_service_spec.rb index 19ad37422a..dd4757bd14 100644 --- a/spec/services/orders/compare_invoice_service_spec.rb +++ b/spec/services/orders/compare_invoice_service_spec.rb @@ -136,7 +136,9 @@ end RSpec.shared_examples "associated attribute changes - line items" do |boolean, type| context "line item changes" do - let(:line_item){ order.line_items.first } + let(:line_item) { order.line_items.first } + let(:variant) { create(:variant) } + context "on quantitity" do before { line_item.update!(quantity: line_item.quantity + 1) } it "returns #{boolean} if a #{type} attribute changes" do @@ -146,7 +148,7 @@ RSpec.shared_examples "associated attribute changes - line items" do |boolean, t end context "on variant id" do - before { line_item.update!(variant_id: Spree::Variant.first.id) } + before { line_item.update!(variant_id: variant.id) } it "returns #{boolean} if a #{type} attribute changes" do order.reload expect(subject).to be boolean From dfe56c1eed93914de1606ac07711956d607c6538 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 26 Jun 2024 20:38:36 +1000 Subject: [PATCH 142/145] Fix flacky spec In practise we shouldn't have product with mutiple variant with different supplier, so I think it's fine to not test it. --- spec/services/products_renderer_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spec/services/products_renderer_spec.rb b/spec/services/products_renderer_spec.rb index 2716448ba2..4044b354e6 100644 --- a/spec/services/products_renderer_spec.rb +++ b/spec/services/products_renderer_spec.rb @@ -19,11 +19,8 @@ RSpec.describe ProductsRenderer do supplier_id: fruits_supplier.id, inherits_properties: true) } let!(:product_banana_bread) { - create(:product, name: "banana bread", inherits_properties: true, - variants: [ - create(:variant, supplier: cakes_supplier, primary_taxon: cakes), - create(:variant, supplier: fruits_supplier, primary_taxon: cakes) - ]) + create(:product, name: "banana bread", primary_taxon_id: cakes.id, + supplier_id: cakes_supplier.id, inherits_properties: true) } let!(:product_cherries) { create(:product, name: "cherries", primary_taxon_id: fruits.id, From be5a228509135078519f45f9a9965903441b4144 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Mon, 1 Jul 2024 12:41:05 +1000 Subject: [PATCH 143/145] Fix rebase issue and add missing translation --- app/views/admin/products_v3/_product_variant_row.html.haml | 6 +++--- config/locales/en.yml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/views/admin/products_v3/_product_variant_row.html.haml b/app/views/admin/products_v3/_product_variant_row.html.haml index b77f30b0f8..5c2765ab2d 100644 --- a/app/views/admin/products_v3/_product_variant_row.html.haml +++ b/app/views/admin/products_v3/_product_variant_row.html.haml @@ -4,17 +4,17 @@ action: 'rails-nested-form:add->bulk-form#registerElements rails-nested-form:remove->bulk-form#toggleFormChanged' }, class: (defined?(should_slide_in) && should_slide_in) ? 'slide-in' : '' } %tr - = render partial: 'product_row', locals: { f: product_form, product:, producer_options:, product_index: } + = render partial: 'product_row', locals: { f: product_form, product:, product_index: } - product.variants.each_with_index do |variant, variant_index| = form.fields_for("products][#{product_index}][variants_attributes][", variant, index: variant_index) do |variant_form| %tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false } - = render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options: } + = render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: } = form.fields_for("products][#{product_index}][variants_attributes][NEW_RECORD", product.variants.build) do |new_variant_form| %template{ 'data-nested-form-target': "template" } %tr.condensed{ 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': "true" } - = render partial: 'variant_row', locals: { variant: new_variant_form.object, f: new_variant_form, category_options:, tax_category_options: } + = render partial: 'variant_row', locals: { variant: new_variant_form.object, f: new_variant_form, category_options:, tax_category_options:, producer_options: } %tr{ 'data-nested-form-target': "target" } %tr.condensed diff --git a/config/locales/en.yml b/config/locales/en.yml index d0764b7a91..2e93115d54 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -902,6 +902,7 @@ en: other: "%{count} products could not be saved. Please review the errors and try again." reset: Discard changes save: Save changes + new_variant: New variant product_variant_row: new_variant: New variant bulk_update: From fb2575aaebc01f96982b82b7945d9441c7985ed8 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Tue, 2 Jul 2024 09:47:48 +1000 Subject: [PATCH 144/145] Fix more rebase issue --- app/views/admin/products_v3/_table.html.haml | 25 +------------------- config/locales/en.yml | 1 - 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/app/views/admin/products_v3/_table.html.haml b/app/views/admin/products_v3/_table.html.haml index 524b3d6d4a..e04f33b00a 100644 --- a/app/views/admin/products_v3/_table.html.haml +++ b/app/views/admin/products_v3/_table.html.haml @@ -63,27 +63,4 @@ %th.align-left.col-inherits_properties= t('admin.products_page.columns.inherits_properties') %th.align-right= t('admin.products_page.columns.actions') - products.each_with_index do |product, product_index| - = form.fields_for("products", product, index: product_index) do |product_form| - %tbody.relaxed{ id: dom_id(product), data: { 'record-id': product_form.object.id, - controller: "nested-form product", - action: 'rails-nested-form:add->bulk-form#registerElements rails-nested-form:remove->bulk-form#toggleFormChanged' } } - %tr - = render partial: 'product_row', locals: { f: product_form, product: } - - - product.variants.each_with_index do |variant, variant_index| - = form.fields_for("products][#{product_index}][variants_attributes][", variant, index: variant_index) do |variant_form| - %tr.condensed{ id: dom_id(variant), 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': variant.new_record? ? "true" : false } - = render partial: 'variant_row', locals: { variant:, f: variant_form, category_options:, tax_category_options:, producer_options: } - - = form.fields_for("products][#{product_index}][variants_attributes][NEW_RECORD", product.variants.build) do |new_variant_form| - %template{ 'data-nested-form-target': "template" } - %tr.condensed{ 'data-controller': "variant", 'class': "nested-form-wrapper", 'data-new-record': "true" } - = render partial: 'variant_row', locals: { variant: new_variant_form.object, f: new_variant_form, category_options:, tax_category_options:, producer_options: } - - %tr{ 'data-nested-form-target': "target" } - %tr.condensed - %td - %td{ colspan: 11 } - %button.secondary.condensed.naked.icon-plus{ 'data-action': "nested-form#add", - 'aria-label': t('.new_variant') } - =t('.new_variant') + = render partial: 'product_variant_row', locals: { form:, product:, product_index:, producer_options:, category_options:, tax_category_options: } diff --git a/config/locales/en.yml b/config/locales/en.yml index 2e93115d54..d0764b7a91 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -902,7 +902,6 @@ en: other: "%{count} products could not be saved. Please review the errors and try again." reset: Discard changes save: Save changes - new_variant: New variant product_variant_row: new_variant: New variant bulk_update: From cfc51f399f63f37dae3e4ba307aee608d963e32c Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 3 Jul 2024 12:04:18 +1000 Subject: [PATCH 145/145] More rebase fix --- spec/support/products_helper.rb | 9 ++++++++- spec/system/admin/products_spec.rb | 6 +++--- spec/system/admin/products_v3/index_spec.rb | 8 +++++--- spec/system/admin/reports_spec.rb | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/spec/support/products_helper.rb b/spec/support/products_helper.rb index f9baececed..518aa45257 100644 --- a/spec/support/products_helper.rb +++ b/spec/support/products_helper.rb @@ -3,7 +3,7 @@ module ProductsHelper def create_products(amount) amount.times do |i| - create(:simple_product, name: "product #{i}", supplier: producer) + create(:simple_product, name: "product #{i}", supplier_id: producer.id) end end @@ -41,6 +41,13 @@ module ProductsHelper "tr:has(input[aria-label=Name][value='#{value}'])" end + # Selector for table row that has an input with a placeholder. + # Variant don't have display_name set, so we look for the input with placeholder matching the + # product's name to get the variant row + def row_containing_placeholder(value) + "tr:has(input[aria-label=Name][placeholder='#{value}'])" + end + # Wait for an element with the given CSS selector and class to be present def wait_for_class(selector, class_name) max_wait_time = Capybara.default_max_wait_time diff --git a/spec/system/admin/products_spec.rb b/spec/system/admin/products_spec.rb index cfbe4d3d2b..5a74e7972a 100644 --- a/spec/system/admin/products_spec.rb +++ b/spec/system/admin/products_spec.rb @@ -255,12 +255,12 @@ RSpec.describe ' describe "deleting" do let!(:product1) { - create(:simple_product, name: 'a product to keep', supplier_id: @supplier.id) + create(:simple_product, name: 'a product to keep', supplier_id: supplier.id) } context 'a simple product' do let!(:product2) { - create(:simple_product, name: 'a product to delete', supplier_id: @supplier.id + create(:simple_product, name: 'a product to delete', supplier_id: supplier.id) } before do @@ -311,7 +311,7 @@ RSpec.describe ' describe 'cloning' do let!(:product1) { - create(:simple_product, name: 'a weight product', supplier_id: @supplier.id, + create(:simple_product, name: 'a weight product', supplier_id: supplier.id, variant_unit: "weight") } diff --git a/spec/system/admin/products_v3/index_spec.rb b/spec/system/admin/products_v3/index_spec.rb index 23b678138e..264bdad71c 100644 --- a/spec/system/admin/products_v3/index_spec.rb +++ b/spec/system/admin/products_v3/index_spec.rb @@ -53,8 +53,8 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi s1 = FactoryBot.create(:supplier_enterprise) s2 = FactoryBot.create(:supplier_enterprise) s3 = FactoryBot.create(:supplier_enterprise) - p1 = FactoryBot.create(:product, supplier: s2) - p2 = FactoryBot.create(:product, supplier: s3) + p1 = FactoryBot.create(:product, supplier_id: s2.id) + p2 = FactoryBot.create(:product, supplier_id: s3.id) visit spree.admin_products_path @@ -269,7 +269,9 @@ RSpec.describe 'As an enterprise user, I can manage my products', feature: :admi # create a product with a different supplier let!(:producer1) { create(:supplier_enterprise, name: "Producer 1") } - let!(:product_by_supplier) { create(:simple_product, name: "Apples", supplier: producer1) } + let!(:product_by_supplier) { + create(:simple_product, name: "Apples", supplier_id: producer1.id) + } before { user.enterprise_roles.create(enterprise: producer1) } diff --git a/spec/system/admin/reports_spec.rb b/spec/system/admin/reports_spec.rb index 835c6c8a4c..62de258992 100644 --- a/spec/system/admin/reports_spec.rb +++ b/spec/system/admin/reports_spec.rb @@ -418,7 +418,7 @@ RSpec.describe ' expect(page).to have_table_row ["Supplier", "Producer Suburb", "Product", "Product Properties", "Taxons", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount", "SKU", - "On Demand?", "On hand"] + "On Demand?", "On Hand"] expect(page).to have_table_row [supplier.name, supplier.address.city, "Product Name", product1.properties.map(&:presentation).join(", "),