Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
84
rsbu_payroll/models/rsbu_employee_child.py
Normal file
84
rsbu_payroll/models/rsbu_employee_child.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""Дети сотрудника для стандартного вычета по НДФЛ (ст. 218 НК РФ).
|
||||
|
||||
Размер вычета зависит от очерёдности рождения и возраста ребёнка;
|
||||
вычет на ребёнка-инвалида суммируется с вычетом по очерёдности. Право
|
||||
на вычет прекращается по достижении возраста (18 лет, либо 24 при очной
|
||||
форме обучения) и при превышении дохода 450 000 ₽ нарастающим итогом
|
||||
(проверяется при расчёте НДФЛ, не здесь).
|
||||
"""
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
|
||||
# Размеры детских вычетов по очерёдности (₽/мес), с 2025 (пп.4 п.1 ст.218 НК).
|
||||
CHILD_DEDUCTION_BY_ORDER = {1: 1400.0, 2: 2800.0, 3: 6000.0}
|
||||
# Вычет на ребёнка-инвалида (₽/мес): родитель/усыновитель — 12000,
|
||||
# опекун/попечитель/приёмный — 6000.
|
||||
DISABLED_DEDUCTION_PARENT = 12000.0
|
||||
DISABLED_DEDUCTION_GUARDIAN = 6000.0
|
||||
|
||||
|
||||
class RsbuEmployeeChild(models.Model):
|
||||
_name = 'rsbu.employee.child'
|
||||
_description = 'РСБУ — Ребёнок сотрудника (вычет НДФЛ)'
|
||||
_order = 'birthdate, id'
|
||||
|
||||
employee_id = fields.Many2one(
|
||||
'hr.employee', string='Сотрудник', required=True,
|
||||
ondelete='cascade', index=True)
|
||||
name = fields.Char(string='ФИО ребёнка')
|
||||
birthdate = fields.Date(string='Дата рождения', required=True)
|
||||
order = fields.Integer(
|
||||
string='Очерёдность', required=True, default=1,
|
||||
help='Порядковый номер ребёнка по рождению (1-й, 2-й, 3-й…). '
|
||||
'Определяет размер вычета: 1400 / 2800 / 6000 ₽. Учитываются '
|
||||
'все дети, включая совершеннолетних, при определении очерёдности.')
|
||||
is_disabled = fields.Boolean(
|
||||
string='Ребёнок-инвалид',
|
||||
help='Добавляет вычет 12 000 ₽ (родителю/усыновителю) или 6 000 ₽ '
|
||||
'(опекуну), суммируется с вычетом по очерёдности.')
|
||||
is_student = fields.Boolean(
|
||||
string='Очная форма обучения',
|
||||
help='Продлевает право на вычет до 24 лет (иначе — до 18 лет).')
|
||||
is_guardian = fields.Boolean(
|
||||
string='Опекун/попечитель',
|
||||
help='Отмечено — применяется вычет на ребёнка-инвалида 6 000 ₽ '
|
||||
'(опекун), иначе 12 000 ₽ (родитель/усыновитель).')
|
||||
single_parent = fields.Boolean(
|
||||
string='Единственный родитель',
|
||||
help='Двойной вычет единственному родителю (пп.4 п.1 ст.218 НК).')
|
||||
|
||||
def _age_on(self, date):
|
||||
"""Полных лет ребёнку на указанную дату."""
|
||||
self.ensure_one()
|
||||
if not self.birthdate:
|
||||
return 0
|
||||
return relativedelta(date, self.birthdate).years
|
||||
|
||||
def _is_eligible_on(self, date):
|
||||
"""Даёт ли ребёнок право на вычет на указанную дату (по возрасту)."""
|
||||
self.ensure_one()
|
||||
age = self._age_on(date)
|
||||
limit = 24 if self.is_student else 18
|
||||
return age < limit
|
||||
|
||||
def _deduction_amount(self, date):
|
||||
"""Сумма месячного вычета по ребёнку на дату (по очерёдности +
|
||||
инвалидность), с учётом двойного вычета единственному родителю."""
|
||||
self.ensure_one()
|
||||
if not self._is_eligible_on(date):
|
||||
return 0.0
|
||||
amount = CHILD_DEDUCTION_BY_ORDER.get(
|
||||
self.order, CHILD_DEDUCTION_BY_ORDER[3]) if self.order else 0.0
|
||||
if self.is_disabled:
|
||||
amount += (DISABLED_DEDUCTION_GUARDIAN if self.is_guardian
|
||||
else DISABLED_DEDUCTION_PARENT)
|
||||
if self.single_parent:
|
||||
amount *= 2.0
|
||||
return amount
|
||||
|
||||
@api.depends('name', 'order', 'birthdate')
|
||||
def _compute_display_name(self):
|
||||
for rec in self:
|
||||
rec.display_name = '%s (%s, №%s)' % (
|
||||
rec.name or _('Ребёнок'), rec.birthdate or '?', rec.order or 0)
|
||||
Reference in New Issue
Block a user