itax_code 2.0.0 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,8 +14,6 @@ module ItaxCode
14
14
  #
15
15
  # @return [String] The encoded tax code
16
16
  class Encoder
17
- MissingDataError = Class.new(StandardError)
18
-
19
17
  # @param [Hash] data The user attributes
20
18
  # @param [Utils] utils
21
19
  #
@@ -25,6 +23,8 @@ module ItaxCode
25
23
  # @option data [String, Date] :birthdate The user birthdate
26
24
  # @option data [String] :birthplace The user birthplace
27
25
  def initialize(data = {}, utils = Utils.new)
26
+ @utils = utils
27
+
28
28
  @surname = data[:surname]
29
29
  @name = data[:name]
30
30
  @gender = data[:gender]&.upcase
@@ -33,7 +33,6 @@ module ItaxCode
33
33
  validate_data_presence!
34
34
 
35
35
  @birthdate = parse_birthdate!
36
- @utils = utils
37
36
  end
38
37
 
39
38
  # Computes the tax code from its components.
@@ -81,8 +80,8 @@ module ItaxCode
81
80
  place_slug = utils.slugged(birthplace)
82
81
  place_item = src.find { |i| place_slug == utils.slugged(i[lookup_key]) }
83
82
 
84
- code = place_item.try(:[], "code")
85
- return code if code.present?
83
+ code = place_item&.[]("code")
84
+ return code if utils.present?(code)
86
85
  raise MissingDataError, "no code found for #{birthplace}" if stop
87
86
 
88
87
  encode_birthplace(utils.countries, stop: true)
@@ -90,7 +89,7 @@ module ItaxCode
90
89
 
91
90
  def validate_data_presence!
92
91
  instance_variables.each do |ivar|
93
- next if instance_variable_get(ivar).present?
92
+ next if utils.present?(instance_variable_get(ivar))
94
93
 
95
94
  raise MissingDataError, "missing #{ivar} value"
96
95
  end
@@ -99,7 +98,7 @@ module ItaxCode
99
98
  def parse_birthdate!
100
99
  Date.parse(birthdate)
101
100
  rescue StandardError
102
- raise ArgumentError, "#{birthdate} is not a valid date"
101
+ raise InvalidBirthdateError, "#{birthdate} is not a valid date"
103
102
  end
104
103
  end
105
104
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ItaxCode
4
+ Error = Class.new(StandardError)
5
+
6
+ class Encoder
7
+ Error = Class.new(Error)
8
+
9
+ InvalidBirthdateError = Class.new(Error)
10
+ MissingDataError = Class.new(Error)
11
+ end
12
+
13
+ class Parser
14
+ Error = Class.new(Error)
15
+
16
+ InvalidControlInternalNumberError = Class.new(Error)
17
+ InvalidTaxCodeError = Class.new(Error)
18
+ NoTaxCodeError = Class.new(Error)
19
+ end
20
+ end
@@ -11,11 +11,6 @@ module ItaxCode
11
11
  #
12
12
  # @return [Hash] The parsed tax code
13
13
  class Parser
14
- Error = Class.new(StandardError)
15
- NoTaxCodeError = Class.new(Error)
16
- InvalidControlInternalNumberError = Class.new(Error)
17
- InvalidTaxCodeError = Class.new(Error)
18
-
19
14
  LENGTH = 16
20
15
 
21
16
  # @param [String] tax_code
@@ -24,7 +19,7 @@ module ItaxCode
24
19
  @tax_code = tax_code&.upcase
25
20
  @utils = utils
26
21
 
27
- raise NoTaxCodeError if @tax_code.blank?
22
+ raise NoTaxCodeError if @utils.blank?(@tax_code)
28
23
  raise InvalidTaxCodeError if @tax_code.length != LENGTH
29
24
  raise InvalidControlInternalNumberError if raw[:cin] != @utils.encode_cin(@tax_code)
30
25
  end
@@ -61,7 +56,7 @@ module ItaxCode
61
56
  end
62
57
 
63
58
  def raw_matches
64
- @raw_matches ||= tax_code.scan(utils.regex).flatten
59
+ @raw_matches ||= tax_code.scan(utils.tax_code_sections_regex).flatten
65
60
  end
