Added the income statement in the accounting application.
This commit is contained in:
		
							
								
								
									
										198
									
								
								accounting/templates/accounting/income-statement.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								accounting/templates/accounting/income-statement.html
									
									
									
									
									
										Normal 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 %} | ||||
| @@ -67,7 +67,7 @@ urlpatterns = [ | ||||
|     path("income-statement", | ||||
|          mia_core_views.todo, name="income-statement.home"), | ||||
|     path("income-statement/<str:period_spec>", | ||||
|          mia_core_views.todo, name="income-statement"), | ||||
|          views.income_statement, name="income-statement"), | ||||
|     path("balance-sheet", | ||||
|          mia_core_views.todo, name="balance-sheet.home"), | ||||
|     path("balance-sheet/<str:period_spec>", | ||||
|   | ||||
| @@ -575,3 +575,66 @@ def trial_balance(request, period_spec): | ||||
|         "reports": ReportUrl(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, | ||||
|     }) | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user