Почему не удается корректно пересоздать движения документа "Операция (бухгалтерский и налоговый учет)" в 1С?

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

При работе с программным созданием и перезаписью документов в 1С, особенно таких специфичных, как "Операция (бухгалтерский и налоговый учет)", часто возникают сложности. Одна из наиболее распространенных проблем – это некорректное отображение данных в отчетах (например, в оборотно-сальдовой ведомости) после программной перезаписи документа, в то время как при первичном создании или интерактивном сохранении все работает правильно. Давайте разберемся, почему возникает такая "чертовщина" и как ее избежать, используя правильные подходы к работе с движениями документа.

Суть проблемы: Когда мы программно "пересоздаем" документ "Операция (бухгалтерский и налоговый учет)", нам необходимо не просто создать новый набор проводок, но и убедиться, что старые проводки по этому документу были корректно удалены. Без этого новые записи будут наслаиваться на старые, приводя к задвоению данных и, как следствие, к неверным цифрам в отчетах.

Особенности документа "Операция (бухгалтерский и налоговый учет)"

Прежде чем перейти к решениям, давайте уясним одну ключевую особенность документа "Операция (бухгалтерский и налоговый учет)" (часто сокращенно "ОперацияБух"):

  1. Этот документ не имеет собственного механизма проведения в отличие от большинства других документов 1С (таких как "Поступление товаров и услуг", "Реализация товаров и услуг" и т.д.). Его проводки записываются в регистры непосредственно в момент записи самого документа.
  2. Соответственно, для него не имеет смысла использовать режимы записи РежимЗаписиДокумента.Проведение или пытаться установить свойство ДокументОбъект.Проведен = Истина. Попытки сделать это могут привести к ошибкам или игнорированию действия.

Для корректной записи движений нам потребуется использовать РежимЗаписиДокумента.Запись.

Подход 1: Использование коллекции движений документа (Рекомендуемый)

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

Шаги по созданию/перезаписи движений через коллекцию документа:

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

Пример кода для использования коллекции движений:


// Предположим, что ИзменитьСтарый - это булево,
// СтарыйДокумент - это ссылка на существующий документ
// или Документы.Операция.СоздатьДокумент() для нового.

Перем ДокументОбъект;

Если ИзменитьСтарый Тогда
    // Получаем объект существующего документа
    ДокументОбъект = Объект.СтарыйДокумент.ПолучитьОбъект(); 
Иначе
    // Создаем новый документ
    ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент(); 
    ДокументОбъект.Дата = ТекущаяДата();
    ДокументОбъект.Организация = ПолучитьЗначениеПоУмолчанию("ОсновнаяОрганизация"); // Пример заполнения
    ДокументОбъект.Содержание = "Автоматическое создание операции";
КонецЕсли;

// 1. Обязательно записываем документ, если он новый и мы хотим получить его Ссылку
// (хотя для ДокументОбъект.Движения это не так критично, как для НабораЗаписей,
// но это хорошая практика для установки базовых реквизитов)
// ДокументОбъект.Записать(РежимЗаписиДокумента.Запись); // Можно записать здесь, если нужно получить ссылку раньше

// 2. Обращаемся к коллекции движений по регистру бухгалтерии Хозрасчетный
ДвиженияХозрасчетный = ДокументОбъект.Движения.Хозрасчетный;

// 3. Устанавливаем режим перезаписи
// Это указывает платформе, что при записи документа нужно сначала очистить
// все старые движения этого документа по данному регистру, а затем записать новые.
ДвиженияХозрасчетный.Записывать = Истина;

// 4. Очищаем существующие движения в коллекции (необязательно, но полезно для наглядности,
// хотя Записывать = Истина уже обеспечит удаление старых при записи документа)
ДвиженияХозрасчетный.Очистить(); 

// 5. Добавляем новые проводки
// Пример одной проводки: Дт 76.05 Кт 51
НоваяПроводка = ДвиженияХозрасчетный.Добавить();
НоваяПроводка.Период = ДокументОбъект.Дата;
НоваяПроводка.СчетДт = ПланыСчетов.Хозрасчетный.РасчетыСРазнымиДебиторамиИКредиторами; // Пример получения счета
НоваяПроводка.СчетКт = ПланыСчетов.Хозрасчетный.РасчетныеСчета; // Пример получения счета
НоваяПроводка.Сумма = 1000;
НоваяПроводка.Валюта = ДокументОбъект.Организация.ВалютаРегламентированногоУчета; // Пример получения валюты
НоваяПроводка.СуммаВВалюте = 1000;
НоваяПроводка.Содержание = "Пример проводки";

// Заполняем субконто, если требуется
// НоваяПроводка.СубконтоДт.Контрагенты = СсылкаНаКонтрагента;
// НоваяПроводка.СубконтоКт.БанковскиеСчета = СсылкаНаБанковскийСчет;

// Добавим еще одну проводку для примера
НоваяПроводка = ДвиженияХозрасчетный.Добавить();
НоваяПроводка.Период = ДокументОбъект.Дата;
НоваяПроводка.СчетДт = ПланыСчетов.Хозрасчетный.Касса;
НоваяПроводка.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСРазнымиДебиторамиИКредиторами;
НоваяПроводка.Сумма = 500;
НоваяПроводка.Содержание = "Еще одна проводка";

// 6. Записываем документ
// Используем РежимЗаписиДокумента.Запись, так как "ОперацияБух" не проводится
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

// Показываем пользователю созданный/измененный документ
Показать(ДокументОбъект.Ссылка);

Использование ДокументОбъект.Движения.Хозрасчетный.Записывать = Истина; является наиболее надежным способом для перезаписи движений, поскольку оно автоматически обеспечивает удаление старых проводок перед записью новых при сохранении документа.

