from flask import jsonify from app.utils.logger import logger from app.api.services.base_service import BaseService from sqlalchemy import func, desc from datetime import datetime, timedelta, timezone from app.extensions import db from app.models import (MembersProducts, Products, Members) from app.api.schemas.office_member_data import OfficeMemberDataSchema from app.api.helpers.response_helper import ResponseHelper from marshmallow import ValidationError class OfficeCustomerService(BaseService): @staticmethod def update_customer_data(data): try: with db.session.begin(): logger.info(f"Incoming BackOffice Member data ==>>>> {data}") validated_data = OfficeCustomerService.validate_data(data, OfficeMemberDataSchema()) member_uid = validated_data.get('member_uid') member_account_name = validated_data.get('member_account_name') member_firstname = validated_data.get('member_account_name') member_lastname = validated_data.get('member_account_name') member_full_address = validated_data.get('member_account_name') member_email = validated_data.get('member_account_name') member_phone = validated_data.get('member_account_name') member_data = Members.get_member_by_uid(member_uid) member_id = member_data.id if member_data and member_id: member_account_name = validated_data.get('member_account_name') member_firstname = validated_data.get('member_account_name') member_lastname = validated_data.get('member_account_name') member_full_address = validated_data.get('member_account_name') member_email = validated_data.get('member_account_name') member_phone = validated_data.get('member_account_name') profile_data = { "member_account_name": member_account_name, "member_firstname": member_firstname, "member_lastname": member_lastname, "member_full_address": member_full_address, "member_email": member_email, "member_phone": member_phone, } Members.set_office_update_profile(member_uid, profile_data) response_data = { "last_update": datetime.datetime.utcnow(), "member_id": member_id } 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 get_customer_data(filters=None): try: if filters is None: filters = {} # Extract filters username = filters.get('username') email = filters.get('email') # Extract pagination parameters page = int(filters.get('page', 1)) limit = int(filters.get('limit', 20)) # Ensure page and limit are valid if page < 1: page = 1 if limit < 1 or limit > 100: limit = 20 membersList, total_count = Members.get_all_member(email,username,page,limit) # Convert loans to dictionary format member_data = [] for member in membersList: member_data.append({ 'id': member.id, 'username': member.username, 'email': member.email, 'firstname': member.firstname, 'lastname': member.lastname, 'country': member.country, 'member_uid': member.uid, 'country': member.country, 'profile_completed': member.profile_completed, "added": member.added, }) # Calculate total pages total_pages = (total_count + limit - 1) // limit response_data = { 'customers': member_data, 'count': len(member_data), 'pagination': { 'total_count': total_count, 'total_pages': total_pages, 'current_page': page, 'limit': limit, 'has_next': page < total_pages, 'has_prev': page > 1 } } return response_data # 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) # country = db.Column(db.String(3), nullable=True) # profile_completed = db.Column(db.DateTime(timezone=False)) # stripe_customer_id = db.Column(db.String(100), nullable=True) # # # 'transaction_id': loan.transaction_id, # 'original_transaction': loan.original_transaction, # 'offer_id': loan.offer_id, # 'eligible_amount': loan.eligible_amount, # 'initial_loan_amount': loan.initial_loan_amount, # 'current_loan_amount': loan.current_loan_amount, # 'status': loan.status, # 'tenor': loan.tenor, # 'product_id': loan.product_id, # 'default_penalty_fee': loan.default_penalty_fee, # 'continuous_fee': loan.continuous_fee, # 'upfront_fee': loan.upfront_fee, # 'repayment_amount': loan.repayment_amount, # 'installment_amount': loan.installment_amount, # 'due_date': loan.due_date.isoformat() if loan.due_date else None, # 'created_at': loan.created_at.isoformat() if loan.created_at else None, # 'updated_at': loan.updated_at.isoformat() if loan.updated_at else None # now = datetime.now() # start_of_week = now - timedelta(days=now.weekday()) # start_of_week = start_of_week.replace(hour=0, minute=0, second=0, microsecond=0) # # # Calculate 24 hours ago # last_24_hours = datetime.now(timezone.utc) - timedelta(hours=24) # # # Loans this week # loans_this_week = db.session.query( # func.sum(Loan.initial_loan_amount) # ).filter( # Loan.created_at >= start_of_week # ).scalar() or 0 # # # Payments this week # payments_this_week = db.session.query( # func.count(Transaction.id) # ).filter( # Transaction.created_at >= start_of_week, # Transaction.type == 'PAYMENT' # ).scalar() or 0 # # # Request summary for the last 24 hours # eligibility_check_count = db.session.query( # func.count(Transaction.id) # ).filter( # Transaction.type == TransactionType.ELIGIBILITY_CHECK.value, # Transaction.created_at >= last_24_hours # ).scalar() or 0 # # select_offer_count = db.session.query( # func.count(Transaction.id) # ).filter( # Transaction.type == TransactionType.SELECT_OFFER.value, # Transaction.created_at >= last_24_hours # ).scalar() or 0 # # provide_loan_count = db.session.query( # func.count(Transaction.id) # ).filter( # Transaction.type == TransactionType.PROVIDE_LOAN.value, # Transaction.created_at >= last_24_hours # ).scalar() or 0 # # repayment_count = db.session.query( # func.count(Transaction.id) # ).filter( # Transaction.type == TransactionType.REPAYMENT.value, # Transaction.created_at >= last_24_hours # ).scalar() or 0 # # # Recent transactions (not limited to 24 hrs, just latest 15) # recent_transactions = Transaction.query.order_by( # Transaction.id.desc() # ).limit(15).all() # # recent_transactions_data = [{ # 'id': t.id, # 'transaction_id': t.transaction_id, # 'account_id': t.account_id, # 'type': t.type, # 'channel': t.channel, # 'created_at': t.created_at.isoformat() if t.created_at else None, # 'updated_at': t.updated_at.isoformat() if t.updated_at else None # } for t in recent_transactions] # # # Final response # dashboard_data = { # "loans": { # "value": float(loans_this_week), # "currency": "Naira", # "currency_text": "₦", # "text": "this week" # }, # "payments": { # "value": payments_this_week, # "currency": "Naira", # "currency_text": "₦", # "text": "this week" # }, # "request_summary": { # "eligibility_check": {"Eligibility": eligibility_check_count}, # "select_offer": {"Offers": select_offer_count}, # "provide_loan": {"Loans": provide_loan_count}, # "repayment": {"Repayments": repayment_count} # }, # "recent_transactions": recent_transactions_data # } subscription = MembersProducts.get_dash_recent_subscription(15) subscription_data = [{ 'id': t.id, 'uid': t.uid, 'product_id': t.product_id, 'internal_url': t.internal_url, 'external_url': t.external_url, 'dns_group': t.dns_group, 'status': t.status, 'added': t.added, 'updated': t.updated } for t in subscription] dashboard_data = { "subscription":subscription_data, "loans": { "currency": "Naira", "currency_text": "\u20a6", "text": "this week", "value": 159999.0 }, "payments": { "currency": "Naira", "currency_text": "\u0024", "text": "this week", "value": 0 }, "request_summary": { "eligibility_check": { "Started": 6 }, "provide_loan": { "Scheduled": 2 }, "repayment": { "Processing": 0 }, "select_offer": { "Completed": 3 } } } return dashboard_data except Exception as e: logger.error(f"An error occurred while getting dashboard data: {str(e)}", exc_info=True) return jsonify({"message": "Internal Server Error"}), 500