[MIG] sale_timesheet: migrate module to new API
This commit is contained in:
committed by
Thibault Delavallée
parent
572053d9f5
commit
fb9414af9a
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="product.service_order_01" model="product.product">
|
||||
<field name="track_service">timesheet</field>
|
||||
@@ -32,4 +32,4 @@
|
||||
<field name="project_id" ref="project_GAP"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,12 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import models, api
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class AccountAnalyticLine(models.Model):
|
||||
_inherit = 'account.analytic.line'
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if values.get('task_id'):
|
||||
task = self.env['project.task'].browse(values['task_id'])
|
||||
values['so_line'] = task.sale_line_id.id or values.get('so_line', False)
|
||||
values.update(self._get_timesheet_cost(values))
|
||||
return super(AccountAnalyticLine, self).create(values)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
if values.get('task_id'):
|
||||
task = self.env['project.task'].browse(values['task_id'])
|
||||
values['so_line'] = task.sale_line_id.id or values.get('so_line', False)
|
||||
for line in self:
|
||||
values.update(line._get_timesheet_cost(values))
|
||||
super(AccountAnalyticLine, line).write(values)
|
||||
return True
|
||||
|
||||
def _get_timesheet_cost(self, values):
|
||||
values = values if values is not None else {}
|
||||
if values.get('project_id') or self.project_id:
|
||||
if values.get('amount'):
|
||||
return {}
|
||||
unit_amount = values.get('unit_amount', 0.0) or self.unit_amount
|
||||
user_id = values.get('user_id') or self.user_id.id or self._default_user()
|
||||
user = self.env['res.users'].browse([user_id])
|
||||
emp = self.env['hr.employee'].search([('user_id', '=', user_id)], limit=1)
|
||||
cost = emp and emp.timesheet_cost or 0.0
|
||||
uom = (emp or user).company_id.project_time_mode_id
|
||||
# Nominal employee cost = 1 * company project UoM (project_time_mode_id)
|
||||
return {
|
||||
'amount': -unit_amount * cost,
|
||||
'product_uom_id': uom.id
|
||||
}
|
||||
return {}
|
||||
|
||||
def _get_sale_order_line(self, vals=None):
|
||||
result = dict(vals or {})
|
||||
if self.project_id:
|
||||
@@ -26,45 +62,6 @@ class AccountAnalyticLine(models.Model):
|
||||
'so_line': sol.id,
|
||||
'product_id': sol.product_id.id,
|
||||
})
|
||||
result = self._get_timesheet_cost(result)
|
||||
result.update(self._get_timesheet_cost(result))
|
||||
|
||||
result = super(AccountAnalyticLine, self)._get_sale_order_line(vals=result)
|
||||
return result
|
||||
|
||||
def _get_timesheet_cost(self, vals=None):
|
||||
result = dict(vals or {})
|
||||
if result.get('project_id') or self.project_id:
|
||||
if result.get('amount'):
|
||||
return result
|
||||
unit_amount = result.get('unit_amount', 0.0) or self.unit_amount
|
||||
user_id = result.get('user_id') or self.user_id.id or self._default_user()
|
||||
user = self.env['res.users'].browse([user_id])
|
||||
emp = self.env['hr.employee'].search([('user_id', '=', user_id)], limit=1)
|
||||
cost = emp and emp.timesheet_cost or 0.0
|
||||
uom = (emp or user).company_id.project_time_mode_id
|
||||
# Nominal employee cost = 1 * company project UoM (project_time_mode_id)
|
||||
result.update(
|
||||
amount=(-unit_amount * cost),
|
||||
product_uom_id=uom.id
|
||||
)
|
||||
return result
|
||||
|
||||
@api.model
|
||||
def _update_values(self, values):
|
||||
if values.get('task_id', False):
|
||||
task = self.env['project.task'].browse(values['task_id'])
|
||||
values['so_line'] = task.sale_line_id and task.sale_line_id.id or values.get('so_line', False)
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
self._update_values(values)
|
||||
for line in self:
|
||||
values = line._get_timesheet_cost(vals=values)
|
||||
super(AccountAnalyticLine, line).write(values)
|
||||
return True
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
self._update_values(values)
|
||||
values = self._get_timesheet_cost(vals=values)
|
||||
return super(AccountAnalyticLine, self).create(values)
|
||||
return super(AccountAnalyticLine, self)._get_sale_order_line(vals=result)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import models, fields
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class HrEmployee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
|
||||
# FIXME: this field should be in module hr_timesheet, not sale_timesheet
|
||||
timesheet_cost = fields.Float(string='Timesheet Cost', default=0.0)
|
||||
timesheet_cost = fields.Float('Timesheet Cost', default=0.0)
|
||||
|
||||
@@ -1,85 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class procurement_order(osv.osv):
|
||||
_name = "procurement.order"
|
||||
_inherit = "procurement.order"
|
||||
_columns = {
|
||||
'task_id': fields.many2one('project.task', 'Task', copy=False),
|
||||
}
|
||||
class ProcurementOrder(models.Model):
|
||||
_inherit = 'procurement.order'
|
||||
|
||||
def _is_procurement_task(self, cr, uid, ids, context=None):
|
||||
procurement = self.browse(cr, uid, ids[0], context=context)
|
||||
return procurement.product_id.type == 'service' and procurement.product_id.track_service=='task' or False
|
||||
task_id = fields.Many2one('project.task', 'Task', copy=False)
|
||||
|
||||
def _assign(self, cr, uid, ids, context=None):
|
||||
procurement = self.browse(cr, uid, ids[0], context=context)
|
||||
res = super(procurement_order, self)._assign(cr, uid, ids, context=context)
|
||||
def _is_procurement_task(self):
|
||||
return self.product_id.type == 'service' and self.product_id.track_service == 'task'
|
||||
|
||||
@api.multi
|
||||
def _assign(self):
|
||||
self.ensure_one()
|
||||
res = super(ProcurementOrder, self)._assign()
|
||||
if not res:
|
||||
#if there isn't any specific procurement.rule defined for the product, we may want to create a task
|
||||
return procurement._is_procurement_task()
|
||||
# if there isn't any specific procurement.rule defined for the product, we may want to create a task
|
||||
return self._is_procurement_task()
|
||||
return res
|
||||
|
||||
def _run(self, cr, uid, ids, context=None):
|
||||
procurement = self.browse(cr, uid, ids[0], context=context)
|
||||
if procurement._is_procurement_task() and not procurement.task_id:
|
||||
#create a task for the procurement
|
||||
return self._create_service_task(cr, uid, procurement, context=context)
|
||||
return super(procurement_order, self)._run(cr, uid, ids, context=context)
|
||||
@api.multi
|
||||
def _run(self):
|
||||
self.ensure_one()
|
||||
if self._is_procurement_task() and not self.task_id:
|
||||
# create a task for the procurement
|
||||
return self._create_service_task()
|
||||
return super(ProcurementOrder, self)._run()
|
||||
|
||||
def _convert_qty_company_hours(self, cr, uid, procurement, context=None):
|
||||
product_uom = self.pool.get('product.uom')
|
||||
company_time_uom_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.project_time_mode_id
|
||||
if procurement.product_uom.id != company_time_uom_id.id and procurement.product_uom.category_id.id == company_time_uom_id.category_id.id:
|
||||
planned_hours = product_uom._compute_quantity(cr, uid, [procurement.product_uom.id], procurement.product_qty, company_time_uom_id)
|
||||
def _convert_qty_company_hours(self):
|
||||
company_time_uom_id = self.env.user.company_id.project_time_mode_id
|
||||
if self.product_uom.id != company_time_uom_id.id and self.product_uom.category_id.id == company_time_uom_id.category_id.id:
|
||||
planned_hours = self.product_uom._compute_quantity(self.product_qty, company_time_uom_id)
|
||||
else:
|
||||
planned_hours = procurement.product_qty
|
||||
planned_hours = self.product_qty
|
||||
return planned_hours
|
||||
|
||||
def _get_project(self, cr, uid, procurement, context=None):
|
||||
project_project = self.pool.get('project.project')
|
||||
project = procurement.product_id.project_id
|
||||
if not project and procurement.sale_line_id:
|
||||
def _get_project(self):
|
||||
Project = self.env['project.project']
|
||||
project = self.product_id.project_id
|
||||
if not project and self.sale_line_id:
|
||||
# find the project corresponding to the analytic account of the sales order
|
||||
account = procurement.sale_line_id.order_id.project_id
|
||||
account = self.sale_line_id.order_id.project_id
|
||||
if not account:
|
||||
procurement.sale_line_id.order_id._create_analytic_account()
|
||||
account = procurement.sale_line_id.order_id.project_id
|
||||
project_ids = project_project.search(cr, uid, [('analytic_account_id', '=', account.id)])
|
||||
projects = project_project.browse(cr, uid, project_ids, context=context)
|
||||
project = projects and projects[0]
|
||||
self.sale_line_id.order_id._create_analytic_account()
|
||||
account = self.sale_line_id.order_id.project_id
|
||||
project = Project.search([('analytic_account_id', '=', account.id)], limit=1)
|
||||
if not project:
|
||||
project_id = account.project_create({'name': account.name, 'use_tasks': True})
|
||||
project = project_project.browse(cr, uid, project_id, context=context)
|
||||
project = Project.browse(project_id)
|
||||
return project
|
||||
|
||||
def _create_service_task(self, cr, uid, procurement, context=None):
|
||||
project_task = self.pool.get('project.task')
|
||||
project = self._get_project(cr, uid, procurement, context=context)
|
||||
planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context)
|
||||
task_id = project_task.create(cr, uid, {
|
||||
'name': '%s:%s' % (procurement.origin or '', procurement.product_id.name),
|
||||
'date_deadline': procurement.date_planned,
|
||||
def _create_service_task(self):
|
||||
project = self._get_project()
|
||||
planned_hours = self._convert_qty_company_hours()
|
||||
task = self.env['project.task'].create({
|
||||
'name': '%s:%s' % (self.origin or '', self.product_id.name),
|
||||
'date_deadline': self.date_planned,
|
||||
'planned_hours': planned_hours,
|
||||
'remaining_hours': planned_hours,
|
||||
'partner_id': procurement.sale_line_id and procurement.sale_line_id.order_id.partner_id.id or procurement.partner_dest_id.id,
|
||||
'user_id': procurement.product_id.product_manager.id,
|
||||
'procurement_id': procurement.id,
|
||||
'description': procurement.name + '\n',
|
||||
'project_id': project and project.id or False,
|
||||
'company_id': procurement.company_id.id,
|
||||
},context=context)
|
||||
self.write(cr, uid, [procurement.id], {'task_id': task_id}, context=context)
|
||||
self.project_task_create_note(cr, uid, [procurement.id], context=context)
|
||||
return task_id
|
||||
'partner_id': self.sale_line_id.order_id.partner_id.id or self.partner_dest_id.id,
|
||||
'user_id': self.product_id.product_manager.id,
|
||||
'procurement_id': self.id,
|
||||
'description': self.name + '\n',
|
||||
'project_id': project.id,
|
||||
'company_id': self.company_id.id,
|
||||
})
|
||||
self.write({'task_id': task.id})
|
||||
|
||||
def project_task_create_note(self, cr, uid, ids, context=None):
|
||||
for procurement in self.browse(cr, uid, ids, context=context):
|
||||
body = _("Task created")
|
||||
self.message_post(cr, uid, [procurement.id], body=body, context=context)
|
||||
if procurement.sale_line_id and procurement.sale_line_id.order_id:
|
||||
procurement.sale_line_id.order_id.message_post(body=body)
|
||||
self.message_post(body=_("Task created"))
|
||||
if self.sale_line_id.order_id:
|
||||
self.sale_line_id.order_id.message_post(body=_("Task created"))
|
||||
|
||||
return task
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import api, fields, models
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
track_service = fields.Selection(selection_add=[('timesheet', 'Timesheets on project'), ('task', 'Create a task and track hours')])
|
||||
project_id = fields.Many2one('project.project', string='Project',
|
||||
help='Create a task under this project on sale order validation. This setting must be set for each company.',
|
||||
company_dependent=True)
|
||||
|
||||
@api.onchange('type', 'invoice_policy')
|
||||
def onchange_type_timesheet(self):
|
||||
track_service = fields.Selection(selection_add=[
|
||||
('timesheet', 'Timesheets on project'),
|
||||
('task', 'Create a task and track hours')])
|
||||
project_id = fields.Many2one(
|
||||
'project.project', 'Project', company_dependent=True,
|
||||
help='Create a task under this project on sale order validation. This setting must be set for each company.')
|
||||
|
||||
@api.onchange('type')
|
||||
def _onchange_type(self):
|
||||
if self.type == 'service':
|
||||
self.track_service = 'timesheet'
|
||||
else:
|
||||
self.track_service = 'manual'
|
||||
return {}
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
|
||||
@@ -1,45 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.exceptions import UserError
|
||||
from openerp.tools.translate import _
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class project_task(osv.osv):
|
||||
_name = "project.task"
|
||||
class ProjectTask(models.Model):
|
||||
_inherit = "project.task"
|
||||
_columns = {
|
||||
'procurement_id': fields.many2one('procurement.order', 'Procurement', ondelete='set null'),
|
||||
'sale_line_id': fields.related('procurement_id', 'sale_line_id', type='many2one', relation='sale.order.line', store=True, string='Sales Order Line'),
|
||||
}
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
for task in self.browse(cr, uid, ids, context=context):
|
||||
if task.sale_line_id:
|
||||
raise UserError(_('You cannot delete a task related to a Sale Order. You can only archive this task.'))
|
||||
res = super(project_task, self).unlink(cr, uid, ids, context)
|
||||
return res
|
||||
procurement_id = fields.Many2one('procurement.order', 'Procurement', ondelete='set null')
|
||||
sale_line_id = fields.Many2one('sale.order.line', 'Sales Order Line', related='procurement_id.sale_line_id', store=True)
|
||||
|
||||
def action_view_so(self, cr, uid, ids, context=None):
|
||||
task = self.browse(cr, uid, ids, context=context)[0]
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
if any(task.sale_line_id for task in self):
|
||||
raise ValidationError(_('You cannot delete a task related to a Sale Order. You can only archive this task.'))
|
||||
return super(ProjectTask, self).unlink()
|
||||
|
||||
@api.multi
|
||||
def action_view_so(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "sale.order",
|
||||
"views": [[False, "form"]],
|
||||
"res_id": task.sale_line_id.order_id.id,
|
||||
"res_id": self.sale_line_id.order_id.id,
|
||||
"context": {"create": False, "show_sale": True},
|
||||
}
|
||||
|
||||
def onchange_parent_id(self, cr, uid, ids, parent_id, context=None):
|
||||
if not parent_id:
|
||||
return {'value' : {'procurement_id': False, 'sale_line_id': False }}
|
||||
parent_task = self.browse(cr, uid, parent_id, context=context)
|
||||
return {
|
||||
'value' : {
|
||||
'procurement_id' : parent_task.procurement_id.id,
|
||||
'sale_line_id' : parent_task.sale_line_id.id,
|
||||
}
|
||||
}
|
||||
@api.onchange('parent_id')
|
||||
def onchange_parent_id(self):
|
||||
self.procurement_id = self.parent_id.procurement_id.id
|
||||
self.sale_line_id = self.parent_id.sale_line_id.id
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import models, api, fields
|
||||
from odoo import models, api, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
@api.model
|
||||
def _get_uom_hours(self):
|
||||
try:
|
||||
return self.env.ref("product.product_uom_hour")
|
||||
except ValueError:
|
||||
return False
|
||||
project_time_mode_id = fields.Many2one('product.uom', string='Timesheet UoM', default=_get_uom_hours)
|
||||
def _get_default_uom_id(self):
|
||||
return self.env.ref("product.product_uom_hour", raise_if_not_found=False)
|
||||
|
||||
project_time_mode_id = fields.Many2one('product.uom', 'Timesheet UoM', default=_get_default_uom_id)
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from openerp import models, api, fields
|
||||
from openerp.tools.translate import _
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
from openerp.exceptions import ValidationError
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
@@ -31,6 +30,19 @@ class SaleOrder(models.Model):
|
||||
order.timesheet_ids = []
|
||||
order.timesheet_count = len(order.timesheet_ids)
|
||||
|
||||
@api.multi
|
||||
@api.depends('order_line.product_id.project_id')
|
||||
def _compute_tasks_ids(self):
|
||||
for order in self:
|
||||
order.tasks_ids = self.env['project.task'].search([('sale_line_id', 'in', order.order_line.ids)])
|
||||
order.tasks_count = len(order.tasks_ids)
|
||||
|
||||
@api.multi
|
||||
@api.depends('project_id.project_ids')
|
||||
def _compute_project_project_id(self):
|
||||
for order in self:
|
||||
order.project_project_id = self.env['project.project'].search([('analytic_account_id', '=', order.project_id.id)])
|
||||
|
||||
@api.multi
|
||||
@api.constrains('order_line')
|
||||
def _check_multi_timesheet(self):
|
||||
@@ -44,19 +56,24 @@ class SaleOrder(models.Model):
|
||||
return {}
|
||||
|
||||
@api.multi
|
||||
@api.depends('order_line.product_id.project_id')
|
||||
def _compute_tasks_ids(self):
|
||||
def action_confirm(self):
|
||||
result = super(SaleOrder, self).action_confirm()
|
||||
for order in self:
|
||||
order.tasks_ids = self.env['project.task'].search([('sale_line_id', 'in', order.order_line.ids)])
|
||||
order.tasks_count = len(order.tasks_ids)
|
||||
if not order.project_project_id:
|
||||
for line in order.order_line:
|
||||
if line.product_id.track_service == 'timesheet':
|
||||
if not order.project_id:
|
||||
order._create_analytic_account(prefix=line.product_id.default_code or None)
|
||||
order.project_id.project_create({'name': order.project_id.name, 'use_tasks': True})
|
||||
break
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_task(self):
|
||||
self.ensure_one()
|
||||
imd = self.env['ir.model.data']
|
||||
action = imd.xmlid_to_object('project.action_view_task')
|
||||
list_view_id = imd.xmlid_to_res_id('project.view_task_tree2')
|
||||
form_view_id = imd.xmlid_to_res_id('project.view_task_form2')
|
||||
action = self.env.ref('project.action_view_task')
|
||||
list_view_id = self.env.ref('project.view_task_tree2').id
|
||||
form_view_id = self.env.ref('project.view_task_form2').id
|
||||
|
||||
result = {
|
||||
'name': action.name,
|
||||
@@ -76,18 +93,11 @@ class SaleOrder(models.Model):
|
||||
result = {'type': 'ir.actions.act_window_close'}
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
@api.depends('project_id.project_ids')
|
||||
def _compute_project_project_id(self):
|
||||
for order in self:
|
||||
order.project_project_id = self.env['project.project'].search([('analytic_account_id', '=', order.project_id.id)])
|
||||
|
||||
@api.multi
|
||||
def action_view_project_project(self):
|
||||
self.ensure_one()
|
||||
imd = self.env['ir.model.data']
|
||||
action = imd.xmlid_to_object('project.open_view_project_all')
|
||||
form_view_id = imd.xmlid_to_res_id('project.edit_project')
|
||||
action = self.env.ref('project.open_view_project_all')
|
||||
form_view_id = self.env.ref('project.edit_project').id
|
||||
|
||||
result = {
|
||||
'name': action.name,
|
||||
@@ -101,26 +111,12 @@ class SaleOrder(models.Model):
|
||||
}
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
result = super(SaleOrder, self).action_confirm()
|
||||
for order in self:
|
||||
if not order.project_project_id:
|
||||
for line in order.order_line:
|
||||
if line.product_id.track_service == 'timesheet':
|
||||
if not order.project_id:
|
||||
order._create_analytic_account(prefix=line.product_id.default_code or None)
|
||||
order.project_id.project_create({'name': order.project_id.name, 'use_tasks': True})
|
||||
break
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def action_view_timesheet(self):
|
||||
self.ensure_one()
|
||||
imd = self.env['ir.model.data']
|
||||
action = imd.xmlid_to_object('hr_timesheet.act_hr_timesheet_line')
|
||||
list_view_id = imd.xmlid_to_res_id('hr_timesheet.hr_timesheet_line_tree')
|
||||
form_view_id = imd.xmlid_to_res_id('hr_timesheet.hr_timesheet_line_form')
|
||||
action = self.env.ref('hr_timesheet.act_hr_timesheet_line')
|
||||
list_view_id = self.env.ref('hr_timesheet.hr_timesheet_line_tree').id
|
||||
form_view_id = self.env.ref('hr_timesheet.hr_timesheet_line_form').id
|
||||
|
||||
result = {
|
||||
'name': action.name,
|
||||
@@ -141,16 +137,16 @@ class SaleOrder(models.Model):
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
@api.multi
|
||||
def _compute_analytic(self, domain=None):
|
||||
if not domain:
|
||||
# To filter on analyic lines linked to an expense
|
||||
domain = [('so_line', 'in', self.ids), '|', ('amount', '<=', 0.0), ('project_id', '!=', False)]
|
||||
return super(SaleOrderLine, self)._compute_analytic(domain=domain)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
line = super(SaleOrderLine, self).create(values)
|
||||
if line.state == 'sale' and not line.order_id.project_id and line.product_id.track_service in ['timesheet', 'task']:
|
||||
line.order_id._create_analytic_account()
|
||||
return line
|
||||
|
||||
@api.multi
|
||||
def _compute_analytic(self, domain=None):
|
||||
if not domain:
|
||||
# To filter on analyic lines linked to an expense
|
||||
domain = [('so_line', 'in', self.ids), '|', ('amount', '<=', 0.0), ('project_id', '!=', False)]
|
||||
return super(SaleOrderLine, self)._compute_analytic(domain=domain)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from openerp.addons.sale.tests.test_sale_common import TestSale
|
||||
from odoo.addons.sale.tests.test_sale_common import TestSale
|
||||
|
||||
|
||||
class TestSaleService(TestSale):
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from openerp.tools import float_is_zero
|
||||
from odoo.tools import float_is_zero
|
||||
|
||||
from openerp.addons.sale.tests.test_sale_common import TestSale
|
||||
from odoo.addons.sale.tests.test_sale_common import TestSale
|
||||
|
||||
|
||||
class TestSaleTimesheet(TestSale):
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="hr_timesheet_employee_extd_form" model="ir.ui.view">
|
||||
<field name="name">hr.timesheet.employee.extd_form</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='active_group']" position="before">
|
||||
<group string="Timesheets">
|
||||
<field name="timesheet_cost"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
<odoo>
|
||||
<record id="hr_timesheet_employee_extd_form" model="ir.ui.view">
|
||||
<field name="name">hr.timesheet.employee.extd_form</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='active_group']" position="before">
|
||||
<group string="Timesheets">
|
||||
<field name="timesheet_cost"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_procurement_task_form" model="ir.ui.view">
|
||||
<field name="name">procurement.procurement.form.view.inherit</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id" ref="procurement.procurement_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="origin" position="after">
|
||||
<field name="task_id"/>
|
||||
</field>
|
||||
<odoo>
|
||||
<record id="view_procurement_task_form" model="ir.ui.view">
|
||||
<field name="name">procurement.procurement.form.view.inherit</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id" ref="procurement.procurement_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="origin" position="after">
|
||||
<field name="task_id"/>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,19 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<record id="view_product_timesheet_form" model="ir.ui.view">
|
||||
<field name="name">product.template.timesheet.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="sale.product_template_form_view_invoice_policy"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='track_service']" position="attributes">
|
||||
<attribute name="invisible">False</attribute>
|
||||
<attribute name="attrs">{'invisible': [('type','!=','service')]}</attribute>
|
||||
</xpath>
|
||||
<field name="track_service" position="after">
|
||||
<field name="project_id" attrs="{'invisible':['|', ('type','!=','service'), ('track_service', '<>', 'task')]}"/>
|
||||
</field>
|
||||
<odoo>
|
||||
<record id="view_product_timesheet_form" model="ir.ui.view">
|
||||
<field name="name">product.template.timesheet.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="sale.product_template_form_view_invoice_policy"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='track_service']" position="attributes">
|
||||
<attribute name="invisible">False</attribute>
|
||||
<attribute name="attrs">{'invisible': [('type','!=','service')]}</attribute>
|
||||
</xpath>
|
||||
<field name="track_service" position="after">
|
||||
<field name="project_id" attrs="{'invisible':['|', ('type','!=','service'), ('track_service', '<>', 'task')]}"/>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
<record id="view_sale_service_inherit_form2" model="ir.ui.view">
|
||||
<field name="name">sale.service.form.view.inherit</field>
|
||||
<field name="model">project.task</field>
|
||||
@@ -17,10 +16,6 @@
|
||||
<field name="procurement_id" groups="base.group_no_one"/>
|
||||
<field name="sale_line_id" string="Order Line" groups="base.group_no_one"/>
|
||||
</field>
|
||||
<field name="parent_id" position="attributes">
|
||||
<attribute name="on_change">onchange_parent_id(parent_id)</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<odoo>
|
||||
<record id="view_order_form_inherit_sale_timesheet" model="ir.ui.view">
|
||||
<field name="name">sale.order.form.sale.timesheet</field>
|
||||
<field name="model">sale.order</field>
|
||||
@@ -39,5 +38,4 @@
|
||||
</data>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user