При автоматизации розничной торговли часто возникает задача очистки базы данных от большого объема первичных кассовых документов (чеков ККМ) за день, чтобы не перегружать систему и не хранить избыточную детализацию на кассовом узле. При этом ключевым требованием является сохранение актуальных складских остатков: товары, проданные покупателям, должны оставаться корректно списанными со склада.
Разберем, как устроена работа с кассовыми документами в типовой конфигурации 1С:Розница, почему простое физическое удаление чеков ломает учет, и как правильно реализовать архивацию или очистку кассовых смен.
Проанализируем базовую архитектуру учета розничных продаж. В конфигурациях линейки «Розница» и «Управление торговлей» изначально заложен двухэтапный механизм отражения продаж:
ЧекККМ. Документ делает оперативные движения по регистрам накопления (списывает остатки номенклатуры и накапливает сумму выручки).ОтчетОРозничныхПродажах (ОРП).ОтчетОРозничныхПродажах успешно проведен и принял на себя все движения по списанию остатков и выручке, исходные документы ЧекККМ переводятся в статус Архивный (при этом их собственные движения по регистрам очищаются) либо автоматически удаляются из информационной базы, если это задано настройками учетной политики.Таким образом, в типовой системе остатки не возвращаются обратно на склад: за списание товаров теперь отвечает сводный отчет о продажах, а чеки больше не влияют на регистры и служат лишь справочной информацией.
Если попытаться принудительно удалить чеки программным методом ДокументОбъект.Удалить() в обход штатной процедуры формирования сводного отчета, система столкнется со следующими критическими проблемами:
ПланыОбмена.ЗарегистрироватьИзменения приводит к фатальным ошибкам при обмене данными между магазином и центральным офисом.Рассмотрим пример кода для регламентного или автоматического закрытия кассовой смены, сбора данных и последующей очистки оперативных документов:
// Пример регламентной процедуры закрытия смен по кассе ККМ
ПараметрыСмены = Новый Структура;
ПараметрыСмены.Вставить("КассаККМ", ТекущаяКасса);
// Формируем и проводим сводный документ "Отчет о розничных продажах"
ДокументОРП = Документы.ОтчетОРозничныхПродажах.СоздатьДокумент();
ДокументОРП.Дата = ТекущаяДата();
ДокументОРП.КассаККМ = ТекущаяКасса;
ДокументОРП.ЗаполнитьПоЧекамСмены(ТекущаяКасса);
Попытка
ДокументОРП.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписьЖурналаРегистрации("ЗакрытиеСмены", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат;
КонецПопытки;
// После успешного проведения ОРП архивируем или удаляем чеки текущей смены
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Чек.Ссылка КАК Ссылка
|ИЗ
| Документ.ЧекККМ КАК Чек
|ГДЕ
| Чек.КассаККМ = &КассаККМ
| И Чек.СтатусЧекаККМ = ЗНАЧЕНИЕ(Перечисление.СтатусыЧековККМ.Пробитый)";
Запрос.УстановитьПараметр("КассаККМ", ТекущаяКасса);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ЧекОбъект = Выборка.Ссылка.ПолучитьОбъект();
// Очищаем движения чека, так как они перешли в ОРП
ЧекОбъект.Движения.Очистить();
ЧекОбъект.СтатусЧекаККМ = Перечисления.СтатусыЧековККМ.Архивный;
ЧекОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;
Если потребность в скрытии чеков вызвана соображениями конфиденциальности данных на рабочих местах кассиров, удаление документов из базы — некорректный и опасный путь. Проанализируем правильные инженерные решения для этой задачи: