Skip to content

Commit

Permalink
Handle charge model validation errors
Browse files Browse the repository at this point in the history
  • Loading branch information
vincent-pochet committed Sep 22, 2022
1 parent 7d212ff commit 6f6fa96
Show file tree
Hide file tree
Showing 13 changed files with 588 additions and 222 deletions.
8 changes: 5 additions & 3 deletions app/models/charge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ def validate_volume
end

def validate_charge_model(validator)
validation_result = validator.new(charge: self).validate
return if validation_result.success?
instance = validator.new(charge: self)
return if instance.valid?

validation_result.error.each { |error| errors.add(:properties, error) }
instance.result.error.messages.map { |_, codes| codes }
.flatten
.each { |code| errors.add(:properties, code) }
end
end
18 changes: 14 additions & 4 deletions app/services/charges/validators/base_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@

module Charges
module Validators
class BaseService < ::BaseService
class BaseService < BaseValidator
def initialize(charge:)
@charge = charge
@result = ::BaseService::Result.new

super(nil)
super(result)
end

def validate
# Override in subclasses
def valid?
# NOTE: override and add validation rules

if errors?
result.validation_failure!(errors: errors)
return false
end

true
end

attr_reader :result

private

attr_reader :charge
Expand Down
41 changes: 22 additions & 19 deletions app/services/charges/validators/graduated_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@
module Charges
module Validators
class GraduatedService < Charges::Validators::BaseService
def validate
errors = []

def valid?
if ranges.blank?
errors << :missing_graduated_range
return result.fail!(code: :invalid_properties, message: errors)
end

next_from_value = 0
ranges.each_with_index do |range, index|
errors << :invalid_amount unless valid_amounts?(range)
errors << :invalid_graduated_ranges unless valid_bounds?(range, index, next_from_value)

next_from_value = (range[:to_value] || 0) + 1
add_error(field: :ranges, error_code: 'missing_graduated_range')
else
next_from_value = 0
ranges.each_with_index do |range, index|
validate_amounts(range)

unless valid_bounds?(range, index, next_from_value)
add_error(field: :ranges, error_code: 'invalid_graduated_ranges')
end

next_from_value = (range[:to_value] || 0) + 1
end
end

return result.fail!(code: :invalid_properties, message: errors) if errors.present?

result
super
end

private
Expand All @@ -30,9 +28,14 @@ def ranges
charge.properties.map(&:with_indifferent_access)
end

def valid_amounts?(range)
::Validators::DecimalAmountService.new(range[:per_unit_amount]).valid_amount? &&
::Validators::DecimalAmountService.new(range[:flat_amount]).valid_amount?
def validate_amounts(range)
unless ::Validators::DecimalAmountService.new(range[:per_unit_amount]).valid_amount?
add_error(field: :per_unit_amount, error_code: 'invalid_amount')
end

unless ::Validators::DecimalAmountService.new(range[:flat_amount]).valid_amount?
add_error(field: :flat_amount, error_code: 'invalid_amount')
end
end

def valid_bounds?(range, index, next_from_value)
Expand Down
31 changes: 17 additions & 14 deletions app/services/charges/validators/package_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@
module Charges
module Validators
class PackageService < Charges::Validators::BaseService
def validate
errors = []
errors << :invalid_amount unless valid_amount?
errors << :invalid_free_units unless valid_free_units?
errors << :invalid_package_size unless valid_package_size?
def valid?
validate_amount
validate_free_units
validate_package_size

return result.fail!(code: :invalid_properties, message: errors) if errors.present?

result
super
end

private
Expand All @@ -20,24 +17,30 @@ def amount
properties['amount']
end

def valid_amount?
::Validators::DecimalAmountService.new(amount).valid_amount?
def validate_amount
return if ::Validators::DecimalAmountService.new(amount).valid_amount?

add_error(field: :amount, error_code: 'invalid_amount')
end

def package_size
properties['package_size']
end

def valid_package_size?
package_size.present? && package_size.is_a?(Integer) && package_size.positive?
def validate_package_size
return if package_size.present? && package_size.is_a?(Integer) && package_size.positive?

add_error(field: :package_size, error_code: 'invalid_package_size')
end

def free_units
properties['free_units']
end

def valid_free_units?
free_units.present? && free_units.is_a?(Integer) && free_units >= 0
def validate_free_units
return if free_units.present? && free_units.is_a?(Integer) && free_units >= 0

add_error(field: :free_units, error_code: 'invalid_free_units')
end
end
end
Expand Down
42 changes: 22 additions & 20 deletions app/services/charges/validators/percentage_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@
module Charges
module Validators
class PercentageService < Charges::Validators::BaseService
def validate
errors = []
errors << :invalid_rate unless valid_rate?
errors << :invalid_fixed_amount unless valid_fixed_amount?
errors << :invalid_free_units_per_events unless valid_free_units_per_events?
errors << :invalid_free_units_per_total_aggregation unless valid_free_units_per_total_aggregation?
def valid?
validate_rate
validate_fixed_amount
validate_free_units_per_events
validate_free_units_per_total_aggregation

