СКД: Корректный расчет остатков по нескольким регистрам

Публикация № 702234

Программирование - Практика программирования

СКД Правильный расчет итогов Итоги Остатки Неправильный остаток

89
Решение проблемы некорректного расчета остатков при получении данных с помощью СКД из нескольких таблиц

Я не претендую на то, что описанные этой статье механизмы работы СКД и мое понимание соответствует действительности, поэтому готов внести поправки в данную статью, если что-то не так.

Постановка задачи

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

Как решалась задача

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

В схеме компоновки данных, я добавил единственный Набор данных - запрос с текстом, который описывает Объединение двух запросов:

1. РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты

2. РегистрНакопления.ПартииТоваровНаСкладахБухгалтерскийУчет.ОстаткиИОбороты

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

Плюс добавил в каждый запрос поле "Раздел" (я всегда так делаю, чтобы при отладке понять из какого запроса выбираются те или иные данные) - значение этого поля текст: для первого - "1. Товары на складах", для запроса к партиям - "2. Партии товаров на складах" соответственно.

 
 Набор данных - Запрос:

При чем, конструктор СКД определил роли полей(что измерения, а что поля начальных, конечных остатков)

Настроил ресурсы для всех полей. Здесь ничего необычного

Настройки компоновки сделал простыми вложенными группировками по разрезам учета Склад, Номенклатура, Характеристика, Серия. И выбрал все поля ресурсов, кроме начальных остатков.

Смотрю, что получается - вроде, правильно:

Но если добавить группировку по регистратору или детальные записи, то итоги по номенклатуре становятся неправильными:

В чем проблема? Дело в том, что в СКД свой собственный механизм расчета начальных и конечных остатков(информация из видео-курса по СКД Гилева)

Алгоритм расчета итогов по полям остатка описан на ИТС https://its.1c.ru/db/v8310doc#bookmark:dev:TI000000628 (Спасибо Armando)

Упрощенно алгоритм для получения Конечных остатков таков: берем последнюю по хронологии запись в разрезе выбранных измерений и считаем, что значение поля Конечный остаток из нее и есть конечный остаток для группировки. И судя по скриншоту, получается, что последняя запись имеет конечный остаток по Товарам на складах = 0, Партии = 0 - СКД считает, что для Номенклатуры это и есть конечный остаток.

Чтобы это победить, для поля Раздел я добавил роль Измерение, и поскольку, данное поле не планируется выбирать в отчете, а СКД его будет оптимизировать и удалять из запроса - флаг Обязательное. Теперь итоги верные.

Верные итоги

Немного красоты

Для того чтобы исключить пустые строки, сообщающие о начальном и конечном остатке на Начало/Конец периода, поле Регистратор можно в запросе заменить на выражение и поставить для этого поля галку Игнорировать значения NULL.

ВЫБОР
    КОГДА Регистратор = НЕОПРЕДЕЛЕНО
        ТОГДА NULL
    ИНАЧЕ Регистратор
КОНЕЦ

В конце я еще дополнил текст запроса описанием характеристик

 
 Характеристики беру из заранее заготовленного шаблона

Выводы

Когда в одном отчете на СКД необходимо корректно показать начальные, конечные остатки нескольких разделов учета следует выполнить следующее:

  1. В наборе данных запрос используем таблицу ОстаткиИОбороты 
  2. В запросе для каждого раздела учета создаем поле "Раздел". Для каждого запроса объединения, пишем туда уникальное значение. Я так и пишу текстом, например "1. Товары на складах", "2. Партии товаров на складах"
  3. В запросе выбираем все нужные поля, в т.ч. поле "Раздел
  4. В СКД настраиваем роли для полей остатков(это СКД сделает сама) 
  5. Очень важный момент! В СКД для поля "Раздел" ставим роль "Измерение" и галку "Обязательное

В этом случае, при расчете итогов СКД всегда будет считать, что начальный и конечный остаток различных разделов учета у вас лежат в разных плоскостях(измерениях) и будет рассчитывать его корректно

