Class: ReimbursableRequest

Inherits:
Request show all
Defined in:
app/models/reimbursable_request.rb

Overview

Request that needs a reimbursement after reaching the final state

Subclasses must implement the can_have_reimbursement method.

Direct Known Subclasses

TravelSponsorship

Instance Attribute Summary

Attributes inherited from Request

#contact_phone_number, #created_at, #description, #state, #state_updated_at, #type, #updated_at, #visa_letter

Has many collapse

Has one collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Request

#event

Methods included from HasState

#active?, #assigned_roles, #can_be_destroyed?, #cancel, #editable?, #human_state_description, #human_state_guide, #in_final_state?, #in_initial_state?, #label, #notify_state, #title, #with_transitions?

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes

Class Method Details

.expenses_sum(attr = :total, requests) ⇒ Object



75
76
77
78
79
80
81
82
83
# File 'app/models/reimbursable_request.rb', line 75

def self.expenses_sum(attr = :total, requests)
  amount_field = :"#{attr}_amount"
  r_ids = if requests.is_a?(ActiveRecord::Relation)
            requests.reorder('').pluck('requests.id')
          else
            requests.map { |i| i.is_a?(Integer) ? i : i.id }
          end
  RequestExpense.by_attr_for_requests(attr, r_ids).sum(amount_field)
end

Instance Method Details

#can_cancel?Boolean

Checks whether can have a transition to 'canceled' state

Overrides the HasState.can_cancel?, preventing cancelation of requests that already have an active reimbursement return [Boolean] true if #cancel can be called

Returns:

  • (Boolean)

See Also:



42
43
44
# File 'app/models/reimbursable_request.rb', line 42

def can_cancel?
  !canceled? && (reimbursement.nil? || !reimbursement.active?)
end

#expensesActiveRecord::Relation<RequestExpense>

Estimated expenses, including (for every expense) the estimated amount, the amount of the help that the corresponding committee aproves, the amount finally expended and the amount that is going to be reimbursed

Returns:

See Also:



12
13
14
15
# File 'app/models/reimbursable_request.rb', line 12

has_many :expenses, class_name: 'RequestExpense',
foreign_key: 'request_id',
inverse_of: :request,
dependent: :destroy

#expenses_sum(attr = :total) ⇒ ActiveSupport::OrderedHash

Summarizes one of the xxx_amount attributes from the request's expenses grouping it by currency.

A value of nil for the amount is ignored (the currency will not be present in the result if all related amounts are nil), but zeros are counted (so the currency will be present even if all the corresponding amounts are 0.0).

All the calculations are done in pure ruby (no SQL involved), so be sure to use includes(:expenses) when using it through an ActiveRecord::Relation

Parameters:

  • attr (Symbol) (defaults to: :total)

    Attribute to summarize, can be :estimated, :approved, :total or :authorized

Returns:

  • (ActiveSupport::OrderedHash)

    with currencies as keys and sums as value, ordered by currencies' alphabetic order



68
69
70
71
72
73
# File 'app/models/reimbursable_request.rb', line 68

def expenses_sum(attr = :total)
  grouped = expenses.group_by(&:"#{attr}_currency")
  nonils = grouped.each_value { |v| v.delete_if { |i| i.send(:"#{attr}_amount").nil? } }.delete_if { |_k, v| v.empty? }
  unordered = nonils.map { |k, v| [k, v.sum(&:"#{attr}_amount")] }
  ActiveSupport::OrderedHash[unordered.sort_by(&:first)]
end

#lacks_reimbursement?Boolean

Checks whether a request is ready for reimbursement but the process have not yet started

Returns:

  • (Boolean)

    if there is no associated reimbursement



50
51
52
# File 'app/models/reimbursable_request.rb', line 50

def lacks_reimbursement?
  can_have_reimbursement? && (reimbursement.nil? || reimbursement.new_record?)
end

#no_expenses?Boolean

Checks is expenses.empty?

This one line method is required in order to the Graphviz automatic documentation to work, because it doesn't work if a string is used in the :unless parameter of a event definition

Returns:

  • (Boolean)


31
32
33
# File 'app/models/reimbursable_request.rb', line 31

def no_expenses?
  expenses.empty?
end

#reimbursementReimbursement

Every accepted request is followed by a reimbursement process



18
19
20
# File 'app/models/reimbursable_request.rb', line 18

has_one :reimbursement, inverse_of: :request,
foreign_key: 'request_id',
dependent: :restrict_with_exception