# Timetabler Backend Specifications

This specification describes the behavior exposed by the current Django backend and its companion Kafka, Redis, and Socket.IO workers.

## API Protocol

| Item | Specification |
| --- | --- |
| Base path | `/api/admin/` |
| Method style | Admin endpoints are implemented as DRF class-based views and primarily handle `POST`. |
| Authentication | Protected endpoints require `Authorization: Token <token>`. `Login` disables token authentication. |
| Token lifecycle | Login deletes any token for the same user, app type, and device, then creates a new `AccessToken` expiring after 2 hours. Logout deletes the presented token. |
| Permission model | Route names such as `staff;create` and `schedule;request` are permission keys. `AdminApiBase.initial()` calls `user.has_perm(route_name)` unless the route appears in `NO_PERMISSION`. |
| Required envelope | `AdminApiBase.basic_validation()` requires `timestamp` and `signature`, and enforces a timestamp window using `API_TIMEOUT_MAX` and `API_TIMEOUT_MIN`. Signature calculation exists, but the comparison is currently commented out in code. |
| Response envelope | Success returns `{ "code": <http code>, "data": {...} }`. Failure returns `{ "code": <http code>, "error": "...", "errors": {...} }`. |
| Localization | `LocaleMiddleware` reads the `locale` header, supports `en`, and writes `settings.CURRENT_LANG`. |

## Endpoint Groups

| Group | Routes |
| --- | --- |
| Auth and account | `login`, `logout`, `register`, `change-password`, `info` |
| Admin and roles | `admin/*`, `role/*`, `permission/list` |
| Organization | `department/*`, `zone/*`, `location/*`, `staff/*`, `suitability/*`, `tag/*` |
| Time and preferences | `academic-term/*`, `week-pattern/*`, `availability/*`, `usage-preference/*`, `start-preference/*`, `time-block/*` |
| Curriculum | `module/*`, `module-group/*`, `pos/*`, `pathway/*`, `student-set/*` |
| Activity | `activity-type/*`, `activity-template/*`, `activity/*`, `jta-create`, `jta-split`, `variant-create` |
| Constraints | `resource-break/*`, `free-block/*`, `maximum-hour/*`, `maximum-workspan/*`, `travel-table/*`, `constraint-profile/*` |
| Scheduling | `schedule-request`, `preschedule-request`, `preschedule-details-request`, `schedule-list`, `simulate-schedule`, `unschedule`, `swap`, `swap/get-resources` |
| Imports and allocation | `import/get-information`, `import/table`, `allocation`, `allocation-rules`, `resources/update-requirement`, `resources/update-current` |

For CRUD-style groups, the common route pattern is `create`, `list`, `rules`, `update`, and `delete`. Some entities add confirmation endpoints or specialized operations, for example `activity-template/allocator`, `pos/update-module`, and `pathway/generate`.

## Domain Rules

### Identity and Permission

- `User` is the custom Django user model, authenticating by unique email.
- Admin users are identified with `User.USER_TYPE["admin"]`.
- Role permissions and user-specific permissions are combined by `CheckPermissionBackend`.
- Token authentication reads an `AccessToken` row and rejects expired tokens.

### Organization and Resources

- Departments and zones are hierarchical and can point to parent records of the same type.
- Staff and locations belong to departments/zones and can carry availability, start preference, and usage preference presets or custom patterns.
- Staff and locations both support suitability, constraint profiles, sharing with departments, avoid-concurrency relationships, and per-week resource maps.

### Calendar and Curriculum

- Academic terms own weeks through `TtAcademicTermWeek`.
- Week patterns group weeks and are referenced by modules, activities, templates, and resource planning flows.
- A POS links to module groups through `TtPosModuleGroup`; each POS module group links to modules through `TtPosModuleGroupModule`.
- Pathways select POS module group module rows for an academic term.
- Student sets belong to a POS and academic term, can be linked to modules, activities, constraint profiles, and resource maps.

### Activity and Scheduling

