gpc-generator/aviza/packeta_comgate_convert.py
2025-03-11 14:12:38 +01:00

229 lines
8.8 KiB
Python

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
def extract_and_process_zip_packeta2comgate(zip_file_path, output_file, mapping):
all_transformed_data = []
# Create a temporary folder for extraction
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 provided outer zip file
with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
zip_ref.extractall(extract_folder)
currency_folders = {
"EUR": {"currency": "EUR", "account_number": "3498710000999125"},
"HUF": {"currency": "HUF", "account_number": "3498710000999141"},
"RON": {"currency": "RON", "account_number": "3498710000999149"},
}
all_transformed_data = []
# Walk through extract_folder to find the currency folders
for root, dirs, files in os.walk(extract_folder):
for folder in dirs:
if folder in currency_folders:
folder_path = os.path.join(root, folder)
currency_info = currency_folders[folder]
currency = currency_info["currency"]
account_number = currency_info["account_number"]
# Process CSV files inside the currency folder
for file in os.listdir(folder_path):
if file.endswith(".csv") and not file.startswith("._"):
file_path = os.path.join(folder_path, file)
try:
transformed_data = convert_payu2comgate(file_path, account_number, currency, mapping)
all_transformed_data.append(transformed_data)
except Exception as e:
print(f"Error processing {file}: {e}")
# Clean up the outer extraction folder
shutil.rmtree(extract_folder)
print(f"Processed and cleaned up: {zip_file_path}")
# Return a ZIP archive (in memory) containing all the output CSV files.
return write_output_gpc_to_zip(output_file, all_transformed_data)
def convert_payu2comgate(csv_file_path, account_number, currency, mapping):
gpc_lines = []
if mapping['forced_encoding'] is not None:
detected_encoding = mapping['forced_encoding']
print(f"Forced encoding: {detected_encoding}")
else:
with open(csv_file_path, 'rb') as f:
rawdata = f.read(1024) # Read a small part of the file
result = chardet.detect(rawdata)
detected_encoding = result['encoding']
print(f"Detected encoding: {detected_encoding}")
with open(csv_file_path, mode='r', encoding=detected_encoding) as csv_file:
reader = csv.DictReader(csv_file, delimiter=mapping['delimiter']) if mapping['is_dict_mapping'] else csv.reader(
csv_file, delimiter=mapping['delimiter'])
if not mapping['is_dict_mapping']:
next(reader)
rows = list(reader) # Convert to list to easily access the last row
if not rows: # Ensure there's at least one row
raise ValueError("CSV file is empty after processing.")
total_payout = 0.0
total_payout_debet = 0.0
total_payout_credit = 0.0
total_payout_abs = 0.0
first = True
created_on = None
for row in rows[:-1]:
if first:
first = False
reference = extract_order_number(row[mapping['reference']])
transaction_id = extract_numbers(row[mapping['transaction_id']]) if mapping['use_transaction_id'] else reference
direction = row[mapping['direction']].lower() if mapping['direction'] is not None else None
source_name = row[mapping['source_name']].replace("Nazwa nadawcy: ", "")[:20].ljust(20) if mapping['use_source_name'] else ""
payer_account = extract_numbers(row[mapping['payer_account']].replace("Rachunek nadawcy: ", "").replace(" ", ""))[:16].ljust(16) if mapping['payer_number_exists'] else 0
if payer_account != 0:
if payer_account.strip() == "":
payer_account = 0
created_on = parse_date(row[mapping['created_on']])
# Convert the value using Decimal instead of float
source_str = row[mapping['source_amount']].replace(',', '.')
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
# vyuctovani row
payout_data = Data(
account=account_number,
payer_account=account_number,
no=int(rows[-1]['ID transakce']),
balance=total_payout,
code=TransactionCode.DEBET,
variable=int(rows[-1]['ID transakce']),
# 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=created_on
)
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")
mapping_payu = {
'transaction_id': 'ID transakce',
'reference': 'ID objednávky',
'direction': None,
'source_name': 'Jméno a příjmení',
'source_amount': 'Částka',
'source_currency': 'Měna',
'payer_account': None,
'created_on': 'Datum',
'fees': 'Provize',
'delimiter': ";",
'is_dict_mapping': True,
'use_transaction_id': True,
'payer_number_exists': False,
'use_source_name': False,
'forced_encoding': "windows-1250"
}
# Example usage:
# convert_csv_to_gpc("../Specification clearing 2024-05-10.csv", "avizo_przelewy24_test.gpc", account_number=3498710000999117, currency="EUR", mapping=mapping_przelewy24_avizo)
# convert_csv_to_gpc("pko_input.csv", "pko_output.gpc", account_number=95102013900000630206821286, currency="PLN", mapping=mapping_pko)
# convert_csv_to_gpc("sparkasse_input.csv", "sparkasse_output.gpc", account_number=95850503000221267034, currency="EUR", mapping=mapping_sparkasse)