diff --git a/src/accounting/report/reports/balance_sheet.py b/src/accounting/report/reports/balance_sheet.py index c5ae4c4..21d9dd1 100644 --- a/src/accounting/report/reports/balance_sheet.py +++ b/src/accounting/report/reports/balance_sheet.py @@ -28,7 +28,7 @@ from accounting.models import Currency, BaseAccount, Account, Transaction, \ JournalEntry from accounting.report.period import Period from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.option_link import OptionLink from .utils.page_params import PageParams from .utils.period_choosers import BalanceSheetPeriodChooser @@ -428,7 +428,8 @@ class BalanceSheet(BaseReport): :return: The response of the report for download. """ filename: str = "balance-sheet-{currency}-{period}.csv"\ - .format(currency=self.__currency.code, period=self.__period.spec) + .format(currency=self.__currency.code, + period=period_spec(self.__period)) return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/income_expenses.py b/src/accounting/report/reports/income_expenses.py index dc492d4..fb1d7f2 100644 --- a/src/accounting/report/reports/income_expenses.py +++ b/src/accounting/report/reports/income_expenses.py @@ -30,7 +30,7 @@ from accounting.report.income_expense_account import IncomeExpensesAccount from accounting.report.period import Period from accounting.utils.pagination import Pagination from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.option_link import OptionLink from .utils.page_params import PageParams from .utils.period_choosers import IncomeExpensesPeriodChooser @@ -421,7 +421,7 @@ class IncomeExpenses(BaseReport): """ filename: str = "income-expenses-{currency}-{account}-{period}.csv"\ .format(currency=self.__currency.code, account=self.__account.code, - period=self.__period.spec) + period=period_spec(self.__period)) return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/income_statement.py b/src/accounting/report/reports/income_statement.py index 061c845..0ac5464 100644 --- a/src/accounting/report/reports/income_statement.py +++ b/src/accounting/report/reports/income_statement.py @@ -28,7 +28,7 @@ from accounting.models import Currency, BaseAccount, Account, Transaction, \ JournalEntry from accounting.report.period import Period from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.option_link import OptionLink from .utils.page_params import PageParams from .utils.period_choosers import IncomeStatementPeriodChooser @@ -310,7 +310,8 @@ class IncomeStatement(BaseReport): :return: The response of the report for download. """ filename: str = "income-statement-{currency}-{period}.csv"\ - .format(currency=self.__currency.code, period=self.__period.spec) + .format(currency=self.__currency.code, + period=period_spec(self.__period)) return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/journal.py b/src/accounting/report/reports/journal.py index 5e03186..32a70b1 100644 --- a/src/accounting/report/reports/journal.py +++ b/src/accounting/report/reports/journal.py @@ -29,7 +29,7 @@ from accounting.models import Currency, Account, Transaction, JournalEntry from accounting.report.period import Period from accounting.utils.pagination import Pagination from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.page_params import PageParams from .utils.period_choosers import JournalPeriodChooser from .utils.report_chooser import ReportChooser @@ -208,7 +208,7 @@ class Journal(BaseReport): :return: The response of the report for download. """ - filename: str = f"journal-{self.__period.spec}.csv" + filename: str = f"journal-{period_spec(self.__period)}.csv" return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/ledger.py b/src/accounting/report/reports/ledger.py index 6e6e659..5b91e94 100644 --- a/src/accounting/report/reports/ledger.py +++ b/src/accounting/report/reports/ledger.py @@ -29,7 +29,7 @@ from accounting.models import Currency, Account, Transaction, JournalEntry from accounting.report.period import Period from accounting.utils.pagination import Pagination from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.option_link import OptionLink from .utils.page_params import PageParams from .utils.period_choosers import LedgerPeriodChooser @@ -375,7 +375,7 @@ class Ledger(BaseReport): """ filename: str = "ledger-{currency}-{account}-{period}.csv"\ .format(currency=self.__currency.code, account=self.__account.code, - period=self.__period.spec) + period=period_spec(self.__period)) return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/trial_balance.py b/src/accounting/report/reports/trial_balance.py index 8c06a63..ac93118 100644 --- a/src/accounting/report/reports/trial_balance.py +++ b/src/accounting/report/reports/trial_balance.py @@ -27,7 +27,7 @@ from accounting.locale import gettext from accounting.models import Currency, Account, Transaction, JournalEntry from accounting.report.period import Period from .utils.base_report import BaseReport -from .utils.csv_export import BaseCSVRow, csv_download +from .utils.csv_export import BaseCSVRow, csv_download, period_spec from .utils.option_link import OptionLink from .utils.page_params import PageParams from .utils.period_choosers import TrialBalancePeriodChooser @@ -234,7 +234,8 @@ class TrialBalance(BaseReport): :return: The response of the report for download. """ filename: str = "trial-balance-{currency}-{period}.csv"\ - .format(currency=self.__currency.code, period=self.__period.spec) + .format(currency=self.__currency.code, + period=period_spec(self.__period)) return csv_download(filename, self.__get_csv_rows()) def __get_csv_rows(self) -> list[CSVRow]: diff --git a/src/accounting/report/reports/utils/csv_export.py b/src/accounting/report/reports/utils/csv_export.py index a1874d4..a7d412d 100644 --- a/src/accounting/report/reports/utils/csv_export.py +++ b/src/accounting/report/reports/utils/csv_export.py @@ -19,11 +19,14 @@ """ import csv from abc import ABC, abstractmethod +from datetime import timedelta from decimal import Decimal from io import StringIO from flask import Response +from accounting.report.period import Period + class BaseCSVRow(ABC): """The base CSV row.""" @@ -52,3 +55,36 @@ def csv_download(filename: str, rows: list[BaseCSVRow]) -> Response: response.headers["Content-Disposition"] \ = f"attachment; filename={filename}" return response + + +def period_spec(period: Period) -> str: + """Constructs the period specification to be used in the filename. + + :param period: The period. + :return: The period specification to be used in the filename. + """ + start: str | None = None + if period.start is not None: + if period.start.month == 1 and period.start.day == 1: + start = str(period.start.year) + elif period.start.day == 1: + start = period.start.strftime("%Y%m") + else: + start = period.start.strftime("%Y%m%d") + end: str | None = None + if period.end is not None: + if period.end.month == 12 and period.end.day == 31: + end = str(period.end.year) + elif (period.end + timedelta(days=1)).day == 1: + end = period.end.strftime("%Y%m") + else: + end = period.end.strftime("%Y%m%d") + if start == end: + return start + if period.start is None and period.end is None: + return "all-time" + if period.start is None: + return f"until-{end}" + if period.end is None: + return f"since-{start}" + return f"{start}-{end}"