Add balance assertions
This commit is contained in:
parent
cf92c9b638
commit
4b9025185d
@ -45,3 +45,17 @@ class GeneralJournalPosting(Base, Posting):
|
|||||||
|
|
||||||
def amount(self):
|
def amount(self):
|
||||||
return Amount(self.quantity, self.commodity)
|
return Amount(self.quantity, self.commodity)
|
||||||
|
|
||||||
|
class BalanceAssertion(Base):
|
||||||
|
__tablename__ = 'balance_assertions'
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True)
|
||||||
|
|
||||||
|
dt = Column(DateTime)
|
||||||
|
description = Column(String)
|
||||||
|
account = Column(String)
|
||||||
|
quantity = Column(Integer)
|
||||||
|
commodity = Column(String)
|
||||||
|
|
||||||
|
def balance(self):
|
||||||
|
return Amount(self.quantity, self.commodity)
|
||||||
|
@ -14,11 +14,81 @@
|
|||||||
# 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 flask import render_template
|
from flask import abort, redirect, render_template, request
|
||||||
|
|
||||||
from ..webapp import app
|
from .. import AMOUNT_DPS
|
||||||
from .models import GeneralJournalTransaction
|
from ..database import db_session
|
||||||
|
from ..models import TrialBalancer
|
||||||
|
from ..webapp import all_transactions, app
|
||||||
|
from .models import BalanceAssertion, GeneralJournalTransaction
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
@app.route('/general-journal')
|
@app.route('/general-journal')
|
||||||
def general_journal():
|
def general_journal():
|
||||||
return render_template('general_journal.html', transactions=GeneralJournalTransaction.query.all())
|
return render_template('general_journal/general_journal.html', transactions=GeneralJournalTransaction.query.all())
|
||||||
|
|
||||||
|
@app.route('/balance-assertions')
|
||||||
|
def balance_assertions():
|
||||||
|
assertions = BalanceAssertion.query.all()
|
||||||
|
|
||||||
|
# Check assertion status
|
||||||
|
transactions = all_transactions()
|
||||||
|
assertion_status = {}
|
||||||
|
for assertion in assertions:
|
||||||
|
# FIXME: This is very inefficient
|
||||||
|
balancer = TrialBalancer()
|
||||||
|
balancer.apply_transactions([t for t in transactions if t.dt <= assertion.dt])
|
||||||
|
|
||||||
|
# TODO: Commodities
|
||||||
|
if balancer.accounts[assertion.account].quantity == assertion.quantity:
|
||||||
|
assertion_status[assertion] = True
|
||||||
|
else:
|
||||||
|
assertion_status[assertion] = False
|
||||||
|
|
||||||
|
return render_template('general_journal/balance_assertions.html', assertions=assertions, assertion_status=assertion_status)
|
||||||
|
|
||||||
|
@app.route('/balance-assertions/new', methods=['GET', 'POST'])
|
||||||
|
def balance_assertions_new():
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_template('general_journal/balance_assertions_edit.html', assertion=None)
|
||||||
|
|
||||||
|
quantity = round(float(request.form['amount']) * (10**AMOUNT_DPS))
|
||||||
|
if request.form['sign'] == 'cr':
|
||||||
|
quantity = -quantity
|
||||||
|
|
||||||
|
# New balance assertion
|
||||||
|
assertion = BalanceAssertion(
|
||||||
|
dt=datetime.strptime(request.form['dt'], '%Y-%m-%d'),
|
||||||
|
description=request.form['description'],
|
||||||
|
account=request.form['account'],
|
||||||
|
quantity=quantity,
|
||||||
|
commodity='$'
|
||||||
|
)
|
||||||
|
db_session.add(assertion)
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
return redirect('/balance-assertions')
|
||||||
|
|
||||||
|
@app.route('/balance-assertions/edit', methods=['GET', 'POST'])
|
||||||
|
def balance_assertions_edit():
|
||||||
|
assertion = db_session.get(BalanceAssertion, request.args['id'])
|
||||||
|
if not assertion:
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
if request.method == 'GET':
|
||||||
|
return render_template('general_journal/balance_assertions_edit.html', assertion=assertion)
|
||||||
|
|
||||||
|
quantity = round(float(request.form['amount']) * (10**AMOUNT_DPS))
|
||||||
|
if request.form['sign'] == 'cr':
|
||||||
|
quantity = -quantity
|
||||||
|
|
||||||
|
# Edit balance assertion
|
||||||
|
assertion.dt = datetime.strptime(request.form['dt'], '%Y-%m-%d')
|
||||||
|
assertion.description = request.form['description']
|
||||||
|
assertion.account = request.form['account']
|
||||||
|
assertion.quantity = quantity
|
||||||
|
|
||||||
|
db_session.commit()
|
||||||
|
|
||||||
|
return redirect('/balance-assertions')
|
||||||
|
54
drcr/templates/general_journal/balance_assertions.html
Normal file
54
drcr/templates/general_journal/balance_assertions.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{# DrCr: Web-based double-entry bookkeeping framework
|
||||||
|
Copyright (C) 2022 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 %}Balance assertions{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="h2 my-4">Balance assertions</h1>
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<a href="/balance-assertions/new" class="btn btn-primary"><i class="bi bi-plus-lg"></i> New assertion</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>Account</th>
|
||||||
|
<th class="text-end">Balance</th>
|
||||||
|
<th></th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for assertion in assertions %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ assertion.dt.strftime('%Y-%m-%d') }}</td>
|
||||||
|
<td>{{ assertion.description }}</td>
|
||||||
|
<td>{{ assertion.account }}</td>
|
||||||
|
<td class="text-end">{{ (assertion.balance()|abs).format() }}</td>
|
||||||
|
<td>{{ 'Dr' if assertion.quantity >= 0 else 'Cr' }}</td>
|
||||||
|
<td>{% if assertion_status[assertion] %}<i class="bi bi-check-lg"></i>{% else %}<i class="bi bi-x-circle-fill text-danger"></i>{% endif %}</td>
|
||||||
|
<td><a href="/balance-assertions/edit?id={{ assertion.id }}"><i class="bi bi-pencil"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
61
drcr/templates/general_journal/balance_assertions_edit.html
Normal file
61
drcr/templates/general_journal/balance_assertions_edit.html
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{# DrCr: Web-based double-entry bookkeeping framework
|
||||||
|
Copyright (C) 2022 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 assertion else 'New' }} balance assertion{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="h2 my-4">{{ 'Edit' if assertion else 'New' }} balance assertion</h1>
|
||||||
|
|
||||||
|
<form method="POST">
|
||||||
|
<div class="row mb-2">
|
||||||
|
<label class="col-sm-2 col-form-label">Date</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input type="date" class="form-control" name="dt" value="{{ assertion.dt.strftime('%Y-%m-%d') if assertion }}">
|
||||||
|
</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="{{ assertion.description if assertion }}">
|
||||||
|
</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="{{ assertion.account if assertion }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="col-sm-2 col-form-label">Balance</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-text">$</div>
|
||||||
|
<input type="number" class="form-control" name="amount" step="0.01" value="{{ assertion.balance().quantity_string() if assertion }}">
|
||||||
|
<select class="form-select" name="sign">
|
||||||
|
<option value="dr">Dr</option>
|
||||||
|
<option value="cr">Cr</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-end">
|
||||||
|
<button type="submit" class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
@ -23,6 +23,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a href="/general-journal">General journal</a></li>
|
<li><a href="/general-journal">General journal</a></li>
|
||||||
<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>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h1 class="h2 my-4">General reports</h1>
|
<h1 class="h2 my-4">General reports</h1>
|
||||||
|
Loading…
Reference in New Issue
Block a user