Renamed summary helper to summary editor.
This commit is contained in:
parent
11966a52ba
commit
4eb9346d8d
@ -1,5 +1,5 @@
|
|||||||
/* The Mia! Accounting Flask Project
|
/* 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.
|
/* Copyright (c) 2023 imacat.
|
||||||
@ -23,23 +23,23 @@
|
|||||||
|
|
||||||
// Initializes the page JavaScript.
|
// Initializes the page JavaScript.
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
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}
|
* @type {HTMLFormElement}
|
||||||
*/
|
*/
|
||||||
#form;
|
#form;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modal of the summary helper
|
* The modal of the summary editor
|
||||||
* @type {HTMLFormElement}
|
* @type {HTMLFormElement}
|
||||||
*/
|
*/
|
||||||
#modal;
|
#modal;
|
||||||
@ -129,14 +129,14 @@ class SummaryHelper {
|
|||||||
tabPlanes = {};
|
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) {
|
constructor(form) {
|
||||||
this.#form = form;
|
this.#form = form;
|
||||||
this.#entryType = form.dataset.entryType;
|
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.#modal = document.getElementById(this.prefix + "-modal");
|
||||||
this.summary = document.getElementById(this.prefix + "-summary");
|
this.summary = document.getElementById(this.prefix + "-summary");
|
||||||
this.number = document.getElementById(this.prefix + "-number-number");
|
this.number = document.getElementById(this.prefix + "-number-number");
|
||||||
@ -156,13 +156,13 @@ class SummaryHelper {
|
|||||||
}
|
}
|
||||||
this.currentTab = this.tabPlanes.general;
|
this.currentTab = this.tabPlanes.general;
|
||||||
this.#initializeSuggestedAccounts();
|
this.#initializeSuggestedAccounts();
|
||||||
const helper = this;
|
const editor = this;
|
||||||
this.summary.onchange = function () {
|
this.summary.onchange = function () {
|
||||||
helper.#onSummaryChange();
|
editor.#onSummaryChange();
|
||||||
};
|
};
|
||||||
this.#form.onsubmit = function () {
|
this.#form.onsubmit = function () {
|
||||||
if (helper.currentTab.validate()) {
|
if (editor.currentTab.validate()) {
|
||||||
helper.#submit();
|
editor.#submit();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -212,10 +212,10 @@ class SummaryHelper {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#initializeSuggestedAccounts() {
|
#initializeSuggestedAccounts() {
|
||||||
const helper = this;
|
const editor = this;
|
||||||
for (const accountButton of this.#accountButtons) {
|
for (const accountButton of this.#accountButtons) {
|
||||||
accountButton.onclick = function () {
|
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() {
|
#onOpen() {
|
||||||
@ -270,7 +270,7 @@ class SummaryHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the summary helper.
|
* Resets the summary editor.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#reset() {
|
#reset() {
|
||||||
@ -282,36 +282,36 @@ class SummaryHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary helpers.
|
* The summary editors.
|
||||||
* @type {{debit: SummaryHelper, credit: SummaryHelper}}
|
* @type {{debit: SummaryEditor, credit: SummaryEditor}}
|
||||||
*/
|
*/
|
||||||
static #helpers = {}
|
static #editors = {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the summary helpers.
|
* Initializes the summary editors.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static initialize() {
|
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 entryForm = document.getElementById("accounting-entry-form");
|
||||||
const formSummaryControl = document.getElementById("accounting-entry-form-summary-control");
|
const formSummaryControl = document.getElementById("accounting-entry-form-summary-control");
|
||||||
for (const form of forms) {
|
for (const form of forms) {
|
||||||
const helper = new SummaryHelper(form);
|
const editor = new SummaryEditor(form);
|
||||||
this.#helpers[helper.#entryType] = helper;
|
this.#editors[editor.#entryType] = editor;
|
||||||
}
|
}
|
||||||
const helpers = this;
|
const editors = this;
|
||||||
formSummaryControl.onclick = function () {
|
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"
|
* @param entryType {string} the entry type, either "debit" or "credit"
|
||||||
*/
|
*/
|
||||||
static initializeNewJournalEntry(entryType) {
|
static initializeNewJournalEntry(entryType) {
|
||||||
this.#helpers[entryType].#onOpen();
|
this.#editors[entryType].#onOpen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,10 +324,10 @@ class SummaryHelper {
|
|||||||
class TabPlane {
|
class TabPlane {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent summary helper
|
* The parent summary editor
|
||||||
* @type {SummaryHelper}
|
* @type {SummaryEditor}
|
||||||
*/
|
*/
|
||||||
helper;
|
editor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and classes
|
* The prefix of the HTML ID and classes
|
||||||
@ -350,11 +350,11 @@ class TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
this.helper = helper;
|
this.editor = editor;
|
||||||
this.prefix = this.helper.prefix + "-" + this.tabId();
|
this.prefix = this.editor.prefix + "-" + this.tabId();
|
||||||
this.#tab = document.getElementById(this.prefix + "-tab");
|
this.#tab = document.getElementById(this.prefix + "-tab");
|
||||||
this.#page = document.getElementById(this.prefix + "-page");
|
this.#page = document.getElementById(this.prefix + "-page");
|
||||||
const tabPlane = this;
|
const tabPlane = this;
|
||||||
@ -399,7 +399,7 @@ class TabPlane {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
switchToMe() {
|
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.classList.remove("active")
|
||||||
tabPlane.#tab.ariaCurrent = "false";
|
tabPlane.#tab.ariaCurrent = "false";
|
||||||
tabPlane.#page.classList.add("d-none");
|
tabPlane.#page.classList.add("d-none");
|
||||||
@ -409,7 +409,7 @@ class TabPlane {
|
|||||||
this.#tab.ariaCurrent = "page";
|
this.#tab.ariaCurrent = "page";
|
||||||
this.#page.classList.remove("d-none");
|
this.#page.classList.remove("d-none");
|
||||||
this.#page.ariaCurrent = "page";
|
this.#page.ariaCurrent = "page";
|
||||||
this.helper.currentTab = this;
|
this.editor.currentTab = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,11 +442,11 @@ class TagTabPlane extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
super(helper);
|
super(editor);
|
||||||
this.tag = document.getElementById(this.prefix + "-tag");
|
this.tag = document.getElementById(this.prefix + "-tag");
|
||||||
this.tagError = document.getElementById(this.prefix + "-tag-error");
|
this.tagError = document.getElementById(this.prefix + "-tag-error");
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
@ -459,7 +459,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
if (tagButton.dataset.value === tabPlane.tag.value) {
|
if (tagButton.dataset.value === tabPlane.tag.value) {
|
||||||
tagButton.classList.remove("btn-outline-primary");
|
tagButton.classList.remove("btn-outline-primary");
|
||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
tabPlane.helper.filterSuggestedAccounts(tagButton);
|
tabPlane.editor.filterSuggestedAccounts(tagButton);
|
||||||
isMatched = true;
|
isMatched = true;
|
||||||
} else {
|
} else {
|
||||||
tagButton.classList.remove("btn-primary");
|
tagButton.classList.remove("btn-primary");
|
||||||
@ -467,7 +467,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isMatched) {
|
if (!isMatched) {
|
||||||
tabPlane.helper.filterSuggestedAccounts(null);
|
tabPlane.editor.filterSuggestedAccounts(null);
|
||||||
}
|
}
|
||||||
tabPlane.updateSummary();
|
tabPlane.updateSummary();
|
||||||
tabPlane.validateTag();
|
tabPlane.validateTag();
|
||||||
@ -494,7 +494,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
break;
|
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.remove("btn-outline-primary");
|
||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
tabPlane.tag.value = tagButton.dataset.value;
|
tabPlane.tag.value = tagButton.dataset.value;
|
||||||
tabPlane.helper.filterSuggestedAccounts(tagButton);
|
tabPlane.editor.filterSuggestedAccounts(tagButton);
|
||||||
tabPlane.updateSummary();
|
tabPlane.updateSummary();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -589,12 +589,12 @@ class GeneralTagTab extends TagTabPlane {
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
updateSummary() {
|
||||||
const pos = this.helper.summary.value.indexOf("—");
|
const pos = this.editor.summary.value.indexOf("—");
|
||||||
const prefix = this.tag.value === ""? "": this.tag.value + "—";
|
const prefix = this.tag.value === ""? "": this.tag.value + "—";
|
||||||
if (pos === -1) {
|
if (pos === -1) {
|
||||||
this.helper.summary.value = prefix + this.helper.summary.value;
|
this.editor.summary.value = prefix + this.editor.summary.value;
|
||||||
} else {
|
} 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
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.helper.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/);
|
const found = this.editor.summary.value.match(/^([^—]+)—.+?(?:×\d+)?$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -614,7 +614,7 @@ class GeneralTagTab extends TagTabPlane {
|
|||||||
if (tagButton.dataset.value === this.tag.value) {
|
if (tagButton.dataset.value === this.tag.value) {
|
||||||
tagButton.classList.remove("btn-outline-primary");
|
tagButton.classList.remove("btn-outline-primary");
|
||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
this.helper.filterSuggestedAccounts(tagButton);
|
this.editor.filterSuggestedAccounts(tagButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.switchToMe();
|
this.switchToMe();
|
||||||
@ -671,11 +671,11 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
super(helper);
|
super(editor);
|
||||||
this.#from = document.getElementById(this.prefix + "-from");
|
this.#from = document.getElementById(this.prefix + "-from");
|
||||||
this.#fromError = document.getElementById(this.prefix + "-from-error");
|
this.#fromError = document.getElementById(this.prefix + "-from-error");
|
||||||
this.#to = document.getElementById(this.prefix + "-to");
|
this.#to = document.getElementById(this.prefix + "-to");
|
||||||
@ -727,7 +727,7 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
break;
|
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
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.helper.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/);
|
const found = this.editor.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:×\d+)?$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -781,7 +781,7 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
if (tagButton.dataset.value === this.tag.value) {
|
if (tagButton.dataset.value === this.tag.value) {
|
||||||
tagButton.classList.remove("btn-outline-primary");
|
tagButton.classList.remove("btn-outline-primary");
|
||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
this.helper.filterSuggestedAccounts(tagButton);
|
this.editor.filterSuggestedAccounts(tagButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.switchToMe();
|
this.switchToMe();
|
||||||
@ -879,11 +879,11 @@ class BusTripTab extends TagTabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
super(helper);
|
super(editor);
|
||||||
this.#route = document.getElementById(this.prefix + "-route");
|
this.#route = document.getElementById(this.prefix + "-route");
|
||||||
this.#routeError = document.getElementById(this.prefix + "-route-error");
|
this.#routeError = document.getElementById(this.prefix + "-route-error");
|
||||||
this.#from = document.getElementById(this.prefix + "-from");
|
this.#from = document.getElementById(this.prefix + "-from");
|
||||||
@ -921,7 +921,7 @@ class BusTripTab extends TagTabPlane {
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
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
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.helper.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/);
|
const found = this.editor.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:×\d+)?$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -961,7 +961,7 @@ class BusTripTab extends TagTabPlane {
|
|||||||
if (tagButton.dataset.value === this.tag.value) {
|
if (tagButton.dataset.value === this.tag.value) {
|
||||||
tagButton.classList.remove("btn-outline-primary");
|
tagButton.classList.remove("btn-outline-primary");
|
||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
this.helper.filterSuggestedAccounts(tagButton);
|
this.editor.filterSuggestedAccounts(tagButton);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1041,11 +1041,11 @@ class RegularPaymentTab extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
super(helper);
|
super(editor);
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
this.#payments = Array.from(document.getElementsByClassName(this.prefix + "-payment"));
|
this.#payments = Array.from(document.getElementsByClassName(this.prefix + "-payment"));
|
||||||
}
|
}
|
||||||
@ -1103,19 +1103,19 @@ class NumberTab extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param helper {SummaryHelper} the parent summary helper
|
* @param editor {SummaryEditor} the parent summary editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(helper) {
|
constructor(editor) {
|
||||||
super(helper);
|
super(editor);
|
||||||
const tabPlane = this;
|
const tabPlane = this;
|
||||||
this.helper.number.onchange = function () {
|
this.editor.number.onchange = function () {
|
||||||
const found = tabPlane.helper.summary.value.match(/^(.+)×(\d+)$/);
|
const found = tabPlane.editor.summary.value.match(/^(.+)×(\d+)$/);
|
||||||
if (found !== null) {
|
if (found !== null) {
|
||||||
tabPlane.helper.summary.value = found[1];
|
tabPlane.editor.summary.value = found[1];
|
||||||
}
|
}
|
||||||
if (parseInt(tabPlane.helper.number.value) > 1) {
|
if (parseInt(tabPlane.editor.number.value) > 1) {
|
||||||
tabPlane.helper.summary.value = tabPlane.helper.summary.value + "×" + tabPlane.helper.number.value;
|
tabPlane.editor.summary.value = tabPlane.editor.summary.value + "×" + tabPlane.editor.number.value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -1136,7 +1136,7 @@ class NumberTab extends TabPlane {
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
reset() {
|
reset() {
|
||||||
this.helper.number.value = "";
|
this.editor.number.value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1146,11 +1146,11 @@ class NumberTab extends TabPlane {
|
|||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.helper.summary.value.match(/^.+×(\d+)$/);
|
const found = this.editor.summary.value.match(/^.+×(\d+)$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
this.helper.number.value = "";
|
this.editor.number.value = "";
|
||||||
} else {
|
} else {
|
||||||
this.helper.number.value = found[1];
|
this.editor.number.value = found[1];
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -171,7 +171,7 @@ function initializeNewEntryButton(button) {
|
|||||||
formAccount.dataset.code = "";
|
formAccount.dataset.code = "";
|
||||||
formAccount.dataset.text = "";
|
formAccount.dataset.text = "";
|
||||||
formAccountError.innerText = "";
|
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("accounting-not-empty");
|
||||||
formSummaryControl.classList.remove("is-invalid");
|
formSummaryControl.classList.remove("is-invalid");
|
||||||
formSummary.dataset.value = "";
|
formSummary.dataset.value = "";
|
||||||
@ -181,7 +181,7 @@ function initializeNewEntryButton(button) {
|
|||||||
formAmount.classList.remove("is-invalid");
|
formAmount.classList.remove("is-invalid");
|
||||||
formAmountError.innerText = "";
|
formAmountError.innerText = "";
|
||||||
AccountSelector.initializeJournalEntryForm();
|
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.innerText = accountCode.dataset.text;
|
||||||
formAccount.dataset.code = accountCode.value;
|
formAccount.dataset.code = accountCode.value;
|
||||||
formAccount.dataset.text = accountCode.dataset.text;
|
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 === "") {
|
if (summary.value === "") {
|
||||||
formSummaryControl.classList.remove("accounting-not-empty");
|
formSummaryControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
|
@ -46,8 +46,8 @@ First written: 2023/2/25
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_helper = form.summary_helper.debit %}
|
{% with summary_editor = form.summary_editor.debit %}
|
||||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with entry_type = "debit",
|
{% with entry_type = "debit",
|
||||||
account_options = form.debit_account_options %}
|
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/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/transaction-form.js") }}"></script>
|
||||||
<script src="{{ url_for("accounting.static", filename="js/account-selector.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 %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% 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 %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_helper = form.summary_helper.credit %}
|
{% with summary_editor = form.summary_editor.credit %}
|
||||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with entry_type = "credit",
|
{% with entry_type = "credit",
|
||||||
account_options = form.credit_account_options %}
|
account_options = form.credit_account_options %}
|
||||||
|
@ -50,11 +50,11 @@ First written: 2023/2/25
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_helper = form.summary_helper.debit %}
|
{% with summary_editor = form.summary_editor.debit %}
|
||||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with summary_helper = form.summary_helper.credit %}
|
{% with summary_editor = form.summary_editor.credit %}
|
||||||
{% include "accounting/transaction/include/summary-helper-modal.html" %}
|
{% include "accounting/transaction/include/summary-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with entry_type = "debit",
|
{% with entry_type = "debit",
|
||||||
account_options = form.debit_account_options %}
|
account_options = form.debit_account_options %}
|
||||||
|
@ -37,7 +37,7 @@ from accounting import db
|
|||||||
from accounting.locale import lazy_gettext
|
from accounting.locale import lazy_gettext
|
||||||
from accounting.models import Transaction, Account, JournalEntry, \
|
from accounting.models import Transaction, Account, JournalEntry, \
|
||||||
TransactionCurrency, Currency
|
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.random_id import new_id
|
||||||
from accounting.utils.strip_text import strip_text, strip_multiline_text
|
from accounting.utils.strip_text import strip_text, strip_multiline_text
|
||||||
from accounting.utils.user import get_current_user_pk
|
from accounting.utils.user import get_current_user_pk
|
||||||
@ -391,12 +391,12 @@ class TransactionForm(FlaskForm):
|
|||||||
if isinstance(x, str) or isinstance(x, LazyString)]
|
if isinstance(x, str) or isinstance(x, LazyString)]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def summary_helper(self) -> SummaryHelper:
|
def summary_editor(self) -> SummaryEditor:
|
||||||
"""Returns the summary helper.
|
"""Returns the summary editor.
|
||||||
|
|
||||||
:return: The summary helper.
|
:return: The summary editor.
|
||||||
"""
|
"""
|
||||||
return SummaryHelper()
|
return SummaryEditor()
|
||||||
|
|
||||||
|
|
||||||
T = t.TypeVar("T", bound=TransactionForm)
|
T = t.TypeVar("T", bound=TransactionForm)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""The summary helper.
|
"""The summary editor.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import typing as t
|
import typing as t
|
||||||
@ -178,7 +178,7 @@ class SummaryEntryType:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def accounts(self) -> list[SummaryAccount]:
|
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.
|
the entry type, in their frequency order.
|
||||||
|
|
||||||
:return: The suggested accounts of all tags, 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])]
|
key=lambda x: -freq[x])]
|
||||||
|
|
||||||
|
|
||||||
class SummaryHelper:
|
class SummaryEditor:
|
||||||
"""The summary helper."""
|
"""The summary editor."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Constructs the summary helper."""
|
"""Constructs the summary editor."""
|
||||||
self.debit: SummaryEntryType = SummaryEntryType("debit")
|
self.debit: SummaryEntryType = SummaryEntryType("debit")
|
||||||
"""The debit tags."""
|
"""The debit tags."""
|
||||||
self.credit: SummaryEntryType = SummaryEntryType("credit")
|
self.credit: SummaryEntryType = SummaryEntryType("credit")
|
@ -14,7 +14,7 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
"""The test for the summary helper.
|
"""The test for the summary editor.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import unittest
|
import unittest
|
||||||
@ -29,8 +29,8 @@ from testlib import get_client
|
|||||||
from testlib_txn import Accounts, NEXT_URI, add_txn
|
from testlib_txn import Accounts, NEXT_URI, add_txn
|
||||||
|
|
||||||
|
|
||||||
class SummeryHelperTestCase(unittest.TestCase):
|
class SummeryEditorTestCase(unittest.TestCase):
|
||||||
"""The summary helper test case."""
|
"""The summary editor test case."""
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
"""Sets up the test.
|
"""Sets up the test.
|
||||||
@ -61,101 +61,101 @@ class SummeryHelperTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
self.client, self.csrf_token = get_client(self.app, "editor")
|
self.client, self.csrf_token = get_client(self.app, "editor")
|
||||||
|
|
||||||
def test_summary_helper(self) -> None:
|
def test_summary_editor(self) -> None:
|
||||||
"""Test the summary helper.
|
"""Test the summary editor.
|
||||||
|
|
||||||
:return: None.
|
: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):
|
for form in get_form_data(self.csrf_token):
|
||||||
add_txn(self.client, form)
|
add_txn(self.client, form)
|
||||||
with self.app.app_context():
|
with self.app.app_context():
|
||||||
helper: SummaryHelper = SummaryHelper()
|
editor: SummaryEditor = SummaryEditor()
|
||||||
|
|
||||||
# Debit-General
|
# Debit-General
|
||||||
self.assertEqual(len(helper.debit.general.tags), 2)
|
self.assertEqual(len(editor.debit.general.tags), 2)
|
||||||
self.assertEqual(helper.debit.general.tags[0].name, "Lunch")
|
self.assertEqual(editor.debit.general.tags[0].name, "Lunch")
|
||||||
self.assertEqual(len(helper.debit.general.tags[0].accounts), 2)
|
self.assertEqual(len(editor.debit.general.tags[0].accounts), 2)
|
||||||
self.assertEqual(helper.debit.general.tags[0].accounts[0].code,
|
self.assertEqual(editor.debit.general.tags[0].accounts[0].code,
|
||||||
Accounts.MEAL)
|
Accounts.MEAL)
|
||||||
self.assertEqual(helper.debit.general.tags[0].accounts[1].code,
|
self.assertEqual(editor.debit.general.tags[0].accounts[1].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
self.assertEqual(helper.debit.general.tags[1].name, "Dinner")
|
self.assertEqual(editor.debit.general.tags[1].name, "Dinner")
|
||||||
self.assertEqual(len(helper.debit.general.tags[1].accounts), 2)
|
self.assertEqual(len(editor.debit.general.tags[1].accounts), 2)
|
||||||
self.assertEqual(helper.debit.general.tags[1].accounts[0].code,
|
self.assertEqual(editor.debit.general.tags[1].accounts[0].code,
|
||||||
Accounts.MEAL)
|
Accounts.MEAL)
|
||||||
self.assertEqual(helper.debit.general.tags[1].accounts[1].code,
|
self.assertEqual(editor.debit.general.tags[1].accounts[1].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
|
|
||||||
# Debit-Travel
|
# Debit-Travel
|
||||||
self.assertEqual(len(helper.debit.travel.tags), 3)
|
self.assertEqual(len(editor.debit.travel.tags), 3)
|
||||||
self.assertEqual(helper.debit.travel.tags[0].name, "Bike")
|
self.assertEqual(editor.debit.travel.tags[0].name, "Bike")
|
||||||
self.assertEqual(len(helper.debit.travel.tags[0].accounts), 1)
|
self.assertEqual(len(editor.debit.travel.tags[0].accounts), 1)
|
||||||
self.assertEqual(helper.debit.travel.tags[0].accounts[0].code,
|
self.assertEqual(editor.debit.travel.tags[0].accounts[0].code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertEqual(helper.debit.travel.tags[1].name, "Taxi")
|
self.assertEqual(editor.debit.travel.tags[1].name, "Taxi")
|
||||||
self.assertEqual(len(helper.debit.travel.tags[1].accounts), 1)
|
self.assertEqual(len(editor.debit.travel.tags[1].accounts), 1)
|
||||||
self.assertEqual(helper.debit.travel.tags[1].accounts[0].code,
|
self.assertEqual(editor.debit.travel.tags[1].accounts[0].code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertEqual(helper.debit.travel.tags[2].name, "Airplane")
|
self.assertEqual(editor.debit.travel.tags[2].name, "Airplane")
|
||||||
self.assertEqual(len(helper.debit.travel.tags[2].accounts), 1)
|
self.assertEqual(len(editor.debit.travel.tags[2].accounts), 1)
|
||||||
self.assertEqual(helper.debit.travel.tags[2].accounts[0].code,
|
self.assertEqual(editor.debit.travel.tags[2].accounts[0].code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
|
|
||||||
# Debit-Bus
|
# Debit-Bus
|
||||||
self.assertEqual(len(helper.debit.bus.tags), 2)
|
self.assertEqual(len(editor.debit.bus.tags), 2)
|
||||||
self.assertEqual(helper.debit.bus.tags[0].name, "Train")
|
self.assertEqual(editor.debit.bus.tags[0].name, "Train")
|
||||||
self.assertEqual(len(helper.debit.bus.tags[0].accounts), 1)
|
self.assertEqual(len(editor.debit.bus.tags[0].accounts), 1)
|
||||||
self.assertEqual(helper.debit.bus.tags[0].accounts[0].code,
|
self.assertEqual(editor.debit.bus.tags[0].accounts[0].code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertEqual(helper.debit.bus.tags[1].name, "Bus")
|
self.assertEqual(editor.debit.bus.tags[1].name, "Bus")
|
||||||
self.assertEqual(len(helper.debit.bus.tags[1].accounts), 1)
|
self.assertEqual(len(editor.debit.bus.tags[1].accounts), 1)
|
||||||
self.assertEqual(helper.debit.bus.tags[1].accounts[0].code,
|
self.assertEqual(editor.debit.bus.tags[1].accounts[0].code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
|
|
||||||
# Credit-General
|
# Credit-General
|
||||||
self.assertEqual(len(helper.credit.general.tags), 2)
|
self.assertEqual(len(editor.credit.general.tags), 2)
|
||||||
self.assertEqual(helper.credit.general.tags[0].name, "Lunch")
|
self.assertEqual(editor.credit.general.tags[0].name, "Lunch")
|
||||||
self.assertEqual(len(helper.credit.general.tags[0].accounts), 3)
|
self.assertEqual(len(editor.credit.general.tags[0].accounts), 3)
|
||||||
self.assertEqual(helper.credit.general.tags[0].accounts[0].code,
|
self.assertEqual(editor.credit.general.tags[0].accounts[0].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
self.assertEqual(helper.credit.general.tags[0].accounts[1].code,
|
self.assertEqual(editor.credit.general.tags[0].accounts[1].code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(helper.credit.general.tags[0].accounts[2].code,
|
self.assertEqual(editor.credit.general.tags[0].accounts[2].code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertEqual(helper.credit.general.tags[1].name, "Dinner")
|
self.assertEqual(editor.credit.general.tags[1].name, "Dinner")
|
||||||
self.assertEqual(len(helper.credit.general.tags[1].accounts), 2)
|
self.assertEqual(len(editor.credit.general.tags[1].accounts), 2)
|
||||||
self.assertEqual(helper.credit.general.tags[1].accounts[0].code,
|
self.assertEqual(editor.credit.general.tags[1].accounts[0].code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(helper.credit.general.tags[1].accounts[1].code,
|
self.assertEqual(editor.credit.general.tags[1].accounts[1].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
|
|
||||||
# Credit-Travel
|
# Credit-Travel
|
||||||
self.assertEqual(len(helper.credit.travel.tags), 2)
|
self.assertEqual(len(editor.credit.travel.tags), 2)
|
||||||
self.assertEqual(helper.credit.travel.tags[0].name, "Bike")
|
self.assertEqual(editor.credit.travel.tags[0].name, "Bike")
|
||||||
self.assertEqual(len(helper.credit.travel.tags[0].accounts), 2)
|
self.assertEqual(len(editor.credit.travel.tags[0].accounts), 2)
|
||||||
self.assertEqual(helper.credit.travel.tags[0].accounts[0].code,
|
self.assertEqual(editor.credit.travel.tags[0].accounts[0].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
self.assertEqual(helper.credit.travel.tags[0].accounts[1].code,
|
self.assertEqual(editor.credit.travel.tags[0].accounts[1].code,
|
||||||
Accounts.PREPAID)
|
Accounts.PREPAID)
|
||||||
self.assertEqual(helper.credit.travel.tags[1].name, "Taxi")
|
self.assertEqual(editor.credit.travel.tags[1].name, "Taxi")
|
||||||
self.assertEqual(len(helper.credit.travel.tags[1].accounts), 2)
|
self.assertEqual(len(editor.credit.travel.tags[1].accounts), 2)
|
||||||
self.assertEqual(helper.credit.travel.tags[1].accounts[0].code,
|
self.assertEqual(editor.credit.travel.tags[1].accounts[0].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
self.assertEqual(helper.credit.travel.tags[1].accounts[1].code,
|
self.assertEqual(editor.credit.travel.tags[1].accounts[1].code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
|
|
||||||
# Credit-Bus
|
# Credit-Bus
|
||||||
self.assertEqual(len(helper.credit.bus.tags), 2)
|
self.assertEqual(len(editor.credit.bus.tags), 2)
|
||||||
self.assertEqual(helper.credit.bus.tags[0].name, "Train")
|
self.assertEqual(editor.credit.bus.tags[0].name, "Train")
|
||||||
self.assertEqual(len(helper.credit.bus.tags[0].accounts), 2)
|
self.assertEqual(len(editor.credit.bus.tags[0].accounts), 2)
|
||||||
self.assertEqual(helper.credit.bus.tags[0].accounts[0].code,
|
self.assertEqual(editor.credit.bus.tags[0].accounts[0].code,
|
||||||
Accounts.PREPAID)
|
Accounts.PREPAID)
|
||||||
self.assertEqual(helper.credit.bus.tags[0].accounts[1].code,
|
self.assertEqual(editor.credit.bus.tags[0].accounts[1].code,
|
||||||
Accounts.PAYABLE)
|
Accounts.PAYABLE)
|
||||||
self.assertEqual(helper.credit.bus.tags[1].name, "Bus")
|
self.assertEqual(editor.credit.bus.tags[1].name, "Bus")
|
||||||
self.assertEqual(len(helper.credit.bus.tags[1].accounts), 1)
|
self.assertEqual(len(editor.credit.bus.tags[1].accounts), 1)
|
||||||
self.assertEqual(helper.credit.bus.tags[1].accounts[0].code,
|
self.assertEqual(editor.credit.bus.tags[1].accounts[0].code,
|
||||||
Accounts.PREPAID)
|
Accounts.PREPAID)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user