196 lines
7.0 KiB
Python
196 lines
7.0 KiB
Python
|
||
from datetime import datetime
|
||
|
||
from odoo import api, fields, models, exceptions
|
||
|
||
|
||
class CommCounterType(models.Model):
|
||
_name = 'comm.countertype'
|
||
_description = 'Тип счётчика'
|
||
|
||
name = fields.Char(string='Название типа счётчика', required=True)
|
||
uom = fields.Many2one('uom.uom', string='Единица измерения')
|
||
|
||
|
||
class CommCounter(models.Model):
|
||
_name = 'comm.counter'
|
||
_description = 'Прибор учёта (счётчик)'
|
||
_order = 'contract_name,type,name'
|
||
|
||
name = fields.Char(string='Номер счётчика', required=True)
|
||
type = fields.Many2one('comm.countertype', string='Тип счётчика')
|
||
contract_id = fields.Many2one('comm.contract', string='Договор')
|
||
contract_name = fields.Char(
|
||
string='Номер договора',
|
||
related='contract_id.name',
|
||
store=True,
|
||
readonly=True,
|
||
)
|
||
price = fields.Float(
|
||
string='Цена',
|
||
compute='_compute_price',
|
||
store=True,
|
||
readonly=True,
|
||
)
|
||
last_value_val = fields.Float(
|
||
string='Последнее показание',
|
||
compute='_compute_last_value',
|
||
store=True,
|
||
)
|
||
last_period = fields.Char(
|
||
string='Последний период',
|
||
compute='_compute_last_period',
|
||
store=True,
|
||
)
|
||
values_ids = fields.Many2many('comm.counterval', string='Показания')
|
||
|
||
@api.depends('name', 'type', 'last_period', 'last_value_val')
|
||
def _compute_display_name(self):
|
||
for rec in self:
|
||
if rec.last_period:
|
||
suffix = ' (%s: %s, %s)' % (
|
||
rec.last_period, rec.last_value_val, rec.type.name,
|
||
)
|
||
elif rec.type:
|
||
suffix = ' (%s)' % rec.type.name
|
||
else:
|
||
suffix = ''
|
||
rec.display_name = '%s%s' % (rec.name or '', suffix)
|
||
|
||
@api.depends('values_ids', 'contract_id')
|
||
def _compute_last_value(self):
|
||
for rec in self:
|
||
rec.last_value_val = rec._last_value()
|
||
|
||
def _last_value(self):
|
||
self.ensure_one()
|
||
value = self.env['comm.counterval'].search(
|
||
[('counter_id', '=', self.id)],
|
||
order='year desc, month desc',
|
||
limit=1,
|
||
)
|
||
return value.name if value else 0.0
|
||
|
||
@api.depends('contract_id', 'contract_id.line_ids.price')
|
||
def _compute_price(self):
|
||
for rec in self:
|
||
line = rec.contract_id.line_ids.filtered(
|
||
lambda ln: ln.counter_id.id == rec.id
|
||
)
|
||
rec.price = line[:1].price
|
||
|
||
@api.depends('values_ids', 'contract_id')
|
||
def _compute_last_period(self):
|
||
for rec in self:
|
||
value = self.env['comm.counterval'].search(
|
||
[('counter_id', '=', rec.id)],
|
||
order='year desc, month desc',
|
||
limit=1,
|
||
)
|
||
rec.last_period = (
|
||
'%s-%s' % (value.year, value.month) if value else ''
|
||
)
|
||
|
||
@api.onchange('contract_id')
|
||
def _onchange_contract_id(self):
|
||
for rec in self:
|
||
if not rec.contract_id:
|
||
continue
|
||
existing = rec.contract_id.line_ids.mapped('counter_id').ids
|
||
if rec.id and rec.id not in existing:
|
||
rec.contract_id.line_ids.create({
|
||
'counter_id': rec.id,
|
||
'contract_id': rec.contract_id.id,
|
||
})
|
||
|
||
def action_show_last_value(self):
|
||
self.ensure_one()
|
||
raise exceptions.UserError(
|
||
'На сегодняшнее число последнее показание этого счётчика, '
|
||
'зарегистрированное в базе: %s' % self._last_value()
|
||
)
|
||
|
||
def action_add_value(self):
|
||
self.ensure_one()
|
||
return {
|
||
'type': 'ir.actions.act_window',
|
||
'res_model': 'comm.counterval',
|
||
'view_mode': 'form',
|
||
'target': 'new',
|
||
'context': {'default_counter_id': self.id},
|
||
}
|
||
|
||
|
||
class CommCounterValue(models.Model):
|
||
_name = 'comm.counterval'
|
||
_description = 'Показание счётчика'
|
||
_order = 'year desc, month desc'
|
||
|
||
name = fields.Float(string='Показание', required=True)
|
||
year = fields.Integer(
|
||
string='Год', required=True,
|
||
default=lambda self: datetime.today().year,
|
||
)
|
||
month = fields.Integer(
|
||
string='Месяц', required=True,
|
||
default=lambda self: datetime.today().month,
|
||
)
|
||
counter_id = fields.Many2one('comm.counter', string='Счётчик', required=True)
|
||
contract_id = fields.Many2one(
|
||
'comm.contract', string='Договор',
|
||
related='counter_id.contract_id', store=True,
|
||
)
|
||
type = fields.Many2one(
|
||
'comm.countertype', string='Тип',
|
||
related='counter_id.type', store=True,
|
||
)
|
||
partner_id = fields.Many2one(
|
||
'res.partner', string='Партнёр',
|
||
related='counter_id.contract_id.partner_id', store=True,
|
||
)
|
||
|
||
@api.constrains('name', 'month', 'year', 'counter_id')
|
||
def _check_value(self):
|
||
for rec in self:
|
||
if rec.month > 12 or rec.month < 1:
|
||
raise exceptions.ValidationError(
|
||
'Счётчик: %s. Месяц должен быть от 1 до 12!' % rec.counter_id.name
|
||
)
|
||
if rec.year < 2010 or rec.year > 2050:
|
||
raise exceptions.ValidationError(
|
||
'Счётчик: %s. Некорректно указан год!' % rec.counter_id.name
|
||
)
|
||
if rec.name == 0:
|
||
raise exceptions.ValidationError(
|
||
'Счётчик: %s. Значение не может быть равно 0.' % rec.counter_id.name
|
||
)
|
||
later = self.search([
|
||
('year', '>=', rec.year),
|
||
('month', '>=', rec.month),
|
||
('counter_id', '=', rec.counter_id.id),
|
||
('id', '!=', rec.id),
|
||
])
|
||
if later:
|
||
raise exceptions.ValidationError(
|
||
'Счётчик: %s. Уже существует показание за указанный или '
|
||
'более поздний период.' % rec.counter_id.name
|
||
)
|
||
bigger = self.search([
|
||
('name', '>', rec.name),
|
||
('counter_id', '=', rec.counter_id.id),
|
||
('id', '!=', rec.id),
|
||
])
|
||
if bigger:
|
||
raise exceptions.ValidationError(
|
||
'Счётчик: %s. Уже существует большее показание для этого '
|
||
'счётчика. Например: %s.' % (rec.counter_id.name, bigger[0].name)
|
||
)
|
||
|
||
@api.model_create_multi
|
||
def create(self, vals_list):
|
||
records = super().create(vals_list)
|
||
for record in records:
|
||
if record.counter_id:
|
||
record.counter_id.values_ids |= record
|
||
return records
|