Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
189
rsbu_payroll/models/rsbu_hr_event.py
Normal file
189
rsbu_payroll/models/rsbu_hr_event.py
Normal file
@@ -0,0 +1,189 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Кадровое мероприятие для ЕФС-1 подраздел 1.1 (СЗВ-ТД).
|
||||
|
||||
Одно мероприятие кадрового учёта (приём, перевод, увольнение и т.п.) по
|
||||
сотруднику — источник для элемента «Мероприятие» (тип ЕФС:ТипТД) формы
|
||||
ЕФС-1 подраздел 1.1 «Сведения о трудовой (иной) деятельности».
|
||||
|
||||
ЕФС-1 (СФР) — событийная форма: подаётся не за период, а по факту кадрового
|
||||
события. При приёме и увольнении — не позднее следующего рабочего дня, при
|
||||
прочих мероприятиях — до 25-го числа следующего месяца. Поэтому мероприятие
|
||||
регистрируется отдельной записью и затем выгружается в документ ЕФС-1
|
||||
(rsbu.efs1.szvtd).
|
||||
|
||||
Поля и справочники — строго по XSD ЕФС:ТипТД (ТипыЕФС_2024-01-01):
|
||||
UUID, Дата, Вид (1..10), Должность, ЯвляетсяСовместителем, ВидПР,
|
||||
СтруктурноеПодразделение, КодВФ, КодВФпоОКЗ, ОснованиеУвольнения
|
||||
(КодПричиныУвольнения, НормативныйДокумент, Статья, Часть, Пункт, Подпункт,
|
||||
Абзац), Причина, Основание (Наименование, Дата, Серия, Номер).
|
||||
"""
|
||||
import uuid
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
# Виды мероприятий (ЕФС:ТипТД/Вид). Значения 1..10 по XSD.
|
||||
EVENT_KIND_SELECTION = [
|
||||
('1', 'ПРИЕМ'),
|
||||
('2', 'ПЕРЕВОД'),
|
||||
('3', 'ПЕРЕИМЕНОВАНИЕ'),
|
||||
('4', 'УСТАНОВЛЕНИЕ (ПРИСВОЕНИЕ)'),
|
||||
('5', 'УВОЛЬНЕНИЕ'),
|
||||
('6', 'ЗАПРЕТ ЗАНИМАТЬ ДОЛЖНОСТЬ'),
|
||||
('7', 'ПРИОСТАНОВЛЕНИЕ'),
|
||||
('8', 'ВОЗОБНОВЛЕНИЕ'),
|
||||
('9', 'НАЧАЛО ДОГОВОРА ГПХ'),
|
||||
('10', 'ОКОНЧАНИЕ ДОГОВОРА ГПХ'),
|
||||
]
|
||||
|
||||
# Виды мероприятий, для которых КодВФпоОКЗ обязателен (по описанию XSD).
|
||||
KINDS_REQUIRE_OKZ = {'1', '2', '4', '5', '7', '8', '9', '10'}
|
||||
|
||||
# Признак совместительства / срочности (ЕФС:ТипТД/ЯвляетсяСовместителем).
|
||||
EMPLOYMENT_TYPE_SELECTION = [
|
||||
('0', 'Бессрочный трудовой договор'),
|
||||
('0.1', 'Срочный ТД до 6 месяцев'),
|
||||
('0.2', 'Срочный ТД более 6 месяцев'),
|
||||
('1', 'Совместительство'),
|
||||
('1.1', 'Совместительство, срочный до 6 месяцев'),
|
||||
('1.2', 'Совместительство, срочный более 6 месяцев'),
|
||||
]
|
||||
|
||||
|
||||
class RsbuHrEvent(models.Model):
|
||||
_name = 'rsbu.hr.event'
|
||||
_description = 'РСБУ — Кадровое мероприятие (ЕФС-1, СЗВ-ТД)'
|
||||
_order = 'event_date desc, id desc'
|
||||
_check_company_auto = True
|
||||
|
||||
name = fields.Char(string='Наименование', compute='_compute_name',
|
||||
store=True)
|
||||
company_id = fields.Many2one(
|
||||
'res.company', string='Компания', required=True, index=True,
|
||||
default=lambda self: self.env.company)
|
||||
employee_id = fields.Many2one(
|
||||
'hr.employee', string='Сотрудник', required=True, index=True,
|
||||
check_company=True)
|
||||
event_uuid = fields.Char(
|
||||
string='UUID мероприятия', required=True, copy=False, index=True,
|
||||
default=lambda self: str(uuid.uuid4()),
|
||||
help='Уникальный идентификатор мероприятия (элемент UUID). '
|
||||
'Используется СФР для сопоставления и отмены мероприятий.')
|
||||
event_date = fields.Date(
|
||||
string='Дата мероприятия', required=True,
|
||||
default=fields.Date.context_today,
|
||||
help='Дата проведения кадрового мероприятия (приёма, увольнения '
|
||||
'и т.п.).')
|
||||
kind = fields.Selection(
|
||||
selection=EVENT_KIND_SELECTION, string='Вид мероприятия',
|
||||
required=True, default='1')
|
||||
# Сведения о занятости.
|
||||
job_title = fields.Char(
|
||||
string='Должность',
|
||||
help='Должность, профессия, специальность, квалификация (элемент '
|
||||
'Должность).')
|
||||
employment_type = fields.Selection(
|
||||
selection=EMPLOYMENT_TYPE_SELECTION, string='Характер работы',
|
||||
default='0',
|
||||
help='Признак совместительства/срочности трудового договора '
|
||||
'(элемент ЯвляетсяСовместителем).')
|
||||
work_kind = fields.Char(
|
||||
string='Вид поручаемой работы',
|
||||
help='Конкретный вид поручаемой работы (элемент ВидПР).')
|
||||
department_name = fields.Char(
|
||||
string='Структурное подразделение',
|
||||
help='Структурное подразделение (элемент СтруктурноеПодразделение).')
|
||||
func_code = fields.Char(
|
||||
string='Код выполняемой функции',
|
||||
help='Код выполняемой функции (элемент КодВФ): особый код трудовой '
|
||||
'функции (ДИСТ, ДГПХ и т.п.) либо код по профстандарту.')
|
||||
okz_code = fields.Char(
|
||||
string='Код по ОКЗ',
|
||||
help='Кодовое обозначение занятия по ОКЗ, формат NNNN.N (элемент '
|
||||
'КодВФпоОКЗ). По умолчанию берётся из карточки сотрудника.')
|
||||
# Документ-основание (приказ).
|
||||
basis_name = fields.Char(
|
||||
string='Документ-основание', default='Приказ',
|
||||
help='Наименование документа-основания (элемент Основание/'
|
||||
'Наименование), напр. «Приказ».')
|
||||
basis_date = fields.Date(
|
||||
string='Дата основания',
|
||||
help='Дата документа-основания (элемент Основание/Дата).')
|
||||
basis_series = fields.Char(
|
||||
string='Серия основания',
|
||||
help='Серия документа-основания (элемент Основание/Серия).')
|
||||
basis_number = fields.Char(
|
||||
string='Номер основания',
|
||||
help='Номер документа-основания (элемент Основание/Номер).')
|
||||
# Основание увольнения (только для вида «УВОЛЬНЕНИЕ»).
|
||||
dismissal_reason_code = fields.Char(
|
||||
string='Код причины увольнения',
|
||||
help='Код причины увольнения (элемент ОснованиеУвольнения/'
|
||||
'КодПричиныУвольнения), напр. «п3ч1с77тк».')
|
||||
dismissal_document = fields.Char(
|
||||
string='Нормативный документ', default='Трудовой кодекс Российской Федерации',
|
||||
help='Наименование нормативного документа (элемент '
|
||||
'ОснованиеУвольнения/НормативныйДокумент).')
|
||||
dismissal_article = fields.Char(
|
||||
string='Статья',
|
||||
help='Номер статьи нормативного акта (элемент ОснованиеУвольнения/'
|
||||
'Статья).')
|
||||
dismissal_part = fields.Char(
|
||||
string='Часть',
|
||||
help='Часть статьи (элемент ОснованиеУвольнения/Часть).')
|
||||
dismissal_point = fields.Char(
|
||||
string='Пункт',
|
||||
help='Пункт статьи (элемент ОснованиеУвольнения/Пункт).')
|
||||
dismissal_subpoint = fields.Char(
|
||||
string='Подпункт',
|
||||
help='Подпункт статьи (элемент ОснованиеУвольнения/Подпункт).')
|
||||
dismissal_paragraph = fields.Char(
|
||||
string='Абзац',
|
||||
help='Абзац статьи (элемент ОснованиеУвольнения/Абзац).')
|
||||
dismissal_reason = fields.Char(
|
||||
string='Причина увольнения',
|
||||
help='Текстовая формулировка причины увольнения (элемент Причина).')
|
||||
|
||||
state = fields.Selection(
|
||||
selection=[('draft', 'Черновик'), ('reported', 'Подано')],
|
||||
default='draft', string='Состояние', copy=False)
|
||||
|
||||
@api.depends('employee_id', 'kind', 'event_date')
|
||||
def _compute_name(self):
|
||||
labels = dict(EVENT_KIND_SELECTION)
|
||||
for rec in self:
|
||||
label = labels.get(rec.kind, '?')
|
||||
emp = rec.employee_id.name or '?'
|
||||
dt = rec.event_date and rec.event_date.strftime('%d.%m.%Y') or '?'
|
||||
rec.name = '%s — %s (%s)' % (label, emp, dt)
|
||||
|
||||
@api.onchange('employee_id')
|
||||
def _onchange_employee_id(self):
|
||||
"""Подставить должность/подразделение/ОКЗ из карточки сотрудника."""
|
||||
for rec in self:
|
||||
emp = rec.employee_id
|
||||
if not emp:
|
||||
continue
|
||||
if not rec.job_title:
|
||||
rec.job_title = emp.job_title or (
|
||||
emp.job_id.name if emp.job_id else False)
|
||||
if not rec.department_name:
|
||||
rec.department_name = (
|
||||
emp.department_id.name if emp.department_id else False)
|
||||
if not rec.okz_code:
|
||||
rec.okz_code = emp.rsbu_okz_code or False
|
||||
|
||||
@api.onchange('kind')
|
||||
def _onchange_kind(self):
|
||||
"""Подставить дату основания из даты мероприятия, если пусто."""
|
||||
for rec in self:
|
||||
if not rec.basis_date and rec.event_date:
|
||||
rec.basis_date = rec.event_date
|
||||
|
||||
def _okz_required(self):
|
||||
self.ensure_one()
|
||||
return self.kind in KINDS_REQUIRE_OKZ
|
||||
|
||||
def _effective_okz(self):
|
||||
"""Код ОКЗ мероприятия (из записи или карточки сотрудника)."""
|
||||
self.ensure_one()
|
||||
return self.okz_code or self.employee_id.rsbu_okz_code or ''
|
||||
Reference in New Issue
Block a user