Class: Oddb2xml::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/oddb2xml/builder.rb

Constant Summary collapse

Data_dir =
File.expand_path(File.join(File.dirname(__FILE__),'..','..', 'data'))
@@article_overrides =
YAML.load_file(File.join(Data_dir, 'article_overrides.yaml'))
@@product_overrides =
YAML.load_file(File.join(Data_dir, 'product_overrides.yaml'))
@@ignore_file =
File.join(Data_dir, 'gtin2ignore.yaml')
@@gtin2ignore =
YAML.load_file(@@ignore_file)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Builder

Returns a new instance of Builder.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/oddb2xml/builder.rb', line 48

def initialize(args = {})
  @options    = args
  @subject    = nil
  @refdata    = {}
  @items      = {} # Spezailitäteniste: SL-Items from Preparations.xml in BAG, using GTINS as key
  @flags      = {}
  @lppvs      = {}
  @infos      = {}
  @packs      = {}
  @migel      = {}
  @infos_zur_rose  ||= {}
  @actions    = []
  @orphan    = []
  @ean14      = false
  @companies  = []
  @people     = []
  @tag_suffix = nil
  @pharmacode = {} # index pharmacode => item
  if block_given?
    yield self
  end
end

Instance Attribute Details

#actionsObject

Returns the value of attribute actions.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def actions
  @actions
end

#companiesObject

Returns the value of attribute companies.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def companies
  @companies
end

#ean14Object

Returns the value of attribute ean14.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def ean14
  @ean14
end

#flagsObject

Returns the value of attribute flags.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def flags
  @flags
end

#infosObject

Returns the value of attribute infos.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def infos
  @infos
end

#infos_zur_roseObject

Returns the value of attribute infos_zur_rose.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def infos_zur_rose
  @infos_zur_rose
end

#itemsObject

Returns the value of attribute items.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def items
  @items
end

#lppvsObject

Returns the value of attribute lppvs.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def lppvs
  @lppvs
end

#migelObject

Returns the value of attribute migel.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def migel
  @migel
end

#orphanObject

Returns the value of attribute orphan.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def orphan
  @orphan
end

#packsObject

Returns the value of attribute packs.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def packs
  @packs
end

#peopleObject

Returns the value of attribute people.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def people
  @people
end

#refdataObject

Returns the value of attribute refdata.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def refdata
  @refdata
end

#subjectObject

Returns the value of attribute subject.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def subject
  @subject
end

#tag_suffixObject

Returns the value of attribute tag_suffix.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def tag_suffix
  @tag_suffix
end

#xsdObject

Returns the value of attribute xsd.



42
43
44
# File 'lib/oddb2xml/builder.rb', line 42

def xsd
  @xsd
end

Instance Method Details

#check_name(obj, lang = :de) ⇒ Object

No. Marco did not filter it, eg. 8804121 in rtikelstamm_oddb2xml_051217_v5.xm



1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
# File 'lib/oddb2xml/builder.rb', line 1405

def check_name(obj, lang = :de)
  ean = obj[:ean13]
  refdata = @refdata[ean]
  if lang == :de
    name = (refdata && refdata[:desc_de]) ? refdata[:desc_de] : obj[:sequence_name]
  elsif lang == :fr
    name = (refdata && refdata[:desc_fr]) ? refdata[:desc_fr] : obj[:sequence_name]
  else
    return false
  end
  return false if !name || name.empty? || name.length < 3
  name
end

#emit_items(xml) ⇒ Object



1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
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
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
# File 'lib/oddb2xml/builder.rb', line 1434

