austax: Implement calculation of mandatory study loan repayment
This commit is contained in:
parent
83a43a1bef
commit
bf86d72175
@ -21,9 +21,7 @@ from drcr.database import db
|
||||
import drcr.plugins
|
||||
from drcr.webapp import app
|
||||
|
||||
from .reports import tax_summary_report
|
||||
|
||||
from datetime import datetime
|
||||
from .reports import eofy_date, tax_summary_report
|
||||
|
||||
def plugin_init():
|
||||
drcr.plugins.advanced_reports.append(('/tax/summary', 'Tax summary'))
|
||||
@ -46,9 +44,7 @@ def make_tax_transactions():
|
||||
tax_amount = report.by_id('total_tax').amount
|
||||
|
||||
# Get EOFY date
|
||||
dt = datetime.now().replace(month=6, day=30)
|
||||
if dt < datetime.now():
|
||||
dt = dt.replace(year=dt.year + 1)
|
||||
dt = eofy_date()
|
||||
|
||||
# Estimated tax payable
|
||||
transactions = [Transaction(
|
||||
@ -60,6 +56,18 @@ def make_tax_transactions():
|
||||
]
|
||||
)]
|
||||
|
||||
# Mandatory study loan repayment
|
||||
loan_repayment = report.by_id('loan_repayment').amount
|
||||
if loan_repayment.quantity != 0:
|
||||
transactions.append(Transaction(
|
||||
dt=dt,
|
||||
description='Mandatory study loan repayment payable',
|
||||
postings=[
|
||||
Posting(account='HELP', quantity=loan_repayment.quantity, commodity='$'), # FIXME: Correct account
|
||||
Posting(account='Income Tax Control', quantity=-loan_repayment.quantity, commodity='$')
|
||||
]
|
||||
))
|
||||
|
||||
# Get trial balance
|
||||
balancer = TrialBalancer()
|
||||
balancer.apply_transactions(db.session.scalars(db.select(Transaction).options(db.selectinload(Transaction.postings))).all())
|
||||
|
@ -14,22 +14,34 @@
|
||||
# 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/>.
|
||||
|
||||
from drcr import AMOUNT_DPS
|
||||
from drcr.database import db
|
||||
from drcr.models import AccountConfiguration, Amount, Transaction, TrialBalancer
|
||||
from drcr.reports import Calculated, Report, Section, Spacer, Subtotal, entries_for_kind
|
||||
|
||||
def base_income_tax(taxable_income):
|
||||
income = taxable_income.quantity
|
||||
from .tax_tables import base_tax, repayment_rates
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
def eofy_date(dt=None):
|
||||
"""Get the datetime for the end of the financial year"""
|
||||
|
||||
if income <= 1820000:
|
||||
return Amount(0, '$')
|
||||
if income <= 4500000:
|
||||
return Amount(int((income - 1820000) * 0.19), '$')
|
||||
if income <= 12000000:
|
||||
return Amount(int(509200 + (income - 4500000) * 0.325), '$')
|
||||
if income <= 18000000:
|
||||
return Amount(int(2946700 + (income - 12000000) * 0.37), '$')
|
||||
return Amount(int(5166700 + (income - 18000000) * 0.45), '$')
|
||||
if dt is None:
|
||||
dt = datetime.now()
|
||||
|
||||
dt_eofy = dt.replace(month=6, day=30)
|
||||
if dt_eofy < dt:
|
||||
dt_eofy = dt_eofy.replace(year=dt.year + 1)
|
||||
|
||||
return dt_eofy
|
||||
|
||||
def base_income_tax(year, taxable_income):
|
||||
"""Get the amount of base income tax"""
|
||||
|
||||
for i, (upper_limit, flat_amount, marginal_rate) in enumerate(base_tax[year]):
|
||||
if upper_limit is None or taxable_income.quantity <= upper_limit * (10**AMOUNT_DPS):
|
||||
lower_limit = base_tax[year][i - 1][0]
|
||||
return Amount(flat_amount * (10**AMOUNT_DPS) + marginal_rate * (taxable_income.quantity - lower_limit * (10**AMOUNT_DPS)), '$')
|
||||
|
||||
def medicare_levy(taxable_income):
|
||||
if taxable_income.quantity < 2920700:
|
||||
@ -37,10 +49,16 @@ def medicare_levy(taxable_income):
|
||||
|
||||
return Amount(int(taxable_income.quantity * 0.02), '$')
|
||||
|
||||
def study_loan_repayment(year, taxable_income):
|
||||
"""Get the amount of mandatory study loan repayment"""
|
||||
|
||||
for upper_limit, rate in repayment_rates[year]:
|
||||
if upper_limit is None or taxable_income.quantity <= upper_limit * (10**AMOUNT_DPS):
|
||||
return Amount(rate * taxable_income.quantity, '$')
|
||||
|
||||
def tax_summary_report():
|
||||
# Get trial balance
|
||||
balancer = TrialBalancer()
|
||||
#balancer.apply_transactions(all_transactions())
|
||||
balancer.apply_transactions(db.session.scalars(db.select(Transaction).options(db.selectinload(Transaction.postings))).all())
|
||||
|
||||
accounts = dict(sorted(balancer.accounts.items()))
|
||||
@ -100,7 +118,7 @@ def tax_summary_report():
|
||||
entries=[
|
||||
Calculated(
|
||||
'Base income tax',
|
||||
lambda _: base_income_tax(report.by_id('taxable').amount)
|
||||
lambda _: base_income_tax(eofy_date().year, report.by_id('taxable').amount)
|
||||
),
|
||||
Calculated(
|
||||
'Medicare levy',
|
||||
@ -116,8 +134,14 @@ def tax_summary_report():
|
||||
),
|
||||
Spacer(),
|
||||
Calculated(
|
||||
'Income tax payable (refundable)',
|
||||
lambda _: report.by_id('total_tax').amount - report.by_id('paygw').amount,
|
||||
'Mandatory study loan repayment',
|
||||
lambda _: study_loan_repayment(eofy_date().year, report.by_id('taxable').amount),
|
||||
id='loan_repayment'
|
||||
),
|
||||
Spacer(),
|
||||
Calculated(
|
||||
'ATO liability payable (refundable)',
|
||||
lambda _: report.by_id('total_tax').amount - report.by_id('paygw').amount + report.by_id('loan_repayment').amount,
|
||||
heading=True,
|
||||
bordered=True
|
||||
)
|
||||
|
55
austax/tax_tables.py
Normal file
55
austax/tax_tables.py
Normal file
@ -0,0 +1,55 @@
|
||||
# DrCr: Web-based double-entry bookkeeping framework
|
||||
# Copyright (C) 2022–2023 Lee Yingtong Li (RunasSudo)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Base income tax
|
||||
# https://www.ato.gov.au/rates/individual-income-tax-rates/
|
||||
# Maps each financial year to list of (upper limit (INclusive), flat amount, marginal rate)
|
||||
base_tax = {
|
||||
2023: [
|
||||
(18200, 0, 0),
|
||||
(45000, 0, 0.19),
|
||||
(120000, 5092, 0.325),
|
||||
(180000, 29467, 0.37),
|
||||
(None, 51667, 0.45)
|
||||
]
|
||||
}
|
||||
|
||||
# Study and training loan (HELP, etc.) repayment thresholds and rates
|
||||
# https://www.ato.gov.au/Rates/HELP,-TSL-and-SFSS-repayment-thresholds-and-rates/
|
||||
# Maps each financial year to list of (upper limit (EXclusive), repayment rate)
|
||||
repayment_rates = {
|
||||
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),
|
||||
(None, 0.1)
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user