- `TtActivityTemplate` defines reusable activity defaults, including module, activity type, weeks, staff/location presets, and staff/location suitability.
- `TtActivity` is the schedulable instance. It links to activity template, module, academic term, week pattern/custom weeks, staff, locations, student sets, JTA parent/children, and variant parent/children.
- Scheduling requests pass activity ids, optional slot, and optional `socket_id` to Kafka.
- Scheduler responses update activity scheduling fields, assigned staff/location rows, variant records, and resource maps.
- Redis is used as the scheduler-facing cache for activity, staff, location, student set, and constraint data.

### Constraint Profiles

- `TtConstraintProfile` aggregates resource breaks, free blocks, maximum hour rules, maximum workspan rules, and travel tables.
- `TtTimeBlock` defines reusable start/end slot windows used by break and maximum-limit entities.
- `TtTravelTable` owns journey rows between locations or zones.

### Import and Allocation

- Import accepts `.csv`, `.xlsx`, and `.xls`.
- Import resolves foreign keys by codes, normalizes pattern columns, bulk creates or updates ORM rows, syncs Redis, and forwards microservice update messages when needed.
- Allocation currently supports pathway-based generation. It computes remaining pathway size, creates student sets, connects them to modules and activities, initializes resource maps, updates Redis, and prepares Kafka student-set payloads.

## Integration Requirements

| Integration | Requirement |
| --- | --- |
| PostgreSQL or configured Django database | Stores all ORM tables, including join tables and logs. |
| Redis with RedisJSON support | `bulk_sync_to_redis()` calls `pipe.json().set()`, so RedisJSON commands must be available. |
| Kafka | `backend.kafka.send_request()` uses `confluent_kafka.Producer`; consumers use `confluent_kafka.Consumer`. |
| Scheduler service | Consumes request topics and returns responses with the same `request_id`. |
| Node broadcaster | Runs `node/broadcast.js` on the configured websocket port and exposes HTTP endpoints used by `push_websocket_notification()`. |

## Logging and Error Handling

- `IncomingApiAdmin` records request and response payloads for admin API calls.
- `AuditTrail` and `AuditTrailDetails` record user-facing changes and actions.
- `KafkaLog` records request and response payloads for Kafka integration, correlated by `request_id`.
- `ErrorLog` stores critical exception details from view and helper exception handlers.

## Redis Data Contract

Redis sync payloads use the shape:

```json
{
  "insert": { "table_name": [{ "id": 1, "field": "value" }] },
  "update": { "table_name": [{ "id": 1, "field": "new value" }] },
  "delete": { "table_name": [1, 2, 3] }
}
```

`bulk_sync_to_redis()` writes keys as `<table_name>:<id>`, inserts whole JSON documents at `$`, updates individual fields at `$.field`, and deletes full keys.

## Kafka Message Contract

Outgoing requests receive a generated `request_id`, a `method` header, and a JSON body. Scheduling methods observed in code include:

- `schedule`
- `preschedule`
- `preschedule_details`
- `swap_get_resources`
- `swap`

The response worker expects scheduler responses to contain `request_id`, `status`, and method-specific result fields such as `schedule`.

## Documentation Artifacts

Architecture and UML diagrams are stored in:

- [`Architecture.md`](./Architecture.md)
- [`uml/class-admin-api.md`](./uml/class-admin-api.md)
- [`uml/class-domain-curriculum.md`](./uml/class-domain-curriculum.md)
- [`uml/class-resource-constraints.md`](./uml/class-resource-constraints.md)
- [`uml/class-integration-observability.md`](./uml/class-integration-observability.md)
- [`uml/sequence-authentication.md`](./uml/sequence-authentication.md)
- [`uml/sequence-admin-mutation.md`](./uml/sequence-admin-mutation.md)
- [`uml/sequence-scheduling.md`](./uml/sequence-scheduling.md)
- [`uml/sequence-import-allocation.md`](./uml/sequence-import-allocation.md)