89

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. Сурикат 203 18.11.17 11:55 Сейчас в теме
Как альтернатива предлагаемого решения - наборы данных
3. echo77 1079 19.11.17 12:39 Сейчас в теме
(1) Я тоже в один момент подумал, что объединив два набора данных можно получить правильные итоги сразу, но, поскольку, роли полей настраиваются уже для Объединения, а не для отдельных наборов данных в него входящих - получим тоже самое
Прикрепленные файлы:
4. Сурикат 203 19.11.17 12:55 Сейчас в теме
(3)
я Объединения, а не для отдельных наборов данных в него входящих - получим тоже самое


Просто такую же проблему у меня получилось решить именно объединением наборов... Причем в наборах поля ресурсов не пересекались.
Но может ситуация была немного другая =)
2. Armando 1387 18.11.17 22:47 Сейчас в теме
На ИТС описан алгорит получения остатка. В виде кода, т.к. ИС съедает отступы

Полем остатка с точки зрения макета компоновки данных является то, у которого в роли проставлен признак Остаток.

10.8.1. Расчет итогов по полям остатка
Если в макете компоновки данных в некотором наборе данных присутствует поле начального остатка, то в наборе данных также должно присутствовать соответствующее ему поле конечного остатка, и наоборот.

Все поля-периоды, описанные в наборе данных, должны иметь непрерывную нумерацию, начинающуюся с единицы.

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

При расчете итогов по полям-остаткам используется следующий алгоритм:

    ● если требуется осуществить расчет итога поля остатка для группировки по полю-периоду:

        ● если по всем полям-периодам уже была осуществлена группировка:

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

                ● получается запись, ближайшая к текущему периоду;

                ● если полученная запись была на текущий период, то из данной записи будут получаться начальные и конечные остатки;

                ● иначе, если полученная запись имеет предыдущий период, конечный остаток записи будет использован как начальный и конечный остаток;

                ● иначе начальный остаток полученной записи будет использоваться как начальный и конечный остаток;

    ● иначе (группировка еще не произведена по всем полям-периодам):

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

            ● получаются первая и последние записи, у которых поля использованных периодов равны текущему периоду;

            ● если записи найдены, то первая запись будет использоваться как начальный остаток, последняя – как конечный;

            ● если записи не найдены, то получается ближайшая запись и ее остатки используются как начальные остатки и конченые остатки в зависимости от того, предшествует ли найденная запись текущему периоду;

    ● иначе (не группировка по полю-периоду):

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


https://its.1c.ru/db/v8310doc#bookmark:dev:TI000000628
d4rkmesa; AlexKo; Сурикат; echo77; +4 Ответить
5. logarifm 1041 22.11.17 00:25 Сейчас в теме
Во-первых чтобы СКД корректно рассчитывала остаток надо обязательно в ресурсах указывать поля Нач.Кон остатки
6. logarifm 1041 22.11.17 00:26 Сейчас в теме
Прекрасно делается через Набор данных Объединение только там есть интересный момент следует учесть Значения разных ресурсов регистров под разныими именами!
7. logarifm 1041 22.11.17 00:53 Сейчас в теме
А вот это диво-дивное и чудо чудное решается как с помощью Набора данных Объединение так и с помощью просто Объеденить в запросе. Но с одной особенностью, что роли необходимо самому указать и проверить для Измерений чтобы были измерениями, а для остатков остатками. Но можно упороться на одну интересную ошибку особенно если использовали к примеру одно поле КонОст и остатка и партии во тут получим ошибку.

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

Оговорюсь только , что это делалось для конфигурашки на обычных формах 10..х под CRM.
Прикрепленные файлы:
ПартииТоваровНаСкладахСУчетомРезерва.erf
Team leader; +1 Ответить
8. echo77 1079 23.11.17 18:55 Сейчас в теме
(7) Все хорошо, пока не добавить группировку по регистратору.
При добавлении группировки - остаток по партиям для Номенклатуры и для Склада - 0
Эти грабли я и описал в статье, и как их поборол

p.s. В отчете, что вы скинули, нет никакого смысла делать объединение наборов, т.к. вы ничего не объединяете. И не совсем понятно, почему так сложно рассчитываются ресурсы
Прикрепленные файлы:
24. Team leader 7 02.01.19 17:37 Сейчас в теме
9. alexz69 06.12.17 09:01 Сейчас в теме
Спасибо большое, за вашу статью. Такая же проблема была, только я использовал три регистра в самописной конфигурации. Пришел к выводу, что при добавлении третьего регистра плывет остаток по конечному остатку по измерениям. Хотя по регистратору всё нормально. Проверял все роли, делал и в одном запросе и в объединении - ничего не помогало. Благодаря добавлению раздела всё стало на свои места. Нутром чувствовал, что СКД путает. Очень выручили )).
10. mitia.mackarevich 26 01.03.18 10:17 Сейчас в теме
Для остатков по регистратору вы использовали вспомогательное поле период секунда?
11. echo77 1079 01.03.18 10:42 Сейчас в теме
(10) Да, псевдоним у поля - Период
12. mitia.mackarevich 26 01.03.18 10:58 Сейчас в теме
(11)Тогда проблем с остатками по регистратору быть не должно, а если вы искусственно добавляете разрез (новое измерение) в набор, то это вроде как правило, именно правило а не фича какая то, что его нужно отметить измерением. Разработка сложных отчетов книга есть у Хрусталевой. Во второй редакции это должно быть описано.
13. rozer 233 01.03.18 12:23 Сейчас в теме
(12) да на итс уже как 100 лет есть это https://its.1c.ru/db/metod8dev/content/3093/hdoc - если регистратор то надо секунду добавлять и роли полей поставить правильно
14. echo77 1079 01.03.18 14:26 Сейчас в теме
(12)
если вы искусственно добавляете разрез (новое измерение) в набор, то это вроде как правило, именно правило а не фича какая то, что его нужно отметить измерением

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

Ничего сверхестественного, просто тонкость, которую нужно понимать
Shrayky2; mitia.mackarevich; +2 Ответить
15. alanchik 21.05.18 14:47 Сейчас в теме
Спасибо автору!!! Столкнулся я с проблемой этих остатков, когда объединял два регистра накопления, день бился не добился результата, пока не наткнулся на эту статью. Интуитивно было понятно, что надо что-то делать с разделами учета, потому что по-отдельности запросы считали корректно, а при объединении нет, но как сочинить сие действо мозгов не хватило)))
16. Noveng 16.10.18 12:02 Сейчас в теме
У меня несколько иная задача(. есть начальный остаток по регистру товары на складах и приход по нему материала. Но расход высчитывается как нормативный. Берется перемещаема продукция. по ней ищется спецификация, выбирается материал и рассчитывается нормативный расход. Общего из двух запросов получается только склад и номенклатура. А вот конечный остаток вычисляется как начальный остаток +приход-нормативный расход. Не получается подружить конечный остаток ни с одним периодом из регистра. Группировка склад и номенклатура - всё нормально, но как только добавляешь регистратор, день...остатки разлетаются. Искусственное измерение типа - раздела учета не помогает....
17. echo77 1079 16.10.18 19:16 Сейчас в теме
(16) И не поможет. Вам в итоге нужно получить выборку вида:
Регистратор НачальныйОстаток, Приход, Расход, КонечныйОстаток

В одной строке выборки должен присутствовать начальный и конечный остаток.
18. rom-x 152 28.11.18 14:31 Сейчас в теме
Почему-то если добавляю поле Раздел, в поля группировки к Регистратору, выходит ошибка: Совместная группировка по периодам с другими выражениями запрещена, убираю Роль период у регистратора и периода - конечный остаток не правильный. Если не добавлять раздел в поля группировки и оставить Роль период как есть, все работает.
19. echo77 1079 28.11.18 15:07 Сейчас в теме
(18) И не нужно группировать регистратор с каким-то еще полем - посмотрите скриншот с настройкой структуры.
20. rom-x 152 28.11.18 15:56 Сейчас в теме
(19) Я хотел сделать также, как на картинке перед заголовком Немного красоты.
21. rom-x 152 28.11.18 18:46 Сейчас в теме
22. echo77 1079 29.11.18 07:43 Сейчас в теме
(21) Это не группировка Регистратор, Раздел. Это детальные записи, в которых выведены эти два поля.
25. German_Tagil 6 07.01.19 00:29 Сейчас в теме
Запомнить - с чем то подобным сталкивался по поводу детальных записей
в консоли все нормально работало-
решил перенести в отчет
часа два ковырялся пока добился нужного результата
теперь немного понятно
Оставьте свое сообщение