Skip to content

Commit a41cafe

Browse files
committed
[MIG] product_contract: Migration to 16.0
1 parent b3f1fa3 commit a41cafe

11 files changed

+109
-90
lines changed

Diff for: product_contract/README.rst

+13-10
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
Recurring - Product Contract
33
============================
44

5-
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
67
!! This file is generated by oca-gen-addon-readme !!
78
!! changes will be overwritten. !!
89
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:ad8724fbb6c54e3f450ed7f3b3aa16384ed79b097065f0de96cc56e87eef2e71
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
912
1013
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
1114
:target: https://odoo-community.org/page/development-status
@@ -14,16 +17,16 @@ Recurring - Product Contract
1417
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
1518
:alt: License: AGPL-3
1619
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github
17-
:target: https://github.com/OCA/contract/tree/14.0/product_contract
20+
:target: https://github.com/OCA/contract/tree/16.0/product_contract
1821
:alt: OCA/contract
1922
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
20-
:target: https://translation.odoo-community.org/projects/contract-14-0/contract-14-0-product_contract
23+
:target: https://translation.odoo-community.org/projects/contract-16-0/contract-16-0-product_contract
2124
:alt: Translate me on Weblate
22-
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
23-
:target: https://runbot.odoo-community.org/runbot/110/14.0
24-
:alt: Try me on Runbot
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/contract&target_branch=16.0
27+
:alt: Try me on Runboat
2528

26-
|badge1| |badge2| |badge3| |badge4| |badge5|
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
2730

2831
This module adds support for products to be linked to contract templates.
2932

@@ -51,8 +54,8 @@ Bug Tracker
5154

