Disable inventory option for product import

This commit is contained in:
Gaetan Craig-Riou
2025-06-02 22:57:53 +10:00
parent cd8b7cd239
commit f30b899569
7 changed files with 268 additions and 230 deletions

View File

@@ -17,7 +17,10 @@ module Admin
end
def import
return unless can_import_into_inventories?
@filepath = save_uploaded_file(params[:file])
@importer = ProductImport::ProductImporter.new(File.new(@filepath), spree_current_user,
params[:settings])
@original_filename = params[:file].try(:original_filename)
@@ -36,7 +39,22 @@ module Admin
def save_data
return unless process_data('save')
render json: @importer.save_results
json = {
results: {
products_created: @importer.products_created_count,
products_updated: @importer.products_updated_count,
products_reset: @importer.products_reset_count,
},
updated_ids: @importer.updated_ids,
errors: @importer.errors.full_messages
}
if helpers.feature?(:inventory, spree_current_user.enterprises)
json[:results][:inventory_created] = @importer.inventory_created_count
json[:results][:inventory_updated] = @importer.inventory_updated_count
end
render json:
end
def reset_absent_products
@@ -154,5 +172,15 @@ module Admin
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
raise 'Invalid File Path'
end
# Return an error if trying to import into inventories when inventory is disable
def can_import_into_inventories?
return true if helpers.feature?(:inventory, spree_current_user.enterprises) ||
params.dig(:settings, "import_into") != 'inventories'
redirect_to admin_product_import_url, notice: I18n.t(:product_import_inventory_disable)
false
end
end
end

View File

@@ -142,20 +142,6 @@ module ProductImport
{ entries: entries_json, reset_counts: }
end
def save_results
{
results: {
products_created: products_created_count,
products_updated: products_updated_count,
inventory_created: inventory_created_count,
inventory_updated: inventory_updated_count,
products_reset: products_reset_count,
},
updated_ids:,
errors: errors.full_messages
}
end
def validate_entries
@validator.validate_all(@entries)
end

View File

@@ -4,8 +4,10 @@
%h6= t('admin.product_import.index.choose_import_type')
%br
- options = { "#{t('admin.product_import.index.product_list')}" => :product_list }
- options = options.merge("#{t('admin.product_import.index.inventories')}" => :inventories) if feature?(:inventory, spree_current_user.enterprises)
= select_tag "settings[import_into]",
options_for_select({"#{t('admin.product_import.index.product_list')}" => :product_list, "#{t('admin.product_import.index.inventories')}" => :inventories}),
options_for_select(options),
{ "data-controller": "tom-select", class: "primary inline no-search", "ng-model": "settings.import_into" }
%br
%br

View File

@@ -5,9 +5,10 @@
%i.icon-external-link
= t('admin.product_import.index.product_list_template')
%a.download{href: '/inventory_template.csv'}
%i.icon-external-link
= t('admin.product_import.index.inventory_template')
- if feature?(:inventory, spree_current_user.enterprises)
%a.download{href: '/inventory_template.csv'}
%i.icon-external-link
= t('admin.product_import.index.inventory_template')
%h5= t('admin.product_import.index.category_values')
@@ -27,4 +28,4 @@
%strong= t('admin.product_import.index.shipping_categories')
- @shipping_categories.each do |sc|
%span.category= sc
%span.category= sc

View File

@@ -3462,6 +3462,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
product_importer_products_save_error: did not save any products successfully
product_import_file_not_found_notice: 'File not found or could not be opened'
product_import_no_data_in_spreadsheet_notice: 'No data found in spreadsheet'
product_import_inventory_disable: Importing into inventories is not available
order_choosing_hub_notice: Your hub has been selected.
order_cycle_selecting_notice: Your order cycle has been selected.
adjustments_tax_rate_error: "^Please check that the tax rate for this adjustment is correct."

View File

@@ -3,6 +3,20 @@
require 'spec_helper'
RSpec.describe Admin::ProductImportController do
describe "#import" do
context "when importing into inventory with inventory disabled" do
it "redirect with an error" do
allow(controller).to receive(:spree_current_user).and_return(create(:admin_user))
allow(controller).to receive(:validate_upload_presence).and_return(true)
spree_post :import, { settings: { import_into: "inventories" } }
expect(response).to redirect_to admin_product_import_url
expect(flash[:notice]).to eq "Importing into inventories is not available"
end
end
end
describe 'validate_file_path' do
let(:tmp_directory_base) { Rails.root.join("tmp/product_import-") }

