Added the view and the templates for the forms of the transactions in the accounting application.

This commit is contained in:
依瑪貓 2020-07-27 22:36:28 +08:00
parent cc18dbd5f1
commit 99fb99b160
7 changed files with 577 additions and 6 deletions

View File

@ -106,7 +106,7 @@ class Transaction(models.Model):
list[Record]: The records. list[Record]: The records.
""" """
if self._records is None: if self._records is None:
self._records = self.record_set.all() self._records = list(self.record_set.all())
return self._records return self._records
@records.setter @records.setter
@ -115,23 +115,33 @@ class Transaction(models.Model):
@property @property
def debit_records(self): def debit_records(self):
"""The debit records of this transaction.""" """The debit records of this transaction.
Returns:
list[Record]: The records.
"""
return [x for x in self.records if not x.is_credit] return [x for x in self.records if not x.is_credit]
@property @property
def debit_total(self): def debit_total(self):
"""The total amount of the debit records.""" """The total amount of the debit records."""
return sum([x.amount for x in self.debit_records]) return sum([x.amount for x in self.debit_records
if isinstance(x.amount, int)])
@property @property
def credit_records(self): def credit_records(self):
"""The credit records of this transaction.""" """The credit records of this transaction.
Returns:
list[Record]: The records.
"""
return [x for x in self.records if x.is_credit] return [x for x in self.records if x.is_credit]
@property @property
def credit_total(self): def credit_total(self):
"""The total amount of the credit records.""" """The total amount of the credit records."""
return sum([x.amount for x in self.credit_records]) return sum([x.amount for x in self.credit_records
if isinstance(x.amount, int)])
_is_balanced = None _is_balanced = None

View File

