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.

This commit is contained in:
依瑪貓 2023-02-08 10:50:20 +08:00
parent d8e0e30c41
commit 354f1ff3d8
3 changed files with 48 additions and 22 deletions

View File

@ -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.")

View File

@ -0,0 +1,3 @@
code,name,l10n-zh_Hant,l10n-zh_Hans
TWD,New Taiwan dollar,新臺幣,新台币
USD,United States dollar,美元,美元
1 code name l10n-zh_Hant l10n-zh_Hans
2 TWD New Taiwan dollar 新臺幣 新台币
3 USD United States dollar 美元 美元

View File

@ -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):