swissmedic-diff 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1,2 +1,9 @@
1
1
  tags
2
2
  *.swp
3
+ pkg
4
+ .*#
5
+ .bundle
6
+ .ruby-version
7
+ *.patch
8
+ InstalledFiles
9
+ SetupConfig
data/.travis.yml CHANGED
@@ -11,7 +11,6 @@ rvm:
11
11
  - 2.1.2
12
12
  - 2.0.0
13
13
  - 1.9.3
14
- - 1.8.7
15
14
  matrix:
16
15
  allow_failures:
17
16
  - rvm: ruby-head
data/Gemfile CHANGED
@@ -11,6 +11,6 @@ group :debugger do
11
11
  gem 'pry-debugger'
12
12
  else
13
13
  gem 'pry-byebug'
14
+ gem 'pry-doc'
14
15
  end
15
16
  end unless RUBY_VERSION =~ /^1\.8/
16
-
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- swissmedic-diff (0.1.9)
4
+ swissmedic-diff (0.2.0)
5
5
  nokogiri
6
- rubyXL
6
+ rubyXL (= 3.3.1)
7
7
  rubyzip
8
8
  spreadsheet
9
9
 
@@ -25,7 +25,7 @@ GEM
25
25
  method_source (0.8.2)
26
26
  mini_portile (0.6.2)
27
27
  minitest (5.7.0)
28
- minitest-reporters (1.0.16)
28
+ minitest-reporters (1.0.17)
29
29
  ansi
30
30
  builder
31
31
  minitest (>= 5.0)
@@ -42,7 +42,7 @@ GEM
42
42
  rake (10.4.2)
43
43
  ruby-ole (1.2.11.8)
44
44
  ruby-progressbar (1.7.5)
45
- rubyXL (3.3.8)
45
+ rubyXL (3.3.1)
46
46
  nokogiri (>= 1.4.4)
47
47
  rubyzip (>= 1.1.6)
48
48
  rubyzip (1.1.7)
@@ -60,3 +60,6 @@ DEPENDENCIES
60
60
  pry-debugger
61
61
  rake
62
62
  swissmedic-diff!
63
+
64
+ BUNDLED WITH
65
+ 1.10.5
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ === 0.2.0 / 03.07.2015
2
+
3
+ * Abort if Swissmedic introduces incompatible header lines
4
+ * Support new format of SwissMedic July 2015
5
+ * Reworked compating xlsx-files
6
+ * Remove support for old .xls-format (used before 2013)
7
+
1
8
  === 0.1.9 / 08.06.2015
2
9
 
3
10
  * Swissmedic has different header lines
data/Manifest.txt CHANGED
@@ -13,12 +13,8 @@ lib/swissmedic-diff.rb
13
13
  lib/version.rb
14
14
  setup.rb
15
15
  swissmedic-diff.gemspec
16
- test/data/Packungen-2013.10.14.xls
17
- test/data/Packungen.older.xls
18
- test/data/Packungen.xls
19
- test/data/Packungen_2013_small.xls
20
- test/data/Packungen_2014_small.xlsx
21
- test/data/Packungen_error_column.xls
22
- test/data/Packungen_error_missing1.xls
23
- test/data/Packungen_error_missing2.xls
16
+ test/data/Packungen-2014.01.01.xlsx
17
+ test/data/Packungen-2014.02.01.xlsx
18
+ test/data/Packungen-2015.06.04.xlsx
19
+ test/data/Packungen-2015.07.02.xlsx
24
20
  test/test_swissmedic-diff.rb
data/README.txt CHANGED
@@ -29,7 +29,7 @@ Then you can get the version 0.1.2.
29
29
 
30
30
  == REQUIREMENTS:
31
31
 
32
- * ruby 1.8 (with oniguruma patch) or ruby 1.9
32
+ * ruby 1.9, ruby 2.x
33
33
  * spreadsheet
34
34
 
35
35
  == INSTALL:
@@ -62,6 +62,7 @@ Usage: /usr/bin/swissmedic-diff [-gnr] <file1> <file2> [<output>]
62
62
  * Hannes Wyss <hwyss@ywesee.com>
63
63
  * Masaomi Hatakeyama <mhatakeyama@ywesee.com>
64
64
  * Zeno R.R. Davatz <zdavatz@ywesee.com>
65
+ * Niklaus Giger <ngiger@ywesee.com>
65
66
 
66
67
  == LICENSE:
67
68
 
@@ -23,11 +23,59 @@ require File.join(File.dirname(__FILE__), 'compatibility.rb')
23
23
  #Source:: http://scm.ywesee.com/?p=swissmedic-diff/.git;a=summary
24
24
  class SwissmedicDiff
25
25
  module Diff
