Added the income statement in the accounting application.

This commit is contained in:
依瑪貓 2020-07-20 20:58:07 +08:00
parent 6a9eb5ed0e
commit 175e28f862
3 changed files with 262 additions and 1 deletions

View File

@ -0,0 +1,198 @@
{% 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|" %}Income Statement 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-file-invoice" %}
{% trans "Income Statement" 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 item_list %}
{# 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 }}</h2>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-borderless table-hover table-sm income-statement-table">
<thead>
<tr>
<th scope="col"></th>
<th class="amount" colspan="2" scope="col">{% trans "Amount" context "Period|" as text %}{{ text|force_escape }}</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for section in item_list %}
<tr class="first-level-header">
<td><div>{{ section.title|title|escape }}</div></td>
<td class="amount"></td>
<td class="amount"></td>
<td class="actions"></td>
</tr>
{% for group in section.groups %}
<tr class="second-level-header">
<td><div class="second-level-header">{{ group.title|title|escape }}</div></td>
<td class="amount"></td>
<td class="amount"></td>
<td class="actions"></td>
</tr>
{% for item in group.details %}
<tr>
<td><div class="subject">{{ item.title|title|escape }}</div></td>
<td class="amount {% if item.balance < 0 %} text-danger {% endif %}">{{ item.balance|accounting_amount }}</td>
<td class="amount"></td>
<td class="actions">
<a href="{% url "accounting:ledger" item.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 %}
<tr class="total">
<td><div>{% trans "Total" context "Period|" as text %}{{ text|force_escape }}</div></td>
<td class="amount"></td>
<td class="amount {% if group.total < 0 %} text-danger {% endif %}">{{ group.total|accounting_amount }}</td>
<td class="actions"></td>
</tr>
{% endfor %}
{% if section.cumulative_total is not None %}
<tr class="cum-total">
<td><div>{{ section.cumulative_total.title|title|escape }}</div></td>
<td class="amount"></td>
<td class="amount {% if section.cumulative_total.total < 0 %} text-danger {% endif %}">{{ section.cumulative_total.total|accounting_amount }}</td>
<td class="actions"></td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{# The list for small screens #}
{% comment %}
<div class="d-sm-none report-block report-block-sm">
<div class="row justify-content-center">
<h2>{{ title }}</h2>
</div>
<div class="row">
<div class="col-sm-12">
<ul class="list-group income-statement-list">
{% for item in item_list %}
<li class="list-group-item d-flex justify-content-between align-items-center <%=$record->class%>">
% if (!defined $record->class && defined $record->subject->code) {
<a class="list-group-item-action" href="<%=url_for("acct.ledger", {"subject_code" => $record->subject->code})%>">
<%=$record->subject->title%>
<div class="float-right">
% if (defined $record->amount) {
<span class="badge <%=$record->amount < 0? "badge-warning": "badge-secondary"%> badge-pill">
<%=format_amount($record->amount)%>
</span>
% }
% if (defined $record->total) {
<span class="badge <%=$record->total < 0? "badge-danger": "badge-info"%> badge-pill">
<%=format_amount($record->total)%>
</span>
% }
</div>
</a>
% } else {
<%=$record->subject->title%>
<div class="float-right">
% if (defined $record->amount) {
<span class="badge <%=$record->amount < 0? "badge-warning": "badge-secondary"%> badge-pill">
<%=format_amount($record->amount)%>
</span>
% }
% if (defined $record->total) {
<span class="badge <%=$record->total < 0? "badge-danger": "badge-info"%> badge-pill">
<%=format_amount($record->total)%>
</span>
% }
</div>
% }
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endcomment %}
{% else %}
<p>{{ _("There is currently no data.")|force_escape }}</p>
{% endif %}
{% endblock %}

View File

@ -67,7 +67,7 @@ urlpatterns = [
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>",
mia_core_views.todo, name="income-statement"), views.income_statement, name="income-statement"),
path("balance-sheet", path("balance-sheet",
mia_core_views.todo, name="balance-sheet.home"), mia_core_views.todo, name="balance-sheet.home"),
path("balance-sheet/<str:period_spec>", path("balance-sheet/<str:period_spec>",

View File

@ -575,3 +575,66 @@ def trial_balance(request, period_spec):
"reports": ReportUrl(period=period), "reports": ReportUrl(period=period),
"period": period, "period": period,
}) })
@require_GET
@digest_login_required
def income_statement(request, period_spec):
"""The income statement."""
# The period
period = _get_period(period_spec)
# The accounts
accounts = 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))
groups = list(Subject.objects.filter(
code__in=[x.code[:2] for x in accounts]))
sections = list(Subject.objects.filter(
Q(code="4") | Q(code="5") | Q(code="6")
| Q(code="7") | Q(code="8") | Q(code="9")).order_by("code"))
cumulative_accounts = {
"4": None,
"5": Subject(title=pgettext("Accounting|", "Gross Income")),
"6": Subject(title=pgettext("Accounting|", "Operating Income")),
"7": Subject(title=pgettext("Accounting|", "Before Tax Income")),
"8": Subject(title=pgettext("Accounting|", "After Tax Income")),
"9": Subject.objects.get(code="3353"),
}
cumulative_total = 0
for section in sections:
section.groups = [x for x in groups
if x.code[:1] == section.code]
for group in section.groups:
group.details = [x for x in accounts
if x.code[:2] == group.code]
group.balance = None
group.total = sum([x.balance
for x in group.details])
section.balance = None
section.total = sum([x.total for x in section.groups])
cumulative_total = cumulative_total + section.total
if section.code in cumulative_accounts:
if cumulative_accounts[section.code] is None:
section.cumulative_total = None
else:
section.cumulative_total\
= cumulative_accounts[section.code]
section.cumulative_total.balance = None
section.cumulative_total.total = cumulative_total
return render(request, "accounting/income-statement.html", {
"item_list": sections,
"reports": ReportUrl(period=period),
"period": period,
})