-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BR1230][T25029][ADD]project_timesheet_detail #212
base: 10.0
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
======================== | ||
Project TimeSheet Detail | ||
======================== | ||
|
||
This module extends the function of project timesheet,allows the manager to | ||
review, approve or reject the timesheet by every single record. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. by every single record -> one by one |
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add the runbot |
||
Installation | ||
============ | ||
|
||
To install this module, you need to: | ||
|
||
#. have basic module installed (project_issue_sheet) | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/Elico-Corp/elico_odoo/issues>`_. In case of trouble, please | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update the url |
||
check there if your issue has already been reported. If you spotted it first, | ||
help us smash it by providing detailed and welcomed feedback. | ||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
Miya Xing <[email protected]> | ||
Joseph Wang <[email protected]> | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: https://www.elico-corp.com/logo.png | ||
:alt: Elico Corp | ||
:target: https://www.elico-corp.com | ||
|
||
This module is maintained by Elico Corporation. | ||
|
||
Elico Corp is an innovative actor in China, Hong-Kong and Singapore servicing | ||
well known international companies and as well as local mid-sized businesses. | ||
Since 2010, our seasoned Sino-European consultants have been providing full | ||
range Odoo services: | ||
|
||
* Business consultancy for Gap analysis, BPM, operational work-flows review. | ||
* Ready-to-use ERP packages aimed at starting businesses. | ||
* Odoo implementation for manufacturing, international trading, service industry | ||
and e-commerce. | ||
* Connectors and integration with 3rd party software (Magento, Taobao, Coswin, | ||
Joomla, Prestashop, Tradevine etc...). | ||
* Odoo Support services such as developments, training, maintenance and hosting. | ||
|
||
Our headquarters are located in Shanghai with branch in Singapore servicing | ||
customers from all over Asia Pacific. | ||
|
||
Contact information: `Sales <[email protected]>`__ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import models |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
{ | ||
'name': "project_timesheet_detailed", | ||
'summary': """This module extends the function of project timesheet, | ||
allows the manager to review, approve or reject the timesheet by every | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. update |
||
single record.""", | ||
'author': "Elico Corp", | ||
"support": "[email protected]", | ||
"license": "AGPL-3", | ||
'website': "https://www.elico-corp.com", | ||
'category': 'Project Management', | ||
'version': '10.0.0.1.0', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 10.0.1.0.0 |
||
'depends': ['project_issue_sheet'], | ||
'data': [ | ||
'security/project_timesheet_detail.xml', | ||
'security/ir.model.access.csv', | ||
'views/project_inherit_view.xml', | ||
'views/project_timesheet_detail_view.xml', | ||
'views/function_views.xml', | ||
], | ||
'installable': True, | ||
'application': False, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import models | ||
from . import project_inherit |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
|
||
from odoo import models, fields, api | ||
from odoo.exceptions import UserError | ||
|
||
|
||
class AccountAnalyticLine(models.Model): | ||
|
||
_inherit = 'account.analytic.line' | ||
|
||
stage = fields.Selection( | ||
selection=[ | ||
('fixed', 'Fixed'), | ||
('to review', 'To review'), | ||
('approved', 'Approved'), | ||
('rejected', 'Rejected'), | ||
], | ||
default='to review', | ||
|
||
) | ||
estimated_time = fields.Float( | ||
'Estimated time', compute='_compute_estimated_time') | ||
approved_time = fields.Float( | ||
'Approved time', compute='_compute_approved_time') | ||
|
||
@api.multi | ||
@api.depends('task_id') | ||
def _compute_estimated_time(self): | ||
for rec in self: | ||
if rec.task_id: | ||
rec.estimated_time = rec.task_id.planned_hours | ||
|
||
@api.multi | ||
@api.depends('task_id') | ||
def _compute_approved_time(self): | ||
for rec in self: | ||
if rec.task_id: | ||
approved_tms = rec.env['account.analytic.line'].search( | ||
[('task_id', '=', rec.task_id.id)]).filtered( | ||
lambda rec: rec.stage == 'approved') | ||
rec.approved_time = \ | ||
sum([tms.unit_amount for tms in approved_tms]) | ||
|
||
@api.multi | ||
def set_approved(self): | ||
current_user = self.env.user | ||
for rec in self: | ||
if (current_user == rec.project_id.user_id) or ( | ||
current_user == | ||
rec.user_id.employee_ids.parent_id.user_id): | ||
rec.stage = 'approved' | ||
else: | ||
raise UserError( | ||
'Sorry,you do not have permission to approve it') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove 'Sorry,' (everywhere) |
||
|
||
@api.multi | ||
def set_rejected(self): | ||
current_user = self.env.user | ||
for rec in self: | ||
if (current_user == rec.project_id.user_id) or ( | ||
current_user == | ||
rec.user_id.employee_ids.parent_id.user_id): | ||
rec.stage = 'rejected' | ||
mail = self.env['mail.mail'].create({ | ||
'body_html': 'Your TMS %s was turn down' % (rec.name), | ||
'email_to': rec.user_id.login, | ||
'subject': 'Reject TMS', | ||
}) | ||
mail.send() | ||
else: | ||
raise UserError( | ||
'Sorry,you do not have permission to reject it') | ||
|
||
@api.multi | ||
def set_review(self): | ||
current_user = self.env.user | ||
for rec in self: | ||
if (current_user == rec.project_id.user_id) or ( | ||
current_user == | ||
rec.user_id.employee_ids.parent_id.user_id): | ||
rec.stage = 'to review' | ||
else: | ||
raise UserError( | ||
'Sorry,you do not have permission to change the state') | ||
|
||
@api.onchange('project_id') | ||
def onchange_project_id(self): | ||
eml = self.task_id | ||
res = super(AccountAnalyticLine, self).onchange_project_id() | ||
self.task_id = eml | ||
return res | ||
|
||
@api.onchange('task_id') | ||
def task_id_on_change(self): | ||
if self.task_id: | ||
self.project_id = self.task_id.project_id.id | ||
|
||
@api.onchange('issue_id') | ||
def issue_id_on_change(self): | ||
if self.issue_id: | ||
self.project_id = self.issue_id.project_id.id | ||
|
||
@api.multi | ||
def write(self, vals): | ||
for rec in self: | ||
if rec.stage == 'rejected' and vals: | ||
vals['stage'] = 'fixed' | ||
if vals.get('task_id'): | ||
vals.update({ | ||
'project_id': | ||
self.env['project.task'].search([ | ||
('id', '=', vals.get('task_id'))]).project_id.id}) | ||
if vals.get('issue_id'): | ||
vals.update( | ||
{'project_id': self.env['project.issue'].search( | ||
[('id', '=', vals.get('issue_id'))]).project_id.id}) | ||
return super(AccountAnalyticLine, self).write(vals) | ||
|
||
@api.multi | ||
def unlink(self): | ||
for rec in self: | ||
if rec.stage != 'to review': | ||
raise UserError('Only records in to review can be deleted!') | ||
return super(AccountAnalyticLine, self).unlink() | ||
|
||
@api.multi | ||
@api.constrains('task_id', 'issue_id') | ||
def _check_task_and_issue(self): | ||
if self.task_id and self.issue_id: | ||
raise ValueError( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would that happen? |
||
'It is not allowed to have task and issue at the same time.') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
from odoo import models, fields | ||
|
||
|
||
class ProjectInherit(models.Model): | ||
_inherit = 'project.project' | ||
|
||
check_timesheet = fields.Boolean( | ||
string="Check TMS", | ||
default=True, | ||
help='If true, the TMS will be assigned to the manager of the' | ||
' employee,if false, the TMS will be assigned to the manager ' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. always ',' then a space |
||
'of the project.') |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" | ||
access_check_timesheet_manager,check_timesheet_manager,model_account_analytic_line,group_timesheet_manager,1,1,1,1 | ||
access_timesheet_project_manager,timesheet_project_manager,model_account_analytic_line,group_timesheet_project_manager,1,1,1,1 | ||
access_group_timesheet_employee,group_timesheet_employee,model_account_analytic_line,base.group_user,1,1,1,0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<odoo> | ||
<record id="group_timesheet_manager" model="res.groups"> | ||
<field name="name">Timesheet Manager</field> | ||
<field name="users" eval="[(4, ref('base.user_root'))]"/> | ||
</record> | ||
<record id="group_timesheet_project_manager" model="res.groups"> | ||
<field name="name">Timesheet Project Manager</field> | ||
</record> | ||
</odoo> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# -*- coding:utf-8 -*- | ||
|
||
from . import test_models |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# -*- coding:utf-8 -*- | ||
# © 2017 Elico Corp (www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
from odoo.tests import common | ||
from odoo.exceptions import UserError | ||
|
||
|
||
class TestTimesheetDetail(common.TransactionCase): | ||
|
||
def setUp(self): | ||
super(TestTimesheetDetail, self).setUp() | ||
self.account = self.env.ref('analytic.analytic_millennium_industries') | ||
self.task_1 = self.env.ref('project.project_task_1') | ||
self.task_2 = self.env.ref('project.project_task_20') | ||
self.issue_1 = self.env.ref( | ||
'project_issue.crm_case_buginaccountsmodule0') | ||
self.issue_2 = self.env.ref( | ||
'project_issue.crm_case_programnotgivingproperoutput0') | ||
self.timesheet_1 = self.env['account.analytic.line'].create({ | ||
'name': 'test timesheet', | ||
'task_id': self.task_1.id, | ||
'date': '2018-1-10', | ||
'unit_amount': 2, | ||
'stage': 'to review', | ||
'account_id': self.account.id | ||
}) | ||
self.timesheet_2 = self.env['account.analytic.line'].create({ | ||
'name': 'test test timesheet', | ||
'task_id': self.task_2.id, | ||
'date': '2018-1-10', | ||
'unit_amount': 2, | ||
'stage': 'to review', | ||
'account_id': self.account.id | ||
}) | ||
self.timesheet_3 = self.env['account.analytic.line'].create({ | ||
'name': 'test timesheet', | ||
'issue_id': self.issue_1.id, | ||
'date': '2018-1-10', | ||
'unit_amount': 2, | ||
'stage': 'approved', | ||
'account_id': self.account.id | ||
}) | ||
try: | ||
self.env['account.analytic.line'].create({ | ||
'name': 'test timesheet', | ||
'issue_id': self.issue_1.id, | ||
'task_id': self.task_1.id, | ||
'date': '2018-1-10', | ||
'unit_amount': 2, | ||
'stage': 'to review', | ||
'account_id': self.account.id | ||
}) | ||
except ValueError: | ||
pass | ||
|
||
def test_set_approved(self): | ||
try: | ||
self.timesheet_1.set_approved() | ||
self.timesheet_2.set_approved() | ||
except UserError as e: | ||
self.assertEquals(e.name, | ||
'Sorry,you do not have permission to approve it') | ||
|
||
def test_set_rejected(self): | ||
try: | ||
self.timesheet_1.set_rejected() | ||
self.timesheet_2.set_rejected() | ||
except UserError as e: | ||
self.assertEquals(e.name, | ||
'Sorry,you do not have permission to reject it') | ||
|
||
def test_set_review(self): | ||
try: | ||
self.timesheet_1.set_review() | ||
self.timesheet_2.set_review() | ||
except UserError as e: | ||
self.assertEquals( | ||
e.name, 'Sorry,you do not have permission to change the state') | ||
|
||
def test_onchange_project_id(self): | ||
self.timesheet_1.task_id = self.task_2.id | ||
self.assertEquals(self.timesheet_1.project_id, self.task_2.project_id) | ||
|
||
def test_issue_id_on_change(self): | ||
self.timesheet_3.issue_id = self.issue_2.id | ||
self.assertEquals(self.timesheet_3.project_id, self.issue_2.project_id) | ||
|
||
def test_write(self): | ||
vals_1 = {'task_id': self.task_2.id} | ||
self.timesheet_1.write(vals_1) | ||
self.assertEquals(self.timesheet_1.project_id, self.task_2.project_id) | ||
|
||
def test_unlink(self): | ||
try: | ||
self.timesheet_3.unlink() | ||
except UserError as e: | ||
self.assertEquals(e.name, | ||
'Only records in to review can be deleted!') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
space after the ','