Compare commits
9 Commits
52807c5322
...
7d084e570e
Author | SHA1 | Date | |
---|---|---|---|
7d084e570e | |||
cb397910f8 | |||
5f8b0dec98 | |||
8398d1e8bb | |||
562801692a | |||
faee1e61c6 | |||
57a4177037 | |||
fa1dedf207 | |||
7ed13dc0af |
@ -40,12 +40,6 @@ class AccountSelector {
|
|||||||
*/
|
*/
|
||||||
#debitCredit;
|
#debitCredit;
|
||||||
|
|
||||||
/**
|
|
||||||
* The prefix of the HTML ID and class
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
#prefix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button to clear the account
|
* The button to clear the account
|
||||||
* @type {HTMLButtonElement}
|
* @type {HTMLButtonElement}
|
||||||
@ -91,14 +85,14 @@ class AccountSelector {
|
|||||||
constructor(lineItemEditor, debitCredit) {
|
constructor(lineItemEditor, debitCredit) {
|
||||||
this.#lineItemEditor = lineItemEditor
|
this.#lineItemEditor = lineItemEditor
|
||||||
this.#debitCredit = debitCredit;
|
this.#debitCredit = debitCredit;
|
||||||
this.#prefix = "accounting-account-selector-" + debitCredit;
|
const prefix = "accounting-account-selector-" + debitCredit;
|
||||||
this.#query = document.getElementById(this.#prefix + "-query");
|
this.#query = document.getElementById(prefix + "-query");
|
||||||
this.#queryNoResult = document.getElementById(this.#prefix + "-option-no-result");
|
this.#queryNoResult = document.getElementById(prefix + "-option-no-result");
|
||||||
this.#optionList = document.getElementById(this.#prefix + "-option-list");
|
this.#optionList = document.getElementById(prefix + "-option-list");
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
this.#options = Array.from(document.getElementsByClassName(this.#prefix + "-option"));
|
this.#options = Array.from(document.getElementsByClassName(prefix + "-option"));
|
||||||
this.#more = document.getElementById(this.#prefix + "-more");
|
this.#more = document.getElementById(prefix + "-more");
|
||||||
this.#clearButton = document.getElementById(this.#prefix + "-btn-clear");
|
this.#clearButton = document.getElementById(prefix + "-btn-clear");
|
||||||
this.#more.onclick = () => {
|
this.#more.onclick = () => {
|
||||||
this.#more.classList.add("d-none");
|
this.#more.classList.add("d-none");
|
||||||
this.#filterOptions();
|
this.#filterOptions();
|
||||||
|
@ -41,7 +41,7 @@ class DescriptionEditor {
|
|||||||
#form;
|
#form;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
prefix;
|
prefix;
|
||||||
@ -278,7 +278,7 @@ class TabPlane {
|
|||||||
editor;
|
editor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and classes
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
prefix;
|
prefix;
|
||||||
@ -1019,7 +1019,7 @@ class RecurringTransactionTab extends TabPlane {
|
|||||||
* @return {string} the description of the recurring item
|
* @return {string} the description of the recurring item
|
||||||
*/
|
*/
|
||||||
#getDescription(itemButton) {
|
#getDescription(itemButton) {
|
||||||
const today = new Date(this.editor.lineItemEditor.form.getDate());
|
const today = new Date(this.editor.lineItemEditor.form.date);
|
||||||
const thisMonth = today.getMonth() + 1;
|
const thisMonth = today.getMonth() + 1;
|
||||||
const lastMonth = (thisMonth + 10) % 12 + 1;
|
const lastMonth = (thisMonth + 10) % 12 + 1;
|
||||||
const lastBimonthlyFrom = ((thisMonth + thisMonth % 2 + 8) % 12 + 1);
|
const lastBimonthlyFrom = ((thisMonth + thisMonth % 2 + 8) % 12 + 1);
|
||||||
|
@ -111,6 +111,7 @@ class JournalEntryForm {
|
|||||||
constructor() {
|
constructor() {
|
||||||
this.#element = document.getElementById("accounting-form");
|
this.#element = document.getElementById("accounting-form");
|
||||||
this.lineItemTemplate = this.#element.dataset.lineItemTemplate;
|
this.lineItemTemplate = this.#element.dataset.lineItemTemplate;
|
||||||
|
this.lineItemEditor = new JournalEntryLineItemEditor(this);
|
||||||
this.#date = document.getElementById("accounting-date");
|
this.#date = document.getElementById("accounting-date");
|
||||||
this.#dateError = document.getElementById("accounting-date-error");
|
this.#dateError = document.getElementById("accounting-date-error");
|
||||||
this.#currencyControl = document.getElementById("accounting-currencies");
|
this.#currencyControl = document.getElementById("accounting-currencies");
|
||||||
@ -121,7 +122,6 @@ class JournalEntryForm {
|
|||||||
this.#addCurrencyButton = document.getElementById("accounting-add-currency");
|
this.#addCurrencyButton = document.getElementById("accounting-add-currency");
|
||||||
this.#note = document.getElementById("accounting-note");
|
this.#note = document.getElementById("accounting-note");
|
||||||
this.#noteError = document.getElementById("accounting-note-error");
|
this.#noteError = document.getElementById("accounting-note-error");
|
||||||
this.lineItemEditor = new JournalEntryLineItemEditor(this);
|
|
||||||
|
|
||||||
this.#addCurrencyButton.onclick = () => {
|
this.#addCurrencyButton.onclick = () => {
|
||||||
const newIndex = 1 + (this.#currencies.length === 0? 0: Math.max(...this.#currencies.map((currency) => currency.index)));
|
const newIndex = 1 + (this.#currencies.length === 0? 0: Math.max(...this.#currencies.map((currency) => currency.index)));
|
||||||
@ -159,7 +159,7 @@ class JournalEntryForm {
|
|||||||
*/
|
*/
|
||||||
#resetDeleteCurrencyButtons() {
|
#resetDeleteCurrencyButtons() {
|
||||||
if (this.#currencies.length === 1) {
|
if (this.#currencies.length === 1) {
|
||||||
this.#currencies[0].deleteButton.classList.add("d-none");
|
this.#currencies[0].setDeleteButtonShown(false);
|
||||||
} else {
|
} else {
|
||||||
for (const currency of this.#currencies) {
|
for (const currency of this.#currencies) {
|
||||||
let isAnyLineItemMatched = false;
|
let isAnyLineItemMatched = false;
|
||||||
@ -169,11 +169,7 @@ class JournalEntryForm {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isAnyLineItemMatched) {
|
currency.setDeleteButtonShown(!isAnyLineItemMatched);
|
||||||
currency.deleteButton.classList.add("d-none");
|
|
||||||
} else {
|
|
||||||
currency.deleteButton.classList.remove("d-none");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -184,10 +180,8 @@ class JournalEntryForm {
|
|||||||
*/
|
*/
|
||||||
#initializeDragAndDropReordering() {
|
#initializeDragAndDropReordering() {
|
||||||
initializeDragAndDropReordering(this.#currencyList, () => {
|
initializeDragAndDropReordering(this.#currencyList, () => {
|
||||||
const currencyId = Array.from(this.#currencyList.children).map((currency) => currency.id);
|
for (const currency of this.#currencies) {
|
||||||
this.#currencies.sort((a, b) => currencyId.indexOf(a.element.id) - currencyId.indexOf(b.element.id));
|
currency.resetNo();
|
||||||
for (let i = 0; i < this.#currencies.length; i++) {
|
|
||||||
this.#currencies[i].no.value = String(i + 1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -213,7 +207,7 @@ class JournalEntryForm {
|
|||||||
* @return {string[]} the account codes used in the form
|
* @return {string[]} the account codes used in the form
|
||||||
*/
|
*/
|
||||||
getAccountCodesUsed(debitCredit) {
|
getAccountCodesUsed(debitCredit) {
|
||||||
return this.getLineItems(debitCredit).map((lineItem) => lineItem.getAccountCode())
|
return this.getLineItems(debitCredit).map((lineItem) => lineItem.accountCode)
|
||||||
.filter((code) => code !== null);
|
.filter((code) => code !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +216,7 @@ class JournalEntryForm {
|
|||||||
*
|
*
|
||||||
* @return {string} the date
|
* @return {string} the date
|
||||||
*/
|
*/
|
||||||
getDate() {
|
get date() {
|
||||||
return this.#date.value;
|
return this.#date.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +227,7 @@ class JournalEntryForm {
|
|||||||
updateMinDate() {
|
updateMinDate() {
|
||||||
let lastOriginalLineItemDate = null;
|
let lastOriginalLineItemDate = null;
|
||||||
for (const lineItem of this.getLineItems()) {
|
for (const lineItem of this.getLineItems()) {
|
||||||
const date = lineItem.getOriginalLineItemDate();
|
const date = lineItem.originalLineItemDate;
|
||||||
if (date !== null) {
|
if (date !== null) {
|
||||||
if (lastOriginalLineItemDate === null || lastOriginalLineItemDate < date) {
|
if (lastOriginalLineItemDate === null || lastOriginalLineItemDate < date) {
|
||||||
lastOriginalLineItemDate = date;
|
lastOriginalLineItemDate = date;
|
||||||
@ -349,7 +343,7 @@ class CurrencySubForm {
|
|||||||
* The element
|
* The element
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
element;
|
#element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The journal entry form
|
* The journal entry form
|
||||||
@ -363,12 +357,6 @@ class CurrencySubForm {
|
|||||||
*/
|
*/
|
||||||
index;
|
index;
|
||||||
|
|
||||||
/**
|
|
||||||
* The prefix of the HTML ID and class
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
#prefix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control
|
* The control
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
@ -385,7 +373,7 @@ class CurrencySubForm {
|
|||||||
* The number
|
* The number
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
no;
|
#no;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currency code
|
* The currency code
|
||||||
@ -403,7 +391,7 @@ class CurrencySubForm {
|
|||||||
* The button to delete the currency
|
* The button to delete the currency
|
||||||
* @type {HTMLButtonElement}
|
* @type {HTMLButtonElement}
|
||||||
*/
|
*/
|
||||||
deleteButton;
|
#deleteButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The debit sub-form
|
* The debit sub-form
|
||||||
@ -424,36 +412,58 @@ class CurrencySubForm {
|
|||||||
* @param element {HTMLDivElement} the currency sub-form element
|
* @param element {HTMLDivElement} the currency sub-form element
|
||||||
*/
|
*/
|
||||||
constructor(form, element) {
|
constructor(form, element) {
|
||||||
this.element = element;
|
this.#element = element;
|
||||||
this.form = form;
|
this.form = form;
|
||||||
this.index = parseInt(this.element.dataset.index);
|
this.index = parseInt(this.#element.dataset.index);
|
||||||
this.#prefix = "accounting-currency-" + String(this.index);
|
const prefix = "accounting-currency-" + String(this.index);
|
||||||
this.#control = document.getElementById(this.#prefix + "-control");
|
this.#control = document.getElementById(prefix + "-control");
|
||||||
this.#error = document.getElementById(this.#prefix + "-error");
|
this.#error = document.getElementById(prefix + "-error");
|
||||||
this.no = document.getElementById(this.#prefix + "-no");
|
this.#no = document.getElementById(prefix + "-no");
|
||||||
this.#code = document.getElementById(this.#prefix + "-code");
|
this.#code = document.getElementById(prefix + "-code");
|
||||||
this.#codeSelect = document.getElementById(this.#prefix + "-code-select");
|
this.#codeSelect = document.getElementById(prefix + "-code-select");
|
||||||
this.deleteButton = document.getElementById(this.#prefix + "-delete");
|
this.#deleteButton = document.getElementById(prefix + "-delete");
|
||||||
const debitElement = document.getElementById(this.#prefix + "-debit");
|
const debitElement = document.getElementById(prefix + "-debit");
|
||||||
this.#debit = debitElement === null? null: new DebitCreditSubForm(this, debitElement, "debit");
|
this.#debit = debitElement === null? null: new DebitCreditSubForm(this, debitElement, "debit");
|
||||||
const creditElement = document.getElementById(this.#prefix + "-credit");
|
const creditElement = document.getElementById(prefix + "-credit");
|
||||||
this.#credit = creditElement == null? null: new DebitCreditSubForm(this, creditElement, "credit");
|
this.#credit = creditElement == null? null: new DebitCreditSubForm(this, creditElement, "credit");
|
||||||
this.#codeSelect.onchange = () => this.#code.value = this.#codeSelect.value;
|
this.#codeSelect.onchange = () => this.#code.value = this.#codeSelect.value;
|
||||||
this.deleteButton.onclick = () => {
|
this.#deleteButton.onclick = () => {
|
||||||
this.element.parentElement.removeChild(this.element);
|
this.#element.parentElement.removeChild(this.#element);
|
||||||
this.form.deleteCurrency(this);
|
this.form.deleteCurrency(this);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the order number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
resetNo() {
|
||||||
|
const siblings = Array.from(this.#element.parentElement.children);
|
||||||
|
this.#no.value = String(siblings.indexOf(this.#element) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the currency code.
|
* Returns the currency code.
|
||||||
*
|
*
|
||||||
* @return {string} the currency code
|
* @return {string} the currency code
|
||||||
*/
|
*/
|
||||||
getCurrencyCode() {
|
get currencyCode() {
|
||||||
return this.#code.value;
|
return this.#code.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the delete button is shown.
|
||||||
|
*
|
||||||
|
* @param isShown {boolean} true to show, or false otherwise
|
||||||
|
*/
|
||||||
|
setDeleteButtonShown(isShown) {
|
||||||
|
if (isShown) {
|
||||||
|
this.#deleteButton.classList.remove("d-none");
|
||||||
|
} else {
|
||||||
|
this.#deleteButton.classList.add("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the line items in the form.
|
* Returns all the line items in the form.
|
||||||
*
|
*
|
||||||
@ -479,7 +489,7 @@ class CurrencySubForm {
|
|||||||
updateCodeSelectorStatus() {
|
updateCodeSelectorStatus() {
|
||||||
let isEnabled = true;
|
let isEnabled = true;
|
||||||
for (const lineItem of this.getLineItems()) {
|
for (const lineItem of this.getLineItems()) {
|
||||||
if (lineItem.getOriginalLineItemId() !== null) {
|
if (lineItem.originalLineItemId !== null) {
|
||||||
isEnabled = false;
|
isEnabled = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -511,7 +521,7 @@ class CurrencySubForm {
|
|||||||
*/
|
*/
|
||||||
validateBalance() {
|
validateBalance() {
|
||||||
if (this.#debit !== null && this.#credit !== null) {
|
if (this.#debit !== null && this.#credit !== null) {
|
||||||
if (!this.#debit.getTotal().equals(this.#credit.getTotal())) {
|
if (!this.#debit.total.equals(this.#credit.total)) {
|
||||||
this.#control.classList.add("is-invalid");
|
this.#control.classList.add("is-invalid");
|
||||||
this.#error.innerText = A_("The totals of the debit and credit amounts do not match.");
|
this.#error.innerText = A_("The totals of the debit and credit amounts do not match.");
|
||||||
return false;
|
return false;
|
||||||
@ -541,6 +551,12 @@ class DebitCreditSubForm {
|
|||||||
*/
|
*/
|
||||||
#element;
|
#element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The content
|
||||||
|
* @type {HTMLDivElement}
|
||||||
|
*/
|
||||||
|
#content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currencyIndex
|
* The currencyIndex
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@ -554,7 +570,7 @@ class DebitCreditSubForm {
|
|||||||
debitCredit;
|
debitCredit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
#prefix;
|
#prefix;
|
||||||
@ -602,12 +618,15 @@ class DebitCreditSubForm {
|
|||||||
this.#currencyIndex = currency.index;
|
this.#currencyIndex = currency.index;
|
||||||
this.debitCredit = debitCredit;
|
this.debitCredit = debitCredit;
|
||||||
this.#prefix = "accounting-currency-" + String(this.#currencyIndex) + "-" + debitCredit;
|
this.#prefix = "accounting-currency-" + String(this.#currencyIndex) + "-" + debitCredit;
|
||||||
|
this.#content = document.getElementById(this.#prefix + "-content");
|
||||||
this.#error = document.getElementById(this.#prefix + "-error");
|
this.#error = document.getElementById(this.#prefix + "-error");
|
||||||
this.#lineItemList = document.getElementById(this.#prefix + "-list");
|
this.#lineItemList = document.getElementById(this.#prefix + "-list");
|
||||||
// noinspection JSValidateTypes
|
// noinspection JSValidateTypes
|
||||||
this.lineItems = Array.from(document.getElementsByClassName(this.#prefix)).map((element) => new LineItemSubForm(this, element));
|
this.lineItems = Array.from(document.getElementsByClassName(this.#prefix)).map((element) => new LineItemSubForm(this, element));
|
||||||
this.#total = document.getElementById(this.#prefix + "-total");
|
this.#total = document.getElementById(this.#prefix + "-total");
|
||||||
this.#addLineItemButton = document.getElementById(this.#prefix + "-add-line-item");
|
this.#addLineItemButton = document.getElementById(this.#prefix + "-add-line-item");
|
||||||
|
|
||||||
|
this.#resetContent();
|
||||||
this.#addLineItemButton.onclick = () => this.currency.form.lineItemEditor.onAddNew(this);
|
this.#addLineItemButton.onclick = () => this.currency.form.lineItemEditor.onAddNew(this);
|
||||||
this.#resetDeleteLineItemButtons();
|
this.#resetDeleteLineItemButtons();
|
||||||
this.#initializeDragAndDropReordering();
|
this.#initializeDragAndDropReordering();
|
||||||
@ -619,7 +638,7 @@ class DebitCreditSubForm {
|
|||||||
* @returns {LineItemSubForm} the newly-added line item sub-form
|
* @returns {LineItemSubForm} the newly-added line item sub-form
|
||||||
*/
|
*/
|
||||||
addLineItem() {
|
addLineItem() {
|
||||||
const newIndex = 1 + (this.lineItems.length === 0? 0: Math.max(...this.lineItems.map((lineItem) => lineItem.lineItemIndex)));
|
const newIndex = 1 + (this.lineItems.length === 0? 0: Math.max(...this.lineItems.map((lineItem) => lineItem.index)));
|
||||||
const html = this.currency.form.lineItemTemplate
|
const html = this.currency.form.lineItemTemplate
|
||||||
.replaceAll("CURRENCY_INDEX", escapeHtml(String(this.#currencyIndex)))
|
.replaceAll("CURRENCY_INDEX", escapeHtml(String(this.#currencyIndex)))
|
||||||
.replaceAll("DEBIT_CREDIT", escapeHtml(this.debitCredit))
|
.replaceAll("DEBIT_CREDIT", escapeHtml(this.debitCredit))
|
||||||
@ -627,6 +646,7 @@ class DebitCreditSubForm {
|
|||||||
this.#lineItemList.insertAdjacentHTML("beforeend", html);
|
this.#lineItemList.insertAdjacentHTML("beforeend", html);
|
||||||
const lineItem = new LineItemSubForm(this, document.getElementById(this.#prefix + "-" + String(newIndex)));
|
const lineItem = new LineItemSubForm(this, document.getElementById(this.#prefix + "-" + String(newIndex)));
|
||||||
this.lineItems.push(lineItem);
|
this.lineItems.push(lineItem);
|
||||||
|
this.#resetContent();
|
||||||
this.#resetDeleteLineItemButtons();
|
this.#resetDeleteLineItemButtons();
|
||||||
this.#initializeDragAndDropReordering();
|
this.#initializeDragAndDropReordering();
|
||||||
this.validate();
|
this.validate();
|
||||||
@ -644,6 +664,7 @@ class DebitCreditSubForm {
|
|||||||
this.updateTotal();
|
this.updateTotal();
|
||||||
this.currency.updateCodeSelectorStatus();
|
this.currency.updateCodeSelectorStatus();
|
||||||
this.currency.form.updateMinDate();
|
this.currency.form.updateMinDate();
|
||||||
|
this.#resetContent();
|
||||||
this.#resetDeleteLineItemButtons();
|
this.#resetDeleteLineItemButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,27 +674,45 @@ class DebitCreditSubForm {
|
|||||||
*/
|
*/
|
||||||
#resetDeleteLineItemButtons() {
|
#resetDeleteLineItemButtons() {
|
||||||
if (this.lineItems.length === 1) {
|
if (this.lineItems.length === 1) {
|
||||||
this.lineItems[0].deleteButton.classList.add("d-none");
|
this.lineItems[0].setDeleteButtonShown(false);
|
||||||
} else {
|
} else {
|
||||||
for (const lineItem of this.lineItems) {
|
for (const lineItem of this.lineItems) {
|
||||||
if (lineItem.isMatched) {
|
lineItem.setDeleteButtonShown(!lineItem.isMatched);
|
||||||
lineItem.deleteButton.classList.add("d-none");
|
|
||||||
} else {
|
|
||||||
lineItem.deleteButton.classList.remove("d-none");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the layout of the content.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#resetContent() {
|
||||||
|
if (this.lineItems.length === 0) {
|
||||||
|
this.#element.classList.remove("accounting-not-empty");
|
||||||
|
this.#element.classList.add("accounting-clickable");
|
||||||
|
this.#element.dataset.bsToggle = "modal"
|
||||||
|
this.#element.dataset.bsTarget = "#" + this.currency.form.lineItemEditor.modal.id;
|
||||||
|
this.#element.onclick = () => this.currency.form.lineItemEditor.onAddNew(this);
|
||||||
|
this.#content.classList.add("d-none");
|
||||||
|
} else {
|
||||||
|
this.#element.classList.add("accounting-not-empty");
|
||||||
|
this.#element.classList.remove("accounting-clickable");
|
||||||
|
delete this.#element.dataset.bsToggle;
|
||||||
|
delete this.#element.dataset.bsTarget;
|
||||||
|
this.#element.onclick = null;
|
||||||
|
this.#content.classList.remove("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total amount.
|
* Returns the total amount.
|
||||||
*
|
*
|
||||||
* @return {Decimal} the total amount
|
* @return {Decimal} the total amount
|
||||||
*/
|
*/
|
||||||
getTotal() {
|
get total() {
|
||||||
let total = new Decimal("0");
|
let total = new Decimal("0");
|
||||||
for (const lineItem of this.lineItems) {
|
for (const lineItem of this.lineItems) {
|
||||||
const amount = lineItem.getAmount();
|
const amount = lineItem.amount;
|
||||||
if (amount !== null) {
|
if (amount !== null) {
|
||||||
total = total.plus(amount);
|
total = total.plus(amount);
|
||||||
}
|
}
|
||||||
@ -686,7 +725,7 @@ class DebitCreditSubForm {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
updateTotal() {
|
updateTotal() {
|
||||||
this.#total.innerText = formatDecimal(this.getTotal());
|
this.#total.innerText = formatDecimal(this.total);
|
||||||
this.currency.validateBalance();
|
this.currency.validateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -696,10 +735,8 @@ class DebitCreditSubForm {
|
|||||||
*/
|
*/
|
||||||
#initializeDragAndDropReordering() {
|
#initializeDragAndDropReordering() {
|
||||||
initializeDragAndDropReordering(this.#lineItemList, () => {
|
initializeDragAndDropReordering(this.#lineItemList, () => {
|
||||||
const lineItemId = Array.from(this.#lineItemList.children).map((lineItem) => lineItem.id);
|
for (const lineItem of this.lineItems) {
|
||||||
this.lineItems.sort((a, b) => lineItemId.indexOf(a.element.id) - lineItemId.indexOf(b.element.id));
|
lineItem.resetNo();
|
||||||
for (let i = 0; i < this.lineItems.length; i++) {
|
|
||||||
this.lineItems[i].no.value = String(i + 1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -751,7 +788,7 @@ class LineItemSubForm {
|
|||||||
* The element
|
* The element
|
||||||
* @type {HTMLLIElement}
|
* @type {HTMLLIElement}
|
||||||
*/
|
*/
|
||||||
element;
|
#element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either "debit" or "credit"
|
* Either "debit" or "credit"
|
||||||
@ -763,7 +800,7 @@ class LineItemSubForm {
|
|||||||
* The line item index
|
* The line item index
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
lineItemIndex;
|
index;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this is an original line item with offsets
|
* Whether this is an original line item with offsets
|
||||||
@ -771,12 +808,6 @@ class LineItemSubForm {
|
|||||||
*/
|
*/
|
||||||
isMatched;
|
isMatched;
|
||||||
|
|
||||||
/**
|
|
||||||
* The prefix of the HTML ID and class
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
#prefix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control
|
* The control
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
@ -793,7 +824,7 @@ class LineItemSubForm {
|
|||||||
* The number
|
* The number
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
no;
|
#no;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The account code
|
* The account code
|
||||||
@ -853,7 +884,7 @@ class LineItemSubForm {
|
|||||||
* The button to delete line item
|
* The button to delete line item
|
||||||
* @type {HTMLButtonElement}
|
* @type {HTMLButtonElement}
|
||||||
*/
|
*/
|
||||||
deleteButton;
|
#deleteButton;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the line item sub-form.
|
* Constructs the line item sub-form.
|
||||||
@ -863,38 +894,47 @@ class LineItemSubForm {
|
|||||||
*/
|
*/
|
||||||
constructor(debitCredit, element) {
|
constructor(debitCredit, element) {
|
||||||
this.debitCreditSubForm = debitCredit;
|
this.debitCreditSubForm = debitCredit;
|
||||||
this.element = element;
|
this.#element = element;
|
||||||
this.debitCredit = element.dataset.debitCredit;
|
this.debitCredit = element.dataset.debitCredit;
|
||||||
this.lineItemIndex = parseInt(element.dataset.lineItemIndex);
|
this.index = parseInt(element.dataset.lineItemIndex);
|
||||||
this.isMatched = element.classList.contains("accounting-matched-line-item");
|
this.isMatched = element.classList.contains("accounting-matched-line-item");
|
||||||
this.#prefix = "accounting-currency-" + element.dataset.currencyIndex + "-" + this.debitCredit + "-" + this.lineItemIndex;
|
const prefix = "accounting-currency-" + element.dataset.currencyIndex + "-" + this.debitCredit + "-" + String(this.index);
|
||||||
this.#control = document.getElementById(this.#prefix + "-control");
|
this.#control = document.getElementById(prefix + "-control");
|
||||||
this.#error = document.getElementById(this.#prefix + "-error");
|
this.#error = document.getElementById(prefix + "-error");
|
||||||
this.no = document.getElementById(this.#prefix + "-no");
|
this.#no = document.getElementById(prefix + "-no");
|
||||||
this.#accountCode = document.getElementById(this.#prefix + "-account-code");
|
this.#accountCode = document.getElementById(prefix + "-account-code");
|
||||||
this.#accountText = document.getElementById(this.#prefix + "-account-text");
|
this.#accountText = document.getElementById(prefix + "-account-text");
|
||||||
this.#description = document.getElementById(this.#prefix + "-description");
|
this.#description = document.getElementById(prefix + "-description");
|
||||||
this.#descriptionText = document.getElementById(this.#prefix + "-description-text");
|
this.#descriptionText = document.getElementById(prefix + "-description-text");
|
||||||
this.#originalLineItemId = document.getElementById(this.#prefix + "-original-line-item-id");
|
this.#originalLineItemId = document.getElementById(prefix + "-original-line-item-id");
|
||||||
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item-text");
|
this.#originalLineItemText = document.getElementById(prefix + "-original-line-item-text");
|
||||||
this.#offsets = document.getElementById(this.#prefix + "-offsets");
|
this.#offsets = document.getElementById(prefix + "-offsets");
|
||||||
this.#amount = document.getElementById(this.#prefix + "-amount");
|
this.#amount = document.getElementById(prefix + "-amount");
|
||||||
this.#amountText = document.getElementById(this.#prefix + "-amount-text");
|
this.#amountText = document.getElementById(prefix + "-amount-text");
|
||||||
this.deleteButton = document.getElementById(this.#prefix + "-delete");
|
this.#deleteButton = document.getElementById(prefix + "-delete");
|
||||||
this.#control.onclick = () => this.debitCreditSubForm.currency.form.lineItemEditor.onEdit(this);
|
this.#control.onclick = () => this.debitCreditSubForm.currency.form.lineItemEditor.onEdit(this);
|
||||||
this.deleteButton.onclick = () => {
|
this.#deleteButton.onclick = () => {
|
||||||
this.element.parentElement.removeChild(this.element);
|
this.#element.parentElement.removeChild(this.#element);
|
||||||
this.debitCreditSubForm.deleteLineItem(this);
|
this.debitCreditSubForm.deleteLineItem(this);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the order number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
resetNo() {
|
||||||
|
const siblings = Array.from(this.#element.parentElement.children);
|
||||||
|
this.#no.value = String(siblings.indexOf(this.#element) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the line item needs offset.
|
* Returns whether the line item needs offset.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the line item needs offset, or false otherwise
|
* @return {boolean} true if the line item needs offset, or false otherwise
|
||||||
*/
|
*/
|
||||||
isNeedOffset() {
|
get isNeedOffset() {
|
||||||
return "isNeedOffset" in this.element.dataset;
|
return "isNeedOffset" in this.#element.dataset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -902,7 +942,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the ID of the original line item
|
* @return {string|null} the ID of the original line item
|
||||||
*/
|
*/
|
||||||
getOriginalLineItemId() {
|
get originalLineItemId() {
|
||||||
return this.#originalLineItemId.value === ""? null: this.#originalLineItemId.value;
|
return this.#originalLineItemId.value === ""? null: this.#originalLineItemId.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +951,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the date of the original line item
|
* @return {string|null} the date of the original line item
|
||||||
*/
|
*/
|
||||||
getOriginalLineItemDate() {
|
get originalLineItemDate() {
|
||||||
return this.#originalLineItemId.dataset.date === ""? null: this.#originalLineItemId.dataset.date;
|
return this.#originalLineItemId.dataset.date === ""? null: this.#originalLineItemId.dataset.date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -920,7 +960,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the text of the original line item
|
* @return {string|null} the text of the original line item
|
||||||
*/
|
*/
|
||||||
getOriginalLineItemText() {
|
get originalLineItemText() {
|
||||||
return this.#originalLineItemId.dataset.text === ""? null: this.#originalLineItemId.dataset.text;
|
return this.#originalLineItemId.dataset.text === ""? null: this.#originalLineItemId.dataset.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -929,7 +969,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the description
|
* @return {string|null} the description
|
||||||
*/
|
*/
|
||||||
getDescription() {
|
get description() {
|
||||||
return this.#description.value === ""? null: this.#description.value;
|
return this.#description.value === ""? null: this.#description.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -938,7 +978,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the account code
|
* @return {string|null} the account code
|
||||||
*/
|
*/
|
||||||
getAccountCode() {
|
get accountCode() {
|
||||||
return this.#accountCode.value === ""? null: this.#accountCode.value;
|
return this.#accountCode.value === ""? null: this.#accountCode.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,7 +987,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the account text
|
* @return {string|null} the account text
|
||||||
*/
|
*/
|
||||||
getAccountText() {
|
get accountText() {
|
||||||
return this.#accountCode.dataset.text === ""? null: this.#accountCode.dataset.text;
|
return this.#accountCode.dataset.text === ""? null: this.#accountCode.dataset.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -956,7 +996,7 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {Decimal|null} the amount
|
* @return {Decimal|null} the amount
|
||||||
*/
|
*/
|
||||||
getAmount() {
|
get amount() {
|
||||||
return this.#amount.value === ""? null: new Decimal(this.#amount.value);
|
return this.#amount.value === ""? null: new Decimal(this.#amount.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -965,10 +1005,23 @@ class LineItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {Decimal|null} the minimal amount
|
* @return {Decimal|null} the minimal amount
|
||||||
*/
|
*/
|
||||||
getAmountMin() {
|
get amountMin() {
|
||||||
return this.#amount.dataset.min === ""? null: new Decimal(this.#amount.dataset.min);
|
return this.#amount.dataset.min === ""? null: new Decimal(this.#amount.dataset.min);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the delete button is shown.
|
||||||
|
*
|
||||||
|
* @param isShown {boolean} true to show, or false otherwise
|
||||||
|
*/
|
||||||
|
setDeleteButtonShown(isShown) {
|
||||||
|
if (isShown) {
|
||||||
|
this.#deleteButton.classList.remove("d-none");
|
||||||
|
} else {
|
||||||
|
this.#deleteButton.classList.add("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the form.
|
* Validates the form.
|
||||||
*
|
*
|
||||||
|
@ -44,7 +44,7 @@ class JournalEntryLineItemEditor {
|
|||||||
* The bootstrap modal
|
* The bootstrap modal
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#modal;
|
modal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either "debit" or "credit"
|
* Either "debit" or "credit"
|
||||||
@ -53,7 +53,7 @@ class JournalEntryLineItemEditor {
|
|||||||
debitCredit;
|
debitCredit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
#prefix = "accounting-line-item-editor"
|
#prefix = "accounting-line-item-editor"
|
||||||
@ -190,12 +190,6 @@ class JournalEntryLineItemEditor {
|
|||||||
*/
|
*/
|
||||||
description = null;
|
description = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* The amount
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
amount = "";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The description editors
|
* The description editors
|
||||||
* @type {{debit: DescriptionEditor, credit: DescriptionEditor}}
|
* @type {{debit: DescriptionEditor, credit: DescriptionEditor}}
|
||||||
@ -222,7 +216,7 @@ class JournalEntryLineItemEditor {
|
|||||||
constructor(form) {
|
constructor(form) {
|
||||||
this.form = form;
|
this.form = form;
|
||||||
this.#element = document.getElementById(this.#prefix);
|
this.#element = document.getElementById(this.#prefix);
|
||||||
this.#modal = document.getElementById(this.#prefix + "-modal");
|
this.modal = document.getElementById(this.#prefix + "-modal");
|
||||||
this.#originalLineItemContainer = document.getElementById(this.#prefix + "-original-line-item-container");
|
this.#originalLineItemContainer = document.getElementById(this.#prefix + "-original-line-item-container");
|
||||||
this.#originalLineItemControl = document.getElementById(this.#prefix + "-original-line-item-control");
|
this.#originalLineItemControl = document.getElementById(this.#prefix + "-original-line-item-control");
|
||||||
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item");
|
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item");
|
||||||
@ -249,14 +243,31 @@ class JournalEntryLineItemEditor {
|
|||||||
if (this.lineItem === null) {
|
if (this.lineItem === null) {
|
||||||
this.lineItem = this.#debitCreditSubForm.addLineItem();
|
this.lineItem = this.#debitCreditSubForm.addLineItem();
|
||||||
}
|
}
|
||||||
this.amount = this.#amountInput.value;
|
|
||||||
this.lineItem.save(this);
|
this.lineItem.save(this);
|
||||||
bootstrap.Modal.getInstance(this.#modal).hide();
|
bootstrap.Modal.getInstance(this.modal).hide();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount.
|
||||||
|
*
|
||||||
|
* @return {string} the amount
|
||||||
|
*/
|
||||||
|
get amount() {
|
||||||
|
return this.#amountInput.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currency code.
|
||||||
|
*
|
||||||
|
* @return {string} the currency code
|
||||||
|
*/
|
||||||
|
get currencyCode() {
|
||||||
|
return this.#debitCreditSubForm.currency.currencyCode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the original line item from the original line item selector.
|
* Saves the original line item from the original line item selector.
|
||||||
*
|
*
|
||||||
@ -308,15 +319,6 @@ class JournalEntryLineItemEditor {
|
|||||||
this.#amountInput.max = "";
|
this.#amountInput.max = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the currency code.
|
|
||||||
*
|
|
||||||
* @return {string} the currency code
|
|
||||||
*/
|
|
||||||
getCurrencyCode() {
|
|
||||||
return this.#debitCreditSubForm.currency.getCurrencyCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the description from the description editor.
|
* Saves the description from the description editor.
|
||||||
*
|
*
|
||||||
@ -331,7 +333,7 @@ class JournalEntryLineItemEditor {
|
|||||||
this.description = description === ""? null: description;
|
this.description = description === ""? null: description;
|
||||||
this.#descriptionText.innerText = description;
|
this.#descriptionText.innerText = description;
|
||||||
this.#validateDescription();
|
this.#validateDescription();
|
||||||
bootstrap.Modal.getOrCreateInstance(this.#modal).show();
|
bootstrap.Modal.getOrCreateInstance(this.modal).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -520,10 +522,10 @@ class JournalEntryLineItemEditor {
|
|||||||
this.lineItem = lineItem;
|
this.lineItem = lineItem;
|
||||||
this.#debitCreditSubForm = lineItem.debitCreditSubForm;
|
this.#debitCreditSubForm = lineItem.debitCreditSubForm;
|
||||||
this.debitCredit = this.#debitCreditSubForm.debitCredit;
|
this.debitCredit = this.#debitCreditSubForm.debitCredit;
|
||||||
this.isNeedOffset = lineItem.isNeedOffset();
|
this.isNeedOffset = lineItem.isNeedOffset;
|
||||||
this.originalLineItemId = lineItem.getOriginalLineItemId();
|
this.originalLineItemId = lineItem.originalLineItemId;
|
||||||
this.originalLineItemDate = lineItem.getOriginalLineItemDate();
|
this.originalLineItemDate = lineItem.originalLineItemDate;
|
||||||
this.originalLineItemText = lineItem.getOriginalLineItemText();
|
this.originalLineItemText = lineItem.originalLineItemText;
|
||||||
this.#originalLineItemText.innerText = this.originalLineItemText;
|
this.#originalLineItemText.innerText = this.originalLineItemText;
|
||||||
if (this.originalLineItemId === null) {
|
if (this.originalLineItemId === null) {
|
||||||
this.#originalLineItemContainer.classList.add("d-none");
|
this.#originalLineItemContainer.classList.add("d-none");
|
||||||
@ -533,25 +535,25 @@ class JournalEntryLineItemEditor {
|
|||||||
this.#originalLineItemControl.classList.add("accounting-not-empty");
|
this.#originalLineItemControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.#setEnableDescriptionAccount(!lineItem.isMatched && this.originalLineItemId === null);
|
this.#setEnableDescriptionAccount(!lineItem.isMatched && this.originalLineItemId === null);
|
||||||
this.description = lineItem.getDescription();
|
this.description = lineItem.description;
|
||||||
if (this.description === null) {
|
if (this.description === null) {
|
||||||
this.#descriptionControl.classList.remove("accounting-not-empty");
|
this.#descriptionControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#descriptionControl.classList.add("accounting-not-empty");
|
this.#descriptionControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.#descriptionText.innerText = this.description === null? "": this.description;
|
this.#descriptionText.innerText = this.description === null? "": this.description;
|
||||||
if (lineItem.getAccountCode() === null) {
|
if (lineItem.accountCode === null) {
|
||||||
this.#accountControl.classList.remove("accounting-not-empty");
|
this.#accountControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#accountControl.classList.add("accounting-not-empty");
|
this.#accountControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.accountCode = lineItem.getAccountCode();
|
this.accountCode = lineItem.accountCode;
|
||||||
this.accountText = lineItem.getAccountText();
|
this.accountText = lineItem.accountText;
|
||||||
this.#accountText.innerText = this.accountText;
|
this.#accountText.innerText = this.accountText;
|
||||||
this.#amountInput.value = lineItem.getAmount() === null? "": String(lineItem.getAmount());
|
this.#amountInput.value = lineItem.amount === null? "": String(lineItem.amount);
|
||||||
const maxAmount = this.#getMaxAmount();
|
const maxAmount = this.#getMaxAmount();
|
||||||
this.#amountInput.max = maxAmount === null? "": maxAmount;
|
this.#amountInput.max = maxAmount === null? "": maxAmount;
|
||||||
this.#amountInput.min = lineItem.getAmountMin() === null? "": String(lineItem.getAmountMin());
|
this.#amountInput.min = lineItem.amountMin === null? "": String(lineItem.amountMin);
|
||||||
this.#validate();
|
this.#validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ class RecurringExpenseIncomeSubForm {
|
|||||||
editor;
|
editor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
#prefix;
|
#prefix;
|
||||||
@ -313,10 +313,8 @@ class RecurringExpenseIncomeSubForm {
|
|||||||
*/
|
*/
|
||||||
#initializeDragAndDropReordering() {
|
#initializeDragAndDropReordering() {
|
||||||
initializeDragAndDropReordering(this.#itemList, () => {
|
initializeDragAndDropReordering(this.#itemList, () => {
|
||||||
const itemId = Array.from(this.#itemList.children).map((item) => item.id);
|
for (const item of this.#items) {
|
||||||
this.#items.sort((a, b) => itemId.indexOf(a.element.id) - itemId.indexOf(b.element.id));
|
item.resetNo();
|
||||||
for (let i = 0; i < this.#items.length; i++) {
|
|
||||||
this.#items[i].no.value = String(i + 1);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -365,7 +363,7 @@ class RecurringItemSubForm {
|
|||||||
* The element
|
* The element
|
||||||
* @type {HTMLLIElement}
|
* @type {HTMLLIElement}
|
||||||
*/
|
*/
|
||||||
element;
|
#element;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item index
|
* The item index
|
||||||
@ -386,10 +384,10 @@ class RecurringItemSubForm {
|
|||||||
#error;
|
#error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number
|
* The order number
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
no;
|
#no;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name input
|
* The name input
|
||||||
@ -441,12 +439,12 @@ class RecurringItemSubForm {
|
|||||||
*/
|
*/
|
||||||
constructor(expenseIncomeSubForm, element) {
|
constructor(expenseIncomeSubForm, element) {
|
||||||
this.#expenseIncomeSubForm = expenseIncomeSubForm
|
this.#expenseIncomeSubForm = expenseIncomeSubForm
|
||||||
this.element = element;
|
this.#element = element;
|
||||||
this.itemIndex = parseInt(element.dataset.itemIndex);
|
this.itemIndex = parseInt(element.dataset.itemIndex);
|
||||||
const prefix = "accounting-recurring-" + expenseIncomeSubForm.expenseIncome + "-" + element.dataset.itemIndex;
|
const prefix = "accounting-recurring-" + expenseIncomeSubForm.expenseIncome + "-" + element.dataset.itemIndex;
|
||||||
this.#control = document.getElementById(prefix + "-control");
|
this.#control = document.getElementById(prefix + "-control");
|
||||||
this.#error = document.getElementById(prefix + "-error");
|
this.#error = document.getElementById(prefix + "-error");
|
||||||
this.no = document.getElementById(prefix + "-no");
|
this.#no = document.getElementById(prefix + "-no");
|
||||||
this.#name = document.getElementById(prefix + "-name");
|
this.#name = document.getElementById(prefix + "-name");
|
||||||
this.#nameText = document.getElementById(prefix + "-name-text");
|
this.#nameText = document.getElementById(prefix + "-name-text");
|
||||||
this.#accountCode = document.getElementById(prefix + "-account-code");
|
this.#accountCode = document.getElementById(prefix + "-account-code");
|
||||||
@ -457,17 +455,26 @@ class RecurringItemSubForm {
|
|||||||
|
|
||||||
this.#control.onclick = () => this.#expenseIncomeSubForm.editor.onEdit(this);
|
this.#control.onclick = () => this.#expenseIncomeSubForm.editor.onEdit(this);
|
||||||
this.deleteButton.onclick = () => {
|
this.deleteButton.onclick = () => {
|
||||||
this.element.parentElement.removeChild(this.element);
|
this.#element.parentElement.removeChild(this.#element);
|
||||||
this.#expenseIncomeSubForm.deleteItem(this);
|
this.#expenseIncomeSubForm.deleteItem(this);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the order number.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
resetNo() {
|
||||||
|
const siblings = Array.from(this.#element.parentElement.children);
|
||||||
|
this.#no.value = String(siblings.indexOf(this.#element) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name.
|
* Returns the name.
|
||||||
*
|
*
|
||||||
* @return {string|null} the name
|
* @return {string|null} the name
|
||||||
*/
|
*/
|
||||||
getName() {
|
get name() {
|
||||||
return this.#name.value === ""? null: this.#name.value;
|
return this.#name.value === ""? null: this.#name.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,7 +483,7 @@ class RecurringItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the account code
|
* @return {string|null} the account code
|
||||||
*/
|
*/
|
||||||
getAccountCode() {
|
get accountCode() {
|
||||||
return this.#accountCode.value === ""? null: this.#accountCode.value;
|
return this.#accountCode.value === ""? null: this.#accountCode.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,7 +492,7 @@ class RecurringItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the account text
|
* @return {string|null} the account text
|
||||||
*/
|
*/
|
||||||
getAccountText() {
|
get accountText() {
|
||||||
return this.#accountCode.dataset.text === ""? null: this.#accountCode.dataset.text;
|
return this.#accountCode.dataset.text === ""? null: this.#accountCode.dataset.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,7 +501,7 @@ class RecurringItemSubForm {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the description template
|
* @return {string|null} the description template
|
||||||
*/
|
*/
|
||||||
getDescriptionTemplate() {
|
get descriptionTemplate() {
|
||||||
return this.#descriptionTemplate.value === ""? null: this.#descriptionTemplate.value;
|
return this.#descriptionTemplate.value === ""? null: this.#descriptionTemplate.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,12 +511,12 @@ class RecurringItemSubForm {
|
|||||||
* @param editor {RecurringItemEditor} the recurring item editor
|
* @param editor {RecurringItemEditor} the recurring item editor
|
||||||
*/
|
*/
|
||||||
save(editor) {
|
save(editor) {
|
||||||
this.#name.value = editor.getName() === null? "": editor.getName();
|
this.#name.value = editor.name === null? "": editor.name;
|
||||||
this.#nameText.innerText = this.#name.value;
|
this.#nameText.innerText = this.#name.value;
|
||||||
this.#accountCode.value = editor.accountCode;
|
this.#accountCode.value = editor.accountCode;
|
||||||
this.#accountCode.dataset.text = editor.accountText;
|
this.#accountCode.dataset.text = editor.accountText;
|
||||||
this.#accountText.innerText = editor.accountText;
|
this.#accountText.innerText = editor.accountText;
|
||||||
this.#descriptionTemplate.value = editor.getDescriptionTemplate() === null? "": editor.getDescriptionTemplate();
|
this.#descriptionTemplate.value = editor.descriptionTemplate === null? "": editor.descriptionTemplate;
|
||||||
this.#descriptionTemplateText.innerText = this.#descriptionTemplate.value;
|
this.#descriptionTemplateText.innerText = this.#descriptionTemplate.value;
|
||||||
this.validate();
|
this.validate();
|
||||||
}
|
}
|
||||||
@ -677,7 +684,7 @@ class RecurringItemEditor {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the name
|
* @return {string|null} the name
|
||||||
*/
|
*/
|
||||||
getName() {
|
get name() {
|
||||||
return this.#name.value === ""? null: this.#name.value;
|
return this.#name.value === ""? null: this.#name.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -686,7 +693,7 @@ class RecurringItemEditor {
|
|||||||
*
|
*
|
||||||
* @return {string|null} the description template
|
* @return {string|null} the description template
|
||||||
*/
|
*/
|
||||||
getDescriptionTemplate() {
|
get descriptionTemplate() {
|
||||||
return this.#descriptionTemplate.value === ""? null: this.#descriptionTemplate.value;
|
return this.#descriptionTemplate.value === ""? null: this.#descriptionTemplate.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,16 +749,16 @@ class RecurringItemEditor {
|
|||||||
*/
|
*/
|
||||||
onEdit(item) {
|
onEdit(item) {
|
||||||
this.#item = item;
|
this.#item = item;
|
||||||
this.#name.value = item.getName() === null? "": item.getName();
|
this.#name.value = item.name === null? "": item.name;
|
||||||
this.accountCode = item.getAccountCode();
|
this.accountCode = item.accountCode;
|
||||||
this.accountText = item.getAccountText();
|
this.accountText = item.accountText;
|
||||||
if (this.accountText === null) {
|
if (this.accountText === null) {
|
||||||
this.#accountControl.classList.remove("accounting-not-empty");
|
this.#accountControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#accountControl.classList.add("accounting-not-empty");
|
this.#accountControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.#accountContainer.innerText = item.getAccountText() == null? "": item.getAccountText();
|
this.#accountContainer.innerText = this.accountText === null? "": this.accountText;
|
||||||
this.#descriptionTemplate.value = item.getDescriptionTemplate() === null? "": item.getDescriptionTemplate();
|
this.#descriptionTemplate.value = item.descriptionTemplate === null? "": item.descriptionTemplate;
|
||||||
this.#validate();
|
this.#validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ class OriginalLineItemSelector {
|
|||||||
lineItemEditor;
|
lineItemEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
#prefix = "accounting-original-line-item-selector";
|
#prefix = "accounting-original-line-item-selector";
|
||||||
@ -113,8 +113,8 @@ class OriginalLineItemSelector {
|
|||||||
const otherLineItems = form.getLineItems().filter((lineItem) => lineItem !== currentLineItem);
|
const otherLineItems = form.getLineItems().filter((lineItem) => lineItem !== currentLineItem);
|
||||||
let otherOffset = new Decimal(0);
|
let otherOffset = new Decimal(0);
|
||||||
for (const otherLineItem of otherLineItems) {
|
for (const otherLineItem of otherLineItems) {
|
||||||
if (otherLineItem.getOriginalLineItemId() === originalLineItemId) {
|
if (otherLineItem.originalLineItemId === originalLineItemId) {
|
||||||
const amount = otherLineItem.getAmount();
|
const amount = otherLineItem.amount;
|
||||||
if (amount !== null) {
|
if (amount !== null) {
|
||||||
otherOffset = otherOffset.plus(amount);
|
otherOffset = otherOffset.plus(amount);
|
||||||
}
|
}
|
||||||
@ -131,8 +131,8 @@ class OriginalLineItemSelector {
|
|||||||
const otherLineItems = this.lineItemEditor.form.getLineItems().filter((lineItem) => lineItem !== this.lineItemEditor.lineItem);
|
const otherLineItems = this.lineItemEditor.form.getLineItems().filter((lineItem) => lineItem !== this.lineItemEditor.lineItem);
|
||||||
const otherOffsets = {}
|
const otherOffsets = {}
|
||||||
for (const otherLineItem of otherLineItems) {
|
for (const otherLineItem of otherLineItems) {
|
||||||
const otherOriginalLineItemId = otherLineItem.getOriginalLineItemId();
|
const otherOriginalLineItemId = otherLineItem.originalLineItemId;
|
||||||
const amount = otherLineItem.getAmount();
|
const amount = otherLineItem.amount;
|
||||||
if (otherOriginalLineItemId === null || amount === null) {
|
if (otherOriginalLineItemId === null || amount === null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -178,7 +178,7 @@ class OriginalLineItemSelector {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
onOpen() {
|
onOpen() {
|
||||||
this.#currencyCode = this.lineItemEditor.getCurrencyCode();
|
this.#currencyCode = this.lineItemEditor.currencyCode;
|
||||||
this.#debitCredit = this.lineItemEditor.debitCredit;
|
this.#debitCredit = this.lineItemEditor.debitCredit;
|
||||||
for (const option of this.#options) {
|
for (const option of this.#options) {
|
||||||
option.setActive(option.id === this.lineItemEditor.originalLineItemId);
|
option.setActive(option.id === this.lineItemEditor.originalLineItemId);
|
||||||
@ -341,7 +341,7 @@ class OriginalLineItem {
|
|||||||
*/
|
*/
|
||||||
isMatched(debitCredit, currencyCode, query = null) {
|
isMatched(debitCredit, currencyCode, query = null) {
|
||||||
return this.netBalance.greaterThan(0)
|
return this.netBalance.greaterThan(0)
|
||||||
&& this.date <= this.#selector.lineItemEditor.form.getDate()
|
&& this.date <= this.#selector.lineItemEditor.form.date
|
||||||
&& this.#isDebitCreditMatches(debitCredit)
|
&& this.#isDebitCreditMatches(debitCredit)
|
||||||
&& this.#currencyCode === currencyCode
|
&& this.#currencyCode === currencyCode
|
||||||
&& this.#isQueryMatches(query);
|
&& this.#isQueryMatches(query);
|
||||||
|
@ -33,12 +33,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
*/
|
*/
|
||||||
class PeriodChooser {
|
class PeriodChooser {
|
||||||
|
|
||||||
/**
|
|
||||||
* The prefix of the HTML ID and class
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
prefix;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modal of the period chooser
|
* The modal of the period chooser
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
@ -56,8 +50,8 @@ class PeriodChooser {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.prefix = "accounting-period-chooser";
|
const prefix = "accounting-period-chooser";
|
||||||
this.modal = document.getElementById(this.prefix + "-modal");
|
this.modal = document.getElementById(prefix + "-modal");
|
||||||
for (const cls of [MonthTab, YearTab, DayTab, CustomTab]) {
|
for (const cls of [MonthTab, YearTab, DayTab, CustomTab]) {
|
||||||
const tab = new cls(this);
|
const tab = new cls(this);
|
||||||
this.tabPlanes[tab.tabId()] = tab;
|
this.tabPlanes[tab.tabId()] = tab;
|
||||||
@ -94,7 +88,7 @@ class TabPlane {
|
|||||||
chooser;
|
chooser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The prefix of the HTML ID and class
|
* The prefix of the HTML ID and class names
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
prefix;
|
prefix;
|
||||||
|
@ -20,29 +20,31 @@ Author: imacat@mail.imacat.idv.tw (imacat)
|
|||||||
First written: 2023/3/21
|
First written: 2023/3/21
|
||||||
#}
|
#}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ debit_credit }}" class="form-control accounting-material-text-field accounting-not-empty {% if debit_errors %} is-invalid {% endif %}">
|
<div id="accounting-currency-{{ currency_index }}-{{ debit_credit }}" class="form-control accounting-material-text-field {% if line_item_forms %} accounting-not-empty {% else %} accounting-clickable {% endif %} {% if debit_errors %} is-invalid {% endif %}">
|
||||||
<label class="form-label" for="accounting-currency-{{ currency_index }}-{{ debit_credit }}">{{ header }}</label>
|
<label class="form-label" for="accounting-currency-{{ currency_index }}-{{ debit_credit }}">{{ header }}</label>
|
||||||
<ul id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-list" class="list-group accounting-line-item-list">
|
<div id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-content" class="mt-2 {% if not line_item_forms %} d-none {% endif %}">
|
||||||
{% for line_item_form in line_item_forms %}
|
<ul id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-list" class="list-group accounting-line-item-list">
|
||||||
{% with currency_index = currency_index,
|
{% for line_item_form in line_item_forms %}
|
||||||
line_item_index = loop.index,
|
{% with currency_index = currency_index,
|
||||||
only_one_line_item_form = line_item_forms|length == 1,
|
line_item_index = loop.index,
|
||||||
form = line_item_form.form %}
|
only_one_line_item_form = line_item_forms|length == 1,
|
||||||
{% include "accounting/journal-entry/include/form-line-item.html" %}
|
form = line_item_form.form %}
|
||||||
{% endwith %}
|
{% include "accounting/journal-entry/include/form-line-item.html" %}
|
||||||
{% endfor %}
|
{% endwith %}
|
||||||
</ul>
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
<div class="d-flex justify-content-between mb-2">
|
<div class="d-flex justify-content-between mt-2 mb-2">
|
||||||
<div>{{ A_("Total") }}</div>
|
<div>{{ A_("Total") }}</div>
|
||||||
<div><span id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-total" class="badge rounded-pill bg-primary">{{ debit_credit_total }}</span></div>
|
<div><span id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-total" class="badge rounded-pill bg-primary">{{ debit_credit_total }}</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-add-line-item" class="btn btn-primary" type="button" data-currency-index="{{ currency_index }}" data-debit-credit="{{ debit_credit }}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
<button id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-add-line-item" class="btn btn-primary" type="button" data-currency-index="{{ currency_index }}" data-debit-credit="{{ debit_credit }}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{ A_("New") }}
|
{{ A_("New") }}
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-error" class="invalid-feedback">{% if debit_credit_errors %}{{ debit_credit_errors[0] }}{% endif %}</div>
|
<div id="accounting-currency-{{ currency_index }}-{{ debit_credit }}-error" class="invalid-feedback">{% if debit_credit_errors %}{{ debit_credit_errors[0] }}{% endif %}</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user