diff --git a/app/api/schemas/repayment.py b/app/api/schemas/repayment.py index 0a393b9..90e1b61 100644 --- a/app/api/schemas/repayment.py +++ b/app/api/schemas/repayment.py @@ -10,3 +10,4 @@ class RepaymentSchema(Schema): accountId = fields.Str(required=True) customerId = fields.Str(required=True) channel = fields.Str(required=True) + initiatedBy = fields.Str(required=False) diff --git a/app/api/services/loan_status.py b/app/api/services/loan_status.py index 704b2d4..c6c688d 100644 --- a/app/api/services/loan_status.py +++ b/app/api/services/loan_status.py @@ -30,8 +30,10 @@ class LoanStatusService(BaseService): validated_data = LoanStatusService.validate_data(data, LoanStatusSchema()) customer_id = validated_data.get('customerId') + logger.info(f"Looking for customer *** {customer_id}") customer = Customer.get_customer_with_loan_list(customer_id) + transactionId = validated_data.get('transactionId') account_id = validated_data.get('accountId') diff --git a/app/api/services/provide_loan.py b/app/api/services/provide_loan.py index 31eefba..61b2a16 100644 --- a/app/api/services/provide_loan.py +++ b/app/api/services/provide_loan.py @@ -109,6 +109,9 @@ class ProvideLoanService(BaseService): insurance = charges["insurance"] vat = charges["vat"] + padded_id = str(transaction_id).zfill(12) + loan_ref = f"{padded_id}{channel}{offer.product_id}" + # Save the loan details loan = Loan.create_loan( @@ -126,6 +129,7 @@ class ProvideLoanService(BaseService): eligible_amount=eligible_amount, status = LoanStatus.ACTIVE, tenor = offer.tenor, + reference = loan_ref ) if not loan: @@ -155,14 +159,12 @@ class ProvideLoanService(BaseService): else: return ResponseHelper.error(result_description="Invalid Customer or Account") - padded_id = str(transaction_id).zfill(12) - loanref = f"{padded_id}{channel}{offer.product_id}" - + response_data = { "requestId": request_id, "transactionId": transaction_id, - "loanRef": loanref, + "loanRef": loan_ref, "customerId": customer_id, "accountId": account_id, "msisdn": customer.msisdn diff --git a/app/api/services/repayment.py b/app/api/services/repayment.py index 4e224aa..c580b60 100644 --- a/app/api/services/repayment.py +++ b/app/api/services/repayment.py @@ -36,6 +36,7 @@ class RepaymentService(BaseService): account_id = validated_data.get('accountId') customer = Customer.get_customer_with_loan_list(customer_id) transaction_id = validated_data.get('transactionId') + initiated_by = validated_data.get('initiatedBy') if(RepaymentService.validate_account_ownership(account_id = account_id, customer_id = customer_id)): diff --git a/app/models/loan.py b/app/models/loan.py index fd0328e..1c5d158 100644 --- a/app/models/loan.py +++ b/app/models/loan.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +from itertools import product from app.extensions import db from app.models.customer import Customer from app.models.account import Account @@ -43,6 +44,7 @@ class Loan(db.Model): eligible_amount = db.Column(db.Float, nullable=True, default=0.0) disburse_date = db.Column(db.DateTime, nullable=True) disburse_verify = db.Column(db.DateTime, nullable=True) + reference = db.Column(db.String(50), nullable=True) customer = relationship( "Customer", @@ -82,6 +84,7 @@ class Loan(db.Model): installment_amount, tenor, eligible_amount, + reference, status = "pending", ): # Check if customer exists @@ -110,6 +113,7 @@ class Loan(db.Model): tenor = tenor, status = status, eligible_amount =eligible_amount, + reference = reference, created_at=datetime.now(timezone.utc), updated_at=datetime.now(timezone.utc) ) @@ -213,6 +217,9 @@ class Loan(db.Model): """ return { 'debtId': self.id, + 'transactionId': self.transaction_id, + 'loanRef': self.reference, + 'productId': self.product_id, 'initialLoanAmount': self.initial_loan_amount, 'currentLoanAmount': self.current_loan_amount, 'defaultPenaltyFee': self.default_penalty_fee, @@ -222,6 +229,7 @@ class Loan(db.Model): 'repaymentAmount': self.repayment_amount, 'installmentAmount': self.installment_amount, 'status': self.status, + 'tenor': self.tenor, 'dueDate': self.due_date.isoformat() if self.due_date else None, 'loanDate': self.created_at.isoformat() if self.created_at else None, } diff --git a/app/models/repayment.py b/app/models/repayment.py index f9ef530..590db56 100644 --- a/app/models/repayment.py +++ b/app/models/repayment.py @@ -34,7 +34,7 @@ class Repayment(db.Model): loan = Loan.get_customer_loan(loan_id = loan_id, customer_id = customer_id) # Check that the loan is active - if loan.status != LoanStatus.ACTIVE: + if loan.status not in [LoanStatus.ACTIVE, LoanStatus.START_REPAY]: raise ValueError(f"Repayment cannot be processed. Loan status: ({loan.status})") diff --git a/migrations/versions/b3a5e10bc77e_.py b/migrations/versions/b3a5e10bc77e_.py new file mode 100644 index 0000000..8a8205a --- /dev/null +++ b/migrations/versions/b3a5e10bc77e_.py @@ -0,0 +1,32 @@ +"""empty message + +Revision ID: b3a5e10bc77e +Revises: e8dd9b841ad7 +Create Date: 2025-05-27 01:52:48.538333 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'b3a5e10bc77e' +down_revision = 'e8dd9b841ad7' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('loans', schema=None) as batch_op: + batch_op.add_column(sa.Column('reference', sa.String(length=50), nullable=True)) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('loans', schema=None) as batch_op: + batch_op.drop_column('reference') + + # ### end Alembic commands ###