Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC

This commit is contained in:
CI Publish Bot
2026-11-01 22:54:30 +00:00
commit 26250aa580
2492 changed files with 664277 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Ежегодный оплачиваемый отпуск -->
<record id="rsbu_leave_annual" model="hr.leave.type">
<field name="name">Ежегодный оплачиваемый отпуск</field>
<field name="requires_allocation" eval="False"/>
<field name="request_unit">day</field>
<field name="leave_validation_type">hr</field>
<field name="time_type">leave</field>
<field name="rsbu_leave_kind">vacation</field>
</record>
<!-- Больничный лист -->
<record id="rsbu_leave_sick" model="hr.leave.type">
<field name="name">Больничный лист</field>
<field name="requires_allocation" eval="False"/>
<field name="request_unit">day</field>
<field name="leave_validation_type">hr</field>
<field name="time_type">leave</field>
<field name="rsbu_leave_kind">sick</field>
</record>
<!-- Отпуск без сохранения заработной платы -->
<record id="rsbu_leave_unpaid" model="hr.leave.type">
<field name="name">Отпуск без сохранения зарплаты</field>
<field name="requires_allocation" eval="False"/>
<field name="request_unit">day</field>
<field name="leave_validation_type">hr</field>
<field name="time_type">leave</field>
<field name="unpaid" eval="True"/>
<field name="rsbu_leave_kind">unpaid</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="rsbu_structure_ru" model="hr.payroll.structure">
<field name="name">Зарплата (РФ, РСБУ)</field>
<field name="code">RU</field>
<field name="rule_ids" eval="[(6, 0, [
ref('rsbu_rule_basic'),
ref('rsbu_rule_premium'),
ref('rsbu_rule_vacation'),
ref('rsbu_rule_sick3'),
ref('rsbu_rule_gross'),
ref('rsbu_rule_ndfl'),
ref('rsbu_rule_insurance'),
ref('rsbu_rule_injury'),
ref('rsbu_rule_net'),
])]"/>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="rsbu_cat_basic" model="hr.salary.rule.category">
<field name="name">Оклад</field>
<field name="code">RSBU_BASIC</field>
</record>
<record id="rsbu_cat_alw" model="hr.salary.rule.category">
<field name="name">Надбавки и премии</field>
<field name="code">RSBU_ALW</field>
</record>
<record id="rsbu_cat_gross" model="hr.salary.rule.category">
<field name="name">Начислено (итог)</field>
<field name="code">RSBU_GROSS</field>
</record>
<record id="rsbu_cat_ndfl" model="hr.salary.rule.category">
<field name="name">НДФЛ</field>
<field name="code">RSBU_NDFL</field>
</record>
<record id="rsbu_cat_insurance" model="hr.salary.rule.category">
<field name="name">Страховые взносы (единый тариф)</field>
<field name="code">RSBU_INSURANCE</field>
</record>
<record id="rsbu_cat_injury" model="hr.salary.rule.category">
<field name="name">Взносы на травматизм</field>
<field name="code">RSBU_INJURY</field>
</record>
<record id="rsbu_cat_net" model="hr.salary.rule.category">
<field name="name">К выплате</field>
<field name="code">RSBU_NET</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Правила расчёта — конфигурация модуля, должны обновляться при -u
(без noupdate). Счета РСБУ на правилах проставляет post_init hook. -->
<data>
<!-- Оклад. Базовый вариант — полный оклад контракта.
Пропорция по отработанным дням (worked_days.WORK100) может быть
добавлена при уточнении алгоритма; сейчас оклад берётся полностью
или из входа BASIC, если задан вручную. -->
<record id="rsbu_rule_basic" model="hr.salary.rule">
<field name="name">Оклад</field>
<field name="code">BASIC</field>
<field name="sequence" eval="10"/>
<field name="category_id" ref="rsbu_cat_basic"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
# Оклад пропорционально отработанным дням (норма и отработанные берутся из
# календаря и hr.leave автоматически: отпуск/больничный/за свой счёт
# уменьшают отработанные дни). Ручной ввод не требуется.
norm = payslip.rsbu_norm_days or 0.0
worked = payslip.rsbu_worked_days or 0.0
if norm:
result = contract.wage * worked / norm
else:
result = contract.wage
</field>
</record>
<!-- Премия: сумма из входа PREMIUM (hr.payslip.input), иначе 0. -->
<record id="rsbu_rule_premium" model="hr.salary.rule">
<field name="name">Премия</field>
<field name="code">PREMIUM</field>
<field name="sequence" eval="20"/>
<field name="category_id" ref="rsbu_cat_alw"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = inputs.PREMIUM.amount if 'PREMIUM' in inputs.dict else 0.0
</field>
</record>
<!-- Отпускные = средний дневной заработок × календарные дни отпуска.
Дни отпуска берутся из hr.leave (тип «Оплачиваемый отпуск»)
автоматически. -->
<record id="rsbu_rule_vacation" model="hr.salary.rule">
<field name="name">Отпускные</field>
<field name="code">VACATION</field>
<field name="sequence" eval="30"/>
<field name="category_id" ref="rsbu_cat_alw"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
avg = employee.rsbu_avg_daily_wage or 0.0
result = avg * (payslip.rsbu_vacation_cal_days or 0.0)
</field>
</record>
<!-- Больничный за счёт работодателя (первые 3 дня).
Пособие = средний дневной заработок × min(3, дни болезни) ×
процент по страховому стажу (≥8 лет 100%, 5-8 лет 80%, <5 лет 60%).
Дни болезни подаются входом SICK_DAYS. Первые 3 дня платит
работодатель, остальные — СФР (в наш учёт не попадают).
Облагается НДФЛ, но НЕ облагается страховыми взносами. -->
<record id="rsbu_rule_sick3" model="hr.salary.rule">
<field name="name">Больничный (3 дня за счёт работодателя)</field>
<field name="code">SICK3</field>
<field name="sequence" eval="40"/>
<field name="category_id" ref="rsbu_cat_alw"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
# Календарные дни больничного берутся из hr.leave (тип «Больничный»)
# автоматически. Работодатель оплачивает первые 3 календарных дня.
sick_days = payslip.rsbu_sick_cal_days or 0.0
employer_days = min(3.0, sick_days)
avg = employee.rsbu_avg_daily_wage or 0.0
rate = employee.rsbu_sick_rate()
result = avg * employer_days * rate
</field>
</record>
<!-- Начислено (итог, облагаемая НДФЛ база). -->
<record id="rsbu_rule_gross" model="hr.salary.rule">
<field name="name">Начислено</field>
<field name="code">GROSS</field>
<field name="sequence" eval="100"/>
<field name="category_id" ref="rsbu_cat_gross"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.RSBU_BASIC + categories.RSBU_ALW
</field>
</record>
<!-- НДФЛ: прогрессивная шкала 13–22% нарастающим итогом с начала
года + стандартные вычеты (ст.224/225/218 НК). Расчёт вынесен
в rsbu_compute_ndfl (нужен доступ к листкам года и вычетам).
Результат отрицательный (удержание). -->
<record id="rsbu_rule_ndfl" model="hr.salary.rule">
<field name="name">НДФЛ</field>
<field name="code">NDFL</field>
<field name="sequence" eval="110"/>
<field name="category_id" ref="rsbu_cat_ndfl"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = - payslip.rsbu_compute_ndfl(current_gross=categories.RSBU_GROSS)
</field>
</record>
<!-- Страховые взносы (единый тариф): база = начислено минус больничный
(больничный взносами не облагается). Затраты работодателя.
Переменная SICK3 в localdict = сумма (total) правила больничного. -->
<record id="rsbu_rule_insurance" model="hr.salary.rule">
<field name="name">Страховые взносы (единый тариф)</field>
<field name="code">INSURANCE</field>
<field name="sequence" eval="120"/>
<field name="category_id" ref="rsbu_cat_insurance"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
# Сумма = разбивка ОПС+ОМС+ВНиМ (с учётом льготы МСП сверх 1.5 МРОТ).
# База берётся из localdict (RSBU_GROSS − SICK3), т.к. строки листка на
# момент расчёта ещё не сохранены. Разбивка по видам для РСВ доступна
# через payslip.rsbu_insurance_breakdown(base).
result = payslip.rsbu_insurance_breakdown(
base=max(0.0, categories.RSBU_GROSS - SICK3))['total']
</field>
</record>
<!-- Взносы на травматизм: та же база, тариф из настроек. -->
<record id="rsbu_rule_injury" model="hr.salary.rule">
<field name="name">Взносы на травматизм</field>
<field name="code">INJURY</field>
<field name="sequence" eval="130"/>
<field name="category_id" ref="rsbu_cat_injury"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
rate = payslip.company_id.rsbu_injury_rate or 0.0
base = categories.RSBU_GROSS - SICK3
result = base * rate / 100.0
</field>
</record>
<!-- К выплате: начислено минус НДФЛ (НДФЛ отрицательный). -->
<record id="rsbu_rule_net" model="hr.salary.rule">
<field name="name">К выплате</field>
<field name="code">NET</field>
<field name="sequence" eval="200"/>
<field name="category_id" ref="rsbu_cat_net"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.RSBU_GROSS + categories.RSBU_NDFL
</field>
</record>
</data>
</odoo>