added penal check query

This commit was merged in pull request #69.
This commit is contained in:
Chinenye Nmoh
2026-03-17 12:16:11 +01:00
parent bfb35e0285
commit 9386573dfd
+20 -8
View File
@@ -2,6 +2,7 @@ from datetime import datetime, timedelta, timezone
from app.extensions import db from app.extensions import db
from app.utils.logger import logger from app.utils.logger import logger
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import or_
from app.enums.repayment_schedule_status import RepaymentScheduleStatus from app.enums.repayment_schedule_status import RepaymentScheduleStatus
from app.config import settings from app.config import settings
@@ -122,17 +123,24 @@ class LoanRepaymentSchedule(db.Model):
except Exception as e: except Exception as e:
logger.error(f"Error fetching active overdue repayment schedules: {e}") logger.error(f"Error fetching active overdue repayment schedules: {e}")
return [] return []
@classmethod @classmethod
def get_overdue_repayment_schedule_with_grace_period(cls, grace_period_days, limit=None): def get_overdue_repayment_schedule_with_grace_period(cls, grace_period_days, limit=None):
"""
Get all overdue repayment schedules that are not repaid and beyond the grace period.
"""
try: try:
grace_period_date = datetime.now(timezone.utc) - timedelta(days=grace_period_days) now = datetime.now(timezone.utc)
grace_period_date = now - timedelta(days=grace_period_days)
penal_interval = timedelta(days=settings.PENAL_CHARGE_INTERVAL_DAYS)
return cls.query.filter( return cls.query.filter(
cls.due_date < grace_period_date, cls.due_date < grace_period_date,
cls.paid == False cls.paid == False,
or_(
cls.last_penal_date == None, # never penalized before
cls.last_penal_date < now - penal_interval
)
).order_by(cls.due_date.asc()).limit(limit).all() ).order_by(cls.due_date.asc()).limit(limit).all()
except Exception as e: except Exception as e:
logger.error(f"Error fetching overdue repayment schedules with grace period: {e}") logger.error(f"Error fetching overdue repayment schedules with grace period: {e}")
return [] return []
@@ -300,22 +308,26 @@ class LoanRepaymentSchedule(db.Model):
db.session.rollback() db.session.rollback()
logger.error(f"Error applying repayment for schedule {schedule_id}: {e}") logger.error(f"Error applying repayment for schedule {schedule_id}: {e}")
raise raise
from decimal import Decimal
@classmethod @classmethod
def apply_penal_to_schedule(cls, schedule_id, penal_amount): def apply_penal_to_schedule(cls, schedule_id, penal_amount):
schedule = cls.query.get(schedule_id) schedule = cls.query.get(schedule_id)
now = datetime.now(timezone.utc) now = datetime.now(timezone.utc)
penal_amount = Decimal(str(penal_amount))
current_penal = Decimal(str(schedule.penal_charge)) if schedule.penal_charge else Decimal("0")
schedule.penal_count = (schedule.penal_count or 0) + 1 schedule.penal_count = (schedule.penal_count or 0) + 1
schedule.penal_charge = (schedule.penal_charge or 0) + penal_amount schedule.penal_charge = current_penal + penal_amount
schedule.last_penal_date = now schedule.last_penal_date = now
schedule.due_process_date = now schedule.due_process_date = now
schedule.updated_at = now schedule.updated_at = now
db.session.commit() db.session.commit()
# Calculate penal charge
@classmethod @classmethod
def calculate_penal_charge(cls, schedule): def calculate_penal_charge(cls, schedule):