[IMP] product,sale: Convert _onchange_type into compute methods

This commit is contained in:
Yannick Tivisse
2021-12-23 15:30:23 +01:00
committed by Victor Feyens
parent 70b9b7a772
commit bbd65b8a3a
7 changed files with 57 additions and 69 deletions
+3 -13
View File
@@ -51,14 +51,9 @@ class ProductTemplate(models.Model):
'A consumable product is a product for which stock is not managed.\n'
'A service is a non-material product you provide.')
type = fields.Selection(
selection=[
('consu', 'Consumable'),
('service', 'Service')
],
compute='_compute_type',
store=True,
readonly=False,
)
[('consu', 'Consumable'),
('service', 'Service')],
compute='_compute_type', store=True, readonly=False, precompute=True)
categ_id = fields.Many2one(
'product.category', 'Product Category',
change_default=True, default=_get_default_category_id, group_expand='_read_group_categ_id',
@@ -389,11 +384,6 @@ class ProductTemplate(models.Model):
if self.uom_id and self.uom_po_id and self.uom_id.category_id != self.uom_po_id.category_id:
self.uom_po_id = self.uom_id
@api.onchange('type')
def _onchange_type(self):
# Do nothing but needed for inheritance
return {}
def _sanitize_vals(self, vals):
"""Sanitize vales for writing/creating product templates and variants.
+16 -18
View File
@@ -15,11 +15,12 @@ _logger = logging.getLogger(__name__)
class ProductTemplate(models.Model):
_inherit = 'product.template'
service_type = fields.Selection([('manual', 'Manually set quantities on order')], string='Track Service',
service_type = fields.Selection(
[('manual', 'Manually set quantities on order')], string='Track Service',
compute='_compute_service_type', store=True, readonly=False, precompute=True,
help="Manually set quantities on order: Invoice based on the manually entered quantity, without creating an analytic account.\n"
"Timesheets on contract: Invoice based on the tracked hours on the related timesheet.\n"
"Create a task and track hours: Create a task on the sales order validation and track the work hours.",
default='manual')
"Create a task and track hours: Create a task on the sales order validation and track the work hours.")
sale_line_warn = fields.Selection(WARNING_MESSAGE, 'Sales Order Line', help=WARNING_HELP, required=True, default="no-message")
sale_line_warn_msg = fields.Text('Message for Sales Order Line')
expense_policy = fields.Selection(
@@ -33,12 +34,12 @@ class ProductTemplate(models.Model):
visible_expense_policy = fields.Boolean("Re-Invoice Policy visible", compute='_compute_visible_expense_policy')
sales_count = fields.Float(compute='_compute_sales_count', string='Sold')
visible_qty_configurator = fields.Boolean("Quantity visible in configurator", compute='_compute_visible_qty_configurator')
invoice_policy = fields.Selection([
('order', 'Ordered quantities'),
('delivery', 'Delivered quantities')], string='Invoicing Policy',
invoice_policy = fields.Selection(
[('order', 'Ordered quantities'),
('delivery', 'Delivered quantities')], string='Invoicing Policy',
compute='_compute_invoice_policy', store=True, readonly=False, precompute=True,
help='Ordered Quantity: Invoice quantities ordered by the customer.\n'
'Delivered Quantity: Invoice quantities delivered to the customer.',
default='order')
'Delivered Quantity: Invoice quantities delivered to the customer.')
def _compute_visible_qty_configurator(self):
for product_template in self:
@@ -50,7 +51,6 @@ class ProductTemplate(models.Model):
for product_template in self:
product_template.visible_expense_policy = visibility
@api.depends('sale_ok')
def _compute_expense_policy(self):
self.filtered(lambda t: not t.sale_ok).expense_policy = 'no'
@@ -126,15 +126,13 @@ class ProductTemplate(models.Model):
return self._create_product_variant(combination, log_warning=True).id or 0
@api.onchange('type')
def _onchange_type(self):
""" Force values to stay consistent with integrity constraints """
res = super(ProductTemplate, self)._onchange_type()
if self.type == 'consu':
if not self.invoice_policy:
self.invoice_policy = 'order'
self.service_type = 'manual'
return res
@api.depends('type')
def _compute_service_type(self):
self.filtered(lambda t: t.type == 'consu' or not t.service_type).service_type = 'manual'
@api.depends('type')
def _compute_invoice_policy(self):
self.filtered(lambda t: t.type == 'consu' or not t.invoice_policy).invoice_policy = 'order'
@api.model
def get_import_templates(self):
@@ -8,7 +8,10 @@ from odoo.exceptions import ValidationError
class ProductTemplate(models.Model):
_inherit = 'product.template'
service_to_purchase = fields.Boolean("Subcontract Service", help="If ticked, each time you sell this product through a SO, a RfQ is automatically created to buy the product. Tip: don't forget to set a vendor on the product.")
service_to_purchase = fields.Boolean(
"Subcontract Service",
compute='_compute_service_to_purchase', store=True, readonly=False,
help="If ticked, each time you sell this product through a SO, a RfQ is automatically created to buy the product. Tip: don't forget to set a vendor on the product.")
_sql_constraints = [
('service_to_purchase', "CHECK((type != 'service' AND service_to_purchase != true) or (type = 'service'))", 'Product that is not a service can not create RFQ.'),
@@ -19,14 +22,8 @@ class ProductTemplate(models.Model):
if self.service_to_purchase and not self.seller_ids:
raise ValidationError("Please define the vendor from whom you would like to purchase this service automatically.")
@api.onchange('type')
def _onchange_type(self):
res = super(ProductTemplate, self)._onchange_type()
if self.type != 'service':
self.service_to_purchase = False
return res
@api.onchange('expense_policy')
def _onchange_expense_policy(self):
if self.expense_policy != 'no':
self.service_to_purchase = False
@api.depends('type', 'expense_policy')
def _compute_service_to_purchase(self):
for template in self:
if template.type != 'service' or template.expense_policy != 'no':
template.service_to_purchase = False
+9 -10
View File
@@ -7,13 +7,12 @@ from odoo import api, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
@api.onchange('type')
def _onchange_type(self):
""" We want to prevent storable product to be expensed, since it make no sense as when confirm
expenses, the product is already out of our stock.
"""
res = super(ProductTemplate, self)._onchange_type()
if self.type == 'product':
self.expense_policy = 'no'
self.service_type = 'manual'
return res
@api.depends('type')
def _compute_expense_policy(self):
super()._compute_expense_policy()
self.filtered(lambda t: t.type == 'product').expense_policy = 'no'
@api.depends('type')
def _compute_service_type(self):
super()._compute_service_type()
self.filtered(lambda t: t.type == 'product').service_type = 'manual'
+1 -1
View File
@@ -24,7 +24,7 @@ class ProductTemplate(models.Model):
], string="Service Invoicing Policy", compute='_compute_service_policy', inverse='_inverse_service_policy')
service_type = fields.Selection(selection_add=[
('timesheet', 'Timesheets on project (one fare per SO/Project)'),
], ondelete={'timesheet': 'set default'})
], ondelete={'timesheet': 'set manual'})
# override domain
project_id = fields.Many2one(domain="[('company_id', '=', current_company_id), ('allow_billable', '=', True), ('pricing_type', '=', 'task_rate'), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True])]")
project_template_id = fields.Many2one(domain="[('company_id', '=', current_company_id), ('allow_billable', '=', True), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True])]")
+19 -13
View File
@@ -624,7 +624,10 @@ class ProductTemplate(models.Model):
tracking = fields.Selection([
('serial', 'By Unique Serial Number'),
('lot', 'By Lots'),
('none', 'No Tracking')], string="Tracking", help="Ensure the traceability of a storable product in your warehouse.", default='none', required=True)
('none', 'No Tracking')],
string="Tracking", required=True,
compute='_compute_tracking', store=True, readonly=False, precompute=True,
help="Ensure the traceability of a storable product in your warehouse.")
description_picking = fields.Text('Description on Picking', translate=True)
description_pickingout = fields.Text('Description on Delivery Orders', translate=True)
description_pickingin = fields.Text('Description on Receptions', translate=True)
@@ -799,25 +802,28 @@ class ProductTemplate(models.Model):
def _onchange_tracking(self):
return self.mapped('product_variant_ids')._onchange_tracking()
@api.depends('type')
def _compute_tracking(self):
self.filtered(
lambda t: not t.tracking or t.type == 'consu' and t.tracking != 'none'
).tracking = 'none'
@api.onchange('type')
def _onchange_type(self):
res = super(ProductTemplate, self)._onchange_type() or {}
if self.type == 'consu' and self.tracking != 'none':
self.tracking = 'none'
# Return a warning when trying to change the product type
if self.ids and self.product_variant_ids.ids and self.env['stock.move.line'].sudo().search_count([
('product_id', 'in', self.product_variant_ids.ids), ('state', '!=', 'cancel')
]):
res['warning'] = {
'title': _('Warning!'),
'message': _(
'This product has been used in at least one inventory movement. '
'It is not advised to change the Product Type since it can lead to inconsistencies. '
'A better solution could be to archive the product and create a new one instead.'
)
return {
'warning': {
'title': _('Warning!'),
'message': _(
'This product has been used in at least one inventory movement. '
'It is not advised to change the Product Type since it can lead to inconsistencies. '
'A better solution could be to archive the product and create a new one instead.'
)
}
}
return res
def write(self, vals):
self._sanitize_vals(vals)
@@ -3,8 +3,6 @@
from odoo.addons.website_sale_stock.tests.test_website_sale_stock_product_warehouse import TestWebsiteSaleStockProductWarehouse
from odoo.tests import tagged
class TestWishlistEmail(TestWebsiteSaleStockProductWarehouse):
@classmethod