Как создать независимый регистр сведений для учета отложенных и удаленных чеков ККМ в 1С:Управление торговлей?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе розничной торговли нередко возникает задача аудита действий кассиров: необходимо контролировать отложенные, аннулированные или удаленные чеки ККМ. При типовом закрытии кассовой смены в 1С:Управление торговлей 11 выполняется регламентная процедура архивации чеков. Во время архивации пробитые чеки сворачиваются в документ ОтчетОРозничныхПродажах, а исходные документы ЧекККМ либо помечаются на удаление, либо физически удаляются из информационной базы. Если хранить историю в подчиненном регистратору регистре, при удалении документа-регистратора пропадут и все накопленные данные.

Разберем по шагам, как спроектировать независимый регистр сведений, настроить перехват событий и защитить аналитические отчеты от появления битых ссылок <Объект не найден>.

Архитектурные особенности: почему регистр должен быть независимым

Проанализируем ключевые причины, по которым для решения данной задачи не подходят стандартные подчиненные регистры или просто документы ЧекККМ:

  1. Регламентная архивация чеков: Документы ЧекККМ являются временными объектами. При их удалении после закрытия смены подчиненные движения очищаются платформой автоматически.
  2. Проблема битых ссылок: Если сделать измерением регистра ссылку на документ ДокументСсылка.ЧекККМ, то после физического удаления документа в отчетах СКД останутся битые ссылки вида <Объект не найден>. По этой причине ключевые данные чека необходимо фиксировать примитивными типами.
  3. Несохраненные чеки в РМК: Чек, который кассир начал набивать и затем аннулировал или очистил в интерфейсе Рабочего места кассира (РМК), может вообще не быть записан в базу как документ. Данные о таком действии требуется фиксировать в момент вызова команды на клиенте или сервере формы РМК.

Проектирование структуры регистра сведений

Создадим новый объект метаданных РегистрСведений с именем ИсторияОтложенныхИУдаленныхЧеков. Зададим режим записи: Независимый, периодичность: Непериодический (точную дату и время операции сохраним в отдельном ресурсе).

Настроим состав полей регистра:

  1. Измерения:
    1. КассаККМ — тип СправочникСсылка.КассыККМ (определяет рабочее место или торговую точку).
    2. КассоваяСмена — тип ДокументСсылка.КассоваяСмена (позволяет группировать данные по сменам даже после удаления самих чеков).
    3. ИдентификаторЧека — тип Строка (длина 36, сохраняет строковое представление УникальныйИдентификатор документа или сессии).
  2. Ресурсы:
    1. Статус — тип ПеречислениеСсылка.СтатусыЧековККМ или Строка (например: «Отложен», «Аннулирован», «Удален»).
    2. СуммаДокумента — тип Число (15, 2, неотрицательное).
    3. Кассир — тип СправочникСсылка.Пользователи.
    4. ДатаСобытия — тип Дата (состав: Дата и время).
  3. Реквизиты:
    1. НомерЧекаККМ — тип Число или Строка.
    2. ПричинаОтмены — тип Строка (длина 150).
    3. ДанныеЧека — тип ХранилищеЗначения (используется для сохранения сериализованной таблицы товаров, если в отчете требуется детальный состав).

Перехват событий через подписки на события

Рассмотрим реализацию механизма сохранения истории при работе с проведенными или сохраненными документами. Для фиксации изменения статуса чека (например, при откладывании) и при его удалении создадим подписки на события.

1. Создадим подписку на событие ЧекККМПриЗаписи для объекта ДокументОбъект.ЧекККМ с источником события ПриЗаписи:


