mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge pull request #2474 from Matt-Yorkley/pi/import_options
PI: import options UI
This commit is contained in:
@@ -3,6 +3,7 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
$scope.entries = {}
|
||||
$scope.update_counts = {}
|
||||
$scope.reset_counts = {}
|
||||
$scope.importSettings = null
|
||||
|
||||
$scope.updates = {}
|
||||
$scope.updated_total = 0
|
||||
@@ -72,20 +73,21 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
'end': end
|
||||
'filepath': $scope.filepath
|
||||
'settings': $scope.importSettings
|
||||
).success((data, status, headers, config) ->
|
||||
).success((data, status) ->
|
||||
angular.merge($scope.entries, angular.fromJson(data['entries']))
|
||||
$scope.sortUpdates(data['reset_counts'])
|
||||
|
||||
$scope.updateProgress()
|
||||
).error((data, status, headers, config) ->
|
||||
).error((data, status) ->
|
||||
$scope.exception = data
|
||||
console.error(data)
|
||||
)
|
||||
|
||||
$scope.importSettings = null
|
||||
|
||||
$scope.getSettings = () ->
|
||||
$scope.importSettings = ProductImportService.getSettings()
|
||||
$scope.importSettings = {
|
||||
reset_all_absent: document.getElementsByName('settings[reset_all_absent]')[0].value,
|
||||
import_into: document.getElementsByName('settings[import_into]')[0].value
|
||||
}
|
||||
|
||||
$scope.sortUpdates = (data) ->
|
||||
angular.forEach data, (value, key) ->
|
||||
@@ -104,7 +106,7 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
'end': end
|
||||
'filepath': $scope.filepath
|
||||
'settings': $scope.importSettings
|
||||
).success((data, status, headers, config) ->
|
||||
).success((data, status) ->
|
||||
$scope.sortResults(data['results'])
|
||||
|
||||
angular.forEach data['updated_ids'], (id) ->
|
||||
@@ -114,7 +116,7 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
$scope.update_errors.push(error)
|
||||
|
||||
$scope.updateProgress()
|
||||
).error((data, status, headers, config) ->
|
||||
).error((data, status) ->
|
||||
$scope.exception = data
|
||||
console.error(data)
|
||||
)
|
||||
@@ -129,10 +131,11 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
$scope.updated_total += value
|
||||
|
||||
$scope.resetAbsent = () ->
|
||||
return unless $scope.importSettings['reset_all_absent']
|
||||
enterprises_to_reset = []
|
||||
angular.forEach $scope.importSettings, (settings, enterprise) ->
|
||||
if settings['reset_all_absent']
|
||||
enterprises_to_reset.push(enterprise)
|
||||
|
||||
angular.forEach $scope.reset_counts, (count, enterprise_id) ->
|
||||
enterprises_to_reset.push(enterprise_id)
|
||||
|
||||
if enterprises_to_reset.length && $scope.updated_ids.length
|
||||
$http(
|
||||
@@ -144,11 +147,9 @@ angular.module("admin.productImport").controller "ImportFormCtrl", ($scope, $htt
|
||||
'reset_absent': true,
|
||||
'updated_ids': $scope.updated_ids,
|
||||
'enterprises_to_reset': enterprises_to_reset
|
||||
).success((data, status, headers, config) ->
|
||||
console.log(data)
|
||||
).success((data, status) ->
|
||||
$scope.updates.products_reset = data
|
||||
|
||||
).error((data, status, headers, config) ->
|
||||
).error((data, status) ->
|
||||
console.error(data)
|
||||
)
|
||||
|
||||
|
||||
@@ -2,37 +2,24 @@ angular.module("admin.productImport").controller "ImportOptionsFormCtrl", ($scop
|
||||
|
||||
$scope.initForm = () ->
|
||||
$scope.settings = {} if $scope.settings == undefined
|
||||
$scope.settings[$scope.supplierId] = {
|
||||
import_into: 'product_list'
|
||||
defaults:
|
||||
count_on_hand:
|
||||
mode: 'overwrite_all'
|
||||
on_hand:
|
||||
mode: 'overwrite_all'
|
||||
tax_category_id:
|
||||
mode: 'overwrite_all'
|
||||
shipping_category_id:
|
||||
mode: 'overwrite_all'
|
||||
available_on:
|
||||
mode: 'overwrite_all'
|
||||
$scope.settings = {
|
||||
import_into: 'product_list',
|
||||
reset_all_absent: false
|
||||
}
|
||||
$scope.import_into = 'product_list'
|
||||
|
||||
$scope.updateImportInto = () ->
|
||||
$scope.import_into = $scope.settings[$scope.supplierId]['import_into']
|
||||
|
||||
$scope.$watch 'settings', (updated) ->
|
||||
ProductImportService.updateSettings(updated)
|
||||
, true
|
||||
|
||||
$scope.toggleResetAbsent = (id) ->
|
||||
checked = $scope.settings[id]['reset_all_absent']
|
||||
$scope.toggleResetAbsent = ->
|
||||
checked = $scope.settings['reset_all_absent']
|
||||
confirmed = confirm t('js.product_import.confirmation') if checked
|
||||
|
||||
if confirmed or !checked
|
||||
ProductImportService.updateResetAbsent($scope.supplierId, $scope.reset_counts[$scope.supplierId], checked)
|
||||
else
|
||||
$scope.settings[id]['reset_all_absent'] = false
|
||||
$scope.settings['reset_all_absent'] = false
|
||||
|
||||
$scope.resetTotal = ProductImportService.resetTotal
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ module ProductImport
|
||||
next unless supplier_id && permission_by_id?(supplier_id)
|
||||
|
||||
products_count =
|
||||
if import_into_inventory_by_supplier?(supplier_id)
|
||||
if importing_into_inventory?
|
||||
VariantOverride.where('variant_overrides.hub_id IN (?)', supplier_id).count
|
||||
else
|
||||
Spree::Variant.
|
||||
@@ -57,19 +57,21 @@ module ProductImport
|
||||
def reset_absent_items
|
||||
# For selected enterprises; set stock to zero for all products/inventory
|
||||
# that were not listed in the newly uploaded spreadsheet
|
||||
return if total_saved_count.zero? || @updated_ids.empty? || !@import_settings.key?(:settings)
|
||||
return unless data_for_stock_reset?
|
||||
suppliers_to_reset_products = []
|
||||
suppliers_to_reset_inventories = []
|
||||
|
||||
@import_settings[:settings].each do |enterprise_id, settings|
|
||||
suppliers_to_reset_products.push enterprise_id if settings['reset_all_absent'] && permission_by_id?(enterprise_id) && !import_into_inventory_by_supplier?(enterprise_id)
|
||||
suppliers_to_reset_inventories.push enterprise_id if settings['reset_all_absent'] && permission_by_id?(enterprise_id) && import_into_inventory_by_supplier?(enterprise_id)
|
||||
settings = @import_settings[:settings]
|
||||
|
||||
@import_settings[:enterprises_to_reset].each do |enterprise_id|
|
||||
suppliers_to_reset_products.push Integer(enterprise_id) if settings['reset_all_absent'] && permission_by_id?(enterprise_id) && !importing_into_inventory?
|
||||
suppliers_to_reset_inventories.push Integer(enterprise_id) if settings['reset_all_absent'] && permission_by_id?(enterprise_id) && importing_into_inventory?
|
||||
end
|
||||
|
||||
unless suppliers_to_reset_inventories.empty?
|
||||
@products_reset_count += VariantOverride.
|
||||
where('variant_overrides.hub_id IN (?)
|
||||
AND variant_overrides.id NOT IN (?)', suppliers_to_reset_inventories, @updated_ids).
|
||||
AND variant_overrides.id NOT IN (?)', suppliers_to_reset_inventories, @import_settings[:updated_ids]).
|
||||
update_all(count_on_hand: 0)
|
||||
end
|
||||
|
||||
@@ -79,7 +81,7 @@ module ProductImport
|
||||
where('spree_products.supplier_id IN (?)
|
||||
AND spree_variants.id NOT IN (?)
|
||||
AND spree_variants.is_master = false
|
||||
AND spree_variants.deleted_at IS NULL', suppliers_to_reset_products, @updated_ids).
|
||||
AND spree_variants.deleted_at IS NULL', suppliers_to_reset_products, @import_settings[:updated_ids]).
|
||||
update_all(count_on_hand: 0)
|
||||
end
|
||||
|
||||
@@ -89,6 +91,10 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
def data_for_stock_reset?
|
||||
@import_settings[:settings] && @import_settings[:updated_ids] && @import_settings[:enterprises_to_reset]
|
||||
end
|
||||
|
||||
def save_to_inventory(entry)
|
||||
save_new_inventory_item entry if entry.validates_as? 'new_inventory_item'
|
||||
save_existing_inventory_item entry if entry.validates_as? 'existing_inventory_item'
|
||||
@@ -109,7 +115,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def import_into_inventory?(entry)
|
||||
entry.supplier_id && @import_settings[:settings][entry.supplier_id.to_s]['import_into'] == 'inventories'
|
||||
entry.supplier_id && @import_settings[:settings]['import_into'] == 'inventories'
|
||||
end
|
||||
|
||||
def save_new_inventory_item(entry)
|
||||
@@ -227,8 +233,8 @@ module ProductImport
|
||||
@editable_enterprises.value?(Integer(supplier_id))
|
||||
end
|
||||
|
||||
def import_into_inventory_by_supplier?(supplier_id)
|
||||
@import_settings[:settings] && @import_settings[:settings][supplier_id.to_s] && @import_settings[:settings][supplier_id.to_s]['import_into'] == 'inventories'
|
||||
def importing_into_inventory?
|
||||
@import_settings[:settings] && @import_settings[:settings]['import_into'] == 'inventories'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -221,7 +221,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def import_into_inventory?(entry)
|
||||
entry.supplier_id && @import_settings[:settings][entry.supplier_id.to_s]['import_into'] == 'inventories'
|
||||
entry.supplier_id && @import_settings[:settings]['import_into'] == 'inventories'
|
||||
end
|
||||
|
||||
def validate_inventory_item(entry, variant_override)
|
||||
|
||||
@@ -6,7 +6,7 @@ module ProductImport
|
||||
include ActiveModel::Conversion
|
||||
include ActiveModel::Validations
|
||||
|
||||
attr_reader :updated_ids
|
||||
attr_reader :updated_ids, :import_settings
|
||||
|
||||
def initialize(file, current_user, import_settings = {})
|
||||
unless file.is_a?(File)
|
||||
|
||||
@@ -3,38 +3,31 @@
|
||||
|
||||
- @importer.suppliers_index.each do |name, supplier_id|
|
||||
- if name and supplier_id and @importer.permission_by_id?(supplier_id)
|
||||
%div.panel-section.import-settings{ng: {controller: 'DropdownPanelsCtrl'}}
|
||||
%div.panel-section.import-settings
|
||||
%div.panel-header{ng: {click: 'togglePanel()', class: '{active: active}'}}
|
||||
%div.header-caret
|
||||
%i{ng: {class: "{'icon-chevron-down': active, 'icon-chevron-right': !active}"}}
|
||||
%div.header-icon.neutral
|
||||
%i.fa.fa-edit
|
||||
%div.header-icon.success
|
||||
%i.fa.fa-check-circle
|
||||
%div.header-description
|
||||
= name
|
||||
%div.panel-content{ng: {hide: '!active'}}
|
||||
= render 'options_form', supplier_id: supplier_id, name: name
|
||||
- elsif name and supplier_id
|
||||
%div.panel-section.import-settings{ng: {controller: 'DropdownPanelsCtrl'}}
|
||||
%div.panel-section.import-settings
|
||||
%div.panel-header
|
||||
%div.header-caret
|
||||
%div.header-icon.error
|
||||
%i.fa.fa-warning
|
||||
%div.header-description
|
||||
= name
|
||||
%span.header-error= " - #{t('admin.product_import.import.no_permission')}"
|
||||
- elsif name
|
||||
%div.panel-section.import-settings{ng: {controller: 'DropdownPanelsCtrl'}}
|
||||
%div.panel-section.import-settings
|
||||
%div.panel-header
|
||||
%div.header-caret
|
||||
%div.header-icon.error
|
||||
%i.fa.fa-warning
|
||||
%div.header-description
|
||||
= name
|
||||
%span.header-error= " - #{t('admin.product_import.import.not_found')}"
|
||||
- else
|
||||
%div.panel-section.import-settings{ng: {controller: 'DropdownPanelsCtrl'}}
|
||||
%div.panel-section.import-settings
|
||||
%div.panel-header
|
||||
%div.header-caret
|
||||
%div.header-icon.error
|
||||
%i.fa.fa-warning
|
||||
%div.header-description
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
%table.import-settings{ng: {controller: 'ImportOptionsFormCtrl', init: "supplierId = #{supplier_id}; initForm()"}}
|
||||
%tr.import-into
|
||||
%td.description
|
||||
Import Into:
|
||||
%td
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][import_into]", options_for_select({"Product List" => :product_list, "Inventories" => :inventories}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['import_into']", 'ng-change' => "updateImportInto()"}
|
||||
%td
|
||||
|
||||
%tr.stock-level.inventory{ng: {show: 'import_into == "inventories"'}}
|
||||
%td.description
|
||||
= t('admin.product_import.import.default_stock')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][defaults][count_on_hand][active]", 1, false, 'ng-model' => "settings[#{supplier_id}]['defaults']['count_on_hand']['active']"
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][count_on_hand][mode]", options_for_select({"#{t('admin.product_import.import.overwrite_all')}" => :overwrite_all, "#{t('admin.product_import.import.overwrite_empty')}" => :overwrite_empty}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['count_on_hand']['mode']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['count_on_hand']['active']"}
|
||||
%td
|
||||
= number_field_tag "settings[#{supplier_id}][defaults][count_on_hand][value]", 0, 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['count_on_hand']['active']", 'ng-model' => "settings[#{supplier_id}]['defaults']['count_on_hand']['value']"
|
||||
|
||||
%tr.stock-level.productlist{ng: {show: 'import_into == "product_list"'}}
|
||||
%td.description
|
||||
= t('admin.product_import.import.default_stock')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][defaults][on_hand][active]", 1, false, 'ng-model' => "settings[#{supplier_id}]['defaults']['on_hand']['active']"
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][on_hand][mode]", options_for_select({"#{t('admin.product_import.import.overwrite_all')}" => :overwrite_all, "#{t('admin.product_import.import.overwrite_empty')}" => :overwrite_empty}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['on_hand']['mode']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['on_hand']['active']"}
|
||||
%td
|
||||
= number_field_tag "settings[#{supplier_id}][defaults][on_hand][value]", 0, 'ng-model' => "settings[#{supplier_id}]['defaults']['on_hand']['value']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['on_hand']['active']"
|
||||
|
||||
%tr.tax-category{ng: {show: 'import_into == "product_list"'}}
|
||||
%td.description
|
||||
= t('admin.product_import.import.default_tax_cat')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][defaults][tax_category_id][active]", 1, false, 'ng-model' => "settings[#{supplier_id}]['defaults']['tax_category_id']['active']"
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][tax_category_id][mode]", options_for_select({"#{t('admin.product_import.import.overwrite_all')}" => :overwrite_all, "#{t('admin.product_import.import.overwrite_empty')}" => :overwrite_empty}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['tax_category_id']['mode']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['tax_category_id']['active']"}
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][tax_category_id][value]", options_for_select(@tax_categories.map {|tc| [tc.name, tc.id]}), {prompt: 'None', class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['tax_category_id']['value']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['tax_category_id']['active']"}
|
||||
|
||||
%tr.shipping-category{ng: {show: 'import_into == "product_list"'}}
|
||||
%td.description
|
||||
= t('admin.product_import.import.default_shipping_cat')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][defaults][shipping_category_id][active]", 1, false, 'ng-model' => "settings[#{supplier_id}]['defaults']['shipping_category_id']['active']"
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][shipping_category_id][mode]", options_for_select({"#{t('admin.product_import.import.overwrite_all')}" => :overwrite_all, "#{t('admin.product_import.import.overwrite_empty')}" => :overwrite_empty}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['shipping_category_id']['mode']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['shipping_category_id']['active']"}
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][shipping_category_id][value]", options_for_select(@shipping_categories.map {|sc| [sc.name, sc.id]}), {prompt: 'None', class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['shipping_category_id']['value']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['shipping_category_id']['active']"}
|
||||
|
||||
%tr.available-date{ng: {show: 'import_into == "product_list"'}}
|
||||
%td.description
|
||||
= t('admin.product_import.import.default_available_date')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][defaults][available_on][active]", 1, false, 'ng-model' => "settings[#{supplier_id}]['defaults']['available_on']['active']"
|
||||
%td
|
||||
= select_tag "settings[#{supplier_id}][defaults][available_on][mode]", options_for_select({"#{t('admin.product_import.import.overwrite_all')}" => :overwrite_all, "#{t('admin.product_import.import.overwrite_empty')}" => :overwrite_empty}), {class: 'select2 fullwidth select2-no-search', 'ng-model' => "settings[#{supplier_id}]['defaults']['available_on']['mode']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['available_on']['active']"}
|
||||
%td
|
||||
= text_field_tag "settings[#{supplier_id}][defaults][available_on][value]", nil, {class: 'datepicker', placeholder: 'Today', 'ng-model' => "settings[#{supplier_id}]['defaults']['available_on']['value']", 'ng-disabled' => "!settings[#{supplier_id}]['defaults']['available_on']['active']"}
|
||||
|
||||
%tr.reset-absent
|
||||
%td.description
|
||||
= t('admin.product_import.import.reset_absent?')
|
||||
%td
|
||||
= check_box_tag "settings[#{supplier_id}][reset_all_absent]", 1, false, :'ng-model' => "settings[#{supplier_id}]['reset_all_absent']", :'ng-change' => "toggleResetAbsent('#{supplier_id}')"
|
||||
%td
|
||||
%td
|
||||
@@ -1,11 +1,30 @@
|
||||
%div{ng: {app: 'admin.productImport'}}
|
||||
%div{ng: {app: 'admin.productImport', controller: 'ImportOptionsFormCtrl', init: "initForm()"}}
|
||||
|
||||
%h5= t('admin.product_import.index.select_file')
|
||||
%br
|
||||
= form_tag main_app.admin_product_import_path, multipart: true, class: 'product-import' do
|
||||
%label #{t('admin.product_import.index.spreadsheet')}
|
||||
|
||||
%h6= t('admin.product_import.index.choose_import_type')
|
||||
%br
|
||||
= select_tag "settings[import_into]", options_for_select({"#{t('admin.product_import.index.product_list')}" => :product_list, "#{t('admin.product_import.index.inventories')}" => :inventories}), {class: 'select2 select2-no-search', 'ng-model' => 'settings.import_into'}
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
|
||||
%h6= t('admin.product_import.index.select_file')
|
||||
%br
|
||||
= file_field_tag :file
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
|
||||
%h6= t('admin.product_import.import.reset_absent?')
|
||||
%br
|
||||
= hidden_field_tag "settings[reset_all_absent]", nil
|
||||
= check_box_tag "settings[reset_all_absent]", true, false, 'ng-model' => 'settings.reset_all_absent'
|
||||
%span= t('admin.product_import.import.reset_absent_tip')
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
|
||||
= submit_tag "#{t('admin.product_import.index.upload')}"
|
||||
%br
|
||||
%br
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
.import-wrapper{ng: {app: 'admin.productImport', controller: 'ImportFormCtrl', init: "supplier_product_counts = #{@importer.supplier_products.to_json}"}}
|
||||
|
||||
= hidden_field_tag "settings[reset_all_absent]", @importer.import_settings['reset_all_absent'], 'ng-model' => "importSettings[reset_all_absent]"
|
||||
= hidden_field_tag "settings[import_into]", @importer.import_settings['import_into'], 'ng-model' => "importSettings[import_into]"
|
||||
|
||||
- if @importer.item_count == 0 #and @importer.invalid_count
|
||||
%h5
|
||||
= t('.no_valid_entries')
|
||||
|
||||
@@ -466,7 +466,8 @@ en:
|
||||
index:
|
||||
select_file: Select a spreadsheet to upload
|
||||
spreadsheet: Spreadsheet
|
||||
import_into: "Import into:"
|
||||
choose_import_type: Select import type
|
||||
import_into: Import type
|
||||
product_list: Product list
|
||||
inventories: Inventories
|
||||
import: Import
|
||||
@@ -496,7 +497,8 @@ en:
|
||||
not_found: enterprise could not be found in database
|
||||
no_name: No name
|
||||
blank_supplier: some products have blank supplier name
|
||||
reset_absent?: Reset absent products?
|
||||
reset_absent?: Reset absent products
|
||||
reset_absent_tip: Set stock to zero for all exiting products not present in the file
|
||||
overwrite_all: Overwrite all
|
||||
overwrite_empty: Overwrite if empty
|
||||
default_stock: Set stock level
|
||||
|
||||
@@ -195,6 +195,39 @@ feature "Product Import", js: true do
|
||||
expect(page).to_not have_field "product_name", with: product2.name
|
||||
end
|
||||
|
||||
it "can reset product stock to zero for products not present in the CSV" do
|
||||
csv_data = CSV.generate do |csv|
|
||||
csv << ["name", "supplier", "category", "on_hand", "price", "units", "unit_type"]
|
||||
csv << ["Carrots", "User Enterprise", "Vegetables", "500", "3.20", "500", "g"]
|
||||
end
|
||||
File.write('/tmp/test.csv', csv_data)
|
||||
|
||||
visit main_app.admin_product_import_path
|
||||
|
||||
attach_file 'file', '/tmp/test.csv'
|
||||
|
||||
check "settings_reset_all_absent"
|
||||
|
||||
click_button 'Upload'
|
||||
|
||||
expect(page).to have_selector 'a.button.proceed', visible: true
|
||||
click_link 'Proceed'
|
||||
|
||||
import_data
|
||||
|
||||
expect(page).to have_selector 'a.button.proceed', visible: true
|
||||
click_link 'Proceed'
|
||||
|
||||
save_data
|
||||
|
||||
expect(page).to have_selector '.created-count', text: '1'
|
||||
expect(page).to have_selector '.reset-count', text: '3'
|
||||
|
||||
expect(Spree::Product.find_by_name('Carrots').on_hand).to eq 500
|
||||
expect(Spree::Product.find_by_name('Cabbage').on_hand).to eq 0
|
||||
expect(Spree::Product.find_by_name('Beans').on_hand).to eq 0
|
||||
end
|
||||
|
||||
it "can import items into inventory" do
|
||||
csv_data = CSV.generate do |csv|
|
||||
csv << ["name", "supplier", "producer", "category", "on_hand", "price", "units"]
|
||||
@@ -205,14 +238,10 @@ feature "Product Import", js: true do
|
||||
File.write('/tmp/test.csv', csv_data)
|
||||
|
||||
visit main_app.admin_product_import_path
|
||||
select2_select I18n.t('admin.product_import.index.inventories'), from: "settings_import_into"
|
||||
attach_file 'file', '/tmp/test.csv'
|
||||
click_button 'Upload'
|
||||
|
||||
within 'div.import-settings' do
|
||||
find('div.header-description').click # Import settings tab
|
||||
select 'Inventories', from: "settings_#{enterprise2.id.to_s}_import_into", visible: false
|
||||
end
|
||||
|
||||
expect(page).to have_selector 'a.button.proceed', visible: true
|
||||
click_link 'Proceed'
|
||||
|
||||
@@ -259,76 +288,6 @@ feature "Product Import", js: true do
|
||||
expect(page).to have_content 'Cabbage'
|
||||
end
|
||||
end
|
||||
|
||||
it "can override import fields via the import settings tab" do
|
||||
csv_data = CSV.generate do |csv|
|
||||
csv << ["name", "supplier", "category", "on_hand", "price", "units", "unit_type", "tax_category", "shipping_category"]
|
||||
csv << ["Carrots", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", tax_category.name, shipping_category.name]
|
||||
csv << ["Pumpkin", "User Enterprise", "Vegetables", "3", "3.50", "1", "kg", tax_category.name, ""]
|
||||
csv << ["Spinach", "User Enterprise", "Vegetables", "7", "3.60", "1", "kg", "", shipping_category.name]
|
||||
end
|
||||
File.write('/tmp/test.csv', csv_data)
|
||||
|
||||
visit main_app.admin_product_import_path
|
||||
|
||||
expect(page).to have_content "Select a spreadsheet to upload"
|
||||
attach_file 'file', '/tmp/test.csv'
|
||||
click_button 'Upload'
|
||||
|
||||
within 'div.import-settings' do
|
||||
find('div.panel-header').click
|
||||
|
||||
within 'tr.stock-level.productlist' do
|
||||
find('input[type="checkbox"]').click
|
||||
select 'Overwrite all', from: "settings_#{enterprise.id}_defaults_on_hand_mode", visible: false
|
||||
fill_in "settings_#{enterprise.id}_defaults_on_hand_value", with: 9000
|
||||
end
|
||||
|
||||
within 'tr.tax-category' do
|
||||
find('input[type="checkbox"]').click
|
||||
select 'Overwrite if empty', from: "settings_#{enterprise.id}_defaults_tax_category_id_mode", visible: false
|
||||
select tax_category2.name, from: "settings_#{enterprise.id}_defaults_tax_category_id_value", visible: false
|
||||
end
|
||||
|
||||
within 'tr.shipping-category' do
|
||||
find('input[type="checkbox"]').click
|
||||
select 'Overwrite all', from: "settings_#{enterprise.id}_defaults_shipping_category_id_mode", visible: false
|
||||
select shipping_category.name, from: "settings_#{enterprise.id}_defaults_shipping_category_id_value", visible: false
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).to have_selector 'a.button.proceed', visible: true
|
||||
click_link 'Proceed'
|
||||
|
||||
import_data
|
||||
|
||||
expect(page).to have_selector '.item-count', text: "3"
|
||||
expect(page).to have_selector '.create-count', text: "3"
|
||||
expect(page).to_not have_selector '.update-count'
|
||||
|
||||
expect(page).to have_selector 'a.button.proceed', visible: true
|
||||
click_link 'Proceed'
|
||||
|
||||
save_data
|
||||
|
||||
expect(page).to have_selector '.created-count', text: '3'
|
||||
expect(page).to_not have_selector '.updated-count'
|
||||
|
||||
carrots = Spree::Product.find_by_name('Carrots')
|
||||
expect(carrots.tax_category).to eq tax_category
|
||||
expect(carrots.shipping_category).to eq shipping_category
|
||||
expect(carrots.count_on_hand).to eq 9000
|
||||
|
||||
pumpkin = Spree::Product.find_by_name('Pumpkin')
|
||||
expect(pumpkin.tax_category).to eq tax_category
|
||||
expect(pumpkin.shipping_category).to eq shipping_category
|
||||
expect(pumpkin.count_on_hand).to eq 9000
|
||||
|
||||
spinach = Spree::Product.find_by_name('Spinach')
|
||||
expect(spinach.tax_category).to eq tax_category2
|
||||
expect(spinach.shipping_category).to eq shipping_category
|
||||
expect(spinach.count_on_hand).to eq 9000
|
||||
end
|
||||
end
|
||||
|
||||
describe "when dealing with uploaded files" do
|
||||
|
||||
@@ -44,7 +44,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'product_list'}}
|
||||
settings = {'import_into' => 'product_list'}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
end
|
||||
after { File.delete('/tmp/test-m.csv') }
|
||||
@@ -131,7 +131,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'product_list'}}
|
||||
settings = {'import_into' => 'product_list'}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
end
|
||||
after { File.delete('/tmp/test-m.csv') }
|
||||
@@ -303,7 +303,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise2.id.to_s => {'import_into' => 'inventories'}}
|
||||
settings = {'import_into' => 'inventories'}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
end
|
||||
after { File.delete('/tmp/test-m.csv') }
|
||||
@@ -341,54 +341,6 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
end
|
||||
|
||||
describe "importing items into inventory and product list simultaneously" do
|
||||
before do
|
||||
csv_data = CSV.generate do |csv|
|
||||
csv << ["name", "supplier", "producer", "category", "on_hand", "price", "units", "unit_type"]
|
||||
csv << ["Beans", "Another Enterprise", "User Enterprise", "Vegetables", "5", "3.20", "500", ""]
|
||||
csv << ["Sprouts", "Another Enterprise", "User Enterprise", "Vegetables", "6", "6.50", "500", ""]
|
||||
csv << ["Garbanzos", "User Enterprise", "", "Vegetables", "2001", "1.50", "500", "g"]
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'product_list'}, enterprise2.id.to_s => {'import_into' => 'inventories'}}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
end
|
||||
after { File.delete('/tmp/test-m.csv') }
|
||||
|
||||
it "validates entries" do
|
||||
@importer.validate_entries
|
||||
entries = JSON.parse(@importer.entries_json)
|
||||
|
||||
expect(filter('valid', entries)).to eq 3
|
||||
expect(filter('invalid', entries)).to eq 0
|
||||
expect(filter('create_inventory', entries)).to eq 2
|
||||
expect(filter('create_product', entries)).to eq 1
|
||||
end
|
||||
|
||||
it "saves and updates inventory" do
|
||||
@importer.save_entries
|
||||
|
||||
expect(@importer.inventory_created_count).to eq 2
|
||||
expect(@importer.products_created_count).to eq 1
|
||||
expect(@importer.updated_ids).to be_a(Array)
|
||||
expect(@importer.updated_ids.count).to eq 3
|
||||
|
||||
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
|
||||
garbanzos = Spree::Product.where(name: "Garbanzos").first
|
||||
|
||||
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(garbanzos.price)).to eq 1.50
|
||||
expect(garbanzos.count_on_hand).to eq 2001
|
||||
end
|
||||
end
|
||||
|
||||
describe "handling enterprise permissions" do
|
||||
after { File.delete('/tmp/test-m.csv') }
|
||||
|
||||
@@ -400,7 +352,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'product_list'}, enterprise2.id.to_s => {'import_into' => 'product_list'}}
|
||||
settings = {'import_into' => 'product_list'}
|
||||
@importer = ProductImport::ProductImporter.new(file, user, start: 1, end: 100, settings: settings)
|
||||
|
||||
@importer.validate_entries
|
||||
@@ -427,7 +379,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise2.id.to_s => {'import_into' => 'inventories'}}
|
||||
settings = {'import_into' => 'inventories'}
|
||||
@importer = ProductImport::ProductImporter.new(file, user2, start: 1, end: 100, settings: settings)
|
||||
|
||||
@importer.validate_entries
|
||||
@@ -455,7 +407,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'inventories'}}
|
||||
settings = {'import_into' => 'inventories'}
|
||||
@importer = ProductImport::ProductImporter.new(file, user2, start: 1, end: 100, settings: settings)
|
||||
|
||||
@importer.validate_entries
|
||||
@@ -484,7 +436,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise.id.to_s => {'import_into' => 'product_list', 'reset_all_absent' => true}}
|
||||
settings = {'import_into' => 'product_list', 'reset_all_absent' => true}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
|
||||
@importer.validate_entries
|
||||
@@ -502,7 +454,9 @@ describe ProductImport::ProductImporter do
|
||||
expect(@importer.updated_ids).to be_a(Array)
|
||||
expect(@importer.updated_ids.count).to eq 2
|
||||
|
||||
@importer.reset_absent(@importer.updated_ids)
|
||||
updated_ids = @importer.updated_ids
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, updated_ids: updated_ids, enterprises_to_reset: [enterprise.id], settings: settings)
|
||||
@importer.reset_absent(updated_ids)
|
||||
|
||||
expect(@importer.products_reset_count).to eq 2
|
||||
|
||||
@@ -521,7 +475,7 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
settings = {enterprise2.id.to_s => {'import_into' => 'inventories', 'reset_all_absent' => true}}
|
||||
settings = {'import_into' => 'inventories', 'reset_all_absent' => true}
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, settings: settings)
|
||||
|
||||
@importer.validate_entries
|
||||
@@ -537,7 +491,9 @@ describe ProductImport::ProductImporter do
|
||||
expect(@importer.updated_ids).to be_a(Array)
|
||||
expect(@importer.updated_ids.count).to eq 2
|
||||
|
||||
@importer.reset_absent(@importer.updated_ids)
|
||||
updated_ids = @importer.updated_ids
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, updated_ids: updated_ids, enterprises_to_reset: [enterprise2.id], settings: settings)
|
||||
@importer.reset_absent(updated_ids)
|
||||
|
||||
# expect(@importer.products_reset_count).to eq 1
|
||||
|
||||
@@ -614,53 +570,6 @@ describe ProductImport::ProductImporter do
|
||||
expect(potatoes.shipping_category_id).to eq shipping_category.id
|
||||
expect(potatoes.available_on).to be_within(1.day).of(Time.zone.local(2020, 1, 1))
|
||||
end
|
||||
|
||||
it "can overwrite fields with selected defaults when importing to inventory" do
|
||||
csv_data = CSV.generate do |csv|
|
||||
csv << ["name", "producer", "supplier", "on_hand", "price", "units", "unit_type"]
|
||||
csv << ["Beans", "User Enterprise", "Another Enterprise", "", "3.20", "500", "g"]
|
||||
csv << ["Sprouts", "User Enterprise", "Another Enterprise", "7", "6.50", "500", "g"]
|
||||
csv << ["Cabbage", "User Enterprise", "Another Enterprise", "", "1.50", "500", "g"]
|
||||
end
|
||||
File.write('/tmp/test-m.csv', csv_data)
|
||||
file = File.new('/tmp/test-m.csv')
|
||||
|
||||
import_settings = {enterprise2.id.to_s => {
|
||||
'import_into' => 'inventories',
|
||||
'defaults' => {
|
||||
'count_on_hand' => {
|
||||
'active' => true,
|
||||
'mode' => 'overwrite_empty',
|
||||
'value' => '9000'
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@importer = ProductImport::ProductImporter.new(file, admin, start: 1, end: 100, import_into: 'inventories', settings: import_settings)
|
||||
|
||||
@importer.validate_entries
|
||||
entries = JSON.parse(@importer.entries_json)
|
||||
|
||||
expect(filter('valid', entries)).to eq 3
|
||||
expect(filter('invalid', entries)).to eq 0
|
||||
expect(filter('create_inventory', entries)).to eq 2
|
||||
expect(filter('update_inventory', entries)).to eq 1
|
||||
|
||||
@importer.save_entries
|
||||
|
||||
expect(@importer.inventory_created_count).to eq 2
|
||||
expect(@importer.inventory_updated_count).to eq 1
|
||||
expect(@importer.updated_ids).to be_a(Array)
|
||||
expect(@importer.updated_ids.count).to eq 3
|
||||
|
||||
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(beans_override.count_on_hand).to eq 9000
|
||||
expect(sprouts_override.count_on_hand).to eq 7
|
||||
expect(cabbage_override.count_on_hand).to eq 9000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user