Added the recurring transactions.

This commit is contained in:
2023-03-21 19:15:43 +08:00
parent 5dccf99a55
commit 3455827c09
4 changed files with 187 additions and 52 deletions

View File

@ -32,7 +32,7 @@ class DescriptionEditor {
* The line item editor
* @type {JournalEntryLineItemEditor}
*/
#lineItemEditor;
lineItemEditor;
/**
* The description editor form
@ -113,7 +113,7 @@ class DescriptionEditor {
* @param debitCredit {string} either "debit" or "credit"
*/
constructor(lineItemEditor, debitCredit) {
this.#lineItemEditor = lineItemEditor;
this.lineItemEditor = lineItemEditor;
this.debitCredit = debitCredit;
this.prefix = "accounting-description-editor-" + debitCredit;
this.#form = document.getElementById(this.prefix);
@ -132,7 +132,7 @@ class DescriptionEditor {
this.currentTab = this.tabPlanes.general;
this.#initializeSuggestedAccounts();
this.description.onchange = () => this.#onDescriptionChange();
this.#offsetButton.onclick = () => this.#lineItemEditor.originalLineItemSelector.onOpen();
this.#offsetButton.onclick = () => this.lineItemEditor.originalLineItemSelector.onOpen();
this.#form.onsubmit = () => {
if (this.currentTab.validate()) {
this.#submit();
@ -147,7 +147,7 @@ class DescriptionEditor {
*/
#onDescriptionChange() {
this.description.value = this.description.value.trim();
for (const tabPlane of [this.tabPlanes.bus, this.tabPlanes.travel, this.tabPlanes.general]) {
for (const tabPlane of [this.tabPlanes.recurring, this.tabPlanes.bus, this.tabPlanes.travel, this.tabPlanes.general]) {
if (tabPlane.populate()) {
break;
}
@ -158,27 +158,31 @@ class DescriptionEditor {
/**
* Filters the suggested accounts.
*
* @param tagButton {HTMLButtonElement|null} the tag button
* @param tagButton {HTMLButtonElement} the tag button
*/
filterSuggestedAccounts(tagButton) {
for (const accountButton of this.#accountButtons) {
accountButton.classList.add("d-none");
}
if (tagButton === null) {
this.#selectAccount(null);
return;
}
this.clearSuggestedAccounts();
const suggested = JSON.parse(tagButton.dataset.accounts);
let selectedAccountButton = null;
for (const accountButton of this.#accountButtons) {
if (suggested.includes(accountButton.dataset.code)) {
accountButton.classList.remove("d-none");
if (accountButton.dataset.code === suggested[0]) {
selectedAccountButton = accountButton;
this.#selectAccount(accountButton);
return;
}
}
}
this.#selectAccount(selectedAccountButton);
}
/**
* Clears the suggested accounts.
*
*/
clearSuggestedAccounts() {
for (const accountButton of this.#accountButtons) {
accountButton.classList.add("d-none");
}
this.#selectAccount(null);
}
/**
@ -215,9 +219,9 @@ class DescriptionEditor {
#submit() {
bootstrap.Modal.getOrCreateInstance(this.#modal).hide();
if (this.#selectedAccount !== null) {
this.#lineItemEditor.saveDescriptionWithAccount(this.description.value, this.#selectedAccount.dataset.code, this.#selectedAccount.dataset.text, this.#selectedAccount.classList.contains("accounting-account-is-need-offset"));
this.lineItemEditor.saveDescriptionWithAccount(this.description.value, this.#selectedAccount.dataset.code, this.#selectedAccount.dataset.text, this.#selectedAccount.classList.contains("accounting-account-is-need-offset"));
} else {
this.#lineItemEditor.saveDescription(this.description.value);
this.lineItemEditor.saveDescription(this.description.value);
}
}
@ -227,7 +231,7 @@ class DescriptionEditor {
*/
onOpen() {
this.#reset();
this.description.value = this.#lineItemEditor.description === null? "": this.#lineItemEditor.description;
this.description.value = this.lineItemEditor.description === null? "": this.lineItemEditor.description;
this.#onDescriptionChange();
}
@ -418,7 +422,7 @@ class TagTabPlane extends TabPlane {
}
}
if (!isMatched) {
this.editor.filterSuggestedAccounts(null);
this.editor.clearSuggestedAccounts();
}
this.validateTag();
}
@ -436,14 +440,13 @@ class TagTabPlane extends TabPlane {
*/
switchToMe() {
super.switchToMe();
let selectedTagButton = null;
for (const tagButton of this.tagButtons) {
if (tagButton.classList.contains("btn-primary")) {
selectedTagButton = tagButton;
break;
this.editor.filterSuggestedAccounts(tagButton);
return;
}
}
this.editor.filterSuggestedAccounts(selectedTagButton);
this.editor.clearSuggestedAccounts();
}
/**
@ -561,13 +564,6 @@ class GeneralTagTab extends TagTabPlane {
this.tag.value = found[1];
this.onTagChange();
}
for (const tagButton of this.tagButtons) {
if (tagButton.dataset.value === this.tag.value) {
tagButton.classList.remove("btn-outline-primary");
tagButton.classList.add("btn-primary");
this.editor.filterSuggestedAccounts(tagButton);
}
}
this.switchToMe();
return true;
}
@ -732,13 +728,6 @@ class GeneralTripTab extends TagTabPlane {
}
}
this.#to.value = found[4];
for (const tagButton of this.tagButtons) {
if (tagButton.dataset.value === this.tag.value) {
tagButton.classList.remove("btn-outline-primary");
tagButton.classList.add("btn-primary");
this.editor.filterSuggestedAccounts(tagButton);
}
}
this.switchToMe();
return true;
}
@ -917,14 +906,6 @@ class BusTripTab extends TagTabPlane {
this.#route.value = found[2];
this.#from.value = found[3];
this.#to.value = found[4];
for (const tagButton of this.tagButtons) {
if (tagButton.dataset.value === this.tag.value) {
tagButton.classList.remove("btn-outline-primary");
tagButton.classList.add("btn-primary");
this.editor.filterSuggestedAccounts(tagButton);
break;
}
}
this.switchToMe();
return true;
}
@ -992,10 +973,16 @@ class BusTripTab extends TagTabPlane {
class RecurringTransactionTab extends TabPlane {
/**
* The transaction buttons
* The month names
* @type {string[]}
*/
#monthNames;
/**
* The buttons of the recurring items
* @type {HTMLButtonElement[]}
*/
#transactions;
#itemButtons;
// noinspection JSValidateTypes
/**
@ -1006,8 +993,44 @@ class RecurringTransactionTab extends TabPlane {
*/
constructor(editor) {
super(editor);
this.#monthNames = [
"",
A_("January"), A_("February"), A_("March"), A_("April"),
A_("May"), A_("June"), A_("July"), A_("August"),
A_("September"), A_("October"), A_("November"), A_("December"),
];
// noinspection JSValidateTypes
this.#transactions = Array.from(document.getElementsByClassName(this.prefix + "-transaction"));
this.#itemButtons = Array.from(document.getElementsByClassName(this.prefix + "-item"));
for (const itemButton of this.#itemButtons) {
itemButton.onclick = () => {
this.reset();
itemButton.classList.add("btn-primary");
itemButton.classList.remove("btn-outline-primary");
this.editor.description.value = this.#getDescription(itemButton);
this.editor.filterSuggestedAccounts(itemButton);
};
}
}
/**
* Returns the description for a recurring item.
*
* @param itemButton {HTMLButtonElement} the recurring item
* @return {string} the description of the recurring item
*/
#getDescription(itemButton) {
const today = new Date(this.editor.lineItemEditor.form.getDate());
const thisMonth = today.getMonth() + 1;
const lastMonth = (thisMonth + 10) % 12 + 1;
const lastBimonthlyFrom = ((thisMonth + thisMonth % 2 + 8) % 12 + 1);
const lastBimonthlyTo = ((thisMonth + thisMonth % 2 + 9) % 12 + 1);
return itemButton.dataset.template
.replaceAll("{this_month_number}", String(thisMonth))
.replaceAll("{this_month_name}", this.#monthNames[thisMonth])
.replaceAll("{last_month_number}", String(lastMonth))
.replaceAll("{last_month_name}", this.#monthNames[lastMonth])
.replaceAll("{last_bimonthly_number}", String(lastBimonthlyFrom) + "" + String(lastBimonthlyTo))
.replaceAll("{last_bimonthly_name}", this.#monthNames[lastBimonthlyFrom] + "" + this.#monthNames[lastBimonthlyTo]);
}
/**
@ -1026,9 +1049,9 @@ class RecurringTransactionTab extends TabPlane {
* @override
*/
reset() {
for (const transaction of this.#transactions) {
transaction.classList.remove("btn-primary");
transaction.classList.add("btn-outline-primary");
for (const itemButton of this.#itemButtons) {
itemButton.classList.remove("btn-primary");
itemButton.classList.add("btn-outline-primary");
}
}
@ -1039,9 +1062,32 @@ class RecurringTransactionTab extends TabPlane {
* @override
*/
populate() {
for (const itemButton of this.#itemButtons) {
if (this.#getDescription(itemButton) === this.editor.description.value) {
itemButton.classList.add("btn-primary");
itemButton.classList.remove("btn-outline-primary");
this.switchToMe();
return true;
}
}
return false;
}
/**
* Switches to the tab plane.
*
*/
switchToMe() {
super.switchToMe();
for (const itemButton of this.#itemButtons) {
if (itemButton.classList.contains("btn-primary")) {
this.editor.filterSuggestedAccounts(itemButton);
return;
}
}
this.editor.clearSuggestedAccounts();
}
/**
* Validates the input in the tab plane.
*