enju_biblio 0.3.16 → 0.3.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/app/models2/agent.rb +331 -0
  3. data/app/models2/agent_import_file.rb +259 -0
  4. data/app/models2/agent_import_file_state_machine.rb +19 -0
  5. data/app/models2/agent_import_file_transition.rb +20 -0
  6. data/app/models2/agent_import_result.rb +20 -0
  7. data/app/models2/agent_merge.rb +17 -0
  8. data/app/models2/agent_merge_list.rb +27 -0
  9. data/app/models2/agent_relationship.rb +24 -0
  10. data/app/models2/agent_relationship_type.rb +20 -0
  11. data/app/models2/agent_type.rb +19 -0
  12. data/app/models2/carrier_type.rb +50 -0
  13. data/app/models2/content_type.rb +19 -0
  14. data/app/models2/country.rb +47 -0
  15. data/app/models2/create.rb +29 -0
  16. data/app/models2/create_type.rb +19 -0
  17. data/app/models2/doi_record.rb +36 -0
  18. data/app/models2/donate.rb +15 -0
  19. data/app/models2/form_of_work.rb +19 -0
  20. data/app/models2/frequency.rb +19 -0
  21. data/app/models2/identifier.rb +83 -0
  22. data/app/models2/identifier_type.rb +18 -0
  23. data/app/models2/import_request.rb +77 -0
  24. data/app/models2/import_request_state_machine.rb +9 -0
  25. data/app/models2/import_request_transition.rb +21 -0
  26. data/app/models2/isbn_record.rb +51 -0
  27. data/app/models2/isbn_record_and_manifestation.rb +18 -0
  28. data/app/models2/issn_record.rb +49 -0
  29. data/app/models2/issn_record_and_manifestation.rb +18 -0
  30. data/app/models2/item.rb +173 -0
  31. data/app/models2/item_custom_property.rb +18 -0
  32. data/app/models2/item_custom_value.rb +17 -0
  33. data/app/models2/language.rb +39 -0
  34. data/app/models2/license.rb +18 -0
  35. data/app/models2/manifestation.rb +764 -0
  36. data/app/models2/manifestation_custom_property.rb +18 -0
  37. data/app/models2/manifestation_custom_value.rb +17 -0
  38. data/app/models2/manifestation_relationship.rb +27 -0
  39. data/app/models2/manifestation_relationship_type.rb +20 -0
  40. data/app/models2/medium_of_performance.rb +19 -0
  41. data/app/models2/own.rb +29 -0
  42. data/app/models2/periodical.rb +33 -0
  43. data/app/models2/periodical_and_manifestation.rb +16 -0
  44. data/app/models2/picture_file.rb +60 -0
  45. data/app/models2/produce.rb +30 -0
  46. data/app/models2/produce_type.rb +19 -0
  47. data/app/models2/realize.rb +29 -0
  48. data/app/models2/realize_type.rb +19 -0
  49. data/app/models2/resource_export_file.rb +64 -0
  50. data/app/models2/resource_export_file_state_machine.rb +15 -0
  51. data/app/models2/resource_export_file_transition.rb +21 -0
  52. data/app/models2/resource_import_file.rb +909 -0
  53. data/app/models2/resource_import_file_state_machine.rb +19 -0
  54. data/app/models2/resource_import_file_transition.rb +21 -0
  55. data/app/models2/resource_import_result.rb +24 -0
  56. data/app/models2/series_statement.rb +72 -0
  57. data/app/models2/series_statement_merge.rb +17 -0
  58. data/app/models2/series_statement_merge_list.rb +17 -0
  59. data/app/views/manifestations/_book_jacket.html.erb +9 -5
  60. data/app/views/manifestations/_colorbox.html.erb +1 -1
  61. data/app/views/manifestations/_pickup.html.erb +1 -1
  62. data/lib/enju_biblio/version.rb +1 -1
  63. data/spec/dummy/yarn.lock +7560 -0
  64. metadata +61 -2
