2010-01-29 07:51:40 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2010-03-11 07:10:06 +00:00
import datetime
from resource . faces import *
from new import classobj
2010-01-29 07:51:40 +00:00
from tools . translate import _
2010-04-06 10:18:27 +00:00
from osv import fields , osv
2010-03-09 11:52:35 +00:00
import working_calendar as wkcal
2010-01-29 07:51:40 +00:00
2010-04-06 10:18:27 +00:00
class project_compute_phases ( osv . osv_memory ) :
2010-01-29 07:51:40 +00:00
2010-04-06 10:18:27 +00:00
_name = ' project.compute.phases '
_description = ' Project Compute Phases '
_columns = {
' project_id ' : fields . many2one ( ' project.project ' , ' Project ' , help = ' If you do not specify project then it will take All projects with state=draft, open, pending ' )
}
2010-01-29 07:51:40 +00:00
2010-03-09 11:52:35 +00:00
def _phase_schedule ( self , cr , uid , phase , start_date , calendar_id = False , context = { } ) :
""" Schedule phase with the start date till all the next phases are completed.
Arguements : start_dsate - - start date for the phase
calendar_id - - working calendar of the project
"""
2010-04-06 10:18:27 +00:00
phase_obj = self . pool . get ( ' project.phase ' )
resource_obj = self . pool . get ( ' resource.resource ' )
uom_obj = self . pool . get ( ' product.uom ' )
2010-03-09 11:52:35 +00:00
phase_resource_obj = False
2010-02-26 11:18:14 +00:00
if phase :
2010-03-09 11:52:35 +00:00
leaves = [ ]
time_efficiency = 1.0
resource_id = resource_obj . search ( cr , uid , [ ( ' user_id ' , ' = ' , phase . responsible_id . id ) ] )
2010-03-11 07:10:06 +00:00
2010-02-26 11:18:14 +00:00
if resource_id :
2010-03-09 11:52:35 +00:00
# Create a new resource object with
# all the attributes of the Resource Class
resource = resource_obj . browse ( cr , uid , resource_id , context = context ) [ 0 ]
time_efficiency = resource . time_efficiency
2010-03-11 07:10:06 +00:00
leaves = wkcal . compute_leaves ( cr , uid , calendar_id , resource . id , resource . calendar_id . id )
2010-03-22 11:26:21 +00:00
phase_resource_obj = classobj ( ( phase . responsible_id . name . encode ( ' utf8 ' ) ) , ( Resource , ) ,
2010-03-09 11:52:35 +00:00
{ ' __doc__ ' : phase . responsible_id . name ,
' __name__ ' : phase . responsible_id . name ,
' vacation ' : tuple ( leaves ) ,
' efficiency ' : time_efficiency
} )
default_uom_id = uom_obj . search ( cr , uid , [ ( ' name ' , ' = ' , ' Hour ' ) ] ) [ 0 ]
avg_hours = uom_obj . _compute_qty ( cr , uid , phase . product_uom . id , phase . duration , default_uom_id )
2010-02-26 11:18:14 +00:00
duration = str ( avg_hours ) + ' H '
2010-03-09 11:52:35 +00:00
# Create a new project for each phase
2010-02-26 11:18:14 +00:00
def Project ( ) :
start = start_date
minimum_time_unit = 1
2010-03-09 11:52:35 +00:00
resource = phase_resource_obj
# If project has working calendar then that
# else the default one would be considered
2010-02-26 11:18:14 +00:00
if calendar_id :
2010-03-17 07:15:53 +00:00
working_days = wkcal . compute_working_calendar ( cr , uid , calendar_id , context = context )
2010-03-09 11:52:35 +00:00
vacation = tuple ( wkcal . compute_leaves ( cr , uid , calendar_id ) )
2010-02-26 11:18:14 +00:00
def phase ( ) :
effort = duration
project = BalancedProject ( Project )
s_date = project . phase . start . to_datetime ( )
e_date = project . phase . end . to_datetime ( )
2010-03-09 11:52:35 +00:00
# Recalculate date_start and date_end
# according to constraints on date start and date end on phase
2010-02-26 11:18:14 +00:00
if phase . constraint_date_start and str ( s_date ) < phase . constraint_date_start :
2010-03-02 13:27:02 +00:00
start_date = datetime . datetime . strptime ( phase . constraint_date_start , ' % Y- % m- %d % H: % M: % S ' )
2010-02-26 11:18:14 +00:00
else :
start_date = s_date
if phase . constraint_date_end and str ( e_date ) > phase . constraint_date_end :
2010-03-02 13:27:02 +00:00
end_date = datetime . datetime . strptime ( phase . constraint_date_end , ' % Y- % m- %d % H: % M: % S ' )
2010-02-26 11:18:14 +00:00
date_start = phase . constraint_date_end [ : - 3 ]
else :
end_date = e_date
date_start = end_date
2010-03-09 11:52:35 +00:00
# Write the calculated dates back
2010-03-11 07:10:06 +00:00
ctx = context . copy ( )
ctx . update ( { ' scheduler ' : True } )
2010-03-09 11:52:35 +00:00
phase_obj . write ( cr , uid , [ phase . id ] , { ' date_start ' : start_date . strftime ( ' % Y- % m- %d % H: % M: % S ' ) ,
' date_end ' : end_date . strftime ( ' % Y- % m- %d % H: % M: % S ' ) } ,
2010-03-11 07:10:06 +00:00
context = ctx )
2010-03-09 11:52:35 +00:00
# Recursive call till all the next phases scheduled
2010-02-26 11:18:14 +00:00
for phase in phase . next_phase_ids :
if phase . state in [ ' draft ' , ' open ' , ' pending ' ] :
2010-03-16 09:41:40 +00:00
id_cal = phase . project_id . resource_calendar_id and phase . project_id . resource_calendar_id . id or False
self . _phase_schedule ( cr , uid , phase , date_start , id_cal , context = context )
2010-02-26 11:18:14 +00:00
else :
continue
2010-02-10 06:14:22 +00:00
2010-04-06 10:18:27 +00:00
def compute_date ( self , cr , uid , ids , context = None ) :
2010-03-09 11:52:35 +00:00
"""
Compute the phases for scheduling .
"""
2010-04-06 10:18:27 +00:00
if context is None :
context = { }
project_obj = self . pool . get ( ' project.project ' )
phase_obj = self . pool . get ( ' project.phase ' )
data = self . read ( cr , uid , ids , [ ] , context = context ) [ 0 ]
if data [ ' project_id ' ] : # If project mentioned find its phases
project_id = project_obj . browse ( cr , uid , data [ ' project_id ' ] , context = context )
2010-03-09 11:52:35 +00:00
phase_ids = phase_obj . search ( cr , uid , [ ( ' project_id ' , ' = ' , project_id . id ) ,
( ' state ' , ' in ' , [ ' draft ' , ' open ' , ' pending ' ] ) ,
( ' previous_phase_ids ' , ' = ' , False )
] )
else : # Else take all the draft,open,pending states phases
phase_ids = phase_obj . search ( cr , uid , [ ( ' state ' , ' in ' , [ ' draft ' , ' open ' , ' pending ' ] ) ,
( ' previous_phase_ids ' , ' = ' , False )
2010-03-11 07:10:06 +00:00
] , context = context )
2010-02-26 11:18:14 +00:00
phase_ids . sort ( )
2010-03-16 09:30:14 +00:00
phases = phase_obj . browse ( cr , uid , phase_ids , context = context )
for phase in phases :
2010-02-26 12:26:17 +00:00
start_date = phase . project_id . date_start
if not phase . project_id . date_start :
start_date = datetime . datetime . now ( ) . strftime ( " % Y- % m- %d " )
2010-03-02 13:27:02 +00:00
start_dt = datetime . datetime . strftime ( ( datetime . datetime . strptime ( start_date , " % Y- % m- %d " ) ) , " % Y- % m- %d % H: % M " )
2010-03-16 09:41:40 +00:00
calendar_id = phase . project_id . resource_calendar_id and phase . project_id . resource_calendar_id . id or False
self . _phase_schedule ( cr , uid , phase , start_dt , calendar_id , context = context )
2010-04-06 10:18:27 +00:00
return self . _open_phases_list ( cr , uid , data , context = context )
2010-02-26 11:18:14 +00:00
2010-04-06 10:18:27 +00:00
def _open_phases_list ( self , cr , uid , data , context = None ) :
2010-03-09 11:52:35 +00:00
"""
Return the scheduled phases list .
"""
2010-04-06 10:18:27 +00:00
if context is None :
context = { }
mod_obj = self . pool . get ( ' ir.model.data ' )
act_obj = self . pool . get ( ' ir.actions.act_window ' )
2010-03-04 09:41:44 +00:00
result = mod_obj . _get_id ( cr , uid , ' project_long_term ' , ' act_project_phase ' )
id = mod_obj . read ( cr , uid , [ result ] , [ ' res_id ' ] ) [ 0 ] [ ' res_id ' ]
result = act_obj . read ( cr , uid , [ id ] , context = context ) [ 0 ]
result [ ' domain ' ] = [ ( ' state ' , ' not in ' , [ ' cancelled ' , ' done ' ] ) ]
2010-04-06 10:18:27 +00:00
if data [ ' project_id ' ] :
result [ ' domain ' ] = [ ( ' project_id ' , ' = ' , data [ ' project_id ' ] ) ,
2010-03-09 11:52:35 +00:00
( ' state ' , ' not in ' , [ ' cancelled ' , ' done ' ] ) ]
2010-03-04 09:41:44 +00:00
return result
2010-04-06 10:18:27 +00:00
project_compute_phases ( )
2010-01-29 07:51:40 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: