mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[13.0][MIG] - migration product_contract
This commit is contained in:
@@ -7,29 +7,24 @@ from odoo.tools.translate import _
|
||||
|
||||
|
||||
class ContractContract(models.Model):
|
||||
_inherit = 'contract.contract'
|
||||
_inherit = "contract.contract"
|
||||
|
||||
sale_order_count = fields.Integer(compute="_compute_sale_order_count")
|
||||
|
||||
@api.depends('contract_line_ids')
|
||||
@api.depends("contract_line_ids")
|
||||
def _compute_sale_order_count(self):
|
||||
for rec in self:
|
||||
try:
|
||||
order_count = len(
|
||||
rec.contract_line_ids.mapped(
|
||||
'sale_order_line_id.order_id'
|
||||
)
|
||||
rec.contract_line_ids.mapped("sale_order_line_id.order_id")
|
||||
)
|
||||
except AccessError:
|
||||
order_count = 0
|
||||
rec.sale_order_count = order_count
|
||||
|
||||
@api.multi
|
||||
def action_view_sales_orders(self):
|
||||
self.ensure_one()
|
||||
orders = self.contract_line_ids.mapped(
|
||||
'sale_order_line_id.order_id'
|
||||
)
|
||||
orders = self.contract_line_ids.mapped("sale_order_line_id.order_id")
|
||||
action = {
|
||||
"name": _("Sales Orders"),
|
||||
"view_mode": "tree,form",
|
||||
@@ -39,5 +34,5 @@ class ContractContract(models.Model):
|
||||
}
|
||||
if len(orders) == 1:
|
||||
# If there is only one order, open it directly
|
||||
action.update({'view_mode': "form", "res_id": orders.id})
|
||||
action.update({"view_mode": "form", "res_id": orders.id})
|
||||
return action
|
||||
|
||||
@@ -7,8 +7,8 @@ from odoo import api, fields, models
|
||||
|
||||
|
||||
class ContractLine(models.Model):
|
||||
_inherit = 'contract.line'
|
||||
_rec_name = 'display_name'
|
||||
_inherit = "contract.line"
|
||||
_rec_name = "display_name"
|
||||
|
||||
sale_order_line_id = fields.Many2one(
|
||||
comodel_name="sale.order.line",
|
||||
@@ -16,18 +16,14 @@ class ContractLine(models.Model):
|
||||
required=False,
|
||||
copy=False,
|
||||
)
|
||||
display_name = fields.Char(compute='_compute_display_name_2')
|
||||
display_name = fields.Char(compute="_compute_display_name_2")
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice_line(self, invoice_id=False, invoice_values=False):
|
||||
res = super(ContractLine, self)._prepare_invoice_line(
|
||||
invoice_id=invoice_id, invoice_values=invoice_values,
|
||||
)
|
||||
def _prepare_invoice_line(self, move_form):
|
||||
res = super(ContractLine, self)._prepare_invoice_line(move_form)
|
||||
if self.sale_order_line_id and res:
|
||||
res['sale_line_ids'] = [(6, 0, [self.sale_order_line_id.id])]
|
||||
res["sale_line_ids"] = [(6, 0, [self.sale_order_line_id.id])]
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _get_auto_renew_rule_type(self):
|
||||
"""monthly last day don't make sense for auto_renew_rule_type"""
|
||||
self.ensure_one()
|
||||
@@ -35,15 +31,13 @@ class ContractLine(models.Model):
|
||||
return "monthly"
|
||||
return self.recurring_rule_type
|
||||
|
||||
@api.onchange('product_id')
|
||||
@api.onchange("product_id")
|
||||
def _onchange_product_id_recurring_info(self):
|
||||
for rec in self:
|
||||
rec.date_start = fields.Date.today()
|
||||
if rec.product_id.is_contract:
|
||||
rec.recurring_rule_type = rec.product_id.recurring_rule_type
|
||||
rec.recurring_invoicing_type = (
|
||||
rec.product_id.recurring_invoicing_type
|
||||
)
|
||||
rec.recurring_invoicing_type = rec.product_id.recurring_invoicing_type
|
||||
rec.recurring_interval = 1
|
||||
rec.is_auto_renew = rec.product_id.is_auto_renew
|
||||
rec.auto_renew_interval = rec.product_id.auto_renew_interval
|
||||
@@ -55,7 +49,7 @@ class ContractLine(models.Model):
|
||||
rec.product_id.termination_notice_rule_type
|
||||
)
|
||||
|
||||
@api.depends('name', 'date_start')
|
||||
@api.depends("name", "date_start")
|
||||
def _compute_display_name_2(self):
|
||||
# FIXME: _compute_display_name depends on rec_name (display_name)
|
||||
# and this trigger a WARNING : display_name depends on itself;
|
||||
|
||||
@@ -2,78 +2,76 @@
|
||||
# Copyright 2018 ACSONE SA/NV.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
_inherit = "product.template"
|
||||
|
||||
is_contract = fields.Boolean('Is a contract')
|
||||
is_contract = fields.Boolean("Is a contract")
|
||||
property_contract_template_id = fields.Many2one(
|
||||
comodel_name='contract.template',
|
||||
string='Contract Template',
|
||||
comodel_name="contract.template",
|
||||
string="Contract Template",
|
||||
company_dependent=True,
|
||||
)
|
||||
default_qty = fields.Integer(string="Default Quantity", default=1)
|
||||
recurring_rule_type = fields.Selection(
|
||||
[
|
||||
('daily', 'Day(s)'),
|
||||
('weekly', 'Week(s)'),
|
||||
('monthly', 'Month(s)'),
|
||||
('monthlylastday', 'Month(s) last day'),
|
||||
('quarterly', 'Quarter(s)'),
|
||||
('semesterly', 'Semester(s)'),
|
||||
('yearly', 'Year(s)'),
|
||||
("daily", "Day(s)"),
|
||||
("weekly", "Week(s)"),
|
||||
("monthly", "Month(s)"),
|
||||
("monthlylastday", "Month(s) last day"),
|
||||
("quarterly", "Quarter(s)"),
|
||||
("semesterly", "Semester(s)"),
|
||||
("yearly", "Year(s)"),
|
||||
],
|
||||
default='monthly',
|
||||
string='Invoice Every',
|
||||
default="monthly",
|
||||
string="Invoice Every",
|
||||
help="Specify Interval for automatic invoice generation.",
|
||||
)
|
||||
recurring_invoicing_type = fields.Selection(
|
||||
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
||||
default='pre-paid',
|
||||
string='Invoicing type',
|
||||
[("pre-paid", "Pre-paid"), ("post-paid", "Post-paid")],
|
||||
default="pre-paid",
|
||||
string="Invoicing type",
|
||||
help="Specify if process date is 'from' or 'to' invoicing date",
|
||||
)
|
||||
is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
|
||||
termination_notice_interval = fields.Integer(
|
||||
default=1, string='Termination Notice Before'
|
||||
default=1, string="Termination Notice Before"
|
||||
)
|
||||
termination_notice_rule_type = fields.Selection(
|
||||
[('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)')],
|
||||
default='monthly',
|
||||
string='Termination Notice type',
|
||||
[("daily", "Day(s)"), ("weekly", "Week(s)"), ("monthly", "Month(s)")],
|
||||
default="monthly",
|
||||
string="Termination Notice type",
|
||||
)
|
||||
auto_renew_interval = fields.Integer(
|
||||
default=1,
|
||||
string='Renew Every',
|
||||
help="Renew every (Days/Week/Month/Year)",
|
||||
default=1, string="Renew Every", help="Renew every (Days/Week/Month/Year)",
|
||||
)
|
||||
auto_renew_rule_type = fields.Selection(
|
||||
[
|
||||
('daily', 'Day(s)'),
|
||||
('weekly', 'Week(s)'),
|
||||
('monthly', 'Month(s)'),
|
||||
('yearly', 'Year(s)'),
|
||||
("daily", "Day(s)"),
|
||||
("weekly", "Week(s)"),
|
||||
("monthly", "Month(s)"),
|
||||
("yearly", "Year(s)"),
|
||||
],
|
||||
default='yearly',
|
||||
string='Renewal type',
|
||||
default="yearly",
|
||||
string="Renewal type",
|
||||
help="Specify Interval for automatic renewal.",
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
if 'is_contract' in vals and vals['is_contract'] is False:
|
||||
for company in self.env['res.company'].search([]):
|
||||
if "is_contract" in vals and vals["is_contract"] is False:
|
||||
for company in self.env["res.company"].search([]):
|
||||
self.with_context(force_company=company.id).write(
|
||||
{'property_contract_template_id': False})
|
||||
{"property_contract_template_id": False}
|
||||
)
|
||||
super().write(vals)
|
||||
|
||||
@api.constrains('is_contract', 'type')
|
||||
@api.constrains("is_contract", "type")
|
||||
def _check_contract_product_type(self):
|
||||
"""
|
||||
Contract product should be service type
|
||||
"""
|
||||
if self.is_contract and self.type != 'service':
|
||||
if self.is_contract and self.type != "service":
|
||||
raise ValidationError(_("Contract product should be service type"))
|
||||
|
||||
@@ -6,7 +6,7 @@ from odoo import fields, models
|
||||
|
||||
class ResCompany(models.Model):
|
||||
|
||||
_inherit = 'res.company'
|
||||
_inherit = "res.company"
|
||||
|
||||
create_contract_at_sale_order_confirmation = fields.Boolean(
|
||||
string="Automatically Create Contracts At Sale Order Confirmation",
|
||||
|
||||
@@ -6,9 +6,8 @@ from odoo import fields, models
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
|
||||
_inherit = 'res.config.settings'
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
create_contract_at_sale_order_confirmation = fields.Boolean(
|
||||
related="company_id.create_contract_at_sale_order_confirmation",
|
||||
readonly=False
|
||||
related="company_id.create_contract_at_sale_order_confirmation", readonly=False
|
||||
)
|
||||
|
||||
@@ -2,37 +2,32 @@
|
||||
# Copyright 2018 ACSONE SA/NV.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import _, fields, api, models
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_inherit = 'sale.order'
|
||||
_inherit = "sale.order"
|
||||
|
||||
is_contract = fields.Boolean(
|
||||
string='Is a contract', compute='_compute_is_contract'
|
||||
)
|
||||
contract_count = fields.Integer(compute='_compute_contract_count')
|
||||
need_contract_creation = fields.Boolean(
|
||||
compute='_compute_need_contract_creation'
|
||||
)
|
||||
is_contract = fields.Boolean(string="Is a contract", compute="_compute_is_contract")
|
||||
contract_count = fields.Integer(compute="_compute_contract_count")
|
||||
need_contract_creation = fields.Boolean(compute="_compute_need_contract_creation")
|
||||
|
||||
@api.constrains('state')
|
||||
@api.constrains("state")
|
||||
def check_contact_is_not_terminated(self):
|
||||
for rec in self:
|
||||
if rec.state not in (
|
||||
'sale',
|
||||
'done',
|
||||
'cancel',
|
||||
) and rec.order_line.filtered('contract_id.is_terminated'):
|
||||
if rec.state not in ("sale", "done", "cancel",) and rec.order_line.filtered(
|
||||
"contract_id.is_terminated"
|
||||
):
|
||||
raise ValidationError(
|
||||
_("You can't upsell or downsell a terminated contract")
|
||||
)
|
||||
|
||||
@api.depends('order_line.contract_id', 'state')
|
||||
@api.depends("order_line.contract_id", "state")
|
||||
def _compute_need_contract_creation(self):
|
||||
for rec in self:
|
||||
if rec.state in ('sale', 'done'):
|
||||
rec.need_contract_creation = False
|
||||
if rec.state in ("sale", "done"):
|
||||
line_to_create_contract = rec.order_line.filtered(
|
||||
lambda r: not r.contract_id and r.product_id.is_contract
|
||||
)
|
||||
@@ -40,38 +35,35 @@ class SaleOrder(models.Model):
|
||||
lambda r: r.contract_id
|
||||
and r.product_id.is_contract
|
||||
and r
|
||||
not in r.contract_id.contract_line_ids.mapped(
|
||||
'sale_order_line_id'
|
||||
)
|
||||
not in r.contract_id.contract_line_ids.mapped("sale_order_line_id")
|
||||
)
|
||||
if line_to_create_contract or line_to_update_contract:
|
||||
rec.need_contract_creation = True
|
||||
|
||||
@api.depends('order_line')
|
||||
@api.depends("order_line")
|
||||
def _compute_is_contract(self):
|
||||
self.is_contract = any(self.order_line.mapped('is_contract'))
|
||||
self.is_contract = any(self.order_line.mapped("is_contract"))
|
||||
|
||||
@api.multi
|
||||
def _prepare_contract_value(self, contract_template):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'name': '{template_name}: {sale_name}'.format(
|
||||
"name": "{template_name}: {sale_name}".format(
|
||||
template_name=contract_template.name, sale_name=self.name
|
||||
),
|
||||
'partner_id': self.partner_id.id,
|
||||
'company_id': self.company_id.id,
|
||||
'contract_template_id': contract_template.id,
|
||||
'user_id': self.user_id.id,
|
||||
'payment_term_id': self.payment_term_id.id,
|
||||
'fiscal_position_id': self.fiscal_position_id.id,
|
||||
'invoice_partner_id': self.partner_invoice_id.id,
|
||||
"partner_id": self.partner_id.id,
|
||||
"company_id": self.company_id.id,
|
||||
"contract_template_id": contract_template.id,
|
||||
"user_id": self.user_id.id,
|
||||
"payment_term_id": self.payment_term_id.id,
|
||||
"fiscal_position_id": self.fiscal_position_id.id,
|
||||
"invoice_partner_id": self.partner_invoice_id.id,
|
||||
"line_recurrence": self.partner_invoice_id.id,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def action_create_contract(self):
|
||||
contract_model = self.env['contract.contract']
|
||||
contracts = self.env['contract.contract']
|
||||
for rec in self.filtered('is_contract'):
|
||||
contract_model = self.env["contract.contract"]
|
||||
contracts = self.env["contract.contract"]
|
||||
for rec in self.filtered("is_contract"):
|
||||
line_to_create_contract = rec.order_line.filtered(
|
||||
lambda r: not r.contract_id and r.product_id.is_contract
|
||||
)
|
||||
@@ -79,9 +71,7 @@ class SaleOrder(models.Model):
|
||||
lambda r: r.contract_id
|
||||
and r.product_id.is_contract
|
||||
and r
|
||||
not in r.contract_id.contract_line_ids.mapped(
|
||||
'sale_order_line_id'
|
||||
)
|
||||
not in r.contract_id.contract_line_ids.mapped("sale_order_line_id")
|
||||
)
|
||||
contract_templates = self.env["contract.template"]
|
||||
for order_line in line_to_create_contract:
|
||||
@@ -90,19 +80,18 @@ class SaleOrder(models.Model):
|
||||
).property_contract_template_id
|
||||
if not contract_template:
|
||||
raise ValidationError(
|
||||
_("You must specify a contract "
|
||||
"template for '{}' product in '{}' company.").format(
|
||||
order_line.product_id.name,
|
||||
rec.company_id.name
|
||||
)
|
||||
_(
|
||||
"You must specify a contract "
|
||||
"template for '{}' product in '{}' company."
|
||||
).format(order_line.product_id.name, rec.company_id.name)
|
||||
)
|
||||
contract_templates |= contract_template
|
||||
for contract_template in contract_templates:
|
||||
order_lines = line_to_create_contract.filtered(
|
||||
lambda r, template=contract_template:
|
||||
r.product_id.with_context(
|
||||
force_company=r.order_id.company_id.id
|
||||
).property_contract_template_id == template
|
||||
lambda r, template=contract_template: r.product_id.with_context(
|
||||
force_company=r.order_id.company_id.id
|
||||
).property_contract_template_id
|
||||
== template
|
||||
)
|
||||
contract = contract_model.create(
|
||||
rec._prepare_contract_value(contract_template)
|
||||
@@ -111,39 +100,32 @@ class SaleOrder(models.Model):
|
||||
contract._onchange_contract_template_id()
|
||||
contract._onchange_contract_type()
|
||||
order_lines.create_contract_line(contract)
|
||||
order_lines.write({'contract_id': contract.id})
|
||||
order_lines.write({"contract_id": contract.id})
|
||||
for line in line_to_update_contract:
|
||||
line.create_contract_line(line.contract_id)
|
||||
return contracts
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
""" If we have a contract in the order, set it up """
|
||||
self.filtered(
|
||||
lambda order: (
|
||||
order.company_id.create_contract_at_sale_order_confirmation
|
||||
)
|
||||
lambda order: (order.company_id.create_contract_at_sale_order_confirmation)
|
||||
).action_create_contract()
|
||||
return super(SaleOrder, self).action_confirm()
|
||||
|
||||
@api.multi
|
||||
@api.depends("order_line")
|
||||
def _compute_contract_count(self):
|
||||
for rec in self:
|
||||
rec.contract_count = len(
|
||||
rec.order_line.mapped('contract_id').filtered(
|
||||
lambda r: r.active))
|
||||
rec.order_line.mapped("contract_id").filtered(lambda r: r.active)
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def action_show_contracts(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref(
|
||||
"contract.action_customer_contract"
|
||||
).read()[0]
|
||||
action = self.env.ref("contract.action_customer_contract").read()[0]
|
||||
contracts = (
|
||||
self.env['contract.line']
|
||||
.search([('sale_order_line_id', 'in', self.order_line.ids)])
|
||||
.mapped('contract_id')
|
||||
self.env["contract.line"]
|
||||
.search([("sale_order_line_id", "in", self.order_line.ids)])
|
||||
.mapped("contract_id")
|
||||
)
|
||||
action["domain"] = [("id", "in", contracts.ids)]
|
||||
if len(contracts) == 1:
|
||||
@@ -152,9 +134,7 @@ class SaleOrder(models.Model):
|
||||
{
|
||||
"res_id": contracts.id,
|
||||
"view_mode": "form",
|
||||
"views": filter(
|
||||
lambda view: view[1] == 'form', action['views']
|
||||
),
|
||||
"views": filter(lambda view: view[1] == "form", action["views"]),
|
||||
}
|
||||
)
|
||||
return action
|
||||
|
||||
@@ -3,47 +3,48 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = 'sale.order.line'
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
is_contract = fields.Boolean(
|
||||
string='Is a contract', related="product_id.is_contract"
|
||||
string="Is a contract", related="product_id.is_contract"
|
||||
)
|
||||
contract_id = fields.Many2one(
|
||||
comodel_name='contract.contract', string='Contract', copy=False
|
||||
comodel_name="contract.contract", string="Contract", copy=False
|
||||
)
|
||||
contract_template_id = fields.Many2one(
|
||||
comodel_name='contract.template',
|
||||
string='Contract Template',
|
||||
compute='_compute_contract_template_id',
|
||||
comodel_name="contract.template",
|
||||
string="Contract Template",
|
||||
compute="_compute_contract_template_id",
|
||||
)
|
||||
recurring_rule_type = fields.Selection(
|
||||
[
|
||||
('daily', 'Day(s)'),
|
||||
('weekly', 'Week(s)'),
|
||||
('monthly', 'Month(s)'),
|
||||
('monthlylastday', 'Month(s) last day'),
|
||||
('quarterly', 'Quarter(s)'),
|
||||
('semesterly', 'Semester(s)'),
|
||||
('yearly', 'Year(s)'),
|
||||
("daily", "Day(s)"),
|
||||
("weekly", "Week(s)"),
|
||||
("monthly", "Month(s)"),
|
||||
("monthlylastday", "Month(s) last day"),
|
||||
("quarterly", "Quarter(s)"),
|
||||
("semesterly", "Semester(s)"),
|
||||
("yearly", "Year(s)"),
|
||||
],
|
||||
default='monthly',
|
||||
string='Invoice Every',
|
||||
default="monthly",
|
||||
string="Invoice Every",
|
||||
copy=False,
|
||||
)
|
||||
recurring_invoicing_type = fields.Selection(
|
||||
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
|
||||
default='pre-paid',
|
||||
string='Invoicing type',
|
||||
[("pre-paid", "Pre-paid"), ("post-paid", "Post-paid")],
|
||||
default="pre-paid",
|
||||
string="Invoicing type",
|
||||
help="Specify if process date is 'from' or 'to' invoicing date",
|
||||
copy=False,
|
||||
)
|
||||
date_start = fields.Date(string='Date Start')
|
||||
date_end = fields.Date(string='Date End')
|
||||
date_start = fields.Date(string="Date Start")
|
||||
date_end = fields.Date(string="Date End")
|
||||
|
||||
contract_line_id = fields.Many2one(
|
||||
comodel_name="contract.line",
|
||||
@@ -53,42 +54,38 @@ class SaleOrderLine(models.Model):
|
||||
)
|
||||
is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
|
||||
auto_renew_interval = fields.Integer(
|
||||
default=1,
|
||||
string='Renew Every',
|
||||
help="Renew every (Days/Week/Month/Year)",
|
||||
default=1, string="Renew Every", help="Renew every (Days/Week/Month/Year)",
|
||||
)
|
||||
auto_renew_rule_type = fields.Selection(
|
||||
[
|
||||
('daily', 'Day(s)'),
|
||||
('weekly', 'Week(s)'),
|
||||
('monthly', 'Month(s)'),
|
||||
('yearly', 'Year(s)'),
|
||||
("daily", "Day(s)"),
|
||||
("weekly", "Week(s)"),
|
||||
("monthly", "Month(s)"),
|
||||
("yearly", "Year(s)"),
|
||||
],
|
||||
default='yearly',
|
||||
string='Renewal type',
|
||||
default="yearly",
|
||||
string="Renewal type",
|
||||
help="Specify Interval for automatic renewal.",
|
||||
)
|
||||
|
||||
@api.constrains('contract_id')
|
||||
@api.constrains("contract_id")
|
||||
def check_contact_is_not_terminated(self):
|
||||
for rec in self:
|
||||
if (
|
||||
rec.order_id.state not in ('sale', 'done', 'cancel')
|
||||
rec.order_id.state not in ("sale", "done", "cancel")
|
||||
and rec.contract_id.is_terminated
|
||||
):
|
||||
raise ValidationError(
|
||||
_("You can't upsell or downsell a terminated contract")
|
||||
)
|
||||
|
||||
@api.multi
|
||||
@api.depends('product_id')
|
||||
@api.depends("product_id")
|
||||
def _compute_contract_template_id(self):
|
||||
for rec in self:
|
||||
rec.contract_template_id = rec.product_id.with_context(
|
||||
force_company=rec.order_id.company_id.id
|
||||
).property_contract_template_id
|
||||
|
||||
@api.multi
|
||||
def _get_auto_renew_rule_type(self):
|
||||
"""monthly last day don't make sense for auto_renew_rule_type"""
|
||||
self.ensure_one()
|
||||
@@ -96,52 +93,43 @@ class SaleOrderLine(models.Model):
|
||||
return "monthly"
|
||||
return self.recurring_rule_type
|
||||
|
||||
@api.onchange('product_id')
|
||||
@api.onchange("product_id")
|
||||
def onchange_product(self):
|
||||
contract_line_model = self.env['contract.line']
|
||||
contract_line_model = self.env["contract.line"]
|
||||
for rec in self:
|
||||
if rec.product_id.is_contract:
|
||||
rec.product_uom_qty = rec.product_id.default_qty
|
||||
rec.recurring_rule_type = rec.product_id.recurring_rule_type
|
||||
rec.recurring_invoicing_type = (
|
||||
rec.product_id.recurring_invoicing_type
|
||||
)
|
||||
rec.recurring_invoicing_type = rec.product_id.recurring_invoicing_type
|
||||
rec.date_start = rec.date_start or fields.Date.today()
|
||||
|
||||
rec.date_end = (
|
||||
rec.date_start
|
||||
+ contract_line_model.get_relative_delta(
|
||||
rec._get_auto_renew_rule_type(),
|
||||
int(rec.product_uom_qty),
|
||||
rec._get_auto_renew_rule_type(), int(rec.product_uom_qty),
|
||||
)
|
||||
- relativedelta(days=1)
|
||||
)
|
||||
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
|
||||
)
|
||||
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', 'recurring_rule_type')
|
||||
@api.onchange("date_start", "product_uom_qty", "recurring_rule_type")
|
||||
def onchange_date_start(self):
|
||||
contract_line_model = self.env['contract.line']
|
||||
for rec in self.filtered('product_id.is_contract'):
|
||||
contract_line_model = self.env["contract.line"]
|
||||
for rec in self.filtered("product_id.is_contract"):
|
||||
if not rec.date_start:
|
||||
rec.date_end = False
|
||||
else:
|
||||
rec.date_end = (
|
||||
rec.date_start
|
||||
+ contract_line_model.get_relative_delta(
|
||||
rec._get_auto_renew_rule_type(),
|
||||
int(rec.product_uom_qty),
|
||||
rec._get_auto_renew_rule_type(), int(rec.product_uom_qty),
|
||||
)
|
||||
- relativedelta(days=1)
|
||||
)
|
||||
|
||||
@api.multi
|
||||
def _prepare_contract_line_values(
|
||||
self, contract, predecessor_contract_line_id=False
|
||||
):
|
||||
@@ -152,23 +140,19 @@ class SaleOrderLine(models.Model):
|
||||
"""
|
||||
self.ensure_one()
|
||||
recurring_next_date = self.env[
|
||||
'contract.line'
|
||||
"contract.line"
|
||||
]._compute_first_recurring_next_date(
|
||||
self.date_start or fields.Date.today(),
|
||||
self.recurring_invoicing_type,
|
||||
self.recurring_rule_type,
|
||||
1,
|
||||
)
|
||||
termination_notice_interval = (
|
||||
self.product_id.termination_notice_interval
|
||||
)
|
||||
termination_notice_rule_type = (
|
||||
self.product_id.termination_notice_rule_type
|
||||
)
|
||||
termination_notice_interval = self.product_id.termination_notice_interval
|
||||
termination_notice_rule_type = self.product_id.termination_notice_rule_type
|
||||
return {
|
||||
'sequence': self.sequence,
|
||||
'product_id': self.product_id.id,
|
||||
'name': self.name,
|
||||
"sequence": self.sequence,
|
||||
"product_id": self.product_id.id,
|
||||
"name": self.name,
|
||||
# The quantity on the generated contract line is 1, as it
|
||||
# correspond to the most common use cases:
|
||||
# - quantity on the SO line = number of periods sold and unit
|
||||
@@ -181,31 +165,30 @@ class SaleOrderLine(models.Model):
|
||||
# quantity formula, in which case the quantity on the contract
|
||||
# line is not used
|
||||
# Other use cases are easy to implement by overriding this method.
|
||||
'quantity': 1.0,
|
||||
'uom_id': self.product_uom.id,
|
||||
'price_unit': self.price_unit,
|
||||
'discount': self.discount,
|
||||
'date_end': self.date_end,
|
||||
'date_start': self.date_start or fields.Date.today(),
|
||||
'recurring_next_date': recurring_next_date,
|
||||
'recurring_interval': 1,
|
||||
'recurring_invoicing_type': self.recurring_invoicing_type,
|
||||
'recurring_rule_type': self.recurring_rule_type,
|
||||
'is_auto_renew': self.is_auto_renew,
|
||||
'auto_renew_interval': self.auto_renew_interval,
|
||||
'auto_renew_rule_type': self.auto_renew_rule_type,
|
||||
'termination_notice_interval': termination_notice_interval,
|
||||
'termination_notice_rule_type': termination_notice_rule_type,
|
||||
'contract_id': contract.id,
|
||||
'sale_order_line_id': self.id,
|
||||
'predecessor_contract_line_id': predecessor_contract_line_id,
|
||||
'analytic_account_id': self.order_id.analytic_account_id.id,
|
||||
"quantity": 1.0,
|
||||
"uom_id": self.product_uom.id,
|
||||
"price_unit": self.price_unit,
|
||||
"discount": self.discount,
|
||||
"date_end": self.date_end,
|
||||
"date_start": self.date_start or fields.Date.today(),
|
||||
"recurring_next_date": recurring_next_date,
|
||||
"recurring_interval": 1,
|
||||
"recurring_invoicing_type": self.recurring_invoicing_type,
|
||||
"recurring_rule_type": self.recurring_rule_type,
|
||||
"is_auto_renew": self.is_auto_renew,
|
||||
"auto_renew_interval": self.auto_renew_interval,
|
||||
"auto_renew_rule_type": self.auto_renew_rule_type,
|
||||
"termination_notice_interval": termination_notice_interval,
|
||||
"termination_notice_rule_type": termination_notice_rule_type,
|
||||
"contract_id": contract.id,
|
||||
"sale_order_line_id": self.id,
|
||||
"predecessor_contract_line_id": predecessor_contract_line_id,
|
||||
"analytic_account_id": self.order_id.analytic_account_id.id,
|
||||
}
|
||||
|
||||
@api.multi
|
||||
def create_contract_line(self, contract):
|
||||
contract_line_model = self.env['contract.line']
|
||||
contract_line = self.env['contract.line']
|
||||
contract_line_model = self.env["contract.line"]
|
||||
contract_line = self.env["contract.line"]
|
||||
predecessor_contract_line = False
|
||||
for rec in self:
|
||||
if rec.contract_line_id:
|
||||
@@ -221,9 +204,7 @@ class SaleOrderLine(models.Model):
|
||||
not rec.contract_line_id.date_end
|
||||
or rec.date_start <= rec.contract_line_id.date_end
|
||||
):
|
||||
rec.contract_line_id.stop(
|
||||
rec.date_start - relativedelta(days=1)
|
||||
)
|
||||
rec.contract_line_id.stop(rec.date_start - relativedelta(days=1))
|
||||
predecessor_contract_line = rec.contract_line_id
|
||||
if predecessor_contract_line:
|
||||
new_contract_line = contract_line_model.create(
|
||||
@@ -231,9 +212,7 @@ class SaleOrderLine(models.Model):
|
||||
contract, predecessor_contract_line.id
|
||||
)
|
||||
)
|
||||
predecessor_contract_line.successor_contract_line_id = (
|
||||
new_contract_line
|
||||
)
|
||||
predecessor_contract_line.successor_contract_line_id = new_contract_line
|
||||
else:
|
||||
new_contract_line = contract_line_model.create(
|
||||
rec._prepare_contract_line_values(contract)
|
||||
@@ -241,7 +220,7 @@ class SaleOrderLine(models.Model):
|
||||
contract_line |= new_contract_line
|
||||
return contract_line
|
||||
|
||||
@api.constrains('contract_id')
|
||||
@api.constrains("contract_id")
|
||||
def _check_contract_sale_partner(self):
|
||||
for rec in self:
|
||||
if rec.contract_id:
|
||||
@@ -253,14 +232,13 @@ class SaleOrderLine(models.Model):
|
||||
)
|
||||
)
|
||||
|
||||
@api.constrains('product_id', 'contract_id')
|
||||
@api.constrains("product_id", "contract_id")
|
||||
def _check_contract_sale_contract_template(self):
|
||||
for rec in self:
|
||||
if rec.contract_id:
|
||||
if (
|
||||
rec.contract_id.contract_template_id
|
||||
and rec.contract_template_id
|
||||
!= rec.contract_id.contract_template_id
|
||||
and rec.contract_template_id != rec.contract_id.contract_template_id
|
||||
):
|
||||
raise ValidationError(
|
||||
_("Contract product has different contract template")
|
||||
@@ -268,27 +246,26 @@ class SaleOrderLine(models.Model):
|
||||
|
||||
def _compute_invoice_status(self):
|
||||
res = super(SaleOrderLine, self)._compute_invoice_status()
|
||||
for line in self.filtered('contract_id'):
|
||||
line.invoice_status = 'no'
|
||||
for line in self.filtered("contract_id"):
|
||||
line.invoice_status = "no"
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def invoice_line_create(self, invoice_id, qty):
|
||||
return super(
|
||||
SaleOrderLine, self.filtered(lambda l: not l.contract_id)
|
||||
).invoice_line_create(invoice_id, qty)
|
||||
|
||||
@api.depends(
|
||||
'qty_invoiced',
|
||||
'qty_delivered',
|
||||
'product_uom_qty',
|
||||
'order_id.state',
|
||||
'product_id.is_contract',
|
||||
"qty_invoiced",
|
||||
"qty_delivered",
|
||||
"product_uom_qty",
|
||||
"order_id.state",
|
||||
"product_id.is_contract",
|
||||
)
|
||||
def _get_to_invoice_qty(self):
|
||||
"""
|
||||
sale line linked to contracts must not be invoiced from sale order
|
||||
"""
|
||||
res = super()._get_to_invoice_qty()
|
||||
self.filtered('product_id.is_contract').update({'qty_to_invoice': 0.0})
|
||||
self.filtered("product_id.is_contract").update({"qty_to_invoice": 0.0})
|
||||
return res
|
||||
|
||||
Reference in New Issue
Block a user