diff --git a/src/cli.py b/src/cli.py index b581bf3..f38bcd8 100755 --- a/src/cli.py +++ b/src/cli.py @@ -10,9 +10,9 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__))) import data_fetcher import database +import holidays import rate_finder import rate_reporter -import holidays # Global debug flag DEBUG = False @@ -23,7 +23,7 @@ def debug_print(*args, **kwargs): print(*args, **kwargs) def set_debug_mode(debug): - """Set the debug mode for all modules.""" + """Set the debug mode for this module.""" global DEBUG DEBUG = debug @@ -39,22 +39,19 @@ def check_and_update_yearly_data(): Zkontroluje konzistenci ročních dat pro aktuální rok a případně je aktualizuje. """ 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 is_consistent = data_fetcher.check_yearly_data_consistency(current_year, output_dir="data") 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 os.makedirs("data", exist_ok=True) # Stáhneme roční data znovu data_fetcher.download_yearly_data(current_year, output_dir="data", force=True) 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(): global DEBUG @@ -89,7 +86,7 @@ def main(): help="Datum pro stažení denních kurzů ve formátu DD.MM.YYYY." ) parser.add_argument( - "--get-rate", + "--get-rate", "-d", type=str, help="Vyhledá kurz pro zadané datum. Formát: DD.MM.YYYY" ) @@ -114,6 +111,15 @@ def main(): metavar=('START_DATE', 'END_DATE'), 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( "--debug", action="store_true", @@ -122,39 +128,51 @@ def main(): 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 DEBUG = args.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) if DEBUG: check_and_update_yearly_data() else: # 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 # Pro jednoduchost v normálním módu nebudeme kontrolovat konzistenci automaticky pass # Zde bude logika pro zpracování argumentů 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 os.makedirs("data", exist_ok=True) # Volání funkce pro stažení ročních dat 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: # 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 os.makedirs("data", exist_ok=True) # 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") 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 os.makedirs("data", exist_ok=True) # Volání funkce pro stažení denních dat @@ -162,8 +180,7 @@ def main(): elif args.get_rate and args.currency: date_str = args.get_rate 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) if rate: # Pro --get-rate v normálním režimu zobrazíme pouze kurz @@ -182,8 +199,7 @@ def main(): if requested_date.date() == today.date(): # Zkontrolujeme, zda je čas po 14:30 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 os.makedirs("data", exist_ok=True) # Stáhneme denní data pro dnešní datum @@ -221,23 +237,105 @@ def main(): print("Kurz nenalezen") else: 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: if args.report_month: # 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") else: # 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") elif args.report_period and args.currency: # Generování reportu za období 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") + 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: if DEBUG: parser.print_help() diff --git a/src/database.py b/src/database.py index 4a7f99d..ee59e79 100644 --- a/src/database.py +++ b/src/database.py @@ -131,6 +131,61 @@ def get_years_with_data(): 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í if __name__ == "__main__": init_db() \ No newline at end of file