Как программно создавать и заполнять документ «Начисление арендной платы» на основании действующих договоров в 1С?

Программист 1С v8.3 (Обычные формы) Управленческий учет Сфера услуг, туризм и социальный сектор
← На главную

Автоматизация регулярных операций — одна из ключевых задач программиста 1С. Типичный пример такой задачи: каждый месяц необходимо начислять арендную плату по множеству договоров. Чтобы не делать это вручную, мы можем реализовать алгоритм, который сам найдет актуальные договоры, проверит, было ли уже начисление, и при необходимости создаст новый документ, заполнив его всеми необходимыми данными. Рассмотрим подробно, как это реализовать.

Постановка задачи и логика работы алгоритма

Для решения задачи нам потребуется обработать три типа объектов: документ Договор аренды помещения, документ Начисление арендной платы и, опционально, регистры для контроля взаиморасчетов. Логика работы программного кода будет следующей:

  1. Получение списка действующих договоров: Нам нужно выбрать те договоры, срок действия которых еще не истек и которые проведены в системе.
  2. Проверка существующих начислений: Программа не должна создавать дубли. Если за текущий месяц начисление по конкретному договору уже проведено, мы должны исключить его из обработки.
  3. Создание документа: Если найдены договоры, по которым начисления еще нет, создаем новый объект ДокументОбъект.НачислениеАренднойПлаты.
  4. Заполнение табличной части: В цикле обходим найденные договоры и добавляем строки в табличную часть (ТЧ) документа.
  5. Проведение: Записываем и проводим готовый документ.

Шаг 1: Получение действующих договоров через запрос

Использование запросов — самый эффективный способ получения данных в 1С. Мы выберем все договоры, у которых дата окончания больше текущей даты, и которые не помечены на удаление. Проанализируем пример кода для получения этой выборки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ДоговорАренды.Ссылка КАК Ссылка,
    |	ДоговорАренды.Арендодатель КАК Арендодатель,
    |	ДоговорАренды.СуммаАренднойПлаты КАК Сумма
    |ИЗ
    |	Документ.ДоговорАрендыПомещения КАК ДоговорАренды
    |ГДЕ
    |	ДоговорАренды.ДатаОкончания > &ТекущаяДата
    |	И ДоговорАренды.Проведен = ИСТИНА
    |	И ДоговорАренды.ПометкаУдаления = ЛОЖЬ";

Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());
РезультатЗапроса = Запрос.Выполнить();
ТаблицаДоговоров = РезультатЗапроса.Выгрузить();

В данном запросе мы получаем ссылку на договор, контрагента (арендодателя) и сумму, указанную в договоре. Метод Выгрузить() позволяет нам получить Таблицу Значений, с которой удобно работать в дальнейшем.

Шаг 2: Решение проблемы «новых договоров» и исключение дублей

Часто возникает ситуация: документ начисления за месяц уже создан, но в середине месяца подписали еще один договор. Обычная проверка «существует ли документ за месяц» тут не сработает. Рассмотрим более надежный способ через Левое Соединение в запросе. Мы соединим таблицу действующих договоров с уже созданными строками начислений за этот месяц. Если связи нет (ЕСТЬ NULL), значит, начисление еще не выполнялось.


Запрос.Текст = 
    "ВЫБРАТЬ
    |	Договоры.Ссылка КАК Договор,
    |	Договоры.Арендодатель КАК Арендодатель,
    |	Договоры.СуммаАренднойПлаты КАК Сумма
    |ИЗ
    |	Документ.ДоговорАрендыПомещения КАК Договоры
    |		ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеАренднойПлаты.ТЧНачисления КАК Начисления
    |		ПО Договоры.Ссылка = Начисления.ДоговорАренды
    |			И Начисления.Ссылка.Дата МЕЖДУ &НачалоМесяца И &КонецМесяца
    |			И Начисления.Ссылка.Проведен = ИСТИНА
    |ГДЕ
    |	Договоры.ДатаОкончания > &ТекущаяДата
    |	И Договоры.Проведен = ИСТИНА
    |	И Начисления.ДоговорАренды ЕСТЬ NULL";

