diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index e7bf67a3d3..be905c8ccc 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -272,18 +272,6 @@ module Spree end end - private - - def update_units - return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name? - - variants.each(&:update_units) - end - - def touch_distributors - Enterprise.distributing_products(id).each(&:touch) - end - def ensure_standard_variant return unless variants.empty? @@ -298,6 +286,18 @@ module Spree variants << variant end + private + + def update_units + return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name? + + variants.each(&:update_units) + end + + def touch_distributors + Enterprise.distributing_products(id).each(&:touch) + end + def validate_image return if image.blank? || image.valid? 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 e4daf3155f..21b4c4b59d 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 @@ -14,13 +14,19 @@ module DfcProvider return head :bad_request unless supplied_product - product = SuppliedProductBuilder.import(supplied_product) - product.supplier = current_enterprise - product.save! + variant = SuppliedProductBuilder.import_variant(supplied_product) + product = variant.product - supplied_product = SuppliedProductBuilder.supplied_product( - product.variants.first - ) + if product.new_record? + product.supplier = current_enterprise + product.save! + end + + if variant.new_record? + variant.save! + end + + supplied_product = SuppliedProductBuilder.supplied_product(variant) render json: DfcIo.export(supplied_product) end diff --git a/engines/dfc_provider/app/services/supplied_product_builder.rb b/engines/dfc_provider/app/services/supplied_product_builder.rb index 53d64f5d3c..a706a72eb7 100644 --- a/engines/dfc_provider/app/services/supplied_product_builder.rb +++ b/engines/dfc_provider/app/services/supplied_product_builder.rb @@ -17,7 +17,25 @@ class SuppliedProductBuilder < DfcBuilder ) end - def self.import(supplied_product) + def self.import_variant(supplied_product) + product_id = supplied_product.spree_product_id + + if product_id.present? + product = Spree::Product.find(product_id) + Spree::Variant.new( + product:, + price: 0, + ).tap do |variant| + apply(supplied_product, variant) + end + else + product = import_product(supplied_product) + product.ensure_standard_variant + product.variants.first + end + end + + def self.import_product(supplied_product) Spree::Product.new( name: supplied_product.name, description: supplied_product.description, diff --git a/engines/dfc_provider/lib/data_food_consortium/connector/importer.rb b/engines/dfc_provider/lib/data_food_consortium/connector/importer.rb index 81c6624f11..2876f853c4 100644 --- a/engines/dfc_provider/lib/data_food_consortium/connector/importer.rb +++ b/engines/dfc_provider/lib/data_food_consortium/connector/importer.rb @@ -127,11 +127,14 @@ module DataFoodConsortium end def guess_setter_name(predicate) - fragment = predicate.fragment + name = - # Some predicates are named like `hasQuantity` - # but the attribute name would be `quantity`. - name = fragment.sub(/^has/, "").camelize(:lower) + # Some predicates are named like `hasQuantity` + # but the attribute name would be `quantity`. + predicate.fragment&.sub(/^has/, "")&.camelize(:lower) || + + # And sometimes the URI looks like `ofn:spree_product_id`. + predicate.to_s.split(":").last "#{name}=" end diff --git a/engines/dfc_provider/spec/requests/supplied_products_spec.rb b/engines/dfc_provider/spec/requests/supplied_products_spec.rb index 966ff2b56f..a3e2ed2d77 100644 --- a/engines/dfc_provider/spec/requests/supplied_products_spec.rb +++ b/engines/dfc_provider/spec/requests/supplied_products_spec.rb @@ -96,6 +96,27 @@ describe "SuppliedProducts", type: :request, swagger_doc: "dfc.yaml", expect(variant.unit_value).to eq 3 expect(variant.product_id).to eq spree_product_id + # References the associated Spree::Product + product_id = json_response["ofn:spree_product_id"] + product = Spree::Product.find(product_id) + expect(product.name).to eq "Apple" + expect(product.variants).to eq [variant] + + # Creates a variant for existing product + supplied_product[:'ofn:spree_product_id'] = product_id + supplied_product[:'dfc-b:hasQuantity'][:'dfc-b:value'] = 6 + + expect { + submit_request(example.metadata) + product.variants.reload + } + .to change { product.variants.count }.by(1) + + variant_id = json_response["@id"].split("/").last.to_i + second_variant = Spree::Variant.find(variant_id) + expect(product.variants).to match_array [variant, second_variant] + expect(second_variant.unit_value).to eq 6 + # Insert static value to keep documentation deterministic: response.body.gsub!( "supplied_products/#{variant_id}",