ulaskelas-backend - Documentation
| Document Status | ||
|---|---|---|
| Document Owner | Product Engineering 2026 | Product Engineering 2026 |
| Contributors | ||
| Project Links | https://github.com/ristekoss/ulaskelas-backend | https://github.com/ristekoss/ulaskelas-backend |
| Project Links | https://api-ulaskelas.ristek.cs.ui.ac.id https://api-ulaskelas-stg.ristek.cs.ui.ac.id | https://api-ulaskelas.ristek.cs.ui.ac.id https://api-ulaskelas-stg.ristek.cs.ui.ac.id |
| Project Links | [Monitoring Dashboard] | [Monitoring Dashboard] |
| Project Links | [API Documentation] | [API Documentation] |
| Project Links | [Other Related Doc/Link] | [Other Related Doc/Link] |
| Team | Theodore Kevin Himawan | theodore.kevin@ristek.cs.ui.ac.id |
| Team | Ari Darrell Muljono | darrell@ristek.cs.ui.ac.id |
| Team | Grace Karina | gracekarin@ristek.cs.ui.ac.id |
| Team | Yeshua Marco G. Manurung | marco@ristek.cs.ui.ac.id |
π Background
Overviewβ
UlasKelas backend provides authenticated access to course information, reviews, bookmarks, discussion features, and GPA calculator data. The main problem it solves is centralizing academic and user-generated data behind a single API so frontend clients can serve course exploration and academic support features consistently.
Stakeholdersβ
- Users: UI students
- Upstream Dependencies: SSO UI
- Downstream Consumers: UlasKelas frontend
Scope & Boundariesβ
- In Scope: course synchronization, reviews, bookmarks, discussion flows, leaderboard, GPA calculator, authenticated API access
- Out of Scope: timetable generation, frontend rendering details, legacy data migration
βοΈ Architecture & Design
System Diagramβ
Architecture Decisions (ADRs)β
- Language/Framework: Python, Django, Django REST
- Database: PostgreSQL
- Communication: synchronous HTTP between frontend, backend, and upstream course provider
π»Technical Specifications
API Documentationβ
GET /pingβ
Response 200
"pong"
GET /health-checkβ
Response 200
{"message":"OK"}
GET /login/β
Response 302
{
"redirect_to":"/token or supplied redirect_url"
}
GET /token/β
Response 200
{
"token":"<drf_token>",
"username":"user123"
}
GET /logout/β
Response 302
{
"redirect_to":"<sso_logout_url>"
}
POST /api-auth-token/β
Request
{
"username":"string",
"password":"string"
}
Response 200
{
"token":"<drf_token>"
}
POST /update-course/β
Response 200
{
"message":"Course updated succeed on 2026-03-23 10:00:00, elapsed time: 2 seconds"
}
GET /api/v1/coursesβ
Response 200
{
"data":{
"courses":[
{
"id":1,
"code":"CSGE601021",
"name":"String",
"sks":3,
"term":5,
"review_count":10,
"rating_average":4.2
}
]
},
"error":null
}
GET /api/v1/courses/{id}β
Response 200
{
"data":{
"course":{
"id":1,
"code":"CSGE601021",
"name":"String"
}
},
"error":null
}
GET /api/v1/reviews?id={id}β
Response 200
{
"data":{
"id":1,
"course_code":"CSGE601021",
"content":"Helpful course",
"author":"user123"
},
"error":null
}
GET /api/v1/reviews?page={page}&course_code={code}β
Response 200
{
"data":[
{
"id":1,
"course_code":"CSGE601021",
"content":"Helpful course",
"likes_count":4,
"tags":["SERU"]
}
],
"total_page":1,
"error":null
}
GET /api/v1/reviews?page={page}&by_author=trueβ
Response 200
{
"data":[
{
"id":1,
"course_code":"CSGE601021",
"content":"Helpful course"
}
],
"total_page":1,
"error":null
}
POST /api/v1/reviewsβ
Request
{
"course_code":"CSGE601021",
"academic_year":"2025/2026",
"semester":1,
"content":"Helpful course",
"is_anonym":false,
"tags":["SERU"]
}
Response 201
{
"data":{
"id":1,
"course_code":"CSGE601021",
"content":"Helpful course"
},
"error":null
}
PUT /api/v1/reviewsβ
Request
{
"review_id":1,
"content":"Updated review"
}
Response 200
{
"data":{
"id":1,
"content":"Updated review"
},
"error":null
}
DELETE /api/v1/reviews?review_id={id}β
Response 200
{
"data":{
"review_id":1,
"is_active":false
},
"error":null
}
GET /api/v1/ds-reviewsβ
Response 200
{
"data":[
{
"id":1,
"content":"Helpful course"
}
],
"error":null
}
POST /api/v1/ds-reviewsβ
Request
[
{
"id":1,
"sentimen":1,
"hate_speech_status":"APPROVED"
}
]
Response 200
{
"data":[
{
"id":1,
"hate_speech_status":"APPROVED"
}
],
"error":null
}
POST /api/v1/likesβ
Request
{
"review_id":1,
"is_like":true
}
Response 200
{
"data":{
"review_id":1,
"is_like":true
},
"error":null
}
GET /api/v1/bookmarksβ
Response 200
{
"data":[
{
"user":"user123",
"course_id":1,
"course_code":"CSGE601021",
"course_name":"String"
}
],
"error":null
}
POST /api/v1/bookmarksβ
Request
{
"course_code":"CSGE601021",
"is_bookmark":true
}
Response 200
{
"data":{
"course_code":"CSGE601021",
"is_bookmark":true
},
"error":null
}
GET /api/v1/tagsβ
Response 200
{
"data":{
"tags":["SERU","JELAS"]
},
"error":null
}
POST /api/v1/tagsβ
Request
{
"tags":["seru","jelas"]
}
Response 200
{
"data":{
"tags":["SERU","JELAS"]
},
"error":null
}
DELETE /api/v1/tagsβ
Request
{
"tags":["seru"]
}
Response 200
{
"data":{
"tags":["SERU"]
},
"error":null
}
GET /api/v1/accountβ
Response 200
{
"data":{
"username":"user123",
"study_program":"Ilmu Komputer"
},
"error":null
}
GET /api/v1/leaderboardβ
Response 200
{
"data":[
{
"username":"user123",
"likes_count":42,
"generation":"2022"
}
],
"error":null
}
GET /update-leaderboard/β
Response 200
{
"message":"Leaderboard updated succeed on 2026-03-23 10:00:00, elapsed time: 1 seconds"
}
GET /api/v1/calculator-gpaβ
Response 200
{
"data":{
"all_semester_gpa":[],
"cumulative_gpa":{
"cumulative_gpa":0.0,
"total_sks":0
},
"courses":[]
},
"error":null
}
POST /api/v1/calculator-gpaβ
Request
{
"given_semesters":["Semester 5","Semester 6"]
}
Response 201
{
"data":[
{
"pk":1,
"given_semester":"Semester 5",
"total_sks":0,
"semester_gpa":0.0,
"semester_mutu":0.0
}
],
"error":null
}
GET /api/v1/calculator-gpa/{given_semester}β
Response 200
{
"data":{
"pk":1,
"given_semester":"Semester 5",
"total_sks":6,
"semester_gpa":3.5,
"semester_mutu":21.0
},
"error":null
}
DELETE /api/v1/calculator-gpa/{given_semester}β
Response 200
{
"data":{
"given_semester":"Semester 5",
"deleted":true
},
"error":null
}
GET /api/v1/course-semester?given_semester=Semester%205β
Response 200
{
"data":{
"semester":{
"pk":1,
"given_semester":"Semester 5",
"total_sks":6,
"semester_gpa":3.5,
"semester_mutu":21.0
},
"courses_calculator":[
{
"id":1,
"course_id":10,
"course_name":"String",
"course_sks":3,
"total_score":85.0,
"total_percentage":100.0
}
]
},
"error":null
}
Data Model/Schemaβ
https://drive.google.com/file/d/1w8n4m_3daoie64Aly3Emxl7NyGBe1esy/view?usp=sharing
Project Structureβ
ulaskelas-backend/
βββ __init__.py # package marker
βββ asgi.py # ASGI entrypoint
βββ settings.py # default Django settings
βββ settings_heroku.py # deployment settings override for Heroku-style runtime
βββ urls.py # root URL router
βββ wsgi.py # WSGI entrypoint and background job bootstrap
main/
βββ __init__.py # package marker
βββ admin.py # Django admin registrations
βββ apps.py # app config
βββ decorators.py # app-level decorators
βββ fasilkom_courses.py # static recommended course grouping for GPA auto-fill
βββ models.py # core relational data model
βββ serializers.py # serializers for course, review, account, GPA, and Tanya Teman payloads
βββ urls.py # API endpoint registration under /api/v1 and /api/v2
βββ utils.py # response helpers, validation, GPA math, pagination, and profile bootstrap
βββ views.py # ping, health, login, logout, bookmarks, tags, account, leaderboard, manual sync
βββ views_calculator.py # calculator and score-component CRUD
βββ views_course.py # course listing, filtering, fuzzy search, and detail retrieval
βββ views_gpa_calculator.py # GPA planner, course-semester, course-component, and subcomponent logic
βββ views_review.py # review CRUD and DS moderation endpoints
βββ views_tanyateman.py # question, answer, like, upload, and notification flows
βββ migrations/
β βββ 0001_initial.py # initial schema
β βββ ... # schema evolution for GPA, Tanya Teman, and likes
β βββ 0026_auto_20251113_1512.py
βββ tests/
βββ __init__.py
βββ test_model.py # model tests
βββ test_serializer.py # serializer tests
courseUpdater/
βββ __init__.py # package marker
βββ courseApi.py # fetches and upserts course catalog from SUNJAD_BASE_URL
βββ updater.py # APScheduler job definition for periodic course sync
leaderboard_updater/
βββ __init__.py # package marker
βββ updater.py # recomputes likes leaderboard values on Profile
live_config/
βββ __init__.py # package marker
βββ admin.py # admin registration for live config models
βββ apps.py # app config
βββ models.py # persisted config model definitions
βββ utils.py # config helper utilities
βββ views.py # runtime config accessors used by serializers and filters
βββ migrations/
β βββ 0001_initial.py # initial live config schema
β βββ __init__.py
βββ defaultConfig/
βββ course_prefixes.json # code prefix to label mapping
βββ cs_course_code_map.json # course code mapping for CS-related logic
βββ kd_org.json # organization code mapping
βββ study_program.json # study program to course prefix mapping
sso/
βββ __init__.py # SSO defaults including base CAS config
βββ cas.py # CAS client implementation
βββ decorators.py # SSO decorator used by login flow
βββ utils.py # protocol, redirect, and logout helper utilities
Dockerfile # container build definition
docker-compose.yml # local compose stack
docker-compose-prod.yml # prod-like compose stack
deployment.sh # deployment helper script
manage.py # Django management entrypoint
requirements.txt # Python dependencies
sample.env # sample environment variables
README.md # repository readme and tech doc
pull_request_template.md # pull request template
Componentsβ
| Layer | Paths | Responsibility |
|---|---|---|
| App Bootstrap | UlasKelas/settings.py, UlasKelas/urls.py, UlasKelas/wsgi.py, UlasKelas/asgi.py | Initializes Django configuration, registers root URL routing, and defines entrypoints for HTTP serving and background processes. |
| Route Layer | main/views.py, main/views_course.py, main/views_review.py, main/views_calculator.py, main/views_gpa_calculator.py, main/urls.py, live_config/views.py | Exposes HTTP endpoints, organized by domain including authentication, course catalog, reviews, bookmarks, leaderboard, GPA planner, Tanya Teman, and live configuration. |
| Auth Services | main/views.py, main/utils.py, main/decorators.py, sso/cas.py, sso/decorators.py, sso/utils.py | Handles CAS-based authentication, token generation, session validation, redirect handling, and first-time user profile initialization. |
| Domain Models | main/models.py, live_config/models.py | Defines relational database schemas for profiles, courses, reviews, bookmarks, likes, GPA planning entities, Tanya Teman content, and configuration data. |
| Course Sync Services | courseUpdater/courseApi.py, courseUpdater/updater.py | Fetches course data from Susun Jadwal, performs upsert operations into the Course model, and provides scheduled synchronization logic. |
| Review and Community Workflow | main/views_review.py, main/views.py, main/views_tanyateman.py, main/serializers.py, main/models.py | Handles review submission, likes, tags, bookmarks, leaderboard retrieval, Tanya Teman questions and answers, optional image uploads, and notification flows. |
| GPA Planner and Score Calculation | main/views_gpa_calculator.py, main/views_calculator.py, main/utils.py, main/models.py | Manages semester planning, course selection, score calculators, weighted components, subcomponent scoring, and cumulative GPA computation. |
| Integration & Message | sso/cas.py, sso/utils.py, live_config/defaultConfig/* | Provides CAS integration, SSO utilities, and static configuration datasets for course labeling and study program mapping. |
| Background Jobs for Leaderboard | leaderboard_updater/updater.py, courseUpdater/updater.py | Handles scheduled leaderboard recalculation and periodic course synchronization. |
βοΈ Operational Playbook
Infrastructureβ
- Cloud Provider: Pusilkom
- Link: https://api-ulaskelas.ristek.cs.ui.ac.id, https://api-ulaskelas-stg.ristek.cs.ui.ac.id
Environment Variablesβ
| Key | Description | Default (Dev) | Sensitive? |
|---|---|---|---|
| ACCESS_KEY_ID | AWS access key ID used to authenticate requests to AWS services | β | Yes |
| ACCESS_KEY_SECRET | AWS secret access key used for secure authentication with AWS services | β | Yes |
| AWS_REGION | AWS region where services (e.g. S3) are hosted | ap-southeast-1 | No |
| AWS_S3_FOLDER_PREFIX | Prefix or folder path used to organize files in the S3 bucket | production | No |
| BUCKET_NAME | Name of the AWS S3 bucket used for file storage | ristek-ulaskelas | No |
| DEBUG | Flag to enable or disable debug mode in the application | FALSE | No |
| DJANGO_SETTINGS_MODULE | Specifies the Django settings module used by the application | UlasKelas.settings | No |
| EMAIL_HOST_PASSWORD | Password used for authenticating the email service account | β | Yes |
| EMAIL_HOST_USER | Email address used as the sender for outgoing emails | noreply@ristek.cs.ui.ac.id | No |
| NOTIFICATION_RECIPIENT_ | Email address that receives system notifications or alerts | temankuliah.ristek@gmail.com | No |
| POSTGRES_DB | Name of the PostgreSQL database used by the application | ulaskelas_backend_prod | No |
| POSTGRES_HOST | Hostname or IP address of the PostgreSQL database server | β | Yes |
| POSTGRES_PASSWORD | Password for PostgreSQL database authentication | β | Yes |
| POSTGRES_PORT | Port used to connect to the PostgreSQL database | 5432 | No |
| POSTGRES_USER | Username for PostgreSQL database authentication | β | Yes |
| PYTHONPATH | Path configuration for Python module resolution | ./env | No |
| SECRET_KEY | Secret key used for cryptographic signing and security in Django | β | Yes |
| SENTRY_DSN | Data Source Name used for sending error logs to Sentry | β | Yes |
| SUNJAD_BASE_URL | Base URL for the SusunJadwal API service | https://api.susunjadwal.cs.ui.ac.id | No |
| ULASKELAS_ADMIN_LINK | URL endpoint for accessing the UlasKelas admin dashboard | https://api-ulaskelas.ristek.cs.ui.ac.id/admin/login | No |
| ULASKELAS_ANSWER_LINK | Relative path for accessing answer management in admin panel | /admin/main/answer | No |
| ULASKELAS_QUESTION_LINK | Relative path for accessing question management in admin panel | /admin/main/question | No |
πQuestions
π List of frequently asked questions or question that need to be answered that is related to this initiative ..