Skip to content
/ api Public

This project contains the api source code that is hosted on a different server

License

Notifications You must be signed in to change notification settings

LLG-Mapper/api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

API

Overview

This project contains the API source code that is hosted on a different server.

The complete REST API is documented below. All endpoints return JSON responses and validate input using Marshmallow schemas.


Health Check:

GET /health → {"status": "ok"}

Main Endpoints:

  • /buildings - Building management
  • /rooms - Room availability and filtering
  • /classes - Class scheduling

🚀 Getting Started

Prerequisites

  • Python 3.8 or higher
  • pip (Python package manager)
  • Modern web browser (Chrome, Firefox, Safari, Edge)

Installation & Setup

1. Clone the Repository

git clone https://github.com/LLG-Mapper/api.git
cd api

Or clone using GitHub Desktop

2. First-Time Setup

Windows

# From api/ directory
scripts\setup

macOS/Linux

# From api/ directory
./scripts/setup.sh # macOS/Linux

3. Start the API Server

Windows

# From api/ directory
scripts\start

macOS/Linux

# From api/ directory
./scripts/start.sh # macOS/Linux

The API will be available at http://localhost:5000 (development mode).


🛠️ Technology Stack

  • Framework: Flask 3.1.2
  • ORM: SQLAlchemy 2.0.45
  • Database: SQLite (development), configurable for production
  • Serialization: Marshmallow 3.21.3
  • Migrations: Flask-Migrate with Alembic
  • CORS: Flask-CORS 6.0.2

📁 Project Structure

api/
├── app/
│   ├── __init__.py              # Flask app factory
│   ├── config.py                # Configuration
│   ├── extensions.py            # Flask extensions
│   ├── models/                  # SQLAlchemy ORM models
│   │   ├── building.py
│   │   ├── room.py
│   │   ├── class_.py
│   │   ├── teacher.py
│   │   ├── group.py
│   │   ├── subject.py
│   │   ├── feature.py
│   │   ├── room_type.py
│   │   └── enums.py
│   ├── schemas/                 # Marshmallow validation
│   │   ├── building.py
│   │   ├── room.py
│   │   ├── class_.py
│   │   ├── teacher.py
│   │   ├── group.py
│   │   ├── subject.py
│   │   ├── feature.py
│   │   └── room_type.py
│   ├── routes/                  # API endpoints
│   │   ├── buildings.py
│   │   ├── rooms.py
│   │   ├── classes.py
│   │   ├── health.py
│   │   └── __init__.py
│   └── services/                # Business logic
│       └── availability_service.py
├── migrations/                  # Database migrations
├── scripts/                     # Database setup
├── app.py                       # Entry point
├── requirements.txt
└── README.md                    # Project overview (this file)

📊 Database Schema

Data Models

Building

Main building/campus entity for organizing rooms.

Field Type Constraints
id Integer Primary Key
name String(50) Unique, Required
code String(3) Unique, Required
floor Integer Default: 0 (for uneven grounds)

Example:

{
  "id": 1,
  "name": "Victor Hugo",
  "code": "VH",
  "floor": 1
}

RoomType

Classification of room types (classroom, lab, auditorium, etc.).

Field Type Constraints
id Integer Primary Key
name String(50) Unique, Required
code String(10) Unique, Required

Example:

{
  "id": 1,
  "name": "Laboratory",
  "code": "LAB"
}

Feature

Room amenities/equipment (projector, whiteboard, computers, etc.).

Field Type Constraints
id Integer Primary Key
name String(50) Unique, Required
code String(10) Unique, Required

Example:

{
  "id": 1,
  "name": "Projector",
  "code": "PROJ"
}

Room

Physical classroom or space.

Field Type Constraints
id Integer Primary Key
number Integer Required
name String(50) Optional (auto: {building.code}{number})
building_id Integer Foreign Key → Building
floor Integer Required
capacity Integer Optional
is_open Boolean Default: true
type_id Integer Foreign Key → RoomType
locationX Integer Required (map coordinate)
locationY Integer Required (map coordinate)
sizeX Integer Required (map dimension)
sizeY Integer Required (map dimension)

Relationships:

  • Building (Many-to-One)
  • RoomType (Many-to-One)
  • Features (Many-to-Many via room_features)
  • Classes (One-to-Many)

Example:

{
  "id": 1,
  "number": 209,
  "name": "VH209",
  "building": {"id": 1, "name": "Victor Hugo", "code": "VH", "floor": 1},
  "floor": 2,
  "capacity": 40,
  "is_open": true,
  "type": {"id": 1, "name": "Classroom", "code": "CLASS"},
  "location": [130, 47],
  "size": [60, 40],
  "features": [
    {"id": 1, "name": "Projector", "code": "PROJ"},
    {"id": 2, "name": "Whiteboard", "code": "WBOARD"}
  ]
}

Subject

Academic subject (Math, French, Physics, etc.).

Field Type Constraints
id Integer Primary Key
name String(50) Unique, Required
code String(10) Unique, Required
color Enum(Color) Default: BLUE

Color Options: BLUE, GREEN, RED, YELLOW, PURPLE, ORANGE, GRAY

Example:

{
  "id": 1,
  "name": "Mathematics",
  "code": "MATH",
  "color": "BLUE"
}

Teacher

Instructor information.

Field Type Constraints
id Integer Primary Key
name String(50) Required
surname String(50) Required
gender Boolean Required (true=F, false=M)
subject_id Integer Foreign Key → Subject (Optional)

Relationships:

  • Subject (Many-to-One)
  • Classes (One-to-Many)

Example:

{
  "id": 1,
  "name": "Michel Dupont",
  "surname": "Dupont",
  "gender": false,
  "subject": {"id": 1, "name": "Mathematics", "code": "MATH", "color": "BLUE"}
}

Note: Response includes formatted name with gender prefix (M/Mme.)


Group

Student class/cohort.

Field Type Constraints
id Integer Primary Key
name String(50) Required
grade Enum(Grade) Required

Grade Options:

  • 10 = 2nde (Grade 10)
  • 11 = 1ère (Grade 11)
  • 12 = Terminale (Grade 12)
  • 13 = CPGE 1 (Grade 13)
  • 14 = CPGE 2 (Grade 14)

Example:

{
  "id": 1,
  "name": "2nd-1",
  "grade": 10
}

Class

Scheduled class session.

Field Type Constraints
id Integer Primary Key
room_id Integer Foreign Key → Room (Required)
teacher_id Integer Foreign Key → Teacher (Required)
group_id Integer Foreign Key → Group (Required)
subject_id Integer Foreign Key → Subject (Required)
start_date Date Required
end_date Date Optional (NULL = one-off session)
start_time Time Required
end_time Time Required
recurrence Enum(Frequency) Default: WEEKLY
weekday Integer 0=Monday, 6=Sunday (optional)

Weekdays 0 = Monday ... 6 = Sunday

Recurrence Options:

  • ONCE = One-time session
  • WEEKLY = Every week
  • WEEK_A = Alternating week A
  • WEEK_B = Alternating week B

Relationships:

  • Room (Many-to-One)
  • Teacher (Many-to-One)
  • Group (Many-to-One)
  • Subject (Many-to-One)

Example:

{
  "id": 1,
  "room": {...},
  "teacher": {...},
  "group": {...},
  "subject": {...},
  "start_date": "2024-01-15",
  "end_date": "2024-06-30",
  "start_time": "09:00:00",
  "end_time": "10:00:00",
  "recurrence": "WEEKLY",
  "weekday": 0
}

API Endpoints

Endpoint Reference

Active Endpoints:

Planned Endpoints (Coming Soon):

  • Room Types

    • GET /room-types - List room types
    • POST /room-types - Create room type
  • Features

    • POST /features - Create feature
  • Teachers

    • GET /teachers - List teachers
    • GET /teachers/{id} - Get teacher by ID
    • POST /teachers - Create teacher
  • Groups

    • GET /groups - List groups
    • POST /groups - Create group

Health Check

GET /health

Response (200 OK):

{
  "status": "ok"
}

Buildings

List All Buildings

GET /buildings

Response (200 OK):

[
  {
    "id": 1,
    "name": "Victor Hugo",
    "code": "VH",
    "floor": 1
  }
]

Get Building by ID

GET /buildings/{id}

Create Building

POST /buildings
Content-Type: application/json

{
  "name": "Molière",
  "code": "M",
  "floor": 0
}

Response (201 Created):

{
  "id": 1,
  "name": "Molière",
  "code": "M",
  "floor": 0
}

Update Building

PUT /buildings/{id}
Content-Type: application/json

{
  "floor": 1
}

Delete Building

DELETE /buildings/{id}

Response (204 No Content)


Rooms

List Rooms (with filtering & availability)

GET /rooms?building_id=1&floor=2&feature_codes=PROJ,WBOARD&is_available=true&availability_at=2024-01-15T09:00:00

