diff --git a/contract/__manifest__.py b/contract/__manifest__.py
index b744df482..d9c67b1be 100644
--- a/contract/__manifest__.py
+++ b/contract/__manifest__.py
@@ -30,6 +30,7 @@
"data/contract_cron.xml",
"data/contract_renew_cron.xml",
"data/mail_template.xml",
+ "data/template_mail_notification.xml",
"data/mail_message_subtype.xml",
"data/ir_ui_menu.xml",
"wizards/contract_line_wizard.xml",
diff --git a/contract/data/mail_template.xml b/contract/data/mail_template.xml
index 1a6f06666..51e78cf1d 100644
--- a/contract/data/mail_template.xml
+++ b/contract/data/mail_template.xml
@@ -112,47 +112,4 @@
We have modifications on the contract that we want to notify you.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Date |
- Description |
-
-
-
-
-
- |
-
- |
-
-
- |
-
-
-
-
-
-
diff --git a/contract/data/template_mail_notification.xml b/contract/data/template_mail_notification.xml
new file mode 100644
index 000000000..a22b5e138
--- /dev/null
+++ b/contract/data/template_mail_notification.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | Date |
+ Description |
+
+
+
+
+
+ |
+
+ |
+
+
+ |
+
+
+
+
+
+
+
diff --git a/contract/models/abstract_contract.py b/contract/models/abstract_contract.py
index 377f32f14..eacea2bfe 100644
--- a/contract/models/abstract_contract.py
+++ b/contract/models/abstract_contract.py
@@ -48,6 +48,19 @@ class ContractAbstractContract(models.AbstractModel):
help="Mark this check if you want to control recurrrence at line level instead"
" of all together for the whole contract.",
)
+ generation_type = fields.Selection(
+ selection=lambda self: self._selection_generation_type(),
+ default=lambda self: self._default_generation_type(),
+ help="Choose the document that will be automatically generated by cron.",
+ )
+
+ @api.model
+ def _selection_generation_type(self):
+ return [("invoice", "Invoice")]
+
+ @api.model
+ def _default_generation_type(self):
+ return "invoice"
@api.onchange("contract_type")
def _onchange_contract_type(self):
diff --git a/contract/models/contract.py b/contract/models/contract.py
index 4b588375e..a09f7a815 100644
--- a/contract/models/contract.py
+++ b/contract/models/contract.py
@@ -6,12 +6,16 @@
# Copyright 2018 ACSONE SA/NV
# Copyright 2021 Tecnativa - Víctor Martínez
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+import logging
from odoo import api, fields, models
from odoo.exceptions import UserError, ValidationError
+from odoo.osv import expression
from odoo.tests import Form
from odoo.tools.translate import _
+_logger = logging.getLogger(__name__)
+
class ContractContract(models.Model):
_name = "contract.contract"
@@ -607,23 +611,46 @@ class ContractContract(models.Model):
return moves
@api.model
- def cron_recurring_create_invoice(self, date_ref=None):
+ def _get_recurring_create_func(self, create_type="invoice"):
+ """
+ Allows to retrieve the recurring create function depending
+ on generate_type attribute
+ """
+ if create_type == "invoice":
+ return self.__class__._recurring_create_invoice
+
+ @api.model
+ def _cron_recurring_create(self, date_ref=False, create_type="invoice"):
+ """
+ The cron function in order to create recurrent documents
+ from contracts.
+ """
+ _recurring_create_func = self._get_recurring_create_func(
+ create_type=create_type
+ )
if not date_ref:
date_ref = fields.Date.context_today(self)
domain = self._get_contracts_to_invoice_domain(date_ref)
- invoices = self.env["account.move"]
+ domain = expression.AND(
+ [
+ domain,
+ [("generation_type", "=", create_type)],
+ ]
+ )
+ contracts = self.search(domain)
+ companies = set(contracts.mapped("company_id"))
# Invoice by companies, so assignation emails get correct context
- companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"])
- for row in companies_to_invoice:
- contracts_to_invoice = (
- self.search(row["__domain"])
- .with_context(allowed_company_ids=[row["company_id"][0]])
- .filtered(
- lambda a: not a.date_end or a.recurring_next_date <= a.date_end
- )
- )
- invoices |= contracts_to_invoice._recurring_create_invoice(date_ref)
- return invoices
+ for company in companies:
+ contracts_to_invoice = contracts.filtered(
+ lambda c: c.company_id == company
+ and (not c.date_end or c.recurring_next_date <= c.date_end)
+ ).with_company(company)
+ _recurring_create_func(contracts_to_invoice, date_ref)
+ return True
+
+ @api.model
+ def cron_recurring_create_invoice(self, date_ref=None):
+ return self._cron_recurring_create(date_ref, create_type="invoice")
def action_terminate_contract(self):
self.ensure_one()
diff --git a/contract/security/contract_security.xml b/contract/security/contract_security.xml
index a3e7249a1..d4769b3c5 100644
--- a/contract/security/contract_security.xml
+++ b/contract/security/contract_security.xml
@@ -40,4 +40,16 @@
name="domain_force"
>['|',('company_id','=',False),('company_id','in',company_ids)]
+
+
+ See All Contracts
+
+ [(1,'=',1)]
+
+
diff --git a/contract/tests/__init__.py b/contract/tests/__init__.py
index 9de1b60ae..9a3586ace 100644
--- a/contract/tests/__init__.py
+++ b/contract/tests/__init__.py
@@ -1,5 +1,4 @@
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-
from . import test_contract
from . import test_contract_manually_create_invoice
from . import test_portal
+from . import test_multicompany
diff --git a/contract/tests/test_multicompany.py b/contract/tests/test_multicompany.py
new file mode 100644
index 000000000..395d5d2e5
--- /dev/null
+++ b/contract/tests/test_multicompany.py
@@ -0,0 +1,110 @@
+# Copyright 2021 ACSONE SA/NV ()
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from .test_contract import TestContractBase
+
+
+class ContractMulticompanyCase(TestContractBase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ chart_template = cls.env.ref("l10n_generic_coa.configurable_chart_template")
+ cls.company_obj = cls.env["res.company"]
+ cls.company_1 = cls.env.ref("base.main_company")
+ vals = {"name": "Company 2"}
+ cls.company_2 = cls.company_obj.create(vals)
+ chart_template.try_loading(company=cls.company_2)
+ cls.env.user.company_ids |= cls.company_2
+
+ cls.contract_mc = (
+ cls.env["contract.contract"]
+ .with_company(cls.company_2)
+ .create(
+ {
+ "name": "Test Contract MC",
+ "partner_id": cls.partner.id,
+ "pricelist_id": cls.partner.property_product_pricelist.id,
+ "line_recurrence": True,
+ "contract_type": "purchase",
+ "contract_line_ids": [
+ (
+ 0,
+ 0,
+ {
+ "product_id": cls.product_1.id,
+ "name": "Services from #START# to #END#",
+ "quantity": 1,
+ "uom_id": cls.product_1.uom_id.id,
+ "price_unit": 100,
+ "discount": 50,
+ "recurring_rule_type": "monthly",
+ "recurring_interval": 1,
+ "date_start": "2018-02-15",
+ "recurring_next_date": "2018-02-22",
+ },
+ )
+ ],
+ }
+ )
+ )
+ cls.line_vals = {
+ "contract_id": cls.contract_mc.id,
+ "product_id": cls.product_1.id,
+ "name": "Services from #START# to #END#",
+ "quantity": 1,
+ "uom_id": cls.product_1.uom_id.id,
+ "price_unit": 100,
+ "discount": 50,
+ "recurring_rule_type": "monthly",
+ "recurring_interval": 1,
+ "date_start": "2018-01-01",
+ "recurring_next_date": "2018-01-15",
+ "is_auto_renew": False,
+ }
+ cls.acct_line_mc = (
+ cls.env["contract.line"].with_company(cls.company_2).create(cls.line_vals)
+ )
+
+ def test_cron_recurring_create_invoice_multi_company(self):
+ self.acct_line.date_start = "2018-01-01"
+ self.acct_line.recurring_invoicing_type = "post-paid"
+ self.acct_line.date_end = "2018-03-15"
+
+ self.acct_line_mc.date_start = "2018-01-01"
+ self.acct_line_mc.recurring_invoicing_type = "post-paid"
+ self.acct_line_mc.date_end = "2018-03-15"
+
+ contracts = self.contract2
+ contracts_company_2 = self.env["contract.contract"].browse()
+ for _i in range(10):
+ contracts |= self.contract.copy()
+ for _i in range(10):
+ vals = (
+ self.contract_mc.with_company(company=self.company_2)
+ .with_context(active_test=False)
+ .copy_data({"company_id": self.company_2.id})
+ )
+ contracts_company_2 |= self.contract_mc.with_company(
+ company=self.company_2
+ ).create(vals)
+ self.env["contract.contract"].cron_recurring_create_invoice()
+ # Check company 1
+ invoice_lines_company_1 = self.env["account.move.line"].search(
+ [("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)]
+ )
+ invoice_lines_company_2 = self.env["account.move.line"].search(
+ [
+ (
+ "contract_line_id",
+ "in",
+ contracts_company_2.mapped("contract_line_ids").ids,
+ )
+ ]
+ )
+ self.assertEqual(
+ len(contracts.mapped("contract_line_ids")), len(invoice_lines_company_1)
+ )
+ self.assertEqual(
+ len(contracts_company_2.mapped("contract_line_ids")),
+ len(invoice_lines_company_2),
+ )
diff --git a/contract/views/contract.xml b/contract/views/contract.xml
index b788f4289..b28e6f8a1 100644
--- a/contract/views/contract.xml
+++ b/contract/views/contract.xml
@@ -40,7 +40,7 @@
@@ -82,6 +82,7 @@
type="object"
icon="fa-list"
class="oe_stat_button"
+ attrs="{'invisible': [('generation_type','!=','invoice')]}"
>
+
+
+