HSupp — University Scheduling API
Backend Developer8 monthsIn ProgressTeam of 2

HSupp — University Scheduling API

Express + MongoDB API for university timetabling with conflict detection, payroll aggregation, and a genetic-algorithm scheduler

EJExpress.jsNode.jsNode.jsMongoDBMongoDBMMongooseJJWTPPythonGAGenetic Algorithms
Source Code

Project Intelligence

Duration

8 months

Technologies

7

Status

In Progress

Key Challenge

Detecting schedule conflicts across overlapping section/group hierarchies in a single Mongo query inside a Mongoose pre-save hook

Skills Demonstrated

API DesignNoSQL Data ModelingAlgorithmsAuthentication

TL;DR

HSupp (HeurSupp) is a production-scale REST API for managing university schedules end-to-end: academic hierarchy (departments → levels → specialties → semesters → subjects → sections → groups), teacher sessions, rooms, and seances. A Mongoose pre-save hook enforces time-overlap conflict detection across teachers, rooms, sections, and groups; a 1,000-line aggregation pipeline computes hourly charges and payroll (Brut → IRG → Net); and a standalone Python genetic algorithm generates conflict-free weekly timetables.

Problem

Manual university timetabling produced teacher, room, and group double-bookings and error-prone payroll

Solution

Mongoose-level conflict detection, payroll aggregation pipeline, and a genetic-algorithm timetable generator

Result

23-resource API that validates schedules at write time and auto-generates conflict-free weekly timetables

23

API resources

1000+

Lines in payroll pipeline

Key Outcomes

23

API resources

7.5k+

Backend LOC

152

Commits

Curated Visuals

API request and response in Postman
1 / 7

API request and response in Postman

Results & Impact

A deep, real-world backend that does far more than CRUD: it enforces scheduling invariants at the database layer and computes payroll-grade financials.

Turns manual, conflict-prone university timetabling into a validated, queryable system with a path to fully automated schedule generation.

8

Months of development

26

Controllers

Architecture

System architecture overview

Layered Express API: route modules per resource → controllers (factory or custom) → Mongoose models with embedded validation.

The academic hierarchy is a tree of referenced documents — Department → Level → Specialty → Semester → Subject → Section → Group — with Room and Teacher as cross-cutting resources. Seances reference these plus a TeacherSession and Session, and all conflict/payroll logic lives in model middleware and controllers rather than the route layer.

The genetic-algorithm scheduler runs as a separate Python package that consumes JSON-serialized model dicts and returns assignments, keeping the optimization logic independent of the Node runtime.

Infrastructure & Deployment

Express server with MongoDB (local or Atlas). Hardened with Helmet, express-rate-limit, mongo-sanitize, xss-clean, and CORS. Emails via Nodemailer with Pug templates; image uploads via Multer + Sharp.

Features

Core

Academic Structure CRUD

Departments, levels, specialties, semesters, subjects, sections, groups, and rooms as referenced collections.

Core

Seance Conflict Detection

Pre-save hook rejects overlapping teacher, room, section, or group bookings with precise messages.

Core

JWT Authentication

Separate teacher and admin auth with bcrypt hashing and Nodemailer password reset.

Core

Payroll Aggregation

Expands recurring seances over a date range and computes Brut → IRG → Net by week and month.

Secondary

Genetic-Algorithm Scheduler

Standalone Python engine that generates conflict-free weekly timetables under hard/soft constraints.

Secondary

Off-Days & Holidays

Teacher- and session-level off-days that subtract from worked hours and payroll.

Planned

Archive UI Integration

Surface the financial aggregation and analytics in a frontend dashboard.

Planned

Scheduler API Endpoint

Expose the genetic algorithm as a REST endpoint that writes generated seances back to Mongo.

Challenges & Solutions

1

Conflict detection across section/group hierarchy

The Problem

A seance can target a whole section (fanning out to all its groups) or a set of groups (rolling up to their sections). Naive equality checks missed overlaps between a section-level lecture and a group-level lab.

How I Solved It

Build an audience scope that unions the section, its groups, and the parent sections of any provided groups, then run one overlap query against teacher, room, section, and group on the same session and day.

const existingSeances = await this.constructor.find({
  session: this.session,
  seanceDay: this.seanceDay,
  $or: orConditions, // group, section, room, teacherSession
  $and: [
    { startHour: { $lt: this.endHour } },
    { endHour: { $gt: this.startHour } },
  ],
});
2

Payroll across recurring seances and off-days

The Problem

Teacher pay depends on how many times a weekly seance actually occurs inside a session date range, minus holidays and off-days, with hourly-charge thresholds.

How I Solved It

Expand each seance into concrete dated occurrences for its weekday, subtract off-days, apply coefficient/threshold rules, then aggregate Brut → IRG → Net grouped by week and month.

groupedData.totalIRG = groupedData.totalBrut - groupedData.totalBrut * 0.1;
groupedData.totalNet = groupedData.totalIRG - groupedData.totalIRG * 0.09;
3

Generating timetables without a solver

The Problem

Producing a full weekly schedule by hand is combinatorial and conflict-prone across teachers, rooms, and groups.

How I Solved It

A genetic algorithm encodes each required session as a gene (an index into its feasible assignments), seeds half the population greedily, uses tournament selection with 10% elitism, and applies adaptive mutation when fitness stagnates.

for existing in teacher_slots.get(t_key, []):
    if self._slots_overlap(existing, slot):
        hard_penalty += HARD  # double-booking = hard violation
teacher_slots.setdefault(t_key, []).append(slot)

Lessons Learned

  1. 1

    Push invariants into the model layer

    Putting conflict detection in a Mongoose pre-save hook meant every code path — REST, seeds, scripts — got the same guarantees for free.

  2. 2

    Factory CRUD, custom where it matters

    A generic handlerFactory removed boilerplate for simple resources so effort could focus on seances, sessions, and the archive pipeline.

  3. 3

    Keep optimization out of the request path

    Modeling the timetable generator as a standalone Python GA kept the API responsive and the algorithm independently testable.

  4. 4

    Hierarchy makes conflicts subtle

    A section-level lecture implicitly occupies every group in that section — the audience-scope expansion was essential to catch those overlaps.

What I'd Do Differently

Wire the genetic-algorithm scheduler into the API as a real endpoint and surface the enterprise archive/payroll features in the frontend — roughly 80% of the backend capability is still unused by the UI. Add automated tests around the conflict and payroll logic.