Как рассчитать сумму запасов по складам по средней цене, если в 1С ведется только количественный складской учет?

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

В практике работы с программой 1С:Бухгалтерия 8 (редакция 3.0) разработчики и аналитики часто сталкиваются с ситуацией, когда в настройках параметров учета (в плане счетов) для материальных счетов (10, 41, 43 и др.) включен количественный учет по складам, но отключен суммовой. Это означает, что программа хранит информацию о суммах только в целом по организации, а на складах учитываются исключительно штуки, литры или килограммы.

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

Почему идея «динамического» переключения настроек перед запросом не работает?

Иногда у начинающих разработчиков возникает мысль: написать во внешнем отчете код, который перед выполнением запроса временно изменит настройку программы на «Учет запасов по складам — по количеству и сумме», выполнит запрос, а затем вернет настройку обратно в режим «только по количеству». Давайте разберем, почему этот подход не только не решит задачу, но и опасен для базы данных:

  1. Изменение структуры метаданных и реструктуризация таблиц. Настройка ведения складского учета в 1С:Бухгалтерии напрямую влияет на свойства Плана счетов Хозрасчетный. При ее изменении у субконто Склады на счетах учета ТМЦ динамически устанавливается или снимается признак «Суммовой». Это транзакционная операция, требующая монопольного доступа к базе данных. Программа инициирует полную реструктуризацию таблиц регистра бухгалтерии. Выполнить такое действие быстро в коде отчета «на лету» технически невозможно — система просто заблокирует базу для всех пользователей на длительное время.
  2. Отсутствие исторических данных в базе. Даже если бы нам удалось моментально изменить настройку, суммы по складам за прошлые периоды в базе чудесным образом не появятся. Все ранее проведенные документы записывали в регистр бухгалтерии только количество по складам, а поля сумм оставляли пустыми. Чтобы эти суммы появились в проводках, базу данных потребовалось бы полностью перепровести с момента начала ведения учета. Без перепроведения запрос все равно вернет пустые значения по суммам за все прошлые периоды.

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

Математическая ловушка «Перемещений»

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

Однако при попытке реализовать этот расчет через стандартные обороты по складам (например, используя виртуальную таблицу РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты) мы сталкиваемся с серьезной проблемой при наличии документов «Перемещение товаров».

Проанализируем проводки, которые делает документ перемещения между складами при выключенном суммовом учете по складам:

Теперь посмотрим, что происходит в виртуальной таблице ОстаткиИОбороты в разрезе складов, если мы пытаемся посчитать среднюю цену прихода за период по формуле: СуммаПрихода / КоличествоПрихода.

Представим ситуацию на примере:

  1. Поступил товар на Склад №1 от поставщика: 10 шт. на сумму 1000 руб. (Средняя цена = 100 руб.).
  2. Документом перемещения мы перевели эти 10 шт. со Склада №1 на Склад №2.
  3. Затем переместили их обратно со Склада №2 на Склад №1.

Если мы снимем обороты по Складу №1, мы увидим:

Если мы попытаемся рассчитать среднюю цену прихода по Складу №1 напрямую по оборотам, мы получим: 1000 руб. / 20 шт. = 50 руб. за штуку! Наша средняя цена искусственно занизилась в два раза просто из-за того, что товар перемещался между складами. Количество оборотов прихода "раздулось" за счет внутренних перемещений без изменения суммовой стоимости. Результат отчета полностью разойдется с реальными данными оборотно-сальдовой ведомости (ОСВ) по организации.

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

Вариант А. Расчет через среднюю цену по организации (наиболее правильный метод)

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

Разберем по шагам, как построить такой запрос с использованием механизма временных таблиц:

  1. ВТ_ДанныеОрганизации: На первом шаге мы получаем остатки и обороты ТМЦ в целом по организации, исключая разрез складов из группировок. Это позволит нам получить чистые суммы и количество без искажений от внутренних перемещений.
  2. ВТ_ДанныеСкладов: На втором шаге мы выбираем данные по количеству в разрезе складов.
  3. Итоговое соединение: Мы соединяем две временные таблицы по полям Номенклатура (и, при необходимости, Счет). Сумму на складе рассчитываем путем умножения количества на складе на среднюю цену, вычисленную по данным организации.

