diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 4429a0e..9aea70d 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -66,3 +66,13 @@ The initial price of the product or service. | | | | - `ending_inventory` (float): The final amount of accounts payable ending the cycle. | | | | - `total_credit_purchases` (float): The amount of purchases on credit during the cycle. | |-----------------------------|----------------------------------------|---------------------------------------------------------------------| +| Endpoint | Description | Request Parameters | +|---------------------------|----------------------------------------|---------------------------------------------------------| +| POST /debt_payoff_planner | Calculate debt payoff plan | - `debt_amount` (float): The total amount of debt. | +| | | - `interest_rate` (float): The annual interest rate. | +| | | - `monthly_payment` (float): The fixed monthly payment. | +|---------------------------|----------------------------------------|---------------------------------------------------------| +| GET /loan_comparison Compare loan plans | - `loan_amount` (float): The loan amount.. | +| | | - `loan_term` (int): The loan term in months. | + + diff --git a/ENDPOINTS.md b/ENDPOINTS.md index 6053276..0d37894 100644 --- a/ENDPOINTS.md +++ b/ENDPOINTS.md @@ -1356,7 +1356,7 @@ ``` \*_GET_ `calculate_lumpsum` --Required Parameters: `principal`, `interest_rate `, `years` +-Required Parameters: `principal`, `interest_rate`, `years` -sample output ```py @@ -1639,6 +1639,7 @@ Add-function-and-endpoint-to-calculate-lump-sum-mutual-fund-investment **GET** `/loan-affordability` - Required parameters : `income`, + `expenses`, `loan_term`, `interest_rate`, @@ -1660,7 +1661,7 @@ Add-function-and-endpoint-to-calculate-lump-sum-mutual-fund-investment **GET** `/calculate_bvps` - Required parameters : `stockholders_equity`, - `preferred_stock`, `average_outstanding_shares`, + `preferred_stock`, `average_outstanding_shares` - Sample output ```py @@ -1678,6 +1679,7 @@ Add-function-and-endpoint-to-calculate-lump-sum-mutual-fund-investment **GET** `/gratuity-amount` - Required parameters : `last_salary`, + `tenure_years`, `tenure_months`, - Sample Request: `GET`, `http://localhost:8000/calculate_gratuity?last_salary=20000000&tenure_years=10&tenure_months=1`, @@ -1709,6 +1711,7 @@ Add-function-and-endpoint-to-calculate-lump-sum-mutual-fund-investment ``` + **GET** `/personal_savings` - Required parameters : 'init','monthly', 'tenure' @@ -1746,7 +1749,7 @@ Add-function-and-endpoint-to-calculate-lump-sum-mutual-fund-investment # GET # Endpoint --> '/mortrage' Required Paramenters --> princial:int,interest_rate:float,years:int,down_payment:int,property_tax_rate:float,insurance_rate:float -Sample request --> http://127.0.0.1:8000/mortrages?princial=200000&interest_rate=4.5&years=45&down_payment=50000&property_tax_rate=1.3&insurance_rate=0.5 +Sample request --> Sample Output @@ -1765,7 +1768,7 @@ Sample Output Required Parameters --> birth_date:str,earnings:int,retirement_age:int -Sample request --> http://127.0.0.1:8000/social_securities?birth_date=10-08-2002&earnings=250000&retirement_age=70 +Sample request --> Sample Output ```py @@ -2132,25 +2135,25 @@ Sample Output **POST** `/defensive_interval_ratio` - Request body : `{ - "cash": 40000.00, - "marketable_securities": 20000.00, - "net_receivables": 10000.00, - "annual_operating_expenses": 300000.00, - "non_cash_charges": 25000.00 + "cash": 40000.00, + "marketable_securities": 20000.00, + "net_receivables": 10000.00, + "annual_operating_expenses": 300000.00, + "non_cash_charges": 25000.00 }` - Sample output ```py { "Tag": "Defensive Interval Ratio", - "Cash": 40000.00, - "Marketable Securites": 20000.00, - "Net Receivables": 10000.00, - "Annual Operating Expenses": 300000.00, - "Non Cash Charges": 25000.00, - "Current Assets": 70000.0, - "Daily Operational Expenses": 753.42, - "Defensive Interval Ratio": 92.90 + "Cash": 40000.00, + "Marketable Securites": 20000.00, + "Net Receivables": 10000.00, + "Annual Operating Expenses": 300000.00, + "Non Cash Charges": 25000.00, + "Current Assets": 70000.0, + "Daily Operational Expenses": 753.42, + "Defensive Interval Ratio": 92.90 } ``` @@ -2214,7 +2217,7 @@ Sample Output - Request body : `{ "beginning_inventory": 1000, - "ending_inventory": 2000, + "ending_inventory": 2000, "beginning_receivables": 100 "ending_receivables": 90, "beginning_payable": 800, @@ -2252,7 +2255,7 @@ Sample Output "deductible": 500, "num_claims": 0, "num_accidents": 1 -**POST** `/price-elasticity` +**POST**`/price-elasticity` - Request body : `{ "initial_price": 10.0, @@ -2274,7 +2277,7 @@ Sample Output - Request body : `{ "beginning_accounts_payable": 110000, - "ending_accounts_payable": 95000, + "ending_accounts_payable": 95000, "total_credit_purchases": 1110000 }` - Sample output @@ -2289,3 +2292,62 @@ Sample Output "Average Payment Period": "33.7days", } ``` + +**POST** `/debt_payoff_planner` +- Request body : + { + "amount_paid": 20.23, + "principle_amount": 30.9, + "months": 5 + } +- Sample Output: +```py +{ + "Tag": "Simple Interest Rate", + "Total amount paid": 20.23, + "Principle amount": 30.9, + "Interest Paid": -10.67, + "Interest Rate": "-82.87%" +} +``` + + +**GET** `/loan_comparison` +- Request body : `{ + "loan_amount": 110000, + "loan_term": 12, +}` +- Sample Output: + ```json + [ + { + "name": "Loan Offer B", + "interest_rate": 7.9, + "loan_term": 24, + "processing_fee": 150, + "total_repayment": 520.23 + }, + { + "name": "Loan Offer C", + "interest_rate": 9.2, + "loan_term": 18, + "processing_fee": 250, + "total_repayment": 522.57 + }, + { + "name": "Loan Offer A", + "interest_rate": 8.5, + "loan_term": 12, + "processing_fee": 200, + "total_repayment": 523.15 + }, + { + "name": "Loan Offer D", + "interest_rate": 6.5, + "loan_term": 36, + "processing_fee": 100, + "total_repayment": 529.28 + } + ] + ``` + diff --git a/helpers/functions.py b/helpers/functions.py index 8425d51..60b05b7 100644 --- a/helpers/functions.py +++ b/helpers/functions.py @@ -5,6 +5,7 @@ import datetime from dateutil.relativedelta import relativedelta from typing import Union +from fastapi import FastAPI, HTTPException, Query # Function to Calculate Simple Interest Rate @@ -2061,4 +2062,37 @@ def calculate_modified_internal_rate_of_return(ending_cash_flow: float, initial_cash_flow: float, number_of_periods: int): mirr = ((ending_cash_flow / initial_cash_flow) ** (1 / number_of_periods)) - 1 - return mirr*100 \ No newline at end of file + return mirr*100 + + +# Function for Debt Payoff Planner + + +def debt_payoff_planner(debt_amount: float, interest_rate: float, monthly_payment: float): + if interest_rate <= 0 or monthly_payment <= 0: + raise ValueError("Interest rate and monthly payment must be positive.") + + # Convert the interest rate from percentage to decimal + monthly_interest_rate = interest_rate / 100 / 12 + + months_left = 0 + total_interest_paid = 0 + remaining_debt = debt_amount + + while remaining_debt > 0: + months_left += 1 + interest_payment = remaining_debt * monthly_interest_rate + total_interest_paid += interest_payment + remaining_debt += interest_payment - monthly_payment + + if remaining_debt <= 0: + break + + return { + "Tag": "Debt Payoff Planner", + "Debt Amount": debt_amount, + "Interest Rate": interest_rate, + "Monthly Payment": monthly_payment, + "Months to Pay Off": months_left, + "Total Interest Paid": round(total_interest_paid, 2), + } \ No newline at end of file diff --git a/main.py b/main.py index e54df32..c7fd3cd 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI, Depends, HTTPException, status +from fastapi import FastAPI, Depends, HTTPException, status,Query from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials from fastapi.responses import JSONResponse import jwt @@ -1985,3 +1985,81 @@ def average_payment_period(request: AveragePaymentPeriod): return average_payment_period_task(request.beginning_accounts_payable , request.ending_accounts_payable , request.total_credit_purchases) +# Endpoint for Debt Payoff Planner + +app = FastAPI() + +@app.get( + "/debt_payoff_planner", + tags=["debt_payoff_planner"], + description="Calculate debt payoff plan", +) +def debt_payoff_planner( + debt_amount: float = Query(..., description="The total amount of debt."), + interest_rate: float = Query(..., description="The annual interest rate (as a percentage)."), + monthly_payment: float = Query(..., description="The fixed monthly payment amount.") +): + try: + if interest_rate <= 0 or monthly_payment <= 0: + raise HTTPException(status_code=400, detail="Interest rate and monthly payment must be positive.") + + # Convert the interest rate from percentage to decimal + monthly_interest_rate = interest_rate / 100 / 12 + + months_left = 0 + total_interest_paid = 0 + remaining_debt = debt_amount + + while remaining_debt > 0: + months_left += 1 + interest_payment = remaining_debt * monthly_interest_rate + total_interest_paid += interest_payment + remaining_debt += interest_payment - monthly_payment + + if remaining_debt <= 0: + break + + return { + "Tag": "Debt Payoff Planner", + "Debt Amount": debt_amount, + "Interest Rate": interest_rate, + "Monthly Payment": monthly_payment, + "Months to Pay Off": months_left, + "Total Interest Paid": round(total_interest_paid, 2), + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +#Endpoint for Loan Comparison +@app.get( + "/loan_comparison", + tags=["loan_comparison"], + description="Compare loan offers based on total repayment amounts", +) +def loan_comparison( + loan_amount: float = Query(..., description="The loan amount."), + loan_term: int = Query(..., description="The loan term in months.") +): + try: + if loan_amount <= 0 or loan_term <= 0: + raise HTTPException(status_code=400, detail="Loan amount and loan term must be positive.") + + # Calculate the total repayment amount for each loan offer + loan_offers_with_total_repayment = [ + { + "name": offer.name, + "interest_rate": offer.interest_rate, + "loan_term": offer.loan_term, + "processing_fee": offer.processing_fee, + "total_repayment": loan_amount + (loan_amount * (offer.interest_rate / 100)) + offer.processing_fee + } + for offer in loan_offers + ] + + # Sort the loan offers based on total repayment amounts (lowest to highest) + sorted_loan_offers = sorted(loan_offers_with_total_repayment, key=lambda x: x["total_repayment"]) + + return sorted_loan_offers + + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file diff --git a/tasks/debt_payoff_planner.py b/tasks/debt_payoff_planner.py new file mode 100644 index 0000000..c4da0d2 --- /dev/null +++ b/tasks/debt_payoff_planner.py @@ -0,0 +1,16 @@ +from fastapi import HTTPException, status +from helpers import functions + +def debt_payoff_planner(debt_amount: float, interest_rate: float, monthly_payment: float): + try: + result = functions.debt_payoff_planner(debt_amount, interest_rate, monthly_payment) + return { + "Tag": "Debt Payoff Planner", + "Debt Amount": debt_amount, + "Interest Rate": interest_rate, + "Monthly Payment": monthly_payment, + "Months to Pay Off": result["Months to Pay Off"], + "Total Interest Paid": result["Total Interest Paid"], + } + except: + return HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR) diff --git a/tasks/loan_comparison.py b/tasks/loan_comparison.py new file mode 100644 index 0000000..40c5da9 --- /dev/null +++ b/tasks/loan_comparison.py @@ -0,0 +1,42 @@ +from fastapi import HTTPException, status +from helpers import functions + +def loan_comparison(loan_amount: float, loan_term: int): + try: + if loan_amount <= 0 or loan_term <= 0: + raise HTTPException(status_code=400, detail="Loan amount and loan term must be positive.") + + class LoanOffer: + def __init__(self, name, interest_rate, loan_term, processing_fee): + self.name = name + self.interest_rate = interest_rate + self.loan_term = loan_term + self.processing_fee = processing_fee + + # Sample loan offers data (You can fetch this from a database or API) + loan_offers = [ + LoanOffer("Loan Offer A", 8.5, 12, 200), + LoanOffer("Loan Offer B", 7.9, 24, 150), + LoanOffer("Loan Offer C", 9.2, 18, 250), + LoanOffer("Loan Offer D", 6.5, 36, 100), + ] + + # Calculate the total repayment amount for each loan offer + loan_offers_with_total_repayment = [ + { + "name": offer.name, + "interest_rate": offer.interest_rate, + "loan_term": offer.loan_term, + "processing_fee": offer.processing_fee, + "total_repayment": loan_amount + (loan_amount * (offer.interest_rate / 100)) + offer.processing_fee + } + for offer in loan_offers + ] + + # Sort the loan offers based on total repayment amounts (lowest to highest) + sorted_loan_offers = sorted(loan_offers_with_total_repayment, key=lambda x: x["total_repayment"]) + + return sorted_loan_offers + + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) diff --git a/validators/request_validators.py b/validators/request_validators.py index 100c2d7..ec76788 100644 --- a/validators/request_validators.py +++ b/validators/request_validators.py @@ -649,7 +649,20 @@ class AveragePaymentPeriod(BaseModel): ending_accounts_payable: float total_credit_purchases: float + class ModifiedInternalRateOfReturn(BaseModel): ending_cash_flow: float initial_cash_flow: float - number_of_periods: int \ No newline at end of file + number_of_periods: int + +class DebtPayoffPlannerRequest(BaseModel): + debt_amount: float + interest_rate: float + monthly_payment: float + + +class LoanOffer(BaseModel): + name: str + interest_rate: float + loan_term: int + processing_fee: float \ No newline at end of file