You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
7.2 KiB
229 lines
7.2 KiB
"""
|
|
Logging and utility services for Plutus payment processing application.
|
|
|
|
This module provides database logging functionality for tracking application activities,
|
|
particularly automated script executions and payment processing operations.
|
|
"""
|
|
|
|
from datetime import datetime, timezone
|
|
from typing import Optional, Union
|
|
from app import db
|
|
from models import Logs
|
|
|
|
# System user ID for automated processes
|
|
SYSTEM_USER_ID = 1
|
|
|
|
def log_activity(
|
|
user_id: int,
|
|
action: str,
|
|
entity_type: str,
|
|
entity_id: Optional[int] = None,
|
|
details: Optional[str] = None,
|
|
ip_address: Optional[str] = None
|
|
) -> Optional[int]:
|
|
"""
|
|
Log an activity to the database.
|
|
|
|
Args:
|
|
user_id (int): ID of the user performing the action (use SYSTEM_USER_ID for automated processes)
|
|
action (str): Type of action performed (e.g., 'BATCH_RUN', 'PAYMENT_PROCESSED', 'API_ACCESS')
|
|
entity_type (str): Type of entity involved (e.g., 'Batch', 'Payment', 'PaymentPlan')
|
|
entity_id (int, optional): ID of the specific entity involved
|
|
details (str, optional): Detailed description of the activity
|
|
ip_address (str, optional): IP address of the request (for web requests)
|
|
|
|
Returns:
|
|
int: ID of the created log entry, or None if failed
|
|
"""
|
|
try:
|
|
log_entry = Logs(
|
|
User_ID=user_id,
|
|
Action=action,
|
|
Entity_Type=entity_type,
|
|
Entity_ID=entity_id,
|
|
Log_Entry=details,
|
|
IP_Address=ip_address,
|
|
Added=datetime.now(timezone.utc)
|
|
)
|
|
|
|
db.session.add(log_entry)
|
|
db.session.commit()
|
|
|
|
return log_entry.id
|
|
|
|
except Exception as e:
|
|
db.session.rollback()
|
|
print(f"Failed to log activity: {e}")
|
|
return None
|
|
|
|
def log_script_start(script_name: str, mode: str, environment: str) -> Optional[int]:
|
|
"""
|
|
Log the start of a script execution.
|
|
|
|
Args:
|
|
script_name (str): Name of the script being executed
|
|
mode (str): Running mode (batch, payintent, payplan)
|
|
environment (str): Environment (live, sandbox)
|
|
|
|
Returns:
|
|
int: Log entry ID or None if failed
|
|
"""
|
|
details = f"{script_name} started in {mode} mode ({environment} environment)"
|
|
return log_activity(
|
|
user_id=SYSTEM_USER_ID,
|
|
action="SCRIPT_START",
|
|
entity_type="Script",
|
|
details=details
|
|
)
|
|
|
|
def log_script_completion(
|
|
script_name: str,
|
|
mode: str,
|
|
success_count: int = 0,
|
|
failed_count: int = 0,
|
|
total_amount: float = 0.0,
|
|
batch_ids: Optional[list] = None,
|
|
duration_seconds: Optional[float] = None,
|
|
errors: Optional[list] = None
|
|
) -> Optional[int]:
|
|
"""
|
|
Log the completion of a script execution with summary statistics.
|
|
|
|
Args:
|
|
script_name (str): Name of the script that completed
|
|
mode (str): Running mode that was executed
|
|
success_count (int): Number of successful operations
|
|
failed_count (int): Number of failed operations
|
|
total_amount (float): Total amount processed
|
|
batch_ids (list, optional): List of batch IDs created
|
|
duration_seconds (float, optional): Execution time in seconds
|
|
errors (list, optional): List of error messages encountered
|
|
|
|
Returns:
|
|
int: Log entry ID or None if failed
|
|
"""
|
|
total_operations = success_count + failed_count
|
|
success_rate = (success_count / total_operations * 100) if total_operations > 0 else 0
|
|
|
|
details_parts = [
|
|
f"{script_name} completed in {mode} mode",
|
|
f"Total operations: {total_operations}",
|
|
f"Successful: {success_count}",
|
|
f"Failed: {failed_count}",
|
|
f"Success rate: {success_rate:.1f}%"
|
|
]
|
|
|
|
if total_amount > 0:
|
|
details_parts.append(f"Total amount: ${total_amount:,.2f}")
|
|
|
|
if batch_ids:
|
|
details_parts.append(f"Batch IDs: {', '.join(map(str, batch_ids))}")
|
|
|
|
if duration_seconds:
|
|
details_parts.append(f"Duration: {duration_seconds:.1f}s")
|
|
|
|
if errors:
|
|
details_parts.append(f"Errors encountered: {len(errors)}")
|
|
if len(errors) <= 3:
|
|
details_parts.extend([f"- {error}" for error in errors])
|
|
else:
|
|
details_parts.extend([f"- {error}" for error in errors[:3]])
|
|
details_parts.append(f"... and {len(errors) - 3} more errors")
|
|
|
|
details = "\\n".join(details_parts)
|
|
|
|
action = "SCRIPT_SUCCESS" if failed_count == 0 else "SCRIPT_PARTIAL" if success_count > 0 else "SCRIPT_FAILED"
|
|
|
|
return log_activity(
|
|
user_id=SYSTEM_USER_ID,
|
|
action=action,
|
|
entity_type="Script",
|
|
details=details
|
|
)
|
|
|
|
def log_batch_created(batch_id: int, payment_method: str, customer_count: int) -> Optional[int]:
|
|
"""
|
|
Log the creation of a payment batch.
|
|
|
|
Args:
|
|
batch_id (int): ID of the created batch
|
|
payment_method (str): Payment method type (Direct Debit, Card, etc.)
|
|
customer_count (int): Number of customers in the batch
|
|
|
|
Returns:
|
|
int: Log entry ID or None if failed
|
|
"""
|
|
details = f"Payment batch created for {payment_method} with {customer_count} customers"
|
|
return log_activity(
|
|
user_id=SYSTEM_USER_ID,
|
|
action="BATCH_CREATED",
|
|
entity_type="PaymentBatch",
|
|
entity_id=batch_id,
|
|
details=details
|
|
)
|
|
|
|
def log_payment_plan_run(
|
|
active_plans: int,
|
|
due_plans: int,
|
|
processed_count: int,
|
|
failed_count: int,
|
|
total_amount: float
|
|
) -> Optional[int]:
|
|
"""
|
|
Log the results of a payment plan execution.
|
|
|
|
Args:
|
|
active_plans (int): Total number of active payment plans
|
|
due_plans (int): Number of plans due for payment today
|
|
processed_count (int): Number of payments successfully processed
|
|
failed_count (int): Number of failed payments
|
|
total_amount (float): Total amount processed
|
|
|
|
Returns:
|
|
int: Log entry ID or None if failed
|
|
"""
|
|
details = (
|
|
f"Payment plan execution: {active_plans} active plans, "
|
|
f"{due_plans} due today, {processed_count} successful, "
|
|
f"{failed_count} failed, ${total_amount:,.2f} total"
|
|
)
|
|
|
|
action = "PAYPLAN_SUCCESS" if failed_count == 0 else "PAYPLAN_PARTIAL" if processed_count > 0 else "PAYPLAN_FAILED"
|
|
|
|
return log_activity(
|
|
user_id=SYSTEM_USER_ID,
|
|
action=action,
|
|
entity_type="PaymentPlan",
|
|
details=details
|
|
)
|
|
|
|
def log_payment_intent_followup(
|
|
pending_count: int,
|
|
succeeded_count: int,
|
|
failed_count: int,
|
|
still_pending: int
|
|
) -> Optional[int]:
|
|
"""
|
|
Log the results of payment intent follow-up processing.
|
|
|
|
Args:
|
|
pending_count (int): Number of payment intents checked
|
|
succeeded_count (int): Number that succeeded
|
|
failed_count (int): Number that failed
|
|
still_pending (int): Number still pending
|
|
|
|
Returns:
|
|
int: Log entry ID or None if failed
|
|
"""
|
|
details = (
|
|
f"Payment intent follow-up: {pending_count} intents checked, "
|
|
f"{succeeded_count} succeeded, {failed_count} failed, "
|
|
f"{still_pending} still pending"
|
|
)
|
|
|
|
return log_activity(
|
|
user_id=SYSTEM_USER_ID,
|
|
action="PAYINTENT_FOLLOWUP",
|
|
entity_type="PaymentIntent",
|
|
details=details
|
|
)
|