The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Business::Tax::ID::PPH21 - Routines to help calculate Indonesian income tax article 21 (PPh pasal 21)

VERSION

This document describes version 0.067 of Business::Tax::ID::PPH21 (from Perl distribution Business-Tax-ID-PPH21), released on 2023-03-30.

SYNOPSIS

DESCRIPTION

Notes about laws/regulations

PP 55/2022

Regarding PPh Pasal 21, this law only regulates the taxing of "natura" (non-cash benefits given to employees, such as laptops, phones, etc). PP 55/2022 does not change PTKP or tax brackets.

UU HPP 7/2021

UU 36/2008

UU 7/1983

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.

FUNCTIONS

calc_net_income_from_pph21_op

Usage:

 calc_net_income_from_pph21_op(%args) -> [$status_code, $reason, $payload, \%result_meta]

Given that someone pays a certain amount of PPh 21 op, calculate her yearly net income.

Examples:

  • Someone who doesn't pay PPh 21 op earns at or below PTKP:

     calc_net_income_from_pph21_op(year => 2016, pph21_op => 0, tp_status => "TK/0"); # -> [200, "OK", 54000000, {}]
  • Example #2:

     calc_net_income_from_pph21_op(year => 2016, pph21_op => 20000000, tp_status => "K/2");

    Result:

     [200, "OK", 234166666.666667, {}]

If pph21_op is 0, will return the PTKP amount. Actually one can earn between zero and the full PTKP amount to pay zero PPh 21 op.

This function is not exported by default, but exportable.

Arguments ('*' denotes required arguments):

  • monthly => bool

    Instead of yearly, return monthly net income.

  • pph21_op* => float

    Amount of PPh 21 op paid.

  • tp_status* => str

    Taxypayer status.

    Taypayer status reflects his/her marital status and affects the amount of his/her non-taxable income.

  • year => int

    (No description)

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)

calc_pph21_op

Usage:

 calc_pph21_op(%args) -> [$status_code, $reason, $payload, \%result_meta]

Calculate PPh 21 for individuals ("OP", "orang pribadi").

Examples:

  • Someone who earns below PTKP:

     calc_pph21_op(year => 2015, net_income => 30000000, tp_status => "TK/0"); # -> [200, "OK", 0, {}]
  • Example #2:

     calc_pph21_op(year => 2015, net_income => 300000000, tp_status => "K/2");

    Result:

     [200, "OK", 33750000, {}]

This function is not exported by default, but exportable.

Arguments ('*' denotes required arguments):

  • net_income* => float

    Yearly net income.

  • tp_status* => str

    Taxypayer status.

    Taypayer status reflects his/her marital status and affects the amount of his/her non-taxable income.

  • year => int

    (No description)

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)

get_pph21_op_ptkp

Usage:

 get_pph21_op_ptkp(%args) -> [$status_code, $reason, $payload, \%result_meta]

Get PPh21 non-taxable income amount ("PTKP") for individuals.

Examples:

  • Example #1:

     get_pph21_op_ptkp(year => 2016);

    Result:

     [
       200,
       "OK",
       {
         "K/0"   => 58500000,
         "K/1"   => 63000000,
         "K/2"   => 67500000,
         "K/3"   => 72000000,
         "K/I/0" => 112500000,
         "K/I/1" => 117000000,
         "K/I/2" => 121500000,
         "K/I/3" => 126000000,
         "TK/0"  => 54000000,
         "TK/1"  => 58500000,
         "TK/2"  => 63000000,
         "TK/3"  => 67500000,
       },
       {},
     ]

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):

  • year => int

    (No description)

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)

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:

  • 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"],
       },
     ]

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):

  • year => int

    (No description)

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)

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/Business-Tax-ID-PPH21.

SOURCE

Source repository is at https://github.com/perlancar/perl-Business-Tax-ID-PPH21.

SEE ALSO

AUTHOR

perlancar <perlancar@cpan.org>

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

If you want to build the distribution (e.g. to try to install it locally on your system), you can install Dist::Zilla, Dist::Zilla::PluginBundle::Author::PERLANCAR, Pod::Weaver::PluginBundle::Author::PERLANCAR, and sometimes one or two other Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond that are considered a bug and can be reported to me.

COPYRIGHT AND LICENSE

This software is copyright (c) 2023, 2021, 2020, 2019, 2017, 2015 by perlancar <perlancar@cpan.org>.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=Business-Tax-ID-PPH21

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.