def emit_items(xml)
  nr_items = 0
  gtins_to_article = {}
  @articles.each {|article| gtins_to_article[article[:ean13]] = article }
  sl_gtins = @items.values.collect{|x| x[:packages].keys}.flatten.uniq;
  gtins = gtins_to_article.keys + @infos_zur_rose.keys + @packs.values.collect{|x| x[:ean13]} + sl_gtins
  gtins = (gtins-@@gtin2ignore)
  gtins.sort!.uniq!
  gtins.each do |ean13|
    pac,no8 = nil,ean13.to_s[4..11] # BAG-XML(SL/LS)
    next if ean13 == 0
    obj = gtins_to_article[ean13] || @items.values.find{|x| x[:packages].keys.index(ean13) } || @infos_zur_rose[ean13]
    if obj
      obj = @packs[no8].merge(obj) if @packs[no8]
    else
      obj = @packs[no8] # obj not yet in refdata. Use data from swissmedic_package.xlsx
    end
    nr_items += 1
    Oddb2xml.log "build_article #{nr_items} of #{gtins.size} articles" if nr_items % 5000 == 0
    item = @items[ean13]
    pack_info = nil
    pack_info = @packs[no8] if no8 && /#{ean13}/.match(@packs[no8].to_s) # info from Packungen.xlsx from swissmedic_info
    next if pack_info && /Tierarzneimittel/.match(pack_info[:list_code])
    next if obj[:desc_de] && /ad us vet/i.match(obj[:desc_de])
    sequence    = obj[:seq]
    if sequence.nil? && @packs[no8] && /#{ean13}/.match(@packs[no8].to_s)
      sequence = {:packages =>{ean13 => @packs[no8]}}
      obj[:seq] = sequence.clone
    end
    if sequence.nil? && @items[ean13] && @items[ean13][:packages][ean13]
      sequence =  @items[ean13]
    end
    if sequence
      if obj[:seq] && !obj[:seq][:packages].keys.index(ean13)
        # puts "unable to find  #{ean13} in #{obj[:seq][:packages].keys}"
        next
      end
      sequence[:packages].each do |gtin, package|
        pkg_gtin = package[:ean13].clone
        if package[:no8] && (newEan13 = Oddb2xml.getEan13forNo8(package[:no8]))
          if !newEan13.eql?(pkg_gtin)
            puts "Setting #{newEan13} for #{pkg_gtin}"
            pkg_gtin = newEan13
          end
        end
        pharma_code = @refdata[pkg_gtin]
        if @refdata[pkg_gtin] && @refdata[pkg_gtin][:pharmacode]
          pharma_code = @refdata[pkg_gtin][:pharmacode]
        elsif obj[:pharmacode]
          pharma_code = obj[:pharmacode]
        elsif @infos_zur_rose[ean13]
           pharma_code = @infos_zur_rose[ean13][:pharmacode]
        end
        info = @calc_items[pkg_gtin]
        if @@emitted_v5_gtins.index(pkg_gtin)
          next
        else
          @@emitted_v5_gtins << pkg_gtin.clone
        end
        options = {'PHARMATYPE' => 'P'}
        xml.ITEM(options) do
          # require 'pry'; binding.pry if pkg_gtin.to_i == 7680665990026
          name =  item[:name_de] + ' ' +  item[:desc_de].strip + ' ' + package[:desc_de] if package && package[:desc_de]
          name ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_de] : nil
          name ||= @infos_zur_rose[ean13][:description] if @infos_zur_rose[ean13]
          name ||= obj[:name_de] + ', ' + obj[:desc_de].strip if  obj[:name_de]
          name ||= (item[:desc_de] + item[:name_de]) if item
          name ||= obj[:sequence_name]
          xml.GTIN pkg_gtin.to_s.rjust(13, '0')
          override(xml, pkg_gtin, :PHAR, pharma_code)
          xml.SALECD('A')
          # maxLength for DSCR is 50 for Artikelstamm v3
          xml.DSCR(name) # for description for zur_rose
          name_fr =  item[:name_fr] + ' ' +  item[:desc_fr].strip + ' ' + package[:desc_fr] if package && package[:desc_fr]
          name_fr ||= @refdata[pkg_gtin] ? @refdata[pkg_gtin][:desc_fr] : nil
          # Zugelassenen Packungen has only german names
          name_fr ||= (obj[:name_fr] + ', ' + obj[:desc_fr]).strip if  obj[:name_fr]
          # ZuRorse has only german names
          name_fr ||= (item[:name_fr] + ', ' + item[:desc_fr]) if item
          name_fr ||= '--missing--'
          xml.DSCRF(name_fr)
          xml.COMP  do # Manufacturer
            xml.NAME  obj[:company_name]
            xml.GLN   obj[:company_ean]
          end if obj[:company_name] || obj[:company_ean]
          pexf = ppub = nil
          if package[:prices]
            pexf ||= package[:prices][:exf_price][:price]
            ppub ||= package[:prices][:pub_price][:price]
          elsif @items[ean13] &&  @items[ean13][:packages] && @items[ean13][:packages][ean13] && (bag_prices = @items[ean13][:packages][ean13][:prices])
            pexf ||= bag_prices[:exf_price][:price]
            ppub ||= bag_prices[:pub_price][:price]
          else
            pexf ||= obj[:price]
            ppub ||= obj[:pub_price]
          end
          ppub = nil if ppub && ppub.size == 0
          pexf = nil if pexf && pexf.size == 0
          xml.PEXF pexf if pexf
          xml.PPUB ppub if ppub
          measure = ''
          if info
            # MEASSURE Measurement Unit,e.g. Pills or milliliters
            #             <DSCR>HIRUDOID Creme 3 mg/g 40 g</DSCR>
            xml.PKG_SIZE info.pkg_size.to_i if info.pkg_size
            if info.measure
              measure = info.measure
            elsif info.pkg_size && info.unit
              measure = info.pkg_size + ' ' + info.unit
            elsif info.pkg_size
              measure = info.pkg_size
            end
            xml.MEASURE   measure
            xml.MEASUREF  measure
            # Die Darreichungsform dieses Items. zB Tablette(n) oder Spritze(n)
            xml.DOSAGE_FORM  info.galenic_form.descriptions['de'] if info.galenic_form.descriptions['de']
            xml.DOSAGE_FORMF info.galenic_form.descriptions['fr'] if info.galenic_form.descriptions['fr']
          end
          xml.SL_ENTRY          'true' if sl_gtins.index(pkg_gtin)
          xml.IKSCAT            package[:swissmedic_category] if package[:swissmedic_category] && package[:swissmedic_category].length > 0
          xml.GENERIC_TYPE sequence[:org_gen_code] if sequence[:org_gen_code] && !sequence[:org_gen_code].empty?
          xml.LPPV              'true' if @lppvs[pkg_gtin.to_s] # detect_nincd
          case item[:deductible]
            when 'Y'; xml.DEDUCTIBLE 20; # 20%
            when 'N'; xml.DEDUCTIBLE 10; # 10%
          end if item && item[:deductible]
          prodno = Oddb2xml.getProdnoForEan13(pkg_gtin)
          xml.PRODNO prodno if prodno
          csv = []
          @csv_file << [pkg_gtin, name, package[:unit], measure,
                        pexf ? pexf : '',
                        ppub ? ppub : '',
                        package[:prodno],  package[:atc_code], package[:substance_swissmedic],
                        sequence[:org_gen_code],  package[:ith_swissmedic],
                        @items[pkg_gtin] ? 'SL' : '',
                        ]
        end
      end
    else # non pharma
       @csv_file << [ ean13, (obj[:desc_de] || obj[:description]), '', '',
                    obj[:price], obj[:pub_price], '', '', '', '', '', '' ]
      if @@emitted_v5_gtins.index(ean13)
        next
      else
        @@emitted_v5_gtins << ean13.clone
      end
      # Set the pharmatype to 'Y' for outdated products, which are no longer found
      # in refdata/packungen
      chap70 = nil
      if @chapter70items.values.find {|x| x[:pharmacode] && x[:pharmacode].eql?(obj[:pharmacode])}
        Oddb2xml.log "found chapter #{obj[:pharmacode]}" if $VERBOSE
        chap70 = true
      end
      patched_pharma_type = (/^7680/.match(ean13.to_s.rjust(13, '0')) || chap70 ? 'P': 'N' )
      next if /^#{Oddb2xml::FAKE_GTIN_START}/.match(ean13.to_s)
      xml.ITEM({'PHARMATYPE' => patched_pharma_type }) do
        xml.GTIN ean13.to_s.rjust(13, '0')
        xml.PHAR obj[:pharmacode]
        emit_salecd(xml, ean13, obj)
        xml.DSCR(obj[:desc_de] || obj[:description]) # for description for zur_rose
        xml.DSCRF(obj[:desc_fr] || '--missing--')
        xml.COMP  do
          xml.GLN obj[:company_ean]
        end if obj[:company_ean] && !obj[:company_ean].empty?
        xml.PEXF obj[:price]      if obj[:price] && !obj[:price].empty?
        xml.PPUB obj[:pub_price]  if obj[:pub_price] && !obj[:pub_price].empty?
        if chap70
          xml.comment "Chapter70 hack" 
          xml.SL_ENTRY 'true'
          xml.PRODNO obj[:pharmacode]
        end
      end
    end
  end
  @csv_file.close if @csv_file && !@csv_file.closed?
  nr_items
