Added thje trial balance in the accounting application.
This commit is contained in:
parent
36389623ef
commit
3cc7c5458b
212
accounting/static/accounting/css/report.css
Normal file
212
accounting/static/accounting/css/report.css
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/* The Mia Website
|
||||||
|
* report.css: The style sheet for the accounting report
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Copyright (c) 2019-2020 imacat.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Author: imacat@mail.imacat.idv.tw (imacat)
|
||||||
|
* First written: 2019/9/12
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.subject-picker {
|
||||||
|
height: auto;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
.date-subject-line {
|
||||||
|
font-size: 0.833em;
|
||||||
|
}
|
||||||
|
.negative {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
.journal-credit {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The general journal tables */
|
||||||
|
.general-journal-table th, .general-journal-table td {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The report block */
|
||||||
|
.report-block {
|
||||||
|
margin: 1em;
|
||||||
|
background-color: #E9ECEF;
|
||||||
|
border-radius: 0.3em;
|
||||||
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
.report-block .table {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.report-block h2 {
|
||||||
|
border-bottom: thick double slategray;
|
||||||
|
}
|
||||||
|
.report-block-lg {
|
||||||
|
padding: 2em 1.5em;
|
||||||
|
}
|
||||||
|
.report-block-sm {
|
||||||
|
padding: 1em 1em;
|
||||||
|
}
|
||||||
|
.report-block-lg table th, .report-block-lg table td {
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.report-block-sm .list-group-item {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The trial balance */
|
||||||
|
.trial-balance-table thead {
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
.trial-balance-table tbody {
|
||||||
|
border-top: thick double slategray;
|
||||||
|
border-bottom: thick double slategray;
|
||||||
|
}
|
||||||
|
.trial-balance-table tfoot {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.trial-balance-list .total {
|
||||||
|
border-top: thick double slategray;
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The income statement */
|
||||||
|
.income-statement-table thead {
|
||||||
|
font-size: 1.21em;
|
||||||
|
}
|
||||||
|
.income-statement-table tbody {
|
||||||
|
border-top: thick double slategray;
|
||||||
|
border-bottom: thick double slategray;
|
||||||
|
}
|
||||||
|
.income-statement-table tr {
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.income-statement-table td .subject {
|
||||||
|
text-indent: 2em;
|
||||||
|
}
|
||||||
|
.income-statement-table tr.first-level-header {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.21em;
|
||||||
|
}
|
||||||
|
.income-statement-table tr.second-level-header {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
.income-statement-table td .second-level-header {
|
||||||
|
text-indent: 1em;
|
||||||
|
}
|
||||||
|
.income-statement-table .total {
|
||||||
|
border-top: 1px solid slategray;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.income-statement-table .cum-total {
|
||||||
|
font-size: 1.21em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.income-statement-list .list-group-item {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.income-statement-list .first-level-header {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.21em;
|
||||||
|
}
|
||||||
|
.income-statement-list .second-level-header {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
.income-statement-list .total {
|
||||||
|
border-top: 1px solid slategray;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.income-statement-list .cum-total {
|
||||||
|
font-weight: bolder;
|
||||||
|
font-size: 1.21em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The balance sheet */
|
||||||
|
.balance-sheet-table thead {
|
||||||
|
font-size: 1.21em;
|
||||||
|
border-bottom: thick double slategray;
|
||||||
|
}
|
||||||
|
.balance-sheet-table tbody {
|
||||||
|
}
|
||||||
|
.balance-sheet-table .second-level-header {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.balance-sheet-table td .subject {
|
||||||
|
text-indent: 1em;
|
||||||
|
}
|
||||||
|
.balance-sheet-table .total {
|
||||||
|
border-top: thick double slategray;
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.balance-sheet-total-table .total {
|
||||||
|
border-top: thick double slategray;
|
||||||
|
font-size: 1.21em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.balance-sheet-list {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.balance-sheet-list .list-group-item {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.balance-sheet-list .section-title {
|
||||||
|
font-size: 1.21em;
|
||||||
|
font-weight: bolder;
|
||||||
|
border-bottom: thick double slategray;
|
||||||
|
}
|
||||||
|
.balance-sheet-list .second-level-header {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
.balance-sheet-list .total {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bolder;
|
||||||
|
border-top: thick double slategray;
|
||||||
|
}
|
||||||
|
.balance-sheet-list .grand-total {
|
||||||
|
font-size: 1.21em;
|
||||||
|
font-weight: bolder;
|
||||||
|
border-top: thick double slategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The search */
|
||||||
|
.btn-actions .btn .search-input {
|
||||||
|
height: calc(1em + .5rem + 2px);
|
||||||
|
border-radius: .2rem;
|
||||||
|
}
|
||||||
|
.btn-actions .btn .search-label {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.btn-actions .btn .search-label button {
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color: inherit;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
172
accounting/templates/accounting/trial-balance.html
Normal file
172
accounting/templates/accounting/trial-balance.html
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% comment %}
|
||||||
|
The Mia Accounting Application
|
||||||
|
cash.html: The template for the cash account reports
|
||||||
|
|
||||||
|
Copyright (c) 2020 imacat.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
Author: imacat@mail.imacat.idv.tw (imacat)
|
||||||
|
First written: 2020/7/1
|
||||||
|
{% endcomment %}
|
||||||
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load humanize %}
|
||||||
|
{% load mia_core %}
|
||||||
|
{% load accounting %}
|
||||||
|
|
||||||
|
{% block settings %}
|
||||||
|
{% blocktrans asvar title with period=period.description context "Accounting|" %}Trial Balance in {{ period }}{% endblocktrans %}
|
||||||
|
{% setvar "title" title %}
|
||||||
|
{% setvar "use_period_chooser" True %}
|
||||||
|
{% static "accounting/css/report.css" as css %}
|
||||||
|
{% setvar "css" css %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="btn-group btn-actions">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fas fa-edit"></i>
|
||||||
|
{% trans "New" context "Accounting|" as text %}
|
||||||
|
{{ text|force_escape }}
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu">
|
||||||
|
{% url "accounting:transaction.create" "expense" as url %}
|
||||||
|
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
|
||||||
|
{% trans "Cash Expense" context "Accounting|" as text %}
|
||||||
|
{{ text|force_escape }}
|
||||||
|
</a>
|
||||||
|
{% url "accounting:transaction.create" "income" as url %}
|
||||||
|
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
|
||||||
|
{% trans "Cash Income" context "Accounting|" as text %}
|
||||||
|
{{ text|force_escape }}
|
||||||
|
</a>
|
||||||
|
{% url "accounting:transaction.create" "transfer" as url %}
|
||||||
|
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
|
||||||
|
{% trans "Transfer" context "Accounting|" as text %}
|
||||||
|
{{ text|force_escape }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% with current_report_icon="fas fa-book" %}
|
||||||
|
{% trans "Journal" context "Accounting|" as current_report_title %}
|
||||||
|
{% include "accounting/include/report-chooser.html" %}
|
||||||
|
{% endwith %}
|
||||||
|
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#period-modal">
|
||||||
|
<i class="far fa-calendar-alt"></i>
|
||||||
|
<span class="d-none d-md-inline">{{ period.description }}</span>
|
||||||
|
<span class="d-md-none">{% trans "Period" context "Period|" as text %}{{ text|force_escape }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% include "mia_core/include/period-chooser.html" %}
|
||||||
|
|
||||||
|
{% if records %}
|
||||||
|
{% include "mia_core/include/pagination.html" %}
|
||||||
|
|
||||||
|
{# The table for large screens #}
|
||||||
|
<div class="d-none d-sm-block report-block report-block-lg">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<h2>{{ title|force_escape }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<table class="table table-borderless table-hover trial-balance-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">{% trans "Subject" context "Accounting|" as text %}{{ text|force_escape }}</th>
|
||||||
|
<th class="amount" scope="col">{% trans "Debit" context "Accounting|" as text %}{{ text|force_escape }}</th>
|
||||||
|
<th class="amount" scope="col">{% trans "Credit" context "Accounting|" as text %}{{ text|force_escape }}</th>
|
||||||
|
<th class="actions" scope="col">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for record in records %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ record.title }}</td>
|
||||||
|
<td class="amount">{{ record.debit|accounting_amount }}</td>
|
||||||
|
<td class="amount">{{ record.credit|accounting_amount }}</td>
|
||||||
|
<td class="actions">
|
||||||
|
<a href="{% url "accounting:ledger" record.code period.spec %}" class="btn btn-info" role="button">
|
||||||
|
<i class="fas fa-eye"></i>
|
||||||
|
<span class="d-none d-lg-inline">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}</td>
|
||||||
|
<td class="amount">{{ record_sum.debit|accounting_amount }}</td>
|
||||||
|
<td class="amount">{{ record_sum.credit|accounting_amount }}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# The list for mobile browsers #}
|
||||||
|
<div class="d-sm-none report-block report-block-sm">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<h2>{{ title|force_escape }}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<ul class="list-group d-lg-none trial-balance-list">
|
||||||
|
{% for record in records %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a class="list-group-item-action d-flex justify-content-between align-items-center" href="{% url "accounting:ledger" record.code period.spec %}">
|
||||||
|
{{ record.title }}
|
||||||
|
<div>
|
||||||
|
{% if record.debit is not None %}
|
||||||
|
<span class="badge badge-success badge-pill">
|
||||||
|
{{ record.debit|intcomma:False }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if record.credit is not None %}
|
||||||
|
<span class="badge badge-warning badge-pill">
|
||||||
|
{{ record.credit|intcomma:False }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li class="list-group-item d-flex justify-content-between align-items-center total">
|
||||||
|
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
|
||||||
|
<div>
|
||||||
|
<span class="badge badge-success badge-pill">
|
||||||
|
{{ record_sum.debit|intcomma:False }}
|
||||||
|
</span>
|
||||||
|
<span class="badge badge-warning badge-pill">
|
||||||
|
{{ record_sum.credit|intcomma:False }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p>{{ _("There is currently no data.")|force_escape }}</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -31,6 +31,7 @@ def accounting_amount(value):
|
|||||||
return ""
|
return ""
|
||||||
if value == 0:
|
if value == 0:
|
||||||
return "-"
|
return "-"
|
||||||
|
print(value)
|
||||||
s = str(abs(value))
|
s = str(abs(value))
|
||||||
while True:
|
while True:
|
||||||
m = re.match("^([1-9][0-9]*)([0-9]{3})", s)
|
m = re.match("^([1-9][0-9]*)([0-9]{3})", s)
|
||||||
|
@ -63,7 +63,7 @@ urlpatterns = [
|
|||||||
path("trial-balance",
|
path("trial-balance",
|
||||||
mia_core_views.todo, name="trial-balance.home"),
|
mia_core_views.todo, name="trial-balance.home"),
|
||||||
path("trial-balance/<str:period_spec>",
|
path("trial-balance/<str:period_spec>",
|
||||||
mia_core_views.todo, name="trial-balance"),
|
views.trial_balance, name="trial-balance"),
|
||||||
path("income-statement",
|
path("income-statement",
|
||||||
mia_core_views.todo, name="income-statement.home"),
|
mia_core_views.todo, name="income-statement.home"),
|
||||||
path("income-statement/<str:period_spec>",
|
path("income-statement/<str:period_spec>",
|
||||||
|
@ -487,3 +487,88 @@ def journal(request, period_spec):
|
|||||||
"pagination": pagination,
|
"pagination": pagination,
|
||||||
"period": period,
|
"period": period,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@require_GET
|
||||||
|
@digest_login_required
|
||||||
|
def trial_balance(request, period_spec):
|
||||||
|
"""The trial blanace."""
|
||||||
|
# The period
|
||||||
|
first_txn = Transaction.objects.order_by("date").first()
|
||||||
|
data_start = first_txn.date if first_txn is not None else None
|
||||||
|
last_txn = Transaction.objects.order_by("-date").first()
|
||||||
|
data_end = last_txn.date if last_txn is not None else None
|
||||||
|
period = Period(period_spec, data_start, data_end)
|
||||||
|
# The accounts
|
||||||
|
nominal = list(
|
||||||
|
Subject.objects.filter(
|
||||||
|
Q(record__transaction__date__gte=period.start),
|
||||||
|
Q(record__transaction__date__lte=period.end),
|
||||||
|
~(Q(code__startswith="1")
|
||||||
|
| Q(code__startswith="2")
|
||||||
|
| Q(code__startswith="3")))
|
||||||
|
.annotate(
|
||||||
|
balance=Sum(Case(
|
||||||
|
When(record__is_credit=True, then=-1),
|
||||||
|
default=1) * F("record__amount")))
|
||||||
|
.filter(balance__isnull=False)
|
||||||
|
.annotate(
|
||||||
|
debit=Case(
|
||||||
|
When(balance__gt=0, then=F("balance")),
|
||||||
|
default=None),
|
||||||
|
credit=Case(
|
||||||
|
When(balance__lt=0, then=-F("balance")),
|
||||||
|
default=None)))
|
||||||
|
real = list(
|
||||||
|
Subject.objects
|
||||||
|
.filter(Q(record__transaction__date__lte=period.end),
|
||||||
|
(Q(code__startswith="1")
|
||||||
|
| Q(code__startswith="2")
|
||||||
|
| Q(code__startswith="3")),
|
||||||
|
~Q(code="3351"))
|
||||||
|
.annotate(
|
||||||
|
balance=Sum(Case(
|
||||||
|
When(record__is_credit=True, then=-1),
|
||||||
|
default=1) * F("record__amount")))
|
||||||
|
.filter(balance__isnull=False)
|
||||||
|
.annotate(
|
||||||
|
debit=Case(
|
||||||
|
When(balance__gt=0, then=F("balance")),
|
||||||
|
default=None),
|
||||||
|
credit=Case(
|
||||||
|
When(balance__lt=0, then=-F("balance")),
|
||||||
|
default=None)))
|
||||||
|
balance = Record.objects.filter(
|
||||||
|
(Q(transaction__date__lt=period.start)
|
||||||
|
& ~(Q(subject__code__startswith="1")
|
||||||
|
| Q(subject__code__startswith="2")
|
||||||
|
| Q(subject__code__startswith="3")))
|
||||||
|
| (Q(transaction__date__lte=period.end)
|
||||||
|
& Q(subject__code="3351")))\
|
||||||
|
.aggregate(
|
||||||
|
balance=Sum(Case(
|
||||||
|
When(is_credit=True, then=-1),
|
||||||
|
default=1) * F("amount")))["balance"]
|
||||||
|
if balance is not None and balance != 0:
|
||||||
|
brought_forward = Subject.objects.filter(code="3351").first()
|
||||||
|
if balance > 0:
|
||||||
|
brought_forward.debit = balance
|
||||||
|
brought_forward.credit = 0
|
||||||
|
else:
|
||||||
|
brought_forward.debit = None
|
||||||
|
brought_forward.credit = -balance
|
||||||
|
real.append(brought_forward)
|
||||||
|
records = nominal + real
|
||||||
|
records.sort(key=lambda x: x.code)
|
||||||
|
record_sum = Subject()
|
||||||
|
record_sum.title = pgettext("Accounting|", "Total")
|
||||||
|
record_sum.debit = sum([x.debit for x in records
|
||||||
|
if x.debit is not None])
|
||||||
|
record_sum.credit = sum([x.credit for x in records
|
||||||
|
if x.credit is not None])
|
||||||
|
return render(request, "accounting/trial-balance.html", {
|
||||||
|
"records": records,
|
||||||
|
"record_sum": record_sum,
|
||||||
|
"reports": ReportUrl(period=period),
|
||||||
|
"period": period,
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user