From 389b188827de6659879712adf1d400f39103e6d8 Mon Sep 17 00:00:00 2001
From: daniquilez <dani.quilez@gmail.com>
Date: Fri, 21 Feb 2025 18:23:55 +0100
Subject: [PATCH] =?UTF-8?q?[IMP]=20=E2=9C=A8=20More=20permissive=20ways=20?=
 =?UTF-8?q?of=20modifying=20and=20reopening=20contracts?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../__manifest__.py                           |  1 +
 .../components/contract_utils.py              |  5 +++-
 .../models/__init__.py                        |  1 +
 .../models/contract.py                        |  3 +-
 .../models/contract_line.py                   | 15 ++++++++--
 .../models/contract_template.py               |  5 ++--
 .../models/res_company.py                     |  2 +-
 .../models/service_invoicing_info_mixin.py    | 28 +++++++++++++++++++
 energy_communities_service_invoicing/utils.py | 15 ----------
 .../views/contract_template_views.xml         | 12 ++++++++
 .../service_invoicing_action_create.py        | 14 ++--------
 11 files changed, 67 insertions(+), 34 deletions(-)
 create mode 100644 energy_communities_service_invoicing/models/service_invoicing_info_mixin.py
 create mode 100644 energy_communities_service_invoicing/views/contract_template_views.xml

diff --git a/energy_communities_service_invoicing/__manifest__.py b/energy_communities_service_invoicing/__manifest__.py
index 5a979d294..a3ec60b9e 100644
--- a/energy_communities_service_invoicing/__manifest__.py
+++ b/energy_communities_service_invoicing/__manifest__.py
@@ -30,6 +30,7 @@
         "data/contract_line_qty_formula_data.xml",
         "data/product_data.xml",
         "views/contract_line_formula_views.xml",
+        "views/contract_template_views.xml",
         "views/contract_views.xml",
         "views/res_company_views.xml",
         "views/res_partner_views.xml",
diff --git a/energy_communities_service_invoicing/components/contract_utils.py b/energy_communities_service_invoicing/components/contract_utils.py
index 101bee90a..c0cd319e4 100644
--- a/energy_communities_service_invoicing/components/contract_utils.py
+++ b/energy_communities_service_invoicing/components/contract_utils.py
@@ -39,7 +39,10 @@ class ContractUtils(Component):
 
     def set_contract_status_closed(self, execution_date):
         for line in self.work.record.contract_line_ids:
-            if self.work.record.status == "ready_to_start":
+            if (
+                self.work.record.status == "ready_to_start"
+                or self.work.record.is_free_pack
+            ):
                 self._activate_contract_lines(execution_date)
             line.write({"date_end": execution_date})
             line._compute_state()
diff --git a/energy_communities_service_invoicing/models/__init__.py b/energy_communities_service_invoicing/models/__init__.py
index 7ba9edcc6..4c3afbbec 100644
--- a/energy_communities_service_invoicing/models/__init__.py
+++ b/energy_communities_service_invoicing/models/__init__.py
@@ -1,3 +1,4 @@
+from . import service_invoicing_info_mixin
 from . import abstract_contract
 from . import account_move
 from . import contract
diff --git a/energy_communities_service_invoicing/models/contract.py b/energy_communities_service_invoicing/models/contract.py
index b06d5d759..acadcae8f 100644
--- a/energy_communities_service_invoicing/models/contract.py
+++ b/energy_communities_service_invoicing/models/contract.py
@@ -41,6 +41,7 @@ class ContractContract(models.Model):
         string="Last Date Invoiced", compute="_compute_last_date_invoiced", store=False
     )
     is_pack = fields.Boolean(related="contract_template_id.is_pack")
+    is_free_pack = fields.Boolean(related="contract_template_id.is_free_pack")
     related_contract_product_ids = fields.One2many(
         "product.product",
         string="Related services",
@@ -216,7 +217,7 @@ class ContractContract(models.Model):
         )
 
     def set_close_status_type_by_date(self):
