diff --git a/drcr/general_journal/models.py b/drcr/general_journal/models.py
index d4a4826..c9c7be5 100644
--- a/drcr/general_journal/models.py
+++ b/drcr/general_journal/models.py
@@ -45,3 +45,17 @@ class GeneralJournalPosting(Base, Posting):
def amount(self):
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)
diff --git a/drcr/general_journal/views.py b/drcr/general_journal/views.py
index 4378376..3c3655a 100644
--- a/drcr/general_journal/views.py
+++ b/drcr/general_journal/views.py
@@ -14,11 +14,81 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-from flask import render_template
+from flask import abort, redirect, render_template, request
-from ..webapp import app
-from .models import GeneralJournalTransaction
+from .. import AMOUNT_DPS
+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')
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')
diff --git a/drcr/templates/general_journal/balance_assertions.html b/drcr/templates/general_journal/balance_assertions.html
new file mode 100644
index 0000000..63da64c
--- /dev/null
+++ b/drcr/templates/general_journal/balance_assertions.html
@@ -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 .
+#}
+
+{% extends 'base.html' %}
+{% block title %}Balance assertions{% endblock %}
+
+{% block content %}
+
Balance assertions
+
+
+
+
+
+
+ Date |
+ Description |
+ Account |
+ Balance |
+ |
+ Status |
+ |
+
+
+
+ {% for assertion in assertions %}
+
+ {{ assertion.dt.strftime('%Y-%m-%d') }} |
+ {{ assertion.description }} |
+ {{ assertion.account }} |
+ {{ (assertion.balance()|abs).format() }} |
+ {{ 'Dr' if assertion.quantity >= 0 else 'Cr' }} |
+ {% if assertion_status[assertion] %}{% else %}{% endif %} |
+ |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/drcr/templates/general_journal/balance_assertions_edit.html b/drcr/templates/general_journal/balance_assertions_edit.html
new file mode 100644
index 0000000..f269309
--- /dev/null
+++ b/drcr/templates/general_journal/balance_assertions_edit.html
@@ -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 .
+#}
+
+{% extends 'base.html' %}
+{% block title %}{{ 'Edit' if assertion else 'New' }} balance assertion{% endblock %}
+
+{% block content %}
+ {{ 'Edit' if assertion else 'New' }} balance assertion
+
+
+{% endblock %}
diff --git a/drcr/templates/general_journal.html b/drcr/templates/general_journal/general_journal.html
similarity index 100%
rename from drcr/templates/general_journal.html
rename to drcr/templates/general_journal/general_journal.html
diff --git a/drcr/templates/index.html b/drcr/templates/index.html
index 477e1cd..b831fcc 100644
--- a/drcr/templates/index.html
+++ b/drcr/templates/index.html
@@ -23,6 +23,7 @@
General reports