itax_code 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "itax_code/omocode"
2
4
 
3
5
  module ItaxCode
@@ -25,17 +27,12 @@ module ItaxCode
25
27
  #
26
28
  # @return [Hash]
27
29
  def decode
28
- year = decode_year
29
- month = utils.months.find_index(raw[:birthdate_month]) + 1
30
- day, gender = decode_day_and_gender
31
- birthplace = decode_birthplace
32
-
33
30
  {
34
31
  code: tax_code,
35
32
  gender: gender,
36
- birthdate: Date.parse([year, month, day].join("-")).to_s,
33
+ birthdate: birthdate,
37
34
  birthplace: birthplace,
38
- omocodes: Omocode.new(tax_code).list,
35
+ omocodes: Omocode.new(tax_code).omocodes,
39
36
  raw: raw
40
37
  }
41
38
  end
@@ -45,53 +42,66 @@ module ItaxCode
45
42
  attr_accessor :tax_code, :utils
46
43
 
47
44
  def raw
48
- matches = tax_code.scan(utils.regex).flatten
49
-
50
- {
51
- surname: matches[0],
52
- name: matches[1],
53
- birthdate: matches[2],
54
- birthdate_year: matches[3],
55
- birthdate_month: matches[4],
56
- birthdate_day: matches[5],
57
- birthplace: matches[6],
58
- cin: matches[7]
45
+ @raw ||= {
46
+ surname: raw_matches[0],
47
+ name: raw_matches[1],
48
+ birthdate: raw_matches[2],
49
+ birthdate_year: raw_matches[3],
50
+ birthdate_month: raw_matches[4],
51
+ birthdate_day: raw_matches[5],
52
+ birthplace: raw_matches[6],
53
+ cin: raw_matches[7]
59
54
  }
60
55
  end
61
56
 
62
- def decode_year
63
- year = utils.omocodia_decode raw[:birthdate_year]
64
- year = (Date.today.year.to_s[0..1] + year).to_i
65
- year -= 100 if year > Date.today.year
66
- year
57
+ def raw_matches
58
+ @raw_matches ||= tax_code.scan(utils.regex).flatten
67
59
  end
68
60
 
69
- def decode_day_and_gender
70
- day = utils.omocodia_decode(raw[:birthdate_day]).to_i
61
+ def gender
62
+ val = utils.omocodia_decode(raw[:birthdate_day]).to_i
63
+ val > 40 ? "F" : "M"
64
+ end
71
65
 
72
- if day > 40
73
- day -= 40
74
- [day, "F"]
75
- else
76
- [day, "M"]
77
- end
66
+ # This method tries to calculate the year based on a raw data. This means that the returned
67
+ # value could be wrong. E.g. a person born on 1920 would have birthdate_year = 20 meaning
68
+ # that both 1920 and 2020 could be valid born years.
69
+ def year
70
+ val = (Date.today.year.to_s[0..1] + utils.omocodia_decode(raw[:birthdate_year])).to_i
71
+ val > Date.today.year ? val - 100 : val
78
72
  end
79
73
 
80
- def decode_birthplace(src = utils.cities, exit: false)
81
- place = src.find do |item|
82
- item["code"] == city_code && !item["name"].include?("soppresso")
83
- end
74
+ def month
75
+ utils.months.find_index(raw[:birthdate_month]) + 1
76
+ end
77
+
78
+ def day
79
+ val = utils.omocodia_decode(raw[:birthdate_day]).to_i
80
+ val > 40 ? val - 40 : val
81
+ end
82
+
83
+ def birthdate
84
+ @birthdate ||= Date.parse("#{year}-#{month}-#{day}").to_s
85
+ end
86
+
87
+ def birthplace(src = utils.cities, stop: false)
88
+ place = src.find { |item| item["code"] == birthplace_code && in_dates?(item) }
84
89
 
85
90
  if place.nil?
86
- exit ? return : decode_birthplace(utils.countries, exit: true)
91
+ birthplace(utils.countries, stop: true) unless stop
87
92
  else
88
- place["name"] = place["name"].gsub(" (soppresso)", "")
89
93
  place.to_h.deep_symbolize_keys
90
94
  end
91
95
  end
92
96
 
93
- def city_code
97
+ def birthplace_code
94
98
  raw[:birthplace][0] + utils.omocodia_decode(raw[:birthplace][1..-1])
95
99
  end
100
+
101
+ def in_dates?(item)
102
+ created_on = Date.parse item.fetch("created_on", "0000-01-01")
103
+ deleted_on = Date.parse item.fetch("deleted_on", "9999-12-31")
104
+ Date.parse(birthdate).between? created_on, deleted_on
105
+ end
96
106
  end
97
107
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "csv"
2
4
 
3
5
  module ItaxCode
@@ -10,9 +12,7 @@ module ItaxCode
10
12
  end
11
13
 
12
14
  def slugged(str, separator = "-")
13
- str.gsub!(/\s*@\s*/, " at ")
14
- str.gsub!(/\s*&\s*/, " and ")
15
- str.parameterize(separator: separator)
15
+ str.gsub(/\s*@\s*/, " at ").gsub(/\s*&\s*/, " and ").parameterize(separator: separator)
16
16
  end
17
17
 
18
18
  def months
@@ -29,23 +29,17 @@ module ItaxCode
29
29
 
30
30
  def cin_odds
31
31
  {
32
- "0": 1, "1": 0, "2": 5, "3": 7, "4": 9, "5": 13,
33
- "6": 15, "7": 17, "8": 19, "9": 21, "A": 1, "B": 0,
34
- "C": 5, "D": 7, "E": 9, "F": 13, "G": 15, "H": 17,
35
- "I": 19, "J": 21, "K": 2, "L": 4, "M": 18, "N": 20,
36
- "O": 11, "P": 3, "Q": 6, "R": 8, "S": 12, "T": 14,
37
- "U": 16, "V": 10, "W": 22, "X": 25, "Y": 24, "Z": 23
32
+ "0": 1, "1": 0, "2": 5, "3": 7, "4": 9, "5": 13, "6": 15, "7": 17, "8": 19, "9": 21,
33
+ A: 1, B: 0, C: 5, D: 7, E: 9, F: 13, G: 15, H: 17, I: 19, J: 21, K: 2, L: 4, M: 18,
34
+ N: 20, O: 11, P: 3, Q: 6, R: 8, S: 12, T: 14, U: 16, V: 10, W: 22, X: 25, Y: 24, Z: 23
38
35
  }
39
36
  end
40
37
 
41
38
  def cin_evens
42
39
  {
43
- "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5,
44
- "6": 6, "7": 7, "8": 8, "9": 9, "A": 0, "B": 1,
45
- "C": 2, "D": 3, "E": 4, "F": 5, "G": 6, "H": 7,
46
- "I": 8, "J": 9, "K": 10, "L": 11, "M": 12, "N": 13,
47
- "O": 14, "P": 15, "Q": 16, "R": 17, "S": 18, "T": 19,
48
- "U": 20, "V": 21, "W": 22, "X": 23, "Y": 24, "Z": 25
40
+ "0": 0, "1": 1, "2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9,
41
+ A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9, K: 10, L: 11, M: 12, N: 13,
42
+ O: 14, P: 15, Q: 16, R: 17, S: 18, T: 19, U: 20, V: 21, W: 22, X: 23, Y: 24, Z: 25
49
43
  }
50
44
  end
51
45
 
@@ -68,8 +62,14 @@ module ItaxCode
68
62
  omocodia.values.join
69
63
  end
70
64
 
71
- def omocodia_subs_indexes
72
- [6, 7, 9, 10, 12, 13, 14]
65
+ def omocodia_indexes
66
+ [6, 7, 9, 10, 12, 13, 14].reverse
67
+ end
68
+
69
+ def omocodia_indexes_combos
70
+ (1..omocodia_indexes.size).flat_map do |index|
71
+ omocodia_indexes.combination(index).to_a
72
+ end
73
73
  end
74
74
 
75
75
  def omocodia_encode(val)
@@ -92,8 +92,7 @@ module ItaxCode
92
92
  tot = 0
93
93
 
94
94
  code.chars.each_with_index do |char, index|
95
- tot += cin_odds[char.to_sym] if (index + 1).odd?
96
- tot += cin_evens[char.to_sym] if (index + 1).even?
95
+ tot += (index + 1).odd? ? cin_odds[char.to_sym] : cin_evens[char.to_sym]
97
96
  end
98
97
 
99
98
  cin_remainders[tot % 26]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ItaxCode
2
4
  # Handles the validation logic.
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ItaxCode
2
- VERSION = "0.2.0".freeze
4
+ VERSION = "0.4.0"
3
5
  end
data/lib/itax_code.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/all"
2
4
 
3
5
  require "itax_code/version"
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+ require "net/http"
5
+ require "tempfile"
6
+ require "uri"
7
+
8
+ namespace :cities do
9
+ desc "Import cities from Istat remote CSV"
10
+ task :import do
11
+ tempfile = Tempfile.new
12
+ tempfile.write Net::HTTP.get(
13
+ URI("https://raw.githubusercontent.com/italia/anpr/master/src/archivi/ANPR_archivio_comuni.csv")
14
+ )
15
+
16
+ output_string = CSV.generate do |csv|
17
+ csv << %w[code province name created_on deleted_on]
18
+
19
+ CSV.foreach(tempfile.path, headers: true) do |row|
20
+ csv << [
21
+ row["CODCATASTALE"],
22
+ row["SIGLAPROVINCIA"],
23
+ row["DENOMINAZIONE_IT"].upcase,
24
+ row["DATAISTITUZIONE"],
25
+ row["DATACESSAZIONE"]
26
+ ]
27
+ end
28
+ end
29
+
30
+ File.write("lib/itax_code/data/cities.csv", output_string)
31
+ ensure
32
+ tempfile.close
33
+ tempfile.unlink
34
+ end
35
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itax_code
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matteo Rossi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-26 00:00:00.000000000 Z
11
+ date: 2023-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -24,119 +24,7 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: byebug
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: minitest
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: mocha
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: rubocop
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rubocop-minitest
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop-performance
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: simplecov
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- description:
27
+ description:
140
28
  email:
141
29
  - mttrss5@gmail.com
142
30
  executables: []
@@ -144,15 +32,15 @@ extensions: []
144
32
  extra_rdoc_files: []
145
33
  files:
146
34
  - ".github/CODEOWNERS"
147
- - ".github/workflows/build-and-push.yml"
148
35
  - ".github/workflows/lint.yml"
36
+ - ".github/workflows/release.yml"
149
37
  - ".github/workflows/test.yml"
150
38
  - ".gitignore"
151
39
  - ".rubocop.yml"
152
40
  - ".travis.yml"
41
+ - CHANGELOG.md
153
42
  - CODE_OF_CONDUCT.md
154
43
  - Gemfile
155
- - Gemfile.lock
156
44
  - README.md
157
45
  - Rakefile
158
46
  - bin/console
@@ -168,6 +56,7 @@ files:
168
56
  - lib/itax_code/utils.rb
169
57
  - lib/itax_code/validator.rb
170
58
  - lib/itax_code/version.rb
59
+ - rakelib/cities.rake
171
60
  homepage: https://github.com/matteoredz/itax-code
172
61
  licenses:
173
62
  - MIT
@@ -175,7 +64,8 @@ metadata:
175
64
  homepage_uri: https://github.com/matteoredz/itax-code
176
65
  source_code_uri: https://github.com/matteoredz/itax-code
177
66
  changelog_uri: https://github.com/matteoredz/itax-code/CHANGELOG.md
178
- post_install_message:
67
+ rubygems_mfa_required: 'true'
68
+ post_install_message:
179
69
  rdoc_options: []
180
70
  require_paths:
181
71
  - lib
@@ -190,8 +80,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
80
  - !ruby/object:Gem::Version
191
81
  version: '0'
192
82
  requirements: []
193
- rubygems_version: 3.1.2
194
- signing_key:
83
+ rubygems_version: 3.4.10
84
+ signing_key:
195
85
  specification_version: 4
196
86
  summary: Encode and decode Italian tax code (Codice Fiscale)
197
87
  test_files: []
@@ -1,27 +0,0 @@
1
- ---
2
- name: Build and Push
3
-
4
- on:
5
- push:
6
- branches:
7
- - main
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - name: Checkout
14
- uses: actions/checkout@v2
15
- - uses: fregante/setup-git-user@v1
16
- - name: Set up Ruby
17
- uses: ruby/setup-ruby@v1
18
- with:
19
- bundler-cache: true
20
- ruby-version: 2.7.0
21
- - run: bundle install
22
- - name: Build and Push to RubyGems
23
- run: ./bin/release
24
- env:
25
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
26
- RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
27
- ...
data/Gemfile.lock DELETED
@@ -1,74 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- itax_code (0.2.0)
5
- activesupport
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activesupport (6.1.4.1)
11
- concurrent-ruby (~> 1.0, >= 1.0.2)
12
- i18n (>= 1.6, < 2)
13
- minitest (>= 5.1)
14
- tzinfo (~> 2.0)
15
- zeitwerk (~> 2.3)
16
- ast (2.4.2)
17
- byebug (11.1.3)
18
- concurrent-ruby (1.1.9)
19
- docile (1.4.0)
20
- i18n (1.8.11)
21
- concurrent-ruby (~> 1.0)
22
- minitest (5.14.4)
23
- mocha (1.13.0)
24
- parallel (1.21.0)
25
- parser (3.0.3.0)
26
- ast (~> 2.4.1)
27
- rainbow (3.0.0)
28
- rake (13.0.6)
29
- regexp_parser (2.1.1)
30
- rexml (3.2.5)
31
- rubocop (1.23.0)
32
- parallel (~> 1.10)
33
- parser (>= 3.0.0.0)
34
- rainbow (>= 2.2.2, < 4.0)
35
- regexp_parser (>= 1.8, < 3.0)
36
- rexml
37
- rubocop-ast (>= 1.12.0, < 2.0)
38
- ruby-progressbar (~> 1.7)
39
- unicode-display_width (>= 1.4.0, < 3.0)
40
- rubocop-ast (1.13.0)
41
- parser (>= 3.0.1.1)
42
- rubocop-minitest (0.17.0)
43
- rubocop (>= 0.90, < 2.0)
44
- rubocop-performance (1.12.0)
45
- rubocop (>= 1.7.0, < 2.0)
46
- rubocop-ast (>= 0.4.0)
47
- ruby-progressbar (1.11.0)
48
- simplecov (0.21.2)
49
- docile (~> 1.1)
50
- simplecov-html (~> 0.11)
51
- simplecov_json_formatter (~> 0.1)
52
- simplecov-html (0.12.3)
53
- simplecov_json_formatter (0.1.3)
54
- tzinfo (2.0.4)
55
- concurrent-ruby (~> 1.0)
56
- unicode-display_width (2.1.0)
57
- zeitwerk (2.5.1)
58
-
59
- PLATFORMS
60
- ruby
61
-
62
- DEPENDENCIES
63
- byebug
64
- itax_code!
65
- minitest
66
- mocha
67
- rake
68
- rubocop
69
- rubocop-minitest
70
- rubocop-performance
71
- simplecov
72
-
73
- BUNDLED WITH
74
- 2.2.28