From ee1de8668553bab1ce95dba5d51b0f51f0d771ad Mon Sep 17 00:00:00 2001 From: Niklaus Giger Date: Tue, 24 Jan 2017 15:30:51 +0100 Subject: [PATCH] Fix calculation of ddd_price --- Gemfile | 1 + Gemfile.lock | 2 + jobs/export_ddd_csv | 16 ++++++++ src/model/package.rb | 38 +++++++++++++---- src/plugin/csv_export.rb | 22 +++++++++- src/util/exporter.rb | 6 +++ src/util/updater.rb | 10 +++++ src/view/drugs/ddd_price.rb | 0 test/test_model/package.rb | 95 ++++++++++++++++++++++++++++++++++++++++++- test/test_model/ruby_units.rb | 28 +++++++++++++ test/test_util/exporter.rb | 7 ++++ test/test_util/updater.rb | 8 ++-- 12 files changed, 220 insertions(+), 13 deletions(-) create mode 100755 jobs/export_ddd_csv mode change 100644 => 100755 src/model/package.rb mode change 100644 => 100755 src/plugin/csv_export.rb mode change 100644 => 100755 src/util/exporter.rb mode change 100644 => 100755 src/util/updater.rb mode change 100644 => 100755 src/view/drugs/ddd_price.rb create mode 100755 test/test_model/ruby_units.rb diff --git a/Gemfile b/Gemfile index 07b59c7..988c574 100644 --- a/Gemfile +++ b/Gemfile @@ -47,6 +47,7 @@ gem 'rmagick', '2.13.4' # cannot build 2.13.2 on oddb-ci2 gem 'rpdf2txt', '0.8.4' gem 'racc' #, '1.4.11' gem 'rubyXL', '3.3.1' +gem 'ruby-units'#, :path => '/home/niklaus/git/ruby-units' gem "rubyntlm", '0.5.1' gem "rubyzip", ">= 1.1.6" , :require => 'zip' gem 'savon', '~>2.11.1' diff --git a/Gemfile.lock b/Gemfile.lock index 22e6ea7..653b621 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,6 +141,7 @@ GEM rspec-support (~> 3.5.0) rspec-support (3.5.0) ruby-ole (1.2.12) + ruby-units (2.1.0) rubyXL (3.3.1) nokogiri (>= 1.4.4) rubyzip (>= 1.1.6) @@ -257,6 +258,7 @@ DEPENDENCIES rpdf2txt (= 0.8.4) rspec rspec-core + ruby-units rubyXL (= 3.3.1) rubyntlm (= 0.5.1) rubyzip (>= 1.1.6) diff --git a/jobs/export_ddd_csv b/jobs/export_ddd_csv new file mode 100755 index 0000000..1b57bda --- /dev/null +++ b/jobs/export_ddd_csv @@ -0,0 +1,16 @@ +#!/usr/local/bin/ruby193 +# must be scheduled in crontab to run as the same user as oddb + +$: << File.expand_path('../src', File.dirname(__FILE__)) +$: << File.expand_path('..', File.dirname(__FILE__)) + +require 'util/job' +require 'util/exporter' + +module ODDB + module Util + Job.run do |system| + Updater.new(system).export_ddd_csv + end + end +end diff --git a/src/model/package.rb b/src/model/package.rb old mode 100644 new mode 100755 index 13475fc..d3cb285 --- a/src/model/package.rb +++ b/src/model/package.rb @@ -13,6 +13,7 @@ require 'model/feedback_observer' require 'model/package' require 'model/sequence' require 'model/part' +require 'ruby-units' module ODDB class PackageCommon @@ -260,12 +261,20 @@ module ODDB _ddd_price = 0.00 factor = (longevity || 1).to_f + puts "@@ddd_galforms #{@@ddd_galforms} galenic_group #{galenic_group} match #{(grp = galenic_group) && grp.match(@@ddd_galforms)}" if (grp = galenic_group) && grp.match(@@ddd_galforms) if(mdose > (ddose * factor)) - _ddd_price = (price / size.to_f) / factor + # old and wrong: _ddd_price = (price / size.to_f) / factor + if @parts.size != 1 + _ddd_price = nil + else + ddose = Unit.new(ddose.to_s.sub(' / ', '/')) + _ddd_price = (price / @parts.first.count) / factor + puts "_ddd_price 1 #{_ddd_price} = #{price} / #{size} / #{factor}" + end else - _ddd_price = (price / size.to_f) \ - * (ddose.to_f * factor / mdose.want(ddose.unit).to_f) / factor + _ddd_price = (price / size.to_f) * (ddose.to_f * factor / mdose.want(ddose.unit).to_f) / factor + puts "_ddd_price 2 #{_ddd_price} = #{price} / #{size} + #{ddose} * #{factor} ( #{mdose.want(ddose.unit)}" end else # This is valid only for the following case, for example, mdose unit: mg/ml, size unit: ml @@ -276,21 +285,34 @@ module ODDB begin if size.to_s.match(@@ddd_grmforms) unless mdose.to_g == 0 - _ddd_price = (price / ((size / mdose.to_g).to_f / ddose.to_f)) / factor + # ( 0.5 g / 40 mg/ml ) x ( 6.45 / 30 ml ) + # _ddd_price 3 0.43 = 6.45 / 30 ml / 40 mg/ml.to_g).to_f / 0.0005)) / 1.0 + # TODO: Adapt show text to this algorithm + mdose = Unit.new(dose.to_s.sub(' / ', '/')) + psize = Unit.new(size.to_s.sub(' / ', '/')) + ddose = Unit.new(ddose.to_s.sub(' / ', '/')) + # _ddd_price = price / ((mdose * psize).base / ddose.base) + _ddd_price = price * (ddose.base / ((mdose * psize).base )) + puts "_ddd_price 3 #{_ddd_price} = #{price} / size #{size} / mdose #{mdose}.to_g).to_f / ddose #{ddose})) / #{factor}" end else _ddd_price = (price / ((size * mdose).to_f / ddose.to_f)) / factor + puts "_ddd_price 4 #{_ddd_price} = #{price} / #{size} * #{mdose}.to_f / #{ddose.to_f})) / #{factor}" end - rescue StandardError + rescue StandardError => e + # require 'pry'; binding.pry + puts "ddd_price #{e} #{iksnr} pack #{ikscd} from \n#{e.backtrace[0..5].join("\n")}" end end unless _ddd_price.to_s.match(/^0.*0$/u) _ddd_price end + _ddd_price end - rescue RuntimeError - end - + rescue RuntimeError => e + # require 'pry'; binding.pry + puts "_ddd_price RuntimeError #{e} #{iksnr} pack #{ikscd} from \n#{e.backtrace[0..5].join("\n")}" + end def delete_part(oid) @parts.delete_if { |comp| comp.oid == oid } end diff --git a/src/plugin/csv_export.rb b/src/plugin/csv_export.rb old mode 100644 new mode 100755 index 4a7e415..a1fcea6 --- a/src/plugin/csv_export.rb +++ b/src/plugin/csv_export.rb @@ -147,6 +147,26 @@ module ODDB puts $!.backtrace raise end + + def export_ddd_csv + @options = { } + recipients.concat self.class::ODDB_RECIPIENTS + files = [] + @file_path = File.join EXPORT_DIR, 'ddd.csv' + CSV.open(@file_path, "a+", {:col_sep => ';', :encoding => 'UTF-8'}) do |csv| + csv << ['pharmacode;iksnr;package;atc_code,description;price_public;ddd_price'] + @app.active_packages.each do |package| + csv << [package.pharmacode, + package.iksnr, + package.ikscd, + package.atc_class ? package.atc_class.code : '', + package.name, + package.price_public, + package.ddd_price, + ] + end + end + end def export_index_therapeuticus @options = { } recipients.concat self.class::ODDB_RECIPIENTS @@ -156,7 +176,7 @@ module ODDB files.push EXPORT_SERVER.export_idx_th_csv(ids, EXPORT_DIR, 'idx_th.csv') ids = @app.packages.compact.sort_by { |pac| pac.ikskey.to_s }.collect { |pac| pac.odba_id } - files.push EXPORT_SERVER.export_ean13_idx_th_csv(ids, EXPORT_DIR, + files.push EXPORT_SERVER.export_ean13_idx_th_csv(ids, EXPORT_DIR, 'ean13_idx_th.csv') EXPORT_SERVER.compress_many(EXPORT_DIR, 'index_therapeuticus', files) end diff --git a/src/util/exporter.rb b/src/util/exporter.rb old mode 100644 new mode 100755 index 1f65fee..0b12386 --- a/src/util/exporter.rb +++ b/src/util/exporter.rb @@ -96,6 +96,12 @@ module ODDB plug.export_competition(company, db_path) plug end + def export_ddd_csv + plug = CsvExportPlugin.new(@app) + safe_export 'ddd.csv' do + plug.export_ddd_csv + end + end def export_csv plug = CsvExportPlugin.new(@app) safe_export 'oddb.csv' do diff --git a/src/util/updater.rb b/src/util/updater.rb old mode 100644 new mode 100755 index 7e684b6..83508c4 --- a/src/util/updater.rb +++ b/src/util/updater.rb @@ -91,6 +91,16 @@ module ODDB log.notify(subj) } end + def export_ddd_csv(date = @@today) + subj = 'ddd.csv' + wrap_update(CsvExportPlugin, subj) { + plug = CsvExportPlugin.new(@app) + plug.export_ddd_csv + log = Log.new(date) + log.update_values(log_info(plug)) + log.notify(subj) + } + end def export_oddb_csv(date = @@today) subj = 'oddb.csv' wrap_update(CsvExportPlugin, subj) { diff --git a/src/view/drugs/ddd_price.rb b/src/view/drugs/ddd_price.rb old mode 100644 new mode 100755 diff --git a/test/test_model/package.rb b/test/test_model/package.rb index 7a3d073..918584d 100755 --- a/test/test_model/package.rb +++ b/test/test_model/package.rb @@ -12,8 +12,8 @@ require 'stub/odba' require 'minitest/autorun' require 'model/package' +require 'model/atcclass' require 'flexmock/minitest' - module ODDB class PackageCommon check_accessor_list = { @@ -93,6 +93,7 @@ class TestPackage ODDB::Dose.new(3, 'g') + atc = flexmock :has_ddd? => true, :ddds => { 'O' => ddd } + seq = flexmock :atc_class => atc, :galenic_group => group, + :dose => ODDB::Dose.new(250, 'mg'), :longevity => nil + @package.price_public = ODDB::Util::Money.new(1.40, 'CHF') + @package.sequence = seq + part = flexmock :comparable_size => ODDB::Dose.new(12, 'Sachet(s)') + @package.parts.push part + price = @package.ddd_price + # require 'pry'; binding.pry + assert_equal ODDB::Util::Money.new(1.40, 'CHF').to_s, @package.ddd_price.to_s + end def test_delete_part part = flexmock(:oid => 4) @package.parts.push part @@ -600,4 +620,77 @@ class TestPackage [act3]) assert_equal %w{sub1 sub2 sub3}, @package.substances end + def test_ddd_Disflatyl_iksnr_52051 + @package = ODDB::Package.new('12') + @package.sequence = StubPackageSequence.new + ddd = ODDB::AtcClass::DDD.new('O') + ddd.dose = ODDB::Dose.new(0.5 , 'g') + atc = flexmock :has_ddd? => true, :ddds => { 'O' => ddd }, :code => 'A03AX13' + seq = flexmock :atc_class => atc, + :galenic_group => 'Tropfen', + :dose => ODDB::Dose.new(40, 'mg / ml'), + :longevity => nil + @package.price_public = ODDB::Util::Money.new(6.45, 'CHF') + @package.sequence = seq + assert_equal(1, atc.ddds.size) + assert_equal('O', atc.ddds.values.first.administration_route) + part = ODDB::Part.new + part.count = 1 + part.multi = 1 + part.addition = 0 + part.measure = ODDB::Dose.new('30','ml') + @package.parts.push part + assert_equal('ml', @package.parts.first.measure.unit) + assert_equal(30, @package.parts.first.measure.qty) + assert_equal('30 ml', @package.parts.first.size) + price = @package.ddd_price + assert_equal ODDB::Util::Money.new(2.69, 'CHF').to_s, @package.ddd_price.to_s + end + def test_ddd_Nitroglycerin_iksnr_36830 + @package = ODDB::Package.new('18') + @package.sequence = StubPackageSequence.new + ddd = ODDB::AtcClass::DDD.new('O') + ddd.dose = ODDB::Dose.new(5 , 'mg') + atc = flexmock :has_ddd? => true, :ddds => { 'O' => ddd }, :code => 'C01DA02' + seq = flexmock :atc_class => atc, + :galenic_group => 'Kaugummi', + :dose => ODDB::Dose.new(0.8, 'mg'), + :longevity => nil + @package.price_public = ODDB::Util::Money.new(7.4, 'CHF') + @package.sequence = seq + assert_equal(1, atc.ddds.size) + assert_equal('O', atc.ddds.values.first.administration_route) + part = ODDB::Part.new + part.count = 30 + part.multi = 1 + part.addition = 0 + part.measure = nil + @package.parts.push part + price = @package.ddd_price + assert_equal ODDB::Util::Money.new(0.77, 'CHF').to_s, @package.ddd_price.to_s + end +end + def test_ddd_Emend_iksnr_56359 + @package = ODDB::Package.new('02') + @package.sequence = StubPackageSequence.new + ddd = ODDB::AtcClass::DDD.new('O') + ddd.dose = ODDB::Dose.new(95 , 'mg') + atc = flexmock :has_ddd? => true, :ddds => { 'O' => ddd }, :code => 'C01DA02' + seq = flexmock :atc_class => atc, + :galenic_group => 'Tabletten', + :dose => ODDB::Dose.new(125, 'mg'), + :longevity => nil + @package.price_public = ODDB::Util::Money.new(103.4, 'CHF') + @package.sequence = seq + assert_equal(1, atc.ddds.size) + assert_equal('O', atc.ddds.values.first.administration_route) + part = ODDB::Part.new + part.count = 3 + part.multi = 1 + part.addition = 0 + part.measure = ODDB::Dose.new(125, 'mg') + @package.parts.push part + price = @package.ddd_price + assert_equal ODDB::Util::Money.new(34.47, 'CHF').to_s, price.to_s + end end diff --git a/test/test_model/ruby_units.rb b/test/test_model/ruby_units.rb new file mode 100755 index 0000000..0b40a0a --- /dev/null +++ b/test/test_model/ruby_units.rb @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby +$: << File.expand_path('..', File.dirname(__FILE__)) +$: << File.expand_path("../../src", File.dirname(__FILE__)) + +require 'ruby-units' +require 'util/money' +require 'minitest/autorun' +module ODDB + class TestSequence