logeswari commited on
Commit
d6bc972
·
1 Parent(s): 8234ee3
.env ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ SUPABASE_URL=https://qxvpaoeakhddzabctekw.supabase.co
2
+ SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InF4dnBhb2Vha2hkZHphYmN0ZWt3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDEwNjU2MzEsImV4cCI6MjA1NjY0MTYzMX0.I3GsBjFRfuBKw-KxmSJ7R5iKn2cgGegqIls2Bf32UpI
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ RUN useradd -m -u 1000 user
4
+ USER user
5
+ ENV PATH="/home/user/.local/bin:$PATH"
6
+
7
+ WORKDIR /app/folder1
8
+
9
+ COPY --chown=user ./requirements.txt requirements.txt
10
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
+
12
+ COPY --chown=user . /app
13
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
__pycache__/database.cpython-313.pyc ADDED
Binary file (505 Bytes). View file
 
__pycache__/main.cpython-313.pyc ADDED
Binary file (557 Bytes). View file
 
config.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+
4
+ # Load environment variables
5
+ load_dotenv()
6
+
7
+ SUPABASE_URL = os.getenv("SUPABASE_URL")
8
+ SUPABASE_KEY = os.getenv("SUPABASE_KEY")
database.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+ from supabase import create_client, Client
4
+
5
+ # Load environment variables
6
+ load_dotenv()
7
+
8
+ # Read Supabase credentials
9
+ SUPABASE_URL = os.getenv("SUPABASE_URL")
10
+ SUPABASE_KEY = os.getenv("SUPABASE_KEY")
11
+
12
+ # Initialize Supabase client
13
+ supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
logger.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+
3
+ logging.basicConfig(
4
+ filename="logs/app.log",
5
+ level=logging.INFO,
6
+ format="%(asctime)s - %(levelname)s - %(message)s",
7
+ )
8
+ logger = logging.getLogger(__name__)
main.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from routes.analytics import router as analytics_router
3
+
4
+ app = FastAPI()
5
+
6
+ app.include_router(analytics_router)
7
+
8
+ @app.get("/")
9
+ def home():
10
+ return {"message": "HR Analytics API is running"}
models/schemas.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+ from typing import Optional
3
+
4
+ class HRAnalysis(BaseModel):
5
+ Employee_ID: str
6
+ DepartmentType: Optional[str]
7
+ Satisfaction_Score: Optional[float]
8
+ Performance_Score: Optional[int]
9
+ Training_Program_Name: Optional[str]
10
+ Training_Outcome: Optional[str]
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ pandas
4
+ supabase
5
+ python-dotenv
routes/__pycache__/analytics.cpython-313.pyc ADDED
Binary file (9.65 kB). View file
 
