Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
89ef25d
added Get api
Itsc2y Nov 6, 2024
facc35c
Adding Delete APIs
Nov 6, 2024
34bc075
Added Put API
Xingjian-Li-117 Nov 6, 2024
9058a84
added post
joycelalalayaa Nov 7, 2024
b71851c
Connected to MongoDB database and updated APIs.
Xingjian-Li-117 Nov 20, 2024
f5ab342
Create pylint action
joycelalalayaa Nov 23, 2024
fcaa962
Improved import order
joycelalalayaa Nov 23, 2024
f73e81b
Added runServer.sh + got rid of some unused code
joycelalalayaa Nov 23, 2024
5838c24
made some updated to router.py
joycelalalayaa Nov 24, 2024
f3730bf
made some updated to logic.py
joycelalalayaa Nov 24, 2024
586b386
Updating schema and database
Nov 24, 2024
345b243
Updating schema and database
Nov 24, 2024
c53fe78
Merge pull request #6 from Itsc2y/testBranch
tianjiewang2022 Nov 24, 2024
3b1a99c
Updating python version on pylint
Nov 24, 2024
d66c576
Updating python version on pylint
Nov 24, 2024
3f03d56
Merge pull request #7 from Itsc2y/testBranch
tianjiewang2022 Nov 24, 2024
54ab6dc
fix pylint errors
Itsc2y Nov 24, 2024
a9e4350
edit pylint
Itsc2y Nov 24, 2024
d89a10c
Updated router.py
Xingjian-Li-117 Nov 24, 2024
efcec61
edit pylint
Itsc2y Nov 24, 2024
fb4e2dc
edit pylint and requirement
Itsc2y Nov 24, 2024
db3c3e2
Updated model.py
Xingjian-Li-117 Nov 24, 2024
1bdac78
Second update on model.py
Xingjian-Li-117 Nov 24, 2024
145447e
made some updated to logic.py
joycelalalayaa Nov 24, 2024
e6b1ba0
made some updated to logic.py
joycelalalayaa Nov 24, 2024
b6342b9
add docker files
Itsc2y Nov 27, 2024
1a8a94b
Fix Docker login issue
Itsc2y Nov 27, 2024
61153bd
Use GitHub secrets for MongoDB configuration
Itsc2y Nov 27, 2024
0d13a3b
fix
Itsc2y Nov 27, 2024
cdfbd2c
fix
Itsc2y Nov 27, 2024
c2ee3bf
fix
Itsc2y Nov 27, 2024
f234732
fix
Itsc2y Nov 27, 2024
87ed2a9
fix
Itsc2y Nov 27, 2024
f678e17
a
Itsc2y Nov 27, 2024
526a7f1
a
Itsc2y Nov 27, 2024
bd49f87
fix
Itsc2y Nov 27, 2024
833f41e
fix
Itsc2y Nov 27, 2024
d0525b6
fix
Itsc2y Nov 27, 2024
740f2fb
fix
Itsc2y Nov 27, 2024
9db3d09
Merge pull request #9 from Itsc2y/docker_build
Itsc2y Nov 27, 2024
23c9f5c
Added tests for update_client method. Updated config.py to make sure …
Xingjian-Li-117 Dec 2, 2024
6056f16
Merge pull request #10 from Itsc2y/xingjianli
joycelalalayaa Dec 2, 2024
7f598fa
add get tests
Itsc2y Dec 3, 2024
ea92356
add bypass
Itsc2y Dec 3, 2024
e7246b1
Merge pull request #11 from Itsc2y/get_tests
Itsc2y Dec 3, 2024
5e35f1c
edited test.py
joycelalalayaa Dec 3, 2024
dc60440
Added tests for delete functions
Dec 3, 2024
7205a34
Covered all functions in router.py
Dec 3, 2024
cf7f573
Merge pull request #12 from Itsc2y/testBranch
tianjiewang2022 Dec 3, 2024
1553dfa
fixed bug in get_all_clients
Xingjian-Li-117 Dec 4, 2024
50aee3a
Merge pull request #13 from Itsc2y/xingjianli
Xingjian-Li-117 Dec 4, 2024
44cb7f0
Added pytest to pylint
Xingjian-Li-117 Dec 4, 2024
92cb6b2
Updated pylint
Xingjian-Li-117 Dec 4, 2024
2d12d05
Updated report upload in pylint
Xingjian-Li-117 Dec 4, 2024
8508606
Merge pull request #14 from Itsc2y/xingjianli
Xingjian-Li-117 Dec 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .coverage
Binary file not shown.
33 changes: 33 additions & 0 deletions .github/workflows/docker-build-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Docker CI Pipeline

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker
uses: docker/setup-buildx-action@v2

