diff --git a/addons/hr_timesheet/__manifest__.py b/addons/hr_timesheet/__manifest__.py
index efedc7384f0..177797d13a0 100644
--- a/addons/hr_timesheet/__manifest__.py
+++ b/addons/hr_timesheet/__manifest__.py
@@ -31,6 +31,7 @@ up a management by affair.
'report/report_timesheet_templates.xml',
'hr_timesheet_installer.xml',
'hr_dashboard.xml',
+ 'views/hr_views.xml',
],
'demo': [
'demo/hr_timesheet_demo.xml',
diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py
index c8b7241e5c5..3c3cdecff9e 100644
--- a/addons/hr_timesheet/hr_timesheet.py
+++ b/addons/hr_timesheet/hr_timesheet.py
@@ -7,24 +7,38 @@ from odoo import api, fields, models
class AccountAnalyticLine(models.Model):
_inherit = 'account.analytic.line'
+ def _default_employee_id(self):
+ return self.env.user.employee_ids[0]
+
task_id = fields.Many2one('project.task', 'Task')
project_id = fields.Many2one('project.project', 'Project', domain=[('allow_timesheets', '=', True)])
- department_id = fields.Many2one('hr.department', "Department", related='user_id.employee_ids.department_id', store=True, readonly=True)
+
+ employee_id = fields.Many2one('hr.employee', "Employee", default=_default_employee_id)
+ department_id = fields.Many2one('hr.department', "Department", related='employee_id.department_id', store=True, readonly=True)
@api.onchange('project_id')
def onchange_project_id(self):
self.task_id = False
+ @api.onchange('employee_id')
+ def _onchange_employee_id(self):
+ self.user_id = self.employee_id.user_id
+
@api.model
def create(self, vals):
- if vals.get('project_id'):
- project = self.env['project.project'].browse(vals.get('project_id'))
- vals['account_id'] = project.analytic_account_id.id
+ vals = self._update_timesheet_values(vals)
return super(AccountAnalyticLine, self).create(vals)
@api.multi
def write(self, vals):
+ vals = self._update_timesheet_values(vals)
+ return super(AccountAnalyticLine, self).write(vals)
+
+ def _update_timesheet_values(self, vals):
if vals.get('project_id'):
project = self.env['project.project'].browse(vals.get('project_id'))
vals['account_id'] = project.analytic_account_id.id
- return super(AccountAnalyticLine, self).write(vals)
+ if vals.get('employee_id'):
+ employee = self.env['hr.employee'].browse(vals['employee_id'])
+ vals['user_id'] = employee.user_id.id
+ return vals
diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml
index 95f3d8617d0..d2bac3c2ac0 100644
--- a/addons/hr_timesheet/hr_timesheet_view.xml
+++ b/addons/hr_timesheet/hr_timesheet_view.xml
@@ -37,7 +37,8 @@
10
-
+
+
@@ -47,7 +48,7 @@
account.analytic.line
-
+
@@ -89,7 +90,8 @@
10
-
+
+
@@ -98,7 +100,7 @@
account.analytic.line.calendar
account.analytic.line
-
+
@@ -111,7 +113,7 @@
-
+
@@ -130,7 +132,7 @@
('date', '<=', (context_today() + relativedelta(months=1, day=1, days=-1)).strftime('%Y-%m-%d')),
]"/>
-
+
@@ -191,7 +193,7 @@
account.analytic.line
[('project_id', '!=', False)]
- {'search_default_week':1, 'search_default_groupby_user':1}
+ {'search_default_week':1, 'search_default_groupby_employee':1}
diff --git a/addons/hr_timesheet/project_timesheet_view.xml b/addons/hr_timesheet/project_timesheet_view.xml
index b7f1b87bab4..f799cc5b76e 100644
--- a/addons/hr_timesheet/project_timesheet_view.xml
+++ b/addons/hr_timesheet/project_timesheet_view.xml
@@ -102,7 +102,8 @@
-
+
+
diff --git a/addons/hr_timesheet/views/hr_views.xml b/addons/hr_timesheet/views/hr_views.xml
new file mode 100644
index 00000000000..6d500f22fa4
--- /dev/null
+++ b/addons/hr_timesheet/views/hr_views.xml
@@ -0,0 +1,36 @@
+
+
+
+
+ Timesheets
+ account.analytic.line
+
+ [('project_id', '!=', False)]
+ {
+ 'search_default_month':1,
+ 'search_default_employee_id': [active_id],
+ 'default_employee_id': active_id
+ }
+
+
+
+ hr.employee.form.timesheet
+ hr.employee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/sale_timesheet/models/account.py b/addons/sale_timesheet/models/account.py
index 812b9b09b1b..7f319ead699 100644
--- a/addons/sale_timesheet/models/account.py
+++ b/addons/sale_timesheet/models/account.py
@@ -37,16 +37,28 @@ class AccountAnalyticLine(models.Model):
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)
+
+ # find the employee
+ employee_id = values.get('employee_id') or self.employee_id.id or self._default_employee_id().id
+ employee = self.env['hr.employee'].browse(employee_id) if employee_id else self.env['hr.employee']
+ if not employee:
+ user_id = values.get('user_id') or self.user_id.id or self._default_user()
+ employee = self.env['hr.employee'].search([('user_id', '=', user_id)], limit=1)
+
+ # find the analytic account
+ account_id = values.get('account_id') or self.account_id.id
+ analytic_account = self.env['account.analytic.account'].browse(account_id) if account_id else self.env['account.analytic.account']
+
+ # convert employee cost into timesheet (analytic account) currency
+ uom = employee.company_id.project_time_mode_id
+ cost = employee.timesheet_cost or 0.0
+ amount = -unit_amount * cost
+ amount_converted = employee.currency_id.compute(amount, analytic_account.currency_id)
+
return {
- 'amount': -unit_amount * cost,
+ 'amount': amount_converted,
'product_uom_id': uom.id,
- 'account_id': values.get('account_id') or self.account_id.id or emp.account_id.id,
+ 'account_id': account_id,
}
return {}
diff --git a/addons/sale_timesheet/models/hr.py b/addons/sale_timesheet/models/hr.py
index 5964b77ab04..a9f94f57bb9 100644
--- a/addons/sale_timesheet/models/hr.py
+++ b/addons/sale_timesheet/models/hr.py
@@ -8,5 +8,5 @@ class HrEmployee(models.Model):
_inherit = 'hr.employee'
# FIXME: this field should be in module hr_timesheet, not sale_timesheet
- timesheet_cost = fields.Float('Timesheet Cost', default=0.0)
- account_id = fields.Many2one('account.account', string='Account')
+ timesheet_cost = fields.Monetary('Timesheet Cost', currency_field='currency_id', default=0.0)
+ currency_id = fields.Many2one('res.currency', related='company_id.currency_id', readonly=True)
diff --git a/addons/sale_timesheet/tests/test_sale_timesheet.py b/addons/sale_timesheet/tests/test_sale_timesheet.py
index 309650aee2f..d75991411cb 100644
--- a/addons/sale_timesheet/tests/test_sale_timesheet.py
+++ b/addons/sale_timesheet/tests/test_sale_timesheet.py
@@ -6,6 +6,19 @@ from odoo.addons.sale.tests.test_sale_common import TestSale
class TestSaleTimesheet(TestSale):
+
+ def setUp(self):
+ super(TestSaleTimesheet, self).setUp()
+ # link hr employee to res.users of sale tests
+ self.employee_user = self.env['hr.employee'].create({
+ 'name': 'Employee User',
+ 'user_id': self.user.id,
+ })
+ self.employee_manager = self.env['hr.employee'].create({
+ 'name': 'Employee Manager',
+ 'user_id': self.manager.id,
+ })
+
def test_timesheet_order(self):
""" Test timesheet invoicing with 'invoice on order' timetracked products """
# intial so
@@ -26,7 +39,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 10.5,
- 'user_id': self.manager.id,
+ 'employee_id': self.employee_user.id,
})
self.assertEqual(so.order_line.qty_delivered, 10.5, 'Sale Timesheet: timesheet does not increase delivered quantity on so line')
self.assertEqual(so.invoice_status, 'invoiced', 'Sale Timesheet: "invoice on order" timesheets should not modify the invoice_status of the so')
@@ -35,7 +48,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 39.5,
- 'user_id': self.user.id,
+ 'employee_id': self.employee_user.id,
})
self.assertEqual(so.order_line.qty_delivered, 50, 'Sale Timesheet: timesheet does not increase delivered quantity on so line')
self.assertEqual(so.invoice_status, 'invoiced', 'Sale Timesheet: "invoice on order" timesheets should not modify the invoice_status of the so')
@@ -44,7 +57,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 10,
- 'user_id': self.user.id,
+ 'employee_id': self.employee_user.id,
})
self.assertEqual(so.order_line.qty_delivered, 60, 'Sale Timesheet: timesheet does not increase delivered quantity on so line')
self.assertEqual(so.invoice_status, 'upselling', 'Sale Timesheet: "invoice on order" timesheets should not modify the invoice_status of the so')
@@ -69,7 +82,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 10.5,
- 'user_id': self.manager.id,
+ 'employee_id': self.employee_manager.id,
})
self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: "invoice on delivery" timesheets should set the so in "to invoice" status when logged')
inv_id = so.action_invoice_create()
@@ -80,7 +93,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 39.5,
- 'user_id': self.user.id,
+ 'employee_id': self.employee_user.id,
})
self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: "invoice on delivery" timesheets should not modify the invoice_status of the so')
so.action_invoice_create()
@@ -90,7 +103,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 10,
- 'user_id': self.user.id,
+ 'employee_id': self.employee_user.id,
})
self.assertEqual(so.invoice_status, 'to invoice', 'Sale Timesheet: supplementary timesheets do not change the status of the SO')
@@ -113,7 +126,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 16,
- 'user_id': self.manager.id,
+ 'employee_id': self.employee_manager.id,
})
self.assertEqual(so.order_line.qty_delivered, 2, 'Sale: uom conversion of timesheets is wrong')
@@ -121,7 +134,7 @@ class TestSaleTimesheet(TestSale):
'name': 'Test Line',
'project_id': so.project_project_id.id,
'unit_amount': 24,
- 'user_id': self.user.id,
+ 'employee_id': self.employee_user.id,
})
so.action_invoice_create()
self.assertEqual(so.invoice_status, 'invoiced', 'Sale Timesheet: "invoice on delivery" timesheets should not modify the invoice_status of the so')
diff --git a/addons/sale_timesheet/views/hr_views.xml b/addons/sale_timesheet/views/hr_views.xml
index 7b17e2dc67e..ce032cc01e0 100644
--- a/addons/sale_timesheet/views/hr_views.xml
+++ b/addons/sale_timesheet/views/hr_views.xml
@@ -3,13 +3,17 @@
hr.timesheet.employee.extd_form
hr.employee
-
+
-
-
-
-
-
+
+
+
+ per hour
+
+
+
+
+ 0