Added the search page in the accounting application.

This commit is contained in:
依瑪貓 2020-07-21 10:04:29 +08:00
parent f114f84c85
commit c6a62d92d5
4 changed files with 227 additions and 4 deletions

View File

@ -0,0 +1,174 @@
{% 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/21
{% endcomment %}
{% load static %}
{% load i18n %}
{% load humanize %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% blocktrans asvar title with query=request.GET.q context "Accounting|" %}Search Result for “{{ query }}”{% 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-search" %}
{% trans "Search" context "Accounting|" as current_report_title %}
{% include "accounting/include/report-chooser.html" %}
{% endwith %}
<form class="btn btn-primary input-group" action="{% url "accounting:search" %}" method="get">
<input id="search-input" class="form-control form-control-sm search-input" type="text" name="q" value="{{ request.GET.q }}" />
<label for="search-input" class="search-label">
<button type="submit">
<i class="fas fa-search"></i>
{% trans "Search" context "Accounting|" as text %}
{{ text|force_escape }}
</button>
</label>
</form>
</div>
{% if item_list %}
{% include "mia_core/include/pagination.html" %}
{# The table for large screens #}
<table class="table table-striped table-hover d-none d-md-table general-journal-table">
<thead>
<tr>
<th scope="col">{% trans "Date" context "Accounting|" as text %}{{ text|force_escape }}</th>
<th scope="col">{% trans "Subject" context "Accounting|" as text %}{{ text|force_escape }}</th>
<th scope="col">{% trans "Summary" 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 scope="col">{% trans "Notes" 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 item in item_list %}
<tr class="{% if not item.is_balanced or item.has_order_hole %} table-danger {% endif %}">
<td>{{ item.transaction.date|smart_date }}</td>
<td>{{ item.subject.title|title }}</td>
<td><div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}">{{ item.summary|default:"" }}{% if not item.is_balanced %}
<span class="badge badge-danger badge-pill">
{% trans "Unbalanced" context "Accounting|" as text %}
{{ text|force_escape }}
</span>
{% endif %}{% if item.has_order_hole %}
<span class="badge badge-danger badge-pill">
{% trans "Need Reorder" context "Accounting|" as text %}
{{ text|force_escape }}
</span>
{% endif %}</div></td>
<td class="amount">{{ item.debit_amount|accounting_amount }}</td>
<td class="amount">{{ item.credit_amount|accounting_amount }}</td>
<td>{{ item.transaction.note|default:"" }}</td>
<td class="actions">
<a href="{{ item.transaction.get_absolute_url }}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i>
{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{# The list for small screens #}
<ul class="list-group d-md-none">
{% for item in item_list %}
<li class="list-group-item {% if not item.is_balanced or item.has_order_hole %} list-group-item-danger {% endif %}">
<a class="list-group-item-action" href="{{ item.transaction.get_absolute_url }}">
<div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}">
<div class="date-subject-line">
{{ item.transaction.date|smart_date }} {{ item.subject.title|title }}
</div>
<div class="d-flex justify-content-between align-items-center">
<div>
{{ item.summary|default:"" }}
{% if not item.is_balanced %}
<span class="badge badge-danger badge-pill">
{% trans "Unbalanced" context "Accounting|" as text %}
{{ text|force_escape }}
</span>
{% endif %}
{% if item.has_order_hole %}
<span class="badge badge-danger badge-pill">
{% trans "Need Reorder" context "Accounting|" as text %}
{{ text|force_escape }}
</span>
{% endif %}
</div>
<div>
{% if item.debit_amount is not None %}
<span class="badge badge-success badge-pill">
{{ item.debit_amount|intcomma:False }}
</span>
{% endif %}
{% if item.credit_amount is not None %}
<span class="badge badge-warning badge-pill">
{{ item.credit_amount|intcomma:False }}
</span>
{% endif %}
</div>
</div>
<div>{{ item.transaction.note|default:"" }}</div>
</div>
</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>{{ _("There is currently no data.")|force_escape }}</p>
{% endif %}
{% endblock %}

View File

@ -74,7 +74,7 @@ urlpatterns = [
path("balance-sheet/<str:period_spec>", path("balance-sheet/<str:period_spec>",
reports.balance_sheet, name="balance-sheet"), reports.balance_sheet, name="balance-sheet"),
path("search", path("search",
mia_core_views.todo, name="search"), reports.search, name="search"),
path("transactions/<txn-type:type>/create", path("transactions/<txn-type:type>/create",
mia_core_views.todo, name="transactions.create"), mia_core_views.todo, name="transactions.create"),
path("transactions/<txn-type:type>/store", path("transactions/<txn-type:type>/store",

View File

@ -26,7 +26,7 @@ from django.http import HttpResponseRedirect, Http404
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.utils import dateformat, timezone from django.utils import dateformat, timezone
from django.utils.translation import pgettext from django.utils.translation import pgettext, get_language
from django.views.decorators.http import require_GET from django.views.decorators.http import require_GET
from accounting.models import Record, Transaction, Subject, \ from accounting.models import Record, Transaction, Subject, \
@ -35,7 +35,7 @@ from accounting.utils import ReportUrl
from mia import settings from mia import settings
from mia_core.digest_auth import digest_login_required from mia_core.digest_auth import digest_login_required
from mia_core.period import Period from mia_core.period import Period
from mia_core.utils import Pagination from mia_core.utils import Pagination, get_multi_lingual_search
@require_GET @require_GET
@ -791,6 +791,34 @@ def balance_sheet(request, period_spec):
}) })
@require_GET
@digest_login_required
def search(request):
"""The search.
Args:
request (HttpRequest) The request.
Returns:
HttpResponse: The response.
"""
# The accounting records
query = request.GET.get("q")
if query is None:
records = []
else:
records = Record.objects.filter(
get_multi_lingual_search("subject__title", query)
| Q(subject__code__icontains=query)
| Q(summary__icontains=query)
| Q(transaction__note__icontains=query))
pagination = Pagination(request, records, True)
return render(request, "accounting/search.html", {
"item_list": pagination.items,
"pagination": pagination,
})
def _get_period(period_spec): def _get_period(period_spec):
"""Obtains the period helper. """Obtains the period helper.

View File

@ -22,7 +22,7 @@ import random
import urllib.parse import urllib.parse
from django.conf import settings from django.conf import settings
from django.db.models import Model from django.db.models import Model, Q
from django.utils.translation import pgettext, get_language from django.utils.translation import pgettext, get_language
@ -104,6 +104,27 @@ def get_multi_lingual_attr(model, name, default=None):
return getattr(model, name + Language.default().db) return getattr(model, name + Language.default().db)
def get_multi_lingual_search(attr, query):
"""Returns the query condition on a multi-lingual attribute.
Args:
attr (str): The base name of the multi-lingual attribute.
query (str): The query.
Returns:
Q: The query condition
"""
language = Language.current()
if language.is_default:
return Q(**{attr + language.db + "__icontains": query})
default = Language.default()
q = (Q(**{attr + language.db + "__isnull": False})
& Q(**{attr + language.db + "__icontains": query}))\
| (Q(**{attr + language.db + "__isnull": True})
& Q(**{attr + default.db + "__icontains": query}))
return q
class UrlBuilder: class UrlBuilder:
"""The URL builder. """The URL builder.