Посмотрим на пример практической реализации такого запроса:


ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.Счет КАК Счет,
    ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
    СУММА(ХозрасчетныйОстаткиИОбороты.КоличествоНачальныйОстатокДт) КАК КоличествоНачОстВсего,
    СУММА(ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстатокДт) КАК СуммаНачОстВсего,
    СУММА(ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстатокДт) КАК КоличествоКонОстВсего,
    СУММА(ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт) КАК СуммаКонОстВсего
ПОМЕСТИТЬ ВТ_ИтогиПоОрганизации
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет В ИЕРАРХИИ (&СчетУчета), , Организация = &Организация) КАК ХозрасчетныйОстаткиИОбороты
ГРУППИРОВАТЬ ПО
    ХозрасчетныйОстаткиИОбороты.Счет,
    ХозрасчетныйОстаткиИОбороты.Субконто1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.Счет КАК Счет,
    ХозрасчетныйОстаткиИОбороты.Субконто1 КАК Номенклатура,
    ВЫБОР
        КОГДА ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Субконто2) = ТИП(Справочник.Склады)
            ТОГДА ХозрасчетныйОстаткиИОбороты.Субконто2
        КОГДА ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Субконто3) = ТИП(Справочник.Склады)
            ТОГДА ХозрасчетныйОстаткиИОбороты.Субконто3
        ИНАЧЕ НЕОПРЕДЕЛЕНО
    КОНЕЦ КАК Склад,
    СУММА(ХозрасчетныйОстаткиИОбороты.КоличествоНачальныйОстатокДт) КАК КоличествоНачОстСклад,
    СУММА(ХозрасчетныйОстаткиИОбороты.КоличествоКонечныйОстатокДт) КАК КоличествоКонОстСклад
ПОМЕСТИТЬ ВТ_ДанныеПоСкладам
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет В ИЕРАРХИИ (&СчетУчета), , Организация = &Организация) КАК ХозрасчетныйОстаткиИОбороты
ГРУППИРОВАТЬ ПО
    ХозрасчетныйОстаткиИОбороты.Счет,
    ХозрасчетныйОстаткиИОбороты.Субконто1,
    ВЫБОР
        КОГДА ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Субконто2) = ТИП(Справочник.Склады)
            ТОГДА ХозрасчетныйОстаткиИОбороты.Субконто2
        КОГДА ТИПЗНАЧЕНИЯ(ХозрасчетныйОстаткиИОбороты.Субконто3) = ТИП(Справочник.Склады)
            ТОГДА ХозрасчетныйОстаткиИОбороты.Субконто3
        ИНАЧЕ НЕОПРЕДЕЛЕНО
    КОНЕЦ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_ДанныеПоСкладам.Счет КАК Счет,
    ВТ_ДанныеПоСкладам.Номенклатура КАК Номенклатура,
    ВТ_ДанныеПоСкладам.Склад КАК Склад,
    
    // Начальный остаток
    ВТ_ДанныеПоСкладам.КоличествоНачОстСклад КАК КоличествоНачальныйОстаток,
    ВЫБОР
        КОГДА ЕСТЬNULL(ВТ_ИтогиПоОрганизации.КоличествоНачОстВсего, 0) <> 0
            ТОГДА ВТ_ДанныеПоСкладам.КоличествоНачОстСклад * (ЕСТЬNULL(ВТ_ИтогиПоОрганизации.СуммаНачОстВсего, 0) / ВТ_ИтогиПоОрганизации.КоличествоНачОстВсего)
        ИНАЧЕ 0
    КОНЕЦ КАК СуммаНачальныйОстаток,
    
    // Конечный остаток
    ВТ_ДанныеПоСкладам.КоличествоКонОстСклад КАК КоличествоКонечныйОстаток,
    ВЫБОР
        КОГДА ЕСТЬNULL(ВТ_ИтогиПоОрганизации.КоличествоКонОстВсего, 0) <> 0
            ТОГДА ВТ_ДанныеПоСкладам.КоличествоКонОстСклад * (ЕСТЬNULL(ВТ_ИтогиПоОрганизации.СуммаКонОстВсего, 0) / ВТ_ИтогиПоОрганизации.КоличествоКонОстВсего)
        ИНАЧЕ 0
    КОНЕЦ КАК СуммаКонечныйОстаток
