24.03.2022
Бывает, что пользователи задают вопрос, можно ли в программе посмотреть, кто и что делал с каким-нибудь товаром. В последнем релизе Купца появился, наконец, такой отчет, работу которого опишу.
Вначале немного теории. Документы в базе данных могут относиться к закрытому или открытому периоду. Закрытие периода происходит путем создания документа "Остатки" последним его днем. В закрытом периоде документы редактировать программа запрещает, в открытом регламентирует правами доступа. Например, для отдельных ролей пользователей можно задать количество последних дней, доступных для редактирования, или запретить редактировать чужие документы, запретить физически удалять документы из базы данных и т.п. То есть, чисто технически, определенные пользователи в открытом периоде могут свободно изменять документы. Поэтому отследить все операции, относящиеся к определенному товару, задача не совсем простая и требует анализа транзакционного лога.
Транзакционный лог в Купце оптимизирован на минимальное количество информации, так как растет быстрее основной базы данных. Для каждой операции сохраняются стандартные реквизиты дата, время, вид операции (добавить/изменить/удалить), пользователь, идентификатор таблицы базы данных, идентификатор записи, идентификатор заглавной записи (обычно для строк документов с многострочной частью) и список установленных полей в виде форматированной строки переменной длины. Если запись добавляется, то сохраняются только значения полей, которые были установлены, если изменяется, то новые значения полей, которые были изменены, если удаляется, то только идентификаторы таблицы и записи.
Построение отчета по операциям с товаром выполняется в 2 фазы. Вначале просматриваем все записи лога по строкам товарных документов. Если операция Добавить, то проверяем наличие установленного поля товара и значения, равного нашему товару. Если находим, то включаем в отчет. Аналогичная проверка выполняется и для операции Изменить. Но она дает только те операции, которые изменяли предыдущее значение товара на наш, а может быть и обратная ситуация. Поэтому, если наш товар не найден, проверяем, было ли установлено поле товара с другим значением. Если да, то смотрим предыдущие записи в логе по этой строке и определяем ближайшую операцию с установкой товара. Если находим и это наш товар, то включаем в отчет. Операция Удалить имеет подобный алгоритм, мы ищем ближайшую предшествующую операцию в логе, в которой было установлено поле товара, если это был наш товар, то включаем в отчет.
На втором этапе проверяем операции с заголовками товарных документов. Всегда проверяется операция удаления, так как документ мог быть полностью удален из базы данных. Если в параметрах отчета задан признак отслеживания изменения статуса товарных документов (см. первый скриншот), то проверяются также операции изменения, в которых присутствует поле статуса. Составляем список таких операций, затем проходим по нему и вызываем функцию получения строк документов на момент ее совершения. Это функция из бизнес логики, которая на основании лога формирует в таблице в оперативной памяти копии строк товарных документов, как они были на заданный момент времени. Пробегаемся по этой таблице и ищем, был ли там наш товар. Если был, то включаем операцию в отчет.
Как видно, алгоритм ресурсоемкий. Поэтому сейчас анализ ограничен периодом в 10 дней. Как правило, этого достаточно. Если нужно больше, то можно построить такой же отчет за другой период. На первом скриншоте параметры отчета, на втором результат построения. В результирующей таблицы можно использовать стандартный функционал поиска, фильтрации по колонкам, печати, экспорта в электронную таблицу. Если щелкнуть по строке отчета, то откроется связанный документ, и можно его проанализировать в разных аспектах. Если, конечно, этот документ не был совсем удален из базы данных.