# Fleet BLE Monitor Backend

Backend starter для системы Fleet BLE Monitor.

Стек:

- Kotlin
- Spring Boot
- Spring GraphQL
- Spring Data JPA
- PostgreSQL
- Docker Compose для локальной базы

## Быстрый локальный запуск

Из папки `backend`:

```powershell
cd docker
docker compose up -d
cd ..
.\gradlew.bat clean bootRun
```

После запуска приложение доступно по адресу:

```text
http://localhost:8080/api
```

GraphiQL:

```text
http://localhost:8080/api/graphiql
```

GraphQL endpoint:

```text
http://localhost:8080/api/graphql
```

## Локальная PostgreSQL

Docker Compose поднимает контейнер:

```text
fleet-ble-monitor-postgres
```

Внутри контейнера PostgreSQL слушает порт `5432`, но на хост проброшен порт `55432`.

Это сделано специально, чтобы локальный запуск не конфликтовал с установленным на машине PostgreSQL, который часто уже занимает `localhost:5432`.

Параметры подключения по умолчанию:

```text
DB_HOST=localhost:55432
DB_NAME=fleet_ble_monitor
DB_USER=fleet_user
DB_PASSWORD=fleet_password
SERVER_PORT=8080
SEED_ENABLED=true
```

Эти же значения указаны в `.env.example`.

Spring использует переменные:

- `DB_HOST`
- `DB_NAME`
- `DB_USER`
- `DB_PASSWORD`

Если переменные не заданы, используются дефолты из `src/main/resources/application.yml`.

## Полный сброс локальной базы

Если контейнер уже создавался раньше с другими `POSTGRES_USER` / `POSTGRES_PASSWORD`, PostgreSQL сохранит старые учетные данные в Docker volume. В таком случае изменение `docker-compose.yml` уже не поменяет пароль существующей базы.

Для полного сброса локальной базы:

```powershell
cd docker
docker compose down -v
docker compose up -d
cd ..
.\gradlew.bat clean bootRun
```

Команда `docker compose down -v` удаляет локальный volume PostgreSQL. Все локальные данные будут потеряны.

## Тестовые пользователи

Seed-данные создаются при первом запуске, если база пустая и `SEED_ENABLED=true`.

```text
admin / 123456
admin@fleet.local / 123456

user / 123456
user@fleet.local / 123456
```

## Пример login mutation

```graphql
mutation {
  login(payload: { loginOrEmail: "admin", password: "123456" }) {
    token
    user {
      id
      login
      email
      role
    }
  }
}
```

Для запросов, требующих авторизации, передавай токен в HTTP header:

```text
Authorization: Bearer <token>
```

## Пример списка АТТ

```graphql
query {
  getMachines(
    page: 0
    pageSize: 20
    sortDirection: ASC
    sortField: NAME
  ) {
    totalElements
    page {
      id
      name
      licensePlate
      lastKnownState
      beacon {
        identifier
        macAddress
        status
      }
    }
  }
}
```

## Что доделывать дальше

- нормальную авторизацию через JWT/AD/LDAP;
- миграции Flyway/Liquibase вместо `ddl-auto: update`;
- полноценный алгоритм распознавания состояний из телеметрии;
- генерацию XLSX/PDF на backend;
- scheduler рассылки отчетов;
- права доступа на уровне GraphQL resolver/use-case.