Процедура ЧекККМПриЗаписиПриЗаписи(Источник, Отказ) Экспорт
    
    // Проверяем, перешел ли чек в статус отложенного или помечен на удаление
    Если Источник.ПометкаУдаления Или Источник.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Отложенный Тогда
        
        МенеджерЗаписи = РегистрыСведений.ИсторияОтложенныхИУдаленныхЧеков.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.КассаККМ           = Источник.КассаККМ;
        МенеджерЗаписи.КассоваяСмена       = Источник.КассоваяСмена;
        МенеджерЗаписи.ИдентификаторЧека   = Строка(Источник.Ссылка.УникальныйИдентификатор());
        
        МенеджерЗаписи.Прочитать();
        
        МенеджерЗаписи.ДатаСобытия         = ТекущаяДатаСеанса();
        МенеджерЗаписи.СуммаДокумента      = Источник.СуммаДокумента;
        МенеджерЗаписи.Кассир              = Источник.Ответственный;
        МенеджерЗаписи.НомерЧекаККМ        = Источник.НомерЧекаККМ;
        
        Если Источник.ПометкаУдаления Тогда
            МенеджерЗаписи.Статус = "Удален";
        Иначе
            МенеджерЗаписи.Статус = "Отложен";
        КонецЕсли;
        
        // При необходимости сериализуем товарный состав
        ТаблицаТоваров = Источник.Товары.Выгрузить();
        МенеджерЗаписи.ДанныеЧека = Новый ХранилищеЗначения(ТаблицаТоваров);
        
        МенеджерЗаписи.Записать(Истина);
        
    КонецЕсли;

КонецПроцедуры

2. Создадим подписку на событие ЧекККМПередУдалением с источником ПередУдалением. Это гарантирует сохранение факта физической очистки базы при закрытии смены:


Процедура ЧекККМПередУдалениемПередУдалением(Источник, Отказ) Экспорт
    
    МенеджерЗаписи = РегистрыСведений.ИсторияОтложенныхИУдаленныхЧеков.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.КассаККМ         = Источник.КассаККМ;
    МенеджерЗаписи.КассоваяСмена     = Источник.КассоваяСмена;
    МенеджерЗаписи.ИдентификаторЧека = Строка(Источник.Ссылка.УникальныйИдентификатор());
    
    МенеджерЗаписи.Прочитать();
    
    // Если запись уже существовала, обновляем статус, иначе создаем новую
    МенеджерЗаписи.ДатаСобытия       = ТекущаяДатаСеанса();
    МенеджерЗаписи.СуммаДокумента    = Источник.СуммаДокумента;
    МенеджерЗаписи.Кассир            = Источник.Ответственный;
    МенеджерЗаписи.Статус            = "Физически удален";
    МенеджерЗаписи.НомерЧекаККМ      = Источник.НомерЧекаККМ;
    
    МенеджерЗаписи.Записать(Истина);

КонецПроцедуры

Перехват действий кассира в интерфейсе РМК

Если кассир отменяет операцию до сохранения чека в базе, подписки на уровне документа не сработают, так как объект еще не был записан. В этом случае требуется доработать форму РМК (рекомендуется использовать расширение конфигурации):

  1. В модуле формы РМК найдем обработчик команды откладывания или аннулирования чека (например, ОтложитьЧек или АннулироватьЧек).
  2. Добавим вызов серверной процедуры с передачей текущих данных формы: кассы, смены, суммы корзины и текущего пользователя.
  3. Запишем набор данных в независимый регистр с генерацией нового строкового GUID (через Новый УникальныйИдентификатор()), чтобы зафиксировать попытку набора корзины.

Построение отчета на СКД

Для создания отчета для администратора или службы безопасности используем Систему компоновки данных (СКД):

  1. В схеме компоновки данных в качестве источника выберем созданный регистр сведений ИсторияОтложенныхИУдаленныхЧеков.
  2. Поскольку все измерения и реквизиты хранятся в виде прямых ссылок на кассы, смены и пользователей либо в виде примитивных типов (строка, дата, число), отчет не будет зависеть от процедуры закрытия смены и покажет полную историю операций.
  3. Настроим группировки по полям КассаККМ, КассоваяСмена, Кассир с выводом детальных записей по времени события и суммам.

Такой подход обеспечивает полную сохранность аудиторского следа и предотвращает потерю аналитических данных при регулярной очистке кассовых документов.

← На главную