При автоматизации розничной торговли часто возникает задача программного формирования документов. Одной из самых коварных ошибок при создании документа ЧекККМ (особенно в режиме возврата) является системное сообщение: «перед открытием формы оплаты не удалось записать документ». Эта ошибка блокирует дальнейшую работу кассира и не дает фискализировать операцию. Разберем детально, почему это происходит и как найти «виновника» в коде.
Рассмотрим ситуацию: вы создаете документ ЧекККМ с видом операции «Возврат» программно из другой формы или обработки. Документ успешно создается, заполняется, и программно открывается его форма. Однако, когда пользователь или программный алгоритм пытается инициировать оплату, система выбрасывает исключение.
Важно понимать внутреннюю логику работы фронт-офиса в типовых и нетиповых решениях 1С. Перед тем как вывести окно приема денег или выбора типа оплаты, система обязана зафиксировать данные документа в базе данных. Это делается вызовом метода Записать(). Если в процессе записи (в модуле объекта или в подписках) возникает отказ (Отказ = Истина), форма оплаты не открывается, а пользователь видит стандартное, но малоинформативное сообщение.
Проанализируем процесс поиска ошибки. Если документ не записывается, значит, срабатывает какая-то проверка. Чтобы понять, где именно «падает» код, необходимо настроить отладчик на остановку по ошибке или пройти по шагам следующие процедуры:
ПередЗаписью в модуле документа.ПриЗаписи в модуле документа.ОбработкаПроведения (если запись идет сразу с проведением).Как показывает практика, часто проблема скрывается именно в подписках на события, так как программисты забывают о них, работая только с модулем самого документа. В случаях, когда отладка сложных цепочек событий затруднена, альтернативой прямому программированию в конфигурации выступает платформа для роботизации и автоматического формирования документов.
Выясним причину на конкретном примере. Предположим, в системе существует самописный регистр накопления, например, Гостиница_Начисления, в который должны попадать данные при проведении чеков. Для этого создана подписка на событие ОбработкаПроведения.
Рассмотрим типичный код такой подписки, который может вызвать ошибку:
Процедура ПроведениеВозврата(Источник, Отказ, РежимПроведения) Экспорт
// Проверяем заполнение реквизита
Если ЗначениеЗаполнено(Источник.ФизЛицо) Тогда
Регистр = Источник.Движения.Гостиница_Начисления;
Регистр.Записывать = Истина;
Движение = Регистр.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Источник.Дата;
// Попытка обращения к реквизитам основания
Движение.Организация = Источник.ДокументОснование.Организация;
Движение.Подразделение = Источник.ДокументОснование.Подразделение;
Движение.ФизЛицо = Источник.ФизЛицо;
Движение.Сумма = Источник.СуммаДокумента;
// Проблемные строки
Движение.ДатаЗаселения = Источник.ДатаНачала;
Движение.ДатаВыезда = Источник.ДатаОкончания;
Движение.Документ = Источник.ДокументОснование;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию: если при программном создании чека вы не заполнили реквизиты ДатаНачала или ДатаОкончания, либо если в самом регистре накопления Гостиница_Начисления отсутствуют такие измерения или ресурсы, система выдаст ошибку времени выполнения. Поскольку подписка выполняется в транзакции записи, любая ошибка в ней приведет к отмене записи всего документа.
Рассмотрим важный нюанс. В коде часто встречается проверка вида Если не ПустаяСтрока(Источник.ФизЛицо) Тогда. Это является методологической ошибкой, если ФизЛицо — это ссылка на справочник. Для проверки заполненности любых типов данных в 1С 8.3 следует использовать универсальную функцию ЗначениеЗаполнено().
Разберем, почему это важно: если реквизит имеет ссылочный тип, то ПустаяСтрока() всегда будет возвращать Ложь (или вызывать ошибку приведения типов), и алгоритм попытается выполнить запись движений даже тогда, когда данных нет.
Чтобы избежать ошибок записи «перед оплатой», при программном создании документа ЧекККМ необходимо соблюдать определенную последовательность и полноту данных:
ДокументОснование (ссылка на исходный чек или отчет о розничных продажах).Объект.ВидОперации = Перечисления.ВидыОперацийЧекККМ.Возврат.ЗаполнитьПоОснованию(), если он предусмотрен в конфигурации. Это гарантирует, что все скрытые аналитики (налоги, серии, маркировка) перенесутся корректно.ПриОткрытии могут блокировать запись, если статус не соответствует «Открыт» или «Чек».Если вы столкнулись с невозможностью записи документа перед оплатой, выполните следующие действия:
1. Временно отключите подписки на события. Если без подписок документ проводится и оплачивается успешно — проблема в коде внешней обработки проведения. Проанализируйте, к каким метаданным обращается подписка. Часто ошибка кроется в обращении к реквизитам через точку (например, Источник.ДокументОснование.Организация), когда ДокументОснование не заполнен.
2. Проверьте состав движений. Если ваш документ должен делать движения по регистрам, убедитесь, что все измерения регистра присутствуют в коде и заполняются корректными типами данных. Как выяснилось в практическом примере, попытка присвоить значение несуществующему измерению (например, ДатаЗаселения в регистре, где её нет) — прямая дорога к отказу в записи.
3. Права доступа. Убедитесь, что у пользователя, под которым работает программный код, есть права на запись в те самые «самопальные» регистры, в которые пишет подписка. Ошибка прав доступа при записи движений также вызывает отказ в записи самого документа.
Проанализировав ситуацию и исправив ошибки в логике движений по регистрам, мы добьемся стабильной работы программного создания документов и корректного вызова формы оплаты. Для контроля отсутствия расхождений в учете после подобных доработок программного кода используется программа для автоматической сверки проводок и записей регистров.