Запрос.УстановитьПараметр("НачалоМесяца", НачалоМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("КонецМесяца", КонецМесяца(ТекущаяДата()));
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());

Этот подход позволяет системе видеть только те договоры, по которым в текущем периоде еще не было движений. Это исключает дублирование и позволяет «дозаполнять» начисления в любое время.

Шаг 3: Программное создание документа и заполнение ТЧ

Теперь, когда у нас есть список договоров, требующих начисления, перейдем к созданию объекта документа. Для этого используется метод СоздатьДокумент() менеджера документа. Разберем процесс заполнения реквизитов и строк табличной части в цикле Для Каждого.


Если НЕ ТаблицаДоговоров.Количество() = 0 Тогда
    НовыйДокумент = Документы.НачислениеАренднойПлаты.СоздатьДокумент();
    НовыйДокумент.Дата = ТекущаяДата();
    НовыйДокумент.Комментарий = "Создано автоматически: " + ТекущаяДата();
    
    // Заполняем табличную часть
    Для Каждого СтрокаДоговора Из ТаблицаДоговоров Цикл
        НоваяСтрока = НовыйДокумент.ТЧНачисления.Добавить();
        
        // Используем ЗаполнитьЗначенияСвойств для одинаковых имен колонок
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДоговора);
        
        // Или заполняем вручную, если имена отличаются
        НоваяСтрока.ДоговорАренды = СтрокаДоговора.Договор;
        НоваяСтрока.СуммаНачисления = СтрокаДоговора.Сумма;
    КонецЦикла;
    
    // Подсчет итога по документу
    НовыйДокумент.СуммаДокумента = НовыйДокумент.ТЧНачисления.Итог("СуммаНачисления");
    
    // Запись и проведение
    Попытка
        НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
        Сообщить("Документ начисления успешно создан и проведен!");
    Исключение
        Сообщить("Ошибка при проведении документа: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецЕсли;

Обратите внимание на использование блока Попытка...Исключение. При программном создании документов это критически важно, так как проведение может сорваться из-за нехватки прав, незаполненных обязательных реквизитов или блокировок базы данных. Метод КраткоеОписаниеОшибки() поможет быстро понять причину сбоя.

Автоматизация: Регламентные задания vs При начале работы системы

Рассмотрим вопрос о том, где именно должен выполняться этот код. В обсуждении часто предлагают запускать проверку ПриНачалеРаботыСистемы. Однако это плохая практика по нескольким причинам:

Правильное решение: Использовать РегламентныеЗадания. Вы можете вынести процедуру создания начислений в общий модуль с признаком «Сервер» и настроить расписание в консоли регламентных заданий (например, раз в сутки в 01:00). Это позволит системе работать полностью автономно, а бухгалтер будет видеть уже готовые документы в списке утром.

Нюансы работы с Таблицей Значений и методом Загрузить()

Многие начинающие программисты пытаются использовать метод ТЧ.Загрузить(ТаблицаЗначений). Рассмотрим причины, по которым это может вызвать ошибку «Несоответствие типов»:

  1. Разные имена колонок: Метод Загрузить() требует, чтобы имена колонок в ТЗ и ТЧ полностью совпадали. Если в ТЗ колонка называется Сумма, а в ТЧ — СуммаНачисления, данные не будут перенесены.
  2. Лишние колонки: Если в вашей таблице значений есть технические колонки из запроса (например, ВерсияДанных), которых нет в табличной части документа, это может привести к ошибке.

Именно поэтому ручной обход в цикле или использование ЗаполнитьЗначенияСвойств считается более надежным и гибким подходом.

Заключение

Мы проанализировали процесс автоматизации начислений по аренде. Главные моменты, которые стоит запомнить: всегда проверяйте наличие уже созданных документов, чтобы избежать дублирования (лучше через ЛЕВОЕ СОЕДИНЕНИЕ), используйте регламентные задания для фоновой работы и всегда обрабатывайте исключения при записи документов. Такая архитектура сделает вашу систему надежной и удобной для конечных пользователей.

← На главную