From ee6b364f81847c556f29d47310e75d6e4ac18326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Mon, 16 Jan 2023 13:37:15 +0100 Subject: [PATCH 1/6] WIP: keyword args and yaml unsafe load --- .ruby-version | 2 +- lib/orbf/rules_engine/services/fetch_and_solve.rb | 2 +- lib/orbf/rules_engine/value_object.rb | 3 ++- orbf-rules_engine.gemspec | 14 ++++++-------- spec/lib_spec.rb | 15 ++++++++------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.ruby-version b/.ruby-version index ecd7ee5..944880f 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.8 +3.2.0 diff --git a/lib/orbf/rules_engine/services/fetch_and_solve.rb b/lib/orbf/rules_engine/services/fetch_and_solve.rb index f6403e4..3e214e7 100644 --- a/lib/orbf/rules_engine/services/fetch_and_solve.rb +++ b/lib/orbf/rules_engine/services/fetch_and_solve.rb @@ -25,7 +25,7 @@ def call @exported_values = RulesEngine::Dhis2ValuesPrinter.new( solver.variables, solver.solution, - project.default_combos_ext_ids + **project.default_combos_ext_ids ).print exported_values diff --git a/lib/orbf/rules_engine/value_object.rb b/lib/orbf/rules_engine/value_object.rb index 8be420d..50449b8 100644 --- a/lib/orbf/rules_engine/value_object.rb +++ b/lib/orbf/rules_engine/value_object.rb @@ -52,6 +52,7 @@ def after_init def check_args_present!(hash) return if (hash.keys & self.class._attributes).count == self.class._attributes.count + raise "#{self.class} : incorrect number of args no such attributes: extra : #{hash.keys - self.class._attributes} missing: #{self.class._attributes - hash.keys} possible attributes: #{self.class._attributes}" end @@ -70,7 +71,7 @@ def attribute(attr) end def with(hash) - new(hash) + new(**hash) end end end diff --git a/orbf-rules_engine.gemspec b/orbf-rules_engine.gemspec index 815babc..1c3e39a 100644 --- a/orbf-rules_engine.gemspec +++ b/orbf-rules_engine.gemspec @@ -1,6 +1,4 @@ -# coding: utf-8 - -lib = File.expand_path("../lib", __FILE__) +lib = File.expand_path("lib", __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require "orbf/rules_engine/version" @@ -33,13 +31,13 @@ Gem::Specification.new do |spec| spec.add_dependency "activesupport" spec.add_dependency "colorize" - spec.add_dependency "hesabu" - spec.add_dependency "dentaku", "3.1.0" - spec.add_dependency "dhis2", "2.3.8" + spec.add_dependency "dentaku", "3.5.1" spec.add_dependency "descriptive_statistics" + spec.add_dependency "dhis2", "2.3.8" + spec.add_dependency "hesabu" + spec.add_development_dependency "allocation_stats" spec.add_development_dependency "bundler", "~> 2.3.5" - spec.add_development_dependency "ruby-prof" spec.add_development_dependency "byebug" spec.add_development_dependency "pronto" spec.add_development_dependency "pronto-flay" @@ -47,8 +45,8 @@ Gem::Specification.new do |spec| spec.add_development_dependency "pronto-simplecov" spec.add_development_dependency "rake", "~> 12.3" spec.add_development_dependency "rspec", "~> 3.0" + spec.add_development_dependency "ruby-prof" spec.add_development_dependency "simplecov" spec.add_development_dependency "stackprof" - spec.add_development_dependency "allocation_stats" spec.add_development_dependency "webmock" end diff --git a/spec/lib_spec.rb b/spec/lib_spec.rb index e9cbd59..919cb09 100644 --- a/spec/lib_spec.rb +++ b/spec/lib_spec.rb @@ -4,8 +4,12 @@ RSpec.describe "Liberia System" do let(:period) { "2016Q1" } - let(:project) { YAML.load_file(File.new("./spec/fixtures/rules_engine/lib_project.yml")) } - let(:pyramid) { YAML.load_file(File.new("./spec/fixtures/rules_engine/lib_pyramid.yml")) } + let(:project) do + YAML.unsafe_load_file( + "./spec/fixtures/rules_engine/lib_project.yml" + ) + end + let(:pyramid) { YAML.unsafe_load_file(File.new("./spec/fixtures/rules_engine/lib_pyramid.yml")) } let(:fetch_and_solve) do Orbf::RulesEngine::FetchAndSolve.new( @@ -32,7 +36,6 @@ RubyProf.start if ENV["PROF"] require "objspace" - stats = AllocationStats.new if ENV["ALLOC"] stats.trace if ENV["ALLOC"] @@ -40,9 +43,7 @@ Orbf::RulesEngine::InvoicePrinter.new(fetch_and_solve.solver.variables, fetch_and_solve.solver.solution).print stats.stop if ENV["ALLOC"] - if ENV["ALLOC"] - puts stats.allocations(alias_paths: true).group_by(:sourcefile, :sourceline, :class).at_least(100).sort_by_count.to_text - end + puts stats.allocations(alias_paths: true).group_by(:sourcefile, :sourceline, :class).at_least(100).sort_by_count.to_text if ENV["ALLOC"] result = RubyProf.stop if ENV["PROF"] if ENV["PROF"] @@ -58,7 +59,7 @@ fixture_record(fetch_and_solve.exported_values, :rules_engine, "lib_exported_values.json") # Only here to help with comparing - index_by_unique = ->(json) { + index_by_unique = lambda { |json| arr = JSON.parse(json) arr.index_by do |h| [h["period"], h["orgUnit"], h["dataElement"]] From b3841902d6c386d8686ee7ec4b80e08c8214e29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Mon, 16 Jan 2023 14:46:15 +0100 Subject: [PATCH 2/6] More arg fixing --- lib/orbf/rules_engine.rb | 22 ++++++- .../fetch_data/fetch_data_analytics.rb | 13 ++-- .../printers/dhis2_values_printer.rb | 2 +- .../rules_engine/services/fetch_and_solve.rb | 4 +- lib/orbf/rules_engine/value_object.rb | 1 + .../printers/dhis2_values_printer_spec.rb | 64 ++++++++++--------- spec/system_spec.rb | 14 ++-- 7 files changed, 71 insertions(+), 49 deletions(-) diff --git a/lib/orbf/rules_engine.rb b/lib/orbf/rules_engine.rb index b2cbfbd..21d872d 100644 --- a/lib/orbf/rules_engine.rb +++ b/lib/orbf/rules_engine.rb @@ -3,12 +3,32 @@ require "dentaku" require "json" require "dhis2" + +# TODO: bad +module Dhis2 + module Api + class Analytic < Base + class << self + def fetch_values(client, args) + params = [ + [:dimension, "ou:#{args[:organisation_units]}"], + [:dimension, "dx:#{args[:data_elements]}"], + [:dimension, "pe:#{args[:periods]}"] + ] + + client.get(resource_name, RestClient::ParamsArray.new(params)) + end + end + end + end +end + require "set" require "active_support/time" require "active_support/core_ext/enumerable" require_relative "./rules_engine/value_object" -require_relative "./rules_engine/assertions.rb" +require_relative "./rules_engine/assertions" require_relative "./rules_engine/log" require_relative "./rules_engine/services/tokenizer" require_relative "./rules_engine/services/period_converter" diff --git a/lib/orbf/rules_engine/fetch_data/fetch_data_analytics.rb b/lib/orbf/rules_engine/fetch_data/fetch_data_analytics.rb index 92a221b..bb21f78 100644 --- a/lib/orbf/rules_engine/fetch_data/fetch_data_analytics.rb +++ b/lib/orbf/rules_engine/fetch_data/fetch_data_analytics.rb @@ -11,19 +11,15 @@ def initialize(dhis2_connection, package_arguments) def call return [] if analytics_activity_states.none? - combined_response = Array(without_yearly_periods).each_slice(MAX_PERIODS_PER_FETCH).inject({}) do |result, period_slice| - puts({periods: period_slice.join(";"), - organisation_units: orgunit_ext_ids, - data_elements: data_elements}.to_json) - - analytics_response = dhis2_connection.analytics.list( + combined_response = Array(without_yearly_periods).each_slice(MAX_PERIODS_PER_FETCH).each_with_object({}) do |period_slice, result| + params = { periods: period_slice.join(";"), organisation_units: orgunit_ext_ids, data_elements: data_elements - ) + } + analytics_response = dhis2_connection.analytics.fetch_values(params) result["rows"] ||= [] result["rows"] += analytics_response["rows"] - result end map_to_data_values(combined_response).uniq @@ -38,6 +34,7 @@ def call def map_to_data_values(analytics_response) analytics_response["rows"].each_with_object([]) do |v, array| next if v[3] == "NaN" + array.push( "dataElement" => data_element_mappings[v[0]] || v[0], "period" => v[2], diff --git a/lib/orbf/rules_engine/printers/dhis2_values_printer.rb b/lib/orbf/rules_engine/printers/dhis2_values_printer.rb index d4f57d1..e909427 100644 --- a/lib/orbf/rules_engine/printers/dhis2_values_printer.rb +++ b/lib/orbf/rules_engine/printers/dhis2_values_printer.rb @@ -5,7 +5,7 @@ module RulesEngine class Dhis2ValuesPrinter attr_reader :variables, :solution, :default_category_option_combo_ext_id, :default_attribute_option_combo_ext_id - def initialize(variables, solution, default_category_option_combo_ext_id: nil, default_attribute_option_combo_ext_id: nil) + def initialize(variables:, solution:, default_category_option_combo_ext_id: nil, default_attribute_option_combo_ext_id: nil) @variables = variables @solution = solution @default_category_option_combo_ext_id = default_category_option_combo_ext_id diff --git a/lib/orbf/rules_engine/services/fetch_and_solve.rb b/lib/orbf/rules_engine/services/fetch_and_solve.rb index 3e214e7..ff293cc 100644 --- a/lib/orbf/rules_engine/services/fetch_and_solve.rb +++ b/lib/orbf/rules_engine/services/fetch_and_solve.rb @@ -23,8 +23,8 @@ def call solver.solve! @exported_values = RulesEngine::Dhis2ValuesPrinter.new( - solver.variables, - solver.solution, + variables: solver.variables, + solution: solver.solution, **project.default_combos_ext_ids ).print diff --git a/lib/orbf/rules_engine/value_object.rb b/lib/orbf/rules_engine/value_object.rb index 50449b8..04254b7 100644 --- a/lib/orbf/rules_engine/value_object.rb +++ b/lib/orbf/rules_engine/value_object.rb @@ -71,6 +71,7 @@ def attribute(attr) end def with(hash) + # TODO: perf problem here new(**hash) end end diff --git a/spec/lib/orbf/rules_engine/printers/dhis2_values_printer_spec.rb b/spec/lib/orbf/rules_engine/printers/dhis2_values_printer_spec.rb index ad2510a..c5c31d6 100644 --- a/spec/lib/orbf/rules_engine/printers/dhis2_values_printer_spec.rb +++ b/spec/lib/orbf/rules_engine/printers/dhis2_values_printer_spec.rb @@ -25,7 +25,7 @@ describe "when no variable" do it "export no values" do - expect(described_class.new([], {}).print).to eq([]) + expect(described_class.new(variables: [], solution: {}).print).to eq([]) end end @@ -36,8 +36,8 @@ end it "export no values" do result_values = described_class.new( - [variable_without_mapping], - variable_without_mapping.key => 1.5 + variables: [variable_without_mapping], + solution: { variable_without_mapping.key => 1.5 } ).print expect(result_values).to eq([]) @@ -51,8 +51,8 @@ end it "export values " do result_values = described_class.new( - [variable_with_mapping], - variable_with_mapping.key => 1.5 + variables: [variable_with_mapping], + solution: { variable_with_mapping.key => 1.5 } ).print expect(result_values).to eq( @@ -76,8 +76,8 @@ end it "export values " do result_values = described_class.new( - [variable_with_mapping], - { variable_with_mapping.key => 1.5 }, + variables: [variable_with_mapping], + solution: { variable_with_mapping.key => 1.5 }, default_category_option_combo_ext_id: "coc_id", default_attribute_option_combo_ext_id: "aoc_id" ).print @@ -152,8 +152,8 @@ def build_package(single_mapping) describe "and NO mapping configured " do it "export no values" do result_values = described_class.new( - [activity_variable_without_mapping], - activity_variable_without_mapping.key => 1.5 + variables: [activity_variable_without_mapping], + solution: { activity_variable_without_mapping.key => 1.5 } ).print expect(result_values).to eq([]) end @@ -190,8 +190,8 @@ def build_package(single_mapping) it "export decimal that are actually integer as integer" do result_values = described_class.new( - [var1, var2], - var1.key => 15, var2.key => 15 + variables: [var1, var2], + solution: { var1.key => 15, var2.key => 15 } ).print expect(result_values).to eq( [ @@ -217,9 +217,11 @@ def build_package(single_mapping) exportable_variable = variables[1] result_values = described_class.new( - variables, - activity_variable_with_exportable_formula_code.key => 15.0, - exportable_variable.key => false + variables: variables, + solution: { + activity_variable_with_exportable_formula_code.key => 15.0, + exportable_variable.key => false + } ).print expect(result_values).to eq( @@ -238,9 +240,11 @@ def build_package(single_mapping) exportable_variable = variables[1] result_values = described_class.new( - variables, - activity_variable_with_exportable_formula_code.key => 15.0, - exportable_variable.key => true + variables: variables, + solution: { + activity_variable_with_exportable_formula_code.key => 15.0, + exportable_variable.key => true + } ).print expect(result_values).to eq( @@ -300,7 +304,7 @@ def build_package(options) formulas: [ Orbf::RulesEngine::Formula.new( "quality_score", "31", "", - options + **options ), Orbf::RulesEngine::Formula.new( "exportable", "1 == 1", "" @@ -333,7 +337,7 @@ def build_package(options) describe "and mapping configured with category combo" do let(:data_element_id) { "dhis2_data_element_id" } - let(:coc_id) { "specific_coc_id"} + let(:coc_id) { "specific_coc_id" } let(:variable_with_mapping) do build_activity_variable( activity_mappings: { @@ -345,19 +349,19 @@ def build_package(options) it "export values " do result_values = described_class.new( - [variable_with_mapping], - { variable_with_mapping.key => 53 } + variables: [variable_with_mapping], + solution: { variable_with_mapping.key => 53 } ).print expect(result_values).to eq( [ { - dataElement: data_element_id, - orgUnit: "1", - period: "201603", - value: 53, - comment: variable_with_mapping.key, - categoryOptionCombo: coc_id + dataElement: data_element_id, + orgUnit: "1", + period: "201603", + value: 53, + comment: variable_with_mapping.key, + categoryOptionCombo: coc_id } ] ) @@ -366,8 +370,8 @@ def build_package(options) def expect_exported_value(variable, solution_value, expected_value, period) result_values = described_class.new( - [variable], - variable.key => solution_value + variables: [variable], + solution: { variable.key => solution_value } ).print expect(result_values).to eq( [ @@ -411,7 +415,7 @@ def build_package(options) formulas: [ Orbf::RulesEngine::Formula.new( "quality_score", "31", "", - options + **options ) ] ) diff --git a/spec/system_spec.rb b/spec/system_spec.rb index 933a4ec..ee5ab88 100644 --- a/spec/system_spec.rb +++ b/spec/system_spec.rb @@ -164,12 +164,12 @@ def build_activity_mappings(formula_code) Orbf::RulesEngine::Project.new( packages: [ Orbf::RulesEngine::Package.new( - code: :facility, - kind: :zone, - frequency: :quarterly, - activities: activities, - groupset_ext_id: "district_groupset_ext_id", - rules: [ + code: :facility, + kind: :zone, + frequency: :quarterly, + activities: activities, + groupset_ext_id: "district_groupset_ext_id", + rules: [ Orbf::RulesEngine::Rule.new( kind: :activity, formulas: [ @@ -293,7 +293,7 @@ def build_activity_mappings(formula_code) expect(solution["county_total_available_budget_for_fosa_for_2016q1"].round).to eq(121_235.0) Orbf::RulesEngine::InvoiceCliPrinter.new(solver.variables, solver.solution).print - exported_values = Orbf::RulesEngine::Dhis2ValuesPrinter.new(solver.variables, solver.solution).print + exported_values = Orbf::RulesEngine::Dhis2ValuesPrinter.new(variables: solver.variables, solution: solver.solution).print expect(exported_values).to include( dataElement: "dhis2_dataelement_id_fosa_indicators_reported_weighted", orgUnit: "14", From 028ae44214ecb39ad7de1f27c393b806e7f892b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Mon, 16 Jan 2023 15:36:47 +0100 Subject: [PATCH 3/6] Use the new Data class where possible --- .../builders/activity_variables_builder.rb | 21 +++++-------------- .../builders/indicator_expression_parser.rb | 14 +++---------- .../indicator_expression_parser_spec.rb | 10 ++++----- 3 files changed, 13 insertions(+), 32 deletions(-) diff --git a/lib/orbf/rules_engine/builders/activity_variables_builder.rb b/lib/orbf/rules_engine/builders/activity_variables_builder.rb index ebd97ca..e059cc6 100644 --- a/lib/orbf/rules_engine/builders/activity_variables_builder.rb +++ b/lib/orbf/rules_engine/builders/activity_variables_builder.rb @@ -5,17 +5,7 @@ module RulesEngine class ActivityVariablesBuilder include VariablesBuilderSupport - class ValueLookup < Orbf::RulesEngine::ValueObject - attributes :value, :is_null - - attr_reader :value, :is_null - - def initialize(value:, is_null:) - @value = value - @is_null = is_null - freeze - end - end + ValueLookup = Data.define(:value, :is_null) class << self def to_variables(package_arguments, dhis2_values) @@ -52,7 +42,8 @@ def convert(period) if using_is_null?(flattened_dependencies, state) express = expression.is_null ? "1" : "0" - array.push register_vars(package, activity.activity_code, suffix_is_null(suffixed_state), express, orgunit_id, period) + array.push register_vars(package, activity.activity_code, suffix_is_null(suffixed_state), express, + orgunit_id, period) end end end @@ -87,7 +78,7 @@ def register_vars(package, activity_code, state, expression, orgunit_id, period) def de_values(activity_state, period, dependencies) orgunits.each do |orgunit| keys = build_keys_with_yearly([orgunit.ext_id, period, activity_state.ext_id]) - if (dependencies.include?(activity_state.state+"_quarterly")) + if dependencies.include?(activity_state.state + "_quarterly") quarter = package.calendar.periods(period, "quarterly").first keys = [[orgunit.ext_id, quarter, activity_state.ext_id]] + keys end @@ -180,9 +171,7 @@ def build_keys_with_yearly(key) [orgunit, package.calendar.periods(period, "financial_july").first, de] ] - if period.include?("Q") - keys << package.calendar.periods(period, "monthly").map { |pe| [orgunit, pe, de] } - end + keys << package.calendar.periods(period, "monthly").map { |pe| [orgunit, pe, de] } if period.include?("Q") keys end diff --git a/lib/orbf/rules_engine/builders/indicator_expression_parser.rb b/lib/orbf/rules_engine/builders/indicator_expression_parser.rb index 9d1770a..b67f946 100644 --- a/lib/orbf/rules_engine/builders/indicator_expression_parser.rb +++ b/lib/orbf/rules_engine/builders/indicator_expression_parser.rb @@ -2,19 +2,11 @@ module Orbf module RulesEngine - class IndicatorExpression < Orbf::RulesEngine::ValueObject - attributes :expression, :data_element, :category_combo - attr_reader :expression, :data_element, :category_combo - def initialize(expression: nil, data_element: nil, category_combo: nil) - @expression = expression - @data_element = data_element - @category_combo = category_combo - freeze - end - end + IndicatorExpression = Data.define(:expression, :data_element, :category_combo) class UnsupportedFormulaException < StandardError attr_reader :formula, :unsupported + def initialize(formula, unsupported) @formula = formula @unsupported = unsupported @@ -46,7 +38,7 @@ def to_indicator_expression(expression) data_element_category = expression.sub('#{', "").sub("}", "") data_element, category = data_element_category.split(".").map(&:strip) IndicatorExpression.new( - expression: '#{' + expression.strip + '}', + expression: '#{' + expression.strip + "}", data_element: data_element, category_combo: category ) diff --git a/spec/lib/orbf/rules_engine/builders/indicator_expression_parser_spec.rb b/spec/lib/orbf/rules_engine/builders/indicator_expression_parser_spec.rb index cdeb31a..5efd3c8 100644 --- a/spec/lib/orbf/rules_engine/builders/indicator_expression_parser_spec.rb +++ b/spec/lib/orbf/rules_engine/builders/indicator_expression_parser_spec.rb @@ -4,17 +4,17 @@ describe 'more complex' do { '(7/100)*#{rfeqp2kdOGi.VVZyXr4y4Sv}*(45/100)*((11.2/(34.9+11.2))*#{FVJ2v5RgBgL.TfexVpwPBYN}+(34.9/(34.9+11.2))*#{a0i3MXpBmhT.kwyUVixl5ts})' => [ - Orbf::RulesEngine::IndicatorExpression.with( + Orbf::RulesEngine::IndicatorExpression.new( expression: '#{rfeqp2kdOGi.VVZyXr4y4Sv}', data_element: "rfeqp2kdOGi", category_combo: "VVZyXr4y4Sv" ), - Orbf::RulesEngine::IndicatorExpression.with( + Orbf::RulesEngine::IndicatorExpression.new( expression: '#{FVJ2v5RgBgL.TfexVpwPBYN}', data_element: "FVJ2v5RgBgL", category_combo: "TfexVpwPBYN" ), - Orbf::RulesEngine::IndicatorExpression.with( + Orbf::RulesEngine::IndicatorExpression.new( expression: '#{a0i3MXpBmhT.kwyUVixl5ts}', data_element: "a0i3MXpBmhT", category_combo: "kwyUVixl5ts" @@ -34,12 +34,12 @@ indicator_expressions = described_class.parse_expression(expression) expect(indicator_expressions).to eq( [ - Orbf::RulesEngine::IndicatorExpression.with( + Orbf::RulesEngine::IndicatorExpression.new( expression: '#{dhjgLt7EYmu.se1qWfbtkmx}', data_element: "dhjgLt7EYmu", category_combo: "se1qWfbtkmx" ), - Orbf::RulesEngine::IndicatorExpression.with( + Orbf::RulesEngine::IndicatorExpression.new( expression: '#{xtVtnuWBBLB}', data_element: "xtVtnuWBBLB", category_combo: nil From 4620544b263d76e7385ebb2a28cc3f9d5ffce361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Tue, 17 Jan 2023 09:07:03 +0100 Subject: [PATCH 4/6] Align all initialize with hash based constructor --- lib/orbf/rules_engine/data/activity.rb | 10 ++--- lib/orbf/rules_engine/data/activity_state.rb | 31 +++++++------- lib/orbf/rules_engine/data/invoice.rb | 26 ++++++------ lib/orbf/rules_engine/data/org_unit.rb | 10 ++--- lib/orbf/rules_engine/data/org_unit_group.rb | 9 +++-- .../rules_engine/data/org_unit_groupset.rb | 11 ++--- .../rules_engine/data/org_unit_with_facts.rb | 6 +-- .../rules_engine/data/package_arguments.rb | 10 ++--- lib/orbf/rules_engine/data/variable.rb | 40 +++++++++---------- lib/orbf/rules_engine/value_object.rb | 5 ++- 10 files changed, 79 insertions(+), 79 deletions(-) diff --git a/lib/orbf/rules_engine/data/activity.rb b/lib/orbf/rules_engine/data/activity.rb index 7808505..3c5d20b 100644 --- a/lib/orbf/rules_engine/data/activity.rb +++ b/lib/orbf/rules_engine/data/activity.rb @@ -7,13 +7,13 @@ class Activity < RulesEngine::ValueObject attr_reader :name, :activity_code, :activity_states - def initialize(name:, activity_code:, activity_states:) - @name = name - @activity_code = activity_code - @activity_states = activity_states + def initialize(hash) + @name = hash[:name] + @activity_code = hash[:activity_code] + @activity_states = hash[:activity_states] end - def states + def states @states ||= activity_states.map(&:state).freeze end end diff --git a/lib/orbf/rules_engine/data/activity_state.rb b/lib/orbf/rules_engine/data/activity_state.rb index c07738e..30311a1 100644 --- a/lib/orbf/rules_engine/data/activity_state.rb +++ b/lib/orbf/rules_engine/data/activity_state.rb @@ -59,12 +59,12 @@ def self.new_constant(state:, name:, formula:) def self.new_data_element(state:, name:, ext_id:, origin:, category_combo_ext_id: nil) with( - state: state, - name: name, - ext_id: ext_id, - kind: Kinds::KIND_DATA_ELEMENT, - origin: origin, - formula: nil, + state: state, + name: name, + ext_id: ext_id, + kind: Kinds::KIND_DATA_ELEMENT, + origin: origin, + formula: nil, category_combo_ext_id: category_combo_ext_id ) end @@ -80,14 +80,15 @@ def self.new_indicator(state:, name:, ext_id:, expression:, origin:) ) end - def initialize(state: nil, ext_id: nil, name: nil, kind: nil, formula: nil, origin: nil, category_combo_ext_id: nil) - @state = state - @ext_id = ext_id - @name = name - @kind = kind - @formula = formula - @origin = origin - @category_combo_ext_id = category_combo_ext_id + def initialize(*_args, **_kwargs) + hash = _args[0] + @state = hash[:state] + @ext_id = hash[:ext_id] + @name = hash[:name] + @kind = hash[:kind] + @formula = hash[:formula] + @origin = hash[:origin] + @category_combo_ext_id = hash[:category_combo_ext_id] after_init end @@ -126,7 +127,7 @@ def after_init raise "State is mandatory #{debug_info}" unless @state @state = state.to_s - Kinds.assert_valid_kind_and_formula(kind, formula,self ) + Kinds.assert_valid_kind_and_formula(kind, formula, self) Origins.assert_valid_origin(origin, self) end end diff --git a/lib/orbf/rules_engine/data/invoice.rb b/lib/orbf/rules_engine/data/invoice.rb index 31bb0bd..411e2a0 100644 --- a/lib/orbf/rules_engine/data/invoice.rb +++ b/lib/orbf/rules_engine/data/invoice.rb @@ -4,12 +4,12 @@ class ActivityItem < Orbf::RulesEngine::ValueObject attributes :activity, :solution, :problem, :substitued, :variables attr_reader :activity, :solution, :problem, :substitued, :variables - def initialize(activity: nil, solution: nil, problem: nil, substitued: nil, variables: nil) - @activity = activity - @solution = solution - @problem = problem - @substitued = substitued - @variables = variables + def initialize(hash) + @activity = hash[:activity] + @solution = hash[:solution] + @problem = hash[:problem] + @substitued = hash[:substitued] + @variables = hash[:variables] @indexed_variables = variables.index_by { |v| [v.state, v.activity_code] } freeze end @@ -23,7 +23,7 @@ def not_exported?(code) return false unless var&.formula&.exportable_formula_code val = solution[var.formula.exportable_formula_code] - val == false || val == 0 + [false, 0].include?(val) end def input?(code) @@ -44,12 +44,12 @@ class TotalItem < Orbf::RulesEngine::ValueObject attributes :key, :formula, :explanations, :value, :not_exported attr_reader :key, :formula, :explanations, :value, :not_exported - def initialize(key:nil, formula: nil, explanations: nil, value: nil, not_exported:) - @key = key - @formula = formula - @explanations = explanations - @value = value - @not_exported = not_exported + def initialize(hash) + @key = hash[:key] + @formula = hash[:formula] + @explanations = hash[:explanations] + @value = hash[:value] + @not_exported = hash[:not_exported] freeze end diff --git a/lib/orbf/rules_engine/data/org_unit.rb b/lib/orbf/rules_engine/data/org_unit.rb index 6e65d8a..3d3feee 100644 --- a/lib/orbf/rules_engine/data/org_unit.rb +++ b/lib/orbf/rules_engine/data/org_unit.rb @@ -7,11 +7,11 @@ class OrgUnit < Orbf::RulesEngine::ValueObject attr_reader :ext_id, :name, :path, :group_ext_ids, :parent_ext_ids - def initialize(ext_id:, name:, path:, group_ext_ids:) - @ext_id = ext_id - @name = name - @path = path - @group_ext_ids = group_ext_ids || [] + def initialize(hash) + @ext_id = hash[:ext_id] + @name = hash[:name] + @path = hash[:path] + @group_ext_ids = hash[:group_ext_ids] || [] end def parent_ext_ids diff --git a/lib/orbf/rules_engine/data/org_unit_group.rb b/lib/orbf/rules_engine/data/org_unit_group.rb index 6a0d3da..4d37ed1 100644 --- a/lib/orbf/rules_engine/data/org_unit_group.rb +++ b/lib/orbf/rules_engine/data/org_unit_group.rb @@ -5,10 +5,11 @@ module RulesEngine class OrgUnitGroup < Orbf::RulesEngine::ValueObject attributes :ext_id, :name, :code attr_reader :ext_id, :name, :code - def initialize(ext_id:, name:, code:) - @ext_id = ext_id - @name = name - @code = code + + def initialize(hash) + @ext_id = hash[:ext_id] + @name = hash[:name] + @code = hash[:code] end def code_downcase diff --git a/lib/orbf/rules_engine/data/org_unit_groupset.rb b/lib/orbf/rules_engine/data/org_unit_groupset.rb index 1a59c1a..b1e75f3 100644 --- a/lib/orbf/rules_engine/data/org_unit_groupset.rb +++ b/lib/orbf/rules_engine/data/org_unit_groupset.rb @@ -5,11 +5,12 @@ module RulesEngine class OrgUnitGroupset < Orbf::RulesEngine::ValueObject attributes :ext_id, :name, :group_ext_ids, :code attr_reader :ext_id, :name, :group_ext_ids, :code - def initialize(ext_id:, name:, group_ext_ids:, code:) - @ext_id = ext_id - @name = name - @group_ext_ids = group_ext_ids - @code = code + + def initialize(hash) + @ext_id = hash[:ext_id] + @name = hash[:name] + @group_ext_ids = hash[:group_ext_ids] + @code = hash[:code] freeze end end diff --git a/lib/orbf/rules_engine/data/org_unit_with_facts.rb b/lib/orbf/rules_engine/data/org_unit_with_facts.rb index 2f7988c..6fc5141 100644 --- a/lib/orbf/rules_engine/data/org_unit_with_facts.rb +++ b/lib/orbf/rules_engine/data/org_unit_with_facts.rb @@ -8,9 +8,9 @@ class OrgUnitWithFacts < Orbf::RulesEngine::ValueObject attr_reader :orgunit, :facts - def initialize(orgunit:, facts:) - @orgunit = orgunit - @facts = facts + def initialize(hash) + @orgunit = hash[:orgunit] + @facts = hash[:facts] freeze end diff --git a/lib/orbf/rules_engine/data/package_arguments.rb b/lib/orbf/rules_engine/data/package_arguments.rb index 08a3b5c..dff1fbd 100644 --- a/lib/orbf/rules_engine/data/package_arguments.rb +++ b/lib/orbf/rules_engine/data/package_arguments.rb @@ -4,11 +4,11 @@ class PackageArguments < Orbf::RulesEngine::ValueObject attributes :periods, :orgunits, :datasets_ext_ids, :package attr_reader :periods, :orgunits, :datasets_ext_ids, :package - def initialize(periods:, orgunits:, datasets_ext_ids:, package:) - @periods = periods - @orgunits = orgunits - @datasets_ext_ids = datasets_ext_ids - @package = package + def initialize(hash) + @periods = hash[:periods] + @orgunits = hash[:orgunits] + @datasets_ext_ids = hash[:datasets_ext_ids] + @package = hash[:package] freeze end end diff --git a/lib/orbf/rules_engine/data/variable.rb b/lib/orbf/rules_engine/data/variable.rb index 6ae7484..6a4c7aa 100644 --- a/lib/orbf/rules_engine/data/variable.rb +++ b/lib/orbf/rules_engine/data/variable.rb @@ -132,30 +132,26 @@ module Types ].freeze end - ATTRIBUTES = %i[key period expression type state activity_code - orgunit_ext_id formula package payment_rule exportable_variable_key - category_option_combo_ext_id - ].freeze + ATTRIBUTES = %i[key period expression type state activity_code + orgunit_ext_id formula package payment_rule exportable_variable_key + category_option_combo_ext_id].freeze attributes(*ATTRIBUTES) - attr_reader(*ATTRIBUTES) - attr_reader :dhis2_period - - def initialize(key: nil, period: nil, expression: nil, type: nil, state: nil, - activity_code: nil, orgunit_ext_id: nil, formula: nil, package: nil, payment_rule: nil, - exportable_variable_key: nil, category_option_combo_ext_id: nil) - @key = key - @period = period - @expression = expression - @type = type - @state = state - @activity_code = activity_code - @orgunit_ext_id = orgunit_ext_id - @formula = formula - @package = package - @payment_rule = payment_rule - @exportable_variable_key = exportable_variable_key - @category_option_combo_ext_id = category_option_combo_ext_id + attr_reader(*ATTRIBUTES, :dhis2_period) + + def initialize(hash) + @key = hash[:key] + @period = hash[:period] + @expression = hash[:expression] + @type = hash[:type] + @state = hash[:state] + @activity_code = hash[:activity_code] + @orgunit_ext_id = hash[:orgunit_ext_id] + @formula = hash[:formula] + @package = hash[:package] + @payment_rule = hash[:payment_rule] + @exportable_variable_key = hash[:exportable_variable_key] + @category_option_combo_ext_id = hash[:category_option_combo_ext_id] after_init end diff --git a/lib/orbf/rules_engine/value_object.rb b/lib/orbf/rules_engine/value_object.rb index 04254b7..29c4c83 100644 --- a/lib/orbf/rules_engine/value_object.rb +++ b/lib/orbf/rules_engine/value_object.rb @@ -7,7 +7,8 @@ class ValueObject class_attribute :_attributes self._attributes = [] - def initialize(hash) + def initialize(*_args, **kwargs) + hash = kwargs check_args_present!(hash) hash.each do |name, value| instance_variable_set("@#{name}", value) @@ -72,7 +73,7 @@ def attribute(attr) def with(hash) # TODO: perf problem here - new(**hash) + new(hash) end end end From c4676c756e1c411483dbd19285c825fe276e216e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Tue, 17 Jan 2023 09:08:04 +0100 Subject: [PATCH 5/6] Align all initialize with hash based constructor --- lib/orbf/rules_engine/value_object.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/orbf/rules_engine/value_object.rb b/lib/orbf/rules_engine/value_object.rb index 29c4c83..c3da454 100644 --- a/lib/orbf/rules_engine/value_object.rb +++ b/lib/orbf/rules_engine/value_object.rb @@ -7,8 +7,7 @@ class ValueObject class_attribute :_attributes self._attributes = [] - def initialize(*_args, **kwargs) - hash = kwargs + def initialize(hash) check_args_present!(hash) hash.each do |name, value| instance_variable_set("@#{name}", value) From 50608a81cb731b2f5c97364ad89c2ebfffe005e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phan=20Mestach?= Date: Tue, 17 Jan 2023 17:01:41 +0100 Subject: [PATCH 6/6] Upgrade bundler --- orbf-rules_engine.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orbf-rules_engine.gemspec b/orbf-rules_engine.gemspec index 1c3e39a..fd9c769 100644 --- a/orbf-rules_engine.gemspec +++ b/orbf-rules_engine.gemspec @@ -37,7 +37,7 @@ Gem::Specification.new do |spec| spec.add_dependency "hesabu" spec.add_development_dependency "allocation_stats" - spec.add_development_dependency "bundler", "~> 2.3.5" + spec.add_development_dependency "bundler", "~> 2.4.1" spec.add_development_dependency "byebug" spec.add_development_dependency "pronto" spec.add_development_dependency "pronto-flay"