From 7fac5b3522c81d88aee9d27e7fe6edb3fe1c8a1f Mon Sep 17 00:00:00 2001 From: Samnang Chhun Date: Thu, 9 Jan 2025 14:36:29 +0700 Subject: [PATCH] Update beneficiary address rules --- .../schema_rules/beneficiary_address_rules.rb | 5 ---- .../v1/beneficiary_address_request_schema.rb | 22 ++++---------- .../v1/beneficiary_request_schema.rb | 13 ++++++++- .../beneficiary_address_validator.rb | 29 +++++++++++++++++++ ...beneficiary_address_request_schema_spec.rb | 22 ++++++++++++++ .../v1/beneficiary_request_schema_spec.rb | 8 +++++ 6 files changed, 76 insertions(+), 23 deletions(-) delete mode 100644 app/request_schemas/schema_rules/beneficiary_address_rules.rb create mode 100644 app/validators/beneficiary_address_validator.rb create mode 100644 spec/request_schemas/v1/beneficiary_address_request_schema_spec.rb diff --git a/app/request_schemas/schema_rules/beneficiary_address_rules.rb b/app/request_schemas/schema_rules/beneficiary_address_rules.rb deleted file mode 100644 index c5515466c..000000000 --- a/app/request_schemas/schema_rules/beneficiary_address_rules.rb +++ /dev/null @@ -1,5 +0,0 @@ -class BeneficiaryAddressRules - def validate(attributes) - address = attributes[:address] - end -end diff --git a/app/request_schemas/v1/beneficiary_address_request_schema.rb b/app/request_schemas/v1/beneficiary_address_request_schema.rb index b379c1203..16b37b3cc 100644 --- a/app/request_schemas/v1/beneficiary_address_request_schema.rb +++ b/app/request_schemas/v1/beneficiary_address_request_schema.rb @@ -1,7 +1,5 @@ module V1 class BeneficiaryAddressRequestSchema < JSONAPIRequestSchema - option :beneficiary_address_rules, default -> { BeneficiaryAddressRules.new } - params do required(:data).value(:hash).schema do required(:type).filled(:str?, eql?: "address") @@ -17,23 +15,13 @@ class BeneficiaryAddressRequestSchema < JSONAPIRequestSchema end end end - end - - attribute_rule do |attributes| - (4..3).each do |level| - division_attributes = [:code, :name].map { |type| :"administrative_division_level_#{level}_#{type}" } - - next if division_attributes.all? { |division_attribute| attributes[division_attribute].blank? } - - (3..2).each do |parent_level| - next if level == parent_level - - parent_division_attributes = [:code, :name].map { |type| :"administrative_division_level_#{parent_level}_#{type}" } - next if parent_division_attributes.any? { |parent_division_attribute| attributes[parent_division_attribute].present? } + attribute_rule do |attributes| + validator = BeneficiaryAddressValidator.new(attributes) + next if validator.valid? - key([:data, :attributes, parent_division_attributes.first]).failure("must be present") - break + validator.errors.each do |error| + key([ :data, :attributes, error.key ]).failure(text: error.message) end end end diff --git a/app/request_schemas/v1/beneficiary_request_schema.rb b/app/request_schemas/v1/beneficiary_request_schema.rb index 42e0f9087..82a64b3fd 100644 --- a/app/request_schemas/v1/beneficiary_request_schema.rb +++ b/app/request_schemas/v1/beneficiary_request_schema.rb @@ -29,7 +29,18 @@ class BeneficiaryRequestSchema < JSONAPIRequestSchema attribute_rule(:phone_number) do |attributes| next unless account.contacts.where_msisdn(attributes.fetch(:phone_number)).exists? - key([:data, :attributes, :phone_number]).failure(text: "must be unique") + key([ :data, :attributes, :phone_number ]).failure(text: "must be unique") + end + + attribute_rule(:address) do |attributes| + next if attributes[:address].blank? + + validator = BeneficiaryAddressValidator.new(attributes[:address]) + next if validator.valid? + + validator.errors.each do |error| + key([ :data, :attributes, :address, error.key ]).failure(text: error.message) + end end def output diff --git a/app/validators/beneficiary_address_validator.rb b/app/validators/beneficiary_address_validator.rb new file mode 100644 index 000000000..4b20877a4 --- /dev/null +++ b/app/validators/beneficiary_address_validator.rb @@ -0,0 +1,29 @@ +class BeneficiaryAddressValidator + attr_reader :attributes, :errors + + Error = Data.define(:key, :message) + + def initialize(attributes) + @attributes = attributes + @errors = [] + end + + + def valid? + 4.downto(3) do |level| + division_attributes = [ :code, :name ].map { |type| :"administrative_division_level_#{level}_#{type}" } + + next if division_attributes.all? { |division_attribute| attributes[division_attribute].blank? } + + parent_level = level - 1 + parent_division_attributes = [ :code, :name ].map { |type| :"administrative_division_level_#{parent_level}_#{type}" } + + next if parent_division_attributes.any? { |parent_division_attribute| attributes[parent_division_attribute].present? } + + errors << Error.new(key: parent_division_attributes.first, message: "must be present") + return false + end + + errors.empty? + end +end diff --git a/spec/request_schemas/v1/beneficiary_address_request_schema_spec.rb b/spec/request_schemas/v1/beneficiary_address_request_schema_spec.rb new file mode 100644 index 000000000..b06d19962 --- /dev/null +++ b/spec/request_schemas/v1/beneficiary_address_request_schema_spec.rb @@ -0,0 +1,22 @@ +require "rails_helper" + +module V1 + RSpec.describe BeneficiaryAddressRequestSchema, type: :request_schema do + it "validates the address" do + expect( + validate_schema(input_params: { data: { attributes: { iso_country_code: "KH", iso_region_code: "KH-1", administrative_division_level_2_code: "0101", administrative_division_level_3_code: "010101" } } }) + ).to have_valid_field(:data, :attributes, :administrative_division_level_2_code) + + expect( + validate_schema(input_params: { data: { attributes: { iso_country_code: "KH", iso_region_code: "KH-1", administrative_division_level_3_code: "010101" } } }) + ).not_to have_valid_field(:data, :attributes, :administrative_division_level_2_code) + end + + def validate_schema(input_params:, options: {}) + BeneficiaryAddressRequestSchema.new( + input_params:, + options: + ) + end + end +end diff --git a/spec/request_schemas/v1/beneficiary_request_schema_spec.rb b/spec/request_schemas/v1/beneficiary_request_schema_spec.rb index 79365d8e6..ffe2355cd 100644 --- a/spec/request_schemas/v1/beneficiary_request_schema_spec.rb +++ b/spec/request_schemas/v1/beneficiary_request_schema_spec.rb @@ -112,6 +112,14 @@ module V1 expect( validate_schema(input_params: { data: { attributes: { address: { iso_region_code: "KH-1" } } } }) ).to have_valid_field(:data, :attributes, :address, :iso_region_code) + + expect( + validate_schema(input_params: { data: { attributes: { address: { iso_country_code: "KH", iso_region_code: "KH-1", administrative_division_level_2_code: "0101", administrative_division_level_3_code: "010101" } } } }) + ).to have_valid_field(:data, :attributes, :address, :administrative_division_level_2_code) + + expect( + validate_schema(input_params: { data: { attributes: { address: { iso_country_code: "KH", iso_region_code: "KH-1", administrative_division_level_3_code: "010101" } } } }) + ).not_to have_valid_field(:data, :attributes, :address, :administrative_division_level_2_code) end it "validates the metadata fields attributes" do