diff --git a/src/accounting/__init__.py b/src/accounting/__init__.py index 7a389c9..81a2fee 100644 --- a/src/accounting/__init__.py +++ b/src/accounting/__init__.py @@ -63,8 +63,9 @@ def init_app(app: Flask, user_utils: UserUtilityInterface, bp.add_app_template_global(default_currency_code, "accounting_default_currency_code") - from .commands import init_db_command + from .commands import init_db_command, titleize_command app.cli.add_command(init_db_command) + app.cli.add_command(titleize_command) from . import locale locale.init_app(app, bp) diff --git a/src/accounting/commands.py b/src/accounting/commands.py index 5ecb235..d262ef1 100644 --- a/src/accounting/commands.py +++ b/src/accounting/commands.py @@ -26,7 +26,10 @@ from accounting import db from accounting.account import init_accounts_command from accounting.base_account import init_base_accounts_command from accounting.currency import init_currencies_command -from accounting.utils.user import has_user +from accounting.models import BaseAccount, Account +from accounting.utils.title_case import title_case +from accounting.utils.user import has_user, get_user_pk +import sqlalchemy as sa def __validate_username(ctx: click.core.Context, param: click.core.Option, @@ -60,3 +63,32 @@ def init_db_command(username: str) -> None: init_currencies_command(username) db.session.commit() click.echo("Accounting database initialized.") + + +@click.command("accounting-titleize") +@click.option("-u", "--username", metavar="USERNAME", prompt=True, + help="The username.", callback=__validate_username, + default=lambda: os.getlogin()) +@with_appcontext +def titleize_command(username: str) -> None: + """Capitalize the account titles.""" + updater_pk: int = get_user_pk(username) + updated: int = 0 + for base in BaseAccount.query: + new_title: str = title_case(base.title_l10n) + if base.title_l10n != new_title: + base.title_l10n = new_title + updated = updated + 1 + for account in Account.query: + if account.title_l10n.lower() == account.base.title_l10n.lower(): + new_title: str = title_case(account.title_l10n) + if account.title_l10n != new_title: + account.title_l10n = new_title + account.updated_at = sa.func.now() + account.updated_by_id = updater_pk + updated = updated + 1 + if updated == 0: + click.echo("All account titles were already capitalized.") + return + db.session.commit() + click.echo(f"{updated} account titles capitalized.") diff --git a/tests/test_commands.py b/tests/test_commands.py index 25d945b..811ec09 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -18,6 +18,7 @@ """ import csv +import datetime as dt import re import unittest from typing import Any @@ -177,3 +178,69 @@ class ConsoleCommandTestCase(unittest.TestCase): self.assertIn(locale, data[currency.code]["l10n"]) self.assertEqual(l10n[locale], data[currency.code]["l10n"][locale]) + + def test_titleize(self) -> None: + """Tests the "accounting-titleize" console command. + + :return: None. + """ + from accounting.models import BaseAccount, Account + from accounting.utils.random_id import new_id + from accounting.utils.user import get_user_pk + runner: FlaskCliRunner = self.__app.test_cli_runner() + + with self.__app.app_context(): + # Resets the accounts. + tables: list[sa.Table] \ + = [db.metadata.tables[x] for x in db.metadata.tables + if x.startswith("accounting_")] + for table in tables: + db.session.execute(DropTable(table)) + db.session.commit() + inspector: sa.Inspector = sa.inspect(db.session.connection()) + self.assertEqual(len({x for x in inspector.get_table_names() + if x.startswith("accounting_")}), + 0) + result: Result = runner.invoke( + args=["accounting-init-db", "-u", "editor"]) + self.assertEqual(result.exit_code, 0, + result.output + str(result.exception)) + + # Turns the titles into lowercase. + for base in BaseAccount.query: + base.title_l10n = base.title_l10n.lower() + for account in Account.query: + account.title_l10n = account.title_l10n.lower() + account.created_at \ + = account.created_at - dt.timedelta(seconds=5) + account.updated_at = account.created_at + + # Adds a custom account. + custom_title = "MBK Bank" + creator_pk: int = get_user_pk("editor") + new_account: Account = Account( + id=new_id(Account), + base_code="1112", + no="2", + title_l10n=custom_title, + is_need_offset=False, + created_by_id=creator_pk, + updated_by_id=creator_pk) + db.session.add(new_account) + db.session.commit() + + result: Result = runner.invoke( + args=["accounting-titleize", "-u", "editor"]) + self.assertEqual(result.exit_code, 0, + result.output + str(result.exception)) + for base in BaseAccount.query: + self.__test_title_case(base.title_l10n) + for account in Account.query: + if account.id != new_account.id: + self.__test_title_case(account.title_l10n) + self.assertNotEqual(account.created_at, account.updated_at) + else: + self.assertEqual(account.title_l10n, custom_title) + + db.session.delete(new_account) + db.session.commit()