oddb2xml 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -1
  3. data/.standard.yml +2 -0
  4. data/Gemfile +3 -3
  5. data/History.txt +8 -0
  6. data/README.md +1 -1
  7. data/Rakefile +24 -23
  8. data/bin/check_artikelstamm +11 -11
  9. data/bin/compare_v5 +23 -23
  10. data/bin/oddb2xml +14 -13
  11. data/lib/oddb2xml.rb +1 -1
  12. data/lib/oddb2xml/builder.rb +1070 -1038
  13. data/lib/oddb2xml/calc.rb +232 -233
  14. data/lib/oddb2xml/chapter_70_hack.rb +38 -32
  15. data/lib/oddb2xml/cli.rb +252 -236
  16. data/lib/oddb2xml/compare.rb +70 -59
  17. data/lib/oddb2xml/compositions_syntax.rb +448 -430
  18. data/lib/oddb2xml/compressor.rb +20 -20
  19. data/lib/oddb2xml/downloader.rb +153 -127
  20. data/lib/oddb2xml/extractor.rb +302 -289
  21. data/lib/oddb2xml/options.rb +34 -35
  22. data/lib/oddb2xml/parslet_compositions.rb +263 -269
  23. data/lib/oddb2xml/semantic_check.rb +39 -33
  24. data/lib/oddb2xml/util.rb +163 -163
  25. data/lib/oddb2xml/version.rb +1 -1
  26. data/lib/oddb2xml/xml_definitions.rb +32 -33
  27. data/oddb2xml.gemspec +31 -32
  28. data/spec/artikelstamm_spec.rb +111 -110
  29. data/spec/builder_spec.rb +489 -505
  30. data/spec/calc_spec.rb +552 -593
  31. data/spec/check_artikelstamm_spec.rb +26 -26
  32. data/spec/cli_spec.rb +173 -174
  33. data/spec/compare_spec.rb +9 -11
  34. data/spec/composition_syntax_spec.rb +390 -409
  35. data/spec/compressor_spec.rb +48 -48
  36. data/spec/data/transfer.dat +1 -0
  37. data/spec/data_helper.rb +47 -49
  38. data/spec/downloader_spec.rb +247 -260
  39. data/spec/extractor_spec.rb +171 -159
  40. data/spec/galenic_spec.rb +233 -256
  41. data/spec/options_spec.rb +116 -119
  42. data/spec/parslet_spec.rb +833 -861
  43. data/spec/spec_helper.rb +154 -153
  44. data/test_options.rb +39 -42
  45. data/tools/win_fetch_cacerts.rb +2 -3
  46. metadata +19 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c31777bcd85038bd65d38d67d6ebdf2197f174389403b76ff146b18d3ef4557e
4
- data.tar.gz: 8d8930ed04518838084ae4aeb69181418b2eddb36cfa83ece2cbc84ccd06e1f4
3
+ metadata.gz: d8da655dd712cff69591fb63c97ad9f0e61d1bf085fd03b4cc1af409c140fe31
4
+ data.tar.gz: ff287b7a4104e8a446a33d12d0f4a64e0741d390329a2fb2446647fb1b99014b
5
5
  SHA512:
6
- metadata.gz: abe9685cc40ba1fbf9525c3cbeb9f332a98725e76621074c9f1df179c91e53cb50a4f15e78a800a28224351d3a47ec8aef0e3b9ee17787a8dccd519db65bc6d8
7
- data.tar.gz: 415b9049a316af98279f7af0b602ecd85b0bd2e86493133af512d37b494d43155822ef754ad6dcaa39b1aa474fddba57081860588b7e896da13bf891e9b522d6
6
+ metadata.gz: 13a5bf2653004efe4365ac0f869b329a0d23e94ef11c5501f03bab1253fa69170a7df0bb78f976dc9c946a4a5f2b5bad21e38f3b5bc24d1e566f5a303eb0bb2f
7
+ data.tar.gz: 5483ac6d5eaeaddf7800e7c1bad5245155b61c7025a2d1325790ebf3ed76e70b8b5b1bd262d35e81011109ccb59d304740d7954ee1bef06b61711012eb1f703c
@@ -22,7 +22,7 @@ jobs:
22
22
  fail-fast: false
23
23
  matrix:
24
24
  os: [ ubuntu]
25
- ruby: [2.4, 2.5, 2.6, 2.7, 3.0, head]
25
+ ruby: [2.5, 2.6, 2.7, 3.0, head]
26
26
  continue-on-error: ${{ endsWith(matrix.ruby, 'head') }}
27
27
  steps:
28
28
  - uses: actions/checkout@v2
data/.standard.yml ADDED
@@ -0,0 +1,2 @@
1
+ ignore: # default: []
2
+ - 'vendor/**/*'
data/Gemfile CHANGED
@@ -1,8 +1,8 @@
1
- source 'https://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
5
  group :debugger do
6
- gem 'pry-byebug'
7
- gem 'pry-doc'
6
+ gem "pry-byebug"
7
+ gem "pry-doc"
8
8
  end
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ === 2.7.2 / 18.03.2021
2
+ * Added https://github.com/testdouble/standard and fixed all useful warnings
3
+ * Added standard to rake tasks
4
+ * Use ATC-code from refdata if available and show differences
5
+ * Get pharmacode from tranfer.dat for artikelstamm if possible
6
+ * We do not longer test Ruby 2.4 with github/actions
7
+ * Update build status to use github/actions instead of travis
8
+
1
9
  === 2.7.1 / 03.02.2021
2
10
  * travis-ci -> Github Actions
3
11
  * limit DSCRD/DSCRF to 120 chars as specified in the XSD
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # oddb2xml
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/zdavatz/oddb2xml.png)](http://travis-ci.org/zdavatz/oddb2xml)
3
+ [![Build Status](https://github.com/zdavatz/oddb2xml/workflows/Ruby/badge.svg)](https://github.com/zdavatz/oddb2xml/actions)
4
4
 
5
5
  * oddb2xml -a nonpharma -o fi
6
6
 
data/Rakefile CHANGED
@@ -1,25 +1,26 @@
1
1
  #!/usr/bin/env ruby
2
- # encoding: utf-8
3
- lib = File.expand_path('../lib', __FILE__)
2
+
3
+ lib = File.expand_path("../lib", __FILE__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'oddb2xml/version'
5
+ require "oddb2xml/version"
6
6
  require "bundler/gem_tasks"
7
- require 'rspec/core/rake_task'
7
+ require "standard/rake"
8
+ require "rspec/core/rake_task"
8
9
 
9
10
  RSpec::Core::RakeTask.new(:spec)
10
11
 
11
12
  # dependencies are now declared in oddb2xml.gemspec
12
13
 
13
- desc 'Offer a gem task like hoe'
14
- task :gem => :build do
14
+ desc "Offer a gem task like hoe"
15
+ task gem: :build do
15
16
  Rake::Task[:build].invoke
16
17
  end
17
18
 
18
- task :spec => :clean
19
+ task spec: :clean
19
20
 
20
- desc 'Run oddb2xml with all commonly used combinations'
21
- task :test => [:clean, :spec, :gem] do
22
- log_file = 'test_options.log'
21
+ desc "Run oddb2xml with all commonly used combinations"
22
+ task test: [:clean, :spec, :gem] do
23
+ log_file = "test_options.log"
23
24
  puts "Running test_options.rb with Output redirected to #{log_file}. This will take some time (e.g. 20 minutes)"
24
25
  # must use bash -o pipefail to catch error in test_options.rb and not tee
25
26
  # see http://stackoverflow.com/questions/985876/tee-and-exit-status
@@ -28,16 +29,16 @@ task :test => [:clean, :spec, :gem] do
28
29
  exit 1 unless res
29
30
  end
30
31
 
31
- require 'rake/clean'
32
- CLEAN.include FileList['pkg/*.gem']
33
- CLEAN.include FileList['*.zip*']
34
- CLEAN.include FileList['*.xls*']
35
- CLEAN.include FileList['*.xml*']
36
- CLEAN.include FileList['*.dat*']
37
- CLEAN.include FileList['*.tar.gz']
38
- CLEAN.include FileList['*.txt.*']
39
- CLEAN.include FileList['*.csv.*']
40
- CLEAN.include FileList['*.zip.*']
41
- CLEAN.include FileList['ruby*.tmp']
42
- CLEAN.include FileList['data/download']
43
- CLEAN.include FileList['duplicate_ean13_from_zur_rose.txt']
32
+ require "rake/clean"
33
+ CLEAN.include FileList["pkg/*.gem"]
34
+ CLEAN.include FileList["*.zip*"]
35
+ CLEAN.include FileList["*.xls*"]
36
+ CLEAN.include FileList["*.xml*"]
37
+ CLEAN.include FileList["*.dat*"]
38
+ CLEAN.include FileList["*.tar.gz"]
39
+ CLEAN.include FileList["*.txt.*"]
40
+ CLEAN.include FileList["*.csv.*"]
41
+ CLEAN.include FileList["*.zip.*"]
42
+ CLEAN.include FileList["ruby*.tmp"]
43
+ CLEAN.include FileList["data/download"]
44
+ CLEAN.include FileList["duplicate_ean13_from_zur_rose.txt"]
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env ruby
2
- require 'pathname'
2
+ require "pathname"
3
3
 
4
4
  root = Pathname.new(__FILE__).realpath.parent.parent
5
- $:.unshift root.join('lib') if $0 == __FILE__
5
+ $:.unshift root.join("lib") if $0 == __FILE__
6
6
 
7
- require 'oddb2xml/version'
8
- require 'oddb2xml/semantic_check'
9
- require 'optimist'
7
+ require "oddb2xml/version"
8
+ require "oddb2xml/semantic_check"
9
+ require "optimist"
10
10
 
11
- @opts = Optimist::options(ARGV) do
12
- version "#$0 ver.#{Oddb2xml::VERSION}"
11
+ @opts = Optimist.options(ARGV) do
12
+ version "#{$0} ver.#{Oddb2xml::VERSION}"
13
13
  banner <<-EOS
14
14
  Runs various semanti_check for the Elexis artikelstamm
15
15
  Usage:
16
16
  #{File.basename(__FILE__)} xml_file_to_check
17
- EOS
17
+ EOS
18
18
  end
19
19
  $stdout.sync = true
20
20
 
@@ -24,7 +24,7 @@ if args.size != 1
24
24
  exit 2
25
25
  end
26
26
 
27
- startTime = Time.now
28
- result = Oddb2xml::SemanticCheck.new(ARGV.first).allSemanticChecks
29
- diff = (Time.now-startTime).to_i
27
+ start_time = Time.now
28
+ Oddb2xml::SemanticCheck.new(ARGV.first).allSemanticChecks
29
+ diff = (Time.now - start_time).to_i
30
30
  puts "#{Time.now.strftime("%H:%M:%S")}: #{__FILE__} done. Took #{diff} seconds"
data/bin/compare_v5 CHANGED
@@ -1,31 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
- require 'pathname'
2
+ require "pathname"
3
3
 
4
4
  root = Pathname.new(__FILE__).realpath.parent.parent
5
- $:.unshift root.join('lib') if $0 == __FILE__
5
+ $:.unshift root.join("lib") if $0 == __FILE__
6
6
 
7
- require 'oddb2xml/version'
8
- require 'oddb2xml/compare'
9
- require 'optimist'
10
- DEFAULTSx = {
11
- :components => ["PRODUCTS", "LIMITATIONS", "ITEMS",],
12
- :fields_to_ignore => ['COMP', 'DOSAGE_FORMF', 'MEASUREF'],
13
- :fields_as_floats => [ 'PEXT', 'PEXF', 'PPUB' ],
14
- :min_diff_for_floats => 0.01,
15
- :case_insensitive => true,
16
- }
7
+ require "oddb2xml/version"
8
+ require "oddb2xml/compare"
9
+ require "optimist"
10
+ DEFAULTS_X = {
11
+ components: ["PRODUCTS", "LIMITATIONS", "ITEMS"],
12
+ fields_to_ignore: ["COMP", "DOSAGE_FORMF", "MEASUREF"],
13
+ fields_as_floats: ["PEXT", "PEXF", "PPUB"],
14
+ min_diff_for_floats: 0.01,
15
+ case_insensitive: true
16
+ }
17
17
 
18
- @opts = Optimist::options(ARGV) do
19
- version "#$0 ver.#{Oddb2xml::VERSION}"
18
+ @opts = Optimist.options(ARGV) do
19
+ version "#{$0} ver.#{Oddb2xml::VERSION}"
20
20
  banner <<-EOS
21
21
  Usage:
22
22
  compare_v5 [option] first_v5_xml second_v5_xml
23
- EOS
24
- opt :components, "components to compare", :default => Oddb2xml::CompareV5::DEFAULTS[:components]
25
- opt :fields_as_floats, "Fields that should be compared as floats", :default => Oddb2xml::CompareV5::DEFAULTS[:fields_as_floats]
26
- opt :fields_to_ignore, "Ignore these fields", :default => Oddb2xml::CompareV5::DEFAULTS[:fields_to_ignore]
27
- opt :min_diff_for_floats, "Minimal difference when comparing floats", :default => Oddb2xml::CompareV5::DEFAULTS[:min_diff_for_floats]
28
- opt :case_insensitive, "case_insensitive comparison", :default => Oddb2xml::CompareV5::DEFAULTS[:case_insensitive]
23
+ EOS
24
+ opt :components, "components to compare", default: Oddb2xml::CompareV5::DEFAULTS[:components]
25
+ opt :fields_as_floats, "Fields that should be compared as floats", default: Oddb2xml::CompareV5::DEFAULTS[:fields_as_floats]
26
+ opt :fields_to_ignore, "Ignore these fields", default: Oddb2xml::CompareV5::DEFAULTS[:fields_to_ignore]
27
+ opt :min_diff_for_floats, "Minimal difference when comparing floats", default: Oddb2xml::CompareV5::DEFAULTS[:min_diff_for_floats]
28
+ opt :case_insensitive, "case_insensitive comparison", default: Oddb2xml::CompareV5::DEFAULTS[:case_insensitive]
29
29
  end
30
30
  $stdout.sync = false
31
31
 
@@ -35,7 +35,7 @@ if args.size != 2
35
35
  exit 2
36
36
  end
37
37
 
38
- startTime = Time.now
39
- result = Oddb2xml::CompareV5.new(ARGV.first, ARGV.last, @opts).compare
40
- diff = (Time.now-startTime).to_i
38
+ start_time = Time.now
39
+ Oddb2xml::CompareV5.new(ARGV.first, ARGV.last, @opts).compare
40
+ diff = (Time.now - start_time).to_i
41
41
  puts "#{Time.now.strftime("%H:%M:%S")}: #{__FILE__} done. Took #{diff} seconds"
data/bin/oddb2xml CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'pathname'
3
+ require "pathname"
4
4
  root = Pathname.new(__FILE__).realpath.parent.parent
5
- $:.unshift root.join('lib') if $0 == __FILE__
5
+ $:.unshift root.join("lib") if $0 == __FILE__
6
6
 
7
- require 'mechanize'
8
- require 'oddb2xml'
9
- require 'oddb2xml/options'
7
+ require "mechanize"
8
+ require "oddb2xml"
9
+ require "oddb2xml/options"
10
10
  $stdout.sync = true
11
11
 
12
12
  opts = Oddb2xml::Options.parse(ARGV)
@@ -17,21 +17,21 @@ if args.size > 0
17
17
  exit 2
18
18
  end
19
19
  # TEMP
20
- if path = args.first
20
+ if (path = args.first)
21
21
  opts[:transfer_dat] = path
22
22
  end
23
23
 
24
- startTime = Time.now
24
+ start_time = Time.now
25
25
  ui = Oddb2xml::Cli.new(opts)
26
26
  begin
27
27
  if opts[:format] == :xml
28
28
  opts[:ean14] = true # force
29
29
  end
30
- #puts opts if opts[:debug]
30
+ # puts opts if opts[:debug]
31
31
  if RUBY_VERSION.to_f < 1.9
32
- message = <<-MES
33
- Once you find some time, please upgrade your Ruby to 1.9.3 ;)
34
- then you will not see anymore warnings
32
+ message = <<~MES
33
+ Once you find some time, please upgrade your Ruby to 1.9.3 ;)
34
+ then you will not see anymore warnings
35
35
  MES
36
36
  warn message
37
37
  end
@@ -39,5 +39,6 @@ then you will not see anymore warnings
39
39
  rescue Interrupt
40
40
  exit
41
41
  end
42
- diff = (Time.now-startTime).to_i
43
- puts "#{Time.now}: #{__LINE__} done. Took #{diff} seconds"; $stdout.sync
42
+ diff = (Time.now - start_time).to_i
43
+ puts "#{Time.now}: #{__LINE__} done. Took #{diff} seconds"
44
+ $stdout.sync
data/lib/oddb2xml.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require "oddb2xml/version"
2
- require 'oddb2xml/cli'
2
+ require "oddb2xml/cli"
3
3
 
4
4
  module Oddb2xml
5
5
  end
@@ -1,21 +1,22 @@
1
- # encoding: utf-8
2
- require 'nokogiri'
3
- require 'oddb2xml/util'
4
- require 'oddb2xml/calc'
5
- require 'csv'
1
+ require "nokogiri"
2
+ require "oddb2xml/util"
3
+ require "oddb2xml/calc"
4
+ require "csv"
5
+
6
6
  class Numeric
7
7
  # round a given number to the nearest step
8
8
  def round_by(increment)
9
9
  (self / increment).round * increment
10
10
  end
11
11
  end
12
+
12
13
  module Nokogiri
13
14
  module XML
14
15
  class Document < Nokogiri::XML::Node
15
16
  attr_writer :tag_suffix
16
- alias :create_element_origin :create_element
17
+ alias_method :create_element_origin, :create_element
17
18
  def create_element name, *args, &block
18
- name += (@tag_suffix || '')
19
+ name += (@tag_suffix || "")
19
20
  create_element_origin(name, *args, &block)
20
21
  end
21
22
  end
@@ -24,108 +25,116 @@ end
24
25
 
25
26
  module Oddb2xml
26
27
  XML_OPTIONS = {
27
- 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
28
- 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
29
- 'xmlns' => 'http://wiki.oddb.org/wiki.php?pagename=Swissmedic.Datendeklaration',
30
- 'CREATION_DATETIME' => Time.new.strftime('%FT%T%z'),
31
- 'PROD_DATE' => Time.new.strftime('%FT%T%z'),
32
- 'VALID_DATE' => Time.new.strftime('%FT%T%z'),
33
- 'GENERATED_BY' => "oddb2xml #{VERSION}"
28
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
29
+ "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
30
+ "xmlns" => "http://wiki.oddb.org/wiki.php?pagename=Swissmedic.Datendeklaration",
31
+ "CREATION_DATETIME" => Time.new.strftime("%FT%T%z"),
32
+ "PROD_DATE" => Time.new.strftime("%FT%T%z"),
33
+ "VALID_DATE" => Time.new.strftime("%FT%T%z"),
34
+ "GENERATED_BY" => "oddb2xml #{VERSION}"
34
35
  }
35
36
  class Builder
36
- Data_dir = File.expand_path(File.join(File.dirname(__FILE__),'..','..', 'data'))
37
- @@article_overrides = YAML.load_file(File.join(Data_dir, 'article_overrides.yaml'))
38
- @@product_overrides = YAML.load_file(File.join(Data_dir, 'product_overrides.yaml'))
39
- @@ignore_file = File.join(Data_dir, 'gtin2ignore.yaml')
40
- @@gtin2ignore = YAML.load_file(@@ignore_file) if File.exist?(@@ignore_file)
37
+ Data_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "data"))
38
+ @@article_overrides = YAML.load_file(File.join(Data_dir, "article_overrides.yaml"))
39
+ @@product_overrides = YAML.load_file(File.join(Data_dir, "product_overrides.yaml"))
40
+ @@ignore_file = File.join(Data_dir, "gtin2ignore.yaml")
41
+ @@gtin2ignore = YAML.load_file(@@ignore_file) if File.exist?(@@ignore_file)
41
42
  @@gtin2ignore ||= []
42
43
  attr_accessor :subject, :refdata, :items, :flags, :lppvs,
