diff --git a/app_main.py b/app_main.py index 7d425ad..41fc471 100644 --- a/app_main.py +++ b/app_main.py @@ -4,6 +4,7 @@ import os from aviza.paynl_single import extract_and_process_zip_paynl_single from aviza.gls_single import extract_and_process_zip_gls_single +from aviza.gls_auto import extract_and_process_zip_gls_auto from csv2gpc import convert_csv_to_gpc, mapping_sparkasse, mapping_pko, mapping_wise from allegro import convert_csv_to_gpc_allegro, mapping_allegro from aviza.przelewy24_report_single import extract_and_process_zip_przelewy_report_single @@ -127,6 +128,24 @@ def index(): as_attachment=True, mimetype="application/zip" ) + elif option == "gls_auto_huf": + + result_data = extract_and_process_zip_gls_auto(tmp_file_path, bank_statement_file_path, f"{option}_aviza_{day_of_year}.gpc", 3498710000999141, "HUF") + return send_file( + result_data, + download_name=f"gls_auto_huf_{day_of_year}.zip", + as_attachment=True, + mimetype="application/zip" + ) + elif option == "gls_auto_ron": + + result_data = extract_and_process_zip_gls_auto(tmp_file_path, bank_statement_file_path, f"{option}_aviza_{day_of_year}.gpc", 3498710000999149, "RON") + return send_file( + result_data, + download_name=f"gls_auto_ron_{day_of_year}.zip", + as_attachment=True, + mimetype="application/zip" + ) elif option == "przelewy24_single": result_data = extract_and_process_zip_przelewy_report_single(tmp_file_path, f"{option}_aviza_{day_of_year}.csv") diff --git a/aviza/gls_auto.py b/aviza/gls_auto.py new file mode 100644 index 0000000..bdbc5f3 --- /dev/null +++ b/aviza/gls_auto.py @@ -0,0 +1,269 @@ +import csv +import pandas as pd +import chardet +import os +import io +import zipfile +import shutil +from datetime import datetime, date +from gpc import Data, Header, TransactionCode, CURRENCIES_GPC +from utils import extract_order_number, extract_numbers, parse_date +from decimal import Decimal, ROUND_HALF_UP +from aviza.helpers import write_output_gpc_to_zip + +GLOBAL_CURRENCY = None +transactions_df = None + + +def load_bank_transactions(csv_file): + """ + Loads the bank transactions CSV file into a DataFrame and returns it. + + :param csv_file: Path to the bank transactions CSV file. + :return: A pandas DataFrame containing the transactions. + """ + global GLOBAL_CURRENCY + df = pd.read_csv(csv_file, delimiter=',', dtype=str) + + if GLOBAL_CURRENCY == "HUF": + if 'Reference' not in df.columns: + raise ValueError("The CSV file does not contain the required column 'Reference'.") + + if GLOBAL_CURRENCY == "RON": + if 'Reference' not in df.columns: + raise ValueError("The CSV file does not contain the required column 'Reference'.") + + return df + +def search_bank_transaction(search_string): + """ + Searches for a given string in the 'Zpráva pro příjemce' column of the loaded DataFrame. + + :param search_string: String to search for in the 'Zpráva pro příjemce' column. + :return: The first matching row as a dictionary or None if not found. + """ + + global GLOBAL_CURRENCY, transactions_df + + if GLOBAL_CURRENCY == "HUF": + row_title = 'Reference' + if GLOBAL_CURRENCY == "RON": + row_title = 'Reference' + matching_row = transactions_df[transactions_df[row_title].str.contains(search_string, na=False, case=False)] + + return matching_row.iloc[0].to_dict() if not matching_row.empty else None + + +def extract_and_process_zip_gls_auto(zip_file_path, bank_statement_file_path, output_file, account_number, currency): + + global GLOBAL_CURRENCY, transactions_df + all_transformed_data = [] + + transactions_df = load_bank_transactions(bank_statement_file_path) + GLOBAL_CURRENCY = currency + + base_dir = os.path.dirname(zip_file_path) + extract_folder = os.path.join(base_dir, "extracted_temp") + os.makedirs(extract_folder, exist_ok=True) + + # Extract the zip file. + with zipfile.ZipFile(zip_file_path, 'r') as zip_ref: + zip_ref.extractall(extract_folder) + + # Search for the folder named 'GLOBAL_CURRENCY' within the extracted contents. + global_currency_folder = None + for root, dirs, files in os.walk(os.path.join(extract_folder, 'Aviza GLS')): + if os.path.basename(root) == GLOBAL_CURRENCY: + global_currency_folder = root + break + + if global_currency_folder: + # Process every CSV file found in the GLOBAL_CURRENCY folder. + for filename in os.listdir(global_currency_folder): + if filename.endswith(".xlsx"): + csv_path = os.path.join(global_currency_folder, filename) + transformed_data = convert_csv_to_gpc_gls_auto(csv_path, account_number, currency) + all_transformed_data.append(transformed_data) + else: + print(f"'GLOBAL_CURRENCY' folder not found in zip file") + + # Clean up extracted files. + for root, dirs, files in os.walk(extract_folder, topdown=False): + for file in files: + os.remove(os.path.join(root, file)) + for dir in dirs: + os.rmdir(os.path.join(root, dir)) + os.rmdir(extract_folder) + + print(f"Processed and cleaned up") + + # Write all collected transformed data to the output file. + return write_output_gpc_to_zip(output_file, all_transformed_data) + + +def convert_csv_to_gpc_gls_auto(csv_file_path, account_number, currency): + gpc_lines = [] + global transactions_df + + df = pd.read_excel(csv_file_path, skiprows=7, dtype=str) + + if currency == "HUF": + payment_date = datetime.strptime(csv_file_path.split("_" + currency + "_")[1].split("_")[0], "%Y%m%d").strftime( + "%Y.%m.%d") + elif currency == "RON": + payment_date = datetime.strptime(csv_file_path.split("_" + currency + "_")[1].replace(".xlsx", ""), "%d%m%Y").strftime("%Y.%m.%d") + + df.iloc[:, 4] = pd.to_numeric(df.iloc[:, 4].str.replace(',', '.'), errors='coerce').fillna(0) + cumsum = 0.00 + transformed_data = [] + total_rows = len(df) + total_payout = 0.0 + total_payout_debet = 0.0 + total_payout_credit = 0.0 + total_payout_abs = 0.0 + + + for index, row in df.iterrows(): + + reference = "0" if pd.isna(row.iloc[2]) else extract_order_number(row.iloc[2]) + transaction_id = extract_numbers(row.iloc[0]) + direction = None + source_name = "" + payer_account = 0 + + created_on = parse_date(row.iloc[3]) + + # Convert the value using Decimal instead of float + source_str = row.iloc[4] + source_amount = Decimal(source_str) + + # Quantize to 2 decimal places (rounding if necessary) + source_amount = source_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) + + # Multiply by 100 to get cents (if that's what you need) and convert to integer + source_amount_cents = int(source_amount * 100) + + # Determine transaction type + if(direction is None): + if source_amount_cents > 0: + transaction_code = TransactionCode.CREDIT + else: + transaction_code = TransactionCode.DEBET + else: + if direction == "out": + transaction_code = TransactionCode.DEBET + else: + transaction_code = TransactionCode.CREDIT + + # Convert currency + currency_code = "100" + str(transaction_code.value) + + # Create GPC Data object + gpc_data = Data( + account=account_number, + payer_account=payer_account, + no=transaction_id, + balance=source_amount_cents, + code=transaction_code, + variable=int(reference) if reference.isdigit() else 0, + constant_symbol=0, + bank_code=0, + specific_symbol=0, + client_name="CG ABCD-EFGH-IJKL" if transaction_code == TransactionCode.CREDIT else "CG refundace", + currency=currency_code, + date=created_on + ) + + gpc_lines.append(gpc_data.to_string()) + total_payout += source_amount_cents + total_payout_abs += abs(source_amount_cents) + total_payout_debet += abs(source_amount_cents) if transaction_code == TransactionCode.DEBET else 0 + total_payout_credit += abs(source_amount_cents) if transaction_code == TransactionCode.CREDIT else 0 + # break + + if index == total_rows - 2: + break + + + corresponding_transaction = search_bank_transaction(payment_date) + + # vyuctovani row + payout_data = Data( + account=account_number, + payer_account=account_number, + no=int(total_payout), + balance=total_payout, + code=TransactionCode.DEBET, + variable=int(total_payout), + # variable=corresponding_transaction['Zpráva pro příjemce'].split(',')[-1].strip(), + constant_symbol=0, + bank_code=0, + specific_symbol=0, + client_name="CG vyúčtování", + currency="1001", + date=parse_date(corresponding_transaction['Created on']) if corresponding_transaction is not None else datetime.now() + ) + + total_payout_credit += abs(total_payout) + total_payout_abs += abs(total_payout) + + gpc_lines.append(payout_data.to_string()) + + # Create and add the header + header = Header( + account=account_number, + account_name=currency.ljust(20), + old_date=datetime.strptime("01-03-20", "%d-%m-%y"), + old_balance=0, + old_sign='+', + new_balance=0, + new_sign='+', + turnover_debet=total_payout, + turnover_debet_sign='+', + turnover_credit=total_payout, + turnover_credit_sign='+', + transaction_list_no=int(date.today().strftime("%j")), + date=datetime.now() + ) + gpc_lines.insert(0, header.to_string()) + + + file_content = "".join(gpc_lines) + print(f"GPC file content successfully created") + return file_content.encode("windows-1250") + + +def transform_csv(input_file): + global transactions_df, GLOBAL_CURRENCY + df = pd.read_excel(input_file, skiprows=7, dtype=str) + + payment_date = datetime.strptime(input_file.split("_" + GLOBAL_CURRENCY + "_")[1].split("_")[0], "%Y%m%d").strftime("%Y.%m.%d") + + df.iloc[:, 4] = pd.to_numeric(df.iloc[:, 4].str.replace(',', '.'), errors='coerce').fillna(0) + cumsum = 0.00 + transformed_data = [] + total_rows = len(df) + for index, row in df.iterrows(): + amount = row.iloc[4] + typ_operace = "t" if amount >= 0 else "c" + cumsum += amount + transformed_row = [ + typ_operace, row.iloc[3], row.iloc[0], amount, cumsum, "TRUE", row.iloc[2], + f"Dobirka za FA s VS {row.iloc[2]}", "", "", "", "", "", "", row.iloc[1], 0, GLOBAL_CURRENCY + ] + transformed_data.append(transformed_row) + + progress = (index + 1) / total_rows * 100 + sys.stdout.write(f"\rProcessing: {progress:.2f}%") + sys.stdout.flush() + + if index == total_rows - 2: + break + + + total_sum = cumsum + corresponding_transaction = search_bank_transaction(payment_date) + final_row = ["w", datetime.strptime(corresponding_transaction['Created on'], "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%d"), corresponding_transaction['ID'].split('-')[-1].strip(), -total_sum, 0, "TRUE", "", "Vyrovnání zůstatku", "12600016-16965466-28438156", "", "", "", "", "", "NEWLINE BREAK", "", GLOBAL_CURRENCY] + transformed_data.append(final_row) + + return transformed_data diff --git a/csv2gpc.py b/csv2gpc.py index db7101e..1bb2dd0 100644 --- a/csv2gpc.py +++ b/csv2gpc.py @@ -91,7 +91,7 @@ def convert_csv_to_gpc(csv_file_path, gpc_file_path, account_number, currency, m else: transaction_code = TransactionCode.DEBET else: - if direction == "out": + if direction == "out" or direction == "neutral": transaction_code = TransactionCode.DEBET else: transaction_code = TransactionCode.CREDIT diff --git a/templates/index.html b/templates/index.html index f3c36dc..0216960 100644 --- a/templates/index.html +++ b/templates/index.html @@ -82,30 +82,37 @@
Pouzijte .zip se vsemi zip soubory z exportu
.gpc aviza pro EUR ucet
-Pouzijte .zip se vsemi .csv soubory z reportu
-.gpc aviza pro Przelewy24
-Pouzijte jeden .csv soubor z transakci
.gpc aviza pro Przelewy24
Pouzijte .zip se vsemi zip soubory z exportu (z disku zazipovat slozku Aviza GLS)
-.gpc aviza pro HUF dobirky
-Pouzijte .zip se vsemi avizy ze zasilkovny
.gpc aviza pro dobirky z packety
Pouzijte .zip se vsemi zip soubory z exportu (z disku zazipovat slozku Aviza GLS)
+.gpc aviza pro HUF dobirky
+Pouzijte .zip se vsemi zip soubory z exportu (z disku zazipovat slozku Aviza GLS)
+.gpc aviza pro RON dobirky
+