├── static ├── input.css └── output.css ├── src ├── config │ ├── __init__.py │ └── AppConfig.py ├── bots │ ├── __init__.py │ └── birthday_bot.py ├── context │ ├── __init__.py │ └── depend_context.py ├── parse │ ├── __init__.py │ ├── EmployeeBirthdayReader.py │ ├── EmployeeBioReader.py │ ├── HotSchedulesStaffReader.py │ └── TimePunchReader.py ├── __init__.py ├── log │ └── __init__.py ├── routes │ ├── post_api_groupme_birthday.py │ ├── __init__.py │ ├── post_tbot_birthday.py │ ├── get_admin.py │ ├── get_index.py │ ├── post_form_employee_update_department.py │ ├── post_form_upload_employee_bio.py │ ├── get_form_logout.py │ ├── get_admin_locations.py │ ├── post_form_upload_hotschedules_staff_html.py │ ├── post_form_cfa_location_delete.py │ ├── post_form_cfa_location_create.py │ ├── post_form_login.py │ ├── post_form_upload_employee_birthday_report.py │ ├── post_form_upload_time_punch.py │ └── get_admin_cfa_location.py ├── middleware │ └── __init__.py └── db │ ├── __init__.py │ ├── Location.py │ ├── Session.py │ └── Employee.py ├── init.sh ├── Makefile ├── pyproject.toml ├── templates ├── page │ ├── admin │ │ ├── home.html │ │ ├── locations.html │ │ └── location.html │ └── guest │ │ └── home.html └── layout │ ├── guest.html │ └── admin.html ├── .gitignore ├── README.md ├── main.py └── birthday_bot.py /static/input.css: -------------------------------------------------------------------------------- 1 | @import 'tailwindcss'; 2 | -------------------------------------------------------------------------------- /src/config/__init__.py: -------------------------------------------------------------------------------- 1 | from .AppConfig import * 2 | -------------------------------------------------------------------------------- /src/bots/__init__.py: -------------------------------------------------------------------------------- 1 | from .birthday_bot import process_daily_birthdays -------------------------------------------------------------------------------- /src/context/__init__.py: -------------------------------------------------------------------------------- 1 | from .depend_context import depend_context 2 | -------------------------------------------------------------------------------- /src/parse/__init__.py: -------------------------------------------------------------------------------- 1 | from .EmployeeBioReader import * 2 | from .EmployeeBirthdayReader import * 3 | from .HotSchedulesStaffReader import * 4 | from .TimePunchReader import * 5 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- 1 | from .config import * 2 | from .context import * 3 | from .db import * 4 | from .log import * 5 | from .middleware import * 6 | from .parse import * 7 | from .routes import * 8 | -------------------------------------------------------------------------------- /src/context/depend_context.py: -------------------------------------------------------------------------------- 1 | from fastapi.templating import Jinja2Templates 2 | 3 | 4 | def depend_context(): 5 | templates = Jinja2Templates(directory="templates") 6 | return {"templates": templates} 7 | -------------------------------------------------------------------------------- /init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "ADMIN_ID=1323123212123123" >> .env 3 | echo "SQLITE_ABSOLUTE_PATH=./main.db" >> .env 4 | echo "ADMIN_USERNAME=cow" >> .env 5 | echo "ADMIN_PASSWORD=chicken" >> .env 6 | echo "TBOT_KEY=asdasdaqweqweqadas" >> .env 7 | mkdir static 8 | echo "@import 'tailwindcss';" >> ./static/input.css -------------------------------------------------------------------------------- /src/log/__init__.py: -------------------------------------------------------------------------------- 1 | def logi(msg): 2 | with open("./temp/logi.log", "w") as f: 3 | f.write(msg) 4 | 5 | 6 | def logi_clear(): 7 | logi("") 8 | 9 | 10 | def logi_append(msg): 11 | with open("./temp/logi.log", "a") as f: 12 | f.write(msg) 13 | f.write("\n\n") 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | run: 3 | uv run uvicorn main:app --reload 4 | 5 | install: 6 | uv pip install -r requirements.txt 7 | 8 | format: 9 | uv run black .; uv run isort .; 10 | 11 | bday: 12 | uv run python birthday_bot.py 13 | 14 | tw: 15 | tailwindcss -i "./static/input.css" -o "./static/output.css" --watch -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "cfasuite" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "bs4>=0.0.2", 9 | "fastapi[standard]>=0.116.1", 10 | "openpyxl>=3.1.5", 11 | "pandas>=2.3.2", 12 | "pypdf2>=3.0.1", 13 | "uvicorn>=0.35.0", 14 | ] 15 | -------------------------------------------------------------------------------- /src/routes/post_api_groupme_birthday.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from fastapi.responses import JSONResponse 3 | 4 | from ..config import AppConfig 5 | 6 | 7 | def post_api_groupme_birthday(app: FastAPI, config: AppConfig): 8 | app.post("/api/groupme/birthday") 9 | 10 | async def post_api_groupme_bithday(): 11 | return JSONResponse(status_code=200, content={"message": "hit"}) 12 | -------------------------------------------------------------------------------- /templates/page/admin/home.html: -------------------------------------------------------------------------------- 1 | {% extends "layout/admin.html" %} 2 | {% block title %}Admin Home{% endblock %} 3 | {% block content %} 4 |
12 | Please sign in to continue 13 |
14 |{{ err_create_location }}
21 |54 | {{ cfa_location.name }} 55 |
56 |58 | #{{ cfa_location.number }} 59 |
60 || Category | 73 |Hours | 74 |Wages | 75 |
|---|---|---|
| Regular | 80 |{{ time_punch_data['regular_hours'] }} | 81 |{{ time_punch_data['regular_wages'] }} | 82 |
| Overtime | 85 |{{ time_punch_data['overtime_hours'] }} | 86 |{{ time_punch_data['overtime_wages'] }} | 87 |
| Total | 90 |{{ time_punch_data['total_hours'] }} | 91 |{{ time_punch_data['total_wages'] }} | 92 |
| Dept | 105 |Percentage | 106 |Cost | 107 |
|---|---|---|
| {{ dept[0] }} | 122 |{{ time_punch_data[dept[1] + '_percentage'] }} | 123 |{{ time_punch_data[dept[1] + '_cost'] }} | 124 |
| Name | 141 |Time Punch Name | 142 |Birthday | 143 |Department | 144 |Action | 145 |
|---|---|---|---|---|
| 151 | {{ employee.name }} 152 | | 153 |154 | {{ employee.time_punch_name }} 155 | {% if employee.department == 'INIT' %} 156 | * 157 | {% endif %} 158 | | 159 |160 | {{ employee.birthday }} 161 | | 162 |163 | 177 | | 178 |179 | 185 | | 186 |
This action cannot be undone. Please type the location number to confirm.
198 | 208 |