View File

@@ -311,99 +311,101 @@ RSpec.describe "Product Import" do
expect(big_bag.product.id).to eq small_bag.product.id
end
it "can import items into inventory" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, units
Beans, Another Enterprise, User Enterprise, Vegetables, 5, 3.20, 500
Sprouts, Another Enterprise, User Enterprise, Vegetables, 6, 6.50, 500
Cabbage, Another Enterprise, User Enterprise, Vegetables, 2001, 1.50, 500
CSV
File.write('/tmp/test.csv', csv_data)
context "when importing into inventory", feature: :inventory do
it "can import items into inventory" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, units
Beans, Another Enterprise, User Enterprise, Vegetables, 5, 3.20, 500
Sprouts, Another Enterprise, User Enterprise, Vegetables, 6, 6.50, 500
Cabbage, Another Enterprise, User Enterprise, Vegetables, 2001, 1.50, 500
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
proceed_to_validation
expect(page).to have_selector '.item-count', text: "3"
expect(page).not_to have_selector '.invalid-count'
expect(page).not_to have_selector '.create-count'
expect(page).not_to have_selector '.update-count'
expect(page).to have_selector '.inv-create-count', text: "2"
expect(page).to have_selector '.inv-update-count', text: "1"
expect(page).to have_selector '.item-count', text: "3"
expect(page).not_to have_selector '.invalid-count'
expect(page).not_to have_selector '.create-count'
expect(page).not_to have_selector '.update-count'
expect(page).to have_selector '.inv-create-count', text: "2"
expect(page).to have_selector '.inv-update-count', text: "1"
save_data
save_data
expect(page).not_to have_selector '.created-count'
expect(page).not_to have_selector '.updated-count'
expect(page).to have_selector '.inv-created-count', text: '2'
expect(page).to have_selector '.inv-updated-count', text: '1'
expect(page).not_to have_selector '.created-count'
expect(page).not_to have_selector '.updated-count'
expect(page).to have_selector '.inv-created-count', text: '2'
expect(page).to have_selector '.inv-updated-count', text: '1'
beans_override = VariantOverride.where(variant_id: product2.variants.first.id,
hub_id: enterprise2.id).first
sprouts_override = VariantOverride.where(variant_id: product3.variants.first.id,
hub_id: enterprise2.id).first
cabbage_override = VariantOverride.where(variant_id: product4.variants.first.id,
beans_override = VariantOverride.where(variant_id: product2.variants.first.id,
hub_id: enterprise2.id).first
sprouts_override = VariantOverride.where(variant_id: product3.variants.first.id,
hub_id: enterprise2.id).first
cabbage_override = VariantOverride.where(variant_id: product4.variants.first.id,
hub_id: enterprise2.id).first
expect(Float(beans_override.price)).to eq 3.20
expect(beans_override.count_on_hand).to eq 5
expect(Float(beans_override.price)).to eq 3.20
expect(beans_override.count_on_hand).to eq 5
expect(Float(sprouts_override.price)).to eq 6.50
expect(sprouts_override.count_on_hand).to eq 6
expect(Float(sprouts_override.price)).to eq 6.50
expect(sprouts_override.count_on_hand).to eq 6
expect(Float(cabbage_override.price)).to eq 1.50
expect(cabbage_override.count_on_hand).to eq 2001
expect(Float(cabbage_override.price)).to eq 1.50
expect(cabbage_override.count_on_hand).to eq 2001
click_link 'Go To Inventory Page'
expect(page).to have_content 'Inventory'
click_link 'Go To Inventory Page'
expect(page).to have_content 'Inventory'
select enterprise2.name, from: "hub_id", visible: false
select enterprise2.name, from: "hub_id", visible: false
within '#variant-overrides' do
expect(page).to have_content 'Beans'
expect(page).to have_content 'Sprouts'
expect(page).to have_content 'Cabbage'
within '#variant-overrides' do
expect(page).to have_content 'Beans'
expect(page).to have_content 'Sprouts'
expect(page).to have_content 'Cabbage'
end
end
end
it "handles a unit of kg for inventory import" do
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
Beets, Another Enterprise, User Enterprise, Vegetables, , 3.20, kg, 1, 1
CSV
File.write('/tmp/test.csv', csv_data)
it "handles a unit of kg for inventory import" do
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
Beets, Another Enterprise, User Enterprise, Vegetables, , 3.20, kg, 1, 1
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
proceed_to_validation
expect(page).to have_selector '.item-count', text: "1"
expect(page).not_to have_selector '.invalid-count'
expect(page).to have_selector '.inv-create-count', text: '1'
expect(page).to have_selector '.item-count', text: "1"
expect(page).not_to have_selector '.invalid-count'
expect(page).to have_selector '.inv-create-count', text: '1'
save_data
save_data
expect(page).to have_selector '.inv-created-count', text: '1'
expect(page).to have_selector '.inv-created-count', text: '1'
visit main_app.admin_inventory_path
visit main_app.admin_inventory_path
expect(page).to have_content "Beets"
expect(page).to have_select(
"variant-overrides-#{Spree::Product.find_by(name: 'Beets').variants.first.id}-on_demand",
selected: "Yes"
)
expect(page).to have_input(
"variant-overrides-#{Spree::Product.find_by(name: 'Beets').variants.first.id}-price",
with: "3.2"
)
expect(page).to have_content "Beets"
expect(page).to have_select(
"variant-overrides-#{Spree::Product.find_by(name: 'Beets').variants.first.id}-on_demand",
selected: "Yes"
)
expect(page).to have_input(
"variant-overrides-#{Spree::Product.find_by(name: 'Beets').variants.first.id}-price",
with: "3.2"
)
end
end
describe "Item type products" do
@@ -412,150 +414,154 @@ RSpec.describe "Product Import" do
unit_value: '1', variant_unit_scale: nil, variant_unit: "items",
variant_unit_name: "Bag")
}
it "are sucessfully imported to inventory" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "1"
expect(page).not_to have_selector '.invalid-count'
expect(page).to have_selector '.inv-create-count', text: '1'
save_data
context "when importing into inventory", feature: :inventory do
it "are sucessfully imported to inventory" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
CSV
expect(page).to have_selector '.inv-created-count', text: '1'
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "1"
expect(page).not_to have_selector '.invalid-count'
expect(page).to have_selector '.inv-create-count', text: '1'
save_data
visit main_app.admin_inventory_path
expect(page).to have_selector '.inv-created-count', text: '1'
expect(page).to have_content "Aubergine"
expect(page).to have_select(
"variant-overrides-#{Spree::Product.find_by(name: 'Aubergine').variants.first.id}" \
"-on_demand", selected: "Yes"
)
expect(page).to have_input(
"variant-overrides-#{Spree::Product.find_by(name: 'Aubergine').variants.first.id}" \
"-price", with: "3.3"
)
visit main_app.admin_inventory_path
expect(page).to have_content "Aubergine"
expect(page).to have_select(
"variant-overrides-#{Spree::Product.find_by(name: 'Aubergine').variants.first.id}" \
"-on_demand", selected: "Yes"
)
expect(page).to have_input(
"variant-overrides-#{Spree::Product.find_by(name: 'Aubergine').variants.first.id}" \
"-price", with: "3.3"
)
end
it "displays the appropriate error message, when variant unit names are inconsistent" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 6.6, kg, 1, 1, Big-Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "Variant_unit_name must be the same for products " \
"with the same name"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
visit main_app.admin_inventory_path
expect(page).not_to have_content "Aubergine"
end
it "invalidates units value if 0 or non-numeric" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Beans, Another Enterprise, User Enterprise, Vegetables, 3, 3.0, kg, 0, 1, Bag
Cabbage, Another Enterprise, User Enterprise, Vegetables, 1, 4.3, kg, XX, , Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "3"
expect(page).to have_selector '.invalid-count', text: "2"
expect(page).to have_selector '.inv-create-count', text: '1'
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "line 4: Cabbage - Units incorrect value"
expect(page).to have_content "line 3: Beans - Units incorrect value"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Aubergine"
end
it "Price validation" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Beans, Another Enterprise, User Enterprise, Vegetables, 3, , kg, 2, 1, Bag
Cabbage, Another Enterprise, User Enterprise, Vegetables, 1, t6, kg, 3, , Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "3"
expect(page).to have_selector '.invalid-count', text: "2"
expect(page).to have_selector '.inv-create-count', text: '1'
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "line 4: Cabbage - Price incorrect value"
expect(page).to have_content "line 3: Beans - Price can't be blank"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Aubergine"
end
it "handles on_demand and on_hand validations with inventory - nill or empty values" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, units, on_demand
Beans, Another Enterprise, User Enterprise, Vegetables, , 3.20, 500, 1
Sprouts, Another Enterprise, User Enterprise, Vegetables, 6, 6.50, 500, 0
Cabbage, Another Enterprise, User Enterprise, Vegetables, , 1.50, 500,
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 1.50, 500,
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "4"
expect(page).to have_selector '.inv-create-count', text: '2'
expect(page).to have_selector '.invalid-count', text: "2"
find('div.header-description', text: 'Items contain errors').click
expect(page)
.to have_content "line 4: Cabbage - On_hand incorrect value - On_demand incorrect value"
expect(page).to have_content(
"line 5: Aubergine - On_hand incorrect value - On_demand incorrect value"
)
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Beans"
expect(page).not_to have_content "line 3: Sprouts"
end
end
it "displays the appropriate error message, when variant unit names are inconsistent" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 6.6, kg, 1, 1, Big-Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "Variant_unit_name must be the same for products " \
"with the same name"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
visit main_app.admin_inventory_path
expect(page).not_to have_content "Aubergine"
end
it "invalidates units value if 0 or non-numeric" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Beans, Another Enterprise, User Enterprise, Vegetables, 3, 3.0, kg, 0, 1, Bag
Cabbage, Another Enterprise, User Enterprise, Vegetables, 1, 4.3, kg, XX, , Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "3"
expect(page).to have_selector '.invalid-count', text: "2"
expect(page).to have_selector '.inv-create-count', text: '1'
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "line 4: Cabbage - Units incorrect value"
expect(page).to have_content "line 3: Beans - Units incorrect value"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Aubergine"
end
it "Price validation" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, unit_type, units, on_demand, \
variant_unit_name
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 3.3, kg, 1, 1, Bag
Beans, Another Enterprise, User Enterprise, Vegetables, 3, , kg, 2, 1, Bag
Cabbage, Another Enterprise, User Enterprise, Vegetables, 1, t6, kg, 3, , Bag
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "3"
expect(page).to have_selector '.invalid-count', text: "2"
expect(page).to have_selector '.inv-create-count', text: '1'
find('div.header-description', text: 'Items contain errors').click
expect(page).to have_content "line 4: Cabbage - Price incorrect value"
expect(page).to have_content "line 3: Beans - Price can't be blank"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Aubergine"
end
end
it "handles on_demand and on_hand validations with inventory - nill or empty values" do
csv_data = <<~CSV
name, distributor, producer, category, on_hand, price, units, on_demand
Beans, Another Enterprise, User Enterprise, Vegetables, , 3.20, 500, 1
Sprouts, Another Enterprise, User Enterprise, Vegetables, 6, 6.50, 500, 0
Cabbage, Another Enterprise, User Enterprise, Vegetables, , 1.50, 500,
Aubergine, Another Enterprise, User Enterprise, Vegetables, , 1.50, 500,
CSV
File.write('/tmp/test.csv', csv_data)
visit main_app.admin_product_import_path
select 'Inventories', from: "settings_import_into"
attach_file 'file', '/tmp/test.csv'
click_button 'Upload'
proceed_to_validation
expect(page).to have_selector '.item-count', text: "4"
expect(page).to have_selector '.inv-create-count', text: '2'
expect(page).to have_selector '.invalid-count', text: "2"
find('div.header-description', text: 'Items contain errors').click
expect(page)
.to have_content "line 4: Cabbage - On_hand incorrect value - On_demand incorrect value"
expect(page)
.to have_content "line 5: Aubergine - On_hand incorrect value - On_demand incorrect value"
expect(page).to have_content "Imported file contains invalid entries"
expect(page).not_to have_selector 'input[type=submit][value="Save"]'
expect(page).not_to have_content "line 2: Beans"
expect(page).not_to have_content "line 3: Sprouts"
end
it "handles on_demand and on_hand validations - non-numeric values" do