-        if self.date_end.strftime("%Y-%m-%d") == datetime.now().strftime("%Y-%m-%d"):
+        if self.date_end.strftime("%Y-%m-%d") <= datetime.now().strftime("%Y-%m-%d"):
             self.write({"status": "closed"})
         else:
             self.write({"status": "closed_planned"})
diff --git a/energy_communities_service_invoicing/models/contract_line.py b/energy_communities_service_invoicing/models/contract_line.py
index ab5763ec7..3bed75255 100644
--- a/energy_communities_service_invoicing/models/contract_line.py
+++ b/energy_communities_service_invoicing/models/contract_line.py
@@ -13,6 +13,15 @@ class ContractLine(models.Model):
         for record in self:
             record.is_cancel_allowed = True
 
-    # TODO:
-    # skip last_date_invoice validation for modification action if contract is ready to start or active on free plan.
-    # def _check_last_date_invoiced(self):
+    # skip last_date_invoice update for modification action if contract is ready to start or on free plan.
+    def _update_recurring_next_date(self):
+        # TODO: Pay attention to original code in order to detect if method has been renamed:
+        # FIXME: Change method name according to real updated field
+        # e.g.: _update_last_date_invoiced()
+        for record in self:
+            if (
+                record.contract_id.status != "ready_to_start"
+                or record.contract_id.is_free_pack
+            ):
+                return
+        super()._update_recurring_next_date()
diff --git a/energy_communities_service_invoicing/models/contract_template.py b/energy_communities_service_invoicing/models/contract_template.py
index 80fd7506e..c4008db80 100644
--- a/energy_communities_service_invoicing/models/contract_template.py
+++ b/energy_communities_service_invoicing/models/contract_template.py
@@ -6,6 +6,7 @@ class ContractTemplate(models.Model):
     _inherit = "contract.template"
 
     is_pack = fields.Boolean(compute="compute_is_pack", store=True)
+    is_free_pack = fields.Boolean(string="Is a free pack")
 
     def compute_is_pack(self):
         try:
@@ -14,8 +15,8 @@ class ContractTemplate(models.Model):
             ).id
         except:
             categ_id = False
