From 354f1ff3d8ed2bbad7d3ae79e7e223ff82e86ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BE=9D=E7=91=AA=E8=B2=93?= Date: Wed, 8 Feb 2023 10:50:20 +0800 Subject: [PATCH] Moved the currency data from the "accounting.currency.commands" module into the currencies.csv file, separating the code and the data. Rewrote the test case to test against each all the content imported. The locales are read from the CSV file instead of hard-coded in the code, so that the translations are not hard-coded to Mandarin. --- src/accounting/currency/commands.py | 37 +++++++++++++++++------------ src/accounting/data/currencies.csv | 3 +++ tests/test_currency.py | 30 +++++++++++++++++------ 3 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 src/accounting/data/currencies.csv 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):