Skip to content
Extraits de code Groupes Projets
acc_priority_group.py 8,33 ko
Newer Older
  • Learn to ignore specific revisions
  • 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"),
    
                ("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",
    
    Julien - Le Filament's avatar
    Julien - Le Filament a validé
            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")
    
        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)
        # ------------------------------------------------------
    
    Julien - Le Filament's avatar
    Julien - Le Filament a validé
        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)]
            )
    
    Julien - Le Filament's avatar
    Julien - Le Filament a validé
            seq = 0
    
            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:
    
    Julien - Le Filament's avatar
    Julien - Le Filament a validé
                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,
    
            }
            d = compute_algo[self.type_algo](data)
            return d
    
        def get_conso_sum(self, data_slot):
    
            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:
    
                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
    
                data[slot]["prod_totale"] = remaining_prod - total_affecte
                # possiblement on peut avoir affecté plus que la production total_affecte=496.00000000000006
    
            return data
    
        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)
    
                    counter_share = priority_group_counter.acc_counter_share
                    conso_k = data.get(slot).get("conso").get(counter.name)
                    if (
    
                        or total_share == 0
                        or conso_k is None
                        or counter_share == 0
                    ):
    
                        newly_affected = 0
                        sum_affected = already_affected + 0.0
    
                    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
    
                data[slot]["prod_totale"] = remaining_prod - total_affecte
    
            return data