return result.fail!(code: :invalid_properties, message: errors) if errors.present?

result
super
end

private
Expand All @@ -21,38 +18,43 @@ def rate
properties['rate']
end

def valid_rate?
::Validators::DecimalAmountService.new(rate).valid_positive_amount?
def validate_rate
return if ::Validators::DecimalAmountService.new(rate).valid_positive_amount?

add_error(field: :rate, error_code: 'invalid_rate')
end

def fixed_amount
properties['fixed_amount']
end

def valid_fixed_amount?
return true if fixed_amount.nil?
def validate_fixed_amount
return if fixed_amount.nil?
return if ::Validators::DecimalAmountService.new(fixed_amount).valid_amount?

::Validators::DecimalAmountService.new(fixed_amount).valid_amount?
add_error(field: :fixed_amount, error_code: 'invalid_fixed_amount')
end

def free_units_per_events
properties['free_units_per_events']
end

def valid_free_units_per_events?
return true if free_units_per_events.nil?
def validate_free_units_per_events
return if free_units_per_events.nil?
return if free_units_per_events.is_a?(Integer) && free_units_per_events.positive?

free_units_per_events.is_a?(Integer) && free_units_per_events.positive?
add_error(field: :free_units_per_events, error_code: 'invalid_free_units_per_events')
end

def free_units_per_total_aggregation
properties['free_units_per_total_aggregation']
end

def valid_free_units_per_total_aggregation?
return true if free_units_per_total_aggregation.nil?
def validate_free_units_per_total_aggregation
return if free_units_per_total_aggregation.nil?
return if ::Validators::DecimalAmountService.new(free_units_per_total_aggregation).valid_amount?

::Validators::DecimalAmountService.new(free_units_per_total_aggregation).valid_amount?
add_error(field: :free_units_per_total_aggregation, error_code: 'invalid_free_units_per_total_aggregation')
end
end
end
Expand Down
15 changes: 7 additions & 8 deletions app/services/charges/validators/standard_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@
module Charges
module Validators
class StandardService < Charges::Validators::BaseService
def validate
errors = []
errors << :invalid_amount unless valid_amount?
def valid?
validate_amount

return result.fail!(code: :invalid_properties, message: errors) if errors.present?

result
super
end

private
Expand All @@ -18,8 +15,10 @@ def amount
properties['amount']
end

def valid_amount?
::Validators::DecimalAmountService.new(amount).valid_amount?
def validate_amount
return if ::Validators::DecimalAmountService.new(amount).valid_amount?

add_error(field: :amount, error_code: 'invalid_amount')
end
end
end
Expand Down
38 changes: 19 additions & 19 deletions app/services/charges/validators/volume_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,20 @@
module Charges
module Validators
class VolumeService < Charges::Validators::BaseService
def validate
errors = []

def valid?
if ranges.blank?
errors << :missing_ranges
return result.fail!(code: :invalid_properties, message: errors)
end

next_from_value = 0
ranges.each_with_index do |range, index|
errors << :invalid_per_unit_amount unless valid_amount?(range[:per_unit_amount])
errors << :invalid_flat_amount unless valid_amount?(range[:flat_amount])
errors << :invalid_ranges unless valid_bounds?(range, index, next_from_value)

next_from_value = (range[:to_value] || 0) + 1
add_error(field: :ranges, error_code: 'missing_ranges')
else
next_from_value = 0
ranges.each_with_index do |range, index|
validate_amounts(range)
add_error(field: :ranges, error_code: 'invalid_ranges') unless valid_bounds?(range, index, next_from_value)

next_from_value = (range[:to_value] || 0) + 1
end
end

return result.fail!(code: :invalid_properties, message: errors) if errors.present?

result
super
end

private
Expand All @@ -31,8 +25,14 @@ def ranges
charge.properties['ranges']&.map(&:with_indifferent_access)
end

def valid_amount?(amount)
::Validators::DecimalAmountService.new(amount).valid_amount?
def validate_amounts(range)
unless ::Validators::DecimalAmountService.new(range[:per_unit_amount]).valid_amount?
add_error(field: :per_unit_amount, error_code: 'invalid_amount')
end

return if ::Validators::DecimalAmountService.new(range[:flat_amount]).valid_amount?

add_error(field: :flat_amount, error_code: 'invalid_amount')
end

def valid_bounds?(range, index, next_from_value)
Expand Down
Loading

0 comments on commit 6f6fa96

Please sign in to comment.