app/validators/fee/base_fee_validator.rb
module Fee
class BaseFeeValidator < BaseValidator
def self.fields
%i[
amount
warrant_issued_date
warrant_executed_date
]
end
def self.mandatory_fields
%i[claim fee_type]
end
private
def validate_warrant_issued_date
validate_absence(:warrant_issued_date, 'present')
end
def validate_warrant_executed_date
validate_absence(:warrant_executed_date, 'present')
end
def validate_claim
validate_presence(:claim, 'blank')
end
def validate_fee_type
validate_presence(:fee_type, 'blank')
validate_agfs_fee_type_rules
end
def validate_agfs_fee_type_rules
rule_sets = Fee::AGFS::FeeTypeRules.where(unique_code: @record.fee_type&.unique_code)
Rule::Validator.new(@record, rule_sets).validate if rule_sets.present?
end
def validate_date
validate_absence(:date, 'present')
end
def validate_quantity
@actual_trial_length = trial_length
case fee_code
when 'BAF'
validate_baf_quantity
when 'PCM'
validate_pcm_quantity
when *Fee::BasicFeeType::ADDITIONAL_DAILY_ATTENDANCE_FEE_CODES
validate_daily_attendance(fee_code)
end
validate_any_quantity
end
def validate_baf_quantity
validate_numericality(:quantity, :baf_qty_numericality, 0, 1)
end
def validate_daily_attendance(code)
return if @record.quantity.zero?
options = validation_options_for_daily_attendance_code(code)
return unless options
check_for_daily_attendance_error(code, **options)
end
def validation_options_for_daily_attendance_code(code)
{
'DAF' => { min: 3, mod: -2, max: 38 },
'DAH' => { min: 41, mod: -40, max: 10 },
'DAJ' => { min: 51, mod: -50, max: nil },
'DAT' => { min: 2, mod: -1, max: nil }
}[code.to_s]
end
def check_for_daily_attendance_error(code, min:, mod:, max:)
add_error(:quantity, :"#{code.downcase}_qty_mismatch") if daf_trial_length_combination_invalid(min, mod,
max)
end
def validate_pcm_quantity
if @record.claim.supplementary? || @record.claim.case_type.try(:allow_pcmh_fee_type?)
add_error(:quantity, :pcm_numericality) if @record.quantity > 3
else
add_error(:quantity, :pcm_not_applicable) unless @record.quantity.zero? || @record.quantity.blank?
end
end
def validate_any_quantity
validate_integer_decimal
add_error(:quantity, :invalid) if @record.quantity.negative? || @record.quantity > 99_999
end
def validate_integer_decimal
return if @record.fee_type.nil? || @record.quantity.nil? || @record.quantity_is_decimal?
add_error(:quantity, :integer) unless @record.quantity.frac == 0.0
end
def validate_rate
# NOTE: this is to ensure we do not validate those fees for claims that have already been submitted
# and are before rate was re-introduced for advocate claim fees
return unless @record.try(:claim).try(:editable?)
code = fee_code
if @record.calculated?
validate_calculated_fee(code)
else
validate_uncalculated_fee(code)
end
end
def validate_calculated_fee(code)
case code
when 'BAF', 'DAF', 'DAH', 'DAJ', 'SAF', 'PCM', 'CAV', 'NDR', 'NOC'
validate_fee_rate(code)
else
validate_fee_rate
end
end
def validate_uncalculated_fee(code)
add_error(:rate, :"#{code.downcase}_must_be_blank") if @record.rate.positive?
end
# if one has a value and the other doesn't then we add error to the one that does NOT have a value
# NOTE: we have specific error messages for basic fees
def validate_fee_rate(code = nil)
if @record.quantity.positive? && @record.rate <= 0
add_error(:rate, code ? :"#{code.downcase}_invalid" : :invalid)
elsif @record.quantity <= 0 && @record.rate.positive?
add_error(:quantity, code ? :"#{code.downcase}_invalid" : :invalid)
end
end
def validate_amount
return if fee_code.nil?
return if @record.calculated?
add_error(:amount, :"#{fee_code.downcase}_invalid") if amount_outside_allowed_range?
return unless @record.quantity <= 0 && @record.amount.positive?
add_error(:quantity, :"#{fee_code.downcase}_invalid")
end
def validate_single_attendance_date
validate_presence(:date, :blank)
validate_on_or_after(@record.claim.try(:earliest_representation_order_date),
:date,
:too_long_before_earliest_reporder)
validate_on_or_after(Settings.earliest_permitted_date, :date, :check_not_too_far_in_past)
validate_not_in_future(:date)
end
# local helpers
# ---------------------
def amount_outside_allowed_range?
@record.amount.negative? || @record.amount > Settings.max_item_amount
end
def fee_code
@record.fee_type.try(:code)
end
def trial_length
@record&.claim&.trial_length || 0
end
def daf_trial_length_combination_invalid(lower_bound, trial_length_modifier, max_quantity = nil)
raise ArgumentError if trial_length_modifier.positive?
return false if daf_trial_length_ignorable?
max_quantity = infinity if max_quantity.blank?
upper_bound = [max_quantity, @actual_trial_length + trial_length_modifier].min
@actual_trial_length < lower_bound || @record.quantity > upper_bound
end
# TODO: allow hardship claims through for now?!
def daf_trial_length_ignorable?
daf_retrial_combo_ignorable || @record.claim.hardship?
end
# This is required for retrial claims created prior to retrial fields being added.
def daf_retrial_combo_ignorable
@record.claim.case_type.requires_retrial_dates? && !@record.claim.editable?
rescue StandardError
false
end
end
end