diff options
| author | Raphael Collet <rco@openerp.com> | 2011-12-12 10:52:37 +0100 |
|---|---|---|
| committer | Raphael Collet <rco@openerp.com> | 2011-12-12 10:52:37 +0100 |
| commit | dcfb5b0f460df97281119aa482e4fd74337f40bc (patch) | |
| tree | baf5e127721f350360a43a7c7c65f8891eb6d50f /addons/project | |
| parent | 6ced5c16c1b269f3820588156c0ba197c55e498e (diff) | |
| parent | d9bbf2f3909e5c8e14306d43afb635f2cf1f4af8 (diff) | |
merge from trunk
bzr revid: rco@openerp.com-20111212095237-x8wdo5m6v1z3yivy
Diffstat (limited to 'addons/project')
| -rw-r--r-- | addons/project/__openerp__.py | 4 | ||||
| -rw-r--r-- | addons/project/board_project_view.xml | 3 | ||||
| -rw-r--r-- | addons/project/project.py | 115 | ||||
| -rw-r--r-- | addons/project/project_demo.xml | 13 | ||||
| -rw-r--r-- | addons/project/project_view.xml | 16 | ||||
| -rw-r--r-- | addons/project/report/project_cumulative.xml | 81 | ||||
| -rw-r--r-- | addons/project/report/project_report_view.xml | 27 | ||||
| -rw-r--r-- | addons/project/res_partner_view.xml | 3 | ||||
| -rw-r--r-- | addons/project/security/ir.model.access.csv | 2 | ||||
| -rw-r--r-- | addons/project/static/src/img/icon.png | bin | 0 -> 4172 bytes |
10 files changed, 231 insertions, 33 deletions
diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py index 9132636b56f..e23ce653702 100644 --- a/addons/project/__openerp__.py +++ b/addons/project/__openerp__.py @@ -55,7 +55,8 @@ Dashboard for project members that includes: "res_partner_view.xml", "report/project_report_view.xml", "board_project_view.xml", - 'board_project_manager_view.xml' + 'board_project_manager_view.xml', + 'report/project_cumulative.xml' ], 'demo_xml': [ 'project_demo.xml', @@ -66,6 +67,7 @@ Dashboard for project members that includes: ], 'installable': True, 'active': False, + 'application': True, 'certificate': '0075116868317', } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/project/board_project_view.xml b/addons/project/board_project_view.xml index 50fa1b4f613..88424be85fa 100644 --- a/addons/project/board_project_view.xml +++ b/addons/project/board_project_view.xml @@ -83,11 +83,10 @@ <form string="My Board"> <board style="2-1"> <column> - <action name="%(my_open_tasks_action)d" string="My Open Tasks"/> + <action name="%(my_open_tasks_action)d" string="My Open Tasks" creatable="true"/> <action name="%(action_view_delegate_task_tree)d" string="My Delegated Tasks"/> </column> <column> - <action name="%(project.action_project_vs_planned_total_hours_graph)d" string="My Projects: Planned vs Total Hours"/> <action name="%(project.action_project_vs_remaining_hours_graph)d" string="My Remaining Hours by Project"/> </column> </board> diff --git a/addons/project/project.py b/addons/project/project.py index abebd2d35ff..5c234cf5e26 100644 --- a/addons/project/project.py +++ b/addons/project/project.py @@ -974,6 +974,24 @@ class task(osv.osv): def prev_type(self, cr, uid, ids, *args): return self._change_type(cr, uid, ids, False, *args) + def _store_history(self, cr, uid, ids, context=None): + for task in self.browse(cr, uid, ids, context=context): + self.pool.get('project.task.history').create(cr, uid, { + 'task_id': task.id, + 'remaining_hours': task.remaining_hours, + 'kanban_state': task.kanban_state, + 'type_id': task.type_id.id, + 'state': task.state, + 'user_id': task.user_id.id + + }, context=context) + return True + + def create(self, cr, uid, vals, context=None): + result = super(task, self).create(cr, uid, vals, context=context) + self._store_history(cr, uid, [result], context=context) + return result + # Overridden to reset the kanban_state to normal whenever # the stage (type_id) of the task changes. def write(self, cr, uid, ids, vals, context=None): @@ -985,8 +1003,12 @@ class task(osv.osv): for t in self.browse(cr, uid, ids, context=context): write_vals = vals_reset_kstate if t.type_id != new_stage else vals super(task,self).write(cr, uid, [t.id], write_vals, context=context) - return True - return super(task,self).write(cr, uid, ids, vals, context=context) + result = True + else: + result = super(task,self).write(cr, uid, ids, vals, context=context) + if ('type_id' in vals) or ('remaining_hours' in vals) or ('user_id' in vals) or ('state' in vals) or ('kanban_state' in vals): + self._store_history(cr, uid, ids, context=context) + return result def unlink(self, cr, uid, ids, context=None): if context == None: @@ -1084,4 +1106,91 @@ class account_analytic_account(osv.osv): account_analytic_account() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: +# +# Tasks History, used for cumulative flow charts (Lean/Agile) +# + +class project_task_history(osv.osv): + _name = 'project.task.history' + _description = 'History of Tasks' + _rec_name = 'task_id' + _log_access = False + def _get_date(self, cr, uid, ids, name, arg, context=None): + result = {} + for history in self.browse(cr, uid, ids, context=context): + if history.state in ('done','cancelled'): + result[history.id] = history.date + continue + cr.execute('''select + date + from + project_task_history + where + task_id=%s and + id>%s + order by id limit 1''', (history.task_id.id, history.id)) + res = cr.fetchone() + result[history.id] = res and res[0] or False + return result + + def _get_related_date(self, cr, uid, ids, context=None): + result = [] + for history in self.browse(cr, uid, ids, context=context): + cr.execute('''select + id + from + project_task_history + where + task_id=%s and + id<%s + order by id desc limit 1''', (history.task_id.id, history.id)) + res = cr.fetchone() + if res: + result.append(res[0]) + return result + + _columns = { + 'task_id': fields.many2one('project.task', 'Task', ondelete='cascade', required=True, select=True), + 'type_id': fields.many2one('project.task.type', 'Stage'), + 'state': fields.selection([('draft', 'New'),('open', 'In Progress'),('pending', 'Pending'), ('done', 'Done'), ('cancelled', 'Cancelled')], 'State'), + 'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready To Pull')], 'Kanban State', required=False), + 'date': fields.date('Date', select=True), + 'end_date': fields.function(_get_date, string='End Date', type="date", store={ + 'project.task.history': (_get_related_date, None, 20) + }), + 'remaining_hours': fields.float('Remaining Hours', digits=(16,2)), + 'user_id': fields.many2one('res.users', 'Responsible'), + } + _defaults = { + 'date': lambda s,c,u,ctx: time.strftime('%Y-%m-%d') + } +project_task_history() + +class project_task_history_cumulative(osv.osv): + _name = 'project.task.history.cumulative' + _table = 'project_task_history_cumulative' + _inherit = 'project.task.history' + _auto = False + _columns = { + 'end_date': fields.date('End Date'), + 'project_id': fields.related('task_id', 'project_id', string='Project', type='many2one', relation='project.project') + } + def init(self, cr): + cr.execute(""" CREATE OR REPLACE VIEW project_task_history_cumulative AS ( + SELECT + history.date::varchar||'-'||history.history_id::varchar as id, + history.date as end_date, + * + FROM ( + SELECT + id as history_id, + date+generate_series(0, CAST((coalesce(end_date,DATE 'tomorrow')::date - date)AS integer)-1) as date, + task_id, type_id, user_id, kanban_state, state, + remaining_hours + FROM + project_task_history + ) as history + ) + """) +project_task_history_cumulative() + diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index 7592d24a145..42da9fdefff 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -77,6 +77,7 @@ <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Prepare Requirements Document</field> <field name="type_id" ref="project_tt_specification"/> + <field name="color">3</field> </record> <record id="project_task_2" model="project.task"> @@ -94,6 +95,7 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Design Use Cases</field> + <field name="date_deadline" eval="time.strftime('%Y-%m-24')"/> <field name="type_id" ref="project_tt_specification"/> </record> @@ -103,6 +105,9 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Budget Planning</field> + <field name="description">Use the account_budget module</field> + <field name="date_deadline" eval="time.strftime('%Y-%m-19')"/> + <field name="color">3</field> <field name="type_id" ref="project_tt_specification"/> </record> @@ -112,6 +117,9 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Quality Planning</field> + <field name="kanban_state">done</field> + <field name="priority">0</field> + <field name="date_deadline" eval="time.strftime('%Y-%m-%d')"/> <field name="type_id" ref="project_tt_specification"/> </record> @@ -139,6 +147,7 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Dataflow Design</field> + <field name="priority">0</field> <field name="type_id" ref="project_tt_specification"/> </record> @@ -157,6 +166,7 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Develop Module in Sale Management</field> + <field name="kanban_state">blocked</field> <field name="type_id" ref="project_tt_development"/> </record> @@ -220,6 +230,7 @@ <field name="priority">2</field> <field name="project_id" ref="project.project_integrate_openerp"/> <field name="name">Performance Tuning</field> + <field name="description">Test on Runbot</field> <field name="type_id" ref="project_tt_specification"/> </record> <function model="project.task" name="do_open" eval="[ref('project_task_16')]"/> @@ -329,6 +340,7 @@ <field name="priority">0</field> <field name="project_id" ref="project_project_21"/> <field name="name">Customer analysis + Architecture</field> + <field name="color">3</field> </record> <record id="project_task_186" model="project.task"> <field name="sequence">15</field> @@ -338,6 +350,7 @@ <field name="user_id" eval="False"/> <field name="project_id" ref="project_project_21"/> <field name="name">Internal testing + Software Install</field> + <field name="color">4</field> </record> <record id="project_task_188" model="project.task"> <field name="sequence">17</field> diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index a01f92a8e24..c8fe92f4194 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -313,7 +313,7 @@ </field> </record> - + <!-- Project Task Kanban View --> <record model="ir.ui.view" id="view_task_kanban"> <field name="name">project.task.kanban</field> @@ -526,13 +526,23 @@ <field name="name">Tasks</field> <field name="res_model">project.task</field> <field name="view_type">form</field> - <field name="view_mode">tree,form,calendar,gantt,graph,kanban</field> + <field name="view_mode">kanban,tree,form,calendar,gantt,graph</field> <field eval="False" name="filter"/> - <field name="view_id" ref="view_task_tree2"/> + <field name="view_id" eval="False"/> <field name="context">{"search_default_draft": 1, "search_default_open":1, "search_default_project_id": project_id}</field> <field name="search_view_id" ref="view_task_search_form"/> <field name="help">A task represents a work that has to be done. Each user works in his own list of tasks where he can record his task work in hours. He can work and close the task itself or delegate it to another user. If you delegate a task to another user, you get a new task in pending state, which will be reopened when you have to review the work achieved. If you install the project_timesheet module, task work can be invoiced based on the project configuration. With the project_mrp module, sales orders can create tasks automatically when they are confirmed.</field> </record> + <record id="open_view_task_list_kanban" model="ir.actions.act_window.view"> + <field name="sequence" eval="0"/> + <field name="view_mode">kanban</field> + <field name="act_window_id" ref="action_view_task"/> + </record> + <record id="open_view_task_list_tree" model="ir.actions.act_window.view"> + <field name="sequence" eval="1"/> + <field name="view_mode">tree</field> + <field name="act_window_id" ref="action_view_task"/> + </record> <menuitem action="action_view_task" id="menu_action_view_task" parent="project.menu_project_management" sequence="3"/> diff --git a/addons/project/report/project_cumulative.xml b/addons/project/report/project_cumulative.xml new file mode 100644 index 00000000000..aff90aea94e --- /dev/null +++ b/addons/project/report/project_cumulative.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <record id="view_task_history_tree" model="ir.ui.view"> + <field name="name">project.task.history.cumulative.tree</field> + <field name="model">project.task.history.cumulative</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Tasks's Cumulative Flow"> + <field name="date"/> + <field name="project_id"/> + <field name="task_id"/> + <field name="type_id"/> + <field name="user_id"/> + <field name="remaining_hours"/> + <field name="kanban_state"/> + <field name="state"/> + </tree> + </field> + </record> + <record id="view_task_history_graph" model="ir.ui.view"> + <field name="name">project.task.history.cumulative.graph</field> + <field name="model">project.task.history.cumulative</field> + <field name="type">graph</field> + <field name="arch" type="xml"> + <graph string="Project Tasks" type="bar"> + <field name="date"/> + <field name="remaining_hours" operator="+"/> + <field name="type_id" group="True"/> + </graph> + </field> + </record> + + <record id="view_task_history_search" model="ir.ui.view"> + <field name="name">project.task.history.cumulative.search</field> + <field name="model">project.task.history.cumulative</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Task's Cumulative Flow"> + <group> + <filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="In Progress Tasks" icon="terp-camera_test"/> + <filter string="Pending" domain="[('state','=','pending')]" context="{'show_delegated':False}" help="Pending Tasks" icon="terp-gtk-media-pause"/> + <separator orientation="vertical"/> + <filter name="kanban_blocked" string="Blocked" domain="[('kanban_state','=','blocked')]" icon="terp-gtk-media-pause"/> + <filter name="kanban_ready" string="Ready" domain="[('kanban_state','=','done')]" icon="terp-camera_test"/> + <separator orientation="vertical"/> + <filter string="Month" icon="terp-go-month" name="this_month" + domain="[('date','<=',(datetime.date.today()+relativedelta(day=31)).strftime('%%Y-%%m-%%d')),('date','>=',(datetime.date.today()-relativedelta(day=1)).strftime('%%Y-%%m-%%d'))]"/> + <filter icon="terp-go-month" string="Month-1" name="month1" + domain="[('date','<=', (datetime.date.today() - relativedelta(day=31, months=1)).strftime('%%Y-%%m-%%d')),('date','>=',(datetime.date.today() - relativedelta(day=1,months=1)).strftime('%%Y-%%m-%%d'))]"/> + <filter icon="terp-go-month" string="Month-2" name="month2" + domain="[('date','<=', (datetime.date.today() - relativedelta(day=31, months=2)).strftime('%%Y-%%m-%%d')),('date','>=',(datetime.date.today() - relativedelta(day=1,months=2)).strftime('%%Y-%%m-%%d'))]"/> + <separator orientation="vertical"/> + <field name="project_id"> + <filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-personal"/> + </field> + <field name="user_id"> + <filter domain="[('user_id','=',uid)]" help="My Tasks" icon="terp-personal" /> + <filter domain="[('user_id','=',False)]" help="Unassigned Tasks" icon="terp-personal-" /> + </field> + </group> + </search> + </field> + </record> + + <record id="action_view_task_history_cumulative" model="ir.actions.act_window"> + <field name="name">Cumulative Flow</field> + <field name="res_model">project.task.history.cumulative</field> + <field name="view_type">form</field> + <field name="view_mode">graph,tree</field> + <field eval="False" name="filter"/> + <field name="context">{"search_default_open":1, "search_default_this_month": 1}</field> + </record> + <menuitem action="action_view_task_history_cumulative" + id="menu_action_view_task_history_cumulative" + parent="project_report_task" /> + + + </data> +</openerp> diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml index cfa667c7590..6348c63fcad 100644 --- a/addons/project/report/project_report_view.xml +++ b/addons/project/report/project_report_view.xml @@ -5,6 +5,8 @@ <menuitem id="base.menu_project_report" name="Reporting" groups="project.group_project_manager" parent="base.menu_main_pm" sequence="50"/> + <menuitem id="project_report_task" name="Tasks" + parent="base.menu_project_report"/> <record id="view_task_project_user_tree" model="ir.ui.view"> <field name="name">report.project.task.user.tree</field> @@ -152,7 +154,7 @@ <field name="help">This report allows you to analyse the performance of your projects and users. You can analyse the quantities of tasks, the hours spent compared to the planned hours, the average number of days to open or close a task, etc.</field> </record> - <menuitem action="action_project_task_user_tree" id="menu_project_task_user_tree" parent="base.menu_project_report"/> + <menuitem action="action_project_task_user_tree" id="menu_project_task_user_tree" parent="project_report_task"/> <!-- Views and action for project dashboard --> <record id="view_project_vs_remaining_hours_tree" model="ir.ui.view"> @@ -267,28 +269,5 @@ </field> </record> - <record id="action_project_vs_planned_total_hours_graph" model="ir.actions.act_window"> - - <field name="name">Projects: Planned Vs Total hours</field> - <field name="res_model">project.vs.hours</field> - <field name="view_type">form</field> - <field name="view_mode">graph,tree</field> - <field name="context">{}</field> - <field name="domain">[('user_id','=',uid),('state','=','open')]</field> - <field name="view_id" ref="view_project_vs_planned_total_hours_graph"/> - </record> - - <record id="open_view_project_vs_planned_total_hours_tree" model="ir.actions.act_window.view"> - <field eval="2" name="sequence"/> - <field name="view_mode">tree</field> - <field name="view_id" ref="view_project_vs_planned_total_hours_tree"/> - <field name="act_window_id" ref="action_project_vs_planned_total_hours_graph"/> - </record> - <record id="open_view_project_vs_planned_total_hours_graph" model="ir.actions.act_window.view"> - <field eval="1" name="sequence"/> - <field name="view_mode">graph</field> - <field name="view_id" ref="view_project_vs_planned_total_hours_graph"/> - <field name="act_window_id" ref="action_project_vs_planned_total_hours_graph"/> - </record> </data> </openerp> diff --git a/addons/project/res_partner_view.xml b/addons/project/res_partner_view.xml index dc0226ba50e..31c88377ddb 100644 --- a/addons/project/res_partner_view.xml +++ b/addons/project/res_partner_view.xml @@ -25,6 +25,9 @@ <tree string="Tasks" editable="bottom"> <field name="name"/> <field name="user_id"/> + <field name="date_deadline"/> + <button name="do_open" states="pending,draft,done,cancelled" string="Start Task" type="object" icon="gtk-media-play" help="For changing to open state" invisible="context.get('set_visible',False)"/> + <button name="action_close" states="draft,pending,open" string="Done" type="object" icon="terp-dialog-close" help="For changing to done state"/> </tree> </field> </page> diff --git a/addons/project/security/ir.model.access.csv b/addons/project/security/ir.model.access.csv index 659948bc4d0..955a6ef0c97 100644 --- a/addons/project/security/ir.model.access.csv +++ b/addons/project/security/ir.model.access.csv @@ -22,3 +22,5 @@ "access_project_task_sale_user","project.task salesman","model_project_task","base.group_sale_salesman",1,0,0,0 "access_project_project_sale_user","project.project salesman","model_project_project","base.group_sale_salesman",1,0,0,0 "access_account_analytic_line_project","account.analytic.line project","analytic.model_account_analytic_line","project.group_project_manager",1,1,1,1 +"access_project_task_history","project.task.history project","project.model_project_task_history","project.group_project_user",1,1,1,0 +"access_project_task_history_cumulative","project.task.history project","project.model_project_task_history_cumulative","project.group_project_manager",1,0,0,0 diff --git a/addons/project/static/src/img/icon.png b/addons/project/static/src/img/icon.png Binary files differnew file mode 100644 index 00000000000..20ba49f07c8 --- /dev/null +++ b/addons/project/static/src/img/icon.png |
