# Axioma

A PHP-based management system for an education center — handles students, teachers, groups, schedules, tariffs/payments, and role-based dashboards for admins, advisers, teachers, and parents.

## Tech stack

- Laravel (PHP 8.4)
- MySQL 8.0
- Redis (session storage)
- Docker / docker-compose for local development
- Composer-managed (`laravel/composer.json`)

## Project structure

```
laravel/         The application — Laravel app/Http/Controllers, Eloquent
                 models, Blade views under resources/views, routes in
                 routes/web.php (see CLAUDE.md's "Request flow" section)
docker/          MySQL init scripts for local dev
scripts/         One-off SQL migration files, applied manually (see CLAUDE.md's
                 "Database" section)
css/, js/, images/
                 Shared static assets, served directly by Apache
```

## Local development setup

1. Copy the environment template and fill in real values:
   ```bash
   cp .env.example .env
   ```
2. Start the app, database, and Redis (the `bot` service builds from a separate
   `teacher_reminder_bot` checkout and isn't needed for local app development
   — see [docker-compose.yml](docker-compose.yml)):
   ```bash
   docker compose up -d app db redis
   ```
3. The app will be available at `http://localhost:8080`.

`DB_PASS` and `MYSQL_ROOT_PASSWORD` must be set in your `.env` file — there are no default passwords baked into the app or Docker setup. Leave `SESSION_COOKIE_DOMAIN` blank for local dev (see `.env.example`) — the production value (`.axioma-study.kz`) doesn't match `localhost` and would silently break session persistence.

On first start, `docker/mysql/init/*.sql` runs automatically against the empty `db` volume: it builds the schema and seeds one login per role (`admin@axioma-study.kz`, `teacher@axioma-study.kz`, `adviser@axioma-study.kz`, `manager@axioma-study.kz`, `parent@axioma-study.kz`, `student.testov@students.axioma-study.kz` — all `password123`) plus a group/lesson/payment so each dashboard has something to show. See [docker/mysql/init/README.md](docker/mysql/init/README.md). To re-seed from scratch: `docker compose down -v` (drops the volume), then `docker compose up -d db redis app` again.

## Roles

`AuthController::ROLE_DASHBOARDS` (`laravel/app/Http/Controllers/AuthController.php`) is the
source of truth for which roles exist and where each one lands after login: `admin`, `teacher`,
`adviser`, `manager`, `parent`, `student`.

| Role      | Entry point                                            |
|-----------|---------------------------------------------------------|
| admin     | `/admin/dashboard.php`                                   |
| adviser   | `/adviser/adviser_dashboard.php`                         |
| parent    | `/parent/parent_dashboard.php`                           |
| teacher   | `/`                                                      |
| student   | external — `https://game.axioma-study.kz/student/hero_account.php` (gamification portal, separate subdomain) |
| manager   | *no working entry point* — redirects to `/sales/sales_dashboard.php`, which doesn't exist as a route; likely vestigial |

The seed data (`docker/mysql/init/999_seed.sql`) creates logins for all six roles above. A
seventh role, `subadmin`, existed only in dead config (never read anywhere, no seeded user, not
a selectable option in the real user-creation form) and was removed entirely.

## Security notes

- All database queries are parameterized (Eloquent / query builder).
- Passwords are hashed with `password_hash()` / verified with `password_verify()` (via Laravel's `Hash` facade).
- CSRF protection is Laravel's own `VerifyCsrfToken` middleware, enforced on all state-changing routes registered with the `web` middleware group.
- Session IDs are regenerated on login; remember-me tokens are high-entropy random values stored server-side, never derived from anything guessable.

## License

See [LICENSE](LICENSE).
