При работе с конфигурацией 1С:Бухгалтерия предприятия 3.0 (БП 3.0) разработчики часто сталкиваются с необходимостью отображения себестоимости списания товаров непосредственно в форме списка документов, например, в Перемещении товаров. Казалось бы, в документе уже существует реквизит СебестоимостьДокумента или аналогичные поля в табличной части, которые так и просятся для заполнения. Однако попытка записать туда данные программно в момент проведения документа может привести к фатальным ошибкам в учете.
В этой статье мы разберем, почему типовой реквизит себестоимости является «неприкасаемым» для обычного алгоритма проведения, проанализируем внутренние механизмы 1С и выберем оптимальный способ решения задачи без вреда для системы.
Для начала проанализируем ситуацию: зачем в типовой конфигурации БП 3.0 вообще существуют поля для ввода себестоимости, если программа должна рассчитывать их автоматически? Ответ кроется в архитектуре взаимодействия систем 1С:Управление торговлей (УТ) и 1С:Бухгалтерия предприятия (БП).
Рассмотрим логику, заложенную методологами 1С: в системе УТ ведется оперативный учет, и именно там формируется «истинная» себестоимость. При синхронизации данных документ переносится в БП уже с готовыми суммами. Чтобы бухгалтерия не пересчитывала эти суммы по своим правилам (которые могут отличаться из-за партионного учета или ФИФО), используется реквизит Себестоимость.
Важный вывод: этот реквизит служит «выключателем» стандартного механизма расчета. Если он заполнен, программный модуль УчетНоменклатуры видит готовую сумму и подставляет ее в проводки по счетам 10, 41 или 43 «как есть», игнорируя реальные остатки и стоимость партий на регистрах бухгалтерии.
Если мы попытаемся заполнить этот реквизит программно в процедуре ОбработкаПроведения, мы столкнемся с тремя критическими проблемами:
ЭтотОбъект.Записать(). Но вызов записи внутри транзакции проведения инициирует повторное проведение, что ведет либо к бесконечной петле, либо к ошибке блокировки таблиц базы данных.Проанализируем альтернативные и безопасные пути реализации этой задачи.
Если наша основная цель — видеть себестоимость в списке документов для визуального контроля, нам вообще не нужно менять структуру документа или записывать что-то в объект. Мы можем воспользоваться мощностью Динамического списка в форме списка документов.
Разберем по шагам, как это реализовать:
ПеремещениеТоваров.РегистрБухгалтерии.Хозрасчетный.Обороты.Рассмотрим пример запроса для динамического списка:
ВЫБРАТЬ
ДокументПеремещение.Ссылка КАК Ссылка,
ДокументПеремещение.Дата КАК Дата,
ДокументПеремещение.Номер КАК Номер,
ЕСТЬNULL(ХозрасчетныйОбороты.СуммаОборот, 0) КАК СебестоимостьДляСписка
ИЗ
Документ.ПеремещениеТоваров КАК ДокументПеремещение
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Обороты(,, Авто, , , , , ) КАК ХозрасчетныйОбороты
ПО ХозрасчетныйОбороты.Регистратор = ДокументПеремещение.Ссылка
И (ХозрасчетныйОбороты.Счет В ИЕРАРХИИ (ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.Товары)))
При таком подходе пользователь всегда видит актуальную сумму, которая реально отражена в проводках, при этом мы не нарушаем типовую логику проведения и не «раздуваем» базу данных лишними реквизитами.
Если себестоимость необходима не только в списке, но и в сложных отчетах, где соединение с регистром бухгалтерии будет работать слишком медленно, мы можем создать собственный реквизит, например, упр_СебестоимостьДляОтчетов.
Выясним, как правильно организовать его заполнение:
ПеремещениеТоваров новый реквизит с типом Число(15, 2).ОбработкаПроведения (или ПриЗаписи).Хозрасчетный, которые только что сформировал документ, и записываем их в наш новый реквизит.Важно помнить: чтобы избежать рекурсии, запись значения в наш реквизит должна происходить вне основной транзакции проведения либо через специальный механизм блокировки повторного входа. Однако наиболее безопасным считается использование вспомогательного регистра сведений или дополнительных сведений.
Если вы не хотите вносить изменения в структуру таблиц (даже через расширения), проанализируем использование механизма Дополнительных сведений. Это типовой функционал БП 3.0, который позволяет хранить произвольные данные, привязанные к объекту.
Посмотрим на алгоритм реализации:
Перемещение товаров с названием «Себестоимость (итог)».ДополнительныеСведения.Этот метод хорош тем, что он абсолютно «чист» с точки зрения поддержки конфигурации. Вы не меняете типовой код и не влияете на механизм закрытия месяца. Сумму из доп. сведений также легко вывести в список документов через стандартную настройку формы («Изменить форму» — выбрать поле из набора дополнительных сведений).
Проанализируем ситуацию, упомянутую в обсуждении: «упрощенный учет и отсутствие закрытия месяца». В БП 3.0, если включена настройка Разрешить списание запасов при отсутствии остатков, себестоимость при проведении может быть нулевой, если товара нет на складе в момент нажатия кнопки «Провести».
В этом случае любая попытка записать «текущую» себестоимость в реквизит объекта зафиксирует 0. Когда позже придет документ поступления, себестоимость перемещения не появится автоматически — потребуется либо перепроведение всех документов, либо выполнение регламентной операции Корректировка стоимости номенклатуры в конце месяца.
Резюмируем: Использование стандартного реквизита СебестоимостьДокумента для хранения расчетных данных — это «путь к катастрофе» в учете 1С:Бухгалтерии. Самым элегантным и производительным решением является настройка динамического списка с запросом к регистру бухгалтерии. Если же физическое хранение суммы необходимо, используйте дополнительные сведения или собственный реквизит в расширении, никогда не трогая типовые поля, предназначенные для обмена данными.