[IMP] product,sale: Convert _onchange_type into compute methods
This commit is contained in:
committed by
Victor Feyens
parent
70b9b7a772
commit
bbd65b8a3a
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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])]")
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user