Где возникла проблема: 4.19.1.SP1 ULTIMATE RU
Суть проблемы:
При построении отчёта по товарам (использующего таблицы cscart_order_details и cscart_orders) при фильтрации по статусу заказа с кодом T формируется логически противоречивое условие в секции WHERE SQL-запроса:
AND a.status IN ('T')
AND a.status != 'T'
В результате:
- заказы со статусом
Tфизически есть в базе (cscart_orders.status = 'T'); - статус
Tможно назначать заказам, и он корректно отображается в списке заказов; - отчёт всегда возвращает пустой результат по статусу
T, так как условиеIN ('T')и!= 'T'одновременно не может быть истинным ни для одной строки.
При этом в интерфейсе настроек отчёта/модуля нет явных ограничений или исключений для статуса T — он не отмечен как “исключаемый”, но в запрос всё равно попадает a.status != 'T'.
Как воспроизвести проблему:
- Чистая установка CS-Cart 4.19.1.SP1 ULTIMATE RU, без сторонних модулей и тем.
- В админке создать новый статус заказа:
- Тип:
O(заказ); - Код:
T(латинская букваT,CHAR(1)); - Название: любое, например «Выполнен Бери-5».
- Тип:
- Создать тестовый заказ и перевести его в статус
T. Убедиться, что:- в таблице
cscart_ordersесть запись сstatus = 'T'и нужнымorder_id; - в списке заказов в админке этот заказ отображается со статусом
Tи заданным названием.
- в таблице
- Включить режим отладки (DEBUG_MODE) в
config.local.php, очистить кэш. - Открыть стандартный отчёт по продажам по товарам, использующий
cscart_order_detailsиcscart_orders(например, Администрирование → Отчёты → Отчёты по продажам, тип отчёта «Товары»). - В настройках отчёта/фильтра:
- выбрать период, в который попадает тестовый заказ;
- в списке включаемых статусов указать только статус с кодом
T; - при этом не указывать
Tни в каких списках “исключаемых” статусов.
- Построить отчёт.
Фактический результат:
Отчёт не выводит ни одной строки по статусу T, хотя в базе есть заказы с этим статусом.
Если открыть панель отладки и посмотреть SQL-запрос, то он выглядит примерно так (фрагмент):
SELECT b.product_id,
SUM(b.price * b.amount) AS product_amount,
c.product
FROM cscart_order_details AS b
LEFT JOIN cscart_orders AS a ON b.order_id = a.order_id
LEFT JOIN cscart_product_descriptions AS c
ON b.product_id = c.product_id
AND c.lang_code = 'ru'
WHERE a.timestamp >= 1735678800
AND a.timestamp <= 1767214799
AND a.status IN ('T')
AND a.status != 'T'
AND a.is_parent_order != 'Y'
GROUP BY b.product_id
ORDER BY product_amount DESC, product_id
LIMIT 5, 1;
Критичный фрагмент:
AND a.status IN ('T')
AND a.status != 'T'
Он делает выборку по статусу T логически невозможной.
Ожидаемое поведение:
При выборе статуса T (и любых других кастомных статусов) в настройках отчёта в запрос должно попадать только положительное условие по выбранным статусам, например:
AND a.status IN ('T')
или
AND a.status IN ('T', 'P', 'C')
Условие a.status != 'T' не должно добавляться одновременно с a.status IN ('T'), если статус T явно не указан в списке исключаемых статусов в интерфейсе.
Дополнительная информация (окружение):
- CS-Cart 4.19.1.SP1 ULTIMATE RU
- Браузер: Chrome на Windows 10 x64
- PHP: 8.1
При необходимости могу предоставить:
- выборку строк из
cscart_statusesиcscart_ordersс примером заказа со статусомT; - полный SQL-лог или скрин панели отладки с приведённым выше запросом.