66
61
 
67
62
  def gender
@@ -73,8 +68,9 @@ module ItaxCode
73
68
  # value could be wrong. E.g. a person born on 1920 would have birthdate_year = 20 meaning
74
69
  # that both 1920 and 2020 could be valid born years.
75
70
  def year
76
- val = (Date.today.year.to_s[0..1] + utils.omocodia_decode(raw[:birthdate_year])).to_i
77
- val > Date.today.year ? val - 100 : val
71
+ current_year = Date.today.year
72
+ val = (current_year.to_s[0..1] + utils.omocodia_decode(raw[:birthdate_year])).to_i
73
+ val > current_year ? val - 100 : val
78
74
  end
79
75
 
80
76
  def month
@@ -96,7 +92,7 @@ module ItaxCode
96
92
  if place.nil?
97
93
  birthplace(utils.countries, stop: true) unless stop
98
94
  else
99
- place.to_h.deep_symbolize_keys
95
+ place.to_h.transform_keys(&:to_sym)
100
96
  end
101
97
  end
102
98
 
@@ -0,0 +1,211 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ItaxCode
4
+ # https://github.com/ruby-i18n/i18n/blob/master/lib/i18n/backend/transliterator.rb
5
+ class Transliterator
6
+ DEFAULT_REPLACEMENT_CHAR = "?"
7
+
8
+ def transliterate(string, replacement = nil)
9
+ replacement ||= DEFAULT_REPLACEMENT_CHAR
10
+ string.gsub(/[^\x00-\x7f]/u) { |char| approximations[char] || replacement }
11
+ end
12
+
13
+ private
14
+
15
+ def approximations
16
+ @approximations ||= {
17
+ "À" => "A",
18
+ "Á" => "A",
19
+ "Â" => "A",
20
+ "Ã" => "A",
21
+ "Ä" => "A",
22
+ "Å" => "A",
23
+ "Æ" => "AE",
24
+ "Ç" => "C",
25
+ "È" => "E",
26
+ "É" => "E",
27
+ "Ê" => "E",
28
+ "Ë" => "E",
29
+ "Ì" => "I",
30
+ "Í" => "I",
31
+ "Î" => "I",
32
+ "Ï" => "I",
33
+ "Ð" => "D",
34
+ "Ñ" => "N",
35
+ "Ò" => "O",
36
+ "Ó" => "O",
37
+ "Ô" => "O",
38
+ "Õ" => "O",
39
+ "Ö" => "O",
40
+ "×" => "x",
41
+ "Ø" => "O",
42
+ "Ù" => "U",
43
+ "Ú" => "U",
44
+ "Û" => "U",
45
+ "Ü" => "U",
46
+ "Ý" => "Y",
47
+ "Þ" => "Th",
48
+ "ß" => "ss",
49
+ "ẞ" => "SS",
50
+ "à" => "a",
51
+ "á" => "a",
52
+ "â" => "a",
53
+ "ã" => "a",
54
+ "ä" => "a",
55
+ "å" => "a",
56
+ "æ" => "ae",
57
+ "ç" => "c",
58
+ "è" => "e",
59
+ "é" => "e",
60
+ "ê" => "e",
61
+ "ë" => "e",
62
+ "ì" => "i",
63
+ "í" => "i",
64
+ "î" => "i",
65
+ "ï" => "i",
66
+ "ð" => "d",
67
+ "ñ" => "n",
68
+ "ò" => "o",
69
+ "ó" => "o",
70
+ "ô" => "o",
71
+ "õ" => "o",
72
+ "ö" => "o",
73
+ "ø" => "o",
74
+ "ù" => "u",
75
+ "ú" => "u",
76
+ "û" => "u",
77
+ "ü" => "u",
78
+ "ý" => "y",
79
+ "þ" => "th",
80
+ "ÿ" => "y",
81
+ "Ā" => "A",
82
+ "ā" => "a",
83
+ "Ă" => "A",
84
+ "ă" => "a",
85
+ "Ą" => "A",
86
+ "ą" => "a",
87
+ "Ć" => "C",
88
+ "ć" => "c",
89
+ "Ĉ" => "C",
90
+ "ĉ" => "c",
91
+ "Ċ" => "C",
92
+ "ċ" => "c",
93
+ "Č" => "C",
94
+ "č" => "c",
95
+ "Ď" => "D",
96
+ "ď" => "d",
97
+ "Đ" => "D",
98
+ "đ" => "d",
99
+ "Ē" => "E",
100
+ "ē" => "e",
101
+ "Ĕ" => "E",
102
+ "ĕ" => "e",
103
+ "Ė" => "E",
104
+ "ė" => "e",
105
+ "Ę" => "E",
106
+ "ę" => "e",
107
+ "Ě" => "E",
108
+ "ě" => "e",
109
+ "Ĝ" => "G",
110
+ "ĝ" => "g",
111
+ "Ğ" => "G",
112
+ "ğ" => "g",
113
+ "Ġ" => "G",
114
+ "ġ" => "g",
115
+ "Ģ" => "G",
116
+ "ģ" => "g",
117
+ "Ĥ" => "H",
118
+ "ĥ" => "h",
119
+ "Ħ" => "H",
120
+ "ħ" => "h",
121
+ "Ĩ" => "I",
122
+ "ĩ" => "i",
123
+ "Ī" => "I",
124
+ "ī" => "i",
125
+ "Ĭ" => "I",
126
+ "ĭ" => "i",
127
+ "Į" => "I",
128
+ "į" => "i",
129
+ "İ" => "I",
130
+ "ı" => "i",
131
+ "IJ" => "IJ",
132
+ "ij" => "ij",
133
+ "Ĵ" => "J",
134
+ "ĵ" => "j",
135
+ "Ķ" => "K",
136
+ "ķ" => "k",
137
+ "ĸ" => "k",
138
+ "Ĺ" => "L",
139
+ "ĺ" => "l",
140
+ "Ļ" => "L",
141
+ "ļ" => "l",
142
+ "Ľ" => "L",
143
+ "ľ" => "l",
144
+ "Ŀ" => "L",
145
+ "ŀ" => "l",
146
+ "Ł" => "L",
147
+ "ł" => "l",
148
+ "Ń" => "N",
149
+ "ń" => "n",
150
+ "Ņ" => "N",
151
+ "ņ" => "n",
152
+ "Ň" => "N",
153
+ "ň" => "n",
154
+ "ʼn" => "'n",
155
+ "Ŋ" => "NG",
156
+ "ŋ" => "ng",
157
+ "Ō" => "O",
158
+ "ō" => "o",
159
+ "Ŏ" => "O",
160
+ "ŏ" => "o",
161
+ "Ő" => "O",
162
+ "ő" => "o",
163
+ "Œ" => "OE",
164
+ "œ" => "oe",
165
+ "Ŕ" => "R",
166
+ "ŕ" => "r",
167
+ "Ŗ" => "R",
168
+ "ŗ" => "r",
169
+ "Ř" => "R",
170
+ "ř" => "r",
171
+ "Ś" => "S",
172
+ "ś" => "s",
173
+ "Ŝ" => "S",
174
+ "ŝ" => "s",
175
+ "Ş" => "S",
176
+ "ş" => "s",
177
+ "Š" => "S",
178
+ "š" => "s",
179
+ "Ţ" => "T",
180
+ "ţ" => "t",
181
+ "Ť" => "T",
182
+ "ť" => "t",
183
+ "Ŧ" => "T",
184
+ "ŧ" => "t",
185
+ "Ũ" => "U",
186
+ "ũ" => "u",
187
+ "Ū" => "U",
188
+ "ū" => "u",
189
+ "Ŭ" => "U",
190
+ "ŭ" => "u",
191
+ "Ů" => "U",
192
+ "ů" => "u",
193
+ "Ű" => "U",
194
+ "ű" => "u",
195
+ "Ų" => "U",
196
+ "ų" => "u",
197
+ "Ŵ" => "W",
198
+ "ŵ" => "w",
199
+ "Ŷ" => "Y",
200
+ "ŷ" => "y",
201
+ "Ÿ" => "Y",
202
+ "Ź" => "Z",
203
+ "ź" => "z",
204
+ "Ż" => "Z",
205
+ "ż" => "z",
206
+ "Ž" => "Z",
207
+ "ž" => "z"
208
+ }
209
+ end
210
+ end
211
+ end
@@ -1,20 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "csv"
4
+ require "itax_code/transliterator"
4
5
 
