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