Подход 2: Использование набора записей регистра напрямую

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

Шаги по созданию/перезаписи движений через набор записей:

  1. Создаем и записываем документ для получения ссылки: Поскольку набор записей требует указания регистратора (который является ссылкой на документ), документ должен быть сначала записан, чтобы получить свою уникальную ссылку.
  2. Создаем объект "НаборЗаписей" для нужного регистра: Используем РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей().
  3. Устанавливаем отбор по регистратору: Это обязательный шаг для того, чтобы работать только с движениями конкретного документа. Используем НаборЗаписей.Отбор.Регистратор.Установить(ДокументОбъект.Ссылка).
  4. Очищаем существующие движения: Чтобы избежать дублирования проводок при перезаписи, необходимо сначала прочитать существующие записи с установленным отбором, а затем вызвать метод Очистить(). Этот шаг критически важен для предотвращения "чертовщины".
  5. Добавляем новые проводки: Используем метод НаборЗаписей.Добавить() для создания новых элементов записей и заполняем их реквизиты, обязательно указывая Регистратор.
  6. Записываем набор записей: После добавления всех проводок сохраняем сам набор записей с помощью НаборЗаписей.Записать().

Пример кода для использования набора записей:


// Предположим, что ИзменитьСтарый - это булево,
// СтарыйДокумент - это ссылка на существующий документ
// или Документы.Операция.СоздатьДокумент() для нового.

Перем ДокументОбъект;

Если ИзменитьСтарый Тогда
    // Получаем объект существующего документа
    ДокументОбъект = Объект.СтарыйДокумент.ПолучитьОбъект(); 
Иначе
    // Создаем новый документ
    ДокументОбъект = Документы.ОперацияБух.СоздатьДокумент();
    ДокументОбъект.Дата = ТекущаяДата();
    ДокументОбъект.Организация = ПолучитьЗначениеПоУмолчанию("ОсновнаяОрганизация");
    ДокументОбъект.Содержание = "Автоматическое создание операции (через НаборЗаписей)";
КонецЕсли;

// 1. Обязательно записываем документ, чтобы получить его Ссылку.
// Если документ уже был записан, эта операция его просто перезапишет.
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

// 2. Создаем объект НаборЗаписей для регистра Хозрасчетный
НаборЗаписей = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();

// 3. Устанавливаем отбор по регистратору
// Это гарантирует, что мы будем работать только с движениями,
// созданными данным документом.
НаборЗаписей.Отбор.Регистратор.Установить(ДокументОбъект.Ссылка);

// 4. Прочитываем существующие записи и очищаем их
// Это критически важно при перезаписи, чтобы избежать дублирования.
НаборЗаписей.Прочитать(); // Читаем текущие движения документа
НаборЗаписей.Очистить();  // Удаляем все прочитанные движения

// 5. Добавляем новые проводки
// Пример одной проводки: Дт 60.01 Кт 51
Запись = НаборЗаписей.Добавить();
Запись.Регистратор = ДокументОбъект.Ссылка; // Обязательно указываем регистратор для каждой записи
Запись.Период = ДокументОбъект.Дата;
Запись.СчетДт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщикамиИПодрядчиками;
Запись.СчетКт = ПланыСчетов.Хозрасчетный.РасчетныеСчета;
Запись.Сумма = 2500;
Запись.Валюта = ДокументОбъект.Организация.ВалютаРегламентированногоУчета;
Запись.СуммаВВалюте = 2500;
Запись.Содержание = "Пример проводки через набор записей";

// Заполняем субконто, если требуется
// Запись.СубконтоДт.Контрагенты = СсылкаНаКонтрагента;

// Добавим еще одну проводку для примера
Запись = НаборЗаписей.Добавить();
Запись.Регистратор = ДокументОбъект.Ссылка;
Запись.Период = ДокументОбъект.Дата;
Запись.СчетДт = ПланыСчетов.Хозрасчетный.Товары;
Запись.СчетКт = ПланыСчетов.Хозрасчетный.РасчетыСПоставщикамиИПодрядчиками;
Запись.Сумма = 2000;
Запись.Содержание = "Еще одна проводка через набор записей";

// 6. Записываем набор записей
НаборЗаписей.Записать();

// Показываем пользователю созданный/измененный документ
Показать(ДокументОбъект.Ссылка);

Сравнение подходов и рекомендации

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

  1. Простота использования: Подход с коллекцией движений документа (ДокументОбъект.Движения) часто проще в реализации, поскольку платформа автоматически управляет многими аспектами, включая связь с документом и очистку старых движений (при установке Записывать = Истина).
  2. Контроль: Подход с набором записей регистра (РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей()) предоставляет более низкоуровневый и детальный контроль. Это может быть полезно в специфических случаях, когда вам нужно манипулировать движениями независимо от их документа-регистратора (хотя в контексте изменения движений конкретного документа это менее применимо).
  3. Обработка перезаписи:
    • При использовании ДокументОбъект.Движения: установка ДокументОбъект.Движения.Хозрасчетный.Записывать = Истина; перед записью документа автоматически позаботится об удалении старых движений, связанных с этим документом.
    • При использовании НаборЗаписей: вам необходимо вручную выполнить НаборЗаписей.Прочитать(); НаборЗаписей.Очистить(); перед добавлением новых записей, чтобы избежать дублирования.

Наша рекомендация: Для создания и изменения движений документа "Операция (бухгалтерский и налоговый учет)" предпочтительнее использовать его коллекцию движений (ДокументОбъект.Движения.Хозрасчетный). Этот подход более "1С-ный", интуитивно понятен и снижает вероятность ошибок при перезаписи благодаря свойству Записывать = Истина.

Важные моменты для запоминания

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

← На главную