43
- :actions, :migel, :orphan,
44
- :infos, :packs, :infos_zur_rose,
45
- :ean14, :tag_suffix,
46
- :companies, :people,
47
- :xsd
44
+ :actions, :migel, :orphan,
45
+ :infos, :packs, :infos_zur_rose,
46
+ :ean14, :tag_suffix,
47
+ :companies, :people,
48
+ :xsd
48
49
  def initialize(args = {})
49
- @options = args
50
- @subject = nil
51
- @refdata = {}
52
- @items = {} # Spezailitäteniste: SL-Items from Preparations.xml in BAG, using GTINS as key
53
- @flags = {}
54
- @lppvs = {}
55
- @infos = {}
56
- @packs = {}
57
- @migel = {}
58
- @infos_zur_rose ||= {}
59
- @actions = []
60
- @orphan = []
61
- @ean14 = false
62
- @companies = []
63
- @people = []
50
+ @options = args
51
+ @subject = nil
52
+ @refdata = {}
53
+ @items = {} # Spezailitäteniste: SL-Items from Preparations.xml in BAG, using GTINS as key
54
+ @flags = {}
55
+ @lppvs = {}
56
+ @infos = {}
57
+ @packs = {}
58
+ @migel = {}
59
+ @infos_zur_rose ||= {}
60
+ @actions = []
61
+ @orphan = []
62
+ @ean14 = false
63
+ @companies = []
64
+ @people = []
64
65
  @tag_suffix = nil
65
66
  @pharmacode = {} # index pharmacode => item
66
67
  if block_given?
67
68
  yield self
68
69
  end
69
70
  end
70
- def to_xml(subject=nil)
71
+
72
+ def to_xml(subject = nil)
71
73
  Oddb2xml.log "to_xml subject #{subject || @subject}"
72
74
  if subject
73
- self.send('build_' + subject.to_s)
75
+ send("build_" + subject.to_s)
74
76
  elsif @subject
75
- self.send('build_' + @subject.to_s)
77
+ send("build_" + @subject.to_s)
76
78
  end
77
79
  end
78
- def to_dat(subject=nil)
79
- Oddb2xml.log "to_dat subject #{subject ? subject.to_s : @subject.to_s} for #{self.class}"
80
+
81
+ def to_dat(subject = nil)
82
+ Oddb2xml.log "to_dat subject #{subject ? subject.to_s : @subject.to_s} for #{self.class}"
80
83
  if subject
81
- self.send('build_' + subject.to_s)
84
+ send("build_" + subject.to_s)
82
85
  elsif @subject
83
- self.send('build_' + @subject.to_s)
86
+ send("build_" + @subject.to_s)
84
87
  end
85
88
  end
86
- private
87
- def prepare_articles(reset=false)
89
+
90
+ private_class_method
91
+
92
+ def prepare_articles(reset = false)
88
93
  @articles = nil if reset
89
94
  unless @articles
90
- Oddb2xml.log("prepare_articles starting with #{@articles ? @articles.size : 'no'} articles.")
95
+ Oddb2xml.log("prepare_articles starting with #{@articles ? @articles.size : "no"} articles.")
91
96
  @articles = []
92
97
  @refdata.each do |ean13, obj|
93
- if migel = @migel[ean13]
94
- # delete duplicates
95
- @migel[ean13] = nil
96
- end unless SkipMigelDownloader
97
- if seq = @items[obj[:ean13]]
98
+ unless SKIP_MIGEL_DOWNLOADER
99
+ if @migel[ean13]
100
+ # delete duplicates
101
+ @migel[ean13] = nil
102
+ end
103
+ end
104
+ if (seq = @items[obj[:ean13]])
98
105
  obj[:seq] = seq.clone
99
106
  end
100
107
  @articles << obj
101
108
  @pharmacode[obj[:pharmacode]] = obj
102
109
  end
103
110
  # add
104
- @migel.values.compact.each do |migel|
105
- next unless migel[:pharmacode]
106
- entry = {
107
- :ean13 => migel[:ean13],
108
- :pharmacode => migel[:pharmacode],
109
- :stat_date => '',
110
- :desc_de => migel[:desc_de],
111
- :desc_fr => migel[:desc_fr],
112
- :atc_code => '',
113
- :quantity => migel[:quantity],
114
- :company_ean => migel[:company_ean],
115
- :company_name => migel[:company_name],
116
- :migel => true,
111
+ unless SKIP_MIGEL_DOWNLOADER
112
+ @migel.values.compact.each do |migel|
113
+ next unless migel[:pharmacode]
114
+ entry = {
115
+ ean13: migel[:ean13],
116
+ pharmacode: migel[:pharmacode],
117
+ stat_date: "",
118
+ desc_de: migel[:desc_de],
119
+ desc_fr: migel[:desc_fr],
120
+ atc_code: "",
121
+ quantity: migel[:quantity],
122
+ company_ean: migel[:company_ean],
123
+ company_name: migel[:company_name],
124
+ migel: true
117
125
  }
118
- @articles << entry
119
- end unless SkipMigelDownloader
120
- nrAdded = 0
126
+ @articles << entry
127
+ end
128
+ end
129
+ nr_added = 0
121
130
  if @options[:extended] || @options[:artikelstamm]
122
131
  Oddb2xml.log("prepare_articles extended prepare_local_index having already #{@articles.size} articles")
123
- nrItems = 0
132
+ nr_items = 0
124
133
  @infos_zur_rose.each do |ean13, info|
125
- nrItems += 1
134
+ nr_items += 1
126
135
  pharmacode = info[:pharmacode]
127
136
  if @pharmacode[pharmacode]
128
- @pharmacode[pharmacode][:price] = info[:price]
137
+ @pharmacode[pharmacode][:price] = info[:price]
129
138
  @pharmacode[pharmacode][:pub_price] = info[:pub_price]
130
139
  next
131
140
  end
@@ -134,20 +143,20 @@ module Oddb2xml
134
143
  existing = @refdata[ean13]
135
144
  if existing
136
145
  found = true
137
- existing[:price] = info[:price]
146
+ existing[:price] = info[:price]
138
147
  existing[:pub_price] = info[:pub_price]
139
148
  else
140
149
  entry = {
141
- :desc => info[:description],
142
- :desc_de => info[:description],
143
- :status => info[:status] == '3' ? 'I' : 'A', # from ZurRose, we got 1,2 or 3 means aktive, aka available in trade
144
- :atc_code => '',
145
- :ean13 => ean13,
146
- :pharmacode => pharmacode,
147
- :price => info[:price],
148
- :pub_price => info[:pub_price],
149
- :type => info[:type],
150
- }
150
+ desc: info[:description],
151
+ desc_de: info[:description],
152
+ status: info[:status] == "3" ? "I" : "A", # from ZurRose, we got 1,2 or 3 means aktive, aka available in trade
153
+ atc_code: "",
154
+ ean13: ean13,
155
+ pharmacode: pharmacode,
156
+ price: info[:price],
157
+ pub_price: info[:pub_price],
158
+ type: info[:type]
159
+ }
151
160
  if pharmacode
152
161
  @refdata[pharmacode] = entry
153
162
  else
@@ -155,15 +164,16 @@ module Oddb2xml
155
164
  end
156
165
  obj = entry
157
166
  end
158
- if not found and obj.size > 0
167
+ if !found && (obj.size > 0)
159
168
  @articles << obj unless @options[:artikelstamm]
160
- nrAdded += 1
169
+ nr_added += 1
161
170
  end
162
171
  end
163
172
  end
164
173
  end
165
- Oddb2xml.log("prepare_articles done. Added #{nrAdded} prices. Total #{@articles.size}")
174
+ Oddb2xml.log("prepare_articles done. Added #{nr_added} prices. Total #{@articles.size}")
166
175
  end
176
+
167
177
  def prepare_substances
168
178
  unless @substances
169
179
  Oddb2xml.log("prepare_substances from #{@items.size} items")
@@ -177,9 +187,10 @@ module Oddb2xml
177
187
  @substances.uniq!
178
188
  @substances.sort!
179
189
  Oddb2xml.log("prepare_substances done. Total #{@substances.size} from #{@items.size} items")
180
- exit 2 if (@options[:extended] || @options[:artikelstamm]) and @substances.size == 0
190
+ exit 2 if (@options[:extended] || @options[:artikelstamm]) && (@substances.size == 0)
181
191
  end
182
192
  end
193
+
183
194
  def prepare_limitations
184
195
  unless @limitations
185
196
  Oddb2xml.log("prepare_limitations from #{@items.size} items")
@@ -193,10 +204,11 @@ module Oddb2xml
193
204
  # ID is no longer fixed TAG (swissmedicNo8, swissmedicNo5, pharmacode)
194
205
  # limitation.xml needs all duplicate entries by this keys.
195
206
  limitations.uniq! { |lim| lim[:id].to_s + lim[:code] + lim[:type] }
196
- @limitations = limitations.sort_by {|lim| lim[:code] }
207
+ @limitations = limitations.sort_by { |lim| lim[:code] }
197
208
  Oddb2xml.log("prepare_limitations done. Total #{@limitations.size} from #{@items.size} items")
198
209
  end
199
210
  end
211
+
200
212
  def prepare_interactions
201
213
  unless @interactions
202
214
  @interactions = []
@@ -205,60 +217,61 @@ module Oddb2xml
205
217
  end
206
218
  end
207
219
  end
220
+
208
221
  def prepare_codes
209
- unless @codes
210
- @codes = {
211
- 'X' => {:int => 11, :txt => 'Kontraindiziert'},
212
- 'D' => {:int => 13, :txt => 'Kombination meiden'},
213
- 'C' => {:int => 14, :txt => 'Monitorisieren'},
214
- 'B' => {:int => 15, :txt => 'Vorsichtsmassnahmen'},
215
- 'A' => {:int => 16, :txt => 'keine Massnahmen'}
216
- }
217
- end
222
+ @codes ||= {
223
+ "X" => {int: 11, txt: "Kontraindiziert"},
224
+ "D" => {int: 13, txt: "Kombination meiden"},
225
+ "C" => {int: 14, txt: "Monitorisieren"},
226
+ "B" => {int: 15, txt: "Vorsichtsmassnahmen"},
227
+ "A" => {int: 16, txt: "keine Massnahmen"}
228
+ }
218
229
  end
230
+
219
231
  def prepare_products
220
232
  unless @products
221
233
  @products = {}
222
234
  if @chapter70items
223
235
  Chapter70xtractor::LIMITATIONS.each do |key, desc_de|
224
236
  puts "Chapter70: Adding lim #{key} #{desc_de}" if $VERBOSE
225
- @limitations<< {:code => key,
226
- :id => ( key.eql?('L') ? '70.02' :'70.01'),
227
- :desc_de => desc_de,
228
- :desc_fr => '',
229
- :chap70 => true,
230
- }
237
+ @limitations << {code: key,
238
+ id: (key.eql?("L") ? "70.02" : "70.01"),
239
+ desc_de: desc_de,
240
+ desc_fr: "",
241
+ chap70: true}
231
242
  end
232
243
  @chapter70items.values.each do |item|
233
244
  next unless item[:limitation] && item[:limitation].length > 0
234
- rose = @infos_zur_rose.values.find {|x| x[:pharmacode] && x[:pharmacode].eql?(item[:pharmacode])}
235
- ean13 = rose[:ean13] if rose
236
- ean13 ||= '9999'+item[:pharmacode]
245
+ rose = @infos_zur_rose.values.find { |x| x[:pharmacode]&.eql?(item[:pharmacode]) }
246
+ ean13 = rose[:ean13] if rose
247
+ ean13 ||= "9999" + item[:pharmacode]
237
248
  prodno = item[:pharmacode]
238
249
  obj = {
239
- :chapter70 => true,
240
- :ean13 => ean13,
241
- :description => item[:description],
242
- :code => item[:limitation], # LIMNAMEBAG
250
+ chapter70: true,
251
+ ean13: ean13,
252
+ description: item[:description],
253
+ code: item[:limitation] # LIMNAMEBAG
243
254
  }
244
255
  @products[prodno] = obj
245
256
  puts "Chapter70: Adding product #{ean13} #{obj}" if $VERBOSE
246
257
  end
247
258
  end
248
259
  @refdata.each_pair do |ean13, item|
249
- next if item and item.is_a?(Hash) and item[:atc_code] and /^Q/i.match(item[:atc_code])
250
- next if item[:prodno] and @products[item[:prodno]]
260
+ next if item&.is_a?(Hash) && item[:atc_code] && /^Q/i.match(item[:atc_code])
261
+ next if item[:prodno] && @products[item[:prodno]]
262
+ refdata_atc = item[:atc_code]
251
263
  obj = {
252
- :seq => @items[ean13] ? @items[ean13] : @items[item[:ean13]],
253
- :pac => nil,
254
- :no8 => nil,
255
- :ean13 => item[:ean13],
256
- :atc => item[:atc_code],
257
- :ith => '',
258
- :siz => '',
259
- :eht => '',
260
- :sub => '',
261
- :comp => '',
264
+ seq: @items[ean13] || @items[item[:ean13]],
265
+ pac: nil,
266
+ no8: nil,
267
+ ean13: item[:ean13],
268
+ atc: refdata_atc,
269
+ ith: "",
270
+ siz: "",
271
+ eht: "",
272
+ sub: "",
273
+ comp: "",
274
+ data_origin: "refdata-product"
262
275
  }
263
276
  # obj[:pexf_refdata] = item[:price]
264
277
  # obj[:ppub_refdata] = item[:pub_price=]
@@ -266,6 +279,15 @@ module Oddb2xml
266
279
  if obj[:ean13] # via EAN-Code
267
280
  obj[:no8] = obj[:ean13].to_s[4..11]
268
281
  end
282
+ swissmedic_pack = @packs[item[:no8]]
283
+ if swissmedic_pack
284
+ swissmedic_atc = swissmedic_pack[:atc_code]
285
+ if swissmedic_atc && swissmedic_atc.length >= 3 && (refdata_atc.nil? || !refdata_atc.eql?(swissmedic_atc))
286
+ puts "WARNING: #{ean13} ATC-code #{swissmedic_atc} from swissmedic overrides #{refdata_atc} one from refdata #{item[:desc_de]}"
287
+ item[:data_origin] += "-swissmedic-ATC"
288
+ item[:atc] = swissmedic_atc
289
+ end
290
+ end
269
291
  if obj[:no8] && (ppac = @packs[obj[:no8]]) && # Packungen.xls
270
292
  !ppac[:is_tier]
271
293
  # If RefData does not have EAN
@@ -273,7 +295,7 @@ module Oddb2xml
273
295
  obj[:ean13] = ppac[:ean13]
274
296
  end
275
297
  # If RefData dose not have ATC-Code
276
- if obj[:atc].nil? or obj[:atc].empty?
298
+ if obj[:atc].nil? || obj[:atc].empty?
277
299
  obj[:atc] = ppac[:atc_code].to_s
278
300
  end
279
301
  obj[:ith] = ppac[:ith_swissmedic]
@@ -285,7 +307,7 @@ module Oddb2xml
285
307
  obj[:price] = item[:price]
286
308
  obj[:pub_price] = item[:pub_price]
287
309
 
288
- if obj[:ean13].to_s[0..3] == '7680'
310
+ if obj[:ean13].to_s[0..3] == "7680"
289
311
  if item[:prodno]
290
312
  @products[item[:prodno]] = obj
291
313
  else
@@ -296,118 +318,118 @@ module Oddb2xml
296
318
  end
297
319
  @products
298
320
  end
321
+
299
322
  def build_substance
300
323
  prepare_substances
301
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
324
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
302
325
  xml.doc.tag_suffix = @tag_suffix
303
- datetime = Time.new.strftime('%FT%T%z')
304
326
  xml.SUBSTANCE(
305
327
  XML_OPTIONS
306
328
  ) {
307
329
  Oddb2xml.log "build_substance #{@substances.size} substances"
308
- exit 2 if (@options[:extended] || @options[:artikelstamm]) and @substances.size == 0
309
- nbr_records = 0
310
- @substances.each_with_index do |sub_name, i|
311
- xml.SB('DT' => '') do
330
+ exit 2 if (@options[:extended] || @options[:artikelstamm]) && (@substances.size == 0)
331
+ nbr_records = 0
332
+ @substances.each_with_index do |sub_name, i|
333
+ xml.SB("DT" => "") do
312
334
  xml.SUBNO((i + 1).to_i)
313
- #xml.NAMD
314
- #xml.ANAMD
315
- #xml.NAMF
335
+ # xml.NAMD
336
+ # xml.ANAMD
337
+ # xml.NAMF
316
338
  xml.NAML sub_name
317
339
  nbr_records += 1
318
340
  end
319
341
  end
320
342
  xml.RESULT {
321
- xml.OK_ERROR 'OK'
343
+ xml.OK_ERROR "OK"
322
344
  xml.NBR_RECORD nbr_records
323
- xml.ERROR_CODE ''
324
- xml.MESSAGE ''
345
+ xml.ERROR_CODE ""
346
+ xml.MESSAGE ""
325
347
  }
326
348
  }
327
349
  end
328
- Oddb2xml.add_hash(_builder.to_xml)
350
+ Oddb2xml.add_hash(a_builder.to_xml)
329
351
  end
352
+
330
353
  def build_limitation
331
354
  prepare_limitations
332
355
  Oddb2xml.log "build_limitation #{@limitations.size} limitations"
333
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
356
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
334
357
  xml.doc.tag_suffix = @tag_suffix
335
- datetime = Time.new.strftime('%FT%T%z')
336
358
  xml.LIMITATION(XML_OPTIONS) do
337
- nbr_records = 0
338
- @limitations.each do |lim|
339
- if lim[:id].empty?
340
- puts "Skipping empty id of #{lim}"
341
- next
342
- end
343
- xml.LIM('DT' => '') do
359
+ nbr_records = 0
360
+ @limitations.each do |lim|
361
+ if lim[:id].empty?
362
+ puts "Skipping empty id of #{lim}"
363
+ next
364
+ end
365
+ xml.LIM("DT" => "") do
344
366
  case lim[:key]
345
367
  when :swissmedic_number8
346
368
  xml.SwissmedicNo8 lim[:id]
347
369
  when :swissmedic_number5
348
370
  xml.SwissmedicNo5 lim[:id]
349
371
  when :pharmacode
350
- xml.Pharmacode lim[:id]
372
+ xml.Pharmacode lim[:id]
351
373
  end
352
- xml.IT lim[:it]
353
- xml.LIMTYP lim[:type]
354
- xml.LIMVAL lim[:value]
374
+ xml.IT lim[:it]
375
+ xml.LIMTYP lim[:type]
376
+ xml.LIMVAL lim[:value]
355
377
  xml.LIMNAMEBAG lim[:code] # original LIMCD
356
- xml.LIMNIV lim[:niv]
357
- xml.DSCRD lim[:desc_de]
358
- xml.DSCRF lim[:desc_fr]
359
- xml.VDAT lim[:vdate]
378
+ xml.LIMNIV lim[:niv]
379
+ xml.DSCRD lim[:desc_de]
380
+ xml.DSCRF lim[:desc_fr]
381
+ xml.VDAT lim[:vdate]
360
382
  nbr_records += 1
361
383
  end
362
384
  end
363
385
  xml.RESULT do
364
- xml.OK_ERROR 'OK'
386
+ xml.OK_ERROR "OK"
365
387
  xml.NBR_RECORD nbr_records
366
- xml.ERROR_CODE ''
367
- xml.MESSAGE ''
388
+ xml.ERROR_CODE ""
389
+ xml.MESSAGE ""
368
390
  end
369
391
  end
370
392
  end
371
- Oddb2xml.add_hash(_builder.to_xml)
393
+ Oddb2xml.add_hash(a_builder.to_xml)
372
394
  end
395
+
373
396
  def build_interaction
374
397
  prepare_interactions
375
398
  prepare_codes
376
399
  nbr_records = 0
377
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
400
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
378
401
  xml.doc.tag_suffix = @tag_suffix
