From 4b0baa3615aee3e528ccef0b60142ba7acb7976f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 10 Jul 2013 14:25:26 +0200 Subject: [PATCH] [CLEAN] project, project_issue, project_mrp: misc cleaning of code + fixed bug in project_mrp + re-added commentred tests in project_mrp bzr revid: tde@openerp.com-20130710122526-tf87avul7huqgigg --- .../tests/test_access_rights.py | 146 +++++++----------- addons/project/doc/changelog.rst | 2 +- addons/project/project.py | 54 ++----- addons/project/project_demo.xml | 10 -- addons/project/project_view.xml | 10 +- addons/project/report/project_report_view.xml | 27 ++-- addons/project/tests/test_project_base.py | 7 + addons/project/tests/test_project_flow.py | 1 + addons/project_issue/project_issue.py | 37 +++-- addons/project_issue/project_issue_data.xml | 3 +- addons/project_issue/project_issue_view.xml | 6 +- .../report/project_issue_report.py | 7 +- addons/project_mrp/project_mrp.py | 3 +- addons/project_mrp/project_mrp_demo.xml | 4 +- addons/project_mrp/project_procurement.py | 2 +- .../test/project_task_procurement.yml | 72 ++++----- 16 files changed, 155 insertions(+), 236 deletions(-) diff --git a/addons/portal_project/tests/test_access_rights.py b/addons/portal_project/tests/test_access_rights.py index a7d56cb3895..bbf029a72d7 100644 --- a/addons/portal_project/tests/test_access_rights.py +++ b/addons/portal_project/tests/test_access_rights.py @@ -19,35 +19,17 @@ # ############################################################################## +from openerp.addons.project.tests.test_project_base import TestProjectBase from openerp.osv.orm import except_orm -from openerp.tests import common from openerp.tools import mute_logger -class TestPortalProject(common.TransactionCase): +class TestPortalProject(TestProjectBase): def setUp(self): super(TestPortalProject, self).setUp() cr, uid = self.cr, self.uid - # Useful models - self.project_project = self.registry('project.project') - self.project_task = self.registry('project.task') - self.res_users = self.registry('res.users') - self.res_partner = self.registry('res.partner') - - # Find Employee group - group_employee_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user') - self.group_employee_id = group_employee_ref and group_employee_ref[1] or False - - # Find Project User group - group_project_user_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'project', 'group_project_user') - self.group_project_user_id = group_project_user_ref and group_project_user_ref[1] or False - - # Find Project Manager group - group_project_manager_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'project', 'group_project_manager') - self.group_project_manager_id = group_project_manager_ref and group_project_manager_ref[1] or False - # Find Portal group group_portal_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_portal') self.group_portal_id = group_portal_ref and group_portal_ref[1] or False @@ -56,37 +38,19 @@ class TestPortalProject(common.TransactionCase): group_anonymous_ref = self.registry('ir.model.data').get_object_reference(cr, uid, 'portal', 'group_anonymous') self.group_anonymous_id = group_anonymous_ref and group_anonymous_ref[1] or False - # Test users to use through the various tests - self.user_alfred_id = self.res_users.create(cr, uid, { - 'name': 'Alfred EmployeeUser', - 'login': 'alfred', - 'alias_name': 'alfred', - 'groups_id': [(6, 0, [self.group_employee_id, self.group_project_user_id])] - }) - self.user_bert_id = self.res_users.create(cr, uid, { - 'name': 'Bert Nobody', - 'login': 'bert', - 'alias_name': 'bert', - 'groups_id': [(6, 0, [])] - }) - self.user_chell_id = self.res_users.create(cr, uid, { + # # Test users to use through the various tests + self.user_portal_id = self.res_users.create(cr, uid, { 'name': 'Chell Portal', 'login': 'chell', 'alias_name': 'chell', 'groups_id': [(6, 0, [self.group_portal_id])] }) - self.user_donovan_id = self.res_users.create(cr, uid, { + self.user_anonymous_id = self.res_users.create(cr, uid, { 'name': 'Donovan Anonymous', 'login': 'donovan', 'alias_name': 'donovan', 'groups_id': [(6, 0, [self.group_anonymous_id])] }) - self.user_ernest_id = self.res_users.create(cr, uid, { - 'name': 'Ernest Manager', - 'login': 'ernest', - 'alias_name': 'ernest', - 'groups_id': [(6, 0, [self.group_project_manager_id])] - }) # Test 'Pigs' project self.project_pigs_id = self.project_project.create(cr, uid, @@ -103,13 +67,13 @@ class TestPortalProject(common.TransactionCase): {'name': 'Test3', 'user_id': False, 'project_id': self.project_pigs_id}, {'mail_create_nolog': True}) self.task_4_id = self.project_task.create(cr, uid, - {'name': 'Test4', 'user_id': self.user_alfred_id, 'project_id': self.project_pigs_id}, + {'name': 'Test4', 'user_id': self.user_projectuser_id, 'project_id': self.project_pigs_id}, {'mail_create_nolog': True}) self.task_5_id = self.project_task.create(cr, uid, - {'name': 'Test5', 'user_id': self.user_chell_id, 'project_id': self.project_pigs_id}, + {'name': 'Test5', 'user_id': self.user_portal_id, 'project_id': self.project_pigs_id}, {'mail_create_nolog': True}) self.task_6_id = self.project_task.create(cr, uid, - {'name': 'Test6', 'user_id': self.user_donovan_id, 'project_id': self.project_pigs_id}, + {'name': 'Test6', 'user_id': self.user_anonymous_id, 'project_id': self.project_pigs_id}, {'mail_create_nolog': True}) @mute_logger('openerp.addons.base.ir.ir_model', 'openerp.osv.orm') @@ -122,53 +86,53 @@ class TestPortalProject(common.TransactionCase): # ---------------------------------------- # Do: Alfred reads project -> ok (employee ok public) - self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_projectuser_id, pigs_id, ['name']) # Test: all project tasks visible - task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_projectuser_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_1_id, self.task_2_id, self.task_3_id, self.task_4_id, self.task_5_id, self.task_6_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: project user cannot see all tasks of a public project') # Test: all project tasks readable - self.project_task.read(cr, self.user_alfred_id, task_ids, ['name']) + self.project_task.read(cr, self.user_projectuser_id, task_ids, ['name']) # Test: all project tasks writable - self.project_task.write(cr, self.user_alfred_id, task_ids, {'description': 'TestDescription'}) + self.project_task.write(cr, self.user_projectuser_id, task_ids, {'description': 'TestDescription'}) # Do: Bert reads project -> crash, no group self.assertRaises(except_orm, self.project_project.read, - cr, self.user_bert_id, pigs_id, ['name']) + cr, self.user_none_id, pigs_id, ['name']) # Test: no project task visible self.assertRaises(except_orm, self.project_task.search, - cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + cr, self.user_none_id, [('project_id', '=', pigs_id)]) # Test: no project task readable self.assertRaises(except_orm, self.project_task.read, - cr, self.user_bert_id, task_ids, ['name']) + cr, self.user_none_id, task_ids, ['name']) # Test: no project task writable self.assertRaises(except_orm, self.project_task.write, - cr, self.user_bert_id, task_ids, {'description': 'TestDescription'}) + cr, self.user_none_id, task_ids, {'description': 'TestDescription'}) # Do: Chell reads project -> ok (portal ok public) - self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_portal_id, pigs_id, ['name']) # Test: all project tasks visible - task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_portal_id, [('project_id', '=', pigs_id)]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: project user cannot see all tasks of a public project') # Test: all project tasks readable - self.project_task.read(cr, self.user_chell_id, task_ids, ['name']) + self.project_task.read(cr, self.user_portal_id, task_ids, ['name']) # Test: no project task writable self.assertRaises(except_orm, self.project_task.write, - cr, self.user_chell_id, task_ids, {'description': 'TestDescription'}) + cr, self.user_portal_id, task_ids, {'description': 'TestDescription'}) # Do: Donovan reads project -> ok (anonymous ok public) - self.project_project.read(cr, self.user_donovan_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_anonymous_id, pigs_id, ['name']) # Test: all project tasks visible - task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_anonymous_id, [('project_id', '=', pigs_id)]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: anonymous user cannot see all tasks of a public project') # Test: all project tasks readable - self.project_task.read(cr, self.user_donovan_id, task_ids, ['name']) + self.project_task.read(cr, self.user_anonymous_id, task_ids, ['name']) # Test: no project task writable self.assertRaises(except_orm, self.project_task.write, - cr, self.user_donovan_id, task_ids, {'description': 'TestDescription'}) + cr, self.user_anonymous_id, task_ids, {'description': 'TestDescription'}) # ---------------------------------------- # CASE2: portal project @@ -176,39 +140,39 @@ class TestPortalProject(common.TransactionCase): self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'portal'}) # Do: Alfred reads project -> ok (employee ok public) - self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_projectuser_id, pigs_id, ['name']) # Test: all project tasks visible - task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_projectuser_id, [('project_id', '=', pigs_id)]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: project user cannot see all tasks of a portal project') # Do: Bert reads project -> crash, no group self.assertRaises(except_orm, self.project_project.read, - cr, self.user_bert_id, pigs_id, ['name']) + cr, self.user_none_id, pigs_id, ['name']) # Test: no project task searchable self.assertRaises(except_orm, self.project_task.search, - cr, self.user_bert_id, [('project_id', '=', pigs_id)]) + cr, self.user_none_id, [('project_id', '=', pigs_id)]) # Data: task follower - self.project_task.message_subscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id]) + self.project_task.message_subscribe_users(cr, self.user_projectuser_id, [self.task_1_id, self.task_3_id], [self.user_portal_id]) # Do: Chell reads project -> ok (portal ok public) - self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_portal_id, pigs_id, ['name']) # Test: only followed project tasks visible + assigned - task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_portal_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_1_id, self.task_3_id, self.task_5_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: portal user should see the followed tasks of a portal project') # Do: Donovan reads project -> ko (anonymous ko portal) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_donovan_id, pigs_id, ['name']) + cr, self.user_anonymous_id, pigs_id, ['name']) # Test: no project task visible - task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_anonymous_id, [('project_id', '=', pigs_id)]) self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of a portal project') # Data: task follower cleaning - self.project_task.message_unsubscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id]) + self.project_task.message_unsubscribe_users(cr, self.user_projectuser_id, [self.task_1_id, self.task_3_id], [self.user_portal_id]) # ---------------------------------------- # CASE3: employee project @@ -216,29 +180,29 @@ class TestPortalProject(common.TransactionCase): self.project_project.write(cr, uid, [pigs_id], {'privacy_visibility': 'employees'}) # Do: Alfred reads project -> ok (employee ok employee) - self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_projectuser_id, pigs_id, ['name']) # Test: all project tasks visible - task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_projectuser_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_1_id, self.task_2_id, self.task_3_id, self.task_4_id, self.task_5_id, self.task_6_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: project user cannot see all tasks of an employees project') # Do: Bert reads project -> crash, no group self.assertRaises(except_orm, self.project_project.read, - cr, self.user_bert_id, pigs_id, ['name']) + cr, self.user_none_id, pigs_id, ['name']) # Do: Chell reads project -> ko (portal ko employee) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_chell_id, pigs_id, ['name']) + cr, self.user_portal_id, pigs_id, ['name']) # Test: no project task visible + assigned - task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_portal_id, [('project_id', '=', pigs_id)]) self.assertFalse(task_ids, 'access rights: portal user should not see tasks of an employees project, even if assigned') # Do: Donovan reads project -> ko (anonymous ko employee) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_donovan_id, pigs_id, ['name']) + cr, self.user_anonymous_id, pigs_id, ['name']) # Test: no project task visible - task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_anonymous_id, [('project_id', '=', pigs_id)]) self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of an employees project') # ---------------------------------------- @@ -248,53 +212,53 @@ class TestPortalProject(common.TransactionCase): # Do: Alfred reads project -> ko (employee ko followers) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_alfred_id, pigs_id, ['name']) + cr, self.user_projectuser_id, pigs_id, ['name']) # Test: no project task visible - task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_projectuser_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_4_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: employee user should not see tasks of a not-followed followers project, only assigned') # Do: Bert reads project -> crash, no group self.assertRaises(except_orm, self.project_project.read, - cr, self.user_bert_id, pigs_id, ['name']) + cr, self.user_none_id, pigs_id, ['name']) # Do: Chell reads project -> ko (portal ko employee) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_chell_id, pigs_id, ['name']) + cr, self.user_portal_id, pigs_id, ['name']) # Test: no project task visible - task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_portal_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_5_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: portal user should not see tasks of a not-followed followers project, only assigned') # Do: Donovan reads project -> ko (anonymous ko employee) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_donovan_id, pigs_id, ['name']) + cr, self.user_anonymous_id, pigs_id, ['name']) # Test: no project task visible - task_ids = self.project_task.search(cr, self.user_donovan_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_anonymous_id, [('project_id', '=', pigs_id)]) self.assertFalse(task_ids, 'access rights: anonymous user should not see tasks of a followers project') # Data: subscribe Alfred, Chell and Donovan as follower - self.project_project.message_subscribe_users(cr, uid, [pigs_id], [self.user_alfred_id, self.user_chell_id, self.user_donovan_id]) - self.project_task.message_subscribe_users(cr, self.user_alfred_id, [self.task_1_id, self.task_3_id], [self.user_chell_id, self.user_alfred_id]) + self.project_project.message_subscribe_users(cr, uid, [pigs_id], [self.user_projectuser_id, self.user_portal_id, self.user_anonymous_id]) + self.project_task.message_subscribe_users(cr, self.user_projectuser_id, [self.task_1_id, self.task_3_id], [self.user_portal_id, self.user_projectuser_id]) # Do: Alfred reads project -> ok (follower ok followers) - self.project_project.read(cr, self.user_alfred_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_projectuser_id, pigs_id, ['name']) # Test: followed + assigned tasks visible - task_ids = self.project_task.search(cr, self.user_alfred_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_projectuser_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_1_id, self.task_3_id, self.task_4_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: employee user should not see followed + assigned tasks of a follower project') # Do: Chell reads project -> ok (follower ok follower) - self.project_project.read(cr, self.user_chell_id, pigs_id, ['name']) + self.project_project.read(cr, self.user_portal_id, pigs_id, ['name']) # Test: followed + assigned tasks visible - task_ids = self.project_task.search(cr, self.user_chell_id, [('project_id', '=', pigs_id)]) + task_ids = self.project_task.search(cr, self.user_portal_id, [('project_id', '=', pigs_id)]) test_task_ids = set([self.task_1_id, self.task_3_id, self.task_5_id]) self.assertEqual(set(task_ids), test_task_ids, 'access rights: employee user should not see followed + assigned tasks of a follower project') # Do: Donovan reads project -> ko (anonymous ko follower even if follower) self.assertRaises(except_orm, self.project_project.read, - cr, self.user_donovan_id, pigs_id, ['name']) + cr, self.user_anonymous_id, pigs_id, ['name']) diff --git a/addons/project/doc/changelog.rst b/addons/project/doc/changelog.rst index ed739d1757e..ba5b242f1c0 100644 --- a/addons/project/doc/changelog.rst +++ b/addons/project/doc/changelog.rst @@ -13,4 +13,4 @@ Changelog modification. Updated reports. - ``project.task.type``: removed ``state`` field. -- Removed ``hired.employee`` wizard. +- Removed ``project.task.reevaluate`` wizard. diff --git a/addons/project/project.py b/addons/project/project.py index 3f80a075da9..7128b188432 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -25,11 +25,10 @@ import time from openerp import SUPERUSER_ID from openerp import tools +from openerp.addons.resource.faces import task as Task from openerp.osv import fields, osv from openerp.tools.translate import _ -from openerp.addons.resource.faces import task as Task - class project_task_type(osv.osv): _name = 'project.task.type' @@ -319,8 +318,7 @@ class project(osv.osv): ] def set_template(self, cr, uid, ids, context=None): - res = self.setActive(cr, uid, ids, value=False, context=context) - return res + return self.setActive(cr, uid, ids, value=False, context=context) def set_done(self, cr, uid, ids, context=None): return self.write(cr, uid, ids, {'state': 'close'}, context=context) @@ -449,7 +447,6 @@ class project(osv.osv): if project.user_id and (project.user_id.id not in u_ids): u_ids.append(project.user_id.id) for task in project.tasks: - # TDE: be sure about this, was if task.state in ('done','cancelled') if task.stage_id and task.stage_id.fold: continue if task.user_id and (task.user_id.id not in u_ids): @@ -516,7 +513,6 @@ def Project(): for project in projects: project_gantt = getattr(projects_gantt, 'Project_%d' % (project.id,)) for task in project.tasks: - # TDE CHECK: was if task.state in ('done', 'cancelled') if task.stage_id and task.stage_id.fold: continue @@ -532,10 +528,6 @@ def Project(): }, context=context) return True - # ------------------------------------------------ - # OpenChatter methods and notifications - # ------------------------------------------------ - def create(self, cr, uid, vals, context=None): if context is None: context = {} @@ -570,6 +562,9 @@ class task(osv.osv): 'project.mt_task_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence == 1, 'project.mt_task_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id.sequence != 1, }, + 'user_id': { + 'project.mt_task_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id, + }, 'kanban_state': { # kanban state: tracked, but only block subtype 'project.mt_task_blocked': lambda self, cr, uid, obj, ctx=None: obj.kanban_state == 'blocked', }, @@ -675,11 +670,11 @@ class task(osv.osv): def onchange_remaining(self, cr, uid, ids, remaining=0.0, planned=0.0): if remaining and not planned: - return {'value':{'planned_hours': remaining}} + return {'value': {'planned_hours': remaining}} return {} def onchange_planned(self, cr, uid, ids, planned=0.0, effective=0.0): - return {'value':{'remaining_hours': planned - effective}} + return {'value': {'remaining_hours': planned - effective}} def onchange_project(self, cr, uid, id, project_id, context=None): if project_id: @@ -691,7 +686,7 @@ class task(osv.osv): def onchange_user_id(self, cr, uid, ids, user_id, context=None): vals = {} if user_id: - vals['date_start'] = time.strftime(tools.DEFAULT_SERVER_DATETIME_FORMAT) + vals['date_start'] = fields.datetime.now() vals['date_end'] = False return {'value': vals} @@ -748,9 +743,7 @@ class task(osv.osv): 'active': fields.function(_is_template, store=True, string='Not a Template Task', type='boolean', help="This field is computed automatically and have the same behavior than the boolean 'active' field: if the task is linked to a template or unactivated project, it will be hidden unless specifically asked."), 'name': fields.char('Task Summary', size=128, required=True, select=True), 'description': fields.text('Description'), - 'priority': fields.selection([('4', 'Very Low'), ('3', 'Low'), ('2', 'Medium'), - ('1', 'Important'), ('0', 'Very important')], - string='Priority', select=True), + 'priority': fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Important'), ('0','Very important')], 'Priority', select=True), 'sequence': fields.integer('Sequence', select=True, help="Gives the sequence order when displaying a list of tasks."), 'stage_id': fields.many2one('project.task.type', 'Stage', track_visibility='onchange', domain="[('project_ids', '=', project_id)]"), @@ -937,8 +930,7 @@ class task(osv.osv): search_domain = [('|')] * (len(section_ids) - 1) for section_id in section_ids: search_domain.append(('project_ids', '=', section_id)) - if domain: - search_domain += list(domain) + search_domain += list(domain) # perform search, return the first found stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context) if stage_ids: @@ -952,7 +944,6 @@ class task(osv.osv): for task in tasks: if task.child_ids: for child in task.child_ids: - # TDE CHECK: was 'if child.state in ['draft', 'open', 'pending']'' if child.stage_id and not child.stage_id.fold: raise osv.except_osv(_("Warning!"), _("Child task still open.\nPlease cancel or complete child task first.")) return True @@ -977,7 +968,7 @@ class task(osv.osv): delegated_task_id = self.copy(cr, uid, task.id, { 'name': delegate_data['name'], 'project_id': delegate_data['project_id'] and delegate_data['project_id'][0] or False, - 'stage_id': delegate_data.get('stage_id', [False])[0], + 'stage_id': delegate_data.get('stage_id') and delegate_data.get('stage_id')[0] or False, 'user_id': delegate_data['user_id'] and delegate_data['user_id'][0] or False, 'planned_hours': delegate_data['planned_hours'] or 0.0, 'parent_ids': [(6, 0, [task.id])], @@ -997,7 +988,6 @@ class task(osv.osv): def set_remaining_time(self, cr, uid, ids, remaining_time=1.0, context=None): for task in self.browse(cr, uid, ids, context=context): - # TDE CHECK: was (task.state=='draft') if (task.stage_id and task.stage_id.sequence == 1) or (task.planned_hours == 0.0): self.write(cr, uid, [task.id], {'planned_hours': remaining_time}, context=context) self.write(cr, uid, ids, {'remaining_hours': remaining_time}, context=context) @@ -1052,12 +1042,6 @@ class task(osv.osv): # user_id change: update date_start if vals.get('user_id'): vals['date_start'] = fields.datetime.now() - # generate a default stage based on context / given project value - if not vals.get('stage_id'): - ctx = context.copy() - if vals.get('project_id'): - ctx['default_project_id'] = vals['project_id'] - vals['stage_id'] = self._get_default_stage_id(cr, uid, context=ctx) # context: no_log, because subtype already handle this create_context = dict(context, mail_create_nolog=True) @@ -1104,7 +1088,6 @@ class task(osv.osv): result = "" ident = ' '*ident for task in tasks: - # TDE CHECK: if task.state in ('done','cancelled'): if task.stage_id and task.stage_id.fold: continue result += ''' @@ -1175,25 +1158,10 @@ class task(osv.osv): update_vals[field] = float(res.group(2).lower()) except (ValueError, TypeError): pass - # elif match.lower() == 'state' \ - # and res.group(2).lower() in ['cancel','close','draft','open','pending']: - # act = 'do_%s' % res.group(2).lower() if act: getattr(self,act)(cr, uid, ids, context=context) return super(task,self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context) - # TDE NOTE: FIXME - def project_task_reevaluate(self, cr, uid, ids, context=None): - if self.pool.get('res.users').has_group(cr, uid, 'project.group_time_work_estimation_tasks'): - return { - 'view_type': 'form', - "view_mode": 'form', - 'res_model': 'project.task.reevaluate', - 'type': 'ir.actions.act_window', - 'target': 'new', - } - return self.do_reopen(cr, uid, ids, context=context) - class project_work(osv.osv): _name = "project.task.work" _description = "Project Task Work" diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index b53c3bb359f..12e373642fd 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -225,7 +225,6 @@ ref('project.project_category_04')])]"/> - @@ -237,7 +236,6 @@ 6 - @@ -248,7 +246,6 @@ Design Use Cases - @@ -282,7 +279,6 @@ Set target for all deparments - @@ -293,7 +289,6 @@ Integration of core components - @@ -315,7 +310,6 @@ - 42.0 @@ -325,7 +319,6 @@ Create new components - 14.0 @@ -337,7 +330,6 @@ - 12.0 @@ -371,7 +363,6 @@ - 20 @@ -382,7 +373,6 @@ Data importation + Doc - 20 diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index e8ed9ed6ede..30943cff331 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -18,25 +18,23 @@ - - - - - + + + - + diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml index ffaf23ccc4e..2e113dfd04f 100644 --- a/addons/project/report/project_report_view.xml +++ b/addons/project/report/project_report_view.xml @@ -11,18 +11,6 @@ report.project.task.user - - - - - - - - - - - - @@ -37,6 +25,17 @@ + + + + + + + + + + + @@ -68,10 +67,6 @@ - - - diff --git a/addons/project/tests/test_project_base.py b/addons/project/tests/test_project_base.py index 4d1b77f46c7..f82561766fe 100644 --- a/addons/project/tests/test_project_base.py +++ b/addons/project/tests/test_project_base.py @@ -66,6 +66,13 @@ class TestProjectBase(TestMailBase): 'email': 'bastien.projectmanager@example.com', 'groups_id': [(6, 0, [self.group_employee_id, self.group_project_manager_id])] }) + self.user_none_id = self.res_users.create(cr, uid, { + 'name': 'Charlie Avotbonkeur', + 'login': 'charlie', + 'alias_name': 'charlie', + 'email': 'charlie.noone@example.com', + 'groups_id': [(6, 0, [])] + }) self.user_projectuser = self.res_users.browse(cr, uid, self.user_projectuser_id) self.user_projectmanager = self.res_users.browse(cr, uid, self.user_projectmanager_id) self.partner_projectuser_id = self.user_projectuser.partner_id.id diff --git a/addons/project/tests/test_project_flow.py b/addons/project/tests/test_project_flow.py index c0d7748ef83..a78bd6de156 100644 --- a/addons/project/tests/test_project_flow.py +++ b/addons/project/tests/test_project_flow.py @@ -146,6 +146,7 @@ class TestProjectFlow(TestProjectBase): # Test: task content self.assertEqual(task.name, 'Frogs', 'project_task: name should be the email subject') self.assertEqual(task.project_id.id, self.project_pigs_id, 'project_task: incorrect project') + self.assertEqual(task.stage_id.sequence, 1, 'project_task: should have a stage with sequence=1') # Open the delegation wizard delegate_id = self.project_task_delegate.create(cr, user_projectuser_id, { diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py index cc71ae7cfa9..30ca08c0ae7 100644 --- a/addons/project_issue/project_issue.py +++ b/addons/project_issue/project_issue.py @@ -19,14 +19,14 @@ # ############################################################################## -from openerp import SUPERUSER_ID -from openerp.addons.crm import crm from datetime import datetime -from openerp.osv import fields, osv, orm -from openerp.tools.translate import _ -import time + +from openerp import SUPERUSER_ID from openerp import tools +from openerp.addons.crm import crm +from openerp.osv import fields, osv, orm from openerp.tools import html2plaintext +from openerp.tools.translate import _ class project_issue_version(osv.Model): _name = "project.issue.version" @@ -50,24 +50,14 @@ class project_issue(osv.Model): 'project_issue.mt_issue_new': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence == 1, 'project_issue.mt_issue_stage': lambda self, cr, uid, obj, ctx=None: obj.stage_id and obj.stage_id.sequence != 1, }, - # 'user_id': { - # 'project_issue.mt_issue_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id, - # }, + 'user_id': { + 'project_issue.mt_issue_assigned': lambda self, cr, uid, obj, ctx=None: obj.user_id and obj.user_id.id, + }, 'kanban_state': { 'project_issue.mt_issue_blocked': lambda self, cr, uid, obj, ctx=None: obj.kanban_state == 'blocked', }, } - def create(self, cr, uid, vals, context=None): - if context is None: - context = {} - if vals.get('project_id') and not context.get('default_project_id'): - context['default_project_id'] = vals.get('project_id') - - # context: no_log, because subtype already handle this - create_context = dict(context, mail_create_nolog=True) - return super(project_issue, self).create(cr, uid, vals, context=create_context) - def _get_default_partner(self, cr, uid, context=None): """ Override of base_stage to add project specific behavior """ project_id = self._get_default_project_id(cr, uid, context) @@ -389,6 +379,16 @@ class project_issue(osv.Model): return super(project_issue, self).copy(cr, uid, id, default=default, context=context) + def create(self, cr, uid, vals, context=None): + if context is None: + context = {} + if vals.get('project_id') and not context.get('default_project_id'): + context['default_project_id'] = vals.get('project_id') + + # context: no_log, because subtype already handle this + create_context = dict(context, mail_create_nolog=True) + return super(project_issue, self).create(cr, uid, vals, context=create_context) + def write(self, cr, uid, ids, vals, context=None): # stage change: update date_last_stage_update if 'stage_id' in vals: @@ -575,7 +575,6 @@ class project(osv.Model): res = dict.fromkeys(ids, 0) issue_ids = self.pool.get('project.issue').search(cr, uid, [('project_id', 'in', ids)]) for issue in self.pool.get('project.issue').browse(cr, uid, issue_ids, context): - # TDE CHECK: if issue.state not in ('done', 'cancelled'): if issue.stage_id and not issue.stage_id.fold: res[issue.project_id.id] += 1 return res diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml index f8c006beaff..25a336d4094 100644 --- a/addons/project_issue/project_issue_data.xml +++ b/addons/project_issue/project_issue_data.xml @@ -1,7 +1,6 @@ - - + diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index 8a535e3bc96..4c4d91850a3 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -141,15 +141,15 @@ - - - + + + diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py index 48c3628832a..496aa819ee2 100644 --- a/addons/project_issue/report/project_issue_report.py +++ b/addons/project_issue/report/project_issue_report.py @@ -31,12 +31,7 @@ class project_issue_report(osv.osv): _columns = { 'name': fields.char('Year', size=64, required=False, readonly=True), 'section_id':fields.many2one('crm.case.section', 'Sale Team', readonly=True), - 'month':fields.selection([('01', 'January'), ('02', 'February'), \ - ('03', 'March'), ('04', 'April'),\ - ('05', 'May'), ('06', 'June'), \ - ('07', 'July'), ('08', 'August'),\ - ('09', 'September'), ('10', 'October'),\ - ('11', 'November'), ('12', 'December')], 'Month', readonly=True), + 'month':fields.selection(fields.date.MONTHS, 'Month', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'day': fields.char('Day', size=128, readonly=True), 'opening_date': fields.date('Date of Opening', readonly=True), diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py index 97e468ce51a..786da81dd34 100644 --- a/addons/project_mrp/project_mrp.py +++ b/addons/project_mrp/project_mrp.py @@ -56,11 +56,12 @@ class project_task(osv.osv): def write(self, cr, uid, ids, values, context=None): """ When closing tasks, validate subflows. """ + res = super(project_task, self).write(cr, uid, ids, values, context=context) if values.get('stage_id'): stage = self.pool.get('project.task.type').browse(cr, uid, values.get('stage_id'), context=context) if stage.closed: self._validate_subflows(cr, uid, ids, context=context) - return super(project_task, self).write(cr, uid, ids, values, context=context) + return res class product_product(osv.osv): diff --git a/addons/project_mrp/project_mrp_demo.xml b/addons/project_mrp/project_mrp_demo.xml index 30d4cfba7ef..a840c0166e7 100644 --- a/addons/project_mrp/project_mrp_demo.xml +++ b/addons/project_mrp/project_mrp_demo.xml @@ -1,7 +1,6 @@ - @@ -14,5 +13,8 @@ make_to_order + + + diff --git a/addons/project_mrp/project_procurement.py b/addons/project_mrp/project_procurement.py index 3587e2167a2..8a6dc811d9a 100644 --- a/addons/project_mrp/project_procurement.py +++ b/addons/project_mrp/project_procurement.py @@ -39,7 +39,7 @@ class procurement_order(osv.osv): @return: True or False. """ for p in self.browse(cr, uid, ids, context=context): - if (p.product_id.type == 'service') and (p.procure_method == 'make_to_order') and p.task_id and p.task_id.stage_id and p.task_id.stage_id.closed: + if (p.product_id.type == 'service') and (p.procure_method == 'make_to_order') and p.task_id and (p.task_id.stage_id and not p.task_id.stage_id.closed): return False return True diff --git a/addons/project_mrp/test/project_task_procurement.yml b/addons/project_mrp/test/project_task_procurement.yml index 50199d40a11..b16cce7590d 100644 --- a/addons/project_mrp/test/project_task_procurement.yml +++ b/addons/project_mrp/test/project_task_procurement.yml @@ -9,39 +9,39 @@ self.run_scheduler(cr, uid) - Now I check that task details after run procurement -# - -# !python {model: procurement.order}: | -# from datetime import datetime -# procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) -# assert procurement_ids, "Procurement is not generated for Service Order Line." -# procurement = self.browse(cr, uid, procurement_ids[0], context=context) -# assert procurement.state != 'done' , "Procurement should not be closed." -# task = procurement.task_id -# assert task, "Task is not generated." -# # check whether task project either is the product's project, or corresponds to the analytic account of sale order -# project = task.project_id -# if procurement.product_id.project_id: -# assert project == procurement.product_id.project_id, "Project does not correspond." -# elif procurement.sale_line_id: -# account = procurement.sale_line_id.order_id.project_id -# assert (not project and not account) or project.analytic_account_id == account, "Project does not correspond." -# planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context) -# assert task.planned_hours == planned_hours, 'Planned Hours do not correspond.' -# assert datetime.strptime(task.date_deadline, '%Y-%m-%d') == datetime.strptime(procurement.date_planned[:10], '%Y-%m-%d'), 'Deadline does not correspond.' -# if procurement.product_id.product_manager: -# assert task.user_id.id == procurement.product_id.product_manager.id, 'Allocated Person does not correspond with Service Product Manager.' -# - -# I close that task. -# - -# !python {model: project.task}: | -# task_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) -# assert task_ids, "Task is not generated for Service Order Line." -# self.do_close(cr, uid, task_ids, context=context) -# - -# I check procurement of Service Order Line after closed task. -# - -# !python {model: procurement.order}: | -# procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) -# assert procurement_ids, "Procurement is not generated for Service Order Line." -# procurement = self.browse(cr, uid, procurement_ids[0], context=context) -# assert procurement.state == 'done' , "Procurement should be closed." \ No newline at end of file +- + !python {model: procurement.order}: | + from datetime import datetime + procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) + assert procurement_ids, "Procurement is not generated for Service Order Line." + procurement = self.browse(cr, uid, procurement_ids[0], context=context) + assert procurement.state != 'done' , "Procurement should not be closed." + task = procurement.task_id + assert task, "Task is not generated." + # check whether task project either is the product's project, or corresponds to the analytic account of sale order + project = task.project_id + if procurement.product_id.project_id: + assert project == procurement.product_id.project_id, "Project does not correspond." + elif procurement.sale_line_id: + account = procurement.sale_line_id.order_id.project_id + assert (not project and not account) or project.analytic_account_id == account, "Project does not correspond." + planned_hours = self._convert_qty_company_hours(cr, uid, procurement, context=context) + assert task.planned_hours == planned_hours, 'Planned Hours do not correspond.' + assert datetime.strptime(task.date_deadline, '%Y-%m-%d') == datetime.strptime(procurement.date_planned[:10], '%Y-%m-%d'), 'Deadline does not correspond.' + if procurement.product_id.product_manager: + assert task.user_id.id == procurement.product_id.product_manager.id, 'Allocated Person does not correspond with Service Product Manager.' +- + I close that task. +- + !python {model: project.task}: | + task_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) + assert task_ids, "Task is not generated for Service Order Line." + self.write(cr, uid, task_ids, {'stage_id': ref('project.project_tt_deployment')}, context=context) +- + I check procurement of Service Order Line after closed task. +- + !python {model: procurement.order}: | + procurement_ids = self.search(cr, uid, [('sale_line_id', '=', ref('line_services'))]) + assert procurement_ids, "Procurement is not generated for Service Order Line." + procurement = self.browse(cr, uid, procurement_ids[0], context=context) + assert procurement.state == 'done' , "Procurement should be closed." \ No newline at end of file