104 lines
5.4 KiB
Python
104 lines
5.4 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""Документ ЕФС-1 подраздел 1.1 (СЗВ-ТД) — сведения о трудовой деятельности.
|
||
|
||
Единая форма сведений ЕФС-1 (СФР), подраздел 1.1 «Сведения о трудовой
|
||
(иной) деятельности зарегистрированного лица». Формат 2024-01-01
|
||
(пространство имён http://пф.рф/ЕФС-1/2024-01-01). Подаётся в
|
||
Социальный фонд России по факту кадровых мероприятий (приём, увольнение,
|
||
перевод и т.п.).
|
||
|
||
Документ группирует кадровые мероприятия (rsbu.hr.event) по
|
||
зарегистрированным лицам: один документ → блок СЗВ с несколькими ЗЛ, у
|
||
каждого ЗЛ — свои мероприятия. Автозаполнение собирает ещё не поданные
|
||
мероприятия за отчётный период. XML-выгрузка и XSD-валидация — в
|
||
rsbu_efs1_szvtd_xml (через xml.etree.ElementTree + xmlschema, т.к. имена
|
||
элементов и namespace СФР — кириллические).
|
||
|
||
Реквизиты страхователя (рег. номер СФР, наименование, ИНН/КПП, ОКВЭД,
|
||
ОГРН) и руководителя берутся из настроек компании (rsbu_reporting_base).
|
||
"""
|
||
from odoo import api, fields, models
|
||
|
||
|
||
class RsbuEfs1Szvtd(models.Model):
|
||
_name = 'rsbu.efs1.szvtd'
|
||
_description = 'РСБУ — ЕФС-1 подраздел 1.1 (СЗВ-ТД)'
|
||
_order = 'date_fill 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)
|
||
date_from = fields.Date(
|
||
string='Период с', required=True,
|
||
default=lambda self: fields.Date.today().replace(day=1),
|
||
help='Начало периода отбора кадровых мероприятий для автозаполнения.')
|
||
date_to = fields.Date(
|
||
string='Период по', required=True,
|
||
default=fields.Date.context_today,
|
||
help='Конец периода отбора кадровых мероприятий для автозаполнения.')
|
||
date_fill = fields.Date(
|
||
string='Дата заполнения', required=True,
|
||
default=fields.Date.context_today,
|
||
help='Дата заполнения сведений (элемент ДатаЗаполнения).')
|
||
state = fields.Selection(
|
||
selection=[('draft', 'Черновик'), ('computed', 'Сформировано'),
|
||
('reported', 'Подано')],
|
||
default='draft', string='Состояние', copy=False)
|
||
event_ids = fields.One2many(
|
||
'rsbu.hr.event', 'efs1_id', string='Кадровые мероприятия')
|
||
event_count = fields.Integer(
|
||
string='Мероприятий', compute='_compute_counts')
|
||
employee_count = fields.Integer(
|
||
string='Сотрудников', compute='_compute_counts')
|
||
|
||
@api.depends('date_from', 'date_to')
|
||
def _compute_name(self):
|
||
for rec in self:
|
||
df = rec.date_from and rec.date_from.strftime('%d.%m.%Y') or '?'
|
||
dt = rec.date_to and rec.date_to.strftime('%d.%m.%Y') or '?'
|
||
rec.name = 'ЕФС-1 (СЗВ-ТД): %s — %s' % (df, dt)
|
||
|
||
@api.depends('event_ids', 'event_ids.employee_id')
|
||
def _compute_counts(self):
|
||
for rec in self:
|
||
rec.event_count = len(rec.event_ids)
|
||
rec.employee_count = len(rec.event_ids.employee_id)
|
||
|
||
# ------------------------------------------------------------------
|
||
def action_compute(self):
|
||
"""Автозаполнить документ ещё не поданными мероприятиями за период."""
|
||
Event = self.env['rsbu.hr.event']
|
||
for rec in self:
|
||
# Отвязать прежний набор (не удаляя сами мероприятия).
|
||
rec.event_ids.write({'efs1_id': False})
|
||
events = Event.search([
|
||
('company_id', '=', rec.company_id.id),
|
||
('event_date', '>=', rec.date_from),
|
||
('event_date', '<=', rec.date_to),
|
||
('state', '=', 'draft'),
|
||
('efs1_id', '=', False),
|
||
])
|
||
events.write({'efs1_id': rec.id})
|
||
rec.state = 'computed'
|
||
return True
|
||
|
||
def _events_by_employee(self):
|
||
"""Сгруппировать мероприятия документа по сотруднику (ЗЛ).
|
||
|
||
Возвращает список пар (employee, events) в стабильном порядке
|
||
(по ФИО сотрудника), мероприятия внутри — по дате.
|
||
"""
|
||
self.ensure_one()
|
||
by_emp = {}
|
||
for ev in self.event_ids:
|
||
by_emp.setdefault(ev.employee_id, self.env['rsbu.hr.event'])
|
||
by_emp[ev.employee_id] |= ev
|
||
pairs = []
|
||
for emp in sorted(by_emp, key=lambda e: (e.name or '')):
|
||
events = by_emp[emp].sorted(lambda e: (e.event_date, e.id))
|
||
pairs.append((emp, events))
|
||
return pairs
|