Added the view and the templates for the forms of the transactions in the accounting application.
This commit is contained in:
parent
cc18dbd5f1
commit
99fb99b160
@ -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
|
||||||
|
|
||||||
|
151
accounting/templates/accounting/transactions/expense/edit.html
Normal file
151
accounting/templates/accounting/transactions/expense/edit.html
Normal 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 %}
|
151
accounting/templates/accounting/transactions/income/edit.html
Normal file
151
accounting/templates/accounting/transactions/income/edit.html
Normal 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 %}
|
213
accounting/templates/accounting/transactions/transfer/edit.html
Normal file
213
accounting/templates/accounting/transactions/transfer/edit.html
Normal 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 %}
|
@ -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"),
|
||||||
]
|
]
|
||||||
|
@ -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,
|
||||||
|
})
|
||||||
|
@ -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]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user