Что такое SAP PaPM? SAP Profitability and Performance Management – это инструмент для расчетов на базе SAP HANA, можно сказать инструмент для создания “считалища”. Типичным примером таких расчетов является дифференциация затрат, когда имеется модель учета затрат, состоящая из сотен, а может и тысяч объектов учета, десятки или сотни тысяч документов на входе и десятки или сотни продуктов на выходе. Задача показать какие элементы затрат или аналитики первичных документов попали в конечный продукт после множества циклов перерасчетов между объектами учета.
![Визуальзация потока затрат в SAP PaPM Визуальзация потока затрат в SAP PaPM](https://habrastorage.org/getpro/habr/upload_files/24d/2bc/e5e/24d2bce5e622ad919e84f239afbe1b98.png)
Решение данной задачи будет нужно налоговикам, для вычисления налоговой стоимости продукта, так как налоговая стоимость первичных затрат отличается от бухгалтерской. Экономисты смогут подробно проанализировать состав затрат на продукт. В отчетности можно исключить внутригрупповые обороты, понимая какие затраты от компаний группы попали в продукт.
Для решения этой задачи нужно протянуть аналитику первичных затрат по всей цепочке перерасчетов. Объем данных в результате расчетов может составлять десятки или сотни миллионов позиций. Стандартный функционал учетной системы этим не занимается, а если и занимается, то с ограничениями и сильным влиянием на производительность. Как быть?
Часто на ERP-проектах помимо транзакционной системы есть еще и аналитическая система и когда появляется задача с выполнением сложных вычислений над большим объемом данных возникает вопрос: “Где считать?”. Если побеждает или проигрывает (тут с какой стороны посмотреть) ERP, то с использованием ABAP создают сложные программы для расчетов, которые очень нестабильно работают и с которыми постоянно возникают проблемы. Если используется BW, то примерно такая же ситуация, в Expert Routine вставляется код для расчетов и это плохо работает. Я несколько раз слышал: “Ну вот, сломали BW, из хранилища сделали считалище…”. Понятно, что есть истории успеха (success story) и найдутся счастливые разработчики и пользователи прекрасной системы, которая хорошо работает, но что-то мне такие не попадались (понимаю, это моя проблема).
Возвращаясь к вариантам решения задачи и к теме “считалища”, можно посмотреть на SAP PaPM (SAP Profitability and Performance Management). Это инструмент для выполнения расчетов над бизнес-данными с использованием настраиваемых цепочек функций. Так как под функции генерируются хранимые процедуры БД SAP HANA и вычисления происходят на уровне базы данных, а потоки данных можно распараллелить и пакетировать, обработка большого объема данных происходит достаточно быстро.
PaPM предоставляет возможность быстро создавать модель данных за счет предопределенных типов функций, способен извлекать и агрегировать данные из различных систем и локальной или удаленных баз данных, выполнять различные сложные вычисления над детальными данными и записывать результаты в другие приложения для дальнейшей обработки. PaPM позволяет:
Управлять конфигурациями функций, с помощью которых консультанты (в логике SAP даже бизнес-пользователи) создают подробные модели расчетов и распределений без сложного кодирования.
Обрабатывать данные почти в реальном времени из физических или виртуальных источников как в локальной базе данных, так и через удаленное подключение к другим базам данных (см. SDA) без необходимости физической репликации/сохранения исходных данных.
Обеспечивать полную прозрачность методологии распределения и результатов расчетов вплоть до уровня отдельных позиций.
Запускать модели с гибко определенными параметрами моделирования для анализа “что, если”.
Переносить результаты расчета/распределения обратно в другие приложения – в главную книгу в S/4HANA, в хранилища данных планирования в SAP BPC, в объекты BW4HANA и т.д.
Пример итеративного распределения затрат по базе
Новый функционал лучше изучать на конкретном примере. Для навигации по статьям и понимания как работает PaPM придумал себе пример и реализовал его в своей системе. Ниже дано описание логики процесса расчета и ссылки на статьи, в которых более подробно описываются используемые (и не только используемые) функции. Также можно скачать транспортный запрос в котором сохранена среда с функциями и тестовыми данными, которые я использовал в примере.
![Пример распределения затрат Пример распределения затрат](https://habrastorage.org/getpro/habr/upload_files/773/204/c7c/773204c7c45a9c109dd69da2507c8205.png)
Важные моменты примера:
Часть затрат возвращается на объекты-отправители (например, котельная дала горячую воду и пар ремонтному цеху, а он, помимо прочего, отремонтировал что-то в котельной). То есть имеем итерации распределения затрат.
При распределении нужно учесть, что для конкретных объектов-отправителей, есть набор объектов-получателей. То есть нужно предварительно сформировать наборы объектов-получателей, по которым распределять затраты. В нашем случае объекты-отправители тоже выступают в качестве получателей затрат, но не для всех отравителей действительны все получатели.
Нужно обрабатывать наборы объектов из п. 2, для этого нужен цикл.
Входные данные:
![Входные данные для расчета Входные данные для расчета](https://habrastorage.org/getpro/habr/upload_files/54d/5c4/de3/54d5c4de3c4d0ecdff83456734b0489b.png)
Тут и базы (определяются 38* счетами) и сами затраты для распределения (не 38* счета).
Структура цепочки функций в PaPM
![Перечень функций PaPM, задействованных в расчете Перечень функций PaPM, задействованных в расчете](https://habrastorage.org/getpro/habr/upload_files/844/473/502/844473502f882e9a61cf33edd84e31fc.png)
Контейнер 1 – Необогащенные данные
1. Все входные данные находятся в одном файле на сервере приложения, файл загружается функцией Файловый адаптер.
![Импорт данных из файла Импорт данных из файла](https://habrastorage.org/getpro/habr/upload_files/93a/66c/84c/93a66c84c056a6e0525bad4237779cba.png)
Можно, конечно, положить данные в таблицу сторонней БД и настроить SDA для виртуализации данных и полного отсутствия репликации. Но пока так.
Описание работы функции в статье Файловый адаптер (File Adapter с типом Import).
2. Из загруженных данных нужно:
Выбрать записи затрат (не 38* счета).
Получить список уникальных объектов-отправителей в этих затратах и пронумеровать их. Для объектов-отправителей далее будут подобраны объекты-получатели.
Пронумеровать записи затрат для того, чтобы далее, при распределении в цикле, по номеру цикла выбирать записи затрат и соответствующие затратам наборы объектов-получателей.
2.1. Отфильтровали записи затрат и дополнительно переложили значения объектов затрат в другое поле, так как потом, при формировании пар отправитель-получатель, PaPM запутается в двух полях, которые называются одинаково, но используются по-разному.
![Структура переноса: копирование поля Структура переноса: копирование поля](https://habrastorage.org/getpro/habr/upload_files/fc8/c36/8b7/fc8c368b746daa5403c236bd29b5474b.png)
![Структура переноса: фильтр строк входных данных Структура переноса: фильтр строк входных данных](https://habrastorage.org/getpro/habr/upload_files/90a/f81/7f3/90af817f366920a9e895824dff0a7dcd.png)
Используем функцию Структура переноса. Описание работы функции в статье Структура переноса (Transfer Structure).
2.2. Выбрали уникальные объекты затрат.
![Представление: определение уникальных значений и их нумерация Представление: определение уникальных значений и их нумерация](https://habrastorage.org/getpro/habr/upload_files/e2a/df6/538/e2adf6538387fa435dc2e79f0643a340.png)
Используем функцию Представление для группирования (GROUP BY) и нумерации с помощью ROW_NUMBER(). Описание работы функции в статье Представление (View) в PaPM.
2.3. Пронумеровали записи затрат уникальными номерами, чтобы далее в функции распределения выбирать записи затрат и соответствующие наборы отправитель-получатель.
![Соединение: нумерация входных данных уникальными номерами объектов Соединение: нумерация входных данных уникальными номерами объектов](https://habrastorage.org/getpro/habr/upload_files/ff0/949/186/ff0949186a296e39f5305225e01d87a3.png)
Используем функцию Соединение и два правила, соединенные Left Outer Join.
![Результат нумерации строк входных данных Результат нумерации строк входных данных](https://habrastorage.org/getpro/habr/upload_files/98e/3cb/19a/98e3cb19a6edc18e3208ecdc45e6d7a1.png)
Получили нумерацию затрат уникальными номерами объектов. Результат работы функции сохраняется в Таблице модели. Описание работы функции в статье Соединение (Join) в PaPM.
Контейнер 2 – Обогащение данных
3. Необходимо к объекту учета затрат подобрать объекты-получатели. Во входных данных есть пары отправитель-получатель для баз распределения. На основе этих данных для каждого уникального объекта затрат, используя функцию Соединение и два правила, соединенные Inner Join, получаем набор баз для распределения:
![Соединение: формирование наборов отправитель-получатели Соединение: формирование наборов отправитель-получатели](https://habrastorage.org/getpro/habr/upload_files/cf8/ff1/6ce/cf8ff16cefc065e7d3f103825481738d.png)
![Результат формирования наборов отправитель-получатели Результат формирования наборов отправитель-получатели](https://habrastorage.org/getpro/habr/upload_files/c34/6c7/04e/c346c704e2b351f27f931a96a94dc66d.png)
Описание работы функции в статье Соединение (Join) в PaPM.
Контейнер 3 – Распределение
4. Теперь нужно суммы затрат распределить пропорционально базе для объекта затрат и сохранить первичную аналитику в распределенных данных. Все это нужно сделать в цикле выбирая для каждого повторения по его номеру строку затрат и соответствующий набор баз. Для организации цикла используется функция Представление
![Представление: цикл по строкам затрат во входных данных Представление: цикл по строкам затрат во входных данных](https://habrastorage.org/getpro/habr/upload_files/c32/280/3e0/c322803e0a3d4e13d8e506076d827a9a.png)
которая вызывает функцию Программа записи (это обязательное условие, с другими типами функций это не работает)
![Программа записи: вызов Распределения и Таблицы модели для записи результатов Программа записи: вызов Распределения и Таблицы модели для записи результатов](https://habrastorage.org/getpro/habr/upload_files/cfe/53b/248/cfe53b248ef529f7ac51c8a8eb73f6f7.png)
которая в свою очередь вызывает функцию Аллокация и записывает результат в Таблицу модели:
![Распределение Распределение](https://habrastorage.org/getpro/habr/upload_files/7e5/dac/d2c/7e5dacd2cc190314dd4fdd92ee0e5cd6.png)
Для организации итерации используется смещение, которое объект-получатель, перекладывает в объект-отправитель в распределенных данных
![Распределение: меппинг для организации итеративного распределения Распределение: меппинг для организации итеративного распределения](https://habrastorage.org/getpro/habr/upload_files/287/149/9bd/2871499bdbb5c46c85ef1ca01fc93362.png)
и цикл повторяется. Для того, чтобы это работало только когда было обратное распределение затрат на объекты-отправители, значения объектов-отправителей после смещения сравниваются с оригинальным значениями объектов в затратах (CASE WHEN ZRCNTR_SEND = ZRCNTR_ORIG THEN HSL ELSE 0 END).
Получаем желаемый результат:
![Результат распределения Результат распределения](https://habrastorage.org/getpro/habr/upload_files/98f/ffe/47c/98fffe47c51d6e2fa8fd02394afa59d4.png)
Описание работы функции в статье Распределение (Allocation) в PaPM.
Важно отметить, что PaPM обладает механизмом разделения объема данных по потокам и пакетам. То есть возможно параллельное выполнение расчетов, что значительно сокращает время их выполнения (см. Приложения PaPM: Администрирование и Моделирование).
Контейнер 4 – Проверка
5. Для проверки правильности распределения агрегируем результат по номеру документа, для сравнения с данными на входе. Используем функцию Представление с группировкой и функцией SUM()
![Представление: агригация результата расчета для сверки с входящими данными Представление: агригация результата расчета для сверки с входящими данными](https://habrastorage.org/getpro/habr/upload_files/def/4a3/a16/def4a3a1624b2eef31f69619fb1ee057.png)
![Результат агрегации результатов расчета по номерам документов Результат агрегации результатов расчета по номерам документов](https://habrastorage.org/getpro/habr/upload_files/84a/eea/b54/84aeeab54d17096a634bcd43bd778913.png)
или так, если добавить объект-получатель:
![Результат агрегации результатов расчета по номерам документов и объектам-получателям Результат агрегации результатов расчета по номерам документов и объектам-получателям](https://habrastorage.org/getpro/habr/upload_files/53b/797/e0e/53b797e0e388120cb769a93ce3fa6b83.png)
В качестве заключения
Наверное, в определенных ситуациях, когда алгоритмы расчетов стабильны и из раза в раз выполняется один и тот же код, собственная разработка на SQL будет проще, быстрее и дешевле чем PaPM. Но если требуется именно моделирование, когда алгоритмы расчетов меняются и необходимо гибко управлять логикой расчетов, то без инструмента управления элементами расчетов (хранимыми процедурами), последовательностью их выполнения, организации запусков, контроля хода выполнения и обработки результатов не обойтись. Создавать это самостоятельно - трата сил, времени и денег, в то время как уже есть SAP PaPM.