-        if categ_id:
-            for record in self:
+        for record in self:
+            if categ_id:
                 record.is_pack = bool(
                     self.env["product.template"].search(
                         [
diff --git a/energy_communities_service_invoicing/models/res_company.py b/energy_communities_service_invoicing/models/res_company.py
index 6d8d8bf50..11701aaea 100644
--- a/energy_communities_service_invoicing/models/res_company.py
+++ b/energy_communities_service_invoicing/models/res_company.py
@@ -4,7 +4,7 @@ from odoo.tools.translate import _
 
 class ResCompany(models.Model):
     _name = "res.company"
-    _inherit = "res.company"
+    _inherit = ["res.company"]
 
     service_invoicing_journal_id = fields.Many2one(
         comodel_name="account.journal",
diff --git a/energy_communities_service_invoicing/models/service_invoicing_info_mixin.py b/energy_communities_service_invoicing/models/service_invoicing_info_mixin.py
new file mode 100644
index 000000000..a1bb3b721
--- /dev/null
+++ b/energy_communities_service_invoicing/models/service_invoicing_info_mixin.py
@@ -0,0 +1,28 @@
+from odoo import api, fields, models
+
+
+class ServiceInvoicingInfoMixin(models.AbstractModel):
+    _name = "service.invoicing.info.mixin"
+    _description = "Get info about current service invoicing configuration"
+
+    pack_product_product_ids = fields.Many2many(
+        comodel_name="product.product",
+        _compute="_compute_pack_product_product_ids",
+        store=False,
+    )
+
+    @api.depends("name")
+    def _compute_pack_product_product_ids(self):
+        for record in self:
+            pack_product_product_ids = []
+            record.pack_product_product_ids = self.env["product.product"].search(
+                [
+                    (
+                        "categ_id",
+                        "=",
+                        self.env.ref(
+                            "energy_communities_service_invoicing.product_category_pack"
+                        ).id,
+                    )
+                ]
+            )
diff --git a/energy_communities_service_invoicing/utils.py b/energy_communities_service_invoicing/utils.py
index f64fd894c..47feda5bc 100644
--- a/energy_communities_service_invoicing/utils.py
+++ b/energy_communities_service_invoicing/utils.py
@@ -45,21 +45,6 @@ def raise_existing_same_open_contract_error():
     )
 
 
-def get_pack_product_product_ids(env):
-    ret = env["product.product"].search(
-        [
-            (
-                "categ_id",
-                "=",
-                env.ref(
-                    "energy_communities_service_invoicing.product_category_pack"
-                ).id,
-            )
-        ]
-    )
-    return ret
-
-
 def get_existing_open_contract(
     env, partner_id, community_company_id, contract_id=False
 ):
diff --git a/energy_communities_service_invoicing/views/contract_template_views.xml b/energy_communities_service_invoicing/views/contract_template_views.xml
new file mode 100644
index 000000000..dfb1bece1
--- /dev/null
+++ b/energy_communities_service_invoicing/views/contract_template_views.xml
@@ -0,0 +1,12 @@
+<odoo>
+<record id="contract_template_form_view" model="ir.ui.view">
+  <field name="name">contract.template form view (in energy_communities service_invoicing)</field>
+  <field name="model">contract.template</field>
+  <field name="inherit_id" ref="contract.contract_template_form_view" />
+  <field name="arch" type="xml">
+    <xpath expr="//field[@name='contract_type']" position="after">
+      <field name="is_free_pack" />
+    </xpath>
+  </field>
+</record>
+</odoo>
diff --git a/energy_communities_service_invoicing/wizards/service_invoicing_action_create.py b/energy_communities_service_invoicing/wizards/service_invoicing_action_create.py
index 290ddba4a..3dfce8f31 100644
--- a/energy_communities_service_invoicing/wizards/service_invoicing_action_create.py
+++ b/energy_communities_service_invoicing/wizards/service_invoicing_action_create.py
@@ -12,7 +12,6 @@ from odoo.addons.energy_communities.utils import (
 from ..utils import (
     get_existing_last_closed_contract,
     get_existing_open_contract,
-    get_pack_product_product_ids,
     raise_existing_same_open_contract_error,
     service_invoicing_view,
 )
@@ -21,7 +20,7 @@ from ..utils import (
 class ServiceInvoicingActionCreateWizard(models.TransientModel):
     _name = "service.invoicing.action.create.wizard"
     _description = "Create service invoicing for an energy community"
-    _inherit = ["user.currentcompany.mixin"]
+    _inherit = ["user.currentcompany.mixin", "service.invoicing.info.mixin"]
 
     company_id = fields.Many2one("res.company", string="Coordinator")
     community_company_id = fields.Many2one(
@@ -33,6 +32,7 @@ class ServiceInvoicingActionCreateWizard(models.TransientModel):
         "product.product",
         string="Service pack",
         domain="[('id', 'in', pack_product_product_ids)]",
+        precompute=True,
     )
     payment_mode_id = fields.Many2one(
         "account.payment.mode",
@@ -52,11 +52,6 @@ class ServiceInvoicingActionCreateWizard(models.TransientModel):
         _compute="_compute_ allowed_payment_mode_ids",
         store=False,
     )
-    pack_product_product_ids = fields.Many2many(
-        comodel_name="product.product",
-        _compute="_compute_pack_product_product_ids",
-        store=False,
-    )
 
     @api.depends("company_id")
     def _compute_allowed_community_company_ids(self):
@@ -74,15 +69,12 @@ class ServiceInvoicingActionCreateWizard(models.TransientModel):
                 [("company_id", "=", self.user_current_company.id)]
             )
 
-    def _compute_pack_product_product_ids(self):
-        for record in self:
-            record.pack_product_product_ids = get_pack_product_product_ids(self.env)
-
     @api.onchange("company_id")
     def _on_change_company_id(self):
         for record in self:
             record._compute_allowed_community_company_ids()
             record._compute_allowed_payment_mode_ids()
+            # TODO: This should be necessary if pack_product_product_ids gets properly auto computed
             record._compute_pack_product_product_ids()
 
     def execute_create(self):
-- 
GitLab