diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/sale_timesheet/models/product.py | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/sale_timesheet/models/product.py')
| -rw-r--r-- | addons/sale_timesheet/models/product.py | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/addons/sale_timesheet/models/product.py b/addons/sale_timesheet/models/product.py new file mode 100644 index 00000000..3d6e0766 --- /dev/null +++ b/addons/sale_timesheet/models/product.py @@ -0,0 +1,136 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import threading + +from odoo import api, fields, models, _ +from odoo.exceptions import ValidationError + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + service_policy = fields.Selection([ + ('ordered_timesheet', 'Prepaid'), + ('delivered_timesheet', 'Timesheets on tasks'), + ('delivered_manual', 'Milestones (manually set quantities on order)') + ], 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'}) + # override domain + project_id = fields.Many2one(domain="[('company_id', '=', current_company_id), ('allow_billable', '=', True), ('bill_type', '=', 'customer_task'), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True])]") + project_template_id = fields.Many2one(domain="[('company_id', '=', current_company_id), ('allow_billable', '=', True), ('bill_type', '=', 'customer_project'), ('allow_timesheets', 'in', [service_policy == 'delivered_timesheet', True])]") + + def _default_visible_expense_policy(self): + visibility = self.user_has_groups('project.group_project_user') + return visibility or super(ProductTemplate, self)._default_visible_expense_policy() + + def _compute_visible_expense_policy(self): + visibility = self.user_has_groups('project.group_project_user') + for product_template in self: + if not product_template.visible_expense_policy: + product_template.visible_expense_policy = visibility + return super(ProductTemplate, self)._compute_visible_expense_policy() + + @api.depends('invoice_policy', 'service_type') + def _compute_service_policy(self): + for product in self: + policy = None + if product.invoice_policy == 'delivery': + policy = 'delivered_manual' if product.service_type == 'manual' else 'delivered_timesheet' + elif product.invoice_policy == 'order' and (product.service_type == 'timesheet' or product.type == 'service'): + policy = 'ordered_timesheet' + product.service_policy = policy + + def _inverse_service_policy(self): + for product in self: + policy = product.service_policy + if not policy and not product.invoice_policy =='delivery': + product.invoice_policy = 'order' + product.service_type = 'manual' + elif policy == 'ordered_timesheet': + product.invoice_policy = 'order' + product.service_type = 'timesheet' + else: + product.invoice_policy = 'delivery' + product.service_type = 'manual' if policy == 'delivered_manual' else 'timesheet' + + @api.onchange('type') + def _onchange_type(self): + res = super(ProductTemplate, self)._onchange_type() + if self.type == 'service' and not self.invoice_policy: + self.invoice_policy = 'order' + self.service_type = 'timesheet' + elif self.type == 'service' and self.invoice_policy == 'order': + self.service_policy = 'ordered_timesheet' + elif self.type == 'consu' and not self.invoice_policy and self.service_policy == 'ordered_timesheet': + self.invoice_policy = 'order' + return res + + @api.model + def _get_onchange_service_policy_updates(self, service_tracking, service_policy, project_id, project_template_id): + vals = {} + if service_tracking != 'no' and service_policy == 'delivered_timesheet': + if project_id and not project_id.allow_timesheets: + vals['project_id'] = False + elif project_template_id and not project_template_id.allow_timesheets: + vals['project_template_id'] = False + return vals + + @api.onchange('service_policy') + def _onchange_service_policy(self): + vals = self._get_onchange_service_policy_updates(self.service_tracking, + self.service_policy, + self.project_id, + self.project_template_id) + if vals: + self.update(vals) + + def unlink(self): + time_product = self.env.ref('sale_timesheet.time_product') + if time_product.product_tmpl_id in self: + raise ValidationError(_('The %s product is required by the Timesheet app and cannot be archived/deleted.') % time_product.name) + return super(ProductTemplate, self).unlink() + + def write(self, vals): + # timesheet product can't be archived + test_mode = getattr(threading.currentThread(), 'testing', False) or self.env.registry.in_test_mode() + if not test_mode and 'active' in vals and not vals['active']: + time_product = self.env.ref('sale_timesheet.time_product') + if time_product.product_tmpl_id in self: + raise ValidationError(_('The %s product is required by the Timesheet app and cannot be archived/deleted.') % time_product.name) + return super(ProductTemplate, self).write(vals) + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + def _is_delivered_timesheet(self): + """ Check if the product is a delivered timesheet """ + self.ensure_one() + return self.type == 'service' and self.service_policy == 'delivered_timesheet' + + @api.onchange('service_policy') + def _onchange_service_policy(self): + vals = self.product_tmpl_id._get_onchange_service_policy_updates(self.service_tracking, + self.service_policy, + self.project_id, + self.project_template_id) + if vals: + self.update(vals) + + def unlink(self): + time_product = self.env.ref('sale_timesheet.time_product') + if time_product in self: + raise ValidationError(_('The %s product is required by the Timesheet app and cannot be archived/deleted.') % time_product.name) + return super(ProductProduct, self).unlink() + + def write(self, vals): + # timesheet product can't be archived + test_mode = getattr(threading.currentThread(), 'testing', False) or self.env.registry.in_test_mode() + if not test_mode and 'active' in vals and not vals['active']: + time_product = self.env.ref('sale_timesheet.time_product') + if time_product in self: + raise ValidationError(_('The %s product is required by the Timesheet app and cannot be archived/deleted.') % time_product.name) + return super(ProductProduct, self).write(vals) |
