oddb2xml 1.9.4 → 1.9.5
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.
- checksums.yaml +5 -13
- data/Gemfile.lock +10 -11
- data/History.txt +7 -0
- data/README.md +14 -9
- data/data/gal_forms.yaml +4704 -0
- data/data/gal_groups.yaml +217 -0
- data/lib/oddb2xml/builder.rb +73 -1
- data/lib/oddb2xml/calc.rb +327 -0
- data/lib/oddb2xml/cli.rb +23 -7
- data/lib/oddb2xml/downloader.rb +10 -4
- data/lib/oddb2xml/extractor.rb +5 -11
- data/lib/oddb2xml/options.rb +3 -0
- data/lib/oddb2xml/util.rb +12 -1
- data/lib/oddb2xml/version.rb +1 -1
- data/oddb2xml.xsd +7 -1
- data/spec/builder_spec.rb +2 -0
- data/spec/calc_spec.rb +324 -0
- data/spec/data/swissmedic_package-galenic.xlsx +0 -0
- data/spec/options_spec.rb +11 -0
- data/spec/spec_helper.rb +3 -3
- metadata +41 -34
data/lib/oddb2xml/cli.rb
CHANGED
@@ -8,6 +8,7 @@ require 'oddb2xml/compressor'
|
|
8
8
|
require 'oddb2xml/options'
|
9
9
|
require 'oddb2xml/util'
|
10
10
|
require 'rubyXL'
|
11
|
+
require 'date' # for today
|
11
12
|
|
12
13
|
module Oddb2xml
|
13
14
|
|
@@ -42,7 +43,9 @@ module Oddb2xml
|
|
42
43
|
end
|
43
44
|
def run
|
44
45
|
threads = []
|
45
|
-
if @options[:
|
46
|
+
if @options[:calc]
|
47
|
+
threads << download(:package) # swissmedic
|
48
|
+
elsif @options[:address]
|
46
49
|
[:company, :person].each do |type|
|
47
50
|
threads << download(type) # medregbm.admin
|
48
51
|
end
|
@@ -91,9 +94,13 @@ module Oddb2xml
|
|
91
94
|
def build
|
92
95
|
Oddb2xml.log("Start build")
|
93
96
|
begin
|
97
|
+
@_files = {"calc"=>"oddb_calc.xml"} if @options[:calc]
|
94
98
|
files.each_pair do |sbj, file|
|
95
99
|
builder = Builder.new(@options) do |builder|
|
96
|
-
if @options[:
|
100
|
+
if @options[:calc]
|
101
|
+
builder.packs = @packs
|
102
|
+
builder.subject = sbj
|
103
|
+
elsif @options[:address]
|
97
104
|
builder.subject = sbj
|
98
105
|
builder.companies = @companies
|
99
106
|
builder.people = @people
|
@@ -143,6 +150,9 @@ module Oddb2xml
|
|
143
150
|
output = builder.to_xml
|
144
151
|
end
|
145
152
|
File.open(File.join(WorkDir, file), 'w:utf-8'){ |fh| fh << output }
|
153
|
+
if @options[:calc]
|
154
|
+
FileUtils.cp(File.join(WorkDir, file), File.join(WorkDir, file.sub('.xml', '_'+Time.now.strftime("%d.%m.%Y_%H.%M")+'.xml')), :verbose => true)
|
155
|
+
end
|
146
156
|
end
|
147
157
|
rescue Interrupt
|
148
158
|
files.values.each do |file|
|
@@ -206,12 +216,13 @@ module Oddb2xml
|
|
206
216
|
end
|
207
217
|
when :package
|
208
218
|
Thread.new do
|
209
|
-
downloader = SwissmedicDownloader.new(:package)
|
219
|
+
downloader = SwissmedicDownloader.new(:package, @options)
|
210
220
|
bin = downloader.download
|
211
221
|
@mutex.synchronize do
|
212
222
|
@packs = SwissmedicExtractor.new(bin, :package).to_hash
|
213
|
-
|
214
|
-
|
223
|
+
Oddb2xml.log("SwissmedicExtractor added #{@packs.size} packs from #{bin}")
|
224
|
+
@packs
|
225
|
+
end unless @options[:calc]
|
215
226
|
end
|
216
227
|
when :bm_update
|
217
228
|
Thread.new do
|
@@ -296,9 +307,9 @@ module Oddb2xml
|
|
296
307
|
else # xml
|
297
308
|
##
|
298
309
|
# building order
|
299
|
-
# 1.
|
310
|
+
# 1. additions
|
300
311
|
# 2. subjects
|
301
|
-
# 3.
|
312
|
+
# 3. optional SUBJECTS
|
302
313
|
_files = (ADDITIONS + SUBJECTS)
|
303
314
|
_files += OPTIONALS if @options[:fi]
|
304
315
|
_files.each do|sbj|
|
@@ -313,6 +324,11 @@ module Oddb2xml
|
|
313
324
|
end
|
314
325
|
def report
|
315
326
|
lines = []
|
327
|
+
if @options[:calc]
|
328
|
+
lines << Calc.dump_new_galenic_forms
|
329
|
+
lines << Calc.dump_names_without_galenic_forms
|
330
|
+
lines << Calc.report_conversion
|
331
|
+
end
|
316
332
|
unless @options[:address]
|
317
333
|
LANGUAGES.each do |lang|
|
318
334
|
lines << lang
|
data/lib/oddb2xml/downloader.rb
CHANGED
@@ -256,8 +256,9 @@ XML
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
class SwissmedicDownloader < Downloader
|
259
|
-
def initialize(type=:orphan)
|
259
|
+
def initialize(type=:orphan, options = {})
|
260
260
|
@type = type
|
261
|
+
@options = options
|
261
262
|
case @type
|
262
263
|
when :orphan
|
263
264
|
action = "arzneimittel/00156/00221/00222/00223/00224/00227/00228/index.html?lang=de"
|
@@ -269,12 +270,17 @@ XML
|
|
269
270
|
action = "arzneimittel/00156/00221/00222/00230/index.html?lang=de"
|
270
271
|
@xpath = "//div[@id='sprungmarke10_7']//a[@title='Excel-Version Zugelassene Verpackungen*']"
|
271
272
|
end
|
272
|
-
url = "
|
273
|
-
super(
|
273
|
+
url = "https://www.swissmedic.ch/#{action}"
|
274
|
+
super(@options, url)
|
274
275
|
end
|
275
276
|
def download
|
276
|
-
@type == file = "swissmedic_#{@type}.xlsx"
|
277
|
+
@type == file = File.join(Oddb2xml::WorkDir, "swissmedic_#{@type}.xlsx")
|
278
|
+
if @options[:calc] and @options[:skip_download] and File.exists?(file) and (Time.now-File.ctime(file)).to_i < 24*60*60
|
279
|
+
Oddb2xml.log "SwissmedicDownloader #{__LINE__}: Skip downloading #{file} #{File.size(file)} bytes"
|
280
|
+
return File.expand_path(file)
|
281
|
+
end
|
277
282
|
begin
|
283
|
+
FileUtils.rm(File.expand_path(file), :verbose => true) if File.exists?(File.expand_path(file))
|
278
284
|
page = @agent.get(@url)
|
279
285
|
if link_node = page.search(@xpath).first
|
280
286
|
link = Mechanize::Page::Link.new(link_node, @agent, page)
|
data/lib/oddb2xml/extractor.rb
CHANGED
@@ -254,6 +254,7 @@ module Oddb2xml
|
|
254
254
|
i_5,i_3 = 0,10 # :swissmedic_numbers
|
255
255
|
p_5,p_1_2 = 0,1 # :prodno
|
256
256
|
cat = 13 # :swissmedic_category
|
257
|
+
seq_name = 2
|
257
258
|
ith = 4 # :ith_swissmedic IT-Code (swissmedic-diff)
|
258
259
|
atc = 5 # :atc_code
|
259
260
|
list_code = 6 # Heilmittelcode, possible values are
|
@@ -276,6 +277,7 @@ module Oddb2xml
|
|
276
277
|
siz = 11 # :package_size
|
277
278
|
eht = 12 # :einheit_swissmedic
|
278
279
|
sub = 14 # :substance_swissmedic
|
280
|
+
comp = 15 # :composition_swissmedic
|
279
281
|
@sheet.each_with_index do |row, i|
|
280
282
|
|
281
283
|
next if (i <= 1)
|
@@ -286,7 +288,7 @@ module Oddb2xml
|
|
286
288
|
next if no8.to_i == 0
|
287
289
|
ean_base12 = "7680#{no8}"
|
288
290
|
data[no8.intern] = {
|
289
|
-
:ean => (ean_base12.ljust(12, '0') + calc_checksum(ean_base12)),
|
291
|
+
:ean => (ean_base12.ljust(12, '0') + Oddb2xml.calc_checksum(ean_base12)),
|
290
292
|
:prodno => prodno ? prodno : '',
|
291
293
|
:ith_swissmedic => row[ith] ? row[ith].value.to_s : '',
|
292
294
|
:swissmedic_category => row[cat].value.to_s,
|
@@ -295,6 +297,8 @@ module Oddb2xml
|
|
295
297
|
:package_size => row[siz] ? row[siz].value.to_s : '',
|
296
298
|
:einheit_swissmedic => row[eht] ? row[eht].value.to_s : '',
|
297
299
|
:substance_swissmedic => row[sub] ? row[sub].value.to_s : '',
|
300
|
+
:composition_swissmedic => row[comp] ? row[comp].value.to_s : '',
|
301
|
+
:sequence_name => row[seq_name] ? row[seq_name].value.to_s : '',
|
298
302
|
:is_tier => (row[typ] == 'Tierarzneimittel' ? true : false),
|
299
303
|
}
|
300
304
|
end
|
@@ -311,16 +315,6 @@ module Oddb2xml
|
|
311
315
|
end unless defined?(RSpec)
|
312
316
|
end
|
313
317
|
|
314
|
-
def calc_checksum(str)
|
315
|
-
str = str.strip
|
316
|
-
sum = 0
|
317
|
-
val = str.split(//u)
|
318
|
-
12.times do |idx|
|
319
|
-
fct = ((idx%2)*2)+1
|
320
|
-
sum += fct*val[idx].to_i
|
321
|
-
end
|
322
|
-
((10-(sum%10))%10).to_s
|
323
|
-
end
|
324
318
|
end
|
325
319
|
class MigelExtractor < Extractor
|
326
320
|
def initialize(bin)
|
data/lib/oddb2xml/options.rb
CHANGED
@@ -14,6 +14,7 @@ module Oddb2xml
|
|
14
14
|
:extended => false,
|
15
15
|
:compress_ext => nil,
|
16
16
|
:format => :xml,
|
17
|
+
:calc => false,
|
17
18
|
:tag_suffix => nil,
|
18
19
|
:debug => false,
|
19
20
|
:ean14 => false,
|
@@ -45,6 +46,7 @@ Usage:
|
|
45
46
|
-t S, --tag-suffix=S XML tag suffix S. Default is none. [A-z0-9]
|
46
47
|
If S is given, it is also used as prefix of filename.
|
47
48
|
-x N, --context=N context N {product|address}. product is default.
|
49
|
+
--calc create only oddb_calc.xml with GTIN, name and galenic information
|
48
50
|
|
49
51
|
For debugging purposes
|
50
52
|
--skip-download skips downloading files it the file is already under downloads.
|
@@ -63,6 +65,7 @@ EOS
|
|
63
65
|
@opts[:price] = :zurrose
|
64
66
|
}
|
65
67
|
@parser.on('-f v', '--format v', /^xml|dat$/) {|v| @opts[:format] = v.intern }
|
68
|
+
@parser.on('--calc') {|v| @opts[:calc] = true }
|
66
69
|
@parser.on('-o', '--option') {|v| @opts[:fi] = true }
|
67
70
|
@parser.on('-I v', '--increment v', /^[0-9]+$/) {|v| @opts[:percent] = v ? v.to_i : 0
|
68
71
|
@opts[:price] = :zurrose
|
data/lib/oddb2xml/util.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
1
|
module Oddb2xml
|
2
|
+
def Oddb2xml.calc_checksum(str)
|
3
|
+
str = str.strip
|
4
|
+
sum = 0
|
5
|
+
val = str.split(//u)
|
6
|
+
12.times do |idx|
|
7
|
+
fct = ((idx%2)*2)+1
|
8
|
+
sum += fct*val[idx].to_i
|
9
|
+
end
|
10
|
+
((10-(sum%10))%10).to_s
|
11
|
+
end
|
12
|
+
|
2
13
|
unless defined?(RSpec)
|
3
14
|
WorkDir = Dir.pwd
|
4
15
|
Downloads = "#{Dir.pwd}/downloads"
|
@@ -8,7 +19,7 @@ module Oddb2xml
|
|
8
19
|
def Oddb2xml.log(msg)
|
9
20
|
return unless @options[:log]
|
10
21
|
$stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}"
|
11
|
-
$stdout.flush
|
22
|
+
# $stdout.flush
|
12
23
|
end
|
13
24
|
|
14
25
|
def Oddb2xml.save_options(options)
|
data/lib/oddb2xml/version.rb
CHANGED
data/oddb2xml.xsd
CHANGED
@@ -25,7 +25,7 @@
|
|
25
25
|
# https://www.medregbm.admin.ch/Publikation/CreateExcelListMedizinalPersons
|
26
26
|
# (epha-)interactions https://download.epha.ch/cleaned/matrix.csv
|
27
27
|
|
28
|
-
For historical reasons the generated *.XML have not a common layout and some fields have different meanings in
|
28
|
+
For historical reasons the generated *.XML have not a common layout and some fields have different meanings in different files.
|
29
29
|
|
30
30
|
The two files oddb_article and oddb_product are not normalized. There if for one swissmedic IKSNR several
|
31
31
|
packages are available you will find an entry inside oddb_article and oddb_product for each of them.
|
@@ -45,6 +45,8 @@
|
|
45
45
|
REF_DATA 1 in oddb_article if coming from a refdata source (migel, bag, swissmedic), else 0
|
46
46
|
|
47
47
|
FIRST import all data from swissINDEX
|
48
|
+
* DSCRD German name
|
49
|
+
* DSCRF French name (Products/article only from ZurRose do not have a french name)
|
48
50
|
* GTIN
|
49
51
|
* PHAR
|
50
52
|
* Status
|
@@ -73,8 +75,10 @@
|
|
73
75
|
C Abgabe nach Fachberatung durch Medizinalpersonen
|
74
76
|
D Abgabe nach Fachberatung
|
75
77
|
E Abgabe ohne Fachberatung
|
78
|
+
* IT IT-Number aka Index Therapeuticus: column 'E' from packages.xlsx
|
76
79
|
* ATC (if missing from swissINDEX) -> Field SubstanceSwissmedic in oddb_article.xml
|
77
80
|
* Wirkstoff (column 'O') -> Field SubstanceSwissmedic in oddb_article.xml
|
81
|
+
* Composition (column 'P') -> Field CompositionSwissmedic in oddb_product.xml
|
78
82
|
* Packungsgrösse (column 'L') -> Field PackGrSwissmedic in oddb_article.xml
|
79
83
|
* Packungseinheit(column 'L') -> Field EinheitSwissmedic in oddb_article.xml
|
80
84
|
|
@@ -802,6 +806,7 @@
|
|
802
806
|
<xs:element minOccurs="0" ref="ns1:PackGrSwissmedic"/>
|
803
807
|
<xs:element minOccurs="0" ref="ns1:EinheitSwissmedic"/>
|
804
808
|
<xs:element minOccurs="0" ref="ns1:SubstanceSwissmedic"/>
|
809
|
+
<xs:element minOccurs="0" ref="ns1:CompositionSwissmedic"/>
|
805
810
|
</xs:sequence>
|
806
811
|
<xs:attribute name="DT" use="required"/>
|
807
812
|
</xs:complexType>
|
@@ -842,6 +847,7 @@
|
|
842
847
|
<xs:element name="PackGrSwissmedic" type="xs:string"/>
|
843
848
|
<xs:element name="EinheitSwissmedic" type="xs:string"/>
|
844
849
|
<xs:element name="SubstanceSwissmedic" type="xs:string"/>
|
850
|
+
<xs:element name="CompositionSwissmedic" type="xs:string"/>
|
845
851
|
<xs:element name="PRODUCTMD">
|
846
852
|
<xs:complexType>
|
847
853
|
<xs:sequence>
|
data/spec/builder_spec.rb
CHANGED
@@ -118,6 +118,8 @@ describe Oddb2xml::Builder do
|
|
118
118
|
product_xml.match(/<GTIN>7680620690084/).should_not == nil
|
119
119
|
product_xml.match(/<DSCRD>Levetiracetam DESITIN Filmtabl 250 mg/).should_not == nil
|
120
120
|
product_xml.match(/<DSCRF>Levetiracetam DESITIN cpr pell 250 mg/).should_not == nil
|
121
|
+
product_xml.match(/<SubstanceSwissmedic>levetiracetamum</)
|
122
|
+
product_xml.match(/<CompositionSwissmedic>levetiracetamum 250 mg, excipiens pro compressi obducti pro charta.</).should_not == nil
|
121
123
|
|
122
124
|
article_xml.scan(/<ART DT=/).size.should eq(NrPharmaArticles)
|
123
125
|
article_xml.should match(/<PHAR>5819012</)
|
data/spec/calc_spec.rb
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'spec_helper'
|
5
|
+
require "rexml/document"
|
6
|
+
include REXML
|
7
|
+
require "#{Dir.pwd}/lib/oddb2xml/calc"
|
8
|
+
include Oddb2xml
|
9
|
+
|
10
|
+
describe Oddb2xml::Calc do
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
FileUtils.rm(Dir.glob(File.join(Oddb2xml::WorkDir, '*.*')))
|
14
|
+
FileUtils.rm(Dir.glob(File.join(Oddb2xml::WorkDir, 'downloads', '*')))
|
15
|
+
end
|
16
|
+
before(:each) do
|
17
|
+
FileUtils.rm(Dir.glob(File.join(Oddb2xml::WorkDir, '*.xml')))
|
18
|
+
FileUtils.rm(Dir.glob(File.join(Oddb2xml::WorkDir, '*.csv')))
|
19
|
+
end
|
20
|
+
|
21
|
+
# after each name you find the column of swissmedic_package.xlsx file
|
22
|
+
TestExample = Struct.new("TestExample", :test_description, :iksnr_A, :seqnr_B, :pack_K, :name_C, :package_size_L, :einheit_M, :composition_P ,
|
23
|
+
:values_to_compare)
|
24
|
+
|
25
|
+
tst_fluorglukose = TestExample.new('Fluorglukose',
|
26
|
+
51908, 2, 16, "2-Fluorglukose (18-F), Injektionslösung",
|
27
|
+
'0,1 - 80', 'GBq',
|
28
|
+
'fludeoxyglucosum(18-F) zum Kalibrierungszeitpunkt 0.1-8 GBq, dinatrii phosphas dihydricus, natrii dihydrogenophosphas dihydricus, natrii chloridum, antiox.: natrii thiosulfas 1.3-1.9 mg, aqua ad iniectabilia q.s. ad solutionem pro 1 ml.',
|
29
|
+
{ :selling_units => 1,
|
30
|
+
:measure => 'GBq',
|
31
|
+
# :count => 10, :multi => 1, :dose => ''
|
32
|
+
}
|
33
|
+
)
|
34
|
+
tst_bicaNova = TestExample.new('bicaNova',
|
35
|
+
58277, 1, 1, "bicaNova 1,5 % Glucose, Peritonealdialyselösung",
|
36
|
+
'1500 ml', '',
|
37
|
+
'I) et II) corresp.: natrii chloridum 5.5 g, natrii hydrogenocarbonas 3.36 g, calcii chloridum dihydricum 184 mg, magnesii chloridum hexahydricum 102 mg, glucosum anhydricum 15 g ut glucosum monohydricum, aqua ad iniectabilia q.s. ad solutionem pro 1000 ml.',
|
38
|
+
{ :selling_units => 1500,
|
39
|
+
:measure => 'ml',
|
40
|
+
# :count => 10, :multi => 1, :dose => ''
|
41
|
+
}
|
42
|
+
)
|
43
|
+
tst_kamillin = TestExample.new('Kamillin Medipharm, Bad',
|
44
|
+
43454, 1, 101, "Kamillin Medipharm, Bad",
|
45
|
+
'25 x 40', 'ml',
|
46
|
+
'haemagglutininum influenzae A (H1N1) (Virus-Stamm A/California/7/2009 (H1N1)-like: reassortant virus NYMC X-179A) 15 µg, haemagglutininum influenzae A (H3N2) (Virus-Stamm A/Texas/50/2012 (H3N2)-like: reassortant virus NYMC X-223A) 15 µg, haemagglutininum influenzae B (Virus-Stamm B/Massachusetts/2/2012-like: B/Massachusetts/2/2012) 15 µg, natrii chloridum, kalii chloridum, dinatrii phosphas dihydricus, kalii dihydrogenophosphas, residui: formaldehydum max. 100 µg, octoxinolum-9 max. 500 µg, ovalbuminum max. 0.05 µg, saccharum nihil, neomycinum nihil, aqua ad iniectabilia q.s. ad suspensionem pro 0.5 ml.',
|
47
|
+
{ :selling_units => 25,
|
48
|
+
:measure => 'ml',
|
49
|
+
# :count => 10, :multi => 1, :dose => ''
|
50
|
+
}
|
51
|
+
)
|
52
|
+
tst_infloran = TestExample.new('Test Infloran, capsule',
|
53
|
+
679, 2, 12, "Infloran, capsule",
|
54
|
+
'2x10', 'Kapsel(n)',
|
55
|
+
'lactobacillus acidophilus cryodesiccatus min. 10^9 CFU, bifidobacterium infantis min. 10^9 CFU, color.: E 127, E 132, E 104, excipiens pro capsula.',
|
56
|
+
{ :selling_units => 20,
|
57
|
+
:measure => 'Kapsel(n)',
|
58
|
+
# :count => 10, :multi => 1, :dose => ''
|
59
|
+
}
|
60
|
+
)
|
61
|
+
tst_mutagrip = TestExample.new('Test Mutagrip (Fertigspritzen)',
|
62
|
+
373, 23, 10, "Mutagrip, Suspension zur Injektion",
|
63
|
+
'10 x 0.5 ml', 'Fertigspritze(n)',
|
64
|
+
'ropivacaini hydrochloridum 2 mg, natrii chloridum, aqua ad iniectabilia q.s. ad solutionem pro 1 ml.',
|
65
|
+
{ :selling_units => 10,
|
66
|
+
:measure => 'Fertigspritze(n)',
|
67
|
+
# :count => 10, :multi => 1, :dose => ''
|
68
|
+
}
|
69
|
+
)
|
70
|
+
|
71
|
+
tst_diamox = TestExample.new('Diamox. Tabletten',
|
72
|
+
21191, 1, 19, 'Diamox, comprimés',
|
73
|
+
'1 x 25', 'Tablette(n)',
|
74
|
+
'haemagglutininum influenzae A (H1N1) (Virus-Stamm A/California/7/2009 (H1N1)-like: reassortant virus NYMC X-179A) 15 µg, haemagglutininum influenzae A (H3N2) (Virus-Stamm A/Texas/50/2012 (H3N2)-like: reassortant virus NYMC X-223A) 15 µg, haemagglutininum influenzae B (Virus-Stamm B/Massachusetts/2/2012-like: B/Massachusetts/2/2012) 15 µg, natrii chloridum, kalii chloridum, dinatrii phosphas dihydricus, kalii dihydrogenophosphas, residui: formaldehydum max. 100 µg, octoxinolum-9 max. 500 µg, ovalbuminum max. 0.05 µg, saccharum nihil, neomycinum nihil, aqua ad iniectabilia q.s. ad suspensionem pro 0.5 ml.',
|
75
|
+
{ :selling_units => 25,
|
76
|
+
:measure => 'Tablette(n)',
|
77
|
+
#:count => 25, :multi => 1
|
78
|
+
}
|
79
|
+
)
|
80
|
+
|
81
|
+
tst_naropin = TestExample.new('Das ist eine Injektionslösung von einer Packung mit 5 x 100 ml',
|
82
|
+
54015, 01, 100, "Naropin 0,2 %, Infusionslösung / Injektionslösung",
|
83
|
+
'1 x 5 x 100', 'ml',
|
84
|
+
'ropivacaini hydrochloridum 2 mg, natrii chloridum, aqua ad iniectabilia q.s. ad solutionem pro 1 ml.',
|
85
|
+
{ :selling_units => 5,
|
86
|
+
:measure => 'ml',
|
87
|
+
#:count => 5, :multi => 1
|
88
|
+
}
|
89
|
+
)
|
90
|
+
|
91
|
+
context 'should return correct value for liquid' do
|
92
|
+
pkg_size_L = '1 x 5 x 200'
|
93
|
+
einheit_M = 'ml'
|
94
|
+
name_C = 'Naropin 0,2 %, Infusionslösung / Injektionslösung'
|
95
|
+
result = Calc.new(name_C, pkg_size_L, einheit_M, nil)
|
96
|
+
specify { expect(result.selling_units).to eq 5 }
|
97
|
+
specify { expect(result.measure).to eq 'ml' }
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'should return correct value for W-Tropfen' do
|
101
|
+
pkg_size_L = '10'
|
102
|
+
einheit_M = 'ml'
|
103
|
+
name_C = 'W-Tropfen'
|
104
|
+
result = Calc.new(name_C, pkg_size_L, einheit_M, nil)
|
105
|
+
specify { expect(result.selling_units).to eq 10 }
|
106
|
+
specify { expect(result.measure).to eq 'ml' }
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
context 'should return correct value for Diamox, comprimés' do
|
111
|
+
pkg_size_L = '1 x 25'
|
112
|
+
einheit_M = 'Tablette(n)'
|
113
|
+
name_C = 'Diamox, comprimés'
|
114
|
+
|
115
|
+
result = Calc.new(name_C, pkg_size_L, einheit_M, nil)
|
116
|
+
specify { expect(result.selling_units).to eq 25 }
|
117
|
+
specify { expect(result.measure).to eq 'Tablette(n)' }
|
118
|
+
|
119
|
+
res = Calc.report_conversion
|
120
|
+
specify { expect(res.class).to eq Array }
|
121
|
+
specify { expect(res.first.class).to eq String }
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'should return correct value for Perindopril' do
|
125
|
+
pkg_size_L = '90'
|
126
|
+
einheit_M = 'Tablette(n)'
|
127
|
+
name_C = 'comprimés pelliculés'
|
128
|
+
|
129
|
+
result = Calc.new(name_C, pkg_size_L, einheit_M, nil)
|
130
|
+
specify { expect(result.selling_units).to eq 90 }
|
131
|
+
specify { expect(result.measure).to eq einheit_M }
|
132
|
+
|
133
|
+
res = Calc.report_conversion
|
134
|
+
specify { expect(res.class).to eq Array }
|
135
|
+
specify { expect(res.first.class).to eq String }
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
context 'should find galenic_group for Kaugummi' do
|
140
|
+
result = Calc.get_galenic_group('Kaugummi')
|
141
|
+
specify { expect(result.class).to eq GalenicGroup }
|
142
|
+
specify { expect(result.description).to eq 'Kaugummi' }
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'should find galenic_form for Infusionslösung / Injektionslösung' do
|
146
|
+
value = 'Infusionslösung / Injektionslösung'
|
147
|
+
result = Calc.get_galenic_form(value)
|
148
|
+
specify { expect(result.class).to eq GalenicForm }
|
149
|
+
specify { expect(result.description).to eq 'Infusionslösung/Injektionslösung' }
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'should return galenic_group unknown for galenic_group Dummy' do
|
153
|
+
result = Calc.get_galenic_group('Dummy')
|
154
|
+
specify { expect(result.class).to eq GalenicGroup }
|
155
|
+
specify { expect(result.oid).to eq 1 }
|
156
|
+
specify { expect(result.descriptions['de']).to eq 'unbekannt' }
|
157
|
+
specify { expect(result.description).to eq 'unbekannt' }
|
158
|
+
end
|
159
|
+
|
160
|
+
class TestExample
|
161
|
+
def url
|
162
|
+
"http://ch.oddb.org/de/gcc/drug/reg/#{sprintf('%05d' % iksnr_A)}/seq/#{sprintf('%02d' % seqnr_B)}/pack/#{sprintf('%03d' % pack_K)}"
|
163
|
+
end
|
164
|
+
end
|
165
|
+
[tst_fluorglukose,
|
166
|
+
tst_kamillin,
|
167
|
+
tst_naropin,
|
168
|
+
tst_diamox,
|
169
|
+
tst_mutagrip,
|
170
|
+
].each {
|
171
|
+
|tst|
|
172
|
+
context "verify #{tst.iksnr_A} #{tst.name_C}: #{tst.url}" do
|
173
|
+
info = Calc.new(tst.name_C, tst.package_size_L, tst.einheit_M, tst.composition_P)
|
174
|
+
tst.values_to_compare.each do
|
175
|
+
|key, value|
|
176
|
+
context key do
|
177
|
+
cmd = "expect(info.#{key}.to_s).to eq '#{value.to_s}'"
|
178
|
+
specify { eval(cmd) }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
}
|
183
|
+
|
184
|
+
context 'find correct result for Injektionslösung' do
|
185
|
+
info = Calc.new(tst_naropin.name_C, tst_naropin.package_size_L, tst_naropin.einheit_M, tst_naropin.composition_P)
|
186
|
+
specify { expect(tst_naropin.url).to eq 'http://ch.oddb.org/de/gcc/drug/reg/54015/seq/01/pack/100' }
|
187
|
+
specify { expect(info.galenic_form.description).to eq 'Infusionslösung/Injektionslösung' }
|
188
|
+
specify { expect(info.galenic_group.description).to eq 'Injektion/Infusion' }
|
189
|
+
specify { expect(info.pkg_size).to eq '1 x 5 x 100' }
|
190
|
+
skip { expect(info.measure).to eq '100 ml' }
|
191
|
+
# specify { expect(info.count).to eq 5 }
|
192
|
+
# specify { expect(info.multi).to eq 1 }
|
193
|
+
# specify { expect(info.addition).to eq 0 }
|
194
|
+
# specify { expect(info.scale).to eq 1 }
|
195
|
+
end
|
196
|
+
|
197
|
+
context 'find correct result for Inflora, capsule' do
|
198
|
+
info = Calc.new(tst_infloran.name_C, tst_infloran.package_size_L, tst_infloran.einheit_M, tst_infloran.composition_P)
|
199
|
+
specify { expect(tst_infloran.url).to eq 'http://ch.oddb.org/de/gcc/drug/reg/00679/seq/02/pack/012' }
|
200
|
+
specify { expect(info.galenic_form.description).to eq 'capsule' }
|
201
|
+
skip { expect(info.galenic_group.description).to eq 'Injektion/Infusion' }
|
202
|
+
specify { expect(info.pkg_size).to eq '2x10' }
|
203
|
+
specify { expect(info.selling_units).to eq 20 }
|
204
|
+
skip { expect(info.measure).to eq '0' }
|
205
|
+
# specify { expect(info.count).to eq 5 }
|
206
|
+
# specify { expect(info.multi).to eq 1 }
|
207
|
+
# specify { expect(info.addition).to eq 0 }
|
208
|
+
# specify { expect(info.scale).to eq 1 }
|
209
|
+
end
|
210
|
+
|
211
|
+
context 'convert mg/l into ml/mg for solutions' do
|
212
|
+
result = Calc.new('50', 'g/l')
|
213
|
+
skip { expect(result.measure).to eq 50 }
|
214
|
+
end
|
215
|
+
|
216
|
+
run_time_options = '--calc --skip-download'
|
217
|
+
context "when passing #{run_time_options}" do
|
218
|
+
let(:cli) do
|
219
|
+
options = Oddb2xml::Options.new
|
220
|
+
options.parser.parse!(run_time_options.split(' '))
|
221
|
+
Oddb2xml::Cli.new(options.opts)
|
222
|
+
end
|
223
|
+
it 'should create a correct xml and a csv file' do
|
224
|
+
src = File.expand_path(File.join(File.dirname(__FILE__), 'data', 'swissmedic_package-galenic.xlsx'))
|
225
|
+
dest = File.join(Oddb2xml::WorkDir, 'swissmedic_package.xlsx')
|
226
|
+
FileUtils.makedirs(Oddb2xml::WorkDir)
|
227
|
+
FileUtils.cp(src, dest, { :verbose => true, :preserve => true})
|
228
|
+
FileUtils.cp(File.expand_path(File.join(File.dirname(__FILE__), 'data', 'XMLPublications.zip')),
|
229
|
+
File.join(Oddb2xml::WorkDir, 'downloads'),
|
230
|
+
{ :verbose => true, :preserve => true})
|
231
|
+
cli.run
|
232
|
+
expected = [
|
233
|
+
'oddb_calc.xml',
|
234
|
+
'oddb_calc.csv',
|
235
|
+
].each { |file|
|
236
|
+
full = File.join(Oddb2xml::WorkDir, file)
|
237
|
+
expect(File.exists?(full)).to eq true
|
238
|
+
}
|
239
|
+
xml = File.read(File.join(Oddb2xml::WorkDir, 'oddb_calc.xml'))
|
240
|
+
doc = REXML::Document.new xml
|
241
|
+
gtin = '7680540151191'
|
242
|
+
tst_naropin.values_to_compare.each{
|
243
|
+
| key, value |
|
244
|
+
result = XPath.match( doc, "//ARTICLE[GTIN='#{gtin}']/#{key.to_s.upcase}").first.text
|
245
|
+
puts "Testing key #{key.inspect} #{value.inspect} against #{result} seems to fail" unless result == value.to_s
|
246
|
+
result.should eq value.to_s
|
247
|
+
}
|
248
|
+
end
|
249
|
+
end
|
250
|
+
context 'find correct result for Kamillin' do
|
251
|
+
info = Calc.new(tst_kamillin.name_C, tst_kamillin.package_size_L, tst_kamillin.einheit_M, tst_kamillin.composition_P)
|
252
|
+
specify { expect(info.selling_units).to eq 25 }
|
253
|
+
end
|
254
|
+
|
255
|
+
context 'find correct result for bicaNova' do
|
256
|
+
info = Calc.new(tst_bicaNova.name_C, tst_bicaNova.package_size_L, tst_bicaNova.einheit_M, tst_bicaNova.composition_P)
|
257
|
+
specify { expect(info.selling_units).to eq 1500 }
|
258
|
+
specify { expect(info.measure).to eq 'ml' }
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'should return correct value for mutagrip' do
|
262
|
+
pkg_size_L = '10 x 0.5 ml'
|
263
|
+
einheit_M = 'Fertigspritze(n)'
|
264
|
+
name_C = 'Suspension zur Injektion'
|
265
|
+
|
266
|
+
result = Calc.new(name_C, pkg_size_L, einheit_M, nil)
|
267
|
+
specify { expect(result.selling_units).to eq 10 }
|
268
|
+
specify { expect(result.measure).to eq einheit_M }
|
269
|
+
|
270
|
+
res = Calc.report_conversion
|
271
|
+
specify { expect(res.class).to eq Array }
|
272
|
+
specify { expect(res.first.class).to eq String }
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
missing_tests = "
|
278
|
+
1. Das ist eine Injektionslösung von einer Packung mit 5 x 100 ml
|
279
|
+
1 x 5 x 100
|
280
|
+
|
281
|
+
2. Hier muss man schauen ob es sich um ein Injektionspräparat handelt
|
282
|
+
oder um ein Tabletten, Kapseln, etc.
|
283
|
+
2 x 100
|
284
|
+
|
285
|
+
a) Beim Injektionspräparat sind es wohl 2 Ampullen à 100 ml
|
286
|
+
b) Bei den Tabletten sind es wohl total 200 Stück.
|
287
|
+
|
288
|
+
3. Das ist ein klarer Fall von einer Lösung, idR wohl Ampullen:
|
289
|
+
10 x 2 mL
|
290
|
+
|
291
|
+
4. Das sind 10 Teebeutel à 1.5g
|
292
|
+
10 x 1.5g
|
293
|
+
|
294
|
+
5. Das sind 20 mg Wirkstoff in einer 10 ml Lösung. 'ml' steht dann in
|
295
|
+
der Spalte M
|
296
|
+
20 mg / 10. Könnte auch so geschrieben sein: 1000mg/50ml oder auch so:
|
297
|
+
1 x 50mg/100ml
|
298
|
+
|
299
|
+
6. 1x1 Urethrastab ist einmal ein Stab. ;)
|
300
|
+
|
301
|
+
7. 30 (3x10) sind Total 30 Tabletten verteilt auf 3 Blister à 10
|
302
|
+
Tabletten. Könnte auch so geschrieben sein: 84 (4 x 21)
|
303
|
+
|
304
|
+
8. 10 + 10 Das sind zehn Ampullen mit einer Trockensubstanz und
|
305
|
+
nochmals zehn Ampullen mit der Lösung. Das ist ein Kombipräparat.
|
306
|
+
|
307
|
+
9. 20 x 0.5 g sind zwanzig Einzeldosen à 0.5g.
|
308
|
+
|
309
|
+
10. Das ist eine Gaze: 1 x 7,5 x 10 cm
|
310
|
+
|
311
|
+
11. 100 (2 x 50) das sind total 100 Beutel, d.h. zweimal fünfzig Stück.
|
312
|
+
|
313
|
+
12. 0,1 - 80 GBq Das ist eine Injektionslösung.
|
314
|
+
|
315
|
+
13. 10 cm x 10 cm imprägnierter Verband. Das ist eine Salbengaze.
|
316
|
+
|
317
|
+
14. Das ist ein Sauerstofftank: 9000-10000 l
|
318
|
+
|
319
|
+
15. 360x1 Das ist eine Packung mit 360 Durchstechflaschen.
|
320
|
+
|
321
|
+
16. 5 + 5 Das sind 10 Durchstechflaschen à 1 Stück.
|
322
|
+
"
|
323
|
+
|
324
|
+
|