[NEW] Project Cumulative Flow and Task History for Kanban

bzr revid: fp@tinyerp.com-20111203140427-jf57fyvvo60g31dl
This commit is contained in:
Fabien Pinckaers 2011-12-03 15:04:27 +01:00
parent 21b068b38d
commit c1810c3483
5 changed files with 200 additions and 5 deletions

View File

@ -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',

View File

@ -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()

View File

@ -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','&lt;=',(datetime.date.today()+relativedelta(day=31)).strftime('%%Y-%%m-%%d')),('date','&gt;=',(datetime.date.today()-relativedelta(day=1)).strftime('%%Y-%%m-%%d'))]"/>
<filter icon="terp-go-month" string="Month-1" name="month1"
domain="[('date','&lt;=', (datetime.date.today() - relativedelta(day=31, months=1)).strftime('%%Y-%%m-%%d')),('date','&gt;=',(datetime.date.today() - relativedelta(day=1,months=1)).strftime('%%Y-%%m-%%d'))]"/>
<filter icon="terp-go-month" string="Month-2" name="month2"
domain="[('date','&lt;=', (datetime.date.today() - relativedelta(day=31, months=2)).strftime('%%Y-%%m-%%d')),('date','&gt;=',(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>

View File

@ -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">

View File

@ -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

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
22 access_project_task_sale_user project.task salesman model_project_task base.group_sale_salesman 1 0 0 0
23 access_project_project_sale_user project.project salesman model_project_project base.group_sale_salesman 1 0 0 0
24 access_account_analytic_line_project account.analytic.line project analytic.model_account_analytic_line project.group_project_manager 1 1 1 1
25 access_project_task_history project.task.history project project.model_project_task_history project.group_project_user 1 1 1 0
26 access_project_task_history_cumulative project.task.history project project.model_project_task_history_cumulative project.group_project_manager 1 0 0 0