ИЗ
    ВТ_ДанныеПоСкладам КАК ВТ_ДанныеПоСкладам
        ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ИтогиПоОрганизации КАК ВТ_ИтогиПоОрганизации
        ПО ВТ_ДанныеПоСкладам.Счет = ВТ_ИтогиПоОрганизации.Счет
            И ВТ_ДанныеПоСкладам.Номенклатура = ВТ_ИтогиПоОрганизации.Номенклатура

Проанализируем этот запрос. Мы разделили получение данных на два независимых потока. В итоговой выборке мы используем классическое деление общей суммы на общее количество (расчет средней цены) и умножаем полученный коэффициент на складской остаток. Конструкция ВЫБОР КОГДА ... <> 0 страхует нас от потенциальной ошибки деления на ноль, которая может возникнуть, если по какой-то причине в системе образовался суммовой остаток без количественного (или наоборот).

Вариант Б. Очистка оборотов от внутренних перемещений

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

Для этого мы можем применить два подхода:

Способ 1. Фильтрация по корреспондирующим счетам

При перемещении товаров проводка происходит внутри одного и того же счета (например, с 41.01 на 41.01). Мы можем исключить такие обороты в запросе, обратившись к оборотам с фильтром по корреспонденции. Нам нужно отсечь записи, в которых корреспондирующий счет равен счету учета.

Рассмотрим пример настройки параметров виртуальной таблицы:


ВЫБРАТЬ
    ХозрасчетныйОбороты.Счет КАК Счет,
    ХозрасчетныйОбороты.Субконто1 КАК Номенклатура,
    ХозрасчетныйОбороты.КоличествоОборотДт КАК КоличествоПриходЧистый,
    ХозрасчетныйОбороты.СуммаОборотДт КАК СуммаПриходЧистый
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Обороты(
        &НачалоПериода,
        &КонецПериода,
        ,
        Счет В ИЕРАРХИИ (&СчетУчета),
        ,
        Организация = &Организация
            И НЕ КорСчет В ИЕРАРХИИ (&СчетУчета), // Исключаем внутренние обороты
        ,
    ) КАК ХозрасчетныйОбороты

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

Способ 2. Фильтрация по типам документов (Регистраторам)

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


ГДЕ
    НЕ ХозрасчетныйОстаткиИОбороты.Регистратор ССЫЛКА Документ.ПеремещениеТоваров

Важное предупреждение: Использование детализации до регистратора в виртуальных таблицах остатков и оборотов может существенно снизить производительность запроса на больших базах данных. Рекомендуется отдавать предпочтение первому способу с анализом корреспондирующих счетов.

Что будет, если официально изменить настройки в программе на «По количеству и сумме»?

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

  1. Необходимость полного перепроведения базы. Как уже упоминалось, после включения настройки во всех старых документах перемещения и списания суммы останутся нулевыми. Чтобы восстановить суммовой учет по складам, придется перепровести абсолютно все документы по движению ТМЦ с самого начала ведения учета в информационной базе (или как минимум с начала текущего года, предварительно зафиксировав и выровняв входящие остатки ручными операциями).
  2. Изменение финансового результата. При ведении только количественного учета по складам себестоимость списываемых товаров рассчитывается по средней стоимости в целом по организации. После включения суммового учета по складам себестоимость списания будет рассчитываться по каждому складу отдельно. Один и тот же товар, купленный на разные склады по разным ценам, при списании будет давать разную себестоимость. Это напрямую повлияет на финансовый результат компании, себестоимость продаж и налог на прибыль.
  3. Риск возникновения суммовых зависаний ("красноты"). В условиях раздельного суммового учета по складам любые ошибки пользователей (например, списание товара не с того склада, проведение документов "задним числом" без контроля остатков) будут приводить к ситуации, когда количество на складе закрылось в ноль, а сумма осталась (или наоборот). База потребует гораздо более строгого контроля и регулярного проведения процедуры "Корректировка стоимости номенклатуры" при закрытии месяца.
  4. Проблемы с раздельным учетом НДС. Если организация ведет раздельный учет НДС (облагаемые и не облагаемые НДС операции), изменение складской политики в середине года гарантированно приведет к сбоям в партионном учете НДС и ошибкам проведения документов со спецификацией "Для целей учета НДС не списано...".

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

Резюме

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

← На главную