Помилка розрахункузалишків у СКД та її програмне виправлення на прикладі Універсального звіту
Не знаю, чи багатьом вже довелося зіткнутися з помилкою розрахунку початкових та кінцевих залишків угруповань. Особисто мені "пощастило", до того ж неодноразово. Причина, як мені вдалося з'ясувати, криється в невірних налаштуваннях полів даних СКД, важливості яких багато програмістів-початківців (та й не дуже) поки до кінця не усвідомлюють.
Коли набір даних СКД створюється автоматично з урахуванням запиту, проблеми зазвичай виникає, т.к. платформа сама коректно заповнює параметри полів, виходячи з тексту запиту. Але бувають ситуації, коли параметри полів даних автоматично не заповнюються (наприклад, ви використовуєте зовнішнє джерело даних), а вихідні дані при цьому містять рухи з залишками та оборотами.
Якщо ви раніше не стикалися з цією проблемою, то для кращого розуміння її суті пропоную відтворити її за допомогою універсального звіту (за метаданими). Запускаємо звіт, вибираємо будь-який непустий регістр накопичення з залишками та оборотами, включаємо в налаштуваннях звіту (скрин1) прапорець "Детальні записи", вказуємо якісь угруповання і додаємо до складу полів, що виводяться Реєстратор. Вуаля - початкові та кінцеві залишки підсумовуються по кожному угрупованню. Виходить звіт із абсолютно некоректними цифрами, який показувати користувачам неможливо.
Для вирішення такої проблеми необхідно коректно заповнити налаштування полів набору даних СКД - зокрема поле "Роль", яке має ключове значення.
РІШЕННЯ інтерактивне (не підходить для Універсального звіту):
Відкриваємо схему компонування даних вашого звіту та дивимось у налаштування полів набору даних.
Для полів початкових і кінцевих залишків по кожному ресурсу необхідно заповнити роль: вибрати групу ролей"Залишок" та в ній вказати значення "Початковий залишок" або "Кон. залишок" відповідно. Так (скрин2) це робиться в конструкторі СКД.
Аналогічно необхідно проставити роль "Вимірювання" для всіх вимірювань вашого набору даних.
Але цього замало коректної роботи звітів. Для правильного розрахунку полів залишків необхідно знати період кожного руху, щоб розставити їх у правильному хронологічному порядку. Якщо у вашому джерелі даних поля періоду немає, необхідно його туди додати. Якщо поле періоду в наборі даних вже є, йому необхідно вказати роль "Період" і відповідний номер періоду (докладніше про нумерацію періодів можна прочитати в довідці).
Такі налаштування полів даних СКД у більшості випадків дозволяють досягти коректного розрахунку залишків за угрупованнями, коли з налаштуваннями за замовчуванням вони розраховуються некоректно.
Рішення програмне (на прикладі Універсального звіту з метаданим):
Тепер розглянемо, як виправити цю ж помилку в Універсальному звіті метаданих. Універсальний звіт відрізняється від більшості інших звітів тим, що схема компонування даних там генерується повністю програмно, тому настроювати ролі для полів даних СКД також доводиться програмно.
Для ролей початкових і кінцевих залишків по кожному з ресурсів найпростіше не винаходити велосипед (все вже написано до нас) і скористатися типовою процедурою ЗаповнитиПолеНаборуДанихЗалишок() із загального модуля ТиповіЗвіти. Туди передаєте як параметри поле набору даних та ім'я ресурсу, і в результаті в наборі даних створюється поле залишку з коректно заповненою роллю.
Аналогічно при створенні полів набору даних для вимірювань необхідно проставити їм роль "Вимірювання". Кодбуде приблизно наступним:
Описані вище маніпуляції з полями ресурсів та вимірювань необхідні, але не достатні для вирішення проблеми – основною бідою універсального звіту є відсутність нумерації періодів. Поля періоду є в наборі даних, але їх ролі не заповнені.
Поля періоду до звіту додаються процедурою загального модуля ТиповіЗвіти.ДодатиПоляПеріодуНабірДаних(), виклик якої відбувається з процедури модуля об'єкта ДодатиПоляНаборуДаних(). На жаль, номери періодів ця процедура не проставляє.
Крім того, до звіту ніде програмно не додаються поля "Номер рядка" та "Реєстратор". Мені це здалося дивним, т.к. у підсумковому наборі даних вони є.
Як з'ясувалося, поля "Номер рядка" та "Реєстратор" (Recorder) додає сама платформа автоматично при ініціалізації компонувальника налаштувань. Причому платформа не заповнює ролі для полів, що створюються нею, а програмно їх заповнити не виходить, що створює проблеми при подальшій роботі з ними. Але якщо ці поля створити "вручну" та програмно прописати їм правильні ролі, то платформа вже не намагається створювати їх заново.
Нижче я пропоную рецепт, який допоміг мені майже повністю вирішити цю проблему платформи та Універсального звіту з метаданих:
Ось цей фрагмент коду модуля об'єкта:
Мені вдалося знайти одне обмеження, пов'язане із цим рішенням. Для коректного розрахунку поч. та кін. залишків необхідно, щоб під час використання у звіті будь-яких реквізитів документа-реєстратора сам реєстратор також було обрано. В іншому універсальний звіт після таких доробок більше не викликає алергії у користувачів.
Тим не менш, я знайшов на Місті посилання на неї і рекомендую ознайомитись, бо корисно:

