Многие организации подходят к теме расчета премий со своими извратами особенностями. В самом простом варианте - премия начисляется в размере некоторого процента от суммы перевыполнения плана по выручке. Но этот вариант неинтересен, так как в популярных конфигурациях оперативного учета ("1С:Розница", "1С:Управление торговлей") можно получить отчет по выручке в разрезе сотрудников, а далее можно использовать пользовательские поля СКД, либо немного "подпилить" отчет.
В нашем случае требования были куда серьезнее: премия должна рассчитываться с использованием некоторых показателей по введенной в пользовательском режиме формуле. Формула должна быть написана с использованием встроенного языка 1С. Некоторые показатели расчета были уже сформированы заказчиком, но было решено реализовать подсистему премирования с учетом того, чтобы можно было добавлять показатели расчета премии в пользовательском режиме
Разработка подсистемы премирования производилась на основе конфигурации "1С:Комплексная автоматизация 2.4" с использованием расширения. Часть объектов для хранения НСИ была продублирована и изменена, дабы не мешать типовому обмену с ЗУП, другая часть была создана с 0. Пользователям должен быть доступен отчет, в котором они смогут увидеть не только сумму премии, но и формулу расчета, а также все показатели, которые влияют на премию. Детально всю архитектуру НСИ разбирать не будем, а остановимся лишь на принципиальных моментах расчета премий.
Основа для расчета премии - это показатели. Для расчета показателей премии было принято решение использовать схемы компоновки данных, так как данный механизм предоставляет удобные средства для получения произвольных данных и последующего вывода/манипулирования.
Для хранения информации о показателях был добавлен отдельный иерархический справочник ВариантыСхемКомпоновкиДанных. Помимо информации о схеме компоновки данных данный справочник может хранить и информацию о параметрах, которые передаются в СКД. Внешний вид элемента справочника представлен ниже:
- Входит в группу - ссылка на родительский элемент
- Наименование - пользовательское наименование показателя расчета
- Имя схемы - содержит список имен макетов данного справочника, заданных в конфигураторе + "Произвольная" для схем, созданных вручную в режиме толстого клиента
- Использовать для расчета премий - данный справочник планируется использовать в других целях, поэтому данный реквизит позволит узнать назначение элемента справочника
- Агрегатная функция - агрегатная функция (Сумма, Количество, Среднее и т.д.), которая используется для данного показателя в отчете по премиям (рассмотрим подробнее ниже)
- Имя параметра - имя параметра из схемы
- Значение параметра - данное значение будет передано при исполнении схемы, если не стоит признак Уточнять интерактивно
- Уточнять интерактивно - данный признак означает, что значение параметра будет указано в самой формуле
Немного подробнее остановимся на параметрах схем компоновки данных. Во-первых, при расчете премии не все параметры должны быть видны в данном справочнике, например, логично, что премия у нас рассчитывается за некоторый стандартный период (обычно за месяц); создавать отдельный показатель для каждого сотрудника/подразделения, задавая его в качестве параметра - тоже дело неблагодарное. Поэтому был определен список постоянных параметров, которые всегда передаются в схему при расчете премии и, соответственно, должны иметь идентичные наименования во всех схемах:
- НачалоПериода - начало периода расчета премии (первое число месяца или дата начала работы сотрудника в должности)
- КонецПериода - конец периода расчета премии (переданная дата или последний день месяца или последний день работы сотрудника в должности)
- Сотрудник - ссылка на справочник Пользователи
- Должность -отдельный справочник, добавлен в расширении
- Подразделение - отдельный справочник, добавлен в расширении
- Правило премирования - ссылка на справочник с формулой расчета премии
- Отдел - отдельный справочник, добавлен в расширении
- Штатное расписание - отдельный справочник, добавлен в расширении
Во-вторых, некоторые параметры могут быть заданы непосредственно в редакторе СКД, а некоторые, например, параметры виртуальных таблиц, использоваться не будут и, соответственно, отображаться они не должны. Поэтому в справочнике ВариантыСхемКомпоновкиДанных было принято решение отображать только те параметры, у которых не стоит галка Ограничение доступности
И, наконец, еще одна особенность - интерактивные параметры. Данный функционал позволит сократить количество показателей расчета за счет того, что параметры СКД можно будет задавать непосредственно в формуле. Например, показатель ВыручкаПродавцаПоСегменту: в зависимости от параметра Сегмент будет давать разные показатели; можно создать для каждого сегмента номенклатуры отдельный показатель, а можно сегмент указывать в формуле. Но здесь есть серьезные ограничения: формула - это строка, поэтому значение интерактивного параметра в формуле тоже должно быть строковым и понятно любому сотруднику, которые будет формировать отчет для просмотра своей премии. Следует отметить, что на данной возможности настаивал сам заказчик и был проинформирован о последствиях. После недолгих согласований пришли к следующим договоренностям:
- Значения интерактивных параметров в формуле будут отделяться знаком &
- Интерактивными могут быть только параметры следующих типов:
- Строка
- Число
- Дата
- Булево
- СправочникСсылка (поиск выполняется по наименованию)
- ПеречислениеСсылка
Для хранения формулы был также добавлен отдельный справочник ПравилаПремирования.
Помимо непосредственно формулы данный справочник хранит еще и дополнительные показатели, которые должны попасть в отчет по премиям и которые в самой формуле не присутствуют. Например, есть такой показатель как КоэффициентВыполненияПланаПоСегменту, который отобразит в отчете расчитанный коэффициент, но не значение самого плана - в этом случае и придут на помощь дополнительные показатели.
Подошли к самому интересному: как же задается формула и как впоследствии считается по премия с ее использованием. Собственно, сама идея редактора не нова и многие найдут аналогию, например, с редактором формулы для вида цен
Окно редактора разбито на 3 основных части:
- Список справочника ВариантыСхемКомпоновкиДанных (вверху слева)
- Дерево вставок (вверху справа) - позволяет вставить некоторые конструкции встроенного языка, а также обращение к параметрам выбранных схем компоновки данных
- Текст формулы - нижняя часть
Показатели расчета заключены в квадратные скобки и имеют следующую структуру:
[ИмяВариантаСКД&ИмяПараметра1=ЗначениеПараметра1&ИмяПараметра2=ЗначениеПараметра2....&ЗначениеПараметраN=ЗначениеПараметраN]
где
- ИмяВариантаСКД - имя элемента справочника ВариантыСхемКомпоновкиДанных
- ИмяПараметраN - имя параметра, у которого установлен признак Уточнять интерактивно
- ЗначениеПараметраN - значение интерактивного параметра
Добавление показателя происходит по двойному щелчку по элементу справочника вариантов СКД. При наличии интерактивных параметров открывается отдельная форма для уточнения значений интерактивных параметров:
Считается, что все параметры должны быть заданы. Исключение - сегмент номенклатуры: если сегмент не задан, то предполагается, что в показателе отбора по сегменту номенклатуры не должно быть.
Сама премия вычисляется с использованием процедуры БСП ОбщегоНазначения.ВыполнитьВБезопасномРежиме(Формула, Параметры), где
- Формула - текст формулы
- Параметры - структура с ключами:
- Результат - в этот ключ передается результат расчета премии
- ПараметрыВыполнения - Соответствие:
- Ключ - имя предопределенного параметра вариантов СКД
- Значение - значение предопределенного параметра вариантов СКД
Для формулы премии обязательно выполняется проверка наличия строки Параметры.Результат, в которую передается итоговое значение премии. Для дополнительных показателей используется та же форма редактирования, но, в отличие от формулы для премии, к ней не применяется метод Выполнить, а, значит, это может быть просто строка с разными показателями, например:
[Показатель1][Показатель2]...[Показатель3]
Давайте рассмотрим, как же происходит расчет премии по некоторой формуле и доп.показателям.
Формула для премии:
Параметры.Результат = [Выручка продавца по сегменту&Сегмент=ПоВсемСегментам] * 0.05 + [Средний чек по сотруднику] / 100;
Строка дополнительных показателей:
[Планируемая выручка продавца по сегменту&Сегмент=ПоВсемСегментам]
На первом шаге из формулы получаем все операнды (что содержится в квадратных скобках):
- Выручка продавца по сегменту&Сегмент=СегментТест
- Средний чек по сотруднику
Из текстовых содержимых получаем имена элементов справочника ВариантыСхемКомпоновкиДанных:
- Выручка продавца по сегменту
- Средний чек по сотруднику
На выходе получаем соответствие:
- Ключ - текстовое описание показателя (например, Выручка продавца по сегменту&Сегмент=СегментТест)
- Значение - ссылка на справочник ВариантыСхемКомпоновкиДанных
Обходим элементы соответствия из прошлого шага и получаем описания интерактивных показателей. В нашем случае интерактивные параметры только в первом показателе:
Сегмент=СегментТест
Из справочника ВариантыСхемКомпоновкиДанных получаем тип параметра Сегмент - СправочникСсылка.СегментыНоменклатуры и ищем данном справочнике ссылку на элемент справочника с наименованием СегментТест.
Далее объединяем соответствие с предопределенными параметрами с интерактивными и теми, что заданы непосредственно в варианте схем компоновки данных, и, наконец, исполняем схему компоновки данных с подготовленными параметрами.
Например, по показателям получили следующие значения:
- Выручка продавца по сегменту&Сегмент=СегментТест = 950 000
- Средний чек по сотруднику = 17 000
В параметр ЗначенияПоказателей записываем рассчитанные показатели (нужны будут для отчета):
- ЗначенияПоказателей .Вставить(Выручка продавца по сегменту&Сегмент=СегментТест, 950000)
- ЗначенияПоказателей .Вставить(Средний чек по сотруднику, 17000)
И, наконец, в формуле производим замену операндов на рассчитанные значения:
- [Выручка продавца по сегменту&Сегмент=СегментТест] --> 950000
- [Средний чек по сотруднику] --> 17000
В итоге формула приобретает вид:
Параметры.Результат = 950000 * 0.05 + 17000 / 100;
Собственно, после вычисления показателей нам остается только выполнить процедуру
ОбщегоНазначения.ВыполнитьВБезопасномРежиме(Формула, Параметры);
где
- Формула - Параметры.Результат = 950000 * 0.05 + 17000 / 100;
- Параметры - соответствие с предопределенными параметрами расчета премии (период расчета, сотрудник и т.д.)
Действуем по аналогии с формулой:
- Получаем список из текстовых описаний показателей
- Получаем ссылки на элементы справочника ВариантыСхемКомпоновкиДанных
- Собираем параметры
- Исполняем схему
- Дополняем соответствие со значениями показателей
Конечно же, немаловажный объект подсистемы - это отчет. Отчет позволит руководству принять решение об изменении некоторых параметров правил премирования, а самим работникам посмотреть итоги их работы.
Поскольку расчет премии должен был быть максимально прозрачным для сотрудников и имел возможность для гибкой настройки, то самым оптимальным решением было написать его также с использованием СКД. Ситуацию, конечно, осложнял тот факт, что заранее неизвестно, сколько и каких показателей будет использовано в формулах с настроенным отбором. Поэтому в качестве набора данных используется таблица значений. Конечно же, некоторое количество колонок нам известно, поэтому их добавляем "ручками" на этапе создания схемы компоновки данных для отчета:
Помимо прочего, чтобы каждый раз не исполнять отчет по всем сотрудникам, а потом накладывать отборы отчета, было принято решение "вытаскивать" программно отборы и накладывать их на этапе подготовки таблицы сотрудников для расчета премий. Это было сделано для следующих полей:
- Сотрудник
- Должность
- Подразделение
- ПравилоПремирования
Таким образом, при формировании отчета:
- Подготавливается фиксированная таблица по сотрудникам (в качестве колонок фигурируют предопределенные параметры, собственно формула, строка дополнительных показателей и колонка со значением премии)
- По каждой строке вычисляется показатели и премия; для каждого показателя добавляется отдельная колонка в таблицу сотрудников и заполняется рассчитанным значением
- Для каждой добавленной колонки в отчет добавляется соответствующее поле
- Каждое поле показателя добавляется также в ресурсы с той агрегатной функцией, которая задана в справочнике ВариантыСхемКомпоновкиДанных
- У отчета снимается признак стандартной обработки и вывод производится полностью программно
В итоге получается примерно такая портянка))
В силу своих особенностей (а может где и в силу подхода к реализации) ожидали достаточно медленной работы отчета. Для разового расчета премий, по сути, скорость работы была не так уж и важна, так как он проводится раз в месяц и по факту увольнений. Но в целом производительность оказалась выше ожидаемой: для примера из 22 сотрудников и 8 показателей для каждого отчет формируется около 15 сек.
В итоге мы получили гибкий инструмент для расчета премий, который заменил собой множество листов Excel и позволил сэкономить огромное количество нервов и часов бухгалтерии. Плюсом дали возможность сотрудникам в любой момент посмотреть свою премию без звонка ответственным лицам)