Added the transaction views in the accounting application.

This commit is contained in:
依瑪貓 2020-07-23 22:02:26 +08:00
parent 41737c250e
commit 2db3899dea
18 changed files with 543 additions and 76 deletions

View File

@ -142,3 +142,33 @@ class LedgerAccountConverter:
str: The account code. str: The account code.
""" """
return value.code return value.code
class TransactionConverter:
"""The path converter for the accounting transactions."""
regex = "[1-9][0-9]{8}"
def to_python(self, value):
"""Returns the transaction by the transaction ID.
Args:
value (str): The transaction ID.
Returns:
Transaction: The account.
"""
try:
return Transaction.objects.get(sn=value)
except Transaction.DoesNotExist:
raise ValueError
def to_url(self, value):
"""Returns the ID of an account.
Args:
value (Transaction): The transaction.
Returns:
str: The transaction ID.
"""
return value.sn

View File

@ -82,7 +82,7 @@ class Transaction(models.Model):
sn = models.PositiveIntegerField(primary_key=True) sn = models.PositiveIntegerField(primary_key=True)
date = models.DateField() date = models.DateField()
ord = models.PositiveSmallIntegerField(default=1) ord = models.PositiveSmallIntegerField(default=1)
note = models.CharField(max_length=128, null=True, blank=True) notes = models.CharField(max_length=128, null=True, blank=True)
created_at = models.DateTimeField( created_at = models.DateTimeField(
auto_now_add=True, db_column="created") auto_now_add=True, db_column="created")
created_by = models.ForeignKey( created_by = models.ForeignKey(
@ -101,11 +101,21 @@ class Transaction(models.Model):
"""The debit records of this transaction.""" """The debit records of this transaction."""
return [x for x in self.record_set.all() if not x.is_credit] return [x for x in self.record_set.all() if not x.is_credit]
@property
def debit_total(self):
"""The total amount of the debit records."""
return sum([x.amount for x in self.debit_records])
@property @property
def credit_records(self): def credit_records(self):
"""The credit records of this transaction.""" """The credit records of this transaction."""
return [x for x in self.record_set.all() if x.is_credit] return [x for x in self.record_set.all() if x.is_credit]
@property
def credit_total(self):
"""The total amount of the credit records."""
return sum([x.amount for x in self.credit_records])
_is_balanced = None _is_balanced = None
@property @property
@ -170,20 +180,27 @@ class Transaction(models.Model):
and credit_records[0].account.code == "1111" and credit_records[0].account.code == "1111"
and credit_records[0].summary is None) and credit_records[0].summary is None)
@property
def type(self):
"""The transaction type."""
if self.is_cash_expense:
return "expense"
elif self.is_cash_income:
return "income"
else:
return "transfer"
def get_absolute_url(self): def get_absolute_url(self):
"""Returns the URL to view this transaction.""" """Returns the URL to view this transaction."""
if self.is_cash_expense: if self.is_cash_expense:
return reverse( return reverse(
"accounting:transactions.view", "accounting:transactions.show", args=("expense", self))
args=("expense", self.sn))
elif self.is_cash_income: elif self.is_cash_income:
return reverse( return reverse(
"accounting:transactions.view", "accounting:transactions.show", args=("income", self))
args=("income", self.sn))
else: else:
return reverse( return reverse(
"accounting:transactions.view", "accounting:transactions.show", args=("transfer", self))
args=("transfer", self.sn))
def __str__(self): def __str__(self):
"""Returns the string representation of this accounting """Returns the string representation of this accounting

View File

@ -44,18 +44,15 @@ First written: 2020/7/20
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>

View File

@ -43,18 +43,15 @@ First written: 2020/7/15
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>

View File

@ -44,18 +44,15 @@ First written: 2020/7/1
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
@ -131,7 +128,7 @@ First written: 2020/7/1
<td class="amount {% if item.balance < 0 %} text-danger {% endif %}">{{ item.balance|accounting_amount }}</td> <td class="amount {% if item.balance < 0 %} text-danger {% endif %}">{{ item.balance|accounting_amount }}</td>
<td class="actions"> <td class="actions">
{% if item.sn is not None %} {% if item.sn is not None %}
<a href="{{ item.transaction.get_absolute_url }}" class="btn btn-info" role="button"> <a href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
<span class="d-none d-lg-inline">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</span> <span class="d-none d-lg-inline">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</span>
</a> </a>
@ -147,7 +144,7 @@ First written: 2020/7/1
{% for item in item_list %} {% 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 %}"> <li class="list-group-item {% if not item.is_balanced or item.has_order_hole %} list-group-item-danger {% endif %}">
{% if item.sn is not None %} {% if item.sn is not None %}
<a class="list-group-item-action" href="{{ item.transaction.get_absolute_url }}"> <a class="list-group-item-action" href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}">
<div class="date-account-line d-flex justify-content-between align-items-center"> <div class="date-account-line d-flex justify-content-between align-items-center">
{{ item.transaction.date|smart_date }} {{ item.account.title|title }} {{ item.transaction.date|smart_date }} {{ item.account.title|title }}
</div> </div>

