oddb2xml 2.6.9 → 2.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/ruby.yml +40 -0
- data/.standard.yml +2 -0
- data/Elexis_Artikelstamm_v5.xsd +0 -3
- data/Gemfile +3 -3
- data/History.txt +28 -0
- data/README.md +3 -3
- data/Rakefile +24 -23
- data/bin/check_artikelstamm +11 -11
- data/bin/compare_v5 +23 -23
- data/bin/oddb2xml +14 -13
- data/lib/oddb2xml.rb +1 -1
- data/lib/oddb2xml/builder.rb +1075 -1048
- data/lib/oddb2xml/calc.rb +232 -233
- data/lib/oddb2xml/chapter_70_hack.rb +38 -32
- data/lib/oddb2xml/cli.rb +252 -235
- data/lib/oddb2xml/compare.rb +70 -59
- data/lib/oddb2xml/compositions_syntax.rb +448 -430
- data/lib/oddb2xml/compressor.rb +20 -20
- data/lib/oddb2xml/downloader.rb +156 -128
- data/lib/oddb2xml/extractor.rb +295 -302
- data/lib/oddb2xml/options.rb +34 -35
- data/lib/oddb2xml/parslet_compositions.rb +263 -269
- data/lib/oddb2xml/semantic_check.rb +39 -33
- data/lib/oddb2xml/util.rb +166 -164
- data/lib/oddb2xml/version.rb +1 -1
- data/lib/oddb2xml/xml_definitions.rb +32 -33
- data/oddb2xml.gemspec +32 -31
- data/spec/artikelstamm_spec.rb +116 -135
- data/spec/builder_spec.rb +495 -524
- data/spec/calc_spec.rb +552 -593
- data/spec/check_artikelstamm_spec.rb +26 -26
- data/spec/cli_spec.rb +173 -174
- data/spec/compare_spec.rb +9 -11
- data/spec/composition_syntax_spec.rb +390 -409
- data/spec/compressor_spec.rb +48 -48
- data/spec/data/refdata_NonPharma.xml +0 -3
- data/spec/data/refdata_Pharma.xml +0 -26
- data/spec/data/transfer.dat +1 -0
- data/spec/data/varia_De.htm +2 -2
- data/spec/data_helper.rb +47 -49
- data/spec/downloader_spec.rb +251 -260
- data/spec/extractor_spec.rb +172 -164
- data/spec/galenic_spec.rb +233 -256
- data/spec/options_spec.rb +116 -119
- data/spec/parslet_spec.rb +833 -861
- data/spec/spec_helper.rb +153 -153
- data/test_options.rb +39 -42
- data/tools/win_fetch_cacerts.rb +2 -3
- metadata +48 -5
- data/.travis.yml +0 -29
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: af1cbeb37bf057e98955776c87dd5092fc5706af18d00ba818efccd2c52a076e
|
|
4
|
+
data.tar.gz: 1f4faf8f73b2cffa14bd3dda23dad4e401b524587c0f95d80e0cc9cbd4ba5d2b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ace048c855b3711fd6b75692373318fe992a5c6529d322c13b516a7bd09390e36efec3f14edaa91ddeb223438d74c97c15ba4691077e9c77ce5063a10bdcc423
|
|
7
|
+
data.tar.gz: 9dcf787039edc02a56b7301f6849e76259628ac55da598a2878e4a08c63fd3c3aaef35bfea6bda8184c6e3552314fba7bb028962d81151ca98bf76f830c3303f
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
2
|
+
# They are provided by a third-party and are governed by
|
|
3
|
+
# separate terms of service, privacy policy, and support
|
|
4
|
+
# documentation.
|
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
|
7
|
+
|
|
8
|
+
name: Ruby
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
branches: [ master ]
|
|
13
|
+
pull_request:
|
|
14
|
+
branches: [ master ]
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
# Using a matrix fails, because /setup-ruby always invokes bundle install without any additional args
|
|
20
|
+
# Fixed by adding not defining the debugger group in the Gemfile
|
|
21
|
+
strategy:
|
|
22
|
+
fail-fast: false
|
|
23
|
+
matrix:
|
|
24
|
+
os: [ ubuntu]
|
|
25
|
+
ruby: [2.5, 2.6, 2.7, 3.0, head]
|
|
26
|
+
continue-on-error: ${{ endsWith(matrix.ruby, 'head') }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v2
|
|
29
|
+
- uses: ruby/setup-ruby@v1
|
|
30
|
+
with:
|
|
31
|
+
ruby-version: ${{ matrix.ruby }}
|
|
32
|
+
bundler-cache: true
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: |
|
|
36
|
+
bundle config set path .bundle/gems --local
|
|
37
|
+
bundle config set without debugger --local
|
|
38
|
+
bundle install
|
|
39
|
+
- name: Test with RSpec
|
|
40
|
+
run: bundle exec rspec
|
data/.standard.yml
ADDED
data/Elexis_Artikelstamm_v5.xsd
CHANGED
data/Gemfile
CHANGED
data/History.txt
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
=== 2.7.4 / 30.03.2021
|
|
2
|
+
* Update needed Ruby-Version to 2.5.0 in gemspec
|
|
3
|
+
* Ensure downloads directory is created at first run
|
|
4
|
+
|
|
5
|
+
=== 2.7.3 / 29.03.2021
|
|
6
|
+
* Do not delete swissmedic_package.xlsx and swissmedic_orphan.xlsx
|
|
7
|
+
* Save swissmedic_package.xlsx and swissmedic_orphan.xlsx under downloads
|
|
8
|
+
* Log removing files
|
|
9
|
+
|
|
10
|
+
=== 2.7.2 / 18.03.2021
|
|
11
|
+
* Added https://github.com/testdouble/standard and fixed all useful warnings
|
|
12
|
+
* Added standard to rake tasks
|
|
13
|
+
* Use ATC-code from refdata if available and show differences
|
|
14
|
+
* Get pharmacode from tranfer.dat for artikelstamm if possible
|
|
15
|
+
* We do not longer test Ruby 2.4 with github/actions
|
|
16
|
+
* Update build status to use github/actions instead of travis
|
|
17
|
+
|
|
18
|
+
=== 2.7.1 / 03.02.2021
|
|
19
|
+
* travis-ci -> Github Actions
|
|
20
|
+
* limit DSCRD/DSCRF to 120 chars as specified in the XSD
|
|
21
|
+
* Use huge option for nokogiri as suggested by https://github.com/sparklemotion/nokogiri/issues/2187
|
|
22
|
+
* Adapt artikelstamm to refdata without pharmacode
|
|
23
|
+
* oddb_article get pharmacode where possible from transfer.dat
|
|
24
|
+
|
|
25
|
+
=== 2.7.0 / 05.11.2020
|
|
26
|
+
* Chapter70 hack nur als Kommentar
|
|
27
|
+
* Avoid double hyphen in comment
|
|
28
|
+
|
|
1
29
|
=== 2.6.9 / 29.06.2020
|
|
2
30
|
|
|
3
31
|
* Fix problem when running bin/oddb2xml -a -f dat. Thanks to Lukas Furre for reporting the problem
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# oddb2xml
|
|
2
2
|
|
|
3
|
-
[](https://github.com/zdavatz/oddb2xml/actions)
|
|
4
4
|
|
|
5
5
|
* oddb2xml -a nonpharma -o fi
|
|
6
6
|
|
|
@@ -106,8 +106,8 @@ FR
|
|
|
106
106
|
|
|
107
107
|
## Supported ruby version
|
|
108
108
|
|
|
109
|
-
We run tests on travis-ci.org for the Ruby versions mentioned in the .travis.yml file. You will need ruby > 2.
|
|
110
|
-
|
|
109
|
+
We run tests on travis-ci.org for the Ruby versions mentioned in the .travis.yml file. You will need ruby > 2.5 to work correctly.
|
|
110
|
+
Look at the github actions to see the spec test results. We ignore errors against ruby head, as it is sometimes unstable.
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
## XSD files
|
data/Rakefile
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
|
|
3
|
-
lib = File.expand_path(
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path("../lib", __FILE__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
-
require
|
|
5
|
+
require "oddb2xml/version"
|
|
6
6
|
require "bundler/gem_tasks"
|
|
7
|
-
require
|
|
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
|
|
14
|
-
task :
|
|
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 :
|
|
19
|
+
task spec: :clean
|
|
19
20
|
|
|
20
|
-
desc
|
|
21
|
-
task :
|
|
22
|
-
log_file =
|
|
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
|
|
32
|
-
CLEAN.include FileList[
|
|
33
|
-
CLEAN.include FileList[
|
|
34
|
-
CLEAN.include FileList[
|
|
35
|
-
CLEAN.include FileList[
|
|
36
|
-
CLEAN.include FileList[
|
|
37
|
-
CLEAN.include FileList[
|
|
38
|
-
CLEAN.include FileList[
|
|
39
|
-
CLEAN.include FileList[
|
|
40
|
-
CLEAN.include FileList[
|
|
41
|
-
CLEAN.include FileList[
|
|
42
|
-
CLEAN.include FileList[
|
|
43
|
-
CLEAN.include FileList[
|
|
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"]
|
data/bin/check_artikelstamm
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
require
|
|
2
|
+
require "pathname"
|
|
3
3
|
|
|
4
4
|
root = Pathname.new(__FILE__).realpath.parent.parent
|
|
5
|
-
$:.unshift root.join(
|
|
5
|
+
$:.unshift root.join("lib") if $0 == __FILE__
|
|
6
6
|
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
7
|
+
require "oddb2xml/version"
|
|
8
|
+
require "oddb2xml/semantic_check"
|
|
9
|
+
require "optimist"
|
|
10
10
|
|
|
11
|
-
@opts = Optimist
|
|
12
|
-
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
|
-
|
|
28
|
-
|
|
29
|
-
diff = (Time.now-
|
|
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
|
|
2
|
+
require "pathname"
|
|
3
3
|
|
|
4
4
|
root = Pathname.new(__FILE__).realpath.parent.parent
|
|
5
|
-
$:.unshift root.join(
|
|
5
|
+
$:.unshift root.join("lib") if $0 == __FILE__
|
|
6
6
|
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
19
|
-
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,
|
|
25
|
-
opt :fields_as_floats,
|
|
26
|
-
opt :fields_to_ignore,
|
|
27
|
-
opt :min_diff_for_floats, "Minimal difference when comparing floats", :
|
|
28
|
-
opt :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
|
-
|
|
39
|
-
|
|
40
|
-
diff = (Time.now-
|
|
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
|
|
3
|
+
require "pathname"
|
|
4
4
|
root = Pathname.new(__FILE__).realpath.parent.parent
|
|
5
|
-
$:.unshift root.join(
|
|
5
|
+
$:.unshift root.join("lib") if $0 == __FILE__
|
|
6
6
|
|
|
7
|
-
require
|
|
8
|
-
require
|
|
9
|
-
require
|
|
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
|
-
|
|
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 =
|
|
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-
|
|
43
|
-
puts "#{Time.now}: #{__LINE__} done. Took #{diff} seconds"
|
|
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
data/lib/oddb2xml/builder.rb
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
require
|
|
3
|
-
require
|
|
4
|
-
require
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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__),
|
|
37
|
-
@@article_overrides
|
|
38
|
-
@@product_overrides
|
|
39
|
-
@@ignore_file
|
|
40
|
-
@@gtin2ignore
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
50
|
-
@subject
|
|
51
|
-
@refdata
|
|
52
|
-
@items
|
|
53
|
-
@flags
|
|
54
|
-
@lppvs
|
|
55
|
-
@infos
|
|
56
|
-
@packs
|
|
57
|
-
@migel
|
|
58
|
-
@infos_zur_rose
|
|
59
|
-
@actions
|
|
60
|
-
@orphan
|
|
61
|
-
@ean14
|
|
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
|
-
|
|
71
|
+
|
|
72
|
+
def to_xml(subject = nil)
|
|
71
73
|
Oddb2xml.log "to_xml subject #{subject || @subject}"
|
|
72
74
|
if subject
|
|
73
|
-
|
|
75
|
+
send("build_" + subject.to_s)
|
|
74
76
|
elsif @subject
|
|
75
|
-
|
|
77
|
+
send("build_" + @subject.to_s)
|
|
76
78
|
end
|
|
77
79
|
end
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
+
send("build_" + subject.to_s)
|
|
82
85
|
elsif @subject
|
|
83
|
-
|
|
86
|
+
send("build_" + @subject.to_s)
|
|
84
87
|
end
|
|
85
88
|
end
|
|
86
|
-
|
|
87
|
-
|
|
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 :
|
|
95
|
+
Oddb2xml.log("prepare_articles starting with #{@articles ? @articles.size : "no"} articles.")
|
|
91
96
|
@articles = []
|
|
92
97
|
@refdata.each do |ean13, obj|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
132
|
+
nr_items = 0
|
|
124
133
|
@infos_zur_rose.each do |ean13, info|
|
|
125
|
-
|
|
134
|
+
nr_items += 1
|
|
126
135
|
pharmacode = info[:pharmacode]
|
|
127
136
|
if @pharmacode[pharmacode]
|
|
128
|
-
@pharmacode[pharmacode][: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]
|
|
146
|
+
existing[:price] = info[:price]
|
|
138
147
|
existing[:pub_price] = info[:pub_price]
|
|
139
148
|
else
|
|
140
149
|
entry = {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
167
|
+
if !found && (obj.size > 0)
|
|
159
168
|
@articles << obj unless @options[:artikelstamm]
|
|
160
|
-
|
|
169
|
+
nr_added += 1
|
|
161
170
|
end
|
|
162
171
|
end
|
|
163
172
|
end
|
|
164
173
|
end
|
|
165
|
-
Oddb2xml.log("prepare_articles done. Added #{
|
|
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])
|
|
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
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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<< {:
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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]
|
|
235
|
-
ean13 =
|
|
236
|
-
ean13 ||=
|
|
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
|
-
:
|
|
240
|
-
:
|
|
241
|
-
:
|
|
242
|
-
:
|
|
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
|
|
250
|
-
next if 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
|
-
:
|
|
253
|
-
:
|
|
254
|
-
:
|
|
255
|
-
:
|
|
256
|
-
:
|
|
257
|
-
:
|
|
258
|
-
:
|
|
259
|
-
:
|
|
260
|
-
:
|
|
261
|
-
:
|
|
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?
|
|
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] ==
|
|
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
|
-
|
|
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
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
xml.SB(
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
xml.LIM(
|
|
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
|
|
372
|
+
xml.Pharmacode lim[:id]
|
|
351
373
|
end
|
|
352
|
-
xml.IT
|
|
353
|
-
xml.LIMTYP
|
|
354
|
-
xml.LIMVAL
|
|
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
|
|
357
|
-
xml.DSCRD
|
|
358
|
-
xml.DSCRF
|
|
359
|
-
xml.VDAT
|
|
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
|
|
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(
|
|
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
|
-
|
|
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(
|
|
384
|
-
xml.IXNO
|
|
385
|
-
xml.TITD
|
|
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
|
|
392
|
-
#xml.EFFF
|
|
393
|
-
if @codes
|
|
394
|
-
if dict = @codes[ix[:grad].upcase]
|
|
395
|
-
xml.RLV
|
|
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
|
|
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(
|
|
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
|
-
|
|
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(
|
|
443
|
-
xml.CDTYP
|
|
444
|
-
xml.CDVAL
|
|
445
|
-
xml.DSCRSD
|
|
446
|
-
#xml.DSCRSF
|
|
447
|
-
#xml.DSCRMD
|
|
448
|
-
#xml.DSCRMF
|
|
449
|
-
#xml.DSCRD
|
|
450
|
-
#xml.DSCRF
|
|
451
|
-
xml.DEL
|
|
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
|
|
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(
|
|
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
|
-
|
|
470
|
-
|
|
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(
|
|
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
|
|
503
|
+
next if list_code && /Tierarzneimittel/.match(list_code)
|
|
482
504
|
if add_to_products
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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 #{
|
|
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
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
|
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
|
|
532
|
-
|
|
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(
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
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
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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 = ((
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
xml.
|
|
576
|
-
xml.
|
|
577
|
-
xml.
|
|
578
|
-
#xml.
|
|
579
|
-
#xml.
|
|
580
|
-
#xml.
|
|
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]
|
|
585
|
-
xml.ADINFF seq[:comment_fr]
|
|
586
|
-
xml.GENCD
|
|
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
|
|
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
|
|
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
|
|
650
|
-
xml.QTYU
|
|
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
|
|
675
|
+
# xml.GRP
|
|
676
|
+
xml.RLV @codes[ix[:grad]]
|
|
660
677
|
}
|
|
661
678
|
end
|
|
662
679
|
end
|
|
663
680
|
end
|
|
664
|
-
#xml.CPTROA {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
#}
|
|
681
|
+
# xml.CPTROA {
|
|
682
|
+
# xml.SYSLOC
|
|
683
|
+
# xml.ROA
|
|
684
|
+
# }
|
|
668
685
|
}
|
|
669
|
-
#xml.PRDICD { # currently empty
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
#}
|
|
676
|
-
xml.PackGrSwissmedic
|
|
677
|
-
xml.EinheitSwissmedic
|
|
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
|
|
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(
|
|
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::
|
|
696
|
-
|
|
697
|
-
return unless File.exists?(packungen_xlsx)
|
|
712
|
+
packungen_xlsx = File.join(Oddb2xml::DOWNLOADS, "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
|
|
703
|
-
iksnr
|
|
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
|
-
|
|
707
|
-
|
|
721
|
+
puts "#{Time.now}: At row #{row_nr} iksnr #{iksnr}"
|
|
722
|
+
$stdout.flush
|
|
708
723
|
end
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
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
|
|
718
|
-
sub
|
|
719
|
-
comp
|
|
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
|
|
722
|
-
name
|
|
723
|
-
atc_code
|
|
724
|
-
list_code
|
|
725
|
-
package_size
|
|
726
|
-
unit
|
|
727
|
-
active_substance
|
|
728
|
-
composition
|
|
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
|
|
732
|
-
next if 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
|
-
|
|
747
|
+
info = if suppress_composition_parsing
|
|
748
|
+
Calc.new(name, package_size, unit)
|
|
737
749
|
else
|
|
738
|
-
|
|
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 =
|
|
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
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
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
|
-
|
|
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
|
-
|
|
783
|
-
xml.
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
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
|
|
826
|
+
end
|
|
812
827
|
end
|
|
813
828
|
end
|
|
814
829
|
end
|
|
815
830
|
|
|
816
|
-
csv_name = File.join(
|
|
817
|
-
CSV.open(csv_name, "w+", :
|
|
818
|
-
csv << [
|
|
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
|
|
821
|
-
csv <<
|
|
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(
|
|
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
|
-
|
|
852
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
838
853
|
xml.doc.tag_suffix = @tag_suffix
|
|
839
|
-
|
|
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] ||=
|
|
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] +
|
|
851
|
-
item[:desc_fr] = item[:name_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,169 +870,166 @@ module Oddb2xml
|
|
|
856
870
|
end
|
|
857
871
|
end
|
|
858
872
|
xml.ARTICLE(XML_OPTIONS) {
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
|
880
|
+
ppac = nil # Packungen
|
|
868
881
|
ean = obj[:ean13]
|
|
869
|
-
next if pack_info
|
|
870
|
-
next if 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
|
|
876
|
-
|
|
877
|
-
pac = @items[ean][:packages][ean]
|
|
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 = ((
|
|
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(
|
|
899
|
+
xml.ART("DT" => obj[:last_change] || "") do
|
|
887
900
|
nbr_records += 1
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
901
|
+
# Ignore Lint/RequireParentheses warning on next line!
|
|
902
|
+
xml.REF_DATA obj[:refdata] || @migel[pharma_code] ? "1" : "0"
|
|
903
|
+
if obj[:pharmacode] && obj[:pharmacode].length > 0
|
|
904
|
+
xml.PHAR obj[:pharmacode]
|
|
905
|
+
elsif zur_rose
|
|
906
|
+
puts "Adding #{zur_rose[:pharmacode]} to article GTIN #{ean}"
|
|
907
|
+
xml.PHAR zur_rose[:pharmacode]
|
|
908
|
+
end
|
|
909
|
+
# xml.GRPCD
|
|
910
|
+
# xml.CDS01
|
|
911
|
+
# xml.CDS02
|
|
894
912
|
if ppac
|
|
895
|
-
xml.SMCAT
|
|
896
|
-
xml.GEN_PRODUCTION
|
|
897
|
-
xml.INSULIN_CATEGORY
|
|
898
|
-
xml.DRUG_INDEX
|
|
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?
|
|
899
917
|
end
|
|
900
|
-
if no8
|
|
901
|
-
if ean
|
|
918
|
+
if no8 && !no8.to_s.empty?
|
|
919
|
+
if ean && (ean.to_s[0..3] == "7680")
|
|
902
920
|
xml.SMNO no8.to_s
|
|
903
921
|
end
|
|
904
922
|
end
|
|
905
923
|
if ppac
|
|
906
|
-
xml.PRODNO ppac[:prodno] if ppac[:prodno]
|
|
924
|
+
xml.PRODNO ppac[:prodno] if ppac[:prodno] && !ppac[:prodno].empty?
|
|
907
925
|
end
|
|
908
|
-
#xml.HOSPCD
|
|
909
|
-
#xml.CLINCD
|
|
910
|
-
#xml.ARTTYP
|
|
926
|
+
# xml.HOSPCD
|
|
927
|
+
# xml.CLINCD
|
|
928
|
+
# xml.ARTTYP
|
|
911
929
|
if zur_rose
|
|
912
930
|
xml.VAT zur_rose[:vat]
|
|
913
931
|
end
|
|
914
932
|
emit_salecd(xml, ean, obj)
|
|
915
|
-
if pac
|
|
916
|
-
#xml.INSLIM
|
|
933
|
+
if pac && pac[:limitation_points]
|
|
934
|
+
# xml.INSLIM
|
|
917
935
|
xml.LIMPTS pac[:limitation_points] unless pac[:limitation_points].empty?
|
|
918
936
|
end
|
|
919
|
-
#xml.GRDFR
|
|
937
|
+
# xml.GRDFR
|
|
920
938
|
xml.COOL 1 if ppac && /Blutprodukte|impfstoffe/.match(ppac[:list_code])
|
|
921
|
-
#xml.TEMP
|
|
939
|
+
# xml.TEMP
|
|
922
940
|
if ean
|
|
923
|
-
flag =
|
|
941
|
+
flag = ppac && !ppac[:drug_index].empty? ? true : false
|
|
924
942
|
# as same flag
|
|
925
|
-
xml.CDBG(flag ?
|
|
926
|
-
xml.BG(flag ?
|
|
943
|
+
xml.CDBG(flag ? "Y" : "N")
|
|
944
|
+
xml.BG(flag ? "Y" : "N")
|
|
927
945
|
end
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
xml.
|
|
933
|
-
xml.
|
|
934
|
-
xml.
|
|
935
|
-
xml.
|
|
936
|
-
xml.
|
|
937
|
-
xml.
|
|
938
|
-
#xml.
|
|
939
|
-
#xml.
|
|
940
|
-
#xml.
|
|
941
|
-
#xml.IMG2
|
|
942
|
-
#xml.PCKTYPD
|
|
943
|
-
#xml.PCKTYPF
|
|
944
|
-
#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
|
|
945
959
|
if obj[:seq]
|
|
946
960
|
xml.SYN1D obj[:seq][:name_de] unless obj[:seq][:name_de].empty?
|
|
947
961
|
xml.SYN1F obj[:seq][:name_fr] unless obj[:seq][:name_fr].empty?
|
|
948
962
|
end
|
|
949
963
|
if obj[:seq]
|
|
950
964
|
case obj[:seq][:deductible]
|
|
951
|
-
when
|
|
952
|
-
when
|
|
953
|
-
else
|
|
965
|
+
when "Y" then xml.SLOPLUS 1; # 20%
|
|
966
|
+
when "N" then xml.SLOPLUS 2; # 10%
|
|
967
|
+
else xml.SLOPLUS "" # k.A.
|
|
954
968
|
end
|
|
955
969
|
end
|
|
956
|
-
#xml.NOPCS
|
|
957
|
-
#xml.HSCD
|
|
958
|
-
#xml.MINI
|
|
959
|
-
#xml.DEPCD
|
|
960
|
-
#xml.DEPOT
|
|
961
|
-
#xml.BAGSL
|
|
962
|
-
#xml.BAGSLC
|
|
963
|
-
#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
|
|
964
978
|
if obj[:stat_date]
|
|
965
|
-
xml.OUTSAL obj[:stat_date] if obj[:stat_date]
|
|
979
|
+
xml.OUTSAL obj[:stat_date] if obj[:stat_date] && !obj[:stat_date].empty?
|
|
966
980
|
end
|
|
967
|
-
#xml.STTOX
|
|
968
|
-
#xml.NOTI
|
|
969
|
-
#xml.GGL
|
|
970
|
-
#xml.CE
|
|
971
|
-
#xml.SMDAT
|
|
972
|
-
#xml.SMCDAT
|
|
973
|
-
#xml.SIST
|
|
974
|
-
#xml.ESIST
|
|
975
|
-
#xml.BIOCID
|
|
976
|
-
#xml.BAGNO
|
|
977
|
-
#xml.LIGHT
|
|
978
|
-
#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
|
|
979
993
|
xml.ARTCOMP {
|
|
980
994
|
# use ean13(gln) as COMPNO
|
|
981
|
-
xml.COMPNO obj[:company_ean] if obj[:company_ean]
|
|
982
|
-
#xml.ROLE
|
|
983
|
-
#xml.ARTNO1
|
|
984
|
-
#xml.ARTNO2
|
|
985
|
-
#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
|
|
986
1000
|
}
|
|
987
|
-
|
|
988
|
-
xml.
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
#xml.CHTYPE
|
|
996
|
-
#xml.LINENO
|
|
997
|
-
#xml.NOUNITS
|
|
998
|
-
#}
|
|
999
|
-
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]
|
|
1000
1009
|
pac[:prices].each_pair do |key, price|
|
|
1001
1010
|
xml.ARTPRI {
|
|
1002
|
-
xml.VDAT
|
|
1003
|
-
xml.PTYP
|
|
1004
|
-
xml.PRICE price[:price]
|
|
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?
|
|
1005
1014
|
}
|
|
1006
1015
|
end
|
|
1007
1016
|
end
|
|
1008
1017
|
if zur_rose
|
|
1009
1018
|
price = zur_rose[:price]
|
|
1010
1019
|
xml.ARTPRI {
|
|
1011
|
-
xml.PTYP
|
|
1020
|
+
xml.PTYP "ZURROSE"
|
|
1012
1021
|
xml.PRICE price
|
|
1013
1022
|
}
|
|
1014
1023
|
xml.ARTPRI {
|
|
1015
|
-
xml.PTYP
|
|
1024
|
+
xml.PTYP "ZURROSEPUB"
|
|
1016
1025
|
xml.PRICE zur_rose[:pub_price]
|
|
1017
1026
|
}
|
|
1018
|
-
|
|
1019
|
-
xml.
|
|
1020
|
-
|
|
1021
|
-
|
|
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
|
|
1022
1033
|
end
|
|
1023
1034
|
nincd = detect_nincd(obj)
|
|
1024
1035
|
if nincd
|
|
@@ -1029,29 +1040,29 @@ module Oddb2xml
|
|
|
1029
1040
|
end
|
|
1030
1041
|
end
|
|
1031
1042
|
xml.RESULT {
|
|
1032
|
-
xml.OK_ERROR
|
|
1043
|
+
xml.OK_ERROR "OK"
|
|
1033
1044
|
xml.NBR_RECORD nbr_records
|
|
1034
|
-
xml.ERROR_CODE
|
|
1035
|
-
xml.MESSAGE
|
|
1045
|
+
xml.ERROR_CODE ""
|
|
1046
|
+
xml.MESSAGE ""
|
|
1036
1047
|
}
|
|
1037
1048
|
}
|
|
1038
1049
|
end
|
|
1039
1050
|
Oddb2xml.log "build_article. Done #{idx} of #{@articles.size} articles. Overrode #{@overriden_salecd.size} SALECD"
|
|
1040
|
-
Oddb2xml.add_hash(
|
|
1051
|
+
Oddb2xml.add_hash(a_builder.to_xml)
|
|
1041
1052
|
end
|
|
1053
|
+
|
|
1042
1054
|
def build_fi
|
|
1043
1055
|
nbr_records = 0
|
|
1044
|
-
|
|
1056
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
1045
1057
|
xml.doc.tag_suffix = @tag_suffix
|
|
1046
|
-
datetime = Time.new.strftime('%FT%T%z')
|
|
1047
1058
|
xml.KOMPENDIUM(XML_OPTIONS) {
|
|
1048
1059
|
%w[de fr].each do |lang|
|
|
1049
|
-
infos = @infos[lang].uniq {|i| i[:monid] }
|
|
1060
|
+
infos = @infos[lang].uniq { |i| i[:monid] }
|
|
1050
1061
|
infos.each do |info|
|
|
1051
1062
|
xml.KMP(
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1063
|
+
"MONTYPE" => "fi", # only
|
|
1064
|
+
"LANG" => lang.upcase,
|
|
1065
|
+
"DT" => ""
|
|
1055
1066
|
) {
|
|
1056
1067
|
unless info[:name].empty?
|
|
1057
1068
|
xml.name info[:name]
|
|
@@ -1059,29 +1070,29 @@ module Oddb2xml
|
|
|
1059
1070
|
unless info[:owner].empty?
|
|
1060
1071
|
xml.owner info[:owner]
|
|
1061
1072
|
end
|
|
1062
|
-
xml.monid
|
|
1073
|
+
xml.monid info[:monid] unless info[:monid].empty?
|
|
1063
1074
|
xml.style { xml.cdata(info[:style]) } if info[:style]
|
|
1064
|
-
xml.paragraph { xml.cdata(Nokogiri::HTML.fragment(info[:paragraph].to_html).to_html(:
|
|
1075
|
+
xml.paragraph { xml.cdata(Nokogiri::HTML.fragment(info[:paragraph].to_html).to_html(encoding: "UTF-8")) } if info[:paragraph]
|
|
1065
1076
|
nbr_records += 1
|
|
1066
1077
|
}
|
|
1067
1078
|
end
|
|
1068
1079
|
end
|
|
1069
1080
|
xml.RESULT {
|
|
1070
|
-
xml.OK_ERROR
|
|
1081
|
+
xml.OK_ERROR "OK"
|
|
1071
1082
|
xml.NBR_RECORD nbr_records
|
|
1072
|
-
xml.ERROR_CODE
|
|
1073
|
-
xml.MESSAGE
|
|
1083
|
+
xml.ERROR_CODE ""
|
|
1084
|
+
xml.MESSAGE ""
|
|
1074
1085
|
}
|
|
1075
1086
|
}
|
|
1076
1087
|
end
|
|
1077
|
-
Oddb2xml.add_hash(
|
|
1088
|
+
Oddb2xml.add_hash(a_builder.to_xml)
|
|
1078
1089
|
end
|
|
1090
|
+
|
|
1079
1091
|
def build_fi_product
|
|
1080
1092
|
prepare_products
|
|
1081
1093
|
nbr_records = 0
|
|
1082
|
-
|
|
1094
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
1083
1095
|
xml.doc.tag_suffix = @tag_suffix
|
|
1084
|
-
datetime = Time.new.strftime('%FT%T%z')
|
|
1085
1096
|
xml.KOMPENDIUM_PRODUCT(XML_OPTIONS) {
|
|
1086
1097
|
info_index = {}
|
|
1087
1098
|
%w[de fr].each do |lang|
|
|
@@ -1090,558 +1101,581 @@ module Oddb2xml
|
|
|
1090
1101
|
end
|
|
1091
1102
|
# prod
|
|
1092
1103
|
@products.each do |ean13, prod|
|
|
1093
|
-
next unless
|
|
1104
|
+
next unless prod[:seq] && prod[:seq][:packages]
|
|
1094
1105
|
seq = prod[:seq]
|
|
1095
|
-
prod[:seq][:packages].each {
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1111
|
-
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
|
+
}
|
|
1112
1121
|
end
|
|
1122
|
+
end
|
|
1113
1123
|
xml.RESULT {
|
|
1114
|
-
xml.OK_ERROR
|
|
1124
|
+
xml.OK_ERROR "OK"
|
|
1115
1125
|
xml.NBR_RECORD nbr_records
|
|
1116
|
-
xml.ERROR_CODE
|
|
1117
|
-
xml.MESSAGE
|
|
1126
|
+
xml.ERROR_CODE ""
|
|
1127
|
+
xml.MESSAGE ""
|
|
1118
1128
|
}
|
|
1119
1129
|
}
|
|
1120
1130
|
end
|
|
1121
|
-
Oddb2xml.add_hash(
|
|
1131
|
+
Oddb2xml.add_hash(a_builder.to_xml)
|
|
1122
1132
|
end
|
|
1133
|
+
|
|
1123
1134
|
def build_company
|
|
1124
1135
|
nbr_records = 0
|
|
1125
1136
|
Oddb2xml.log "build_company #{@companies.size} companies"
|
|
1126
|
-
|
|
1137
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
1127
1138
|
xml.doc.tag_suffix = @tag_suffix
|
|
1128
|
-
datetime = Time.new.strftime('%FT%T%z')
|
|
1129
1139
|
xml.Betriebe(XML_OPTIONS) {
|
|
1130
1140
|
@companies.each do |c|
|
|
1131
|
-
xml.Betrieb(
|
|
1132
|
-
xml.GLN_Betrieb
|
|
1133
|
-
xml.Betriebsname_1
|
|
1134
|
-
xml.Betriebsname_2
|
|
1135
|
-
xml.Strasse
|
|
1136
|
-
xml.Nummer
|
|
1137
|
-
xml.PLZ
|
|
1138
|
-
xml.Ort
|
|
1139
|
-
xml.Bewilligungskanton c[:region]
|
|
1140
|
-
xml.Land
|
|
1141
|
-
xml.Betriebstyp
|
|
1142
|
-
xml.BTM_Berechtigung
|
|
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?
|
|
1143
1153
|
nbr_records += 1
|
|
1144
1154
|
}
|
|
1145
1155
|
end
|
|
1146
1156
|
xml.RESULT {
|
|
1147
|
-
xml.OK_ERROR
|
|
1157
|
+
xml.OK_ERROR "OK"
|
|
1148
1158
|
xml.NBR_RECORD nbr_records
|
|
1149
|
-
xml.ERROR_CODE
|
|
1150
|
-
xml.MESSAGE
|
|
1159
|
+
xml.ERROR_CODE ""
|
|
1160
|
+
xml.MESSAGE ""
|
|
1151
1161
|
}
|
|
1152
1162
|
}
|
|
1153
1163
|
end
|
|
1154
|
-
Oddb2xml.add_hash(
|
|
1164
|
+
Oddb2xml.add_hash(a_builder.to_xml)
|
|
1155
1165
|
end
|
|
1166
|
+
|
|
1156
1167
|
def build_person
|
|
1157
1168
|
nbr_records = 0
|
|
1158
1169
|
Oddb2xml.log "build_person #{@people.size} persons"
|
|
1159
|
-
|
|
1170
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
1160
1171
|
xml.doc.tag_suffix = @tag_suffix
|
|
1161
|
-
datetime = Time.new.strftime('%FT%T%z')
|
|
1162
1172
|
xml.Personen(XML_OPTIONS) {
|
|
1163
1173
|
@people.each do |p|
|
|
1164
|
-
xml.Person(
|
|
1165
|
-
xml.GLN_Person
|
|
1166
|
-
xml.Name
|
|
1167
|
-
xml.Vorname
|
|
1168
|
-
xml.PLZ
|
|
1169
|
-
xml.Ort
|
|
1170
|
-
xml.Bewilligungskanton p[:region]
|
|
1171
|
-
xml.Land
|
|
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?
|
|
1172
1182
|
xml.Bewilligung_Selbstdispensation p[:license] unless p[:license].empty?
|
|
1173
|
-
xml.Diplom
|
|
1174
|
-
xml.BTM_Berechtigung
|
|
1183
|
+
xml.Diplom p[:certificate] unless p[:certificate].empty?
|
|
1184
|
+
xml.BTM_Berechtigung p[:authorization] unless p[:authorization].empty?
|
|
1175
1185
|
nbr_records += 1
|
|
1176
1186
|
}
|
|
1177
1187
|
end
|
|
1178
1188
|
xml.RESULT {
|
|
1179
|
-
xml.OK_ERROR
|
|
1189
|
+
xml.OK_ERROR "OK"
|
|
1180
1190
|
xml.NBR_RECORD nbr_records
|
|
1181
|
-
xml.ERROR_CODE
|
|
1182
|
-
xml.MESSAGE
|
|
1191
|
+
xml.ERROR_CODE ""
|
|
1192
|
+
xml.MESSAGE ""
|
|
1183
1193
|
}
|
|
1184
1194
|
}
|
|
1185
1195
|
end
|
|
1186
|
-
Oddb2xml.add_hash(
|
|
1196
|
+
Oddb2xml.add_hash(a_builder.to_xml)
|
|
1187
1197
|
end
|
|
1198
|
+
|
|
1188
1199
|
def detect_nincd(de_idx)
|
|
1189
1200
|
if @lppvs[de_idx[:ean13].to_s] # LPPV
|
|
1190
1201
|
20
|
|
1191
1202
|
elsif @items[de_idx[:pharmacode]] # BAG-XML (SL/LS)
|
|
1192
1203
|
10
|
|
1193
|
-
elsif
|
|
1194
|
-
|
|
1204
|
+
elsif de_idx[:migel] || # MiGel (xls)
|
|
1205
|
+
(de_idx[:_type] == :nonpharma) # MiGel (swissindex)
|
|
1195
1206
|
13
|
|
1196
1207
|
else
|
|
1197
1208
|
# fallback via EAN
|
|
1198
1209
|
bag_entry_via_ean = @items.values.select do |item|
|
|
1199
1210
|
next unless item[:packages]
|
|
1200
|
-
item[:packages].values.
|
|
1211
|
+
item[:packages].values.count { |a_pac| a_pac[:ean13].to_s.eql?(de_idx[:ean13].to_s) } != 0
|
|
1201
1212
|
end
|
|
1202
1213
|
if bag_entry_via_ean.length > 0
|
|
1203
1214
|
10
|
|
1204
|
-
else
|
|
1205
|
-
nil
|
|
1206
1215
|
end
|
|
1207
1216
|
end
|
|
1208
1217
|
end
|
|
1209
1218
|
|
|
1210
1219
|
### --- see oddb2tdat
|
|
1211
1220
|
DAT_LEN = {
|
|
1212
|
-
:
|
|
1213
|
-
:
|
|
1214
|
-
:
|
|
1215
|
-
:
|
|
1216
|
-
:
|
|
1217
|
-
:
|
|
1218
|
-
:
|
|
1219
|
-
:
|
|
1220
|
-
:
|
|
1221
|
-
:
|
|
1222
|
-
:
|
|
1223
|
-
:
|
|
1224
|
-
:
|
|
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
|
|
1225
1234
|
}
|
|
1226
|
-
def format_price(price_str, len=6, int_len=4, frac_len=2)
|
|
1227
|
-
price = price_str.split(
|
|
1228
|
-
pre =
|
|
1229
|
-
las = ''
|
|
1230
|
-
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")
|
|
1231
1238
|
las = if price[1]
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
(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]
|
|
1241
1248
|
end
|
|
1242
|
-
|
|
1243
|
-
|
|
1249
|
+
|
|
1250
|
+
def format_date(date_str, len = 7)
|
|
1251
|
+
date = date_str.delete(".")
|
|
1244
1252
|
if date.size < len
|
|
1245
|
-
date
|
|
1253
|
+
date += "0" * (len - date.size)
|
|
1246
1254
|
end
|
|
1247
|
-
date[0,len]
|
|
1255
|
+
date[0, len]
|
|
1248
1256
|
end
|
|
1249
1257
|
|
|
1250
1258
|
# The migel name must be always 50 chars wide and in ISO 8859-1 format
|
|
1251
1259
|
def format_name(name, length)
|
|
1252
|
-
("%-#{length}s" % name)[0..length-1]
|
|
1260
|
+
("%-#{length}s" % name)[0..length - 1]
|
|
1253
1261
|
end
|
|
1262
|
+
|
|
1254
1263
|
def build_dat
|
|
1255
1264
|
prepare_articles
|
|
1256
1265
|
rows = []
|
|
1257
1266
|
@articles.each do |obj|
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
end
|
|
1301
|
-
elsif pac and pac[:prices]
|
|
1302
|
-
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]
|
|
1303
|
-
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]
|
|
1304
|
-
end
|
|
1305
|
-
row << format_name(Oddb2xml.patch_some_utf8(abez), DAT_LEN[:ABEZ])
|
|
1306
|
-
if price_exf.to_s.length > DAT_LEN[:PRMO] ||
|
|
1307
|
-
price_public.to_s.length > DAT_LEN[:PRPU]
|
|
1308
|
-
puts "Price exfactory #{price_exf} or public #{price_public} is too high to be added into transfer.dat"
|
|
1309
|
-
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))
|
|
1310
1309
|
end
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
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
|
|
1343
1352
|
end
|
|
1344
1353
|
rows.join("\n")
|
|
1345
1354
|
end
|
|
1355
|
+
|
|
1346
1356
|
def build_with_migel_dat
|
|
1347
1357
|
reset = true
|
|
1348
1358
|
prepare_articles(reset)
|
|
1349
1359
|
rows = []
|
|
1350
1360
|
@articles.each do |obj|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
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
|
|
1377
1387
|
rows.join("\n")
|
|
1378
1388
|
end
|
|
1389
|
+
|
|
1379
1390
|
def emit_salecd(xml, ean13, obj)
|
|
1380
1391
|
zur_rose = nil
|
|
1381
1392
|
if !@infos_zur_rose.empty? && ean13 && @infos_zur_rose[ean13]
|
|
1382
1393
|
zur_rose = @infos_zur_rose[ean13] # zurrose
|
|
1383
1394
|
end
|
|
1384
1395
|
nincd = detect_nincd(obj)
|
|
1385
|
-
in_refdata = !!(
|
|
1386
|
-
status =
|
|
1387
|
-
|
|
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)
|
|
1388
1403
|
msg = "Overriding status #{status} nincd #{nincd} for #{ean13} as in refdata_pharma"
|
|
1389
1404
|
# Oddb2xml.log msg
|
|
1390
1405
|
@overriden_salecd << ean13
|
|
1391
|
-
xml.SALECD(
|
|
1406
|
+
xml.SALECD("A") { xml.comment(msg) }
|
|
1392
1407
|
else
|
|
1393
|
-
xml.SALECD(status) { xml.comment(
|
|
1408
|
+
xml.SALECD(status) { xml.comment("expiry_date #{obj[:expiry_date]}") if obj[:expiry_date] }
|
|
1394
1409
|
end
|
|
1395
1410
|
end
|
|
1396
1411
|
|
|
1397
1412
|
def build_artikelstamm
|
|
1398
1413
|
@@emitted_v5_gtins = []
|
|
1399
|
-
@csv_file = CSV.open(File.join(
|
|
1400
|
-
@csv_file << [
|
|
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"]
|
|
1401
1416
|
@csv_file.sync = true
|
|
1402
1417
|
variant = "build_artikelstamm"
|
|
1403
1418
|
# @infos_zur_rose.delete_if { |key, val| val[:cmut].eql?('3') } # collect only active zur rose item
|
|
1404
1419
|
# No. Marco did not filter it, eg. 8804121 in rtikelstamm_oddb2xml_051217_v5.xm
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
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
|
|
1414
1433
|
end
|
|
1415
|
-
return '--missing--' if !name || name.empty? || name.length < 3
|
|
1416
|
-
name
|
|
1417
1434
|
end
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
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
|
|
1426
1445
|
cmd = "xml.#{field} \"#{new_value}\""
|
|
1427
1446
|
else
|
|
1428
|
-
xml
|
|
1429
|
-
cmd ="xml.#{field} \"#{new_value}\""
|
|
1447
|
+
cmd = "xml.#{field} \"#{default_value.to_s.delete('"')}\""
|
|
1430
1448
|
end
|
|
1449
|
+
eval cmd if default_value
|
|
1431
1450
|
end
|
|
1432
|
-
eval cmd if default_value
|
|
1433
1451
|
end
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
nr_items += 1
|
|
1452
|
-
Oddb2xml.log "build_artikelstamm #{ean13}: #{nr_items} of #{gtins.size} articles" if nr_items % 5000 == 0
|
|
1453
|
-
item = @items[ean13]
|
|
1454
|
-
pack_info = nil
|
|
1455
|
-
pack_info = @packs[no8] if no8 && /#{ean13}/.match(@packs[no8].to_s) # info from Packungen.xlsx from swissmedic_info
|
|
1456
|
-
next if pack_info && /Tierarzneimittel/.match(pack_info[:list_code])
|
|
1457
|
-
next if obj[:desc_de] && /ad us vet/i.match(obj[:desc_de])
|
|
1458
|
-
sequence = obj[:seq]
|
|
1459
|
-
if sequence.nil? && @packs[no8] && /#{ean13}/.match(@packs[no8].to_s)
|
|
1460
|
-
sequence = {:packages =>{ean13 => @packs[no8]}}
|
|
1461
|
-
obj[:seq] = sequence.clone
|
|
1462
|
-
end
|
|
1463
|
-
if sequence.nil? && @items[ean13] && @items[ean13][:packages][ean13]
|
|
1464
|
-
sequence = @items[ean13]
|
|
1465
|
-
end
|
|
1466
|
-
if sequence
|
|
1467
|
-
if obj[:seq] && !obj[:seq][:packages].keys.index(ean13)
|
|
1468
|
-
# puts "unable to find #{ean13} in #{obj[:seq][:packages].keys}"
|
|
1469
|
-
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
|
|
1470
1469
|
end
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
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}"
|
|
1489
1488
|
next
|
|
1490
|
-
else
|
|
1491
|
-
@@emitted_v5_gtins << pkg_gtin.clone
|
|
1492
1489
|
end
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
# maxLength for DSCR is 50 for Artikelstamm v3
|
|
1505
|
-
xml.DSCR(name) # for description for zur_rose
|
|
1506
|
-
name_fr = item[:name_fr] + ' ' + item[:desc_fr].strip + ' ' + package[:desc_fr] if package && package[:desc_fr]
|
|
1507
|
-
name_fr ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_fr] : nil
|
|
1508
|
-
# Zugelassenen Packungen has only german names
|
|
1509
|
-
name_fr ||= (obj[:name_fr] + ', ' + obj[:desc_fr]).strip if obj[:name_fr]
|
|
1510
|
-
# ZuRorse has only german names
|
|
1511
|
-
name_fr ||= (item[:name_fr] + ', ' + item[:desc_fr]) if item
|
|
1512
|
-
name_fr ||= name
|
|
1513
|
-
xml.DSCRF(name_fr)
|
|
1514
|
-
xml.COMP do # Manufacturer
|
|
1515
|
-
xml.NAME obj[:company_name]
|
|
1516
|
-
xml.GLN obj[:company_ean]
|
|
1517
|
-
end if obj[:company_name] || obj[:company_ean]
|
|
1518
|
-
pexf = ppub = nil
|
|
1519
|
-
if package[:prices]
|
|
1520
|
-
pexf ||= package[:prices][:exf_price][:price]
|
|
1521
|
-
ppub ||= package[:prices][:pub_price][:price]
|
|
1522
|
-
elsif @items[ean13] && @items[ean13][:packages] && @items[ean13][:packages][ean13] && (bag_prices = @items[ean13][:packages][ean13][:prices])
|
|
1523
|
-
pexf ||= bag_prices[:exf_price][:price]
|
|
1524
|
-
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
|
|
1525
1501
|
else
|
|
1526
|
-
|
|
1527
|
-
ppub ||= obj[:pub_price]
|
|
1502
|
+
@@emitted_v5_gtins << pkg_gtin.clone
|
|
1528
1503
|
end
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
xml.
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
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
|
|
1544
1529
|
end
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
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
|
|
1570
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"]
|
|
1571
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
|
|
1596
|
+
end
|
|
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" : ""]
|
|
1572
1605
|
end
|
|
1573
|
-
xml.PRODNO prodno if prodno
|
|
1574
|
-
csv = []
|
|
1575
|
-
@csv_file << [pkg_gtin, name, package[:unit], measure,
|
|
1576
|
-
pexf ? pexf : '',
|
|
1577
|
-
ppub ? ppub : '',
|
|
1578
|
-
prodno, atc, package[:substance_swissmedic],
|
|
1579
|
-
sequence[:org_gen_code], package[:ith_swissmedic],
|
|
1580
|
-
@items[pkg_gtin] ? 'SL' : '',
|
|
1581
|
-
]
|
|
1582
1606
|
end
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
@@emitted_v5_gtins << ean13.clone
|
|
1589
|
-
end
|
|
1590
|
-
# Set the pharmatype to 'Y' for outdated products, which are no longer found
|
|
1591
|
-
# in refdata/packungen
|
|
1592
|
-
chap70 = nil
|
|
1593
|
-
if @chapter70items.values.find {|x| x[:pharmacode] && x[:pharmacode].eql?(obj[:pharmacode])}
|
|
1594
|
-
Oddb2xml.log "found chapter #{obj[:pharmacode]}" if $VERBOSE
|
|
1595
|
-
chap70 = true
|
|
1596
|
-
end
|
|
1597
|
-
patched_pharma_type = (/^7680/.match(ean13.to_s.rjust(13, '0')) || chap70 ? 'P': 'N' )
|
|
1598
|
-
next if /^#{Oddb2xml::FAKE_GTIN_START}/.match(ean13.to_s)
|
|
1599
|
-
xml.ITEM({'PHARMATYPE' => patched_pharma_type }) do
|
|
1600
|
-
xml.GTIN ean13.to_s.rjust(13, '0')
|
|
1601
|
-
xml.PHAR obj[:pharmacode]
|
|
1602
|
-
emit_salecd(xml, ean13, obj)
|
|
1603
|
-
description = obj[:desc_de] || obj[:description] # for description for zur_rose
|
|
1604
|
-
xml.DSCR(description)
|
|
1605
|
-
xml.DSCRF(obj[:desc_fr] || '--missing--')
|
|
1606
|
-
xml.COMP do
|
|
1607
|
-
xml.GLN obj[:company_ean]
|
|
1608
|
-
end if obj[:company_ean] && !obj[:company_ean].empty?
|
|
1609
|
-
if !(obj[:price] && !obj[:price].empty?) || !(obj[:pub_price] && !obj[:pub_price].empty?)
|
|
1610
|
-
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
|
|
1611
1612
|
end
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
xml.PEXF (pexf = zur_rose_detail[:price])
|
|
1619
|
-
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
|
|
1620
1619
|
end
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
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]
|
|
1627
1668
|
end
|
|
1628
|
-
end
|
|
1629
|
-
@csv_file << [ ean13, description, '', '', pexf, ppub, '', '', '', '', '', '' ]
|
|
1630
|
-
if chap70
|
|
1631
|
-
xml.comment "Chapter70 hack"
|
|
1632
|
-
xml.SL_ENTRY 'true'
|
|
1633
|
-
xml.PRODNO obj[:pharmacode]
|
|
1634
|
-
xml.Chapter70_HACK 'true'
|
|
1635
1669
|
end
|
|
1636
1670
|
end
|
|
1637
1671
|
end
|
|
1672
|
+
@csv_file.close if @csv_file && !@csv_file.closed?
|
|
1673
|
+
nr_items
|
|
1638
1674
|
end
|
|
1639
|
-
@csv_file.close if @csv_file && !@csv_file.closed?
|
|
1640
|
-
nr_items
|
|
1641
1675
|
end
|
|
1642
1676
|
unless @prepared
|
|
1643
|
-
require
|
|
1644
|
-
Oddb2xml::Chapter70xtractor.parse
|
|
1677
|
+
require "oddb2xml/chapter_70_hack"
|
|
1678
|
+
Oddb2xml::Chapter70xtractor.parse
|
|
1645
1679
|
@chapter70items = Oddb2xml::Chapter70xtractor.items
|
|
1646
1680
|
prepare_limitations
|
|
1647
1681
|
prepare_articles
|
|
@@ -1650,33 +1684,25 @@ module Oddb2xml
|
|
|
1650
1684
|
prepare_calc_items(suppress_composition_parsing: true)
|
|
1651
1685
|
@prepared = true
|
|
1652
1686
|
@old_rose_size = @infos_zur_rose.size
|
|
1653
|
-
@infos_zur_rose.each do |ean13, value|
|
|
1654
|
-
if /^7680/.match(ean13.to_s) && @options[:artikelstamm]
|
|
1655
|
-
@infos_zur_rose.delete(ean13)
|
|
1656
|
-
end
|
|
1657
|
-
end if false
|
|
1658
|
-
@new_rose_size = @infos_zur_rose.size
|
|
1659
1687
|
end
|
|
1660
1688
|
nr_products = 0
|
|
1661
1689
|
nr_articles = 0
|
|
1662
1690
|
@nr_articles = 0
|
|
1663
1691
|
used_limitations = []
|
|
1664
|
-
Oddb2xml.log "#{variant}: Deleted #{@old_rose_size - @new_rose_size} entries from ZurRose where GTIN start with 7680 (Swissmedic)"
|
|
1665
1692
|
# Oddb2xml.log "#{variant} #{nr_products} of #{@products.size} articles and ignore #{@@gtin2ignore.size} gtins specified via #{@@ignore_file}"
|
|
1666
|
-
|
|
1693
|
+
a_builder = Nokogiri::XML::Builder.new(encoding: "utf-8") do |xml|
|
|
1667
1694
|
xml.doc.tag_suffix = @tag_suffix
|
|
1668
|
-
datetime = Time.new.strftime('%FT%T%z')
|
|
1669
1695
|
elexis_strftime_format = "%FT%T\.%L%:z"
|
|
1670
|
-
@@cumul_ver = (Date.today.year-2013)*12+Date.today.month
|
|
1671
|
-
options_xml =
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
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"
|
|
1676
1702
|
}
|
|
1677
1703
|
emitted_prodno = []
|
|
1678
1704
|
no8_to_prodno = {}
|
|
1679
|
-
@packs.collect{ |key, val| no8_to_prodno[key] = val [:prodno] }
|
|
1705
|
+
@packs.collect { |key, val| no8_to_prodno[key] = val [:prodno] }
|
|
1680
1706
|
xml.comment("Produced by #{__FILE__} version #{VERSION} at #{Time.now}")
|
|
1681
1707
|
xml.ARTIKELSTAMM(options_xml) do
|
|
1682
1708
|
xml.PRODUCTS do
|
|
@@ -1684,22 +1710,22 @@ module Oddb2xml
|
|
|
1684
1710
|
products.each do |product|
|
|
1685
1711
|
ean13 = product[0]
|
|
1686
1712
|
obj = product[1]
|
|
1687
|
-
next if /^Q/i.match(obj[:atc])
|
|
1713
|
+
next if /^Q/i.match?(obj[:atc])
|
|
1688
1714
|
ean = obj[:ean13]
|
|
1689
1715
|
sequence = obj[:seq]
|
|
1690
1716
|
sequence ||= @products[ean][:seq] if @products[ean]
|
|
1691
|
-
next unless
|
|
1692
|
-
ppac = ((
|
|
1693
|
-
prodno = ppac[:prodno] if ppac[:prodno]
|
|
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?
|
|
1694
1720
|
prodno = obj[:pharmacode] if obj[:chapter70]
|
|
1695
|
-
|
|
1696
|
-
if
|
|
1697
|
-
prodno ||=
|
|
1698
|
-
puts "Setting prodno #{prodno} for #{ean13} #{
|
|
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]}"
|
|
1699
1725
|
end
|
|
1700
1726
|
next unless prodno
|
|
1701
1727
|
next if emitted_prodno.index(prodno)
|
|
1702
|
-
sequence ||= @articles.find{|x| x[:ean13].eql?(ean)}
|
|
1728
|
+
sequence ||= @articles.find { |x| x[:ean13].eql?(ean) }
|
|
1703
1729
|
unless obj[:chapter70]
|
|
1704
1730
|
next unless sequence && (sequence[:name_de] || sequence[:desc_de])
|
|
1705
1731
|
if Oddb2xml.getEan13forProdno(prodno).size == 0 && !obj[:no8].eql?(Oddb2xml.getNo8ForEan13(ean))
|
|
@@ -1712,44 +1738,43 @@ module Oddb2xml
|
|
|
1712
1738
|
xml.PRODUCT do
|
|
1713
1739
|
xml.PRODNO prodno
|
|
1714
1740
|
if sequence
|
|
1715
|
-
xml.SALECD(
|
|
1741
|
+
xml.SALECD("A") # these products are always active!
|
|
1716
1742
|
name_de = "#{sequence[:name_de]} #{sequence[:desc_de]}".strip if sequence[:name_de]
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
name_de = sequence[:desc_de]
|
|
1722
|
-
end
|
|
1743
|
+
name_de ||= if ppac && /stk/i.match(sequence[:desc_de])
|
|
1744
|
+
ppac[:sequence_name]
|
|
1745
|
+
else
|
|
1746
|
+
sequence[:desc_de]
|
|
1723
1747
|
end
|
|
1724
1748
|
name_fr = "#{sequence[:name_fr]} #{sequence[:desc_fr]}".strip if sequence[:name_fr]
|
|
1725
1749
|
name_fr ||= (ppac && ppac[:sequence_name])
|
|
1726
|
-
override(xml, prodno, :DSCR,
|
|
1750
|
+
override(xml, prodno, :DSCR, name_de.strip)
|
|
1727
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?
|
|
1728
1755
|
end
|
|
1729
|
-
xml.ATC sequence[:atc_code] if sequence && sequence[:atc_code] && !sequence[:atc_code].empty?
|
|
1730
1756
|
if sequence && sequence[:packages] && (first_package = sequence[:packages].values.first) &&
|
|
1731
|
-
|
|
1757
|
+
(first_limitation = first_package[:limitations].first)
|
|
1732
1758
|
lim_code = first_limitation[:code]
|
|
1733
1759
|
used_limitations << lim_code unless used_limitations.index(lim_code)
|
|
1734
1760
|
xml.LIMNAMEBAG lim_code
|
|
1735
1761
|
elsif obj[:chapter70]
|
|
1736
|
-
xml.comment "Chapter70 hack"
|
|
1737
|
-
xml.SALECD(
|
|
1762
|
+
xml.comment "Chapter70 hack prodno #{prodno} #{obj[:description].encode(xml: :text).gsub("--", "-")}"
|
|
1763
|
+
xml.SALECD("A") # these products are always active!
|
|
1738
1764
|
xml.DSCR obj[:description]
|
|
1739
|
-
xml.DSCRF
|
|
1765
|
+
xml.DSCRF ""
|
|
1740
1766
|
if @limitations.index(obj[:code])
|
|
1741
1767
|
xml.LIMNAMEBAG obj[:code]
|
|
1742
1768
|
used_limitations << obj[:code]
|
|
1743
1769
|
end
|
|
1744
1770
|
end
|
|
1745
1771
|
if sequence && sequence[:substances]
|
|
1746
|
-
value =
|
|
1747
|
-
|
|
1748
|
-
value = 'Verschiedene Kombinationen'
|
|
1772
|
+
value = if sequence[:substances].size > 1
|
|
1773
|
+
"Verschiedene Kombinationen"
|
|
1749
1774
|
elsif sequence[:substances].first
|
|
1750
|
-
|
|
1775
|
+
sequence[:substances].first[:name]
|
|
1751
1776
|
else
|
|
1752
|
-
|
|
1777
|
+
obj[:sub]
|
|
1753
1778
|
end
|
|
1754
1779
|
override(xml, prodno, :SUBSTANCE, value) if value
|
|
1755
1780
|
end
|
|
@@ -1766,11 +1791,11 @@ module Oddb2xml
|
|
|
1766
1791
|
end
|
|
1767
1792
|
emitted_lim_code << lim[:code]
|
|
1768
1793
|
xml.LIMITATION do
|
|
1769
|
-
xml.comment "Chapter70 hack" if lim[:chap70]
|
|
1794
|
+
xml.comment "Chapter70 2 hack" if lim[:chap70]
|
|
1770
1795
|
xml.LIMNAMEBAG lim[:code] # original LIMCD
|
|
1771
|
-
xml.DSCR
|
|
1772
|
-
xml.DSCRF
|
|
1773
|
-
xml.LIMITATION_PTS
|
|
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)
|
|
1774
1799
|
end
|
|
1775
1800
|
end
|
|
1776
1801
|
end
|
|
@@ -1781,17 +1806,19 @@ module Oddb2xml
|
|
|
1781
1806
|
end
|
|
1782
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}"
|
|
1783
1808
|
# we don't add a SHA256 hash for each element in the article
|
|
1784
|
-
# Oddb2xml.add_hash(
|
|
1809
|
+
# Oddb2xml.add_hash(a_builder.to_xml)
|
|
1785
1810
|
# doc = REXML::Document.new( source, { :raw => :all })
|
|
1786
1811
|
# doc.write( $stdout, 0 )
|
|
1787
1812
|
lines = []
|
|
1788
|
-
lines << " - #{sprintf(
|
|
1789
|
-
lines << " - #{sprintf(
|
|
1790
|
-
lines << " - #{sprintf(
|
|
1791
|
-
lines << " - #{sprintf(
|
|
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"
|
|
1792
1817
|
@@articlestamm_v5_info_lines = lines
|
|
1793
|
-
|
|
1818
|
+
a_builder.to_xml({indent: 4, encoding: "UTF-8"})
|
|
1794
1819
|
end
|
|
1820
|
+
|
|
1821
|
+
private_class_method
|
|
1795
1822
|
def self.articlestamm_v5_info_lines
|
|
1796
1823
|
@@articlestamm_v5_info_lines
|
|
1797
1824
|
end
|