fix(reports): refine financial export summaries
Some checks failed
Backend CI/CD / test (push) Has been cancelled
Backend CI/CD / deploy (push) Has been cancelled

This commit is contained in:
2026-05-23 20:13:35 +03:30
parent 59cf62bc73
commit 22e08a099c
3 changed files with 260 additions and 111 deletions

View File

@@ -49,9 +49,13 @@ TRANSLATIONS = {
"rate_history": "Hourly rate history",
"from": "From",
"to": "To",
"now": "Now",
"project": "Project",
"percentage": "Percentage",
"hour_percentage": "Hour %",
"income_percentage": "Income %",
"multiple_rates": "Multiple rates - see details",
"variable_rate": "Variable rate",
"none": "None",
"daily_summary": "Daily Summary",
"clients": "Clients",
@@ -93,9 +97,13 @@ TRANSLATIONS = {
"rate_history": "\u062a\u0627\u0631\u06cc\u062e\u0686\u0647 \u0646\u0631\u062e \u0633\u0627\u0639\u062a\u06cc",
"from": "\u0627\u0632",
"to": "\u062a\u0627",
"now": "\u062d\u0627\u0644",
"project": "\u067e\u0631\u0648\u0698\u0647",
"percentage": "\u062f\u0631\u0635\u062f",
"hour_percentage": "\u062f\u0631\u0635\u062f \u0633\u0627\u0639\u062a",
"income_percentage": "\u062f\u0631\u0635\u062f \u06a9\u0627\u0631\u06a9\u0631\u062f",
"multiple_rates": "\u0686\u0646\u062f \u0646\u0631\u062e - \u062c\u0632\u0626\u06cc\u0627\u062a \u062f\u0631 \u06af\u0632\u0627\u0631\u0634 \u06a9\u0627\u0631\u0628\u0631",
"variable_rate": "\u0646\u0631\u062e \u0645\u062a\u063a\u06cc\u0631",
"none": "\u0628\u062f\u0648\u0646 \u0645\u0648\u0631\u062f",
"daily_summary": "\u062e\u0644\u0627\u0635\u0647 \u0631\u0648\u0632\u0627\u0646\u0647",
"clients": "\u0645\u0634\u062a\u0631\u06cc\u0627\u0646",
@@ -140,6 +148,8 @@ CURRENCY_LABELS = {
"TRY": {"en": "TRY", "fa": "\u0644\u06cc\u0631"},
}
DECIMAL_TRIM_CURRENCIES = {"IRR", "IRT"}
@dataclass(frozen=True)
class ExportLocale:
@@ -174,6 +184,15 @@ class ExportLocale:
return self.format_number(value, ascii_digits=ascii_digits)
def format_amount(self, value: object, *, ascii_digits: bool = False) -> str:
return self.format_amount_for_currency(value, None, ascii_digits=ascii_digits)
def format_amount_for_currency(
self,
value: object,
currency: str | None,
*,
ascii_digits: bool = False,
) -> str:
raw = str(value).strip()
if not raw:
return raw
@@ -189,7 +208,11 @@ class ExportLocale:
grouped_integer = f"{int(integer_part):,}"
formatted = f"{sign}{grouped_integer}"
if fractional_part:
trimmed_fraction = fractional_part.rstrip("0")
trimmed_fraction = (
""
if str(currency or "").upper() in DECIMAL_TRIM_CURRENCIES
else fractional_part.rstrip("0")
)
if trimmed_fraction:
formatted = f"{formatted}.{trimmed_fraction}"
return self.format_number(formatted, ascii_digits=ascii_digits)
@@ -200,7 +223,9 @@ class ExportLocale:
parts = []
for item in income_totals:
currency = self.currency_label(item["currency"])
parts.append(f"{self.format_amount(item['amount'], ascii_digits=ascii_digits)} {currency}")
parts.append(
f"{self.format_amount_for_currency(item['amount'], item['currency'], ascii_digits=ascii_digits)} {currency}"
)
return " | ".join(parts)
def currency_label(self, code: str | None) -> str: