austax: Port full income tax implementation from Python
This commit is contained in:
parent
023d1035c5
commit
a0071cf120
@ -20,6 +20,7 @@ local tax_tables = require('../austax/tax_tables')
|
|||||||
|
|
||||||
local calc = {}
|
local calc = {}
|
||||||
|
|
||||||
|
-- Get the amount of base income tax
|
||||||
function calc.base_income_tax(net_taxable: number, context: libdrcr.ReportingContext): number
|
function calc.base_income_tax(net_taxable: number, context: libdrcr.ReportingContext): number
|
||||||
local year, _, _ = libdrcr.parse_date(context.eofy_date)
|
local year, _, _ = libdrcr.parse_date(context.eofy_date)
|
||||||
local base_tax_table = tax_tables.base_tax[year]
|
local base_tax_table = tax_tables.base_tax[year]
|
||||||
@ -36,11 +37,93 @@ function calc.base_income_tax(net_taxable: number, context: libdrcr.ReportingCon
|
|||||||
end
|
end
|
||||||
|
|
||||||
if net_taxable <= upper_limit then
|
if net_taxable <= upper_limit then
|
||||||
return flat_amount + marginal_rate * (net_taxable - lower_limit)
|
return flat_amount + math.floor(marginal_rate * (net_taxable - lower_limit))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
error('Taxable income not within any tax bracket')
|
error('Taxable income not within any tax bracket')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get the amount of low income tax offset
|
||||||
|
-- https://www.ato.gov.au/forms-and-instructions/low-and-middle-income-earner-tax-offsets
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/itaa1997240/s61.115.html
|
||||||
|
function calc.lito(net_taxable: number, tax_total: number, context: libdrcr.ReportingContext): number
|
||||||
|
if net_taxable <= 37500 * (10 ^ context.dps) then
|
||||||
|
-- LITO is non-refundable
|
||||||
|
-- FIXME: This will not work if we implement multiple non-refundable tax offsets
|
||||||
|
if tax_total <= 700 * (10 ^ context.dps) then
|
||||||
|
return tax_total
|
||||||
|
else
|
||||||
|
return 700 * (10 ^ context.dps)
|
||||||
|
end
|
||||||
|
elseif net_taxable <= 45000 * (10 ^ context.dps) then
|
||||||
|
return 700 * (10 ^ context.dps) - math.floor(0.05 * (net_taxable - 37500 * (10 ^ context.dps)))
|
||||||
|
elseif net_taxable <= 66667 * (10 ^ context.dps) then
|
||||||
|
return 325 * (10 ^ context.dps) - math.floor(0.015 * (net_taxable - 45000 * (10 ^ context.dps)))
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get the amount of Medicare levy
|
||||||
|
function calc.medicare_levy(net_taxable: number, context: libdrcr.ReportingContext): number
|
||||||
|
local year, _, _ = libdrcr.parse_date(context.eofy_date)
|
||||||
|
local threshold_table = tax_tables.medicare_levy_threshold[year]
|
||||||
|
local lower_threshold = threshold_table[1] * (10 ^ context.dps)
|
||||||
|
local upper_threshold = threshold_table[2] * (10 ^ context.dps)
|
||||||
|
|
||||||
|
if net_taxable < lower_threshold then
|
||||||
|
return 0
|
||||||
|
elseif net_taxable < upper_threshold then
|
||||||
|
-- Medicare levy is 10% of the amount above the lower threshold
|
||||||
|
return math.floor((net_taxable - lower_threshold) * 0.1)
|
||||||
|
else
|
||||||
|
-- Normal Medicare levy
|
||||||
|
return math.floor(net_taxable * 0.02)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get the amount of Medicare levy surcharge
|
||||||
|
function calc.medicare_levy_surcharge(net_taxable: number, rfb_grossedup: number, context: libdrcr.ReportingContext): number
|
||||||
|
local mls_income = net_taxable + rfb_grossedup
|
||||||
|
|
||||||
|
local year, _, _ = libdrcr.parse_date(context.eofy_date)
|
||||||
|
local mls_table = tax_tables.medicare_levy_surcharge_single[year]
|
||||||
|
|
||||||
|
for _, row in ipairs(mls_table) do
|
||||||
|
local upper_limit = row[1] * (10 ^ context.dps)
|
||||||
|
local rate = row[2]
|
||||||
|
|
||||||
|
if mls_income <= upper_limit then
|
||||||
|
return math.floor(rate * mls_income)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error('MLS income not within any MLS bracket')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the grossed-up reportable fringe benefit
|
||||||
|
function calc.rfb_grossup(rfb_taxable: number, context: libdrcr.ReportingContext): number
|
||||||
|
return math.floor(rfb_taxable * tax_tables.fbt_grossup)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get the amount of mandatory study loan repayment
|
||||||
|
function calc.study_loan_repayment(net_taxable: number, rfb_grossedup: number, context: libdrcr.ReportingContext): number
|
||||||
|
local repayment_income = net_taxable + rfb_grossedup
|
||||||
|
|
||||||
|
local year, _, _ = libdrcr.parse_date(context.eofy_date)
|
||||||
|
local repayment_table = tax_tables.study_loan_repayment_rates[year]
|
||||||
|
|
||||||
|
for _, row in ipairs(repayment_table) do
|
||||||
|
local upper_limit = row[1] * (10 ^ context.dps)
|
||||||
|
local rate = row[2]
|
||||||
|
|
||||||
|
if repayment_income < upper_limit then
|
||||||
|
return math.floor(rate * repayment_income)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
error('HELP repayment income not within any repayment bracket')
|
||||||
|
end
|
||||||
|
|
||||||
return calc
|
return calc
|
||||||
|
@ -111,7 +111,7 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
visible = true,
|
visible = true,
|
||||||
link = nil,
|
link = nil,
|
||||||
heading = true,
|
heading = true,
|
||||||
bordered = true,
|
bordered = false,
|
||||||
}})
|
}})
|
||||||
table.insert(report.entries, { Section = section })
|
table.insert(report.entries, { Section = section })
|
||||||
table.insert(report.entries, 'Spacer')
|
table.insert(report.entries, 'Spacer')
|
||||||
@ -159,7 +159,7 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
visible = true,
|
visible = true,
|
||||||
link = nil,
|
link = nil,
|
||||||
heading = true,
|
heading = true,
|
||||||
bordered = true,
|
bordered = false,
|
||||||
}})
|
}})
|
||||||
table.insert(report.entries, { Section = section })
|
table.insert(report.entries, { Section = section })
|
||||||
table.insert(report.entries, 'Spacer')
|
table.insert(report.entries, 'Spacer')
|
||||||
@ -202,8 +202,45 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
bordered = false,
|
bordered = false,
|
||||||
}})
|
}})
|
||||||
|
|
||||||
|
-- Medicare levy row
|
||||||
|
local tax_ml = calc.medicare_levy(net_taxable, context)
|
||||||
|
if tax_ml ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Medicare levy',
|
||||||
|
quantity = {tax_ml},
|
||||||
|
id = 'tax_ml',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = false,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Precompute RFB amount as this is required for MLS
|
||||||
|
local rfb_taxable = 0
|
||||||
|
for account, kinds in pairs(kinds_for_account) do
|
||||||
|
if libdrcr.arr_contains(kinds, 'austax.rfb') then
|
||||||
|
rfb_taxable -= balances[account] or 0 -- Invert as income = credit balances
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local rfb_grossedup = calc.rfb_grossup(rfb_taxable, context)
|
||||||
|
|
||||||
|
-- Medicare levy surcharge row
|
||||||
|
local tax_mls = calc.medicare_levy_surcharge(net_taxable, rfb_grossedup, context)
|
||||||
|
if tax_mls ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Medicare levy surcharge',
|
||||||
|
quantity = {tax_mls},
|
||||||
|
id = 'tax_mls',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = false,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
|
||||||
-- Total income tax row
|
-- Total income tax row
|
||||||
local tax_total = tax_base
|
local tax_total = tax_base + tax_ml + tax_mls
|
||||||
table.insert(report.entries, { Row = {
|
table.insert(report.entries, { Row = {
|
||||||
text = 'Total income tax',
|
text = 'Total income tax',
|
||||||
quantity = {tax_total},
|
quantity = {tax_total},
|
||||||
@ -213,10 +250,126 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
heading = true,
|
heading = true,
|
||||||
bordered = true,
|
bordered = true,
|
||||||
}})
|
}})
|
||||||
|
table.insert(report.entries, 'Spacer')
|
||||||
|
|
||||||
-- Generate income tax transaction
|
-- Low income tax offset row
|
||||||
|
local offset_lito = calc.lito(net_taxable, tax_total, context)
|
||||||
|
if offset_lito ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Low income tax offset',
|
||||||
|
quantity = {offset_lito},
|
||||||
|
id = nil,
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = false,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Total tax offsets row
|
||||||
|
local offset_total = offset_lito
|
||||||
|
if offset_total ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Total tax offsets',
|
||||||
|
quantity = {offset_total},
|
||||||
|
id = nil,
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = true,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
table.insert(report.entries, 'Spacer')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate mandatory study loan repayment
|
||||||
|
local study_loan_repayment = calc.study_loan_repayment(net_taxable, rfb_grossedup, context)
|
||||||
|
|
||||||
|
-- Mandatory study loan repayment section
|
||||||
|
if study_loan_repayment ~= 0 then
|
||||||
|
-- Taxable value of reportable fringe benefits row
|
||||||
|
if rfb_taxable ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Taxable value of reportable fringe benefits',
|
||||||
|
quantity = {rfb_taxable},
|
||||||
|
id = 'rfb_taxable',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = false,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Grossed-up value row
|
||||||
|
if rfb_grossedup ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Grossed-up value',
|
||||||
|
quantity = {rfb_grossedup},
|
||||||
|
id = 'rfb_grossedup',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = false,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mandatory study loan repayment row
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Mandatory study loan repayment',
|
||||||
|
quantity = {study_loan_repayment},
|
||||||
|
id = 'study_loan_repayment',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = true,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
table.insert(report.entries, 'Spacer')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add PAYGW entries
|
||||||
|
local total_paygw = 0
|
||||||
|
local entries = entries_for_kind('austax.paygw', false, balances, kinds_for_account)
|
||||||
|
|
||||||
|
if #entries ~= 0 then
|
||||||
|
local section: libdrcr.Section = {
|
||||||
|
text = 'PAYG withheld amounts',
|
||||||
|
id = nil,
|
||||||
|
visible = true,
|
||||||
|
entries = entries,
|
||||||
|
}
|
||||||
|
table.insert(report.entries, { Section = section })
|
||||||
|
total_paygw = math.floor(entries_subtotal(entries) / 100) * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Total PAYGW row
|
||||||
|
if total_paygw ~= 0 then
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'Total withheld amounts',
|
||||||
|
quantity = {total_paygw},
|
||||||
|
id = 'total_paygw',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = true,
|
||||||
|
bordered = false,
|
||||||
|
}})
|
||||||
|
table.insert(report.entries, 'Spacer')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ATO liability row
|
||||||
|
local ato_payable = tax_total - offset_total - total_paygw + study_loan_repayment
|
||||||
|
table.insert(report.entries, { Row = {
|
||||||
|
text = 'ATO liability payable (refundable)',
|
||||||
|
quantity = {ato_payable},
|
||||||
|
id = 'ato_payable',
|
||||||
|
visible = true,
|
||||||
|
link = nil,
|
||||||
|
heading = true,
|
||||||
|
bordered = true,
|
||||||
|
}})
|
||||||
|
|
||||||
|
-- Generate income tax transactions
|
||||||
local transactions: {libdrcr.Transaction} = {
|
local transactions: {libdrcr.Transaction} = {
|
||||||
{
|
{
|
||||||
|
-- # Estimated tax payable
|
||||||
id = nil,
|
id = nil,
|
||||||
dt = libdrcr.date_to_dt(context.eofy_date),
|
dt = libdrcr.date_to_dt(context.eofy_date),
|
||||||
description = 'Estimated income tax',
|
description = 'Estimated income tax',
|
||||||
@ -226,23 +379,83 @@ function reporting.CalculateIncomeTax.execute(args, context, kinds_for_account,
|
|||||||
transaction_id = nil,
|
transaction_id = nil,
|
||||||
description = nil,
|
description = nil,
|
||||||
account = 'Income Tax',
|
account = 'Income Tax',
|
||||||
quantity = tax_total,
|
quantity = (tax_total - offset_total),
|
||||||
commodity = context.reporting_commodity,
|
commodity = context.reporting_commodity,
|
||||||
quantity_ascost = tax_total,
|
quantity_ascost = (tax_total - offset_total),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id = nil,
|
id = nil,
|
||||||
transaction_id = nil,
|
transaction_id = nil,
|
||||||
description = nil,
|
description = nil,
|
||||||
account = 'Income Tax Control',
|
account = 'Income Tax Control',
|
||||||
quantity = -tax_total,
|
quantity = -(tax_total - offset_total),
|
||||||
commodity = context.reporting_commodity,
|
commodity = context.reporting_commodity,
|
||||||
quantity_ascost = -tax_total,
|
quantity_ascost = -(tax_total - offset_total),
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- Mandatory study loan repayment
|
||||||
|
id = nil,
|
||||||
|
dt = libdrcr.date_to_dt(context.eofy_date),
|
||||||
|
description = 'Mandatory study loan repayment payable',
|
||||||
|
postings = {
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = 'HELP',
|
||||||
|
quantity = study_loan_repayment,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = study_loan_repayment,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = 'Income Tax Control',
|
||||||
|
quantity = -study_loan_repayment,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = -study_loan_repayment,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Transfer PAYGW balances to Income Tax Control
|
||||||
|
for account, kinds in pairs(kinds_for_account) do
|
||||||
|
if libdrcr.arr_contains(kinds, 'austax.paygw') then
|
||||||
|
local balance = balances[account] or 0
|
||||||
|
if balance ~= 0 then
|
||||||
|
table.insert(transactions, {
|
||||||
|
id = nil,
|
||||||
|
dt = libdrcr.date_to_dt(context.eofy_date),
|
||||||
|
description = 'PAYG withheld amounts',
|
||||||
|
postings = {
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = 'Income Tax Control',
|
||||||
|
quantity = balance,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = balance,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = nil,
|
||||||
|
transaction_id = nil,
|
||||||
|
description = nil,
|
||||||
|
account = account,
|
||||||
|
quantity = -balance,
|
||||||
|
commodity = context.reporting_commodity,
|
||||||
|
quantity_ascost = -balance,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
[{ name = 'CalculateIncomeTax', kind = 'Transactions', args = 'VoidArgs' }] = {
|
[{ name = 'CalculateIncomeTax', kind = 'Transactions', args = 'VoidArgs' }] = {
|
||||||
Transactions = {
|
Transactions = {
|
||||||
|
@ -15,10 +15,14 @@
|
|||||||
-- You should have received a copy of the GNU Affero General Public License
|
-- You should have received a copy of the GNU Affero General Public License
|
||||||
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
-- along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
local tax_tables = {}
|
||||||
|
|
||||||
-- Base income tax
|
-- Base income tax
|
||||||
-- https://www.ato.gov.au/rates/individual-income-tax-rates/
|
-- https://www.ato.gov.au/rates/individual-income-tax-rates/
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/itra1986174/sch7.html
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/itra1986174/s3.html (tax-free threshold)
|
||||||
-- Maps each financial year to list of (upper limit (INclusive), flat amount, marginal rate)
|
-- Maps each financial year to list of (upper limit (INclusive), flat amount, marginal rate)
|
||||||
local base_tax = {
|
tax_tables.base_tax = {
|
||||||
[2025] = {
|
[2025] = {
|
||||||
{18200, 0, 0},
|
{18200, 0, 0},
|
||||||
{45000, 0, 0.16},
|
{45000, 0, 0.16},
|
||||||
@ -42,8 +46,114 @@ local base_tax = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local tax_tables = {
|
-- FBT type 1 gross-up factor
|
||||||
base_tax = base_tax,
|
-- https://www.ato.gov.au/rates/fbt/#GrossupratesforFBT
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/fbtaa1986312/s5b.html
|
||||||
|
tax_tables.fbt_grossup = 2.0802
|
||||||
|
|
||||||
|
-- Medicare levy thresholds
|
||||||
|
-- https://www.ato.gov.au/Individuals/Medicare-and-private-health-insurance/Medicare-levy/Medicare-levy-reduction/Medicare-levy-reduction-for-low-income-earners/
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/mla1986131/s3.html
|
||||||
|
-- Maps each financial year to list of (lower threshold, upper threshold)
|
||||||
|
tax_tables.medicare_levy_threshold = {
|
||||||
|
[2025] = {27222, 34027},
|
||||||
|
[2024] = {26000, 32500},
|
||||||
|
[2023] = {24276, 30345},
|
||||||
|
[2022] = {23365, 29207}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Medicare levy surcharge rates (singles)
|
||||||
|
-- https://www.ato.gov.au/individuals-and-families/medicare-and-private-health-insurance/medicare-levy-surcharge/medicare-levy-surcharge-income-thresholds-and-rates
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdb/au/legis/cth/consol_act/mla1986131/s8b.html
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/phia2007248/s22.35.html
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/phia2007248/s22.45.html
|
||||||
|
-- Maps each financial year to list of (upper limit (INclusive), MLS rate)
|
||||||
|
-- FIXME: Only supports singles
|
||||||
|
tax_tables.medicare_levy_surcharge_single = {
|
||||||
|
[2025] = {
|
||||||
|
{97000, 0},
|
||||||
|
{113000, 0.01},
|
||||||
|
{151000, 0.0125},
|
||||||
|
{math.huge, 0.015}
|
||||||
|
},
|
||||||
|
[2024] = {
|
||||||
|
{93000, 0},
|
||||||
|
{108000, 0.01},
|
||||||
|
{144000, 0.0125},
|
||||||
|
{math.huge, 0.015}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Study and training loan (HELP, etc.) repayment thresholds and rates
|
||||||
|
-- https://www.ato.gov.au/Rates/HELP,-TSL-and-SFSS-repayment-thresholds-and-rates/
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/hesa2003271/s154.20.html
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/hesa2003271/s154.25.html
|
||||||
|
-- https://www.austlii.edu.au/cgi-bin/viewdoc/au/legis/cth/consol_act/hesa2003271/s154.30.html
|
||||||
|
-- Maps each financial year to list of (upper limit (EXclusive), repayment rate)
|
||||||
|
tax_tables.study_loan_repayment_rates = {
|
||||||
|
[2025] = {
|
||||||
|
{54435, 0},
|
||||||
|
{62851, 0.01},
|
||||||
|
{66621, 0.02},
|
||||||
|
{70619, 0.025},
|
||||||
|
{74856, 0.03},
|
||||||
|
{79347, 0.035},
|
||||||
|
{84108, 0.04},
|
||||||
|
{89155, 0.045},
|
||||||
|
{94504, 0.05},
|
||||||
|
{100175, 0.055},
|
||||||
|
{106186, 0.06},
|
||||||
|
{112557, 0.065},
|
||||||
|
{119310, 0.07},
|
||||||
|
{126468, 0.075},
|
||||||
|
{134057, 0.08},
|
||||||
|
{142101, 0.085},
|
||||||
|
{150627, 0.09},
|
||||||
|
{159664, 0.095},
|
||||||
|
{math.huge, 0.1}
|
||||||
|
},
|
||||||
|
[2024] = {
|
||||||
|
{51550, 0},
|
||||||
|
{59519, 0.01},
|
||||||
|
{63090, 0.02},
|
||||||
|
{66876, 0.025},
|
||||||
|
{70889, 0.03},
|
||||||
|
{75141, 0.035},
|
||||||
|
{79650, 0.04},
|
||||||
|
{84430, 0.045},
|
||||||
|
{89495, 0.05},
|
||||||
|
{94866, 0.055},
|
||||||
|
{100558, 0.06},
|
||||||
|
{106591, 0.065},
|
||||||
|
{112986, 0.07},
|
||||||
|
{119765, 0.075},
|
||||||
|
{126951, 0.08},
|
||||||
|
{134569, 0.085},
|
||||||
|
{142643, 0.09},
|
||||||
|
{151201, 0.095},
|
||||||
|
{math.huge, 0.1}
|
||||||
|
},
|
||||||
|
[2023] = {
|
||||||
|
{48361, 0},
|
||||||
|
{55837, 0.01},
|
||||||
|
{59187, 0.02},
|
||||||
|
{62739, 0.025},
|
||||||
|
{66503, 0.03},
|
||||||
|
{70493, 0.035},
|
||||||
|
{74723, 0.04},
|
||||||
|
{79207, 0.045},
|
||||||
|
{83959, 0.05},
|
||||||
|
{88997, 0.055},
|
||||||
|
{94337, 0.06},
|
||||||
|
{99997, 0.065},
|
||||||
|
{105997, 0.07},
|
||||||
|
{112356, 0.075},
|
||||||
|
{119098, 0.08},
|
||||||
|
{126244, 0.085},
|
||||||
|
{133819, 0.09},
|
||||||
|
{141848, 0.095},
|
||||||
|
{math.huge, 0.1}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tax_tables
|
return tax_tables
|
||||||
|
@ -13,6 +13,4 @@ pub type QuantityInt = i64;
|
|||||||
// Magic strings
|
// Magic strings
|
||||||
// TODO: Make this configurable
|
// TODO: Make this configurable
|
||||||
pub const CURRENT_YEAR_EARNINGS: &'static str = "Current Year Earnings";
|
pub const CURRENT_YEAR_EARNINGS: &'static str = "Current Year Earnings";
|
||||||
pub const INCOME_TAX: &'static str = "Income Tax";
|
|
||||||
pub const INCOME_TAX_CONTROL: &'static str = "Income Tax Control";
|
|
||||||
pub const RETAINED_EARNINGS: &'static str = "Retained Earnings";
|
pub const RETAINED_EARNINGS: &'static str = "Retained Earnings";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user