Newer
Older
from odoo import api, fields, models
class AccPriorityGroup(models.Model):
_name = "acc.priority.group"
_description = "Groupe de clés de répartition"
_rec_name = "display_name"
_order = "sequence, id"
# ------------------------------------------------------
# Fields declaration
# ------------------------------------------------------
acc_operation_id = fields.Many2one("acc.operation", "Opération", required=True)
sequence = fields.Integer(required=True, default=1)
type_algo = fields.Selection(
[
("prorata", "Répartition au prorata"),

Stéphane - Enercoop
a validé
("quotepart", "Répartition par quote-part"),
],
string="Répartition au sein du groupe",
default="prorata",
required=True,
)
display_name = fields.Char(
compute="_compute_display_name", store=True, readonly=True
)
acc_priority_group_counter_ids = fields.One2many(
comodel_name="acc.priority.group.counter",
inverse_name="acc_priority_group_id",
string="Affectation de compteur par groupes de priorité",
required=True,
)
counter_datas = fields.Json(compute="_compute_counter_datas")
total_share = fields.Float(compute="_compute_total_share", store=True)
# ------------------------------------------------------
# SQL Constraints
# ------------------------------------------------------
# ------------------------------------------------------
# Default methods
# ------------------------------------------------------
# ------------------------------------------------------
# Computed fields / Search Fields
# ------------------------------------------------------
@api.depends("acc_priority_group_counter_ids", "acc_priority_group_counter_ids.acc_counter_share")

Stéphane - Enercoop
a validé
def _compute_total_share(self):
for record in self:
record.total_share = sum(
record.acc_priority_group_counter_ids.mapped("acc_counter_share")
)
@api.depends("type_algo", "sequence")
def _compute_display_name(self):
for prio_group in self:
prio_group.display_name = f"Priorité {str(prio_group.sequence)}"
def _compute_counter_datas(self):
for priority in self:
priority.counter_datas = (
priority.acc_priority_group_counter_ids.acc_counter_id.mapped(
lambda q: {
"name": q.name,
"partner": q.partner_id.name,
"street": q.street,
}
)
)
# ------------------------------------------------------
# Onchange / Constraints
# ------------------------------------------------------
# ------------------------------------------------------
# CRUD methods (ORM overrides)
# ------------------------------------------------------
def write(self, vals):
seq = vals.get("sequence")
if seq is not None:
vals["sequence"] = seq + 1
res = super().write(vals)
return res
@api.model
def unlink(self, _id):
self = self.env["acc.priority.group"].browse(_id)
current_operation_id = self.env.context.get("active_id")
existing_groups = self.env["acc.priority.group"].search(
[("acc_operation_id", "=", current_operation_id), ("id", "!=", _id)]
)
for group in existing_groups:
group.sequence = seq
seq += 1
return super().unlink()
@api.model_create_multi
def create(self, vals_list):
"""
si c est le premier groupe cree on y affecte tout les compteurs
"""
current_operation_id = self.env.context.get("active_id")
existing_groups = self.env["acc.priority.group"].search(
[
("acc_operation_id", "=", current_operation_id),
]
)
res = super().create(vals_list)
if existing_groups:
res.sequence = max(existing_groups.mapped("sequence"))
return res
counters_to_affect = self.env["acc.counter"].search(
[
("acc_operation_id", "=", res.acc_operation_id.id),
("type", "in", ["del", "del_inj"]),
]
)
for counter in counters_to_affect:
res.add_counter(counter_id=counter)
def add_counter(self, counter_id):
self.env["acc.priority.group.counter"].create(
{
"acc_priority_group_id": self.id,
"acc_operation_id": self.acc_operation_id.id,
"acc_counter_id": counter_id.id,
"counter_street": counter_id.street,
"counter_owner": counter_id.partner_id.name,
}
)
# ------------------------------------------------------
# Actions
# ------------------------------------------------------
def compute(self, data=None):
compute_algo = {
"prorata": self._prorata,

Stéphane - Enercoop
a validé
"quotepart": self._quotepart,
}
d = compute_algo[self.type_algo](data)
return d
def get_conso_sum(self, data_slot):
conso_sum = 0.0
for counter in self.acc_priority_group_counter_ids.acc_counter_id.mapped(
"name"
):
conso_sum += data_slot.get("conso").get(counter, 0)
return conso_sum
def _prorata(self, data):
for slot in data:

Stéphane - Enercoop
a validé
remaining_prod = data.get(slot).get("prod_totale")
total_conso = self.get_conso_sum(data.get(slot))
total_affecte = 0.0
if not data.get(slot).get("affect"):
data[slot]["affect"] = {}
for counter in self.acc_priority_group_counter_ids.acc_counter_id:
# un compteur peut être présent dans deux groupes de priorité
already_affected = data.get(slot).get("affect").get(counter, 0)
conso_k = data.get(slot).get("conso").get(counter.name)
# si le compteur rentre en cours de periode il figure dans le
# groupe de repartition mais pas dans les données brutes conso_k = None
# dans ce cas on affecte 0
if remaining_prod <= 0 or total_conso == 0 or conso_k is None:
newly_affected = 0
sum_affected = already_affected + 0.0
part_a_affecter = (remaining_prod * conso_k) / total_conso
sum_affected = min(conso_k, (already_affected + part_a_affecter))
newly_affected = sum_affected - already_affected
data[slot]["affect"][counter] = sum_affected
total_affecte += newly_affected
# on met à jour la prod restant à affecter

Stéphane - Enercoop
a validé
data[slot]["prod_totale"] = remaining_prod - total_affecte
# possiblement on peut avoir affecté plus que la production total_affecte=496.00000000000006
return data

Stéphane - Enercoop
a validé
def _quotepart(self, data):
total_share = self.total_share
for slot in data:
remaining_prod = data.get(slot).get("prod_totale")
total_affecte = 0.0
if not data.get(slot).get("affect"):
data[slot]["affect"] = {}
for priority_group_counter in self.acc_priority_group_counter_ids:
counter = priority_group_counter.acc_counter_id
already_affected = data.get(slot).get("affect").get(counter, 0)

Stéphane - Enercoop
a validé
counter_share = priority_group_counter.acc_counter_share
conso_k = data.get(slot).get("conso").get(counter.name)
if (
remaining_prod <= 0

Stéphane - Enercoop
a validé
or total_share == 0
or conso_k is None
or counter_share == 0
):
newly_affected = 0
sum_affected = already_affected + 0.0

Stéphane - Enercoop
a validé
else:
part_a_affecter = (remaining_prod * counter_share) / total_share
sum_affected = min(conso_k, (already_affected + part_a_affecter))
newly_affected = sum_affected - already_affected
data[slot]["affect"][counter] = sum_affected
total_affecte += newly_affected

Stéphane - Enercoop
a validé
data[slot]["prod_totale"] = remaining_prod - total_affecte