mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
@@ -65,8 +65,8 @@ To use this module, you need to:
|
|||||||
Known issues / Roadmap
|
Known issues / Roadmap
|
||||||
======================
|
======================
|
||||||
|
|
||||||
- There's no support right now for computing the start date for the
|
- There's no support right now for computing the start date for the
|
||||||
following recurrent types: daily, weekly and monthlylastday.
|
following recurrent types: daily, weekly and monthlylastday.
|
||||||
|
|
||||||
Bug Tracker
|
Bug Tracker
|
||||||
===========
|
===========
|
||||||
@@ -90,15 +90,16 @@ Authors
|
|||||||
Contributors
|
Contributors
|
||||||
------------
|
------------
|
||||||
|
|
||||||
- Ted Salmon <tsalmon@laslabs.com>
|
- Ted Salmon <tsalmon@laslabs.com>
|
||||||
- Souheil Bejaoui <souheil.bejaoui@acsone.eu>
|
- Souheil Bejaoui <souheil.bejaoui@acsone.eu>
|
||||||
- `Tecnativa <https://www.tecnativa.com>`__:
|
- `Tecnativa <https://www.tecnativa.com>`__:
|
||||||
|
|
||||||
- Ernesto Tejeda
|
- Ernesto Tejeda
|
||||||
- Pedro M. Baeza
|
- Pedro M. Baeza
|
||||||
- Carlos Roca
|
- Carlos Roca
|
||||||
|
- Sergio Teruel
|
||||||
|
|
||||||
- David Jaen <david.jaen.revert@gmail.com>
|
- David Jaen <david.jaen.revert@gmail.com>
|
||||||
|
|
||||||
Maintainers
|
Maintainers
|
||||||
-----------
|
-----------
|
||||||
|
|||||||
@@ -30,25 +30,32 @@ class SaleOrderLine(models.Model):
|
|||||||
string="Contract Template",
|
string="Contract Template",
|
||||||
compute="_compute_contract_template_id",
|
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_rule_type = fields.Selection(related="product_id.recurring_rule_type")
|
||||||
recurring_invoicing_type = fields.Selection(
|
recurring_invoicing_type = fields.Selection(
|
||||||
related="product_id.recurring_invoicing_type"
|
related="product_id.recurring_invoicing_type"
|
||||||
)
|
)
|
||||||
date_start = fields.Date()
|
date_start = fields.Date(
|
||||||
date_end = 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(
|
contract_line_id = fields.Many2one(
|
||||||
comodel_name="contract.line",
|
comodel_name="contract.line",
|
||||||
string="Contract Line to replace",
|
string="Contract Line to replace",
|
||||||
required=False,
|
|
||||||
copy=False,
|
copy=False,
|
||||||
)
|
)
|
||||||
is_auto_renew = fields.Boolean(
|
is_auto_renew = fields.Boolean(
|
||||||
string="Auto Renew",
|
string="Auto Renew",
|
||||||
compute="_compute_auto_renew",
|
compute="_compute_auto_renew",
|
||||||
default=False,
|
|
||||||
store=True,
|
store=True,
|
||||||
readonly=False,
|
readonly=False,
|
||||||
|
precompute=True,
|
||||||
)
|
)
|
||||||
auto_renew_interval = fields.Integer(
|
auto_renew_interval = fields.Integer(
|
||||||
default=1,
|
default=1,
|
||||||
@@ -57,6 +64,7 @@ class SaleOrderLine(models.Model):
|
|||||||
store=True,
|
store=True,
|
||||||
readonly=False,
|
readonly=False,
|
||||||
help="Renew every (Days/Week/Month/Year)",
|
help="Renew every (Days/Week/Month/Year)",
|
||||||
|
precompute=True,
|
||||||
)
|
)
|
||||||
auto_renew_rule_type = fields.Selection(
|
auto_renew_rule_type = fields.Selection(
|
||||||
[
|
[
|
||||||
@@ -71,6 +79,7 @@ class SaleOrderLine(models.Model):
|
|||||||
readonly=False,
|
readonly=False,
|
||||||
string="Renewal type",
|
string="Renewal type",
|
||||||
help="Specify Interval for automatic renewal.",
|
help="Specify Interval for automatic renewal.",
|
||||||
|
precompute=True,
|
||||||
)
|
)
|
||||||
contract_start_date_method = fields.Selection(
|
contract_start_date_method = fields.Selection(
|
||||||
related="product_id.contract_start_date_method"
|
related="product_id.contract_start_date_method"
|
||||||
@@ -97,47 +106,68 @@ class SaleOrderLine(models.Model):
|
|||||||
rec.order_id.company_id
|
rec.order_id.company_id
|
||||||
).property_contract_template_id
|
).property_contract_template_id
|
||||||
|
|
||||||
def _get_auto_renew_rule_type(self):
|
@api.depends("product_id")
|
||||||
"""monthly last day don't make sense for auto_renew_rule_type"""
|
def _compute_date_start(self):
|
||||||
self.ensure_one()
|
for sol in self:
|
||||||
if self.recurring_rule_type == "monthlylastday":
|
if sol.contract_start_date_method == "start_this":
|
||||||
return "monthly"
|
sol.date_start = sol.order_id.date_order.replace(day=1)
|
||||||
return self.recurring_rule_type
|
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):
|
@api.depends(
|
||||||
self.ensure_one()
|
"is_auto_renew",
|
||||||
contract_start_date_method = self.product_id.contract_start_date_method
|
"date_start",
|
||||||
date_end = False
|
"auto_renew_interval",
|
||||||
if contract_start_date_method == "manual":
|
"auto_renew_rule_type",
|
||||||
contract_line_model = self.env["contract.line"]
|
)
|
||||||
date_end = (
|
def _compute_date_end(self):
|
||||||
self.date_start
|
for sol in self:
|
||||||
+ contract_line_model.get_relative_delta(
|
if sol.is_auto_renew and sol.date_start:
|
||||||
self._get_auto_renew_rule_type(),
|
sol.date_end = self.env["contract.line"]._get_first_date_end(
|
||||||
int(self.product_uom_qty),
|
sol.date_start,
|
||||||
|
sol.auto_renew_rule_type,
|
||||||
|
sol.auto_renew_interval,
|
||||||
)
|
)
|
||||||
- relativedelta(days=1)
|
else:
|
||||||
)
|
sol.date_end = False
|
||||||
return date_end
|
|
||||||
|
@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")
|
@api.depends("product_id")
|
||||||
def _compute_auto_renew(self):
|
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"):
|
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):
|
def _get_contract_line_qty(self):
|
||||||
"""Returns the amount that will be placed in new contract lines."""
|
"""Returns the amount that will be placed in new contract lines."""
|
||||||
@@ -178,7 +208,7 @@ class SaleOrderLine(models.Model):
|
|||||||
"date_end": self.date_end,
|
"date_end": self.date_end,
|
||||||
"date_start": self.date_start or fields.Date.today(),
|
"date_start": self.date_start or fields.Date.today(),
|
||||||
"recurring_next_date": recurring_next_date,
|
"recurring_next_date": recurring_next_date,
|
||||||
"recurring_interval": 1,
|
"recurring_interval": self.recurring_interval or 1,
|
||||||
"recurring_invoicing_type": self.recurring_invoicing_type,
|
"recurring_invoicing_type": self.recurring_invoicing_type,
|
||||||
"recurring_rule_type": self.recurring_rule_type,
|
"recurring_rule_type": self.recurring_rule_type,
|
||||||
"is_auto_renew": self.is_auto_renew,
|
"is_auto_renew": self.is_auto_renew,
|
||||||
|
|||||||
@@ -4,4 +4,5 @@
|
|||||||
- Ernesto Tejeda
|
- Ernesto Tejeda
|
||||||
- Pedro M. Baeza
|
- Pedro M. Baeza
|
||||||
- Carlos Roca
|
- Carlos Roca
|
||||||
|
- Sergio Teruel
|
||||||
- David Jaen \<<david.jaen.revert@gmail.com>\>
|
- David Jaen \<<david.jaen.revert@gmail.com>\>
|
||||||
|
|||||||
@@ -444,6 +444,7 @@ If you spotted it first, help us to smash it by providing a detailed and welcome
|
|||||||
<li>Ernesto Tejeda</li>
|
<li>Ernesto Tejeda</li>
|
||||||
<li>Pedro M. Baeza</li>
|
<li>Pedro M. Baeza</li>
|
||||||
<li>Carlos Roca</li>
|
<li>Carlos Roca</li>
|
||||||
|
<li>Sergio Teruel</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li>David Jaen <<a class="reference external" href="mailto:david.jaen.revert@gmail.com">david.jaen.revert@gmail.com</a>></li>
|
<li>David Jaen <<a class="reference external" href="mailto:david.jaen.revert@gmail.com">david.jaen.revert@gmail.com</a>></li>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export class ProductContractConfiguratorController extends formView.Controller {
|
|||||||
is_auto_renew,
|
is_auto_renew,
|
||||||
auto_renew_interval,
|
auto_renew_interval,
|
||||||
auto_renew_rule_type,
|
auto_renew_rule_type,
|
||||||
|
recurring_interval,
|
||||||
} = record.data;
|
} = record.data;
|
||||||
return this.action.doAction({
|
return this.action.doAction({
|
||||||
type: "ir.actions.act_window_close",
|
type: "ir.actions.act_window_close",
|
||||||
@@ -34,6 +35,7 @@ export class ProductContractConfiguratorController extends formView.Controller {
|
|||||||
is_auto_renew,
|
is_auto_renew,
|
||||||
auto_renew_interval,
|
auto_renew_interval,
|
||||||
auto_renew_rule_type,
|
auto_renew_rule_type,
|
||||||
|
recurring_interval,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,24 +37,31 @@ patch(SaleOrderLineProductField.prototype, {
|
|||||||
return super.isConfigurableLine || this.props.record.data.is_contract;
|
return super.isConfigurableLine || this.props.record.data.is_contract;
|
||||||
},
|
},
|
||||||
|
|
||||||
async _openContractConfigurator(isNew = false) {
|
get contractContext() {
|
||||||
const actionContext = {
|
return {
|
||||||
default_product_id: this.props.record.data.product_id[0],
|
default_product_id: this.props.record.data.product_id[0],
|
||||||
default_partner_id: this.props.record.model.root.data.partner_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_company_id: this.props.record.model.root.data.company_id[0],
|
||||||
default_product_uom_qty: this.props.record.data.product_uom_qty,
|
default_product_uom_qty: this.props.record.data.product_uom_qty,
|
||||||
default_contract_id: this.props.record.data.contract_id[0],
|
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_start: this.props.record.data.date_start,
|
||||||
default_date_end: this.props.record.data.date_end,
|
default_date_end: this.props.record.data.date_end,
|
||||||
default_is_auto_renew: this.props.record.data.is_auto_renew,
|
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_interval: this.props.record.data.auto_renew_interval,
|
||||||
default_auto_renew_rule_type: this.props.record.data.auto_renew_rule_type,
|
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", {
|
this.action.doAction("product_contract.product_contract_configurator_action", {
|
||||||
additionalContext: actionContext,
|
additionalContext: actionContext,
|
||||||
onClose: async (closeInfo) => {
|
onClose: async (closeInfo) => {
|
||||||
if (closeInfo && !closeInfo.special) {
|
if (closeInfo && !closeInfo.special) {
|
||||||
this.props.record.update(closeInfo.productContractConfiguration);
|
this.props.record._update(closeInfo.productContractConfiguration, {
|
||||||
|
withoutOnchange: true,
|
||||||
|
});
|
||||||
} else if (isNew) {
|
} else if (isNew) {
|
||||||
this.props.record.update({
|
this.props.record.update({
|
||||||
[this.props.name]: undefined,
|
[this.props.name]: undefined,
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class TestSaleOrder(TransactionCase):
|
|||||||
def test_action_confirm(self):
|
def test_action_confirm(self):
|
||||||
"""It should create a contract for each contract template used in
|
"""It should create a contract for each contract template used in
|
||||||
order_line"""
|
order_line"""
|
||||||
self.order_line1._compute_auto_renew()
|
self.order_line1.is_auto_renew = True
|
||||||
self.sale.action_confirm()
|
self.sale.action_confirm()
|
||||||
contracts = self.sale.order_line.mapped("contract_id")
|
contracts = self.sale.order_line.mapped("contract_id")
|
||||||
self.assertEqual(len(contracts), 2)
|
self.assertEqual(len(contracts), 2)
|
||||||
@@ -155,7 +155,7 @@ class TestSaleOrder(TransactionCase):
|
|||||||
"""It should create a contract for each contract template used in
|
"""It should create a contract for each contract template used in
|
||||||
order_line"""
|
order_line"""
|
||||||
self.sale.company_id.create_contract_at_sale_order_confirmation = False
|
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.sale.action_confirm()
|
||||||
self.assertEqual(len(self.sale.order_line.mapped("contract_id")), 0)
|
self.assertEqual(len(self.sale.order_line.mapped("contract_id")), 0)
|
||||||
self.assertTrue(self.sale.need_contract_creation)
|
self.assertTrue(self.sale.need_contract_creation)
|
||||||
@@ -174,14 +174,14 @@ class TestSaleOrder(TransactionCase):
|
|||||||
def test_sale_contract_count(self):
|
def test_sale_contract_count(self):
|
||||||
"""It should count contracts as many different contract template used
|
"""It should count contracts as many different contract template used
|
||||||
in order_line"""
|
in order_line"""
|
||||||
self.order_line1._compute_auto_renew()
|
self.order_line1.is_auto_renew = True
|
||||||
self.sale.action_confirm()
|
self.sale.action_confirm()
|
||||||
self.assertEqual(self.sale.contract_count, 2)
|
self.assertEqual(self.sale.contract_count, 2)
|
||||||
|
|
||||||
def test_onchange_product(self):
|
def test_onchange_product(self):
|
||||||
"""It should get recurrence invoicing info to the sale line from
|
"""It should get recurrence invoicing info to the sale line from
|
||||||
its product"""
|
its product"""
|
||||||
self.order_line1._compute_auto_renew()
|
self.order_line1.is_auto_renew = True
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.order_line1.recurring_rule_type,
|
self.order_line1.recurring_rule_type,
|
||||||
self.product1.recurring_rule_type,
|
self.product1.recurring_rule_type,
|
||||||
|
|||||||
@@ -62,19 +62,30 @@
|
|||||||
invisible="not is_contract"
|
invisible="not is_contract"
|
||||||
/>
|
/>
|
||||||
<group 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>
|
||||||
<group invisible="not is_contract">
|
<group invisible="not is_contract">
|
||||||
<field name="recurring_invoicing_type" />
|
<field name="recurring_invoicing_type" />
|
||||||
</group>
|
</group>
|
||||||
<group invisible="not is_contract">
|
<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>
|
||||||
<group invisible="not is_contract">
|
<group invisible="not is_contract">
|
||||||
<field name="date_end" />
|
<field name="date_end" readonly="product_uom_readonly" />
|
||||||
</group>
|
</group>
|
||||||
<group invisible="not is_contract">
|
<group invisible="not is_contract">
|
||||||
<field name="is_auto_renew" />
|
<field name="is_auto_renew" readonly="product_uom_readonly" />
|
||||||
</group>
|
</group>
|
||||||
<group invisible="not is_auto_renew">
|
<group invisible="not is_auto_renew">
|
||||||
<label for="auto_renew_interval" />
|
<label for="auto_renew_interval" />
|
||||||
@@ -84,12 +95,14 @@
|
|||||||
class="oe_inline"
|
class="oe_inline"
|
||||||
nolabel="1"
|
nolabel="1"
|
||||||
required="is_auto_renew"
|
required="is_auto_renew"
|
||||||
|
readonly="product_uom_readonly"
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="auto_renew_rule_type"
|
name="auto_renew_rule_type"
|
||||||
class="oe_inline"
|
class="oe_inline"
|
||||||
nolabel="1"
|
nolabel="1"
|
||||||
required="is_auto_renew"
|
required="is_auto_renew"
|
||||||
|
readonly="product_uom_readonly"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
@@ -113,6 +126,11 @@
|
|||||||
domain="[('contract_id','=',contract_id)]"
|
domain="[('contract_id','=',contract_id)]"
|
||||||
optional="hide"
|
optional="hide"
|
||||||
/>
|
/>
|
||||||
|
<field
|
||||||
|
name="recurring_interval"
|
||||||
|
optional="hide"
|
||||||
|
readonly="product_uom_readonly"
|
||||||
|
/>
|
||||||
<field name="recurring_rule_type" optional="hide" />
|
<field name="recurring_rule_type" optional="hide" />
|
||||||
<field name="recurring_invoicing_type" optional="hide" />
|
<field name="recurring_invoicing_type" optional="hide" />
|
||||||
<field name="contract_start_date_method" column_invisible="1" />
|
<field name="contract_start_date_method" column_invisible="1" />
|
||||||
@@ -120,15 +138,25 @@
|
|||||||
name="date_start"
|
name="date_start"
|
||||||
optional="hide"
|
optional="hide"
|
||||||
required="is_contract and contract_start_date_method == 'manual'"
|
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
|
<field
|
||||||
name="auto_renew_interval"
|
name="auto_renew_interval"
|
||||||
class="oe_inline"
|
class="oe_inline"
|
||||||
nolabel="1"
|
nolabel="1"
|
||||||
required="is_auto_renew"
|
required="is_auto_renew"
|
||||||
optional="hide"
|
optional="hide"
|
||||||
|
readonly="product_uom_readonly"
|
||||||
/>
|
/>
|
||||||
<field
|
<field
|
||||||
name="auto_renew_rule_type"
|
name="auto_renew_rule_type"
|
||||||
@@ -136,6 +164,7 @@
|
|||||||
nolabel="1"
|
nolabel="1"
|
||||||
required="is_auto_renew"
|
required="is_auto_renew"
|
||||||
optional="hide"
|
optional="hide"
|
||||||
|
readonly="product_uom_readonly"
|
||||||
/>
|
/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# Copyright 2024 Tecnativa - Carlos Roca
|
# Copyright 2024 Tecnativa - Carlos Roca
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models
|
||||||
|
|
||||||
@@ -20,12 +19,17 @@ class ProductContractConfigurator(models.TransientModel):
|
|||||||
string="Contract Template",
|
string="Contract Template",
|
||||||
compute="_compute_contract_template_id",
|
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_rule_type = fields.Selection(related="product_id.recurring_rule_type")
|
||||||
recurring_invoicing_type = fields.Selection(
|
recurring_invoicing_type = fields.Selection(
|
||||||
related="product_id.recurring_invoicing_type"
|
related="product_id.recurring_invoicing_type"
|
||||||
)
|
)
|
||||||
date_start = fields.Date()
|
date_start = fields.Date()
|
||||||
date_end = fields.Date()
|
date_end = fields.Date(compute="_compute_date_end", readonly=False, store=True)
|
||||||
contract_line_id = fields.Many2one(
|
contract_line_id = fields.Many2one(
|
||||||
comodel_name="contract.line",
|
comodel_name="contract.line",
|
||||||
string="Contract Line to replace",
|
string="Contract Line to replace",
|
||||||
@@ -79,33 +83,15 @@ class ProductContractConfigurator(models.TransientModel):
|
|||||||
contract_start_date_method = rec.product_id.contract_start_date_method
|
contract_start_date_method = rec.product_id.contract_start_date_method
|
||||||
if contract_start_date_method == "manual":
|
if contract_start_date_method == "manual":
|
||||||
rec.date_start = rec.date_start or fields.Date.today()
|
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
|
rec.is_auto_renew = rec.product_id.is_auto_renew
|
||||||
if rec.is_auto_renew:
|
if rec.is_auto_renew:
|
||||||
rec.auto_renew_interval = rec.product_id.auto_renew_interval
|
rec.auto_renew_interval = rec.product_id.auto_renew_interval
|
||||||
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type
|
rec.auto_renew_rule_type = rec.product_id.auto_renew_rule_type
|
||||||
|
|
||||||
def _get_auto_renew_rule_type(self):
|
@api.depends("date_start", "recurring_interval")
|
||||||
"""monthly last day don't make sense for auto_renew_rule_type"""
|
def _compute_date_end(self):
|
||||||
self.ensure_one()
|
self.update({"date_end": False})
|
||||||
if self.recurring_rule_type == "monthlylastday":
|
for rec in self.filtered(lambda ln: ln.is_auto_renew and ln.date_start):
|
||||||
return "monthly"
|
rec.date_end = self.env["contract.line"]._get_first_date_end(
|
||||||
return self.recurring_rule_type
|
rec.date_start, rec.auto_renew_rule_type, rec.auto_renew_interval
|
||||||
|
|
||||||
def _get_date_end(self):
|
|
||||||
self.ensure_one()
|
|
||||||
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),
|
|
||||||
)
|
)
|
||||||
- relativedelta(days=1)
|
|
||||||
)
|
|
||||||
return date_end
|
|
||||||
|
|
||||||
@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
|
|
||||||
|
|||||||
@@ -13,21 +13,21 @@
|
|||||||
</group>
|
</group>
|
||||||
<separator colspan="4" string="Recurrence Invoicing" />
|
<separator colspan="4" string="Recurrence Invoicing" />
|
||||||
<group>
|
<group>
|
||||||
<field name="recurring_rule_type" />
|
<label for="recurring_interval" />
|
||||||
<field name="contract_start_date_method" />
|
<div class="o_row">
|
||||||
<field
|
<field name="recurring_interval" />
|
||||||
name="date_start"
|
<field name="recurring_rule_type" />
|
||||||
required="contract_start_date_method == 'manual'"
|
</div>
|
||||||
invisible="contract_start_date_method != 'manual'"
|
|
||||||
/>
|
|
||||||
<field name="is_auto_renew" invisible="not date_end" />
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="recurring_invoicing_type" />
|
<field name="recurring_invoicing_type" />
|
||||||
<field
|
</group>
|
||||||
name="date_end"
|
<separator colspan="4" string="Contract renew" />
|
||||||
invisible="contract_start_date_method != 'manual'"
|
<group>
|
||||||
/>
|
<field name="is_auto_renew" invisible="not date_end" />
|
||||||
|
<field name="contract_start_date_method" />
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
<label
|
<label
|
||||||
for="auto_renew_interval"
|
for="auto_renew_interval"
|
||||||
invisible="not is_auto_renew or contract_start_date_method != 'manual'"
|
invisible="not is_auto_renew or contract_start_date_method != 'manual'"
|
||||||
@@ -49,6 +49,21 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
|
<group>
|
||||||
|
<field
|
||||||
|
name="date_start"
|
||||||
|
required="contract_start_date_method == 'manual'"
|
||||||
|
invisible="contract_start_date_method != 'manual'"
|
||||||
|
force_save="1"
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field
|
||||||
|
name="date_end"
|
||||||
|
invisible="contract_start_date_method != 'manual'"
|
||||||
|
force_save="1"
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
<separator colspan="4" string="Contract" />
|
<separator colspan="4" string="Contract" />
|
||||||
<group colspan="2">
|
<group colspan="2">
|
||||||
<field
|
<field
|
||||||
|
|||||||
Reference in New Issue
Block a user