@@ -0,0 +1,909 @@
1
+ class ResourceImportFile < ApplicationRecord
2
+ include Statesman::Adapters::ActiveRecordQueries[
3
+ transition_class: ResourceImportFileTransition,
4
+ initial_state: :pending
5
+ ]
6
+ include ImportFile
7
+ default_scope { order('resource_import_files.id DESC') }
8
+ scope :not_imported, -> { in_state(:pending) }
9
+ scope :stucked, -> { in_state(:pending).where('resource_import_files.created_at < ?', 1.hour.ago) }
10
+
11
+ if ENV['ENJU_STORAGE'] == 's3'
12
+ has_attached_file :resource_import, storage: :s3,
13
+ s3_credentials: {
14
+ access_key: ENV['AWS_ACCESS_KEY_ID'],
15
+ secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
16
+ bucket: ENV['S3_BUCKET_NAME'],
17
+ s3_host_name: ENV['S3_HOST_NAME'],
18
+ s3_region: ENV['S3_REGION']
19
+ },
20
+ s3_permissions: :private
21
+ else
22
+ has_attached_file :resource_import,
23
+ path: ":rails_root/private/system/:class/:attachment/:id_partition/:style/:filename"
24
+ end
25
+ validates_attachment_content_type :resource_import, content_type: [
26
+ 'text/csv',
27
+ 'text/plain',
28
+ 'text/tab-separated-values',
29
+ 'application/octet-stream',
30
+ 'application/vnd.ms-excel'
31
+ ]
32
+ validates_attachment_presence :resource_import
33
+ validates :resource_import, presence: true, on: :create
34
+ validates :default_shelf_id, presence: true, if: Proc.new{|model| model.edit_mode == 'create'}
35
+ belongs_to :user
36
+ belongs_to :default_shelf, class_name: 'Shelf', optional: true
37
+ has_many :resource_import_results, dependent: :destroy
38
+ has_many :resource_import_file_transitions, autosave: false, dependent: :destroy
39
+
40
+ attr_accessor :mode, :library_id
41
+
42
+ def state_machine
43
+ ResourceImportFileStateMachine.new(self, transition_class: ResourceImportFileTransition)
44
+ end
45
+
46
+ delegate :can_transition_to?, :transition_to!, :transition_to, :current_state,
47
+ to: :state_machine
48
+
49
+ def import_start
50
+ case edit_mode
51
+ when 'create'
52
+ import
53
+ when 'update'
54
+ modify
55
+ when 'destroy'
56
+ remove
57
+ when 'update_relationship'
58
+ update_relationship
59
+ else
60
+ import
61
+ end
62
+ end
63
+
64
+ def import
65
+ transition_to!(:started)
66
+ num = {
67
+ manifestation_imported: 0,
68
+ item_imported: 0,
69
+ manifestation_found: 0,
70
+ item_found: 0,
71
+ failed: 0
72
+ }
73
+ rows = open_import_file(create_import_temp_file(resource_import))
74
+ rows.shift
75
+ #if [field['manifestation_id'], field['manifestation_identifier'], field['isbn'], field['original_title']].reject{|f|
76
+ # f.to_s.strip == ''
77
+ #}.empty?
78
+ # raise "You should specify isbn or original_title in the first line"
79
+ #end
80
+ row_num = 1
81
+
82
+ ResourceImportResult.create!(resource_import_file_id: id, body: (%w( imported_manifestation_id imported_item_id ) + rows.headers).join("\t"))
83
+ rows.each do |row|
84
+ row_num += 1
85
+ import_result = ResourceImportResult.new(resource_import_file_id: id)
86
+ if row['dummy'].to_s.strip.present?
87
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.dummy')}"
88
+ import_result.body = ([nil, nil] + row.fields).join("\t")
89
+ import_result.save!
90
+ next
91
+ end
92
+
93
+ item_identifier = row['item_identifier'].to_s.strip
94
+ item = Item.find_by(item_identifier: item_identifier)
95
+ if item
96
+ import_result.item = item
97
+ import_result.manifestation = item.manifestation
98
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.item_found')}"
99
+ import_result.body = ([item.manifestation.id, item.id] + row.fields).join("\t")
100
+ import_result.save!
101
+ num[:item_found] += 1
102
+ next
103
+ end
104
+
105
+ if row['manifestation_identifier'].present?
106
+ manifestation = Manifestation.find_by(manifestation_identifier: row['manifestation_identifier'].to_s.strip)
107
+ end
108
+
109
+ unless manifestation
110
+ if row['manifestation_id'].present?
111
+ manifestation = Manifestation.find_by(id: row['manifestation_id'].to_s.strip)
112
+ end
113
+ end
114
+
115
+ unless manifestation
116
+ if row['doi'].present?
117
+ doi = URI.parse(row['doi']).path.gsub(/^\//, "")
118
+ identifier_type_doi = IdentifierType.find_by(name: 'doi')
119
+ identifier_type_doi = IdentifierType.create!(name: 'doi') unless identifier_type_doi
120
+ manifestation = Identifier.find_by(body: doi, identifier_type_id: identifier_type_doi.id).try(:manifestation)
121
+ end
122
+ end
123
+
124
+ unless manifestation
125
+ if row['jpno'].present?
126
+ jpno = row['jpno'].to_s.strip
127
+ identifier_type_jpno = IdentifierType.find_by(name: 'jpno')
128
+ identifier_type_jpno = IdentifierType.create!(name: 'jpno') unless identifier_type_jpno
129
+ manifestation = Identifier.find_by(body: jpno, identifier_type_id: identifier_type_jpno.id).try(:manifestation)
130
+ end
131
+ end
132
+
133
+ unless manifestation
134
+ if row['ncid'].present?
135
+ ncid = row['ncid'].to_s.strip
136
+ identifier_type_ncid = IdentifierType.find_by(name: 'ncid')
137
+ identifier_type_ncid = IdentifierType.where(name: 'ncid').create! unless identifier_type_ncid
138
+ manifestation = Identifier.find_by(body: ncid, identifier_type_id: identifier_type_ncid.id).try(:manifestation)
139
+ end
140
+ end
141
+
142
+ unless manifestation
143
+ if row['isbn'].present?
144
+ if StdNum::ISBN.valid?(row['isbn'])
145
+ isbn = StdNum::ISBN.normalize(row['isbn'])
146
+ identifier_type_isbn = IdentifierType.find_by(name: 'isbn')
147
+ identifier_type_isbn = IdentifierType.where(name: 'isbn').create! unless identifier_type_isbn
148
+ m = Identifier.find_by(body: isbn, identifier_type_id: identifier_type_isbn.id).try(:manifestation)
149
+ if m
150
+ if m.series_statements.exists?
151
+ manifestation = m
152
+ end
153
+ end
154
+ else
155
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.isbn_invalid')}"
156
+ end
157
+ end
158
+ end
159
+
160
+ if manifestation
161
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.manifestation_found')}"
162
+ num[:manifestation_found] += 1
163
+ end
164
+
165
+ if row['original_title'].blank?
166
+ unless manifestation
167
+ begin
168
+ manifestation = Manifestation.import_isbn(isbn) if isbn
169
+ if manifestation
170
+ num[:manifestation_imported] += 1
171
+ end
172
+ rescue EnjuNdl::InvalidIsbn
173
+ manifestation = nil
174
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.isbn_invalid')}"
175
+ rescue EnjuNdl::RecordNotFound
176
+ manifestation = nil
177
+ import_result.error_message = "line #{row_num}: #{I18n.t('import.isbn_record_not_found')}"
178
+ end
179
+ end
180
+ if manifestation.nil? and row['ndl_bib_id']
181
+ manifestation = Manifestation.import_ndl_bib_id(row['ndl_bib_id'])
182
+ if manifestation
183
+ num[:manifestation_imported] += 1
184
+ end
185
+ end
186
+ end
187
+
188
+ unless manifestation
189
+ manifestation = fetch(row)
190
+ num[:manifestation_imported] += 1 if manifestation
191
+ end
192
+ import_result.manifestation = manifestation
193
+
194
+ if manifestation
195
+ ResourceImportFile.import_manifestation_custom_value(row, manifestation).each do |value|
196
+ value.update!(manifestation: manifestation)
197
+ end
198
+
199
+ item = nil
200
+ if item_identifier.present? || row['shelf'].present? || row['call_number'].present?
201
+ item = create_item(row, manifestation)
202
+ else
203
+ if manifestation.fulltext_content?
204
+ item = create_item(row, manifestation)
205
+ item.circulation_status = CirculationStatus.find_by(name: 'Available On Shelf')
206
+ begin
207
+ item.acquired_at = Time.zone.parse(row['acquired_at'].to_s.strip)
208
+ rescue ArgumentError
209
+ end
210
+ end
211
+ num[:failed] += 1
212
+ end
213
+
214
+ if item
215
+ ResourceImportFile.import_item_custom_value(row, item).each do |value|
216
+ value.update!(item: item)
217
+ end
218
+
219
+ import_result.item = item
220
+ end
221
+ else
222
+ num[:failed] += 1
223
+ end
224
+
225
+ import_result.body = ([manifestation.try(:id), item.try(:id)] + row.fields).join("\t")
226
+ import_result.save!
227
+ num[:item_imported] += 1 if import_result.item
228
+ end
229
+
230
+ Sunspot.commit
231
+ rows.close
232
+ transition_to!(:completed)
233
+ mailer = ResourceImportMailer.completed(self)
234
+ send_message(mailer)
235
+ Rails.cache.write("manifestation_search_total", Manifestation.search.total)
236
+ num
237
+ rescue => e
238
+ self.error_message = "line #{row_num}: #{e.message}"
239
+ save
240
+ transition_to!(:failed)
241
+ mailer = ResourceImportMailer.failed(self)
242
+ send_message(mailer)
243
+ raise e
244
+ end
245
+
246
+ def self.import_work(title, agents, options = {edit_mode: 'create'})
247
+ work = Manifestation.new(title)
248
+ work.save
249
+ work.creators = agents.uniq unless agents.empty?
250
+ work
251
+ end
252
+
253
+ def self.import_expression(work, agents, options = {edit_mode: 'create'})
254
+ expression = work
255
+ expression.save
256
+ expression.contributors = agents.uniq unless agents.empty?
257
+ expression
258
+ end
259
+
260
+ def self.import_manifestation(expression, agents, options = {}, edit_options = {edit_mode: 'create'})
261
+ manifestation = expression
262
+ manifestation.during_import = true
263
+ manifestation.reload
264
+ manifestation.update!(options)
265
+ manifestation.publishers = agents.uniq unless agents.empty?
266
+ manifestation.reload
267
+ manifestation
268
+ end
269
+
270
+ def import_marc(marc_type)
271
+ file = File.open(resource_import.path)
272
+ case marc_type
273
+ when 'marcxml'
274
+ reader = MARC::XMLReader.new(file)
275
+ else
276
+ reader = MARC::Reader.new(file)
277
+ end
278
+ file.close
279
+
280
+ #when 'marc_xml_url'
281
+ # url = URI(params[:marc_xml_url])
282
+ # xml = open(url).read
283
+ # reader = MARC::XMLReader.new(StringIO.new(xml))
284
+ #end
285
+
286
+ # TODO
287
+ for record in reader
288
+ manifestation = Manifestation.new(original_title: expression.original_title)
289
+ manifestation.carrier_type = CarrierType.find(1)
290
+ manifestation.frequency = Frequency.find(1)
291
+ manifestation.language = Language.find(1)
292
+ manifestation.save
293
+
294
+ full_name = record['700']['a']
295
+ publisher = Agent.find_by(full_name: record['700']['a'])
296
+ unless publisher
297
+ publisher = Agent.new(full_name: full_name)
298
+ publisher.save
299
+ end
300
+ manifestation.publishers << publisher
301
+ end
302
+ end
303
+
304
+ def self.import
305
+ ResourceImportFile.not_imported.each do |file|
306
+ file.import_start
307
+ end
308
+ rescue
309
+ Rails.logger.info "#{Time.zone.now} importing resources failed!"
310
+ end
311
+
312
+ #def import_jpmarc
313
+ # marc = NKF::nkf('-wc', self.db_file.data)
314
+ # marc.split("\r\n").each do |record|
315
+ # end
316
+ #end
317
+
318
+ def modify
319
+ transition_to!(:started)
320
+ rows = open_import_file(create_import_temp_file(resource_import))
321
+ rows.shift
322
+ row_num = 1
323
+
324
+ ResourceImportResult.create!(resource_import_file_id: id, body: rows.headers.join("\t"))
325
+ rows.each do |row|
326
+ row_num += 1
327
+ import_result = ResourceImportResult.create!(resource_import_file_id: id, body: row.fields.join("\t"))
328
+ item = Item.find_by(item_identifier: row['item_identifier'].to_s.strip) if row['item_identifier'].to_s.strip.present?
329
+ unless item
330
+ item = Item.find_by(id: row['item_id'].to_s.strip) if row['item_id'].to_s.strip.present?
331
+ end
332
+
333
+ if item
334
+ if item.manifestation
335
+ fetch(row, edit_mode: 'update')
336
+ item = update_item(item, row)
337
+ end
338
+
339
+ ResourceImportFile.import_item_custom_value(row, item).each do |value|
340
+ value.update!(item: item)
341
+ end
342
+ ResourceImportFile.import_manifestation_custom_value(row, item.manifestation).each do |value|
343
+ value.update!(manifestation: item.manifestation)
344
+ end
345
+
346
+ item.manifestation.reload
347
+ item.save!
348
+ import_result.item = item
349
+ else
350
+ manifestation_identifier = row['manifestation_identifier'].to_s.strip
351
+ manifestation = Manifestation.find_by(manifestation_identifier: manifestation_identifier) if manifestation_identifier.present?
352
+ unless manifestation
353
+ manifestation = Manifestation.find_by(id: row['manifestation_id'])
354
+ end
355
+ if manifestation
356
+ fetch(row, edit_mode: 'update')
357
+ ResourceImportFile.import_manifestation_custom_value(row, manifestation).each do |value|
358
+ value.update!(manifestation: manifestation)
359
+ end
360
+ import_result.manifestation = manifestation
361
+ end
362
+ end
363
+ import_result.save!
364
+ end
365
+ transition_to!(:completed)
366
+ mailer = ResourceImportMailer.completed(self)
367
+ send_message(mailer)
368
+ rescue => e
369
+ self.error_message = "line #{row_num}: #{e.message}"
370
+ save
371
+ transition_to!(:failed)
372
+ mailer = ResourceImportMailer.failed(self)
373
+ send_message(mailer)
374
+ raise e
375
+ end
376
+
377
+ def remove
378
+ transition_to!(:started)
379
+ rows = open_import_file(create_import_temp_file(resource_import))
380
+ rows.shift
381
+ row_num = 1
382
+
383
+ rows.each do |row|
384
+ row_num += 1
385
+ item = Item.find_by(item_identifier: row['item_identifier'].to_s.strip) if row['item_identifier'].to_s.strip.present?
386
+ unless item
387
+ item = Item.find_by(id: row['item_id'].to_s.strip) if row['item_id'].to_s.strip.present?
388
+ end
389
+
390
+ if item
391
+ item.destroy if item.removable?
392
+ end
393
+ end
394
+ transition_to!(:completed)
395
+ mailer = ResourceImportMailer.completed(self)
396
+ send_message(mailer)
397
+ rescue => e
398
+ self.error_message = "line #{row_num}: #{e.message}"
399
+ save
400
+ transition_to!(:failed)
401
+ mailer = ResourceImportMailer.failed(self)
402
+ send_message(mailer)
403
+ raise e
404
+ end
405
+
406
+ def update_relationship
407
+ transition_to!(:started)
408
+ rows = open_import_file(create_import_temp_file(resource_import))
409
+ rows.shift
410
+ row_num = 1
411
+
412
+ rows.each do |row|
413
+ item = Item.find_by(item_identifier: row['item_identifier'].to_s.strip) if row['item_identifier'].to_s.strip.present?
414
+ unless item
415
+ item = Item.find_by(id: row['item_id'].to_s.strip) if row['item_id'].to_s.strip.present?
416
+ end
417
+
418
+ manifestation_identifier = row['manifestation_identifier'].to_s.strip
419
+ manifestation = Manifestation.find_by(manifestation_identifier: manifestation_identifier)
420
+ unless manifestation
421
+ manifestation = Manifestation.find_by(id: row['manifestation_id'].to_s.strip)
422
+ end
423
+
424
+ if item && manifestation
425
+ item.manifestation = manifestation
426
+ item.save!
427
+ end
428
+
429
+ import_result = ResourceImportResult.create!(resource_import_file_id: id, body: row.fields.join("\t"))
430
+ import_result.item = item
431
+ import_result.manifestation = manifestation
432
+ import_result.save!
433
+ row_num += 1
434
+ end
435
+ transition_to!(:completed)
436
+ mailer = ResourceImportMailer.completed(self)
437
+ send_message(mailer)
438
+ rescue => e
439
+ self.error_message = "line #{row_num}: #{e.message}"
440
+ save
441
+ transition_to!(:failed)
442
+ mailer = ResourceImportMailer.failed(self)
443
+ send_message(mailer)
444
+ raise e
445
+ end
446
+
447
+ private
448
+ def open_import_file(tempfile)
449
+ file = CSV.open(tempfile, col_sep: "\t")
450
+ header_columns = %w(
451
+ original_title manifestation_identifier item_identifier shelf note
452
+ title_transcription title_alternative title_alternative_transcription
453
+ serial manifestation_id publication_place carrier_type
454
+ series_statement_identifier series_original_title series_creator_string
455
+ series_title_transcription series_volume_number_string
456
+ series_title_subseries series_title_subseries_transcription
457
+ creator creator_transcription publisher
458
+ publisher_transcription pub_date creator creator_transcription
459
+ contributor contributor_transcription description access_address
460
+ volume_number volume_number_string issue_number issue_number_string
461
+ edition edition_string serial_number isbn issn manifestation_price
462
+ width height depth number_of_pages jpno lccn budget_type bookstore
463
+ language fulltext_content required_role doi content_type frequency
464
+ extent start_page end_page dimensions
465
+ ncid
466
+ ndl_bib_id
467
+ statement_of_responsibility acquired_at call_number circulation_status
468
+ binding_item_identifier binding_call_number binded_at item_price
469
+ use_restriction include_supplements item_note item_url
470
+ dummy
471
+ )
472
+ header_columns += ManifestationCustomProperty.order(:position).pluck(:name).map{|c| "manifestation:#{c}"}
473
+ header_columns += ItemCustomProperty.order(:position).pluck(:name).map{|c| "item:#{c}"}
474
+
475
+ if defined?(EnjuSubject)
476
+ header_columns += ClassificationType.order(:position).pluck(:name).map{|c| "classification:#{c}"}
477
+ header_columns += SubjectHeadingType.order(:position).pluck(:name).map{|s| "subject:#{s}"}
478
+ end
479
+ header = file.first
480
+ ignored_columns = header - header_columns
481
+ unless ignored_columns.empty?
482
+ self.error_message = I18n.t('import.following_column_were_ignored', column: ignored_columns.join(', '))
483
+ save!
484
+ end
485
+ rows = CSV.open(tempfile, headers: header, col_sep: "\t")
486
+ #ResourceImportResult.create!(resource_import_file_id: id, body: header.join("\t"))
487
+ tempfile.close(true)
488
+ file.close
489
+ rows
490
+ end
491
+
492
+ def import_subject(row)
493
+ subjects = []
494
+ SubjectHeadingType.order(:position).pluck(:name).map{|s| "subject:#{s}"}.each do |column_name|
495
+ type = column_name.split(':').last
496
+ subject_list = row[column_name].to_s.split('//')
497
+ subject_list.map{|value|
498
+ subject_heading_type = SubjectHeadingType.find_by(name: type)
499
+ next unless subject_heading_type
500
+ subject = Subject.new(term: value)
501
+ subject.subject_heading_type = subject_heading_type
502
+ # TODO: Subject typeの設定
503
+ subject.subject_type = SubjectType.find_by(name: 'concept')
504
+ subject.save!
505
+ subjects << subject
506
+ }
507
+ end
508
+ subjects
509
+ end
510
+
511
+ def import_classification(row)
512
+ classifications = []
513
+ ClassificationType.order(:position).pluck(:name).map{|c| "classification:#{c}"}.each do |column_name|
514
+ type = column_name.split(':').last
515
+ classification_list = row[column_name].to_s.split('//')
516
+ classification_list.map{|value|
517
+ classification_type = ClassificationType.find_by(name: type)
518
+ next unless classification_type
519
+ classification = Classification.new(category: value)
520
+ classification.classification_type = classification_type
521
+ classification.save!
522
+ classifications << classification
523
+ }
524
+ end
525
+ classifications
526
+ end
527
+
528
+ def create_item(row, manifestation)
529
+ shelf = Shelf.find_by(name: row['shelf'].to_s.strip)
530
+ unless shelf
531
+ shelf = default_shelf || Shelf.web
532
+ end
533
+ bookstore = Bookstore.find_by(name: row['bookstore'].to_s.strip)
534
+ budget_type = BudgetType.find_by(name: row['budget_type'].to_s.strip)
535
+ acquired_at = Time.zone.parse(row['acquired_at']) rescue nil
536
+ binded_at = Time.zone.parse(row['binded_at']) rescue nil
537
+ item = Item.new(
538
+ manifestation_id: manifestation.id,
539
+ item_identifier: row['item_identifier'],
540
+ price: row['item_price'],
541
+ call_number: row['call_number'].to_s.strip,
542
+ acquired_at: acquired_at,
543
+ binding_item_identifier: row['binding_item_identifier'],
544
+ binding_call_number: row['binding_call_number'],
545
+ binded_at: binded_at,
546
+ url: row['item_url'],
547
+ note: row['item_note'].try(:gsub, /\\n/, "\n")
548
+ )
549
+ manifestation.items << item
550
+ if defined?(EnjuCirculation)
551
+ circulation_status = CirculationStatus.find_by(name: row['circulation_status'].to_s.strip) || CirculationStatus.find_by(name: 'In Process')
552
+ item.circulation_status = circulation_status
553
+ use_restriction = UseRestriction.find_by(name: row['use_restriction'].to_s.strip)
554
+ unless use_restriction
555
+ use_restriction = UseRestriction.find_by(name: 'Not For Loan')
556
+ end
557
+ item.use_restriction = use_restriction
558
+ end
559
+ item.bookstore = bookstore
560
+ item.budget_type = budget_type
561
+ item.shelf = shelf
562
+ item.shelf = Shelf.web unless item.shelf
563
+
564
+ if %w(t true).include?(row['include_supplements'].to_s.downcase.strip)
565
+ item.include_supplements = true
566
+ end
567
+ item.save!
568
+ item
569
+ end
570
+
571
+ def update_item(item, row)
572
+ shelf = Shelf.find_by(name: row['shelf'].to_s.strip)
573
+ bookstore = Bookstore.find_by(name: row['bookstore'])
574
+ required_role = Role.find_by(name: row['required_role'])
575
+
576
+ item.shelf = shelf if shelf
577
+ item.bookstore = bookstore if bookstore
578
+ item.required_role = required_role if required_role
579
+
580
+ acquired_at = Time.zone.parse(row['acquired_at']) rescue nil
581
+ binded_at = Time.zone.parse(row['binded_at']) rescue nil
582
+ item.acquired_at = acquired_at if acquired_at
583
+ item.binded_at = binded_at if binded_at
584
+
585
+ if defined?(EnjuCirculation)
586
+ circulation_status = CirculationStatus.find_by(name: row['circulation_status'])
587
+ checkout_type = CheckoutType.find_by(name: row['checkout_type'])
588
+ use_restriction = UseRestriction.find_by(name: row['use_restriction'].to_s.strip)
589
+ item.circulation_status = circulation_status if circulation_status
590
+ item.checkout_type = checkout_type if checkout_type
591
+ item.use_restriction = use_restriction if use_restriction
592
+ end
593
+
594
+ item_columns = %w(
595
+ call_number
596
+ binding_item_identifier binding_call_number binded_at
597
+ )
598
+ item_columns.each do |column|
599
+ if row[column].present?
600
+ item.assign_attributes(:"#{column}" => row[column])
601
+ end
602
+ end
603
+
604
+ item.price = row['item_price'] if row['item_price'].present?
605
+ item.note = row['item_note'].try(:gsub, /\\n/, "\n") if row['item_note'].present?
606
+ item.url = row['item_url'] if row['item_url'].present?
607
+
608
+ if row['include_supplements']
609
+ if %w(t true).include?(row['include_supplements'].downcase.strip)
610
+ item.include_supplements = true
611
+ else
612
+ item.include_supplements = false if item.include_supplements
613
+ end
614
+ end
615
+
616
+ item
617
+ end
618
+
619
+ def fetch(row, options = {edit_mode: 'create'})
620
+ manifestation = nil
621
+ item = nil
622
+
623
+ if options[:edit_mode] == 'update'
624
+ if row['item_identifier'].to_s.strip.present?
625
+ item = Item.find_by(item_identifier: row['item_identifier'].to_s.strip)
626
+ end
627
+ if row['item_id'].to_s.strip.present?
628
+ item = Item.find_by(id: row['item_id'].to_s.strip)
629
+ end
630
+
631
+ manifestation = item.manifestation if item
632
+
633
+ unless manifestation
634
+ manifestation_identifier = row['manifestation_identifier'].to_s.strip
635
+ manifestation = Manifestation.find_by(manifestation_identifier: manifestation_identifier) if manifestation_identifier
636
+ manifestation = Manifestation.find_by(id: row['manifestation_id']) unless manifestation
637
+ end
638
+ end
639
+
640
+ title = {}
641
+ title[:original_title] = row['original_title'].to_s.strip
642
+ title[:title_transcription] = row['title_transcription'].to_s.strip
643
+ title[:title_alternative] = row['title_alternative'].to_s.strip
644
+ title[:title_alternative_transcription] = row['title_alternative_transcription'].to_s.strip
645
+ if options[:edit_mode] == 'update'
646
+ title[:original_title] = manifestation.original_title if row['original_title'].to_s.strip.blank?
647
+ title[:title_transcription] = manifestation.title_transcription if row['title_transcription'].to_s.strip.blank?
648
+ title[:title_alternative] = manifestation.title_alternative if row['title_alternative'].to_s.strip.blank?
649
+ title[:title_alternative_transcription] = manifestation.title_alternative_transcription if row['title_alternative_transcription'].to_s.strip.blank?
650
+ end
651
+ #title[:title_transcription_alternative] = row['title_transcription_alternative']
652
+ if title[:original_title].blank? && options[:edit_mode] == 'create'
653
+ return nil
654
+ end
655
+
656
+ # TODO: 小数点以下の表現
657
+ language = Language.find_by(name: row['language'].to_s.strip.camelize)
658
+ language = Language.find_by(iso_639_2: row['language'].to_s.strip.downcase) unless language
659
+ language = Language.find_by(iso_639_1: row['language'].to_s.strip.downcase) unless language
660
+ carrier_type = CarrierType.find_by(name: row['carrier_type'].to_s.strip)
661
+ content_type = ContentType.find_by(name: row['content_type'].to_s.strip)
662
+ frequency = Frequency.find_by(name: row['frequency'].to_s.strip)
663
+
664
+ fulltext_content = serial = nil
665
+ if %w(t true).include?(row['fulltext_content'].to_s.downcase.strip)
666
+ fulltext_content = true
667
+ end
668
+
669
+ if %w(t true).include?(row['serial'].to_s.downcase.strip)
670
+ serial = true
671
+ end
672
+
673
+ creators = row['creator'].to_s.split('//')
674
+ creator_transcriptions = row['creator_transcription'].to_s.split('//')
675
+ creators_list = creators.zip(creator_transcriptions).map{|f,t| {full_name: f.to_s.strip, full_name_transcription: t.to_s.strip}}
676
+ contributors = row['contributor'].to_s.split('//')
677
+ contributor_transcriptions = row['contributor_transcription'].to_s.split('//')
678
+ contributors_list = contributors.zip(contributor_transcriptions).map{|f,t| {full_name: f.to_s.strip, full_name_transcription: t.to_s.strip}}
679
+ publishers = row['publisher'].to_s.split('//')
680
+ publisher_transcriptions = row['publisher_transcription'].to_s.split('//')
681
+ publishers_list = publishers.zip(publisher_transcriptions).map{|f,t| {full_name: f.to_s.strip, full_name_transcription: t.to_s.strip}}
682
+ ResourceImportFile.transaction do
683
+ creator_agents = Agent.import_agents(creators_list)
684
+ contributor_agents = Agent.import_agents(contributors_list)
685
+ publisher_agents = Agent.import_agents(publishers_list)
686
+ subjects = import_subject(row) if defined?(EnjuSubject)
687
+ case options[:edit_mode]
688
+ when 'create'
689
+ work = self.class.import_work(title, creator_agents, options)
690
+ if defined?(EnjuSubject)
691
+ work.subjects = subjects.uniq unless subjects.empty?
692
+ end
693
+ expression = self.class.import_expression(work, contributor_agents)
694
+ when 'update'
695
+ expression = manifestation
696
+ work = expression
697
+ work.creators = creator_agents.uniq unless creator_agents.empty?
698
+ expression.contributors = contributor_agents.uniq unless contributor_agents.empty?
699
+ if defined?(EnjuSubject)
700
+ work.subjects = subjects.uniq unless subjects.empty?
701
+ end
702
+ end
703
+
704
+ attributes = {
705
+ original_title: title[:original_title],
706
+ title_transcription: title[:title_transcription],
707
+ title_alternative: title[:title_alternative],
708
+ title_alternative_transcription: title[:title_alternative_transcription],
709
+ pub_date: row['pub_date'],
710
+ volume_number: row['volume_number'],
711
+ volume_number_string: row['volume_number_string'],
712
+ issue_number: row['issue_number'],
713
+ issue_number_string: row['issue_number_string'],
714
+ serial_number: row['serial_number'],
715
+ edition: row['edition'],
716
+ edition_string: row['edition_string'],
717
+ width: row['width'],
718
+ depth: row['depth'],
719
+ height: row['height'],
720
+ price: row['manifestation_price'],
721
+ description: row['description'].try(:gsub, /\\n/, "\n"),
722
+ #:description_transcription => row['description_transcription'],
723
+ note: row['note'].try(:gsub, /\\n/, "\n"),
724
+ statement_of_responsibility: row['statement_of_responsibility'],
725
+ access_address: row['access_address'],
726
+ manifestation_identifier: row['manifestation_identifier'],
727
+ publication_place: row['publication_place'],
728
+ extent: row['extent'],
729
+ dimensions: row['dimensions'],
730
+ start_page: row['start_page'],
731
+ end_page: row['end_page'],
732
+ }.delete_if{|_key, value| value.nil?}
733
+
734
+ manifestation = self.class.import_manifestation(expression, publisher_agents, attributes,
735
+ {
736
+ edit_mode: options[:edit_mode]
737
+ })
738
+
739
+ required_role = Role.find_by(name: row['required_role_name'].to_s.strip.camelize)
740
+ if required_role && row['required_role_name'].present?
741
+ manifestation.required_role = required_role
742
+ else
743
+ manifestation.required_role = Role.find_by(name: 'Guest') unless manifestation.required_role
744
+ end
745
+
746
+ if language && row['language'].present?
747
+ manifestation.language = language
748
+ else
749
+ manifestation.language = Language.find_by(name: 'unknown') unless manifestation.language
750
+ end
751
+
752
+ manifestation.carrier_type = carrier_type if carrier_type
753
+ manifestation.manifestation_content_type = content_type if content_type
754
+ manifestation.frequency = frequency if frequency
755
+ #manifestation.start_page = row[:start_page].to_i if row[:start_page]
756
+ #manifestation.end_page = row[:end_page].to_i if row[:end_page]
757
+ manifestation.serial = serial if row['serial']
758
+ manifestation.fulltext_content = fulltext_content if row['fulltext_content']
759
+
760
+ if row['series_original_title'].to_s.strip.present?
761
+ Manifestation.transaction do
762
+ if manifestation.series_statements.exists?
763
+ manifestation.series_statements.delete_all
764
+ end
765
+ if row['series_original_title']
766
+ series_statement = SeriesStatement.new(
767
+ original_title: row['series_original_title'],
768
+ title_transcription: row['series_title_transcription'],
769
+ title_subseries: row['series_title_subseries'],
770
+ title_subseries_transcription: row['series_title_subseries_transcription'],
771
+ volume_number_string: row['series_volume_number_string'],
772
+ creator_string: row['series_creator_string'],
773
+ )
774
+ series_statement.manifestation = manifestation
775
+ series_statement.save!
776
+ end
777
+ end
778
+ end
779
+
780
+ identifiers = set_identifier(row)
781
+
782
+ if manifestation.save
783
+ Manifestation.transaction do
784
+ if options[:edit_mode] == 'update'
785
+ unless identifiers.empty?
786
+ identifiers.each do |v|
787
+ v.manifestation = manifestation
788
+ v.save!
789
+ end
790
+ end
791
+ else
792
+ manifestation.identifiers << identifiers
793
+ end
794
+ end
795
+
796
+ if defined?(EnjuSubject)
797
+ classifications = import_classification(row)
798
+ if classifications.present?
799
+ manifestation.classifications = classifications
800
+ end
801
+ end
802
+ end
803
+
804
+ manifestation.save!
805
+
806
+ if options[:edit_mode] == 'create'
807
+ manifestation.set_agent_role_type(creators_list)
808
+ manifestation.set_agent_role_type(contributors_list, scope: :contributor)
809
+ manifestation.set_agent_role_type(publishers_list, scope: :publisher)
810
+ end
811
+ end
812
+
813
+ manifestation
814
+ end
815
+
816
+ def self.transition_class
817
+ ResourceImportFileTransition
818
+ end
819
+
820
+ def self.initial_state
821
+ :pending
822
+ end
823
+
824
+ def set_identifier(row)
825
+ identifiers = []
826
+ %w(isbn issn doi jpno ncid).each do |id_type|
827
+ if row[id_type.to_s].present?
828
+ row[id_type].split(/\/\//).each do |identifier_s|
829
+ import_id = Identifier.new(body: identifier_s)
830
+ identifier_type = IdentifierType.find_by(name: id_type)
831
+ identifier_type = IdentifierType.create!(name: id_type) unless identifier_type
832
+ import_id.identifier_type = identifier_type
833
+ identifiers << import_id if import_id.valid?
834
+ end
835
+ end
836
+ end
837
+ identifiers
838
+ end
839
+
840
+ def self.import_manifestation_custom_value(row, manifestation)
841
+ values = []
842
+ ManifestationCustomProperty.order(:position).pluck(:name).map{|c| "manifestation:#{c}"}.each do |column_name|
843
+ value = nil
844
+ property = column_name.split(':').last
845
+ next if row[column_name].blank?
846
+ if manifestation
847
+ value = manifestation.manifestation_custom_values.find_by(manifestation_custom_property: property)
848
+ end
849
+
850
+ if value
851
+ value.value = row[column_name]
852
+ else
853
+ value = ManifestationCustomValue.new(
854
+ manifestation_custom_property: ManifestationCustomProperty.find_by(name: property),
855
+ value: row[column_name]
856
+ )
857
+ end
858
+ values << value
859
+ end
860
+ values
861
+ end
862
+
863
+ def self.import_item_custom_value(row, item)
864
+ values = []
865
+ ItemCustomProperty.order(:position).pluck(:name).map{|c| "item:#{c}"}.each do |column_name|
866
+ value = nil
867
+ property = column_name.split(':').last
868
+ next if row[column_name].blank?
869
+ if item
870
+ value = item.item_custom_values.find_by(item_custom_property: property)
871
+ end
872
+
873
+ if value
874
+ value.value = row[column_name]
875
+ else
876
+ value = ItemCustomValue.new(
877
+ item_custom_property: ItemCustomProperty.find_by(name: property),
878
+ value: row[column_name]
879
+ )
880
+ end
881
+ values << value
882
+ end
883
+ values
884
+ end
885
+ end
886
+
887
+ # == Schema Information
888
+ #
889
+ # Table name: resource_import_files
890
+ #
891
+ # id :integer not null, primary key
892
+ # parent_id :integer
893
+ # content_type :string
894
+ # size :integer
895
+ # user_id :integer
896
+ # note :text
897
+ # executed_at :datetime
898
+ # resource_import_file_name :string
899
+ # resource_import_content_type :string
900
+ # resource_import_file_size :integer
901
+ # resource_import_updated_at :datetime
902
+ # created_at :datetime
903
+ # updated_at :datetime
904
+ # edit_mode :string
905
+ # resource_import_fingerprint :string
906
+ # error_message :text
907
+ # user_encoding :string
908
+ # default_shelf_id :integer
909
+ #