Skip to content

Commit d02da6d

Browse files
authored
feat!: allow empty or partial data argument in ItaxCode.valid? (#26)
1 parent 121cbca commit d02da6d

File tree

4 files changed

+94
-23
lines changed

4 files changed

+94
-23
lines changed

lib/itax_code.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def decode(tax_code)
4040
# encoded from user informations.
4141
#
4242
# @param [String] tax_code The user tax code
43-
# @param [Hash] data The user attributes
43+
# @param [Hash] data The optional user attributes
4444
#
4545
# @option data [String] :surname
4646
# @option data [String] :name
@@ -49,8 +49,8 @@ def decode(tax_code)
4949
# @option data [String] :birthplace
5050
#
5151
# @return [Boolean]
52-
def valid?(tax_code, data)
53-
Validator.new(data).valid?(tax_code)
52+
def valid?(tax_code, data = {})
53+
Validator.new(tax_code, data).valid?
5454
end
5555
end
5656
end

lib/itax_code/parser.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ module ItaxCode
1313
#
1414
# @return [Hash]
1515
class Parser
16-
NoTaxCodeError = Class.new(StandardError)
17-
InvalidControlInternalNumberError = Class.new(StandardError)
18-
InvalidTaxCodeError = Class.new(StandardError)
16+
Error = Class.new(StandardError)
17+
NoTaxCodeError = Class.new(Error)
18+
InvalidControlInternalNumberError = Class.new(Error)
19+
InvalidTaxCodeError = Class.new(Error)
1920

2021
def initialize(tax_code, utils = Utils.new)
2122
@tax_code = tax_code.upcase

lib/itax_code/validator.rb

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,35 +5,76 @@ module ItaxCode
55
#
66
# @param [Hash] data The user input data
77
class Validator
8-
LENGTH = 16
8+
LENGTH = 16
9+
REQUIRED_KEYS = %i[surname name gender birthdate birthplace].freeze
910

10-
def initialize(data = {})
11-
@encoded = Encoder.new(data).encode
11+
# @param [String] tax_code The pre-computed tax code
12+
# @param [Hash] data The optional user attributes
13+
#
14+
def initialize(tax_code, data = {})
15+
@tax_code = tax_code
16+
@data = data
1217
end
1318

1419
class << self
1520
# Checks the tax code standard length against user
1621
# and business fiscal code standards.
1722
#
18-
# @param [String] code The tax code
23+
# @param [String] tax_code The tax code
1924
#
2025
# @return [true, false]
21-
def standard_length?(code)
22-
code.length == LENGTH
26+
def standard_length?(tax_code)
27+
tax_code.length == LENGTH
2328
end
2429
end
2530

26-
# Checks pre computed tax code validity against newly encoded tax code.
27-
#
28-
# @param [String] tax_code The pre-computed tax code
31+
# Checks pre-computed tax code validity against newly encoded tax code.
2932
#
3033
# @return [true, false]
31-
def valid?(tax_code)
32-
encoded[0..10] == tax_code[0..10]
34+
def valid?
35+
encoded_tax_code == tax_code
3336
end
3437

3538
private
3639

37-
attr_accessor :encoded
40+
attr_reader :tax_code, :data
41+
42+
# Encodes the tax code from the given 'data' hash, also backfilling missing information
43+
# by decoding the pre-computed tax code.
44+
#
45+
# @return [String, nil] The encoded tax code or nil if decoding the tax code fails
46+
def encoded_tax_code
47+
if partial_data?
48+
decoded_tax_code ? backfill_data! : return
49+
end
50+
51+
Encoder.new(data).encode
52+
end
53+
54+
# Decodes the given tax code to backfill possibly missing data in the 'data' hash.
55+
# If the decode fails, it means that the provided tax code is not valid.
56+
#
57+
# @return [Hash, nil] The decoded hash or nil if the tax code is not valid
58+
def decoded_tax_code
59+
@decoded_tax_code ||= begin
60+
Parser.new(tax_code).decode
61+
rescue Parser::Error
62+
nil
63+
end
64+
end
65+
66+
def partial_data?
67+
REQUIRED_KEYS.any? { |required_key| data[required_key].blank? }
68+
end
69+
70+
def backfill_data!
71+
data.tap do |hash|
72+
hash[:surname] ||= decoded_tax_code[:raw][:surname]
73+
hash[:name] ||= decoded_tax_code[:raw][:name]
74+
hash[:gender] ||= decoded_tax_code[:gender]
75+
hash[:birthdate] ||= decoded_tax_code[:birthdate]
76+
hash[:birthplace] ||= decoded_tax_code[:birthplace][:code]
77+
end
78+
end
3879
end
3980
end

test/itax_code/validator_test.rb

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,39 @@ class ValidatorTest < ActiveSupport::TestCase
1212
assert_equal %i[standard_length?], class_methods
1313
end
1414

15-
test "#valid?" do
16-
assert Validator.new(user_data).valid?("RSSMRA80A01F205X")
17-
assert_not Validator.new(user_data).valid?("RSSMRA11A01F205F")
15+
test "#valid? is truthy when data matches with the provided tax code" do
16+
assert_predicate Validator.new("RSSMRA80A01F205X", data), :valid?
1817
end
1918

20-
test "#standard_length?" do
19+
test "#valid? is truthy with matching partial and backfilled data" do
20+
data_combos.each do |data_combo|
21+
assert_predicate Validator.new("RSSMRA80A01F205X", data_combo), :valid?
22+
end
23+
end
24+
25+
test "#valid? is truthy when the tax code is valid and no data is provided" do
26+
assert_predicate Validator.new("RSSMRA80A01F205X"), :valid?
27+
end
28+
29+
test "#valid? is falsy when data don't matches with the provided tax code" do
30+
assert_not Validator.new("RSSMRA11A01F205F", data).valid?
31+
end
32+
33+
test "#valid? is falsy when the parser cannot decode the given tax code" do
34+
assert_not Validator.new("WRONG").valid?
35+
end
36+
37+
test "#standard_length? is truthy when the tax code length is 16" do
2138
assert Validator.standard_length?("RSSMRA00A01F205F")
39+
end
40+
41+
test "#standard_length? is falsy when the tax code hasn't 16 chars" do
2242
assert_not Validator.standard_length?("WRONG")
2343
end
2444

2545
private
2646

27-
def user_data
47+
def data
2848
{
2949
surname: "Rossi",
3050
name: "Mario",
@@ -33,5 +53,14 @@ def user_data
3353
birthplace: "Milano"
3454
}
3555
end
56+
57+
# Creates all the possible combinations from the 'data' hash.
58+
def data_combos
59+
(1..data.keys.size).flat_map do |size|
60+
data.keys.combination(size).map do |keys|
61+
keys.map { |key| [key, data[key]] }.to_h
62+
end
63+
end
64+
end
3665
end
3766
end

0 commit comments

Comments
 (0)