Skip to content

Commit

Permalink
Merge PR #1188 into 17.0
Browse files Browse the repository at this point in the history
Signed-off-by pedrobaeza
  • Loading branch information
OCA-git-bot committed Jan 28, 2025
2 parents caab7b2 + 6629826 commit f91a487
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 101 deletions.
19 changes: 10 additions & 9 deletions product_contract/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ To use this module, you need to:
Known issues / Roadmap
======================

- There's no support right now for computing the start date for the
following recurrent types: daily, weekly and monthlylastday.
- There's no support right now for computing the start date for the
following recurrent types: daily, weekly and monthlylastday.

Bug Tracker
===========
Expand All @@ -90,15 +90,16 @@ Authors
Contributors
------------

- Ted Salmon <[email protected]>
- Souheil Bejaoui <[email protected]>
- `Tecnativa <https://www.tecnativa.com>`__:
- Ted Salmon <[email protected]>
- Souheil Bejaoui <[email protected]>
- `Tecnativa <https://www.tecnativa.com>`__:

- Ernesto Tejeda
- Pedro M. Baeza
- Carlos Roca
- Ernesto Tejeda
- Pedro M. Baeza
- Carlos Roca
- Sergio Teruel

- David Jaen <[email protected]>
- David Jaen <[email protected]>

Maintainers
-----------
Expand Down
112 changes: 71 additions & 41 deletions product_contract/models/sale_order_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,32 @@ class SaleOrderLine(models.Model):
string="Contract Template",
compute="_compute_contract_template_id",
)
recurring_interval = fields.Integer(
default=1,
string="Invoice Every",
help="Invoice every (Days/Week/Month/Year)",
)
recurring_rule_type = fields.Selection(related="product_id.recurring_rule_type")
recurring_invoicing_type = fields.Selection(
related="product_id.recurring_invoicing_type"
)
date_start = fields.Date()
date_end = fields.Date()

