373 lines
13 KiB
Python
373 lines
13 KiB
Python
# The Mia! Accounting Demonstration Website.
|
|
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/4/12
|
|
|
|
# Copyright (c) 2023-2024 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.
|
|
"""The data reset for the Mia! Accounting demonstration website.
|
|
|
|
"""
|
|
import datetime as dt
|
|
|
|
from flask import Flask, Blueprint, url_for, flash, redirect, session, \
|
|
render_template, current_app
|
|
from flask_babel import lazy_gettext
|
|
|
|
from accounting.utils.timezone import get_tz_today
|
|
from . import db
|
|
from .auth import admin_required
|
|
from .lib import Accounts, JournalEntryLineItemData, JournalEntryData, \
|
|
JournalEntryCurrencyData, BaseTestData
|
|
|
|
bp: Blueprint = Blueprint("reset", __name__, url_prefix="/")
|
|
"""The blueprint for the data reset."""
|
|
|
|
|
|
@bp.get("reset", endpoint="reset-page")
|
|
@admin_required
|
|
def reset() -> str:
|
|
"""Resets the sample data.
|
|
|
|
:return: Redirection to the accounting application.
|
|
"""
|
|
return render_template("reset.html")
|
|
|
|
|
|
@bp.post("sample", endpoint="sample")
|
|
@admin_required
|
|
def reset_sample() -> redirect:
|
|
"""Resets the sample data.
|
|
|
|
:return: Redirection to the accounting application.
|
|
"""
|
|
from accounting.utils.cast import s
|
|
__reset_database()
|
|
SampleData(current_app, "editor").populate()
|
|
flash(s(lazy_gettext(
|
|
"The sample data are emptied and reset successfully.")), "success")
|
|
return redirect(url_for("accounting-report.default"))
|
|
|
|
|
|
@bp.post("reset", endpoint="clean-up")
|
|
@admin_required
|
|
def clean_up() -> redirect:
|
|
"""Clean-up the database data.
|
|
|
|
:return: Redirection to the accounting application.
|
|
"""
|
|
from accounting.utils.cast import s
|
|
__reset_database()
|
|
flash(s(lazy_gettext("The database is emptied successfully.")), "success")
|
|
return redirect(url_for("accounting-report.default"))
|
|
|
|
|
|
def __reset_database() -> None:
|
|
"""Resets the database.
|
|
|
|
:return: None.
|
|
"""
|
|
from accounting.models import Currency, CurrencyL10n, BaseAccount, \
|
|
BaseAccountL10n, Account, AccountL10n, JournalEntry, \
|
|
JournalEntryLineItem
|
|
from accounting.base_account import init_base_accounts_command
|
|
from accounting.account import init_accounts_command
|
|
from accounting.currency import init_currencies_command
|
|
|
|
JournalEntryLineItem.query.delete()
|
|
JournalEntry.query.delete()
|
|
CurrencyL10n.query.delete()
|
|
Currency.query.delete()
|
|
AccountL10n.query.delete()
|
|
Account.query.delete()
|
|
BaseAccountL10n.query.delete()
|
|
BaseAccount.query.delete()
|
|
init_base_accounts_command()
|
|
init_accounts_command(session["user"])
|
|
init_currencies_command(session["user"])
|
|
db.session.commit()
|
|
|
|
|
|
class SampleData(BaseTestData):
|
|
"""The sample data."""
|
|
|
|
def _init_data(self) -> None:
|
|
self.__add_recurring()
|
|
self.__add_offsets()
|
|
self.__add_meals()
|
|
|
|
def __add_recurring(self) -> None:
|
|
"""Adds the recurring data.
|
|
|
|
:return: None.
|
|
"""
|
|
self.__add_usd_recurring()
|
|
self.__add_twd_recurring()
|
|
|
|
def __add_usd_recurring(self) -> None:
|
|
"""Adds the recurring data in USD.
|
|
|
|
:return: None.
|
|
"""
|
|
today: dt.date = get_tz_today()
|
|
days: int
|
|
year: int
|
|
month: int
|
|
|
|
# Recurring in USD
|
|
date: dt.date = dt.date(today.year - 5, today.month, today.day)
|
|
date = date + dt.timedelta(days=(4 - date.weekday()))
|
|
days = (today - date).days
|
|
while True:
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "USD", "2600",
|
|
Accounts.BANK, "Transfer", Accounts.SERVICE, "Payroll")
|
|
|
|
days = days - 1
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "USD", "1200",
|
|
Accounts.CASH, None, Accounts.BANK, "Withdraw")
|
|
days = days - 13
|
|
|
|
year = today.year - 5
|
|
month = today.month
|
|
while True:
|
|
month = month + 1
|
|
if month > 12:
|
|
year = year + 1
|
|
month = 1
|
|
days = (today - dt.date(year, month, 1)).days
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "USD", "1800",
|
|
Accounts.RENT_EXPENSE, "Rent", Accounts.BANK, "Transfer")
|
|
|
|
def __add_twd_recurring(self) -> None:
|
|
"""Adds the recurring data in TWD.
|
|
|
|
:return: None.
|
|
"""
|
|
today: dt.date = get_tz_today()
|
|
|
|
year: int = today.year - 5
|
|
month: int = today.month
|
|
while True:
|
|
days: int = (today - dt.date(year, month, 5)).days
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "TWD", "50000",
|
|
Accounts.BANK, "薪資轉帳", Accounts.SERVICE, "薪水")
|
|
|
|
days = days - 1
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "TWD", "25000",
|
|
Accounts.CASH, None, Accounts.BANK, "提款")
|
|
|
|
days = days - 4
|
|
if days < 0:
|
|
break
|
|
self.__add_journal_entry(
|
|
days, "TWD", "18000",
|
|
Accounts.RENT_EXPENSE, "房租", Accounts.BANK, "轉帳")
|
|
|
|
month = month + 1
|
|
if month > 12:
|
|
year = year + 1
|
|
month = 1
|
|
|
|
def __add_offsets(self) -> None:
|
|
"""Adds the offset data.
|
|
|
|
:return: None.
|
|
"""
|
|
days: int
|
|
year: int
|
|
month: int
|
|
description: str
|
|
line_item_or: JournalEntryLineItemData
|
|
line_item_of: JournalEntryLineItemData
|
|
|
|
# Full offset and unmatched in USD
|
|
description = "Speaking—Institute"
|
|
line_item_or = JournalEntryLineItemData(
|
|
Accounts.RECEIVABLE, description, "120")
|
|
self._add_journal_entry(JournalEntryData(
|
|
40, [JournalEntryCurrencyData(
|
|
"USD", [line_item_or], [JournalEntryLineItemData(
|
|
Accounts.SERVICE, description, "120")])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.RECEIVABLE, description, "120",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
5, [JournalEntryCurrencyData(
|
|
"USD", [JournalEntryLineItemData(
|
|
Accounts.BANK, description, "120")],
|
|
[line_item_of])]))
|
|
self.__add_journal_entry(
|
|
30, "USD", "120",
|
|
Accounts.BANK, description, Accounts.SERVICE, description)
|
|
|
|
# Partial offset in USD
|
|
line_item_or = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "Computer", "1600")
|
|
self._add_journal_entry(JournalEntryData(
|
|
60, [JournalEntryCurrencyData(
|
|
"USD", [JournalEntryLineItemData(
|
|
Accounts.MACHINERY, "Computer", "1600")],
|
|
[line_item_or])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "Computer", "800",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
35, [JournalEntryCurrencyData(
|
|
"USD", [line_item_of], [JournalEntryLineItemData(
|
|
Accounts.BANK, "Computer", "800")])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "Computer", "400",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
10, [JournalEntryCurrencyData(
|
|
"USD", [line_item_of], [JournalEntryLineItemData(
|
|
Accounts.CASH, "Computer", "400")])]))
|
|
|
|
# Full offset and unmatched in TWD
|
|
description = "演講費—母校"
|
|
line_item_or = JournalEntryLineItemData(
|
|
Accounts.RECEIVABLE, description, "3000")
|
|
self._add_journal_entry(JournalEntryData(
|
|
45, [JournalEntryCurrencyData(
|
|
"TWD", [line_item_or], [JournalEntryLineItemData(
|
|
Accounts.SERVICE, description, "3000")])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.RECEIVABLE, description, "3000",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
6, [JournalEntryCurrencyData(
|
|
"TWD", [JournalEntryLineItemData(
|
|
Accounts.BANK, description, "3000")],
|
|
[line_item_of])]))
|
|
self.__add_journal_entry(
|
|
25, "TWD", "3000",
|
|
Accounts.BANK, description, Accounts.SERVICE, description)
|
|
|
|
# Partial offset in TWD
|
|
line_item_or = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "手機", "30000")
|
|
self._add_journal_entry(JournalEntryData(
|
|
55, [JournalEntryCurrencyData(
|
|
"TWD", [JournalEntryLineItemData(
|
|
Accounts.MACHINERY, "手機", "30000")],
|
|
[line_item_or])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "手機", "16000",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
27, [JournalEntryCurrencyData(
|
|
"TWD", [line_item_of], [JournalEntryLineItemData(
|
|
Accounts.BANK, "手機", "16000")])]))
|
|
line_item_of = JournalEntryLineItemData(
|
|
Accounts.PAYABLE, "手機", "6000",
|
|
original_line_item=line_item_or)
|
|
self._add_journal_entry(JournalEntryData(
|
|
8, [JournalEntryCurrencyData(
|
|
"TWD", [line_item_of], [JournalEntryLineItemData(
|
|
Accounts.CASH, "手機", "6000")])]))
|
|
|
|
def __add_meals(self) -> None:
|
|
"""Adds the meal data.
|
|
|
|
:return: None.
|
|
"""
|
|
days = 60
|
|
while days >= 0:
|
|
# Meals in USD
|
|
if days % 4 == 2:
|
|
self.__add_journal_entry(
|
|
days, "USD", "2.9",
|
|
Accounts.MEAL, "Lunch—Coffee", Accounts.CASH, None)
|
|
else:
|
|
self.__add_journal_entry(
|
|
days, "USD", "3.9",
|
|
Accounts.MEAL, "Lunch—Coffee", Accounts.CASH, None)
|
|
|
|
if days % 15 == 3:
|
|
self.__add_journal_entry(
|
|
days, "USD", "5.45",
|
|
Accounts.MEAL, "Dinner—Pizza",
|
|
Accounts.PAYABLE, "Dinner—Pizza")
|
|
else:
|
|
self.__add_journal_entry(
|
|
days, "USD", "5.9",
|
|
Accounts.MEAL, "Dinner—Pasta", Accounts.CASH, None)
|
|
|
|
# Meals in TWD
|
|
if days % 5 == 3:
|
|
self.__add_journal_entry(
|
|
days, "TWD", "125",
|
|
Accounts.MEAL, "午餐—鄰家咖啡", Accounts.CASH, None)
|
|
else:
|
|
self.__add_journal_entry(
|
|
days, "TWD", "80",
|
|
Accounts.MEAL, "午餐—便當", Accounts.CASH, None)
|
|
|
|
if days % 15 == 3:
|
|
self.__add_journal_entry(
|
|
days, "TWD", "320",
|
|
Accounts.MEAL, "晚餐—牛排", Accounts.PAYABLE, "晚餐—牛排")
|
|
else:
|
|
self.__add_journal_entry(
|
|
days, "TWD", "100",
|
|
Accounts.MEAL, "晚餐—自助餐", Accounts.CASH, None)
|
|
|
|
days = days - 1
|
|
|
|
def __add_journal_entry(
|
|
self, days: int, currency: str, amount: str,
|
|
debit_account: str, debit_description: str | None,
|
|
credit_account: str, credit_description: str | None) -> None:
|
|
"""Adds a simple journal entry.
|
|
|
|
:param days: The number of days before today.
|
|
:param currency: The currency code.
|
|
:param amount: The amount.
|
|
:param debit_account: The debit account code.
|
|
:param debit_description: The debit description.
|
|
:param credit_account: The credit account code.
|
|
:param credit_description: The credit description.
|
|
:return: None.
|
|
"""
|
|
self._add_journal_entry(JournalEntryData(
|
|
days,
|
|
[JournalEntryCurrencyData(
|
|
currency,
|
|
[JournalEntryLineItemData(
|
|
debit_account, debit_description, amount)],
|
|
[JournalEntryLineItemData(
|
|
credit_account, credit_description, amount)])]))
|
|
|
|
|
|
def init_app(app: Flask) -> None:
|
|
"""Initialize the localization.
|
|
|
|
:param app: The Flask application.
|
|
:return: None.
|
|
"""
|
|
app.register_blueprint(bp)
|