line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Business::RO::TaxDeduction; |
2
|
|
|
|
|
|
|
$Business::RO::TaxDeduction::VERSION = '0.012'; |
3
|
|
|
|
|
|
|
# ABSTRACT: Romanian salary tax deduction calculator |
4
|
|
|
|
|
|
|
|
5
|
2
|
|
|
2
|
|
193470
|
use 5.010001; |
|
2
|
|
|
|
|
49
|
|
6
|
2
|
|
|
2
|
|
942
|
use utf8; |
|
2
|
|
|
|
|
23
|
|
|
2
|
|
|
|
|
9
|
|
7
|
2
|
|
|
2
|
|
874
|
use Moo; |
|
2
|
|
|
|
|
18635
|
|
|
2
|
|
|
|
|
7
|
|
8
|
2
|
|
|
2
|
|
3105
|
use MooX::HandlesVia; |
|
2
|
|
|
|
|
15413
|
|
|
2
|
|
|
|
|
10
|
|
9
|
2
|
|
|
2
|
|
1952
|
use Math::BigFloat; |
|
2
|
|
|
|
|
85353
|
|
|
2
|
|
|
|
|
10
|
|
10
|
2
|
|
|
2
|
|
36617
|
use Scalar::Util qw(blessed); |
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
114
|
|
11
|
2
|
|
|
|
|
22
|
use Business::RO::TaxDeduction::Types qw( |
12
|
|
|
|
|
|
|
Int |
13
|
|
|
|
|
|
|
MathBigFloat |
14
|
2
|
|
|
2
|
|
846
|
); |
|
2
|
|
|
|
|
6
|
|
15
|
2
|
|
|
2
|
|
2360
|
use Business::RO::TaxDeduction::Amount; |
|
2
|
|
|
|
|
8
|
|
|
2
|
|
|
|
|
63
|
|
16
|
2
|
|
|
2
|
|
774
|
use Business::RO::TaxDeduction::Ranges; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
52
|
|
17
|
2
|
|
|
2
|
|
794
|
use Business::RO::TaxDeduction::Table; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
1086
|
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has 'vbl' => ( |
20
|
|
|
|
|
|
|
is => 'ro', |
21
|
|
|
|
|
|
|
isa => Int, |
22
|
|
|
|
|
|
|
required => 1, |
23
|
|
|
|
|
|
|
); |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
has 'year' => ( |
26
|
|
|
|
|
|
|
is => 'ro', |
27
|
|
|
|
|
|
|
isa => Int, |
28
|
|
|
|
|
|
|
default => sub { 2018 }, |
29
|
|
|
|
|
|
|
); |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
has 'persons' => ( |
32
|
|
|
|
|
|
|
is => 'ro', |
33
|
|
|
|
|
|
|
isa => Int, |
34
|
|
|
|
|
|
|
default => sub { 0 }, |
35
|
|
|
|
|
|
|
); |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
has 'deduction' => ( |
38
|
|
|
|
|
|
|
is => 'ro', |
39
|
|
|
|
|
|
|
lazy => 1, |
40
|
|
|
|
|
|
|
default => sub { |
41
|
|
|
|
|
|
|
my $self = shift; |
42
|
|
|
|
|
|
|
return Business::RO::TaxDeduction::Amount->new( |
43
|
|
|
|
|
|
|
year => $self->year, |
44
|
|
|
|
|
|
|
persons => $self->persons, |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
}, |
47
|
|
|
|
|
|
|
); |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
has 'ranges' => ( |
50
|
|
|
|
|
|
|
is => 'ro', |
51
|
|
|
|
|
|
|
lazy => 1, |
52
|
|
|
|
|
|
|
default => sub { |
53
|
|
|
|
|
|
|
my $self = shift; |
54
|
|
|
|
|
|
|
return Business::RO::TaxDeduction::Ranges->new( |
55
|
|
|
|
|
|
|
year => $self->year, |
56
|
|
|
|
|
|
|
); |
57
|
|
|
|
|
|
|
}, |
58
|
|
|
|
|
|
|
handles => [ qw( vbl_min vbl_max f_min f_max ) ], |
59
|
|
|
|
|
|
|
); |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
has 'ten' => ( |
62
|
|
|
|
|
|
|
is => 'ro', |
63
|
|
|
|
|
|
|
isa => MathBigFloat, |
64
|
|
|
|
|
|
|
default => sub { |
65
|
|
|
|
|
|
|
return Math::BigFloat->new(10); |
66
|
|
|
|
|
|
|
}, |
67
|
|
|
|
|
|
|
); |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub tax_deduction { |
70
|
1341
|
|
|
1341
|
1
|
605442
|
my $self = shift; |
71
|
1341
|
|
|
|
|
3636
|
my $vbl = $self->_round_to_int( $self->vbl ); |
72
|
|
|
|
|
|
|
|
73
|
1341
|
100
|
|
|
|
3682
|
return $self->_amount_for_2018 if $self->year >= 2018; |
74
|
|
|
|
|
|
|
|
75
|
990
|
|
|
|
|
18303
|
my $amount = $self->deduction->amount; |
76
|
990
|
100
|
66
|
|
|
119513
|
if ( $vbl <= $self->vbl_min ) { |
|
|
100
|
|
|
|
|
|
77
|
10
|
|
|
|
|
410
|
return $amount; |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
elsif ( ( $vbl > $self->vbl_min ) && ( $vbl <= $self->vbl_max ) ) { |
80
|
970
|
|
|
|
|
34267
|
$amount = $self->_tax_deduction_formula($vbl, $amount); |
81
|
970
|
100
|
|
|
|
245656
|
return ( blessed $amount ) ? $amount->bstr : $amount; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
else { |
84
|
10
|
|
|
|
|
359
|
return 0; # 0 for VBL > vbl_max |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub _tax_deduction_formula { |
89
|
970
|
|
|
970
|
|
1737
|
my ( $self, $vbl, $base_deduction ) = @_; |
90
|
970
|
|
|
|
|
12621
|
my $amount = $base_deduction * ( 1 - ( $vbl - $self->f_min ) / $self->f_max ); |
91
|
970
|
|
|
|
|
32000
|
return $self->_round_to_tens($amount); |
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub _round_to_int { |
95
|
1353
|
|
|
1353
|
|
8417
|
my ( $self, $amount ) = @_; |
96
|
1353
|
|
|
|
|
4487
|
return int( $amount + 0.5 * ( $amount <=> 0 ) ); |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub _round_to_tens { |
100
|
978
|
|
|
978
|
|
5563
|
my ( $self, $para_amount ) = @_; |
101
|
978
|
|
|
|
|
2749
|
my $amount = Math::BigFloat->new($para_amount); |
102
|
|
|
|
|
|
|
|
103
|
978
|
100
|
|
|
|
162804
|
return 0 if $amount == 0; |
104
|
|
|
|
|
|
|
|
105
|
967
|
|
|
|
|
158481
|
my $afloor = $amount->copy()->bfloor(); |
106
|
967
|
|
|
|
|
74491
|
my $amodulo = $afloor->copy()->bmod( $self->ten ); |
107
|
|
|
|
|
|
|
|
108
|
967
|
100
|
100
|
|
|
255765
|
return $amount if $amount->is_int && $amodulo == 0; |
109
|
752
|
|
|
|
|
5992
|
return $afloor->bsub($amodulo)->badd( $self->ten ); |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub _amount_for_2018 { |
113
|
351
|
|
|
351
|
|
451
|
my $self = shift; |
114
|
351
|
|
|
|
|
6798
|
my $table = Business::RO::TaxDeduction::Table->new( |
115
|
|
|
|
|
|
|
year => $self->year, |
116
|
|
|
|
|
|
|
persons => $self->persons, |
117
|
|
|
|
|
|
|
vbl => $self->vbl, |
118
|
|
|
|
|
|
|
); |
119
|
351
|
|
|
|
|
17477
|
return $table->deduction; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
1; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
__END__ |