View File

@ -44,18 +44,15 @@ First written: 2020/7/19
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>

View File

@ -44,18 +44,15 @@ First written: 2020/7/17
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
@ -111,7 +108,7 @@ First written: 2020/7/17
<td>{{ item.transaction.note|default:"" }}</td> <td>{{ item.transaction.note|default:"" }}</td>
<td class="actions"> <td class="actions">
{% if item.sn is not None %} {% if item.sn is not None %}
<a href="{{ item.transaction.get_absolute_url }}" class="btn btn-info" role="button"> <a href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
{% trans "View" context "Accounting|" as text %}{{ text|force_escape }} {% trans "View" context "Accounting|" as text %}{{ text|force_escape }}
</a> </a>
@ -127,7 +124,7 @@ First written: 2020/7/17
{% for item in item_list %} {% 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 %}"> <li class="list-group-item {% if not item.is_balanced or item.has_order_hole %} list-group-item-danger {% endif %}">
{% if item.sn is not None %} {% if item.sn is not None %}
<a class="list-group-item-action" href="{{ item.transaction.get_absolute_url }}"> <a class="list-group-item-action" href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}">
<div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}"> <div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}">
<div class="date-account-line"> <div class="date-account-line">
{{ item.transaction.date|smart_date }} {{ item.account.title|title }} {{ item.transaction.date|smart_date }} {{ item.account.title|title }}

View File

@ -43,18 +43,15 @@ First written: 2020/7/16
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>

View File

@ -44,18 +44,15 @@ First written: 2020/7/16
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
@ -134,7 +131,7 @@ First written: 2020/7/16
<td class="amount {% if item.balance < 0 %} text-danger {% endif %}">{{ item.balance|accounting_amount }}</td> <td class="amount {% if item.balance < 0 %} text-danger {% endif %}">{{ item.balance|accounting_amount }}</td>
<td class="actions"> <td class="actions">
{% if item.sn is not None %} {% if item.sn is not None %}
<a href="{{ item.transaction.get_absolute_url }}" class="btn btn-info" role="button"> <a href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
<span class="d-none d-lg-inline">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</span> <span class="d-none d-lg-inline">{% trans "View" context "Accounting|" as text %}{{ text|force_escape }}</span>
</a> </a>
@ -150,7 +147,7 @@ First written: 2020/7/16
{% for item in item_list %} {% for item in item_list %}
<li class="list-group-item {% if not item.is_balanced or item.has_order_hole or not item.is_credit_card_paid %} list-group-item-danger {% endif %}{% if item.is_existing_equipment %} list-group-item-info {% endif %}"> <li class="list-group-item {% if not item.is_balanced or item.has_order_hole or not item.is_credit_card_paid %} list-group-item-danger {% endif %}{% if item.is_existing_equipment %} list-group-item-info {% endif %}">
{% if item.sn is not None %} {% if item.sn is not None %}
<a class="list-group-item-action" href="{{ item.transaction.get_absolute_url }}"> <a class="list-group-item-action" href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}">
<div class="date-account-line"> <div class="date-account-line">
{{ item.transaction.date|smart_date }} {{ item.account.title|title }} {{ item.transaction.date|smart_date }} {{ item.account.title|title }}
</div> </div>

View File

@ -44,18 +44,15 @@ First written: 2020/7/21
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
@ -113,7 +110,7 @@ First written: 2020/7/21
<td class="amount">{{ item.credit_amount|accounting_amount }}</td> <td class="amount">{{ item.credit_amount|accounting_amount }}</td>
<td>{{ item.transaction.note|default:"" }}</td> <td>{{ item.transaction.note|default:"" }}</td>
<td class="actions"> <td class="actions">
<a href="{{ item.transaction.get_absolute_url }}" class="btn btn-info" role="button"> <a href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}" class="btn btn-info" role="button">
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
{% trans "View" context "Accounting|" as text %}{{ text|force_escape }} {% trans "View" context "Accounting|" as text %}{{ text|force_escape }}
</a> </a>
@ -127,7 +124,7 @@ First written: 2020/7/21
<ul class="list-group d-md-none"> <ul class="list-group d-md-none">
{% for item in item_list %} {% 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 %}"> <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 }}"> <a class="list-group-item-action" href="{% url_with_return "accounting:transactions.show" item.transaction.type item.transaction %}">
<div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}"> <div class="{% if item.is_credit %} journal-credit {% else %} journal-debit {% endif %}">
<div class="date-account-line"> <div class="date-account-line">
{{ item.transaction.date|smart_date }} {{ item.account.title|title }} {{ item.transaction.date|smart_date }} {{ item.account.title|title }}