end

#emit_substance(xml, substance, emit_active = false) ⇒ Object



749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
# File 'lib/oddb2xml/builder.rb', line 749

def emit_substance(xml, substance, emit_active=false)
    xml.MORE_INFO substance.more_info if substance.more_info
    xml.SUBSTANCE_NAME substance.name
    xml.IS_ACTIVE_AGENT substance.is_active_agent if emit_active
    if substance.dose
      if substance.qty.is_a?(Float) or substance.qty.is_a?(Integer)
        xml.QTY  substance.qty
        xml.UNIT substance.unit
      else
        xml.DOSE_TEXT substance.dose.to_s
      end
    end
    if substance.chemical_substance
      xml.CHEMICAL_SUBSTANCE {
        emit_substance(xml, substance.chemical_substance)
      }
    end
    if substance.salts and substance.salts.size > 0
      xml.SALTS do
        substance.salts.each do |salt|
          xml.SALT do
            emit_substance(xml, salt)
          end
        end
      end
    end
end

#override(xml, id, field, default_value) ⇒ Object



1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
# File 'lib/oddb2xml/builder.rb', line 1418

def override(xml, id, field, default_value)
  has_overrides =  /\d{13}/.match(id.to_s) ? @@article_overrides[id.to_i] : @@product_overrides[id.to_i]
  unless (has_overrides && has_overrides[field.to_s])
    cmd = "xml.#{field} \"#{default_value.to_s.gsub('"','')}\""
  else
    new_value = has_overrides[field.to_s]
    if new_value.to_s.eql?(default_value.to_s)
      xml.comment('obsolete override')
      cmd = "xml.#{field} \"#{new_value}\""
    else
      xml.comment("override #{default_value.to_s} with")
      cmd ="xml.#{field} \"#{new_value}\""
    end
  end
  eval cmd if default_value
end

#to_dat(subject = nil) ⇒ Object



78
79
80
81
82
83
84
85
# File 'lib/oddb2xml/builder.rb', line 78

def to_dat(subject=nil)
  Oddb2xml.log  "to_dat subject #{subject ? subject.to_s :  @subject.to_s} for #{self.class}"
  if subject
    self.send('build_' + subject.to_s)
  elsif @subject
    self.send('build_' + @subject.to_s)
  end
end

#to_xml(subject = nil) ⇒ Object



70
71
72
73
74
75
76
77
# File 'lib/oddb2xml/builder.rb', line 70

def to_xml(subject=nil)
  Oddb2xml.log "to_xml subject #{subject || @subject}"
  if subject
    self.send('build_' + subject.to_s)
  elsif @subject
    self.send('build_' + @subject.to_s)
  end
end