- name: Build Docker Image
run: |
docker build -t fastapi-app .

- name: Run Docker Container
run: |
docker run -d --name fastapi-container -p 8000:8000 fastapi-app

- name: Cleanup
run: |
docker stop fastapi-container
docker rm fastapi-container
45 changes: 45 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Docker CI Pipeline

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
# Step 1: Check out the code
- name: Checkout code
uses: actions/checkout@v4

# Step 2: Log in to DockerHub (Optional, if pushing the image)
- name: Log in to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

# Step 3: Set up Docker
- name: Set up Docker
uses: docker/setup-buildx-action@v2

# Step 4: Build Docker image
- name: Build Docker Image
run: |
docker build -t fastapi-app .

# Step 5: Run Docker Container with GitHub Secrets
- name: Run Docker Container
run: |
docker run -d -p 8000:8000 -e MONGODB_URI='${{ secrets.MONGODB_URI }}' -e MONGODB_NAME='${{ secrets.MONGODB_NAME }}' fastapi-app:latest

# Step 6: Test API Endpoints
- name: Test API Endpoints
run: |
sleep 5 # Allow time for the container to start
curl -f http://localhost:8000/docs
33 changes: 33 additions & 0 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Pylint

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pylint pytest pytest-asyncio pytest-cov
- name: Analysing the code with pylint
run: |
pylint ./app; # pylint $(git ls-files '*.py')
- name: Run tests with coverage
env:
PYTHONPATH: ${{ github.workspace }}
run: |
pytest --cov=app tests/ --cov-report=term-missing
- name: Upload coverage reports
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
.venv
venv/
.idea
__pycache__
.DS_Store
.env
30 changes: 30 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Use an official Python runtime as a parent image
FROM python:3.10-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# Set the working directory in the container
WORKDIR /app

# Install system dependencies required for psutil and other packages
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
python3-dev \
libffi-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Install dependencies
COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir --upgrade pip && pip install -r requirements.txt

# Copy the FastAPI app into the container
COPY . /app

# Expose port 8000 for FastAPI
EXPOSE 8000

# Command to run the FastAPI server
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Binary file added app/.coverage
Binary file not shown.
2 changes: 2 additions & 0 deletions app/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MONGODB_URI=mongodb+srv://team:IOi4XgpRxWVkKLv2@cluster0.mcjdj.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
MONGODB_NAME=Cluster0
144 changes: 135 additions & 9 deletions app/clients/router.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,141 @@
from fastapi import APIRouter
from fastapi.responses import HTMLResponse
"""
This module handles client-related API routes for the application.
"""

from app.clients.service.logic import interpret_and_calculate
from app.clients.schema import PredictionInput
from datetime import datetime, date
from typing import List

from bson import ObjectId
from fastapi import APIRouter, HTTPException

from app.clients.schema import Client, ClientUpdate
from app.database import clients_collection

router = APIRouter(prefix="/clients", tags=["clients"])

@router.post("/predictions")
async def predict(data: PredictionInput):
print("HERE")
print(data.model_dump())
return interpret_and_calculate(data.model_dump())

@router.post("/create", response_model=Client, summary="Create a new client")
async def create_client(client_data: Client):
"""
Create a new client in the database.

Args:
client_data (Client): The client data to create.

Returns:
Client: The created client object.
"""
client_dict = client_data.dict(exclude={"id"})
for key, value in client_dict.items():
if isinstance(value, date):
client_dict[key] = datetime.combine(value, datetime.min.time())
result = await clients_collection.insert_one(client_dict)
client_dict["_id"] = result.inserted_id
return Client(id=str(client_dict["_id"]), **client_dict)


