В процессе розничной торговли нередко возникает задача аудита действий кассиров: необходимо контролировать отложенные, аннулированные или удаленные чеки ККМ. При типовом закрытии кассовой смены в 1С:Управление торговлей 11 выполняется регламентная процедура архивации чеков. Во время архивации пробитые чеки сворачиваются в документ ОтчетОРозничныхПродажах, а исходные документы ЧекККМ либо помечаются на удаление, либо физически удаляются из информационной базы. Если хранить историю в подчиненном регистратору регистре, при удалении документа-регистратора пропадут и все накопленные данные.
Разберем по шагам, как спроектировать независимый регистр сведений, настроить перехват событий и защитить аналитические отчеты от появления битых ссылок <Объект не найден>.
Проанализируем ключевые причины, по которым для решения данной задачи не подходят стандартные подчиненные регистры или просто документы ЧекККМ:
ЧекККМ являются временными объектами. При их удалении после закрытия смены подчиненные движения очищаются платформой автоматически.ДокументСсылка.ЧекККМ, то после физического удаления документа в отчетах СКД останутся битые ссылки вида <Объект не найден>. По этой причине ключевые данные чека необходимо фиксировать примитивными типами.Создадим новый объект метаданных РегистрСведений с именем ИсторияОтложенныхИУдаленныхЧеков. Зададим режим записи: Независимый, периодичность: Непериодический (точную дату и время операции сохраним в отдельном ресурсе).
Настроим состав полей регистра:
КассаККМ — тип СправочникСсылка.КассыККМ (определяет рабочее место или торговую точку).КассоваяСмена — тип ДокументСсылка.КассоваяСмена (позволяет группировать данные по сменам даже после удаления самих чеков).ИдентификаторЧека — тип Строка (длина 36, сохраняет строковое представление УникальныйИдентификатор документа или сессии).Статус — тип ПеречислениеСсылка.СтатусыЧековККМ или Строка (например: «Отложен», «Аннулирован», «Удален»).СуммаДокумента — тип Число (15, 2, неотрицательное).Кассир — тип СправочникСсылка.Пользователи.ДатаСобытия — тип Дата (состав: Дата и время).НомерЧекаККМ — тип Число или Строка.ПричинаОтмены — тип Строка (длина 150).ДанныеЧека — тип ХранилищеЗначения (используется для сохранения сериализованной таблицы товаров, если в отчете требуется детальный состав).Рассмотрим реализацию механизма сохранения истории при работе с проведенными или сохраненными документами. Для фиксации изменения статуса чека (например, при откладывании) и при его удалении создадим подписки на события.
1. Создадим подписку на событие ЧекККМПриЗаписи для объекта ДокументОбъект.ЧекККМ с источником события ПриЗаписи:
Процедура ЧекККМПриЗаписиПриЗаписи(Источник, Отказ) Экспорт
// Проверяем, перешел ли чек в статус отложенного или помечен на удаление
Если Источник.ПометкаУдаления Или Источник.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Отложенный Тогда
МенеджерЗаписи = РегистрыСведений.ИсторияОтложенныхИУдаленныхЧеков.СоздатьМенеджерЗаписи();
МенеджерЗаписи.КассаККМ = Источник.КассаККМ;
МенеджерЗаписи.КассоваяСмена = Источник.КассоваяСмена;
МенеджерЗаписи.ИдентификаторЧека = Строка(Источник.Ссылка.УникальныйИдентификатор());
МенеджерЗаписи.Прочитать();
МенеджерЗаписи.ДатаСобытия = ТекущаяДатаСеанса();
МенеджерЗаписи.СуммаДокумента = Источник.СуммаДокумента;
МенеджерЗаписи.Кассир = Источник.Ответственный;
МенеджерЗаписи.НомерЧекаККМ = Источник.НомерЧекаККМ;
Если Источник.ПометкаУдаления Тогда
МенеджерЗаписи.Статус = "Удален";
Иначе
МенеджерЗаписи.Статус = "Отложен";
КонецЕсли;
// При необходимости сериализуем товарный состав
ТаблицаТоваров = Источник.Товары.Выгрузить();
МенеджерЗаписи.ДанныеЧека = Новый ХранилищеЗначения(ТаблицаТоваров);
МенеджерЗаписи.Записать(Истина);
КонецЕсли;
КонецПроцедуры
2. Создадим подписку на событие ЧекККМПередУдалением с источником ПередУдалением. Это гарантирует сохранение факта физической очистки базы при закрытии смены:
Процедура ЧекККМПередУдалениемПередУдалением(Источник, Отказ) Экспорт
МенеджерЗаписи = РегистрыСведений.ИсторияОтложенныхИУдаленныхЧеков.СоздатьМенеджерЗаписи();
МенеджерЗаписи.КассаККМ = Источник.КассаККМ;
МенеджерЗаписи.КассоваяСмена = Источник.КассоваяСмена;
МенеджерЗаписи.ИдентификаторЧека = Строка(Источник.Ссылка.УникальныйИдентификатор());
МенеджерЗаписи.Прочитать();
// Если запись уже существовала, обновляем статус, иначе создаем новую
МенеджерЗаписи.ДатаСобытия = ТекущаяДатаСеанса();
МенеджерЗаписи.СуммаДокумента = Источник.СуммаДокумента;
МенеджерЗаписи.Кассир = Источник.Ответственный;
МенеджерЗаписи.Статус = "Физически удален";
МенеджерЗаписи.НомерЧекаККМ = Источник.НомерЧекаККМ;
МенеджерЗаписи.Записать(Истина);
КонецПроцедуры
Если кассир отменяет операцию до сохранения чека в базе, подписки на уровне документа не сработают, так как объект еще не был записан. В этом случае требуется доработать форму РМК (рекомендуется использовать расширение конфигурации):
ОтложитьЧек или АннулироватьЧек).GUID (через Новый УникальныйИдентификатор()), чтобы зафиксировать попытку набора корзины.Для создания отчета для администратора или службы безопасности используем Систему компоновки данных (СКД):
ИсторияОтложенныхИУдаленныхЧеков.КассаККМ, КассоваяСмена, Кассир с выводом детальных записей по времени события и суммам.Такой подход обеспечивает полную сохранность аудиторского следа и предотвращает потерю аналитических данных при регулярной очистке кассовых документов.