Как правильно удалить и создать проводки при проведении документа в 1С

Программист 1С v8.3 (Обычные формы) 1C:Бухгалтерия Бухгалтерский учет
← На главную

В практике разработчика 1С часто возникает задача модификации стандартного механизма проведения. Например, когда типовое решение формирует проводки, которые не совсем подходят под специфику бизнес-процесса предприятия. В таких случаях нам нужно не просто добавить новые записи, а сначала «вычистить» ошибочные или лишние проводки, созданные системой автоматически, и заменить их своими. Разберем, как это сделать корректно, избегая типичных ошибок с блокировками и потерей данных.

Анализ типичной ошибки: Почему нельзя использовать СоздатьНаборЗаписей()

Рассмотрим ситуацию, с которой столкнулся автор темы. Попытка создать новый набор записей через РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей() внутри процедуры ОбработкаПроведения является методически неверной. Проанализируем причину: когда документ проводится, платформа уже открыла транзакцию и подготовила коллекцию Движения. Создавая отдельный объект набора записей и пытаясь его записать, вы фактически пытаетесь работать «в обход» стандартного механизма регистрации движений документа, что может привести к конфликтам блокировок или к тому, что изменения просто будут перезаписаны платформой в конце процедуры проведения.

Правильный подход заключается в использовании встроенной коллекции Движения. Выясним, как это реализовать на практике.

Шаг 1: Получение доступа к проводкам и выборка для удаления

Вместо создания нового набора записей, мы обратимся к уже существующим движениям документа. Если документ уже имеет проводки (например, сформированные ранее в этой же процедуре типовым кодом), мы можем их прочитать и проанализировать. Выполним выборочное удаление. Важный нюанс: нельзя удалять элементы коллекции прямо во время цикла Для каждого, так как это нарушит индекс обхода. Правильнее сначала собрать нужные записи в отдельный массив.

Рассмотрим правильный алгоритм удаления:


// Работаем с существующими движениями документа
НаборЗаписей = Движения.Хозрасчетный;

// Если записи еще не подгружены в память, читаем их
// (В ОбработкеПроведения они обычно уже доступны, если это не первое проведение)
НаборЗаписей.Прочитать(); 

ЗаписиДляУдаления = Новый Массив;

// Определяем ссылки на счета заранее, чтобы не вызывать НайтиПоКоду в цикле
Счет62_01 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("62.01");
Счет62_02 = ПланыСчетов.Хозрасчетный.НайтиПоКоду("62.02");

Для каждого Запись Из НаборЗаписей Цикл
    // Проверяем условия для удаления
    Если (Запись.СчетДт = Счет62_01 И Запись.СчетКт = Счет62_02) 
        Или (Запись.СчетДт = Счет62_01 И Запись.СчетКт = Счет62_01) Тогда
        
        ЗаписиДляУдаления.Добавить(Запись);
    КонецЕсли;    
КонецЦикла;

// Теперь удаляем собранные записи из коллекции
Для каждого Запись Из ЗаписиДляУдаления Цикл
    НаборЗаписей.Удалить(Запись);
КонецЦикла;

Шаг 2: Создание новых «правильных» проводок

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

Важный момент: Если вы не заполните измерение Организация, проводки могут «не схлопнуться» в оборотно-сальдовой ведомости (ОСВ) или вовсе не отобразиться в отчетах по конкретной организации. Также обратите внимание на заполнение субконто по типам.

Посмотрим на пример создания проводки:


НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период      = ЭтотОбъект.Дата;
НоваяЗапись.Регистратор = ЭтотОбъект.Ссылка;
НоваяЗапись.Организация = ЭтотОбъект.Организация; // Обязательное измерение!

НоваяЗапись.СчетДт = Счет62_01;
НоваяЗапись.СчетКт = Счет62_01;

// Заполнение Субконто. Безопаснее использовать поиск по виду субконто, 
// а не по индексу в массиве, но в простом случае можно и так:
ВидСубкКонтрагент = НоваяЗапись.СчетКт.ВидыСубконто[0].ВидСубконто;
НоваяЗапись.СубконтоКт.Вставить(ВидСубкКонтрагент, ЭтотОбъект.Контрагент);
НоваяЗапись.СубконтоДт.Вставить(ВидСубкКонтрагент, ЭтотОбъект.Контрагент);

ВидСубкДоговор = НоваяЗапись.СчетКт.ВидыСубконто[1].ВидСубконто;
НоваяЗапись.СубконтоКт.Вставить(ВидСубкДоговор, ДоговорПроводки);
НоваяЗапись.СубконтоДт.Вставить(ВидСубкДоговор, ДоговорПроводки);

// Сумма проводки
НоваяЗапись.Сумма = ОставшаясяСумма;

Шаг 3: Запись результатов

В обработчике ОбработкаПроведения у нас есть два пути для сохранения движений:

  1. Установить флаг автоматической записи: Движения.Хозрасчетный.Записывать = Истина;. В этом случае платформа сама запишет все накопленные в коллекции Движения.Хозрасчетный записи после завершения процедуры проведения. Это рекомендуемый способ.
  2. Вызвать метод НаборЗаписей.Записать(); принудительно. Это может потребоваться, если вам нужно, чтобы записи попали в базу данных немедленно (например, для использования в последующих запросах внутри этой же транзакции). Однако злоупотреблять этим не стоит.

Рекомендации по оптимизации кода

Разберем несколько советов, которые сделают ваш код более профессиональным и устойчивым к изменениям конфигурации:

Соблюдение этих правил позволит вам эффективно управлять проводками документов, сохраняя чистоту кода и высокую производительность системы 1С.

← На главную