379
- datetime = Time.new.strftime('%FT%T%z')
380
402
  xml.INTERACTION(XML_OPTIONS) {
381
403
  Oddb2xml.log "build_interaction #{@interactions.size} interactions"
382
- @interactions.sort_by{|ix| ix[:ixno] }.each do |ix|
383
- xml.IX('DT' => '') {
384
- xml.IXNO ix[:ixno]
385
- xml.TITD ix[:title]
386
- #xml.TITF
404
+ @interactions.sort_by { |ix| ix[:ixno] }.each do |ix|
405
+ xml.IX("DT" => "") {
406
+ xml.IXNO ix[:ixno]
407
+ xml.TITD ix[:title]
408
+ # xml.TITF
387
409
  xml.GRP1D ix[:atc1]
388
- #xml.GRP1F
410
+ # xml.GRP1F
389
411
  xml.GRP2D ix[:atc2]
390
- #xml.GRP2F
391
- xml.EFFD ix[:effect]
392
- #xml.EFFF
393
- if @codes and ix[:grad]
394
- if dict = @codes[ix[:grad].upcase]
395
- xml.RLV dict[:int]
412
+ # xml.GRP2F
413
+ xml.EFFD ix[:effect]
414
+ # xml.EFFF
415
+ if @codes && ix[:grad]
416
+ if (dict = @codes[ix[:grad].upcase])
417
+ xml.RLV dict[:int]
396
418
  xml.RLVD dict[:txt]
397
- #xml.RLVF
419
+ # xml.RLVF
398
420
  end
399
421
  end
400
- #xml.EFFTXTD
401
- #xml.EFFTXTF
422
+ # xml.EFFTXTD
423
+ # xml.EFFTXTF
402
424
  xml.MECHD ix[:mechanism]
403
- #xml.MECHF
425
+ # xml.MECHF
404
426
  xml.MEASD ix[:measures]
405
- #xml.MEASF
406
- #xml.REMD
407
- #xml.REMF
408
- #xml.LIT
427
+ # xml.MEASF
428
+ # xml.REMD
429
+ # xml.REMF
430
+ # xml.LIT
409
431
  xml.DEL false
410
- #xml.IXMCH {
432
+ # xml.IXMCH {
411
433
  # xml.TYP
412
434
  # xml.TYPD
413
435
  # xml.TYPF
@@ -416,61 +438,61 @@ module Oddb2xml
416
438
  # xml.CDF
417
439
  # xml.TXTD
418
440
  # xml.TXTF
419
- #}
441
+ # }
420
442
  nbr_records += 1
421
443
  }
422
444
  end
423
445
  xml.RESULT {
424
- xml.OK_ERROR 'OK'
446
+ xml.OK_ERROR "OK"
425
447
  xml.NBR_RECORD nbr_records
426
- xml.ERROR_CODE ''
427
- xml.MESSAGE ''
448
+ xml.ERROR_CODE ""
449
+ xml.MESSAGE ""
428
450
  }
429
451
  }
430
452
  end
431
- Oddb2xml.add_hash(_builder.to_xml)
453
+ Oddb2xml.add_hash(a_builder.to_xml)
432
454
  end
455
+
433
456
  def build_code
434
457
  prepare_codes
435
458
  nbr_records = 0
436
459
  Oddb2xml.log "build_code #{@codes.size} codes"
437
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
460
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
438
461
  xml.doc.tag_suffix = @tag_suffix
439
- datetime = Time.new.strftime('%FT%T%z')
440
462
  xml.CODE(XML_OPTIONS) {
441
463
  @codes.each_pair do |val, definition|
442
- xml.CD('DT' => '') {
443
- xml.CDTYP definition[:int]
444
- xml.CDVAL val
445
- xml.DSCRSD definition[:txt]
446
- #xml.DSCRSF
447
- #xml.DSCRMD
448
- #xml.DSCRMF
449
- #xml.DSCRD
450
- #xml.DSCRF
451
- xml.DEL false
464
+ xml.CD("DT" => "") {
465
+ xml.CDTYP definition[:int]
466
+ xml.CDVAL val
467
+ xml.DSCRSD definition[:txt]
468
+ # xml.DSCRSF
469
+ # xml.DSCRMD
470
+ # xml.DSCRMF
471
+ # xml.DSCRD
472
+ # xml.DSCRF
473
+ xml.DEL false
452
474
  nbr_records += 1
453
475
  }
454
476
  end
455
477
  xml.RESULT {
456
- xml.OK_ERROR 'OK'
478
+ xml.OK_ERROR "OK"
457
479
  xml.NBR_RECORD nbr_records
458
- xml.ERROR_CODE ''
459
- xml.MESSAGE ''
480
+ xml.ERROR_CODE ""
481
+ xml.MESSAGE ""
460
482
  }
461
483
  }
462
484
  end
463
- Oddb2xml.add_hash(_builder.to_xml)
485
+ Oddb2xml.add_hash(a_builder.to_xml)
464
486
  end
487
+
465
488
  def add_missing_products_from_swissmedic(add_to_products = false)
466
489
  Oddb2xml.log "build_product add_missing_products_from_swissmedic. Starting with #{@products.size} products and #{@packs.size} @packs"
467
490
  ean13_to_product = {}
468
- @products.each{
469
- |ean13, obj|
470
- ean13_to_product[ean13] = obj
471
- obj[:pharmacode] ||= @refdata[ean13][:pharmacode] if @refdata[ean13]
491
+ @products.each { |ean13, obj|
492
+ ean13_to_product[ean13] = obj
493
+ obj[:pharmacode] ||= @refdata[ean13][:pharmacode] if @refdata[ean13]
472
494
  }
473
- ausgabe = File.open(File.join(WorkDir, 'missing_in_refdata.txt'), 'w+')
495
+ ausgabe = File.open(File.join(WORK_DIR, "missing_in_refdata.txt"), "w+")
474
496
  size_old = ean13_to_product.size
475
497
  @missing = []
476
498
  Oddb2xml.log "build_product add_missing_products_from_swissmedic. Imported #{size_old} ean13_to_product from @products. Checking #{@packs.size} @packs"
@@ -478,49 +500,48 @@ module Oddb2xml
478
500
  ean = de_idx[1][:ean13]
479
501
  next if @refdata[ean]
480
502
  list_code = de_idx[1][:list_code]
481
- next if list_code and /Tierarzneimittel/.match(list_code)
503
+ next if list_code && /Tierarzneimittel/.match(list_code)
482
504
  if add_to_products
483
- @products[ean] = { :seq=>
484
- {:name_de => de_idx.last[:sequence_name],
485
- :desc_de => '',
486
- :name_fr => '',
487
- :desc_fr => '',
488
- :atc_code => de_idx.last[:atc_code],
489
- },
490
- :pac=>nil,
491
- :sequence_name => de_idx.last[:sequence_name],
492
- :no8=> de_idx.last[:prodno],
493
- :ean13=> ean,
494
- :atc=> de_idx.last[:atc_code],
495
- :ith=> de_idx.last[:ith_swissmedic],
496
- :siz=> de_idx.last[:package_size],
497
- :eht=> de_idx.last[:einheit_swissmedic],
498
- :sub=> de_idx.last[:substance_swissmedic],
499
- :comp=> de_idx.last[:composition_swissmedic],
500
- :drug_index => de_idx.last[:drug_index],
501
- }
505
+ @products[ean] = {seq: {name_de: de_idx.last[:sequence_name],
506
+ desc_de: "",
507
+ name_fr: "",
508
+ desc_fr: "",
509
+ atc_code: de_idx.last[:atc_code]},
510
+ pac: nil,
511
+ sequence_name: de_idx.last[:sequence_name],
512
+ no8: de_idx.last[:prodno],
513
+ ean13: ean,
514
+ atc: de_idx.last[:atc_code],
515
+ ith: de_idx.last[:ith_swissmedic],
516
+ siz: de_idx.last[:package_size],
517
+ eht: de_idx.last[:einheit_swissmedic],
518
+ sub: de_idx.last[:substance_swissmedic],
519
+ comp: de_idx.last[:composition_swissmedic],
520
+ drug_index: de_idx.last[:drug_index]}
502
521
  end
503
522
  ean13_to_product[ean] = de_idx[1]
504
523
  @missing << de_idx[1]
505
524
  ausgabe.puts "#{ean},#{de_idx[1][:sequence_name]}"
506
525
  end
507
526
  corrected_size = ean13_to_product.size
508
- Oddb2xml.log "build_product add_missing_products_from_swissmedic. Added #{(corrected_size - size_old)} corrected_size #{corrected_size} size_old #{size_old} ean13_to_product."
527
+ Oddb2xml.log "build_product add_missing_products_from_swissmedic. Added #{corrected_size - size_old} corrected_size #{corrected_size} size_old #{size_old} ean13_to_product."
509
528
  end
510
529
 
511
530
  def build_product
512
- def check_name(obj, lang = :de)
513
- ean = obj[:ean13]
514
- refdata = @refdata[ean]
515
- if lang == :de
516
- name = (refdata && refdata[:desc_de]) ? refdata[:desc_de] : obj[:sequence_name]
517
- elsif lang == :fr
518
- name = (refdata && refdata[:desc_fr]) ? refdata[:desc_fr] : obj[:sequence_name]
519
- else
520
- return false
531
+ self.class.class_eval do
532
+ def check_name(obj, lang = :de)
533
+ ean = obj[:ean13]
534
+ refdata = @refdata[ean]
535
+ if lang == :de
536
+ name = refdata && refdata[:desc_de] ? refdata[:desc_de] : obj[:sequence_name]
537
+ elsif lang == :fr
538
+ name = refdata && refdata[:desc_fr] ? refdata[:desc_fr] : obj[:sequence_name]
539
+ else
540
+ return false
541
+ end
542
+ return false if !name || name.empty? || name.length < 3
543
+ name[0..119] # limit to maximal 120 chars as specified in the XSD
521
544
  end
522
- return false if !name || name.empty? || name.length < 3
523
- name[0..119] # limit to maximal 120 chars as specified in the XSD
524
545
  end
525
546
  prepare_substances
526
547
  prepare_products
@@ -528,303 +549,297 @@ module Oddb2xml
528
549
  prepare_codes
529
550
  add_missing_products_from_swissmedic
530
551
  nbr_products = 0
531
- Oddb2xml.log "build_product #{@products.size+@missing.size} products"
532
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
552
+ Oddb2xml.log "build_product #{@products.size + @missing.size} products"
553
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
533
554
  xml.doc.tag_suffix = @tag_suffix
534
- datetime = Time.new.strftime('%FT%T%z')
535
555
  emitted = []
536
556
  xml.PRODUCT(XML_OPTIONS) {
537
- list = []
538
557
  @missing.each do |obj|
539
558
  ean = obj[:ean13]
540
559
  next unless check_name(obj, :de)
541
560
  next unless check_name(obj, :fr)
542
- next if /^Q/i.match(obj[:atc])
561
+ next if /^Q/i.match?(obj[:atc])
543
562
  if obj[:prodno]
544
563
  next if emitted.index(obj[:prodno])
545
564
  emitted << obj[:prodno]
546
565
  end
547
- xml.PRD('DT' => obj[:last_change]) {
548
- nbr_products += 1
549
- xml.GTIN ean
550
- xml.PRODNO obj[:prodno] if obj[:prodno]
551
- xml.DSCRD check_name(obj, :de)
552
- xml.DSCRF check_name(obj, :fr)
553
- xml.ATC obj[:atc_code] unless obj[:atc_code].empty?
554
- xml.IT obj[:ith_swissmedic] if obj[:ith_swissmedic]
555
- xml.CPT
556
- xml.PackGrSwissmedic obj[:package_size] if obj[:package_size]
557
- xml.EinheitSwissmedic obj[:einheit_swissmedic] if obj[:einheit_swissmedic]
558
- xml.SubstanceSwissmedic obj[:substance_swissmedic] if obj[:substance_swissmedic]
559
- xml.CompositionSwissmedic obj[:composition_swissmedic] if obj[:composition_swissmedic]
560
- }
566
+ xml.PRD("DT" => obj[:last_change]) {
567
+ nbr_products += 1
568
+ xml.GTIN ean
569
+ xml.PRODNO obj[:prodno] if obj[:prodno]
570
+ xml.DSCRD check_name(obj, :de)
571
+ xml.DSCRF check_name(obj, :fr)
572
+ xml.ATC obj[:atc_code] unless obj[:atc_code].empty?
573
+ xml.IT obj[:ith_swissmedic] if obj[:ith_swissmedic]
574
+ xml.CPT
575
+ xml.PackGrSwissmedic obj[:package_size] if obj[:package_size]
576
+ xml.EinheitSwissmedic obj[:einheit_swissmedic] if obj[:einheit_swissmedic]
577
+ xml.SubstanceSwissmedic obj[:substance_swissmedic] if obj[:substance_swissmedic]
578
+ xml.CompositionSwissmedic obj[:composition_swissmedic] if obj[:composition_swissmedic]
579
+ }
561
580
  end
562
581
  @products.sort.to_h.each do |ean13, obj|
563
- next if /^Q/i.match(obj[:atc])
582
+ next if /^Q/i.match?(obj[:atc])
564
583
  seq = obj[:seq]
565
- ean = obj[:ean13]
566
- next unless check_name(obj, :de)
567
- next unless check_name(obj, :fr)
568
- xml.PRD('DT' => obj[:last_change]) do
584
+ ean = obj[:ean13]
585
+ next unless check_name(obj, :de)
586
+ next unless check_name(obj, :fr)
587
+ xml.PRD("DT" => obj[:last_change]) do
569
588
  nbr_products += 1
570
589
  xml.GTIN ean
571
- ppac = ((_ppac = @packs[ean.to_s[4..11]] and !_ppac[:is_tier]) ? _ppac : {})
572
- unless ppac
573
- ppac = @packs.find{|pac| pac.ean == ean }.first
574
- end
575
- xml.PRODNO ppac[:prodno] if ppac[:prodno] and !ppac[:prodno].empty?
576
- xml.DSCRD check_name(obj, :de)
577
- xml.DSCRF check_name(obj, :fr)
578
- #xml.BNAMD
579
- #xml.BNAMF
580
- #xml.ADNAMD
581
- #xml.ADNAMF
582
- #xml.SIZE
590
+ ppac = ((a_ppac = @packs[ean.to_s[4..11]]) && !a_ppac[:is_tier] ? a_ppac : {})
591
+ ppac ||= @packs.find { |pac| pac.ean == ean }.first
592
+ xml.PRODNO ppac[:prodno] if ppac[:prodno] && !ppac[:prodno].empty?
593
+ xml.DSCRD check_name(obj, :de)
594
+ xml.DSCRF check_name(obj, :fr)
595
+ # xml.BNAMD
596
+ # xml.BNAMF
597
+ # xml.ADNAMD
598
+ # xml.ADNAMF
599
+ # xml.SIZE
583
600
  if seq
584
- xml.ADINFD seq[:comment_de] unless seq[:comment_de] && seq[:comment_de].empty?
585
- xml.ADINFF seq[:comment_fr] unless seq[:comment_fr] && seq[:comment_fr].empty?
586
- xml.GENCD seq[:org_gen_code] unless seq[:org_gen_code] && seq[:org_gen_code].empty?
601
+ xml.ADINFD seq[:comment_de] unless seq[:comment_de] && seq[:comment_de].empty?
602
+ xml.ADINFF seq[:comment_fr] unless seq[:comment_fr] && seq[:comment_fr].empty?
603
+ xml.GENCD seq[:org_gen_code] unless seq[:org_gen_code] && seq[:org_gen_code].empty?
587
604
  end
588
- #xml.GENGRP
605
+ # xml.GENGRP
589
606
  xml.ATC obj[:atc] unless obj[:atc].empty?
590
- xml.IT obj[:ith] unless obj[:ith].empty?
591
- #xml.ITBAG
592
- #xml.KONO
593
- #xml.TRADE
594
- #xml.PRTNO
595
- #xml.MONO
596
- #xml.CDGALD
597
- #xml.CDGALF
598
- #xml.FORMD
599
- #xml.FORMF
600
- #xml.DOSE
601
- #xml.DOSEU
602
- #xml.DRGFD
603
- #xml.DRGFF
607
+ xml.IT obj[:ith] unless obj[:ith].empty?
608
+ # xml.ITBAG
609
+ # xml.KONO
610
+ # xml.TRADE
611
+ # xml.PRTNO
612
+ # xml.MONO
613
+ # xml.CDGALD
614
+ # xml.CDGALF
615
+ # xml.FORMD
616
+ # xml.FORMF
617
+ # xml.DOSE
618
+ # xml.DOSEU
619
+ # xml.DRGFD
620
+ # xml.DRGFF
604
621
  obj[:no8] =~ /(\d{5})(\d{3})/
605
622
  if @orphan.include?($1.to_s)
606
623
  xml.ORPH true
607
624
  end
608
- #xml.BIOPHA
609
- #xml.BIOSIM
610
- #xml.BFS
611
- #xml.BLOOD
612
- #xml.MSCD # always empty
613
- #xml.DEL
625
+ # xml.BIOPHA
626
+ # xml.BIOSIM
627
+ # xml.BFS
628
+ # xml.BLOOD
629
+ # xml.MSCD # always empty
630
+ # xml.DEL
614
631
  xml.CPT {
615
- #xml.CPTLNO
616
- #xml.CNAMED
617
- #xml.CNAMEF
618
- #xml.IDXIND
619
- #xml.DDDD
620
- #xml.DDDU
621
- #xml.DDDA
622
- #xml.IDXIA
623
- #xml.IXREL
624
- #xml.GALF
625
- #xml.DRGGRPCD
626
- #xml.PRBSUIT
627
- #xml.CSOLV
628
- #xml.CSOLVQ
629
- #xml.CSOLVQU
630
- #xml.PHVAL
631
- #xml.LSPNSOL
632
- #xml.APDURSOL
633
- #xml.EXCIP
634
- #xml.EXCIPQ
635
- #xml.EXCIPCD
636
- #xml.EXCIPCF
637
- #xml.PQTY
638
- #xml.PQTYU
639
- #xml.SIZEMM
640
- #xml.WEIGHT
641
- #xml.LOOKD
642
- #xml.LOOKF
643
- #xml.IMG2
632
+ # xml.CPTLNO
633
+ # xml.CNAMED
634
+ # xml.CNAMEF
635
+ # xml.IDXIND
636
+ # xml.DDDD
637
+ # xml.DDDU
638
+ # xml.DDDA
639
+ # xml.IDXIA
640
+ # xml.IXREL
641
+ # xml.GALF
642
+ # xml.DRGGRPCD
643
+ # xml.PRBSUIT
644
+ # xml.CSOLV
645
+ # xml.CSOLVQ
646
+ # xml.CSOLVQU
647
+ # xml.PHVAL
648
+ # xml.LSPNSOL
649
+ # xml.APDURSOL
650
+ # xml.EXCIP
651
+ # xml.EXCIPQ
652
+ # xml.EXCIPCD
653
+ # xml.EXCIPCF
654
+ # xml.PQTY
655
+ # xml.PQTYU
656
+ # xml.SIZEMM
657
+ # xml.WEIGHT
658
+ # xml.LOOKD
659
+ # xml.LOOKF
660
+ # xml.IMG2
644
661
  if seq
645
662
  seq[:substances].each do |sub|
646
663
  xml.CPTCMP {
647
- xml.LINE sub[:index] unless sub[:index].empty?
664
+ xml.LINE sub[:index] unless sub[:index].empty?
648
665
  xml.SUBNO(@substances.index(sub[:name]) + 1) if @substances.include?(sub[:name])
649
- xml.QTY sub[:quantity] unless sub[:quantity].empty?
650
- xml.QTYU sub[:unit] unless sub[:unit].empty?
651
- #xml.WHK
666
+ xml.QTY sub[:quantity] unless sub[:quantity].empty?
667
+ xml.QTYU sub[:unit] unless sub[:unit].empty?
668
+ # xml.WHK
652
669
  }
653
670
  end
654
671
  @interactions.each do |ix|
655
672
  if [ix[:act1], ix[:act2]].include?(seq[:atc_code])
656
673
  xml.CPTIX {
657
674
  xml.IXNO ix[:ixno]
658
- #xml.GRP
659
- xml.RLV @codes[ix[:grad]]
675
+ # xml.GRP
676
+ xml.RLV @codes[ix[:grad]]
660
677
  }
661
678
  end
662
679
  end
663
680
  end
664
- #xml.CPTROA {
665
- #xml.SYSLOC
666
- #xml.ROA
667
- #}
681
+ # xml.CPTROA {
682
+ # xml.SYSLOC
683
+ # xml.ROA
684
+ # }
668
685
  }
669
- #xml.PRDICD { # currently empty
670
- #xml.ICD
671
- #xml.RTYP
672
- #xml.RSIG
673
- #xml.REMD
674
- #xml.REMF
675
- #}
676
- xml.PackGrSwissmedic obj[:siz] unless obj[:siz].empty?
677
- xml.EinheitSwissmedic obj[:eht] unless obj[:eht].empty?
686
+ # xml.PRDICD { # currently empty
687
+ # xml.ICD
688
+ # xml.RTYP
689
+ # xml.RSIG
690
+ # xml.REMD
691
+ # xml.REMF
692
+ # }
693
+ xml.PackGrSwissmedic obj[:siz] unless obj[:siz].empty?
694
+ xml.EinheitSwissmedic obj[:eht] unless obj[:eht].empty?
678
695
  xml.SubstanceSwissmedic obj[:sub] unless obj[:sub].empty?
679
696
  xml.CompositionSwissmedic obj[:comp] unless obj[:comp].empty?
680
697
  end
681
698
  end
682
699
  xml.RESULT {
683
- xml.OK_ERROR 'OK'
700
+ xml.OK_ERROR "OK"
684
701
  xml.NBR_RECORD nbr_products
685
- xml.ERROR_CODE ''
686
- xml.MESSAGE ''
702
+ xml.ERROR_CODE ""
703
+ xml.MESSAGE ""
687
704
  }
688
705
  }
689
706
  end
690
- Oddb2xml.add_hash(_builder.to_xml)
707
+ Oddb2xml.add_hash(a_builder.to_xml)
691
708
  end
692
709
 
693
710
  def prepare_calc_items(suppress_composition_parsing: false)
694
711
  @calc_items = {}
695
- packungen_xlsx = File.join(Oddb2xml::WorkDir, "swissmedic_package.xlsx")
696
- idx = 0
697
- return unless File.exists?(packungen_xlsx)
712
+ packungen_xlsx = File.join(Oddb2xml::WORK_DIR, "swissmedic_package.xlsx")
713
+ return unless File.exist?(packungen_xlsx)
698
714
  workbook = RubyXL::Parser.parse(packungen_xlsx)
699
715
  row_nr = 0
700
716
  workbook.worksheets[0].each do |row|
701
717
  row_nr += 1
702
- next unless row and row.cells[0] and row.cells[0].value and row.cells[0].value.to_i > 0
703
- iksnr = "%05i" % row.cells[0].value.to_i
704
- seqnr = "%02d" % row.cells[1].value.to_i
718
+ next unless row && row.cells[0] && row.cells[0].value && (row.cells[0].value.to_i > 0)
719
+ iksnr = "%05i" % row.cells[0].value.to_i
705
720
  if row_nr % 250 == 0
706
- puts "#{Time.now}: At row #{row_nr} iksnr #{iksnr}";
707
- $stdout.flush
721
+ puts "#{Time.now}: At row #{row_nr} iksnr #{iksnr}"
722
+ $stdout.flush
708
723
  end
709
- ith = COLUMNS_FEBRUARY_2019.keys.index(:index_therapeuticus)
710
- seq_name = COLUMNS_FEBRUARY_2019.keys.index(:name_base)
711
- i_3 = COLUMNS_FEBRUARY_2019.keys.index(:ikscd)
712
- p_1_2 = COLUMNS_FEBRUARY_2019.keys.index(:seqnr)
713
- cat = COLUMNS_FEBRUARY_2019.keys.index(:ikscat)
714
- siz = COLUMNS_FEBRUARY_2019.keys.index(:size)
715
- atc = COLUMNS_FEBRUARY_2019.keys.index(:atc_class)
724
+ seq_name = COLUMNS_FEBRUARY_2019.keys.index(:name_base)
725
+ i_3 = COLUMNS_FEBRUARY_2019.keys.index(:ikscd)
726
+ siz = COLUMNS_FEBRUARY_2019.keys.index(:size)
727
+ atc = COLUMNS_FEBRUARY_2019.keys.index(:atc_class)
716
728
  list_code = COLUMNS_FEBRUARY_2019.keys.index(:production_science)
717
- unit = COLUMNS_FEBRUARY_2019.keys.index(:unit)
718
- sub = COLUMNS_FEBRUARY_2019.keys.index(:substances)
719
- comp = COLUMNS_FEBRUARY_2019.keys.index(:composition)
729
+ unit = COLUMNS_FEBRUARY_2019.keys.index(:unit)
730
+ sub = COLUMNS_FEBRUARY_2019.keys.index(:substances)
731
+ comp = COLUMNS_FEBRUARY_2019.keys.index(:composition)
720
732
 
721
- no8 = iksnr + sprintf('%03d',row.cells[i_3].value.to_i)
722
- name = row.cells[seq_name] ? row.cells[seq_name].value : nil
723
- atc_code = row.cells[atc] ? row.cells[atc].value : nil
724
- list_code = row.cells[list_code] ? row.cells[list_code].value : nil
725
- package_size = row.cells[siz] ? row.cells[siz].value : nil
726
- unit = row.cells[unit] ? row.cells[unit].value : nil
727
- active_substance = row.cells[sub] ? row.cells[sub].value : nil
728
- composition = row.cells[comp] ? row.cells[comp].value : nil
733
+ no8 = iksnr + sprintf("%03d", row.cells[i_3].value.to_i)
734
+ name = row.cells[seq_name] ? row.cells[seq_name].value : nil
735
+ atc_code = row.cells[atc] ? row.cells[atc].value : nil
736
+ list_code = row.cells[list_code] ? row.cells[list_code].value : nil
737
+ package_size = row.cells[siz] ? row.cells[siz].value : nil
738
+ unit = row.cells[unit] ? row.cells[unit].value : nil
739
+ active_substance = row.cells[sub] ? row.cells[sub].value : nil
740
+ composition = row.cells[comp] ? row.cells[comp].value : nil
729
741
 
730
742
  # skip veterinary product
731
- next if atc_code and /^Q/i.match(atc_code)
732
- next if list_code and /Tierarzneimittel/.match(list_code)
743
+ next if atc_code && /^Q/i.match(atc_code)
744
+ next if list_code && /Tierarzneimittel/.match(list_code)
733
745
  info = nil
734
746
  begin
735
- if suppress_composition_parsing
736
- info = Calc.new(name, package_size, unit)
747
+ info = if suppress_composition_parsing
748
+ Calc.new(name, package_size, unit)
737
749
  else
738
- info = Calc.new(name, package_size, unit, active_substance, composition)
750
+ Calc.new(name, package_size, unit, active_substance, composition)
739
751
  end
740
752
  rescue
741
753
  puts "#{Time.now}: #{row_nr} iksnr #{iksnr} rescue from Calc.new"
742
754
  end
743
- ean12 = '7680' + no8
755
+ ean12 = "7680" + no8
744
756
  ean13 = (ean12 + Oddb2xml.calc_checksum(ean12))
745
757
  @calc_items[ean13] = info
746
758
  end
747
759
  end
748
- def build_calc
749
- def emit_substance(xml, substance, emit_active=false)
750
- xml.MORE_INFO substance.more_info if substance.more_info
751
- xml.SUBSTANCE_NAME substance.name
752
- xml.IS_ACTIVE_AGENT substance.is_active_agent if emit_active
753
- if substance.dose
754
- if substance.qty.is_a?(Float) or substance.qty.is_a?(Integer)
755
- xml.QTY substance.qty
756
- xml.UNIT substance.unit
757
- else
758
- xml.DOSE_TEXT substance.dose.to_s
759
- end
760
- end
761
- if substance.chemical_substance
762
- xml.CHEMICAL_SUBSTANCE {
763
- emit_substance(xml, substance.chemical_substance)
764
- }
765
- end
766
- if substance.salts and substance.salts.size > 0
767
- xml.SALTS do
768
- substance.salts.each do |salt|
769
- xml.SALT do
770
- emit_substance(xml, salt)
771
- end
772
- end
760
+
761
+ def emit_substance(xml, substance, emit_active = false)
762
+ xml.MORE_INFO substance.more_info if substance.more_info
763
+ xml.SUBSTANCE_NAME substance.name
764
+ xml.IS_ACTIVE_AGENT substance.is_active_agent if emit_active
765
+ if substance.dose
766
+ if substance.qty.is_a?(Float) || substance.qty.is_a?(Integer)
767
+ xml.QTY substance.qty
768
+ xml.UNIT substance.unit
769
+ else
770
+ xml.DOSE_TEXT substance.dose.to_s
771
+ end
772
+ end
773
+ if substance.chemical_substance
774
+ xml.CHEMICAL_SUBSTANCE {
775
+ emit_substance(xml, substance.chemical_substance)
776
+ }
777
+ end
778
+ if substance.salts && (substance.salts.size > 0)
779
+ xml.SALTS do
780
+ substance.salts.each do |salt|
781
+ xml.SALT do
782
+ emit_substance(xml, salt)
773
783
  end
774
784
  end
785
+ end
775
786
  end
787
+ end
788
+
789
+ def build_calc
776
790
  prepare_calc_items
777
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
791
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
778
792
  xml.doc.tag_suffix = @tag_suffix
779
- datetime = Time.new.strftime('%FT%T%z')
780
793
  xml.ARTICLES(XML_OPTIONS) do
781
794
  @calc_items.each do |ean13, info|
782
- xml.ARTICLE do
783
- xml.GTIN ean13
784
- xml.NAME info.column_c
785
- xml.PKG_SIZE info.pkg_size
786
- xml.SELLING_UNITS info.selling_units
787
- xml.MEASURE info.measure # Nur wenn Lösung wen Spalte M ml, Spritze
795
+ if info&.compositions
796
+ xml.ARTICLE do
797
+ xml.GTIN ean13
798
+ xml.NAME info.column_c
799
+ xml.PKG_SIZE info.pkg_size
800
+ xml.SELLING_UNITS info.selling_units
801
+ xml.MEASURE info.measure # Nur wenn Lösung wen Spalte M ml, Spritze
788
802
 
789
- if info.galenic_form.is_a?(String)
790
- xml.GALENIC_FORM info.galenic_form
791
- xml.GALENIC_GROUP "Unknown"
792
- else
793
- xml.GALENIC_FORM info.galenic_form.description
794
- xml.GALENIC_GROUP info.galenic_group ? info.galenic_group.description : "Unknown"
795
- end
796
- xml.COMPOSITIONS do
797
- info.compositions.each do |composition|
798
- xml.COMPOSITION do
799
- xml.EXCIPIENS { emit_substance(xml, composition.excipiens) } if composition.excipiens
800
- xml.LABEL composition.label if composition.label
801
- xml.LABEL_DESCRIPTION composition.label_description if composition.label_description
802
- xml.CORRESP composition.corresp if composition.corresp
803
- if composition.substances and composition.substances.size > 0
804
- xml.SUBSTANCES do
805
- composition.substances.each { |substance| xml.SUBSTANCE { emit_substance(xml, substance, true) }}
803
+ if info.galenic_form.is_a?(String)
804
+ xml.GALENIC_FORM info.galenic_form
805
+ xml.GALENIC_GROUP "Unknown"
806
+ else
807
+ xml.GALENIC_FORM info.galenic_form.description
808
+ xml.GALENIC_GROUP info.galenic_group ? info.galenic_group.description : "Unknown"
809
+ end
810
+ xml.COMPOSITIONS do
811
+ info.compositions.each do |composition|
812
+ xml.COMPOSITION do
813
+ xml.EXCIPIENS { emit_substance(xml, composition.excipiens) } if composition.excipiens
814
+ xml.LABEL composition.label if composition.label
815
+ xml.LABEL_DESCRIPTION composition.label_description if composition.label_description
816
+ xml.CORRESP composition.corresp if composition.corresp
817
+ if composition.substances && (composition.substances.size > 0)
818
+ xml.SUBSTANCES do
819
+ composition.substances.each { |substance| xml.SUBSTANCE { emit_substance(xml, substance, true) } }
820
+ end
806
821
  end
807
822
  end
808
823
  end
809
824
  end
810
825
  end
811
- end if info and info.compositions
826
+ end
812
827
  end
813
828
  end
814
829
  end
815
830
 
816
- csv_name = File.join(WorkDir, 'oddb_calc.csv')
817
- CSV.open(csv_name, "w+", :col_sep => ';') do |csv|
818
- csv << ['gtin'] + @calc_items.values.first.headers
831
+ csv_name = File.join(WORK_DIR, "oddb_calc.csv")
832
+ CSV.open(csv_name, "w+", col_sep: ";") do |csv|
833
+ csv << ["gtin"] + @calc_items.values.first.headers
819
834
  @calc_items.each do |key, value|
820
- if value and value.to_array
821
- csv << [key] + value.to_array
835
+ if value&.to_array
836
+ csv << [key] + value.to_array
822
837
  else
823
838
  puts "key #{key.inspect} WITHOUT #{value.inspect}"
824
839
  end
825
840
  end
826
841
  end
827
- Oddb2xml.add_hash(_builder.to_xml)
842
+ Oddb2xml.add_hash(a_builder.to_xml)
828
843
  end
829
844
 
830
845
  def build_article
@@ -834,21 +849,20 @@ module Oddb2xml
834
849
  idx = 0
835
850
  nbr_records = 0
836
851
  Oddb2xml.log "build_article #{idx} of #{@articles.size} articles"
837
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
852
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
838
853
  xml.doc.tag_suffix = @tag_suffix
839
- datetime = Time.new.strftime('%FT%T%z')
840
- eans_from_refdata = @articles.collect{|refdata| refdata[:ean13] }
854
+ eans_from_refdata = @articles.collect { |refdata| refdata[:ean13] }
841
855
  eans_from_preparations = @items.keys
842
856
  missing_eans = []
843
857
  eans_from_preparations.each do |ean|
844
858
  next if ean.to_i == 0
845
- unless @articles.collect {|x| x[:ean13] }.index(ean)
859
+ unless @articles.collect { |x| x[:ean13] }.index(ean)
846
860
  item = @items[ean].clone
847
- item[:pharmacode] ||= '123456' if defined?(RSpec)
861
+ item[:pharmacode] ||= "123456" if defined?(RSpec)
848
862
  item[:ean13] = ean
849
863
  item[:_type] = :preparations_xml
850
- item[:desc_de] = item[:name_de] + ' ' + item[:desc_de]
851
- item[:desc_fr] = item[:name_fr] + ' ' + item[:desc_fr]
864
+ item[:desc_de] = item[:name_de] + " " + item[:desc_de]
865
+ item[:desc_fr] = item[:name_fr] + " " + item[:desc_fr]
852
866
  @articles << item
853
867
  end
854
868
  unless eans_from_refdata.index(ean)
@@ -856,166 +870,166 @@ module Oddb2xml
856
870
  end
857
871
  end
858
872
  xml.ARTICLE(XML_OPTIONS) {
859
- @articles.sort! { |a,b| a[:ean13] <=> b[:ean13] }
860
- @articles.each do |obj|
861
- idx += 1
862
- Oddb2xml.log "build_article #{obj[:ean13]}: #{idx} of #{@articles.size} articles" if idx % 500 == 0
863
- item = @items[obj[:ean13]]
864
- pac,no8 = nil,obj[:ean13].to_s[4..11] # BAG-XML(SL/LS)
873
+ @articles.sort! { |a, b| a[:ean13] <=> b[:ean13] }
874
+ @articles.each do |obj|
875
+ idx += 1
876
+ Oddb2xml.log "build_article #{obj[:ean13]}: #{idx} of #{@articles.size} articles" if idx % 500 == 0
877
+ pac, no8 = nil, obj[:ean13].to_s[4..11] # BAG-XML(SL/LS)
865
878
  pack_info = nil
866
879
  pack_info = @packs[no8] if no8 # info from Packungen.xlsx from swissmedic_info
867
- ppac = nil # Packungen
880
+ ppac = nil # Packungen
868
881
  ean = obj[:ean13]
869
- next if pack_info and /Tierarzneimittel/.match(pack_info[:list_code])
870
- next if obj[:desc_de] and /ad us vet/i.match(obj[:desc_de])
882
+ next if pack_info && /Tierarzneimittel/.match(pack_info[:list_code])
883
+ next if obj[:desc_de] && /ad us vet/i.match(obj[:desc_de])
871
884
  pharma_code = obj[:pharmacode]
872
885
  # ean = 0 if sprintf('%013d', ean).match(/^000000/)
873
886
  if obj[:seq]
874
887
  pac = obj[:seq][:packages][obj[:pharmacode]]
875
- pac = obj[:seq][:packages][ean] unless pac
876
- else
877
- pac = @items[ean][:packages][ean] if @items and ean and @items[ean] and @items[ean][:packages]
888
+ pac ||= obj[:seq][:packages][ean]
889
+ elsif @items && ean && @items[ean] && @items[ean][:packages]
890
+ pac = @items[ean][:packages][ean]
878
891
  end
879
892
  if no8
880
- ppac = ((_ppac = pack_info and !_ppac[:is_tier]) ? _ppac : nil)
893
+ ppac = ((a_ppac = pack_info) && !a_ppac[:is_tier] ? a_ppac : nil)
881
894
  end
882
895
  zur_rose = nil
883
896
  if !@infos_zur_rose.empty? && ean && @infos_zur_rose[ean]
884
897
  zur_rose = @infos_zur_rose[ean] # zurrose
885
898
  end
886
- xml.ART('DT' => obj[:last_change] ? obj[:last_change] : '') do
899
+ xml.ART("DT" => obj[:last_change] || "") do
887
900
  nbr_records += 1
888
- xml.REF_DATA (obj[:refdata] || @migel[pharma_code]) ? '1' : '0'
901
+ # Ignore Lint/RequireParentheses warning on next line!
902
+ xml.REF_DATA obj[:refdata] || @migel[pharma_code] ? "1" : "0"
889
903
  if obj[:pharmacode] && obj[:pharmacode].length > 0
890
- xml.PHAR obj[:pharmacode]
904
+ xml.PHAR obj[:pharmacode]
891
905
  elsif zur_rose
892
906
  puts "Adding #{zur_rose[:pharmacode]} to article GTIN #{ean}"
893
- xml.PHAR zur_rose[:pharmacode]
907
+ xml.PHAR zur_rose[:pharmacode]
894
908
  end
895
- #xml.GRPCD
896
- #xml.CDS01
897
- #xml.CDS02
909
+ # xml.GRPCD
910
+ # xml.CDS01
911
+ # xml.CDS02
898
912
  if ppac
899
- xml.SMCAT ppac[:swissmedic_category] unless ppac[:swissmedic_category].empty?
900
- xml.GEN_PRODUCTION ppac[:gen_production] unless ppac[:gen_production].empty?
901
- xml.INSULIN_CATEGORY ppac[:insulin_category] unless ppac[:insulin_category].empty?
902
- xml.DRUG_INDEX ppac[:drug_index] unless ppac[:drug_index].empty?
913
+ xml.SMCAT ppac[:swissmedic_category] unless ppac[:swissmedic_category].empty?
914
+ xml.GEN_PRODUCTION ppac[:gen_production] unless ppac[:gen_production].empty?
915
+ xml.INSULIN_CATEGORY ppac[:insulin_category] unless ppac[:insulin_category].empty?
916
+ xml.DRUG_INDEX ppac[:drug_index] unless ppac[:drug_index].empty?
903
917
  end
904
- if no8 and !no8.to_s.empty?
905
- if ean and ean.to_s[0..3] == "7680"
918
+ if no8 && !no8.to_s.empty?
919
+ if ean && (ean.to_s[0..3] == "7680")
906
920
  xml.SMNO no8.to_s
907
921
  end
908
922
  end
909
923
  if ppac
910
- xml.PRODNO ppac[:prodno] if ppac[:prodno] and !ppac[:prodno].empty?
924
+ xml.PRODNO ppac[:prodno] if ppac[:prodno] && !ppac[:prodno].empty?
911
925
  end
912
- #xml.HOSPCD
913
- #xml.CLINCD
914
- #xml.ARTTYP
926
+ # xml.HOSPCD
927
+ # xml.CLINCD
928
+ # xml.ARTTYP
915
929
  if zur_rose
916
930
  xml.VAT zur_rose[:vat]
917
931
  end
918
932
  emit_salecd(xml, ean, obj)
919
- if pac and pac[:limitation_points]
920
- #xml.INSLIM
933
+ if pac && pac[:limitation_points]
934
+ # xml.INSLIM
921
935
  xml.LIMPTS pac[:limitation_points] unless pac[:limitation_points].empty?
922
936
  end
923
- #xml.GRDFR
937
+ # xml.GRDFR
924
938
  xml.COOL 1 if ppac && /Blutprodukte|impfstoffe/.match(ppac[:list_code])
925
- #xml.TEMP
939
+ # xml.TEMP
926
940
  if ean
927
- flag = (ppac && !ppac[:drug_index].empty?) ? true : false
941
+ flag = ppac && !ppac[:drug_index].empty? ? true : false
928
942
  # as same flag
929
- xml.CDBG(flag ? 'Y' : 'N')
930
- xml.BG(flag ? 'Y' : 'N')
943
+ xml.CDBG(flag ? "Y" : "N")
944
+ xml.BG(flag ? "Y" : "N")
931
945
  end
932
- #xml.EXP
933
- if item and item[:substances] and substance = item[:substances].first
934
- xml.QTY "#{substance[:quantity]}#{substance[:unit] ? ' ' + substance[:unit] : ''}"
935
- end if false # TODO: get qty/unit from refdata name
936
- xml.DSCRD obj[:desc_de] if obj[:desc_de] and not obj[:desc_de].empty?
937
- xml.DSCRF obj[:desc_fr] if obj[:desc_fr] and not obj[:desc_fr].empty?
938
- xml.DSCRF obj[:desc_de] if !obj[:desc_fr] or obj[:desc_fr].empty?
939
- xml.SORTD obj[:desc_de].upcase if obj[:desc_de] and not obj[:desc_de].empty?
940
- xml.SORTF obj[:desc_fr].upcase if obj[:desc_fr] and not obj[:desc_fr].empty?
941
- xml.SORTF obj[:desc_de].upcase if !obj[:desc_fr] or obj[:desc_fr].empty?
942
- #xml.QTYUD
943
- #xml.QTYUF
944
- #xml.IMG
945
- #xml.IMG2
946
- #xml.PCKTYPD
947
- #xml.PCKTYPF
948
- #xml.MULT
946
+ xml.DSCRD obj[:desc_de] if obj[:desc_de] && !obj[:desc_de].empty?
947
+ xml.DSCRF obj[:desc_fr] if obj[:desc_fr] && !obj[:desc_fr].empty?
948
+ xml.DSCRF obj[:desc_de] if !obj[:desc_fr] || obj[:desc_fr].empty?
949
+ xml.SORTD obj[:desc_de].upcase if obj[:desc_de] && !obj[:desc_de].empty?
950
+ xml.SORTF obj[:desc_fr].upcase if obj[:desc_fr] && !obj[:desc_fr].empty?
951
+ xml.SORTF obj[:desc_de].upcase if !obj[:desc_fr] || obj[:desc_fr].empty?
952
+ # xml.QTYUD
953
+ # xml.QTYUF
954
+ # xml.IMG
955
+ # xml.IMG2
956
+ # xml.PCKTYPD
957
+ # xml.PCKTYPF
958
+ # xml.MULT
949
959
  if obj[:seq]
950
960
  xml.SYN1D obj[:seq][:name_de] unless obj[:seq][:name_de].empty?
951
961
  xml.SYN1F obj[:seq][:name_fr] unless obj[:seq][:name_fr].empty?
952
962
  end
953
963
  if obj[:seq]
954
964
  case obj[:seq][:deductible]
955
- when 'Y'; xml.SLOPLUS 1; # 20%
956
- when 'N'; xml.SLOPLUS 2; # 10%
957
- else xml.SLOPLUS '' # k.A.
965
+ when "Y" then xml.SLOPLUS 1; # 20%
966
+ when "N" then xml.SLOPLUS 2; # 10%
967
+ else xml.SLOPLUS "" # k.A.
958
968
  end
959
969
  end
960
- #xml.NOPCS
961
- #xml.HSCD
962
- #xml.MINI
963
- #xml.DEPCD
964
- #xml.DEPOT
965
- #xml.BAGSL
966
- #xml.BAGSLC
967
- #xml.LOACD
970
+ # xml.NOPCS
971
+ # xml.HSCD
972
+ # xml.MINI
973
+ # xml.DEPCD
974
+ # xml.DEPOT
975
+ # xml.BAGSL
976
+ # xml.BAGSLC
977
+ # xml.LOACD
968
978
  if obj[:stat_date]
969
- xml.OUTSAL obj[:stat_date] if obj[:stat_date] and not obj[:stat_date].empty?
979
+ xml.OUTSAL obj[:stat_date] if obj[:stat_date] && !obj[:stat_date].empty?
970
980
  end
971
- #xml.STTOX
972
- #xml.NOTI
973
- #xml.GGL
974
- #xml.CE
975
- #xml.SMDAT
976
- #xml.SMCDAT
977
- #xml.SIST
978
- #xml.ESIST
979
- #xml.BIOCID
980
- #xml.BAGNO
981
- #xml.LIGHT
982
- #xml.DEL
981
+ # xml.STTOX
982
+ # xml.NOTI
983
+ # xml.GGL
984
+ # xml.CE
985
+ # xml.SMDAT
986
+ # xml.SMCDAT
987
+ # xml.SIST
988
+ # xml.ESIST
989
+ # xml.BIOCID
990
+ # xml.BAGNO
991
+ # xml.LIGHT
992
+ # xml.DEL
983
993
  xml.ARTCOMP {
984
994
  # use ean13(gln) as COMPNO
985
- xml.COMPNO obj[:company_ean] if obj[:company_ean] and obj[:company_ean].to_s.length > 1
986
- #xml.ROLE
987
- #xml.ARTNO1
988
- #xml.ARTNO2
989
- #xml.ARTNO3
995
+ xml.COMPNO obj[:company_ean] if obj[:company_ean] && (obj[:company_ean].to_s.length > 1)
996
+ # xml.ROLE
997
+ # xml.ARTNO1
998
+ # xml.ARTNO2
999
+ # xml.ARTNO3
990
1000
  }
991
- xml.ARTBAR {
992
- xml.CDTYP 'E13'
993
- xml.BC ean # /^9999|^0000|^0$/.match(ean.to_s) ? 0 : sprintf('%013d', ean)
994
- xml.BCSTAT 'A' # P is alternative
995
- } if ean
996
- if pac and pac[:prices]
1001
+ if ean
1002
+ xml.ARTBAR {
1003
+ xml.CDTYP "E13"
1004
+ xml.BC ean # /^9999|^0000|^0$/.match(ean.to_s) ? 0 : sprintf('%013d', ean)
1005
+ xml.BCSTAT "A" # P is alternative
1006
+ }
1007
+ end
1008
+ if pac && pac[:prices]
997
1009
  pac[:prices].each_pair do |key, price|
998
1010
  xml.ARTPRI {
999
- xml.VDAT price[:valid_date] unless price[:valid_date].empty?
1000
- xml.PTYP price[:price_code] unless price[:price_code].empty?
1001
- xml.PRICE price[:price] unless price[:price].empty?
1011
+ xml.VDAT price[:valid_date] unless price[:valid_date].empty?
1012
+ xml.PTYP price[:price_code] unless price[:price_code].empty?
1013
+ xml.PRICE price[:price] unless price[:price].empty?
1002
1014
  }
1003
1015
  end
1004
1016
  end
1005
1017
  if zur_rose
1006
1018
  price = zur_rose[:price]
1007
1019
  xml.ARTPRI {
1008
- xml.PTYP "ZURROSE"
1020
+ xml.PTYP "ZURROSE"
1009
1021
  xml.PRICE price
1010
1022
  }
1011
1023
  xml.ARTPRI {
1012
- xml.PTYP "ZURROSEPUB"
1024
+ xml.PTYP "ZURROSEPUB"
1013
1025
  xml.PRICE zur_rose[:pub_price]
1014
1026
  }
1015
- xml.ARTPRI {
1016
- xml.PTYP "RESELLERPUB"
1017
- xml.PRICE (price.to_f*(1 + (@options[:percent].to_f/100))).round_by(0.05).round(2)
1018
- } if @options[:percent] != nil
1027
+ unless @options[:percent].nil?
1028
+ xml.ARTPRI {
1029
+ xml.PTYP "RESELLERPUB"
1030
+ xml.PRICE (price.to_f * (1 + (@options[:percent].to_f / 100))).round_by(0.05).round(2)
1031
+ }
1032
+ end
1019
1033
  end
1020
1034
  nincd = detect_nincd(obj)
1021
1035
  if nincd
@@ -1026,29 +1040,29 @@ module Oddb2xml
1026
1040
  end
1027
1041
  end
1028
1042
  xml.RESULT {
1029
- xml.OK_ERROR 'OK'
1043
+ xml.OK_ERROR "OK"
1030
1044
  xml.NBR_RECORD nbr_records
1031
- xml.ERROR_CODE ''
1032
- xml.MESSAGE ''
1045
+ xml.ERROR_CODE ""
1046
+ xml.MESSAGE ""
1033
1047
  }
1034
1048
  }
1035
1049
  end
1036
1050
  Oddb2xml.log "build_article. Done #{idx} of #{@articles.size} articles. Overrode #{@overriden_salecd.size} SALECD"
1037
- Oddb2xml.add_hash(_builder.to_xml)
1051
+ Oddb2xml.add_hash(a_builder.to_xml)
1038
1052
  end
1053
+
1039
1054
  def build_fi
1040
1055
  nbr_records = 0
1041
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
1056
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
1042
1057
  xml.doc.tag_suffix = @tag_suffix
1043
- datetime = Time.new.strftime('%FT%T%z')
1044
1058
  xml.KOMPENDIUM(XML_OPTIONS) {
1045
1059
  %w[de fr].each do |lang|
1046
- infos = @infos[lang].uniq {|i| i[:monid] }
1060
+ infos = @infos[lang].uniq { |i| i[:monid] }
1047
1061
  infos.each do |info|
1048
1062
  xml.KMP(
1049
- 'MONTYPE' => 'fi', # only
1050
- 'LANG' => lang.upcase,
1051
- 'DT' => ''
1063
+ "MONTYPE" => "fi", # only
1064
+ "LANG" => lang.upcase,
1065
+ "DT" => ""
1052
1066
  ) {
1053
1067
  unless info[:name].empty?
1054
1068
  xml.name info[:name]
@@ -1056,29 +1070,29 @@ module Oddb2xml
1056
1070
  unless info[:owner].empty?
1057
1071
  xml.owner info[:owner]
1058
1072
  end
1059
- xml.monid info[:monid] unless info[:monid].empty?
1073
+ xml.monid info[:monid] unless info[:monid].empty?
1060
1074
  xml.style { xml.cdata(info[:style]) } if info[:style]
1061
- xml.paragraph { xml.cdata(Nokogiri::HTML.fragment(info[:paragraph].to_html).to_html(:encoding => 'UTF-8')) } if info[:paragraph]
1075
+ xml.paragraph { xml.cdata(Nokogiri::HTML.fragment(info[:paragraph].to_html).to_html(encoding: "UTF-8")) } if info[:paragraph]
1062
1076
  nbr_records += 1
1063
1077
  }
1064
1078
  end
1065
1079
  end
1066
1080
  xml.RESULT {
1067
- xml.OK_ERROR 'OK'
1081
+ xml.OK_ERROR "OK"
1068
1082
  xml.NBR_RECORD nbr_records
1069
- xml.ERROR_CODE ''
1070
- xml.MESSAGE ''
1083
+ xml.ERROR_CODE ""
1084
+ xml.MESSAGE ""
1071
1085
  }
1072
1086
  }
1073
1087
  end
1074
- Oddb2xml.add_hash(_builder.to_xml)
1088
+ Oddb2xml.add_hash(a_builder.to_xml)
1075
1089
  end
1090
+
1076
1091
  def build_fi_product
1077
1092
  prepare_products
1078
1093
  nbr_records = 0
1079
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
1094
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
1080
1095
  xml.doc.tag_suffix = @tag_suffix
1081
- datetime = Time.new.strftime('%FT%T%z')
1082
1096
  xml.KOMPENDIUM_PRODUCT(XML_OPTIONS) {
1083
1097
  info_index = {}
1084
1098
  %w[de fr].each do |lang|
@@ -1087,556 +1101,581 @@ module Oddb2xml
1087
1101
  end
1088
1102
  # prod
1089
1103
  @products.each do |ean13, prod|
1090
- next unless prod[:seq] and prod[:seq][:packages]
1104
+ next unless prod[:seq] && prod[:seq][:packages]
1091
1105
  seq = prod[:seq]
1092
- prod[:seq][:packages].each {
1093
- |phar, package|
1094
- next unless package[:swissmedic_number8]
1095
- m = /(\d{5})(\d{3})/.match(package[:swissmedic_number8])
1096
- next unless m
1097
- number = m[1].to_s
1098
- idx = info_index[number]
1099
- next unless idx
1100
- xml.KP('DT' => '') {
1101
- xml.MONID @infos[lang][idx][:monid]
1102
- xml.PRDNO seq[:product_key] unless seq[:product_key].empty?
1103
- # as orphan ?
1104
- xml.DEL @orphan.include?(number) ? true : false
1105
- nbr_records += 1
1106
- }
1107
- }
1108
- end
1106
+ prod[:seq][:packages].each { |phar, package|
1107
+ next unless package[:swissmedic_number8]
1108
+ m = /(\d{5})(\d{3})/.match(package[:swissmedic_number8])
1109
+ next unless m
1110
+ number = m[1].to_s
1111
+ idx = info_index[number]
1112
+ next unless idx
1113
+ xml.KP("DT" => "") {
1114
+ xml.MONID @infos[lang][idx][:monid]
1115
+ xml.PRDNO seq[:product_key] unless seq[:product_key].empty?
1116
+ # as orphan ?
1117
+ xml.DEL @orphan.include?(number) ? true : false
1118
+ nbr_records += 1
1119
+ }
1120
+ }
1109
1121
  end
1122
+ end
1110
1123
  xml.RESULT {
1111
- xml.OK_ERROR 'OK'
1124
+ xml.OK_ERROR "OK"
1112
1125
  xml.NBR_RECORD nbr_records
1113
- xml.ERROR_CODE ''
1114
- xml.MESSAGE ''
1126
+ xml.ERROR_CODE ""
1127
+ xml.MESSAGE ""
1115
1128
  }
1116
1129
  }
1117
1130
  end
1118
- Oddb2xml.add_hash(_builder.to_xml)
1131
+ Oddb2xml.add_hash(a_builder.to_xml)
1119
1132
  end
1133
+
1120
1134
  def build_company
1121
1135
  nbr_records = 0
1122
1136
  Oddb2xml.log "build_company #{@companies.size} companies"
1123
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
1137
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
1124
1138
  xml.doc.tag_suffix = @tag_suffix
1125
- datetime = Time.new.strftime('%FT%T%z')
1126
1139
  xml.Betriebe(XML_OPTIONS) {
1127
1140
  @companies.each do |c|
1128
- xml.Betrieb('DT' => '') {
1129
- xml.GLN_Betrieb c[:gln] unless c[:gln].empty?
1130
- xml.Betriebsname_1 c[:name_1] unless c[:name_1].empty?
1131
- xml.Betriebsname_2 c[:name_2] unless c[:name_2].empty?
1132
- xml.Strasse c[:address] unless c[:address].empty?
1133
- xml.Nummer c[:number] unless c[:number].empty?
1134
- xml.PLZ c[:post] unless c[:post].empty?
1135
- xml.Ort c[:place] unless c[:place].empty?
1136
- xml.Bewilligungskanton c[:region] unless c[:region].empty?
1137
- xml.Land c[:country] unless c[:country].empty?
1138
- xml.Betriebstyp c[:type] unless c[:type].empty?
1139
- xml.BTM_Berechtigung c[:authorization] unless c[:authorization].empty?
1141
+ xml.Betrieb("DT" => "") {
1142
+ xml.GLN_Betrieb c[:gln] unless c[:gln].empty?
1143
+ xml.Betriebsname_1 c[:name_1] unless c[:name_1].empty?
1144
+ xml.Betriebsname_2 c[:name_2] unless c[:name_2].empty?
1145
+ xml.Strasse c[:address] unless c[:address].empty?
1146
+ xml.Nummer c[:number] unless c[:number].empty?
1147
+ xml.PLZ c[:post] unless c[:post].empty?
1148
+ xml.Ort c[:place] unless c[:place].empty?
1149
+ xml.Bewilligungskanton c[:region] unless c[:region].empty?
1150
+ xml.Land c[:country] unless c[:country].empty?
1151
+ xml.Betriebstyp c[:type] unless c[:type].empty?
1152
+ xml.BTM_Berechtigung c[:authorization] unless c[:authorization].empty?
1140
1153
  nbr_records += 1
1141
1154
  }
1142
1155
  end
1143
1156
  xml.RESULT {
1144
- xml.OK_ERROR 'OK'
1157
+ xml.OK_ERROR "OK"
1145
1158
  xml.NBR_RECORD nbr_records
1146
- xml.ERROR_CODE ''
1147
- xml.MESSAGE ''
1159
+ xml.ERROR_CODE ""
1160
+ xml.MESSAGE ""
1148
1161
  }
1149
1162
  }
1150
1163
  end
1151
- Oddb2xml.add_hash(_builder.to_xml)
1164
+ Oddb2xml.add_hash(a_builder.to_xml)
1152
1165
  end
1166
+
1153
1167
  def build_person
1154
1168
  nbr_records = 0
1155
1169
  Oddb2xml.log "build_person #{@people.size} persons"
1156
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
1170
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
1157
1171
  xml.doc.tag_suffix = @tag_suffix
1158
- datetime = Time.new.strftime('%FT%T%z')
1159
1172
  xml.Personen(XML_OPTIONS) {
1160
1173
  @people.each do |p|
1161
- xml.Person('DT' => '') {
1162
- xml.GLN_Person p[:gln] unless p[:gln].empty?
1163
- xml.Name p[:last_name] unless p[:last_name].empty?
1164
- xml.Vorname p[:first_name] unless p[:first_name].empty?
1165
- xml.PLZ p[:post] unless p[:post].empty?
1166
- xml.Ort p[:place] unless p[:place].empty?
1167
- xml.Bewilligungskanton p[:region] unless p[:region].empty?
1168
- xml.Land p[:country] unless p[:country].empty?
1174
+ xml.Person("DT" => "") {
1175
+ xml.GLN_Person p[:gln] unless p[:gln].empty?
1176
+ xml.Name p[:last_name] unless p[:last_name].empty?
1177
+ xml.Vorname p[:first_name] unless p[:first_name].empty?
1178
+ xml.PLZ p[:post] unless p[:post].empty?
1179
+ xml.Ort p[:place] unless p[:place].empty?
1180
+ xml.Bewilligungskanton p[:region] unless p[:region].empty?
1181
+ xml.Land p[:country] unless p[:country].empty?
1169
1182
  xml.Bewilligung_Selbstdispensation p[:license] unless p[:license].empty?
1170
- xml.Diplom p[:certificate] unless p[:certificate].empty?
1171
- xml.BTM_Berechtigung p[:authorization] unless p[:authorization].empty?
1183
+ xml.Diplom p[:certificate] unless p[:certificate].empty?
1184
+ xml.BTM_Berechtigung p[:authorization] unless p[:authorization].empty?
1172
1185
  nbr_records += 1
1173
1186
  }
1174
1187
  end
1175
1188
  xml.RESULT {
1176
- xml.OK_ERROR 'OK'
1189
+ xml.OK_ERROR "OK"
1177
1190
  xml.NBR_RECORD nbr_records
1178
- xml.ERROR_CODE ''
1179
- xml.MESSAGE ''
1191
+ xml.ERROR_CODE ""
1192
+ xml.MESSAGE ""
1180
1193
  }
1181
1194
  }
1182
1195
  end
1183
- Oddb2xml.add_hash(_builder.to_xml)
1196
+ Oddb2xml.add_hash(a_builder.to_xml)
1184
1197
  end
1198
+
1185
1199
  def detect_nincd(de_idx)
1186
1200
  if @lppvs[de_idx[:ean13].to_s] # LPPV
1187
1201
  20
1188
1202
  elsif @items[de_idx[:pharmacode]] # BAG-XML (SL/LS)
1189
1203
  10
1190
- elsif (de_idx[:migel] or # MiGel (xls)
1191
- de_idx[:_type] == :nonpharma) # MiGel (swissindex)
1204
+ elsif de_idx[:migel] || # MiGel (xls)
1205
+ (de_idx[:_type] == :nonpharma) # MiGel (swissindex)
1192
1206
  13
1193
1207
  else
1194
1208
  # fallback via EAN
1195
1209
  bag_entry_via_ean = @items.values.select do |item|
1196
1210
  next unless item[:packages]
1197
- item[:packages].values.select {|_pac| _pac[:ean13].to_s.eql?(de_idx[:ean13].to_s) }.length != 0
1211
+ item[:packages].values.count { |a_pac| a_pac[:ean13].to_s.eql?(de_idx[:ean13].to_s) } != 0
1198
1212
  end
1199
1213
  if bag_entry_via_ean.length > 0
1200
1214
  10
1201
- else
1202
- nil
1203
1215
  end
1204
1216
  end
1205
1217
  end
1206
1218
 
1207
1219
  ### --- see oddb2tdat
1208
1220
  DAT_LEN = {
1209
- :RECA => 2,
1210
- :CMUT => 1,
1211
- :PHAR => 7,
1212
- :ABEZ => 50,
1213
- :PRMO => 6,
1214
- :PRPU => 6,
1215
- :CKZL => 1,
1216
- :CLAG => 1,
1217
- :CBGG => 1,
1218
- :CIKS => 1,
1219
- :ITHE => 7,
1220
- :CEAN => 13,
1221
- :CMWS => 1,
1221
+ RECA: 2,
1222
+ CMUT: 1,
1223
+ PHAR: 7,
1224
+ ABEZ: 50,
1225
+ PRMO: 6,
1226
+ PRPU: 6,
1227
+ CKZL: 1,
1228
+ CLAG: 1,
1229
+ CBGG: 1,
1230
+ CIKS: 1,
1231
+ ITHE: 7,
1232
+ CEAN: 13,
1233
+ CMWS: 1
1222
1234
  }
1223
- def format_price(price_str, len=6, int_len=4, frac_len=2)
1224
- price = price_str.split('.')
1225
- pre = ''
1226
- las = ''
1227
- pre = "%0#{int_len}d" % (price[0] ? price[0] : '0')
1235
+ def format_price(price_str, len = 6, int_len = 4, frac_len = 2)
1236
+ price = price_str.split(".")
1237
+ pre = "%0#{int_len}d" % (price[0] || "0")
1228
1238
  las = if price[1]
1229
- if price[1].size < frac_len
1230
- price[1] + "0"*(frac_len-price[2].to_s.size)
1231
- else
1232
- price[1][0,frac_len]
1233
- end
1234
- else
1235
- '0'*frac_len
1236
- end
1237
- (pre.to_s + las.to_s)[0,len]
1239
+ if price[1].size < frac_len
1240
+ price[1] + "0" * (frac_len - price[2].to_s.size)
1241
+ else
1242
+ price[1][0, frac_len]
1243
+ end
1244
+ else
1245
+ "0" * frac_len
1246
+ end
1247
+ (pre.to_s + las.to_s)[0, len]
1238
1248
  end
1239
- def format_date(date_str, len=7)
1240
- date = date_str.gsub('.','')
1249
+
1250
+ def format_date(date_str, len = 7)
1251
+ date = date_str.delete(".")
1241
1252
  if date.size < len
1242
- date = date + '0'*(len-date.size)
1253
+ date += "0" * (len - date.size)
1243
1254
  end
1244
- date[0,len]
1255
+ date[0, len]
1245
1256
  end
1246
1257
 
1247
1258
  # The migel name must be always 50 chars wide and in ISO 8859-1 format
1248
1259
  def format_name(name, length)
1249
- ("%-#{length}s" % name)[0..length-1]
1260
+ ("%-#{length}s" % name)[0..length - 1]
1250
1261
  end
1262
+
1251
1263
  def build_dat
1252
1264
  prepare_articles
1253
1265
  rows = []
1254
1266
  @articles.each do |obj|
1255
- ean = obj[:ean13]
1256
- next if ((ean.to_s.length != 13) and !ean14)
1257
- next if obj[:type] == :nonpharma
1258
- row = ''
1259
- pack_info = nil
1260
- if (x = @packs.find{|k,v| v[:ean13].eql?(ean)})
1261
- pack_info = x[1]
1262
- end
1263
- # Oddb2tdat.parse
1264
- pac,no8 = nil,nil
1265
- if obj[:seq] and obj[:seq][:packages]
1266
- pac = obj[:seq][:packages][obj[:pharmacode]]
1267
- pac = obj[:seq][:packages][ean] unless pac
1268
- else
1269
- pac = @items[ean][:packages][ean] if @items and @items[ean] and @items[ean][:packages]
1270
- end
1271
- # :swissmedic_numbers
1272
- if pac
1273
- no8 = pac[:swissmedic_number8]
1274
- end
1275
- if pac and pac[:prices] == nil and no8
1276
- ppac = ((ppac = pack_info and ppac[:is_tier]) ? ppac : nil)
1277
- pac = ppac if ppac
1278
- end
1279
- row << "%#{DAT_LEN[:RECA]}s" % '11'
1280
- zur_rose = @infos_zur_rose[ean] # zurrose
1281
- if zur_rose && zur_rose[:cmut]
1282
- row << zur_rose[:cmut]
1283
- else
1284
- row << '1'
1285
- end
1286
- row << "%0#{DAT_LEN[:PHAR]}d" % obj[:pharmacode].to_i
1287
- abez = ( # de name
1288
- obj[:desc_de].to_s + " " +
1289
- (pac ? pac[:name_de].to_s : '') +
1290
- (obj[:quantity] ? obj[:quantity] : '')
1291
- ).gsub(/"/, '')
1292
- if @infos_zur_rose[ean]
1293
- price_exf = sprintf('%06i', ((@infos_zur_rose[ean][:price].to_f)*100).to_i)
1294
- price_public = sprintf('%06i', ((@infos_zur_rose[ean][:pub_price].to_f)*100).to_i)
1295
- if @options[:percent] != nil
1296
- price_public = sprintf('%06i', (price_exf.to_f*(1 + (@options[:percent].to_f/100))).round_by(0.05).round(2))
1297
- end
1298
- elsif pac and pac[:prices]
1299
- price_exf = sprintf('%06i', (pac[:prices][:exf_price][:price].to_f*100).to_i) if pac[:prices][:exf_price] and pac[:prices][:exf_price][:price]
1300
- price_public = sprintf('%06i', (pac[:prices][:pub_price][:price].to_f*100).to_i) if pac[:prices][:pub_price] and pac[:prices][:pub_price][:price]
1301
- end
1302
- row << format_name(Oddb2xml.patch_some_utf8(abez), DAT_LEN[:ABEZ])
1303
- if price_exf.to_s.length > DAT_LEN[:PRMO] ||
1304
- price_public.to_s.length > DAT_LEN[:PRPU]
1305
- puts "Price exfactory #{price_exf} or public #{price_public} is too high to be added into transfer.dat"
1306
- break
1267
+ ean = obj[:ean13]
1268
+ next if (ean.to_s.length != 13) && !ean14
1269
+ next if obj[:type] == :nonpharma
1270
+ row = ""
1271
+ pack_info = nil
1272
+ if (x = @packs.find { |k, v| v[:ean13].eql?(ean) })
1273
+ pack_info = x[1]
1274
+ end
1275
+ # Oddb2tdat.parse
1276
+ pac, no8 = nil, nil
1277
+ if obj[:seq] && obj[:seq][:packages]
1278
+ pac = obj[:seq][:packages][obj[:pharmacode]]
1279
+ pac ||= obj[:seq][:packages][ean]
1280
+ elsif @items && @items[ean] && @items[ean][:packages]
1281
+ pac = @items[ean][:packages][ean]
1282
+ end
1283
+ # :swissmedic_numbers
1284
+ if pac
1285
+ no8 = pac[:swissmedic_number8]
1286
+ end
1287
+ if pac && pac[:prices].nil? && no8
1288
+ ppac = ((ppac = pack_info) && ppac[:is_tier] ? ppac : nil)
1289
+ pac = ppac if ppac
1290
+ end
1291
+ row << "%#{DAT_LEN[:RECA]}s" % "11"
1292
+ zur_rose = @infos_zur_rose[ean] # zurrose
1293
+ row << if zur_rose && zur_rose[:cmut]
1294
+ zur_rose[:cmut]
1295
+ else
1296
+ "1"
1297
+ end
1298
+ row << "%0#{DAT_LEN[:PHAR]}d" % obj[:pharmacode].to_i
1299
+ abez = ( # de name
1300
+ obj[:desc_de].to_s + " " +
1301
+ (pac ? pac[:name_de].to_s : "") +
1302
+ (obj[:quantity] || "")
1303
+ ).delete('"')
1304
+ if @infos_zur_rose[ean]
1305
+ price_exf = sprintf("%06i", (@infos_zur_rose[ean][:price].to_f * 100).to_i)
1306
+ price_public = sprintf("%06i", (@infos_zur_rose[ean][:pub_price].to_f * 100).to_i)
1307
+ if !@options[:percent].nil?
1308
+ price_public = sprintf("%06i", (price_exf.to_f * (1 + (@options[:percent].to_f / 100))).round_by(0.05).round(2))
1307
1309
  end
1308
- row << "%#{DAT_LEN[:PRMO]}s" % (price_exf ? price_exf.to_s : ('0' * DAT_LEN[:PRMO]))
1309
- row << "%#{DAT_LEN[:PRPU]}s" % (price_public ? price_public.to_s : ('0' * DAT_LEN[:PRPU]))
1310
- row << "%#{DAT_LEN[:CKZL]}s" % if (@lppvs[ean])
1311
- '2'
1312
- elsif pac # sl_entry
1313
- '1'
1314
- else
1315
- '3'
1316
- end
1317
- row << "%#{DAT_LEN[:CLAG]}s" % if ppac && /Blutproduct|impfstoffe/.match(ppac[:list_code]) # COOL
1318
- '1'
1319
- else
1320
- '0'
1321
- end
1322
- row << "%#{DAT_LEN[:CBGG]}s" % if (pack_info && pack_info[:drug_index])
1323
- '3'
1324
- else
1325
- '0'
1326
- end
1327
- row << "%#{DAT_LEN[:CIKS]}s" % if (no8 && pack_info && !pack_info[:is_tier]) # Packungen.xls
1328
- pack_info[:swissmedic_category]
1329
- else
1330
- '0'
1331
- end.gsub(/(\+|\s)/, '')
1332
- row << "%0#{DAT_LEN[:ITHE]}d" % if (no8 && pack_info && !pack_info[:is_tier])
1333
- format_date(pack_info[:ith_swissmedic])
1334
- else
1335
- ('0' * DAT_LEN[:ITHE])
1336
- end.to_i
1337
- row << "%0#{DAT_LEN[:CEAN]}d" % (sprintf('%013d', ean.to_i).match(/^000000/) ? 0 : ean.to_i)
1338
- row << "%#{DAT_LEN[:CMWS]}s" % '2' # pharma
1339
- rows << row
1310
+ elsif pac && pac[:prices]
1311
+ price_exf = sprintf("%06i", (pac[:prices][:exf_price][:price].to_f * 100).to_i) if pac[:prices][:exf_price] && pac[:prices][:exf_price][:price]
1312
+ price_public = sprintf("%06i", (pac[:prices][:pub_price][:price].to_f * 100).to_i) if pac[:prices][:pub_price] && pac[:prices][:pub_price][:price]
1313
+ end
1314
+ row << format_name(Oddb2xml.patch_some_utf8(abez), DAT_LEN[:ABEZ])
1315
+ if price_exf.to_s.length > DAT_LEN[:PRMO] ||
1316
+ price_public.to_s.length > DAT_LEN[:PRPU]
1317
+ puts "Price exfactory #{price_exf} or public #{price_public} is too high to be added into transfer.dat"
1318
+ break
1319
+ end
1320
+ row << "%#{DAT_LEN[:PRMO]}s" % (price_exf ? price_exf.to_s : ("0" * DAT_LEN[:PRMO]))
1321
+ row << "%#{DAT_LEN[:PRPU]}s" % (price_public ? price_public.to_s : ("0" * DAT_LEN[:PRPU]))
1322
+ row << "%#{DAT_LEN[:CKZL]}s" % if @lppvs[ean]
1323
+ "2"
1324
+ elsif pac # sl_entry
1325
+ "1"
1326
+ else
1327
+ "3"
1328
+ end
1329
+ row << "%#{DAT_LEN[:CLAG]}s" % if ppac && /Blutproduct|impfstoffe/.match(ppac[:list_code]) # COOL
1330
+ "1"
1331
+ else
1332
+ "0"
1333
+ end
1334
+ row << "%#{DAT_LEN[:CBGG]}s" % if pack_info && pack_info[:drug_index]
1335
+ "3"
1336
+ else
1337
+ "0"
1338
+ end
1339
+ row << "%#{DAT_LEN[:CIKS]}s" % if no8 && pack_info && !pack_info[:is_tier] # Packungen.xls
1340
+ pack_info[:swissmedic_category]
1341
+ else
1342
+ "0"
1343
+ end.gsub(/(\+|\s)/, "")
1344
+ row << "%0#{DAT_LEN[:ITHE]}d" % if no8 && pack_info && !pack_info[:is_tier]
1345
+ format_date(pack_info[:ith_swissmedic])
1346
+ else
1347
+ ("0" * DAT_LEN[:ITHE])
1348
+ end.to_i
1349
+ row << "%0#{DAT_LEN[:CEAN]}d" % (/^000000/.match?(sprintf("%013d", ean.to_i)) ? 0 : ean.to_i)
1350
+ row << "%#{DAT_LEN[:CMWS]}s" % "2" # pharma
1351
+ rows << row
1340
1352
  end
1341
1353
  rows.join("\n")
1342
1354
  end
1355
+
1343
1356
  def build_with_migel_dat
1344
1357
  reset = true
1345
1358
  prepare_articles(reset)
1346
1359
  rows = []
1347
1360
  @articles.each do |obj|
1348
- row = ''
1349
- next if ((obj[:ean13].to_s.length != 13) and !ean14)
1350
- # Oddb2tdat.parse_migel
1351
- row << "%#{DAT_LEN[:RECA]}s" % '11'
1352
- row << "%#{DAT_LEN[:CMUT]}s" % if (phar = obj[:pharmacode] and phar.size > 3)
1353
- '1'
1354
- else
1355
- '3'
1356
- end
1357
- row << "%0#{DAT_LEN[:PHAR]}d" % obj[:pharmacode].to_i
1358
- abez = ( # de name
1359
- obj[:desc_de].to_s + " " +
1360
- (obj[:quantity] ? obj[:quantity] : '')
1361
- ).gsub(/"/, '')
1362
- row << format_name(Oddb2xml.patch_some_utf8(abez), DAT_LEN[:ABEZ])
1363
- row << '0' * DAT_LEN[:PRMO]
1364
- row << '0' * DAT_LEN[:PRPU]
1365
- row << "%#{DAT_LEN[:CKZL]}s" % '3' # sl_entry and lppv
1366
- row << "%#{DAT_LEN[:CLAG]}s" % '0'
1367
- row << "%#{DAT_LEN[:CBGG]}s" % '0'
1368
- row << "%#{DAT_LEN[:CIKS]}s" % ' ' # no category
1369
- row << "%0#{DAT_LEN[:ITHE]}d" % 0
1370
- row << obj[:ean13].to_s.rjust(DAT_LEN[:CEAN], '0')
1371
- row << "%#{DAT_LEN[:CMWS]}s" % '1' # nonpharma
1372
- rows << row
1373
- end
1361
+ row = ""
1362
+ next if (obj[:ean13].to_s.length != 13) && !ean14
1363
+ # Oddb2tdat.parse_migel
1364
+ row << "%#{DAT_LEN[:RECA]}s" % "11"
1365
+ row << "%#{DAT_LEN[:CMUT]}s" % if (phar = obj[:pharmacode]) && (phar.size > 3)
1366
+ "1"
1367
+ else
1368
+ "3"
1369
+ end
1370
+ row << "%0#{DAT_LEN[:PHAR]}d" % obj[:pharmacode].to_i
1371
+ abez = ( # de name
1372
+ obj[:desc_de].to_s + " " +
1373
+ (obj[:quantity] || "")
1374
+ ).delete('"')
1375
+ row << format_name(Oddb2xml.patch_some_utf8(abez), DAT_LEN[:ABEZ])
1376
+ row << "0" * DAT_LEN[:PRMO]
1377
+ row << "0" * DAT_LEN[:PRPU]
1378
+ row << "%#{DAT_LEN[:CKZL]}s" % "3" # sl_entry and lppv
1379
+ row << "%#{DAT_LEN[:CLAG]}s" % "0"
1380
+ row << "%#{DAT_LEN[:CBGG]}s" % "0"
1381
+ row << "%#{DAT_LEN[:CIKS]}s" % " " # no category
1382
+ row << "%0#{DAT_LEN[:ITHE]}d" % 0
1383
+ row << obj[:ean13].to_s.rjust(DAT_LEN[:CEAN], "0")
1384
+ row << "%#{DAT_LEN[:CMWS]}s" % "1" # nonpharma
1385
+ rows << row
1386
+ end
1374
1387
  rows.join("\n")
1375
1388
  end
1389
+
1376
1390
  def emit_salecd(xml, ean13, obj)
1377
1391
  zur_rose = nil
1378
1392
  if !@infos_zur_rose.empty? && ean13 && @infos_zur_rose[ean13]
1379
1393
  zur_rose = @infos_zur_rose[ean13] # zurrose
1380
1394
  end
1381
1395
  nincd = detect_nincd(obj)
1382
- in_refdata = !!( obj[:seq] && obj[:seq][:packages] && obj[:seq][:packages][ean13] && obj[:seq][:packages][ean13][:swissmedic_number8])
1383
- status = (nincd && nincd == 13) ? 'A' : (zur_rose && zur_rose[:cmut] != '3') ? 'A' : 'I'
1384
- if in_refdata && !'A'.eql?(status)
1396
+ in_refdata = !!(obj[:seq] && obj[:seq][:packages] && obj[:seq][:packages][ean13] && obj[:seq][:packages][ean13][:swissmedic_number8])
1397
+ status = if nincd && nincd == 13
1398
+ "A"
1399
+ else
1400
+ zur_rose && zur_rose[:cmut] != "3" ? "A" : "I"
1401
+ end
1402
+ if in_refdata && !"A".eql?(status)
1385
1403
  msg = "Overriding status #{status} nincd #{nincd} for #{ean13} as in refdata_pharma"
1386
1404
  # Oddb2xml.log msg
1387
1405
  @overriden_salecd << ean13
1388
- xml.SALECD('A') { xml.comment(msg)}
1406
+ xml.SALECD("A") { xml.comment(msg) }
1389
1407
  else
1390
- xml.SALECD(status) { xml.comment( "expiry_date #{obj[:expiry_date]}") if obj[:expiry_date] }
1408
+ xml.SALECD(status) { xml.comment("expiry_date #{obj[:expiry_date]}") if obj[:expiry_date] }
1391
1409
  end
1392
1410
  end
1393
1411
 
1394
1412
  def build_artikelstamm
1395
1413
  @@emitted_v5_gtins = []
1396
- @csv_file = CSV.open(File.join(WorkDir, "artikelstamm_#{Date.today.strftime('%d%m%Y')}_v5.csv"), "w+")
1397
- @csv_file << ['gtin', 'name', 'pkg_size', 'galenic_form', 'price_ex_factory', 'price_public', 'prodno', 'atc_code', 'active_substance', 'original', 'it-code', 'sl-liste']
1414
+ @csv_file = CSV.open(File.join(WORK_DIR, "artikelstamm_#{Date.today.strftime("%d%m%Y")}_v5.csv"), "w+")
1415
+ @csv_file << ["gtin", "name", "pkg_size", "galenic_form", "price_ex_factory", "price_public", "prodno", "atc_code", "active_substance", "original", "it-code", "sl-liste"]
1398
1416
  @csv_file.sync = true
1399
1417
  variant = "build_artikelstamm"
1400
1418
  # @infos_zur_rose.delete_if { |key, val| val[:cmut].eql?('3') } # collect only active zur rose item
1401
1419
  # No. Marco did not filter it, eg. 8804121 in rtikelstamm_oddb2xml_051217_v5.xm
1402
- def check_name(obj, lang = :de)
1403
- ean = obj[:ean13]
1404
- refdata = @refdata[ean]
1405
- if lang == :de
1406
- name = (refdata && refdata[:desc_de]) ? refdata[:desc_de] : obj[:sequence_name]
1407
- elsif lang == :fr
1408
- name = (refdata && refdata[:desc_fr]) ? refdata[:desc_fr] : obj[:sequence_name]
1409
- else
1410
- return '--missing--'
1420
+ self.class.class_eval do
1421
+ def check_article_name(obj, lang = :de)
1422
+ ean = obj[:ean13]
1423
+ refdata = @refdata[ean]
1424
+ if lang == :de
1425
+ name = refdata && refdata[:desc_de] ? refdata[:desc_de] : obj[:sequence_name]
1426
+ elsif lang == :fr
1427
+ name = refdata && refdata[:desc_fr] ? refdata[:desc_fr] : obj[:sequence_name]
1428
+ else
1429
+ return "--missing--"
1430
+ end
1431
+ return "--missing--" if !name || name.empty? || name.length < 3
1432
+ name[0..119] # limit to maximal 120 chars as specified in the XSD
1411
1433
  end
1412
- return '--missing--' if !name || name.empty? || name.length < 3
1413
- name[0..119] # limit to maximal 120 chars as specified in the XSD
1414
1434
  end
1415
- def override(xml, id, field, default_value)
1416
- has_overrides = /\d{13}/.match(id.to_s) ? @@article_overrides[id.to_i] : @@product_overrides[id.to_i]
1417
- unless (has_overrides && has_overrides[field.to_s])
1418
- cmd = "xml.#{field} \"#{default_value.to_s.gsub('"','')}\""
1419
- else
1420
- new_value = has_overrides[field.to_s]
1421
- if new_value.to_s.eql?(default_value.to_s)
1422
- xml.comment('obsolete override')
1435
+ self.class.class_eval do
1436
+ def override(xml, id, field, default_value)
1437
+ has_overrides = /\d{13}/.match?(id.to_s) ? @@article_overrides[id.to_i] : @@product_overrides[id.to_i]
1438
+ if has_overrides && has_overrides[field.to_s]
1439
+ new_value = has_overrides[field.to_s]
1440
+ if new_value.to_s.eql?(default_value.to_s)
1441
+ xml.comment("obsolete override")
1442
+ else
1443
+ xml.comment("override #{default_value} with")
1444
+ end
1423
1445
  cmd = "xml.#{field} \"#{new_value}\""
1424
1446
  else
1425
- xml.comment("override #{default_value.to_s} with")
1426
- cmd ="xml.#{field} \"#{new_value}\""
1447
+ cmd = "xml.#{field} \"#{default_value.to_s.delete('"')}\""
1427
1448
  end
1449
+ eval cmd if default_value
1428
1450
  end
1429
- eval cmd if default_value
1430
1451
  end
1431
- def emit_items(xml)
1432
- nr_items = 0
1433
- gtins_to_article = {}
1434
- @articles.each {|article| gtins_to_article[article[:ean13]] = article }
1435
- sl_gtins = @items.values.collect{|x| x[:packages].keys}.flatten.uniq;
1436
- gtins = gtins_to_article.keys + @infos_zur_rose.keys + @packs.values.collect{|x| x[:ean13]} + sl_gtins
1437
- gtins = (gtins-@@gtin2ignore)
1438
- gtins.sort!.uniq!
1439
- gtins.each do |ean13|
1440
- pac,no8 = nil,ean13.to_s[4..11] # BAG-XML(SL/LS)
1441
- next if ean13 == 0
1442
- obj = gtins_to_article[ean13] || @items.values.find{|x| x[:packages].keys.index(ean13) } || @infos_zur_rose[ean13]
1443
- if obj
1444
- obj = @packs[no8].merge(obj) if @packs[no8]
1445
- else
1446
- obj = @packs[no8] # obj not yet in refdata. Use data from swissmedic_package.xlsx
1447
- end
1448
- nr_items += 1
1449
- Oddb2xml.log "build_artikelstamm #{ean13}: #{nr_items} of #{gtins.size} articles" if nr_items % 5000 == 0
1450
- item = @items[ean13]
1451
- pack_info = nil
1452
- pack_info = @packs[no8] if no8 && /#{ean13}/.match(@packs[no8].to_s) # info from Packungen.xlsx from swissmedic_info
1453
- next if pack_info && /Tierarzneimittel/.match(pack_info[:list_code])
1454
- next if obj[:desc_de] && /ad us vet/i.match(obj[:desc_de])
1455
- sequence = obj[:seq]
1456
- if sequence.nil? && @packs[no8] && /#{ean13}/.match(@packs[no8].to_s)
1457
- sequence = {:packages =>{ean13 => @packs[no8]}}
1458
- obj[:seq] = sequence.clone
1459
- end
1460
- if sequence.nil? && @items[ean13] && @items[ean13][:packages][ean13]
1461
- sequence = @items[ean13]
1462
- end
1463
- if sequence
1464
- if obj[:seq] && !obj[:seq][:packages].keys.index(ean13)
1465
- # puts "unable to find #{ean13} in #{obj[:seq][:packages].keys}"
1466
- next
1452
+ self.class.class_eval do
1453
+ def emit_items(xml)
1454
+ nr_items = 0
1455
+ gtins_to_article = {}
1456
+ @articles.each { |article| gtins_to_article[article[:ean13]] = article }
1457
+ sl_gtins = @items.values.collect { |x| x[:packages].keys }.flatten.uniq
1458
+ gtins = gtins_to_article.keys + @infos_zur_rose.keys + @packs.values.collect { |x| x[:ean13] } + sl_gtins
1459
+ gtins = (gtins - @@gtin2ignore)
1460
+ gtins.sort!.uniq!
1461
+ gtins.each do |ean13|
1462
+ no8 = ean13.to_s[4..11] # BAG-XML(SL/LS)
1463
+ next if ean13 == 0
1464
+ obj = gtins_to_article[ean13] || @items.values.find { |x| x[:packages].keys.index(ean13) } || @infos_zur_rose[ean13]
1465
+ if obj
1466
+ obj = @packs[no8].merge(obj) if @packs[no8]
1467
+ else
1468
+ obj = @packs[no8] # obj not yet in refdata. Use data from swissmedic_package.xlsx
1467
1469
  end
1468
- sequence[:packages].each do |gtin, package|
1469
- pkg_gtin = package[:ean13].clone
1470
- if package[:no8] && (newEan13 = Oddb2xml.getEan13forNo8(package[:no8]))
1471
- if !newEan13.eql?(pkg_gtin)
1472
- puts "Setting #{newEan13} for #{pkg_gtin}"
1473
- pkg_gtin = newEan13
1474
- end
1475
- end
1476
- pharma_code = @refdata[pkg_gtin]
1477
- if @refdata[pkg_gtin] && @refdata[pkg_gtin][:pharmacode]
1478
- pharma_code = @refdata[pkg_gtin][:pharmacode]
1479
- elsif obj[:pharmacode]
1480
- pharma_code = obj[:pharmacode]
1481
- elsif @infos_zur_rose[ean13]
1482
- pharma_code = @infos_zur_rose[ean13][:pharmacode]
1483
- end
1484
- info = @calc_items[pkg_gtin]
1485
- if @@emitted_v5_gtins.index(pkg_gtin)
1470
+ nr_items += 1
1471
+ Oddb2xml.log "build_artikelstamm #{ean13}: #{nr_items} of #{gtins.size} articles" if nr_items % 5000 == 0
1472
+ item = @items[ean13]
1473
+ pack_info = nil
1474
+ pack_info = @packs[no8] if no8 && /#{ean13}/.match(@packs[no8].to_s) # info from Packungen.xlsx from swissmedic_info
1475
+ next if pack_info && /Tierarzneimittel/.match(pack_info[:list_code])
1476
+ next if obj[:desc_de] && /ad us vet/i.match(obj[:desc_de])
1477
+ sequence = obj[:seq]
1478
+ if sequence.nil? && @packs[no8] && /#{ean13}/.match(@packs[no8].to_s)
1479
+ sequence = {packages: {ean13 => @packs[no8]}}
1480
+ obj[:seq] = sequence.clone
1481
+ end
1482
+ if sequence.nil? && @items[ean13] && @items[ean13][:packages][ean13]
1483
+ sequence = @items[ean13]
1484
+ end
1485
+ if sequence
1486
+ if obj[:seq] && !obj[:seq][:packages].keys.index(ean13)
1487
+ # puts "unable to find #{ean13} in #{obj[:seq][:packages].keys}"
1486
1488
  next
1487
- else
1488
- @@emitted_v5_gtins << pkg_gtin.clone
1489
1489
  end
1490
- options = {'PHARMATYPE' => 'P'}
1491
- xml.ITEM(options) do
1492
- name = item[:name_de] + ' ' + item[:desc_de].strip + ' ' + package[:desc_de] if package && package[:desc_de]
1493
- name ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_de] : nil
1494
- name ||= @infos_zur_rose[ean13][:description] if @infos_zur_rose[ean13]
1495
- name ||= obj[:name_de] + ', ' + obj[:desc_de].strip if obj[:name_de]
1496
- name ||= (item[:desc_de] + item[:name_de]) if item
1497
- name ||= obj[:sequence_name]
1498
- xml.GTIN pkg_gtin.to_s.rjust(13, '0')
1499
- xml.SALECD('A')
1500
- # maxLength for DSCR is 50 for Artikelstamm v3
1501
- xml.DSCR(name) # for description for zur_rose
1502
- name_fr = item[:name_fr] + ' ' + item[:desc_fr].strip + ' ' + package[:desc_fr] if package && package[:desc_fr]
1503
- name_fr ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_fr] : nil
1504
- # Zugelassenen Packungen has only german names
1505
- name_fr ||= (obj[:name_fr] + ', ' + obj[:desc_fr]).strip if obj[:name_fr]
1506
- # ZuRorse has only german names
1507
- name_fr ||= (item[:name_fr] + ', ' + item[:desc_fr]) if item
1508
- name_fr ||= name
1509
- xml.DSCRF(name_fr)
1510
- xml.COMP do # Manufacturer
1511
- xml.NAME obj[:company_name]
1512
- xml.GLN obj[:company_ean]
1513
- end if obj[:company_name] || obj[:company_ean]
1514
- pexf = ppub = nil
1515
- if package[:prices]
1516
- pexf ||= package[:prices][:exf_price][:price]
1517
- ppub ||= package[:prices][:pub_price][:price]
1518
- elsif @items[ean13] && @items[ean13][:packages] && @items[ean13][:packages][ean13] && (bag_prices = @items[ean13][:packages][ean13][:prices])
1519
- pexf ||= bag_prices[:exf_price][:price]
1520
- ppub ||= bag_prices[:pub_price][:price]
1490
+ sequence[:packages].each do |gtin, package|
1491
+ pkg_gtin = package[:ean13].clone
1492
+ if package[:no8] && (new_ean_13 = Oddb2xml.getEan13forNo8(package[:no8]))
1493
+ if !new_ean_13.eql?(pkg_gtin)
1494
+ puts "Setting #{new_ean_13} for #{pkg_gtin}"
1495
+ pkg_gtin = new_ean_13
1496
+ end
1497
+ end
1498
+ info = @calc_items[pkg_gtin]
1499
+ if @@emitted_v5_gtins.index(pkg_gtin)
1500
+ next
1521
1501
  else
1522
- pexf ||= obj[:price]
1523
- ppub ||= obj[:pub_price]
1502
+ @@emitted_v5_gtins << pkg_gtin.clone
1524
1503
  end
1525
- ppub = nil if ppub && ppub.size == 0
1526
- pexf = nil if pexf && pexf.size == 0
1527
- xml.PEXF pexf if pexf
1528
- xml.PPUB ppub if ppub
1529
- measure = ''
1530
- if info
1531
- # MEASSURE Measurement Unit,e.g. Pills or milliliters
1532
- # <DSCR>HIRUDOID Creme 3 mg/g 40 g</DSCR>
1533
- xml.PKG_SIZE info.pkg_size.to_i if info.pkg_size
1534
- if info.measure
1535
- measure = info.measure
1536
- elsif info.pkg_size && info.unit
1537
- measure = info.pkg_size + ' ' + info.unit
1538
- elsif info.pkg_size
1539
- measure = info.pkg_size
1504
+ options = {"PHARMATYPE" => "P"}
1505
+ xml.ITEM(options) do
1506
+ name = item[:name_de] + " " + item[:desc_de].strip + " " + package[:desc_de] if package && package[:desc_de]
1507
+ name ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_de] : nil
1508
+ name ||= @infos_zur_rose[ean13][:description] if @infos_zur_rose[ean13]
1509
+ name ||= obj[:name_de] + ", " + obj[:desc_de].strip if obj[:name_de]
1510
+ name ||= (item[:desc_de] + item[:name_de]) if item
1511
+ name ||= obj[:sequence_name]
1512
+ xml.GTIN pkg_gtin.to_s.rjust(13, "0")
1513
+ xml.SALECD("A")
1514
+ # maxLength for DSCR is 50 for Artikelstamm v3
1515
+ xml.DSCR(name) # for description for zur_rose
1516
+ name_fr = item[:name_fr] + " " + item[:desc_fr].strip + " " + package[:desc_fr] if package && package[:desc_fr]
1517
+ name_fr ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_fr] : nil
1518
+ # Zugelassenen Packungen has only german names
1519
+ name_fr ||= (obj[:name_fr] + ", " + obj[:desc_fr]).strip if obj[:name_fr]
1520
+ # ZuRorse has only german names
1521
+ name_fr ||= (item[:name_fr] + ", " + item[:desc_fr]) if item
1522
+ name_fr ||= name
1523
+ xml.DSCRF(name_fr)
1524
+ if obj[:company_name] || obj[:company_ean]
1525
+ xml.COMP do # Manufacturer
1526
+ xml.NAME obj[:company_name][0..99] # limit to 100 chars as in XSD
1527
+ xml.GLN obj[:company_ean]
1528
+ end
1540
1529
  end
1541
- xml.MEASURE measure
1542
- xml.MEASUREF measure
1543
- # Die Darreichungsform dieses Items. zB Tablette(n) oder Spritze(n)
1544
- xml.DOSAGE_FORM info.galenic_form.descriptions['de'] if info.galenic_form.descriptions['de']
1545
- xml.DOSAGE_FORMF info.galenic_form.descriptions['fr'] if info.galenic_form.descriptions['fr']
1546
- end
1547
- xml.SL_ENTRY 'true' if sl_gtins.index(pkg_gtin)
1548
- xml.IKSCAT package[:swissmedic_category] if package[:swissmedic_category] && package[:swissmedic_category].length > 0
1549
- xml.GENERIC_TYPE sequence[:org_gen_code] if sequence[:org_gen_code] && !sequence[:org_gen_code].empty?
1550
- xml.LPPV 'true' if @lppvs[pkg_gtin.to_s] # detect_nincd
1551
- case item[:deductible]
1552
- when 'Y'; xml.DEDUCTIBLE 20; # 20%
1553
- when 'N'; xml.DEDUCTIBLE 10; # 10%
1554
- end if item && item[:deductible]
1555
- prodno = Oddb2xml.getProdnoForEan13(pkg_gtin)
1556
- atc = package[:atc_code]
1557
- atc ||= @refdata[pkg_gtin][:seq][:atc_code] if @refdata[pkg_gtin]
1558
- unless prodno # find a prodno from packages for vaccinations
1559
- if atc && /^J07/.match(atc) && !/^J07AX/.match(atc)
1560
- pack = @packs.values.find{ |v| v && v[:atc_code].eql?(atc)}
1561
- if pack
1562
- prodno = pack[:prodno]
1563
- Oddb2xml.log "Patching vaccination for #{pkg_gtin} #{atc} #{name} via prodno #{prodno}"
1564
- else
1565
- Oddb2xml.log "unable to find a pack/prodno for vaccination for #{pkg_gtin} #{atc} #{name}"
1530
+ pexf = ppub = nil
1531
+ if package[:prices]
1532
+ pexf ||= package[:prices][:exf_price][:price]
1533
+ ppub ||= package[:prices][:pub_price][:price]
1534
+ elsif @items[ean13] && @items[ean13][:packages] && @items[ean13][:packages][ean13] && (bag_prices = @items[ean13][:packages][ean13][:prices])
1535
+ pexf ||= bag_prices[:exf_price][:price]
1536
+ ppub ||= bag_prices[:pub_price][:price]
1537
+ else
1538
+ pexf ||= obj[:price]
1539
+ ppub ||= obj[:pub_price]
1540
+ end
1541
+ ppub = nil if ppub && ppub.size == 0
1542
+ pexf = nil if pexf && pexf.size == 0
1543
+ if !(obj[:price] && !obj[:price].empty?) || !(obj[:pub_price] && !obj[:pub_price].empty?)
1544
+ zur_rose_detail = @infos_zur_rose.values.find { |x| x[:ean13].to_i == ean13.to_i }
1545
+ if zur_rose_detail
1546
+ pexf ||= zur_rose_detail[:price]
1547
+ ppub ||= zur_rose_detail[:pub_price]
1548
+ end
1549
+ end
1550
+ xml.PEXF pexf if pexf
1551
+ xml.PPUB ppub if ppub
1552
+ measure = ""
1553
+ if info
1554
+ # MEASSURE Measurement Unit,e.g. Pills or milliliters
1555
+ # <DSCR>HIRUDOID Creme 3 mg/g 40 g</DSCR>
1556
+ xml.PKG_SIZE info.pkg_size.to_i if info.pkg_size
1557
+ if info.measure
1558
+ measure = info.measure
1559
+ elsif info.pkg_size && info.unit
1560
+ measure = info.pkg_size + " " + info.unit
1561
+ elsif info.pkg_size
1562
+ measure = info.pkg_size
1563
+ end
1564
+ xml.MEASURE measure
1565
+ xml.MEASUREF measure
1566
+ # Die Darreichungsform dieses Items. zB Tablette(n) oder Spritze(n)
1567
+ xml.DOSAGE_FORM info.galenic_form.descriptions["de"] if info.galenic_form.descriptions["de"]
1568
+ xml.DOSAGE_FORMF info.galenic_form.descriptions["fr"] if info.galenic_form.descriptions["fr"]
1569
+ end
1570
+ xml.SL_ENTRY "true" if sl_gtins.index(pkg_gtin)
1571
+ xml.IKSCAT package[:swissmedic_category] if package[:swissmedic_category] && package[:swissmedic_category].length > 0
1572
+ xml.GENERIC_TYPE sequence[:org_gen_code] if sequence[:org_gen_code] && !sequence[:org_gen_code].empty?
1573
+ xml.LPPV "true" if @lppvs[pkg_gtin.to_s] # detect_nincd
1574
+ if item && item[:deductible]
1575
+ case item[:deductible]
1576
+ when "Y" then xml.DEDUCTIBLE 20; # 20%
1577
+ when "N" then xml.DEDUCTIBLE 10; # 10%
1578
+ end
1579
+ end
1580
+ prodno = Oddb2xml.getProdnoForEan13(pkg_gtin)
1581
+ atc = package[:atc_code]
1582
+ refdata_atc = @refdata[pkg_gtin][:atc_code] if @refdata && @refdata[pkg_gtin] && @refdata[pkg_gtin]
1583
+ if refdata_atc && atc.nil?
1584
+ puts "WARNING: #{pkg_gtin} ATC-code from refdata #{refdata_atc} as Swissmedic ATC is nil #{name}"
1585
+ atc = refdata_atc
1586
+ end
1587
+ unless prodno # find a prodno from packages for vaccinations
1588
+ if atc && /^J07/.match(atc) && !/^J07AX/.match(atc)
1589
+ pack = @packs.values.find { |v| v && v[:atc_code].eql?(atc) }
1590
+ if pack
1591
+ prodno = pack[:prodno]
1592
+ Oddb2xml.log "Patching vaccination for #{pkg_gtin} #{atc} #{name} via prodno #{prodno}"
1593
+ else
1594
+ Oddb2xml.log "unable to find a pack/prodno for vaccination for #{pkg_gtin} #{atc} #{name}"
1595
+ end
1566
1596
  end
1567
1597
  end
1598
+ xml.PRODNO prodno if prodno
1599
+ @csv_file << [pkg_gtin, name, package[:unit], measure,
1600
+ pexf || "",
1601
+ ppub || "",
1602
+ prodno, atc, package[:substance_swissmedic],
1603
+ sequence[:org_gen_code], package[:ith_swissmedic],
1604
+ @items[pkg_gtin] ? "SL" : ""]
1568
1605
  end
1569
- xml.PRODNO prodno if prodno
1570
- csv = []
1571
- @csv_file << [pkg_gtin, name, package[:unit], measure,
1572
- pexf ? pexf : '',
1573
- ppub ? ppub : '',
1574
- prodno, atc, package[:substance_swissmedic],
1575
- sequence[:org_gen_code], package[:ith_swissmedic],
1576
- @items[pkg_gtin] ? 'SL' : '',
1577
- ]
1578
1606
  end
1579
- end
1580
- else # non pharma
1581
- if @@emitted_v5_gtins.index(ean13)
1582
- next
1583
- else
1584
- @@emitted_v5_gtins << ean13.clone
1585
- end
1586
- # Set the pharmatype to 'Y' for outdated products, which are no longer found
1587
- # in refdata/packungen
1588
- chap70 = nil
1589
- if @chapter70items.values.find {|x| x[:pharmacode] && x[:pharmacode].eql?(obj[:pharmacode])}
1590
- Oddb2xml.log "found chapter #{obj[:pharmacode]}" if $VERBOSE
1591
- chap70 = true
1592
- end
1593
- patched_pharma_type = (/^7680/.match(ean13.to_s.rjust(13, '0')) || chap70 ? 'P': 'N' )
1594
- next if /^#{Oddb2xml::FAKE_GTIN_START}/.match(ean13.to_s)
1595
- xml.ITEM({'PHARMATYPE' => patched_pharma_type }) do
1596
- xml.GTIN ean13.to_s.rjust(13, '0')
1597
- xml.PHAR obj[:pharmacode] if obj[:pharmacode] && obj[:pharmacode].length > 0
1598
- emit_salecd(xml, ean13, obj)
1599
- description = obj[:desc_de] || obj[:description] # for description for zur_rose
1600
- xml.DSCR(description)
1601
- xml.DSCRF(obj[:desc_fr] || '--missing--')
1602
- xml.COMP do
1603
- xml.GLN obj[:company_ean]
1604
- end if obj[:company_ean] && !obj[:company_ean].empty?
1605
- if !(obj[:price] && !obj[:price].empty?) || !(obj[:pub_price] && !obj[:pub_price].empty?)
1606
- zur_rose_detail = @infos_zur_rose.values.find{|x| x[:ean13].to_i == ean13.to_i}
1607
+ else # non pharma
1608
+ if @@emitted_v5_gtins.index(ean13)
1609
+ next
1610
+ else
1611
+ @@emitted_v5_gtins << ean13.clone
1607
1612
  end
1608
- ppub = nil; pexf=nil
1609
- if obj[:price] && !obj[:price].empty?
1610
- xml.PEXF (pexf = obj[:price])
1611
- elsif zur_rose_detail
1612
- if zur_rose_detail[:price] && !zur_rose_detail[:price].empty? && !zur_rose_detail[:price].eql?('0.00')
1613
- Oddb2xml.log "NonPharma: #{ean13} adding PEXF #{zur_rose_detail[:price]} #{description}"
1614
- xml.PEXF (pexf = zur_rose_detail[:price])
1615
- end
1613
+ # Set the pharmatype to 'Y' for outdated products, which are no longer found
1614
+ # in refdata/packungen
1615
+ chap70 = nil
1616
+ if @chapter70items.values.find { |x| x[:pharmacode]&.eql?(obj[:pharmacode]) }
1617
+ Oddb2xml.log "found chapter #{obj[:pharmacode]}" if $VERBOSE
1618
+ chap70 = true
1616
1619
  end
1617
- if obj[:pub_price] && !obj[:pub_price].empty?
1618
- xml.PPUB (ppub = obj[:pub_price])
1619
- elsif zur_rose_detail
1620
- if zur_rose_detail[:pub_price] && !zur_rose_detail[:pub_price].empty? && !zur_rose_detail[:pub_price].eql?('0.00')
1621
- Oddb2xml.log "NonPharma: #{ean13} adding PPUB #{zur_rose_detail[:pub_price]} #{description}"
1622
- xml.PPUB (ppub = zur_rose_detail[:pub_price])
1620
+ patched_pharma_type = (/^7680/.match(ean13.to_s.rjust(13, "0")) || chap70 ? "P" : "N")
1621
+ next if /^#{Oddb2xml::FAKE_GTIN_START}/o.match?(ean13.to_s)
1622
+ next if obj[:data_origin].eql?("zur_rose") && /^7680/.match(ean13) # must skip inactiv items
1623
+ xml.ITEM({"PHARMATYPE" => patched_pharma_type}) do
1624
+ xml.GTIN ean13.to_s.rjust(13, "0")
1625
+ if obj[:pharmacode] && obj[:pharmacode].length > 0
1626
+ xml.PHAR obj[:pharmacode]
1627
+ elsif (zur_rose = @infos_zur_rose[ean13])
1628
+ puts "Artikelstamm: Adding #{zur_rose[:pharmacode]} to article GTIN #{ean13}"
1629
+ xml.PHAR zur_rose[:pharmacode]
1630
+ elsif /^7680/.match?(ean13)
1631
+ puts "Artikelstamm: No pharmacode for article GTIN #{ean13} via ZurRose"
1632
+ end
1633
+ emit_salecd(xml, ean13, obj)
1634
+ description = obj[:desc_de] || obj[:description] # for description for zur_rose
1635
+ xml.DSCR(description)
1636
+ xml.DSCRF(obj[:desc_fr] || "--missing--")
1637
+ if obj[:company_ean] && !obj[:company_ean].empty?
1638
+ xml.COMP do
1639
+ xml.GLN obj[:company_ean]
1640
+ end
1641
+ end
1642
+ if !(obj[:price] && !obj[:price].empty?) || !(obj[:pub_price] && !obj[:pub_price].empty?)
1643
+ zur_rose_detail = @infos_zur_rose.values.find { |x| x[:ean13].to_i == ean13.to_i }
1644
+ end
1645
+ ppub = nil
1646
+ pexf = nil
1647
+ if obj[:price] && !obj[:price].empty?
1648
+ xml.PEXF(pexf = obj[:price])
1649
+ elsif zur_rose_detail
1650
+ if zur_rose_detail[:price] && !zur_rose_detail[:price].empty? && !zur_rose_detail[:price].eql?("0.00")
1651
+ # Oddb2xml.log "NonPharma: #{ean13} adding PEXF #{zur_rose_detail[:price]} #{description}"
1652
+ xml.PEXF(pexf = zur_rose_detail[:price])
1653
+ end
1654
+ end
1655
+ if obj[:pub_price] && !obj[:pub_price].empty?
1656
+ xml.PPUB(ppub = obj[:pub_price])
1657
+ elsif zur_rose_detail
1658
+ if zur_rose_detail[:pub_price] && !zur_rose_detail[:pub_price].empty? && !zur_rose_detail[:pub_price].eql?("0.00")
1659
+ # Oddb2xml.log "NonPharma: #{ean13} adding PPUB #{zur_rose_detail[:pub_price]} #{description}"
1660
+ xml.PPUB(ppub = zur_rose_detail[:pub_price])
1661
+ end
1662
+ end
1663
+ @csv_file << [ean13, description, "", "", pexf, ppub, "", "", "", "", "", ""]
1664
+ if chap70
1665
+ xml.comment "Chapter70 hack #{ean13.to_s.rjust(13, "0")} #{description.encode(xml: :text).gsub("--", "-")}"
1666
+ xml.SL_ENTRY "true"
1667
+ xml.PRODNO obj[:pharmacode]
1623
1668
  end
1624
- end
1625
- @csv_file << [ ean13, description, '', '', pexf, ppub, '', '', '', '', '', '' ]
1626
- if chap70
1627
- xml.comment "Chapter70 hack #{ean13.to_s.rjust(13, '0')} #{description.encode(:xml => :text).gsub('--','-')}"
1628
- xml.SL_ENTRY 'true'
1629
- xml.PRODNO obj[:pharmacode]
1630
1669
  end
1631
1670
  end
1632
1671
  end
1672
+ @csv_file.close if @csv_file && !@csv_file.closed?
1673
+ nr_items
1633
1674
  end
1634
- @csv_file.close if @csv_file && !@csv_file.closed?
1635
- nr_items
1636
1675
  end
1637
1676
  unless @prepared
1638
- require 'oddb2xml/chapter_70_hack'
1639
- Oddb2xml::Chapter70xtractor.parse()
1677
+ require "oddb2xml/chapter_70_hack"
1678
+ Oddb2xml::Chapter70xtractor.parse
1640
1679
  @chapter70items = Oddb2xml::Chapter70xtractor.items
1641
1680
  prepare_limitations
1642
1681
  prepare_articles
@@ -1645,33 +1684,25 @@ module Oddb2xml
1645
1684
  prepare_calc_items(suppress_composition_parsing: true)
1646
1685
  @prepared = true
1647
1686
  @old_rose_size = @infos_zur_rose.size
1648
- @infos_zur_rose.each do |ean13, value|
1649
- if /^7680/.match(ean13.to_s) && @options[:artikelstamm]
1650
- @infos_zur_rose.delete(ean13)
1651
- end
1652
- end if false
1653
- @new_rose_size = @infos_zur_rose.size
1654
1687
  end
1655
1688
  nr_products = 0
1656
1689
  nr_articles = 0
1657
1690
  @nr_articles = 0
1658
1691
  used_limitations = []
1659
- Oddb2xml.log "#{variant}: Deleted #{@old_rose_size - @new_rose_size} entries from ZurRose where GTIN start with 7680 (Swissmedic)"
1660
1692
  # Oddb2xml.log "#{variant} #{nr_products} of #{@products.size} articles and ignore #{@@gtin2ignore.size} gtins specified via #{@@ignore_file}"
1661
- _builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
1693
+ a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
1662
1694
  xml.doc.tag_suffix = @tag_suffix
1663
- datetime = Time.new.strftime('%FT%T%z')
1664
1695
  elexis_strftime_format = "%FT%T\.%L%:z"
1665
- @@cumul_ver = (Date.today.year-2013)*12+Date.today.month
1666
- options_xml = {
1667
- 'xmlns' => 'http://elexis.ch/Elexis_Artikelstamm_v5',
1668
- 'CREATION_DATETIME' => Time.new.strftime(elexis_strftime_format),
1669
- 'BUILD_DATETIME' => Time.new.strftime(elexis_strftime_format),
1670
- 'DATA_SOURCE' => 'oddb2xml'
1696
+ @@cumul_ver = (Date.today.year - 2013) * 12 + Date.today.month
1697
+ options_xml = {
1698
+ "xmlns" => "http://elexis.ch/Elexis_Artikelstamm_v5",
1699
+ "CREATION_DATETIME" => Time.new.strftime(elexis_strftime_format),
1700
+ "BUILD_DATETIME" => Time.new.strftime(elexis_strftime_format),
1701
+ "DATA_SOURCE" => "oddb2xml"
1671
1702
  }
1672
1703
  emitted_prodno = []
1673
1704
  no8_to_prodno = {}
1674
- @packs.collect{ |key, val| no8_to_prodno[key] = val [:prodno] }
1705
+ @packs.collect { |key, val| no8_to_prodno[key] = val [:prodno] }
1675
1706
  xml.comment("Produced by #{__FILE__} version #{VERSION} at #{Time.now}")
1676
1707
  xml.ARTIKELSTAMM(options_xml) do
1677
1708
  xml.PRODUCTS do
@@ -1679,22 +1710,22 @@ module Oddb2xml
1679
1710
  products.each do |product|
1680
1711
  ean13 = product[0]
1681
1712
  obj = product[1]
1682
- next if /^Q/i.match(obj[:atc])
1713
+ next if /^Q/i.match?(obj[:atc])
1683
1714
  ean = obj[:ean13]
1684
1715
  sequence = obj[:seq]
1685
1716
  sequence ||= @products[ean][:seq] if @products[ean]
1686
- next unless check_name(obj, :de)
1687
- ppac = ((_ppac = @packs[ean.to_s[4..11]] and !_ppac[:is_tier]) ? _ppac : {})
1688
- prodno = ppac[:prodno] if ppac[:prodno] and !ppac[:prodno].empty?
1717
+ next unless check_article_name(obj, :de)
1718
+ ppac = ((a_ppac = @packs[ean.to_s[4..11]]) && !a_ppac[:is_tier] ? a_ppac : {})
1719
+ prodno = ppac[:prodno] if ppac[:prodno] && !ppac[:prodno].empty?
1689
1720
  prodno = obj[:pharmacode] if obj[:chapter70]
1690
- myPack = @packs.values.find{ |x| x[:iksnr].to_i == obj[:seq][:swissmedic_number5].to_i } if obj[:seq]
1691
- if myPack && !prodno
1692
- prodno ||= myPack[:prodno]
1693
- puts "Setting prodno #{prodno} for #{ean13} #{myPack[:sequence_name]}"
1721
+ my_pack = @packs.values.find { |x| x[:iksnr].to_i == obj[:seq][:swissmedic_number5].to_i } if obj[:seq]
1722
+ if my_pack && !prodno
1723
+ prodno ||= my_pack[:prodno]
1724
+ puts "Setting prodno #{prodno} for #{ean13} #{my_pack[:sequence_name]}"
1694
1725
  end
1695
1726
  next unless prodno
1696
1727
  next if emitted_prodno.index(prodno)
1697
- sequence ||= @articles.find{|x| x[:ean13].eql?(ean)}
1728
+ sequence ||= @articles.find { |x| x[:ean13].eql?(ean) }
1698
1729
  unless obj[:chapter70]
1699
1730
  next unless sequence && (sequence[:name_de] || sequence[:desc_de])
1700
1731
  if Oddb2xml.getEan13forProdno(prodno).size == 0 && !obj[:no8].eql?(Oddb2xml.getNo8ForEan13(ean))
@@ -1707,44 +1738,43 @@ module Oddb2xml
1707
1738
  xml.PRODUCT do
1708
1739
  xml.PRODNO prodno
1709
1740
  if sequence
1710
- xml.SALECD('A') # these products are always active!
1741
+ xml.SALECD("A") # these products are always active!
1711
1742
  name_de = "#{sequence[:name_de]} #{sequence[:desc_de]}".strip if sequence[:name_de]
1712
- unless name_de # eg. 7680002770014 Coeur-Vaisseaux Sérocytol, suppositoire
1713
- if ppac && /stk/i.match( sequence[:desc_de])
1714
- name_de = ppac[:sequence_name]
1715
- else
1716
- name_de = sequence[:desc_de]
1717
- end
1743
+ name_de ||= if ppac && /stk/i.match(sequence[:desc_de])
1744
+ ppac[:sequence_name]
1745
+ else
1746
+ sequence[:desc_de]
1718
1747
  end
1719
1748
  name_fr = "#{sequence[:name_fr]} #{sequence[:desc_fr]}".strip if sequence[:name_fr]
1720
1749
  name_fr ||= (ppac && ppac[:sequence_name])
1721
- override(xml, prodno, :DSCR, name_de.strip)
1750
+ override(xml, prodno, :DSCR, name_de.strip)
1722
1751
  override(xml, prodno, :DSCRF, name_fr.strip)
1752
+ # use overriden ATC if possibel
1753
+ atc = sequence[:atc] || sequence[:atc_code]
1754
+ xml.ATC atc if atc && !atc.empty?
1723
1755
  end
1724
- xml.ATC sequence[:atc_code] if sequence && sequence[:atc_code] && !sequence[:atc_code].empty?
1725
1756
  if sequence && sequence[:packages] && (first_package = sequence[:packages].values.first) &&
1726
- (first_limitation = first_package[:limitations].first)
1757
+ (first_limitation = first_package[:limitations].first)
1727
1758
  lim_code = first_limitation[:code]
1728
1759
  used_limitations << lim_code unless used_limitations.index(lim_code)
1729
1760
  xml.LIMNAMEBAG lim_code
1730
1761
  elsif obj[:chapter70]
1731
- xml.comment "Chapter70 hack prodno #{prodno} #{obj[:description].encode(:xml => :text).gsub('--','-')}"
1732
- xml.SALECD('A') # these products are always active!
1762
+ xml.comment "Chapter70 hack prodno #{prodno} #{obj[:description].encode(xml: :text).gsub("--", "-")}"
1763
+ xml.SALECD("A") # these products are always active!
1733
1764
  xml.DSCR obj[:description]
1734
- xml.DSCRF ''
1765
+ xml.DSCRF ""
1735
1766
  if @limitations.index(obj[:code])
1736
1767
  xml.LIMNAMEBAG obj[:code]
1737
1768
  used_limitations << obj[:code]
1738
1769
  end
1739
1770
  end
1740
1771
  if sequence && sequence[:substances]
1741
- value = nil
1742
- if sequence[:substances].size > 1
1743
- value = 'Verschiedene Kombinationen'
1772
+ value = if sequence[:substances].size > 1
1773
+ "Verschiedene Kombinationen"
1744
1774
  elsif sequence[:substances].first
1745
- value = sequence[:substances].first[:name]
1775
+ sequence[:substances].first[:name]
1746
1776
  else
1747
- value = obj[:sub]
1777
+ obj[:sub]
1748
1778
  end
1749
1779
  override(xml, prodno, :SUBSTANCE, value) if value
1750
1780
  end
@@ -1763,9 +1793,9 @@ module Oddb2xml
1763
1793
  xml.LIMITATION do
1764
1794
  xml.comment "Chapter70 2 hack" if lim[:chap70]
1765
1795
  xml.LIMNAMEBAG lim[:code] # original LIMCD
1766
- xml.DSCR Oddb2xml.html_decode(lim[:desc_de])
1767
- xml.DSCRF Oddb2xml.html_decode(lim[:desc_fr])
1768
- xml.LIMITATION_PTS (lim[:value].to_s.length > 1 ? lim[:value] : 1)
1796
+ xml.DSCR Oddb2xml.html_decode(lim[:desc_de])
1797
+ xml.DSCRF Oddb2xml.html_decode(lim[:desc_fr])
1798
+ xml.LIMITATION_PTS(lim[:value].to_s.length > 1 ? lim[:value] : 1)
1769
1799
  end
1770
1800
  end
1771
1801
  end
@@ -1776,17 +1806,19 @@ module Oddb2xml
1776
1806
  end
1777
1807
  Oddb2xml.log "#{variant}. Done #{nr_products} of #{@products.size} products, #{@limitations.size} limitations and #{nr_articles}/#{@nr_articles} articles. @@emitted_v5_gtins #{@@emitted_v5_gtins.size}"
1778
1808
  # we don't add a SHA256 hash for each element in the article
1779
- # Oddb2xml.add_hash(_builder.to_xml)
1809
+ # Oddb2xml.add_hash(a_builder.to_xml)
1780
1810
  # doc = REXML::Document.new( source, { :raw => :all })
1781
1811
  # doc.write( $stdout, 0 )
1782
1812
  lines = []
1783
- lines << " - #{sprintf('%5d', @products.size)} products"
1784
- lines << " - #{sprintf('%5d', @limitations.size)} limitations"
1785
- lines << " - #{sprintf('%5d', @nr_articles)} articles"
1786
- lines << " - #{sprintf('%5d', @@gtin2ignore.size)} ignored GTINS"
1813
+ lines << " - #{sprintf("%5d", @products.size)} products"
1814
+ lines << " - #{sprintf("%5d", @limitations.size)} limitations"
1815
+ lines << " - #{sprintf("%5d", @nr_articles)} articles"
1816
+ lines << " - #{sprintf("%5d", @@gtin2ignore.size)} ignored GTINS"
1787
1817
  @@articlestamm_v5_info_lines = lines
1788
- _builder.to_xml({:indent => 4, :encoding => 'UTF-8'})
1818
+ a_builder.to_xml({indent: 4, encoding: "UTF-8"})
1789
1819
  end
1820
+
1821
+ private_class_method
1790
1822
  def self.articlestamm_v5_info_lines
1791
1823
  @@articlestamm_v5_info_lines
1792
1824
  end