gtin2atc 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.txt +7 -0
- data/bin/gtin2atc +5 -5
- data/lib/gtin2atc/builder.rb +53 -13
- data/lib/gtin2atc/downloader.rb +1 -1
- data/lib/gtin2atc/options.rb +5 -1
- data/lib/gtin2atc/version.rb +1 -1
- data/lib/gtin2atc/xml_definitions.rb +47 -0
- data/spec/builder_spec.rb +39 -10
- data/spec/data/bluecare.gtin +2248 -0
- data/spec/data/oddb_calc.xml +75 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6d462072d516aec948e6cf2ec404d60d78634d0
|
4
|
+
data.tar.gz: 965cfb24672bc54f53ec3cd347104dda20d8d39b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a9490c9a9d5efa5498153c8020b9119cfba390d7d09fc59524decb26f497502402f01ab79f10fdb5ae1757fe65be9a4b839a430d0f21c4d4e53130d7ba2c6b1
|
7
|
+
data.tar.gz: d1acea60db039502005e629dbb48f611dd9f4c18c50ef58c3bbf7426cb843090cf227bb4d6e88ef3f51f1aef1529afc7428e7567491b02e25a0b95e66578fdee
|
data/History.txt
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
+
=== 0.1.5 04.03.2015
|
2
|
+
|
3
|
+
* Added optional second parameter to specify output file
|
4
|
+
* Added output for dosis (name, unit, qty) for mono-preparations
|
5
|
+
|
1
6
|
=== 0.1.4 03.03.2015
|
2
7
|
|
8
|
+
* Add selling units ot generated gtin2atc.csv file
|
9
|
+
* Use ';' as column separator for generated CSV files
|
3
10
|
* Create file pharmacode_gtin_not_found.txt
|
4
11
|
|
5
12
|
=== 0.1.3 27.01.2015
|
data/bin/gtin2atc
CHANGED
@@ -23,12 +23,12 @@ end
|
|
23
23
|
|
24
24
|
opts = options.opts
|
25
25
|
startTime = Time.now
|
26
|
-
if
|
27
|
-
|
28
|
-
IO.readlines(ARGV[0]).each{ |x|
|
26
|
+
if File.exists?(ARGV[0])
|
27
|
+
gtins2parse = []
|
28
|
+
IO.readlines(ARGV[0]).each{ |x| gtins2parse << x.chomp}
|
29
29
|
else
|
30
|
-
|
30
|
+
gtins2parse = ARGV.clone
|
31
31
|
end
|
32
|
-
Gtin2atc::Builder.new(opts).run(
|
32
|
+
Gtin2atc::Builder.new(opts).run(gtins2parse, ARGV[1])
|
33
33
|
diff = (Time.now-startTime).to_i
|
34
34
|
Gtin2atc::Util.debug_msg "#{File.basename(__FILE__)} done. Took #{diff} seconds"
|
data/lib/gtin2atc/builder.rb
CHANGED
@@ -14,11 +14,13 @@ module Gtin2atc
|
|
14
14
|
AtcNotInSwissmedic = 'atc not in swissmedic'
|
15
15
|
AtcNotInBag = 'atc not in bag'
|
16
16
|
AtcDifferent = 'atc differed'
|
17
|
+
CsvOutputOptions = { :col_sep => ';', :encoding => 'UTF-8'}
|
17
18
|
def initialize(opts)
|
18
19
|
Util.set_logging(opts[:log])
|
20
|
+
@output = opts[:output]
|
19
21
|
@do_compare = opts[:compare]
|
20
22
|
@gen_reports = opts[:compare] and opts[:full]
|
21
|
-
Util.debug_msg "Builder: opts are #{opts} @do_compare is #{@do_compare}"
|
23
|
+
Util.debug_msg "Builder: opts are #{opts} @do_compare is #{@do_compare} output #{@output}"
|
22
24
|
@data_swissmedic = {}
|
23
25
|
@data_bag = {}
|
24
26
|
@data_swissindex = {}
|
@@ -93,6 +95,31 @@ module Gtin2atc
|
|
93
95
|
Util.debug_msg "swissindex_xml_extractor extracted #{data.size} items"
|
94
96
|
data
|
95
97
|
end
|
98
|
+
def oddb_calc_xml_extractor
|
99
|
+
filename = 'oddb_calc.xml'
|
100
|
+
data = {}
|
101
|
+
unless File.exists?('oddb_calc.xml')
|
102
|
+
puts "Unable to open #{filename}"
|
103
|
+
else
|
104
|
+
xml = IO.read(filename)
|
105
|
+
Util.debug_msg "oddb_calc_xml_extractor xml is #{xml.size} bytes long"
|
106
|
+
result = ARTICLESEntry.parse(xml.sub(Strip_For_Sax_Machine, ''), :lazy => true)
|
107
|
+
result.ARTICLES.ARTICLE.each do |article|
|
108
|
+
item = {}
|
109
|
+
gtin = article.GTIN.to_i
|
110
|
+
item[:gtin] = gtin
|
111
|
+
item[:PKG_SIZE] = article.PKG_SIZE
|
112
|
+
item[:SELLING_UNITS] = article.SELLING_UNITS
|
113
|
+
item[:MEASURE] = article.MEASURE
|
114
|
+
if article.COMPOSITIONS.COMPONENT and article.COMPOSITIONS.COMPONENT.size == 1
|
115
|
+
item[:COMPOSITIONS] = article.COMPOSITIONS
|
116
|
+
end
|
117
|
+
data[gtin] = item
|
118
|
+
end
|
119
|
+
Util.debug_msg "oddb_calc_xml_extractor extracted #{data.size} items"
|
120
|
+
end
|
121
|
+
data
|
122
|
+
end
|
96
123
|
def bag_xml_extractor
|
97
124
|
data = {}
|
98
125
|
@bag = BagDownloader.new
|
@@ -121,24 +148,37 @@ module Gtin2atc
|
|
121
148
|
Util.debug_msg "bag_xml_extractor extracted #{data.size} items. Skipped #{@bag_entries_without_gtin} entries without gtin"
|
122
149
|
data
|
123
150
|
end
|
124
|
-
|
151
|
+
|
152
|
+
def run(gtins_to_parse=[], output_name=nil)
|
125
153
|
Util.debug_msg("run #{gtins_to_parse}")
|
126
154
|
Util.debug_msg("@use_swissindex true")
|
155
|
+
@oddb_calc = oddb_calc_xml_extractor
|
127
156
|
@data_epha_atc = epha_atc_extractor
|
128
157
|
@data_swissindex = swissindex_xml_extractor
|
129
158
|
emitted_ids = []
|
130
|
-
|
131
|
-
|
132
|
-
|
159
|
+
if @do_compare
|
160
|
+
output_name = File.join(Util.get_archive, 'gtin2atc_swissindex.csv')
|
161
|
+
else
|
162
|
+
output_name ||= 'gtin2atc.csv'
|
163
|
+
output_name = File.join(Util.get_archive, output_name)
|
164
|
+
end
|
165
|
+
CSV.open(output_name,'w+', CsvOutputOptions) do |csvfile|
|
166
|
+
csvfile << ["gtin", "ATC", 'pharmacode', 'description', 'daily drug dose', 'selling units']
|
133
167
|
@data_swissindex.sort.each do |gtin, item|
|
134
168
|
if @do_compare or gtins_to_parse.size == 0 or
|
135
169
|
gtins_to_parse.index(gtin.to_s) or
|
136
|
-
gtins_to_parse.index(item[:pharmacode])
|
170
|
+
gtins_to_parse.index(item[:pharmacode].to_s)
|
137
171
|
atc = item[:atc_code]
|
138
172
|
ddd = @data_epha_atc[atc]
|
139
|
-
|
140
|
-
emitted_ids <<
|
141
|
-
|
173
|
+
selling_units = @oddb_calc[gtin] ? @oddb_calc[gtin][:SELLING_UNITS] : nil
|
174
|
+
emitted_ids << gtin.to_i if gtin
|
175
|
+
emitted_ids << item[:pharmacode].to_i if item[:pharmacode]
|
176
|
+
if @oddb_calc[gtin] and @oddb_calc[gtin][:COMPOSITIONS]
|
177
|
+
comp = @oddb_calc[gtin][:COMPOSITIONS].COMPONENT.first
|
178
|
+
csvfile << [gtin, atc, item[:pharmacode], item[:description], ddd, selling_units, comp.NAME, comp.QTY, comp.UNIT]
|
179
|
+
else
|
180
|
+
csvfile << [gtin, atc, item[:pharmacode], item[:description], ddd, selling_units]
|
181
|
+
end
|
142
182
|
end
|
143
183
|
end
|
144
184
|
end
|
@@ -147,16 +187,16 @@ module Gtin2atc
|
|
147
187
|
missing_ids = []
|
148
188
|
gtins_to_parse.each{
|
149
189
|
|id|
|
150
|
-
next if emitted_ids.index(id)
|
190
|
+
next if emitted_ids.index(id.to_i)
|
151
191
|
missing_ids << id
|
152
192
|
}
|
153
|
-
File.open('pharmacode_gtin_not_found.txt', 'w+') { |f| f.write missing_ids.join("\n") }
|
193
|
+
File.open('pharmacode_gtin_not_found.txt', 'w+', CsvOutputOptions) { |f| f.write missing_ids.join("\n") }
|
154
194
|
msg = "swissindex: Could not find info for #{missing_ids.size} missing ids see file pharmacode_gtin_not_found.txt"
|
155
195
|
Util.debug_msg(msg)
|
156
196
|
return unless @do_compare
|
157
197
|
@data_bag = bag_xml_extractor
|
158
198
|
output_name = File.join(Util.get_archive, 'gtin2atc_bag.csv')
|
159
|
-
CSV.open(output_name,'w+') do |csvfile|
|
199
|
+
CSV.open(output_name,'w+', CsvOutputOptions) do |csvfile|
|
160
200
|
csvfile << ["gtin", "ATC", 'description']
|
161
201
|
@data_bag.sort.each do |gtin, item|
|
162
202
|
csvfile << [gtin, item[:atc_code], item[:description]]
|
@@ -165,7 +205,7 @@ module Gtin2atc
|
|
165
205
|
Util.debug_msg "bag: Extracted #{gtins_to_parse.size} of #{@data_bag.size} items into #{output_name} for #{gtins_to_parse}"
|
166
206
|
@data_swissmedic = swissmedic_xls_extractor
|
167
207
|
output_name = File.join(Util.get_archive, 'gtin2atc_swissmedic.csv')
|
168
|
-
CSV.open(output_name,'w+') do |csvfile|
|
208
|
+
CSV.open(output_name,'w+', CsvOutputOptions) do |csvfile|
|
169
209
|
csvfile << ["gtin", "ATC", 'description']
|
170
210
|
@data_swissmedic.sort.each do |gtin, item|
|
171
211
|
csvfile << [gtin, item[:atc_code], item[:pharmacode], item[:description]]
|
data/lib/gtin2atc/downloader.rb
CHANGED
@@ -129,7 +129,7 @@ module Gtin2atc
|
|
129
129
|
if File.exists?(file) and diff_hours = ((Time.now-File.ctime(file)).to_i/3600) and diff_hours < 24
|
130
130
|
Util.debug_msg "Skip download of #{file} as only #{diff_hours} hours old"
|
131
131
|
else
|
132
|
-
FileUtils.rm_f(file, :verbose =>
|
132
|
+
FileUtils.rm_f(file, :verbose => false)
|
133
133
|
begin
|
134
134
|
response = @agent.get(@url)
|
135
135
|
response.save_as(file)
|
data/lib/gtin2atc/options.rb
CHANGED
@@ -16,9 +16,13 @@ module Gtin2atc
|
|
16
16
|
<<EOS
|
17
17
|
#$0 ver.#{Gtin2atc::VERSION}
|
18
18
|
Usage:
|
19
|
-
gtin2atc [--compare] [--log] [file_with_gtin or gtin or pharmacode] [
|
19
|
+
gtin2atc [--compare] [--log] [file_with_gtin or gtin or pharmacode] [output_file]
|
20
20
|
If file_with_gtin is given only the GTIN (or pharamacode) (one per line) is outputted.
|
21
|
+
If a second parameter output_file is given the name of the generated csv file.
|
21
22
|
If no file or gtin is given, alle GTIN will be processed.
|
23
|
+
If a file oddb_calc.xml (produced via oddb2xml --calc) is found in the current directory,
|
24
|
+
its content is read to add the daily drug dose and dose information for each article.
|
25
|
+
|
22
26
|
--log log important actions
|
23
27
|
|
24
28
|
--compare download an compare GTIN/ATC_code from BAG, SwissIndex and RefData
|
data/lib/gtin2atc/version.rb
CHANGED
@@ -248,3 +248,50 @@ class MedicalInformationsEntry
|
|
248
248
|
element :medicalInformations, :class => MedicalInformationsContent
|
249
249
|
end
|
250
250
|
|
251
|
+
class COMPONENTContent
|
252
|
+
include SAXMachine
|
253
|
+
element :NAME
|
254
|
+
element :QTY
|
255
|
+
element :UNIT
|
256
|
+
end
|
257
|
+
|
258
|
+
class COMPONENTEntry
|
259
|
+
include SAXMachine
|
260
|
+
element :COMPONENT, :class => COMPONENTContent
|
261
|
+
end
|
262
|
+
|
263
|
+
class COMPONENTSContent
|
264
|
+
include SAXMachine
|
265
|
+
element :components, :class => COMPONENTContent
|
266
|
+
end
|
267
|
+
|
268
|
+
class COMPOSITIONSContent
|
269
|
+
include SAXMachine
|
270
|
+
attribute :ReleaseDate
|
271
|
+
elements :COMPONENT, :class => COMPONENTContent
|
272
|
+
end
|
273
|
+
|
274
|
+
|
275
|
+
class ARTICLEContent
|
276
|
+
include SAXMachine
|
277
|
+
element :GTIN
|
278
|
+
element :NAME
|
279
|
+
element :PKG_SIZE
|
280
|
+
element :MEASURE
|
281
|
+
element :SELLING_UNITS
|
282
|
+
element :GALENIC_FORM
|
283
|
+
element :GALENIC_GROUP
|
284
|
+
element :COMPOSITIONS, :class => COMPOSITIONSContent
|
285
|
+
end
|
286
|
+
|
287
|
+
class ARTICLESContent
|
288
|
+
include SAXMachine
|
289
|
+
attribute :ReleaseDate
|
290
|
+
elements :ARTICLE, :class => ARTICLEContent
|
291
|
+
end
|
292
|
+
|
293
|
+
class ARTICLESEntry
|
294
|
+
include SAXMachine
|
295
|
+
element :ARTICLES, :class => ARTICLESContent
|
296
|
+
end
|
297
|
+
|
data/spec/builder_spec.rb
CHANGED
@@ -48,11 +48,10 @@ describe Gtin2atc::Builder do
|
|
48
48
|
def check_csv(filename)
|
49
49
|
File.exists?(filename).should eq true
|
50
50
|
inhalt = IO.readlines(filename)
|
51
|
-
|
52
|
-
/^\d{13},\w{4}/.should match inhalt[1]
|
51
|
+
/^\d{13};\w{4}/.should match inhalt[1]
|
53
52
|
# Packungsgrösse, Dosierung, DDD, Route of Administration
|
54
|
-
/^gtin
|
55
|
-
/^7680316440115
|
53
|
+
/^gtin;ATC;pharmacode;description;daily drug dose/.should match inhalt.first
|
54
|
+
/^7680316440115;B03AA07;20244;FERRO-GRADUMET Depottabl;0,2 g O Fe2\+;/.should match inhalt.join("\n")
|
56
55
|
end
|
57
56
|
|
58
57
|
context 'when 20273 41803 (Pharmacodes) is given' do
|
@@ -102,8 +101,8 @@ describe Gtin2atc::Builder do
|
|
102
101
|
check_csv(CSV_NAME)
|
103
102
|
inhalt = IO.readlines(CSV_NAME)
|
104
103
|
inhalt.size.should eq 2+1 # one header lines + two items
|
105
|
-
inhalt[1].chomp.should eq '7680147690482
|
106
|
-
inhalt[2].chomp.should eq '7680353660163
|
104
|
+
inhalt[1].chomp.should eq '7680147690482;N07BC02;41803;KETALGIN Inj Lös 10 mg/ml;25 mg O,P;'
|
105
|
+
inhalt[2].chomp.should eq '7680353660163;B03AE10;20273;KENDURAL Depottabl;;'
|
107
106
|
end
|
108
107
|
end
|
109
108
|
|
@@ -123,15 +122,15 @@ describe Gtin2atc::Builder do
|
|
123
122
|
/7680353660163/.match(inhalt[1]).should == nil
|
124
123
|
/7680147690482/.match(inhalt[2]).should == nil
|
125
124
|
/7680353660163/.match(inhalt[2]).should_not == nil
|
126
|
-
/7680353660163
|
125
|
+
/7680353660163;B03AE10;20273;KENDURAL Depottabl/.match(inhalt[2]).should_not == nil
|
127
126
|
end
|
128
127
|
end
|
129
128
|
|
130
129
|
def check_csv(filename)
|
131
130
|
File.exists?(filename).should eq true
|
132
131
|
inhalt = IO.readlines(filename)
|
133
|
-
/^gtin
|
134
|
-
/^\d{13}
|
132
|
+
/^gtin;ATC/.match(inhalt.first).should_not == nil
|
133
|
+
/^\d{13};\w{4}/.match(inhalt[1]).should_not == nil
|
135
134
|
end
|
136
135
|
|
137
136
|
context 'when --compare is given' do
|
@@ -144,8 +143,8 @@ describe Gtin2atc::Builder do
|
|
144
143
|
it 'should produce three correct csv' do
|
145
144
|
@res = buildr_capture(:stdout){ cli.run }
|
146
145
|
check_csv('gtin2atc_bag.csv')
|
147
|
-
check_csv('gtin2atc_swissindex.csv')
|
148
146
|
check_csv('gtin2atc_swissmedic.csv')
|
147
|
+
check_csv('gtin2atc_swissindex.csv')
|
149
148
|
end
|
150
149
|
|
151
150
|
it 'should produce a good logging output' do
|
@@ -186,4 +185,34 @@ describe Gtin2atc::Builder do
|
|
186
185
|
|
187
186
|
end
|
188
187
|
|
188
|
+
context 'when outputfile is given' do
|
189
|
+
let(:cli) do
|
190
|
+
options = Gtin2atc::Options.new
|
191
|
+
options.parser.parse!('7680316440115 tst.csv'.split(' '))
|
192
|
+
Gtin2atc::Builder.new(options.opts)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'should produce a correct tst.csv' do
|
196
|
+
tst_name = 'tst.csv'
|
197
|
+
buildr_capture(:stdout){ cli.run(["7680316440115"], tst_name) }
|
198
|
+
check_csv(tst_name)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
context 'when producing csv' do
|
203
|
+
let(:cli) do
|
204
|
+
options = Gtin2atc::Options.new
|
205
|
+
Gtin2atc::Builder.new(options.opts)
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should contain dose for FERRO-GRADUMET Depottab' do
|
209
|
+
oddb_calc_xml = File.expand_path(File.join( __FILE__, '../data/oddb_calc.xml'))
|
210
|
+
FileUtils.cp(oddb_calc_xml, Gtin2atc::WorkDir, :verbose => false)
|
211
|
+
@res = buildr_capture(:stdout){ cli.run() }
|
212
|
+
check_csv(CSV_NAME)
|
213
|
+
inhalt = IO.readlines(CSV_NAME)
|
214
|
+
inhalt.index("7680316440115;B03AA07;20244;FERRO-GRADUMET Depottabl;0,2 g O Fe2+;30;Ferrum(ii);105.0;mg\n").should_not == nil
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
189
218
|
end
|