date_start = fields.Date(
compute="_compute_date_start", readonly=False, store=True, precompute=True
)
date_end = fields.Date(
compute="_compute_date_end", readonly=False, store=True, precompute=True
)
contract_line_id = fields.Many2one(
comodel_name="contract.line",
string="Contract Line to replace",
required=False,
copy=False,
)
is_auto_renew = fields.Boolean(
string="Auto Renew",
compute="_compute_auto_renew",
default=False,
store=True,
readonly=False,
precompute=True,
)
auto_renew_interval = fields.Integer(
default=1,
Expand All @@ -57,6 +64,7 @@ class SaleOrderLine(models.Model):
store=True,
readonly=False,
help="Renew every (Days/Week/Month/Year)",
precompute=True,
)
auto_renew_rule_type = fields.Selection(
[
Expand All @@ -71,6 +79,7 @@ class SaleOrderLine(models.Model):
readonly=False,
string="Renewal type",
help="Specify Interval for automatic renewal.",
precompute=True,
)
contract_start_date_method = fields.Selection(
related="product_id.contract_start_date_method"
Expand All @@ -97,47 +106,68 @@ def _compute_contract_template_id(self):
rec.order_id.company_id
).property_contract_template_id

def _get_auto_renew_rule_type(self):
"""monthly last day don't make sense for auto_renew_rule_type"""
self.ensure_one()
if self.recurring_rule_type == "monthlylastday":
return "monthly"
return self.recurring_rule_type
@api.depends("product_id")
def _compute_date_start(self):
for sol in self:
if sol.contract_start_date_method == "start_this":
sol.date_start = sol.order_id.date_order.replace(day=1)
elif sol.contract_start_date_method == "end_this":
sol.date_start = (
sol.order_id.date_order
+ self.get_relative_delta(
sol.recurring_rule_type, sol.product_id.default_qty
)
).replace(day=1) - relativedelta(days=1)
elif sol.contract_start_date_method == "start_next":
# Dia 1 del siguiente recurring_rule_type
sol.date_start = (
sol.order_id.date_order
+ self.get_relative_delta(
sol.recurring_rule_type, sol.product_id.default_qty
)
).replace(day=1)
elif sol.contract_start_date_method == "end_next":
# Last day of next recurring period
sol.date_start = (
sol.order_id.date_order
+ self.get_relative_delta(
sol.recurring_rule_type, sol.product_id.default_qty + 1
)
).replace(day=1) - relativedelta(days=1)
else:
# Manual method
sol.date_start = False

def _get_date_end(self):
self.ensure_one()
contract_start_date_method = self.product_id.contract_start_date_method
date_end = False
if contract_start_date_method == "manual":
contract_line_model = self.env["contract.line"]
date_end = (
self.date_start
+ contract_line_model.get_relative_delta(
self._get_auto_renew_rule_type(),
int(self.product_uom_qty),
@api.depends(
"is_auto_renew",
"date_start",
"auto_renew_interval",
"auto_renew_rule_type",
)
def _compute_date_end(self):
for sol in self:
if sol.is_auto_renew and sol.date_start:
sol.date_end = self.env["contract.line"]._get_first_date_end(
sol.date_start,
sol.auto_renew_rule_type,
sol.auto_renew_interval,
)
- relativedelta(days=1)
)
return date_end
else:
sol.date_end = False

@api.model
def get_relative_delta(self, recurring_rule_type, interval):
return self.env["contract.recurrency.mixin"].get_relative_delta(
recurring_rule_type, interval
)

@api.depends("product_id")
def _compute_auto_renew(self):
for rec in self:
if rec.product_id.is_contract:
rec.product_uom_qty = rec.product_id.default_qty
contract_start_date_method = rec.product_id.contract_start_date_method
if contract_start_date_method == "manual":
rec.date_start = rec.date_start or fields.Date.today()
rec.date_end = rec._get_date_end()
rec.is_auto_renew = rec.product_id.is_auto_renew
if rec.is_auto_renew:
rec.auto_renew_interval = rec.product_id.auto_renew_interval
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type

@api.onchange("date_start", "product_uom_qty")
def onchange_date_start(self):
for rec in self.filtered("product_id.is_contract"):
rec.date_end = rec._get_date_end() if rec.date_start else False
rec.product_uom_qty = rec.product_id.default_qty
rec.is_auto_renew = rec.product_id.is_auto_renew
rec.auto_renew_interval = rec.product_id.auto_renew_interval
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type

def _get_contract_line_qty(self):
"""Returns the amount that will be placed in new contract lines."""
Expand Down Expand Up @@ -178,7 +208,7 @@ def _prepare_contract_line_values(
"date_end": self.date_end,
"date_start": self.date_start or fields.Date.today(),
"recurring_next_date": recurring_next_date,
"recurring_interval": 1,
"recurring_interval": self.recurring_interval or 1,
"recurring_invoicing_type": self.recurring_invoicing_type,
"recurring_rule_type": self.recurring_rule_type,
"is_auto_renew": self.is_auto_renew,
Expand Down
1 change: 1 addition & 0 deletions product_contract/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
- Ernesto Tejeda
- Pedro M. Baeza
- Carlos Roca
- Sergio Teruel
- David Jaen \<<[email protected]>\>
1 change: 1 addition & 0 deletions product_contract/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,7 @@ <h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
<li>Ernesto Tejeda</li>
<li>Pedro M. Baeza</li>
<li>Carlos Roca</li>
<li>Sergio Teruel</li>
</ul>
</li>
<li>David Jaen &lt;<a class="reference external" href="mailto:david.jaen.revert&#64;gmail.com">david.jaen.revert&#64;gmail.com</a>&gt;</li>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export class ProductContractConfiguratorController extends formView.Controller {
is_auto_renew,
auto_renew_interval,
auto_renew_rule_type,
recurring_interval,
} = record.data;
return this.action.doAction({
type: "ir.actions.act_window_close",
Expand All @@ -34,6 +35,7 @@ export class ProductContractConfiguratorController extends formView.Controller {
is_auto_renew,
auto_renew_interval,
auto_renew_rule_type,
recurring_interval,
},
},
});
Expand Down
13 changes: 10 additions & 3 deletions product_contract/static/src/js/sale_product_field.esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,31 @@ patch(SaleOrderLineProductField.prototype, {
return super.isConfigurableLine || this.props.record.data.is_contract;
},

async _openContractConfigurator(isNew = false) {
const actionContext = {
get contractContext() {
return {
default_product_id: this.props.record.data.product_id[0],
default_partner_id: this.props.record.model.root.data.partner_id[0],
default_company_id: this.props.record.model.root.data.company_id[0],
default_product_uom_qty: this.props.record.data.product_uom_qty,
default_contract_id: this.props.record.data.contract_id[0],
default_recurring_interval: this.props.record.data.recurring_interval,
default_date_start: this.props.record.data.date_start,
default_date_end: this.props.record.data.date_end,
default_is_auto_renew: this.props.record.data.is_auto_renew,
default_auto_renew_interval: this.props.record.data.auto_renew_interval,
default_auto_renew_rule_type: this.props.record.data.auto_renew_rule_type,
};
},

async _openContractConfigurator(isNew = false) {
const actionContext = this.contractContext;
this.action.doAction("product_contract.product_contract_configurator_action", {
additionalContext: actionContext,
onClose: async (closeInfo) => {
if (closeInfo && !closeInfo.special) {
this.props.record.update(closeInfo.productContractConfiguration);
this.props.record._update(closeInfo.productContractConfiguration, {
withoutOnchange: true,
});
} else if (isNew) {
this.props.record.update({
[this.props.name]: undefined,
Expand Down
8 changes: 4 additions & 4 deletions product_contract/tests/test_sale_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_compute_is_contract(self):
def test_action_confirm(self):
"""It should create a contract for each contract template used in
order_line"""
self.order_line1._compute_auto_renew()
self.order_line1.is_auto_renew = True
self.sale.action_confirm()
contracts = self.sale.order_line.mapped("contract_id")
self.assertEqual(len(contracts), 2)
Expand Down Expand Up @@ -155,7 +155,7 @@ def test_action_confirm_without_contract_creation(self):
"""It should create a contract for each contract template used in
order_line"""
self.sale.company_id.create_contract_at_sale_order_confirmation = False
self.order_line1._compute_auto_renew()
self.order_line1.is_auto_renew = True
self.sale.action_confirm()
self.assertEqual(len(self.sale.order_line.mapped("contract_id")), 0)
self.assertTrue(self.sale.need_contract_creation)
Expand All @@ -174,14 +174,14 @@ def test_action_confirm_without_contract_creation(self):
def test_sale_contract_count(self):
"""It should count contracts as many different contract template used
in order_line"""
self.order_line1._compute_auto_renew()
self.order_line1.is_auto_renew = True
self.sale.action_confirm()
self.assertEqual(self.sale.contract_count, 2)

def test_onchange_product(self):
"""It should get recurrence invoicing info to the sale line from
its product"""
self.order_line1._compute_auto_renew()
self.order_line1.is_auto_renew = True
self.assertEqual(
self.order_line1.recurring_rule_type,
self.product1.recurring_rule_type,
Expand Down
41 changes: 35 additions & 6 deletions product_contract/views/sale_order.xml
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,30 @@
invisible="not is_contract"
/>
<group invisible="not is_contract">
<field name="recurring_rule_type" />
<label for="recurring_interval" />
<div class="o_row">
<field
name="recurring_interval"
readonly="product_uom_readonly"
/>
<field name="recurring_rule_type" />
</div>
</group>
<group invisible="not is_contract">
<field name="recurring_invoicing_type" />
</group>
<group invisible="not is_contract">
<field name="date_start" required="is_contract" />
<field
name="date_start"
required="is_contract"
readonly="product_uom_readonly"
/>
</group>
<group invisible="not is_contract">
<field name="date_end" />
<field name="date_end" readonly="product_uom_readonly" />
</group>
<group invisible="not is_contract">
<field name="is_auto_renew" />
<field name="is_auto_renew" readonly="product_uom_readonly" />
</group>
<group invisible="not is_auto_renew">
<label for="auto_renew_interval" />
Expand All @@ -84,12 +95,14 @@
class="oe_inline"
nolabel="1"
required="is_auto_renew"
readonly="product_uom_readonly"
/>
<field
name="auto_renew_rule_type"
class="oe_inline"
nolabel="1"
required="is_auto_renew"
readonly="product_uom_readonly"
/>
</div>
</group>
Expand All @@ -113,29 +126,45 @@
domain="[('contract_id','=',contract_id)]"
optional="hide"
/>
<field
name="recurring_interval"
optional="hide"
readonly="product_uom_readonly"
/>
<field name="recurring_rule_type" optional="hide" />
<field name="recurring_invoicing_type" optional="hide" />
<field name="contract_start_date_method" column_invisible="1" />
<field
name="date_start"
optional="hide"
required="is_contract and contract_start_date_method == 'manual'"
readonly="product_uom_readonly"
/>
<field
name="date_end"
optional="hide"
readonly="product_uom_readonly"
/>
<field
name="is_auto_renew"
optional="hide"
readonly="product_uom_readonly"
/>
<field name="date_end" optional="hide" />
<field name="is_auto_renew" optional="hide" />
<field
name="auto_renew_interval"
class="oe_inline"
nolabel="1"
required="is_auto_renew"
optional="hide"
readonly="product_uom_readonly"
/>
<field
name="auto_renew_rule_type"
class="oe_inline"
nolabel="1"
required="is_auto_renew"
optional="hide"
readonly="product_uom_readonly"
/>
</xpath>
</field>
Expand Down
Loading

0 comments on commit f91a487

Please sign in to comment.