Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ ItaxCode.decode(tax_code) #=> Hash:
# code: String, # the input code, upcased
# gender: "M" | "F",
# birthdate: String, # "YYYY-MM-DD"
# birthplace: { # nil if not found in either CSV
# birthplace: { # raises InvalidTaxCodeError if not found in either CSV
# code: String, # e.g. "F205"
# province: String, # e.g. "MI"
# name: String, # e.g. "MILANO"
Expand Down
8 changes: 5 additions & 3 deletions lib/itax_code/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ def birthplace(src = utils.cities, stop: false)
place = src.find { |item| item["code"] == birthplace_code && in_dates?(item) }

if place.nil?
birthplace(utils.countries, stop: true) unless stop
else
place.to_h.transform_keys(&:to_sym)
return birthplace(utils.countries, stop: true) unless stop

raise InvalidTaxCodeError
end

place.to_h.transform_keys(&:to_sym)
end

def birthplace_code
Expand Down
52 changes: 52 additions & 0 deletions test/itax_code/encoder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,64 @@ class EncoderTest < Minitest::Test
).encode
end

test "#encode for female gender applies +40 day offset" do
assert_equal "RSSMRA80A41F205B",
Encoder.new(
surname: "Rossi",
name: "Mario",
gender: "F",
birthdate: "1980-01-01",
birthplace: "Milano"
).encode
end

test "#encode raises MissingDataError on missing data" do
assert_raises Encoder::MissingDataError do
Encoder.new.encode
end
end

test "#encode raises MissingDataError on missing surname" do
assert_raises(Encoder::MissingDataError) do
Encoder.new(
surname: nil, name: "Mario", gender: "M", birthdate: "1980-01-01", birthplace: "Milano"
)
end
end

test "#encode raises MissingDataError on missing name" do
assert_raises(Encoder::MissingDataError) do
Encoder.new(
surname: "Rossi", name: nil, gender: "M", birthdate: "1980-01-01", birthplace: "Milano"
)
end
end

test "#encode raises MissingDataError on missing gender" do
assert_raises(Encoder::MissingDataError) do
Encoder.new(
surname: "Rossi", name: "Mario", gender: nil,
birthdate: "1980-01-01", birthplace: "Milano"
)
end
end

test "#encode raises MissingDataError on missing birthdate" do
assert_raises(Encoder::MissingDataError) do
Encoder.new(
surname: "Rossi", name: "Mario", gender: "M", birthdate: nil, birthplace: "Milano"
)
end
end

test "#encode raises MissingDataError on missing birthplace field" do
assert_raises(Encoder::MissingDataError) do
Encoder.new(
surname: "Rossi", name: "Mario", gender: "M", birthdate: "1980-01-01", birthplace: nil
)
end
end

test "#encode raises MissingDataError on missing birthplace" do
assert_raises Encoder::MissingDataError do
Encoder.new(
Expand Down
44 changes: 41 additions & 3 deletions test/itax_code/parser_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,8 @@ class ParserTest < Minitest::Test
end
end

# FIXME: This behaviour needs to be fixed, maybe by raising an InvalidTaxCodeError.
test "returns nil birthplace when the lookup on both cities and countries fails" do
assert_nil klass.new("BRRDRN70M41ZXXXE").decode[:birthplace]
test "raises InvalidTaxCodeError when birthplace code is not found in cities or countries" do
assert_raises(klass::InvalidTaxCodeError) { klass.new("BRRDRN70M41ZXXXE").decode }
end

test "raises NoTaxCodeError with an empty tax code" do
Expand Down Expand Up @@ -62,6 +61,45 @@ class ParserTest < Minitest::Test
end
end

test "raises InvalidTaxCodeError when birthdate falls outside city validity window" do
# Stub cities to expose a single F205 entry whose window excludes birthdate 1980-01-01
stub_city = { "code" => "F205", "province" => "MI", "name" => "MILANO",
"created_on" => "1960-01-01", "deleted_on" => "1975-12-31" }
Utils.stubs(:cities).returns([stub_city])
Utils.stubs(:countries).returns([])
# in_dates? returns false (1980-01-01 > deleted_on) → F205 not matched in cities
# F205 not in countries either → raises InvalidTaxCodeError
assert_raises(klass::InvalidTaxCodeError) { klass.new("RSSMRA80A01F205X").decode }
end

test "decodes a birthdate in the current year" do
Timecop.freeze(Date.parse("2026-06-01")) do
# year "26" → 20+26=2026, 2026 <= 2026 → 2026 (not 1926)
assert_equal "2026-01-01", klass.new("RSSMRA26A01L219E").decode[:birthdate]
end
end

test "decodes a birthdate as 1927 when current year is 2026 and year code is 27" do
Timecop.freeze(Date.parse("2026-06-01")) do
# year "27" → 20+27=2027, 2027 > 2026 → 2027-100 = 1927
assert_equal "1927-01-01", klass.new("RSSMRA27A01L219F").decode[:birthdate]
end
end

test "decodes day 31 as male gender with day 31" do
result = klass.new("RSSMRA80A31L219P").decode

assert_equal "M", result[:gender]
assert_equal "1980-01-31", result[:birthdate]
end

test "decodes day 41 as female gender with day 1" do
result = klass.new("RSSMRA80A41F205B").decode

assert_equal "F", result[:gender]
assert_equal "1980-01-01", result[:birthdate]
end

private

def klass
Expand Down
27 changes: 27 additions & 0 deletions test/itax_code_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,33 @@ class ItaxCodeTest < Minitest::Test
refute klass.valid?("WRONG")
end

test "encode/decode round-trip for male" do
result = klass.decode(klass.encode(surname: "Rossi", name: "Mario", gender: "M",
birthdate: "1980-01-01", birthplace: "Milano"))

assert_equal "M", result[:gender]
assert_equal "1980-01-01", result[:birthdate]
assert_equal "F205", result[:birthplace][:code]
end

test "encode/decode round-trip for female (day offset)" do
result = klass.decode(klass.encode(surname: "Rossi", name: "Mario", gender: "F",
birthdate: "1980-01-01", birthplace: "Milano"))

assert_equal "F", result[:gender]
assert_equal "1980-01-01", result[:birthdate]
assert_equal "F205", result[:birthplace][:code]
end

test "encode/decode round-trip for foreign birthplace" do
result = klass.decode(klass.encode(surname: "Berardi", name: "Adriana", gender: "F",
birthdate: "1970-08-01", birthplace: "Brasile"))

assert_equal "F", result[:gender]
assert_equal "1970-08-01", result[:birthdate]
assert_equal "Z602", result[:birthplace][:code]
end

private

def klass
Expand Down
Loading