BUG-015: 500 при загрузке списка заказов

Описание

При открытии страницы “Активные заказы” (/admin/orders/active) бэкенд возвращает 500 Internal Server Error. Список заказов не грузится — страница пустая. Блокер для всей функциональности заказов в админке (затрагивает ActiveOrdersPage и OrderHistoryPage).

Шаги воспроизведения

  1. Залогиниться в админку под франшизой
  2. Перейти в раздел Заказы → Активные
  3. Выбрать любую торговую точку из дропдауна

Ожидаемое поведение

Загружается список активных заказов (статусы new, in_progress, ready) или пустое состояние “Нет активных заказов” — HTTP 200.

Фактическое поведение

  • Запрос: GET /api/v1/admin/orders?store_id={uuid}&status=ready&per_page=100
  • Статус: 500 Internal Server Error
  • Тело ответа:
    {
      "error": {
        "code": "INTERNAL_ERROR",
        "message": "Internal server error"
      }
    }

Корневая причина (из логов erp-order-service)

org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $6

Exception бросается в OrderRepository.findFiltered():

@Query("SELECT o FROM Order o WHERE o.franchiseId = :franchiseId" +
        " AND (:storeIds IS NULL OR o.storeId IN :storeIds)" +
        " AND (:status IS NULL OR o.status = :status)" +
        " AND (:dateFrom IS NULL OR o.createdAt >= :dateFrom)" +
        " AND (:dateTo IS NULL OR o.createdAt <= :dateTo)")

PostgreSQL JDBC не может вывести тип для nullable параметров в конструкции :param IS NULL OR ..., так как оба плеча OR не содержат явного type-hint. Классическая проблема Hibernate + PostgreSQL: при dateFrom/dateTo = null driver не знает какого типа параметр.

Затронутые сервисы

  • erp-order-service — баг в OrderRepository.findFiltered() (исправить JPQL-запрос)
  • erp-admin (web) — косвенно: ActiveOrdersPage и OrderHistoryPage не могут отобразить данные

Варианты исправления

  1. Dynamic query через Specification (предпочтительно) — собирать WHERE-условия только для non-null параметров, проблема нулевых типов исчезает сама.
  2. CAST(:param AS ...) — добавить явное приведение типа в JPQL: (CAST(:dateFrom AS timestamp) IS NULL OR o.createdAt >= :dateFrom). Работает, но уродливо.
  3. Несколько методов репозитория — отдельный метод на каждую комбинацию фильтров. Плохо масштабируется.

Рекомендация: Spring Data JPA Specification<Order> + JpaSpecificationExecutor<Order>.