Before this commit, the values of selection `service_policy` field are given with a function and so the choices are dynamically given according to the modules installed and the project settings. The problem is the string for those values are not translated because the ORM cannot do it automatically since the values are dynamically given and so those string should be translated with `_` function. This commit translates the string of those values with `_` function to be sure the strings are translated in the language of the current user. closes odoo/odoo#108154 X-original-commit: 90cf43789d849df3908f4636228cb643a005427f Signed-off-by: Laurent Stukkens (ltu) <ltu@odoo.com> Signed-off-by: Xavier Bol (xbo) <xbo@odoo.com>
211 lines
10 KiB
Python
211 lines
10 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class ProductTemplate(models.Model):
|
|
_inherit = 'product.template'
|
|
|
|
@api.model
|
|
def _selection_service_policy(self):
|
|
service_policies = [
|
|
# (service_policy, string)
|
|
('ordered_prepaid', _('Prepaid/Fixed Price')),
|
|
('delivered_manual', _('Based on Delivered Quantity (Manual)')),
|
|
]
|
|
if self.user_has_groups('project.group_project_milestone'):
|
|
service_policies.insert(1, ('delivered_milestones', _('Based on Milestones')))
|
|
return service_policies
|
|
|
|
service_tracking = fields.Selection(
|
|
selection=[
|
|
('no', 'Nothing'),
|
|
('task_global_project', 'Task'),
|
|
('task_in_project', 'Project & Task'),
|
|
('project_only', 'Project'),
|
|
],
|
|
string="Create on Order", default="no",
|
|
help="On Sales order confirmation, this product can generate a project and/or task. \
|
|
From those, you can track the service you are selling.\n \
|
|
'In sale order\'s project': Will use the sale order\'s configured project if defined or fallback to \
|
|
creating a new project based on the selected template.")
|
|
project_id = fields.Many2one(
|
|
'project.project', 'Project', company_dependent=True,
|
|
domain="[('company_id', '=', current_company_id)]")
|
|
project_template_id = fields.Many2one(
|
|
'project.project', 'Project Template', company_dependent=True, copy=True,
|
|
domain="[('company_id', '=', current_company_id)]")
|
|
service_policy = fields.Selection('_selection_service_policy', string="Service Invoicing Policy", compute='_compute_service_policy', inverse='_inverse_service_policy')
|
|
service_type = fields.Selection(selection_add=[
|
|
('milestones', 'Project Milestones'),
|
|
])
|
|
|
|
@api.depends('invoice_policy', 'service_type', 'type')
|
|
def _compute_service_policy(self):
|
|
for product in self:
|
|
product.service_policy = self._get_general_to_service(product.invoice_policy, product.service_type)
|
|
if not product.service_policy and product.type == 'service':
|
|
product.service_policy = 'ordered_prepaid'
|
|
|
|
@api.depends('service_tracking', 'service_policy', 'type')
|
|
def _compute_product_tooltip(self):
|
|
super()._compute_product_tooltip()
|
|
for record in self.filtered(lambda record: record.type == 'service'):
|
|
if record.service_policy == 'ordered_prepaid':
|
|
if record.service_tracking == 'no':
|
|
record.product_tooltip = _(
|
|
"Invoice ordered quantities as soon as this service is sold."
|
|
)
|
|
elif record.service_tracking == 'task_global_project':
|
|
record.product_tooltip = _(
|
|
"Invoice ordered quantities as soon as this service is sold. "
|
|
"Create a task in an existing project to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'project_only':
|
|
record.product_tooltip = _(
|
|
"Invoice ordered quantities as soon as this service is sold. "
|
|
"Create a project for the order with a task for each sales order line "
|
|
"to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'task_in_project':
|
|
record.product_tooltip = _(
|
|
"Invoice ordered quantities as soon as this service is sold. "
|
|
"Create an empty project for the order to track the time spent."
|
|
)
|
|
elif record.service_policy == 'delivered_milestones':
|
|
if record.service_tracking == 'no':
|
|
record.product_tooltip = _(
|
|
"Invoice your milestones when they are reached."
|
|
)
|
|
elif record.service_tracking == 'task_global_project':
|
|
record.product_tooltip = _(
|
|
"Invoice your milestones when they are reached. "
|
|
"Create a task in an existing project to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'project_only':
|
|
record.product_tooltip = _(
|
|
"Invoice your milestones when they are reached. "
|
|
"Create a project for the order with a task for each sales order line "
|
|
"to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'task_in_project':
|
|
record.product_tooltip = _(
|
|
"Invoice your milestones when they are reached. "
|
|
"Create an empty project for the order to track the time spent."
|
|
)
|
|
elif record.service_policy == 'delivered_manual':
|
|
if record.service_tracking == 'no':
|
|
record.product_tooltip = _(
|
|
"Invoice this service when it is delivered (set the quantity by hand on your sales order lines). "
|
|
)
|
|
elif record.service_tracking == 'task_global_project':
|
|
record.product_tooltip = _(
|
|
"Invoice this service when it is delivered (set the quantity by hand on your sales order lines). "
|
|
"Create a task in an existing project to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'project_only':
|
|
record.product_tooltip = _(
|
|
"Invoice this service when it is delivered (set the quantity by hand on your sales order lines). "
|
|
"Create a project for the order with a task for each sales order line "
|
|
"to track the time spent."
|
|
)
|
|
elif record.service_tracking == 'task_in_project':
|
|
record.product_tooltip = _(
|
|
"Invoice this service when it is delivered (set the quantity by hand on your sales order lines). "
|
|
"Create an empty project for the order to track the time spent."
|
|
)
|
|
|
|
def _get_service_to_general_map(self):
|
|
return {
|
|
# service_policy: (invoice_policy, service_type)
|
|
'ordered_prepaid': ('order', 'manual'),
|
|
'delivered_milestones': ('delivery', 'milestones'),
|
|
'delivered_manual': ('delivery', 'manual'),
|
|
}
|
|
|
|
def _get_general_to_service_map(self):
|
|
return {v: k for k, v in self._get_service_to_general_map().items()}
|
|
|
|
def _get_service_to_general(self, service_policy):
|
|
return self._get_service_to_general_map().get(service_policy, (False, False))
|
|
|
|
def _get_general_to_service(self, invoice_policy, service_type):
|
|
general_to_service = self._get_general_to_service_map()
|
|
return general_to_service.get((invoice_policy, service_type), False)
|
|
|
|
@api.onchange('service_policy')
|
|
def _inverse_service_policy(self):
|
|
for product in self:
|
|
if product.service_policy:
|
|
product.invoice_policy, product.service_type = self._get_service_to_general(product.service_policy)
|
|
|
|
@api.constrains('project_id', 'project_template_id')
|
|
def _check_project_and_template(self):
|
|
""" NOTE 'service_tracking' should be in decorator parameters but since ORM check constraints twice (one after setting
|
|
stored fields, one after setting non stored field), the error is raised when company-dependent fields are not set.
|
|
So, this constraints does cover all cases and inconsistent can still be recorded until the ORM change its behavior.
|
|
"""
|
|
for product in self:
|
|
if product.service_tracking == 'no' and (product.project_id or product.project_template_id):
|
|
raise ValidationError(_('The product %s should not have a project nor a project template since it will not generate project.') % (product.name,))
|
|
elif product.service_tracking == 'task_global_project' and product.project_template_id:
|
|
raise ValidationError(_('The product %s should not have a project template since it will generate a task in a global project.') % (product.name,))
|
|
elif product.service_tracking in ['task_in_project', 'project_only'] and product.project_id:
|
|
raise ValidationError(_('The product %s should not have a global project since it will generate a project.') % (product.name,))
|
|
|
|
@api.onchange('service_tracking')
|
|
def _onchange_service_tracking(self):
|
|
if self.service_tracking == 'no':
|
|
self.project_id = False
|
|
self.project_template_id = False
|
|
elif self.service_tracking == 'task_global_project':
|
|
self.project_template_id = False
|
|
elif self.service_tracking in ['task_in_project', 'project_only']:
|
|
self.project_id = False
|
|
|
|
@api.onchange('type')
|
|
def _onchange_type(self):
|
|
res = super(ProductTemplate, self)._onchange_type()
|
|
if self.type != 'service':
|
|
self.service_tracking = 'no'
|
|
return res
|
|
|
|
def write(self, vals):
|
|
if 'type' in vals and vals['type'] != 'service':
|
|
vals.update({
|
|
'service_tracking': 'no',
|
|
'project_id': False
|
|
})
|
|
return super(ProductTemplate, self).write(vals)
|
|
|
|
|
|
class ProductProduct(models.Model):
|
|
_inherit = 'product.product'
|
|
|
|
@api.onchange('service_tracking')
|
|
def _onchange_service_tracking(self):
|
|
if self.service_tracking == 'no':
|
|
self.project_id = False
|
|
self.project_template_id = False
|
|
elif self.service_tracking == 'task_global_project':
|
|
self.project_template_id = False
|
|
elif self.service_tracking in ['task_in_project', 'project_only']:
|
|
self.project_id = False
|
|
|
|
@api.onchange('type')
|
|
def _onchange_type(self):
|
|
res = super(ProductProduct, self)._onchange_type()
|
|
if self.type != 'service':
|
|
self.service_tracking = 'no'
|
|
return res
|
|
|
|
def write(self, vals):
|
|
if 'type' in vals and vals['type'] != 'service':
|
|
vals.update({
|
|
'service_tracking': 'no',
|
|
'project_id': False
|
|
})
|
|
return super(ProductProduct, self).write(vals)
|