5
6
  module ItaxCode
6
7
  class Utils
7
- def regex
8
+ def blank?(obj)
9
+ obj.respond_to?(:empty?) ? !!obj.empty? : !obj
10
+ end
11
+
12
+ def present?(obj)
13
+ !blank?(obj)
14
+ end
15
+
16
+ def slugged(string)
17
+ transliterated = transliterate(string.downcase.strip)
18
+ transliterated.gsub(/[^\w-]+/, "-").gsub(/-{2,}/, "-").gsub(/^-+|-+$/, "")
19
+ end
20
+
21
+ def transliterate(string)
22
+ return string if string.ascii_only?
23
+
24
+ transliterator = Transliterator.new
25
+ transliterator.transliterate(string.unicode_normalize(:nfc))
26
+ end
27
+
28
+ def tax_code_sections_regex
8
29
  /^([A-Z]{3})([A-Z]{3})
9
30
  (([A-Z\d]{2})([ABCDEHLMPRST]{1})([A-Z\d]{2}))
10
31
  ([A-Z]{1}[A-Z\d]{3})
11
32
  ([A-Z]{1})$/x
12
33
  end
13
34
 
14
- def slugged(str, separator = "-")
15
- str.gsub(/\s*@\s*/, " at ").gsub(/\s*&\s*/, " and ").parameterize(separator: separator)
16
- end
17
-
18
35
  def months
