Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
103
rsbu_fns_reporting/models/rsbu_efs1_szvtd.py
Normal file
103
rsbu_fns_reporting/models/rsbu_efs1_szvtd.py
Normal file
@@ -0,0 +1,103 @@
|
||||
# -*- 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
|
||||
Reference in New Issue
Block a user