[IMP] sale_timesheet : set the partner_id on the wizard for sale order creation.
The partner_id on the wizard for sale order creation (from project and from tasks) is now set with the one on the project or on the task if it is set. Some fields were moved to community (from sale_timesheet_enterprise). Concerned fields : allow_billable (project and task), allow_timesheet_timer (project) This also move timesheet_product_id to community. This field was being added in industry_fsm_sale and was required if allow_billable and allow_timesheets were true. But those 2 other fields are already available once sale_timesheet is installed. The field timesheet_product_id is thus being moved to sale_timesheet for more coherence. Task-2157571 closes odoo/odoo#44509 Related: odoo/enterprise#8118 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
@@ -15,6 +15,7 @@ have real delivered quantities in sales orders.
|
||||
""",
|
||||
'depends': ['sale_project', 'hr_timesheet'],
|
||||
'data': [
|
||||
'data/sale_service_data.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'security/sale_timesheet_security.xml',
|
||||
'views/account_invoice_views.xml',
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="time_product" model="product.product">
|
||||
<field name="name">Service on Timesheet</field>
|
||||
<field name="type">service</field>
|
||||
<field name="list_price">40</field>
|
||||
<field name="service_policy">delivered_timesheet</field>
|
||||
<field name="image_1920" type="base64" file="sale_timesheet/static/img/product_product_time_product.png"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -5,9 +5,20 @@ from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
# YTI PLEASE SPLIT ME
|
||||
class Project(models.Model):
|
||||
_inherit = 'project.project'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
""" Pre-fill timesheet product as "Time" data product when creating new project allowing billable tasks by default. """
|
||||
result = super(Project, self).default_get(fields)
|
||||
if 'timesheet_product_id' in fields and result.get('allow_billable') and result.get('allow_timesheets') and not result.get('timesheet_product_id'):
|
||||
default_product = self.env.ref('sale_timesheet.time_product', False)
|
||||
if default_product:
|
||||
result['timesheet_product_id'] = default_product.id
|
||||
return result
|
||||
|
||||
billable_type = fields.Selection([
|
||||
('task_rate', 'At Task Rate'),
|
||||
('employee_rate', 'At Employee Rate'),
|
||||
@@ -22,6 +33,18 @@ class Project(models.Model):
|
||||
"By extension, it defines the rate at which an employee's time on the project is billed.")
|
||||
allow_billable = fields.Boolean("Bill from Tasks")
|
||||
display_create_order = fields.Boolean(compute='_compute_display_create_order')
|
||||
timesheet_product_id = fields.Many2one(
|
||||
'product.product', string='Timesheet Product',
|
||||
domain="""[
|
||||
('type', '=', 'service'),
|
||||
('invoice_policy', '=', 'delivery'),
|
||||
('service_type', '=', 'timesheet'),
|
||||
'|', ('company_id', '=', False), ('company_id', '=', company_id)]""",
|
||||
help='Select a Service product with which you would like to bill your time spent on tasks.')
|
||||
|
||||
_sql_constraints = [
|
||||
('timesheet_product_required_if_billable_and_timesheets', "CHECK((allow_billable = 't' AND allow_timesheets = 't' AND timesheet_product_id IS NOT NULL) OR (allow_billable = 'f') OR (allow_timesheets = 'f'))", 'The timesheet product is required when the task can be billed and timesheets are allowed.'),
|
||||
]
|
||||
|
||||
@api.depends('billable_type', 'allow_billable', 'sale_order_id', 'partner_id')
|
||||
def _compute_display_create_order(self):
|
||||
@@ -51,14 +74,24 @@ class Project(models.Model):
|
||||
if self.billable_type == 'no':
|
||||
self.sale_line_employee_ids = False
|
||||
|
||||
@api.onchange('allow_billable')
|
||||
def _onchange_allow_billable(self):
|
||||
@api.depends('allow_timesheets', 'allow_billable')
|
||||
def _compute_timesheet_product_id(self):
|
||||
default_product = self.env.ref('sale_timesheet.time_product', False)
|
||||
for project in self:
|
||||
if not project.allow_timesheets or not project.allow_billable:
|
||||
project.timesheet_product_id = False
|
||||
elif not project.timesheet_product_id:
|
||||
project.timesheet_product_id = default_product
|
||||
|
||||
@api.depends('allow_billable')
|
||||
def _compute_allow_billable(self):
|
||||
""" In order to keep task billable type as 'task_rate' using sale_timesheet usual flow.
|
||||
(see _compute_billable_type method in sale_timesheet)
|
||||
"""
|
||||
if self.allow_billable:
|
||||
self.sale_order_id = False
|
||||
self.sale_line_employee_ids = False
|
||||
self.filtered(lambda p: p.allow_billable).update({
|
||||
'sale_order_id': False,
|
||||
'sale_line_employee_ids': False,
|
||||
})
|
||||
|
||||
@api.constrains('sale_line_id', 'billable_type')
|
||||
def _check_sale_line_type(self):
|
||||
@@ -118,6 +151,7 @@ class Project(models.Model):
|
||||
"context": {
|
||||
'active_id': self.id,
|
||||
'active_model': 'project.project',
|
||||
'default_product_id': self.timesheet_product_id.id,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -233,6 +267,7 @@ class ProjectTask(models.Model):
|
||||
'active_id': self.id,
|
||||
'active_model': 'project.task',
|
||||
'form_view_initial_mode': 'edit',
|
||||
'default_product_id': self.project_id.timesheet_product_id.id,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
@@ -4,7 +4,7 @@
|
||||
<record id="project_project_view_form" model="ir.ui.view">
|
||||
<field name="name">project.project.form.inherit</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="project.edit_project"/>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header" position="inside">
|
||||
<button name="action_make_billable" string="Create Sales Order" type="object" attrs="{'invisible': [('display_create_order', '=', False)]}" groups="sales_team.group_sale_salesman"/>
|
||||
@@ -26,25 +26,18 @@
|
||||
</field>
|
||||
</page>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_view_form_inherit" model="ir.ui.view">
|
||||
<field name="name">project.view.form.inherit</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='timesheet_settings']/.." position="after">
|
||||
<div class="row mt16 o_settings_container">
|
||||
<div class="col-lg-6 o_setting_box" id="allow_billable_container" attrs="{'invisible': [('billable_type', '=', 'employee_rate')]}">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="allow_billable"/>
|
||||
<field name="allow_billable" attrs="{'readonly': [('sale_order_id', '!=', False)]}"/>
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="allow_billable"/>
|
||||
<div class="text-muted" id="allow_billable_setting">
|
||||
Invoice your time and material from tasks
|
||||
</div>
|
||||
<field name="timesheet_product_id" attrs="{'invisible': ['|', ('allow_billable', '=', False), ('allow_timesheets', '=', False)], 'required': ['&', ('allow_billable', '=', True), ('allow_timesheets', '=', True)]}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -52,6 +45,20 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_project_view_form_simplified_inherit" model="ir.ui.view">
|
||||
<field name="name">project.project.view.form.simplified.inherit</field>
|
||||
<field name="model">project.project</field>
|
||||
<field name="inherit_id" ref="hr_timesheet.project_project_view_form_simplified_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="allow_timesheet_timer" position="after">
|
||||
<field name="billable_type" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="allow_billable" attrs="{'invisible': [('billable_type', '=', 'employee_rate')]}"/>
|
||||
<field name="timesheet_product_id" attrs="{'invisible': ['|', ('allow_billable', '=', False), ('allow_timesheets', '=', False)], 'required': ['&', ('allow_billable', '=', True), ('allow_timesheets', '=', True)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="project_project_view_kanban_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">project.project.kanban.inherit.sale.timesheet</field>
|
||||
<field name="model">project.project</field>
|
||||
|
||||
@@ -23,7 +23,8 @@ class ProjectCreateSalesOrder(models.TransientModel):
|
||||
if project.billable_type != 'no':
|
||||
raise UserError(_("The project is already billable."))
|
||||
result['project_id'] = active_id
|
||||
result['partner_id'] = project.partner_id.id
|
||||
if not result.get('partner_id', False):
|
||||
result['partner_id'] = project.partner_id.id
|
||||
return result
|
||||
|
||||
project_id = fields.Many2one('project.project', "Project", domain=[('sale_line_id', '=', False)], help="Project for which we are creating a sales order", required=True)
|
||||
|
||||
@@ -23,7 +23,8 @@ class ProjectTaskCreateSalesOrder(models.TransientModel):
|
||||
if task.billable_type != 'no':
|
||||
raise UserError(_("The task is already billable."))
|
||||
result['task_id'] = active_id
|
||||
result['partner_id'] = task.partner_id.id
|
||||
if not result.get('partner_id', False):
|
||||
result['partner_id'] = task.partner_id.id
|
||||
return result
|
||||
|
||||
task_id = fields.Many2one('project.task', "Task", domain=[('sale_line_id', '=', False)], help="Task for which we are creating a sales order", required=True)
|
||||
|
||||
Reference in New Issue
Block a user