przelewy, packeta comgate
This commit is contained in:
parent
14a7239068
commit
02f7bfdc9f
14
app_main.py
14
app_main.py
@ -67,6 +67,16 @@ def index():
|
|||||||
except:
|
except:
|
||||||
print("no bank_statement")
|
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"))
|
day_of_year = int(datetime.date.today().strftime("%j"))
|
||||||
out_filename = f"{option}_vypis_{day_of_year}.gpc"
|
out_filename = f"{option}_vypis_{day_of_year}.gpc"
|
||||||
mimetype = "text/plain"
|
mimetype = "text/plain"
|
||||||
@ -153,13 +163,13 @@ def index():
|
|||||||
)
|
)
|
||||||
elif option == "przelewy24_transactions":
|
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,
|
account_number=3498710000999133,
|
||||||
currency="PLN", mapping=mapping_przelewy_transactions)
|
currency="PLN", mapping=mapping_przelewy_transactions)
|
||||||
|
|
||||||
return send_file(
|
return send_file(
|
||||||
result_data,
|
result_data,
|
||||||
download_name=f"przelewy24_auto_{day_of_year}.zip",
|
download_name=f"przelewy24_transactions_{day_of_year}.zip",
|
||||||
as_attachment=True,
|
as_attachment=True,
|
||||||
mimetype="application/zip"
|
mimetype="application/zip"
|
||||||
)
|
)
|
||||||
|
@ -20,33 +20,40 @@ def load_bank_transactions(csv_file):
|
|||||||
:param csv_file: Path to the bank transactions CSV file.
|
:param csv_file: Path to the bank transactions CSV file.
|
||||||
:return: A pandas DataFrame containing the transactions.
|
: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
|
df = pd.read_csv(csv_file, delimiter=',', dtype=str, encoding=encoding)
|
||||||
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'.")
|
|
||||||
|
|
||||||
return df
|
return df
|
||||||
|
|
||||||
|
|
||||||
def search_bank_transaction(search_string):
|
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 specified column.
|
||||||
: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.
|
:return: The first matching row as a dictionary or None if not found.
|
||||||
"""
|
"""
|
||||||
global transactions_df
|
global transactions_df
|
||||||
matching_row = transactions_df[transactions_df['Zpráva pro příjemce'].str.contains(search_string, na=False, case=False)]
|
# 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)
|
||||||
return matching_row.iloc[0].to_dict() if not matching_row.empty else None
|
# 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
|
global transactions_df
|
||||||
transactions_df = load_bank_transactions(bank_statement_file_path)
|
transactions_df = load_bank_transactions(bank_statement_file_path)
|
||||||
all_transformed_data = []
|
all_transformed_data = []
|
||||||
grouped_data = defaultdict(list)
|
grouped_data = defaultdict(list)
|
||||||
|
grouped_data_refunds = defaultdict(list)
|
||||||
|
|
||||||
if mapping['forced_encoding'] is not None:
|
if mapping['forced_encoding'] is not None:
|
||||||
detected_encoding = mapping['forced_encoding']
|
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:
|
except Exception as e:
|
||||||
print(f"Error processing {csv_file_path}: {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():
|
for payout_number, rows in grouped_data.items():
|
||||||
try:
|
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)
|
all_transformed_data.append(transformed_data)
|
||||||
|
|
||||||
except Exception as e:
|
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)
|
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 = []
|
gpc_lines = []
|
||||||
global transactions_df
|
global transactions_df
|
||||||
|
|
||||||
|
|
||||||
total_payout = 0.0
|
total_payout = 0
|
||||||
total_payout_debet = 0.0
|
total_payout_debet = 0
|
||||||
total_payout_credit = 0.0
|
total_payout_credit = 0
|
||||||
total_payout_abs = 0.0
|
total_payout_abs = 0
|
||||||
first = True
|
first = True
|
||||||
clearing_id = ""
|
clearing_id = ""
|
||||||
created_on = None
|
created_on = None
|
||||||
@ -153,38 +171,59 @@ 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_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
|
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)
|
||||||
gpc_data_refund = Data(
|
|
||||||
account=account_number,
|
|
||||||
payer_account=payer_account,
|
|
||||||
no=transaction_id,
|
|
||||||
balance=refund_amount_cents,
|
|
||||||
code=TransactionCode.DEBET,
|
|
||||||
variable=int(reference) if reference.isdigit() else 0,
|
|
||||||
constant_symbol=0,
|
|
||||||
bank_code=0,
|
|
||||||
specific_symbol=0,
|
|
||||||
client_name="CG refundace",
|
|
||||||
currency="1001",
|
|
||||||
date=created_on
|
|
||||||
)
|
|
||||||
|
|
||||||
gpc_lines.append(gpc_data_refund.to_string())
|
for ref in refunds:
|
||||||
total_payout += refund_amount_cents
|
refund_reference = extract_order_number(ref['Opis transakcji'])
|
||||||
total_payout_abs += abs(refund_amount_cents)
|
gpc_data_refund = Data(
|
||||||
total_payout_debet += abs(refund_amount_cents) if transaction_code == TransactionCode.DEBET else 0
|
account=account_number,
|
||||||
|
payer_account=0,
|
||||||
|
no=int(refund_reference) if refund_reference.isdigit() else 0,
|
||||||
|
balance=Decimal(ref['Kwota']),
|
||||||
|
code=TransactionCode.DEBET,
|
||||||
|
variable=int(refund_reference) if refund_reference.isdigit() else 0,
|
||||||
|
constant_symbol=0,
|
||||||
|
bank_code=0,
|
||||||
|
specific_symbol=0,
|
||||||
|
client_name="CG refundace",
|
||||||
|
currency="1001",
|
||||||
|
date=created_on
|
||||||
|
)
|
||||||
|
gpc_lines.append(gpc_data_refund.to_string())
|
||||||
|
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
|
# vyuctovani row
|
||||||
payout_data = Data(
|
payout_data = Data(
|
||||||
account=account_number,
|
account=account_number,
|
||||||
payer_account=95102013900000630206821286,
|
payer_account=95102013900000630206821286,
|
||||||
no=int(total_payout),
|
no=int(real_payout_amount_cents),
|
||||||
balance=total_payout,
|
balance=real_payout_amount_cents,
|
||||||
code=TransactionCode.DEBET,
|
code=TransactionCode.DEBET,
|
||||||
variable=int(total_payout),
|
variable=int(real_payout_amount_cents),
|
||||||
# variable=corresponding_transaction['Zpráva pro příjemce'].split(',')[-1].strip(),
|
# variable=corresponding_transaction['Zpráva pro příjemce'].split(',')[-1].strip(),
|
||||||
constant_symbol=0,
|
constant_symbol=0,
|
||||||
bank_code=0,
|
bank_code=0,
|
||||||
|
@ -89,7 +89,7 @@
|
|||||||
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
|
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile bg-white shadow-md rounded-lg p-4 cursor-pointer hover:bg-blue-50"
|
<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>
|
<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 italic">Pouzijte jeden .csv soubor z transakci</p>
|
||||||
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
|
<p class="text-gray-600 text-sm">.gpc aviza pro Przelewy24</p>
|
||||||
@ -137,6 +137,15 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</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">
|
<button type="submit" class="w-full bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
|
||||||
Submit
|
Submit
|
||||||
</button>
|
</button>
|
||||||
@ -163,6 +172,16 @@
|
|||||||
} else {
|
} else {
|
||||||
$('#bankStatementDiv').addClass('hidden');
|
$('#bankStatementDiv').addClass('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (section === 'aviza-refunds') {
|
||||||
|
$('#refundFileDiv').removeClass('hidden');
|
||||||
|
$('#bankStatementDiv').removeClass('hidden');
|
||||||
|
} else {
|
||||||
|
$('#refundFileDiv').addClass('hidden');
|
||||||
|
$('#bankStatementDiv').addClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$('#modal').removeClass('hidden');
|
$('#modal').removeClass('hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
4
utils.py
4
utils.py
@ -30,5 +30,5 @@ def parse_date(date_str):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
continue # Try the next format
|
continue # Try the next format
|
||||||
|
|
||||||
raise ValueError(f"Unsupported date format: {date_str}") # Raise error if none match
|
# raise ValueError(f"Unsupported date format: {date_str}") # Raise error if none match
|
||||||
return datetime(Now)
|
return datetime.today()
|
||||||
|
Loading…
Reference in New Issue
Block a user