Enhanced CLI functionality: added short version for get-rate, show last available rate when no date provided, show available currencies when no arguments given, and improved stats functionality
This commit is contained in:
128
src/cli.py
128
src/cli.py
@@ -10,9 +10,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
|
|||||||
|
|
||||||
import data_fetcher
|
import data_fetcher
|
||||||
import database
|
import database
|
||||||
|
import holidays
|
||||||
import rate_finder
|
import rate_finder
|
||||||
import rate_reporter
|
import rate_reporter
|
||||||
import holidays
|
|
||||||
|
|
||||||
# Global debug flag
|
# Global debug flag
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
@@ -23,7 +23,7 @@ def debug_print(*args, **kwargs):
|
|||||||
print(*args, **kwargs)
|
print(*args, **kwargs)
|
||||||
|
|
||||||
def set_debug_mode(debug):
|
def set_debug_mode(debug):
|
||||||
"""Set the debug mode for all modules."""
|
"""Set the debug mode for this module."""
|
||||||
global DEBUG
|
global DEBUG
|
||||||
DEBUG = debug
|
DEBUG = debug
|
||||||
|
|
||||||
@@ -39,21 +39,18 @@ def check_and_update_yearly_data():
|
|||||||
Zkontroluje konzistenci ročních dat pro aktuální rok a případně je aktualizuje.
|
Zkontroluje konzistenci ročních dat pro aktuální rok a případně je aktualizuje.
|
||||||
"""
|
"""
|
||||||
current_year = datetime.now().year
|
current_year = datetime.now().year
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Kontroluji konzistenci ročních dat pro rok {current_year}...")
|
debug_print(f"Kontroluji konzistenci ročních dat pro rok {current_year}...")
|
||||||
|
|
||||||
# Zkontrolujeme konzistenci dat
|
# Zkontrolujeme konzistenci dat
|
||||||
is_consistent = data_fetcher.check_yearly_data_consistency(current_year, output_dir="data")
|
is_consistent = data_fetcher.check_yearly_data_consistency(current_year, output_dir="data")
|
||||||
|
|
||||||
if not is_consistent:
|
if not is_consistent:
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Roční data pro rok {current_year} nejsou konzistentní. Stahuji aktualizovaná data...")
|
debug_print(f"Roční data pro rok {current_year} nejsou konzistentní. Stahuji aktualizovaná data...")
|
||||||
# Ujistěme se, že adresář data existuje
|
# Ujistěme se, že adresář data existuje
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
# Stáhneme roční data znovu
|
# Stáhneme roční data znovu
|
||||||
data_fetcher.download_yearly_data(current_year, output_dir="data", force=True)
|
data_fetcher.download_yearly_data(current_year, output_dir="data", force=True)
|
||||||
else:
|
else:
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Roční data pro rok {current_year} jsou aktuální.")
|
debug_print(f"Roční data pro rok {current_year} jsou aktuální.")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -89,7 +86,7 @@ def main():
|
|||||||
help="Datum pro stažení denních kurzů ve formátu DD.MM.YYYY."
|
help="Datum pro stažení denních kurzů ve formátu DD.MM.YYYY."
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--get-rate",
|
"--get-rate", "-d",
|
||||||
type=str,
|
type=str,
|
||||||
help="Vyhledá kurz pro zadané datum. Formát: DD.MM.YYYY"
|
help="Vyhledá kurz pro zadané datum. Formát: DD.MM.YYYY"
|
||||||
)
|
)
|
||||||
@@ -114,6 +111,15 @@ def main():
|
|||||||
metavar=('START_DATE', 'END_DATE'),
|
metavar=('START_DATE', 'END_DATE'),
|
||||||
help="Období, pro které se má vygenerovat report kurzů. Formát: DD.MM.YYYY DD.MM.YYYY"
|
help="Období, pro které se má vygenerovat report kurzů. Formát: DD.MM.YYYY DD.MM.YYYY"
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--stats",
|
||||||
|
nargs='?',
|
||||||
|
const=True,
|
||||||
|
type=int,
|
||||||
|
help="Vygeneruje 'Jednotný kurz' pro daňové účely podle metodiky ČNB. "
|
||||||
|
"Pokud je zadán rok, vytvoří kurz pro konkrétní rok. "
|
||||||
|
"Pokud není rok zadán, vytvoří kurzy pro všechny roky s dostupnými daty."
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--debug",
|
"--debug",
|
||||||
action="store_true",
|
action="store_true",
|
||||||
@@ -122,23 +128,37 @@ def main():
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Pokud nebyly zadány žádné argumenty, vytiskneme nápovědu a seznam dostupných měn
|
||||||
|
if len(sys.argv) == 1:
|
||||||
|
parser.print_help()
|
||||||
|
print("\nDostupné měny:")
|
||||||
|
currencies = database.get_available_currencies()
|
||||||
|
if currencies:
|
||||||
|
print(", ".join(currencies))
|
||||||
|
else:
|
||||||
|
print("Žádné měny nejsou v databázi k dispozici.")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
# Nastavíme debug mód
|
# Nastavíme debug mód
|
||||||
DEBUG = args.debug
|
DEBUG = args.debug
|
||||||
set_debug_mode(DEBUG)
|
set_debug_mode(DEBUG)
|
||||||
|
|
||||||
|
# Převedeme kód měny na velká písmena, pokud byl zadán
|
||||||
|
if args.currency:
|
||||||
|
args.currency = args.currency.upper()
|
||||||
|
|
||||||
# Kontrola a případná aktualizace ročních dat pro aktuální rok (pouze v debug módu)
|
# Kontrola a případná aktualizace ročních dat pro aktuální rok (pouze v debug módu)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
check_and_update_yearly_data()
|
check_and_update_yearly_data()
|
||||||
else:
|
else:
|
||||||
# V normálním módu zkontrolujeme pouze při stahování dat
|
# V normálním módu zkontrolujeme pouze při stahování dat
|
||||||
if args.year or args.start_date or args.end_date or args.date or args.get_rate or args.report_year or args.report_period:
|
if args.year or args.start_date or args.end_date or args.date or args.get_rate or args.report_year or args.report_period or args.stats:
|
||||||
current_year = datetime.now().year
|
current_year = datetime.now().year
|
||||||
# Pro jednoduchost v normálním módu nebudeme kontrolovat konzistenci automaticky
|
# Pro jednoduchost v normálním módu nebudeme kontrolovat konzistenci automaticky
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Zde bude logika pro zpracování argumentů
|
# Zde bude logika pro zpracování argumentů
|
||||||
if args.year:
|
if args.year:
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Stahuji roční data pro rok {args.year}...")
|
debug_print(f"Stahuji roční data pro rok {args.year}...")
|
||||||
# Ujistěme se, že adresář data existuje
|
# Ujistěme se, že adresář data existuje
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
@@ -146,14 +166,12 @@ def main():
|
|||||||
data_fetcher.download_yearly_data(args.year, output_dir="data")
|
data_fetcher.download_yearly_data(args.year, output_dir="data")
|
||||||
elif args.currency and args.start_date and args.end_date and not args.report_period:
|
elif args.currency and args.start_date and args.end_date and not args.report_period:
|
||||||
# Měsíční stahování dat
|
# Měsíční stahování dat
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Stahuji měsíční data pro měnu {args.currency} od {args.start_date} do {args.end_date}...")
|
debug_print(f"Stahuji měsíční data pro měnu {args.currency} od {args.start_date} do {args.end_date}...")
|
||||||
# Ujistěme se, že adresář data existuje
|
# Ujistěme se, že adresář data existuje
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
# Volání funkce pro stažení měsíčních dat
|
# Volání funkce pro stažení měsíčních dat
|
||||||
data_fetcher.download_monthly_data(args.currency, args.start_date, args.end_date, output_dir="data")
|
data_fetcher.download_monthly_data(args.currency, args.start_date, args.end_date, output_dir="data")
|
||||||
elif args.date:
|
elif args.date:
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Stahuji denní data pro datum {args.date}...")
|
debug_print(f"Stahuji denní data pro datum {args.date}...")
|
||||||
# Ujistěme se, že adresář data existuje
|
# Ujistěme se, že adresář data existuje
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
@@ -162,7 +180,6 @@ def main():
|
|||||||
elif args.get_rate and args.currency:
|
elif args.get_rate and args.currency:
|
||||||
date_str = args.get_rate
|
date_str = args.get_rate
|
||||||
currency_code = args.currency
|
currency_code = args.currency
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Vyhledávám kurz pro {currency_code} na datum {date_str}...")
|
debug_print(f"Vyhledávám kurz pro {currency_code} na datum {date_str}...")
|
||||||
rate = rate_finder.get_rate_for_date(date_str, currency_code)
|
rate = rate_finder.get_rate_for_date(date_str, currency_code)
|
||||||
if rate:
|
if rate:
|
||||||
@@ -182,7 +199,6 @@ def main():
|
|||||||
if requested_date.date() == today.date():
|
if requested_date.date() == today.date():
|
||||||
# Zkontrolujeme, zda je čas po 14:30
|
# Zkontrolujeme, zda je čas po 14:30
|
||||||
if today.time() >= datetime.strptime("14:30", "%H:%M").time():
|
if today.time() >= datetime.strptime("14:30", "%H:%M").time():
|
||||||
if DEBUG:
|
|
||||||
debug_print("Automaticky stahuji denní data...")
|
debug_print("Automaticky stahuji denní data...")
|
||||||
# Ujistěme se, že adresář data existuje
|
# Ujistěme se, že adresář data existuje
|
||||||
os.makedirs("data", exist_ok=True)
|
os.makedirs("data", exist_ok=True)
|
||||||
@@ -221,23 +237,105 @@ def main():
|
|||||||
print("Kurz nenalezen")
|
print("Kurz nenalezen")
|
||||||
else:
|
else:
|
||||||
print(f"Kurz {currency_code} na datum {date_str} (ani v předchozích dnech) nebyl nalezen.")
|
print(f"Kurz {currency_code} na datum {date_str} (ani v předchozích dnech) nebyl nalezen.")
|
||||||
|
elif args.get_rate is not None and not args.currency:
|
||||||
|
# Pokud je zadán --get-rate bez data a bez měny
|
||||||
|
if DEBUG:
|
||||||
|
print("Chyba: Pro použití --get-rate musí být zadána měna pomocí -c/--currency.")
|
||||||
|
sys.exit(1)
|
||||||
|
elif args.currency and not args.get_rate:
|
||||||
|
# Pokud je zadána měna, ale není zadán --get-rate, vytiskneme poslední dostupný kurz
|
||||||
|
currency_code = args.currency
|
||||||
|
debug_print(f"Vyhledávám poslední dostupný kurz pro {currency_code}...")
|
||||||
|
rate, date = database.get_last_rate_for_currency(currency_code)
|
||||||
|
if rate and date:
|
||||||
|
# Pro normální režim zobrazíme kurz ve formátu "11.11 # dated: dd.mm.yyyy"
|
||||||
|
if not DEBUG:
|
||||||
|
print(f"{rate} # dated: {date}")
|
||||||
|
else:
|
||||||
|
print(f"Poslední dostupný kurz {currency_code}: {rate} # dated: {date}")
|
||||||
|
else:
|
||||||
|
if not DEBUG:
|
||||||
|
print("Kurz nenalezen")
|
||||||
|
else:
|
||||||
|
print(f"Poslední dostupný kurz pro {currency_code} nebyl nalezen.")
|
||||||
elif args.report_year and args.currency:
|
elif args.report_year and args.currency:
|
||||||
if args.report_month:
|
if args.report_month:
|
||||||
# Generování měsíčního reportu
|
# Generování měsíčního reportu
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Generuji měsíční report pro {args.currency} za {args.report_month}/{args.report_year}...")
|
debug_print(f"Generuji měsíční report pro {args.currency} za {args.report_month}/{args.report_year}...")
|
||||||
rate_reporter.generate_monthly_report(args.report_year, args.report_month, args.currency, output_dir="data")
|
rate_reporter.generate_monthly_report(args.report_year, args.report_month, args.currency, output_dir="data")
|
||||||
else:
|
else:
|
||||||
# Generování ročního reportu
|
# Generování ročního reportu
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Generuji roční report pro {args.currency} za rok {args.report_year}...")
|
debug_print(f"Generuji roční report pro {args.currency} za rok {args.report_year}...")
|
||||||
rate_reporter.generate_yearly_report(args.report_year, args.currency, output_dir="data")
|
rate_reporter.generate_yearly_report(args.report_year, args.currency, output_dir="data")
|
||||||
elif args.report_period and args.currency:
|
elif args.report_period and args.currency:
|
||||||
# Generování reportu za období
|
# Generování reportu za období
|
||||||
start_date, end_date = args.report_period
|
start_date, end_date = args.report_period
|
||||||
if DEBUG:
|
|
||||||
debug_print(f"Generuji report pro {args.currency} za období {start_date} - {end_date}...")
|
debug_print(f"Generuji report pro {args.currency} za období {start_date} - {end_date}...")
|
||||||
rate_reporter.generate_period_report(start_date, end_date, args.currency, output_dir="data")
|
rate_reporter.generate_period_report(start_date, end_date, args.currency, output_dir="data")
|
||||||
|
elif args.stats is not None and args.currency:
|
||||||
|
currency_code = args.currency
|
||||||
|
if args.stats is True:
|
||||||
|
# Pokud je --stats zadán bez roku, vytvoříme kurzy pro všechny roky s dostupnými daty
|
||||||
|
debug_print(f"Generuji 'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} pro všechny roky...")
|
||||||
|
|
||||||
|
# Získáme seznam všech roků s daty
|
||||||
|
years = database.get_years_with_data()
|
||||||
|
if not years:
|
||||||
|
if not DEBUG:
|
||||||
|
print("Žádná data nenalezena")
|
||||||
|
else:
|
||||||
|
print("Databáze neobsahuje žádná data.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Pro každý rok vypočítáme 'Jednotný kurz'
|
||||||
|
for year in years:
|
||||||
|
# Zkontrolujeme, zda databáze obsahuje data pro daný rok
|
||||||
|
if not rate_finder.check_year_data_in_db(year):
|
||||||
|
debug_print(f"Databáze neobsahuje data pro rok {year}. Stahuji roční data...")
|
||||||
|
# Ujistěme se, že adresář data existuje
|
||||||
|
os.makedirs("data", exist_ok=True)
|
||||||
|
# Stáhneme roční data s vynuceným stažením
|
||||||
|
data_fetcher.download_yearly_data(year, output_dir="data", force=True)
|
||||||
|
|
||||||
|
# Vypočítáme 'Jednotný kurz' podle metodiky ČNB
|
||||||
|
tax_rate = rate_reporter.calculate_tax_yearly_average(year, currency_code, output_dir="data")
|
||||||
|
if tax_rate:
|
||||||
|
# Pro --stats v normálním režimu zobrazíme pouze 'Jednotný kurz' zaokrouhlený na 2 desetinná místa
|
||||||
|
if not DEBUG:
|
||||||
|
print(f"{year}: {tax_rate:.2f}")
|
||||||
|
else:
|
||||||
|
print(f"'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} za rok {year}: {tax_rate:.2f}")
|
||||||
|
else:
|
||||||
|
if not DEBUG:
|
||||||
|
print(f"{year}: 'Jednotný kurz' nenalezen")
|
||||||
|
else:
|
||||||
|
print(f"'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} za rok {year} nebyl nalezen.")
|
||||||
|
else:
|
||||||
|
# Pokud je --stats zadán s konkrétním rokem
|
||||||
|
year = args.stats
|
||||||
|
debug_print(f"Generuji 'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} za rok {year}...")
|
||||||
|
|
||||||
|
# Zkontrolujeme, zda databáze obsahuje data pro daný rok
|
||||||
|
if not rate_finder.check_year_data_in_db(year):
|
||||||
|
debug_print(f"Databáze neobsahuje data pro rok {year}. Stahuji roční data...")
|
||||||
|
# Ujistěme se, že adresář data existuje
|
||||||
|
os.makedirs("data", exist_ok=True)
|
||||||
|
# Stáhneme roční data s vynuceným stažením
|
||||||
|
data_fetcher.download_yearly_data(year, output_dir="data", force=True)
|
||||||
|
|
||||||
|
# Vypočítáme 'Jednotný kurz' podle metodiky ČNB
|
||||||
|
tax_rate = rate_reporter.calculate_tax_yearly_average(year, currency_code, output_dir="data")
|
||||||
|
if tax_rate:
|
||||||
|
# Pro --stats v normálním režimu zobrazíme pouze 'Jednotný kurz' zaokrouhlený na 2 desetinná místa
|
||||||
|
if not DEBUG:
|
||||||
|
print(f"{tax_rate:.2f}")
|
||||||
|
else:
|
||||||
|
print(f"'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} za rok {year}: {tax_rate:.2f}")
|
||||||
|
else:
|
||||||
|
if not DEBUG:
|
||||||
|
print("'Jednotný kurz' nenalezen")
|
||||||
|
else:
|
||||||
|
print(f"'Jednotný kurz' pro daňové účely podle metodiky ČNB pro {currency_code} za rok {year} nebyl nalezen.")
|
||||||
else:
|
else:
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
|
|||||||
@@ -131,6 +131,61 @@ def get_years_with_data():
|
|||||||
|
|
||||||
return years
|
return years
|
||||||
|
|
||||||
|
def get_available_currencies():
|
||||||
|
"""
|
||||||
|
Vrátí seznam všech měn, pro které databáze obsahuje data.
|
||||||
|
|
||||||
|
:return: Seznam kódů měn jako řetězce.
|
||||||
|
"""
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Získáme seznam všech měn z databáze
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT DISTINCT currency_code FROM exchange_rates
|
||||||
|
ORDER BY currency_code
|
||||||
|
''')
|
||||||
|
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
# Extrahujeme kódy měn
|
||||||
|
currencies = [row[0] for row in rows if row[0]]
|
||||||
|
|
||||||
|
return currencies
|
||||||
|
|
||||||
|
def get_last_rate_for_currency(currency_code):
|
||||||
|
"""
|
||||||
|
Vrátí poslední dostupný kurz pro zadanou měnu.
|
||||||
|
|
||||||
|
:param currency_code: Kód měny (např. USD).
|
||||||
|
:return: Tuple (rate, date) s kurzem a datem, nebo (None, None) pokud není nalezen.
|
||||||
|
"""
|
||||||
|
conn = sqlite3.connect(DB_PATH)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
# Vyhledání posledního kurzu pro měnu
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT rate, date FROM exchange_rates
|
||||||
|
WHERE currency_code = ?
|
||||||
|
ORDER BY date DESC
|
||||||
|
LIMIT 1
|
||||||
|
''', (currency_code,))
|
||||||
|
|
||||||
|
row = cursor.fetchone()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
if row:
|
||||||
|
# Převod data zpět do formátu DD.MM.YYYY
|
||||||
|
try:
|
||||||
|
dt = datetime.strptime(row[1], "%Y-%m-%d")
|
||||||
|
formatted_date = dt.strftime("%d.%m.%Y")
|
||||||
|
return (row[0], formatted_date)
|
||||||
|
except ValueError:
|
||||||
|
return (row[0], row[1]) # V případě chyby vrátíme původní datum
|
||||||
|
else:
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
# Příklad použití
|
# Příklad použití
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
init_db()
|
init_db()
|
||||||
Reference in New Issue
Block a user