Class: CalculationService

Inherits:
Object
  • Object
show all
Defined in:
app/services/calculation_service.rb

Overview

The primary interface for the calculator

This class is used with sanitized data in the form of a hash

The second example shows that there is not a definitive answer yet, and further fields are required as specified in the correct order in 'fields_required' also 'required_fields_affecting_likelihood' lists any fields remaining that will affect the Yes/No result. This allows the front end to inform the user upon a partial success that it depends on them providing the listed fields.

Examples:

Example usage for a complete calculation with no further info needed:

inputs = {
  marital_status: 'single',
  fee: 1000.0,
  date_of_birth: Date.parse('1 December 2000'),
  disposable_capital: 10000.0,
  benefits_received: [],
  number_of_children: 2,
  total_income: 10000.0
}
service = CalculationService.call(inputs)
service.help_not_available? # => true
service.help_available? # => false
service.messages # => [{ key: :likely, source: :disposable_capital }]
service.fields_required # => []
service.required_fields_affecting_likelihood  # => []

Example usage for a partial calculation with more fields to fill in

inputs = {
  marital_status: 'single',
  fee: 1000.0,
}
service = CalculationService.call(inputs)
service.help_not_available? # => false
service.help_available? # => false
service.messages # => [{ key: :likely, source: :disposable_capital }]
service.fields_required # => [:date_of_birth, :disposable_capital, :benefits_received,
                              :number_of_children, :total_income]
service.required_fields_affecting_likelihood  # => [:date_of_birth, :disposable_capital,
                                                    :benefits_received, :total_income]

Constant Summary collapse

MY_FIELDS =
[:marital_status].freeze
FIELDS_AFFECTING_LIKELIHOOD =
[:date_of_birth, :disposable_capital, :benefits_received, :total_income].freeze
DEFAULT_CALCULATORS =
[
  'DisposableCapital',
  'BenefitsReceived',
  'HouseholdIncome'
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(inputs, calculators: default_calculators) ⇒ CalculationService

Create an instance of CalculationService


57
58
59
60
61
62
63
64
# File 'app/services/calculation_service.rb', line 57

def initialize(inputs, calculators: default_calculators)
  self.inputs = inputs.freeze
  self.available_help = :undecided
  self.final_decision_by = :none
  self.remission = 0.0
  self.messages = []
  self.calculators = calculators
end

Instance Attribute Details

#available_helpObject

Returns the value of attribute available_help


50
51
52
# File 'app/services/calculation_service.rb', line 50

def available_help
  @available_help
end

#final_decision_byObject

Returns the value of attribute final_decision_by


50
51
52
# File 'app/services/calculation_service.rb', line 50

def final_decision_by
  @final_decision_by
end

#inputsObject

Returns the value of attribute inputs


50
51
52
# File 'app/services/calculation_service.rb', line 50

def inputs
  @inputs
end

#messagesObject

Returns the value of attribute messages


50
51
52
# File 'app/services/calculation_service.rb', line 50

def messages
  @messages
end

#remissionObject

Returns the value of attribute remission


50
51
52
# File 'app/services/calculation_service.rb', line 50

def remission
  @remission
end

Class Method Details

.call(*args) ⇒ CalculationService

Performs the calculation with the given inputs and configured calculators


72
73
74
# File 'app/services/calculation_service.rb', line 72

def self.call(*args)
  new(*args).call
end

Instance Method Details

#callCalculationService

Performs the calculation with the stored inputs and configured calculators


79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/services/calculation_service.rb', line 79

def call
  # @TODO Decide what to do here and remove this comment
  # There are 2 catch blocks here which at present has little value
  # but, I am planning ahead a little in that invalid inputs might
  # want to add something to this instance in terms of messages etc..
  # but unsure right now.
  catch(:abort) do
    calculators.each do |calculator|
      my_result = catch(:invalid_inputs) do
        perform_calculation_using(calculator)
      end
      throw :abort, self if my_result.final_decision? || !my_result.valid?
    end
  end
  self
end

#fields_requiredArray<Symbol>

Indicates what fields are required to be filled in by the user - in the order the questions should be asked.

possible values are :marital_status, :fee, :date_of_birth, :disposable_capital, :benefits_received, :number_of_children, :total_income


117
118
119
120
121
122
123
124
# File 'app/services/calculation_service.rb', line 117

def fields_required
  @fields_required ||= begin
    required = calculators.map do |c|
      c.fields_required(inputs)
    end.flatten
    my_fields_required + required
  end
end

#final_decision_made?Boolean

Indicates if a calculator has made a final decision, preventing any further calculations from being done. This can be done by any calculator, but currently it is used by the disposable capital calculator as it has the right to say - no more questions this person has too much in savings.


142
143
144
# File 'app/services/calculation_service.rb', line 142

def final_decision_made?
  final_decision_by != :none
end

#required_fields_affecting_likelihoodArray<Symbol>

Indicates the fields that are required to be filled in that can change the Yes/No result. This will exclude (for example) the number_of_children fields which might just change the amount of help rather than the decision to provide help or not.


132
133
134
# File 'app/services/calculation_service.rb', line 132

def required_fields_affecting_likelihood
  FIELDS_AFFECTING_LIKELIHOOD - inputs.keys
end

#to_hHash

Provides a hash representation of the calculation result.


99
100
101
102
103
104
105
106
107
108
109
# File 'app/services/calculation_service.rb', line 99

def to_h
  {
    inputs: inputs,
    available_help: available_help,
    final_decision_by: final_decision_by,
    remission: remission,
    fields_required: fields_required,
    required_fields_affecting_likelihood: required_fields_affecting_likelihood,
    messages: messages
  }
end