Сегодня столкнулся с ошибкой, присутствовавшей в SuiteCRM 7.3.2 (а возможно и в более ранних и более поздних модификациях этой CRM): Если создать новый отчет в модуле Отчеты (AOR_Reports), и одним из параметров фильтрации указать поле типа Datetime, то при построении отчета записи по этому полю не ищутся.
У меня это проявилось, когда я хотел найти все Задачи, созданные за определенный день (по календарику). Вот как выглядел отчет:
Таким образом у нас отчет будет состоять из трех колонок: ID записи, Название и Дата создания записи.
А фильтровать данные мы по идее должны по Дате создания записей:
Но если заполнить поле в колонке "Значение" и нажать на кнопку "Обновить", то ничего не происходит. Записи не ищутся, хотя я точно знаю, что они есть на указанную дату.
В результате разбора модуля AOR_Reports было выявлено, что непосредственно генерацией WHERE-условия для выборки по отчету занимается функция build_report_query_where, находящаяся в классе AOR_Report в файле modules/AOR_Reports/AOR_Report.php
Результатом работы функции build_report_query_where являлся массив:
Array
(
[select] => Array
(
[0] => `project_task`.id AS 'project_task_id'
[1] => `project_task`.id AS 'ID0'
[2] => `project_task`.name AS 'Название1'
[3] => `project_task`.date_entered AS 'Дата_создания2'
)
[where] => Array
(
[0] => `project_task`.date_entered = '23.12.2015'
[1] => project_task.deleted = 0
который потом уже далее собирался в конечный SQL-запрос:
SELECT `project_task`.id AS 'project_task_id', `project_task`.id AS 'ID0', `project_task`.name AS 'Название1', `project_task`.date_entered AS 'Дата_создания2' FROM `project_task` WHERE `project_task`.date_entered = '23.12.2015' AND project_task.deleted = 0
Как мы видим, `project_task`.date_entered = '23.12.2015' - абсолютно не то, что нам надо, чтобы корректно найти данные. Мало того, что формат даты указан не верный, так еще подвешенным остается что делать с временем. Ведь date_entered (дата создания) у нас в базе имеет значения что то типа такого: 2015-12-23 12:34:02, что никак не идентично 23.12.2015, хотя по логике это должно быть наше значение.
В общем нам надо преобразовать наш запрос таким образом, чтобы занчения в базе уравнялись в формате с вводимыми значениями.
Я решил, что самым оптимальным будет введенное значение оставить как есть, а модернизации подвергнуть указание поля в базе данных: у нас должен на выходе получиться вот такой запрос:
SELECT `project_task`.id AS 'project_task_id', `project_task`.id AS 'ID0', `project_task`.name AS 'Название1', `project_task`.date_entered AS 'Дата_создания2' FROM `project_task` WHERE DATE_FORMAT(`project_task`.date_entered, '%d.%m.%Y') = '23.12.2015' AND project_task.deleted = 0
Таким образом прибегнув к функции DATE_FORMAT мы сможем сделать эти значения идентичными по своему формату, что позволит их начать сравнивать.
Реализация:
Во первых в функцию build_report_query_where в самый верх добавляем строку с подключением глобальной переменной $timedate, из которой мы в последствии сможем извлечь текущие настройки формата даты для текущего пользователя:
/** * @param array $query * @return array */ function build_report_query_where($query = array()){ global $beanList, $app_list_strings, $sugar_config; global $timedate;
а чуть дальше в этой же функции ищем строчки:
if ((isset($data['source']) && $data['source'] == 'custom_fields')) { $field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $condition->field; $query = $this->build_report_query_join($table_alias . '_cstm', $table_alias . '_cstm', $oldAlias, $condition_module, 'custom', $query); } else { $field = $this->db->quoteIdentifier($table_alias) . '.' . $condition->field;
$condition->value = date($timedate->get_date_format(), strtotime("+{$timedate->getUserUTCOffset()} minutes", strtotime($condition->value)));
}
Здесь переменная $field - это название нашего поля в базе данных (`project_task`.date_entered). Нам надо указать его не как просто `project_task`.date_entered, а как DATE_FORMAT(`project_task`.date_entered, '%d.%m.%Y')
Для этого модернизируем этот участок кода следующим образом:
if ((isset($data['source']) && $data['source'] == 'custom_fields')) { $field = $this->db->quoteIdentifier($table_alias . '_cstm') . '.' . $condition->field; $query = $this->build_report_query_join($table_alias . '_cstm', $table_alias . '_cstm', $oldAlias, $condition_module, 'custom', $query); } elseif($condition_module->field_defs[$condition->field]['type'] == 'datetime') { // Для случая, когда поле с типом Datetime $field = "DATE_FORMAT(". $this->db->quoteIdentifier($table_alias) . '.' . $condition->field.", '" . $timedate->get_cal_date_format() . "')"; } else { // Все остальные стандартные случаи $field = $this->db->quoteIdentifier($table_alias) . '.' . $condition->field; }
Теперь у нас для всех полей с типом Datetime будет происходить корректное применение фильтров в Отчетах. Ну а в нашем случае получился запрос:
SELECT `project_task`.id AS 'project_task_id', `project_task`.id AS 'ID0', `project_task`.name AS 'Название1', `project_task`.date_entered AS 'Дата_создания2' FROM `project_task` WHERE DATE_FORMAT(`project_task`.date_entered, '%d.%m.%Y') = '23.12.2015' AND project_task.deleted = 0
И вот его результат работы:
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new account
Sign in
Already have an account? Sign in here.
Sign In Now