Renamed summary helper to summary editor.
This commit is contained in:
parent
11966a52ba
commit
4eb9346d8d
@ -1,5 +1,5 @@
|
||||
/* The Mia! Accounting Flask Project
|
||||
* summary-helper.js: The JavaScript for the summary helper
|
||||
* summary-editor.js: The JavaScript for the summary editor
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2023 imacat.
|
||||
@ -23,23 +23,23 @@
|
||||
|
||||
// Initializes the page JavaScript.
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
SummaryHelper.initialize();
|
||||
SummaryEditor.initialize();
|
||||
});
|
||||
|
||||
/**
|
||||
* A summary helper.
|
||||
* A summary editor.
|
||||
*
|
||||
*/
|
||||
class SummaryHelper {
|
||||
class SummaryEditor {
|
||||
|
||||
/**
|
||||
* The summary helper form
|
||||
* The summary editor form
|
||||
* @type {HTMLFormElement}
|
||||
*/
|
||||
#form;
|
||||
|
||||
/**
|
||||
* The modal of the summary helper
|
||||
* The modal of the summary editor
|
||||
* @type {HTMLFormElement}
|
||||
*/
|
||||
#modal;
|
||||
@ -129,14 +129,14 @@ class SummaryHelper {
|
||||
tabPlanes = {};
|
||||
|
||||
/**
|
||||
* Constructs a summary helper.
|
||||
* Constructs a summary editor.
|
||||
*
|
||||
* @param form {HTMLFormElement} the summary helper form
|
||||
* @param form {HTMLFormElement} the summary editor form
|
||||
*/
|
||||
constructor(form) {
|
||||
this.#form = form;
|
||||
this.#entryType = form.dataset.entryType;
|
||||
this.prefix = "accounting-summary-helper-" + form.dataset.entryType;
|
||||
this.prefix = "accounting-summary-editor-" + form.dataset.entryType;
|
||||
this.#modal = document.getElementById(this.prefix + "-modal");
|
||||
this.summary = document.getElementById(this.prefix + "-summary");
|
||||
this.number = document.getElementById(this.prefix + "-number-number");
|
||||
@ -156,13 +156,13 @@ class SummaryHelper {
|
||||
}
|
||||
this.currentTab = this.tabPlanes.general;
|
||||
this.#initializeSuggestedAccounts();
|
||||
const helper = this;
|
||||
const editor = this;
|
||||
this.summary.onchange = function () {
|
||||
helper.#onSummaryChange();
|
||||
editor.#onSummaryChange();
|
||||
};
|
||||
this.#form.onsubmit = function () {
|
||||
if (helper.currentTab.validate()) {
|
||||
helper.#submit();
|
||||
if (editor.currentTab.validate()) {
|
||||
editor.#submit();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@ -212,10 +212,10 @@ class SummaryHelper {
|
||||
*
|
||||
*/
|
||||
#initializeSuggestedAccounts() {
|
||||
const helper = this;
|
||||
const editor = this;
|
||||
for (const accountButton of this.#accountButtons) {
|
||||
accountButton.onclick = function () {
|
||||
helper.#selectAccount(accountButton);
|
||||
editor.#selectAccount(accountButton);
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -260,7 +260,7 @@ class SummaryHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback when the summary helper is shown.
|
||||
* The callback when the summary editor is shown.
|
||||
*
|
||||
*/
|
||||
#onOpen() {
|
||||
@ -270,7 +270,7 @@ class SummaryHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the summary helper.
|
||||
* Resets the summary editor.
|
||||
*
|
||||
*/
|
||||
#reset() {
|
||||
@ -282,36 +282,36 @@ class SummaryHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* The summary helpers.
|
||||
* @type {{debit: SummaryHelper, credit: SummaryHelper}}
|
||||
* The summary editors.
|
||||
* @type {{debit: SummaryEditor, credit: SummaryEditor}}
|
||||
*/
|
||||
static #helpers = {}
|
||||
static #editors = {}
|
||||
|
||||
/**
|
||||
* Initializes the summary helpers.
|
||||
* Initializes the summary editors.
|
||||
*
|
||||
*/
|
||||
static initialize() {
|
||||
const forms = Array.from(document.getElementsByClassName("accounting-summary-helper"));
|
||||
const forms = Array.from(document.getElementsByClassName("accounting-summary-editor"));
|
||||
const entryForm = document.getElementById("accounting-entry-form");
|
||||
const formSummaryControl = document.getElementById("accounting-entry-form-summary-control");
|
||||
for (const form of forms) {
|
||||
const helper = new SummaryHelper(form);
|
||||
this.#helpers[helper.#entryType] = helper;
|
||||
const editor = new SummaryEditor(form);
|
||||
this.#editors[editor.#entryType] = editor;
|
||||
}
|
||||
const helpers = this;
|
||||
const editors = this;
|
||||
formSummaryControl.onclick = function () {
|
||||
helpers.#helpers[entryForm.dataset.entryType].#onOpen();
|
||||
editors.#editors[entryForm.dataset.entryType].#onOpen();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the summary helper for a new journal entry.
|
||||
* Initializes the summary editor for a new journal entry.
|
||||
*
|
||||
* @param entryType {string} the entry type, either "debit" or "credit"
|
||||
*/
|
||||
static initializeNewJournalEntry(entryType) {
|
||||
this.#helpers[entryType].#onOpen();
|
||||
this.#editors[entryType].#onOpen();
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,10 +324,10 @@ class SummaryHelper {
|
||||
class TabPlane {
|
||||
|
||||
/**
|
||||
* The parent summary helper
|
||||
* @type {SummaryHelper}
|
||||
* The parent summary editor
|
||||
* @type {SummaryEditor}
|
||||
*/
|
||||
helper;
|
||||
editor;
|
||||
|
||||
/**
|
||||
* The prefix of the HTML ID and classes
|
||||
@ -350,11 +350,11 @@ class TabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
*/
|
||||
constructor(helper) {
|
||||
this.helper = helper;
|
||||
this.prefix = this.helper.prefix + "-" + this.tabId();
|
||||
constructor(editor) {
|
||||
this.editor = editor;
|
||||
this.prefix = this.editor.prefix + "-" + this.tabId();
|
||||
this.#tab = document.getElementById(this.prefix + "-tab");
|
||||
this.#page = document.getElementById(this.prefix + "-page");
|
||||
const tabPlane = this;
|
||||
@ -399,7 +399,7 @@ class TabPlane {
|
||||
*
|
||||
*/
|
||||
switchToMe() {
|
||||
for (const tabPlane of Object.values(this.helper.tabPlanes)) {
|
||||
for (const tabPlane of Object.values(this.editor.tabPlanes)) {
|
||||
tabPlane.#tab.classList.remove("active")
|
||||
tabPlane.#tab.ariaCurrent = "false";
|
||||
tabPlane.#page.classList.add("d-none");
|
||||
@ -409,7 +409,7 @@ class TabPlane {
|
||||
this.#tab.ariaCurrent = "page";
|
||||
this.#page.classList.remove("d-none");
|
||||
this.#page.ariaCurrent = "page";
|
||||
this.helper.currentTab = this;
|
||||
this.editor.currentTab = this;
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,11 +442,11 @@ class TagTabPlane extends TabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
* @override
|
||||
*/
|
||||
constructor(helper) {
|
||||
super(helper);
|
||||
constructor(editor) {
|
||||
super(editor);
|
||||
this.tag = document.getElementById(this.prefix + "-tag");
|
||||
this.tagError = document.getElementById(this.prefix + "-tag-error");
|
||||
// noinspection JSValidateTypes
|
||||
@ -459,7 +459,7 @@ class TagTabPlane extends TabPlane {
|
||||
if (tagButton.dataset.value === tabPlane.tag.value) {
|
||||
tagButton.classList.remove("btn-outline-primary");
|
||||
tagButton.classList.add("btn-primary");
|
||||
tabPlane.helper.filterSuggestedAccounts(tagButton);
|
||||
tabPlane.editor.filterSuggestedAccounts(tagButton);
|
||||
isMatched = true;
|
||||
} else {
|
||||
tagButton.classList.remove("btn-primary");
|
||||
@ -467,7 +467,7 @@ class TagTabPlane extends TabPlane {
|
||||
}
|
||||
}
|
||||
if (!isMatched) {
|
||||
tabPlane.helper.filterSuggestedAccounts(null);
|
||||
tabPlane.editor.filterSuggestedAccounts(null);
|
||||
}
|
||||
tabPlane.updateSummary();
|
||||
tabPlane.validateTag();
|
||||
@ -494,7 +494,7 @@ class TagTabPlane extends TabPlane {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.helper.filterSuggestedAccounts(selectedTagButton);
|
||||
this.editor.filterSuggestedAccounts(selectedTagButton);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -512,7 +512,7 @@ class TagTabPlane extends TabPlane {
|
||||
tagButton.classList.remove("btn-outline-primary");
|
||||
tagButton.classList.add("btn-primary");
|
||||
tabPlane.tag.value = tagButton.dataset.value;
|
||||
tabPlane.helper.filterSuggestedAccounts(tagButton);
|
||||
tabPlane.editor.filterSuggestedAccounts(tagButton);
|
||||
tabPlane.updateSummary();
|
||||
};
|
||||
}
|
||||
@ -589,12 +589,12 @@ class GeneralTagTab extends TagTabPlane {
|
||||
* @override
|
||||
*/
|
||||
updateSummary() {
|
||||
const pos = this.helper.summary.value.indexOf("—");
|
||||
const pos = this.editor.summary.value.indexOf("—");
|
||||
const prefix = this.tag.value === ""? "": this.tag.value + "—";
|
||||
if (pos === -1) {
|
||||
this.helper.summary.value = prefix + this.helper.summary.value;
|
||||
this.editor.summary.value = prefix + this.editor.summary.value;
|
||||
} else {
|
||||
this.helper.summary.value = prefix + this.helper.summary.value.substring(pos + 1);
|
||||
this.editor.summary.value = prefix + this.editor.summary.value.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -605,7 +605,7 @@ class GeneralTagTab extends TagTabPlane {
|
||||
* @override
|
||||
*/
|
||||
populate() {
|
||||
const found = this.helper.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/);
|
||||
const found = this.editor.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/);
|
||||
if (found === null) {
|
||||
return false;
|
||||
}
|
||||
@ -614,7 +614,7 @@ class GeneralTagTab extends TagTabPlane {
|
||||
if (tagButton.dataset.value === this.tag.value) {
|
||||
tagButton.classList.remove("btn-outline-primary");
|
||||
tagButton.classList.add("btn-primary");
|
||||
this.helper.filterSuggestedAccounts(tagButton);
|
||||
this.editor.filterSuggestedAccounts(tagButton);
|
||||
}
|
||||
}
|
||||
this.switchToMe();
|
||||
@ -671,11 +671,11 @@ class GeneralTripTab extends TagTabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
* @override
|
||||
*/
|
||||
constructor(helper) {
|
||||
super(helper);
|
||||
constructor(editor) {
|
||||
super(editor);
|
||||
this.#from = document.getElementById(this.prefix + "-from");
|
||||
this.#fromError = document.getElementById(this.prefix + "-from-error");
|
||||
this.#to = document.getElementById(this.prefix + "-to");
|
||||
@ -727,7 +727,7 @@ class GeneralTripTab extends TagTabPlane {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.helper.summary.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value;
|
||||
this.editor.summary.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -761,7 +761,7 @@ class GeneralTripTab extends TagTabPlane {
|
||||
* @override
|
||||
*/
|
||||
populate() {
|
||||
const found = this.helper.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/);
|
||||
const found = this.editor.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/);
|
||||
if (found === null) {
|
||||
return false;
|
||||
}
|
||||
@ -781,7 +781,7 @@ class GeneralTripTab extends TagTabPlane {
|
||||
if (tagButton.dataset.value === this.tag.value) {
|
||||
tagButton.classList.remove("btn-outline-primary");
|
||||
tagButton.classList.add("btn-primary");
|
||||
this.helper.filterSuggestedAccounts(tagButton);
|
||||
this.editor.filterSuggestedAccounts(tagButton);
|
||||
}
|
||||
}
|
||||
this.switchToMe();
|
||||
@ -879,11 +879,11 @@ class BusTripTab extends TagTabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
* @override
|
||||
*/
|
||||
constructor(helper) {
|
||||
super(helper);
|
||||
constructor(editor) {
|
||||
super(editor);
|
||||
this.#route = document.getElementById(this.prefix + "-route");
|
||||
this.#routeError = document.getElementById(this.prefix + "-route-error");
|
||||
this.#from = document.getElementById(this.prefix + "-from");
|
||||
@ -921,7 +921,7 @@ class BusTripTab extends TagTabPlane {
|
||||
* @override
|
||||
*/
|
||||
updateSummary() {
|
||||
this.helper.summary.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value;
|
||||
this.editor.summary.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -949,7 +949,7 @@ class BusTripTab extends TagTabPlane {
|
||||
* @override
|
||||
*/
|
||||
populate() {
|
||||
const found = this.helper.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/);
|
||||
const found = this.editor.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/);
|
||||
if (found === null) {
|
||||
return false;
|
||||
}
|
||||
@ -961,7 +961,7 @@ class BusTripTab extends TagTabPlane {
|
||||
if (tagButton.dataset.value === this.tag.value) {
|
||||
tagButton.classList.remove("btn-outline-primary");
|
||||
tagButton.classList.add("btn-primary");
|
||||
this.helper.filterSuggestedAccounts(tagButton);
|
||||
this.editor.filterSuggestedAccounts(tagButton);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1041,11 +1041,11 @@ class RegularPaymentTab extends TabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
* @override
|
||||
*/
|
||||
constructor(helper) {
|
||||
super(helper);
|
||||
constructor(editor) {
|
||||
super(editor);
|
||||
// noinspection JSValidateTypes
|
||||
this.#payments = Array.from(document.getElementsByClassName(this.prefix + "-payment"));
|
||||
}
|
||||
@ -1103,19 +1103,19 @@ class NumberTab extends TabPlane {
|
||||
/**
|
||||
* Constructs a tab plane.
|
||||
*
|
||||
* @param helper {SummaryHelper} the parent summary helper
|
||||
* @param editor {SummaryEditor} the parent summary editor
|
||||
* @override
|
||||
*/
|
||||
constructor(helper) {
|
||||
super(helper);
|
||||
constructor(editor) {
|
||||
super(editor);
|
||||
const tabPlane = this;
|
||||
this.helper.number.onchange = function () {
|
||||
const found = tabPlane.helper.summary.value.match(/^(.+)×(\d+)$/);
|
||||
this.editor.number.onchange = function () {
|
||||
const found = tabPlane.editor.summary.value.match(/^(.+)×(\d+)$/);
|
||||
if (found !== null) {
|
||||
tabPlane.helper.summary.value = found[1];
|
||||
tabPlane.editor.summary.value = found[1];
|
||||
}
|
||||
if (parseInt(tabPlane.helper.number.value) > 1) {
|
||||
tabPlane.helper.summary.value = tabPlane.helper.summary.value + "×" + tabPlane.helper.number.value;
|
||||
if (parseInt(tabPlane.editor.number.value) > 1) {
|
||||
tabPlane.editor.summary.value = tabPlane.editor.summary.value + "×" + tabPlane.editor.number.value;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -1136,7 +1136,7 @@ class NumberTab extends TabPlane {
|
||||
* @override
|
||||
*/
|
||||
reset() {
|
||||
this.helper.number.value = "";
|
||||
this.editor.number.value = "";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1146,11 +1146,11 @@ class NumberTab extends TabPlane {
|
||||
* @override
|
||||
*/
|
||||
populate() {
|
||||
const found = this.helper.summary.value.match(/^.+×(\d+)$/);
|
||||
const found = this.editor.summary.value.match(/^.+×(\d+)$/);
|
||||
if (found === null) {
|
||||
this.helper.number.value = "";
|
||||
this.editor.number.value = "";
|
||||
} else {
|
||||
this.helper.number.value = found[1];
|
||||
this.editor.number.value = found[1];
|
||||
}
|
||||
return true;
|
||||
}
|
@ -171,7 +171,7 @@ function initializeNewEntryButton(button) {
|
||||
formAccount.dataset.code = "";
|
||||
formAccount.dataset.text = "";
|
||||
formAccountError.innerText = "";
|
||||
formSummaryControl.dataset.bsTarget = "#accounting-summary-helper-" + button.dataset.entryType + "-modal";
|
||||
formSummaryControl.dataset.bsTarget = "#accounting-summary-editor-" + button.dataset.entryType + "-modal";
|
||||
formSummaryControl.classList.remove("accounting-not-empty");
|
||||
formSummaryControl.classList.remove("is-invalid");
|
||||
formSummary.dataset.value = "";
|
||||
@ -181,7 +181,7 @@ function initializeNewEntryButton(button) {
|
||||
formAmount.classList.remove("is-invalid");
|
||||
formAmountError.innerText = "";
|
||||
AccountSelector.initializeJournalEntryForm();
|
||||
SummaryHelper.initializeNewJournalEntry(button.dataset.entryType);
|
||||
SummaryEditor.initializeNewJournalEntry(button.dataset.entryType);
|
||||
};
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ function initializeJournalEntry(entry) {
|
||||
formAccount.innerText = accountCode.dataset.text;
|
||||
formAccount.dataset.code = accountCode.value;
|
||||
formAccount.dataset.text = accountCode.dataset.text;
|
||||
formSummaryControl.dataset.bsTarget = "#accounting-summary-helper-" + entry.dataset.entryType + "-modal";
|
||||
formSummaryControl.dataset.bsTarget = "#accounting-summary-editor-" + entry.dataset.entryType + "-modal";
|
||||
if (summary.value === "") {
|
||||
formSummaryControl.classList.remove("accounting-not-empty");
|
||||
} else {
|
||||
|
@ -46,8 +46,8 @@ First written: 2023/2/25
|
||||
{% endblock %}
|
||||
|
||||
{% block form_modals %}
|
||||
{% with summary_helper = form.summary_helper.debit %}
|
||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
||||
{% with summary_editor = form.summary_editor.debit %}
|
||||
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||
{% endwith %}
|
||||
{% with entry_type = "debit",
|
||||
account_options = form.debit_account_options %}
|
||||
|
@ -25,7 +25,7 @@ First written: 2023/2/26
|
||||
<script src="{{ url_for("accounting.static", filename="js/drag-and-drop-reorder.js") }}"></script>
|
||||
<script src="{{ url_for("accounting.static", filename="js/transaction-form.js") }}"></script>
|
||||
<script src="{{ url_for("accounting.static", filename="js/account-selector.js") }}"></script>
|
||||
<script src="{{ url_for("accounting.static", filename="js/summary-helper.js") }}"></script>
|
||||
<script src="{{ url_for("accounting.static", filename="js/summary-editor.js") }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -0,0 +1,181 @@
|
||||
{#
|
||||
The Mia! Accounting Flask Project
|
||||
summary-editor-modal.html: The modal of the summary editor
|
||||
|
||||
Copyright (c) 2023 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: 2023/2/28
|
||||
#}
|
||||
<form id="accounting-summary-editor-{{ summary_editor.type }}" class="accounting-summary-editor" data-entry-type="{{ summary_editor.type }}">
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-modal-label" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="accounting-summary-editor-{{ summary_editor.type }}-modal-label">
|
||||
<label for="accounting-summary-editor-{{ summary_editor.type }}-summary">{{ A_("Summary") }}</label>
|
||||
</h1>
|
||||
<button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal" aria-label="{{ A_("Close") }}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-summary" class="form-control" type="text" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-modal-label">
|
||||
</div>
|
||||
<ul class="nav nav-tabs mb-2">
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-editor-{{ summary_editor.type }}-general-tab" class="nav-link active accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="page" data-tab-id="general">
|
||||
{{ A_("General") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-editor-{{ summary_editor.type }}-travel-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="travel">
|
||||
{{ A_("Travel") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-editor-{{ summary_editor.type }}-bus-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="bus">
|
||||
{{ A_("Bus") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-editor-{{ summary_editor.type }}-regular-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="regular">
|
||||
{{ A_("Regular") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-editor-{{ summary_editor.type }}-number-tab" class="nav-link accounting-clickable accounting-summary-editor-{{ summary_editor.type }}-tab" aria-current="false" data-tab-id="number">
|
||||
{{ A_("Number") }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
{# A general summary with a tag #}
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-general-page" class="accounting-summary-editor-{{ summary_editor.type }}-page" aria-current="page" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-general" data-tab-id="general">
|
||||
<div class="form-floating mb-2">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-general-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-general-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-general-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_editor.general.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-general-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A general trip with the origin and distination #}
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-travel-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-travel" data-tab-id="travel">
|
||||
<div class="form-floating mb-2">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-travel-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-travel-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_editor.travel.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-travel-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-travel-from" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-from">{{ A_("From") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-travel-from-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="btn-group-vertical ms-1 me-1">
|
||||
<button class="btn btn-primary accounting-summary-editor-{{ summary_editor.type }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button>
|
||||
<button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-travel-to" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-travel-to">{{ A_("To") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-travel-to-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A bus trip with the route name or route number, the origin and distination #}
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-bus-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-bus" data-tab-id="bus">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<div class="form-floating me-2">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-bus-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-bus-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-bus-route" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-route">{{ A_("Route") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-bus-route-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_editor.bus.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.type }}-bus-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<div class="form-floating me-2">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-bus-from" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-from">{{ A_("From") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-bus-from-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-bus-to" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-bus-to">{{ A_("To") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-bus-to-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A regular income or payment #}
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-regular-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-regular" data-tab-id="regular">
|
||||
{# TODO: To be done #}
|
||||
</div>
|
||||
|
||||
{# The number of items #}
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-number-page" class="accounting-summary-editor-{{ summary_editor.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.type }}-tab-number" data-tab-id="number">
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-editor-{{ summary_editor.type }}-number-number" class="form-control" type="number" min="1" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.type }}-number">{{ A_("The number of items") }}</label>
|
||||
<div id="accounting-summary-editor-{{ summary_editor.type }}-number-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# The suggested accounts #}
|
||||
<div class="mt-3">
|
||||
{% for account in summary_editor.accounts %}
|
||||
<button class="btn btn-outline-primary d-none accounting-summary-editor-{{ summary_editor.type }}-account" type="button" data-code="{{ account.code }}" data-text="{{ account }}">
|
||||
{{ account }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal">{{ A_("Cancel") }}</button>
|
||||
<button id="accounting-summary-editor-{{ summary_editor.type }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -1,181 +0,0 @@
|
||||
{#
|
||||
The Mia! Accounting Flask Project
|
||||
entry-form-modal.html: The modal of the summary helper
|
||||
|
||||
Copyright (c) 2023 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: 2023/2/28
|
||||
#}
|
||||
<form id="accounting-summary-helper-{{ summary_helper.type }}" class="accounting-summary-helper" data-entry-type="{{ summary_helper.type }}">
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-modal-label" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="accounting-summary-helper-{{ summary_helper.type }}-modal-label">
|
||||
<label for="accounting-summary-helper-{{ summary_helper.type }}-summary">{{ A_("Summary") }}</label>
|
||||
</h1>
|
||||
<button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal" aria-label="{{ A_("Close") }}"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-summary" class="form-control" type="text" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-modal-label">
|
||||
</div>
|
||||
<ul class="nav nav-tabs mb-2">
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-helper-{{ summary_helper.type }}-general-tab" class="nav-link active accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="page" data-tab-id="general">
|
||||
{{ A_("General") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-helper-{{ summary_helper.type }}-travel-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="travel">
|
||||
{{ A_("Travel") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-helper-{{ summary_helper.type }}-bus-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="bus">
|
||||
{{ A_("Bus") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-helper-{{ summary_helper.type }}-regular-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="regular">
|
||||
{{ A_("Regular") }}
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span id="accounting-summary-helper-{{ summary_helper.type }}-number-tab" class="nav-link accounting-clickable accounting-summary-helper-{{ summary_helper.type }}-tab" aria-current="false" data-tab-id="number">
|
||||
{{ A_("Number") }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
{# A general summary with a tag #}
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-general-page" class="accounting-summary-helper-{{ summary_helper.type }}-page" aria-current="page" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-general" data-tab-id="general">
|
||||
<div class="form-floating mb-2">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-general-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-general-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-general-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_helper.general.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-general-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A general trip with the origin and distination #}
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-travel-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-travel" data-tab-id="travel">
|
||||
<div class="form-floating mb-2">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-travel-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-travel-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_helper.travel.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-travel-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-travel-from" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-from">{{ A_("From") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-travel-from-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="btn-group-vertical ms-1 me-1">
|
||||
<button class="btn btn-primary accounting-summary-helper-{{ summary_helper.type }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button>
|
||||
<button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-travel-to" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-travel-to">{{ A_("To") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-travel-to-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A bus trip with the route name or route number, the origin and distination #}
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-bus-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-bus" data-tab-id="bus">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<div class="form-floating me-2">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-bus-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-tag">{{ A_("Tag") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-bus-tag-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-bus-route" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-route">{{ A_("Route") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-bus-route-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{% for tag in summary_helper.bus.tags %}
|
||||
<button class="btn btn-outline-primary accounting-summary-helper-{{ summary_helper.type }}-bus-btn-tag" type="button" tabindex="-1" data-value="{{ tag.name }}" data-accounts="{{ tag.account_codes|tojson|forceescape }}">
|
||||
{{ tag }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between mt-2">
|
||||
<div class="form-floating me-2">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-bus-from" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-from">{{ A_("From") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-bus-from-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-bus-to" class="form-control" type="text" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-bus-to">{{ A_("To") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-bus-to-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# A regular income or payment #}
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-regular-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-regular" data-tab-id="regular">
|
||||
{# TODO: To be done #}
|
||||
</div>
|
||||
|
||||
{# The number of items #}
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-number-page" class="accounting-summary-helper-{{ summary_helper.type }}-page d-none" aria-current="false" aria-labelledby="accounting-summary-helper-{{ summary_helper.type }}-tab-number" data-tab-id="number">
|
||||
<div class="form-floating">
|
||||
<input id="accounting-summary-helper-{{ summary_helper.type }}-number-number" class="form-control" type="number" min="1" value="" placeholder=" ">
|
||||
<label class="form-label" for="accounting-summary-helper-{{ summary_helper.type }}-number">{{ A_("The number of items") }}</label>
|
||||
<div id="accounting-summary-helper-{{ summary_helper.type }}-number-error" class="invalid-feedback"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# The suggested accounts #}
|
||||
<div class="mt-3">
|
||||
{% for account in summary_helper.accounts %}
|
||||
<button class="btn btn-outline-primary d-none accounting-summary-helper-{{ summary_helper.type }}-account" type="button" data-code="{{ account.code }}" data-text="{{ account }}">
|
||||
{{ account }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" type="button" data-bs-toggle="modal" data-bs-target="#accounting-entry-form-modal">{{ A_("Cancel") }}</button>
|
||||
<button id="accounting-summary-helper-{{ summary_helper.type }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -46,8 +46,8 @@ First written: 2023/2/25
|
||||
{% endblock %}
|
||||
|
||||
{% block form_modals %}
|
||||
{% with summary_helper = form.summary_helper.credit %}
|
||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
||||
{% with summary_editor = form.summary_editor.credit %}
|
||||
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||
{% endwith %}
|
||||
{% with entry_type = "credit",
|
||||
account_options = form.credit_account_options %}
|
||||
|
@ -50,11 +50,11 @@ First written: 2023/2/25
|
||||
{% endblock %}
|
||||
|
||||
{% block form_modals %}
|
||||
{% with summary_helper = form.summary_helper.debit %}
|
||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
||||
{% with summary_editor = form.summary_editor.debit %}
|
||||
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||
{% endwith %}
|
||||
{% with summary_helper = form.summary_helper.credit %}
|
||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
||||
{% with summary_editor = form.summary_editor.credit %}
|
||||
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||
{% endwith %}
|
||||
{% with entry_type = "debit",
|
||||
account_options = form.debit_account_options %}
|
||||
|
@ -37,7 +37,7 @@ from accounting import db
|
||||
from accounting.locale import lazy_gettext
|
||||
from accounting.models import Transaction, Account, JournalEntry, \
|
||||
TransactionCurrency, Currency
|
||||
from accounting.transaction.summary_helper import SummaryHelper
|
||||
from accounting.transaction.summary_editor import SummaryEditor
|
||||
from accounting.utils.random_id import new_id
|
||||
from accounting.utils.strip_text import strip_text, strip_multiline_text
|
||||
from accounting.utils.user import get_current_user_pk
|
||||
@ -391,12 +391,12 @@ class TransactionForm(FlaskForm):
|
||||
if isinstance(x, str) or isinstance(x, LazyString)]
|
||||
|
||||
@property
|
||||
def summary_helper(self) -> SummaryHelper:
|
||||
"""Returns the summary helper.
|
||||
def summary_editor(self) -> SummaryEditor:
|
||||
"""Returns the summary editor.
|
||||
|
||||
:return: The summary helper.
|
||||
:return: The summary editor.
|
||||
"""
|
||||
return SummaryHelper()
|
||||
return SummaryEditor()
|
||||
|
||||
|
||||
T = t.TypeVar("T", bound=TransactionForm)
|
||||
|
@ -14,7 +14,7 @@
|
||||
# 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.
|
||||
"""The summary helper.
|
||||
"""The summary editor.
|
||||
|
||||
"""
|
||||
import typing as t
|
||||
@ -178,7 +178,7 @@ class SummaryEntryType:
|
||||
|
||||
@property
|
||||
def accounts(self) -> list[SummaryAccount]:
|
||||
"""Returns the suggested accounts of all tags in the summary helper in
|
||||
"""Returns the suggested accounts of all tags in the summary editor in
|
||||
the entry type, in their frequency order.
|
||||
|
||||
:return: The suggested accounts of all tags, in their frequency order.
|
||||
@ -197,11 +197,11 @@ class SummaryEntryType:
|
||||
key=lambda x: -freq[x])]
|
||||
|
||||
|
||||
class SummaryHelper:
|
||||
"""The summary helper."""
|
||||
class SummaryEditor:
|
||||
"""The summary editor."""
|
||||
|
||||
def __init__(self):
|
||||
"""Constructs the summary helper."""
|
||||
"""Constructs the summary editor."""
|
||||
self.debit: SummaryEntryType = SummaryEntryType("debit")
|
||||
"""The debit tags."""
|
||||
self.credit: SummaryEntryType = SummaryEntryType("credit")
|
@ -14,7 +14,7 @@
|
||||
# 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.
|
||||
"""The test for the summary helper.
|
||||
"""The test for the summary editor.
|
||||
|
||||
"""
|
||||
import unittest
|
||||
@ -29,8 +29,8 @@ from testlib import get_client
|
||||
from testlib_txn import Accounts, NEXT_URI, add_txn
|
||||
|
||||
|
||||
class SummeryHelperTestCase(unittest.TestCase):
|
||||
"""The summary helper test case."""
|
||||
class SummeryEditorTestCase(unittest.TestCase):
|
||||
"""The summary editor test case."""
|
||||
|
||||
def setUp(self) -> None:
|
||||
"""Sets up the test.
|
||||
@ -61,101 +61,101 @@ class SummeryHelperTestCase(unittest.TestCase):
|
||||
|
||||
self.client, self.csrf_token = get_client(self.app, "editor")
|
||||
|
||||
def test_summary_helper(self) -> None:
|
||||
"""Test the summary helper.
|
||||
def test_summary_editor(self) -> None:
|
||||
"""Test the summary editor.
|
||||
|
||||
:return: None.
|
||||
"""
|
||||
from accounting.transaction.summary_helper import SummaryHelper
|
||||
from accounting.transaction.summary_editor import SummaryEditor
|
||||
for form in get_form_data(self.csrf_token):
|
||||
add_txn(self.client, form)
|
||||
with self.app.app_context():
|
||||
helper: SummaryHelper = SummaryHelper()
|
||||
editor: SummaryEditor = SummaryEditor()
|
||||
|
||||
# Debit-General
|
||||
self.assertEqual(len(helper.debit.general.tags), 2)
|
||||
self.assertEqual(helper.debit.general.tags[0].name, "Lunch")
|
||||
self.assertEqual(len(helper.debit.general.tags[0].accounts), 2)
|
||||
self.assertEqual(helper.debit.general.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.debit.general.tags), 2)
|
||||
self.assertEqual(editor.debit.general.tags[0].name, "Lunch")
|
||||
self.assertEqual(len(editor.debit.general.tags[0].accounts), 2)
|
||||
self.assertEqual(editor.debit.general.tags[0].accounts[0].code,
|
||||
Accounts.MEAL)
|
||||
self.assertEqual(helper.debit.general.tags[0].accounts[1].code,
|
||||
self.assertEqual(editor.debit.general.tags[0].accounts[1].code,
|
||||
Accounts.PAYABLE)
|
||||
self.assertEqual(helper.debit.general.tags[1].name, "Dinner")
|
||||
self.assertEqual(len(helper.debit.general.tags[1].accounts), 2)
|
||||
self.assertEqual(helper.debit.general.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.debit.general.tags[1].name, "Dinner")
|
||||
self.assertEqual(len(editor.debit.general.tags[1].accounts), 2)
|
||||
self.assertEqual(editor.debit.general.tags[1].accounts[0].code,
|
||||
Accounts.MEAL)
|
||||
self.assertEqual(helper.debit.general.tags[1].accounts[1].code,
|
||||
self.assertEqual(editor.debit.general.tags[1].accounts[1].code,
|
||||
Accounts.PAYABLE)
|
||||
|
||||
# Debit-Travel
|
||||
self.assertEqual(len(helper.debit.travel.tags), 3)
|
||||
self.assertEqual(helper.debit.travel.tags[0].name, "Bike")
|
||||
self.assertEqual(len(helper.debit.travel.tags[0].accounts), 1)
|
||||
self.assertEqual(helper.debit.travel.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.debit.travel.tags), 3)
|
||||
self.assertEqual(editor.debit.travel.tags[0].name, "Bike")
|
||||
self.assertEqual(len(editor.debit.travel.tags[0].accounts), 1)
|
||||
self.assertEqual(editor.debit.travel.tags[0].accounts[0].code,
|
||||
Accounts.TRAVEL)
|
||||
self.assertEqual(helper.debit.travel.tags[1].name, "Taxi")
|
||||
self.assertEqual(len(helper.debit.travel.tags[1].accounts), 1)
|
||||
self.assertEqual(helper.debit.travel.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.debit.travel.tags[1].name, "Taxi")
|
||||
self.assertEqual(len(editor.debit.travel.tags[1].accounts), 1)
|
||||
self.assertEqual(editor.debit.travel.tags[1].accounts[0].code,
|
||||
Accounts.TRAVEL)
|
||||
self.assertEqual(helper.debit.travel.tags[2].name, "Airplane")
|
||||
self.assertEqual(len(helper.debit.travel.tags[2].accounts), 1)
|
||||
self.assertEqual(helper.debit.travel.tags[2].accounts[0].code,
|
||||
self.assertEqual(editor.debit.travel.tags[2].name, "Airplane")
|
||||
self.assertEqual(len(editor.debit.travel.tags[2].accounts), 1)
|
||||
self.assertEqual(editor.debit.travel.tags[2].accounts[0].code,
|
||||
Accounts.TRAVEL)
|
||||
|
||||
# Debit-Bus
|
||||
self.assertEqual(len(helper.debit.bus.tags), 2)
|
||||
self.assertEqual(helper.debit.bus.tags[0].name, "Train")
|
||||
self.assertEqual(len(helper.debit.bus.tags[0].accounts), 1)
|
||||
self.assertEqual(helper.debit.bus.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.debit.bus.tags), 2)
|
||||
self.assertEqual(editor.debit.bus.tags[0].name, "Train")
|
||||
self.assertEqual(len(editor.debit.bus.tags[0].accounts), 1)
|
||||
self.assertEqual(editor.debit.bus.tags[0].accounts[0].code,
|
||||
Accounts.TRAVEL)
|
||||
self.assertEqual(helper.debit.bus.tags[1].name, "Bus")
|
||||
self.assertEqual(len(helper.debit.bus.tags[1].accounts), 1)
|
||||
self.assertEqual(helper.debit.bus.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.debit.bus.tags[1].name, "Bus")
|
||||
self.assertEqual(len(editor.debit.bus.tags[1].accounts), 1)
|
||||
self.assertEqual(editor.debit.bus.tags[1].accounts[0].code,
|
||||
Accounts.TRAVEL)
|
||||
|
||||
# Credit-General
|
||||
self.assertEqual(len(helper.credit.general.tags), 2)
|
||||
self.assertEqual(helper.credit.general.tags[0].name, "Lunch")
|
||||
self.assertEqual(len(helper.credit.general.tags[0].accounts), 3)
|
||||
self.assertEqual(helper.credit.general.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.credit.general.tags), 2)
|
||||
self.assertEqual(editor.credit.general.tags[0].name, "Lunch")
|
||||
self.assertEqual(len(editor.credit.general.tags[0].accounts), 3)
|
||||
self.assertEqual(editor.credit.general.tags[0].accounts[0].code,
|
||||
Accounts.PAYABLE)
|
||||
self.assertEqual(helper.credit.general.tags[0].accounts[1].code,
|
||||
self.assertEqual(editor.credit.general.tags[0].accounts[1].code,
|
||||
Accounts.BANK)
|
||||
self.assertEqual(helper.credit.general.tags[0].accounts[2].code,
|
||||
self.assertEqual(editor.credit.general.tags[0].accounts[2].code,
|
||||
Accounts.CASH)
|
||||
self.assertEqual(helper.credit.general.tags[1].name, "Dinner")
|
||||
self.assertEqual(len(helper.credit.general.tags[1].accounts), 2)
|
||||
self.assertEqual(helper.credit.general.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.credit.general.tags[1].name, "Dinner")
|
||||
self.assertEqual(len(editor.credit.general.tags[1].accounts), 2)
|
||||
self.assertEqual(editor.credit.general.tags[1].accounts[0].code,
|
||||
Accounts.BANK)
|
||||
self.assertEqual(helper.credit.general.tags[1].accounts[1].code,
|
||||
self.assertEqual(editor.credit.general.tags[1].accounts[1].code,
|
||||
Accounts.PAYABLE)
|
||||
|
||||
# Credit-Travel
|
||||
self.assertEqual(len(helper.credit.travel.tags), 2)
|
||||
self.assertEqual(helper.credit.travel.tags[0].name, "Bike")
|
||||
self.assertEqual(len(helper.credit.travel.tags[0].accounts), 2)
|
||||
self.assertEqual(helper.credit.travel.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.credit.travel.tags), 2)
|
||||
self.assertEqual(editor.credit.travel.tags[0].name, "Bike")
|
||||
self.assertEqual(len(editor.credit.travel.tags[0].accounts), 2)
|
||||
self.assertEqual(editor.credit.travel.tags[0].accounts[0].code,
|
||||
Accounts.PAYABLE)
|
||||
self.assertEqual(helper.credit.travel.tags[0].accounts[1].code,
|
||||
self.assertEqual(editor.credit.travel.tags[0].accounts[1].code,
|
||||
Accounts.PREPAID)
|
||||
self.assertEqual(helper.credit.travel.tags[1].name, "Taxi")
|
||||
self.assertEqual(len(helper.credit.travel.tags[1].accounts), 2)
|
||||
self.assertEqual(helper.credit.travel.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.credit.travel.tags[1].name, "Taxi")
|
||||
self.assertEqual(len(editor.credit.travel.tags[1].accounts), 2)
|
||||
self.assertEqual(editor.credit.travel.tags[1].accounts[0].code,
|
||||
Accounts.PAYABLE)
|
||||
self.assertEqual(helper.credit.travel.tags[1].accounts[1].code,
|
||||
self.assertEqual(editor.credit.travel.tags[1].accounts[1].code,
|
||||
Accounts.CASH)
|
||||
|
||||
# Credit-Bus
|
||||
self.assertEqual(len(helper.credit.bus.tags), 2)
|
||||
self.assertEqual(helper.credit.bus.tags[0].name, "Train")
|
||||
self.assertEqual(len(helper.credit.bus.tags[0].accounts), 2)
|
||||
self.assertEqual(helper.credit.bus.tags[0].accounts[0].code,
|
||||
self.assertEqual(len(editor.credit.bus.tags), 2)
|
||||
self.assertEqual(editor.credit.bus.tags[0].name, "Train")
|
||||
self.assertEqual(len(editor.credit.bus.tags[0].accounts), 2)
|
||||
self.assertEqual(editor.credit.bus.tags[0].accounts[0].code,
|
||||
Accounts.PREPAID)
|
||||
self.assertEqual(helper.credit.bus.tags[0].accounts[1].code,
|
||||
self.assertEqual(editor.credit.bus.tags[0].accounts[1].code,
|
||||
Accounts.PAYABLE)
|
||||
self.assertEqual(helper.credit.bus.tags[1].name, "Bus")
|
||||
self.assertEqual(len(helper.credit.bus.tags[1].accounts), 1)
|
||||
self.assertEqual(helper.credit.bus.tags[1].accounts[0].code,
|
||||
self.assertEqual(editor.credit.bus.tags[1].name, "Bus")
|
||||
self.assertEqual(len(editor.credit.bus.tags[1].accounts), 1)
|
||||
self.assertEqual(editor.credit.bus.tags[1].accounts[0].code,
|
||||
Accounts.PREPAID)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user