19
36
  %w[A B C D E H L M P R S T]
20
37
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ItaxCode
4
- VERSION = "2.0.0"
4
+ VERSION = "2.0.2"
5
5
  end
data/lib/itax_code.rb CHANGED
@@ -1,15 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/all"
4
-
5
3
  require "itax_code/version"
6
4
  require "itax_code/utils"
7
5
  require "itax_code/encoder"
8
6
  require "itax_code/parser"
7
+ require "itax_code/error"
9
8
 
10
9
  module ItaxCode
11
- Error = Class.new(StandardError)
12
-
13
10
  class << self
14
11
  # Encodes the user tax code.
15
12
  #
data/rakelib/cities.rake CHANGED
@@ -16,7 +16,7 @@ namespace :cities do
16
16
  output_string = CSV.generate do |csv|
17
17
  csv << %w[code province name created_on deleted_on]
18
18
 
19
- CSV.foreach(tempfile.path, headers: true) do |row|
19
+ CSV.foreach(tempfile.path, encoding: "bom|utf-8", headers: true) do |row|
20
20
  csv << [
21
21
  row["CODCATASTALE"],
22
22
  row["SIGLAPROVINCIA"],
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itax_code
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matteo Rossi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-01 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activesupport
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
11
+ date: 2023-11-04 00:00:00.000000000 Z
12
+ dependencies: []
27
13
  description:
28
14
  email:
29
15
  - mttrss5@gmail.com
@@ -37,7 +23,6 @@ files:
37
23
  - ".github/workflows/test.yml"
38
24
  - ".gitignore"
39
25
  - ".rubocop.yml"
40
- - ".travis.yml"
41
26
  - CHANGELOG.md
42
27
  - CODE_OF_CONDUCT.md
43
28
  - Gemfile
@@ -51,8 +36,10 @@ files:
51
36
  - lib/itax_code/data/cities.csv
52
37
  - lib/itax_code/data/countries.csv
53
38
  - lib/itax_code/encoder.rb
39
+ - lib/itax_code/error.rb
54
40
  - lib/itax_code/omocode.rb
55
41
  - lib/itax_code/parser.rb
42
+ - lib/itax_code/transliterator.rb
56
43
  - lib/itax_code/utils.rb
57
44
  - lib/itax_code/version.rb
58
45
  - rakelib/cities.rake
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- ---
2
- language: ruby
3
- cache: bundler
4
- rvm:
5
- - 2.7.0
6
- before_install: gem install bundler -v 2.1.4