122 lines
4.7 KiB
Python
122 lines
4.7 KiB
Python
from odoo import api, fields, models
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.fields import Domain
|
|
|
|
|
|
class EsgEmissionSource(models.Model):
|
|
_name = 'esg.emission.source'
|
|
_description = 'Emission Source'
|
|
_order = 'level desc,sequence,name'
|
|
_rec_name = 'complete_name'
|
|
_parent_name = 'parent_id'
|
|
_parent_store = True
|
|
|
|
sequence = fields.Integer(default=10)
|
|
name = fields.Char(translate=True, required=True)
|
|
parent_id = fields.Many2one('esg.emission.source', domain="['!', ('id', 'child_of', id)]", index=True)
|
|
child_ids = fields.One2many('esg.emission.source', 'parent_id')
|
|
parent_path = fields.Char(index=True)
|
|
complete_name = fields.Char(compute='_compute_complete_name', search='_search_complete_name', recursive=True)
|
|
scope = fields.Selection(selection=[
|
|
('direct', 'Scope 1: Direct'),
|
|
('indirect', 'Scope 2: Indirect'),
|
|
('indirect_others', 'Scope 3: Others Indirect')
|
|
],
|
|
default='direct',
|
|
compute='_compute_scope',
|
|
store=True,
|
|
readonly=False,
|
|
recursive=True,
|
|
required=True,
|
|
)
|
|
|
|
activity_flow_direct_indirect = fields.Selection(
|
|
selection=[
|
|
('company_reporting', 'Company Reporting'),
|
|
('upstream', 'Upstream'),
|
|
],
|
|
compute='_compute_activity_flow',
|
|
export_string_translation=False,
|
|
)
|
|
activity_flow_indirect_others = fields.Selection(
|
|
selection=[
|
|
('upstream', 'Upstream'),
|
|
('downstream', 'Downstream'),
|
|
],
|
|
required=True,
|
|
default='upstream',
|
|
export_string_translation=False,
|
|
)
|
|
activity_flow = fields.Selection(
|
|
selection=lambda self: list(set(self._fields['activity_flow_direct_indirect'].selection) | set(self._fields['activity_flow_indirect_others'].selection)),
|
|
compute='_compute_activity_flow',
|
|
)
|
|
|
|
level = fields.Integer(compute='_compute_level', store=True, recursive=True)
|
|
|
|
@api.constrains('parent_id')
|
|
def _check_no_cyclic_dependencies(self):
|
|
for source in self:
|
|
parent_path_ids = source.parent_path[:-1].split("/")
|
|
if len(parent_path_ids) != len(set(parent_path_ids)):
|
|
raise ValidationError(self.env._("You cannot create a cyclic hierarchy of emission sources."))
|
|
|
|
@api.depends('parent_id.level')
|
|
def _compute_level(self):
|
|
for source in self:
|
|
if not source.parent_id:
|
|
source.level = 1
|
|
else:
|
|
source.level = source.parent_id.level + 1
|
|
|
|
@api.depends('parent_id.scope')
|
|
def _compute_scope(self):
|
|
for source in self:
|
|
if not source.parent_id:
|
|
continue
|
|
source.scope = source.parent_id.scope
|
|
|
|
@api.depends('scope', 'activity_flow_indirect_others')
|
|
def _compute_activity_flow(self):
|
|
for source in self:
|
|
source.activity_flow_direct_indirect = source.activity_flow = False
|
|
match source.scope:
|
|
case 'direct':
|
|
source.activity_flow_direct_indirect = source.activity_flow = 'company_reporting'
|
|
case 'indirect':
|
|
source.activity_flow_direct_indirect = source.activity_flow = 'upstream'
|
|
case 'indirect_others':
|
|
source.activity_flow = source.activity_flow_indirect_others
|
|
|
|
@api.depends('name', 'parent_id.complete_name', 'scope')
|
|
def _compute_complete_name(self):
|
|
for source in self:
|
|
if source.parent_id:
|
|
source.complete_name = f"{source.parent_id.complete_name} > {source.name}"
|
|
else:
|
|
source.complete_name = f"{dict(self.env['esg.emission.source']._fields['scope']._description_selection(self.env)).get(source.scope)} > {source.name}"
|
|
|
|
@api.model
|
|
def _search_complete_name(self, operator, value):
|
|
if operator not in ('ilike', 'like', '=', '=ilike'):
|
|
raise NotImplementedError(f"Operator {operator} not supported")
|
|
|
|
domain = Domain('name', operator, value)
|
|
|
|
scope_labels = dict(self.env['esg.emission.source']._fields['scope']._description_selection(self.env))
|
|
matching_scope_keys = [
|
|
key for key, label in scope_labels.items()
|
|
if (
|
|
operator in ('ilike', '=ilike') and value in label.lower()
|
|
) or (
|
|
operator in ('like', '=') and value in label
|
|
)
|
|
]
|
|
if matching_scope_keys:
|
|
domain |= Domain('scope', 'in', matching_scope_keys)
|
|
matched_sources = self.env['esg.emission.source'].search(domain)
|
|
|
|
if not matched_sources:
|
|
return Domain.FALSE
|
|
return Domain('id', 'child_of', matched_sources.ids)
|