przelewy, packeta comgate

This commit is contained in:
t0is 2025-03-11 11:16:20 +01:00
parent 14a7239068
commit 02f7bfdc9f
4 changed files with 113 additions and 45 deletions

View File

@ -67,6 +67,16 @@ def index():
except:
print("no bank_statement")
try:
file_refunds = request.files["file_refunds"]
suffix = os.path.splitext(file_refunds.filename)[1]
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp_input:
file_refunds.save(tmp_input.name)
refunds_file_path = tmp_input.name
except:
print("no bank_statement")
day_of_year = int(datetime.date.today().strftime("%j"))
out_filename = f"{option}_vypis_{day_of_year}.gpc"
mimetype = "text/plain"
@ -153,13 +163,13 @@ def index():
)
elif option == "przelewy24_transactions":
result_data = extract_and_process_csv_przelewy24_transactions(tmp_file_path, bank_statement_file_path, f"{option}_avizo_{day_of_year}.gpc",
result_data = extract_and_process_csv_przelewy24_transactions(tmp_file_path, bank_statement_file_path, refunds_file_path, f"{option}_avizo_{day_of_year}.gpc",
account_number=3498710000999133,
currency="PLN", mapping=mapping_przelewy_transactions)
return send_file(
result_data,
download_name=f"przelewy24_auto_{day_of_year}.zip",
download_name=f"przelewy24_transactions_{day_of_year}.zip",
as_attachment=True,
mimetype="application/zip"
)

View File

@ -20,33 +20,40 @@ def load_bank_transactions(csv_file):
:param csv_file: Path to the bank transactions CSV file.
:return: A pandas DataFrame containing the transactions.
"""
df = pd.read_csv(csv_file, delimiter=';', dtype=str)
with open(csv_file, 'rb') as f:
raw_data = f.read(10000) # Read first 10KB for encoding detection
detected = chardet.detect(raw_data)
encoding = detected['encoding']
print(f"Detected encoding: {encoding}")
# Ensure the required column exists
if 'Zpráva pro příjemce' not in df.columns:
raise ValueError("The CSV file does not contain the required column 'Zpráva pro příjemce'.")
df = pd.read_csv(csv_file, delimiter=',', dtype=str, encoding=encoding)
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.
Searches for a given string in the 10th column (position 9) of the loaded DataFrame.
:param df: Pandas DataFrame containing bank transactions.
:param search_string: String to search for in the 'Zpráva pro příjemce' column.
:param search_string: String to search for in the specified column.
:return: The first matching row as a dictionary or None if not found.
"""
global transactions_df
matching_row = transactions_df[transactions_df['Zpráva pro příjemce'].str.contains(search_string, na=False, case=False)]
return matching_row.iloc[0].to_dict() if not matching_row.empty else None
# Create a boolean mask based on the 10th column (using positional index)
mask = transactions_df.iloc[:, 9].str.contains(search_string, na=False, case=False)
# Use .loc to filter rows; this will always return a DataFrame
matching_rows = transactions_df.loc[mask]
# Convert the DataFrame rows into a list of dictionaries
records = matching_rows.to_dict('records')
return records[0] if records else None
def extract_and_process_csv_przelewy24_transactions(csv_file_path, bank_statement_file_path, output_file, account_number, currency, mapping):
def extract_and_process_csv_przelewy24_transactions(csv_file_path, bank_statement_file_path, refunds_file_path, output_file, account_number, currency, mapping):
global transactions_df
transactions_df = load_bank_transactions(bank_statement_file_path)
all_transformed_data = []
grouped_data = defaultdict(list)
grouped_data_refunds = defaultdict(list)
if mapping['forced_encoding'] is not None:
detected_encoding = mapping['forced_encoding']
@ -70,9 +77,20 @@ def extract_and_process_csv_przelewy24_transactions(csv_file_path, bank_statemen
except Exception as e:
print(f"Error processing {csv_file_path}: {e}")
try:
with open(refunds_file_path, mode="r", encoding=detected_encoding) as csv_file:
reader = csv.DictReader(csv_file, delimiter=mapping['delimiter'])
for row in reader:
payout_number = row["ID wypłaty"] # Get payout number from column "N"
grouped_data_refunds[payout_number].append(row) # Store row under its payout number
except Exception as e:
print(f"Error processing {refunds_file_path}: {e}")
for payout_number, rows in grouped_data.items():
try:
transformed_data = convert_csv_to_gpc_przelewy24_transactions(rows, payout_number, account_number, currency, mapping)
transformed_data = convert_csv_to_gpc_przelewy24_transactions(rows, grouped_data_refunds[payout_number], payout_number, account_number, currency, mapping)
all_transformed_data.append(transformed_data)
except Exception as e:
@ -82,15 +100,15 @@ def extract_and_process_csv_przelewy24_transactions(csv_file_path, bank_statemen
return write_output_gpc_to_zip(output_file, all_transformed_data)
def convert_csv_to_gpc_przelewy24_transactions(rows, payout_id, account_number, currency, mapping):
def convert_csv_to_gpc_przelewy24_transactions(rows, refunds, payout_id, account_number, currency, mapping):
gpc_lines = []
global transactions_df
total_payout = 0.0
total_payout_debet = 0.0
total_payout_credit = 0.0
total_payout_abs = 0.0
total_payout = 0
total_payout_debet = 0
total_payout_credit = 0
total_payout_abs = 0
first = True
clearing_id = ""
created_on = None
@ -153,14 +171,17 @@ def convert_csv_to_gpc_przelewy24_transactions(rows, payout_id, account_number,
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
if refund_amount_cents != 0:
corresponding_transaction = search_bank_transaction(payout_id)
for ref in refunds:
refund_reference = extract_order_number(ref['Opis transakcji'])
gpc_data_refund = Data(
account=account_number,
payer_account=payer_account,
no=transaction_id,
balance=refund_amount_cents,
payer_account=0,
no=int(refund_reference) if refund_reference.isdigit() else 0,
balance=Decimal(ref['Kwota']),
code=TransactionCode.DEBET,
variable=int(reference) if reference.isdigit() else 0,
variable=int(refund_reference) if refund_reference.isdigit() else 0,
constant_symbol=0,
bank_code=0,
specific_symbol=0,
@ -168,23 +189,41 @@ def convert_csv_to_gpc_przelewy24_transactions(rows, payout_id, account_number,
currency="1001",
date=created_on
)
gpc_lines.append(gpc_data_refund.to_string())
total_payout += refund_amount_cents
total_payout_abs += abs(refund_amount_cents)
total_payout_debet += abs(refund_amount_cents) if transaction_code == TransactionCode.DEBET else 0
total_payout_debet += abs(Decimal(ref['Kwota']))
# use payout_id instead as variable
real_payout_amount = Decimal(corresponding_transaction['Kwota'].replace("+", "").replace("-", ""))
real_payout_amount = real_payout_amount.quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
real_payout_amount_cents = int(real_payout_amount * 100)
# poplatky
poplatek_data = Data(
account=account_number,
payer_account=0,
no=int(total_payout_credit-real_payout_amount_cents-total_payout_debet),
balance=int(total_payout_credit-real_payout_amount_cents-total_payout_debet),
code=TransactionCode.DEBET,
variable=0,
# variable=corresponding_transaction['Zpráva pro příjemce'].split(',')[-1].strip(),
constant_symbol=0,
bank_code=0,
specific_symbol=0,
client_name="CG poplatek platba",
currency="1001",
date=created_on
)
gpc_lines.append(poplatek_data.to_string())
# vyuctovani row
payout_data = Data(
account=account_number,
payer_account=95102013900000630206821286,
no=int(total_payout),
balance=total_payout,
no=int(real_payout_amount_cents),
balance=real_payout_amount_cents,
code=TransactionCode.DEBET,
variable=int(total_payout),
variable=int(real_payout_amount_cents),
# variable=corresponding_transaction['Zpráva pro příjemce'].split(',')[-1].strip(),
constant_symbol=0,
bank_code=0,

View File

@ -89,7 +89,7 @@
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
</div>
<div class="tile bg-white shadow-md rounded-lg p-4 cursor-pointer hover:bg-blue-50"
data-option="przelewy24_transactions" data-section="aviza">
data-option="przelewy24_transactions" data-section="aviza-refunds">
<h2 class="text-xl font-semibold mb-2">Przelewy24 transakce .gpc</h2>
<p class="text-gray-600 text-sm italic">Pouzijte jeden .csv soubor z transakci</p>
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
@ -137,6 +137,15 @@
</p>
</div>
<!-- Extra file input for aviza-refunds section (refund file) -->
<div id="refundFileDiv" class="mb-4 hidden">
<label class="block text-gray-700 mb-1">Nahrát soubor s refundy</label>
<input type="file" name="file_refunds" class="border p-2 w-full">
<p class="text-gray-500 text-sm">
Výpis by měl být za stejné nebo delší období, jako je soubor importu, slouží k načtení vrácených plateb.
</p>
</div>
<button type="submit" class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
Submit
</button>
@ -163,6 +172,16 @@
} else {
$('#bankStatementDiv').addClass('hidden');
}
if (section === 'aviza-refunds') {
$('#refundFileDiv').removeClass('hidden');
$('#bankStatementDiv').removeClass('hidden');
} else {
$('#refundFileDiv').addClass('hidden');
$('#bankStatementDiv').addClass('hidden');
}
$('#modal').removeClass('hidden');
});

View File

@ -30,5 +30,5 @@ def parse_date(date_str):
except ValueError:
continue # Try the next format
raise ValueError(f"Unsupported date format: {date_str}") # Raise error if none match
return datetime(Now)
# raise ValueError(f"Unsupported date format: {date_str}") # Raise error if none match
return datetime.today()