При работе в системе 1С:Предприятие 7.7 пользователи и разработчики часто сталкиваются с ситуацией, когда при попытке интерактивного изменения даты в уже проведенном документе платформа выдает блокирующее сообщение: «изменена дата проведенного документа». Это не просто информационное уведомление, а защитный механизм платформы, который не дает записать изменения. В этой статье мы подробно разберем, почему это происходит, и рассмотрим все доступные способы решения этой задачи — от простых пользовательских приемов до глубокого программного вмешательства.
Для начала проанализируем внутреннюю логику работы 1С 7.7. В этой версии платформы время и дата документа жестко связаны с его позицией на временной оси (Sequence). Проведение документа порождает записи в регистрах или бухгалтерские проводки, которые актуальны именно на тот момент времени, в который документ был проведен. Если мы просто поменяем дату без перепроведения, возникнет логический разрыв: документ «числится» в одной дате, а его движения в регистрах «остались» в другой.
Платформа 1С 7.7 защищает целостность данных, запрещая менять дату проведенного объекта через форму. Стандартный алгоритм действий подразумевает, что вы сначала должны снять документ с проведения, затем изменить дату и провести его снова. Однако при больших объемах работы это крайне неудобно, поэтому мы рассмотрим способы автоматизации этого процесса.
Если нам необходимо, чтобы пользователь мог менять дату прямо в форме, и система не «ругалась», мы можем перехватить стандартное поведение в модуле формы. Разберем, как это реализовать. Основная идея заключается в том, чтобы при сохранении документа программно проверить, была ли изменена дата, и если да — временно снять его с проведения.
Рассмотрим пример кода, который можно разместить в процедуре ПриЗаписи() модуля формы документа:
Процедура ПриЗаписи()
// Проверяем, проведен ли документ
Если Выбран() = 1 Тогда
Если Проведен() = 1 Тогда
// Проверяем, изменилась ли дата по сравнению с записанной в базе
// ТекущийДокумент() вернет состояние объекта до записи
Если ДатаДок <> ТекущийДокумент().ДатаДок Тогда
Ответ = Вопрос("Дата документа изменена. Перепровести документ?", "Да+Нет");
Если Ответ = "Да" Тогда
// Снимаем с проведения без удаления движений,
// чтобы платформа позволила изменить дату
СделатьНепроведенным();
Иначе
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В этом примере мы используем метод СделатьНепроведенным(). После того как выполнение процедуры завершится, платформа позволит сохранить новую дату, так как документ технически уже не будет проведен. Однако не забудьте, что после этого пользователю нужно будет нажать кнопку «Провести» или реализовать автоматический вызов Провести() после записи.
Часто задача изменения даты стоит не для одного документа, а для группы. В этом случае ограничение интерактивного интерфейса (формы) вообще не действует. Если менять дату через программный объект Документ во внешней обработке, сообщение «изменена дата...» не выводится.
Разберем по шагам алгоритм действия такой обработки:
Документ.НайтиДокумент() или перебором выборки.СделатьНепроведенным() (это критически важно для корректности итогов).УстановитьДатуВремени() или простым присваиванием ДатаДок = НоваяДата.Провести().Посмотрим на пример кода для массового изменения даты:
Док = СоздатьОбъект("Документ.Реализация");
Док.ВыбратьДокументы(ДатаНач, ДатаКон);
Пока Док.ПолучитьДокумент() = 1 Цикл
Если Док.Проведен() = 1 Тогда
// Программное изменение даты
Док.СделатьНепроведенным();
Док.ДатаДок = НужнаяДата;
Док.Записать();
Док.Провести();
КонецЕсли;
КонецЦикла;
Важный нюанс: при программном изменении даты документа, платформа автоматически переместит его в конец дня (или по правилам сортировки времени), но не выдаст предупреждений, характерных для формы.
Для продвинутых разработчиков существует способ «обхода системных блокировок», который упоминался в профессиональных сообществах (например, на ресурсе Sinor). Использование компоненты FormEx позволяет расширить возможности встроенного языка.
С помощью FormEx можно перехватить события нажатия кнопок или программно имитировать действия пользователя. Это позволяет «обмануть» форму, заставив ее думать, что документ не проведен в момент смены даты, либо просто подавить вывод системных сообщений. Однако данный метод требует регистрации DLL в системе и определенных навыков работы с низкоуровневым API 1С.
Выясним причину, почему иногда программисты прибегают к редактированию таблиц напрямую. Это самый быстрый, но и самый опасный метод. В 1С 7.7 данные о датах документов хранятся в общем журнале документов.
1SJOURN.DBF._1SJOURN.Поле DATE_TIME_IDDOC содержит упакованную информацию о дате и времени. Изменение этого поля напрямую позволит мгновенно «перебросить» документ на другую дату без открытия формы и без выполнения кода 1С. Внимание: это крайне не рекомендуется делать без последующего пересчета бухгалтерских итогов и восстановления последовательности, так как движения документа останутся на старых периодах в регистрах, что приведет к неверным отчетам!
Проанализируем ситуацию с точки зрения удобства пользователя. Вместо того чтобы заставлять бухгалтера открывать документ, снимать его с проведения и снова открывать, можно добавить в журнал документов кнопку «Изменить дату».
Алгоритм работы кнопки:
ВвестиДату().ТекущийДокумент().СделатьНепроведенным() -> ДатаДок = ... -> Записать() -> Провести().Это самый «чистый» способ с точки зрения методологии 1С, так как он соблюдает все правила бизнес-логики и при этом экономит время пользователя.
Мы рассмотрели различные варианты решения проблемы сообщения «изменена дата проведенного документа». Подведем итог:
СделатьНепроведенным(), чтобы не нарушать целостность регистров.Главное помнить: изменение даты документа в 1С 7.7 — это операция, влияющая на точку актуальности и последовательность проведения. Всегда проверяйте остатки после массового переноса документов в прошлые или будущие периоды.