austax: Record CGT cost adjustments
This commit is contained in:
parent
0ebbebc43b
commit
1afc48f218
@ -16,16 +16,15 @@
|
|||||||
|
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
|
|
||||||
from drcr.models import AccountConfiguration, Amount, Posting, Transaction, TrialBalancer
|
from drcr.models import AccountConfiguration, Posting, Transaction, TrialBalancer
|
||||||
from drcr.database import db
|
from drcr.database import db
|
||||||
import drcr.plugins
|
import drcr.plugins
|
||||||
from drcr.plugins import render_plugin_template
|
|
||||||
from drcr.webapp import app
|
|
||||||
|
|
||||||
from .models import CGTAsset
|
|
||||||
from .reports import eofy_date, tax_summary_report
|
from .reports import eofy_date, tax_summary_report
|
||||||
|
from . import views
|
||||||
|
|
||||||
def plugin_init():
|
def plugin_init():
|
||||||
|
drcr.plugins.data_sources.append(('/tax/cgt-adjustments', 'CGT adjustments'))
|
||||||
drcr.plugins.advanced_reports.append(('/tax/cgt-assets', 'CGT assets'))
|
drcr.plugins.advanced_reports.append(('/tax/cgt-assets', 'CGT assets'))
|
||||||
drcr.plugins.advanced_reports.append(('/tax/summary', 'Tax summary'))
|
drcr.plugins.advanced_reports.append(('/tax/summary', 'Tax summary'))
|
||||||
|
|
||||||
@ -39,55 +38,6 @@ def plugin_init():
|
|||||||
|
|
||||||
drcr.plugins.transaction_providers.append(make_tax_transactions)
|
drcr.plugins.transaction_providers.append(make_tax_transactions)
|
||||||
|
|
||||||
@app.route('/tax/cgt-assets')
|
|
||||||
def cgt_assets():
|
|
||||||
# Find all CGT asset accounts
|
|
||||||
cgt_accounts = []
|
|
||||||
account_configurations = AccountConfiguration.get_all_kinds()
|
|
||||||
for account_name, kinds in account_configurations.items():
|
|
||||||
if 'austax.cgtasset' in kinds:
|
|
||||||
cgt_accounts.append(account_name)
|
|
||||||
|
|
||||||
# Get all postings to CGT asset accounts
|
|
||||||
cgt_postings = db.session.scalars(
|
|
||||||
db.select(Posting)
|
|
||||||
.where(Posting.account.in_(cgt_accounts))
|
|
||||||
.join(Posting.transaction)
|
|
||||||
.order_by(Transaction.dt)
|
|
||||||
).all()
|
|
||||||
|
|
||||||
# Process postings to determine final balances
|
|
||||||
assets = []
|
|
||||||
|
|
||||||
for posting in cgt_postings:
|
|
||||||
if posting.quantity >= 0:
|
|
||||||
assets.append(CGTAsset(posting.quantity, posting.commodity, posting.account, posting.transaction.dt))
|
|
||||||
elif posting.quantity < 0:
|
|
||||||
asset = next((a for a in assets if a.commodity == posting.commodity and a.account == posting.account), None)
|
|
||||||
|
|
||||||
if asset is None:
|
|
||||||
raise Exception('Attempted credit {} without preceding debit balance'.quantity(posting.amount()))
|
|
||||||
if asset.quantity + posting.quantity < 0:
|
|
||||||
raise Exception('Attempted credit {} with insufficient debit balance {}'.quantity(posting.amount(), asset.amount()))
|
|
||||||
|
|
||||||
if asset.quantity + posting.quantity != 0:
|
|
||||||
raise NotImplementedError('Partial disposal of CGT asset not implemented')
|
|
||||||
|
|
||||||
asset.disposal_date = posting.transaction.dt
|
|
||||||
|
|
||||||
# Calculate disposal value by searching for matching asset postings
|
|
||||||
asset.disposal_value = Amount(0, '$')
|
|
||||||
for other_posting in posting.transaction.postings:
|
|
||||||
if posting != other_posting and 'drcr.asset' in account_configurations.get(other_posting.account, []):
|
|
||||||
asset.disposal_value.quantity += other_posting.amount().as_cost().quantity
|
|
||||||
|
|
||||||
return render_plugin_template('austax', 'cgt_assets.html', assets=assets)
|
|
||||||
|
|
||||||
@app.route('/tax/summary')
|
|
||||||
def tax_summary():
|
|
||||||
report = tax_summary_report()
|
|
||||||
return render_template('report.html', report=report)
|
|
||||||
|
|
||||||
def make_tax_transactions():
|
def make_tax_transactions():
|
||||||
report = tax_summary_report()
|
report = tax_summary_report()
|
||||||
tax_amount = report.by_id('total_tax').amount
|
tax_amount = report.by_id('total_tax').amount
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
|
from drcr.database import db
|
||||||
from drcr.models import Amount
|
from drcr.models import Amount
|
||||||
|
|
||||||
class CGTAsset(Amount):
|
class CGTAsset(Amount):
|
||||||
@ -25,9 +26,38 @@ class CGTAsset(Amount):
|
|||||||
|
|
||||||
self.disposal_date = None
|
self.disposal_date = None
|
||||||
self.disposal_value = None
|
self.disposal_value = None
|
||||||
|
|
||||||
|
self.cost_adjustments = []
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<{}: {} [{:%Y-%m-%d}]>'.format(self.__class__.__name__, self.format(True), self.acquisition_date)
|
return '<{}: {} [{:%Y-%m-%d}]>'.format(self.__class__.__name__, self.format(True), self.acquisition_date)
|
||||||
|
|
||||||
def commodity_name(self):
|
def commodity_name(self):
|
||||||
return self.commodity[:self.commodity.index('{')].strip()
|
return self.commodity[:self.commodity.index('{')].strip()
|
||||||
|
|
||||||
|
def cost_adjustment(self):
|
||||||
|
# TODO: brought forward vs current period
|
||||||
|
return Amount(sum(a.cost_adjustment for a in self.cost_adjustments), '$')
|
||||||
|
|
||||||
|
def gain(self):
|
||||||
|
return self.disposal_value - (self.as_cost() + self.cost_adjustment())
|
||||||
|
|
||||||
|
class CGTCostAdjustment(db.Model):
|
||||||
|
__tablename__ = 'austax_cgt_cost_adjustments'
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
quantity = db.Column(db.Integer)
|
||||||
|
commodity = db.Column(db.String)
|
||||||
|
account = db.Column(db.String)
|
||||||
|
acquisition_date = db.Column(db.DateTime)
|
||||||
|
|
||||||
|
dt = db.Column(db.DateTime)
|
||||||
|
description = db.Column(db.String)
|
||||||
|
cost_adjustment = db.Column(db.Integer)
|
||||||
|
|
||||||
|
def asset(self):
|
||||||
|
return CGTAsset(self.quantity, self.commodity, self.account, self.acquisition_date)
|
||||||
|
|
||||||
|
def cost_adjustment_amount(self):
|
||||||
|
return Amount(self.cost_adjustment, '$')
|
||||||
|
56
austax/templates/cgt_adjustments.html
Normal file
56
austax/templates/cgt_adjustments.html
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{# 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/>.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block title %}CGT adjustments{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="h2 my-4">CGT adjustments</h1>
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<a href="/tax/cgt-adjustments/new" class="btn btn-primary"><i class="bi bi-plus-lg"></i> New CGT adjustment</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Account</th>
|
||||||
|
<th>Asset</th>
|
||||||
|
<th class="text-end">Units</th>
|
||||||
|
<th>Acquisition date</th>
|
||||||
|
<th class="text-end">Acquisition value</th>
|
||||||
|
<th>Adjustment date</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th class="text-end">Cost adjustment </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for cgt_adjustment in cgt_adjustments %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ cgt_adjustment.account }}</td>
|
||||||
|
<td>{{ cgt_adjustment.asset().commodity_name() }}</td>
|
||||||
|
<td class="text-end">{{ cgt_adjustment.asset().format('hide') }}</td>
|
||||||
|
<td>{{ cgt_adjustment.acquisition_date.strftime('%Y-%m-%d') }}</td>
|
||||||
|
<td class="text-end">{{ cgt_adjustment.asset().as_cost().format() }}</td>
|
||||||
|
<td>{{ cgt_adjustment.dt.strftime('%Y-%m-%d') }}</td>
|
||||||
|
<td>{{ cgt_adjustment.description }}</td>
|
||||||
|
<td class="text-end">{{ cgt_adjustment.cost_adjustment_amount().format_accounting() }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
71
austax/templates/cgt_adjustments_edit.html
Normal file
71
austax/templates/cgt_adjustments_edit.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
{# 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/>.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block title %}{{ 'Edit' if adjustment else 'New' }} CGT adjustment{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="h2 my-4">{{ 'Edit' if adjustment else 'New' }} CGT adjustment</h1>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
<h2 class="h3">CGT asset</h2>
|
||||||
|
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Acquisition date</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="date" class="form-control" name="acquisition_date" value="{{ adjustment.acquisition_date.strftime('%Y-%m-%d') if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Account</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" class="form-control" name="account" value="{{ adjustment.account if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Asset</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" class="form-control" name="asset" value="{{ adjustment.asset().quantity_string() if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="h3 mt-4">CGT adjustment</h2>
|
||||||
|
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Adjustment date</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="date" class="form-control" name="dt" value="{{ adjustment.dt.strftime('%Y-%m-%d') if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Description</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="text" class="form-control" name="description" value="{{ adjustment.description if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="col-sm-2 col-form-label">Cost adjustment</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="number" class="form-control" name="cost_adjustment" step="0.01" value="{{ adjustment.cost_adjustment_amount().quantity_string() if adjustment }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-end">
|
||||||
|
<button type="submit" class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
@ -28,6 +28,7 @@
|
|||||||
<th style="border-bottom-width:0"></th>
|
<th style="border-bottom-width:0"></th>
|
||||||
<th style="border-bottom-width:0"></th>
|
<th style="border-bottom-width:0"></th>
|
||||||
<th style="border-left-width:1px" colspan="2">Acquisition</th>
|
<th style="border-left-width:1px" colspan="2">Acquisition</th>
|
||||||
|
<th style="border-left-width:1px" colspan="2">Adjustment</th>
|
||||||
<th style="border-left-width:1px" colspan="2">Disposal</th>
|
<th style="border-left-width:1px" colspan="2">Disposal</th>
|
||||||
<th style="border-bottom-width:0;border-left-width:1px"></th>
|
<th style="border-bottom-width:0;border-left-width:1px"></th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -37,6 +38,8 @@
|
|||||||
<th class="text-end">Units</th>
|
<th class="text-end">Units</th>
|
||||||
<th style="border-left-width:1px">Date</th>
|
<th style="border-left-width:1px">Date</th>
|
||||||
<th class="text-end">Value</th>
|
<th class="text-end">Value</th>
|
||||||
|
<th style="border-left-width:1px" class="text-end">b/f </th>
|
||||||
|
<th class="text-end">{{ eofy_date.year }}</th>
|
||||||
<th style="border-left-width:1px">Date</th>
|
<th style="border-left-width:1px">Date</th>
|
||||||
<th class="text-end">Value</th>
|
<th class="text-end">Value</th>
|
||||||
<th style="border-left-width:1px" class="text-end">Gain </th>
|
<th style="border-left-width:1px" class="text-end">Gain </th>
|
||||||
@ -50,9 +53,11 @@
|
|||||||
<td class="text-end">{{ asset.format('hide') }}</td>
|
<td class="text-end">{{ asset.format('hide') }}</td>
|
||||||
<td style="border-left-width:1px">{{ asset.acquisition_date.strftime('%Y-%m-%d') }}</td>
|
<td style="border-left-width:1px">{{ asset.acquisition_date.strftime('%Y-%m-%d') }}</td>
|
||||||
<td class="text-end">{{ asset.as_cost().format() }}</td>
|
<td class="text-end">{{ asset.as_cost().format() }}</td>
|
||||||
|
<td style="border-left-width:1px" class="text-end">{{ asset.cost_adjustment().format_accounting() if asset.cost_adjustments }}</td>
|
||||||
|
<td></td>
|
||||||
<td style="border-left-width:1px">{{ asset.disposal_date.strftime('%Y-%m-%d') if asset.disposal_date else '' }}</td>
|
<td style="border-left-width:1px">{{ asset.disposal_date.strftime('%Y-%m-%d') if asset.disposal_date else '' }}</td>
|
||||||
<td class="text-end">{{ asset.disposal_value.format() if asset.disposal_value else '' }}</td>
|
<td class="text-end">{{ asset.disposal_value.format() if asset.disposal_value else '' }}</td>
|
||||||
<td style="border-left-width:1px" class="text-end">{% if asset.disposal_date %}{{ (asset.disposal_value - asset.as_cost()).format_accounting() }}{% endif %}</td>
|
<td style="border-left-width:1px" class="text-end">{% if asset.disposal_date %}{{ asset.gain().format_accounting() }}{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
110
austax/views.py
Normal file
110
austax/views.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# 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/>.
|
||||||
|
|
||||||
|
from flask import redirect, render_template, request
|
||||||
|
|
||||||
|
from drcr.models import AccountConfiguration, Amount, Posting, Transaction
|
||||||
|
from drcr.database import db
|
||||||
|
from drcr.plugins import render_plugin_template
|
||||||
|
from drcr.webapp import app
|
||||||
|
|
||||||
|
from .models import CGTAsset, CGTCostAdjustment
|
||||||
|
from .reports import eofy_date, tax_summary_report
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
@app.route('/tax/cgt-adjustments')
|
||||||
|
def cgt_adjustments():
|
||||||
|
adjustments = db.session.scalars(db.select(CGTCostAdjustment)).all()
|
||||||
|
return render_plugin_template('austax', 'cgt_adjustments.html', cgt_adjustments=adjustments)
|
||||||
|
|
||||||
|
@app.route('/tax/cgt-adjustments/new', methods=['GET', 'POST'])
|
||||||
|
def cgt_adjustment_new():
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_plugin_template('austax', 'cgt_adjustments_edit.html', adjustment=None)
|
||||||
|
|
||||||
|
asset = Amount.parse(request.form['asset'])
|
||||||
|
adjustment = CGTCostAdjustment(
|
||||||
|
quantity=asset.quantity,
|
||||||
|
commodity=asset.commodity,
|
||||||
|
account=request.form['account'],
|
||||||
|
acquisition_date=datetime.strptime(request.form['acquisition_date'], '%Y-%m-%d'),
|
||||||
|
dt=datetime.strptime(request.form['dt'], '%Y-%m-%d'),
|
||||||
|
description=request.form['description'],
|
||||||
|
cost_adjustment=Amount.parse(request.form['cost_adjustment']).quantity
|
||||||
|
)
|
||||||
|
db.session.add(adjustment)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return redirect('/tax/cgt-adjustments')
|
||||||
|
|
||||||
|
@app.route('/tax/cgt-assets')
|
||||||
|
def cgt_assets():
|
||||||
|
# Find all CGT asset accounts
|
||||||
|
cgt_accounts = []
|
||||||
|
account_configurations = AccountConfiguration.get_all_kinds()
|
||||||
|
for account_name, kinds in account_configurations.items():
|
||||||
|
if 'austax.cgtasset' in kinds:
|
||||||
|
cgt_accounts.append(account_name)
|
||||||
|
|
||||||
|
# Get all postings to CGT asset accounts
|
||||||
|
cgt_postings = db.session.scalars(
|
||||||
|
db.select(Posting)
|
||||||
|
.where(Posting.account.in_(cgt_accounts))
|
||||||
|
.join(Posting.transaction)
|
||||||
|
.order_by(Transaction.dt)
|
||||||
|
).all()
|
||||||
|
|
||||||
|
# Process postings to determine final balances
|
||||||
|
assets = []
|
||||||
|
|
||||||
|
for posting in cgt_postings:
|
||||||
|
if posting.quantity >= 0:
|
||||||
|
assets.append(CGTAsset(posting.quantity, posting.commodity, posting.account, posting.transaction.dt))
|
||||||
|
elif posting.quantity < 0:
|
||||||
|
asset = next((a for a in assets if a.commodity == posting.commodity and a.account == posting.account), None)
|
||||||
|
|
||||||
|
if asset is None:
|
||||||
|
raise Exception('Attempted credit {} without preceding debit balance'.quantity(posting.amount()))
|
||||||
|
if asset.quantity + posting.quantity < 0:
|
||||||
|
raise Exception('Attempted credit {} with insufficient debit balance {}'.quantity(posting.amount(), asset.amount()))
|
||||||
|
|
||||||
|
if asset.quantity + posting.quantity != 0:
|
||||||
|
raise NotImplementedError('Partial disposal of CGT asset not implemented')
|
||||||
|
|
||||||
|
asset.disposal_date = posting.transaction.dt
|
||||||
|
|
||||||
|
# Calculate disposal value by searching for matching asset postings
|
||||||
|
asset.disposal_value = Amount(0, '$')
|
||||||
|
for other_posting in posting.transaction.postings:
|
||||||
|
if posting != other_posting and 'drcr.asset' in account_configurations.get(other_posting.account, []):
|
||||||
|
asset.disposal_value.quantity += other_posting.amount().as_cost().quantity
|
||||||
|
|
||||||
|
# Process CGT adjustments
|
||||||
|
for cost_adjustment in db.session.scalars(db.select(CGTCostAdjustment)).all():
|
||||||
|
asset = next((a for a in assets if a.quantity == cost_adjustment.quantity and a.commodity == cost_adjustment.commodity and a.account == cost_adjustment.account and a.acquisition_date == cost_adjustment.acquisition_date), None)
|
||||||
|
|
||||||
|
if asset is None:
|
||||||
|
raise Exception('No matching CGT asset for {}'.format(repr(cost_adjustment.asset())))
|
||||||
|
|
||||||
|
asset.cost_adjustments.append(cost_adjustment)
|
||||||
|
|
||||||
|
return render_plugin_template('austax', 'cgt_assets.html', assets=assets, eofy_date=eofy_date())
|
||||||
|
|
||||||
|
@app.route('/tax/summary')
|
||||||
|
def tax_summary():
|
||||||
|
report = tax_summary_report()
|
||||||
|
return render_template('report.html', report=report)
|
@ -21,7 +21,9 @@ from .webapp import app
|
|||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
|
|
||||||
|
data_sources = [] # list of tuplet (url, label)
|
||||||
advanced_reports = [] # list of tuplet (url, label)
|
advanced_reports = [] # list of tuplet (url, label)
|
||||||
|
|
||||||
account_kinds = [
|
account_kinds = [
|
||||||
# list of tuplet (id, label)
|
# list of tuplet (id, label)
|
||||||
('drcr.asset', 'Asset'),
|
('drcr.asset', 'Asset'),
|
||||||
@ -30,6 +32,7 @@ account_kinds = [
|
|||||||
('drcr.expense', 'Expense'),
|
('drcr.expense', 'Expense'),
|
||||||
('drcr.equity', 'Equity')
|
('drcr.equity', 'Equity')
|
||||||
]
|
]
|
||||||
|
|
||||||
transaction_providers = [] # list of callable
|
transaction_providers = [] # list of callable
|
||||||
|
|
||||||
def init_plugins():
|
def init_plugins():
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
<li><a href="/statement-lines">Statement lines</a></li>
|
<li><a href="/statement-lines">Statement lines</a></li>
|
||||||
<li><a href="/balance-assertions">Balance assertions</a></li>
|
<li><a href="/balance-assertions">Balance assertions</a></li>
|
||||||
<li><a href="/chart-of-accounts">Chart of accounts</a></li>
|
<li><a href="/chart-of-accounts">Chart of accounts</a></li>
|
||||||
|
{% for report in data_sources %}
|
||||||
|
<li><a href="{{ report[0] }}">{{ report[1] }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h1 class="h2 my-4">General reports</h1>
|
<h1 class="h2 my-4">General reports</h1>
|
||||||
|
@ -18,7 +18,7 @@ from flask import redirect, render_template, request
|
|||||||
|
|
||||||
from .database import db
|
from .database import db
|
||||||
from .models import AccountConfiguration, Amount, Balance, Posting, TrialBalancer
|
from .models import AccountConfiguration, Amount, Balance, Posting, TrialBalancer
|
||||||
from .plugins import account_kinds, advanced_reports
|
from .plugins import account_kinds, advanced_reports, data_sources
|
||||||
from .reports import balance_sheet_report, income_statement_report
|
from .reports import balance_sheet_report, income_statement_report
|
||||||
from .webapp import all_transactions, app
|
from .webapp import all_transactions, app
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ from itertools import groupby
|
|||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html', advanced_reports=advanced_reports)
|
return render_template('index.html', data_sources=data_sources, advanced_reports=advanced_reports)
|
||||||
|
|
||||||
@app.route('/chart-of-accounts')
|
@app.route('/chart-of-accounts')
|
||||||
def chart_of_accounts():
|
def chart_of_accounts():
|
||||||
|
Loading…
Reference in New Issue
Block a user