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,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