5255
Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/issues>`_.
5356
In case of trouble, please check there if your issue has already been reported.
54-
If you spotted it first, help us smashing it by providing a detailed and welcomed
55-
`feedback <https://github.com/OCA/contract/issues/new?body=module:%20product_contract%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
57+
If you spotted it first, help us to smash it by providing a detailed and welcomed
58+
`feedback <https://github.com/OCA/contract/issues/new?body=module:%20product_contract%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
5659

5760
Do not contact contributors directly about support or help with technical issues.
5861

@@ -96,6 +99,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
9699

97100
|maintainer-sbejaoui|
98101

99-
This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/14.0/product_contract>`_ project on GitHub.
102+
This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/16.0/product_contract>`_ project on GitHub.
100103

101104
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

Diff for: product_contract/__manifest__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
{
66
"name": "Recurring - Product Contract",
7-
"version": "14.0.1.0.1",
7+
"version": "16.0.1.0.0",
88
"category": "Contract Management",
99
"license": "AGPL-3",
1010
"author": "LasLabs, " "ACSONE SA/NV, " "Odoo Community Association (OCA)",

Diff for: product_contract/models/contract_line.py

+31-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
44

55

6-
from odoo import api, fields, models
6+
from odoo import Command, api, fields, models
77

88

99
class ContractLine(models.Model):
@@ -17,10 +17,10 @@ class ContractLine(models.Model):
1717
copy=False,
1818
)
1919

20-
def _prepare_invoice_line(self, move_form):
21-
res = super(ContractLine, self)._prepare_invoice_line(move_form)
20+
def _prepare_invoice_line(self):
21+
res = super()._prepare_invoice_line()
2222
if self.sale_order_line_id and res:
23-
res["sale_line_ids"] = [(6, 0, [self.sale_order_line_id.id])]
23+
res["sale_line_ids"] = [Command.set([self.sale_order_line_id.id])]
2424
return res
2525

2626
def _get_auto_renew_rule_type(self):
@@ -37,9 +37,6 @@ def _onchange_product_id_recurring_info(self):
3737
if rec.product_id.is_contract:
3838
rec.update(
3939
{
40-
"recurring_rule_type": rec.product_id.recurring_rule_type,
41-
"recurring_invoicing_type": rec.product_id.recurring_invoicing_type,
42-
"recurring_interval": 1,
4340
"is_auto_renew": rec.product_id.is_auto_renew,
4441
"auto_renew_interval": rec.product_id.auto_renew_interval,
4542
"auto_renew_rule_type": rec.product_id.auto_renew_rule_type,
@@ -51,3 +48,30 @@ def _onchange_product_id_recurring_info(self):
5148
),
5249
}
5350
)
51+
52+
def _set_recurrence_field(self, field):
53+
res = super()._set_recurrence_field(field)
54+
for record in self:
55+
if record.product_id.is_contract and field in record.product_id:
56+
record[field] = record.product_id[field]
57+
return res
58+
59+
@api.depends(
60+
"contract_id.recurring_rule_type", "contract_id.line_recurrence", "product_id"
61+
)
62+
def _compute_recurring_rule_type(self):
63+
return super()._compute_recurring_rule_type()
64+
65+
@api.depends(
66+
"contract_id.recurring_invoicing_type",
67+
"contract_id.line_recurrence",
68+
"product_id",
69+
)
70+
def _compute_recurring_invoicing_type(self):
71+
return super()._compute_recurring_invoicing_type()
72+
73+
@api.depends(
74+
"contract_id.recurring_interval", "contract_id.line_recurrence", "product_id"
75+
)
76+
def _compute_recurring_interval(self):
77+
return super()._compute_recurring_interval()

Diff for: product_contract/models/product_template.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ def write(self, vals):
6868
self.with_company(company).write(
6969
{"property_contract_template_id": False}
7070
)
71-
super().write(vals)
71+
return super().write(vals)
7272

7373
@api.constrains("is_contract", "type")
7474
def _check_contract_product_type(self):
7575
"""
7676
Contract product should be service type
7777
"""
78-
if self.is_contract and self.type != "service":
78+
if any([product.is_contract and product.type != "service" for product in self]):
7979
raise ValidationError(_("Contract product should be service type"))

Diff for: product_contract/models/sale_order.py

+12-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class SaleOrder(models.Model):
1414
need_contract_creation = fields.Boolean(compute="_compute_need_contract_creation")
1515

1616
@api.constrains("state")
17-
def _check_contact_is_not_terminated(self):
17+
def _check_contract_is_not_terminated(self):
1818
for rec in self:
1919
if rec.state not in (
2020
"sale",
@@ -49,17 +49,15 @@ def _compute_is_contract(self):
4949
def _prepare_contract_value(self, contract_template):
5050
self.ensure_one()
5151
return {
52-
"name": "{template_name}: {sale_name}".format(
53-
template_name=contract_template.name, sale_name=self.name
54-
),
52+
"name": f"{contract_template.name}: {self.name}",
5553
"partner_id": self.partner_id.id,
5654
"company_id": self.company_id.id,
5755
"contract_template_id": contract_template.id,
5856
"user_id": self.user_id.id,
5957
"payment_term_id": self.payment_term_id.id,
6058
"fiscal_position_id": self.fiscal_position_id.id,
6159
"invoice_partner_id": self.partner_invoice_id.id,
62-
"line_recurrence": self.partner_invoice_id.id,
60+
"line_recurrence": True,
6361
}
6462

6563
def action_create_contract(self):
@@ -84,8 +82,13 @@ def action_create_contract(self):
8482
raise ValidationError(
8583
_(
8684
"You must specify a contract "
87-
"template for '{}' product in '{}' company."
88-
).format(order_line.product_id.name, rec.company_id.name)
85+
"template for '%(product_name)s' product "
86+
"in '%(company_name)s' company."
87+
)
88+
% {
89+
"product_name": order_line.product_id.name,
90+
"company_name": rec.company_id.name,
91+
}
8992
)
9093
contract_templates |= contract_template
9194
for contract_template in contract_templates:
@@ -98,7 +101,7 @@ def action_create_contract(self):
98101
contract = contract_model.create(
99102
rec._prepare_contract_value(contract_template)
100103
)
101-
contracts.append(contract)
104+
contracts.append(contract.id)
102105
contract._onchange_contract_template_id()
103106
contract._onchange_contract_type()
104107
order_lines.create_contract_line(contract)
@@ -112,7 +115,7 @@ def action_confirm(self):
112115
self.filtered(
113116
lambda order: (order.company_id.create_contract_at_sale_order_confirmation)
114117
).action_create_contract()
115-
return super(SaleOrder, self).action_confirm()
118+
return super().action_confirm()
116119

117120
@api.depends("order_line")
118121
def _compute_contract_count(self):

Diff for: product_contract/models/sale_order_line.py

+12-26
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class SaleOrderLine(models.Model):
4343
help="Specify if process date is 'from' or 'to' invoicing date",
4444
copy=False,
4545
)
46-
date_start = fields.Date(string="Date Start")
47-
date_end = fields.Date(string="Date End")
46+
date_start = fields.Date()
47+
date_end = fields.Date()
4848

4949
contract_line_id = fields.Many2one(
5050
comodel_name="contract.line",
@@ -93,7 +93,7 @@ def _check_contact_is_not_terminated(self):
9393
_("You can't upsell or downsell a terminated contract")
9494
)
9595

96-
@api.depends("product_id")
96+
@api.depends("product_id", "order_id.company_id")
9797
def _compute_contract_template_id(self):
9898
for rec in self:
9999
rec.contract_template_id = rec.product_id.with_company(
@@ -141,21 +141,13 @@ def onchange_date_start(self):
141141
rec.date_end = rec._get_date_end() if rec.date_start else False
142142

143143
def _get_contract_line_qty(self):
144-
"""Returns the quantity to be put on new contract lines."""
144+
"""Returns the amount that will be placed in new contract lines."""
145145
self.ensure_one()
146-
# The quantity on the generated contract line is 1, as it
147-
# correspond to the most common use cases:
148-
# - quantity on the SO line = number of periods sold and unit
149-
# price the price of one period, so the
150-
# total amount of the SO corresponds to the planned value
151-
# of the contract; in this case the quantity on the contract
152-
# line must be 1
153-
# - quantity on the SO line = number of hours sold,
154-
# automatic invoicing of the actual hours through a variable
155-
# quantity formula, in which case the quantity on the contract
156-
# line is not used
146+
# The quantity in the generated contract line is the quantity of
147+
# product requested in the order, since they correspond to the most common
148+
# use cases.
157149
# Other use cases are easy to implement by overriding this method.
158-
return 1.0
150+
return self.product_uom_qty
159151

160152
def _prepare_contract_line_values(
161153
self, contract, predecessor_contract_line_id=False
@@ -198,7 +190,7 @@ def _prepare_contract_line_values(
198190
"contract_id": contract.id,
199191
"sale_order_line_id": self.id,
200192
"predecessor_contract_line_id": predecessor_contract_line_id,
201-
"analytic_account_id": self.order_id.analytic_account_id.id,
193+
"analytic_distribution": self.analytic_distribution,
202194
}
203195

204196
def create_contract_line(self, contract):
@@ -269,17 +261,11 @@ def invoice_line_create(self, invoice_id, qty):
269261
SaleOrderLine, self.filtered(lambda l: not l.contract_id)
270262
).invoice_line_create(invoice_id, qty)
271263

272-
@api.depends(
273-
"qty_invoiced",
274-
"qty_delivered",
275-
"product_uom_qty",
276-
"order_id.state",
277-
"product_id.is_contract",
278-
)
279-
def _get_to_invoice_qty(self):
264+
@api.depends("qty_invoiced", "qty_delivered", "product_uom_qty", "state")
265+
def _compute_qty_to_invoice(self):
280266
"""
281267
sale line linked to contracts must not be invoiced from sale order
282268
"""
283-
res = super()._get_to_invoice_qty()
269+
res = super()._compute_qty_to_invoice()
284270
self.filtered("product_id.is_contract").update({"qty_to_invoice": 0.0})
285271
return res

0 commit comments

Comments
 (0)