Merge branch 'Response_fix' of DigiFi/digifi-BankToProductCore into master

This commit is contained in:
2025-05-16 19:21:59 +00:00
committed by Gogs
12 changed files with 286 additions and 31 deletions
+3 -2
View File
@@ -2,6 +2,7 @@ from datetime import datetime, timezone
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from app.extensions import db from app.extensions import db
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.sql import func
class Account(db.Model): class Account(db.Model):
__tablename__ = 'accounts' __tablename__ = 'accounts'
@@ -11,8 +12,8 @@ class Account(db.Model):
account_type = db.Column(db.String(50)) account_type = db.Column(db.String(50))
status = db.Column(db.String(20), default='active') status = db.Column(db.String(20), default='active')
lien_amount = db.Column(db.Float, default=0.0) lien_amount = db.Column(db.Float, default=0.0)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
customer = relationship( customer = relationship(
"Customer", "Customer",
+3 -3
View File
@@ -1,6 +1,7 @@
from datetime import datetime, timezone, timedelta from datetime import datetime, timezone, timedelta
from app.extensions import db from app.extensions import db
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
class Charge(db.Model): class Charge(db.Model):
@@ -12,9 +13,8 @@ class Charge(db.Model):
percent = db.Column(db.Float, default=0.0) percent = db.Column(db.Float, default=0.0)
description = db.Column(db.Text, nullable=True) description = db.Column(db.Text, nullable=True)
due = db.Column(db.Integer, nullable=False) due = db.Column(db.Integer, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
offer = relationship( offer = relationship(
"Offer", "Offer",
primaryjoin="Charge.offer_id == Offer.id", primaryjoin="Charge.offer_id == Offer.id",
+3 -3
View File
@@ -3,6 +3,7 @@ from sqlalchemy.orm import relationship
from app.extensions import db from app.extensions import db
from app.models.account import Account from app.models.account import Account
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.sql import func
class Customer(db.Model): class Customer(db.Model):
__tablename__ = 'customers' __tablename__ = 'customers'
@@ -10,9 +11,8 @@ class Customer(db.Model):
id = db.Column(db.String(50), primary_key=True) id = db.Column(db.String(50), primary_key=True)
msisdn = db.Column(db.String(20), unique=True, nullable=False) msisdn = db.Column(db.String(20), unique=True, nullable=False)
country_code = db.Column(db.String(3), nullable=False) country_code = db.Column(db.String(3), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
accounts = relationship( accounts = relationship(
"Account", "Account",
primaryjoin="Customer.id == Account.customer_id", primaryjoin="Customer.id == Account.customer_id",
+3 -2
View File
@@ -8,6 +8,7 @@ from dateutil.relativedelta import relativedelta
from datetime import timedelta from datetime import timedelta
import logging import logging
from sqlalchemy import and_, or_, not_ from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import func
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -37,8 +38,8 @@ class Loan(db.Model):
status = db.Column(db.String(20), default='pending') status = db.Column(db.String(20), default='pending')
tenor = db.Column(db.Integer, nullable=True) tenor = db.Column(db.Integer, nullable=True)
due_date = db.Column(db.DateTime, nullable=True) due_date = db.Column(db.DateTime, nullable=True)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
eligible_amount = db.Column(db.Float, nullable=True, default=0.0) eligible_amount = db.Column(db.Float, nullable=True, default=0.0)
disburse_date = db.Column(db.DateTime, nullable=True) disburse_date = db.Column(db.DateTime, nullable=True)
disburse_verify = db.Column(db.DateTime, nullable=True) disburse_verify = db.Column(db.DateTime, nullable=True)
+3 -3
View File
@@ -2,6 +2,7 @@ from datetime import datetime, timezone, timedelta
from app.extensions import db from app.extensions import db
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from app.utils.logger import logger from app.utils.logger import logger
from sqlalchemy.sql import func
class LoanCharge(db.Model): class LoanCharge(db.Model):
@@ -16,9 +17,8 @@ class LoanCharge(db.Model):
description = db.Column(db.Text, nullable=True) description = db.Column(db.Text, nullable=True)
due = db.Column(db.Integer, nullable=False) due = db.Column(db.Integer, nullable=False)
due_date = db.Column(db.DateTime, nullable=True) due_date = db.Column(db.DateTime, nullable=True)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
loan = relationship( loan = relationship(
"Loan", "Loan",
primaryjoin="LoanCharge.loan_id == Loan.id", primaryjoin="LoanCharge.loan_id == Loan.id",
+3 -3
View File
@@ -2,6 +2,7 @@ from datetime import datetime, timezone
from app.extensions import db from app.extensions import db
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from sqlalchemy.sql import func
class LoanRepaymentSchedule(db.Model): class LoanRepaymentSchedule(db.Model):
__tablename__ = 'loan_repayment_schedules' __tablename__ = 'loan_repayment_schedules'
@@ -17,9 +18,8 @@ class LoanRepaymentSchedule(db.Model):
paid = db.Column(db.Boolean, default=False) paid = db.Column(db.Boolean, default=False)
paid_at = db.Column(db.DateTime, nullable=True) paid_at = db.Column(db.DateTime, nullable=True)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
loan = relationship( loan = relationship(
"Loan", "Loan",
primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id", primaryjoin="LoanRepaymentSchedule.loan_id == Loan.id",
+3 -3
View File
@@ -2,6 +2,7 @@ from datetime import datetime, timezone
from app.extensions import db from app.extensions import db
from app.models.charge import Charge from app.models.charge import Charge
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
class Offer(db.Model): class Offer(db.Model):
__tablename__ = 'offers' __tablename__ = 'offers'
@@ -17,9 +18,8 @@ class Offer(db.Model):
insurance_rate = db.Column(db.Float, default=1.0) insurance_rate = db.Column(db.Float, default=1.0)
vat_rate = db.Column(db.Float, default=7.5) vat_rate = db.Column(db.Float, default=7.5)
list_order = db.Column(db.Integer, nullable=True) list_order = db.Column(db.Integer, nullable=True)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
charges = relationship( charges = relationship(
"Charge", "Charge",
primaryjoin="Offer.id == Charge.offer_id", primaryjoin="Offer.id == Charge.offer_id",
+3 -3
View File
@@ -4,6 +4,7 @@ from sqlalchemy.orm import relationship
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from uuid import uuid4 from uuid import uuid4
from sqlalchemy.types import JSON from sqlalchemy.types import JSON
from sqlalchemy.sql import func
class RACCheck(db.Model): class RACCheck(db.Model):
__tablename__ = 'rac_checks' __tablename__ = 'rac_checks'
@@ -13,9 +14,8 @@ class RACCheck(db.Model):
customer_id = db.Column(db.String, nullable=False) customer_id = db.Column(db.String, nullable=False)
account_id = db.Column(db.String, nullable=False) account_id = db.Column(db.String, nullable=False)
rac_response = db.Column(db.JSON, nullable=False) rac_response = db.Column(db.JSON, nullable=False)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
@classmethod @classmethod
def add_rac_check(cls, customer_id, account_id, transaction_id, data = None): def add_rac_check(cls, customer_id, account_id, transaction_id, data = None):
+3 -2
View File
@@ -4,6 +4,7 @@ from app.extensions import db
from app.models.customer import Customer from app.models.customer import Customer
from app.models.loan import Loan from app.models.loan import Loan
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.sql import func
class Repayment(db.Model): class Repayment(db.Model):
@@ -17,8 +18,8 @@ class Repayment(db.Model):
loan_id = db.Column(db.String(50), nullable=False) loan_id = db.Column(db.String(50), nullable=False)
customer_id = db.Column(db.String(50), nullable=False) customer_id = db.Column(db.String(50), nullable=False)
product_id = db.Column(db.String(20), nullable=True) product_id = db.Column(db.String(20), nullable=True)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
transaction_id = db.Column(db.String(50), nullable=True) transaction_id = db.Column(db.String(50), nullable=True)
@classmethod @classmethod
+3 -3
View File
@@ -3,6 +3,7 @@ from app.extensions import db
from app.models import account from app.models import account
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy import and_, or_, not_ from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import func
class Transaction(db.Model): class Transaction(db.Model):
__tablename__ = 'transactions' __tablename__ = 'transactions'
@@ -16,9 +17,8 @@ class Transaction(db.Model):
customer_id = db.Column(db.String(50), nullable=True) customer_id = db.Column(db.String(50), nullable=True)
type = db.Column(db.String(50), nullable=False) type = db.Column(db.String(50), nullable=False)
channel = db.Column(db.String(50), nullable=False) channel = db.Column(db.String(50), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
def __repr__(self): def __repr__(self):
return f'<Transaction {self.id}>' return f'<Transaction {self.id}>'
+6 -4
View File
@@ -1,9 +1,12 @@
from datetime import datetime, timezone from datetime import datetime, timezone
from app.extensions import db from app.extensions import db
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
import logging import logging
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class TransactionOffer(db.Model): class TransactionOffer(db.Model):
__tablename__ = 'transaction_offers' __tablename__ = 'transaction_offers'
@@ -18,9 +21,8 @@ class TransactionOffer(db.Model):
eligible_amount = db.Column(db.Float, nullable=True) eligible_amount = db.Column(db.Float, nullable=True)
tenor = db.Column(db.Integer, nullable=True) # tenor in months, typically tenor = db.Column(db.Integer, nullable=True) # tenor in months, typically
created_at = db.Column(db.DateTime, default=datetime.now(timezone.utc)) created_at = db.Column(db.DateTime(timezone=True), server_default=func.now())
updated_at = db.Column(db.DateTime, default=datetime.now(timezone.utc), onupdate=datetime.now(timezone.utc)) updated_at = db.Column(db.DateTime(timezone=True), onupdate=func.now())
customer = relationship( customer = relationship(
"Customer", "Customer",
primaryjoin="Customer.id == TransactionOffer.customer_id", primaryjoin="Customer.id == TransactionOffer.customer_id",
@@ -34,7 +36,7 @@ class TransactionOffer(db.Model):
transaction_offer = cls.query.filter_by( transaction_offer = cls.query.filter_by(
id = transaction_offer, id = transaction_offer,
customer_id = customer_id, customer_id = customer_id,
# product_id = product_id product_id = product_id
# transaction_id = transaction_id, # transaction_id = transaction_id,
).first() ).first()
+250
View File
@@ -0,0 +1,250 @@
"""empty message
Revision ID: 2eee4157505f
Revises: 565bc3d0ba6e
Create Date: 2025-05-16 13:24:41.914400
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '2eee4157505f'
down_revision = '565bc3d0ba6e'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('accounts', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('charges', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('customers', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('loan_charges', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('loan_repayment_schedules', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('loans', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('offers', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('rac_checks', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('repayments', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('transaction_offers', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True)
with op.batch_alter_table('transactions', schema=None) as batch_op:
batch_op.alter_column('created_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True,
existing_server_default=sa.text('now()'))
batch_op.alter_column('updated_at',
existing_type=postgresql.TIMESTAMP(),
type_=sa.DateTime(timezone=True),
existing_nullable=True,
existing_server_default=sa.text('now()'))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('transactions', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True,
existing_server_default=sa.text('now()'))
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True,
existing_server_default=sa.text('now()'))
with op.batch_alter_table('transaction_offers', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('repayments', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('rac_checks', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('offers', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('loans', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('loan_repayment_schedules', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('loan_charges', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('customers', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('charges', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
with op.batch_alter_table('accounts', schema=None) as batch_op:
batch_op.alter_column('updated_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
batch_op.alter_column('created_at',
existing_type=sa.DateTime(timezone=True),
type_=postgresql.TIMESTAMP(),
existing_nullable=True)
# ### end Alembic commands ###