inss_calculator 0.3.2 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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