-
-
Notifications
You must be signed in to change notification settings - Fork 708
/
product_import_controller.rb
150 lines (119 loc) · 4.45 KB
/
product_import_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
require 'roo'
module Admin
class ProductImportController < Spree::Admin::BaseController
before_action :validate_upload_presence, except: %i[index guide validate_data]
def index
@product_categories = Spree::Taxon.order('name ASC').pluck(:name).uniq
@tax_categories = Spree::TaxCategory.order('name ASC').pluck(:name)
@shipping_categories = Spree::ShippingCategory.order('name ASC').pluck(:name)
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
managed_product_enterprises.is_primary_producer.by_name.to_a
end
def import
@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)
@non_updatable_fields = ProductImport::EntryValidator.non_updatable_fields
return if contains_errors? @importer
@ams_data = ams_data
end
def validate_data
return unless process_data('validate')
render json: @importer.import_results, response: 200
end
def save_data
return unless process_data('save')
render json: @importer.save_results, response: 200
end
def reset_absent_products
@importer = ProductImport::ProductImporter.new(
File.new(file_path),
spree_current_user,
import_into: params[:import_into],
enterprises_to_reset: params[:enterprises_to_reset],
updated_ids: params[:updated_ids],
settings: params[:settings]
)
if params.key?(:enterprises_to_reset) && params.key?(:updated_ids)
@importer.reset_absent(params[:updated_ids])
end
render json: @importer.products_reset_count
end
private
def validate_upload_presence
return if params[:file] || (params[:filepath] && File.exist?(params[:filepath]))
redirect_to '/admin/product_import', notice: I18n.t(:product_import_file_not_found_notice)
end
def process_data(method)
@importer = ProductImport::ProductImporter.new(
File.new(file_path),
spree_current_user,
start: params[:start],
end: params[:end],
settings: params[:settings]
)
begin
@importer.public_send("#{method}_entries")
rescue StandardError => e
render json: e.message, response: 500
return false
end
true
end
def contains_errors?(importer)
if importer.errors.present?
redirect_to '/admin/product_import', notice: @importer.errors.full_messages.to_sentence
return true
end
check_spreadsheet_has_data importer
end
def check_spreadsheet_has_data(importer)
return if importer.item_count
redirect_to '/admin/product_import',
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
true
end
def save_uploaded_file(upload)
extension = File.extname(upload.original_filename)
directory = Dir.mktmpdir 'product_import'
File.open(File.join(directory, "import#{extension}"), 'wb') do |f|
data = UploadSanitizer.new(upload.read).call
f.write(data)
f.path
end
end
def ams_data
{
filepath: @filepath,
item_count: @importer.item_count,
enterprise_product_counts: @importer.enterprise_products,
import_url: main_app.admin_product_import_process_async_path,
save_url: main_app.admin_product_import_save_async_path,
reset_url: main_app.admin_product_import_reset_async_path,
importSettings: @importer.import_settings,
}
end
# Define custom model class for Cancan permissions
def model_class
ProductImport::ProductImporter
end
def file_path
@file_path ||= validate_file_path(sanitize_file_path(params[:filepath]))
end
def sanitize_file_path(file_path)
FilePathSanitizer.new.sanitize(file_path, on_error: method(:raise_invalid_file_path))
end
def validate_file_path(file_path)
return file_path if file_path.to_s.match?(TEMP_FILE_PATH_REGEX)
raise_invalid_file_path
end
def raise_invalid_file_path
redirect_to '/admin/product_import',
notice: I18n.t(:product_import_no_data_in_spreadsheet_notice)
raise 'Invalid File Path'
end
TEMP_FILE_PATH_REGEX = %r{^/tmp/product_import[A-Za-z0-9-]*/import\.csv$}
end
end