View File

@ -0,0 +1,117 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
cash.html: The template for 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 %}
{% if item.has_order_hole %}
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{ _("Error:") }}</strong> {% trans "The transactions on this day are not well-ordered. Please reorder them." context "Accounting|" as text %}{{ text|force_escape }}
</div>
{% endif %}
<div class="row">
<div class="col-sm-2">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.date|smart_date }}</div>
</div>
<table class="table table-striped table-hover d-none d-sm-table">
<thead>
<tr>
<th scope="col">{% trans "Account" 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 "$" context "Accounting|" as text %}{{ text|force_escape }}</th>
</tr>
</thead>
<tbody>
{% for x in item.debit_records %}
<tr>
<td>{{ x.account.title|title }}</td>
<td>{{ x.summary|default:"" }}</td>
<td class="amount">{{ x.amount|accounting_amount }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="2">{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}</td>
<td class="amount">{{ item.debit_total|accounting_amount }}</td>
</tr>
</tfoot>
</table>
<ul class="list-group d-sm-none">
{% for x in item.debit_records %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{{ x.account.title|title }}
<span class="badge badge-info">{{ x.amount|accounting_amount }}</span>
</div>
<div>{{ x.summary|default:"" }}</div>
</li>
{% endfor %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span class="badge badge-info">{{ item.debit_total|accounting_amount }}</span>
</div>
</li>
</ul>
{% if item.notes %}
<div class="row">
<div class="col-sm-2">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.notes }}</div>
</div>
{% endif %}
<div class="row form-group">
<div class="col-sm-2">{{ _("Created at:") }}</div>
<div class="col-sm-10">{{ item.created_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Created by:") }}</div>
<div class="col-sm-10">{{ item.created_by.name }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated at:") }}</div>
<div class="col-sm-10">{{ item.updated_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated by:") }}</div>
<div class="col-sm-10">{{ item.updated_by.name }}</div>
</div>
{% endblock %}

View File

@ -0,0 +1,119 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
cash.html: The template for 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 %}
{% if item.has_order_hole %}
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{ _("Error:") }}</strong> {% trans "The transactions on this day are not well-ordered. Please reorder them." context "Accounting|" as text %}{{ text|force_escape }}
</div>
{% endif %}
<div class="row">
<div class="col-sm-2">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.date|smart_date }}</div>
</div>
<table class="table table-striped table-hover d-none d-sm-table">
<thead>
<tr>
<th scope="col">{% trans "Account" 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 "$" context "Accounting|" as text %}{{ text|force_escape }}</th>
</tr>
</thead>
<tbody>
{% for x in item.credit_records %}
<tr>
<td>{{ x.account.title|title }}</td>
<td>{{ x.summary|default:"" }}</td>
<td class="amount">{{ x.amount|accounting_amount }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="2">{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}</td>
<td class="amount">{{ item.credit_total|accounting_amount }}</td>
</tr>
</tfoot>
</table>
<ul class="list-group d-sm-none">
{% for x in item.credit_records %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{{ x.account.title|title }}
<span class="badge badge-info">{{ x.amount|accounting_amount }}</span>
</div>
<div>{{ x.summary|default:"" }}</div>
</li>
{% endfor %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span class="badge badge-info">{{ item.credit_total|accounting_amount }}</span>
</div>
</li>
</ul>
{% if item.notes %}
<div class="row">
<div class="col-sm-2">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.notes }}</div>
</div>
{% endif %}
<div class="row form-group">
<div class="col-sm-2">{{ _("Created at:") }}</div>
<div class="col-sm-10">{{ item.created_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Created by:") }}</div>
<div class="col-sm-10">{{ item.created_by.name }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated at:") }}</div>
<div class="col-sm-10">{{ item.updated_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated by:") }}</div>
<div class="col-sm-10">{{ item.updated_by.name }}</div>
</div>
{% endblock %}

View File

@ -0,0 +1,171 @@
{% extends "base.html" %}
{% comment %}
The Mia Accounting Application
cash.html: The template for 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 %}
{% if item.has_order_hole %}
<div class="alert alert-danger alert-dismissible fade show">
<button type="button" class="close" data-dismiss="alert">&times;</button>
<strong>{{ _("Error:") }}</strong> {% trans "The transactions on this day are not well-ordered. Please reorder them." context "Accounting|" as text %}{{ text|force_escape }}
</div>
{% endif %}
<div class="row">
<div class="col-sm-2">{% trans "Date:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.date|smart_date }}</div>
</div>
<div class="row">
<div class="col-sm-6">
<h2>{% trans "Debit" context "Accounting|" as text %}{{ text|force_escape }}</h2>
<table class="table table-striped table-hover d-none d-lg-table">
<thead>
<tr>
<th scope="col">{% trans "Account" 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 "$" context "Accounting|" as text %}{{ text|force_escape }}</th>
</tr>
</thead>
<tbody>
{% for x in item.debit_records %}
<tr>
<td>{{ x.account.title|title }}</td>
<td>{{ x.summary|default:"" }}</td>
<td class="amount">{{ x.amount|accounting_amount }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="2">{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}</td>
<td class="amount">{{ item.debit_total|accounting_amount }}</td>
</tr>
</tfoot>
</table>
<ul class="list-group d-lg-none">
{% for x in item.debit_records %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{{ x.account.title|title }}
<span class="badge badge-info">{{ x.amount|accounting_amount }}</span>
</div>
<div>{{ x.summary|default:"" }}</div>x
</li>
{% endfor %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span class="badge badge-info">{{ item.debit_total|accounting_amount }}</span>
</div>
</li>
</ul>
</div>
<div class="col-sm-6">
<h2>{% trans "Credit" context "Accounting|" as text %}{{ text|force_escape }}</h2>
<table class="table table-striped table-hover d-none d-lg-table">
<thead>
<tr>
<th scope="col">{% trans "Account" 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 "$" context "Accounting|" as text %}{{ text|force_escape }}</th>
</tr>
</thead>
<tbody>
{% for x in item.credit_records %}
<tr>
<td>{{ x.account.title|title }}</td>
<td>{{ x.summary|default:"" }}</td>
<td class="amount">{{ x.amount|accounting_amount }}</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="2">{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}</td>
<td class="amount">{{ item.credit_total|accounting_amount }}</td>
</tr>
</tfoot>
</table>
<ul class="list-group d-lg-none">
{% for x in item.credit_records %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{{ x.account.title|title }}
<span class="badge badge-info">{{ x.amount|accounting_amount }}</span>
</div>
<div>{{ x.summary|default:"" }}</div>x
</li>
% }
{% endfor %}
<li class="list-group-item">
<div class="d-flex justify-content-between align-items-center subject-line">
{% trans "Total" context "Accounting|" as text %}{{ text|force_escape }}
<span class="badge badge-info">{{ item.credit_total|accounting_amount }}</span>
</div>
</li>
</ul>
</div>
</div>
{% if item.notes %}
<div class="row">
<div class="col-sm-2">{% trans "Notes:" context "Accounting|" as text %}{{ text|force_escape }}</div>
<div class="col-sm-10">{{ item.notes }}</div>
</div>
{% endif %}
<div class="row form-group">
<div class="col-sm-2">{{ _("Created at:") }}</div>
<div class="col-sm-10">{{ item.created_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Created by:") }}</div>
<div class="col-sm-10">{{ item.created_by.name }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated at:") }}</div>
<div class="col-sm-10">{{ item.updated_at }}</div>
</div>
<div class="row form-group">
<div class="col-sm-2">{{ _("Updated by:") }}</div>
<div class="col-sm-10">{{ item.updated_by.name }}</div>
</div>
{% endblock %}

View File

@ -44,18 +44,15 @@ First written: 2020/7/19
{{ text|force_escape }} {{ text|force_escape }}
</button> </button>
<div class="dropdown-menu"> <div class="dropdown-menu">
{% url "accounting:transaction.create" "expense" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "expense" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Expense" context "Accounting|" as text %} {% trans "Cash Expense" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "income" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "income" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Cash Income" context "Accounting|" as text %} {% trans "Cash Income" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>
{% url "accounting:transaction.create" "transfer" as url %} <a class="dropdown-item" href="{% url_with_return "accounting:transactions.create" "transfer" %}">
<a class="dropdown-item" href="{% url_query url r=request.get_full_path %}">
{% trans "Transfer" context "Accounting|" as text %} {% trans "Transfer" context "Accounting|" as text %}
{{ text|force_escape }} {{ text|force_escape }}
</a> </a>

View File

@ -21,6 +21,9 @@
import re import re
from django import template from django import template
from django.urls import reverse
from mia_core.utils import UrlBuilder
register = template.Library() register = template.Library()
@ -40,3 +43,20 @@ def accounting_amount(value):
if value < 0: if value < 0:
s = "(%s)" % (s) s = "(%s)" % (s)
return s return s
@register.simple_tag(takes_context=True)
def url_with_return(context, view_name, *args):
"""Returns the transaction URL.
Args:
context (RequestContext): The request context.
view_name (str): The view name.
*args (tuple[any]): The URL arguments.
Returns:
str: The URL.
"""
url = reverse(view_name, args=args)
return_to = context.request.get_full_path()
return str(UrlBuilder(url).set_param("return-to", return_to))

View File

@ -24,10 +24,11 @@ from django.urls import path, register_converter
from mia_core import views as mia_core_views from mia_core import views as mia_core_views
from . import converters, views from . import converters, views
register_converter(converters.TransactionTypeConverter, "txn-type")
register_converter(converters.PeriodConverter, "period") register_converter(converters.PeriodConverter, "period")
register_converter(converters.CashAccountConverter, "cash-account") register_converter(converters.CashAccountConverter, "cash-account")
register_converter(converters.LedgerAccountConverter, "ledger-account") register_converter(converters.LedgerAccountConverter, "ledger-account")
register_converter(converters.TransactionTypeConverter, "txn-type")
register_converter(converters.TransactionConverter, "txn")
app_name = "accounting" app_name = "accounting"
urlpatterns = [ urlpatterns = [
@ -69,13 +70,13 @@ urlpatterns = [
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",
mia_core_views.todo, name="transactions.store"), mia_core_views.todo, name="transactions.store"),
path("transactions/<txn-type:type>/<int:pk>", path("transactions/<txn-type:type>/<txn:transaction>",
mia_core_views.todo, name="transactions.view"), views.transaction_show, name="transactions.show"),
path("transactions/<txn-type:type>/<int:pk>/edit", path("transactions/<txn-type:type>/<txn:transaction>/edit",
mia_core_views.todo, name="transactions.edit"), mia_core_views.todo, name="transactions.edit"),
path("transactions/<txn-type:type>/<int:pk>/update", path("transactions/<txn-type:type>/<txn:transaction>/update",
mia_core_views.todo, name="transactions.update"), mia_core_views.todo, name="transactions.update"),
path("transactions/<int:pk>/delete", path("transactions/<txn:transaction>/delete",
mia_core_views.todo, name="transactions.delete"), mia_core_views.todo, name="transactions.delete"),
path("accounts", path("accounts",
mia_core_views.todo, name="accounts"), mia_core_views.todo, name="accounts"),
@ -84,7 +85,7 @@ urlpatterns = [
path("accounts/store", path("accounts/store",
mia_core_views.todo, name="accounts.store"), mia_core_views.todo, name="accounts.store"),
path("accounts/<str:account_code>", path("accounts/<str:account_code>",
mia_core_views.todo, name="accounts.view"), mia_core_views.todo, name="accounts.show"),
path("accounts/<str:account_code>/edit", path("accounts/<str:account_code>/edit",
mia_core_views.todo, name="accounts.edit"), mia_core_views.todo, name="accounts.edit"),
path("accounts/<str:account_code>/update", path("accounts/<str:account_code>/update",

View File

@ -840,3 +840,21 @@ def search(request):
"pagination": pagination, "pagination": pagination,
"reports": ReportUrl(), "reports": ReportUrl(),
}) })
@require_GET
@digest_login_required
def transaction_show(request, type, transaction):
"""The view of an accounting transaction.
Args:
request (HttpRequest): The request.
type (str): The transaction type.
transaction (Transaction): The transaction.
Returns:
HttpResponse: The response.
"""
return render(request, F"accounting/transactions/{type}/show.html", {
"item": transaction,
})

View File

@ -72,6 +72,7 @@ def url_query(url, **kwargs):
Returns: Returns:
str: The URL with query parameters set. str: The URL with query parameters set.
""" """
print(url)
builder = UrlBuilder(url) builder = UrlBuilder(url)
for key in kwargs.keys(): for key in kwargs.keys():
if kwargs[key] is not None: if kwargs[key] is not None: