From 5d37ba30fbb697d608637a04c9af983ece030ce6 Mon Sep 17 00:00:00 2001 From: VivianDee <115420678+VivianDee@users.noreply.github.com> Date: Fri, 25 Apr 2025 16:04:44 +0100 Subject: [PATCH] [update]: repayment schedule table --- app/api/services/provide_loan.py | 3 +- app/models/loan_repayment_schedule.py | 23 ++++------ ...b_migration_on_fri_apr_25_15_01_00_utc_.py | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 migrations/versions/2a45dd99c9cb_migration_on_fri_apr_25_15_01_00_utc_.py diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index 232466c..da25802 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -71,6 +71,7 @@ class ProvideLoanService(BaseService): upfront_fee = charges["upfront_payment"] repayment_amount = charges["repayment_amount"] installment_amount = charges["installment_amount"] + tenor = offer.tenor // 30 # Convert to months @@ -97,7 +98,7 @@ class ProvideLoanService(BaseService): db.session.flush() - schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, Offer = offer, charges = charges) + schedule = LoanRepaymentSchedule.add_repayment_schedule(loan = loan, tenor = tenor) if not schedule: diff --git a/app/models/loan_repayment_schedule.py b/app/models/loan_repayment_schedule.py index 1eafb46..6fed08c 100644 --- a/app/models/loan_repayment_schedule.py +++ b/app/models/loan_repayment_schedule.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +from itertools import product from app.extensions import db from sqlalchemy.orm import relationship from dateutil.relativedelta import relativedelta @@ -8,13 +9,14 @@ class LoanRepaymentSchedule(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) loan_id = db.Column(db.Integer, nullable=False) + product_id = db.Column(db.String(20), nullable=True) installment_number = db.Column(db.Integer, nullable=False) due_date = db.Column(db.DateTime, nullable=False) - principal_amount = db.Column(db.Float, default=0.0) - interest_amount = db.Column(db.Float, default=0.0) - total_installment = db.Column(db.Float, default=0.0) + installment_amount= db.Column(db.Float, default=0.0) + total_repayment_amount = db.Column(db.Float, default=0.0) paid = db.Column(db.Boolean, default=False) paid_at = db.Column(db.DateTime, nullable=True) + created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) @@ -27,19 +29,12 @@ class LoanRepaymentSchedule(db.Model): @classmethod - def add_repayment_schedule(cls, loan, Offer, charges): + def add_repayment_schedule(cls, loan, tenor): """ Add repayment schedules for a given loan. """ - now = datetime.now(timezone.utc) schedules = [] - interest_fee = charges["interest"] - - tenor = Offer.tenor // 30 - - principal = loan.initial_loan_amount / tenor - interest = interest_fee["fee"] / tenor for i in range(tenor): due_date = now + relativedelta(months=i + 1) @@ -47,9 +42,9 @@ class LoanRepaymentSchedule(db.Model): loan_id=loan.id, installment_number=i + 1, due_date=due_date, - principal_amount=round(principal, 2), - interest_amount=round(interest, 2), - total_installment=round(loan.installment_amount, 2) + total_repayment_amount = round(loan.repayment_amount, 2), + installment_amount=round(loan.installment_amount, 2), + product_id = loan.product_id ) db.session.add(schedule) diff --git a/migrations/versions/2a45dd99c9cb_migration_on_fri_apr_25_15_01_00_utc_.py b/migrations/versions/2a45dd99c9cb_migration_on_fri_apr_25_15_01_00_utc_.py new file mode 100644 index 0000000..7b388b5 --- /dev/null +++ b/migrations/versions/2a45dd99c9cb_migration_on_fri_apr_25_15_01_00_utc_.py @@ -0,0 +1,42 @@ +"""Migration on Fri Apr 25 15:01:00 UTC 2025 + +Revision ID: 2a45dd99c9cb +Revises: 2cf0c177ca02 +Create Date: 2025-04-25 15:01:51.129681 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '2a45dd99c9cb' +down_revision = '2cf0c177ca02' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('loan_repayment_schedules', schema=None) as batch_op: + batch_op.add_column(sa.Column('product_id', sa.String(length=20), nullable=True)) + batch_op.add_column(sa.Column('installment_amount', sa.Float(), nullable=True)) + batch_op.add_column(sa.Column('total_repayment_amount', sa.Float(), nullable=True)) + batch_op.drop_column('principal_amount') + batch_op.drop_column('interest_amount') + batch_op.drop_column('total_installment') + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('loan_repayment_schedules', schema=None) as batch_op: + batch_op.add_column(sa.Column('total_installment', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column('interest_amount', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True)) + batch_op.add_column(sa.Column('principal_amount', sa.DOUBLE_PRECISION(precision=53), autoincrement=False, nullable=True)) + batch_op.drop_column('total_repayment_amount') + batch_op.drop_column('installment_amount') + batch_op.drop_column('product_id') + + # ### end Alembic commands ###