diff options
| author | Jigar Amin - OpenERP <jam@tinyerp.com> | 2012-06-27 17:10:52 +0530 |
|---|---|---|
| committer | Jigar Amin - OpenERP <jam@tinyerp.com> | 2012-06-27 17:10:52 +0530 |
| commit | 7c645856fe8dc05c237d070c98c4c22641776a2c (patch) | |
| tree | 359a4bb4e9fafb63d4398a444b595a861466363c /addons/project | |
| parent | f89c6f0a0b5be2b76fcd4735b9a05616c0191099 (diff) | |
| parent | b22523e08242edb8df5d1d39f6a76121833956d4 (diff) | |
[MERGE] lp:openobject-addons
bzr revid: jam@tinyerp.com-20120627114052-094g4yequ34sr59d
Diffstat (limited to 'addons/project')
| -rw-r--r-- | addons/project/project.py | 90 | ||||
| -rw-r--r-- | addons/project/project_demo.xml | 2 | ||||
| -rw-r--r-- | addons/project/project_view.xml | 102 | ||||
| -rw-r--r-- | addons/project/security/project_security.xml | 9 | ||||
| -rw-r--r-- | addons/project/wizard/__init__.py | 1 | ||||
| -rw-r--r-- | addons/project/wizard/mail_compose_message.py | 72 |
6 files changed, 123 insertions, 153 deletions
diff --git a/addons/project/project.py b/addons/project/project.py index 429672d3269..ab02cc870bb 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -165,14 +165,29 @@ class project(osv.osv): res[task.project_id.id] += 1 return res + def _get_followers(self, cr, uid, ids, name, arg, context=None): + ''' + Functional field that computes the users that are 'following' a thread. + ''' + res = {} + for project in self.browse(cr, uid, ids, context=context): + l = set() + for message in project.message_ids: + l.add(message.user_id and message.user_id.id or False) + res[project.id] = list(filter(None, l)) + return res + + def _search_followers(self, cr, uid, obj, name, args, context=None): + project_obj = self.pool.get('project.project') + project_ids = project_obj.search(cr, uid, [('message_ids.user_id.id', 'in', args[0][2])], context=context) + return [('id', 'in', project_ids)] + _columns = { 'complete_name': fields.function(_complete_name, string="Project Name", type='char', size=250), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the project without removing it."), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of Projects."), 'analytic_account_id': fields.many2one('account.analytic.account', 'Analytic Account', help="Link this project to an analytic account if you need financial management on projects. It enables you to connect projects with budgets, planning, cost and revenue analysis, timesheets on projects, etc.", ondelete="cascade", required=True), 'priority': fields.integer('Sequence', help="Gives the sequence order when displaying the list of projects"), - 'warn_manager': fields.boolean('Notify Manager', help="If you check this field, the project manager will receive an email each time a task is completed by his team.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), - 'members': fields.many2many('res.users', 'project_user_rel', 'project_id', 'uid', 'Project Members', help="Project's members are users who can have an access to the tasks related to this project.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), 'tasks': fields.one2many('project.task', 'project_id', "Task Activities"), @@ -197,19 +212,18 @@ class project(osv.osv): 'project.task': (_get_projects_from_tasks, ['planned_hours', 'remaining_hours', 'work_ids', 'state'], 20), }), 'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ), - 'warn_customer': fields.boolean('Warn Partner', help="If you check this, the user will have a popup when closing a task that propose a message to send by email to the customer.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), - 'warn_header': fields.text('Mail Header', help="Header added at the beginning of the email for the warning message sent to the customer when a task is closed.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), - 'warn_footer': fields.text('Mail Footer', help="Footer added at the beginning of the email for the warning message sent to the customer when a task is closed.", states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), 'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}), - 'use_tasks': fields.boolean('Use Tasks', help="Check this field if this project is aimed at managing tasks"), 'task_count': fields.function(_task_count, type='integer', string="Open Tasks"), 'color': fields.integer('Color Index'), - 'company_uom_id': fields.related('company_id', 'project_time_mode_id', type='many2one', relation='product.uom'), + 'privacy_visibility': fields.selection([('public','Public'), ('followers','Followers Only')], 'Privacy / Visibility'), + 'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','Pending'),('close','Closed')], 'Status', required=True,), + 'followers': fields.function(_get_followers, method=True, fnct_search=_search_followers, + type='many2many', relation='res.users', string='Followers'), } def dummy(self, cr, uid, ids, context): return True - + def _get_type_common(self, cr, uid, context): ids = self.pool.get('project.task.type').search(cr, uid, [('case_default','=',1)], context=context) return ids @@ -217,10 +231,11 @@ class project(osv.osv): _order = "sequence" _defaults = { 'active': True, + 'type': 'contract', + 'state': 'open', 'priority': 1, 'sequence': 10, 'type_ids': _get_type_common, - 'use_tasks': True, } # TODO: Why not using a SQL contraints ? @@ -894,28 +909,12 @@ class task(base_stage, osv.osv): return True def action_close(self, cr, uid, ids, context=None): - """ This action closes the task, then opens the wizard to send an - email to the partner or the project manager. + """ This action closes the task """ task_id = len(ids) and ids[0] or False self._check_child_task(cr, uid, ids, context=context) if not task_id: return False - task = self.browse(cr, uid, task_id, context=context) - project = task.project_id - res = self.do_close(cr, uid, [task_id], context=context) - if project.warn_manager or project.warn_customer: - return { - 'name': _('Send Email after close task'), - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'mail.compose.message', - 'type': 'ir.actions.act_window', - 'target': 'new', - 'nodestroy': True, - 'context': {'active_id': task.id, - 'active_model': 'project.task'} - } - return res + return self.do_close(cr, uid, [task_id], context=context) def do_close(self, cr, uid, ids, context=None): """ Compatibility when changing to case_close. """ @@ -1217,16 +1216,49 @@ class project_work(osv.osv): class account_analytic_account(osv.osv): - _inherit = 'account.analytic.account' _description = 'Analytic Account' + _columns = { + 'use_tasks': fields.boolean('Tasks Management',help="If check,this contract will be available in the project menu and you will be able to manage tasks or track issues"), + 'company_uom_id': fields.related('company_id', 'project_time_mode_id', type='many2one', relation='product.uom'), + } + + def _trigger_project_creation(self, cr, uid, vals, context=None): + ''' + This function is used to decide if a project needs to be automatically created or not when an analytic account is created. It returns True if it needs to be so, False otherwise. + ''' + return vals.get('use_tasks') + + def project_create(self, cr, uid, analytic_account_id, vals, context=None): + ''' + This function is called at the time of analytic account creation and is used to create a project automatically linked to it if the conditions are meet. + ''' + project_pool = self.pool.get('project.project') + project_id = project_pool.search(cr, uid, [('analytic_account_id','=', analytic_account_id)]) + if not project_id and self._trigger_project_creation(cr, uid, vals, context=context): + project_values = { + 'name': vals.get('name'), + 'analytic_account_id': analytic_account_id, + } + return project_pool.create(cr, uid, project_values, context=context) + return False def create(self, cr, uid, vals, context=None): if context is None: context = {} if vals.get('child_ids', False) and context.get('analytic_project_copy', False): vals['child_ids'] = [] - return super(account_analytic_account, self).create(cr, uid, vals, context=context) + analytic_account_id = super(account_analytic_account, self).create(cr, uid, vals, context=context) + self.project_create(cr, uid, analytic_account_id, vals, context=context) + return analytic_account_id + + def write(self, cr, uid, ids, vals, context=None): + name = vals.get('name') + for account in self.browse(cr, uid, ids, context=context): + if not name: + vals['name'] = account.name + self.project_create(cr, uid, account.id, vals, context=context) + return super(account_analytic_account, self).write(cr, uid, ids, vals, context=context) def unlink(self, cr, uid, ids, *args, **kwargs): project_obj = self.pool.get('project.project') diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index f685f14c85b..07951280dc7 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -286,14 +286,12 @@ <record id="project_project_9" model="project.project"> - <field name="warn_manager">1</field> <field name="name">OpenERP Integration</field> <field name="parent_id" ref="all_projects_account"/> <field name="user_id" ref="base.user_root"/> <field eval="[(6, 0, [ref('project_tt_specification'),ref('project_tt_development'),ref('project_tt_testing'),ref('project_tt_merge')])]" name="type_ids"/> </record> <record id="project_project_21" model="project.project"> - <field name="warn_manager">1</field> <field name="priority">10</field> <field name="parent_id" ref="all_projects_account"/> <field name="name">Study + Prototype</field> diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index 4c79441ad18..ac67cbe0319 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -10,7 +10,16 @@ web_icon_hover="images/project-hover.png"/> <menuitem id="menu_project_management" name="Project" parent="base.menu_main_pm" sequence="1"/> - <menuitem id="menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/> + <menuitem id="base.menu_definitions" name="Configuration" parent="base.menu_main_pm" sequence="60"/> + + <act_window + context="{'search_default_project_id': [active_id], 'default_project_id': active_id}" + id="act_project_project_2_project_task_all" + name="Tasks" + res_model="project.task" + src_model="project.project" + view_mode="kanban,tree,form,calendar,graph" + view_type="form"/> <!-- Project --> <record id="edit_project" model="ir.ui.view"> @@ -34,7 +43,7 @@ <field name="analytic_account_id" invisible="1" required="0"/> <label for="name" class="oe_edit_only" string="Project Name"/> <h1> - <field name="name"/> + <field name="name" string="Project Name"/> </h1> <label for="parent_id" class="oe_edit_only" string="Parent Project"/> <h2> @@ -42,16 +51,28 @@ </h2> <group> <group> + <field name="partner_id" on_change="onchange_partner_id(partner_id)" select="1"/> <field name="user_id" string="Project Manager" attrs="{'readonly':[('state','in',['close', 'cancelled'])]}"/> - </group><group> - <field name="date_start" string="Start Date" attrs="{'readonly':[('state','in',['close', 'cancelled'])]}"/> - <field name="date" string="End Date" attrs="{'readonly':[('state','in',['close', 'cancelled'])]}"/> - <field name="progress_rate" widget="progressbar"/> + <field name="analytic_account_id" invisible="1" required="0"/> + <field name="parent_id" invisible="1" string="Parent" domain="[('id','!=',analytic_account_id)]" context="{'current_model': 'project.project'}"/> + <field name="privacy_visibility"/> + </group> + <group> + <table> + <tr name="use_tasks_row"> + <td><group><field name="use_tasks"/></group></td> + <td><button icon="terp-gtk-go-back-rtl" name="%(act_project_project_2_project_task_all)d" string="Tasks" type="action" attrs="{'invisible':[('use_tasks','=', 0)]}"/></td> + </tr> + <tr name="use_attachment_row"> + <td/> + <td><button icon="terp-gtk-go-back-rtl" class="oe_btn_width" name="%(base.action_attachment)d" string="Documents" type="action" /></td> + </tr> + </table> </group> </group> - <notebook colspan="4"> - <page string="Members"> - <field colspan="4" name="members" nolabel="1" widget="many2many_kanban"> + <notebook> + <page string="Team" name="team"> + <field colspan="4" name="members" widget="many2many_kanban"> <kanban quick_create="true" create="false"> <field name="name"/> <templates> @@ -69,55 +90,24 @@ </kanban> </field> </page> - <page string="Administration"> + <page string="Other Info"> <group> - <group name="kanban" string="Project Management"> - <field name="use_tasks"/> - </group> - <group string="Performance"> + <group string="Administration"> <field name="planned_hours" widget="float_time"/> <field name="effective_hours" widget="float_time" /> <field name="resource_calendar_id"/> </group> - <newline/> - <group name="misc" string="Miscellaneous"> - <field name="company_id" groups="base.group_multi_company" widget="selection" required="1"/> - <field name="warn_manager"/> + <group string="Miscellaneous" name="misc"> + <field name="company_id" select="1" groups="base.group_multi_company" widget="selection" required="1"/> <field name="priority"/> <field name="active" attrs="{'invisible':[('state','in',['open', 'pending', 'template'])]}"/> + <field name="currency_id" select="1" groups="base.group_multi_company" required="1"/> </group> </group> </page> - <page string="Billing" groups="account.group_account_invoice"> - <group col="4"> - <field colspan="4" name="partner_id" on_change="onchange_partner_id(partner_id)" string="Customer"/> - <field name="warn_customer"/> - <field name="currency_id" groups="base.group_multi_company" required="1"/> - </group> - <group col="4"> - <separator colspan="2" string="Mail Header"/> - <separator colspan="2" string="Mail Footer"/> - <field name="warn_header" nolabel="1" colspan="2"/> - <field name="warn_footer" nolabel="1" colspan="2"/> - </group> - <group col="3"> - <b> - <label string="Variables you can use for headers and footer." colspan="3"/> - </b> - <label string="Task: %%(name)s"/> - <label string="User: %%(user_id)s"/> - <label string="ID: %%(task_id)s"/> - <label string="Status: %%(state)s"/> - <label string="Date Start: %%(date_start)s"/> - <label string="Date Stop: %%(date)s"/> - </group> - </page> <page string="Tasks Stages"> <field name="type_ids"/> </page> - <page string="Notes"> - <field name="description"/> - </page> </notebook> </sheet> <footer> @@ -624,6 +614,22 @@ </search> </field> </record> + + <record id="analytic_account_inherited_form" model="ir.ui.view"> + <field name="name">account.analytic.account.form.inherit</field> + <field name="model">account.analytic.account</field> + <field name="type">form</field> + <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/> + <field eval="18" name="priority"/> + <field name="arch" type="xml"> + <xpath expr='//separator[@name="project_sep"]' position='replace'> + <separator colspan="4" string="Project Management" name="project_sep"/> <!-- removal of invisible attribute --> + </xpath> + <xpath expr='//separator[@name="project_sep"]' position='after'> + <field name="use_tasks" /> + </xpath> + </field> + </record> <record id="action_view_task" model="ir.actions.act_window"> <field name="name">Tasks</field> @@ -735,11 +741,11 @@ <field name="help">Define the steps that will be used in the project from the creation of the task, up to the closing of the task or issue. You will use these stages in order to track the progress in solving a task or an issue.</field> </record> - <menuitem id="menu_tasks_config" name="GTD" parent="project.menu_definitions" sequence="1"/> + <menuitem id="menu_tasks_config" name="GTD" parent="base.menu_definitions" sequence="1"/> - <menuitem id="menu_project_config_project" name="Stages" parent="project.menu_definitions" sequence="1"/> + <menuitem id="base.menu_project_config_project" name="Stages" parent="base.menu_definitions" sequence="1"/> - <menuitem action="open_task_type_form" name="Task Stages" id="menu_task_types_view" parent="menu_project_config_project" sequence="2"/> + <menuitem action="open_task_type_form" name="Task Stages" id="menu_task_types_view" parent="base.menu_project_config_project" sequence="2"/> <menuitem action="open_view_project_all" id="menu_projects" name="Projects" parent="menu_project_management" sequence="1"/> <act_window context="{'search_default_user_id': active_id, 'default_user_id': active_id}" id="act_res_users_2_project_project" name="User's projects" res_model="project.project" src_model="res.users" view_mode="tree,form" view_type="form"/> diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml index 199d3c0c422..829ec6c6971 100644 --- a/addons/project/security/project_security.xml +++ b/addons/project/security/project_security.xml @@ -14,7 +14,7 @@ <field name="users" eval="[(4, ref('base.user_root'))]"/> </record> - <record model="ir.ui.menu" id="menu_definitions"> + <record model="ir.ui.menu" id="base.menu_definitions"> <field name="groups_id" eval="[(6,0,[ref('group_project_manager')])]"/> </record> @@ -41,6 +41,13 @@ <field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field> </record> + <record model="ir.rule" id="project_public_members_rule"> + <field name="name">public Members</field> + <field name="model_id" ref="model_project_project"/> + <field name="global" eval="True"/> + <field name="domain_force">['|','|',('privacy_visibility','in',[False,'public']),('members','in',[user.id]),('followers','in',[user.id])]</field> + </record> + <record model="ir.rule" id="task_comp_rule"> <field name="name" >Task multi-company</field> <field name="model_id" ref="model_project_task"/> diff --git a/addons/project/wizard/__init__.py b/addons/project/wizard/__init__.py index f5324d2b6aa..7a9a734b2bd 100644 --- a/addons/project/wizard/__init__.py +++ b/addons/project/wizard/__init__.py @@ -19,7 +19,6 @@ # ############################################################################## -import mail_compose_message import project_task_delegate import project_task_reevaluate diff --git a/addons/project/wizard/mail_compose_message.py b/addons/project/wizard/mail_compose_message.py deleted file mode 100644 index 1609cc04c1c..00000000000 --- a/addons/project/wizard/mail_compose_message.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2010-Today OpenERP SA (<http://www.openerp.com>) -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/> -# -############################################################################## - -from osv import osv -from osv import fields -from tools.translate import _ - -class mail_compose_message(osv.osv_memory): - _inherit = 'mail.compose.message' - - def get_value(self, cr, uid, model, resource_id, context=None): - ''' - To get values of the resource_id for the model - @param model: Object - @param resource_id: id of a record for which values to be read - - @return: Returns a dictionary - ''' - result = super(mail_compose_message, self).get_value(cr, uid, model, resource_id, context=context) - if model == 'project.task' and resource_id: - task_pool = self.pool.get('project.task') - task_data = task_pool.browse(cr, uid, resource_id, context=context) - partner = task_data.partner_id or task_data.project_id.partner_id - if task_data.project_id.warn_manager and (not task_data.project_id.user_id or task_data.project_id.user_id and not task_data.project_id.user_id.user_email) : - raise osv.except_osv(_('Error'), _("Please specify the Project Manager or email address of Project Manager.")) - elif task_data.project_id.warn_customer and (not partner or (partner and not partner.email)): - raise osv.except_osv(_('Error'), _("Please specify the Customer or email address of Customer.")) - - result.update({'email_from': task_data.user_id and task_data.user_id.user_email or False}) - val = { - 'name': task_data.name, - 'user_id': task_data.user_id.name, - 'task_id': "%d/%d" % (task_data.project_id.id, task_data.id), - 'date_start': task_data.date_start, - 'date': task_data.date_end, - 'state': task_data.state - } - header = (task_data.project_id.warn_header or '') % val - footer = (task_data.project_id.warn_footer or '') % val - description = u'%s\n %s\n %s\n\n \n%s' % (header, task_data.description or '', footer, task_data.user_id and task_data.user_id.signature) - if partner : - result.update({'email_to': result.get('email_to',False) and result.get('email_to') + ',' + partner.email}) - result.update({ - 'body_text': description or False, - 'email_to': task_data.project_id.user_id and task_data.project_id.user_id.user_email or False, - 'subject': _("Task '%s' Closed") % task_data.name, - 'model': model, - 'res_id': resource_id, - }) - - return result - - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