@router.get("/clients/{client_id}", response_model=Client, summary="Retrieve client by ID")
async def get_client_by_id(client_id: str):
"""
Retrieve a client by their ID.

Args:
client_id (str): The ID of the client to retrieve.

Returns:
Client: The retrieved client object.
"""
client = await clients_collection.find_one({"_id": ObjectId(client_id)})
if client is None:
raise HTTPException(status_code=404, detail="Client not found")
# Convert ObjectId to string and return a formatted client object
client["id"] = str(client["_id"])
del client["_id"]
return client


@router.get("/clients", response_model=List[Client], summary="Retrieve all clients")
async def get_all_clients():
"""
Retrieve all clients in the database.

Returns:
List[Client]: A list of all clients.
"""
# clients_cursor = list(await clients_collection.find())
clients_cursor = await clients_collection.find().to_list(length=None)
# Convert _id to id and return the list
for client in clients_cursor:
client["id"] = str(client["_id"])
del client["_id"]

return clients_cursor


@router.delete("/clients/{client_id}", response_model=None, summary="Delete client by ID")
async def delete_client_by_id(client_id: str):
"""
Delete a client by their ID.

Args:
client_id (str): The ID of the client to delete.

Returns:
dict: A message indicating successful deletion.
"""
if not ObjectId.is_valid(client_id):
raise HTTPException(status_code=400, detail="Invalid ObjectId format")

client = await clients_collection.find_one({"_id": ObjectId(client_id)})
if client is None:
raise HTTPException(status_code=404, detail="Client not found")

delete_result = await clients_collection.delete_one({"_id": ObjectId(client_id)})
if delete_result.deleted_count == 0:
raise HTTPException(status_code=404, detail="Client not found")

return {"message": f"Client with ID {client_id} deleted successfully."}


@router.delete("/clients", response_model=None, summary="Delete all clients")
async def delete_all_clients():
"""
Delete all clients in the database.

Returns:
dict: A message indicating successful deletion of all clients.
"""
await clients_collection.delete_many({})
return {"message": "All clients deleted successfully."}


@router.put("/clients/{client_id}", response_model=Client, summary="Update client by ID")
async def update_client(client_id: str, client_data: ClientUpdate):
"""
Update a client's information by their ID.

Args:
client_id (str): The ID of the client to update.
client_data (ClientUpdate): The updated client data.

Returns:
Client: The updated client object.
"""
client = await clients_collection.find_one({"_id": ObjectId(client_id)})
if client is None:
raise HTTPException(status_code=404, detail="Client not found")

# Convert datetime.date to datetime.datetime for fields that are datetime.date
updated_fields = client_data.dict(exclude_unset=True)
for field, value in updated_fields.items():
if isinstance(value, date):
updated_fields[field] = datetime.combine(
value, datetime.min.time())

await clients_collection.update_one({"_id": ObjectId(client_id)}, {"$set": updated_fields})

updated_client = await clients_collection.find_one({"_id": ObjectId(client_id)})
updated_client["id"] = str(updated_client["_id"])
del updated_client["_id"]

return updated_client
39 changes: 39 additions & 0 deletions app/clients/schema.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
"""
Schemas for client and prediction data models.
Defines Pydantic models for validation and data manipulation.
"""

from datetime import date
from typing import Optional
from pydantic import BaseModel


class PredictionInput(BaseModel):
"""
Schema for prediction input parameters.
Used for validating data submitted for predictions.
"""
age: int
gender: str
work_experience: int
Expand All @@ -25,3 +37,30 @@ class PredictionInput(BaseModel):
substance_use: str
time_unemployed: int
need_mental_health_support_bool: str


class Client(BaseModel):
"""
Schema for client data.
Represents information stored about a client in the database.
"""
id: str
first_name: str
last_name: str
email: str
date_of_birth: date
address: Optional[str] = None
phone: Optional[str] = None


class ClientUpdate(BaseModel):
"""
Schema for client update data.
Used for partial updates to client information.
"""
first_name: Optional[str] = None
last_name: Optional[str] = None
email: Optional[str] = None
date_of_birth: Optional[date] = None
address: Optional[str] = None
phone: Optional[str] = None
Loading