21 KiB
manager_employees_python — Python Backend
Assignment 4: Implementing Control Structures — Python Backend Carlos Gutierrez ·
cgutierrez44833@ucumberlands.edu· University of the Cumberlands — MSCS — Fall 2026 This repository is the Python backend for Assignment 4. The full assignment is implemented in contrasting languages across a 3-repo suite.
Author
Carlos Gutierrez — Graduate Student, Department of Computer Science, University of the Cumberlands
- Email:
cgutierrez44833@ucumberlands.edu - Git:
CarGDev - License: MIT — Copyright (c) 2026 CarGDev (see
LICENSE)
Repositories — Project Suite
This assignment requires implementing the same scheduling application in two contrasting languages. This repo is the Python backend. The complete suite is:
| Repo | Role / Language | Description | Link |
|---|---|---|---|
| manager_employees_python — You are here | Python / Backend (FastAPI + Psycopg) | REST API, business logic, validation, and persistence. This README documents this repo. | https://git.cargdev.io/CarGDev/manager_employees_python |
| manager_employees_rust | Rust / Backend | Systems-language counterpart to contrast ownership/borrowing, match, and zero-cost abstractions against Python’s GC and dynamic typing. |
https://git.cargdev.io/CarGDev/manager_employees_rust |
| manager_employees_gui | GUI (Bonus) | Graphical input/output for employee names, shift preferences, and weekly schedule rendering. Connects to the Python/Rust backends. | https://git.cargdev.io/CarGDev/manager_employees_gui |
git clone https://git.cargdev.io/CarGDev/manager_employees_python
git clone https://git.cargdev.io/CarGDev/manager_employees_rust
git clone https://git.cargdev.io/CarGDev/manager_employees_gui
ℹ️ Scope of this README: Only the Python backend (
manager_employees_python). For the Rust implementation or the GUI bonus, see the links above.
Brief Story — Assignment 4: Implementing Control Structures
Assignment 4 challenged us to implement without logical errors the core control structures — conditionals (if/elif/else), loops (for, while), and branching (match/switch, early returns, error handling) — in multiple, paradigmatically different languages.
I chose Python for the backend because its explicit loop/conditional syntax and FastAPI’s dependency-injection make the five scheduling rules highly readable and testable, while Rust forces manual ownership, strict match exhaustiveness, and compile-time borrowing — a deliberate contrast that highlights how the same requirements map to a high-level scripting paradigm vs. a systems paradigm.
For the Python backend, I structured the code so every requirement is traceable to a control-structure site: nested for day in WEEK / for shift in SHIFTS loops in src/scheduler/manager/scheduler.py, if count >= 2 / if count >= 5 guards in src/scheduler/manager/validator.py, and same-day → next-day fallback branching in src/scheduler/manager/conflict.py. PostgreSQL persists the data, FastAPI exposes it, and a Swagger UI provides immediate visual feedback — keeping the focus on correct control flow rather than framework magic. The optional GUI bonus lives in manager_employees_gui, keeping this repo focused on backend correctness.
1. Overview
You will implement, without logical errors, various control structures such as conditionals, loops, and branching, in multiple programming languages. This assignment will demonstrate your mastery of syntax and control flow in different paradigms.
Learning objectives:
- Correct use of
if/else,for/while,match/switch, and branching/early-returns across languages. - Designing data structures that support those control structures.
- Validating scheduling invariants without logical gaps.
2. Application Prompt
You are tasked with developing a small application for managing employee schedules at a company. The company operates 7 days a week and allows employees to choose shifts in morning, afternoon, or evening.
2.1 Input and Storage
Collect employee names and their preferred shifts (morning/afternoon/evening) for each day. Store in an appropriate data structure.
Python backend mapping: POST /employees (src/scheduler/api/employee_routes.py:25), schemas CreateEmployeeRequest / DayPreferenceRequest / WeeklyPreferenceRequest (src/scheduler/core/schemas/employee.py:6-25), enums WorkTime (src/scheduler/core/enums/work_time.py:4) and DayOfWeek (src/scheduler/core/enums/day_of_week.py:4), persistence via users + weekly_preferences tables (src/scheduler/database/database.py:53-104).
2.2 Scheduling Logic
Assign shifts ensuring:
- No employee works more than one shift per day.
- An employee can work a maximum of 5 days per week.
- At least 2 employees per shift per day. If fewer, randomly assign additional available employees who have not hit 5 days.
Mapping: generate_weekly_schedule() guide (src/scheduler/manager/scheduler.py:5-16) → validate_user_has_not_worked_same_day / validate_user_has_not_worked_more_than_five_days / validate_shift_has_minimum_two_employees (src/scheduler/manager/validator.py:5-37), service ScheduleService.generate_weekly_schedule() (src/scheduler/core/services/schedule_service.py:43).
2.3 Shift Conflicts
Detect and resolve where preferred shift is full: assign to another available shift on the same or next day.
Mapping: detect_preferred_shift_conflict / resolve_conflict_same_day / resolve_conflict_next_day / resolve_missing_second_employee (src/scheduler/manager/conflict.py:5-32), fallback fill_missing_shift_coverage() (src/scheduler/manager/scheduler.py:26-31).
2.4 Output
After scheduling, output the final weekly schedule in readable format indicating employee → shift → day.
Mapping: output_weekly_schedule() (src/scheduler/models/schedule.py:18-23), print_final_schedule() (src/scheduler/manager/scheduler.py:47-52), endpoint GET /schedules/weekly (src/scheduler/api/schedule_routes.py:55) returning WeeklyScheduleResponse grouped by day_of_week → shift.
2.5 Bonus (Optional)
Allow priority ranking (e.g., 1st=morning, 2nd=evening) and accommodate as much as possible while meeting coverage.
Mapping: weekly_preferences table with first/second/third (src/scheduler/database/database.py:92-104), DayPreferenceRequest.first/second/third (src/scheduler/core/schemas/employee.py:17-21), PUT /employees/{id}/weekly-preferences (src/scheduler/api/employee_routes.py:77), repo persists and replays preferences during generation.
In addition, students may implement a GUI for input/output in one language — see manager_employees_gui (https://git.cargdev.io/CarGDev/manager_employees_gui). This Python backend exposes Swagger UI as the backend’s visual interface; full GUI is in the companion repo. TUI stubs exist at src/scheduler/tui/ (WIP).
3. Programming Language Suggestions & Contrast
Prompt allows any two distinctly different languages (e.g., not C++ and C#). Suggested: Python, Java, C++, JavaScript, Go, Rust.
Chosen for this suite:
| Language | Repo | Paradigm | Why it contrasts |
|---|---|---|---|
| Python (this repo) | manager_employees_python |
Dynamic, GC, interpreted, FastAPI, Pydantic validation | Concise loops/comprehensions, runtime exceptions, DI via Depends (src/scheduler/api/dependencies.py:25) |
| Rust | manager_employees_rust |
Static, ownership/borrowing, compiled, match exhaustiveness |
Compile-time guarantees, explicit Result/Option branching, no GC |
| GUI | manager_employees_gui |
Frontend/GUI layer | Visualizes the bonus requirement; consumes either backend |
Contrast is visible in how the same if count >= 5 { reject } / for day in days { for shift in shifts } logic is expressed.
Features — Python Backend
- Company CRUD —
CompanyService(src/scheduler/core/services/company_service.py:5) +CompanyRepository(src/scheduler/database/company_repository.py:1) - Employee CRUD — create/update/delete employees, assign to company, patch, preference updates (
src/scheduler/core/services/employee_service.py:5,src/scheduler/database/employee_repository.py:1) - Weekly Preferences — ranked
first/second/thirdper day (PUT /employees/{id}/weekly-preferences) - Schedules — direct create,
clock-in/clock-outper day, weekly view/generate (src/scheduler/core/services/schedule_service.py:8,src/scheduler/database/schedule_repository.py:1) - Health Check —
GET /health(src/scheduler/api/health_routes.py:8) - OpenAPI — auto-generated at
/api-docs/openapi.json+/swagger-ui/+ alias/api-docs/openai.json(src/scheduler/app.py:22-41)
Tech Stack — Python Backend
| Layer | Technology | Version | Source |
|---|---|---|---|
| Language | Python | >=3.10 |
pyproject.toml:9 |
| Framework | FastAPI | >=0.118 |
pyproject.toml:11 |
| Server | Uvicorn (standard) | >=0.37 |
pyproject.toml:14 |
| DB Driver | psycopg (binary) | >=3.2 |
pyproject.toml:12 |
| Env | python-dotenv | >=1.0 |
pyproject.toml:13 |
| DB | PostgreSQL | 15+ | src/scheduler/database/database.py:7 |
| Validation | Pydantic | via FastAPI | src/scheduler/core/schemas/* |
| Entry | scheduler CLI |
— | pyproject.toml:18 src/scheduler/__main__.py:6 |
Architecture — Python Backend
Client (curl / GUI / Rust) → FastAPI app.py:create_app()
→ APIRouter (api/*_routes.py)
→ Service (core/services/*) — business rules + control structures
→ Repository (database/*_repository.py + storage.py)
→ PostgreSQL (Database.initialize_schema())
Project Structure
manager_employees_python/
├── pyproject.toml # employee-manager, deps, scheduler entry
├── package.json # mirror author metadata (Carlos Gutierrez)
├── src/scheduler/
│ ├── app.py # create_app(), lifespan, routers, CORS, OpenAPI paths
│ ├── main.py # re-exports app
│ ├── __main__.py # uvicorn run (APP_HOST/APP_PORT)
│ ├── api/
│ │ ├── company_routes.py # /companies CRUD
│ │ ├── employee_routes.py # /employees + preference + company assignment
│ │ ├── schedule_routes.py # /schedules + clock-in/out + weekly
│ │ ├── health_routes.py # /health
│ │ └── dependencies.py # get_company/employee/schedule_service (Generator DI)
│ ├── core/
│ │ ├── enums/ {day_of_week.py, work_time.py}
│ │ ├── schemas/ {company.py, employee.py, schedule.py, health.py}
│ │ └── services/ {company_service.py, employee_service.py, schedule_service.py}
│ ├── database/
│ │ ├── database.py # Database class + DDL (enums, tables)
│ │ ├── company_repository.py
│ │ ├── employee_repository.py
│ │ ├── schedule_repository.py
│ │ └── storage.py # legacy helper wrappers
│ ├── manager/
│ │ ├── scheduler.py # generation guides (loops, coverage)
│ │ ├── validator.py # one-shift/day, five-days/week, min-2
│ │ └── conflict.py # same-day → next-day resolution
│ ├── models/ {employee.py, schedule.py, shift.py} # guide stubs
│ └── tui/{screens,styles}/ # GUI stub (WIP, see manager_employees_gui)
└── .env # DATABASE_URL
Database Schema
Auto-created on startup via Database().initialize_schema() in app.lifespan (src/scheduler/app.py:12).
Enums (src/scheduler/database/database.py:22-41):
CREATE TYPE work_time AS ENUM ('morning','afternoon','evening');
CREATE TYPE day_of_week AS ENUM ('sunday','monday','tuesday','wednesday','thursday','friday','saturday');
Tables:
companies(id, name UNIQUE, date_created, date_updated)(database.py:43-50)users(id, name, last_name, preference work_time, date_*)(database.py:53-62)company_users(id, user_id FK users, company_id FK companies, UNIQUE(user_id, company_id))(database.py:65-74)schedules(id, user_id FK users, enter_time, day_of_week, out_time NULLABLE, date_*)(database.py:77-89)weekly_preferences(id, user_id FK, day_of_week, first/second/third work_time, UNIQUE(user_id, day_of_week))(database.py:92-104)
Default URL: postgres://carlos:password@localhost/rust_manager_employees (database.py:7, .env:1).
API Reference — Python Backend
Base URL default: http://127.0.0.1:5006 (src/scheduler/__main__.py:7-9) — Swagger at /swagger-ui/, OpenAPI at /api-docs/openapi.json.
Health
| Method | Path | Description | Source |
|---|---|---|---|
| GET | /health |
Liveness check {status:"ok"} |
api/health_routes.py:8 |
Companies
| Method | Path | Description |
|---|---|---|
| GET | /companies |
List all companies |
| POST | /companies |
Create {name} |
| GET | /companies/{id} |
Get by id |
| DELETE | /companies/{id} |
Delete by id |
Employees
| Method | Path | Description |
|---|---|---|
| GET | /employees |
List employees |
| POST | /employees |
Create {company_id, name, last_name, preference} |
| PUT | /employees/{id} |
Full update {company_id?, name, last_name, preference} |
| PATCH | /employees/{id} |
Patch (same as PUT) |
| DELETE | /employees/{id} |
Delete |
| PUT | /employees/{id}/preference |
Update single preference |
| PUT | /employees/{id}/weekly-preferences |
Ranked 7-day prefs {preferences:[{day_of_week,first,second,third}]} |
| POST | /companies/{company_id}/employees/{employee_id} |
Assign to company |
| GET | /companies/{company_name}/employees/names |
Names by company |
Schedules
| Method | Path | Description |
|---|---|---|
| POST | /schedules |
Create {user_id, enter_time, day_of_week, out_time} |
| POST | /employees/{id}/clock-in |
Clock in {day_of_week, enter_time} |
| PUT | /employees/{id}/clock-out |
Clock out {day_of_week, out_time} |
| GET | /schedules/weekly |
Weekly schedule {schedules:[]} |
| POST | /schedules/weekly/generate |
Generate for company {company_id} |
Schemas: core/schemas/company.py, employee.py:6-44, schedule.py:8-38.
Getting Started — Python Backend
Prerequisites
- Python
>=3.10(pyproject.toml:9) - PostgreSQL 15+ running locally
psqlfor DB creation (optional)
Environment
Create .env at repo root (see .env:1):
DATABASE_URL=postgres://carlos:password@localhost/rust_manager_employees
APP_HOST=127.0.0.1
APP_PORT=5006
Set DATABASE_URL to your local Postgres if different (fallback default database.py:7 is the same).
Install
# clone this backend
git clone https://git.cargdev.io/CarGDev/manager_employees_python
cd manager_employees_python
# venv
python3 -m venv .venv
source .venv/bin/activate
# install (editable, uses src layout pyproject.toml:20-22)
pip install -e .
# or directly
pip install "fastapi>=0.118" "psycopg[binary]>=3.2" "python-dotenv>=1.0" "uvicorn[standard]>=0.37"
Database Setup
# create DB (name matches .env / database.py:7)
createdb rust_manager_employees
# or: psql -c "CREATE DATABASE rust_manager_employees;"
# schema auto-creates on app startup via lifespan (app.py:12)
# to force: python -c "from scheduler.database import Database; Database().initialize_schema()"
Run — Python Backend
# via entry point (pyproject.toml:18)
scheduler
# → uvicorn scheduler.main:app --host 127.0.0.1 --port 5006
# or directly
python -m scheduler
# or
uvicorn scheduler.main:app --host 127.0.0.1 --port 5006 --reload
# docs
open http://127.0.0.1:5006/swagger-ui/
open http://127.0.0.1:5006/api-docs/openapi.json
Usage Examples
BASE=http://127.0.0.1:5006
# health
curl $BASE/health
# 1) company
curl -X POST $BASE/companies -H "Content-Type: application/json" \
-d '{"name":"Acme Corp"}'
# 2) employees
curl -X POST $BASE/employees -H "Content-Type: application/json" \
-d '{"company_id":1,"name":"Ada","last_name":"Lovelace","preference":"morning"}'
curl -X POST $BASE/employees -H "Content-Type: application/json" \
-d '{"company_id":1,"name":"Alan","last_name":"Turing","preference":"evening"}'
curl -X POST $BASE/employees -H "Content-Type: application/json" \
-d '{"company_id":1,"name":"Grace","last_name":"Hopper","preference":"afternoon"}'
# 3) weekly ranked preferences (bonus)
curl -X PUT $BASE/employees/1/weekly-preferences -H "Content-Type: application/json" \
-d '{"preferences":[
{"day_of_week":"monday","first":"morning","second":"afternoon","third":"evening"},
{"day_of_week":"tuesday","first":"morning","second":"evening","third":"afternoon"}
]}'
# 4) clock in / out
curl -X POST $BASE/employees/1/clock-in -H "Content-Type: application/json" \
-d '{"day_of_week":"monday","enter_time":"2026-09-18T08:00:00"}'
curl -X PUT $BASE/employees/1/clock-out -H "Content-Type: application/json" \
-d '{"day_of_week":"monday","out_time":"2026-09-18T16:00:00"}'
# 5) weekly schedule
curl $BASE/schedules/weekly
curl -X POST $BASE/schedules/weekly/generate -H "Content-Type: application/json" \
-d '{"company_id":1}'
# 6) employee names by company
curl $BASE/companies/Acme%20Corp/employees/names
Scheduling Logic — Control Structures in Code
| Requirement | Control Structure | Code Location |
|---|---|---|
| Loop over 7 days × 3 shifts | for day in days: for shift in shifts: |
manager/scheduler.py:5-16 guide, services/schedule_service.py:43 |
| Preference-first assignment | if preferred == shift: assign |
manager/scheduler.py:19-23 |
| One-shift-per-day guard | if exists(user,day): reject |
manager/validator.py:5-8 |
| ≤5-days-per-week guard | count distinct days; if >=5: reject |
manager/validator.py:12-16, database/storage.py:62-73 |
| ≥2-per-shift coverage | if count < 2: add employee |
manager/validator.py:20-23, manager/scheduler.py:26-31 |
| Conflict same-day fallback | for other_shift in day: if valid: assign |
manager/conflict.py:12-16 |
| Conflict next-day fallback | for shift in next_day: if valid: assign |
manager/conflict.py:19-23 |
| Missing-second-employee | loop over company employees, skip invalid | manager/conflict.py:26-32 |
All guides are stubbed with pass and comments indicating the exact storage.* queries and validator calls to implement — ready for Assignment 4 grading of logical correctness.
GUI Bonus
The prompt’s GUI bonus is implemented in the companion repo:
- GUI Repo: https://git.cargdev.io/CarGDev/manager_employees_gui
- This Python backend serves the GUI via REST; Swagger UI at
/swagger-ui/is the backend’s immediate visual output. - TUI placeholders
src/scheduler/tui/screens/andstyles/are reserved for an in-repo TUI if needed, but the deliverable GUI lives inmanager_employees_gui.
Testing
# no test suite committed yet — manual via curl / Swagger
curl http://127.0.0.1:5006/health
curl http://127.0.0.1:5006/companies
curl http://127.0.0.1:5006/employees
Add pytest + httpx and test create_app() (app.py:17) with dependency overrides for get_db (api/dependencies.py:17) when ready.
License
MIT — Copyright (c) 2026 Carlos Gutierrez (CarGDev) — see LICENSE.
Acknowledgments
- Assignment prompt: Assignment 4 — Implementing Control Structures (University of the Cumberlands)
- Framework docs: FastAPI, Uvicorn, Psycopg, Pydantic
- Repo suite: Python Backend · Rust Backend · GUI