tallty_import_export 1.1.0 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +13 -9
- data/lib/tallty_import_export/attr/export_header.rb +1 -1
- data/lib/tallty_import_export/common.rb +2 -2
- data/lib/tallty_import_export/excel.rb +1 -0
- data/lib/tallty_import_export/export.rb +33 -23
- data/lib/tallty_import_export/export_form.rb +1 -1
- data/lib/tallty_import_export/import.rb +68 -28
- data/lib/tallty_import_export/importable.rb +4 -0
- data/lib/tallty_import_export/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 284928193ebed0e079f44ba98ee7a2f0d51c05f0c1ea5100dd68973940f56369
|
4
|
+
data.tar.gz: 75dbf1351c7a08ce445b508ea60aba31da811fcfc87e9355c5f8c710f66be47a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d335d50b6059608dcdb41cc3f44e16f75746d900d698ff1ea3960de8d2541b0fdfadf9b7fceeadef33f70906a3c4673f8247c6aa9406195826f0b45a9977d5e
|
7
|
+
data.tar.gz: e72f4ddf2a9bb43f00d031aa74c56723870b63ce0b548110d6c3112a0945dbd21f789759a88834fb1101f24c61e30ce179bd14dea19001c2e4bb81f5e7721c9e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tallty_import_export (1.
|
4
|
+
tallty_import_export (1.1.1)
|
5
5
|
activesupport
|
6
6
|
attr_json
|
7
7
|
caxlsx
|
@@ -27,27 +27,31 @@ GEM
|
|
27
27
|
tzinfo (~> 2.0)
|
28
28
|
attr_json (1.4.0)
|
29
29
|
activerecord (>= 5.0.0, < 7.1)
|
30
|
-
caxlsx (3.
|
30
|
+
caxlsx (3.3.0)
|
31
31
|
htmlentities (~> 4.3, >= 4.3.4)
|
32
32
|
marcel (~> 1.0)
|
33
33
|
nokogiri (~> 1.10, >= 1.10.4)
|
34
34
|
rubyzip (>= 1.3.0, < 3)
|
35
35
|
concurrent-ruby (1.1.10)
|
36
|
+
connection_pool (2.3.0)
|
36
37
|
diff-lcs (1.4.4)
|
37
38
|
htmlentities (4.3.4)
|
38
|
-
i18n (1.
|
39
|
+
i18n (1.12.0)
|
39
40
|
concurrent-ruby (~> 1.0)
|
40
41
|
marcel (1.0.2)
|
41
42
|
mini_portile2 (2.8.0)
|
42
|
-
minitest (5.
|
43
|
-
nokogiri (1.13.
|
43
|
+
minitest (5.16.3)
|
44
|
+
nokogiri (1.13.9)
|
44
45
|
mini_portile2 (~> 2.8.0)
|
45
46
|
racc (~> 1.4)
|
46
47
|
racc (1.6.0)
|
47
48
|
rake (12.3.3)
|
48
|
-
redis (
|
49
|
-
|
50
|
-
|
49
|
+
redis (5.0.5)
|
50
|
+
redis-client (>= 0.9.0)
|
51
|
+
redis-client (0.10.0)
|
52
|
+
connection_pool
|
53
|
+
redis-objects (1.7.0)
|
54
|
+
redis
|
51
55
|
roo (2.9.0)
|
52
56
|
nokogiri (~> 1)
|
53
57
|
rubyzip (>= 1.3.0, < 3.0.0)
|
@@ -77,7 +81,7 @@ GEM
|
|
77
81
|
activesupport (>= 5.0)
|
78
82
|
tallty_form (1.0.0)
|
79
83
|
tallty_duck_record
|
80
|
-
tzinfo (2.0.
|
84
|
+
tzinfo (2.0.5)
|
81
85
|
concurrent-ruby (~> 1.0)
|
82
86
|
zip-zip (0.3)
|
83
87
|
rubyzip (>= 1.0.0)
|
@@ -14,7 +14,7 @@ module TalltyImportExport
|
|
14
14
|
attr_json :json, :string
|
15
15
|
attr_json :select, ActiveModel::Type::Value.new, array: true
|
16
16
|
attr_json :source, :boolean
|
17
|
-
attr_json :proc, ActiveModel::Type::Value.new
|
17
|
+
attr_json :proc, ActiveModel::Type::Value.new
|
18
18
|
attr_json :children, self.to_type, array: true
|
19
19
|
|
20
20
|
attr_accessor :depth, :parent_path, :seq
|
@@ -6,14 +6,14 @@ module TalltyImportExport
|
|
6
6
|
end
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
def model_headers
|
9
|
+
def model_headers(**args)
|
10
10
|
columns.map do |column|
|
11
11
|
{
|
12
12
|
key: column.name,
|
13
13
|
name: column.comment || column.name,
|
14
14
|
attr_type: column.type,
|
15
15
|
format: column.type == :string ? :string : nil,
|
16
|
-
primary_key: column.name == 'id'
|
16
|
+
primary_key: column.name == 'id',
|
17
17
|
}
|
18
18
|
end
|
19
19
|
end
|
@@ -2,7 +2,7 @@ module TalltyImportExport
|
|
2
2
|
class Export
|
3
3
|
attr_reader :klass, :context
|
4
4
|
|
5
|
-
def initialize
|
5
|
+
def initialize(klass)
|
6
6
|
@klass = klass
|
7
7
|
@context = Context.new({})
|
8
8
|
end
|
@@ -34,7 +34,7 @@ module TalltyImportExport
|
|
34
34
|
# proc: proc或者lamda,支持call,传入 record 和 context
|
35
35
|
# list: 对于list布局的,进行嵌套,生成子表格
|
36
36
|
|
37
|
-
def export_xlsx
|
37
|
+
def export_xlsx(records, **options)
|
38
38
|
records = with_scope records
|
39
39
|
process_options(options)
|
40
40
|
|
@@ -46,14 +46,16 @@ module TalltyImportExport
|
|
46
46
|
|
47
47
|
if @group_by.present?
|
48
48
|
if records.is_a?(Array)
|
49
|
-
records.group_by { |record| record.send(@group_by)}.each do |key, group_records|
|
49
|
+
records.group_by { |record| record.send(@group_by) }.each do |key, group_records|
|
50
50
|
next unless key.present?
|
51
|
+
|
51
52
|
@group_key = key
|
52
53
|
export_workbook workbook, group_records, **options
|
53
54
|
end
|
54
55
|
else
|
55
56
|
records.group(@group_by).count.keys.each do |key|
|
56
57
|
next unless key.present?
|
58
|
+
|
57
59
|
@group_key = key
|
58
60
|
export_workbook workbook, records.ransack("#{@group_where}" => key).result, **options
|
59
61
|
end
|
@@ -72,16 +74,16 @@ module TalltyImportExport
|
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
|
-
def export_workbook
|
77
|
+
def export_workbook(workbook, association_records, **options)
|
76
78
|
# excel导出样式
|
77
79
|
alignment = { vertical: :center, horizontal: :center }
|
78
80
|
border = { color: '969696', style: :thin }
|
79
81
|
title1 = workbook.styles.add_style(alignment: alignment, border: border, sz: 12, b: true)
|
80
|
-
title2 = workbook.styles.add_style(alignment: alignment, border: border, bg_color:
|
82
|
+
title2 = workbook.styles.add_style(alignment: alignment, border: border, bg_color: '2a5caa', sz: 12, fg_color: 'fffffb')
|
81
83
|
title3 = workbook.styles.add_style(alignment: alignment.merge(wrap_text: true), border: border, sz: 10)
|
82
|
-
headers = export_headers_result
|
84
|
+
headers = export_headers_result(**options)
|
83
85
|
|
84
|
-
_sheet_name = respond_to?(:sheet_name) ?
|
86
|
+
_sheet_name = respond_to?(:sheet_name) ? sheet_name : nil
|
85
87
|
|
86
88
|
workbook.add_worksheet(name: _sheet_name) do |sheet|
|
87
89
|
if respond_to?(:first_header)
|
@@ -90,7 +92,7 @@ module TalltyImportExport
|
|
90
92
|
sheet.add_row [first_header], style: title1, height: 30
|
91
93
|
end
|
92
94
|
|
93
|
-
sheet.add_row headers.map{|header| header[:name]}, style: title2, height: 25
|
95
|
+
sheet.add_row headers.map { |header| header[:name] }, style: title2, height: 25
|
94
96
|
|
95
97
|
last_row = nil
|
96
98
|
merge_column_hash = {}
|
@@ -133,12 +135,12 @@ module TalltyImportExport
|
|
133
135
|
merge_column_hash.each do |col_index, row_arr|
|
134
136
|
row_arr.each do |arr|
|
135
137
|
sheet.merge_cells(
|
136
|
-
Axlsx
|
138
|
+
Axlsx.cell_r(col_index, arr.first) + ':' + Axlsx.cell_r(col_index, arr.last),
|
137
139
|
)
|
138
140
|
end
|
139
141
|
end
|
140
142
|
end
|
141
|
-
sheet.column_widths(*headers.map{|header| (header[:width] || @width).to_f})
|
143
|
+
sheet.column_widths(*headers.map { |header| (header[:width] || @width).to_f })
|
142
144
|
end
|
143
145
|
end
|
144
146
|
|
@@ -147,7 +149,7 @@ module TalltyImportExport
|
|
147
149
|
{}
|
148
150
|
end
|
149
151
|
|
150
|
-
def process_options
|
152
|
+
def process_options(options = {})
|
151
153
|
options = export_options.merge(options).with_indifferent_access
|
152
154
|
|
153
155
|
@row_height ||= options.delete(:row_height) || 25
|
@@ -161,30 +163,30 @@ module TalltyImportExport
|
|
161
163
|
context.params = @params
|
162
164
|
end
|
163
165
|
|
164
|
-
def with_scope
|
166
|
+
def with_scope(records)
|
165
167
|
records
|
166
168
|
end
|
167
169
|
|
168
|
-
def export_headers_result
|
170
|
+
def export_headers_result(**options)
|
169
171
|
if @headers.present? && @group_key.blank?
|
170
172
|
headers_hash = @headers.to_h { |header| [header.with_indifferent_access[:key], header] }.with_indifferent_access
|
171
173
|
export_headers(**options.symbolize_keys).select do |_header|
|
172
174
|
_header.with_indifferent_access[:key].to_s.in?(headers_hash.keys)
|
173
175
|
end.map do |_header|
|
174
176
|
_header = _header.with_indifferent_access
|
175
|
-
_header.merge(headers_hash[_header[:key]].delete_if { |
|
177
|
+
_header.merge(headers_hash[_header[:key]].delete_if { |_k, v| v.blank? })
|
176
178
|
end
|
177
179
|
else
|
178
180
|
@headers = export_headers(**options.symbolize_keys)
|
179
181
|
end
|
180
182
|
end
|
181
183
|
|
182
|
-
def export_headers
|
184
|
+
def export_headers(**args)
|
183
185
|
@headers || klass.try(:headers) || klass.try(:model_headers)
|
184
186
|
end
|
185
187
|
|
186
188
|
# 处理一个记录的数据
|
187
|
-
def handle_data
|
189
|
+
def handle_data(record, header, index = 0, **opts)
|
188
190
|
data =
|
189
191
|
if header[:key] == '_index'
|
190
192
|
index
|
@@ -200,28 +202,36 @@ module TalltyImportExport
|
|
200
202
|
data = handle_format(data, header, **opts)
|
201
203
|
data = handle_data_type(data, **opts)
|
202
204
|
data = handle_select(data, header, **opts)
|
203
|
-
rescue
|
205
|
+
rescue StandardError
|
204
206
|
''
|
205
207
|
end
|
206
208
|
|
207
|
-
def try_chain
|
209
|
+
def try_chain(record, arr)
|
208
210
|
arr.reduce(record) do |r, m|
|
209
211
|
if r.is_a?(Array)
|
210
212
|
r.try(m) || r.try(:[], m.to_i)
|
211
213
|
else
|
212
|
-
|
214
|
+
begin
|
215
|
+
r.try(:[], m)
|
216
|
+
rescue StandardError
|
217
|
+
nil
|
218
|
+
end || begin
|
219
|
+
r.try(:[], m.to_sym)
|
220
|
+
rescue StandardError
|
221
|
+
nil
|
222
|
+
end || r.try(m)
|
213
223
|
end
|
214
224
|
end
|
215
225
|
end
|
216
226
|
|
217
|
-
def try_method
|
227
|
+
def try_method(record, method, prefix: nil)
|
218
228
|
prefix_arr = prefix.to_s.split(/\./)
|
219
229
|
arr = method.to_s.split(/\./)
|
220
230
|
try_chain record, prefix_arr + arr
|
221
231
|
end
|
222
232
|
|
223
233
|
# 根据数据类型 attr_type 进行数据的格式化
|
224
|
-
def handle_format
|
234
|
+
def handle_format(data, header, **opts)
|
225
235
|
case header[:attr_type].to_s
|
226
236
|
when 'string'
|
227
237
|
data.to_s
|
@@ -234,7 +244,7 @@ module TalltyImportExport
|
|
234
244
|
end
|
235
245
|
end
|
236
246
|
|
237
|
-
def handle_data_type
|
247
|
+
def handle_data_type(data, **opts)
|
238
248
|
if data.is_a?(Time)
|
239
249
|
data.in_time_zone.strftime('%F %H:%M')
|
240
250
|
elsif data.is_a?(Date)
|
@@ -257,7 +267,7 @@ module TalltyImportExport
|
|
257
267
|
end
|
258
268
|
end
|
259
269
|
|
260
|
-
def handle_select
|
270
|
+
def handle_select(data, header, **opts)
|
261
271
|
if header[:select].present?
|
262
272
|
select_option = header[:select].find { |option| option[:value].to_s == data.to_s }
|
263
273
|
select_option.present? ? select_option[:label] : data
|
@@ -126,7 +126,7 @@ module TalltyImportExport
|
|
126
126
|
|
127
127
|
def export_headers_result **options
|
128
128
|
@headers = options.symbolize_keys[:headers]
|
129
|
-
super(**options)
|
129
|
+
@headers = super(**options)
|
130
130
|
@headers = TalltyImportExport::Attr::ExportHeader.new({ items: @headers })
|
131
131
|
end
|
132
132
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module TalltyImportExport
|
2
2
|
class Import
|
3
3
|
require 'roo'
|
4
|
+
require 'roo-xls'
|
4
5
|
attr_reader :klass, :context, :primary_keys, :associations
|
5
6
|
|
6
|
-
def initialize
|
7
|
+
def initialize(klass)
|
7
8
|
@klass = klass
|
8
9
|
@context = Context.new({})
|
9
10
|
end
|
@@ -20,13 +21,41 @@ module TalltyImportExport
|
|
20
21
|
# skip: 用来综合使用的数据,但是不导入
|
21
22
|
|
22
23
|
# xlsx_file 为 file path or file object or TalltyImportExport::Excel.new
|
23
|
-
def import_xlsx
|
24
|
+
def import_xlsx(xlsx_file, associations, **options)
|
24
25
|
process_xlsx_line_info(xlsx_file, associations, **options) do |line_info, associations|
|
25
26
|
process_line_info(line_info, associations)
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
# 导出excel的空模版
|
31
|
+
def export_template_xlsx(**options)
|
32
|
+
origin_options = options.dup
|
33
|
+
process_options(options)
|
34
|
+
|
35
|
+
Axlsx::Package.new do |pack|
|
36
|
+
pack.use_shared_strings = true
|
37
|
+
workbook = pack.workbook
|
38
|
+
|
39
|
+
export_workbook workbook, **origin_options
|
40
|
+
|
41
|
+
file_path = File.join(Rails.root, 'public', 'import')
|
42
|
+
FileUtils.mkdir_p(file_path) unless Dir.exist?(file_path)
|
43
|
+
file_name = "#{Time.now.strftime('%Y%m%d%H%M%S')}#{@filename}.xlsx"
|
44
|
+
file_path_with_name = File.join(file_path, file_name)
|
45
|
+
pack.serialize(file_path_with_name)
|
46
|
+
return file_path_with_name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def export_workbook(workbook, **options)
|
51
|
+
export_instance = TalltyImportExport::Export.new(@klass)
|
52
|
+
opts = options.symbolize_keys.merge({ headers: @headers })
|
53
|
+
Rails.logger.info opts
|
54
|
+
export_instance.process_options(opts)
|
55
|
+
export_instance.export_workbook(workbook, [], **opts)
|
56
|
+
end
|
57
|
+
|
58
|
+
def exchange_to_ids(xlsx_file, associations, **options)
|
30
59
|
errors = []
|
31
60
|
ids = []
|
32
61
|
process_xlsx_line_info(xlsx_file, associations, **options) do |line_info, associations|
|
@@ -37,33 +66,34 @@ module TalltyImportExport
|
|
37
66
|
error_msg = errors.map do |line_info|
|
38
67
|
"【#{@primary_keys.map { |key| line_info[key] }.join(' - ')}】"
|
39
68
|
end.join(' ')
|
40
|
-
raise RecordNotFountError
|
69
|
+
raise RecordNotFountError, "以下内容未找到: #{error_msg}"
|
41
70
|
end
|
42
|
-
|
71
|
+
ids.compact.uniq
|
43
72
|
end
|
44
73
|
|
45
|
-
def process_xlsx_line_info
|
74
|
+
def process_xlsx_line_info(xlsx_file, associations, **options)
|
46
75
|
@associations = associations
|
47
76
|
# 先处理获取出来Excel每行的数据, line_info
|
48
77
|
process_options(options)
|
49
78
|
|
50
|
-
if TalltyImportExport::Excel
|
79
|
+
if xlsx_file.is_a?(TalltyImportExport::Excel)
|
51
80
|
xlsx_file.rows.each_with_excel_hash(@excel_hash) do |line_info|
|
52
81
|
yield line_info.with_indifferent_access, associations
|
53
82
|
end
|
54
83
|
else
|
55
84
|
file_path = xlsx_file.is_a?(String) ? xlsx_file : xlsx_file.path
|
56
|
-
xlsx = ::Roo::
|
85
|
+
xlsx = ::Roo::Spreadsheet.open(file_path, extension: File.extname(file_path) == '.xls' ? :xls : :xlsx)
|
57
86
|
xlsx.each_with_pagename do |_sheetname, sheet|
|
58
87
|
sheet.each(**@excel_hash).with_index do |line_info, index|
|
59
88
|
next if index == 0
|
89
|
+
|
60
90
|
yield line_info.with_indifferent_access, associations
|
61
91
|
end
|
62
92
|
end
|
63
93
|
end
|
64
94
|
end
|
65
95
|
|
66
|
-
def import_data
|
96
|
+
def import_data(data, associations, **options)
|
67
97
|
process_options(options)
|
68
98
|
TalltyImportExport::Excel::Rows.new(data).each_with_excel_hash(@excel_hash) do |line_info|
|
69
99
|
process_line_info(line_info.with_indifferent_access, associations)
|
@@ -74,25 +104,25 @@ module TalltyImportExport
|
|
74
104
|
TalltyImportExport::Excel
|
75
105
|
end
|
76
106
|
|
77
|
-
def process_options
|
107
|
+
def process_options(options)
|
78
108
|
options = import_options.merge(options).with_indifferent_access
|
79
|
-
@headers = options.delete(:headers) || import_headers
|
109
|
+
@headers = options.delete(:headers) || import_headers(**options)
|
80
110
|
@primary_keys = options.delete(:primary_keys) || @headers.map { |header| header[:primary_key] ? header[:key].to_sym : nil }.compact
|
81
111
|
@skip_keys = options.delete(:skip_keys) || @headers.map { |header| header[:skip] ? header[:key].to_sym : nil }.compact
|
82
112
|
@params = options
|
83
113
|
context.params = @params
|
84
114
|
|
85
|
-
@excel_hash = @headers.
|
115
|
+
@excel_hash = @headers.each_with_object({}) do |header, h|
|
86
116
|
h[header[:key].to_sym] = header[:name]
|
87
|
-
h
|
88
117
|
end
|
89
118
|
|
90
119
|
options
|
91
120
|
end
|
92
121
|
|
93
|
-
def process_line_info
|
122
|
+
def process_line_info(line_info, associations)
|
94
123
|
# 去除空行内容
|
95
124
|
return unless line_info.values.any?(&:present?)
|
125
|
+
|
96
126
|
context.line_info = line_info
|
97
127
|
# 转换处理导入的数据格式
|
98
128
|
line_info = convert_data(line_info)
|
@@ -104,14 +134,16 @@ module TalltyImportExport
|
|
104
134
|
context.last_line_info = line_info
|
105
135
|
end
|
106
136
|
|
107
|
-
def convert_data
|
137
|
+
def convert_data(line_info)
|
108
138
|
info = line_info.with_indifferent_access
|
109
|
-
import_headers_result.
|
139
|
+
import_headers_result.each_with_object({}.with_indifferent_access) do |header, h|
|
110
140
|
k = header[:key]
|
141
|
+
k_arr = k.to_s.split(/\./)
|
111
142
|
v = info[k]
|
112
143
|
# header[:convert] = handle_xxx
|
113
144
|
# handle_xxx(val, processing_line_info, raw_line_info)
|
114
145
|
val = header[:convert] ? send(header[:convert], v, h, info) : v
|
146
|
+
val.strip! if val.is_a?(String)
|
115
147
|
if header[:json]
|
116
148
|
h[header[:json]] ||= {}
|
117
149
|
h[header[:json]][k] = val
|
@@ -120,15 +152,20 @@ module TalltyImportExport
|
|
120
152
|
elsif header[:finder]
|
121
153
|
# $SAFE = 2
|
122
154
|
h[k.to_sym] = eval header[:finder]
|
155
|
+
elsif k_arr.size > 1
|
156
|
+
# hash设置
|
157
|
+
attr = k_arr.first
|
158
|
+
val = { k_arr[1..-1].join('.') => v }.to_nested_hash
|
159
|
+
h[attr.to_sym] ||= {}
|
160
|
+
h[attr.to_sym].merge! val
|
123
161
|
else
|
124
162
|
h[k.to_sym] = val
|
125
163
|
end
|
126
|
-
h
|
127
164
|
end.with_indifferent_access
|
128
165
|
end
|
129
166
|
|
130
167
|
# 通过转换后,数据是否合法,如果不合法,则直接跳过不处理这个数据
|
131
|
-
def valid?
|
168
|
+
def valid?(line_info)
|
132
169
|
true
|
133
170
|
end
|
134
171
|
|
@@ -141,12 +178,12 @@ module TalltyImportExport
|
|
141
178
|
_header.with_indifferent_access[:key].to_s.in?(headers_hash.keys)
|
142
179
|
end.map do |_header|
|
143
180
|
_header = _header.with_indifferent_access
|
144
|
-
_header.merge(headers_hash[_header[:key]].delete_if { |
|
181
|
+
_header.merge(headers_hash[_header[:key]].delete_if { |_k, v| v.blank? })
|
145
182
|
end
|
146
183
|
else
|
147
|
-
@headers = import_headers
|
184
|
+
@headers = import_headers
|
148
185
|
end
|
149
|
-
rescue
|
186
|
+
rescue StandardError
|
150
187
|
@headers
|
151
188
|
end
|
152
189
|
|
@@ -154,8 +191,8 @@ module TalltyImportExport
|
|
154
191
|
{}
|
155
192
|
end
|
156
193
|
|
157
|
-
def import_headers
|
158
|
-
@headers || klass.try(:headers) || klass.try(:model_headers) || (raise ArgumentError
|
194
|
+
def import_headers(**args)
|
195
|
+
@headers || klass.try(:headers) || klass.try(:model_headers) || (raise ArgumentError, 'missing import_headers')
|
159
196
|
end
|
160
197
|
|
161
198
|
# # 只保留 key, name, json, 合并到 import_header
|
@@ -182,12 +219,12 @@ module TalltyImportExport
|
|
182
219
|
# @headers = result
|
183
220
|
# end
|
184
221
|
|
185
|
-
def skip
|
222
|
+
def skip(val, processing_line_info, raw_line_info)
|
186
223
|
# do nothing there, use for header[:convert]
|
187
224
|
end
|
188
225
|
|
189
226
|
### 这个方法是可以由复杂业务进行重载的 ###
|
190
|
-
def import_record
|
227
|
+
def import_record(line_info, associations)
|
191
228
|
if primary_keys.present?
|
192
229
|
_record = associations.find_or_initialize_by(line_info.clone.extract!(*primary_keys))
|
193
230
|
_record.update!(line_info.clone.except!(*primary_keys, *@skip_keys))
|
@@ -196,23 +233,26 @@ module TalltyImportExport
|
|
196
233
|
end
|
197
234
|
end
|
198
235
|
|
199
|
-
def exchange_line_info_to_id
|
236
|
+
def exchange_line_info_to_id(line_info, associations, errors)
|
200
237
|
# 去除空行内容
|
201
238
|
return unless line_info.values.any?(&:present?)
|
239
|
+
|
202
240
|
context.line_info = line_info
|
203
241
|
|
204
242
|
return unless primary_keys.present?
|
243
|
+
|
205
244
|
ids = associations.where(line_info.clone.extract!(*primary_keys)).pluck(:id)
|
206
245
|
|
207
246
|
context.last_line_info = line_info
|
208
247
|
|
209
248
|
errors << line_info unless ids[0]
|
210
|
-
|
249
|
+
ids[0]
|
211
250
|
end
|
212
251
|
|
213
252
|
class RecordNotFountError < StandardError
|
214
253
|
attr_accessor :message
|
215
|
-
|
254
|
+
|
255
|
+
def initialize(message)
|
216
256
|
@message = message
|
217
257
|
super()
|
218
258
|
end
|
@@ -28,6 +28,10 @@ module TalltyImportExport
|
|
28
28
|
def exchange_to_ids xlsx_file, associations, **options
|
29
29
|
import_instance.exchange_to_ids(xlsx_file, associations, **options)
|
30
30
|
end
|
31
|
+
|
32
|
+
def export_template_xlsx **options
|
33
|
+
import_instance.export_template_xlsx(**options)
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
33
37
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tallty_import_export
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- liyijie
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zip-zip
|