diff --git a/app/__init__.py b/app/__init__.py index e5e7e35..ed6ddc3 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,9 +1,10 @@ from flask import Flask +from flask_mail import Mail from flask_cors import CORS from app.config import Config from app.routes import auth_bp, autocall_bp from app.response import (method_not_allowed, unsupported_media_type, not_found, bad_request) -from app.extensions import db +from app.extensions import db, mail def create_app(): @@ -15,6 +16,9 @@ def create_app(): # Setup CORS CORS(app) + + # Initialize Flask-Mail + mail.init_app(app) # Register blueprints app.register_blueprint(auth_bp) diff --git a/app/config.py b/app/config.py index 04cc785..948a00a 100644 --- a/app/config.py +++ b/app/config.py @@ -43,6 +43,15 @@ class Config: # SQLALCHEMY_ECHO = True + MAIL_SERVER = os.getenv('MAIL_SERVER','smtp.zoho.com') + MAIL_PORT = 587 + MAIL_USERNAME = os.getenv('MAIL_USERNAME', 'firstadvance@dynamikservices.tech') + MAIL_PASSWORD = os.getenv('MAIL_PASSWORD') + MAIL_USE_TLS = True + MAIL_USE_SSL = False + MAIL_DEFAULT_SENDER = ('FirstAdvance', 'firstadvance@dynamikservices.tech') + MAIL_RECEIVER= os.getenv('MAIL_RECEIVER', 'chinenyeumeaku@gmail.com,umeakuchinenye@gmail.com') + BANK_CALL_BASE_URL = os.getenv("BANK_CALL_BASE_URL", "https://bank-emulator.dev.simbrellang.net/api") BANK_CALL_SMS_BASE_URL= os.getenv("BANK_CALL_SMS_BASE_URL","https://first-advance-middleware-develop.fbn-devops-dev-asenv.appserviceenvironment.net/SMS") BANK_CALL_DISBURSE_LOAN_ENDPOINT = os.getenv("BANK_CALL_DISBURSE_LOAN_ENDPOINT","/DisburseLoan") diff --git a/app/extensions.py b/app/extensions.py index 2e1eeb6..1afa3d6 100644 --- a/app/extensions.py +++ b/app/extensions.py @@ -1,3 +1,5 @@ from flask_sqlalchemy import SQLAlchemy +from flask_mail import Mail +mail = Mail() db = SQLAlchemy() \ No newline at end of file diff --git a/app/routes/autocall.py b/app/routes/autocall.py index 679608f..7a291b6 100644 --- a/app/routes/autocall.py +++ b/app/routes/autocall.py @@ -10,6 +10,8 @@ from app.services.loan import LoanService from app.services.repayment import RepaymentService from app.services.salary import SalaryService from app.enums.loan_status import LoanStatus +from app.utils.mail import send_report_email, get_report_data +from app.config import settings autocall_bp = Blueprint("autocall", __name__) @@ -238,3 +240,19 @@ def process_salary_list(): logger.info(f"Finished processing salary ID: {pending_salary.id}") return ResponseHelper.success([], "Processed all pending salaries") + + + +@autocall_bp.route("/report", methods=["GET"]) +def report(): + try: + report_data = get_report_data() + logger.info(f"Generated report data: {report_data}") + send_report_email( + report_data, + recipients = [email.strip() for email in settings.MAIL_RECEIVER.split(",")]) + + return ResponseHelper.success(message="Report sent successfully",status_code=200) + except Exception as e: + logger.error(f"Error generating or sending report: {e}") + return ResponseHelper.error("Failed to send report", status_code=500, error=str(e)) diff --git a/app/utils/mail.py b/app/utils/mail.py new file mode 100644 index 0000000..3e39255 --- /dev/null +++ b/app/utils/mail.py @@ -0,0 +1,40 @@ +from flask_mail import Message +from flask import current_app +from app.extensions import mail +import pandas as pd +from io import BytesIO + +def get_report_data(): + """ + Fetch and return loan summary data. + """ + return [ + {"Type": "Disbursement", "Count": 45}, + {"Type": "Repayment", "Count": 32}, + ] +def send_report_email(report_data: list, recipients: list): + """ + Sends an HTML + Excel report to the given email recipients. + """ + df = pd.DataFrame(report_data) + output = BytesIO() + df.to_excel(output, index=False) + output.seek(0) + + html_table = df.to_html(index=False, border=1) + + msg = Message( + subject="Loan Report Summary", + recipients=recipients, + html=f"

Loan Report Summary

{html_table}", + ) + msg.attach( + "loan_report.xlsx", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + output.read() + ) + + with current_app.app_context(): + mail.send(msg) + + return "Report email sent" \ No newline at end of file diff --git a/openapi.yml b/openapi.yml index 8bedff7..9b03e59 100644 --- a/openapi.yml +++ b/openapi.yml @@ -200,4 +200,12 @@ paths: example: "2025-01-01" responses: 200: - description: A successful response \ No newline at end of file + description: A successful response + + /autocall/report: + get: + summary: Generate and send a report + responses: + 200: + description: A successful response + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 32e6887..25b198e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,3 +11,6 @@ psycopg2-binary alembic python-dateutil oracledb +Flask-Mail==0.10.0 +pandas==2.1.3 +openpyxl==3.1.5