diff --git a/src/accounting/currency/commands.py b/src/accounting/currency/commands.py index e3321f6..6a151fb 100644 --- a/src/accounting/currency/commands.py +++ b/src/accounting/currency/commands.py @@ -17,11 +17,14 @@ """The console commands for the currency management. """ +import csv import os +import typing as t import click from flask.cli import with_appcontext +from accounting import data_dir from accounting.database import db from accounting.models import Currency, CurrencyL10n from accounting.utils.user import has_user, get_user_pk @@ -54,25 +57,29 @@ def __validate_username(ctx: click.core.Context, param: click.core.Option, @with_appcontext def init_currencies_command(username: str) -> None: """Initializes the currencies.""" - data: list[CurrencyData] = [ - ("TWD", "New Taiwan dollar", "新臺幣", "新台币"), - ("USD", "United States dollar", "美元", "美元"), - ] - creator_pk: int = get_user_pk(username) - existing: list[Currency] = Currency.query.all() - existing_code: set[str] = {x.code for x in existing} - to_add: list[CurrencyData] = [x for x in data if x[0] not in existing_code] + existing_codes: set[str] = {x.code for x in Currency.query.all()} + + with open(data_dir / "currencies.csv") as fh: + data: list[dict[str, str]] = [x for x in csv.DictReader(fh)] + to_add: list[dict[str, str]] = [x for x in data + if x["code"] not in existing_codes] if len(to_add) == 0: click.echo("No more currency to add.") return - db.session.bulk_save_objects( - [Currency(code=x[0], name_l10n=x[1], - created_by_id=creator_pk, updated_by_id=creator_pk) - for x in data]) - db.session.bulk_save_objects( - [CurrencyL10n(currency_code=x[0], locale=y[0], name=y[1]) - for x in data for y in (("zh_Hant", x[2]), ("zh_Hans", x[3]))]) + creator_pk: int = get_user_pk(username) + currency_data: list[dict[str, t.Any]] = [{"code": x["code"], + "name_l10n": x["name"], + "created_by_id": creator_pk, + "updated_by_id": creator_pk} + for x in to_add] + locales: list[str] = [x[5:] for x in to_add[0] if x.startswith("l10n-")] + l10n_data: list[dict[str, str]] = [{"currency_code": x["code"], + "locale": y, + "name": x[f"l10n-{y}"]} + for x in to_add for y in locales] + db.session.bulk_insert_mappings(Currency, currency_data) + db.session.bulk_insert_mappings(CurrencyL10n, l10n_data) db.session.commit() click.echo(F"{len(to_add)} added. Currencies initialized.") diff --git a/src/accounting/data/currencies.csv b/src/accounting/data/currencies.csv new file mode 100644 index 0000000..e5e0698 --- /dev/null +++ b/src/accounting/data/currencies.csv @@ -0,0 +1,3 @@ +code,name,l10n-zh_Hant,l10n-zh_Hans +TWD,New Taiwan dollar,新臺幣,新台币 +USD,United States dollar,美元,美元 diff --git a/tests/test_currency.py b/tests/test_currency.py index e7dc7cb..df186dd 100644 --- a/tests/test_currency.py +++ b/tests/test_currency.py @@ -17,7 +17,9 @@ """The test for the currency management. """ +import csv import time +import typing as t import unittest import httpx @@ -83,20 +85,34 @@ class CurrencyCommandTestCase(unittest.TestCase): :return: None. """ - from accounting.models import Currency, CurrencyL10n + from accounting import data_dir + from accounting.models import Currency + + with open(data_dir / "currencies.csv") as fh: + data: dict[dict[str, t.Any]] \ + = {x["code"]: {"code": x["code"], + "name": x["name"], + "l10n": {y[5:]: x[y] + for y in x if y.startswith("l10n-")}} + for x in csv.DictReader(fh)} + runner: FlaskCliRunner = self.app.test_cli_runner() with self.app.app_context(): result: Result = runner.invoke( args=["accounting-init-currencies", "-u", "editor"]) self.assertEqual(result.exit_code, 0) currencies: list[Currency] = Currency.query.all() - l10n: list[CurrencyL10n] = CurrencyL10n.query.all() - self.assertEqual(len(currencies), 2) - self.assertEqual(len(l10n), 2 * 2) - l10n_keys: set[str] = {f"{x.currency_code}-{x.locale}" for x in l10n} + + self.assertEqual(len(currencies), len(data)) for currency in currencies: - self.assertIn(f"{currency.code}-zh_Hant", l10n_keys) - self.assertIn(f"{currency.code}-zh_Hant", l10n_keys) + self.assertIn(currency.code, data) + self.assertEqual(currency.name_l10n, data[currency.code]["name"]) + l10n: dict[str, str] = {x.locale: x.name for x in currency.l10n} + self.assertEqual(len(l10n), len(data[currency.code]["l10n"])) + for locale in l10n: + self.assertIn(locale, data[currency.code]["l10n"]) + self.assertEqual(l10n[locale], + data[currency.code]["l10n"][locale]) class CurrencyTestCase(unittest.TestCase):