26
- COLUMNS = [ :iksnr, :seqnr, :name_base, :company,
26
+ COLUMNS_2014 = {
27
+ :iksnr => /Zulassungs-Nummer/i, # column-nr: 0
28
+ :seqnr => /Dosistärke-nummer|^Sequenz$/i,
29
+ :name_base => /Präparatebezeichnung|^Sequenzname$/i,
30
+ :company => /Zulassungsinhaberin/i,
31
+ :index_therapeuticus => /IT-Nummer/i,
32
+ :atc_class => /ATC-Code/i, # column-nr: 5
33
+ :production_science => /Heilmittelcode/i,
34
+ :registration_date => /Erstzul.datum Präp./i,
35
+ :sequence_date => /Zul.datum Dosisstärke *|Zul.datum Sequenz/i,
36
+ :expiry_date => /Gültigkeits-datum */i,
37
+ :ikscd => /Verpackungs ID/i, # column-nr: 10
38
+ :size => /Packungsgrösse/i,
39
+ :unit => /Einheit/i,
40
+ :ikscat => /Abgabekategorie/i,
41
+ :substances => /Wirkstoff/i,
42
+ :composition => /Zusammensetzung/i, # column-nr: 15
43
+ :indication_registration => /Anwendungsgebiet Präparate/i,
44
+ :indication_sequence => /Anwendungsgebiet Dosisstärke|Anwendungsgebiet Sequenz/i,
45
+ }
46
+
47
+ COLUMNS_OLD = [ :iksnr, :seqnr, :name_base, :company,
27
48
  :index_therapeuticus, :atc_class, :production_science,
28
49
  :registration_date, :sequence_date, :expiry_date, :ikscd,
29
50
  :size, :unit, :ikscat, :substances, :composition,
30
51
  :indication_registration, :indication_sequence ]
52
+
53
+ COLUMNS_JULY_2015 = {
54
+ :iksnr => /Zulassungs-Nummer/i, # column-nr: 0
55
+ :seqnr => /Dosisstärke-nummer/i,
56
+ :name_base => /Präparatebezeichnung/i,
57
+ :company => /Zulassungsinhaberin/i,
58
+ :production_science => /Heilmittelcode/i,
59
+ :index_therapeuticus => /IT-Nummer/i, # column-nr: 5
60
+ :atc_class => /ATC-Code/i,
61
+ :registration_date => /Erstzulassungs-datum./i,
62
+ :sequence_date => /Zul.datum Dosisstärke/i,
63
+ :expiry_date => /Gültigkeitsdauer der Zulassung/i,
64
+ :ikscd => /Packungscode/i, # column-nr: 10
65
+ :size => /Packungsgrösse/i,
66
+ :unit => /Einheit/i,
67
+ :ikscat => /Abgabekategorie Packung/i,
68
+ :ikscat_seq => /Abgabekategorie Dosisstärke/i,
69
+ :ikscat_preparation => /Abgabekategorie Präparat/i, # column-nr: 15
70
+ :substances => /Wirkstoff/i,
71
+ :composition => /Zusammensetzung/i,
72
+ :indication_registration => /Anwendungsgebiet Präparat/i,
73
+ :indication_sequence => /Anwendungsgebiet Dosisstärke/i,
74
+ :gen_production => /Gentechnisch hergestellte Wirkstoffe/i, # column-nr 20
75
+ :insulin_category => /Kategorie bei Insulinen/i,
76
+ :drug_index => /Verz. bei betäubunsmittel-haltigen Präparaten/i,
77
+ }
78
+
31
79
  FLAGS = {
32
80
  :new => 'Neues Produkt',
33
81
  :name_base => 'Namensänderung',
@@ -58,9 +106,6 @@ class SwissmedicDiff
58
106
  cell.to_s
59
107
  end
60
108
  end
61
- def column(key)
62
- COLUMNS.index(key)
63
- end
64
109
  def describe(diff, iksnr)
65
110
  sprintf("%s: %s", iksnr, name(diff, iksnr))
66
111
  end
@@ -77,10 +122,10 @@ class SwissmedicDiff
77
122
  sprintf "%s (%s)", txt, pairs.join(',')
78
123
  when :registration_date, :expiry_date
79
124
  row = diff.newest_rows[iksnr].sort.first.last
80
- sprintf "%s (%s)", txt, row[column(flag)].strftime('%d.%m.%Y')
125
+ sprintf "%s (%s)", txt, row[COLUMNS_2014.keys.index(flag)].value.strftime('%d.%m.%Y')
81
126
  else
82
127
  row = diff.newest_rows[iksnr].sort.first.last
83
- sprintf "%s (%s)", txt, cell(row, column(flag))
128
+ sprintf "%s (%s)", txt, cell(row, COLUMNS_2014.keys.index(flag))
84
129
  end
85
130
  end
86
131
 
@@ -101,26 +146,27 @@ class SwissmedicDiff
101
146
  @diff.newest_rows = newest_rows
102
147
  Spreadsheet.client_encoding = 'UTF-8'
103
148
  tbook = Spreadsheet.open(target)
104
- sheet = tbook.worksheet(0)
105
149
  idx, prr, prp = nil
106
150
  multiples = {}
151
+ latest_keys = get_column_indices(Spreadsheet.open(latest)).keys
152
+ target_keys = get_column_indices(tbook).keys
107
153
  each_valid_row(tbook) { |row|
108
- iksnr = cell(row, column(:iksnr))
109
- seqnr = cell(row, column(:seqnr))
110
- pacnr = cell(row, column(:ikscd))
154
+ iksnr = cell(row, target_keys.index(:iksnr))
155
+ seqnr = cell(row, target_keys.index(:seqnr))
156
+ pacnr = cell(row, target_keys.index(:ikscd))
111
157
  (multiples[iksnr] ||= {})
112
158
  if prr == iksnr && prp == pacnr
113
159
  idx += 1
114
160
  elsif previous = multiples[iksnr][pacnr]
115
161
  prr = iksnr
116
162
  prp = pacnr
117
- idx = previous[COLUMNS.size].to_i + 1
163
+ idx = previous[target_keys.size].to_i + 1
118
164
  else
119
165
  prr = iksnr
120
166
  prp = pacnr
121
167
  idx = 0
122
168
  end
123
- row[COLUMNS.size] = idx
169
+ row[target_keys.size] = idx
124
170
  (newest_rows[iksnr] ||= {})[pacnr] = row
125
171
  multiples[iksnr][pacnr] = row
126
172
  if(other = known_regs.delete([iksnr]))
@@ -130,12 +176,12 @@ class SwissmedicDiff
130
176
  end
131
177
  known_seqs.delete([iksnr, seqnr])
132
178
  if(other = known_pacs.delete([iksnr, pacnr, idx]))
133
- flags = rows_diff(row, other, ignore)
179
+ flags = rows_diff(row, target_keys, other, latest_keys, ignore)
134
180
  (changes[iksnr].concat flags).uniq!
135
181
  updates.push row unless flags.empty?
136
182
  else
137
- replacements.store [ iksnr, seqnr, cell(row, column(:size)),
138
- cell(row, column(:unit)) ], row
183
+ replacements.store [ iksnr, seqnr, cell(row, target_keys.index(:size)),
184
+ cell(row, target_keys.index(:unit)) ], row
139
185
  flags = changes[iksnr]
140
186
  flags.push(:sequence).uniq! unless(flags.include? :new)
141
187
  news.push row
@@ -143,8 +189,8 @@ class SwissmedicDiff
143
189
  }
144
190
  @diff.replacements = reps = {}
145
191
  known_pacs.each { |(iksnr, pacnr), row|
146
- key = [iksnr, '%02i' % cell(row, column(:seqnr)).to_i,
147
- cell(row, column(:size)), cell(row, column(:unit))]
192
+ key = [iksnr, '%02i' % cell(row, target_keys.index(:seqnr)).to_i,
193
+ cell(row, target_keys.index(:size)), cell(row, target_keys.index(:unit))]
148
194
  if(rep = replacements[key])
149
195
  changes[iksnr].push :replaced_package
150
196
  reps.store rep, pacnr
@@ -156,7 +202,7 @@ class SwissmedicDiff
156
202
  ## the keys in known_pacs don't include the sequence number (which
157
203
  # would prevent us from properly recognizing multi-sequence-Packages),
158
204
  # so we need complete the path to the package now
159
- key[1,0] = '%02i' % cell(row, column(:seqnr)).to_i
205
+ key[1,0] = '%02i' % cell(row, target_keys.index(:seqnr)).to_i
160
206
  key
161
207
  }
162
208
  @diff.sequence_deletions = known_seqs.keys
@@ -181,24 +227,25 @@ class SwissmedicDiff
181
227
  lbook = Spreadsheet.open(latest)
182
228
  idx, prr, prp = nil
183
229
  multiples = {}
230
+ latest_keys = get_column_indices(lbook).keys
184
231
  each_valid_row(lbook) { |row|
185
- iksnr = cell(row, column(:iksnr))
186
- seqnr = cell(row, column(:seqnr))
187
- pacnr = cell(row, column(:ikscd))
232
+ iksnr = cell(row, latest_keys.index(:iksnr))
233
+ seqnr = cell(row, latest_keys.index(:seqnr))
234
+ pacnr = cell(row, latest_keys.index(:ikscd))
188
235
  multiples[iksnr] ||= {}
189
236
  if prr == iksnr && prp == pacnr
190
237
  idx += 1
191
238
  elsif previous = multiples[iksnr][pacnr]
192
239
  prr = iksnr
193
240
  prp = pacnr
194
- idx = previous[COLUMNS.size].to_i + 1
241
+ idx = previous[latest_keys.size].to_i + 1
195
242
  else
196
243
  prr = iksnr
197
244
  prp = pacnr
198
245
  idx = 0
199
246
  end
200
247
  multiples[iksnr][pacnr] = row
201
- row[COLUMNS.size] = idx
248
+ row[latest_keys.size] = idx
202
249
  known_regs.store [iksnr], row
203
250
  known_seqs.store [iksnr, seqnr], row
204
251
  known_pacs.store [iksnr, pacnr, idx], row
@@ -208,16 +255,19 @@ class SwissmedicDiff
208
255
  def name(diff, iksnr)
209
256
  rows = diff.newest_rows[iksnr]
210
257
  row = rows.sort.first.last
211
- cell(row, column(:name_base))
258
+ cell(row, COLUMNS_2014.keys.index(:name_base))
212
259
  end
213
- def rows_diff(row, other, ignore = [])
260
+ def rows_diff(row, row_keys, other, other_keys, ignore = [])
214
261
  flags = []
215
- COLUMNS.each_with_index { |key, idx|
216
- if(!ignore.include?(key) \
217
- && _comparable(key, row, idx) != _comparable(key, other, idx))
218
- # binding.pry if key == :expiry_date
219
-
220
- flags.push key
262
+ COLUMNS_OLD.each_with_index {
263
+ |key, idx|
264
+ if !ignore.include?(key)
265
+ left = _comparable(key, row, row_keys.index(key))
266
+ right = _comparable(key, other, other_keys.index(key))
267
+ if left != right
268
+ puts "Pushing key #{key}: '#{left.inspect}' != '#{right.inspect}'" if $VERBOSE
269
+ flags.push key
270
+ end
221
271
  end
222
272
  }
223
273
  flags
@@ -277,6 +327,42 @@ class SwissmedicDiff
277
327
  end
278
328
  end
279
329
 
330
+ def get_column_indices(spreadsheet)
331
+ error_2014 = nil
332
+ filename = spreadsheet.root.filepath
333
+ headerRowId = rows_to_skip(spreadsheet)-1
334
+ row = spreadsheet.worksheet(0)[headerRowId]
335
+
336
+ COLUMNS_2014.each{
337
+ |key, value|
338
+ header_name = row[COLUMNS_2014.keys.index(key)].value
339
+ unless value.match(header_name)
340
+ puts "#{__LINE__}: #{key} -> #{COLUMNS_2014.keys.index(key)} #{value}\nbut was #{header_name}" if $VERBOSE
341
+ error_2014 = "#{filename}_has_unexpected_column_#{COLUMNS_2014.keys.index(key)}_#{key}_#{value.to_s}_but_was_#{header_name}"
342
+ break
343
+ end
344
+ }
345
+ return COLUMNS_2014 unless error_2014
346
+ error_2015 = nil
347
+ COLUMNS_JULY_2015.each{
348
+ |key, value|
349
+ header_name = row[COLUMNS_JULY_2015.keys.index(key)].value
350
+ unless value.match(header_name)
351
+ puts "#{__LINE__}: #{key} -> #{COLUMNS_JULY_2015.keys.index(key)} #{value}\nbut was #{header_name}" if $VERBOSE
352
+ error_2015 = "#{filename}_has_unexpected_column_#{COLUMNS_JULY_2015.keys.index(key)}_#{key}_#{value.to_s}_but_was_#{header_name}"
353
+ break
354
+ end
355
+ }
356
+ unless error_2015
357
+ idx14 = COLUMNS_2014.keys.index(:name_base)
358
+ idx15 = COLUMNS_2014.keys.index(:name_base)
359
+ if (idx14 != idx15)
360
+ raise ":name_base must be same index in COLUMNS_JULY_2015 and COLUMNS_2014. Is #{idx14} and #{idx15}"
361
+ end
362
+ return COLUMNS_JULY_2015
363
+ end
364
+ raise "#{error_2015}\n#{error_2014}"
365
+ end
280
366
  #=== iterate over all valid rows of a swissmedic Packungen.xls
281
367
  #
282
368
  # Iterates over all rows, ignoring Tierarzneimittel and
@@ -292,20 +378,22 @@ class SwissmedicDiff
292
378
  #return ::
293
379
  def each_valid_row(spreadsheet)
294
380
  skipRows = rows_to_skip(spreadsheet)
381
+ column_keys = get_column_indices(spreadsheet).keys
295
382
  worksheet = spreadsheet.worksheet(0)
296
383
  row_nr = 0
297
384
  worksheet.each() {
298
385
  |row|
299
386
  row_nr += 1
300
387
  next if row_nr <= skipRows
301
- if row.size < COLUMNS.size/2
388
+ break unless row
389
+ if row.size < column_keys.size/2
302
390
  $stdout.puts "Data missing in \n(line " + (row_nr).to_s + "): " + row.join(", ").to_s + "\n"
303
391
  next
304
392
  end
305
- next if (cell(row, column(:production_science)) == 'Tierarzneimittel')
306
- row[column(:iksnr)] = "%05i" % cell(row, column(:iksnr)).to_i
307
- row[column(:seqnr)] = "%02i" % cell(row, column(:seqnr)).to_i
308
- row[column(:ikscd)] = "%03i" % cell(row, column(:ikscd)).to_i
393
+ next if (cell(row, column_keys.index(:production_science)) == 'Tierarzneimittel')
394
+ row[column_keys.index(:iksnr)] = "%05i" % cell(row, column_keys.index(:iksnr)).to_i
395
+ row[column_keys.index(:seqnr)] = "%02i" % cell(row, column_keys.index(:seqnr)).to_i
396
+ row[column_keys.index(:ikscd)] = "%03i" % cell(row, column_keys.index(:ikscd)).to_i
309
397
  yield row
310
398
  }
311
399
  end
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class SwissmedicDiff
2
- VERSION = '0.1.9'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -15,7 +15,7 @@ spec = Gem::Specification.new do |s|
15
15
  Dir.glob('test/data/*.xls')
16
16
  s.test_file = "test/test_swissmedic-diff.rb"
17
17
  s.executables << 'swissmedic-diff'
18
- s.add_dependency('rubyXL')
18
+ s.add_dependency('rubyXL', '3.3.1')
19
19
  s.add_dependency('nokogiri')
20
20
  s.add_dependency('rubyzip')
21
21
  s.add_dependency('spreadsheet')
Binary file
Binary file
Binary file
@@ -6,58 +6,40 @@ $: << File.expand_path("../lib", File.dirname(__FILE__))
6
6
 
7
7
  require 'minitest/autorun'
8
8
  require 'swissmedic-diff'
9
- require 'pp'
9
+ require 'pp'
10
10
 
11
11
  module ODDB
12
12
  class SwissmedicPluginTest < Minitest::Test
13
13
  def setup
14
14
  @diff = SwissmedicDiff.new
15
- @data = File.expand_path 'data/Packungen.xls',
16
- File.dirname(__FILE__)
17
- @older = File.expand_path 'data/Packungen.older.xls',
18
- File.dirname(__FILE__)
19
- @data_error_column = File.expand_path 'data/Packungen_error_column.xls',
20
- File.dirname(__FILE__)
21
- @data_error_missing_case1 = File.expand_path 'data/Packungen_error_missing1.xls',
22
- File.dirname(__FILE__)
23
- @data_error_missing_case2 = File.expand_path 'data/Packungen_error_missing2.xls',
24
- File.dirname(__FILE__)
25
- @data_2013 = File.expand_path 'data/Packungen-2013.10.14.xls',
26
- File.dirname(__FILE__)
27
- @workbook = Spreadsheet.open(@data)
15
+ @january_2014 = File.expand_path 'data/Packungen-2014.01.01.xlsx', File.dirname(__FILE__)
16
+ @february_2014 = File.expand_path 'data/Packungen-2014.02.01.xlsx', File.dirname(__FILE__)
28
17
  end
29
-
30
- def test_diff_xls_and_xlsx
18
+
19
+ def test_diff_new_format_july_2015
31
20
  @diff = SwissmedicDiff.new
32
- last_month = File.expand_path 'data/Packungen_2013_small.xls', File.dirname(__FILE__)
33
- this_month = File.expand_path 'data/Packungen_2014_small.xlsx', File.dirname(__FILE__)
34
- result = @diff.diff last_month, this_month, [:atc_class, :sequence_date]
21
+ last_month = File.expand_path 'data/Packungen-2015.06.04.xlsx', File.dirname(__FILE__)
22
+ this_month = File.expand_path 'data/Packungen-2015.07.02.xlsx', File.dirname(__FILE__)
23
+ result = @diff.diff this_month, last_month, [:atc_class, :sequence_date]
35
24
  assert(result.changes.flatten.index('Zulassungs-Nummer') == nil, "Should not find Zulassungs-Nummer in changes")
36
- # puts "Got #{result.news.size} news, #{result.changes.size} changes, #{result.updates.size} updates."
37
- assert_equal(8, result.news.size)
38
- assert_equal(4, result.changes.size)
39
- assert_equal(2, result.updates.size)
40
- assert(result.news.first.index('00280'), "Should find 00280 in news")
41
- assert(result.news.flatten.index('65034'), "Should find 65034 in news")
42
- assert(result.news.flatten.index('00277') == nil, "Should not find 00277 in news")
43
- assert(result.news.flatten.index('Zulassungs-Nummer') == nil, "Should not find Zulassungs-Nummer in changes")
25
+ assert_equal(1, result.news.size)
26
+ assert_equal(2, result.changes.size)
27
+ assert_equal(1, result.updates.size)
28
+ assert_equal(['65838'], result.news.collect{|x| x[0] if x[0] == '65838'})
29
+ assert_equal({"65837"=>[:indication_sequence], "65838"=>[:new]}, result.changes)
44
30
  end
45
31
 
46
- def test_date_xls
47
- tbook = Spreadsheet.open(File.expand_path('data/Packungen.xls', File.dirname(__FILE__)))
48
- sheet = tbook.worksheet(0)
49
- assert_equal(nil, sheet.row(0)[8]) # sequence_date
50
- assert_equal(2010, sheet.row(4).date(8).year)
51
- assert_equal(26, sheet.row(4).date(8).day)
52
- # assert_equal(26, Spreadsheet.date_cell(sheet.row(4), 8))
53
- assert_equal(26, Spreadsheet.date_cell(sheet.row(4), 8).day)
54
- assert_equal(2010, Spreadsheet.date_cell(sheet.row(4), 8).year)
32
+ def test_diff_wrong_header
33
+ @diff = SwissmedicDiff.new
34
+ last_month = File.expand_path 'data/Packungen-2015.06.04.xlsx', File.dirname(__FILE__)
35
+ this_month = File.expand_path 'data/Packungen-wrong-header.xlsx', File.dirname(__FILE__)
36
+ assert_raises(RuntimeError) { @diff.diff this_month, last_month, [:atc_class, :sequence_date]}
55
37
  end
56
-
38
+
39
+
57
40
  def test_date_xlsx
58
- tbook = Spreadsheet.open(File.expand_path('data/Packungen_2014_small.xlsx', File.dirname(__FILE__)))
41
+ tbook = Spreadsheet.open(@january_2014)
59
42
  sheet = tbook.worksheet(0)
60
- # sheet = RubyXL::Parser.parse(File.expand_path(File.expand_path 'data/Packungen_2014_small.xlsx', File.dirname(__FILE__)))[0]
61
43
  assert_equal(nil, sheet.row(0)[8]) # sequence_date
62
44
  assert_equal(2010, sheet.row(4).date(8).year)
63
45
  assert_equal(26, sheet.row(4).date(8).day)
@@ -65,188 +47,87 @@ module ODDB
65
47
  assert_equal(2010, Spreadsheet.date_cell(sheet.row(4), 8).year)
66
48
  end
67
49
 
68
- def test_diff_xlsx_and_xls
69
- @diff = SwissmedicDiff.new
70
- last_month = File.expand_path 'data/Packungen_2014_01.xlsx', File.dirname(__FILE__)
71
- this_month = File.expand_path 'data/Packungen.xls', File.dirname(__FILE__)
72
- result = @diff.diff last_month, this_month, [:atc_class, :sequence_date]
73
- assert_equal(7, result.news.size)
74
- assert_equal(2, result.updates.size)
75
- assert_equal(10, result.changes.size)
76
- assert(result.changes.flatten.index('00275'), "Should find 00275 in changes")
77
- assert(result.changes.flatten.index('00277'), "Should find 00277 in changes")
78
- assert(result.news.flatten.index('Zulassungs-Nummer') == nil, "Should not find Zulassungs-Nummer in changes")
79
- end
80
50
  def test_diff_xlsx_and_xlsx
81
- @diff = SwissmedicDiff.new
82
- last_month = File.expand_path 'data/Packungen_2014_01.xlsx', File.dirname(__FILE__)
83
- this_month = File.expand_path 'data/Packungen_2014_small.xlsx', File.dirname(__FILE__)
84
- result = @diff.diff last_month, this_month, [:atc_class, :sequence_date]
85
- assert_equal({"00277"=>[:expiry_date, :indication_sequence]}, result.changes)
86
- assert_equal(1, result.updates.size)
87
- assert_equal([], result.news)
88
- end
89
-
90
- def test_iterate
91
- diff = SwissmedicDiff.new
92
- strings = []
93
- diff.each_valid_row(Spreadsheet.open(@data_2013)) { |x| strings << "iksnr #{x[0]} packungs id #{x[diff.column(:ikscd)]}" }
94
- expected = [
95
- "iksnr 00277 packungs id 001",
96
- "iksnr 00277 packungs id 002",
97
- "iksnr 61338 packungs id 001",
98
- "iksnr 61338 packungs id 002",
99
- "iksnr 61367 packungs id 001",
100
- "iksnr 61367 packungs id 002",
101
- "iksnr 61367 packungs id 003",
102
- "iksnr 61367 packungs id 004",
103
- "iksnr 61367 packungs id 005",
104
- "iksnr 61416 packungs id 001",
105
- "iksnr 63164 packungs id 001",
106
- "iksnr 63164 packungs id 002",
107
- "iksnr 63164 packungs id 003",
108
- "iksnr 65040 packungs id 001"
109
- ]
110
- assert_equal(expected, strings)
111
- end
112
-
113
- def test_diff_pre_2013_to_2013
114
- result = @diff.diff(@data_2013, @data)
115
- assert(result.changes.flatten.index('Zulassungs-Nummer') == nil, "Should not find Zulassungs-Nummer in changes")
116
- assert(result.news.flatten.index('Zulassungs-Nummer') == nil, "Should not find Zulassungs-Nummer in changes")
117
- assert(result.news.flatten.index('00277') == nil, "Should not find 00277 in news")
118
- assert_equal 6, result.news.size
51
+ result = @diff.diff @february_2014, @january_2014, [:atc_class, :sequence_date]
52
+ assert_equal 4, result.news.size
119
53
  expected = {
120
- "00277"=>[:company, :sequence_date, :substances, :composition, :name_base],
121
- "61338"=>[:sequence_date, :company, :atc_class],
122
- "61367"=>
123
- [:sequence_date,
124
- :ikscat,
125
- :substances,
126
- :composition,
127
- :sequence,
128
- :replaced_package],
129
- "61416"=>[:sequence_date],
130
- "63164"=>[:new],
131
- "65040"=>[:new],
132
- "00275"=>[:delete],
133
- "61345"=>[:delete]
134
- }
135
- assert_equal(expected, result.changes)
136
- diff_string =%(+ 63164: Rivastigmin Patch Sandoz 5, Transdermales Pflaster
137
- + 65040: Panthoben, Salbe
138
- - 00275: Cardio-Pulmo-Rénal Sérocytol, suppositoire
139
- - 61345: Terbinafin-Teva 125 mg, Tabletten
140
- > 00277: Coeur-Vaisseaux Sérocytol, suppositoire; Zulassungsinhaber (Sérolab, société anonyme), Zulassungsdatum Sequenz (2010-04-26), Wirkstoffe (globulina equina (immunisé avec coeur, endothélium vasculaire porcins)), Zusammensetzung (globulina equina (immunisé avec coeur, endothélium vasculaire porcins) 8 mg, propylenglycolum, conserv.: E 216, E 218, excipiens pro suppositorio.), Namensänderung (Coeur-Vaisseaux Sérocytol, suppositoire)
141
- > 61338: Cefuroxim Fresenius i.v. 750 mg, Pulver zur Herstellung einer i.v. Lösung; Zulassungsdatum Sequenz (2010-03-16), Zulassungsinhaber (Fresenius Kabi (Schweiz) AG), ATC-Code (J01DC02)
142
- > 61367: Hypericum-Mepha 250, Lactab; Zulassungsdatum Sequenz (2010-04-23), Abgabekategorie (D), Wirkstoffe (hyperici herbae extractum ethanolicum siccum quantificatum), Zusammensetzung (hyperici herbae extractum ethanolicum siccum quantificatum 250 mg corresp. hypericinum 0.25-0.75 mg, DER: 4-7:1, excipiens pro compresso obducto.), Packungs-Nummer (006 -> 005)
143
- > 61416: Otriduo Schnupfen, Nasentropfen; Zulassungsdatum Sequenz (2010-05-12))
144
- assert_equal(diff_string, @diff.to_s)
145
- end
146
- def test_diff
147
- result = @diff.diff(@data, @older)
148
- assert_equal 3, result.news.size
149
- assert_equal 'Cardio-Pulmo-Rénal Sérocytol, suppositoire',
150
- result.news.first.at(2)
151
- assert_equal 2, result.updates.size
152
- assert_equal 'Coeur-Vaisseaux Sérocytol, suppositoire(update)',
153
- result.updates.first.at(2)
154
- assert_equal 6, result.changes.size
155
- expected = {
156
- "00275"=>[:new],
157
- "00277"=>[:name_base],
158
- "61338"=>[:company, :atc_class],
159
- "61367"=>[:sequence, :replaced_package],
160
- "61416"=>[:new],
161
- "00274"=>[:delete]
54
+ "00277"=>[:name_base, :expiry_date, :indication_sequence],
55
+ "65040"=>[:sequence, :replaced_package],
56
+ "60125"=>[:new],
57
+ "61367"=>[:new],
58
+ "00274"=>[:delete]
162
59
  }
163
60
  assert_equal(expected, result.changes)
61
+ assert_equal 1, result.updates.size
62
+ assert_equal 5, result.changes.size
164
63
  assert_equal 3, result.package_deletions.size
165
64
  assert_equal 4, result.package_deletions.first.size
166
65
  iksnrs = result.package_deletions.collect { |row| row.at(0) }.sort
167
66
  ikscds = result.package_deletions.collect { |row| row.at(2) }.sort
168
- assert_equal ["00274", "61367", "61367"], iksnrs
169
- assert_equal ["001", "002", "005"], ikscds
67
+ assert_equal ["00274", "00274", "65040"], iksnrs
68
+ assert_equal ["001", "001", "002"], ikscds
170
69
  assert_equal 1, result.sequence_deletions.size
171
70
  assert_equal ["00274", "01"], result.sequence_deletions.at(0)
172
71
  assert_equal 1, result.registration_deletions.size
173
72
  assert_equal ["00274"], result.registration_deletions.at(0)
174
73
  assert_equal 1, result.replacements.size
175
- assert_equal '005', result.replacements.values.first
74
+ assert_equal '001', result.replacements.values.first
75
+
76
+ assert_equal 'Panthoben, Salbe', result.news.first[2].value
77
+ assert_equal 'Coeur-Vaisseaux Sérocytol, Namensänderung', result.updates.first[2].value
176
78
  end
79
+
177
80
  def test_diff_error_column
178
- res = @diff.diff(@data_error_column, @older)
81
+ res = @diff.diff(@february_2014, @january_2014)
179
82
  assert_equal(OpenStruct, res.class)
180
83
  end
181
84
 
182
- # if row.size < COLUMNS.size/2
183
- # as per december 2013 does no longer raise an error, but outputs the problematic line
184
- def test_diff_error_missing_case1
185
- @diff.diff(@data_error_missing_case1, @older)
186
- end
187
-
188
- # if row.select{|val| val==nil}.size > COLUMNS.size/2
189
- # as per december 2013 does no longer raise an error, but outputs the problematic line
190
- def test_diff_error_missing_case2
191
- @diff.diff(@data_error_missing_case2, @older)
192
- end
193
85
  def test_diff__ignore
194
- ignore = [:company, :atc_class]
195
- result = @diff.diff(@data, @older, ignore)
196
- assert_equal 3, result.news.size
197
- assert_equal 'Cardio-Pulmo-Rénal Sérocytol, suppositoire',
198
- result.news.first.at(2)
199
- assert_equal 1, result.updates.size
200
- assert_equal 'Coeur-Vaisseaux Sérocytol, suppositoire(update)',
201
- result.updates.first.at(2)
202
- assert_equal 5, result.changes.size
86
+ ignore = [:company, :name_base, :expiry_date, :indication_sequence]
87
+ result = @diff.diff(@february_2014, @january_2014, ignore)
203
88
  expected = {
204
- "00275"=>[:new],
205
- "00277"=>[:name_base],
206
- "61367"=>[:sequence, :replaced_package],
207
- "61416"=>[:new],
89
+ "00278"=>[:atc_class],
90
+ "00279"=>[:atc_class],
91
+ "65040"=>[:sequence, :replaced_package],
92
+ "60125"=>[:new],
93
+ "61367"=>[:new],
208
94
  "00274"=>[:delete]
209
95
  }
210
96
  assert_equal(expected, result.changes)
97
+ assert_equal 4, result.news.size
98
+ assert_equal 3, result.updates.size
99
+ assert_equal 6, result.changes.size
211
100
  assert_equal 3, result.package_deletions.size
212
- assert_equal 4, result.package_deletions.first.size
213
- iksnrs = result.package_deletions.collect { |row| row.at(0) }.sort
214
- ikscds = result.package_deletions.collect { |row| row.at(2) }.sort
215
- assert_equal ["00274", "61367", "61367"], iksnrs
216
- assert_equal ["001", "002", "005"], ikscds
217
- assert_equal 1, result.sequence_deletions.size
218
- assert_equal ["00274", "01"], result.sequence_deletions.at(0)
219
- assert_equal 1, result.registration_deletions.size
220
- assert_equal ["00274"], result.registration_deletions.at(0)
221
- assert_equal 1, result.replacements.size
222
- assert_equal '005', result.replacements.values.first
223
101
  end
224
102
  def test_to_s
225
103
  @diff.to_s
226
- @diff.diff(@data, @older)
104
+ @diff.diff(@february_2014, @january_2014)
227
105
  assert_equal <<-EOS.strip, @diff.to_s
228
- + 00275: Cardio-Pulmo-Rénal Sérocytol, suppositoire
229
- + 61416: Otriduo Schnupfen, Nasentropfen
106
+ + 60125: Otriduo Schnupfen, Dosierspray
107
+ + 61367: Hypericum-Mepha 250, Lactab
230
108
  - 00274: Cardio-Pulmo-Rénal Sérocytol, suppositoire
231
- > 00277: Coeur-Vaisseaux Sérocytol, suppositoire; Namensänderung (Coeur-Vaisseaux Sérocytol, suppositoire)
232
- > 61338: Cefuroxim Fresenius i.v. 750 mg, Pulver zur Herstellung einer i.v. Lösung; Zulassungsinhaber (Fresenius Kabi (Schweiz) AG), ATC-Code (J01DC02)
233
- > 61367: Hypericum-Mepha 250, Lactab; Packungs-Nummer (005 -> 006)
109
+ > 00277: Coeur-Vaisseaux Sérocytol, Namensänderung; Namensänderung (Coeur-Vaisseaux Sérocytol, Namensänderung), Ablaufdatum der Zulassung (25.04.2020), Anwendungsgebiet Sequenz ()
110
+ > 00278: Colon Sérocytol, suppositoire; ATC-Code (J06AA)
111
+ > 00279: Conjonctif Sérocytol, suppositoire; ATC-Code (D03AX04)
112
+ > 65040: Panthoben, Salbe; Packungs-Nummer (001 -> 003)
234
113
  EOS
235
114
  assert_equal <<-EOS.strip, @diff.to_s(:name)
236
115
  - 00274: Cardio-Pulmo-Rénal Sérocytol, suppositoire
237
- + 00275: Cardio-Pulmo-Rénal Sérocytol, suppositoire
238
- > 61338: Cefuroxim Fresenius i.v. 750 mg, Pulver zur Herstellung einer i.v. Lösung; Zulassungsinhaber (Fresenius Kabi (Schweiz) AG), ATC-Code (J01DC02)
239
- > 00277: Coeur-Vaisseaux Sérocytol, suppositoire; Namensänderung (Coeur-Vaisseaux Sérocytol, suppositoire)
240
- > 61367: Hypericum-Mepha 250, Lactab; Packungs-Nummer (005 -> 006)
241
- + 61416: Otriduo Schnupfen, Nasentropfen
242
- EOS
116
+ > 00277: Coeur-Vaisseaux Sérocytol, Namensänderung; Namensänderung (Coeur-Vaisseaux Sérocytol, Namensänderung), Ablaufdatum der Zulassung (25.04.2020), Anwendungsgebiet Sequenz ()
117
+ > 00278: Colon Sérocytol, suppositoire; ATC-Code (J06AA)
118
+ > 00279: Conjonctif Sérocytol, suppositoire; ATC-Code (D03AX04)
119
+ + 61367: Hypericum-Mepha 250, Lactab
120
+ + 60125: Otriduo Schnupfen, Dosierspray
121
+ > 65040: Panthoben, Salbe; Packungs-Nummer (001 -> 003)
122
+ EOS
243
123
  assert_equal <<-EOS.strip, @diff.to_s(:registration)
244
124
  - 00274: Cardio-Pulmo-Rénal Sérocytol, suppositoire
245
- + 00275: Cardio-Pulmo-Rénal Sérocytol, suppositoire
246
- > 00277: Coeur-Vaisseaux Sérocytol, suppositoire; Namensänderung (Coeur-Vaisseaux Sérocytol, suppositoire)
247
- > 61338: Cefuroxim Fresenius i.v. 750 mg, Pulver zur Herstellung einer i.v. Lösung; Zulassungsinhaber (Fresenius Kabi (Schweiz) AG), ATC-Code (J01DC02)
248
- > 61367: Hypericum-Mepha 250, Lactab; Packungs-Nummer (005 -> 006)
249
- + 61416: Otriduo Schnupfen, Nasentropfen
125
+ > 00277: Coeur-Vaisseaux Sérocytol, Namensänderung; Namensänderung (Coeur-Vaisseaux Sérocytol, Namensänderung), Ablaufdatum der Zulassung (25.04.2020), Anwendungsgebiet Sequenz ()
126
+ > 00278: Colon Sérocytol, suppositoire; ATC-Code (J06AA)
127
+ > 00279: Conjonctif Sérocytol, suppositoire; ATC-Code (D03AX04)
128
+ + 60125: Otriduo Schnupfen, Dosierspray
129
+ + 61367: Hypericum-Mepha 250, Lactab
130
+ > 65040: Panthoben, Salbe; Packungs-Nummer (001 -> 003)
250
131
  EOS
251
132
  end
252
133
  end
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: swissmedic-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Masaomi Hatakeyama, Zeno R.R. Davatz
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-06-08 00:00:00.000000000 Z
12
+ date: 2015-07-04 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rdoc
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ~>
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
@@ -27,17 +30,19 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: hoe
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ~>
32
36
  - !ruby/object:Gem::Version
33
- version: '3.7'
37
+ version: '3.13'
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ~>
39
44
  - !ruby/object:Gem::Version
40
- version: '3.7'
45
+ version: '3.13'
41
46
  description: ! '* Compares two Excel Documents provided by Swissmedic and displays
42
47
  the
43
48
 
@@ -60,7 +65,6 @@ extra_rdoc_files:
60
65
  - Manifest.txt
61
66
  - README.txt
62
67
  files:
63
- - .gemtest
64
68
  - .gitignore
65
69
  - .travis.yml
66
70
  - Gemfile
@@ -76,19 +80,15 @@ files:
76
80
  - lib/version.rb
77
81
  - setup.rb
78
82
  - swissmedic-diff.gemspec
79
- - test/data/Packungen-2013.10.14.xls
80
- - test/data/Packungen.older.xls
81
- - test/data/Packungen.xls
82
- - test/data/Packungen_2013_small.xls
83
- - test/data/Packungen_2014_small.xlsx
84
- - test/data/Packungen_error_column.xls
85
- - test/data/Packungen_error_missing1.xls
86
- - test/data/Packungen_error_missing2.xls
83
+ - test/data/Packungen-2014.01.01.xlsx
84
+ - test/data/Packungen-2014.02.01.xlsx
85
+ - test/data/Packungen-2015.06.04.xlsx
86
+ - test/data/Packungen-2015.07.02.xlsx
87
87
  - test/test_swissmedic-diff.rb
88
+ - .gemtest
88
89
  homepage: https://github.com/zdavatz/swissmedic-diff
89
90
  licenses:
90
91
  - MIT
91
- metadata: {}
92
92
  post_install_message:
93
93
  rdoc_options:
94
94
  - --main
@@ -96,21 +96,28 @@ rdoc_options:
96
96
  require_paths:
97
97
  - lib
98
98
  required_ruby_version: !ruby/object:Gem::Requirement
99
+ none: false
99
100
  requirements:
100
101
  - - ! '>='
101
102
  - !ruby/object:Gem::Version
102
103
  version: '0'
104
+ segments:
105
+ - 0
106
+ hash: -1183980882964765712
103
107
  required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
104
109
  requirements:
105
110
  - - ! '>='
106
111
  - !ruby/object:Gem::Version
107
112
  version: '0'
113
+ segments:
114
+ - 0
115
+ hash: -1183980882964765712
108
116
  requirements: []
109
- rubyforge_project: swissmedic-diff
110
- rubygems_version: 2.3.0
117
+ rubyforge_project:
118
+ rubygems_version: 1.8.23.2
111
119
  signing_key:
112
- specification_version: 4
120
+ specification_version: 3
113
121
  summary: ! '* Compares two Excel Documents provided by Swissmedic and displays the
114
122
  salient differences'
115
- test_files:
116
- - test/test_swissmedic-diff.rb
123
+ test_files: []
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NGZmZDYzOTBkNGI4MWQ5OTdlMTU4YmYyNzExNzI0YmU1MmZjOWIyMg==
5
- data.tar.gz: !binary |-
6
- NTA2M2YwNTU3M2RjNTIxNzJmZTUxZjM5MTg2NWZhZjg1NGM3ZGZlNA==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- YzU4YjQ4ODRkMzc4OTZmMWM3MWM2MjUxNTBlNDFmY2Q5ZmM0ZmVhMTJhZDZj
10
- MmQ2MTg2NWY2NzY1MzEzZTRkZTBlY2FkMTA3MGY0OGRkOWE4M2YxOTIxM2M2
11
- YTZkZWQyODMzZDRjMDE2OGVjNGVhNGM5NTFhNjc2ZjYyYTQ0ZmI=
12
- data.tar.gz: !binary |-
13
- MjUwYjRmZThhMGUxMTZkMDUxNzdjZTRkNWQyYWFlMzZmMzdmNjI2YmMwZjFk
14
- MWFjMmEwOWMwYTNjNTM3YTkyODNjOGE1MGMxNTFhMDIyZjRjOWQ0OWM4M2Qz
15
- YTM1ZTgyY2MwZTIwNTM0NzcyNjkwNDFhMjExM2MyZDMzNTgzZjI=
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file