oddb2xml 1.9.4 → 1.9.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|