Replaced the records in the transaction form with external templates, so that these templates can also be used to add new records and replace the complex jQuery operation in the accounting application.

This commit is contained in:
依瑪貓 2020-08-05 23:24:52 +08:00
parent 8294f2af36
commit c7bb3504e9
8 changed files with 194 additions and 404 deletions

View File

@ -29,8 +29,6 @@ $(function () {
return false;
});
$(".record-summary")
.attr("data-toggle", "modal")
.attr("data-target", "#summary-modal")
.on("click", function () {
startSummaryHelper(this);
});

View File

@ -254,121 +254,11 @@ function addNewRecord(button) {
* @private
*/
function insertNewRecord(type, newNo) {
if (isTransfer()) {
insertNewTransferRecord(type, newNo);
} else {
insertNewNonTransferRecord(type, newNo);
}
}
/**
* Inserts a new accounting record for a transfer transaction.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @private
*/
function insertNewTransferRecord(type, newNo) {
const divAccount = createAccountBlock(type, newNo)
.addClass("col-sm-12");
const divAccountRow = $("<div/>")
.addClass("row")
.append(divAccount);
const divSummary = createSummaryBlock(type, newNo)
.addClass("col-lg-8");
const divAmount = createAmountBlock(type, newNo)
.addClass("col-lg-4");
const divSummaryAmountRow = $("<div/>")
.addClass("row")
.append(divSummary, divAmount);
const divContent = $("<div/>")
.append(divAccountRow)
.append(divSummaryAmountRow);
const divBtnGroup = createActionButtonBlock(
type, newNo, type + "-" + newNo + "-delete")
.addClass("btn-group-vertical");
const divActions = $("<div/>")
.append(divBtnGroup);
$("<li/>")
.attr("id", type + "-" + newNo)
.addClass("list-group-item")
.addClass("d-flex")
.addClass(type + "-record")
.append(divContent, divActions)
.appendTo("#" + type + "-records");
}
/**
* Inserts a new accounting record for a non-transfer transaction.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @private
*/
function insertNewNonTransferRecord(type, newNo) {
const divAccount = createAccountBlock(type, newNo)
.addClass("col-lg-6");
const divSummary = createSummaryBlock(type, newNo)
.addClass("col-sm-8");
const divAmount = createAmountBlock(type, newNo)
.addClass("col-sm-4");
const divSummaryAmountRow = $("<div/>")
.addClass("row")
.append(divSummary, divAmount);
const divSummaryAmount = $("<div/>")
.addClass("col-lg-6")
.append(divSummaryAmountRow);
const divContent = $("<div/>")
.addClass("row")
.append(divAccount, divSummaryAmount);
const divBtnGroup = createActionButtonBlock(
type, newNo, type + "-" + newNo + "-delete")
.addClass("btn-group")
.addClass("d-none d-lg-flex");
const divBtnGroupVertical = createActionButtonBlock(
type, newNo, type + "-" + newNo + "-m-delete")
.addClass("btn-group-vertical")
.addClass("d-lg-none");
const divActions = $("<div/>")
.append(divBtnGroup, divBtnGroupVertical);
$("<li/>")
.attr("id", type + "-" + newNo)
.addClass("list-group-item")
.addClass("d-flex")
.addClass("justify-content-between")
.addClass(type + "-record")
.append(divContent, divActions)
.appendTo("#" + type + "-records");
}
/**
* Creates and returns a new <div></div> account block.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @returns {JQuery<HTMLElement>} the new <div></div> account block
* @private
*/
function createAccountBlock(type, newNo) {
const order = $("<input/>")
.attr("id", type + "-" + newNo + "-ord")
.attr("type", "hidden")
.attr("name", type + "-" + newNo + "-ord")
.addClass(type + "-ord");
const account = $("<select/>")
.attr("id", type + "-" + newNo + "-account")
.attr("name", type + "-" + newNo + "-account")
.addClass("form-control")
.addClass("record-account")
.addClass(type + "-account")
$("#" + type + "-records").append(
JSON.parse($("#new-record-template").val())
.replace(/TTT/g, type)
.replace(/NNN/g, String(newNo)));
$("#" + type + "-" + newNo + "-account")
.on("focus", function () {
removeBlankOption(this);
})
@ -378,64 +268,16 @@ function createAccountBlock(type, newNo) {
.each(function () {
initializeAccountOptions(this);
});
const accountError = $("<div/>")
.attr("id", type + "-" + newNo + "-account-error")
.addClass("invalid-feedback");
return $("<div/>")
.append(order, account, accountError);
}
/**
* Creates and returns a new <div></div> summary block.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @returns {JQuery<HTMLElement>} the new <div></div> summary block
* @private
*/
function createSummaryBlock(type, newNo) {
const summary = $("<input/>")
.attr("id", type + "-" + newNo + "-summary")
.attr("type", "text")
.attr("name", type + "-" + newNo + "-summary")
.addClass("form-control")
.addClass("record-summary")
$("#" + type + "-" + newNo + "-summary")
.on("blur", function () {
validateSummary(this);
});
if (typeof startSummaryHelper === "function") {
summary
.attr("data-toggle", "modal")
.attr("data-target", "#summary-modal")
.on("click", function () {
})
.on("click", function () {
if (typeof startSummaryHelper === "function") {
startSummaryHelper(this);
});
}
const summaryError = $("<div/>")
.attr("id", type + "-" + newNo + "-summary-error")
.addClass("invalid-feedback");
return $("<div/>")
.append(summary, summaryError);
}
/**
* Creates and returns a new <div></div> amount block.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @returns {JQuery<HTMLElement>} the new <div></div> amount block
* @private
*/
function createAmountBlock(type, newNo) {
const amount = $("<input/>")
.attr("id", type + "-" + newNo + "-amount")
.attr("type", "number")
.attr("name", type + "-" + newNo + "-amount")
.attr("min", 1)
.attr("required", "required")
.addClass("form-control")
.addClass("record-amount")
.addClass(type + "-to-sum")
}
});
$("#" + type + "-" + newNo + "-amount")
.on("blur", function () {
validateAmount(this);
})
@ -443,41 +285,10 @@ function createAmountBlock(type, newNo) {
updateTotalAmount(this);
validateBalance();
});
const amountError = $("<div/>")
.attr("id", type + "-" + newNo + "-amount-error")
.addClass("invalid-feedback");
return $("<div/>")
.append(amount, amountError);
}
/**
* Creates and returns a new <div></div> action button block.
*
* @param {string} type the record type, either "debit" or "credit"
* @param {number} newNo the number of this new accounting record
* @param {string} btnDelId the ID of the delete button
* @returns {JQuery<HTMLElement>} the new <div></div> button block
* @private
*/
function createActionButtonBlock(type, newNo, btnDelId) {
const btnSort = $("<button/>")
.attr("type", "button")
.addClass("btn btn-outline-secondary")
.addClass("btn-sort-" + type)
.append($("<i/>").addClass("fas fa-sort"));
const btnDelete = $("<button/>")
.attr("id", btnDelId)
.attr("type", "button")
.addClass("btn btn-danger")
.addClass("btn-del-record")
.addClass("btn-del-" + type)
$("#" + type + "-" + newNo + "-delete")
.on("click", function () {
deleteRecord(this);
})
.append($("<i/>").addClass("fas fa-trash"));
return $("<div/>")
.addClass("btn-actions-" + type)
.append(btnSort, btnDelete);
});
}
/**

View File

@ -23,7 +23,6 @@ First written: 2020/7/23
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Cash Expense Transaction" context "Accounting|" as title %}
@ -47,12 +46,13 @@ First written: 2020/7/23
</a>
</div>
{# 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="summary-categories" type="hidden" value="{{ summary_categories }}" />
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
<form id="txn-form" action="{% if item.transaction %}{% url_keep_return "accounting:transactions.update" "expense" item.transaction %}{% 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="summary-categories" type="hidden" value="{{ summary_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>
@ -66,56 +66,10 @@ First written: 2020/7/23
<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.id.value %}
<input type="hidden" name="debit-{{ forloop.counter }}-id" value="{{ x.id.value }}" />
{% endif %}
<input id="debit-{{ forloop.counter }}-ord" class="debit-ord" type="hidden" name="debit-{{ forloop.counter }}-ord" value="{{ forloop.counter }}" />
<select id="debit-{{ forloop.counter }}-account" class="form-control record-account debit-account {% if x.account.errors %} is-invalid {% endif %}" name="debit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.value|default:"" }}" selected="selected">{{ x.account.value|default:"" }} {{ x.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="debit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ x.account.errors.0|default:"" }}</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 x.summary.errors %} is-invalid {% endif %}" type="text" name="debit-{{ forloop.counter }}-summary" value="{{ x.summary.value|default:"" }}" maxlength="128" />
<div id="debit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ x.summary.errors.0|default:"" }}</div>
</div>
<div class="col-sm-4">
<input id="debit-{{ forloop.counter }}-amount" class="form-control record-amount debit-to-sum {% if x.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="debit-{{ forloop.counter }}-amount" value="{{ x.amount.value|default:"" }}" required="required" />
<div id="debit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ x.amount.errors.0|default:"" }}</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>
{% for record in item.debit_records %}
{% with record_type="debit" no=forloop.counter order=forloop.counter %}
{% include "accounting/transactions/form-record-non-transfer.html" %}
{% endwith %}
{% endfor %}
</ul>
<ul class="list-group">

View File

@ -0,0 +1,71 @@
{% comment %}
The Mia Accounting Application
form-record-non-transfer.html: The template for a record in the non-transfer transaction form
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/8/5
{% endcomment %}
<li id="{{ record_type }}-{{ no }}" class="list-group-item d-flex justify-content-between draggable-record {{ record_type }}-record">
<div class="row">
<div class="col-lg-6">
{% if record.id.value %}
<input type="hidden" name="{{ record_type }}-{{ no }}-id" value="{{ record.id.value }}" />
{% endif %}
<input id="{{ record_type }}-{{ no }}-ord" class="{{ record_type }}-ord" type="hidden" name="{{ record_type }}-{{ no }}-ord" value="{{ order }}" />
<select id="{{ record_type }}-{{ no }}-account" class="form-control record-account {{ record_type }}-account {% if record.account.errors %} is-invalid {% endif %}" name="{{ record_type }}-{{ no }}-account">
{% if record.account is not None %}
<option value="{{ record.account.value|default:"" }}" selected="selected">{{ record.account.value|default:"" }} {{ record.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="{{ record_type }}-{{ no }}-account-error" class="invalid-feedback">{{ record.account.errors.0|default:"" }}</div>
</div>
<div class="col-lg-6">
<div class="row">
<div class="col-sm-8">
<input id="{{ record_type }}-{{ no }}-summary" class="form-control record-summary {% if record.summary.errors %} is-invalid {% endif %}" type="text" name="{{ record_type }}-{{ no }}-summary" value="{{ record.summary.value|default:"" }}" maxlength="128" data-toggle="modal" data-target="#summary-modal" />
<div id="{{ record_type }}-{{ no }}-summary-error" class="invalid-feedback">{{ record.summary.errors.0|default:"" }}</div>
</div>
<div class="col-sm-4">
<input id="{{ record_type }}-{{ no }}-amount" class="form-control record-amount {{ record_type }}-to-sum {% if record.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="{{ record_type }}-{{ no }}-amount" value="{{ record.amount.value|default:"" }}" required="required" />
<div id="{{ record_type }}-{{ no }}-amount-error" class="invalid-feedback">{{ record.amount.errors.0|default:"" }}</div>
</div>
</div>
</div>
</div>
<div>
<div class="btn-group d-none d-lg-flex btn-actions-{{ record_type }}">
<button class="btn btn-outline-secondary btn-sort-{{ record_type }}" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="{{ record_type }}-{{ no }}-delete" type="button" class="btn btn-danger btn-del-record btn-del-{{ record_type }}">
<i class="fas fa-trash"></i>
</button>
</div>
<div class="btn-group-vertical d-lg-none btn-actions-{{ record_type }}">
<button class="btn btn-outline-secondary btn-sort-{{ record_type }}" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="{{ record_type }}-{{ no }}-delete" type="button" class="btn btn-danger btn-del-record btn-del-{{ record_type }}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>

View File

@ -0,0 +1,63 @@
{% comment %}
The Mia Accounting Application
form-record-transfer.html: The template for a record in the transfer transaction form
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/8/5
{% endcomment %}
<li id="{{ record_type }}-{{ no }}" class="list-group-item d-flex draggable-record {{ record_type }}-record">
<div>
<div class="row">
<div class="col-sm-12">
{% if record.id.value %}
<input type="hidden" name="{{ record_type }}-{{ no }}-id" value="{{ record.id.value }}" />
{% endif %}
<input id="{{ record_type }}-{{ no }}-ord" class="{{ record_type }}-ord" type="hidden" name="{{ record_type }}-{{ no }}-ord" value="{{ order }}" />
<select id="{{ record_type }}-{{ no }}-account" class="form-control record-account {{ record_type }}-account {% if record.account.errors %} is-invalid {% endif %}" name="{{ record_type }}-{{ no }}-account">
{% if record.account is not None %}
<option value="{{ record.account.value|default:"" }}" selected="selected">{{ record.account.value|default:"" }} {{ record.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="{{ record_type }}-{{ no }}-account-error" class="invalid-feedback">{{ record.account.errors.0|default:"" }}</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<input id="{{ record_type }}-{{ no }}-summary" class="form-control record-summary {% if record.summary.errors %} is-invalid {% endif %}" type="text" name="{{ record_type }}-{{ no }}-summary" value="{{ record.summary.value|default:"" }}" maxlength="128" data-toggle="modal" data-target="#summary-modal" />
<div id="{{ record_type }}-{{ no }}-summary-error" class="invalid-feedback">{{ record.summary.errors.0|default:"" }}</div>
</div>
<div class="col-lg-4">
<input id="{{ record_type }}-{{ no }}-amount" class="form-control record-amount {{ record_type }}-to-sum {% if record.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="{{ record_type }}-{{ no }}-amount" value="{{ record.amount.value|default:"" }}" required="required" />
<div id="{{ record_type }}-{{ no }}-amount-error" class="invalid-feedback">{{ record.amount.errors.0|default:"" }}</div>
</div>
</div>
</div>
<div>
<div class="btn-group-vertical btn-actions-{{ record_type }}">
<button class="btn btn-outline-secondary btn-sort-{{ record_type }}" type="button">
<i class="fas fa-sort"></i>
</button>
<button id="{{ record_type }}-{{ no }}-m-delete" type="button" class="btn btn-danger btn-del-record btn-del-{{ record_type }}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</li>

View File

@ -23,7 +23,6 @@ First written: 2020/7/23
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Cash Income Transaction" context "Accounting|" as title %}
@ -47,12 +46,13 @@ First written: 2020/7/23
</a>
</div>
{# 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="summary-categories" type="hidden" value="{{ summary_categories }}" />
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
<form id="txn-form" action="{% if item.transaction %}{% url_keep_return "accounting:transactions.update" "income" item.transaction %}{% 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="summary-categories" type="hidden" value="{{ summary_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>
@ -66,56 +66,10 @@ First written: 2020/7/23
<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.id.value %}
<input type="hidden" name="credit-{{ forloop.counter }}-id" value="{{ x.id.value }}" />
{% endif %}
<input id="credit-{{ forloop.counter }}-ord" class="credit-ord" type="hidden" name="credit-{{ forloop.counter }}-ord" value="{{ forloop.counter }}" />
<select id="credit-{{ forloop.counter }}-account" class="form-control record-account credit-account {% if x.account.errors %} is-invalid {% endif %}" name="credit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.value|default:"" }}" selected="selected">{{ x.account.value|default:"" }} {{ x.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="credit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ x.account.errors.0|default:"" }}</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 x.summary.errors %} is-invalid {% endif %}" type="text" name="credit-{{ forloop.counter }}-summary" value="{{ x.summary.value|default:"" }}" maxlength="128" />
<div id="credit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ x.summary.errors.0|default:"" }}</div>
</div>
<div class="col-sm-4">
<input id="credit-{{ forloop.counter }}-amount" class="form-control record-amount credit-to-sum {% if x.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="credit-{{ forloop.counter }}-amount" value="{{ x.amount.value|default:"" }}" required="required" />
<div id="credit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ x.amount.errors.0|default:"" }}</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>
{% for record in item.credit_records %}
{% with record_type="credit" no=forloop.counter order=forloop.counter %}
{% include "accounting/transactions/form-record-non-transfer.html" %}
{% endwith %}
{% endfor %}
</ul>
<ul class="list-group">

View File

@ -23,7 +23,6 @@ First written: 2020/7/23
{% load static %}
{% load i18n %}
{% load mia_core %}
{% load accounting %}
{% block settings %}
{% trans "Transfer Transaction" context "Accounting|" as title %}
@ -47,12 +46,13 @@ First written: 2020/7/23
</a>
</div>
{# 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="summary-categories" type="hidden" value="{{ summary_categories }}" />
<input id="new-record-template" type="hidden" value="{{ new_record_template }}" />
<form id="txn-form" action="{% if item.transaction %}{% url_keep_return "accounting:transactions.update" "transfer" item.transaction %}{% 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="summary-categories" type="hidden" value="{{ summary_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>
@ -68,48 +68,10 @@ First written: 2020/7/23
<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.id.value %}
<input type="hidden" name="debit-{{ forloop.counter }}-id" value="{{ x.id.value }}" />
{% endif %}
<input id="debit-{{ forloop.counter }}-ord" class="debit-ord" type="hidden" name="debit-{{ forloop.counter }}-ord" value="{{ forloop.counter }}" />
<select id="debit-{{ forloop.counter }}-account" class="form-control record-account debit-account {% if x.account.errors %} is-invalid {% endif %}" name="debit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.value|default:"" }}" selected="selected">{{ x.account.value|default:"" }} {{ x.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="debit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ x.account.errors.0|default:"" }}</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<input id="debit-{{ forloop.counter }}-summary" class="form-control record-summary {% if x.summary.errors %} is-invalid {% endif %}" type="text" name="debit-{{ forloop.counter }}-summary" value="{{ x.summary.value|default:"" }}" maxlength="128" />
<div id="debit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ x.summary.errors.0|default:"" }}</div>
</div>
<div class="col-lg-4">
<input id="debit-{{ forloop.counter }}-amount" class="form-control record-amount debit-to-sum {% if x.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="debit-{{ forloop.counter }}-amount" value="{{ x.amount.value|default:"" }}" required="required" />
<div id="debit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ x.amount.errors.0|default:"" }}</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>
{% for record in item.debit_records %}
{% with record_type="debit" no=forloop.counter order=forloop.counter %}
{% include "accounting/transactions/form-record-transfer.html" %}
{% endwith %}
{% endfor %}
</ul>
<ul class="list-group">
@ -132,48 +94,10 @@ First written: 2020/7/23
<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.id.value %}
<input type="hidden" name="credit-{{ forloop.counter }}-id" value="{{ x.id.value }}" />
{% endif %}
<input id="credit-{{ forloop.counter }}-ord" class="credit-ord" type="hidden" name="credit-{{ forloop.counter }}-ord" value="{{ forloop.counter }}" />
<select id="credit-{{ forloop.counter }}-account" class="form-control record-account credit-account {% if x.account.errors %} is-invalid {% endif %}" name="credit-{{ forloop.counter }}-account">
{% if x.account is not None %}
<option value="{{ x.account.value|default:"" }}" selected="selected">{{ x.account.value|default:"" }} {{ x.account_title|default:"" }}</option>
{% else %}
<option value=""></option>
{% endif %}
<option value="">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</option>
</select>
<div id="credit-{{ forloop.counter }}-account-error" class="invalid-feedback">{{ x.account.errors.0|default:"" }}</div>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<input id="credit-{{ forloop.counter }}-summary" class="form-control record-summary {% if x.summary.errors %} is-invalid {% endif %}" type="text" name="credit-{{ forloop.counter }}-summary" value="{{ x.summary.value|default:"" }}" maxlength="128" />
<div id="credit-{{ forloop.counter }}-summary-error" class="invalid-feedback">{{ x.summary.errors.0|default:"" }}</div>
</div>
<div class="col-lg-4">
<input id="credit-{{ forloop.counter }}-amount" class="form-control record-amount credit-to-sum {% if x.amount.errors %} is-invalid {% endif %}" type="number" min="1" name="credit-{{ forloop.counter }}-amount" value="{{ x.amount.value|default:"" }}" required="required" />
<div id="credit-{{ forloop.counter }}-amount-error" class="invalid-feedback">{{ x.amount.errors.0|default:"" }}</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>
{% for record in item.credit_records %}
{% with record_type="credit" no=forloop.counter order=forloop.counter %}
{% include "accounting/transactions/form-record-transfer.html" %}
{% endwith %}
{% endfor %}
</ul>
<ul class="list-group">

View File

@ -18,6 +18,7 @@
"""The view controllers of the accounting application.
"""
import json
import re
from django.conf import settings
@ -26,6 +27,7 @@ from django.db.models import Sum, Case, When, F, Q, Max, Count, BooleanField
from django.db.models.functions import TruncMonth, Coalesce, Now
from django.http import JsonResponse, HttpResponseRedirect
from django.shortcuts import render
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import timezone
from django.utils.decorators import method_decorator
@ -853,9 +855,22 @@ def txn_edit(request, txn_type, txn=None):
if len(txn.credit_records) == 0:
txn.records.append(Record(ord=1, is_credit=True))
form = make_txn_form_from_model(txn_type, txn)
new_record_context = {"record": Record(),
"record_type": "TTT",
"no": "NNN",
"order": ""}
if txn_type == "transfer":
new_record_template = json.dumps(render_to_string(
"accounting/transactions/form-record-transfer.html",
new_record_context))
else:
new_record_template = json.dumps(render_to_string(
"accounting/transactions/form-record-non-transfer.html",
new_record_context))
return render(request, F"accounting/transactions/{txn_type}/form.html", {
"item": form,
"summary_categories": get_summary_categories,
"new_record_template": new_record_template,
})