inss_calculator 0.3.2 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d673c4bb7f501cd23ec833c8b7aa9a444f99fb31a2f27494367badcfe1666be9
4
- data.tar.gz: 461ee7971062fcd270ead0209d98a420e9216a5b3a3b13f53d8144e168c39f0c
3
+ metadata.gz: dda408b24c4c0da00dbd74687fb89520ec440d089c169bb16bb9fef83163f287
4
+ data.tar.gz: d86a04f19fb5fb6b66115f60f0b4026cb4594b8771d50ad422c4f9f9f330adbb
5
5
  SHA512:
6
- metadata.gz: 057a8e450fd6ea86f6e2439740d03e051d6629abb6a3b16068fb9e9723fb2d5c509edabd3774e439f455b13cf055b5d6e0bc3e3b388043303d46bf9972c3301e
7
- data.tar.gz: 5163df7767c5f209702c9a293c4d1cc268d22707e7d3770f8155b02a53f72ae8361bd9b8004245aa2043c4344033aeb88cd5294e7087611bdba0d9ce019c8fee
6
+ metadata.gz: 553359d8be075e3c58c83e9512f2f8d5a3247be37fa878bc13baa0c9d76ff6f6530d6ff772ca5925e5c9bce181ddc5212cc73dc5af77293cca500c8dc6dae6ef
7
+ data.tar.gz: 8b8f0a3a04ea4148c8608b2a76ed8335b8e7a0e6f86f96ac5c6a373c47ccd6fededb58398a1186963d01494ae11a886be90e6b016e9838dea7b3aa709ea8e423
data/.rubocop.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 3.2.2
3
3
  Include:
4
- - 'lib/**/*.rb'
4
+ - 'lib/inss_calculator/*.rb'
5
+ - 'inss_calculator.rb'
5
6
 
6
7
  Style/StringLiterals:
7
8
  Enabled: true
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- inss_calculator (0.3.1)
4
+ inss_calculator (0.4.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -10,15 +10,15 @@ GEM
10
10
  diff-lcs (1.5.1)
11
11
  json (2.7.2)
12
12
  language_server-protocol (3.17.0.3)
13
- parallel (1.25.1)
14
- parser (3.3.3.0)
13
+ parallel (1.26.3)
14
+ parser (3.3.4.2)
15
15
  ast (~> 2.4.1)
16
16
  racc
17
- racc (1.8.0)
17
+ racc (1.8.1)
18
18
  rainbow (3.1.1)
19
19
  rake (13.2.1)
20
20
  regexp_parser (2.9.2)
21
- rexml (3.3.1)
21
+ rexml (3.3.4)
22
22
  strscan
23
23
  rspec (3.13.0)
24
24
  rspec-core (~> 3.13.0)
@@ -33,24 +33,25 @@ GEM
33
33
  diff-lcs (>= 1.2.0, < 2.0)
34
34
  rspec-support (~> 3.13.0)
35
35
  rspec-support (3.13.1)
36
- rubocop (1.64.1)
36
+ rubocop (1.65.1)
37
37
  json (~> 2.3)
38
38
  language_server-protocol (>= 3.17.0)
39
39
  parallel (~> 1.10)
40
40
  parser (>= 3.3.0.2)
41
41
  rainbow (>= 2.2.2, < 4.0)
42
- regexp_parser (>= 1.8, < 3.0)
42
+ regexp_parser (>= 2.4, < 3.0)
43
43
  rexml (>= 3.2.5, < 4.0)
44
44
  rubocop-ast (>= 1.31.1, < 2.0)
45
45
  ruby-progressbar (~> 1.7)
46
46
  unicode-display_width (>= 2.4.0, < 3.0)
47
- rubocop-ast (1.31.3)
47
+ rubocop-ast (1.32.0)
48
48
  parser (>= 3.3.1.0)
49
49
  ruby-progressbar (1.13.0)
50
50
  strscan (3.1.0)
51
51
  unicode-display_width (2.5.0)
52
52
 
53
53
  PLATFORMS
54
+ ruby
54
55
  x86_64-linux
55
56
 
56
57
  DEPENDENCIES
@@ -60,4 +61,4 @@ DEPENDENCIES
60
61
  rubocop (~> 1.21)
61
62
 
62
63
  BUNDLED WITH
63
- 2.4.10
64
+ 2.5.17
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # InssCalculator
2
2
 
3
- Calculadora do desconto do INSS sobre o salário bruto 2024
3
+ Calculadora do desconto do INSS sobre o salário bruto 2024 de acordo com a [Portaria Inter Ministerial
4
+ número 2 de 11 de Janeiro de 2024](https://www.in.gov.br/en/web/dou/-/portaria-interministerial-mps/mf-n-2-de-11-de-janeiro-de-2024-537035232).
5
+
6
+ Esta mesma portaria discorre tanto sobre a contribuição do trabalhador do setor público quanto do setor privado.
4
7
 
5
8
  ## Instalation
6
9
 
@@ -12,12 +15,28 @@ Não conhecia [esse comando?](https://bundler.io/v2.5/man/bundle-add.1.html) Ele
12
15
 
13
16
  ## Usage
14
17
 
18
+ Para calcular a contribuição do trabalhador no setor privado:
19
+
15
20
  ```
16
21
  gross_salary = 3000
17
22
  calculator = InssCalculator::DiscountPrevidenceCalculator.new(gross_salary)
18
23
  calculator.contribution => 258.81
19
24
  calculator.salary => 3000.0
20
25
  calculator.net_salary => 2741.19
26
+
27
+ ```
28
+ Para calcular a contribuição do trabalhador no setor público:
29
+
30
+ ```
31
+
32
+ gross_salary = 52000.54
33
+ calculator = InssCalculator::PublicInssCalculator.new(gross_salary)
34
+ calculator.contribution => 8726.63
35
+ calculator.salary => 52000.54
36
+ calculator.net_salary => 43273.91
37
+
38
+ ```
39
+ ```
21
40
  ```
22
41
  ### Precisas realizar uma query ao Banco de Dados por grupo de faixa salarial?
23
42
 
@@ -36,6 +55,21 @@ InssCalculator providencia as seguintes constantes:
36
55
  InssCalculator::FOURTH_SALARY_BASE = 4000.04
37
56
  InssCalculator::FOURTH_SALARY_LIMIT = 7786.02
38
57
 
58
+ # Abaixo as bases e os limites do setor público
59
+
60
+ InssCalculator::FIFTH_SALARY_BASE = 7786.03
61
+ InssCalculator::FIFTH_SALARY_LIMIT = 13_333.48
62
+
63
+ InssCalculator::SIXTH_SALARY_BASE = 13_333.49
64
+ InssCalculator::SIXTH_SALARY_LIMIT = 26_666.94
65
+
66
+ InssCalculator::SEVENTH_SALARY_BASE = 26_666.95
67
+ InssCalculator::SEVENTH_SALARY_LIMIT = 52_000.54
68
+
69
+ InssCalculator::EIGTH_SALARY_BASE = 52_000.55
70
+ InssCalculator::EIGTH_SALARY_LIMIT = Float::INFINITY
71
+
72
+
39
73
  ```
40
74
 
41
75
  Desta forma, uma requisição que busca somente a primeira faixa salarial seria:
@@ -44,6 +78,21 @@ Desta forma, uma requisição que busca somente a primeira faixa salarial seria:
44
78
  YourModel.where("salary <= ?", InssCalculator::FIRST_SALARY_LIMIT)
45
79
  ```
46
80
 
81
+ ## Decorators
82
+
83
+ `InssCalculator::Decorator::Text` explica no formato de texto o que o trabalhador precisa saber.
84
+ Ideal para uso no parágrafo do HTML. Retire da view esta responsabildade e deixe com este decorator.
85
+ Você ainda tem acesso à classe original com `#calculator`.
86
+
87
+ ```
88
+ calculator = InssCalculator::DiscountPrevidenceCalculator.new(3000)
89
+ text_decorator = InssCalculator::Decorator::Text.new(calculator)
90
+ text_decorator.present => "Com o salário de R$ 3.000,00, sua contribuição é de R$ 258,81. Seu salário líquido, portanto, é de R$ 2.741,19."
91
+
92
+ text_decorator.calculator => InssCalculator::DiscountPrevidenceCalculator.new(3000)
93
+
94
+ ```
95
+
47
96
  ## Nota sobre trabalhar com números decimais em Ruby
48
97
 
49
98
  Após investigar os resultados dos exemplos contábeis, concluiu-se que os números são truncados.
data/lib/dinheiro.rb ADDED
@@ -0,0 +1,303 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Com base em https://github.com/tapajos/brazilian-rails/blob/master/brdinheiro/lib/brdinheiro/dinheiro.rb
4
+ class Dinheiro
5
+ include Comparable
6
+
7
+ attr_reader :quantia
8
+
9
+ FORMATO_VALIDO_BR = /^([R|r]\$\s*)?(([+-]?\d{1,3}(\.?\d{3})*))?(,\d{0,2})?$/
10
+ FORMATO_VALIDO_EUA = /^([R|r]\$\s*)?(([+-]?\d{1,3}(,?\d{3})*))?(\.\d{0,2})?$/
11
+ SEPARADOR_MILHAR = '.'
12
+ SEPARADOR_FRACIONARIO = ','
13
+ QUANTIDADE_DIGITOS = 3
14
+ PRECISAO_DECIMAL = 100
15
+
16
+ def initialize(quantia)
17
+ self.quantia = quantia
18
+ end
19
+
20
+ # Retorna o valor em Float quando uma coleção
21
+ # ou objeto é convertido para JSON
22
+ #
23
+ # Exemplo:
24
+ # produto = Produto.find 1
25
+ # produto.to_json // {"nome": "MacBook", "valor": 3500.0}
26
+ def as_json
27
+ to_f
28
+ end
29
+
30
+ # Retorna o valor armazenado em string.
31
+ #
32
+ # Exemplo:
33
+ # 1000.to_s ==> '1.000,00'
34
+ def to_s
35
+ inteiro_com_milhar(parte_inteira) + parte_decimal
36
+ end
37
+
38
+ # Compara com outro dinheiro se eh igual.
39
+ #
40
+ # Exemplo:
41
+ # um_real = Dinheiro.new(1)
42
+ # um_real == Dinheiro.new(1) ==> true
43
+ # um_real == Dinheiro.new(2) ==> false
44
+ def ==(other)
45
+ begin
46
+ other = Dinheiro.new(other) unless other.is_a?(Dinheiro)
47
+ rescue StandardError
48
+ return false
49
+ end
50
+ @quantia == other.quantia
51
+ end
52
+
53
+ # Compara com outro dinheiro se eh maior ou menor.
54
+ #
55
+ # Exemplo:
56
+ # 1.real < 2.reais ==> true
57
+ # 1.real > 2.reais ==> false
58
+ # 2.real < 1.reais ==> false
59
+ # 2.real > 1.reais ==> true
60
+ def <=>(other)
61
+ other = Dinheiro.new(other) unless other.is_a?(Dinheiro)
62
+ @quantia <=> other.quantia
63
+ end
64
+
65
+ # Retorna a adicao entre dinheiros.
66
+ #
67
+ # Exemplo:
68
+ # 1.real + 1.real == 2.reais
69
+ # 1.real + 1 == 2.reais
70
+ def +(other)
71
+ Dinheiro.new(transforma_em_string_que_represente_a_quantia(@quantia + quantia_de(other)))
72
+ end
73
+
74
+ # Retorna a subtracao entre dinheiros.
75
+ #
76
+ # Exemplo:
77
+ # 10.reais - 2.reais == 8.reais
78
+ # 10.reais - 2 == 8.reais
79
+ def -(other)
80
+ Dinheiro.new(transforma_em_string_que_represente_a_quantia(@quantia - quantia_de(other)))
81
+ end
82
+
83
+ # Retorna a multiplicacao entre dinheiros.
84
+ #
85
+ # Exemplo:
86
+ # 5.reais * 2 == 10.reais
87
+ # 5.reais * 2.reais == 10.reais
88
+ def *(other)
89
+ return Dinheiro.new(to_f * other) unless other.is_a? Dinheiro
90
+
91
+ other * to_f
92
+ end
93
+
94
+ # Retorna a divisao entre dinheiros.
95
+ #
96
+ # Exemplo:
97
+ # 5.reais / 2 == (2.5).reais
98
+ # 5.reais / 2.reais == DivisaPorNaoEscalarError
99
+ # 5.reais / 0 == ZeroDivisionError
100
+ #
101
+ # Veja também o método parcelar
102
+ def /(other)
103
+ raise DivisaPorNaoEscalarError unless other.is_a?(Numeric)
104
+ return @quantia / other if other.zero?
105
+
106
+ Dinheiro.new(to_f / other)
107
+ end
108
+
109
+ # Retorna um array de dinheiro com as parcelas
110
+ #
111
+ # Exemplo:
112
+ # 6.reais.parcelar(2) == [3.reais, 3.reais]
113
+ # 6.reais.parcelar(2.reais) == DisivaPorNaoEscalarError
114
+ # 6.reais.parcelar(0) == ZeroDivisionError
115
+ def parcelar(numero_de_parcelar)
116
+ raise DivisaPorNaoEscalarError unless numero_de_parcelar.is_a?(Integer)
117
+
118
+ resto = @quantia % numero_de_parcelar
119
+ valor_menor = Dinheiro.new((@quantia / numero_de_parcelar) / 100.0)
120
+ valor_maior = Dinheiro.new((@quantia / numero_de_parcelar + 1) / 100.0)
121
+ [valor_menor] * (numero_de_parcelar - resto) + [valor_maior] * resto
122
+ end
123
+
124
+ # Escreve o valor por extenso.
125
+ #
126
+ # Exemplo:
127
+ # 1.real.to_extenso ==> 'um real'
128
+ # (100.58).to_extenso ==> 'cem reais e cinquenta e oito centavos'
129
+ def to_extenso
130
+ (@quantia / 100.0).por_extenso_em_reais
131
+ end
132
+
133
+ # Alias para o metodo to_extenso.
134
+ alias por_extenso to_extenso
135
+
136
+ # Alias para o metodo to_extenso.
137
+ alias por_extenso_em_reais to_extenso
138
+
139
+ # Verifica se o valor é zero.
140
+ def zero?
141
+ to_f.zero?
142
+ end
143
+
144
+ # Retorna um Float.
145
+ def to_f
146
+ to_s.gsub('.', '').gsub(',', '.').to_f
147
+ end
148
+
149
+ def coerce(outro) # :nodoc:
150
+ [Dinheiro.new(outro), self]
151
+ end
152
+
153
+ # Retorna a própria instância/
154
+ def real
155
+ self
156
+ end
157
+
158
+ # Alias para real.
159
+ alias reais real
160
+
161
+ # Retorna uma string formatada com sigla em valor monetário.
162
+ # Exemplo:
163
+ # Dinheiro.new(1).real_formatado ==> 'R$ 1,00'
164
+ # Dinheiro.new(-1).real_formatado ==> 'R$ -1,00'
165
+ def real_formatado
166
+ "R$ #{self}"
167
+ end
168
+
169
+ # Alias para real_formatado.
170
+ alias reais_formatado real_formatado
171
+
172
+ # Retorna uma string formatada com sigla em valor contábil.
173
+ #
174
+ # Exemplo:
175
+ # Dinheiro.new(1).real_contabil ==> 'R$ 1,00'
176
+ # Dinheiro.new(-1).real_contabil ==> 'R$ (1,00)'
177
+ def real_contabil
178
+ "R$ #{contabil}"
179
+ end
180
+
181
+ # Alias para real_contabil.
182
+ alias reais_contabeis real_contabil
183
+
184
+ # Retorna uma string formatada sem sigla.
185
+ #
186
+ # Exemplo:
187
+ # Dinheiro.new(1).contabil ==> '1,00'
188
+ # Dinheiro.new(-1).contabil ==> '(1,00)'
189
+ def contabil
190
+ if @quantia >= 0
191
+ to_s
192
+ else
193
+ "(#{to_s[1..]})"
194
+ end
195
+ end
196
+
197
+ # Method missing para retorna um BigDecinal quando chamada .
198
+ def method_missing(symbol, *args) # :nodoc:
199
+ # Ex: Chama ao método valor_decimal()
200
+ if (symbol.to_s =~ /^(.*)_decimal$/) && args.empty?
201
+ BigDecimal quantia_sem_separacao_milhares.gsub(',', '.')
202
+ else
203
+ super.method_missing(symbol, *args)
204
+ end
205
+ end
206
+
207
+ private
208
+
209
+ def quantia_de(outro)
210
+ outro = outro.to_f if outro.is_a?(BigDecimal)
211
+ return outro.quantia if outro.is_a?(Dinheiro)
212
+
213
+ (outro * 100).round
214
+ end
215
+
216
+ def transforma_em_string_que_represente_a_quantia(quantia)
217
+ if /^([+-]?)(\d)$/ =~ quantia.to_s
218
+ return "#{::Regexp.last_match(1)}0.0#{::Regexp.last_match(2)}"
219
+ end
220
+
221
+ /^([+-]?)(\d*)(\d\d)$/ =~ quantia.to_s
222
+ "#{::Regexp.last_match(1)}#{::Regexp.last_match(2).to_i}.#{::Regexp.last_match(3)}"
223
+ end
224
+
225
+ def quantia=(quantia)
226
+ @quantia = (quantia * 100).round if quantia.is_a?(Numeric)
227
+ @quantia = extrai_quantia_como_inteiro(quantia) if quantia.is_a?(String)
228
+ end
229
+
230
+ def parte_inteira
231
+ quantia_sem_separacao_milhares[0, quantia_sem_separacao_milhares.length - QUANTIDADE_DIGITOS]
232
+ end
233
+
234
+ def parte_decimal
235
+ quantia_sem_separacao_milhares[-QUANTIDADE_DIGITOS, QUANTIDADE_DIGITOS]
236
+ end
237
+
238
+ def inteiro_com_milhar(inteiro)
239
+ return inteiro if quantidade_de_passos(inteiro).zero?
240
+
241
+ resultado = ''
242
+ quantidade_de_passos(inteiro).times do |passo|
243
+ resultado = ".#{inteiro[-QUANTIDADE_DIGITOS + passo * -QUANTIDADE_DIGITOS, QUANTIDADE_DIGITOS]}#{resultado}"
244
+ end
245
+ resultado = inteiro[0, digitos_que_sobraram(inteiro)] + resultado
246
+ resultado.gsub(/^(-?)\./, '\1')
247
+ end
248
+
249
+ def quantia_sem_separacao_milhares
250
+ format('%.2f', (@quantia.to_f / PRECISAO_DECIMAL)).gsub(SEPARADOR_MILHAR, SEPARADOR_FRACIONARIO)
251
+ end
252
+
253
+ def quantidade_de_passos(inteiro)
254
+ resultado = inteiro.length / QUANTIDADE_DIGITOS
255
+ resultado = (resultado - 1) if (inteiro.length % QUANTIDADE_DIGITOS).zero?
256
+ resultado
257
+ end
258
+
259
+ def digitos_que_sobraram(inteiro)
260
+ inteiro.length - (quantidade_de_passos(inteiro) * QUANTIDADE_DIGITOS)
261
+ end
262
+
263
+ def quantia_valida?(quantia)
264
+ return false if quantia.is_a?(String) && !quantia_respeita_formato?(quantia)
265
+
266
+ quantia.is_a?(String) || quantia.is_a?(Numeric)
267
+ end
268
+
269
+ def extrai_quantia_como_inteiro(quantia)
270
+ return sem_milhar(::Regexp.last_match(2), ::Regexp.last_match(5), '.') if FORMATO_VALIDO_BR =~ quantia
271
+ return unless FORMATO_VALIDO_EUA =~ quantia
272
+
273
+ sem_milhar(::Regexp.last_match(2), ::Regexp.last_match(5), ',')
274
+ end
275
+
276
+ def sem_milhar(parte_inteira, parte_decimal, delimitador_de_milhar)
277
+ (inteiro(parte_inteira, delimitador_de_milhar) + decimal(parte_decimal)).to_i
278
+ end
279
+
280
+ def inteiro(inteiro_com_separador_milhar, separador)
281
+ return inteiro_com_separador_milhar.gsub(separador, '') unless inteiro_com_separador_milhar.blank?
282
+
283
+ ''
284
+ end
285
+
286
+ def decimal(parte_fracionaria)
287
+ unless parte_fracionaria.blank?
288
+ return sem_delimitador_decimal(parte_fracionaria) if parte_fracionaria.length == 3
289
+ return "#{sem_delimitador_decimal(parte_fracionaria)}0" if parte_fracionaria.length == 2
290
+ end
291
+ '00'
292
+ end
293
+
294
+ def sem_delimitador_decimal(parte_fracionaria)
295
+ parte_fracionaria.to_s.gsub(/[.|,]/, '')
296
+ end
297
+
298
+ def quantia_respeita_formato?(quantia)
299
+ return true if FORMATO_VALIDO_BR.match(quantia) || FORMATO_VALIDO_EUA.match(quantia)
300
+
301
+ false
302
+ end
303
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # It extends Calculator contribution to a presentable format.
5
+ module Decorator
6
+ require 'forwardable'
7
+ # InssCalculator::Decorator::Text implements the same Calculator interface
8
+ # and its #present method presents the contribution result in a text format.
9
+ class Text
10
+ extend Forwardable
11
+
12
+ def_delegators :@calculator, :salary, :net_salary, :contribution
13
+
14
+ attr_reader :calculator
15
+
16
+ def initialize(inss_calculator)
17
+ @calculator = inss_calculator
18
+ end
19
+
20
+ def present
21
+ "#{salary_text} #{contribution_text} #{net_salary_text}"
22
+ end
23
+
24
+ private
25
+
26
+ def salary_text
27
+ "Com o salário de #{Dinheiro.new(calculator.salary).real_formatado},"
28
+ end
29
+
30
+ def contribution_text
31
+ "sua contribuição é de #{Dinheiro.new(calculator.contribution).real_formatado}."
32
+ end
33
+
34
+ def net_salary_text
35
+ "Seu salário líquido, portanto, é de #{Dinheiro.new(calculator.net_salary).real_formatado}."
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  module InssCalculator
4
4
  # Based on this insecure protocoll site https://www.coalize.com.br/calculadora-de-inss
5
+ # Check also the official law https://www.in.gov.br/en/web/dou/-/portaria-interministerial-mps/mf-n-2-de-11-de-janeiro-de-2024-537035232
5
6
  class DiscountPrevidenceCalculator
6
7
  attr_reader :salary
7
8
 
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # EigthDiscountCalculator calculates between its range limit
5
+ # As the limit is infinity, it always eacrease the contribution.
6
+ class EigthDiscountCalculator < DiscountCalculatorBase
7
+ QUOTATION = 0.22
8
+
9
+ def contribution
10
+ return NO_CONTRIBUTION if salary <= salary_base
11
+
12
+ return full_contribution if salary > salary_limit
13
+
14
+ calculate_contribution
15
+ end
16
+
17
+ private
18
+
19
+ def calculate_contribution
20
+ ((salary - salary_base) * QUOTATION).truncate(2)
21
+ end
22
+
23
+ def full_contribution
24
+ ((salary_limit - salary_base) * QUOTATION).truncate(2)
25
+ end
26
+
27
+ def salary_limit
28
+ InssCalculator::EIGTH_SALARY_LIMIT
29
+ end
30
+
31
+ def salary_base
32
+ InssCalculator::SEVENTH_SALARY_LIMIT
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # FifthDiscountCalculator calculates between its range limit
5
+ # In case the salary is beyond this limit, it will use its quotation apply inside the range salary limit
6
+ class FifthDiscountCalculator < DiscountCalculatorBase
7
+ QUOTATION = 0.145
8
+
9
+ def contribution
10
+ return NO_CONTRIBUTION if salary <= salary_base
11
+
12
+ return full_contribution if salary > salary_limit
13
+
14
+ calculate_contribution
15
+ end
16
+
17
+ private
18
+
19
+ def calculate_contribution
20
+ ((salary - salary_base) * QUOTATION).truncate(2)
21
+ end
22
+
23
+ def full_contribution
24
+ ((salary_limit - salary_base) * QUOTATION).truncate(2)
25
+ end
26
+
27
+ def salary_limit
28
+ InssCalculator::FIFTH_SALARY_LIMIT
29
+ end
30
+
31
+ def salary_base
32
+ InssCalculator::FOURTH_SALARY_LIMIT
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # Based on this insecure protocoll site https://www.coalize.com.br/calculadora-de-inss
5
+ # Check also the official law https://www.in.gov.br/en/web/dou/-/portaria-interministerial-mps/mf-n-2-de-11-de-janeiro-de-2024-537035232
6
+ # The public contribution is an extension of the private contribution.
7
+ # They have the same rules and quotes percentagen until the fourth salary level.
8
+ class PublicInssCalculator < InssCalculator::DiscountPrevidenceCalculator
9
+ def contribution
10
+ super + public_contribution
11
+ end
12
+
13
+ private
14
+
15
+ def public_contribution
16
+ [
17
+ FifthDiscountCalculator.new(salary).contribution,
18
+ SixthDiscountCalculator.new(salary).contribution,
19
+ SeventhDiscountCalculator.new(salary).contribution,
20
+ EigthDiscountCalculator.new(salary).contribution
21
+ ].reduce(:+).round(2)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # SeventhDiscountCalculator calculates between its range limit
5
+ # In case the salary is beyond this limit, it will use its quotation apply inside the range salary limit
6
+ class SeventhDiscountCalculator < DiscountCalculatorBase
7
+ QUOTATION = 0.19
8
+
9
+ def contribution
10
+ return NO_CONTRIBUTION if salary <= salary_base
11
+
12
+ return full_contribution if salary > salary_limit
13
+
14
+ calculate_contribution
15
+ end
16
+
17
+ private
18
+
19
+ def calculate_contribution
20
+ ((salary - salary_base) * QUOTATION).truncate(2)
21
+ end
22
+
23
+ def full_contribution
24
+ ((salary_limit - salary_base) * QUOTATION).truncate(2)
25
+ end
26
+
27
+ def salary_limit
28
+ InssCalculator::SEVENTH_SALARY_LIMIT
29
+ end
30
+
31
+ def salary_base
32
+ InssCalculator::SIXTH_SALARY_LIMIT
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InssCalculator
4
+ # SixthDiscountCalculator calculates between its range limit
5
+ # In case the salary is beyond this limit, it will use its quotation apply inside the range salary limit
6
+ class SixthDiscountCalculator < DiscountCalculatorBase
7
+ QUOTATION = 0.165
8
+
9
+ def contribution
10
+ return NO_CONTRIBUTION if salary <= salary_base
11
+
12
+ return full_contribution if salary > salary_limit
13
+
14
+ calculate_contribution
15
+ end
16
+
17
+ private
18
+
19
+ def calculate_contribution
20
+ ((salary - salary_base) * QUOTATION).truncate(2)
21
+ end
22
+
23
+ def full_contribution
24
+ ((salary_limit - salary_base) * QUOTATION).truncate(2)
25
+ end
26
+
27
+ def salary_limit
28
+ InssCalculator::SIXTH_SALARY_LIMIT
29
+ end
30
+
31
+ def salary_base
32
+ InssCalculator::FIFTH_SALARY_LIMIT
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InssCalculator
4
- VERSION = '0.3.2'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -1,12 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'inss_calculator/version'
4
+ require_relative './dinheiro'
4
5
  require_relative 'inss_calculator/discount_calculator_base'
5
6
  require_relative 'inss_calculator/discount_previdence_calculator'
7
+ require_relative 'inss_calculator/public_inss_calculator'
6
8
  require_relative 'inss_calculator/first_discount_calculator'
7
9
  require_relative 'inss_calculator/second_discount_calculator'
8
10
  require_relative 'inss_calculator/third_discount_calculator'
9
11
  require_relative 'inss_calculator/fourth_discount_calculator'
12
+ require_relative 'inss_calculator/fifth_discount_calculator'
13
+ require_relative 'inss_calculator/sixth_discount_calculator'
14
+ require_relative 'inss_calculator/seventh_discount_calculator'
15
+ require_relative 'inss_calculator/eigth_discount_calculator'
16
+ require_relative 'inss_calculator/decorator/text'
10
17
 
11
18
  module InssCalculator
12
19
  class Error < StandardError; end
@@ -22,4 +29,16 @@ module InssCalculator
22
29
 
23
30
  FOURTH_SALARY_BASE = 4000.04
24
31
  FOURTH_SALARY_LIMIT = 7786.02
32
+
33
+ FIFTH_SALARY_BASE = 7786.03
34
+ FIFTH_SALARY_LIMIT = 13_333.48
35
+
36
+ SIXTH_SALARY_BASE = 13_333.49
37
+ SIXTH_SALARY_LIMIT = 26_666.94
38
+
39
+ SEVENTH_SALARY_BASE = 26_666.95
40
+ SEVENTH_SALARY_LIMIT = 52_000.54
41
+
42
+ EIGTH_SALARY_BASE = 52_000.55
43
+ EIGTH_SALARY_LIMIT = Float::INFINITY
25
44
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inss_calculator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paulo Felipe Souza
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-14 00:00:00.000000000 Z
11
+ date: 2024-12-23 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Calcula o valor a descontar de acordo com a faixa salarial. Os novos
14
14
  valores corrente em 2024.
@@ -29,12 +29,19 @@ files:
29
29
  - README.md
30
30
  - Rakefile
31
31
  - inss_calculator.gemspec
32
+ - lib/dinheiro.rb
32
33
  - lib/inss_calculator.rb
34
+ - lib/inss_calculator/decorator/text.rb
33
35
  - lib/inss_calculator/discount_calculator_base.rb
34
36
  - lib/inss_calculator/discount_previdence_calculator.rb
37
+ - lib/inss_calculator/eigth_discount_calculator.rb
38
+ - lib/inss_calculator/fifth_discount_calculator.rb
35
39
  - lib/inss_calculator/first_discount_calculator.rb
36
40
  - lib/inss_calculator/fourth_discount_calculator.rb
41
+ - lib/inss_calculator/public_inss_calculator.rb
37
42
  - lib/inss_calculator/second_discount_calculator.rb
43
+ - lib/inss_calculator/seventh_discount_calculator.rb
44
+ - lib/inss_calculator/sixth_discount_calculator.rb
38
45
  - lib/inss_calculator/third_discount_calculator.rb
39
46
  - lib/inss_calculator/version.rb
40
47
  - sig/inss_calculator.rbs
@@ -60,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
67
  - !ruby/object:Gem::Version
61
68
  version: '0'
62
69
  requirements: []
63
- rubygems_version: 3.4.10
70
+ rubygems_version: 3.5.17
64
71
  signing_key:
65
72
  specification_version: 4
66
73
  summary: Calculadora de desconto do INSS