""" Controller for transaction check endpoints. """ from flask import Blueprint, request, jsonify from flask.typing import ResponseReturnValue from api.middleware import api_key_required from api.models import ( TransactionCheckRequest, TransactionCheckResponse, NewTransactionCheckRequest, NewTransactionCheckResponse, TransactionData ) import logging from typing import Dict, Any # Configure logger logger = logging.getLogger(__name__) # Create blueprint transaction_bp = Blueprint('transaction', __name__) @transaction_bp.route('/TransactionCheck', methods=['POST']) @api_key_required def transaction_check() -> ResponseReturnValue: """ Endpoint to check transaction status. This method is used to double-check the response received from DisburseLoan and CollectLoan Synchronous APIs. It verifies transaction results on FirstBank. Returns: JSON response with transaction status details """ try: # Parse and validate request data = request.get_json() if not data: logger.warning("Invalid JSON payload received") return jsonify({ 'resultCode': '400', 'resultDescription': 'Invalid JSON payload' }), 400 # Validate required fields required_fields = ['counter', 'TransactionId', 'requestID', 'customerId', 'accountId', 'countryId', 'transactionType'] missing_fields = [field for field in required_fields if field not in data] if missing_fields: logger.warning(f"Missing required fields: {', '.join(missing_fields)}") return jsonify({ 'resultCode': '422', 'resultDescription': f'Missing required fields: {", ".join(missing_fields)}' }), 422 # Create request model req = TransactionCheckRequest.from_dict(data) # Process transaction check (this would connect to the business logic) # For demonstration, we'll return a mock response # Create response based on transaction type provided_amount = 0.0 collected_amount = 0.0 if req.transactionType == "Disbursement": provided_amount = 10000.0 elif req.transactionType == "Collection" or req.transactionType == "Penalty": collected_amount = 7.50 # Create response response = TransactionCheckResponse( type_field="TransactionCheckResponse", # This will be converted to $type in JSON nativeId=f"FBN20191031104405{req.customerId}", customerId=req.customerId, accountId=req.accountId, providedAmount=provided_amount, collectedAmount=collected_amount, resultCode="00", resultDescription=f"{req.transactionType} Status retrieved successfully." ) logger.info(f"Processed transaction check for {req.transactionType}, ID {req.TransactionId}") return jsonify(response.to_dict()) except Exception as e: logger.exception(f"Error processing transaction check: {str(e)}") return jsonify({ 'resultCode': '500', 'resultDescription': f'Internal server error: {str(e)}' }), 500 @transaction_bp.route('/NewTransactionCheck', methods=['POST']) @api_key_required def new_transaction_check() -> ResponseReturnValue: """ Endpoint to check status of transactions in asynchronous requests. This method is used for checking the status of transactions when Simbrella doesn't receive a callback notification within 5 minutes of the initial request. Returns: JSON response with detailed transaction status """ try: # Parse and validate request data = request.get_json() if not data: logger.warning("Invalid JSON payload received") return jsonify({ 'resultCode': '400', 'resultDescription': 'Invalid JSON payload' }), 400 # Validate required fields required_fields = ['transactionId', 'debtId', 'transactionType', 'fbnTransactionId', 'origTransactionId', 'customerId'] missing_fields = [field for field in required_fields if field not in data] if missing_fields: logger.warning(f"Missing required fields: {', '.join(missing_fields)}") return jsonify({ 'resultCode': '422', 'resultDescription': f'Missing required fields: {", ".join(missing_fields)}' }), 422 # Create request model req = NewTransactionCheckRequest.from_dict(data) # Process new transaction check (this would connect to the business logic) # For demonstration, we'll return a mock response # Create transaction data based on transaction type provided_amount = 0.0 collected_amount = 0.0 if req.transactionType == "Disbursement": provided_amount = 1000.0 result_description = "Loan Provision is successful" elif req.transactionType == "Collection": collected_amount = 500.0 result_description = "Loan Collection is successful" else: # PenalCharge collected_amount = 50.0 result_description = "Penal Charge is successful" # Create transaction data transaction_data = TransactionData( transactionId=req.origTransactionId, providedAmount=provided_amount, collectedAmount=collected_amount, resultCode="00", resultDescription=result_description ) # Create response response = NewTransactionCheckResponse( transactionId=req.transactionId, data=transaction_data.to_dict(), resultCode="00", resultDescription="SUCCESS" ) logger.info(f"Processed new transaction check for {req.transactionType}, ID {req.transactionId}") return jsonify(response.to_dict()) except Exception as e: logger.exception(f"Error processing new transaction check: {str(e)}") return jsonify({ 'resultCode': '500', 'resultDescription': f'Internal server error: {str(e)}' }), 500