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