gtin2atc 0.1.4 → 0.1.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 +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
|