routes/analytics.py ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Query
2
+ import pandas as pd
3
+ from database import supabase
4
+
5
+ router = APIRouter()
6
+
7
+ # Fetch data from Supabase
8
+ try:
9
+ response = supabase.table("HR analysis").select("*").execute()
10
+ data = pd.DataFrame(response.data) if response.data else pd.DataFrame()
11
+ except Exception as e:
12
+ print(f"Error fetching data: {e}")
13
+ data = pd.DataFrame()
14
+
15
+ # Convert date columns
16
+ for col in ['Survey Date', 'StartDate', 'DOB']:
17
+ if col in data.columns:
18
+ data[col] = pd.to_datetime(data[col], errors='coerce')
19
+
20
+ # Calculate Age
21
+ if 'DOB' in data.columns:
22
+ data['Age'] = (pd.to_datetime("today") - data['DOB']).dt.days // 365
23
+
24
+ # Clean Performance Score
25
+ score_map = {"Exceeds": 5, "Fully Meets": 4, "Needs Improvement": 3, "PIP": 2}
26
+ if 'Performance Score' in data.columns:
27
+ data['Performance Score'] = data['Performance Score'].map(lambda x: score_map.get(str(x).strip(), None))
28
+ data['Performance Score'] = pd.to_numeric(data['Performance Score'], errors='coerce')
29
+
30
+ @router.get("/satisfaction-analysis")
31
+ def satisfaction_analysis(department: str = Query(None, description="Filter by department")):
32
+ try:
33
+ if "DepartmentType" not in data.columns or "Satisfaction Score" not in data.columns:
34
+ raise HTTPException(status_code=500, detail="Required columns missing in dataset")
35
+
36
+ filtered_data = data.copy()
37
+
38
+ if department:
39
+ department = department.strip().title()
40
+ filtered_data = filtered_data[filtered_data["DepartmentType"].str.strip().str.title() == department]
41
+
42
+ if filtered_data.empty:
43
+ return []
44
+
45
+ result = filtered_data.groupby("DepartmentType")["Satisfaction Score"].mean().reset_index()
46
+ return result.to_dict(orient="records")
47
+ except Exception as e:
48
+ raise HTTPException(status_code=500, detail=str(e))
49
+
50
+ @router.get("/department-performance")
51
+ def department_performance():
52
+ try:
53
+ result = data.groupby("DepartmentType")[["Performance Score", "Current Employee Rating"]].mean().reset_index()
54
+ return result.to_dict(orient="records")
55
+ except Exception as e:
56
+ raise HTTPException(status_code=500, detail=str(e))
57
+
58
+ @router.get("/training-analytics")
59
+ def training_analytics(program_name: str = Query(None, description="Filter by training program name")):
60
+ try:
61
+ filtered_data = data if program_name is None else data[data["Training Program Name"] == program_name]
62
+
63
+ if filtered_data.empty:
64
+ return []
65
+
66
+ result = filtered_data.groupby("Training Program Name")["Training Outcome"].value_counts(normalize=True).unstack(fill_value=0)
67
+ return result.reset_index().to_dict(orient="records")
68
+ except Exception as e:
69
+ raise HTTPException(status_code=500, detail=str(e))
70
+
71
+
72
+
73
+ @router.get("/engagement-performance")
74
+ def engagement_performance():
75
+ try:
76
+ correlation = data[['Engagement Score', 'Performance Score']].corr().iloc[0, 1]
77
+ return {"correlation_coefficient": correlation}
78
+ except Exception as e:
79
+ raise HTTPException(status_code=500, detail=str(e))
80
+
81
+ @router.get("/cost-benefit-analysis")
82
+ def cost_benefit_analysis():
83
+ try:
84
+ result = data.groupby("DepartmentType").apply(lambda x: x['Performance Score'].mean() / x['Training Cost'].sum()).reset_index(name="ROI")
85
+ return result.to_dict(orient="records")
86
+ except Exception as e:
87
+ raise HTTPException(status_code=500, detail=str(e))
88
+
89
+ @router.get("/training-effectiveness")
90
+ def training_effectiveness():
91
+ try:
92
+ result = data.groupby("Training Program Name")["Performance Score"].mean().reset_index()
93
+ return result.to_dict(orient="records")
94
+ except Exception as e:
95
+ raise HTTPException(status_code=500, detail=str(e))
96
+
97
+ @router.get("/diversity-inclusion")
98
+ def diversity_dashboard():
99
+ try:
100
+ if "DepartmentType" not in data.columns or "GenderCode" not in data.columns:
101
+ raise HTTPException(status_code=500, detail="Required columns missing in dataset")
102
+
103
+ # Compute gender distribution by department
104
+ diversity_metrics = data.groupby("DepartmentType")["GenderCode"].value_counts(normalize=True).unstack(fill_value=0).reset_index()
105
+
106
+ return diversity_metrics.to_dict(orient="records")
107
+ except Exception as e:
108
+ raise HTTPException(status_code=500, detail=str(e))
109
+
110
+
111
+ @router.get("/work-life-balance")
112
+ def worklife_balance_impact():
113
+ try:
114
+ correlation = data[['Work-Life Balance Score', 'Performance Score']].corr().iloc[0, 1]
115
+ return {"correlation_coefficient": round(correlation, 3)} # Return as a JSON object
116
+ except Exception as e:
117
+ raise HTTPException(status_code=500, detail=str(e))
118
+
119
+
120
+ @router.get("/career-development")
121
+ def career_development(employee_id: str = Query(None, description="Filter by Employee ID")):
122
+ try:
123
+ if "Employee ID" not in data.columns or "StartDate" not in data.columns:
124
+ raise HTTPException(status_code=500, detail="Required columns missing in dataset")
125
+
126
+ # Print available Employee IDs for debugging
127
+ print("Available Employee IDs:", data["Employee ID"].unique())
128
+
129
+ filtered_data = data.copy()
130
+
131
+ if employee_id:
132
+ employee_id = employee_id.strip() # Remove leading/trailing spaces
133
+ filtered_data = filtered_data[filtered_data["Employee ID"].astype(str) == employee_id]
134
+
135
+ if filtered_data.empty:
136
+ return [] # Return an empty list if no matching records
137
+
138
+ career_progress = filtered_data.groupby("Employee ID")["StartDate"].count().reset_index(name="Career Movements")
139
+ return career_progress.to_dict(orient="records")
140
+ except Exception as e:
141
+ raise HTTPException(status_code=500, detail=str(e))
utils/data_processing.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+
3
+ def convert_dates(df, columns):
4
+ for col in columns:
5
+ if col in df.columns:
6
+ df[col] = pd.to_datetime(df[col], errors='coerce')
7
+ return df
8
+
9
+ def calculate_age(df, dob_col="DOB"):
10
+ if dob_col in df.columns:
11
+ df["Age"] = (pd.to_datetime("today") - df[dob_col]).dt.days // 365
12
+ return df
13
+
14
+ def clean_performance_score(df, col="Performance Score"):
15
+ score_map = {"Exceeds": 5, "Fully Meets": 4, "Needs Improvement": 3, "PIP": 2}
16
+ if col in df.columns:
17
+ df[col] = df[col].map(lambda x: score_map.get(str(x).strip(), None))
18
+ df[col] = pd.to_numeric(df[col], errors='coerce')
19
+ return df