Query Parameters:

Parameter Type Description
building_id integer Filter by building
floor integer Filter by floor number
feature_codes string[] Filter by features (comma-separated codes)
is_available boolean Filter by availability status
availability_at ISO datetime Check availability at specific time

Response (200 OK):

[
  {
    "id": 1,
    "number": 209,
    "name": "VH209",
    "building": {...},
    "floor": 2,
    "capacity": 40,
    "is_open": true,
    "type": {...},
    "location": [130, 47],
    "size": [60, 40],
    "features": [...]
  }
]

Or with availability:

{
  "availability_at": "2024-01-15T09:00:00",
  "rooms": [...]
}

Get Room by ID

GET /rooms/{id}

Create Room

POST /rooms
Content-Type: application/json

{
  "number": 209,
  "name": "VH209",
  "building_id": 1,
  "floor": 2,
  "capacity": 40,
  "is_open": true,
  "type_id": 1,
  "locationX": 130,
  "locationY": 47,
  "sizeX": 60,
  "sizeY": 40,
  "feature_ids": [1, 2]
}

Response (201 Created):

{
  "id": 1,
  "number": 209,
  "name": "VH209",
  ...
}

Update Room

PUT /rooms/{id}
Content-Type: application/json

{
  "capacity": 45,
  "is_open": false,
  "feature_ids": [1, 3]
}

Delete Room

DELETE /rooms/{id}

Response (204 No Content)


Classes

List Classes

GET /classes

Response (200 OK):

[
  {
    "id": 1,
    "room": {...},
    "teacher": {...},
    "group": {...},
    "subject": {...},
    "start_date": "2024-01-15",
    "end_date": "2024-06-30",
    "start_time": "09:00:00",
    "end_time": "10:00:00",
    "recurrence": "WEEKLY",
    "weekday": 0
  }
]

Get Class by ID

GET /classes/{id}

Create Class

POST /classes
Content-Type: application/json

{
  "room_id": 1,
  "teacher_id": 1,
  "group_id": 1,
  "subject_id": 1,
  "start_date": "2024-01-15",
  "end_date": "2024-06-30",
  "start_time": "09:00:00",
  "end_time": "10:00:00",
  "recurrence": "WEEKLY",
  "weekday": 0
}

Response (201 Created):

{
  "id": 1,
  ...
}

Update Class

PUT /classes/{id}
Content-Type: application/json

{
  "start_time": "10:00:00",
  "end_time": "11:00:00"
}

Delete Class

DELETE /classes/{id}

Response (204 No Content)


Request/Response Examples

Error Handling

All endpoints return validation errors with detailed messages:

POST /buildings
Content-Type: application/json

{
  "name": "Test"
}

Response (400 Bad Request):

{
  "errors": {
    "code": ["Missing data for required field."]
  }
}

Date/Time Formatting

  • Dates: ISO format YYYY-MM-DD
  • Times: ISO format HH:MM:SS
  • DateTime: ISO format YYYY-MM-DDTHH:MM:SS

Location & Size

Room coordinates are returned as arrays:

{
  "location": [130, 47],  // [X, Y]
  "size": [60, 40]        // [width, height]
}

Data Types & Enums

Frequency (Class Recurrence)

ONCE   - "once"
WEEKLY - "weekly"
WEEK_A - "weekA"
WEEK_B - "weekB"

Color (Subject Color)

BLUE
GREEN
RED
YELLOW
PURPLE
ORANGE
GRAY

Grade (Student Grade Level)

10 → 2nde (Grade 10)
11 → 1ère (Grade 11)
12 → Terminale (Grade 12)
13 → CPGE 1 (Grade 13)
14 → CPGE 2 (Grade 14)

🔧 Development Notes

Database Migrations

# Create new migration
flask db migrate -m "Description"

# Apply migrations
flask db upgrade

# Rollback
flask db downgrade

Validation

All POST/PUT requests are validated using Marshmallow schemas:

  • Type checking
  • Required field validation
  • Relationship integrity

Serialization

Responses automatically handle:

  • Enum value conversion
  • Datetime/Date/Time formatting
  • Nested relationship serialization
  • Field inclusion/exclusion based on context

📞 Support & Questions

For issues or questions about the API or project setup, please refer to the main project README or open an issue on the repository.


📝 License

This project is licensed under the MIT License. See the LICENSE file for details.

About

This project contains the api source code that is hosted on a different server

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •