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

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

При разработке расширений для конфигурации 1С:Бухгалтерия предприятия 3.0 часто возникает задача корректировки движений документа «на лету». Типичный сценарий: после выполнения стандартной процедуры проведения необходимо заменить один счет учета на другой (например, заменить счет учета затрат на счет учета прибыли) и заполнить соответствующие аналитики (субконто). Однако программисты часто сталкиваются с тем, что стандартный метод Очистить() для коллекции субконто не удаляет связи со старым счетом, что приводит к ошибкам несоответствия метаданных. В этой статье мы подробно разберем, почему это происходит и какими способами можно гарантированно изменить проводку.

Анализ проблемы: почему не работает стандартная очистка

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

Проблема заключается в том, что коллекция Субконто в платформе 1С жестко типизирована согласно настройкам Плана счетов. Когда мы меняем значение счета в строке движения, платформа не всегда автоматически «перестраивает» структуру коллекции субконто. Вызов Очистить() удаляет лишь значения субконто, но сами ключи (Виды субконто), принадлежавшие старому счету, могут остаться в памяти объекта. В итоге при попытке записи набора возникает ошибка: «Субконто не соответствует данному счету».

Решение №1: Использование таблицы значений для перезагрузки движений

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

Рассмотрим алгоритм действий:

  1. Выгружаем движения в таблицу значений.
  2. Модифицируем данные в таблице, явно очищая не только значения, но и колонки видов субконто (ВидСубконтоДт1, ВидСубконтоДт2 и т.д.).
  3. Загружаем таблицу обратно в набор движений.

Пример программного кода:


&После("ОбработкаПроведения")
Процедура Расш_ОбработкаПроведения(Отказ, РежимПроведения)
    
    ДвиженияХозрасчетный = ЭтотОбъект.Движения.Хозрасчетный;
    ДвиженияХозрасчетный.Записывать = Истина;
    
    // Выгружаем текущие проводки в ТЗ
    ТЗПроводок = ДвиженияХозрасчетный.Выгрузить();
    
    Для каждого Движение Из ТЗПроводок Цикл
        // Определяем условие, по которому нужно изменить проводку
        Если Движение.СчетДт = ПланыСчетов.Хозрасчетный.СебестоимостьПродаж Тогда
            
            // Устанавливаем новый счет
            Движение.СчетДт = ПланыСчетов.Хозрасчетный.НераспределеннаяПрибыль;
            
            // Принудительно очищаем виды субконто, чтобы убрать привязку к старому счету
            Движение.ВидСубконтоДт1 = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка;
            Движение.ВидСубконтоДт2 = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка;
            Движение.ВидСубконтоДт3 = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ПустаяСсылка;
            
            // Заполняем новое субконто согласно новому счету
            ВидСуб = Движение.СчетДт.ВидыСубконто[0].ВидСубконто;
            Движение.ВидСубконтоДт1 = ВидСуб;
            // Устанавливаем значение (СубконтоБлаготворительность - ваша переменная со ссылкой)
            Движение["СубконтоДт1"] = СубконтоБлаготворительность;
            
            // Обнуляем количественный учет, если на новом счете его нет
            Движение.КоличествоДт = 0;
            Движение.Содержание = "Перенос затрат на благотворительность";
        КонецЕсли;
    КонецЦикла;
    
    // Загружаем измененные данные обратно
    ДвиженияХозрасчетный.Загрузить(ТЗПроводок);
    
КонецПроцедуры

Решение №2: Использование типовой функции «УстановитьСубконто»

В конфигурации БП 3.0 существует специализированный общий модуль БухгалтерскийУчет, методы которого позволяют корректно работать с аналитикой. Функция УстановитьСубконто самостоятельно проверяет, входит ли данный вид субконто в настройки счета, и очищает лишние записи.

Проанализируем применение этого метода:


// Вместо ручной вставки в коллекцию используйте:
БухгалтерскийУчет.УстановитьСубконто(Движение.СчетДт, Движение.СубконтоДт, 1, ЗначениеСубконто);

Однако помните, что даже эта функция может не справиться, если вы сначала не обнулили старые виды субконто при радикальной смене счета. Поэтому рекомендуется комбинировать этот подход с методом ЗаполнитьСубконто(), который доступен у объекта записи регистра бухгалтерии.

Решение №3: Метод полного пересоздания строки

Если модификация существующей записи вызывает ошибки при повторном проведении документа, наиболее надежным (хотя и более трудоемким) методом будет удаление старой записи и добавление новой «с нуля».

Выясним, как реализовать этот подход:

  1. При переборе движений мы находим нужную строку и копируем её значения во временную структуру.
  2. Удаляем текущую строку из коллекции Движения.Хозрасчетный.
  3. Добавляем новую строку методом Добавить().
  4. Заполняем новую строку данными, устанавливаем новый счет и вызываем метод Движение.ЗаполнитьСубконто(). Этот метод автоматически создаст в коллекции Субконто только те ключи, которые предусмотрены в метаданных нового счета.

Важные нюансы при работе в расширениях

Проанализируем несколько критических моментов, о которых часто забывают разработчики:

1. Налоговый учет (НУ, ПР, ВР)

При изменении проводок в БП 3.0 нельзя забывать о ресурсах налогового учета. Если вы меняете счет 90.02 (где есть НУ) на счет 84 (где НУ обычно не ведется), вы обязаны обнулить не только Сумма, но и СуммаНУДт, СуммаНУКт, а также СуммаПРДт и СуммаВРДт. Несоблюдение баланса БУ = НУ + ПР + ВР приведет к ошибкам в регламентированной отчетности и при закрытии месяца.

2. Флаг записи движений

В процедуре &После("ОбработкаПроведения") установка Движения.Хозрасчетный.Записывать = Истина обязательна. Однако, если вы делаете сложные манипуляции или удаление строк, в конце процедуры может потребоваться явный вызов Движения.Хозрасчетный.Записать(), чтобы гарантировать сохранение ваших изменений в транзакции проведения.

3. Повторное проведение

Всегда проверяйте, не были ли движения уже изменены вашим кодом. При повторном проведении (например, при групповом перепроведении) документ может содержать уже модифицированные вами данные. Чтобы избежать дублирования или ошибок, добавьте проверку: Если Движение.СчетДт = НовыйСчет Тогда Продолжить; КонецЕсли;.

Используя предложенные методы (особенно работу через таблицу значений с очисткой ВидСубконто), вы сможете избежать конфликтов метаданных и корректно управлять проводками в любых версиях платформы 1С:Предприятие 8.3.

← На главную