@ -0,0 +1,151 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
edit.html: The template for the form of a cash-expense transaction
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/23
{% endcomment %}
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Cash Expense Transaction" context "Accounting|" as title %}
{% setvar "title" title %}
{% endblock %}
{% block content %}
<div class="btn-group btn-actions">
<a class="btn btn-primary" role="button" href="{% if item.pk %}{% url_keep_return "accounting:transactions.show" "expense" item %}{% elif request.GET.r %}{{ request.GET.r }}{% else %}{% url "accounting:home" %}{% endif %}">
<i class="fas fa-chevron-circle-left"></i>
{% trans "Back" context "Navigation|" as text %}{{ text|force_escape }}
</a>
</div>
<form id="txn-form" action="{% if item.pk %}{% url_keep_return "accounting:transactions.update" "expense" item %}{% else %}{% url_keep_return "accounting:transactions.store" "expense" %}{% endif %}" method="post">
{% csrf_token %}
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="debit-general-categories" type="hidden" value="{{ debit_general_categories }}" />
<input id="debit-travel-categories" type="hidden" value="{{ debit_travel_categories }}" />
<input id="debit-bus-categories" type="hidden" value="{{ debit_bus_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<input id="txn-date" class="form-control {% if errors.date %} is-invalid {% endif %}" type="date" name="date" value="{{ item.date }}" required="required" />
<div id="txn-date-error" class="invalid-feedback">{{ errors.date|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12">
<ul id="debit-records" class="list-group">
{% for x in item.debit_records %}
<li id="debit-{{ forloop.counter }}" class="list-group-item d-flex justify-content-between draggable-record debit-record">
<div class="row">
<div class="col-lg-6">
{% if x.pk is not None %}
<input type="hidden" name="debit-{{ forloop.counter }}-sn" value="{{ x.pk }}" />
{% endif %}
<input id="debit-{{ forloop.counter }}-ord" class="debit-ord" type="hidden" name="debit-{{ forloop.counter }}-ord" value="{{ x.ord }}" />
<select id="debit-{{ forloop.counter }}-account" class="form-control record-account debit-account {% if errors.debit.account|index:forloop.counter %} is-invalid {% endif %}" name="debit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.pk }}" selected="selected">{{ x.account.code }} {{ x.account.title }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="debit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ errors.debit.account|index:forloop.counter }}</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="col-sm-8">
<input id="debit-{{ forloop.counter }}-summary" class="form-control record-summary {% if errors.debit.summary|index:forloop.counter %} is-invalid {% endif %}" type="text" name="debit-{{ forloop.counter }}-summary" value="{{ x.summary|default:"" }}" maxlength="128" />
<div id="debit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ errors.debit.summary|index:forloop.counter }}</div>
</div>
<div class="col-sm-4">
<input id="debit-{{ forloop.counter }}-amount" class="form-control record-amount debit-to-sum {% if errors.debit.amount|index:forloop.counter %} is-invalid {% endif %}" type="number" min="1" name="debit-{{ forloop.counter }}-amount" value="{{ x.amount|default:"" }}" required="required" />
<div id="debit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ errors.debit.amount|index:forloop.counter }}</div>
</div>
</div>
</div>
</div>
<div>
<div class="btn-group d-none d-lg-flex btn-actions-debit">
<button class="btn btn-outline-secondary btn-sort-debit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="debit-{{ forloop.counter }}-delete" type="button" class="btn btn-danger btn-del-record btn-del-debit">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="btn-group-vertical d-lg-none btn-actions-debit">
<button class="btn btn-outline-secondary btn-sort-debit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="debit-{{ forloop.counter }}-m-delete" type="button" class="btn btn-danger btn-del-record btn-del-debit">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
{% endfor %}
</ul>
<ul class="list-group">
<li class="list-group-item">
<button id="debit-new" class="btn btn-primary btn-new" type="button">
<i class="fas fa-plus"></i>
</button>
</li>
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span id="debit-total" class="amount">{{ item.debit_total }}</span>
</div>
</li>
</ul>
</div>
</div>
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-note">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<textarea id="txn-note" class="form-control {% if errors.notes %} is-invalid {% endif %}" name="note">{{ item.notes|default:"" }}</textarea>
<div id="txn-note-error" class="invalid-feedback">{{ errors.notes|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12">
<button class="btn btn-primary" type="submit">
<i class="fas fa-save"></i>
{% trans "Save" context "Accounting|" as text %}{{ text|force_escape }}
</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,151 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
edit.html: The template for the form of a cash-income transaction
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/23
{% endcomment %}
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Cash Income Transaction" context "Accounting|" as title %}
{% setvar "title" title %}
{% endblock %}
{% block content %}
<div class="btn-group btn-actions">
<a class="btn btn-primary" role="button" href="{% if item.pk %}{% url_keep_return "accounting:transactions.show" "income" item %}{% elif request.GET.r %}{{ request.GET.r }}{% else %}{% url "accounting:home" %}{% endif %}">
<i class="fas fa-chevron-circle-left"></i>
{% trans "Back" context "Navigation|" as text %}{{ text|force_escape }}
</a>
</div>
<form id="txn-form" action="{% if item.pk %}{% url_keep_return "accounting:transactions.update" "income" item %}{% else %}{% url_keep_return "accounting:transactions.store" "income" %}{% endif %}" method="post">
{% csrf_token %}
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="credit-general-categories" type="hidden" value="{{ credit_general_categories }}" />
<input id="credit-travel-categories" type="hidden" value="{{ credit_travel_categories }}" />
<input id="credit-bus-categories" type="hidden" value="{{ credit_bus_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<input id="txn-date" class="form-control {% if errors.date %} is-invalid {% endif %}" type="date" name="date" value="{{ item.date }}" required="required" />
<div id="txn-date-error" class="invalid-feedback">{{ errors.date|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12">
<ul id="credit-records" class="list-group">
{% for x in item.credit_records %}
<li id="credit-{{ forloop.counter }}" class="list-group-item d-flex justify-content-between draggable-record credit-record">
<div class="row">
<div class="col-lg-6">
{% if x.pk is not None %}
<input type="hidden" name="credit-{{ forloop.counter }}-sn" value="{{ x.pk }}" />
{% endif %}
<input id="credit-{{ forloop.counter }}-ord" class="credit-ord" type="hidden" name="credit-{{ forloop.counter }}-ord" value="{{ x.ord }}" />
<select id="credit-{{ forloop.counter }}-account" class="form-control record-account credit-account {% if errors.credit.account|index:forloop.counter %} is-invalid {% endif %}" name="credit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.pk }}" selected="selected">{{ x.account.code }} {{ x.account.title }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="credit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ errors.credit.account|index:forloop.counter }}</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="col-sm-8">
<input id="credit-{{ forloop.counter }}-summary" class="form-control record-summary {% if errors.credit.summary|index:forloop.counter %} is-invalid {% endif %}" type="text" name="credit-{{ forloop.counter }}-summary" value="{{ x.summary|default:"" }}" maxlength="128" />
<div id="credit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ errors.credit.summary|index:forloop.counter }}</div>
</div>
<div class="col-sm-4">
<input id="credit-{{ forloop.counter }}-amount" class="form-control record-amount credit-to-sum {% if errors.credit.amount|index:forloop.counter %} is-invalid {% endif %}" type="number" min="1" name="credit-{{ forloop.counter }}-amount" value="{{ x.amount|default:"" }}" required="required" />
<div id="credit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ errors.credit.amount|index:forloop.counter }}</div>
</div>
</div>
</div>
</div>
<div>
<div class="btn-group d-none d-lg-flex btn-actions-credit">
<button class="btn btn-outline-secondary btn-sort-credit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="credit-{{ forloop.counter }}-delete" type="button" class="btn btn-danger btn-del-record btn-del-credit">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="btn-group-vertical d-lg-none btn-actions-credit">
<button class="btn btn-outline-secondary btn-sort-credit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="credit-{{ forloop.counter }}-delete" type="button" class="btn btn-danger btn-del-record btn-del-credit">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
{% endfor %}
</ul>
<ul class="list-group">
<li class="list-group-item">
<button id="credit-new" class="btn btn-primary btn-new" type="button">
<i class="fas fa-plus"></i>
</button>
</li>
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span id="credit-total" class="amount">{{ item.credit_total }}</span>
</div>
</li>
</ul>
</div>
</div>
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-note">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<textarea id="txn-note" class="form-control {% if errors.notes %} is-invalid {% endif %}" name="note">{{ item.notes|default:"" }}</textarea>
<div id="txn-note-error" class="invalid-feedback">{{ errors.notes|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12">
<button class="btn btn-primary" type="submit">
<i class="fas fa-save"></i>
{% trans "Save" context "Accounting|" as text %}{{ text|force_escape }}
</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,213 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
edit.html: The template for the form of a transfer transaction
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/23
{% endcomment %}
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Transfer Transaction" context "Accounting|" as title %}
{% setvar "title" title %}
{% endblock %}
{% block content %}
<div class="btn-group btn-actions">
<a class="btn btn-primary" role="button" href="{% if item.pk %}{% url_keep_return "accounting:transactions.show" "transfer" item %}{% elif request.GET.r %}{{ request.GET.r }}{% else %}{% url "accounting:home" %}{% endif %}">
<i class="fas fa-chevron-circle-left"></i>
{% trans "Back" context "Navigation|" as text %}{{ text|force_escape }}
</a>
</div>
<form id="txn-form" action="{% if transaction.pk %}{% url_keep_return "accounting:transactions.update" "transfer" item %}{% else %}{% url_keep_return "accounting:transactions.store" "transfer" %}{% endif %}" method="post">
{% csrf_token %}
{# TODO: To be done #}
<input id="l10n-messages" type="hidden" value="{{ l10n_messages }}" />
<input id="account-option-url" type="hidden" value="{% url "accounting:accounts.options" %}" />
<input id="debit-general-categories" type="hidden" value="{{ debit_general_categories }}" />
<input id="debit-travel-categories" type="hidden" value="{{ debit_travel_categories }}" />
<input id="debit-bus-categories" type="hidden" value="{{ debit_bus_categories }}" />
<input id="credit-general-categories" type="hidden" value="{{ credit_general_categories }}" />
<input id="credit-travel-categories" type="hidden" value="{{ credit_travel_categories }}" />
<input id="credit-bus-categories" type="hidden" value="{{ credit_bus_categories }}" />
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-date">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<input id="txn-date" class="form-control {% if errors.date %} is-invalid {% endif %}" type="date" name="date" value="{{ item.date }}" required="required" />
<div id="txn-date-error" class="invalid-feedback">{{ errors.date|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-6">
<h2>{% trans "Debit" context "Accounting|" as text %}{{ text|force_escape }}</h2>
<ul id="debit-records" class="list-group">
{% for x in item.debit_records %}
<li id="debit-{{ forloop.counter }}" class="list-group-item d-flex draggable-record debit-record">
<div>
<div class="row">
<div class="col-sm-12">
{% if x.pk is not None %}
<input type="hidden" name="debit-{{ forloop.counter }}-sn" value="{{ x.pk }}" />
{% endif %}
<input id="debit-{{ forloop.counter }}-ord" class="debit-ord" type="hidden" name="debit-{{ forloop.counter }}-ord" value="{{ x.ord }}" />
<select id="debit-{{ forloop.counter }}-account" class="form-control record-account debit-account {% if errors.debit.account|index:forloop.counter %} is-invalid {% endif %}" name="debit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.pk }}" selected="selected">{{ x.account.code }} {{ x.account.title }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="debit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ errors.debit.account|index:forloop.counter }}</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<input id="debit-{{ forloop.counter }}-summary" class="form-control record-summary {% if errors.debit.summary|index:forloop.counter %} is-invalid {% endif %}" type="text" name="debit-{{ forloop.counter }}-summary" value="{{ x.summary|default:"" }}" maxlength="128" />
<div id="debit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ errors.debit.summary|index:forloop.counter }}</div>
</div>
<div class="col-lg-4">
<input id="debit-{{ forloop.counter }}-amount" class="form-control record-amount debit-to-sum {% if errors.debit.amount|index:forloop.counter %} is-invalid {% endif %}" type="number" min="1" name="debit-{{ forloop.counter }}-amount" value="{{ x.amount|default:"" }}" required="required" />
<div id="debit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ errors.debit.amount|index:forloop.counter }}</div>
</div>
</div>
</div>
<div>
<div class="btn-group-vertical btn-actions-debit">
<button class="btn btn-outline-secondary btn-sort-debit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="debit-{{ forloop.counter }}-m-delete" type="button" class="btn btn-danger btn-del-record btn-del-debit">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
{% endfor %}
</ul>
<ul class="list-group">
<li class="list-group-item">
<button id="debit-new" class="btn btn-primary btn-new" type="button">
<i class="fas fa-plus"></i>
</button>
</li>
<li class="list-group-item">
<div id="debit-total-row" class="d-flex justify-content-between align-items-center form-control {% if errors.balance %} is-invalid {% endif %} balance-row">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span id="debit-total" class="amount">{{ item.debit_total }}</span>
</div>
<div id="debit-total-error" class="invalid-feedback balance-error">{{ errors.balance }}</div>
</li>
</ul>
</div>
<div class="col-sm-6">
<h2>{% trans "Credit" context "Accounting|" as text %}{{ text|force_escape }}</h2>
<ul id="credit-records" class="list-group">
{% for x in item.credit_records %}
<li id="credit-{{ forloop.counter }}" class="list-group-item d-flex draggable-record credit-record">
<div>
<div class="row">
<div class="col-sm-12">
{% if x.pk is not None %}
<input type="hidden" name="credit-{{ forloop.counter }}-sn" value="{{ x.pk }}" />
{% endif %}
<input id="credit-{{ forloop.counter }}-ord" class="credit-ord" type="hidden" name="credit-{{ forloop.counter }}-ord" value="{{ x.ord }}" />
<select id="credit-{{ forloop.counter }}-account" class="form-control record-account credit-account {% if errors.credit.account|index:forloop.counter %} is-invalid {% endif %}" name="credit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.pk }}" selected="selected">{{ x.account.code }} {{ x.account.title }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="credit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ errors.credit.account|index:forloop.counter }}</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<input id="credit-{{ forloop.counter }}-summary" class="form-control record-summary {% if errors.credit.summary|index:forloop.counter %} is-invalid {% endif %}" type="text" name="credit-{{ forloop.counter }}-summary" value="{{ x.summary|default:"" }}" maxlength="128" />
<div id="credit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ errors.credit.summary|index:forloop.counter }}</div>
</div>
<div class="col-lg-4">
<input id="credit-{{ forloop.counter }}-amount" class="form-control record-amount credit-to-sum {% if errors.credit.amount|index:forloop.counter %} is-invalid {% endif %}" type="number" min="1" name="credit-{{ forloop.counter }}-amount" value="{{ x.amount|default:"" }}" required="required" />
<div id="credit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ errors.credit.amount|index:forloop.counter }}</div>
</div>
</div>
</div>
<div>
<div class="btn-group-vertical btn-actions-credit">
<button class="btn btn-outline-secondary btn-sort-credit" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="credit-{{ forloop.counter }}-m-delete" type="button" class="btn btn-danger btn-del-record btn-del-credit">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>
{% endfor %}
</ul>
<ul class="list-group">
<li class="list-group-item">
<button id="credit-new" class="btn btn-primary btn-new" type="button">
<i class="fas fa-plus"></i>
</button>
</li>
<li class="list-group-item">
<div id="credit-total-row" class="d-flex justify-content-between align-items-center form-control {% if errors.balance %} is-invalid {% endif %} balance-row">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span id="credit-total" class="amount">{{ item.credit_total }}</span>
</div>
<div id="credit-total-error" class="invalid-feedback balance-error">{{ errors.balance }}</div>
</li>
</ul>
</div>
</div>
<div class="row form-group">
<div class="col-sm-2">
<label for="txn-note">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</label>
</div>
<div class="col-sm-10">
<textarea id="txn-note" class="form-control {% if errors.notes %} is-invalid {% endif %}" name="note">{{ item.notes|default:"" }}</textarea>
<div id="txn-note-error" class="invalid-feedback">{{ errors.notes|default:"" }}</div>
</div>
</div>
<div class="row form-group">
<div class="col-sm-12">
<button class="btn btn-primary" type="submit">
<i class="fas fa-save"></i>
{% trans "Save" context "Accounting|" as text %}{{ text|force_escape }}
</button>
</div>
</div>
</form>
{% endblock %}

View File

@ -68,7 +68,7 @@ urlpatterns = [
path("search", path("search",
views.search, name="search"), views.search, name="search"),
path("transactions/<txn-type:type>/create", path("transactions/<txn-type:type>/create",
mia_core_views.todo, name="transactions.create"), views.transaction_create, name="transactions.create"),
path("transactions/<txn-type:type>/store", path("transactions/<txn-type:type>/store",
mia_core_views.todo, name="transactions.store"), mia_core_views.todo, name="transactions.store"),
path("transactions/<txn-type:type>/<txn:transaction>", path("transactions/<txn-type:type>/<txn:transaction>",
@ -95,4 +95,6 @@ urlpatterns = [
mia_core_views.todo, name="accounts.update"), mia_core_views.todo, name="accounts.update"),
path("accounts/<str:account_code>/delete", path("accounts/<str:account_code>/delete",
mia_core_views.todo, name="accounts.delete"), mia_core_views.todo, name="accounts.delete"),
path("accounts/options",
mia_core_views.todo, name="accounts.options"),
] ]

View File

@ -859,3 +859,26 @@ def transaction_show(request, type, transaction):
"transaction_type": type, "transaction_type": type,
"item": transaction, "item": transaction,
}) })
@require_GET
@digest_login_required
def transaction_create(request, type):
"""The view to create an accounting transaction.
Args:
request (HttpRequest): The request.
type (str): The transaction type.
Returns:
HttpResponse: The response.
"""
transaction = Transaction()
if len(transaction.debit_records) == 0:
transaction.records.append(Record(ord=1, is_credit=False))
if len(transaction.credit_records) == 0:
transaction.records.append(Record(ord=1, is_credit=True))
return render(request, F"accounting/transactions/{type}/edit.html", {
"transaction_type": type,
"item": transaction,
})

View File

@ -153,3 +153,24 @@ def smart_month(value):
if value.year == year and value.month == month: if value.year == year and value.month == month:
return gettext("Last Month") return gettext("Last Month")
return defaultfilters.date(value, "Y/n") return defaultfilters.date(value, "Y/n")
@register.filter()
def index(value, arg):
"""Returns the arg-th element of the value list or tuple.
Args:
value (list|tuple): The list or tuple.
arg (int): The index.
Returns:
any: The arg-th element of the value
"""
if not (isinstance(value, list) or isinstance(value, tuple)):
return None
if not isinstance(arg, int):
return None
if arg >= len(value):
return None
return value[arg]