# Student Management System (MW600) A mini system for managing student records, built with **Express** and **MySQL**. Backend is a single file (`server.js`) exposing a CRUD API; the frontend is a plain HTML page (`index.html`) served from the same server. ## Requirements - Node.js 20.6+ (uses `process.loadEnvFile`) - A running MySQL server ## Setup ```sh npm install cp .env.example .env # then fill in your MySQL credentials npm run db:push # creates the database and imports student_db.sql npm start ``` Open http://localhost:3000 `npm run db:push` creates the `student_db` database and imports the schema and seed data from `student_db.sql`. It is safe to re-run — the script drops and recreates the `students` table. ## Database `student_db.sql` holds the schema and seed rows for a single table: | Column | Type | Notes | | ------------ | ------------ | ---------------------------- | | `id` | `INT` | Primary key, assigned by app | | `name` | `VARCHAR(100)` | Required | | `course` | `VARCHAR(50)` | Required | | `year_level` | `INT` | Required, 1–6 | ### ID format Ids are **8 digits**: a 2-digit year followed by a 6-digit counter that resets each year. ``` 26 000001 -> first student added in 2026 26 000002 -> second student added in 2026 27 000001 -> first student added in 2027 ``` The counter is per year, so ids never collide across years. Because MySQL cannot generate this pattern, `id` has no `AUTO_INCREMENT` — the application assigns it. Allocation is guarded by a MySQL advisory lock (`GET_LOCK`) so simultaneous requests cannot receive the same id. ## API | Method | Path | Response | | -------- | -------------------- | -------------------------------------------- | | `GET` | `/api/students` | `200` list of students | | `GET` | `/api/students/:id` | `200` student, `400` bad id, `404` not found | | `POST` | `/api/students` | `201` created, `400` invalid, `415` not JSON | | `PUT` | `/api/students/:id` | `200` updated, `400` invalid, `404` not found | | `DELETE` | `/api/students/:id` | `204` deleted, `404` not found | Errors use one envelope: ```json { "error": { "code": "VALIDATION_ERROR", "message": "...", "details": [] } } ``` ## Configuration All connection settings live in `.env` (not committed): | Variable | Default | | ------------- | ------------- | | `DB_HOST` | `127.0.0.1` | | `DB_PORT` | `3306` | | `DB_USER` | `root` | | `DB_PASSWORD` | *required* | | `DB_NAME` | `student_db` | | `PORT` | `3000` |