Files
upi_inward_file_based/db/repository.py
T
2026-06-13 14:58:21 +05:30

201 lines
5.9 KiB
Python

#!/usr/bin/env python3
"""
Data access layer for UPI inward file processing.
Handles CRUD operations and transaction management.
"""
from typing import List, Optional
from logging_config import get_logger
from .oracle_connector import get_connector
from .models import UPIInwardRecord, ProcessedFile
logger = get_logger(__name__)
class Repository:
"""Data access layer for UPI inward processing."""
def __init__(self):
self.connector = get_connector()
# ---------------------------------------------------------
# Account validation (same as NEFT)
# ---------------------------------------------------------
def validate_account_exists(self, account_number: str) -> bool:
if not account_number:
return False
last12 = str(account_number)[-12:]
conn = self.connector.get_connection()
try:
cursor = conn.cursor()
cursor.execute(
"SELECT COUNT(*) FROM dep_account WHERE link_accno = :accno",
{'accno': last12}
)
count = cursor.fetchone()[0]
return count > 0
except Exception as e:
logger.warning(f"Error validating account {account_number}: {e}")
return False
finally:
cursor.close()
conn.close()
# ---------------------------------------------------------
# UPDATED: UPI BULK INSERT WITH VALIDATION
# ---------------------------------------------------------
def bulk_insert_transactions(self, transactions: List[UPIInwardRecord]) -> tuple:
if not transactions:
logger.warning("No transactions to insert")
return 0, 0
valid_transactions = []
skipped_count = 0
for txn in transactions:
acct = txn.credit_account
# Condition 1: account exists
account_valid = self.validate_account_exists(acct)
# Condition 2: only CREDIT transactions
is_credit = (txn.txn_type == "CREDIT")
if account_valid and is_credit:
# Force DB value to CR
txn.txn_type = "CR"
valid_transactions.append(txn)
else:
skipped_count += 1
if not valid_transactions:
logger.info(f"All {skipped_count} transactions skipped")
return 0, skipped_count
conn = self.connector.get_connection()
cursor = None
try:
cursor = conn.cursor()
batch_data = [txn.to_dict() for txn in valid_transactions]
logger.info(batch_data)
insert_sql = """
INSERT INTO pacs_db.upi_inward_api_log (
BANKCODE,
RRN,
TXN_DATE,
TXN_AMT,
TXN_TYPE,
CREDIT_ACCOUNT,
STATUS,
NOTE
) VALUES (
:BANKCODE,
:RRN,
:TXN_DATE,
:TXN_AMT,
:TXN_TYPE,
:CREDIT_ACCOUNT,
:STATUS,
:NOTE
)
"""
cursor.executemany(insert_sql, batch_data)
logger.info(f"executemany rowcount: {cursor.rowcount}")
conn.commit()
logger.info("UPI transactions committed successfully")
inserted_count = len(valid_transactions)
logger.info(f"Inserted {inserted_count} UPI transactions")
return inserted_count, skipped_count
except Exception as e:
if conn:
conn.rollback()
logger.error(f"Error inserting UPI transactions: {e}", exc_info=True)
raise
finally:
if cursor:
cursor.close()
conn.close()
# ---------------------------------------------------------
# FILE TRACKING (UNCHANGED)
# ---------------------------------------------------------
def is_file_processed(self, filename: str, bankcode: str) -> bool:
conn = self.connector.get_connection()
cursor = None
try:
cursor = conn.cursor()
cursor.execute(
"""
SELECT COUNT(*)
FROM neft_processed_files
WHERE filename = :filename
AND bankcode = :bankcode
""",
{'filename': filename, 'bankcode': bankcode}
)
count = cursor.fetchone()[0]
return count > 0
except Exception as e:
logger.error(f"Error checking processed file: {e}", exc_info=True)
return False
finally:
if cursor:
cursor.close()
conn.close()
def mark_file_processed(self, processed_file: ProcessedFile) -> bool:
conn = self.connector.get_connection()
cursor = None
try:
cursor = conn.cursor()
file_data = processed_file.to_dict()
insert_sql = """
INSERT INTO neft_processed_files (
filename, bankcode, file_path, transaction_count,
status, error_message, processed_at
) VALUES (
:filename, :bankcode, :file_path, :transaction_count,
:status, :error_message, :processed_at
)
"""
cursor.execute(insert_sql, file_data)
conn.commit()
logger.info(f"Marked file as processed: {processed_file.filename}")
return True
except Exception as e:
if conn:
conn.rollback()
logger.error(f"Error marking file as processed: {e}", exc_info=True)
return False
finally:
if cursor:
cursor.close()
conn.close()