Расчет заработной платы на Платформе 1С 8: можно ли обойтись без реквизита КатегорияРасчета?
Все, кто работает в 1С 8 с расчетными механизмами, знают, что такое План видов расчета (ПВР), а также знают, каким образом изначально организуется порядок следования расчета отдельных начислений и удержаний в соответствии с "глубиной" их зависимости по базе.
Изначально, с самых первых версий ЗУП, в объекты конфигурации План видов расчета вводится реквизит КатегорияРасчета, значение которого пользователь должен задавать в соответствии с определенным "уровнем глубины" базовой зависимости каждого вида расчета (ВР). Например, ВР Оклад по дням, Оклад по часам, Оплата сверхурочных часов - не зависят по базе от других ВР, поэтому им пользователь назначает категорию расчета Первичное. Виды расчета Месячная премия и Квартальная премия - зависят по базе только от "первичных" ВР, поэтому им назначается категория расчета Зависимое первого уровня. Виды расчета Районный коэффициент и Северная надбавка зависят по базе как от "первичных" ВР, так и от "зависимых первого уровня" - следовательно, им назначается категория Зависимое второго уровня - и т.п.
Ручное назначение категории расчета чревато ошибками и неприятностями для пользователя. Если категория расчета установлена "меньшая", чем требуется, это приведет к неправильному значению суммы базы и ошибке при расчетах. А если такой вид расчета входит в базу других видов расчета, а те, в свою очередь, третьих, и т.д., то последствия всего лишь одной ошибки назначения категории расчета будут носить лавинообразный характер...
Современная версия ЗУП, правда, отслеживает ситуацию, когда в состав базы некоторого ВР вводится такой, категория расчета которого имеет больший либо равный уровень - в этом случае программа предлагает пользователю "повысить" категорию расчета данного ВР. Например, если в состав базы ВР Месячная премия (категория расчета Зависимое первого уровня) ввести вид расчета с такой же категорией, то будет предложено повысить категорию Месячной премии до Зависимое второго уровня. Однако для тех видов расчета, в базу которых входит Месячная премия, категория расчета не изменится, и пользователю все равно надо будет изменить все категории вручную, что по-прежнему чревато серьезными ошибками.
Таким образом, в общем случае неправильно установленное значение категории расчета влечет за собой длинный и широкий "хвост" ошибок расчета для всей информационной базы ЗУП. А учитывая, что состав базовых ВР у отдельных видов расчета может достигать нескольких десятков, а также то, что "глубина зависимости" по базе у некоторых созданных пользователем ВР может достигать четвертого и даже пятого уровня, ошибка в значении категории расчета может грозить срывом расчетного регламента у всего предприятия - и чем предприятие крупнее, тем последствия такого срыва значительнее.
Автор уже третий год ведет учебные занятия по курсу "Решение расчетных задач на Платформе 1С 8", и практически на каждом потоке находятся учащиеся, задающие один и тот же резонный вопрос: А зачем вообще нужен реквизит КатегорияРасчета, если структура ("дерево") базовой зависимости потенциально определяется из содержания табличных частей БазовыеВидыРасчета всех ПВР, следовательно, категория расчета в принципе может быть получена автоматически, расчетным путем?
В предлагаемой статье сделана попытка дать пример реализации такого алгоритма автоматического определения "категории расчета" каждого ВР перед началом расчетов.
Довольно широко известен алгоритм, который позволяет получить "дерево базовой зависимости" для видов расчета всех ПВР ЗУП примерно такого вида (приводится фрагмент для ВР Районный коэффициент):
Вид расчета |
План видов расчета |
Районный коэффициент |
Основные начисления организаций |
Доплата за вечерние часы |
Основные начисления организаций |
Доплата за ночные часы |
Основные начисления организаций |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
Квартальная премия |
Дополнительные начисления организаций |
Месячная премия |
Дополнительные начисления организаций |
Доплата за вечерние часы |
Основные начисления организаций |
Доплата за ночные часы |
Основные начисления организаций |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
Оклад по дням |
Основные начисления организаций |
Оклад по часам |
Основные начисления организаций |
Оплата по дневному тарифу |
Основные начисления организаций |
Оплата по производственным нарядам |
Основные начисления организаций |
Оплата по часовому тарифу |
Основные начисления организаций |
Оплата праздничных и выходных дней |
Основные начисления организаций |
Оплата сверхурочных часов |
Основные начисления организаций |
Оклад по дням |
Основные начисления организаций |
Оклад по часам |
Основные начисления организаций |
Оплата по дневному тарифу |
Основные начисления организаций |
Оплата по производственным нарядам |
Основные начисления организаций |
Оплата по часовому тарифу |
Основные начисления организаций |
Оплата праздничных и выходных дней |
Основные начисления организаций |
Оплата сверхурочных часов |
Основные начисления организаций |
По итогам работы за год |
Дополнительные начисления организаций |
Доплата за вечерние часы |
Основные начисления организаций |
Доплата за ночные часы |
Основные начисления организаций |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
Оклад по дням |
Основные начисления организаций |
Оклад по часам |
Основные начисления организаций |
Оплата по дневному тарифу |
Основные начисления организаций |
Оплата по производственным нарядам |
Основные начисления организаций |
Оплата по часовому тарифу |
Основные начисления организаций |
Оплата праздничных и выходных дней |
Основные начисления организаций |
Оплата сверхурочных часов |
Основные начисления организаций |
Т.е. в дереве состав базы каждого ВР представляются дочерними ветвями элемента дерева, представляющего данный ВР. Таким образом, мы имеем полную картину базовой зависимости для всех ВР информационной базы ЗУП.
Модифицируем дерево базовой зависимости, программно проставив напротив каждого ВР номер уровня "глубины", который этот элемент занимает в дереве (приведен фрагмент; см. прилагаемый файл Глубина.mxl):
Вид расчета |
План видов расчета |
Глубина |
Районный коэффициент |
Основные начисления организаций |
0 |
Доплата за вечерние часы |
Основные начисления организаций |
1 |
Доплата за ночные часы |
Основные начисления организаций |
1 |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
1 |
Квартальная премия |
Дополнительные начисления организаций |
1 |
Доплата за вечерние часы |
Основные начисления организаций |
2 |
Доплата за ночные часы |
Основные начисления организаций |
2 |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
2 |
Оклад по дням |
Основные начисления организаций |
2 |
Оклад по часам |
Основные начисления организаций |
2 |
Оплата по дневному тарифу |
Основные начисления организаций |
2 |
Оплата по производственным нарядам |
Основные начисления организаций |
2 |
Оплата по часовому тарифу |
Основные начисления организаций |
2 |
Оплата праздничных и выходных дней |
Основные начисления организаций |
2 |
Оплата сверхурочных часов |
Основные начисления организаций |
2 |
Месячная премия |
Дополнительные начисления организаций |
1 |
Доплата за вечерние часы |
Основные начисления организаций |
2 |
Доплата за ночные часы |
Основные начисления организаций |
2 |
Доплата за работу в праздники и выходные |
Основные начисления организаций |
2 |
Оклад по дням |
Основные начисления организаций |
2 |
Оклад по часам |
Основные начисления организаций |
2 |
Оплата по дневному тарифу |
Основные начисления организаций |
2 |
Оплата по производственным нарядам |
Основные начисления организаций |
2 |
Оплата по часовому тарифу |
Основные начисления организаций |
2 |
Оплата праздничных и выходных дней |
Основные начисления организаций |
2 |
Оплата сверхурочных часов |
Основные начисления организаций |
2 |
Оклад по дням |
Основные начисления организаций |
1 |
Оклад по часам |
Основные начисления организаций |
1 |
Оплата по дневному тарифу |
Основные начисления организаций |
1 |
Оплата по производственным нарядам |
Основные начисления организаций |
1 |
Оплата по часовому тарифу |
Основные начисления организаций |
1 |
Оплата праздничных и выходных дней |
Основные начисления организаций |
1 |
Оплата сверхурочных часов |
Основные начисления организаций |
1 |
По итогам работы за год |
Дополнительные начисления организаций |
1 |
Мы видим, что в таком дереве одни и те же виды расчета имеют разные уровни "глубины": например, вид расчета Оклад по дням в одной строчке имеет уровень 1, поскольку он входит в базу ВР Районный коэффициент, в других строчках он имеет уровень 2, поскольку входит также в базу ВР Квартальная премия и Месячная премия, которые, в свою очередь, являются базовыми для ВР Районный коэффициент.
Вопрос: что является мерой "категории расчета" для каждого ВР? Ответ будет такой: мерой категории расчета, а точнее, мерой очередности расчета каждого ВР будет максимальное значение уровня глубины его расположения в этом дереве. Чем "глубже" мы находим данный ВР в этом дереве, тем раньше мы его должны рассчитать, чтобы получить правильный состав базы для тех ВР, которые от него зависят. И максимальное значение уровня для данного ВР в этом дереве можно рассматривать как приоритет порядка расчета этого ВР при расчете всего документа.
Из этого следует, что, получив максимальное значение уровня каждого ВР в этом дереве, сгруппировав ВР по полученным максимумам и отсортировав по ним в убывающем порядке, мы получим дерево приоритетов расчета:
Приоритет расчета |
Вид расчета |
3 |
|
3 |
Доплата за вечерние часы |
3 |
Доплата за ночные часы |
3 |
Доплата за работу в праздники и выходные |
3 |
Оклад по дням |
3 |
Оклад по часам |
3 |
Оплата по дневному тарифу |
3 |
Оплата по производственным нарядам |
3 |
Оплата по часовому тарифу |
3 |
Оплата праздничных и выходных дней |
3 |
Оплата сверхурочных часов |
2 |
|
2 |
Квартальная премия |
2 |
Месячная премия |
2 |
По итогам работы за год |
1 |
|
1 |
БЛ по травме в быту (не оплачивается) |
1 |
Дивиденды акционеров |
1 |
Дивиденды работников |
1 |
Доплата до среднего заработка |
1 |
Компенсация отпуска по календарным дням |
1 |
Компенсация отпуска по шестидневке |
1 |
Компенсация отпуска при увольнении по календарным дням |
1 |
Компенсация отпуска при увольнении по шестидневке |
1 |
Оплата авторских договоров |
1 |
Оплата БЛ по травме на производстве |
1 |
Оплата больничных листов |
1 |
Оплата дополнительных выходных дней по уходу за детьми - инвалидами |
1 |
Оплата лицензионных договоров |
1 |
Оплата отпуска по календарным дням |
1 |
Оплата отпуска по шестидневке |
1 |
Оплата по договорам подряда |
1 |
Оплата по среднему заработку |
1 |
Оплата простоя от оклада по дням |
1 |
Оплата простоя от оклада по часам |
1 |
Оплата простоя по дневному тарифу |
1 |
Оплата простоя по часовому тарифу |
1 |
Простой по вине работодателя |
1 |
Районный коэффициент |
1 |
Северная надбавка |
0 |
|
0 |
Удержание по исп. листу процентом |
Таким образом, приоритет являет собой величину, "дополнительную" по отношению к категории расчета: чем "выше" категория расчета у ВР, тем ниже его приоритет расчета.
Выбирая из него виды расчета в обратном порядке следования их приоритетов, можно организовать расчет в правильной последовательности согласно "глубине" зависимости по базе, что делает реквизит КатегорияРасчета принципиально не нужным.
Изложенный алгоритм реализован в учебной каркасной базе. Файл выгрузки загружается в пустую базу версии 1С 8.2; конфигурация работает в обычном режиме. Исходная конфигурация (с использованием для расчетов реквизитов КатегорияРасчета в Планах видов расчета) находится в файле ИсходнаяКонфигурация.dt, реализация описанного алгоритма расчета без реквизита КатегорияРасчета - в файле РасчетБезКатегорииРасчета.dt.
Демонстрация происходит при помощи документа Начисление зарплаты (расчет в форме): для автозаполнения документа нужно нажать кнопку Заполнить, для производства расчета начислений и удержаний - нажать кнопку Рассчитать. Можно убедиться, что результаты расчета в исходном варианте конфигурации и в варианте "без реквизита КатегорияРасчета" идентичны.
Расчетные алгоритмы находятся в общем модуле ПроведениеРасчетов.
При желании можно доработать конфигурацию так, что пользователь сможет устанавливать приоритет расчета "принудительно". В этом случае, если приоритет установлен, то для расчета суммы начисления берется установленное пользователем значение приоритета, если не установлен (равен 0), то берется значение приоритета, рассчитанное при помощи вышеописанного алгоритма. Этот вариант находится в файле РасчетБезКатегорииРасчетаСНазначениемПриоритета.dt, там в Планы видов расчета добавлен числовой реквизит ПриоритетРасчета, значение по умолчанию которого равно 0 - т.е. приоритет рассчитывается программно.
В заключение - несколько замечаний.
1. Цель алгоритма такова, чтобы рассчитанный приоритет ВР был просто меньше всех приоритетов его базовых начислений, а не в точности на единицу меньше. Поэтому не стоит удивляться, если вид расчета, в базу которого входит ВР с приоритетом 3, получает приоритет 1, а не 2 - на правильность расчета по базе это не повлияет.
2. Согласно алгоритму "невовлеченные" виды расчета - т.е. такие, которые сами не имеют зависимости по базе и от них также не зависит по базе ни один ВР - получают наинизший приоритет, т.е. рассчитываются в последнюю очередь. (В ЗУП "невовлеченным" ВР присваивается категория Первичные - т.е. они рассчитываются в первую очередь). Это тоже не влияет на правильность расчета, поскольку для таких ВР очередность расчета значения вообще не имеет.
3. Практическое воплощение идеи в ЗУП потребует, конечно, решения множества попутных задач, о сложности которых сейчас можно только гадать. Предлагаемая статья не излагает практический план, а представляет только идею альтернативного способа организации последовательности расчетов.