From 12797867803dfb8d5d0e4b5d83ad0ca388ec5824 Mon Sep 17 00:00:00 2001 From: "CHIEFSOFT\\ameye" Date: Mon, 23 Jun 2025 12:20:22 -0400 Subject: [PATCH] fis path --- .env | 8 ++- app/api/routes/routes.py | 32 ++++++++- app/api/schemas/products.py | 7 ++ app/api/schemas/user.py | 5 ++ app/api/services/__init__.py | 4 +- app/api/services/account.py | 59 +++++++++++++++++ app/api/services/products.py | 113 ++++++++++++++++++++++++++++++++ app/models/members_pending.py | 51 ++++++++++++++ app/swagger/merms_swagger.json | 2 +- app/swagger/paths/Products.json | 2 +- 10 files changed, 278 insertions(+), 5 deletions(-) create mode 100644 app/api/schemas/products.py create mode 100644 app/api/schemas/user.py create mode 100644 app/api/services/account.py create mode 100644 app/api/services/products.py create mode 100644 app/models/members_pending.py diff --git a/.env b/.env index 2a5f7c1..31b5a46 100644 --- a/.env +++ b/.env @@ -37,7 +37,13 @@ SIMBRELLA_BASE_URL="https://bank-emulator.dev.simbrellang.net" SIMBRELLA_APP_ID="app1" SIMBRELLA_API_KEY="testtest-api-key-12345" -JWT_SECRET_KEY=dce6bd64f7d7101de4f +#JWT_SECRET_KEY=dce6bd64f7d7101de4f + +MAIL_SERVER=smtp.gmail.com +MAIL_PORT= 465 +MAIL_USERNAME=message@chiefsoft.com +MAIL_PASSWORD=may12002! +JWT_SECRET_KEY=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1 # APP_PORT=14700 # FLASK_APP=project/__init__.py diff --git a/app/api/routes/routes.py b/app/api/routes/routes.py index 62a007b..bedbc48 100644 --- a/app/api/routes/routes.py +++ b/app/api/routes/routes.py @@ -2,6 +2,8 @@ from flask import Blueprint, request, jsonify, send_from_directory from app.api.services import ( LoginService, RegisterService, + AccountService, + ProductsService, EligibilityCheckService, SelectOfferService, ProvideLoanService, @@ -31,7 +33,6 @@ def cors_middleware(): """Middleware applied globally to all API routes in this blueprint""" return enforce_json() - # Swagger JSON file @api.route("/swagger.json", methods=["GET"]) def swagger_json(): @@ -59,6 +60,35 @@ def merms_register(): response = RegisterService.process_request(data) return response +@api.route("/panel/RegisterVerify", methods=["POST"]) +@jwt_required() +def merms_register_verify(): + data = request.get_json() + response = RegisterService.process_request(data) + return response + +@api.route("/panel/RegisterComplete", methods=["POST"]) +@jwt_required() +def merms_register_complete(): + data = request.get_json() + response = RegisterService.process_request(data) + return response + +@api.route("/panel/Account", methods=["GET"]) +@jwt_required() +def merms_account(): + data = request.get_json() + response = AccountService.process_request(data) + return response + +@api.route("/panel/Products", methods=["GET"]) +@jwt_required() +def merms_products(): + data = request.get_json() + response = ProductsService.process_request(data) + return response + + # EligibilityCheck Endpoint @api.route("/EligibilityCheck", methods=["POST"]) @jwt_required() diff --git a/app/api/schemas/products.py b/app/api/schemas/products.py new file mode 100644 index 0000000..443e4cb --- /dev/null +++ b/app/api/schemas/products.py @@ -0,0 +1,7 @@ +from marshmallow import Schema, fields + +class ProductsSchema(Schema): + email = fields.Str(required=True) + firstname = fields.Str(required=True) + lastname = fields.Str(required=True) + isChecked = fields.Str(required=True) diff --git a/app/api/schemas/user.py b/app/api/schemas/user.py new file mode 100644 index 0000000..c26a84d --- /dev/null +++ b/app/api/schemas/user.py @@ -0,0 +1,5 @@ +from marshmallow import Schema, fields + +class UserSchema(Schema): + token = fields.Str(required=True) + uid = fields.Str(required=True) diff --git a/app/api/services/__init__.py b/app/api/services/__init__.py index 8592877..60b9731 100644 --- a/app/api/services/__init__.py +++ b/app/api/services/__init__.py @@ -8,4 +8,6 @@ from app.api.services.notification_callback import NotificationCallbackService from app.api.services.authorization import AuthorizationService from app.api.services.offer_analysis import OfferAnalysis from app.api.services.login import LoginService -from app.api.services.register import RegisterService \ No newline at end of file +from app.api.services.register import RegisterService +from app.api.services.products import ProductsService +from app.api.services.account import AccountService \ No newline at end of file diff --git a/app/api/services/account.py b/app/api/services/account.py new file mode 100644 index 0000000..29d7619 --- /dev/null +++ b/app/api/services/account.py @@ -0,0 +1,59 @@ +from flask import session, jsonify +from app.models.loan import Loan +from app.utils.logger import logger +from app.api.services.base_service import BaseService +from app.api.schemas.eligibility_check import EligibilityCheckSchema +from marshmallow import ValidationError +from app.api.enums import TransactionType +from app.api.integrations import SimbrellaIntegration +from app.extensions import db +from app.models import Offer, RACCheck, Members +from app.api.services.offer_analysis import OfferAnalysis +from app.api.helpers.response_helper import ResponseHelper +from werkzeug.security import generate_password_hash, check_password_hash +from app.api.schemas.user import UserSchema + +import datetime +import jwt +import random +from app.config import Config + + +class AccountService(BaseService): + + @staticmethod + def process_request(data): + + try: + with db.session.begin(): + + validated_data = RegisterService.validate_data(data, UserSchema()) + # username = validated_data.get('username') + # password = validated_data.get('password') + + + # Simulate processing + response_data = { + "member_id": 0, + "uid": 0, + } + + return ResponseHelper.success(data=response_data) + + except ValidationError as err: + + logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.unprocessable_entity(result_description="Validation exception") + + except ValueError as err: + logger.error(f"{getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.error(result_description=str(err)) + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + db.session.rollback() + return ResponseHelper.internal_server_error() + + diff --git a/app/api/services/products.py b/app/api/services/products.py new file mode 100644 index 0000000..2d699bb --- /dev/null +++ b/app/api/services/products.py @@ -0,0 +1,113 @@ +from flask import session, jsonify +from app.models.loan import Loan +from app.utils.logger import logger +from app.api.services.base_service import BaseService +from app.api.schemas.eligibility_check import EligibilityCheckSchema +from marshmallow import ValidationError +from app.api.enums import TransactionType +from app.api.integrations import SimbrellaIntegration +from app.extensions import db +from app.models import Offer, RACCheck, Members +from app.api.services.offer_analysis import OfferAnalysis +from app.api.helpers.response_helper import ResponseHelper +from werkzeug.security import generate_password_hash, check_password_hash +from app.api.schemas.register import RegisterSchema +from app.api.schemas.products import ProductsSchema + +import datetime +import jwt +import random +from app.config import Config + + +class ProductsService(BaseService): + + @staticmethod + def process_request(data): + """ + Process the Login request. + + Args: + data (dict): The request data. + + Returns: + dict: A standardized response. + """ + try: + + user_id = 1 # current_user["user"]["id"] + PRODUCT_LIST = f"""SELECT p.id,p.uid,p.product_id,p.name,p.description,p.status,p.banner, + mp.status AS prov_status, + (CASE WHEN mp.status =6 THEN 'Preparing' WHEN mp.status=7 THEN 'Active' ELSE 'Activate Now' END) AS status_text + FROM products p + LEFT JOIN members_products mp ON mp.product_id = p.product_id + AND mp.member_id ={user_id} + ORDER BY p.id ASC""" + print(PRODUCT_LIST) + + with db.session.begin(): + + validated_data = RegisterService.validate_data(data, ProductsSchema()) + # username = validated_data.get('username') + # password = validated_data.get('password') + + + # Simulate processing + response_data = { + "member_id": 0, + "uid": 0, + } + + return ResponseHelper.success(data=response_data) + + except ValidationError as err: + + logger.error(f"Validation Error: {getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.unprocessable_entity(result_description="Validation exception") + + except ValueError as err: + logger.error(f"{getattr(err, 'messages', str(err))}") + db.session.rollback() + return ResponseHelper.error(result_description=str(err)) + + except Exception as e: + logger.error(f"An error occurred: {str(e)}", exc_info=True) + db.session.rollback() + return ResponseHelper.internal_server_error() + + @staticmethod + def check_loan_limits(customer_id): + """ + Checks if a customer has exceeded the loan limits for given offer. + """ + loan = Loan.get_customer_last_loan(customer_id) + + if not loan: + return True + + offer_id = loan.offer_id[:5] + + offer = Offer.get_offer_by_id(offer_id) + if not offer: + logger.error(f"Offer not found for offer_id: {offer_id} (customer_id: {customer_id})") + return False + + daily_count = Loan.get_daily_loan_count(customer_id, offer.product_id) + + logger.info(f"daily_count: {daily_count}, Max: {offer.max_daily_loans}") + + if offer.max_daily_loans is not None and daily_count >= offer.max_daily_loans: + return False + + return True + + + + +# { +# "email": "ameye@chiefsoft.com", +# "firstname": "Olusesan", +# "lastname": "Ameye", +# "isChecked": true +# } \ No newline at end of file diff --git a/app/models/members_pending.py b/app/models/members_pending.py new file mode 100644 index 0000000..a4b014f --- /dev/null +++ b/app/models/members_pending.py @@ -0,0 +1,51 @@ +from datetime import datetime, timezone +from app.extensions import db +from sqlalchemy.sql import func + + +class MembersPending(db.Model): + __tablename__ = 'members_pending' + + id = db.Column(db.Integer, primary_key=True, autoincrement=True) + uid = db.Column(db.String(150), nullable=False) + username = db.Column(db.String(25), nullable=False) + password = db.Column(db.String(100), nullable=True) + loc = db.Column(db.String(20), nullable=True) + status = db.Column(db.Integer, default=1) + added = db.Column(db.DateTime(timezone=False), server_default=func.now()) + updated = db.Column(db.DateTime(timezone=False), server_default=func.now(), onupdate=func.now()) + email = db.Column(db.String(100), nullable=False) + account_name = db.Column(db.String(100), nullable=True) + firstname = db.Column(db.String(25), nullable=False) + lastname = db.Column(db.String(100), nullable=True) + + def to_dict(self): + return { + "id": self.id, + "uid": self.uid, + "username": self.account_id, + "account_id": self.username, + "password": self.password, + "loc": self.loc, + "status": self.status, + "added": self.added.isoformat() if self.added else None, + "updated": self.updated.isoformat() if self.updated else None, + "email": self.email, + "account_name": self.account_name, + "firstname": self.firstname, + "lastname": self.lastname + } + + def __repr__(self): + return f'' + + @classmethod + def get_member_by_username(cls, username): + """ + Return an offer by its ID. + """ + member = cls.query.filter_by(username=str(username)).first() + + if not member: + raise ValueError(f"Username = {username} not found") + return member \ No newline at end of file diff --git a/app/swagger/merms_swagger.json b/app/swagger/merms_swagger.json index 0b8b752..4c6c7ac 100644 --- a/app/swagger/merms_swagger.json +++ b/app/swagger/merms_swagger.json @@ -86,7 +86,7 @@ "$ref": "swagger/paths/Account.json" }, "/panel/Products": { - "$ref": "swagger/paths/Register.json" + "$ref": "swagger/paths/Products.json" } }, "components": { diff --git a/app/swagger/paths/Products.json b/app/swagger/paths/Products.json index 02b8135..db49dbb 100644 --- a/app/swagger/paths/Products.json +++ b/app/swagger/paths/Products.json @@ -1,7 +1,7 @@ { "get": { "tags": [ - "Account" + "Products" ], "summary": "User Products Request ", "description": "Initiate Login Request",