2026-09-18 12:51:31 -04:00
2026-09-18 12:26:25 -04:00
2026-09-17 18:49:19 -04:00
2026-09-17 22:48:56 +00:00
2026-09-18 12:51:31 -04:00
2026-09-18 12:51:31 -04:00
2026-09-18 12:51:31 -04:00

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.

Python 3.10+ FastAPI PostgreSQL License: MIT


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/third per day (PUT /employees/{id}/weekly-preferences)
  • Schedules — direct create, clock-in / clock-out per 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
  • psql for 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/ and styles/ are reserved for an in-repo TUI if needed, but the deliverable GUI lives in manager_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
S
Description
No description provided
Readme MIT 91 KiB
Languages
Python 100%