Renamed "summary" to "description" in the voucher line item.
This commit is contained in:
parent
3251660092
commit
d18dd7d4d2
@ -653,8 +653,8 @@ class VoucherLineItem(db.Model):
|
|||||||
"""The account ID."""
|
"""The account ID."""
|
||||||
account = db.relationship(Account, back_populates="line_items", lazy=False)
|
account = db.relationship(Account, back_populates="line_items", lazy=False)
|
||||||
"""The account."""
|
"""The account."""
|
||||||
summary = db.Column(db.String, nullable=True)
|
description = db.Column(db.String, nullable=True)
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
amount = db.Column(db.Numeric(14, 2), nullable=False)
|
amount = db.Column(db.Numeric(14, 2), nullable=False)
|
||||||
"""The amount."""
|
"""The amount."""
|
||||||
|
|
||||||
@ -666,10 +666,10 @@ class VoucherLineItem(db.Model):
|
|||||||
if not hasattr(self, "__str"):
|
if not hasattr(self, "__str"):
|
||||||
from accounting.template_filters import format_date, format_amount
|
from accounting.template_filters import format_date, format_amount
|
||||||
setattr(self, "__str",
|
setattr(self, "__str",
|
||||||
gettext("%(date)s %(summary)s %(amount)s",
|
gettext("%(date)s %(description)s %(amount)s",
|
||||||
date=format_date(self.voucher.date),
|
date=format_date(self.voucher.date),
|
||||||
summary="" if self.summary is None
|
description="" if self.description is None
|
||||||
else self.summary,
|
else self.description,
|
||||||
amount=format_amount(self.amount)))
|
amount=format_amount(self.amount)))
|
||||||
return getattr(self, "__str")
|
return getattr(self, "__str")
|
||||||
|
|
||||||
@ -753,8 +753,8 @@ class VoucherLineItem(db.Model):
|
|||||||
return str(whole) + str(abs(frac))[1:]
|
return str(whole) + str(abs(frac))[1:]
|
||||||
|
|
||||||
voucher_day: date = self.voucher.date
|
voucher_day: date = self.voucher.date
|
||||||
summary: str = "" if self.summary is None else self.summary
|
description: str = "" if self.description is None else self.description
|
||||||
return ([summary],
|
return ([description],
|
||||||
[str(voucher_day.year),
|
[str(voucher_day.year),
|
||||||
"{}/{}".format(voucher_day.year, voucher_day.month),
|
"{}/{}".format(voucher_day.year, voucher_day.month),
|
||||||
"{}/{}".format(voucher_day.month, voucher_day.day),
|
"{}/{}".format(voucher_day.month, voucher_day.day),
|
||||||
|
@ -57,8 +57,8 @@ class ReportLineItem:
|
|||||||
"""The date."""
|
"""The date."""
|
||||||
self.account: Account | None = None
|
self.account: Account | None = None
|
||||||
"""The account."""
|
"""The account."""
|
||||||
self.summary: str | None = None
|
self.description: str | None = None
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.income: Decimal | None = None
|
self.income: Decimal | None = None
|
||||||
"""The income amount."""
|
"""The income amount."""
|
||||||
self.expense: Decimal | None = None
|
self.expense: Decimal | None = None
|
||||||
@ -72,7 +72,7 @@ class ReportLineItem:
|
|||||||
if line_item is not None:
|
if line_item is not None:
|
||||||
self.date = line_item.voucher.date
|
self.date = line_item.voucher.date
|
||||||
self.account = line_item.account
|
self.account = line_item.account
|
||||||
self.summary = line_item.summary
|
self.description = line_item.description
|
||||||
self.income = None if line_item.is_debit else line_item.amount
|
self.income = None if line_item.is_debit else line_item.amount
|
||||||
self.expense = line_item.amount if line_item.is_debit else None
|
self.expense = line_item.amount if line_item.is_debit else None
|
||||||
self.note = line_item.voucher.note
|
self.note = line_item.voucher.note
|
||||||
@ -131,7 +131,7 @@ class LineItemCollector:
|
|||||||
line_item.is_brought_forward = True
|
line_item.is_brought_forward = True
|
||||||
line_item.date = self.__period.start
|
line_item.date = self.__period.start
|
||||||
line_item.account = Account.accumulated_change()
|
line_item.account = Account.accumulated_change()
|
||||||
line_item.summary = gettext("Brought forward")
|
line_item.description = gettext("Brought forward")
|
||||||
if balance > 0:
|
if balance > 0:
|
||||||
line_item.income = balance
|
line_item.income = balance
|
||||||
elif balance < 0:
|
elif balance < 0:
|
||||||
@ -184,7 +184,7 @@ class LineItemCollector:
|
|||||||
return None
|
return None
|
||||||
line_item: ReportLineItem = ReportLineItem()
|
line_item: ReportLineItem = ReportLineItem()
|
||||||
line_item.is_total = True
|
line_item.is_total = True
|
||||||
line_item.summary = gettext("Total")
|
line_item.description = gettext("Total")
|
||||||
line_item.income = sum([x.income for x in self.line_items
|
line_item.income = sum([x.income for x in self.line_items
|
||||||
if x.income is not None])
|
if x.income is not None])
|
||||||
line_item.expense = sum([x.expense for x in self.line_items
|
line_item.expense = sum([x.expense for x in self.line_items
|
||||||
@ -215,7 +215,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
|
|
||||||
def __init__(self, voucher_date: date | str | None,
|
def __init__(self, voucher_date: date | str | None,
|
||||||
account: str | None,
|
account: str | None,
|
||||||
summary: str | None,
|
description: str | None,
|
||||||
income: str | Decimal | None,
|
income: str | Decimal | None,
|
||||||
expense: str | Decimal | None,
|
expense: str | Decimal | None,
|
||||||
balance: str | Decimal | None,
|
balance: str | Decimal | None,
|
||||||
@ -224,7 +224,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
|
|
||||||
:param voucher_date: The voucher date.
|
:param voucher_date: The voucher date.
|
||||||
:param account: The account.
|
:param account: The account.
|
||||||
:param summary: The summary.
|
:param description: The description.
|
||||||
:param income: The income.
|
:param income: The income.
|
||||||
:param expense: The expense.
|
:param expense: The expense.
|
||||||
:param balance: The balance.
|
:param balance: The balance.
|
||||||
@ -234,8 +234,8 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""The date."""
|
"""The date."""
|
||||||
self.account: str | None = account
|
self.account: str | None = account
|
||||||
"""The account."""
|
"""The account."""
|
||||||
self.summary: str | None = summary
|
self.description: str | None = description
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.income: str | Decimal | None = income
|
self.income: str | Decimal | None = income
|
||||||
"""The income."""
|
"""The income."""
|
||||||
self.expense: str | Decimal | None = expense
|
self.expense: str | Decimal | None = expense
|
||||||
@ -251,7 +251,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
|
|
||||||
:return: The values of the row.
|
:return: The values of the row.
|
||||||
"""
|
"""
|
||||||
return [self.date, self.account, self.summary,
|
return [self.date, self.account, self.description,
|
||||||
self.income, self.expense, self.balance, self.note]
|
self.income, self.expense, self.balance, self.note]
|
||||||
|
|
||||||
|
|
||||||
@ -405,18 +405,18 @@ class IncomeExpenses(BaseReport):
|
|||||||
:return: The CSV rows.
|
:return: The CSV rows.
|
||||||
"""
|
"""
|
||||||
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Account"),
|
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Account"),
|
||||||
gettext("Summary"), gettext("Income"),
|
gettext("Description"), gettext("Income"),
|
||||||
gettext("Expense"), gettext("Balance"),
|
gettext("Expense"), gettext("Balance"),
|
||||||
gettext("Note"))]
|
gettext("Note"))]
|
||||||
if self.__brought_forward is not None:
|
if self.__brought_forward is not None:
|
||||||
rows.append(CSVRow(self.__brought_forward.date,
|
rows.append(CSVRow(self.__brought_forward.date,
|
||||||
str(self.__brought_forward.account).title(),
|
str(self.__brought_forward.account).title(),
|
||||||
self.__brought_forward.summary,
|
self.__brought_forward.description,
|
||||||
self.__brought_forward.income,
|
self.__brought_forward.income,
|
||||||
self.__brought_forward.expense,
|
self.__brought_forward.expense,
|
||||||
self.__brought_forward.balance,
|
self.__brought_forward.balance,
|
||||||
None))
|
None))
|
||||||
rows.extend([CSVRow(x.date, str(x.account).title(), x.summary,
|
rows.extend([CSVRow(x.date, str(x.account).title(), x.description,
|
||||||
x.income, x.expense, x.balance, x.note)
|
x.income, x.expense, x.balance, x.note)
|
||||||
for x in self.__line_items])
|
for x in self.__line_items])
|
||||||
if self.__total is not None:
|
if self.__total is not None:
|
||||||
|
@ -53,8 +53,8 @@ class ReportLineItem:
|
|||||||
"""The account."""
|
"""The account."""
|
||||||
self.account: Account = line_item.account
|
self.account: Account = line_item.account
|
||||||
"""The account."""
|
"""The account."""
|
||||||
self.summary: str | None = line_item.summary
|
self.description: str | None = line_item.description
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.debit: Decimal | None = line_item.debit
|
self.debit: Decimal | None = line_item.debit
|
||||||
"""The debit amount."""
|
"""The debit amount."""
|
||||||
self.credit: Decimal | None = line_item.credit
|
self.credit: Decimal | None = line_item.credit
|
||||||
@ -69,14 +69,14 @@ class CSVRow(BaseCSVRow):
|
|||||||
def __init__(self, voucher_date: str | date,
|
def __init__(self, voucher_date: str | date,
|
||||||
currency: str,
|
currency: str,
|
||||||
account: str,
|
account: str,
|
||||||
summary: str | None,
|
description: str | None,
|
||||||
debit: str | Decimal | None,
|
debit: str | Decimal | None,
|
||||||
credit: str | Decimal | None,
|
credit: str | Decimal | None,
|
||||||
note: str | None):
|
note: str | None):
|
||||||
"""Constructs a row in the CSV.
|
"""Constructs a row in the CSV.
|
||||||
|
|
||||||
:param voucher_date: The voucher date.
|
:param voucher_date: The voucher date.
|
||||||
:param summary: The summary.
|
:param description: The description.
|
||||||
:param debit: The debit amount.
|
:param debit: The debit amount.
|
||||||
:param credit: The credit amount.
|
:param credit: The credit amount.
|
||||||
:param note: The note.
|
:param note: The note.
|
||||||
@ -87,8 +87,8 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""The currency."""
|
"""The currency."""
|
||||||
self.account: str = account
|
self.account: str = account
|
||||||
"""The account."""
|
"""The account."""
|
||||||
self.summary: str | None = summary
|
self.description: str | None = description
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.debit: str | Decimal | None = debit
|
self.debit: str | Decimal | None = debit
|
||||||
"""The debit amount."""
|
"""The debit amount."""
|
||||||
self.credit: str | Decimal | None = credit
|
self.credit: str | Decimal | None = credit
|
||||||
@ -102,7 +102,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
|
|
||||||
:return: The values of the row.
|
:return: The values of the row.
|
||||||
"""
|
"""
|
||||||
return [self.date, self.currency, self.account, self.summary,
|
return [self.date, self.currency, self.account, self.description,
|
||||||
self.debit, self.credit, self.note]
|
self.debit, self.credit, self.note]
|
||||||
|
|
||||||
|
|
||||||
@ -152,11 +152,11 @@ def get_csv_rows(line_items: list[VoucherLineItem]) -> list[CSVRow]:
|
|||||||
:return: The CSV rows.
|
:return: The CSV rows.
|
||||||
"""
|
"""
|
||||||
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Currency"),
|
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Currency"),
|
||||||
gettext("Account"), gettext("Summary"),
|
gettext("Account"), gettext("Description"),
|
||||||
gettext("Debit"), gettext("Credit"),
|
gettext("Debit"), gettext("Credit"),
|
||||||
gettext("Note"))]
|
gettext("Note"))]
|
||||||
rows.extend([CSVRow(x.voucher.date, x.currency.code,
|
rows.extend([CSVRow(x.voucher.date, x.currency.code,
|
||||||
str(x.account).title(), x.summary,
|
str(x.account).title(), x.description,
|
||||||
x.debit, x.credit, x.voucher.note)
|
x.debit, x.credit, x.voucher.note)
|
||||||
for x in line_items])
|
for x in line_items])
|
||||||
return rows
|
return rows
|
||||||
|
@ -54,8 +54,8 @@ class ReportLineItem:
|
|||||||
"""Whether this is the total line item."""
|
"""Whether this is the total line item."""
|
||||||
self.date: date | None = None
|
self.date: date | None = None
|
||||||
"""The date."""
|
"""The date."""
|
||||||
self.summary: str | None = None
|
self.description: str | None = None
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.debit: Decimal | None = None
|
self.debit: Decimal | None = None
|
||||||
"""The debit amount."""
|
"""The debit amount."""
|
||||||
self.credit: Decimal | None = None
|
self.credit: Decimal | None = None
|
||||||
@ -68,7 +68,7 @@ class ReportLineItem:
|
|||||||
"""The URL to the voucher line item."""
|
"""The URL to the voucher line item."""
|
||||||
if line_item is not None:
|
if line_item is not None:
|
||||||
self.date = line_item.voucher.date
|
self.date = line_item.voucher.date
|
||||||
self.summary = line_item.summary
|
self.description = line_item.description
|
||||||
self.debit = line_item.amount if line_item.is_debit else None
|
self.debit = line_item.amount if line_item.is_debit else None
|
||||||
self.credit = None if line_item.is_debit else line_item.amount
|
self.credit = None if line_item.is_debit else line_item.amount
|
||||||
self.note = line_item.voucher.note
|
self.note = line_item.voucher.note
|
||||||
@ -126,7 +126,7 @@ class LineItemCollector:
|
|||||||
line_item: ReportLineItem = ReportLineItem()
|
line_item: ReportLineItem = ReportLineItem()
|
||||||
line_item.is_brought_forward = True
|
line_item.is_brought_forward = True
|
||||||
line_item.date = self.__period.start
|
line_item.date = self.__period.start
|
||||||
line_item.summary = gettext("Brought forward")
|
line_item.description = gettext("Brought forward")
|
||||||
if balance > 0:
|
if balance > 0:
|
||||||
line_item.debit = balance
|
line_item.debit = balance
|
||||||
elif balance < 0:
|
elif balance < 0:
|
||||||
@ -163,7 +163,7 @@ class LineItemCollector:
|
|||||||
return None
|
return None
|
||||||
line_item: ReportLineItem = ReportLineItem()
|
line_item: ReportLineItem = ReportLineItem()
|
||||||
line_item.is_total = True
|
line_item.is_total = True
|
||||||
line_item.summary = gettext("Total")
|
line_item.description = gettext("Total")
|
||||||
line_item.debit = sum([x.debit for x in self.line_items
|
line_item.debit = sum([x.debit for x in self.line_items
|
||||||
if x.debit is not None])
|
if x.debit is not None])
|
||||||
line_item.credit = sum([x.credit for x in self.line_items
|
line_item.credit = sum([x.credit for x in self.line_items
|
||||||
@ -195,7 +195,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""A row in the CSV."""
|
"""A row in the CSV."""
|
||||||
|
|
||||||
def __init__(self, voucher_date: date | str | None,
|
def __init__(self, voucher_date: date | str | None,
|
||||||
summary: str | None,
|
description: str | None,
|
||||||
debit: str | Decimal | None,
|
debit: str | Decimal | None,
|
||||||
credit: str | Decimal | None,
|
credit: str | Decimal | None,
|
||||||
balance: str | Decimal | None,
|
balance: str | Decimal | None,
|
||||||
@ -203,7 +203,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""Constructs a row in the CSV.
|
"""Constructs a row in the CSV.
|
||||||
|
|
||||||
:param voucher_date: The voucher date.
|
:param voucher_date: The voucher date.
|
||||||
:param summary: The summary.
|
:param description: The description.
|
||||||
:param debit: The debit amount.
|
:param debit: The debit amount.
|
||||||
:param credit: The credit amount.
|
:param credit: The credit amount.
|
||||||
:param balance: The balance.
|
:param balance: The balance.
|
||||||
@ -211,8 +211,8 @@ class CSVRow(BaseCSVRow):
|
|||||||
"""
|
"""
|
||||||
self.date: date | str | None = voucher_date
|
self.date: date | str | None = voucher_date
|
||||||
"""The date."""
|
"""The date."""
|
||||||
self.summary: str | None = summary
|
self.description: str | None = description
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
self.debit: str | Decimal | None = debit
|
self.debit: str | Decimal | None = debit
|
||||||
"""The debit amount."""
|
"""The debit amount."""
|
||||||
self.credit: str | Decimal | None = credit
|
self.credit: str | Decimal | None = credit
|
||||||
@ -228,7 +228,7 @@ class CSVRow(BaseCSVRow):
|
|||||||
|
|
||||||
:return: The values of the row.
|
:return: The values of the row.
|
||||||
"""
|
"""
|
||||||
return [self.date, self.summary,
|
return [self.date, self.description,
|
||||||
self.debit, self.credit, self.balance, self.note]
|
self.debit, self.credit, self.balance, self.note]
|
||||||
|
|
||||||
|
|
||||||
@ -357,17 +357,17 @@ class Ledger(BaseReport):
|
|||||||
|
|
||||||
:return: The CSV rows.
|
:return: The CSV rows.
|
||||||
"""
|
"""
|
||||||
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Summary"),
|
rows: list[CSVRow] = [CSVRow(gettext("Date"), gettext("Description"),
|
||||||
gettext("Debit"), gettext("Credit"),
|
gettext("Debit"), gettext("Credit"),
|
||||||
gettext("Balance"), gettext("Note"))]
|
gettext("Balance"), gettext("Note"))]
|
||||||
if self.__brought_forward is not None:
|
if self.__brought_forward is not None:
|
||||||
rows.append(CSVRow(self.__brought_forward.date,
|
rows.append(CSVRow(self.__brought_forward.date,
|
||||||
self.__brought_forward.summary,
|
self.__brought_forward.description,
|
||||||
self.__brought_forward.debit,
|
self.__brought_forward.debit,
|
||||||
self.__brought_forward.credit,
|
self.__brought_forward.credit,
|
||||||
self.__brought_forward.balance,
|
self.__brought_forward.balance,
|
||||||
None))
|
None))
|
||||||
rows.extend([CSVRow(x.date, x.summary,
|
rows.extend([CSVRow(x.date, x.description,
|
||||||
x.debit, x.credit, x.balance, x.note)
|
x.debit, x.credit, x.balance, x.note)
|
||||||
for x in self.__line_items])
|
for x in self.__line_items])
|
||||||
if self.__total is not None:
|
if self.__total is not None:
|
||||||
|
@ -57,7 +57,7 @@ class LineItemCollector:
|
|||||||
conditions: list[sa.BinaryExpression] = []
|
conditions: list[sa.BinaryExpression] = []
|
||||||
for k in keywords:
|
for k in keywords:
|
||||||
sub_conditions: list[sa.BinaryExpression] \
|
sub_conditions: list[sa.BinaryExpression] \
|
||||||
= [VoucherLineItem.summary.contains(k),
|
= [VoucherLineItem.description.contains(k),
|
||||||
VoucherLineItem.account_id.in_(
|
VoucherLineItem.account_id.in_(
|
||||||
self.__get_account_condition(k)),
|
self.__get_account_condition(k)),
|
||||||
VoucherLineItem.currency_code.in_(
|
VoucherLineItem.currency_code.in_(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* The Mia! Accounting Flask Project
|
/* The Mia! Accounting Flask Project
|
||||||
* summary-editor.js: The JavaScript for the summary editor
|
* description-editor.js: The JavaScript for the description editor
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Copyright (c) 2023 imacat.
|
/* Copyright (c) 2023 imacat.
|
||||||
@ -23,10 +23,10 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A summary editor.
|
* A description editor.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class SummaryEditor {
|
class DescriptionEditor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The line item editor
|
* The line item editor
|
||||||
@ -35,7 +35,7 @@ class SummaryEditor {
|
|||||||
#lineItemEditor;
|
#lineItemEditor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary editor form
|
* The description editor form
|
||||||
* @type {HTMLFormElement}
|
* @type {HTMLFormElement}
|
||||||
*/
|
*/
|
||||||
#form;
|
#form;
|
||||||
@ -47,7 +47,7 @@ class SummaryEditor {
|
|||||||
prefix;
|
prefix;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The modal of the summary editor
|
* The modal of the description editor
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#modal;
|
#modal;
|
||||||
@ -65,10 +65,10 @@ class SummaryEditor {
|
|||||||
currentTab;
|
currentTab;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary input
|
* The description input
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
summary;
|
description;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The button to the original line item selector
|
* The button to the original line item selector
|
||||||
@ -107,7 +107,7 @@ class SummaryEditor {
|
|||||||
tabPlanes = {};
|
tabPlanes = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a summary editor.
|
* Constructs a description editor.
|
||||||
*
|
*
|
||||||
* @param lineItemEditor {VoucherLineItemEditor} the line item editor
|
* @param lineItemEditor {VoucherLineItemEditor} the line item editor
|
||||||
* @param side {string} the side, either "debit" or "credit"
|
* @param side {string} the side, either "debit" or "credit"
|
||||||
@ -115,10 +115,10 @@ class SummaryEditor {
|
|||||||
constructor(lineItemEditor, side) {
|
constructor(lineItemEditor, side) {
|
||||||
this.#lineItemEditor = lineItemEditor;
|
this.#lineItemEditor = lineItemEditor;
|
||||||
this.side = side;
|
this.side = side;
|
||||||
this.prefix = "accounting-summary-editor-" + side;
|
this.prefix = "accounting-description-editor-" + side;
|
||||||
this.#form = document.getElementById(this.prefix);
|
this.#form = document.getElementById(this.prefix);
|
||||||
this.#modal = document.getElementById(this.prefix + "-modal");
|
this.#modal = document.getElementById(this.prefix + "-modal");
|
||||||
this.summary = document.getElementById(this.prefix + "-summary");
|
this.description = document.getElementById(this.prefix + "-description");
|
||||||
this.#offsetButton = document.getElementById(this.prefix + "-offset");
|
this.#offsetButton = document.getElementById(this.prefix + "-offset");
|
||||||
this.number = document.getElementById(this.prefix + "-annotation-number");
|
this.number = document.getElementById(this.prefix + "-annotation-number");
|
||||||
this.note = document.getElementById(this.prefix + "-annotation-note");
|
this.note = document.getElementById(this.prefix + "-annotation-note");
|
||||||
@ -131,7 +131,7 @@ class SummaryEditor {
|
|||||||
}
|
}
|
||||||
this.currentTab = this.tabPlanes.general;
|
this.currentTab = this.tabPlanes.general;
|
||||||
this.#initializeSuggestedAccounts();
|
this.#initializeSuggestedAccounts();
|
||||||
this.summary.onchange = () => this.#onSummaryChange();
|
this.description.onchange = () => this.#onDescriptionChange();
|
||||||
this.#offsetButton.onclick = () => this.#lineItemEditor.originalLineItemSelector.onOpen();
|
this.#offsetButton.onclick = () => this.#lineItemEditor.originalLineItemSelector.onOpen();
|
||||||
this.#form.onsubmit = () => {
|
this.#form.onsubmit = () => {
|
||||||
if (this.currentTab.validate()) {
|
if (this.currentTab.validate()) {
|
||||||
@ -142,11 +142,11 @@ class SummaryEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback when the summary input is changed.
|
* The callback when the description input is changed.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#onSummaryChange() {
|
#onDescriptionChange() {
|
||||||
this.summary.value = this.summary.value.trim();
|
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.bus, this.tabPlanes.travel, this.tabPlanes.general]) {
|
||||||
if (tabPlane.populate()) {
|
if (tabPlane.populate()) {
|
||||||
break;
|
break;
|
||||||
@ -209,34 +209,34 @@ class SummaryEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the summary.
|
* Submits the description.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#submit() {
|
#submit() {
|
||||||
bootstrap.Modal.getOrCreateInstance(this.#modal).hide();
|
bootstrap.Modal.getOrCreateInstance(this.#modal).hide();
|
||||||
if (this.#selectedAccount !== null) {
|
if (this.#selectedAccount !== null) {
|
||||||
this.#lineItemEditor.saveSummaryWithAccount(this.summary.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 {
|
} else {
|
||||||
this.#lineItemEditor.saveSummary(this.summary.value);
|
this.#lineItemEditor.saveDescription(this.description.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback when the summary editor is shown.
|
* The callback when the description editor is shown.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
onOpen() {
|
onOpen() {
|
||||||
this.#reset();
|
this.#reset();
|
||||||
this.summary.value = this.#lineItemEditor.summary === null? "": this.#lineItemEditor.summary;
|
this.description.value = this.#lineItemEditor.description === null? "": this.#lineItemEditor.description;
|
||||||
this.#onSummaryChange();
|
this.#onDescriptionChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the summary editor.
|
* Resets the description editor.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#reset() {
|
#reset() {
|
||||||
this.summary.value = "";
|
this.description.value = "";
|
||||||
for (const tabPlane of Object.values(this.tabPlanes)) {
|
for (const tabPlane of Object.values(this.tabPlanes)) {
|
||||||
tabPlane.reset();
|
tabPlane.reset();
|
||||||
}
|
}
|
||||||
@ -244,16 +244,16 @@ class SummaryEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the summary editor instances.
|
* Returns the description editor instances.
|
||||||
*
|
*
|
||||||
* @param lineItemEditor {VoucherLineItemEditor} the line item editor
|
* @param lineItemEditor {VoucherLineItemEditor} the line item editor
|
||||||
* @return {{debit: SummaryEditor, credit: SummaryEditor}}
|
* @return {{debit: DescriptionEditor, credit: DescriptionEditor}}
|
||||||
*/
|
*/
|
||||||
static getInstances(lineItemEditor) {
|
static getInstances(lineItemEditor) {
|
||||||
const editors = {}
|
const editors = {}
|
||||||
const forms = Array.from(document.getElementsByClassName("accounting-summary-editor"));
|
const forms = Array.from(document.getElementsByClassName("accounting-description-editor"));
|
||||||
for (const form of forms) {
|
for (const form of forms) {
|
||||||
editors[form.dataset.side] = new SummaryEditor(lineItemEditor, form.dataset.side);
|
editors[form.dataset.side] = new DescriptionEditor(lineItemEditor, form.dataset.side);
|
||||||
}
|
}
|
||||||
return editors;
|
return editors;
|
||||||
}
|
}
|
||||||
@ -268,8 +268,8 @@ class SummaryEditor {
|
|||||||
class TabPlane {
|
class TabPlane {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent summary editor
|
* The parent description editor
|
||||||
* @type {SummaryEditor}
|
* @type {DescriptionEditor}
|
||||||
*/
|
*/
|
||||||
editor;
|
editor;
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ class TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
@ -320,9 +320,9 @@ class TabPlane {
|
|||||||
reset() { throw new Error("Method not implemented."); }
|
reset() { throw new Error("Method not implemented."); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @abstract
|
* @abstract
|
||||||
*/
|
*/
|
||||||
populate() { throw new Error("Method not implemented."); }
|
populate() { throw new Error("Method not implemented."); }
|
||||||
@ -383,7 +383,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
@ -395,7 +395,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
this.initializeTagButtons();
|
this.initializeTagButtons();
|
||||||
this.tag.onchange = () => {
|
this.tag.onchange = () => {
|
||||||
this.onTagChange();
|
this.onTagChange();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,11 +424,11 @@ class TagTabPlane extends TabPlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the summary according to the input in the tab plane.
|
* Updates the description according to the input in the tab plane.
|
||||||
*
|
*
|
||||||
* @abstract
|
* @abstract
|
||||||
*/
|
*/
|
||||||
updateSummary() { throw new Error("Method not implemented."); }
|
updateDescription() { throw new Error("Method not implemented."); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches to the tab plane.
|
* Switches to the tab plane.
|
||||||
@ -461,7 +461,7 @@ class TagTabPlane extends TabPlane {
|
|||||||
tagButton.classList.add("btn-primary");
|
tagButton.classList.add("btn-primary");
|
||||||
this.tag.value = tagButton.dataset.value;
|
this.tag.value = tagButton.dataset.value;
|
||||||
this.editor.filterSuggestedAccounts(tagButton);
|
this.editor.filterSuggestedAccounts(tagButton);
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -532,28 +532,28 @@ class GeneralTagTab extends TagTabPlane {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the summary according to the input in the tab plane.
|
* Updates the description according to the input in the tab plane.
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
updateDescription() {
|
||||||
const pos = this.editor.summary.value.indexOf("—");
|
const pos = this.editor.description.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.editor.summary.value = prefix + this.editor.summary.value;
|
this.editor.description.value = prefix + this.editor.description.value;
|
||||||
} else {
|
} else {
|
||||||
this.editor.summary.value = prefix + this.editor.summary.value.substring(pos + 1);
|
this.editor.description.value = prefix + this.editor.description.value.substring(pos + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.editor.summary.value.match(/^([^—]+)—/);
|
const found = this.editor.description.value.match(/^([^—]+)—/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -622,7 +622,7 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
@ -635,7 +635,7 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
this.#directionButtons = Array.from(document.getElementsByClassName(this.prefix + "-direction"));
|
this.#directionButtons = Array.from(document.getElementsByClassName(this.prefix + "-direction"));
|
||||||
this.#from.onchange = () => {
|
this.#from.onchange = () => {
|
||||||
this.#from.value = this.#from.value.trim();
|
this.#from.value = this.#from.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
this.validateFrom();
|
this.validateFrom();
|
||||||
};
|
};
|
||||||
for (const directionButton of this.#directionButtons) {
|
for (const directionButton of this.#directionButtons) {
|
||||||
@ -646,12 +646,12 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
}
|
}
|
||||||
directionButton.classList.remove("btn-outline-primary");
|
directionButton.classList.remove("btn-outline-primary");
|
||||||
directionButton.classList.add("btn-primary");
|
directionButton.classList.add("btn-primary");
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.#to.onchange = () => {
|
this.#to.onchange = () => {
|
||||||
this.#to.value = this.#to.value.trim();
|
this.#to.value = this.#to.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
this.validateTo();
|
this.validateTo();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -667,11 +667,11 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the summary according to the input in the tab plane.
|
* Updates the description according to the input in the tab plane.
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
updateDescription() {
|
||||||
let direction;
|
let direction;
|
||||||
for (const directionButton of this.#directionButtons) {
|
for (const directionButton of this.#directionButtons) {
|
||||||
if (directionButton.classList.contains("btn-primary")) {
|
if (directionButton.classList.contains("btn-primary")) {
|
||||||
@ -679,7 +679,7 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.editor.summary.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value;
|
this.editor.description.value = this.tag.value + "—" + this.#from.value + direction + this.#to.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -707,13 +707,13 @@ class GeneralTripTab extends TagTabPlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.editor.summary.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
const found = this.editor.description.value.match(/^([^—]+)—([^—→↔]+)([→↔])(.+?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -834,7 +834,7 @@ class BusTripTab extends TagTabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
@ -847,17 +847,17 @@ class BusTripTab extends TagTabPlane {
|
|||||||
this.#toError = document.getElementById(this.prefix + "-to-error")
|
this.#toError = document.getElementById(this.prefix + "-to-error")
|
||||||
this.#route.onchange = () => {
|
this.#route.onchange = () => {
|
||||||
this.#route.value = this.#route.value.trim();
|
this.#route.value = this.#route.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
this.validateRoute();
|
this.validateRoute();
|
||||||
};
|
};
|
||||||
this.#from.onchange = () => {
|
this.#from.onchange = () => {
|
||||||
this.#from.value = this.#from.value.trim();
|
this.#from.value = this.#from.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
this.validateFrom();
|
this.validateFrom();
|
||||||
};
|
};
|
||||||
this.#to.onchange = () => {
|
this.#to.onchange = () => {
|
||||||
this.#to.value = this.#to.value.trim();
|
this.#to.value = this.#to.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
this.validateTo();
|
this.validateTo();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -873,12 +873,12 @@ class BusTripTab extends TagTabPlane {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the summary according to the input in the tab plane.
|
* Updates the description according to the input in the tab plane.
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
updateDescription() {
|
||||||
this.editor.summary.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value;
|
this.editor.description.value = this.tag.value + "—" + this.#route.value + "—" + this.#from.value + "→" + this.#to.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -900,13 +900,13 @@ class BusTripTab extends TagTabPlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.editor.summary.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
const found = this.editor.description.value.match(/^([^—]+)—([^—]+)—([^—→]+)→(.+?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
||||||
if (found === null) {
|
if (found === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1001,7 +1001,7 @@ class RegularPaymentTab extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
@ -1033,9 +1033,9 @@ class RegularPaymentTab extends TabPlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
@ -1063,15 +1063,15 @@ class AnnotationTab extends TabPlane {
|
|||||||
/**
|
/**
|
||||||
* Constructs a tab plane.
|
* Constructs a tab plane.
|
||||||
*
|
*
|
||||||
* @param editor {SummaryEditor} the parent summary editor
|
* @param editor {DescriptionEditor} the parent description editor
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
constructor(editor) {
|
constructor(editor) {
|
||||||
super(editor);
|
super(editor);
|
||||||
this.editor.number.onchange = () => this.updateSummary();
|
this.editor.number.onchange = () => this.updateDescription();
|
||||||
this.editor.note.onchange = () => {
|
this.editor.note.onchange = () => {
|
||||||
this.editor.note.value = this.editor.note.value.trim();
|
this.editor.note.value = this.editor.note.value.trim();
|
||||||
this.updateSummary();
|
this.updateDescription();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,20 +1086,20 @@ class AnnotationTab extends TabPlane {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the summary according to the input in the tab plane.
|
* Updates the description according to the input in the tab plane.
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
updateSummary() {
|
updateDescription() {
|
||||||
const found = this.editor.summary.value.match(/^(.*?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
const found = this.editor.description.value.match(/^(.*?)(?:[*×]\d+)?(?:\([^()]+\))?$/);
|
||||||
if (found !== null) {
|
if (found !== null) {
|
||||||
this.editor.summary.value = found[1];
|
this.editor.description.value = found[1];
|
||||||
}
|
}
|
||||||
if (parseInt(this.editor.number.value) > 1) {
|
if (parseInt(this.editor.number.value) > 1) {
|
||||||
this.editor.summary.value = this.editor.summary.value + "×" + this.editor.number.value;
|
this.editor.description.value = this.editor.description.value + "×" + this.editor.number.value;
|
||||||
}
|
}
|
||||||
if (this.editor.note.value !== "") {
|
if (this.editor.note.value !== "") {
|
||||||
this.editor.summary.value = this.editor.summary.value + "(" + this.editor.note.value + ")";
|
this.editor.description.value = this.editor.description.value + "(" + this.editor.note.value + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1114,25 +1114,25 @@ class AnnotationTab extends TabPlane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the tab plane with the summary input.
|
* Populates the tab plane with the description input.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if the summary input matches this tab, or false otherwise
|
* @return {boolean} true if the description input matches this tab, or false otherwise
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
populate() {
|
populate() {
|
||||||
const found = this.editor.summary.value.match(/^(.*?)(?:[*×](\d+))?(?:\(([^()]+)\))?$/);
|
const found = this.editor.description.value.match(/^(.*?)(?:[*×](\d+))?(?:\(([^()]+)\))?$/);
|
||||||
this.editor.summary.value = found[1];
|
this.editor.description.value = found[1];
|
||||||
if (found[2] === undefined || parseInt(found[2]) === 1) {
|
if (found[2] === undefined || parseInt(found[2]) === 1) {
|
||||||
this.editor.number.value = "";
|
this.editor.number.value = "";
|
||||||
} else {
|
} else {
|
||||||
this.editor.number.value = found[2];
|
this.editor.number.value = found[2];
|
||||||
this.editor.summary.value = this.editor.summary.value + "×" + this.editor.number.value;
|
this.editor.description.value = this.editor.description.value + "×" + this.editor.number.value;
|
||||||
}
|
}
|
||||||
if (found[3] === undefined) {
|
if (found[3] === undefined) {
|
||||||
this.editor.note.value = "";
|
this.editor.note.value = "";
|
||||||
} else {
|
} else {
|
||||||
this.editor.note.value = found[3];
|
this.editor.note.value = found[3];
|
||||||
this.editor.summary.value = this.editor.summary.value + "(" + this.editor.note.value + ")";
|
this.editor.description.value = this.editor.description.value + "(" + this.editor.note.value + ")";
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -244,10 +244,10 @@ class OriginalLineItem {
|
|||||||
accountText;
|
accountText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary
|
* The description
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
summary;
|
description;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The net balance, without the offset amounts on the form
|
* The net balance, without the offset amounts on the form
|
||||||
@ -294,7 +294,7 @@ class OriginalLineItem {
|
|||||||
this.#currencyCode = element.dataset.currencyCode;
|
this.#currencyCode = element.dataset.currencyCode;
|
||||||
this.accountCode = element.dataset.accountCode;
|
this.accountCode = element.dataset.accountCode;
|
||||||
this.accountText = element.dataset.accountText;
|
this.accountText = element.dataset.accountText;
|
||||||
this.summary = element.dataset.summary;
|
this.description = element.dataset.description;
|
||||||
this.bareNetBalance = new Decimal(element.dataset.netBalance);
|
this.bareNetBalance = new Decimal(element.dataset.netBalance);
|
||||||
this.netBalance = this.bareNetBalance;
|
this.netBalance = this.bareNetBalance;
|
||||||
this.netBalanceText = document.getElementById("accounting-original-line-item-selector-option-" + this.id + "-net-balance");
|
this.netBalanceText = document.getElementById("accounting-original-line-item-selector-option-" + this.id + "-net-balance");
|
||||||
|
@ -808,16 +808,16 @@ class LineItemSubForm {
|
|||||||
#accountText;
|
#accountText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary
|
* The description
|
||||||
* @type {HTMLInputElement}
|
* @type {HTMLInputElement}
|
||||||
*/
|
*/
|
||||||
#summary;
|
#description;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The text display of the summary
|
* The text display of the description
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#summaryText;
|
#descriptionText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ID of the original line item
|
* The ID of the original line item
|
||||||
@ -873,8 +873,8 @@ class LineItemSubForm {
|
|||||||
this.no = document.getElementById(this.#prefix + "-no");
|
this.no = document.getElementById(this.#prefix + "-no");
|
||||||
this.#accountCode = document.getElementById(this.#prefix + "-account-code");
|
this.#accountCode = document.getElementById(this.#prefix + "-account-code");
|
||||||
this.#accountText = document.getElementById(this.#prefix + "-account-text");
|
this.#accountText = document.getElementById(this.#prefix + "-account-text");
|
||||||
this.#summary = document.getElementById(this.#prefix + "-summary");
|
this.#description = document.getElementById(this.#prefix + "-description");
|
||||||
this.#summaryText = document.getElementById(this.#prefix + "-summary-text");
|
this.#descriptionText = document.getElementById(this.#prefix + "-description-text");
|
||||||
this.#originalLineItemId = document.getElementById(this.#prefix + "-original-line-item-id");
|
this.#originalLineItemId = document.getElementById(this.#prefix + "-original-line-item-id");
|
||||||
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item-text");
|
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item-text");
|
||||||
this.#offsets = document.getElementById(this.#prefix + "-offsets");
|
this.#offsets = document.getElementById(this.#prefix + "-offsets");
|
||||||
@ -925,12 +925,12 @@ class LineItemSubForm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the summary.
|
* Returns the description.
|
||||||
*
|
*
|
||||||
* @return {string|null} the summary
|
* @return {string|null} the description
|
||||||
*/
|
*/
|
||||||
getSummary() {
|
getDescription() {
|
||||||
return this.#summary.value === ""? null: this.#summary.value;
|
return this.#description.value === ""? null: this.#description.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1014,8 +1014,8 @@ class LineItemSubForm {
|
|||||||
this.#accountCode.value = editor.accountCode === null? "": editor.accountCode;
|
this.#accountCode.value = editor.accountCode === null? "": editor.accountCode;
|
||||||
this.#accountCode.dataset.text = editor.accountText === null? "": editor.accountText;
|
this.#accountCode.dataset.text = editor.accountText === null? "": editor.accountText;
|
||||||
this.#accountText.innerText = editor.accountText === null? "": editor.accountText;
|
this.#accountText.innerText = editor.accountText === null? "": editor.accountText;
|
||||||
this.#summary.value = editor.summary === null? "": editor.summary;
|
this.#description.value = editor.description === null? "": editor.description;
|
||||||
this.#summaryText.innerText = editor.summary === null? "": editor.summary;
|
this.#descriptionText.innerText = editor.description === null? "": editor.description;
|
||||||
this.#amount.value = editor.amount;
|
this.#amount.value = editor.amount;
|
||||||
this.#amountText.innerText = formatDecimal(new Decimal(editor.amount));
|
this.#amountText.innerText = formatDecimal(new Decimal(editor.amount));
|
||||||
this.validate();
|
this.validate();
|
||||||
|
@ -89,22 +89,22 @@ class VoucherLineItemEditor {
|
|||||||
#originalLineItemDelete;
|
#originalLineItemDelete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control of the summary
|
* The control of the description
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#summaryControl;
|
#descriptionControl;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary
|
* The description
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#summaryText;
|
#descriptionText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The error message of the summary
|
* The error message of the description
|
||||||
* @type {HTMLDivElement}
|
* @type {HTMLDivElement}
|
||||||
*/
|
*/
|
||||||
#summaryError;
|
#descriptionError;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The control of the account
|
* The control of the account
|
||||||
@ -185,10 +185,10 @@ class VoucherLineItemEditor {
|
|||||||
accountText = null;
|
accountText = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary
|
* The description
|
||||||
* @type {string|null}
|
* @type {string|null}
|
||||||
*/
|
*/
|
||||||
summary = null;
|
description = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount
|
* The amount
|
||||||
@ -197,10 +197,10 @@ class VoucherLineItemEditor {
|
|||||||
amount = "";
|
amount = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The summary editors
|
* The description editors
|
||||||
* @type {{debit: SummaryEditor, credit: SummaryEditor}}
|
* @type {{debit: DescriptionEditor, credit: DescriptionEditor}}
|
||||||
*/
|
*/
|
||||||
#summaryEditors;
|
#descriptionEditors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The account selectors
|
* The account selectors
|
||||||
@ -228,20 +228,20 @@ class VoucherLineItemEditor {
|
|||||||
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item");
|
this.#originalLineItemText = document.getElementById(this.#prefix + "-original-line-item");
|
||||||
this.#originalLineItemError = document.getElementById(this.#prefix + "-original-line-item-error");
|
this.#originalLineItemError = document.getElementById(this.#prefix + "-original-line-item-error");
|
||||||
this.#originalLineItemDelete = document.getElementById(this.#prefix + "-original-line-item-delete");
|
this.#originalLineItemDelete = document.getElementById(this.#prefix + "-original-line-item-delete");
|
||||||
this.#summaryControl = document.getElementById(this.#prefix + "-summary-control");
|
this.#descriptionControl = document.getElementById(this.#prefix + "-description-control");
|
||||||
this.#summaryText = document.getElementById(this.#prefix + "-summary");
|
this.#descriptionText = document.getElementById(this.#prefix + "-description");
|
||||||
this.#summaryError = document.getElementById(this.#prefix + "-summary-error");
|
this.#descriptionError = document.getElementById(this.#prefix + "-description-error");
|
||||||
this.#accountControl = document.getElementById(this.#prefix + "-account-control");
|
this.#accountControl = document.getElementById(this.#prefix + "-account-control");
|
||||||
this.#accountText = document.getElementById(this.#prefix + "-account");
|
this.#accountText = document.getElementById(this.#prefix + "-account");
|
||||||
this.#accountError = document.getElementById(this.#prefix + "-account-error")
|
this.#accountError = document.getElementById(this.#prefix + "-account-error")
|
||||||
this.#amountInput = document.getElementById(this.#prefix + "-amount");
|
this.#amountInput = document.getElementById(this.#prefix + "-amount");
|
||||||
this.#amountError = document.getElementById(this.#prefix + "-amount-error");
|
this.#amountError = document.getElementById(this.#prefix + "-amount-error");
|
||||||
this.#summaryEditors = SummaryEditor.getInstances(this);
|
this.#descriptionEditors = DescriptionEditor.getInstances(this);
|
||||||
this.#accountSelectors = AccountSelector.getInstances(this);
|
this.#accountSelectors = AccountSelector.getInstances(this);
|
||||||
this.originalLineItemSelector = new OriginalLineItemSelector(this);
|
this.originalLineItemSelector = new OriginalLineItemSelector(this);
|
||||||
this.#originalLineItemControl.onclick = () => this.originalLineItemSelector.onOpen()
|
this.#originalLineItemControl.onclick = () => this.originalLineItemSelector.onOpen()
|
||||||
this.#originalLineItemDelete.onclick = () => this.clearOriginalLineItem();
|
this.#originalLineItemDelete.onclick = () => this.clearOriginalLineItem();
|
||||||
this.#summaryControl.onclick = () => this.#summaryEditors[this.side].onOpen();
|
this.#descriptionControl.onclick = () => this.#descriptionEditors[this.side].onOpen();
|
||||||
this.#accountControl.onclick = () => this.#accountSelectors[this.side].onOpen();
|
this.#accountControl.onclick = () => this.#accountSelectors[this.side].onOpen();
|
||||||
this.#amountInput.onchange = () => this.#validateAmount();
|
this.#amountInput.onchange = () => this.#validateAmount();
|
||||||
this.#element.onsubmit = () => {
|
this.#element.onsubmit = () => {
|
||||||
@ -270,14 +270,14 @@ class VoucherLineItemEditor {
|
|||||||
this.originalLineItemDate = originalLineItem.date;
|
this.originalLineItemDate = originalLineItem.date;
|
||||||
this.originalLineItemText = originalLineItem.text;
|
this.originalLineItemText = originalLineItem.text;
|
||||||
this.#originalLineItemText.innerText = originalLineItem.text;
|
this.#originalLineItemText.innerText = originalLineItem.text;
|
||||||
this.#setEnableSummaryAccount(false);
|
this.#setEnableDescriptionAccount(false);
|
||||||
if (originalLineItem.summary === "") {
|
if (originalLineItem.description === "") {
|
||||||
this.#summaryControl.classList.remove("accounting-not-empty");
|
this.#descriptionControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#summaryControl.classList.add("accounting-not-empty");
|
this.#descriptionControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.summary = originalLineItem.summary === ""? null: originalLineItem.summary;
|
this.description = originalLineItem.description === ""? null: originalLineItem.description;
|
||||||
this.#summaryText.innerText = originalLineItem.summary;
|
this.#descriptionText.innerText = originalLineItem.description;
|
||||||
this.#accountControl.classList.add("accounting-not-empty");
|
this.#accountControl.classList.add("accounting-not-empty");
|
||||||
this.accountCode = originalLineItem.accountCode;
|
this.accountCode = originalLineItem.accountCode;
|
||||||
this.accountText = originalLineItem.accountText;
|
this.accountText = originalLineItem.accountText;
|
||||||
@ -300,7 +300,7 @@ class VoucherLineItemEditor {
|
|||||||
this.originalLineItemDate = null;
|
this.originalLineItemDate = null;
|
||||||
this.originalLineItemText = null;
|
this.originalLineItemText = null;
|
||||||
this.#originalLineItemText.innerText = "";
|
this.#originalLineItemText.innerText = "";
|
||||||
this.#setEnableSummaryAccount(true);
|
this.#setEnableDescriptionAccount(true);
|
||||||
this.#accountControl.classList.remove("accounting-not-empty");
|
this.#accountControl.classList.remove("accounting-not-empty");
|
||||||
this.accountCode = null;
|
this.accountCode = null;
|
||||||
this.accountText = null;
|
this.accountText = null;
|
||||||
@ -318,38 +318,38 @@ class VoucherLineItemEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the summary from the summary editor.
|
* Saves the description from the description editor.
|
||||||
*
|
*
|
||||||
* @param summary {string} the summary
|
* @param description {string} the description
|
||||||
*/
|
*/
|
||||||
saveSummary(summary) {
|
saveDescription(description) {
|
||||||
if (summary === "") {
|
if (description === "") {
|
||||||
this.#summaryControl.classList.remove("accounting-not-empty");
|
this.#descriptionControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#summaryControl.classList.add("accounting-not-empty");
|
this.#descriptionControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.summary = summary === ""? null: summary;
|
this.description = description === ""? null: description;
|
||||||
this.#summaryText.innerText = summary;
|
this.#descriptionText.innerText = description;
|
||||||
this.#validateSummary();
|
this.#validateDescription();
|
||||||
bootstrap.Modal.getOrCreateInstance(this.#modal).show();
|
bootstrap.Modal.getOrCreateInstance(this.#modal).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the summary with the suggested account from the summary editor.
|
* Saves the description with the suggested account from the description editor.
|
||||||
*
|
*
|
||||||
* @param summary {string} the summary
|
* @param description {string} the description
|
||||||
* @param accountCode {string} the account code
|
* @param accountCode {string} the account code
|
||||||
* @param accountText {string} the account text
|
* @param accountText {string} the account text
|
||||||
* @param isAccountNeedOffset {boolean} true if the line items in the account need offset, or false otherwise
|
* @param isAccountNeedOffset {boolean} true if the line items in the account need offset, or false otherwise
|
||||||
*/
|
*/
|
||||||
saveSummaryWithAccount(summary, accountCode, accountText, isAccountNeedOffset) {
|
saveDescriptionWithAccount(description, accountCode, accountText, isAccountNeedOffset) {
|
||||||
this.isNeedOffset = isAccountNeedOffset;
|
this.isNeedOffset = isAccountNeedOffset;
|
||||||
this.#accountControl.classList.add("accounting-not-empty");
|
this.#accountControl.classList.add("accounting-not-empty");
|
||||||
this.accountCode = accountCode;
|
this.accountCode = accountCode;
|
||||||
this.accountText = accountText;
|
this.accountText = accountText;
|
||||||
this.#accountText.innerText = accountText;
|
this.#accountText.innerText = accountText;
|
||||||
this.#validateAccount();
|
this.#validateAccount();
|
||||||
this.saveSummary(summary)
|
this.saveDescription(description)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -389,7 +389,7 @@ class VoucherLineItemEditor {
|
|||||||
#validate() {
|
#validate() {
|
||||||
let isValid = true;
|
let isValid = true;
|
||||||
isValid = this.#validateOriginalLineItem() && isValid;
|
isValid = this.#validateOriginalLineItem() && isValid;
|
||||||
isValid = this.#validateSummary() && isValid;
|
isValid = this.#validateDescription() && isValid;
|
||||||
isValid = this.#validateAccount() && isValid;
|
isValid = this.#validateAccount() && isValid;
|
||||||
isValid = this.#validateAmount() && isValid
|
isValid = this.#validateAmount() && isValid
|
||||||
return isValid;
|
return isValid;
|
||||||
@ -408,14 +408,14 @@ class VoucherLineItemEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the summary.
|
* Validates the description.
|
||||||
*
|
*
|
||||||
* @return {boolean} true if valid, or false otherwise
|
* @return {boolean} true if valid, or false otherwise
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
#validateSummary() {
|
#validateDescription() {
|
||||||
this.#summaryText.classList.remove("is-invalid");
|
this.#descriptionText.classList.remove("is-invalid");
|
||||||
this.#summaryError.innerText = "";
|
this.#descriptionError.innerText = "";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,12 +492,12 @@ class VoucherLineItemEditor {
|
|||||||
this.originalLineItemDate = null;
|
this.originalLineItemDate = null;
|
||||||
this.originalLineItemText = null;
|
this.originalLineItemText = null;
|
||||||
this.#originalLineItemText.innerText = "";
|
this.#originalLineItemText.innerText = "";
|
||||||
this.#setEnableSummaryAccount(true);
|
this.#setEnableDescriptionAccount(true);
|
||||||
this.#summaryControl.classList.remove("accounting-not-empty");
|
this.#descriptionControl.classList.remove("accounting-not-empty");
|
||||||
this.#summaryControl.classList.remove("is-invalid");
|
this.#descriptionControl.classList.remove("is-invalid");
|
||||||
this.summary = null;
|
this.description = null;
|
||||||
this.#summaryText.innerText = ""
|
this.#descriptionText.innerText = ""
|
||||||
this.#summaryError.innerText = ""
|
this.#descriptionError.innerText = ""
|
||||||
this.#accountControl.classList.remove("accounting-not-empty");
|
this.#accountControl.classList.remove("accounting-not-empty");
|
||||||
this.#accountControl.classList.remove("is-invalid");
|
this.#accountControl.classList.remove("is-invalid");
|
||||||
this.accountCode = null;
|
this.accountCode = null;
|
||||||
@ -532,14 +532,14 @@ class VoucherLineItemEditor {
|
|||||||
this.#originalLineItemContainer.classList.remove("d-none");
|
this.#originalLineItemContainer.classList.remove("d-none");
|
||||||
this.#originalLineItemControl.classList.add("accounting-not-empty");
|
this.#originalLineItemControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.#setEnableSummaryAccount(!lineItem.isMatched && this.originalLineItemId === null);
|
this.#setEnableDescriptionAccount(!lineItem.isMatched && this.originalLineItemId === null);
|
||||||
this.summary = lineItem.getSummary();
|
this.description = lineItem.getDescription();
|
||||||
if (this.summary === null) {
|
if (this.description === null) {
|
||||||
this.#summaryControl.classList.remove("accounting-not-empty");
|
this.#descriptionControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
this.#summaryControl.classList.add("accounting-not-empty");
|
this.#descriptionControl.classList.add("accounting-not-empty");
|
||||||
}
|
}
|
||||||
this.#summaryText.innerText = this.summary === null? "": this.summary;
|
this.#descriptionText.innerText = this.description === null? "": this.description;
|
||||||
if (lineItem.getAccountCode() === null) {
|
if (lineItem.getAccountCode() === null) {
|
||||||
this.#accountControl.classList.remove("accounting-not-empty");
|
this.#accountControl.classList.remove("accounting-not-empty");
|
||||||
} else {
|
} else {
|
||||||
@ -568,25 +568,25 @@ class VoucherLineItemEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the enable status of the summary and account.
|
* Sets the enable status of the description and account.
|
||||||
*
|
*
|
||||||
* @param isEnabled {boolean} true to enable, or false otherwise
|
* @param isEnabled {boolean} true to enable, or false otherwise
|
||||||
*/
|
*/
|
||||||
#setEnableSummaryAccount(isEnabled) {
|
#setEnableDescriptionAccount(isEnabled) {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
this.#summaryControl.dataset.bsToggle = "modal";
|
this.#descriptionControl.dataset.bsToggle = "modal";
|
||||||
this.#summaryControl.dataset.bsTarget = "#accounting-summary-editor-" + this.#sideSubForm.side + "-modal";
|
this.#descriptionControl.dataset.bsTarget = "#accounting-description-editor-" + this.#sideSubForm.side + "-modal";
|
||||||
this.#summaryControl.classList.remove("accounting-disabled");
|
this.#descriptionControl.classList.remove("accounting-disabled");
|
||||||
this.#summaryControl.classList.add("accounting-clickable");
|
this.#descriptionControl.classList.add("accounting-clickable");
|
||||||
this.#accountControl.dataset.bsToggle = "modal";
|
this.#accountControl.dataset.bsToggle = "modal";
|
||||||
this.#accountControl.dataset.bsTarget = "#accounting-account-selector-" + this.#sideSubForm.side + "-modal";
|
this.#accountControl.dataset.bsTarget = "#accounting-account-selector-" + this.#sideSubForm.side + "-modal";
|
||||||
this.#accountControl.classList.remove("accounting-disabled");
|
this.#accountControl.classList.remove("accounting-disabled");
|
||||||
this.#accountControl.classList.add("accounting-clickable");
|
this.#accountControl.classList.add("accounting-clickable");
|
||||||
} else {
|
} else {
|
||||||
this.#summaryControl.dataset.bsToggle = "";
|
this.#descriptionControl.dataset.bsToggle = "";
|
||||||
this.#summaryControl.dataset.bsTarget = "";
|
this.#descriptionControl.dataset.bsTarget = "";
|
||||||
this.#summaryControl.classList.add("accounting-disabled");
|
this.#descriptionControl.classList.add("accounting-disabled");
|
||||||
this.#summaryControl.classList.remove("accounting-clickable");
|
this.#descriptionControl.classList.remove("accounting-clickable");
|
||||||
this.#accountControl.dataset.bsToggle = "";
|
this.#accountControl.dataset.bsToggle = "";
|
||||||
this.#accountControl.dataset.bsTarget = "";
|
this.#accountControl.dataset.bsTarget = "";
|
||||||
this.#accountControl.classList.add("accounting-disabled");
|
this.#accountControl.classList.add("accounting-disabled");
|
||||||
|
@ -21,7 +21,7 @@ First written: 2023/3/8
|
|||||||
#}
|
#}
|
||||||
<div>{{ line_item.date|accounting_format_date }}</div>
|
<div>{{ line_item.date|accounting_format_date }}</div>
|
||||||
<div>{{ line_item.account.title|title }}</div>
|
<div>{{ line_item.account.title|title }}</div>
|
||||||
<div>{{ line_item.summary|accounting_default }}</div>
|
<div>{{ line_item.description|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.income|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.income|accounting_format_amount|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.expense|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.expense|accounting_format_amount|accounting_default }}</div>
|
||||||
<div class="accounting-amount {% if line_item.balance < 0 %} text-danger {% endif %}">{{ line_item.balance|accounting_report_format_amount }}</div>
|
<div class="accounting-amount {% if line_item.balance < 0 %} text-danger {% endif %}">{{ line_item.balance|accounting_report_format_amount }}</div>
|
||||||
|
@ -30,8 +30,8 @@ First written: 2023/3/5
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if line_item.summary %}
|
{% if line_item.description %}
|
||||||
<div>{{ line_item.summary }}</div>
|
<div>{{ line_item.description }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ Author: imacat@mail.imacat.idv.tw (imacat)
|
|||||||
First written: 2023/3/8
|
First written: 2023/3/8
|
||||||
#}
|
#}
|
||||||
<div>{{ line_item.date|accounting_format_date }}</div>
|
<div>{{ line_item.date|accounting_format_date }}</div>
|
||||||
<div>{{ line_item.summary|accounting_default }}</div>
|
<div>{{ line_item.description|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
||||||
{% if report.account.is_real %}
|
{% if report.account.is_real %}
|
||||||
|
@ -25,8 +25,8 @@ First written: 2023/3/5
|
|||||||
{{ line_item.date|accounting_format_date }}
|
{{ line_item.date|accounting_format_date }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if line_item.summary %}
|
{% if line_item.description %}
|
||||||
<div>{{ line_item.summary }}</div>
|
<div>{{ line_item.description }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ First written: 2023/3/5
|
|||||||
<div class="accounting-report-table-row">
|
<div class="accounting-report-table-row">
|
||||||
<div>{{ A_("Date") }}</div>
|
<div>{{ A_("Date") }}</div>
|
||||||
<div>{{ A_("Account") }}</div>
|
<div>{{ A_("Account") }}</div>
|
||||||
<div>{{ A_("Summary") }}</div>
|
<div>{{ A_("Description") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Income") }}</div>
|
<div class="accounting-amount">{{ A_("Income") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Expense") }}</div>
|
<div class="accounting-amount">{{ A_("Expense") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Balance") }}</div>
|
<div class="accounting-amount">{{ A_("Balance") }}</div>
|
||||||
|
@ -53,7 +53,7 @@ First written: 2023/3/4
|
|||||||
<div>{{ A_("Date") }}</div>
|
<div>{{ A_("Date") }}</div>
|
||||||
<div>{{ A_("Currency") }}</div>
|
<div>{{ A_("Currency") }}</div>
|
||||||
<div>{{ A_("Account") }}</div>
|
<div>{{ A_("Account") }}</div>
|
||||||
<div>{{ A_("Summary") }}</div>
|
<div>{{ A_("Description") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -67,7 +67,7 @@ First written: 2023/3/4
|
|||||||
<span class="d-none d-md-inline">{{ line_item.account.code }}</span>
|
<span class="d-none d-md-inline">{{ line_item.account.code }}</span>
|
||||||
{{ line_item.account.title|title }}
|
{{ line_item.account.title|title }}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ line_item.summary|accounting_default }}</div>
|
<div>{{ line_item.description|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
||||||
</a>
|
</a>
|
||||||
@ -87,8 +87,8 @@ First written: 2023/3/4
|
|||||||
<span class="badge rounded-pill bg-info">{{ line_item.currency.code }}</span>
|
<span class="badge rounded-pill bg-info">{{ line_item.currency.code }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if line_item.summary is not none %}
|
{% if line_item.description is not none %}
|
||||||
<div>{{ line_item.summary }}</div>
|
<div>{{ line_item.description }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ First written: 2023/3/5
|
|||||||
<div class="accounting-report-table-header">
|
<div class="accounting-report-table-header">
|
||||||
<div class="accounting-report-table-row">
|
<div class="accounting-report-table-row">
|
||||||
<div>{{ A_("Date") }}</div>
|
<div>{{ A_("Date") }}</div>
|
||||||
<div>{{ A_("Summary") }}</div>
|
<div>{{ A_("Description") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
||||||
{% if report.account.is_real %}
|
{% if report.account.is_real %}
|
||||||
|
@ -50,7 +50,7 @@ First written: 2023/3/8
|
|||||||
<div>{{ A_("Date") }}</div>
|
<div>{{ A_("Date") }}</div>
|
||||||
<div>{{ A_("Currency") }}</div>
|
<div>{{ A_("Currency") }}</div>
|
||||||
<div>{{ A_("Account") }}</div>
|
<div>{{ A_("Account") }}</div>
|
||||||
<div>{{ A_("Summary") }}</div>
|
<div>{{ A_("Description") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
<div class="accounting-amount">{{ A_("Debit") }}</div>
|
||||||
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
<div class="accounting-amount">{{ A_("Credit") }}</div>
|
||||||
</div>
|
</div>
|
||||||
@ -64,7 +64,7 @@ First written: 2023/3/8
|
|||||||
<span class="d-none d-md-inline">{{ line_item.account.code }}</span>
|
<span class="d-none d-md-inline">{{ line_item.account.code }}</span>
|
||||||
{{ line_item.account.title|title }}
|
{{ line_item.account.title|title }}
|
||||||
</div>
|
</div>
|
||||||
<div>{{ line_item.summary|accounting_default }}</div>
|
<div>{{ line_item.description|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.debit|accounting_format_amount|accounting_default }}</div>
|
||||||
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
<div class="accounting-amount">{{ line_item.credit|accounting_format_amount|accounting_default }}</div>
|
||||||
</a>
|
</a>
|
||||||
@ -84,8 +84,8 @@ First written: 2023/3/8
|
|||||||
<span class="badge rounded-pill bg-info">{{ line_item.currency.code }}</span>
|
<span class="badge rounded-pill bg-info">{{ line_item.currency.code }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% if line_item.summary is not none %}
|
{% if line_item.description is not none %}
|
||||||
<div>{{ line_item.summary }}</div>
|
<div>{{ line_item.description }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -49,25 +49,25 @@ First written: 2023/2/25
|
|||||||
{% with currency_index = currency_index,
|
{% with currency_index = currency_index,
|
||||||
side = "debit",
|
side = "debit",
|
||||||
line_item_index = loop.index,
|
line_item_index = loop.index,
|
||||||
line_item_id = line_item_form.eid.data,
|
line_item_id = line_item_form.form.eid.data,
|
||||||
only_one_line_item_form = debit_forms|length == 1,
|
only_one_line_item_form = debit_forms|length == 1,
|
||||||
account_code_data = line_item_form.account_code.data|accounting_default,
|
account_code_data = line_item_form.form.account_code.data|accounting_default,
|
||||||
account_code_error = line_item_form.account_code.errors,
|
account_code_error = line_item_form.form.account_code.errors,
|
||||||
account_text = line_item_form.account_text,
|
account_text = line_item_form.form.account_text,
|
||||||
summary_data = line_item_form.summary.data|accounting_default,
|
description_data = line_item_form.form.description.data|accounting_default,
|
||||||
summary_errors = line_item_form.summary.errors,
|
description_errors = line_item_form.form.description.errors,
|
||||||
original_line_item_id_data = line_item_form.original_line_item_id.data|accounting_default,
|
original_line_item_id_data = line_item_form.form.original_line_item_id.data|accounting_default,
|
||||||
original_line_item_date = line_item_form.original_line_item_date|accounting_default,
|
original_line_item_date = line_item_form.form.original_line_item_date|accounting_default,
|
||||||
original_line_item_text = line_item_form.original_line_item_text|accounting_default,
|
original_line_item_text = line_item_form.form.original_line_item_text|accounting_default,
|
||||||
is_need_offset = line_item_form.is_need_offset,
|
is_need_offset = line_item_form.form.is_need_offset,
|
||||||
offset_items = line_item_form.offsets,
|
offset_items = line_item_form.form.offsets,
|
||||||
offset_total = line_item_form.offset_total|accounting_default("0"),
|
offset_total = line_item_form.form.offset_total|accounting_default("0"),
|
||||||
net_balance_data = line_item_form.net_balance,
|
net_balance_data = line_item_form.form.net_balance,
|
||||||
net_balance_text = line_item_form.net_balance|accounting_format_amount,
|
net_balance_text = line_item_form.form.net_balance|accounting_format_amount,
|
||||||
amount_data = line_item_form.amount.data|accounting_voucher_format_amount_input,
|
amount_data = line_item_form.form.amount.data|accounting_voucher_format_amount_input,
|
||||||
amount_errors = line_item_form.amount.errors,
|
amount_errors = line_item_form.form.amount.errors,
|
||||||
amount_text = line_item_form.amount.data|accounting_format_amount,
|
amount_text = line_item_form.form.amount.data|accounting_format_amount,
|
||||||
line_item_errors = line_item_form.all_errors %}
|
line_item_errors = line_item_form.form.all_errors %}
|
||||||
{% include "accounting/voucher/include/form-line-item.html" %}
|
{% include "accounting/voucher/include/form-line-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -47,8 +47,8 @@ First written: 2023/2/25
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_editor = form.summary_editor.debit %}
|
{% with description_editor = form.description_editor.debit %}
|
||||||
{% include "accounting/voucher/include/summary-editor-modal.html" %}
|
{% include "accounting/voucher/include/description-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with side = "debit",
|
{% with side = "debit",
|
||||||
account_options = form.debit_account_options %}
|
account_options = form.debit_account_options %}
|
||||||
|
@ -0,0 +1,193 @@
|
|||||||
|
{#
|
||||||
|
The Mia! Accounting Flask Project
|
||||||
|
description-editor-modal.html: The modal of the description 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-description-editor-{{ description_editor.side }}" class="accounting-description-editor" data-side="{{ description_editor.side }}">
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-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-description-editor-{{ description_editor.side }}-modal-label">
|
||||||
|
<label for="accounting-description-editor-{{ description_editor.side }}-description">{{ A_("Description") }}</label>
|
||||||
|
</h1>
|
||||||
|
<button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="d-flex justify-content-between mb-3">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-description" class="form-control" type="text" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-modal-label">
|
||||||
|
<button id="accounting-description-editor-{{ description_editor.side }}-offset" class="btn btn-primary text-nowrap ms-2" type="button" data-bs-toggle="modal" data-bs-target="#accounting-original-line-item-selector-modal">
|
||||||
|
{{ A_("Offset...") }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# Tab navigation #}
|
||||||
|
<ul class="nav nav-tabs mb-2">
|
||||||
|
<li class="nav-item">
|
||||||
|
<span id="accounting-description-editor-{{ description_editor.side }}-general-tab" class="nav-link active accounting-clickable" aria-current="page">
|
||||||
|
{{ A_("General") }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<span id="accounting-description-editor-{{ description_editor.side }}-travel-tab" class="nav-link accounting-clickable" aria-current="false">
|
||||||
|
{{ A_("Travel") }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<span id="accounting-description-editor-{{ description_editor.side }}-bus-tab" class="nav-link accounting-clickable" aria-current="false">
|
||||||
|
{{ A_("Bus") }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<span id="accounting-description-editor-{{ description_editor.side }}-regular-tab" class="nav-link accounting-clickable" aria-current="false">
|
||||||
|
{{ A_("Regular") }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<span id="accounting-description-editor-{{ description_editor.side }}-annotation-tab" class="nav-link accounting-clickable" aria-current="false">
|
||||||
|
{{ A_("Annotation") }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{# A general description with a tag #}
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-general-page" aria-current="page" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-general-tab">
|
||||||
|
<div class="form-floating mb-2">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-general-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-general-tag">{{ A_("Tag") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-general-tag-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% for tag in description_editor.general.tags %}
|
||||||
|
<button class="btn btn-outline-primary accounting-description-editor-{{ description_editor.side }}-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-description-editor-{{ description_editor.side }}-travel-page" class="d-none" aria-current="false" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-travel-tab">
|
||||||
|
<div class="form-floating mb-2">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-travel-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-travel-tag">{{ A_("Tag") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-travel-tag-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% for tag in description_editor.travel.tags %}
|
||||||
|
<button class="btn btn-outline-primary accounting-description-editor-{{ description_editor.side }}-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-description-editor-{{ description_editor.side }}-travel-from" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-travel-from">{{ A_("From") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-travel-from-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group-vertical ms-1 me-1">
|
||||||
|
<button class="btn btn-primary accounting-description-editor-{{ description_editor.side }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button>
|
||||||
|
<button class="btn btn-outline-primary accounting-description-editor-{{ description_editor.side }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-travel-to" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-travel-to">{{ A_("To") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-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-description-editor-{{ description_editor.side }}-bus-page" class="d-none" aria-current="false" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-bus-tab">
|
||||||
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<div class="form-floating me-2">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-bus-tag" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-bus-tag">{{ A_("Tag") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-bus-tag-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-bus-route" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-bus-route">{{ A_("Route") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-bus-route-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% for tag in description_editor.bus.tags %}
|
||||||
|
<button class="btn btn-outline-primary accounting-description-editor-{{ description_editor.side }}-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-description-editor-{{ description_editor.side }}-bus-from" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-bus-from">{{ A_("From") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-bus-from-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
<div class="form-floating">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-bus-to" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-bus-to">{{ A_("To") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-bus-to-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# A regular income or payment #}
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-regular-page" class="d-none" aria-current="false" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-regular-tab">
|
||||||
|
{# TODO: To be done #}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# The annotation #}
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-annotation-page" class="d-none" aria-current="false" aria-labelledby="accounting-description-editor-{{ description_editor.side }}-annotation-tab">
|
||||||
|
<div class="form-floating">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-annotation-number" class="form-control" type="number" min="1" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-annotation-number">{{ A_("The number of items") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-annotation-number-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mt-2">
|
||||||
|
<input id="accounting-description-editor-{{ description_editor.side }}-annotation-note" class="form-control" type="text" value="" placeholder=" ">
|
||||||
|
<label class="form-label" for="accounting-description-editor-{{ description_editor.side }}-annotation-note">{{ A_("Note") }}</label>
|
||||||
|
<div id="accounting-description-editor-{{ description_editor.side }}-annotation-note-error" class="invalid-feedback"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# The suggested accounts #}
|
||||||
|
<div class="mt-3">
|
||||||
|
{% for account in description_editor.accounts %}
|
||||||
|
<button class="btn btn-outline-primary d-none accounting-description-editor-{{ description_editor.side }}-account {% if account.is_need_offset %} accounting-account-is-need-offset {% endif %}" 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-line-item-editor-modal">{{ A_("Cancel") }}</button>
|
||||||
|
<button id="accounting-description-editor-{{ description_editor.side }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
@ -25,8 +25,8 @@ First written: 2023/3/14
|
|||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<div>
|
<div>
|
||||||
<div class="small">{{ line_item.account }}</div>
|
<div class="small">{{ line_item.account }}</div>
|
||||||
{% if line_item.summary is not none %}
|
{% if line_item.description is not none %}
|
||||||
<div>{{ line_item.summary }}</div>
|
<div>{{ line_item.description }}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if line_item.original_line_item %}
|
{% if line_item.original_line_item %}
|
||||||
<div class="fst-italic small accounting-original-line-item">
|
<div class="fst-italic small accounting-original-line-item">
|
||||||
|
@ -27,13 +27,13 @@ First written: 2023/2/25
|
|||||||
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-no" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-no" value="{{ line_item_index }}">
|
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-no" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-no" value="{{ line_item_index }}">
|
||||||
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original-line-item-id" class="accounting-original-line-item-id" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original_line_item_id" value="{{ original_line_item_id_data }}" data-date="{{ original_line_item_date }}" data-text="{{ original_line_item_text }}">
|
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original-line-item-id" class="accounting-original-line-item-id" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original_line_item_id" value="{{ original_line_item_id_data }}" data-date="{{ original_line_item_date }}" data-text="{{ original_line_item_text }}">
|
||||||
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account-code" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account_code" value="{{ account_code_data }}" data-text="{{ account_text }}">
|
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account-code" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account_code" value="{{ account_code_data }}" data-text="{{ account_text }}">
|
||||||
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-summary" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-summary" value="{{ summary_data }}">
|
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-description" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-description" value="{{ description_data }}">
|
||||||
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-amount" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-amount" value="{{ amount_data }}" data-min="{{ offset_total }}">
|
<input id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-amount" type="hidden" name="currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-amount" value="{{ amount_data }}" data-min="{{ offset_total }}">
|
||||||
<div class="accounting-line-item-content">
|
<div class="accounting-line-item-content">
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-control" class="form-control clickable d-flex justify-content-between {% if line_item_errors %} is-invalid {% endif %}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-control" class="form-control clickable d-flex justify-content-between {% if line_item_errors %} is-invalid {% endif %}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
||||||
<div>
|
<div>
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account-text" class="small">{{ account_text }}</div>
|
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-account-text" class="small">{{ account_text }}</div>
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-summary-text">{{ summary_data }}</div>
|
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-description-text">{{ description_data }}</div>
|
||||||
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original-line-item-text" class="fst-italic small accounting-original-line-item {% if not original_line_item_text %} d-none {% endif %}">
|
<div id="accounting-currency-{{ currency_index }}-{{ side }}-{{ line_item_index }}-original-line-item-text" class="fst-italic small accounting-original-line-item {% if not original_line_item_text %} d-none {% endif %}">
|
||||||
{% if original_line_item_text %}{{ A_("Offset %(item)s", item=original_line_item_text) }}{% endif %}
|
{% if original_line_item_text %}{{ A_("Offset %(item)s", item=original_line_item_text) }}{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,7 +27,7 @@ First written: 2023/2/26
|
|||||||
<script src="{{ url_for("accounting.static", filename="js/voucher-line-item-editor.js") }}"></script>
|
<script src="{{ url_for("accounting.static", filename="js/voucher-line-item-editor.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/original-line-item-selector.js") }}"></script>
|
<script src="{{ url_for("accounting.static", filename="js/original-line-item-selector.js") }}"></script>
|
||||||
<script src="{{ url_for("accounting.static", filename="js/summary-editor.js") }}"></script>
|
<script src="{{ url_for("accounting.static", filename="js/description-editor.js") }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -37,8 +37,8 @@ First written: 2023/2/25
|
|||||||
|
|
||||||
<ul id="accounting-original-line-item-selector-option-list" class="list-group accounting-selector-list">
|
<ul id="accounting-original-line-item-selector-option-list" class="list-group accounting-selector-list">
|
||||||
{% for line_item in form.original_line_item_options %}
|
{% for line_item in form.original_line_item_options %}
|
||||||
<li id="accounting-original-line-item-selector-option-{{ line_item.id }}" class="list-group-item d-flex justify-content-between accounting-clickable accounting-original-line-item-selector-option" data-id="{{ line_item.id }}" data-date="{{ line_item.voucher.date }}" data-side="{{ "debit" if line_item.is_debit else "credit" }}" data-currency-code="{{ line_item.currency.code }}" data-account-code="{{ line_item.account_code }}" data-account-text="{{ line_item.account }}" data-summary="{{ line_item.summary|accounting_default }}" data-net-balance="{{ line_item.net_balance|accounting_voucher_format_amount_input }}" data-text="{{ line_item }}" data-query-values="{{ line_item.query_values|tojson|forceescape }}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
<li id="accounting-original-line-item-selector-option-{{ line_item.id }}" class="list-group-item d-flex justify-content-between accounting-clickable accounting-original-line-item-selector-option" data-id="{{ line_item.id }}" data-date="{{ line_item.voucher.date }}" data-side="{{ "debit" if line_item.is_debit else "credit" }}" data-currency-code="{{ line_item.currency.code }}" data-account-code="{{ line_item.account_code }}" data-account-text="{{ line_item.account }}" data-description="{{ line_item.description|accounting_default }}" data-net-balance="{{ line_item.net_balance|accounting_voucher_format_amount_input }}" data-text="{{ line_item }}" data-query-values="{{ line_item.query_values|tojson|forceescape }}" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal">
|
||||||
<div>{{ line_item.voucher.date|accounting_format_date }} {{ line_item.summary|accounting_default }}</div>
|
<div>{{ line_item.voucher.date|accounting_format_date }} {{ line_item.description|accounting_default }}</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="badge bg-primary rounded-pill">
|
<span class="badge bg-primary rounded-pill">
|
||||||
<span id="accounting-original-line-item-selector-option-{{ line_item.id }}-net-balance">{{ line_item.net_balance|accounting_format_amount }}</span>
|
<span id="accounting-original-line-item-selector-option-{{ line_item.id }}-net-balance">{{ line_item.net_balance|accounting_format_amount }}</span>
|
||||||
|
@ -1,193 +0,0 @@
|
|||||||
{#
|
|
||||||
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.side }}" class="accounting-summary-editor" data-side="{{ summary_editor.side }}">
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-modal-label">
|
|
||||||
<label for="accounting-summary-editor-{{ summary_editor.side }}-summary">{{ A_("Summary") }}</label>
|
|
||||||
</h1>
|
|
||||||
<button class="btn-close" type="button" data-bs-toggle="modal" data-bs-target="#accounting-line-item-editor-modal" aria-label="{{ A_("Close") }}"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="d-flex justify-content-between mb-3">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-summary" class="form-control" type="text" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-modal-label">
|
|
||||||
<button id="accounting-summary-editor-{{ summary_editor.side }}-offset" class="btn btn-primary text-nowrap ms-2" type="button" data-bs-toggle="modal" data-bs-target="#accounting-original-line-item-selector-modal">
|
|
||||||
{{ A_("Offset...") }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Tab navigation #}
|
|
||||||
<ul class="nav nav-tabs mb-2">
|
|
||||||
<li class="nav-item">
|
|
||||||
<span id="accounting-summary-editor-{{ summary_editor.side }}-general-tab" class="nav-link active accounting-clickable" aria-current="page">
|
|
||||||
{{ A_("General") }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<span id="accounting-summary-editor-{{ summary_editor.side }}-travel-tab" class="nav-link accounting-clickable" aria-current="false">
|
|
||||||
{{ A_("Travel") }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<span id="accounting-summary-editor-{{ summary_editor.side }}-bus-tab" class="nav-link accounting-clickable" aria-current="false">
|
|
||||||
{{ A_("Bus") }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<span id="accounting-summary-editor-{{ summary_editor.side }}-regular-tab" class="nav-link accounting-clickable" aria-current="false">
|
|
||||||
{{ A_("Regular") }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<span id="accounting-summary-editor-{{ summary_editor.side }}-annotation-tab" class="nav-link accounting-clickable" aria-current="false">
|
|
||||||
{{ A_("Annotation") }}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{# A general summary with a tag #}
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-general-page" aria-current="page" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-general-tab">
|
|
||||||
<div class="form-floating mb-2">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-general-tag" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-general-tag">{{ A_("Tag") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-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.side }}-travel-page" class="d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-travel-tab">
|
|
||||||
<div class="form-floating mb-2">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-travel-tag" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-travel-tag">{{ A_("Tag") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-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.side }}-travel-from" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-travel-from">{{ A_("From") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-travel-direction accounting-default" type="button" tabindex="-1" data-arrow="→">→</button>
|
|
||||||
<button class="btn btn-outline-primary accounting-summary-editor-{{ summary_editor.side }}-travel-direction" type="button" tabindex="-1" data-arrow="↔">↔</button>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-travel-to" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-travel-to">{{ A_("To") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-bus-page" class="d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-bus-tab">
|
|
||||||
<div class="d-flex justify-content-between mb-2">
|
|
||||||
<div class="form-floating me-2">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-bus-tag" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-bus-tag">{{ A_("Tag") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-bus-tag-error" class="invalid-feedback"></div>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-bus-route" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-bus-route">{{ A_("Route") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-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.side }}-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.side }}-bus-from" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-bus-from">{{ A_("From") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-bus-from-error" class="invalid-feedback"></div>
|
|
||||||
</div>
|
|
||||||
<div class="form-floating">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-bus-to" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-bus-to">{{ A_("To") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-bus-to-error" class="invalid-feedback"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# A regular income or payment #}
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-regular-page" class="d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-regular-tab">
|
|
||||||
{# TODO: To be done #}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# The annotation #}
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-annotation-page" class="d-none" aria-current="false" aria-labelledby="accounting-summary-editor-{{ summary_editor.side }}-annotation-tab">
|
|
||||||
<div class="form-floating">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-annotation-number" class="form-control" type="number" min="1" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-annotation-number">{{ A_("The number of items") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-annotation-number-error" class="invalid-feedback"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-floating mt-2">
|
|
||||||
<input id="accounting-summary-editor-{{ summary_editor.side }}-annotation-note" class="form-control" type="text" value="" placeholder=" ">
|
|
||||||
<label class="form-label" for="accounting-summary-editor-{{ summary_editor.side }}-annotation-note">{{ A_("Note") }}</label>
|
|
||||||
<div id="accounting-summary-editor-{{ summary_editor.side }}-annotation-note-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.side }}-account {% if account.is_need_offset %} accounting-account-is-need-offset {% endif %}" 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-line-item-editor-modal">{{ A_("Cancel") }}</button>
|
|
||||||
<button id="accounting-summary-editor-{{ summary_editor.side }}-btn-save" type="submit" class="btn btn-primary">{{ A_("Save") }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
@ -45,11 +45,11 @@ First written: 2023/2/25
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div id="accounting-line-item-editor-summary-control" class="form-control accounting-clickable accounting-material-text-field" data-bs-toggle="modal" data-bs-target="">
|
<div id="accounting-line-item-editor-description-control" class="form-control accounting-clickable accounting-material-text-field" data-bs-toggle="modal" data-bs-target="">
|
||||||
<label class="form-label" for="accounting-line-item-editor-summary">{{ A_("Summary") }}</label>
|
<label class="form-label" for="accounting-line-item-editor-description">{{ A_("Description") }}</label>
|
||||||
<div id="accounting-line-item-editor-summary"></div>
|
<div id="accounting-line-item-editor-description"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="accounting-line-item-editor-summary-error" class="invalid-feedback"></div>
|
<div id="accounting-line-item-editor-description-error" class="invalid-feedback"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
@ -49,25 +49,25 @@ First written: 2023/2/25
|
|||||||
{% with currency_index = currency_index,
|
{% with currency_index = currency_index,
|
||||||
side = "credit",
|
side = "credit",
|
||||||
line_item_index = loop.index,
|
line_item_index = loop.index,
|
||||||
only_one_line_item_form = debit_forms|length == 1,
|
only_one_line_item_form = credit_forms|length == 1,
|
||||||
line_item_id = line_item_form.eid.data,
|
line_item_id = line_item_form.form.eid.data,
|
||||||
account_code_data = line_item_form.account_code.data|accounting_default,
|
account_code_data = line_item_form.form.account_code.data|accounting_default,
|
||||||
account_code_error = line_item_form.account_code.errors,
|
account_code_error = line_item_form.form.account_code.errors,
|
||||||
account_text = line_item_form.account_text,
|
account_text = line_item_form.form.account_text,
|
||||||
summary_data = line_item_form.summary.data|accounting_default,
|
description_data = line_item_form.form.description.data|accounting_default,
|
||||||
summary_errors = line_item_form.summary.errors,
|
description_errors = line_item_form.form.description.errors,
|
||||||
original_line_item_id_data = line_item_form.original_line_item_id.data|accounting_default,
|
original_line_item_id_data = line_item_form.form.original_line_item_id.data|accounting_default,
|
||||||
original_line_item_date = line_item_form.original_line_item_date|accounting_default,
|
original_line_item_date = line_item_form.form.original_line_item_date|accounting_default,
|
||||||
original_line_item_text = line_item_form.original_line_item_text|accounting_default,
|
original_line_item_text = line_item_form.form.original_line_item_text|accounting_default,
|
||||||
is_need_offset = line_item_form.is_need_offset,
|
is_need_offset = line_item_form.form.is_need_offset,
|
||||||
offset_items = line_item_form.offsets,
|
offset_items = line_item_form.form.offsets,
|
||||||
offset_total = line_item_form.offset_total|accounting_default("0"),
|
offset_total = line_item_form.form.offset_total|accounting_default("0"),
|
||||||
net_balance_data = line_item_form.net_balance,
|
net_balance_data = line_item_form.form.net_balance,
|
||||||
net_balance_text = line_item_form.net_balance|accounting_format_amount,
|
net_balance_text = line_item_form.form.net_balance|accounting_format_amount,
|
||||||
amount_data = line_item_form.amount.data|accounting_voucher_format_amount_input,
|
amount_data = line_item_form.form.amount.data|accounting_voucher_format_amount_input,
|
||||||
amount_errors = line_item_form.amount.errors,
|
amount_errors = line_item_form.form.amount.errors,
|
||||||
amount_text = line_item_form.amount.data|accounting_format_amount,
|
amount_text = line_item_form.form.amount.data|accounting_format_amount,
|
||||||
line_item_errors = line_item_form.all_errors %}
|
line_item_errors = line_item_form.form.all_errors %}
|
||||||
{% include "accounting/voucher/include/form-line-item.html" %}
|
{% include "accounting/voucher/include/form-line-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -47,8 +47,8 @@ First written: 2023/2/25
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_editor = form.summary_editor.credit %}
|
{% with description_editor = form.description_editor.credit %}
|
||||||
{% include "accounting/voucher/include/summary-editor-modal.html" %}
|
{% include "accounting/voucher/include/description-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with side = "credit",
|
{% with side = "credit",
|
||||||
account_options = form.credit_account_options %}
|
account_options = form.credit_account_options %}
|
||||||
|
@ -52,24 +52,24 @@ First written: 2023/2/25
|
|||||||
side = "debit",
|
side = "debit",
|
||||||
line_item_index = loop.index,
|
line_item_index = loop.index,
|
||||||
only_one_line_item_form = debit_forms|length == 1,
|
only_one_line_item_form = debit_forms|length == 1,
|
||||||
line_item_id = line_item_form.eid.data,
|
line_item_id = line_item_form.form.eid.data,
|
||||||
account_code_data = line_item_form.account_code.data|accounting_default,
|
account_code_data = line_item_form.form.account_code.data|accounting_default,
|
||||||
account_code_error = line_item_form.account_code.errors,
|
account_code_error = line_item_form.form.account_code.errors,
|
||||||
account_text = line_item_form.account_text,
|
account_text = line_item_form.form.account_text,
|
||||||
summary_data = line_item_form.summary.data|accounting_default,
|
description_data = line_item_form.form.description.data|accounting_default,
|
||||||
summary_errors = line_item_form.summary.errors,
|
description_errors = line_item_form.form.description.errors,
|
||||||
original_line_item_id_data = line_item_form.original_line_item_id.data|accounting_default,
|
original_line_item_id_data = line_item_form.form.original_line_item_id.data|accounting_default,
|
||||||
original_line_item_date = line_item_form.original_line_item_date|accounting_default,
|
original_line_item_date = line_item_form.form.original_line_item_date|accounting_default,
|
||||||
original_line_item_text = line_item_form.original_line_item_text|accounting_default,
|
original_line_item_text = line_item_form.form.original_line_item_text|accounting_default,
|
||||||
is_need_offset = line_item_form.is_need_offset,
|
is_need_offset = line_item_form.form.is_need_offset,
|
||||||
offset_items = line_item_form.offsets,
|
offset_items = line_item_form.form.offsets,
|
||||||
offset_total = line_item_form.offset_total|accounting_default,
|
offset_total = line_item_form.form.offset_total|accounting_default,
|
||||||
net_balance_data = line_item_form.net_balance,
|
net_balance_data = line_item_form.form.net_balance,
|
||||||
net_balance_text = line_item_form.net_balance|accounting_format_amount,
|
net_balance_text = line_item_form.form.net_balance|accounting_format_amount,
|
||||||
amount_data = line_item_form.amount.data|accounting_voucher_format_amount_input,
|
amount_data = line_item_form.form.amount.data|accounting_voucher_format_amount_input,
|
||||||
amount_errors = line_item_form.amount.errors,
|
amount_errors = line_item_form.form.amount.errors,
|
||||||
amount_text = line_item_form.amount.data|accounting_format_amount,
|
amount_text = line_item_form.form.amount.data|accounting_format_amount,
|
||||||
line_item_errors = line_item_form.all_errors %}
|
line_item_errors = line_item_form.form.all_errors %}
|
||||||
{% include "accounting/voucher/include/form-line-item.html" %}
|
{% include "accounting/voucher/include/form-line-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -100,24 +100,24 @@ First written: 2023/2/25
|
|||||||
side = "credit",
|
side = "credit",
|
||||||
line_item_index = loop.index,
|
line_item_index = loop.index,
|
||||||
only_one_line_item_form = debit_forms|length == 1,
|
only_one_line_item_form = debit_forms|length == 1,
|
||||||
line_item_id = line_item_form.eid.data,
|
line_item_id = line_item_form.form.eid.data,
|
||||||
account_code_data = line_item_form.account_code.data|accounting_default,
|
account_code_data = line_item_form.form.account_code.data|accounting_default,
|
||||||
account_code_error = line_item_form.account_code.errors,
|
account_code_error = line_item_form.form.account_code.errors,
|
||||||
account_text = line_item_form.account_text,
|
account_text = line_item_form.form.account_text,
|
||||||
summary_data = line_item_form.summary.data|accounting_default,
|
description_data = line_item_form.form.description.data|accounting_default,
|
||||||
summary_errors = line_item_form.summary.errors,
|
description_errors = line_item_form.form.description.errors,
|
||||||
original_line_item_id_data = line_item_form.original_line_item_id.data|accounting_default,
|
original_line_item_id_data = line_item_form.form.original_line_item_id.data|accounting_default,
|
||||||
original_line_item_date = line_item_form.original_line_item_date|accounting_default,
|
original_line_item_date = line_item_form.form.original_line_item_date|accounting_default,
|
||||||
original_line_item_text = line_item_form.original_line_item_text|accounting_default,
|
original_line_item_text = line_item_form.form.original_line_item_text|accounting_default,
|
||||||
is_need_offset = line_item_form.is_need_offset,
|
is_need_offset = line_item_form.form.is_need_offset,
|
||||||
offset_items = line_item_form.offsets,
|
offset_items = line_item_form.form.offsets,
|
||||||
offset_total = line_item_form.offset_total|accounting_default("0"),
|
offset_total = line_item_form.form.offset_total|accounting_default("0"),
|
||||||
net_balance_data = line_item_form.net_balance,
|
net_balance_data = line_item_form.form.net_balance,
|
||||||
net_balance_text = line_item_form.net_balance|accounting_format_amount,
|
net_balance_text = line_item_form.form.net_balance|accounting_format_amount,
|
||||||
amount_data = line_item_form.amount.data|accounting_voucher_format_amount_input,
|
amount_data = line_item_form.form.amount.data|accounting_voucher_format_amount_input,
|
||||||
amount_errors = line_item_form.amount.errors,
|
amount_errors = line_item_form.form.amount.errors,
|
||||||
amount_text = line_item_form.amount.data|accounting_format_amount,
|
amount_text = line_item_form.form.amount.data|accounting_format_amount,
|
||||||
line_item_errors = line_item_form.all_errors %}
|
line_item_errors = line_item_form.form.all_errors %}
|
||||||
{% include "accounting/voucher/include/form-line-item.html" %}
|
{% include "accounting/voucher/include/form-line-item.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -51,11 +51,11 @@ First written: 2023/2/25
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block form_modals %}
|
{% block form_modals %}
|
||||||
{% with summary_editor = form.summary_editor.debit %}
|
{% with description_editor = form.description_editor.debit %}
|
||||||
{% include "accounting/voucher/include/summary-editor-modal.html" %}
|
{% include "accounting/voucher/include/description-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with summary_editor = form.summary_editor.credit %}
|
{% with description_editor = form.description_editor.credit %}
|
||||||
{% include "accounting/voucher/include/summary-editor-modal.html" %}
|
{% include "accounting/voucher/include/description-editor-modal.html" %}
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% with side = "debit",
|
{% with side = "debit",
|
||||||
account_options = form.debit_account_options %}
|
account_options = form.debit_account_options %}
|
||||||
|
@ -452,8 +452,8 @@ class DebitLineItemForm(LineItemForm):
|
|||||||
"""The account code."""
|
"""The account code."""
|
||||||
offset_original_line_item_id = IntegerField()
|
offset_original_line_item_id = IntegerField()
|
||||||
"""The ID of the original line item."""
|
"""The ID of the original line item."""
|
||||||
summary = StringField(filters=[strip_text])
|
description = StringField(filters=[strip_text])
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
amount = DecimalField(
|
amount = DecimalField(
|
||||||
validators=[PositiveAmount(),
|
validators=[PositiveAmount(),
|
||||||
NotExceedingOriginalLineItemNetBalance(),
|
NotExceedingOriginalLineItemNetBalance(),
|
||||||
@ -471,7 +471,7 @@ class DebitLineItemForm(LineItemForm):
|
|||||||
obj.id = new_id(VoucherLineItem)
|
obj.id = new_id(VoucherLineItem)
|
||||||
obj.original_line_item_id = self.original_line_item_id.data
|
obj.original_line_item_id = self.original_line_item_id.data
|
||||||
obj.account_id = Account.find_by_code(self.account_code.data).id
|
obj.account_id = Account.find_by_code(self.account_code.data).id
|
||||||
obj.summary = self.summary.data
|
obj.description = self.description.data
|
||||||
obj.is_debit = True
|
obj.is_debit = True
|
||||||
obj.amount = self.amount.data
|
obj.amount = self.amount.data
|
||||||
if is_new:
|
if is_new:
|
||||||
@ -502,8 +502,8 @@ class CreditLineItemForm(LineItemForm):
|
|||||||
KeepAccountWhenHavingOffset(),
|
KeepAccountWhenHavingOffset(),
|
||||||
NotStartReceivableFromCredit()])
|
NotStartReceivableFromCredit()])
|
||||||
"""The account code."""
|
"""The account code."""
|
||||||
summary = StringField(filters=[strip_text])
|
description = StringField(filters=[strip_text])
|
||||||
"""The summary."""
|
"""The description."""
|
||||||
amount = DecimalField(
|
amount = DecimalField(
|
||||||
validators=[PositiveAmount(),
|
validators=[PositiveAmount(),
|
||||||
NotExceedingOriginalLineItemNetBalance(),
|
NotExceedingOriginalLineItemNetBalance(),
|
||||||
@ -521,7 +521,7 @@ class CreditLineItemForm(LineItemForm):
|
|||||||
obj.id = new_id(VoucherLineItem)
|
obj.id = new_id(VoucherLineItem)
|
||||||
obj.original_line_item_id = self.original_line_item_id.data
|
obj.original_line_item_id = self.original_line_item_id.data
|
||||||
obj.account_id = Account.find_by_code(self.account_code.data).id
|
obj.account_id = Account.find_by_code(self.account_code.data).id
|
||||||
obj.summary = self.summary.data
|
obj.description = self.description.data
|
||||||
obj.is_debit = False
|
obj.is_debit = False
|
||||||
obj.amount = self.amount.data
|
obj.amount = self.amount.data
|
||||||
if is_new:
|
if is_new:
|
||||||
|
@ -35,7 +35,7 @@ from accounting.models import Voucher, Account, VoucherLineItem, \
|
|||||||
from accounting.voucher.utils.account_option import AccountOption
|
from accounting.voucher.utils.account_option import AccountOption
|
||||||
from accounting.voucher.utils.original_line_items import \
|
from accounting.voucher.utils.original_line_items import \
|
||||||
get_selectable_original_line_items
|
get_selectable_original_line_items
|
||||||
from accounting.voucher.utils.summary_editor import SummaryEditor
|
from accounting.voucher.utils.description_editor import DescriptionEditor
|
||||||
from accounting.utils.random_id import new_id
|
from accounting.utils.random_id import new_id
|
||||||
from accounting.utils.strip_text import strip_multiline_text
|
from accounting.utils.strip_text import strip_multiline_text
|
||||||
from accounting.utils.user import get_current_user_pk
|
from accounting.utils.user import get_current_user_pk
|
||||||
@ -256,12 +256,12 @@ class VoucherForm(FlaskForm):
|
|||||||
if isinstance(x, str) or isinstance(x, LazyString)]
|
if isinstance(x, str) or isinstance(x, LazyString)]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def summary_editor(self) -> SummaryEditor:
|
def description_editor(self) -> DescriptionEditor:
|
||||||
"""Returns the summary editor.
|
"""Returns the description editor.
|
||||||
|
|
||||||
:return: The summary editor.
|
:return: The description editor.
|
||||||
"""
|
"""
|
||||||
return SummaryEditor()
|
return DescriptionEditor()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def original_line_item_options(self) -> list[VoucherLineItem]:
|
def original_line_item_options(self) -> list[VoucherLineItem]:
|
||||||
@ -394,7 +394,7 @@ class LineItemCollector(t.Generic[T], ABC):
|
|||||||
candidates.sort(key=lambda x: x.no)
|
candidates.sort(key=lambda x: x.no)
|
||||||
line_item = candidates[0]
|
line_item = candidates[0]
|
||||||
line_item.account_id = Account.cash().id
|
line_item.account_id = Account.cash().id
|
||||||
line_item.summary = None
|
line_item.description = None
|
||||||
line_item.amount = sum([x.amount.data for x in forms])
|
line_item.amount = sum([x.amount.data for x in forms])
|
||||||
line_item.no = no
|
line_item.no = no
|
||||||
if db.session.is_modified(line_item):
|
if db.session.is_modified(line_item):
|
||||||
@ -405,7 +405,7 @@ class LineItemCollector(t.Generic[T], ABC):
|
|||||||
line_item.is_debit = is_debit
|
line_item.is_debit = is_debit
|
||||||
line_item.currency_code = currency_code
|
line_item.currency_code = currency_code
|
||||||
line_item.account_id = Account.cash().id
|
line_item.account_id = Account.cash().id
|
||||||
line_item.summary = None
|
line_item.description = None
|
||||||
line_item.amount = sum([x.amount.data for x in forms])
|
line_item.amount = sum([x.amount.data for x in forms])
|
||||||
line_item.no = no
|
line_item.no = no
|
||||||
self.__obj.line_items.append(line_item)
|
self.__obj.line_items.append(line_item)
|
||||||
|
@ -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 editor.
|
"""The description editor.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import typing as t
|
import typing as t
|
||||||
@ -25,11 +25,11 @@ from accounting import db
|
|||||||
from accounting.models import Account, VoucherLineItem
|
from accounting.models import Account, VoucherLineItem
|
||||||
|
|
||||||
|
|
||||||
class SummaryAccount:
|
class DescriptionAccount:
|
||||||
"""An account for a summary tag."""
|
"""An account for a description tag."""
|
||||||
|
|
||||||
def __init__(self, account: Account, freq: int):
|
def __init__(self, account: Account, freq: int):
|
||||||
"""Constructs an account for a summary tag.
|
"""Constructs an account for a description tag.
|
||||||
|
|
||||||
:param account: The account.
|
:param account: The account.
|
||||||
:param freq: The frequency of the tag with the account.
|
:param freq: The frequency of the tag with the account.
|
||||||
@ -59,17 +59,17 @@ class SummaryAccount:
|
|||||||
self.freq = self.freq + freq
|
self.freq = self.freq + freq
|
||||||
|
|
||||||
|
|
||||||
class SummaryTag:
|
class DescriptionTag:
|
||||||
"""A summary tag."""
|
"""A description tag."""
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
"""Constructs a summary tag.
|
"""Constructs a description tag.
|
||||||
|
|
||||||
:param name: The tag name.
|
:param name: The tag name.
|
||||||
"""
|
"""
|
||||||
self.name: str = name
|
self.name: str = name
|
||||||
"""The tag name."""
|
"""The tag name."""
|
||||||
self.__account_dict: dict[int, SummaryAccount] = {}
|
self.__account_dict: dict[int, DescriptionAccount] = {}
|
||||||
"""The accounts that come with the tag, in the order of their
|
"""The accounts that come with the tag, in the order of their
|
||||||
frequency."""
|
frequency."""
|
||||||
self.freq: int = 0
|
self.freq: int = 0
|
||||||
@ -89,11 +89,11 @@ class SummaryTag:
|
|||||||
:param freq: The frequency of the tag name with the account.
|
:param freq: The frequency of the tag name with the account.
|
||||||
:return: None.
|
:return: None.
|
||||||
"""
|
"""
|
||||||
self.__account_dict[account.id] = SummaryAccount(account, freq)
|
self.__account_dict[account.id] = DescriptionAccount(account, freq)
|
||||||
self.freq = self.freq + freq
|
self.freq = self.freq + freq
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def accounts(self) -> list[SummaryAccount]:
|
def accounts(self) -> list[DescriptionAccount]:
|
||||||
"""Returns the accounts by the order of their frequencies.
|
"""Returns the accounts by the order of their frequencies.
|
||||||
|
|
||||||
:return: The accounts by the order of their frequencies.
|
:return: The accounts by the order of their frequencies.
|
||||||
@ -109,17 +109,17 @@ class SummaryTag:
|
|||||||
return [x.code for x in self.accounts]
|
return [x.code for x in self.accounts]
|
||||||
|
|
||||||
|
|
||||||
class SummaryType:
|
class DescriptionType:
|
||||||
"""A summary type"""
|
"""A description type"""
|
||||||
|
|
||||||
def __init__(self, type_id: t.Literal["general", "travel", "bus"]):
|
def __init__(self, type_id: t.Literal["general", "travel", "bus"]):
|
||||||
"""Constructs a summary type.
|
"""Constructs a description type.
|
||||||
|
|
||||||
:param type_id: The type ID, either "general", "travel", or "bus".
|
:param type_id: The type ID, either "general", "travel", or "bus".
|
||||||
"""
|
"""
|
||||||
self.id: t.Literal["general", "travel", "bus"] = type_id
|
self.id: t.Literal["general", "travel", "bus"] = type_id
|
||||||
"""The type ID."""
|
"""The type ID."""
|
||||||
self.__tag_dict: dict[str, SummaryTag] = {}
|
self.__tag_dict: dict[str, DescriptionTag] = {}
|
||||||
"""A dictionary from the tag name to their corresponding tag."""
|
"""A dictionary from the tag name to their corresponding tag."""
|
||||||
|
|
||||||
def add_tag(self, name: str, account: Account, freq: int) -> None:
|
def add_tag(self, name: str, account: Account, freq: int) -> None:
|
||||||
@ -131,11 +131,11 @@ class SummaryType:
|
|||||||
:return: None.
|
:return: None.
|
||||||
"""
|
"""
|
||||||
if name not in self.__tag_dict:
|
if name not in self.__tag_dict:
|
||||||
self.__tag_dict[name] = SummaryTag(name)
|
self.__tag_dict[name] = DescriptionTag(name)
|
||||||
self.__tag_dict[name].add_account(account, freq)
|
self.__tag_dict[name].add_account(account, freq)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags(self) -> list[SummaryTag]:
|
def tags(self) -> list[DescriptionTag]:
|
||||||
"""Returns the tags by the order of their frequencies.
|
"""Returns the tags by the order of their frequencies.
|
||||||
|
|
||||||
:return: The tags by the order of their frequencies.
|
:return: The tags by the order of their frequencies.
|
||||||
@ -143,24 +143,24 @@ class SummaryType:
|
|||||||
return sorted(self.__tag_dict.values(), key=lambda x: -x.freq)
|
return sorted(self.__tag_dict.values(), key=lambda x: -x.freq)
|
||||||
|
|
||||||
|
|
||||||
class SummarySide:
|
class DescriptionSide:
|
||||||
"""A summary side"""
|
"""A description side"""
|
||||||
|
|
||||||
def __init__(self, side_id: t.Literal["debit", "credit"]):
|
def __init__(self, side_id: t.Literal["debit", "credit"]):
|
||||||
"""Constructs a summary side.
|
"""Constructs a description side.
|
||||||
|
|
||||||
:param side_id: The side ID, either "debit" or "credit".
|
:param side_id: The side ID, either "debit" or "credit".
|
||||||
"""
|
"""
|
||||||
self.side: t.Literal["debit", "credit"] = side_id
|
self.side: t.Literal["debit", "credit"] = side_id
|
||||||
"""The side."""
|
"""The side."""
|
||||||
self.general: SummaryType = SummaryType("general")
|
self.general: DescriptionType = DescriptionType("general")
|
||||||
"""The general tags."""
|
"""The general tags."""
|
||||||
self.travel: SummaryType = SummaryType("travel")
|
self.travel: DescriptionType = DescriptionType("travel")
|
||||||
"""The travel tags."""
|
"""The travel tags."""
|
||||||
self.bus: SummaryType = SummaryType("bus")
|
self.bus: DescriptionType = DescriptionType("bus")
|
||||||
"""The bus tags."""
|
"""The bus tags."""
|
||||||
self.__type_dict: dict[t.Literal["general", "travel", "bus"],
|
self.__type_dict: dict[t.Literal["general", "travel", "bus"],
|
||||||
SummaryType] \
|
DescriptionType] \
|
||||||
= {x.id: x for x in {self.general, self.travel, self.bus}}
|
= {x.id: x for x in {self.general, self.travel, self.bus}}
|
||||||
"""A dictionary from the type ID to the corresponding tags."""
|
"""A dictionary from the type ID to the corresponding tags."""
|
||||||
|
|
||||||
@ -177,13 +177,13 @@ class SummarySide:
|
|||||||
self.__type_dict[tag_type].add_tag(name, account, freq)
|
self.__type_dict[tag_type].add_tag(name, account, freq)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def accounts(self) -> list[SummaryAccount]:
|
def accounts(self) -> list[DescriptionAccount]:
|
||||||
"""Returns the suggested accounts of all tags in the summary editor in
|
"""Returns the suggested accounts of all tags in the description editor
|
||||||
the side, in their frequency order.
|
in the side, 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.
|
||||||
"""
|
"""
|
||||||
accounts: dict[int, SummaryAccount] = {}
|
accounts: dict[int, DescriptionAccount] = {}
|
||||||
freq: dict[int, int] = {}
|
freq: dict[int, int] = {}
|
||||||
for tag_type in self.__type_dict.values():
|
for tag_type in self.__type_dict.values():
|
||||||
for tag in tag_type.tags:
|
for tag in tag_type.tags:
|
||||||
@ -197,35 +197,36 @@ class SummarySide:
|
|||||||
key=lambda x: -freq[x])]
|
key=lambda x: -freq[x])]
|
||||||
|
|
||||||
|
|
||||||
class SummaryEditor:
|
class DescriptionEditor:
|
||||||
"""The summary editor."""
|
"""The description editor."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Constructs the summary editor."""
|
"""Constructs the description editor."""
|
||||||
self.debit: SummarySide = SummarySide("debit")
|
self.debit: DescriptionSide = DescriptionSide("debit")
|
||||||
"""The debit tags."""
|
"""The debit tags."""
|
||||||
self.credit: SummarySide = SummarySide("credit")
|
self.credit: DescriptionSide = DescriptionSide("credit")
|
||||||
"""The credit tags."""
|
"""The credit tags."""
|
||||||
side: sa.Label = sa.case((VoucherLineItem.is_debit, "debit"),
|
side: sa.Label = sa.case((VoucherLineItem.is_debit, "debit"),
|
||||||
else_="credit").label("side")
|
else_="credit").label("side")
|
||||||
tag_type: sa.Label = sa.case(
|
tag_type: sa.Label = sa.case(
|
||||||
(VoucherLineItem.summary.like("_%—_%—_%→_%"), "bus"),
|
(VoucherLineItem.description.like("_%—_%—_%→_%"), "bus"),
|
||||||
(sa.or_(VoucherLineItem.summary.like("_%—_%→_%"),
|
(sa.or_(VoucherLineItem.description.like("_%—_%→_%"),
|
||||||
VoucherLineItem.summary.like("_%—_%↔_%")), "travel"),
|
VoucherLineItem.description.like("_%—_%↔_%")), "travel"),
|
||||||
else_="general").label("tag_type")
|
else_="general").label("tag_type")
|
||||||
tag: sa.Label = get_prefix(VoucherLineItem.summary, "—").label("tag")
|
tag: sa.Label = get_prefix(VoucherLineItem.description, "—")\
|
||||||
|
.label("tag")
|
||||||
select: sa.Select = sa.Select(side, tag_type, tag,
|
select: sa.Select = sa.Select(side, tag_type, tag,
|
||||||
VoucherLineItem.account_id,
|
VoucherLineItem.account_id,
|
||||||
sa.func.count().label("freq"))\
|
sa.func.count().label("freq"))\
|
||||||
.filter(VoucherLineItem.summary.is_not(None),
|
.filter(VoucherLineItem.description.is_not(None),
|
||||||
VoucherLineItem.summary.like("_%—_%"),
|
VoucherLineItem.description.like("_%—_%"),
|
||||||
VoucherLineItem.original_line_item_id.is_(None))\
|
VoucherLineItem.original_line_item_id.is_(None))\
|
||||||
.group_by(side, tag_type, tag, VoucherLineItem.account_id)
|
.group_by(side, tag_type, tag, VoucherLineItem.account_id)
|
||||||
result: list[sa.Row] = db.session.execute(select).all()
|
result: list[sa.Row] = db.session.execute(select).all()
|
||||||
accounts: dict[int, Account] \
|
accounts: dict[int, Account] \
|
||||||
= {x.id: x for x in Account.query
|
= {x.id: x for x in Account.query
|
||||||
.filter(Account.id.in_({x.account_id for x in result})).all()}
|
.filter(Account.id.in_({x.account_id for x in result})).all()}
|
||||||
side_dict: dict[t.Literal["debit", "credit"], SummarySide] \
|
side_dict: dict[t.Literal["debit", "credit"], DescriptionSide] \
|
||||||
= {x.side: x for x in {self.debit, self.credit}}
|
= {x.side: x for x in {self.debit, self.credit}}
|
||||||
for row in result:
|
for row in result:
|
||||||
side_dict[row.side].add_tag(
|
side_dict[row.side].add_tag(
|
@ -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 editor.
|
"""The test for the description editor.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import unittest
|
import unittest
|
||||||
@ -28,8 +28,8 @@ from testlib import create_test_app, get_client
|
|||||||
from testlib_voucher import Accounts, NEXT_URI, add_voucher
|
from testlib_voucher import Accounts, NEXT_URI, add_voucher
|
||||||
|
|
||||||
|
|
||||||
class SummeryEditorTestCase(unittest.TestCase):
|
class DescriptionEditorTestCase(unittest.TestCase):
|
||||||
"""The summary editor test case."""
|
"""The description editor test case."""
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
"""Sets up the test.
|
"""Sets up the test.
|
||||||
@ -60,16 +60,17 @@ class SummeryEditorTestCase(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_editor(self) -> None:
|
def test_description_editor(self) -> None:
|
||||||
"""Test the summary editor.
|
"""Test the description editor.
|
||||||
|
|
||||||
:return: None.
|
:return: None.
|
||||||
"""
|
"""
|
||||||
from accounting.voucher.utils.summary_editor import SummaryEditor
|
from accounting.voucher.utils.description_editor import \
|
||||||
|
DescriptionEditor
|
||||||
for form in get_form_data(self.csrf_token):
|
for form in get_form_data(self.csrf_token):
|
||||||
add_voucher(self.client, form)
|
add_voucher(self.client, form)
|
||||||
with self.app.app_context():
|
with self.app.app_context():
|
||||||
editor: SummaryEditor = SummaryEditor()
|
editor: DescriptionEditor = DescriptionEditor()
|
||||||
|
|
||||||
# Debit-General
|
# Debit-General
|
||||||
self.assertEqual(len(editor.debit.general.tags), 2)
|
self.assertEqual(len(editor.debit.general.tags), 2)
|
||||||
@ -170,156 +171,156 @@ def get_form_data(csrf_token: str) -> list[dict[str, str]]:
|
|||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-credit-0-account_code": Accounts.SERVICE,
|
"currency-0-credit-0-account_code": Accounts.SERVICE,
|
||||||
"currency-0-credit-0-summary": " Salary ",
|
"currency-0-credit-0-description": " Salary ",
|
||||||
"currency-0-credit-0-amount": "2500"},
|
"currency-0-credit-0-amount": "2500"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.MEAL,
|
"currency-0-debit-0-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-0-summary": " Lunch—Fish ",
|
"currency-0-debit-0-description": " Lunch—Fish ",
|
||||||
"currency-0-debit-0-amount": "4.7",
|
"currency-0-debit-0-amount": "4.7",
|
||||||
"currency-0-credit-0-account_code": Accounts.BANK,
|
"currency-0-credit-0-account_code": Accounts.BANK,
|
||||||
"currency-0-credit-0-summary": " Lunch—Fish ",
|
"currency-0-credit-0-description": " Lunch—Fish ",
|
||||||
"currency-0-credit-0-amount": "4.7",
|
"currency-0-credit-0-amount": "4.7",
|
||||||
"currency-0-debit-1-account_code": Accounts.MEAL,
|
"currency-0-debit-1-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-1-summary": " Lunch—Fries ",
|
"currency-0-debit-1-description": " Lunch—Fries ",
|
||||||
"currency-0-debit-1-amount": "2.15",
|
"currency-0-debit-1-amount": "2.15",
|
||||||
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-1-summary": " Lunch—Fries ",
|
"currency-0-credit-1-description": " Lunch—Fries ",
|
||||||
"currency-0-credit-1-amount": "2.15",
|
"currency-0-credit-1-amount": "2.15",
|
||||||
"currency-0-debit-2-account_code": Accounts.MEAL,
|
"currency-0-debit-2-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-2-summary": " Dinner—Hamburger ",
|
"currency-0-debit-2-description": " Dinner—Hamburger ",
|
||||||
"currency-0-debit-2-amount": "4.25",
|
"currency-0-debit-2-amount": "4.25",
|
||||||
"currency-0-credit-2-account_code": Accounts.BANK,
|
"currency-0-credit-2-account_code": Accounts.BANK,
|
||||||
"currency-0-credit-2-summary": " Dinner—Hamburger ",
|
"currency-0-credit-2-description": " Dinner—Hamburger ",
|
||||||
"currency-0-credit-2-amount": "4.25"},
|
"currency-0-credit-2-amount": "4.25"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.MEAL,
|
"currency-0-debit-0-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-0-summary": " Lunch—Salad ",
|
"currency-0-debit-0-description": " Lunch—Salad ",
|
||||||
"currency-0-debit-0-amount": "4.99",
|
"currency-0-debit-0-amount": "4.99",
|
||||||
"currency-0-credit-0-account_code": Accounts.CASH,
|
"currency-0-credit-0-account_code": Accounts.CASH,
|
||||||
"currency-0-credit-0-summary": " Lunch—Salad ",
|
"currency-0-credit-0-description": " Lunch—Salad ",
|
||||||
"currency-0-credit-0-amount": "4.99",
|
"currency-0-credit-0-amount": "4.99",
|
||||||
"currency-0-debit-1-account_code": Accounts.MEAL,
|
"currency-0-debit-1-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-1-summary": " Dinner—Steak ",
|
"currency-0-debit-1-description": " Dinner—Steak ",
|
||||||
"currency-0-debit-1-amount": "8.28",
|
"currency-0-debit-1-amount": "8.28",
|
||||||
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-1-summary": " Dinner—Steak ",
|
"currency-0-credit-1-description": " Dinner—Steak ",
|
||||||
"currency-0-credit-1-amount": "8.28"},
|
"currency-0-credit-1-amount": "8.28"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.MEAL,
|
"currency-0-debit-0-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-0-summary": " Lunch—Pizza ",
|
"currency-0-debit-0-description": " Lunch—Pizza ",
|
||||||
"currency-0-debit-0-amount": "5.49",
|
"currency-0-debit-0-amount": "5.49",
|
||||||
"currency-0-credit-0-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-0-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-0-summary": " Lunch—Pizza ",
|
"currency-0-credit-0-description": " Lunch—Pizza ",
|
||||||
"currency-0-credit-0-amount": "5.49",
|
"currency-0-credit-0-amount": "5.49",
|
||||||
"currency-0-debit-1-account_code": Accounts.MEAL,
|
"currency-0-debit-1-account_code": Accounts.MEAL,
|
||||||
"currency-0-debit-1-summary": " Lunch—Noodles ",
|
"currency-0-debit-1-description": " Lunch—Noodles ",
|
||||||
"currency-0-debit-1-amount": "7.47",
|
"currency-0-debit-1-amount": "7.47",
|
||||||
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-1-summary": " Lunch—Noodles ",
|
"currency-0-credit-1-description": " Lunch—Noodles ",
|
||||||
"currency-0-credit-1-amount": "7.47"},
|
"currency-0-credit-1-amount": "7.47"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-0-summary": " Airplane—Lake City↔Hill Town ",
|
"currency-0-debit-0-description": " Airplane—Lake City↔Hill Town",
|
||||||
"currency-0-debit-0-amount": "800"},
|
"currency-0-debit-0-amount": "800"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-0-summary": " Bus—323—Downtown→Museum ",
|
"currency-0-debit-0-description": " Bus—323—Downtown→Museum ",
|
||||||
"currency-0-debit-0-amount": "2.5",
|
"currency-0-debit-0-amount": "2.5",
|
||||||
"currency-0-credit-0-account_code": Accounts.PREPAID,
|
"currency-0-credit-0-account_code": Accounts.PREPAID,
|
||||||
"currency-0-credit-0-summary": " Bus—323—Downtown→Museum ",
|
"currency-0-credit-0-description": " Bus—323—Downtown→Museum ",
|
||||||
"currency-0-credit-0-amount": "2.5",
|
"currency-0-credit-0-amount": "2.5",
|
||||||
"currency-0-debit-1-account_code": Accounts.TRAVEL,
|
"currency-0-debit-1-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-1-summary": " Train—Blue—Museum→Central ",
|
"currency-0-debit-1-description": " Train—Blue—Museum→Central ",
|
||||||
"currency-0-debit-1-amount": "3.2",
|
"currency-0-debit-1-amount": "3.2",
|
||||||
"currency-0-credit-1-account_code": Accounts.PREPAID,
|
"currency-0-credit-1-account_code": Accounts.PREPAID,
|
||||||
"currency-0-credit-1-summary": " Train—Blue—Museum→Central ",
|
"currency-0-credit-1-description": " Train—Blue—Museum→Central ",
|
||||||
"currency-0-credit-1-amount": "3.2",
|
"currency-0-credit-1-amount": "3.2",
|
||||||
"currency-0-debit-2-account_code": Accounts.TRAVEL,
|
"currency-0-debit-2-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-2-summary": " Train—Green—Central→Mall ",
|
"currency-0-debit-2-description": " Train—Green—Central→Mall ",
|
||||||
"currency-0-debit-2-amount": "3.2",
|
"currency-0-debit-2-amount": "3.2",
|
||||||
"currency-0-credit-2-account_code": Accounts.PREPAID,
|
"currency-0-credit-2-account_code": Accounts.PREPAID,
|
||||||
"currency-0-credit-2-summary": " Train—Green—Central→Mall ",
|
"currency-0-credit-2-description": " Train—Green—Central→Mall ",
|
||||||
"currency-0-credit-2-amount": "3.2",
|
"currency-0-credit-2-amount": "3.2",
|
||||||
"currency-0-debit-3-account_code": Accounts.TRAVEL,
|
"currency-0-debit-3-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-3-summary": " Train—Red—Mall→Museum ",
|
"currency-0-debit-3-description": " Train—Red—Mall→Museum ",
|
||||||
"currency-0-debit-3-amount": "4.4",
|
"currency-0-debit-3-amount": "4.4",
|
||||||
"currency-0-credit-3-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-3-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-3-summary": " Train—Red—Mall→Museum ",
|
"currency-0-credit-3-description": " Train—Red—Mall→Museum ",
|
||||||
"currency-0-credit-3-amount": "4.4"},
|
"currency-0-credit-3-amount": "4.4"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
"currency-0-debit-0-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-0-summary": " Taxi—Museum→Office ",
|
"currency-0-debit-0-description": " Taxi—Museum→Office ",
|
||||||
"currency-0-debit-0-amount": "15.5",
|
"currency-0-debit-0-amount": "15.5",
|
||||||
"currency-0-credit-0-account_code": Accounts.CASH,
|
"currency-0-credit-0-account_code": Accounts.CASH,
|
||||||
"currency-0-credit-0-summary": " Taxi—Museum→Office ",
|
"currency-0-credit-0-description": " Taxi—Museum→Office ",
|
||||||
"currency-0-credit-0-amount": "15.5",
|
"currency-0-credit-0-amount": "15.5",
|
||||||
"currency-0-debit-1-account_code": Accounts.TRAVEL,
|
"currency-0-debit-1-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-1-summary": " Taxi—Office→Restaurant ",
|
"currency-0-debit-1-description": " Taxi—Office→Restaurant ",
|
||||||
"currency-0-debit-1-amount": "12",
|
"currency-0-debit-1-amount": "12",
|
||||||
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-1-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-1-summary": " Taxi—Office→Restaurant ",
|
"currency-0-credit-1-description": " Taxi—Office→Restaurant ",
|
||||||
"currency-0-credit-1-amount": "12",
|
"currency-0-credit-1-amount": "12",
|
||||||
"currency-0-debit-2-account_code": Accounts.TRAVEL,
|
"currency-0-debit-2-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-2-summary": " Taxi—Restaurant→City Hall ",
|
"currency-0-debit-2-description": " Taxi—Restaurant→City Hall ",
|
||||||
"currency-0-debit-2-amount": "8",
|
"currency-0-debit-2-amount": "8",
|
||||||
"currency-0-credit-2-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-2-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-2-summary": " Taxi—Restaurant→City Hall ",
|
"currency-0-credit-2-description": " Taxi—Restaurant→City Hall ",
|
||||||
"currency-0-credit-2-amount": "8",
|
"currency-0-credit-2-amount": "8",
|
||||||
"currency-0-debit-3-account_code": Accounts.TRAVEL,
|
"currency-0-debit-3-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-3-summary": " Bike—City Hall→Office ",
|
"currency-0-debit-3-description": " Bike—City Hall→Office ",
|
||||||
"currency-0-debit-3-amount": "3.5",
|
"currency-0-debit-3-amount": "3.5",
|
||||||
"currency-0-credit-3-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-3-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-3-summary": " Bike—City Hall→Office ",
|
"currency-0-credit-3-description": " Bike—City Hall→Office ",
|
||||||
"currency-0-credit-3-amount": "3.5",
|
"currency-0-credit-3-amount": "3.5",
|
||||||
"currency-0-debit-4-account_code": Accounts.TRAVEL,
|
"currency-0-debit-4-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-4-summary": " Bike—Restaurant→Office ",
|
"currency-0-debit-4-description": " Bike—Restaurant→Office ",
|
||||||
"currency-0-debit-4-amount": "4",
|
"currency-0-debit-4-amount": "4",
|
||||||
"currency-0-credit-4-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-4-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-4-summary": " Bike—Restaurant→Office ",
|
"currency-0-credit-4-description": " Bike—Restaurant→Office ",
|
||||||
"currency-0-credit-4-amount": "4",
|
"currency-0-credit-4-amount": "4",
|
||||||
"currency-0-debit-5-account_code": Accounts.TRAVEL,
|
"currency-0-debit-5-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-5-summary": " Bike—Office→Theatre ",
|
"currency-0-debit-5-description": " Bike—Office→Theatre ",
|
||||||
"currency-0-debit-5-amount": "1.5",
|
"currency-0-debit-5-amount": "1.5",
|
||||||
"currency-0-credit-5-account_code": Accounts.PETTY_CASH,
|
"currency-0-credit-5-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-credit-5-summary": " Bike—Office→Theatre ",
|
"currency-0-credit-5-description": " Bike—Office→Theatre ",
|
||||||
"currency-0-credit-5-amount": "1.5",
|
"currency-0-credit-5-amount": "1.5",
|
||||||
"currency-0-debit-6-account_code": Accounts.TRAVEL,
|
"currency-0-debit-6-account_code": Accounts.TRAVEL,
|
||||||
"currency-0-debit-6-summary": " Bike—Theatre→Home ",
|
"currency-0-debit-6-description": " Bike—Theatre→Home ",
|
||||||
"currency-0-debit-6-amount": "5.5",
|
"currency-0-debit-6-amount": "5.5",
|
||||||
"currency-0-credit-6-account_code": Accounts.PREPAID,
|
"currency-0-credit-6-account_code": Accounts.PREPAID,
|
||||||
"currency-0-credit-6-summary": " Bike—Theatre→Home ",
|
"currency-0-credit-6-description": " Bike—Theatre→Home ",
|
||||||
"currency-0-credit-6-amount": "5.5"},
|
"currency-0-credit-6-amount": "5.5"},
|
||||||
{"csrf_token": csrf_token,
|
{"csrf_token": csrf_token,
|
||||||
"next": NEXT_URI,
|
"next": NEXT_URI,
|
||||||
"date": voucher_date,
|
"date": voucher_date,
|
||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-account_code": Accounts.PETTY_CASH,
|
"currency-0-debit-0-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-debit-0-summary": " Dinner—Steak ",
|
"currency-0-debit-0-description": " Dinner—Steak ",
|
||||||
"currency-0-debit-0-amount": "8.28",
|
"currency-0-debit-0-amount": "8.28",
|
||||||
"currency-0-credit-0-account_code": Accounts.BANK,
|
"currency-0-credit-0-account_code": Accounts.BANK,
|
||||||
"currency-0-credit-0-summary": " Dinner—Steak ",
|
"currency-0-credit-0-description": " Dinner—Steak ",
|
||||||
"currency-0-credit-0-amount": "8.28",
|
"currency-0-credit-0-amount": "8.28",
|
||||||
"currency-0-debit-1-account_code": Accounts.PETTY_CASH,
|
"currency-0-debit-1-account_code": Accounts.PETTY_CASH,
|
||||||
"currency-0-debit-1-summary": " Lunch—Pizza ",
|
"currency-0-debit-1-description": " Lunch—Pizza ",
|
||||||
"currency-0-debit-1-amount": "5.49",
|
"currency-0-debit-1-amount": "5.49",
|
||||||
"currency-0-credit-1-account_code": Accounts.BANK,
|
"currency-0-credit-1-account_code": Accounts.BANK,
|
||||||
"currency-0-credit-1-summary": " Lunch—Pizza ",
|
"currency-0-credit-1-description": " Lunch—Pizza ",
|
||||||
"currency-0-credit-1-amount": "5.49"}]
|
"currency-0-credit-1-amount": "5.49"}]
|
@ -85,13 +85,13 @@ class OffsetTestCase(unittest.TestCase):
|
|||||||
"USD",
|
"USD",
|
||||||
[],
|
[],
|
||||||
[VoucherLineItemData(Accounts.RECEIVABLE,
|
[VoucherLineItemData(Accounts.RECEIVABLE,
|
||||||
self.data.e_r_or1d.summary, "300",
|
self.data.e_r_or1d.description, "300",
|
||||||
original_line_item=self.data.e_r_or1d),
|
original_line_item=self.data.e_r_or1d),
|
||||||
VoucherLineItemData(Accounts.RECEIVABLE,
|
VoucherLineItemData(Accounts.RECEIVABLE,
|
||||||
self.data.e_r_or1d.summary, "100",
|
self.data.e_r_or1d.description, "100",
|
||||||
original_line_item=self.data.e_r_or1d),
|
original_line_item=self.data.e_r_or1d),
|
||||||
VoucherLineItemData(Accounts.RECEIVABLE,
|
VoucherLineItemData(Accounts.RECEIVABLE,
|
||||||
self.data.e_r_or3d.summary, "100",
|
self.data.e_r_or3d.description, "100",
|
||||||
original_line_item=self.data.e_r_or3d)])])
|
original_line_item=self.data.e_r_or3d)])])
|
||||||
|
|
||||||
# Non-existing original line item ID
|
# Non-existing original line item ID
|
||||||
@ -400,13 +400,13 @@ class OffsetTestCase(unittest.TestCase):
|
|||||||
self.data.e_p_or3c.voucher.days, [CurrencyData(
|
self.data.e_p_or3c.voucher.days, [CurrencyData(
|
||||||
"USD",
|
"USD",
|
||||||
[VoucherLineItemData(Accounts.PAYABLE,
|
[VoucherLineItemData(Accounts.PAYABLE,
|
||||||
self.data.e_p_or1c.summary, "500",
|
self.data.e_p_or1c.description, "500",
|
||||||
original_line_item=self.data.e_p_or1c),
|
original_line_item=self.data.e_p_or1c),
|
||||||
VoucherLineItemData(Accounts.PAYABLE,
|
VoucherLineItemData(Accounts.PAYABLE,
|
||||||
self.data.e_p_or1c.summary, "300",
|
self.data.e_p_or1c.description, "300",
|
||||||
original_line_item=self.data.e_p_or1c),
|
original_line_item=self.data.e_p_or1c),
|
||||||
VoucherLineItemData(Accounts.PAYABLE,
|
VoucherLineItemData(Accounts.PAYABLE,
|
||||||
self.data.e_p_or3c.summary, "120",
|
self.data.e_p_or3c.description, "120",
|
||||||
original_line_item=self.data.e_p_or3c)],
|
original_line_item=self.data.e_p_or3c)],
|
||||||
[])])
|
[])])
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[0].debit[0].no, 1)
|
self.assertEqual(currencies[0].debit[0].no, 1)
|
||||||
self.assertEqual(currencies[0].debit[0].account.code,
|
self.assertEqual(currencies[0].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[0].debit[0].summary)
|
self.assertIsNone(currencies[0].debit[0].description)
|
||||||
self.assertEqual(currencies[0].debit[0].amount,
|
self.assertEqual(currencies[0].debit[0].amount,
|
||||||
sum([x.amount for x in currencies[0].credit]))
|
sum([x.amount for x in currencies[0].credit]))
|
||||||
self.assertEqual(len(currencies[0].credit), 2)
|
self.assertEqual(len(currencies[0].credit), 2)
|
||||||
@ -280,7 +280,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[1].debit[0].no, 2)
|
self.assertEqual(currencies[1].debit[0].no, 2)
|
||||||
self.assertEqual(currencies[1].debit[0].account.code,
|
self.assertEqual(currencies[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[1].debit[0].summary)
|
self.assertIsNone(currencies[1].debit[0].description)
|
||||||
self.assertEqual(currencies[1].debit[0].amount,
|
self.assertEqual(currencies[1].debit[0].amount,
|
||||||
sum([x.amount for x in currencies[1].credit]))
|
sum([x.amount for x in currencies[1].credit]))
|
||||||
self.assertEqual(len(currencies[1].credit), 3)
|
self.assertEqual(len(currencies[1].credit), 3)
|
||||||
@ -299,7 +299,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[2].debit[0].no, 3)
|
self.assertEqual(currencies[2].debit[0].no, 3)
|
||||||
self.assertEqual(currencies[2].debit[0].account.code,
|
self.assertEqual(currencies[2].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[2].debit[0].summary)
|
self.assertIsNone(currencies[2].debit[0].description)
|
||||||
self.assertEqual(currencies[2].debit[0].amount,
|
self.assertEqual(currencies[2].debit[0].amount,
|
||||||
sum([x.amount for x in currencies[2].credit]))
|
sum([x.amount for x in currencies[2].credit]))
|
||||||
self.assertEqual(len(currencies[2].credit), 2)
|
self.assertEqual(len(currencies[2].credit), 2)
|
||||||
@ -424,7 +424,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[0].debit[0].no, 1)
|
self.assertEqual(currencies1[0].debit[0].no, 1)
|
||||||
self.assertEqual(currencies1[0].debit[0].account.code,
|
self.assertEqual(currencies1[0].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[0].debit[0].summary)
|
self.assertIsNone(currencies1[0].debit[0].description)
|
||||||
self.assertEqual(currencies1[0].debit[0].amount,
|
self.assertEqual(currencies1[0].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[0].credit]))
|
sum([x.amount for x in currencies1[0].credit]))
|
||||||
self.assertEqual(len(currencies1[0].credit), 2)
|
self.assertEqual(len(currencies1[0].credit), 2)
|
||||||
@ -443,7 +443,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].debit[0].no, 2)
|
self.assertEqual(currencies1[1].debit[0].no, 2)
|
||||||
self.assertEqual(currencies1[1].debit[0].account.code,
|
self.assertEqual(currencies1[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].debit[0].summary)
|
self.assertIsNone(currencies1[1].debit[0].description)
|
||||||
self.assertEqual(currencies1[1].debit[0].amount,
|
self.assertEqual(currencies1[1].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[1].credit]))
|
sum([x.amount for x in currencies1[1].credit]))
|
||||||
self.assertEqual(len(currencies1[1].credit), 2)
|
self.assertEqual(len(currencies1[1].credit), 2)
|
||||||
@ -465,7 +465,7 @@ class CashReceiptVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[2].debit[0].no, 3)
|
self.assertEqual(currencies1[2].debit[0].no, 3)
|
||||||
self.assertEqual(currencies1[2].debit[0].account.code,
|
self.assertEqual(currencies1[2].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].debit[0].summary)
|
self.assertIsNone(currencies1[2].debit[0].description)
|
||||||
self.assertEqual(currencies1[2].debit[0].amount,
|
self.assertEqual(currencies1[2].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[2].credit]))
|
sum([x.amount for x in currencies1[2].credit]))
|
||||||
self.assertEqual(len(currencies1[2].credit), 3)
|
self.assertEqual(len(currencies1[2].credit), 3)
|
||||||
@ -843,7 +843,7 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[0].credit[0].no, 1)
|
self.assertEqual(currencies[0].credit[0].no, 1)
|
||||||
self.assertEqual(currencies[0].credit[0].account.code,
|
self.assertEqual(currencies[0].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[0].credit[0].summary)
|
self.assertIsNone(currencies[0].credit[0].description)
|
||||||
self.assertEqual(currencies[0].credit[0].amount,
|
self.assertEqual(currencies[0].credit[0].amount,
|
||||||
sum([x.amount for x in currencies[0].debit]))
|
sum([x.amount for x in currencies[0].debit]))
|
||||||
|
|
||||||
@ -852,20 +852,20 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[1].debit[0].no, 3)
|
self.assertEqual(currencies[1].debit[0].no, 3)
|
||||||
self.assertEqual(currencies[1].debit[0].account.code,
|
self.assertEqual(currencies[1].debit[0].account.code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(currencies[1].debit[0].summary, "Deposit")
|
self.assertEqual(currencies[1].debit[0].description, "Deposit")
|
||||||
self.assertEqual(currencies[1].debit[1].no, 4)
|
self.assertEqual(currencies[1].debit[1].no, 4)
|
||||||
self.assertEqual(currencies[1].debit[1].account.code,
|
self.assertEqual(currencies[1].debit[1].account.code,
|
||||||
Accounts.OFFICE)
|
Accounts.OFFICE)
|
||||||
self.assertEqual(currencies[1].debit[1].summary, "Pens")
|
self.assertEqual(currencies[1].debit[1].description, "Pens")
|
||||||
self.assertEqual(currencies[1].debit[2].no, 5)
|
self.assertEqual(currencies[1].debit[2].no, 5)
|
||||||
self.assertEqual(currencies[1].debit[2].account.code,
|
self.assertEqual(currencies[1].debit[2].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[1].debit[2].summary)
|
self.assertIsNone(currencies[1].debit[2].description)
|
||||||
self.assertEqual(len(currencies[1].credit), 1)
|
self.assertEqual(len(currencies[1].credit), 1)
|
||||||
self.assertEqual(currencies[1].credit[0].no, 2)
|
self.assertEqual(currencies[1].credit[0].no, 2)
|
||||||
self.assertEqual(currencies[1].credit[0].account.code,
|
self.assertEqual(currencies[1].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[1].credit[0].summary)
|
self.assertIsNone(currencies[1].credit[0].description)
|
||||||
self.assertEqual(currencies[1].credit[0].amount,
|
self.assertEqual(currencies[1].credit[0].amount,
|
||||||
sum([x.amount for x in currencies[1].debit]))
|
sum([x.amount for x in currencies[1].debit]))
|
||||||
|
|
||||||
@ -881,7 +881,7 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[2].credit[0].no, 3)
|
self.assertEqual(currencies[2].credit[0].no, 3)
|
||||||
self.assertEqual(currencies[2].credit[0].account.code,
|
self.assertEqual(currencies[2].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[2].credit[0].summary)
|
self.assertIsNone(currencies[2].credit[0].description)
|
||||||
self.assertEqual(currencies[2].credit[0].amount,
|
self.assertEqual(currencies[2].credit[0].amount,
|
||||||
sum([x.amount for x in currencies[2].debit]))
|
sum([x.amount for x in currencies[2].debit]))
|
||||||
|
|
||||||
@ -1008,7 +1008,7 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[0].credit[0].no, 1)
|
self.assertEqual(currencies1[0].credit[0].no, 1)
|
||||||
self.assertEqual(currencies1[0].credit[0].account.code,
|
self.assertEqual(currencies1[0].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[0].credit[0].summary)
|
self.assertIsNone(currencies1[0].credit[0].description)
|
||||||
self.assertEqual(currencies1[0].credit[0].amount,
|
self.assertEqual(currencies1[0].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[0].debit]))
|
sum([x.amount for x in currencies1[0].debit]))
|
||||||
|
|
||||||
@ -1019,7 +1019,7 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].debit[0].no, 3)
|
self.assertEqual(currencies1[1].debit[0].no, 3)
|
||||||
self.assertEqual(currencies1[1].debit[0].account.code,
|
self.assertEqual(currencies1[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].debit[0].summary)
|
self.assertIsNone(currencies1[1].debit[0].description)
|
||||||
self.assertEqual(currencies1[1].debit[1].id,
|
self.assertEqual(currencies1[1].debit[1].id,
|
||||||
currencies0[2].debit[1].id)
|
currencies0[2].debit[1].id)
|
||||||
self.assertEqual(currencies1[1].debit[1].no, 4)
|
self.assertEqual(currencies1[1].debit[1].no, 4)
|
||||||
@ -1030,7 +1030,7 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].credit[0].no, 2)
|
self.assertEqual(currencies1[1].credit[0].no, 2)
|
||||||
self.assertEqual(currencies1[1].credit[0].account.code,
|
self.assertEqual(currencies1[1].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].credit[0].summary)
|
self.assertIsNone(currencies1[1].credit[0].description)
|
||||||
self.assertEqual(currencies1[1].credit[0].amount,
|
self.assertEqual(currencies1[1].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[1].debit]))
|
sum([x.amount for x in currencies1[1].debit]))
|
||||||
|
|
||||||
@ -1040,26 +1040,26 @@ class CashDisbursementVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[2].debit[0].no, 5)
|
self.assertEqual(currencies1[2].debit[0].no, 5)
|
||||||
self.assertEqual(currencies1[2].debit[0].account.code,
|
self.assertEqual(currencies1[2].debit[0].account.code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertIsNone(currencies1[2].debit[0].summary)
|
self.assertIsNone(currencies1[2].debit[0].description)
|
||||||
self.assertEqual(currencies1[2].debit[1].id,
|
self.assertEqual(currencies1[2].debit[1].id,
|
||||||
currencies0[1].debit[2].id)
|
currencies0[1].debit[2].id)
|
||||||
self.assertEqual(currencies1[2].debit[1].no, 6)
|
self.assertEqual(currencies1[2].debit[1].no, 6)
|
||||||
self.assertEqual(currencies1[2].debit[1].account.code,
|
self.assertEqual(currencies1[2].debit[1].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].debit[1].summary)
|
self.assertIsNone(currencies1[2].debit[1].description)
|
||||||
self.assertEqual(currencies1[2].debit[2].id,
|
self.assertEqual(currencies1[2].debit[2].id,
|
||||||
currencies0[1].debit[0].id)
|
currencies0[1].debit[0].id)
|
||||||
self.assertEqual(currencies1[2].debit[2].no, 7)
|
self.assertEqual(currencies1[2].debit[2].no, 7)
|
||||||
self.assertEqual(currencies1[2].debit[2].account.code,
|
self.assertEqual(currencies1[2].debit[2].account.code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(currencies1[2].debit[2].summary, "Deposit")
|
self.assertEqual(currencies1[2].debit[2].description, "Deposit")
|
||||||
self.assertEqual(len(currencies1[2].credit), 1)
|
self.assertEqual(len(currencies1[2].credit), 1)
|
||||||
self.assertEqual(currencies1[2].credit[0].id,
|
self.assertEqual(currencies1[2].credit[0].id,
|
||||||
currencies0[1].credit[0].id)
|
currencies0[1].credit[0].id)
|
||||||
self.assertEqual(currencies1[2].credit[0].no, 3)
|
self.assertEqual(currencies1[2].credit[0].no, 3)
|
||||||
self.assertEqual(currencies1[2].credit[0].account.code,
|
self.assertEqual(currencies1[2].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].credit[0].summary)
|
self.assertIsNone(currencies1[2].credit[0].description)
|
||||||
self.assertEqual(currencies1[2].credit[0].amount,
|
self.assertEqual(currencies1[2].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[2].debit]))
|
sum([x.amount for x in currencies1[2].debit]))
|
||||||
|
|
||||||
@ -1464,15 +1464,15 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies[1].debit[0].no, 3)
|
self.assertEqual(currencies[1].debit[0].no, 3)
|
||||||
self.assertEqual(currencies[1].debit[0].account.code,
|
self.assertEqual(currencies[1].debit[0].account.code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(currencies[1].debit[0].summary, "Deposit")
|
self.assertEqual(currencies[1].debit[0].description, "Deposit")
|
||||||
self.assertEqual(currencies[1].debit[1].no, 4)
|
self.assertEqual(currencies[1].debit[1].no, 4)
|
||||||
self.assertEqual(currencies[1].debit[1].account.code,
|
self.assertEqual(currencies[1].debit[1].account.code,
|
||||||
Accounts.OFFICE)
|
Accounts.OFFICE)
|
||||||
self.assertEqual(currencies[1].debit[1].summary, "Pens")
|
self.assertEqual(currencies[1].debit[1].description, "Pens")
|
||||||
self.assertEqual(currencies[1].debit[2].no, 5)
|
self.assertEqual(currencies[1].debit[2].no, 5)
|
||||||
self.assertEqual(currencies[1].debit[2].account.code,
|
self.assertEqual(currencies[1].debit[2].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies[1].debit[2].summary)
|
self.assertIsNone(currencies[1].debit[2].description)
|
||||||
self.assertEqual(len(currencies[1].credit), 3)
|
self.assertEqual(len(currencies[1].credit), 3)
|
||||||
self.assertEqual(currencies[1].credit[0].no, 3)
|
self.assertEqual(currencies[1].credit[0].no, 3)
|
||||||
self.assertEqual(currencies[1].credit[0].account.code,
|
self.assertEqual(currencies[1].credit[0].account.code,
|
||||||
@ -1668,7 +1668,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].debit[0].no, 3)
|
self.assertEqual(currencies1[1].debit[0].no, 3)
|
||||||
self.assertEqual(currencies1[1].debit[0].account.code,
|
self.assertEqual(currencies1[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].debit[0].summary)
|
self.assertIsNone(currencies1[1].debit[0].description)
|
||||||
self.assertEqual(currencies1[1].debit[1].id,
|
self.assertEqual(currencies1[1].debit[1].id,
|
||||||
currencies0[2].debit[1].id)
|
currencies0[2].debit[1].id)
|
||||||
self.assertEqual(currencies1[1].debit[1].no, 4)
|
self.assertEqual(currencies1[1].debit[1].no, 4)
|
||||||
@ -1692,19 +1692,19 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[2].debit[0].no, 5)
|
self.assertEqual(currencies1[2].debit[0].no, 5)
|
||||||
self.assertEqual(currencies1[2].debit[0].account.code,
|
self.assertEqual(currencies1[2].debit[0].account.code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertIsNone(currencies1[2].debit[0].summary)
|
self.assertIsNone(currencies1[2].debit[0].description)
|
||||||
self.assertEqual(currencies1[2].debit[1].id,
|
self.assertEqual(currencies1[2].debit[1].id,
|
||||||
currencies0[1].debit[2].id)
|
currencies0[1].debit[2].id)
|
||||||
self.assertEqual(currencies1[2].debit[1].no, 6)
|
self.assertEqual(currencies1[2].debit[1].no, 6)
|
||||||
self.assertEqual(currencies1[2].debit[1].account.code,
|
self.assertEqual(currencies1[2].debit[1].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].debit[1].summary)
|
self.assertIsNone(currencies1[2].debit[1].description)
|
||||||
self.assertEqual(currencies1[2].debit[2].id,
|
self.assertEqual(currencies1[2].debit[2].id,
|
||||||
currencies0[1].debit[0].id)
|
currencies0[1].debit[0].id)
|
||||||
self.assertEqual(currencies1[2].debit[2].no, 7)
|
self.assertEqual(currencies1[2].debit[2].no, 7)
|
||||||
self.assertEqual(currencies1[2].debit[2].account.code,
|
self.assertEqual(currencies1[2].debit[2].account.code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(currencies1[2].debit[2].summary, "Deposit")
|
self.assertEqual(currencies1[2].debit[2].description, "Deposit")
|
||||||
self.assertEqual(len(currencies1[2].credit), 3)
|
self.assertEqual(len(currencies1[2].credit), 3)
|
||||||
self.assertNotIn(currencies1[2].credit[0].id, old_id)
|
self.assertNotIn(currencies1[2].credit[0].id, old_id)
|
||||||
self.assertEqual(currencies1[2].credit[0].no, 5)
|
self.assertEqual(currencies1[2].credit[0].no, 5)
|
||||||
@ -1824,7 +1824,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[0].debit[0].no, 1)
|
self.assertEqual(currencies1[0].debit[0].no, 1)
|
||||||
self.assertEqual(currencies1[0].debit[0].account.code,
|
self.assertEqual(currencies1[0].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[0].debit[0].summary)
|
self.assertIsNone(currencies1[0].debit[0].description)
|
||||||
self.assertEqual(currencies1[0].debit[0].amount,
|
self.assertEqual(currencies1[0].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[0].credit]))
|
sum([x.amount for x in currencies1[0].credit]))
|
||||||
self.assertEqual(len(currencies1[0].credit), 2)
|
self.assertEqual(len(currencies1[0].credit), 2)
|
||||||
@ -1843,7 +1843,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].debit[0].no, 2)
|
self.assertEqual(currencies1[1].debit[0].no, 2)
|
||||||
self.assertEqual(currencies1[1].debit[0].account.code,
|
self.assertEqual(currencies1[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].debit[0].summary)
|
self.assertIsNone(currencies1[1].debit[0].description)
|
||||||
self.assertEqual(currencies1[1].debit[0].amount,
|
self.assertEqual(currencies1[1].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[1].credit]))
|
sum([x.amount for x in currencies1[1].credit]))
|
||||||
self.assertEqual(len(currencies1[1].credit), 2)
|
self.assertEqual(len(currencies1[1].credit), 2)
|
||||||
@ -1865,7 +1865,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[2].debit[0].no, 3)
|
self.assertEqual(currencies1[2].debit[0].no, 3)
|
||||||
self.assertEqual(currencies1[2].debit[0].account.code,
|
self.assertEqual(currencies1[2].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].debit[0].summary)
|
self.assertIsNone(currencies1[2].debit[0].description)
|
||||||
self.assertEqual(currencies1[2].debit[0].amount,
|
self.assertEqual(currencies1[2].debit[0].amount,
|
||||||
sum([x.amount for x in currencies1[2].credit]))
|
sum([x.amount for x in currencies1[2].credit]))
|
||||||
self.assertEqual(len(currencies1[2].credit), 3)
|
self.assertEqual(len(currencies1[2].credit), 3)
|
||||||
@ -1932,7 +1932,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[0].credit[0].no, 1)
|
self.assertEqual(currencies1[0].credit[0].no, 1)
|
||||||
self.assertEqual(currencies1[0].credit[0].account.code,
|
self.assertEqual(currencies1[0].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[0].credit[0].summary)
|
self.assertIsNone(currencies1[0].credit[0].description)
|
||||||
self.assertEqual(currencies1[0].credit[0].amount,
|
self.assertEqual(currencies1[0].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[0].debit]))
|
sum([x.amount for x in currencies1[0].debit]))
|
||||||
|
|
||||||
@ -1943,7 +1943,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].debit[0].no, 3)
|
self.assertEqual(currencies1[1].debit[0].no, 3)
|
||||||
self.assertEqual(currencies1[1].debit[0].account.code,
|
self.assertEqual(currencies1[1].debit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].debit[0].summary)
|
self.assertIsNone(currencies1[1].debit[0].description)
|
||||||
self.assertEqual(currencies1[1].debit[1].id,
|
self.assertEqual(currencies1[1].debit[1].id,
|
||||||
currencies0[2].debit[1].id)
|
currencies0[2].debit[1].id)
|
||||||
self.assertEqual(currencies1[1].debit[1].no, 4)
|
self.assertEqual(currencies1[1].debit[1].no, 4)
|
||||||
@ -1954,7 +1954,7 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[1].credit[0].no, 2)
|
self.assertEqual(currencies1[1].credit[0].no, 2)
|
||||||
self.assertEqual(currencies1[1].credit[0].account.code,
|
self.assertEqual(currencies1[1].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[1].credit[0].summary)
|
self.assertIsNone(currencies1[1].credit[0].description)
|
||||||
self.assertEqual(currencies1[1].credit[0].amount,
|
self.assertEqual(currencies1[1].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[1].debit]))
|
sum([x.amount for x in currencies1[1].debit]))
|
||||||
|
|
||||||
@ -1964,26 +1964,26 @@ class TransferVoucherTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(currencies1[2].debit[0].no, 5)
|
self.assertEqual(currencies1[2].debit[0].no, 5)
|
||||||
self.assertEqual(currencies1[2].debit[0].account.code,
|
self.assertEqual(currencies1[2].debit[0].account.code,
|
||||||
Accounts.TRAVEL)
|
Accounts.TRAVEL)
|
||||||
self.assertIsNone(currencies1[2].debit[0].summary)
|
self.assertIsNone(currencies1[2].debit[0].description)
|
||||||
self.assertEqual(currencies1[2].debit[1].id,
|
self.assertEqual(currencies1[2].debit[1].id,
|
||||||
currencies0[1].debit[2].id)
|
currencies0[1].debit[2].id)
|
||||||
self.assertEqual(currencies1[2].debit[1].no, 6)
|
self.assertEqual(currencies1[2].debit[1].no, 6)
|
||||||
self.assertEqual(currencies1[2].debit[1].account.code,
|
self.assertEqual(currencies1[2].debit[1].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].debit[1].summary)
|
self.assertIsNone(currencies1[2].debit[1].description)
|
||||||
self.assertEqual(currencies1[2].debit[2].id,
|
self.assertEqual(currencies1[2].debit[2].id,
|
||||||
currencies0[1].debit[0].id)
|
currencies0[1].debit[0].id)
|
||||||
self.assertEqual(currencies1[2].debit[2].no, 7)
|
self.assertEqual(currencies1[2].debit[2].no, 7)
|
||||||
self.assertEqual(currencies1[2].debit[2].account.code,
|
self.assertEqual(currencies1[2].debit[2].account.code,
|
||||||
Accounts.BANK)
|
Accounts.BANK)
|
||||||
self.assertEqual(currencies1[2].debit[2].summary, "Deposit")
|
self.assertEqual(currencies1[2].debit[2].description, "Deposit")
|
||||||
self.assertEqual(len(currencies1[2].credit), 1)
|
self.assertEqual(len(currencies1[2].credit), 1)
|
||||||
self.assertEqual(currencies1[2].credit[0].id,
|
self.assertEqual(currencies1[2].credit[0].id,
|
||||||
currencies0[1].credit[0].id)
|
currencies0[1].credit[0].id)
|
||||||
self.assertEqual(currencies1[2].credit[0].no, 3)
|
self.assertEqual(currencies1[2].credit[0].no, 3)
|
||||||
self.assertEqual(currencies1[2].credit[0].account.code,
|
self.assertEqual(currencies1[2].credit[0].account.code,
|
||||||
Accounts.CASH)
|
Accounts.CASH)
|
||||||
self.assertIsNone(currencies1[2].credit[0].summary)
|
self.assertIsNone(currencies1[2].credit[0].description)
|
||||||
self.assertEqual(currencies1[2].credit[0].amount,
|
self.assertEqual(currencies1[2].credit[0].amount,
|
||||||
sum([x.amount for x in currencies1[2].debit]))
|
sum([x.amount for x in currencies1[2].debit]))
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@ from testlib_voucher import Accounts, match_voucher_detail, NEXT_URI
|
|||||||
class VoucherLineItemData:
|
class VoucherLineItemData:
|
||||||
"""The voucher line item data."""
|
"""The voucher line item data."""
|
||||||
|
|
||||||
def __init__(self, account: str, summary: str, amount: str,
|
def __init__(self, account: str, description: str, amount: str,
|
||||||
original_line_item: VoucherLineItemData | None = None):
|
original_line_item: VoucherLineItemData | None = None):
|
||||||
"""Constructs the voucher line item data.
|
"""Constructs the voucher line item data.
|
||||||
|
|
||||||
:param account: The account code.
|
:param account: The account code.
|
||||||
:param summary: The summary.
|
:param description: The description.
|
||||||
:param amount: The amount.
|
:param amount: The amount.
|
||||||
:param original_line_item: The original voucher line item.
|
:param original_line_item: The original voucher line item.
|
||||||
"""
|
"""
|
||||||
@ -47,7 +47,7 @@ class VoucherLineItemData:
|
|||||||
self.original_line_item: VoucherLineItemData | None \
|
self.original_line_item: VoucherLineItemData | None \
|
||||||
= original_line_item
|
= original_line_item
|
||||||
self.account: str = account
|
self.account: str = account
|
||||||
self.summary: str = summary
|
self.description: str = description
|
||||||
self.amount: Decimal = Decimal(amount)
|
self.amount: Decimal = Decimal(amount)
|
||||||
|
|
||||||
def form(self, prefix: str, side: str, index: int, is_update: bool) \
|
def form(self, prefix: str, side: str, index: int, is_update: bool) \
|
||||||
@ -62,7 +62,7 @@ class VoucherLineItemData:
|
|||||||
"""
|
"""
|
||||||
prefix = f"{prefix}-{side}-{index}"
|
prefix = f"{prefix}-{side}-{index}"
|
||||||
form: dict[str, str] = {f"{prefix}-account_code": self.account,
|
form: dict[str, str] = {f"{prefix}-account_code": self.account,
|
||||||
f"{prefix}-summary": self.summary,
|
f"{prefix}-description": self.description,
|
||||||
f"{prefix}-amount": str(self.amount)}
|
f"{prefix}-amount": str(self.amount)}
|
||||||
if is_update and self.id != -1:
|
if is_update and self.id != -1:
|
||||||
form[f"{prefix}-eid"] = str(self.id)
|
form[f"{prefix}-eid"] = str(self.id)
|
||||||
@ -174,18 +174,18 @@ class TestData:
|
|||||||
self.client: httpx.Client = client
|
self.client: httpx.Client = client
|
||||||
self.csrf_token: str = csrf_token
|
self.csrf_token: str = csrf_token
|
||||||
|
|
||||||
def couple(summary: str, amount: str, debit: str, credit: str) \
|
def couple(description: str, amount: str, debit: str, credit: str) \
|
||||||
-> tuple[VoucherLineItemData, VoucherLineItemData]:
|
-> tuple[VoucherLineItemData, VoucherLineItemData]:
|
||||||
"""Returns a couple of debit-credit line items.
|
"""Returns a couple of debit-credit line items.
|
||||||
|
|
||||||
:param summary: The summary.
|
:param description: The description.
|
||||||
:param amount: The amount.
|
:param amount: The amount.
|
||||||
:param debit: The debit account code.
|
:param debit: The debit account code.
|
||||||
:param credit: The credit account code.
|
:param credit: The credit account code.
|
||||||
:return: The debit line item and credit line item.
|
:return: The debit line item and credit line item.
|
||||||
"""
|
"""
|
||||||
return VoucherLineItemData(debit, summary, amount),\
|
return VoucherLineItemData(debit, description, amount),\
|
||||||
VoucherLineItemData(credit, summary, amount)
|
VoucherLineItemData(credit, description, amount)
|
||||||
|
|
||||||
# Receivable original line items
|
# Receivable original line items
|
||||||
self.e_r_or1d, self.e_r_or1c = couple(
|
self.e_r_or1d, self.e_r_or1c = couple(
|
||||||
|
@ -68,58 +68,58 @@ def get_add_form(csrf_token: str) -> dict[str, str]:
|
|||||||
"currency-0-code": "USD",
|
"currency-0-code": "USD",
|
||||||
"currency-0-debit-0-no": "16",
|
"currency-0-debit-0-no": "16",
|
||||||
"currency-0-debit-0-account_code": Accounts.CASH,
|
"currency-0-debit-0-account_code": Accounts.CASH,
|
||||||
"currency-0-debit-0-summary": " ",
|
"currency-0-debit-0-description": " ",
|
||||||
"currency-0-debit-0-amount": " 495.26 ",
|
"currency-0-debit-0-amount": " 495.26 ",
|
||||||
"currency-0-debit-6-no": "2",
|
"currency-0-debit-6-no": "2",
|
||||||
"currency-0-debit-6-account_code": Accounts.BANK,
|
"currency-0-debit-6-account_code": Accounts.BANK,
|
||||||
"currency-0-debit-6-summary": " Deposit ",
|
"currency-0-debit-6-description": " Deposit ",
|
||||||
"currency-0-debit-6-amount": "6000",
|
"currency-0-debit-6-amount": "6000",
|
||||||
"currency-0-debit-12-no": "2",
|
"currency-0-debit-12-no": "2",
|
||||||
"currency-0-debit-12-account_code": Accounts.OFFICE,
|
"currency-0-debit-12-account_code": Accounts.OFFICE,
|
||||||
"currency-0-debit-12-summary": " Pens ",
|
"currency-0-debit-12-description": " Pens ",
|
||||||
"currency-0-debit-12-amount": "4.99",
|
"currency-0-debit-12-amount": "4.99",
|
||||||
"currency-0-credit-2-no": "6",
|
"currency-0-credit-2-no": "6",
|
||||||
"currency-0-credit-2-account_code": Accounts.SERVICE,
|
"currency-0-credit-2-account_code": Accounts.SERVICE,
|
||||||
"currency-0-credit-2-summary": " ",
|
"currency-0-credit-2-description": " ",
|
||||||
"currency-0-credit-2-amount": "5500",
|
"currency-0-credit-2-amount": "5500",
|
||||||
"currency-0-credit-7-account_code": Accounts.SALES,
|
"currency-0-credit-7-account_code": Accounts.SALES,
|
||||||
"currency-0-credit-7-summary": " ",
|
"currency-0-credit-7-description": " ",
|
||||||
"currency-0-credit-7-amount": "950",
|
"currency-0-credit-7-amount": "950",
|
||||||
"currency-0-credit-27-account_code": Accounts.INTEREST,
|
"currency-0-credit-27-account_code": Accounts.INTEREST,
|
||||||
"currency-0-credit-27-summary": " ",
|
"currency-0-credit-27-description": " ",
|
||||||
"currency-0-credit-27-amount": "50.25",
|
"currency-0-credit-27-amount": "50.25",
|
||||||
"currency-3-no": "2",
|
"currency-3-no": "2",
|
||||||
"currency-3-code": "JPY",
|
"currency-3-code": "JPY",
|
||||||
"currency-3-debit-2-no": "2",
|
"currency-3-debit-2-no": "2",
|
||||||
"currency-3-debit-2-account_code": Accounts.CASH,
|
"currency-3-debit-2-account_code": Accounts.CASH,
|
||||||
"currency-3-debit-2-summary": " ",
|
"currency-3-debit-2-description": " ",
|
||||||
"currency-3-debit-2-amount": "15000",
|
"currency-3-debit-2-amount": "15000",
|
||||||
"currency-3-debit-9-no": "5",
|
"currency-3-debit-9-no": "5",
|
||||||
"currency-3-debit-9-account_code": Accounts.BANK,
|
"currency-3-debit-9-account_code": Accounts.BANK,
|
||||||
"currency-3-debit-9-summary": " Deposit ",
|
"currency-3-debit-9-description": " Deposit ",
|
||||||
"currency-3-debit-9-amount": "95000",
|
"currency-3-debit-9-amount": "95000",
|
||||||
"currency-3-credit-3-account_code": Accounts.AGENCY,
|
"currency-3-credit-3-account_code": Accounts.AGENCY,
|
||||||
"currency-3-credit-3-summary": " Realtor ",
|
"currency-3-credit-3-description": " Realtor ",
|
||||||
"currency-3-credit-3-amount": "65000",
|
"currency-3-credit-3-amount": "65000",
|
||||||
"currency-3-credit-5-no": "4",
|
"currency-3-credit-5-no": "4",
|
||||||
"currency-3-credit-5-account_code": Accounts.DONATION,
|
"currency-3-credit-5-account_code": Accounts.DONATION,
|
||||||
"currency-3-credit-5-summary": " Donation ",
|
"currency-3-credit-5-description": " Donation ",
|
||||||
"currency-3-credit-5-amount": "45000",
|
"currency-3-credit-5-amount": "45000",
|
||||||
"currency-16-code": "TWD",
|
"currency-16-code": "TWD",
|
||||||
"currency-16-debit-2-no": "2",
|
"currency-16-debit-2-no": "2",
|
||||||
"currency-16-debit-2-account_code": Accounts.CASH,
|
"currency-16-debit-2-account_code": Accounts.CASH,
|
||||||
"currency-16-debit-2-summary": " ",
|
"currency-16-debit-2-description": " ",
|
||||||
"currency-16-debit-2-amount": "10000",
|
"currency-16-debit-2-amount": "10000",
|
||||||
"currency-16-debit-9-no": "2",
|
"currency-16-debit-9-no": "2",
|
||||||
"currency-16-debit-9-account_code": Accounts.TRAVEL,
|
"currency-16-debit-9-account_code": Accounts.TRAVEL,
|
||||||
"currency-16-debit-9-summary": " Gas ",
|
"currency-16-debit-9-description": " Gas ",
|
||||||
"currency-16-debit-9-amount": "30000",
|
"currency-16-debit-9-amount": "30000",
|
||||||
"currency-16-credit-6-no": "6",
|
"currency-16-credit-6-no": "6",
|
||||||
"currency-16-credit-6-account_code": Accounts.RENT,
|
"currency-16-credit-6-account_code": Accounts.RENT,
|
||||||
"currency-16-credit-6-summary": " Rent ",
|
"currency-16-credit-6-description": " Rent ",
|
||||||
"currency-16-credit-6-amount": "35000",
|
"currency-16-credit-6-amount": "35000",
|
||||||
"currency-16-credit-9-account_code": Accounts.DONATION,
|
"currency-16-credit-9-account_code": Accounts.DONATION,
|
||||||
"currency-16-credit-9-summary": " Donation ",
|
"currency-16-credit-9-description": " Donation ",
|
||||||
"currency-16-credit-9-amount": "5000",
|
"currency-16-credit-9-amount": "5000",
|
||||||
"note": f"\n \n\n \n{NON_EMPTY_NOTE} \n \n\n "}
|
"note": f"\n \n\n \n{NON_EMPTY_NOTE} \n \n\n "}
|
||||||
|
|
||||||
@ -167,9 +167,9 @@ def get_unchanged_update_form(voucher_id: int, app: Flask, csrf_token: str) \
|
|||||||
form[f"{prefix}-eid"] = str(line_item.id)
|
form[f"{prefix}-eid"] = str(line_item.id)
|
||||||
form[f"{prefix}-no"] = str(line_item_no)
|
form[f"{prefix}-no"] = str(line_item_no)
|
||||||
form[f"{prefix}-account_code"] = line_item.account.code
|
form[f"{prefix}-account_code"] = line_item.account.code
|
||||||
form[f"{prefix}-summary"] \
|
form[f"{prefix}-description"] \
|
||||||
= " " if line_item.summary is None \
|
= " " if line_item.description is None \
|
||||||
else f" {line_item.summary} "
|
else f" {line_item.description} "
|
||||||
form[f"{prefix}-amount"] = str(line_item.amount)
|
form[f"{prefix}-amount"] = str(line_item.amount)
|
||||||
|
|
||||||
line_item_indices_used = set()
|
line_item_indices_used = set()
|
||||||
@ -181,8 +181,8 @@ def get_unchanged_update_form(voucher_id: int, app: Flask, csrf_token: str) \
|
|||||||
form[f"{prefix}-eid"] = str(line_item.id)
|
form[f"{prefix}-eid"] = str(line_item.id)
|
||||||
form[f"{prefix}-no"] = str(line_item_no)
|
form[f"{prefix}-no"] = str(line_item_no)
|
||||||
form[f"{prefix}-account_code"] = line_item.account.code
|
form[f"{prefix}-account_code"] = line_item.account.code
|
||||||
form[f"{prefix}-summary"] \
|
form[f"{prefix}-description"] \
|
||||||
= " " if line_item.summary is None else f" {line_item.summary} "
|
= " " if line_item.description is None else f" {line_item.description} "
|
||||||
form[f"{prefix}-amount"] = str(line_item.amount)
|
form[f"{prefix}-amount"] = str(line_item.amount)
|
||||||
|
|
||||||
return form
|
return form
|
||||||
@ -335,19 +335,19 @@ def __mess_up_currencies(form: dict[str, str]) -> dict[str, str]:
|
|||||||
f"{prefix}no": str(1 + randbelow(min_no - 1)),
|
f"{prefix}no": str(1 + randbelow(min_no - 1)),
|
||||||
f"{prefix}debit-0-no": "6",
|
f"{prefix}debit-0-no": "6",
|
||||||
f"{prefix}debit-0-account_code": Accounts.OFFICE,
|
f"{prefix}debit-0-account_code": Accounts.OFFICE,
|
||||||
f"{prefix}debit-0-summary": " Envelop ",
|
f"{prefix}debit-0-description": " Envelop ",
|
||||||
f"{prefix}debit-0-amount": "5.45",
|
f"{prefix}debit-0-amount": "5.45",
|
||||||
f"{prefix}debit-14-no": "6",
|
f"{prefix}debit-14-no": "6",
|
||||||
f"{prefix}debit-14-account_code": Accounts.CASH,
|
f"{prefix}debit-14-account_code": Accounts.CASH,
|
||||||
f"{prefix}debit-14-summary": " ",
|
f"{prefix}debit-14-description": " ",
|
||||||
f"{prefix}debit-14-amount": "14.55",
|
f"{prefix}debit-14-amount": "14.55",
|
||||||
f"{prefix}credit-16-no": "7",
|
f"{prefix}credit-16-no": "7",
|
||||||
f"{prefix}credit-16-account_code": Accounts.RENT,
|
f"{prefix}credit-16-account_code": Accounts.RENT,
|
||||||
f"{prefix}credit-16-summary": " Bike ",
|
f"{prefix}credit-16-description": " Bike ",
|
||||||
f"{prefix}credit-16-amount": "19.5",
|
f"{prefix}credit-16-amount": "19.5",
|
||||||
f"{prefix}credit-22-no": "5",
|
f"{prefix}credit-22-no": "5",
|
||||||
f"{prefix}credit-22-account_code": Accounts.DONATION,
|
f"{prefix}credit-22-account_code": Accounts.DONATION,
|
||||||
f"{prefix}credit-22-summary": " Artist ",
|
f"{prefix}credit-22-description": " Artist ",
|
||||||
f"{prefix}credit-22-amount": "0.5",
|
f"{prefix}credit-22-amount": "0.5",
|
||||||
})
|
})
|
||||||
# Swap the USD and TWD order
|
# Swap the USD and TWD order
|
||||||
|
Loading…
Reference in New Issue
Block a user