HSupp — University Scheduling API
Backend Developer8 monthsEn coursTeam 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
Code source

Intelligence projet

Durée

8 months

Technologies

7

Statut

In Progress

Défi principal

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

Compétences démontrées

API DesignNoSQL Data ModelingAlgorithmsAuthentication

En bref

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.

Problème

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

Résultat

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

23

API resources

1000+

Lines in payroll pipeline

Résultats clés

23

API resources

7.5k+

Backend LOC

152

Commits

Visuels sélectionnés

API request and response in Postman
1 / 7

API request and response in Postman

Résultats & 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 & déploiement

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.

Fonctionnalités

Essentiel

Academic Structure CRUD

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

Essentiel

Seance Conflict Detection

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

Essentiel

JWT Authentication

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

Essentiel

Payroll Aggregation

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

Secondaire

Genetic-Algorithm Scheduler

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

Secondaire

Off-Days & Holidays

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

Planifié

Archive UI Integration

Surface the financial aggregation and analytics in a frontend dashboard.

Planifié

Scheduler API Endpoint

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

Défis & solutions

1

Conflict detection across section/group hierarchy

Le problème

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.

Comment je l'ai résolu

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

Le problème

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.

Comment je l'ai résolu

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

Le problème

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

Comment je l'ai résolu

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)

Leçons apprises

  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.

Ce que je ferais différemment

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.