Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
116
rsbu_fns_reporting/models/rsbu_pers_info.py
Normal file
116
rsbu_fns_reporting/models/rsbu_pers_info.py
Normal file
@@ -0,0 +1,116 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Персонифицированные сведения о физических лицах (ПСВ, КНД 1151162).
|
||||
|
||||
Форма ФНС NO_PERSSVFL версии 5.01. Подаётся ЕЖЕМЕСЯЧНО в налоговый орган:
|
||||
по каждому застрахованному лицу — ФИО, СНИЛС, ИНН и сумма выплат за месяц.
|
||||
|
||||
Автозаполнение строк из помесячных итогов выплат rsbu.rsv.summary
|
||||
(поле payments) за отчётный месяц.
|
||||
"""
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class RsbuPersInfo(models.Model):
|
||||
_name = 'rsbu.pers.info'
|
||||
_description = 'РСБУ — Персонифицированные сведения (ПСВ)'
|
||||
_order = 'year desc, month 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)
|
||||
year = fields.Integer(string='Год', required=True,
|
||||
default=lambda self: fields.Date.today().year)
|
||||
month = fields.Integer(
|
||||
string='Отчётный месяц', required=True,
|
||||
default=lambda self: fields.Date.today().month,
|
||||
help='Календарный месяц, за который подаются сведения.')
|
||||
date_doc = fields.Date(
|
||||
string='Дата документа', default=fields.Date.context_today)
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency', related='company_id.currency_id')
|
||||
state = fields.Selection(
|
||||
selection=[('draft', 'Черновик'), ('computed', 'Рассчитано')],
|
||||
default='draft', string='Состояние', copy=False)
|
||||
line_ids = fields.One2many(
|
||||
'rsbu.pers.info.line', 'report_id', string='Сведения по физлицам')
|
||||
|
||||
@api.depends('year', 'month')
|
||||
def _compute_name(self):
|
||||
names = ['', 'январь', 'февраль', 'март', 'апрель', 'май', 'июнь',
|
||||
'июль', 'август', 'сентябрь', 'октябрь', 'ноябрь', 'декабрь']
|
||||
for rec in self:
|
||||
m = names[rec.month] if rec.month and 1 <= rec.month <= 12 else '?'
|
||||
rec.name = 'Перс. сведения: %s %s' % (m, rec.year or '?')
|
||||
|
||||
def _month_bounds(self):
|
||||
import calendar
|
||||
self.ensure_one()
|
||||
last = calendar.monthrange(self.year, self.month)[1]
|
||||
return (fields.Date.to_date('%04d-%02d-01' % (self.year, self.month)),
|
||||
fields.Date.to_date('%04d-%02d-%02d' % (
|
||||
self.year, self.month, last)))
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
def action_compute(self):
|
||||
"""Пересобрать итоги выплат за месяц и автозаполнить строки."""
|
||||
Summary = self.env['rsbu.rsv.summary'].sudo()
|
||||
for rec in self:
|
||||
df, dt = rec._month_bounds()
|
||||
Summary.recompute_period(df, dt, rec.company_id)
|
||||
return self.fill_lines()
|
||||
|
||||
def fill_lines(self):
|
||||
"""Автозаполнить строки по сотрудникам из итогов выплат за месяц.
|
||||
|
||||
Отделено от action_compute, чтобы заполнять по существующим данным
|
||||
без принудительного пересбора (тесты, повторный расчёт).
|
||||
"""
|
||||
Summary = self.env['rsbu.rsv.summary'].sudo()
|
||||
Line = self.env['rsbu.pers.info.line']
|
||||
for rec in self:
|
||||
rec.line_ids.unlink()
|
||||
recs = Summary.search([
|
||||
('company_id', '=', rec.company_id.id),
|
||||
('year', '=', rec.year),
|
||||
('month', '=', rec.month),
|
||||
])
|
||||
# Суммируем выплаты по сотруднику (на случай нескольких записей).
|
||||
by_emp = {}
|
||||
for r in recs:
|
||||
by_emp.setdefault(r.employee_id, 0.0)
|
||||
by_emp[r.employee_id] += r.payments
|
||||
vals = []
|
||||
for emp, pay in by_emp.items():
|
||||
vals.append({
|
||||
'report_id': rec.id,
|
||||
'employee_id': emp.id,
|
||||
'amount': round(pay, 2),
|
||||
})
|
||||
if vals:
|
||||
Line.create(vals)
|
||||
rec.state = 'computed'
|
||||
return True
|
||||
|
||||
|
||||
class RsbuPersInfoLine(models.Model):
|
||||
_name = 'rsbu.pers.info.line'
|
||||
_description = 'РСБУ — Строка ПСВ (физлицо)'
|
||||
_order = 'report_id, employee_id'
|
||||
|
||||
report_id = fields.Many2one(
|
||||
'rsbu.pers.info', string='Сведения', required=True,
|
||||
ondelete='cascade', index=True)
|
||||
currency_id = fields.Many2one(
|
||||
'res.currency', related='report_id.currency_id')
|
||||
employee_id = fields.Many2one('hr.employee', string='Сотрудник',
|
||||
required=True)
|
||||
snils = fields.Char(string='СНИЛС', related='employee_id.rsbu_snils')
|
||||
inn = fields.Char(string='ИНН', related='employee_id.rsbu_inn')
|
||||
amount = fields.Monetary(string='Сумма выплат',
|
||||
currency_field='currency_id')
|
||||
cancelled = fields.Boolean(
|
||||
string='Аннулирующие сведения',
|
||||
help='Признак аннулирования ранее поданных сведений (ПрАннулир).')
|
||||
Reference in New Issue
Block a user