Business-Tax-ID-PPH21
view release on metacpan or search on metacpan
lib/Business/Tax/ID/PPH21.pm view on Meta::CPAN
);
$SPEC{':package'} = {
v => 1.1,
summary => 'Routines to help calculate Indonesian income tax article 21 (PPh pasal 21)',
description => <<'_',
The law ("undang-undang") for income tax ("pajak penghasilan") in Indonesia is
UU 7/1983 (along with its several amendments, the latest two of which are UU
36/2008, UU HPP 7/2021, and PP 55/2022). This law is comprised of several
articles ("pasal"). Article 21 ("pasal 21") regulates earned income, which is
income generated by individual/statutory bodies from performed work/services,
including: employment (salary and benefits, as well as severance pay), freelance
work, business, pension, and "jaminan hari tua" (life insurance paid to
dependents when a worker is deceased). Article 21 also regulates some types of
passive income, which is income generated from capital or other non-work
sources, including: savings interests, gifts/lotteries, royalties.
Some other passive income like rent and dividends are regulated in article 23
("pasal 23") instead of article 21. And some articles regulate other aspects or
special cases, e.g. income tax for sales to government agencies/import/specific
industries ("pasal 22"), rules regarding monthly tax payments ("pasal 25"), or
rules regarding work earned in Indonesia by non-citizens ("pasal 26").
This module contains several routines to help calculate income tax article 21.
_
};
$SPEC{get_pph21_op_rates} = {
v => 1.1,
summary => 'Get tax rates for PPh21 for individuals ("OP", "orang pribadi")',
description => <<'_',
PPh21 differentiates rates between individuals ("OP", "orang pribadi") and
statutory bodies ("badan"). Both are progressive. This routine returns the tax
rates for individuals.
Keywords: tax rates, tax brackets.
_
'description.alt.lang.id_ID' => <<'_',
Kata kunci: tarif pajak, lapisan pajak.
_
args => {
%arg_year,
},
examples => [
{args=>{year=>2022}},
],
};
sub get_pph21_op_rates {
my %args = @_;
my $year = $args{year} or return [400, "Please specify year"];
my $resmeta = {
'table.fields' => [qw/xmin max rate/],
'table.field_formats' => [
undef, undef, ['percent', {sprintf=>'%3.0f%%'}]
],
};
if ($year >= 2022 && $year <= $latest_supported_year) {
state $res = [
200, "OK",
[
{ max=> 60_000_000, rate=>0.05},
{xmin=> 60_000_000, max=> 250_000_000, rate=>0.15},
{xmin=> 250_000_000, max=> 500_000_000, rate=>0.25},
{xmin=> 500_000_000, max=>5_000_000_000, rate=>0.30},
{xmin=>5_000_000_000, rate=>0.35},
],
$resmeta,
];
return $res;
} elsif ($year >= 2009 && $year <= 2022) {
state $res = [
200, "OK",
[
{ max=> 50_000_000, rate=>0.05},
{xmin=> 50_000_000, max=>250_000_000, rate=>0.15},
{xmin=>250_000_000, max=>500_000_000, rate=>0.25},
{xmin=>500_000_000, rate=>0.30},
],
$resmeta,
];
return $res;
} elsif ($year >= 2000 && $year <= 2008) {
state $res = [
200, "OK",
[
{ max=> 25_000_000, rate=>0.05},
{xmin=> 25_000_000, max=> 50_000_000, rate=>0.10},
{xmin=> 50_000_000, max=>100_000_000, rate=>0.15},
{xmin=>100_000_000, max=>200_000_000, rate=>0.25},
{xmin=>200_000_000, rate=>0.35},
],
$resmeta,
];
return $res;
} else {
return [412, "Year unknown or unsupported (latest supported year is ".
"$latest_supported_year)"];
}
}
# TODO: get_pph21_badan_rates
$SPEC{get_pph21_op_ptkp} = {
v => 1.1,
summary => 'Get PPh21 non-taxable income amount ("PTKP") for individuals',
description => <<'_',
When calculating individual income tax, the net income is subtracted by this
amount first. This means that if a person has income below this amount, he/she
does not need to pay income tax.
_
'description.alt.lang.id_ID' => <<'_',
lib/Business/Tax/ID/PPH21.pm view on Meta::CPAN
When calculating individual income tax, the net income is subtracted by this
amount first. This means that if a person has income below this amount, he/she
does not need to pay income tax.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
=over 4
=item * B<year> => I<int>
(No description)
=back
Returns an enveloped result (an array).
First element ($status_code) is an integer containing HTTP-like status code
(200 means OK, 4xx caller error, 5xx function error). Second element
($reason) is a string containing error message, or something like "OK" if status is
200. Third element ($payload) is the actual result, but usually not present when enveloped result is an error response ($status_code is not 2xx). Fourth
element (%result_meta) is called result metadata and is optional, a hash
that contains extra information, much like how HTTP response headers provide additional metadata.
Return value: (any)
=head2 get_pph21_op_rates
Usage:
get_pph21_op_rates(%args) -> [$status_code, $reason, $payload, \%result_meta]
Get tax rates for PPh21 for individuals ("OP", "orang pribadi").
Examples:
=over
=item * Example #1:
get_pph21_op_rates(year => 2022);
Result:
[
200,
"OK",
[
{ max => 60000000, rate => 0.05 },
{ xmin => 60000000, max => 250000000, rate => 0.15 },
{ xmin => 250000000, max => 500000000, rate => 0.25 },
{ xmin => 500000000, max => 5000000000, rate => 0.3 },
{ xmin => 5000000000, rate => 0.35 },
],
{
"table.field_formats" => [undef, undef, ["percent", { sprintf => "%3.0f%%" }]],
"table.fields" => ["xmin", "max", "rate"],
},
]
=back
PPh21 differentiates rates between individuals ("OP", "orang pribadi") and
statutory bodies ("badan"). Both are progressive. This routine returns the tax
rates for individuals.
Keywords: tax rates, tax brackets.
This function is not exported by default, but exportable.
Arguments ('*' denotes required arguments):
=over 4
=item * B<year> => I<int>
(No description)
=back
Returns an enveloped result (an array).
First element ($status_code) is an integer containing HTTP-like status code
(200 means OK, 4xx caller error, 5xx function error). Second element
($reason) is a string containing error message, or something like "OK" if status is
200. Third element ($payload) is the actual result, but usually not present when enveloped result is an error response ($status_code is not 2xx). Fourth
element (%result_meta) is called result metadata and is optional, a hash
that contains extra information, much like how HTTP response headers provide additional metadata.
Return value: (any)
=head1 HOMEPAGE
Please visit the project's homepage at L<https://metacpan.org/release/Business-Tax-ID-PPH21>.
=head1 SOURCE
Source repository is at L<https://github.com/perlancar/perl-Business-Tax-ID-PPH21>.
=head1 SEE ALSO
=head1 AUTHOR
perlancar <perlancar@cpan.org>
=head1 CONTRIBUTING
To contribute, you can send patches by email/via RT, or send pull requests on
GitHub.
Most of the time, you don't need to build the distribution yourself. You can
simply modify the code, then test via:
% prove -l
( run in 3.306 seconds using v1.01-cache-2.11-cpan-364913b4093 )