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