2009-10-13 05:58:37 +00:00
# -*- coding: utf-8 -*-
2007-03-05 18:22:32 +00:00
##############################################################################
2009-12-24 07:05:23 +00:00
#
2009-10-14 11:15:34 +00:00
# OpenERP, Open Source Management Solution
2010-01-12 09:18:39 +00:00
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
2007-03-05 18:22:32 +00:00
#
2008-11-03 19:18:56 +00:00
# This program is free software: you can redistribute it and/or modify
2009-10-14 11:15:34 +00:00
# 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.
2007-03-05 18:22:32 +00:00
#
2008-11-03 19:18:56 +00:00
# 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
2009-10-14 11:15:34 +00:00
# GNU Affero General Public License for more details.
2007-03-05 18:22:32 +00:00
#
2009-10-14 11:15:34 +00:00
# You should have received a copy of the GNU Affero General Public License
2009-12-24 07:05:23 +00:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
2007-03-05 18:22:32 +00:00
#
##############################################################################
import time
2014-04-24 14:28:29 +00:00
from datetime import datetime
2010-10-15 14:01:53 +00:00
from dateutil . relativedelta import relativedelta
2013-07-23 18:43:41 +00:00
from pytz import timezone
import pytz
2010-11-02 11:11:12 +00:00
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
2014-04-28 14:20:17 +00:00
from openerp . tools import DEFAULT_SERVER_DATE_FORMAT , DEFAULT_SERVER_DATETIME_FORMAT
2012-12-06 14:56:32 +00:00
from openerp . tools . translate import _
2007-03-05 18:22:32 +00:00
class hr_timesheet_sheet ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " hr_timesheet_sheet.sheet "
2012-09-24 10:38:12 +00:00
_inherit = " mail.thread "
2008-07-22 15:11:28 +00:00
_table = ' hr_timesheet_sheet_sheet '
_order = " id desc "
2010-09-01 12:04:41 +00:00
_description = " Timesheet "
2008-07-22 15:11:28 +00:00
2010-05-19 13:07:03 +00:00
def _total ( self , cr , uid , ids , name , args , context = None ) :
2012-01-06 09:25:20 +00:00
""" Compute the attendances, analytic lines timesheets and differences between them
for all the days of a timesheet and the current day
2011-11-14 12:20:42 +00:00
"""
2009-09-24 10:46:21 +00:00
res = { }
2012-10-26 07:57:15 +00:00
for sheet in self . browse ( cr , uid , ids , context = context or { } ) :
res . setdefault ( sheet . id , {
' total_attendance ' : 0.0 ,
' total_timesheet ' : 0.0 ,
' total_difference ' : 0.0 ,
} )
for period in sheet . period_ids :
res [ sheet . id ] [ ' total_attendance ' ] + = period . total_attendance
res [ sheet . id ] [ ' total_timesheet ' ] + = period . total_timesheet
res [ sheet . id ] [ ' total_difference ' ] + = period . total_attendance - period . total_timesheet
2009-09-24 10:46:21 +00:00
return res
2008-07-22 15:11:28 +00:00
2010-08-11 15:58:57 +00:00
def check_employee_attendance_state ( self , cr , uid , sheet_id , context = None ) :
ids_signin = self . pool . get ( ' hr.attendance ' ) . search ( cr , uid , [ ( ' sheet_id ' , ' = ' , sheet_id ) , ( ' action ' , ' = ' , ' sign_in ' ) ] )
ids_signout = self . pool . get ( ' hr.attendance ' ) . search ( cr , uid , [ ( ' sheet_id ' , ' = ' , sheet_id ) , ( ' action ' , ' = ' , ' sign_out ' ) ] )
if len ( ids_signin ) != len ( ids_signout ) :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( ( ' Warning! ' ) , _ ( ' The timesheet cannot be validated as it does not contain an equal number of sign ins and sign outs. ' ) )
2010-08-11 15:58:57 +00:00
return True
2008-07-22 15:11:28 +00:00
2009-01-15 16:57:02 +00:00
def copy ( self , cr , uid , ids , * args , * * argv ) :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' You cannot duplicate a timesheet. ' ) )
2009-01-15 16:57:02 +00:00
2014-04-23 11:25:54 +00:00
def create ( self , cr , uid , vals , context = None ) :
2010-10-06 16:39:01 +00:00
if ' employee_id ' in vals :
2014-04-23 11:25:54 +00:00
if not self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . user_id :
2014-04-22 12:30:22 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must link him/her to a user. ' ) )
2014-04-23 11:25:54 +00:00
if not self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . product_id :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must link the employee to a product, like \' Consultant \' . ' ) )
2014-04-23 11:25:54 +00:00
if not self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . journal_id :
2012-10-11 12:20:36 +00:00
raise osv . except_osv ( _ ( ' Configuration Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \' Timesheet Journal \' . ' ) )
2013-06-04 07:01:31 +00:00
if vals . get ( ' attendances_ids ' ) :
2014-04-23 11:25:54 +00:00
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
vals [ ' attendances_ids ' ] = self . sort_attendances ( cr , uid , vals [ ' attendances_ids ' ] , context = context )
return super ( hr_timesheet_sheet , self ) . create ( cr , uid , vals , context = context )
2010-10-06 16:39:01 +00:00
2014-04-23 11:25:54 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2010-10-06 16:39:01 +00:00
if ' employee_id ' in vals :
2013-06-10 09:29:48 +00:00
new_user_id = self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . user_id . id or False
2010-10-06 16:39:01 +00:00
if not new_user_id :
2014-04-22 12:30:22 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must link him/her to a user. ' ) )
2013-06-10 09:29:48 +00:00
if not self . _sheet_date ( cr , uid , ids , forced_user_id = new_user_id , context = context ) :
2012-10-29 15:08:09 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' You cannot have 2 timesheets that overlap! \n You should use the menu \' My Timesheet \' to avoid this problem. ' ) )
2013-06-10 09:29:48 +00:00
if not self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . product_id :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must link the employee to a product. ' ) )
2013-06-10 09:29:48 +00:00
if not self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , vals [ ' employee_id ' ] , context = context ) . journal_id :
2012-10-22 07:02:15 +00:00
raise osv . except_osv ( _ ( ' Configuration Error! ' ) , _ ( ' In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \' Timesheet Journal \' . ' ) )
2014-04-23 11:25:54 +00:00
if vals . get ( ' attendances_ids ' ) :
# If attendances, we sort them by date asc before writing them, to satisfy the alternance constraint
# In addition to the date order, deleting attendances are done before inserting attendances
vals [ ' attendances_ids ' ] = self . sort_attendances ( cr , uid , vals [ ' attendances_ids ' ] , context = context )
res = super ( hr_timesheet_sheet , self ) . write ( cr , uid , ids , vals , context = context )
if vals . get ( ' attendances_ids ' ) :
for timesheet in self . browse ( cr , uid , ids ) :
if not self . pool [ ' hr.attendance ' ] . _altern_si_so ( cr , uid , [ att . id for att in timesheet . attendances_ids ] ) :
raise osv . except_osv ( _ ( ' Warning ! ' ) , _ ( ' Error ! Sign in (resp. Sign out) must follow Sign out (resp. Sign in) ' ) )
return res
def sort_attendances ( self , cr , uid , attendance_tuples , context = None ) :
date_attendances = [ ]
for att_tuple in attendance_tuples :
if att_tuple [ 0 ] in [ 0 , 1 , 4 ] :
if att_tuple [ 0 ] in [ 0 , 1 ] :
2014-09-10 07:45:51 +00:00
if att_tuple [ 2 ] and att_tuple [ 2 ] . has_key ( ' name ' ) :
name = att_tuple [ 2 ] [ ' name ' ]
else :
name = self . pool [ ' hr.attendance ' ] . browse ( cr , uid , att_tuple [ 1 ] ) . name
2014-04-23 11:25:54 +00:00
else :
name = self . pool [ ' hr.attendance ' ] . browse ( cr , uid , att_tuple [ 1 ] ) . name
date_attendances . append ( ( 1 , name , att_tuple ) )
elif att_tuple [ 0 ] in [ 2 , 3 ] :
date_attendances . append ( ( 0 , self . pool [ ' hr.attendance ' ] . browse ( cr , uid , att_tuple [ 1 ] ) . name , att_tuple ) )
else :
date_attendances . append ( ( 0 , False , att_tuple ) )
date_attendances . sort ( )
return [ att [ 2 ] for att in date_attendances ]
2010-10-06 16:39:01 +00:00
2010-05-19 13:07:03 +00:00
def button_confirm ( self , cr , uid , ids , context = None ) :
for sheet in self . browse ( cr , uid , ids , context = context ) :
2012-09-24 10:38:12 +00:00
if sheet . employee_id and sheet . employee_id . parent_id and sheet . employee_id . parent_id . user_id :
2012-09-25 17:33:20 +00:00
self . message_subscribe_users ( cr , uid , [ sheet . id ] , user_ids = [ sheet . employee_id . parent_id . user_id . id ] , context = context )
2011-11-14 12:20:42 +00:00
self . check_employee_attendance_state ( cr , uid , sheet . id , context = context )
2008-07-22 15:11:28 +00:00
di = sheet . user_id . company_id . timesheet_max_difference
if ( abs ( sheet . total_difference ) < di ) or not di :
2014-07-06 14:44:26 +00:00
sheet . signal_workflow ( ' confirm ' )
2008-07-22 15:11:28 +00:00
else :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' Please verify that the total difference of the sheet is lower than %.2f . ' ) % ( di , ) )
2008-07-22 15:11:28 +00:00
return True
2012-05-11 07:33:20 +00:00
def attendance_action_change ( self , cr , uid , ids , context = None ) :
hr_employee = self . pool . get ( ' hr.employee ' )
employee_ids = [ ]
for sheet in self . browse ( cr , uid , ids , context = context ) :
if sheet . employee_id . id not in employee_ids : employee_ids . append ( sheet . employee_id . id )
return hr_employee . attendance_action_change ( cr , uid , employee_ids , context = context )
2014-03-26 12:00:56 +00:00
def _count_all ( self , cr , uid , ids , field_name , arg , context = None ) :
2014-05-07 14:17:25 +00:00
Timesheet = self . pool [ ' hr.analytic.timesheet ' ]
Attendance = self . pool [ ' hr.attendance ' ]
return {
sheet_id : {
' timesheet_activity_count ' : Timesheet . search_count ( cr , uid , [ ( ' sheet_id ' , ' = ' , sheet_id ) ] , context = context ) ,
2014-06-02 16:37:52 +00:00
' attendance_count ' : Attendance . search_count ( cr , uid , [ ( ' sheet_id ' , ' = ' , sheet_id ) ] , context = context )
2014-05-07 14:17:25 +00:00
}
for sheet_id in ids
}
2008-07-22 15:11:28 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Note ' , select = 1 ,
2009-01-20 18:51:08 +00:00
states = { ' confirm ' : [ ( ' readonly ' , True ) ] , ' done ' : [ ( ' readonly ' , True ) ] } ) ,
2010-10-06 16:39:01 +00:00
' employee_id ' : fields . many2one ( ' hr.employee ' , ' Employee ' , required = True ) ,
' user_id ' : fields . related ( ' employee_id ' , ' user_id ' , type = " many2one " , relation = " res.users " , store = True , string = " User " , required = False , readonly = True ) , #fields.many2one('res.users', 'User', required=True, select=1, states={'confirm':[('readonly', True)], 'done':[('readonly', True)]}),
2008-07-22 15:11:28 +00:00
' date_from ' : fields . date ( ' Date from ' , required = True , select = 1 , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
' date_to ' : fields . date ( ' Date to ' , required = True , select = 1 , readonly = True , states = { ' new ' : [ ( ' readonly ' , False ) ] } ) ,
2012-10-01 15:46:05 +00:00
' timesheet_ids ' : fields . one2many ( ' hr.analytic.timesheet ' , ' sheet_id ' ,
' Timesheet lines ' ,
2008-07-22 15:11:28 +00:00
readonly = True , states = {
' draft ' : [ ( ' readonly ' , False ) ] ,
' new ' : [ ( ' readonly ' , False ) ] }
) ,
2012-10-01 15:46:05 +00:00
' attendances_ids ' : fields . one2many ( ' hr.attendance ' , ' sheet_id ' , ' Attendances ' ) ,
2009-12-24 07:05:23 +00:00
' state ' : fields . selection ( [
( ' new ' , ' New ' ) ,
2011-09-10 12:43:55 +00:00
( ' draft ' , ' Open ' ) ,
( ' confirm ' , ' Waiting Approval ' ) ,
2012-05-04 11:57:48 +00:00
( ' done ' , ' Approved ' ) ] , ' Status ' , select = True , required = True , readonly = True ,
2012-10-12 11:42:58 +00:00
help = ' * The \' Draft \' status is used when a user is encoding a new and unconfirmed timesheet. \
\n * The \' Confirmed \' status is used for to confirm the timesheet by user. \
\n * The \' Done \' status is used when users timesheet is accepted by his/her senior. ' ) ,
2011-10-28 11:57:17 +00:00
' state_attendance ' : fields . related ( ' employee_id ' , ' state ' , type = ' selection ' , selection = [ ( ' absent ' , ' Absent ' ) , ( ' present ' , ' Present ' ) ] , string = ' Current Status ' , readonly = True ) ,
2011-11-14 12:20:42 +00:00
' total_attendance ' : fields . function ( _total , method = True , string = ' Total Attendance ' , multi = " _total " ) ,
' total_timesheet ' : fields . function ( _total , method = True , string = ' Total Timesheet ' , multi = " _total " ) ,
' total_difference ' : fields . function ( _total , method = True , string = ' Difference ' , multi = " _total " ) ,
2008-07-22 15:11:28 +00:00
' period_ids ' : fields . one2many ( ' hr_timesheet_sheet.sheet.day ' , ' sheet_id ' , ' Period ' , readonly = True ) ,
' account_ids ' : fields . one2many ( ' hr_timesheet_sheet.sheet.account ' , ' sheet_id ' , ' Analytic accounts ' , readonly = True ) ,
2009-11-10 12:49:20 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' ) ,
2010-02-17 08:49:38 +00:00
' department_id ' : fields . many2one ( ' hr.department ' , ' Department ' ) ,
2014-03-27 11:37:20 +00:00
' timesheet_activity_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Timesheet Activities ' , multi = True ) ,
2014-03-26 12:00:56 +00:00
' attendance_count ' : fields . function ( _count_all , type = ' integer ' , string = " Attendances " , multi = True ) ,
2008-07-22 15:11:28 +00:00
}
2012-03-05 18:40:03 +00:00
def _default_date_from ( self , cr , uid , context = None ) :
2010-05-19 13:07:03 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
2008-07-22 15:11:28 +00:00
r = user . company_id and user . company_id . timesheet_range or ' month '
if r == ' month ' :
return time . strftime ( ' % Y- % m-01 ' )
elif r == ' week ' :
2011-12-08 06:28:56 +00:00
return ( datetime . today ( ) + relativedelta ( weekday = 0 , days = - 6 ) ) . strftime ( ' % Y- % m- %d ' )
2008-07-22 15:11:28 +00:00
elif r == ' year ' :
return time . strftime ( ' % Y-01-01 ' )
2015-09-02 09:46:02 +00:00
return fields . date . context_today ( self , cr , uid , context )
2008-07-22 15:11:28 +00:00
2012-03-05 18:40:03 +00:00
def _default_date_to ( self , cr , uid , context = None ) :
2010-05-19 13:07:03 +00:00
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
2008-07-22 15:11:28 +00:00
r = user . company_id and user . company_id . timesheet_range or ' month '
if r == ' month ' :
2010-10-15 14:01:53 +00:00
return ( datetime . today ( ) + relativedelta ( months = + 1 , day = 1 , days = - 1 ) ) . strftime ( ' % Y- % m- %d ' )
2008-07-22 15:11:28 +00:00
elif r == ' week ' :
2010-10-15 14:01:53 +00:00
return ( datetime . today ( ) + relativedelta ( weekday = 6 ) ) . strftime ( ' % Y- % m- %d ' )
2008-07-22 15:11:28 +00:00
elif r == ' year ' :
return time . strftime ( ' % Y-12-31 ' )
2015-09-02 09:46:02 +00:00
return fields . date . context_today ( self , cr , uid , context )
2008-07-22 15:11:28 +00:00
2011-06-15 10:04:11 +00:00
def _default_employee ( self , cr , uid , context = None ) :
2010-10-13 12:00:39 +00:00
emp_ids = self . pool . get ( ' hr.employee ' ) . search ( cr , uid , [ ( ' user_id ' , ' = ' , uid ) ] , context = context )
return emp_ids and emp_ids [ 0 ] or False
2011-11-09 06:25:43 +00:00
2008-07-22 15:11:28 +00:00
_defaults = {
' date_from ' : _default_date_from ,
' date_to ' : _default_date_to ,
2010-05-19 13:07:03 +00:00
' state ' : ' new ' ,
2010-10-13 12:00:39 +00:00
' employee_id ' : _default_employee ,
2010-10-06 16:39:01 +00:00
' company_id ' : lambda self , cr , uid , c : self . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' hr_timesheet_sheet.sheet ' , context = c )
2008-07-22 15:11:28 +00:00
}
2010-11-19 13:48:01 +00:00
def _sheet_date ( self , cr , uid , ids , forced_user_id = False , context = None ) :
for sheet in self . browse ( cr , uid , ids , context = context ) :
2015-01-14 12:32:24 +00:00
new_user_id = forced_user_id or sheet . employee_id . user_id and sheet . employee_id . user_id . id
2010-10-06 16:39:01 +00:00
if new_user_id :
cr . execute ( ' SELECT id \
2008-07-22 15:11:28 +00:00
FROM hr_timesheet_sheet_sheet \
2011-11-09 06:25:43 +00:00
WHERE ( date_from < = % s and % s < = date_to ) \
2008-12-10 14:29:55 +00:00
AND user_id = % s \
2010-10-06 16:39:01 +00:00
AND id < > % s ' ,(sheet.date_to, sheet.date_from, new_user_id, sheet.id))
if cr . fetchall ( ) :
return False
2008-07-22 15:11:28 +00:00
return True
2008-08-19 09:15:24 +00:00
2008-07-22 15:11:28 +00:00
_constraints = [
2012-10-29 15:08:09 +00:00
( _sheet_date , ' You cannot have 2 timesheets that overlap! \n Please use the menu \' My Current Timesheet \' to avoid this problem. ' , [ ' date_from ' , ' date_to ' ] ) ,
2008-07-22 15:11:28 +00:00
]
def action_set_to_draft ( self , cr , uid , ids , * args ) :
self . write ( cr , uid , ids , { ' state ' : ' draft ' } )
2013-02-01 09:23:07 +00:00
self . create_workflow ( cr , uid , ids )
2008-07-22 15:11:28 +00:00
return True
2010-07-27 07:11:45 +00:00
def name_get ( self , cr , uid , ids , context = None ) :
2012-08-21 09:07:50 +00:00
if not ids :
2008-07-22 15:11:28 +00:00
return [ ]
2012-09-06 12:54:07 +00:00
if isinstance ( ids , ( long , int ) ) :
2012-08-17 10:47:02 +00:00
ids = [ ids ]
2012-10-26 07:57:15 +00:00
return [ ( r [ ' id ' ] , _ ( ' Week ' ) + datetime . strptime ( r [ ' date_from ' ] , ' % Y- % m- %d ' ) . strftime ( ' % U ' ) ) \
for r in self . read ( cr , uid , ids , [ ' date_from ' ] ,
2010-07-27 07:11:45 +00:00
context = context , load = ' _classic_write ' ) ]
2007-07-09 09:08:41 +00:00
2009-01-20 20:32:58 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
2010-07-27 07:11:45 +00:00
sheets = self . read ( cr , uid , ids , [ ' state ' , ' total_attendance ' ] , context = context )
2009-12-21 13:00:04 +00:00
for sheet in sheets :
if sheet [ ' state ' ] in ( ' confirm ' , ' done ' ) :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Invalid Action! ' ) , _ ( ' You cannot delete a timesheet which is already confirmed. ' ) )
2009-12-21 13:00:04 +00:00
elif sheet [ ' total_attendance ' ] < > 0.00 :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Invalid Action! ' ) , _ ( ' You cannot delete a timesheet which have attendance entries. ' ) )
2015-02-26 14:42:01 +00:00
toremove = [ ]
analytic_timesheet = self . pool . get ( ' hr.analytic.timesheet ' )
for sheet in self . browse ( cr , uid , ids , context = context ) :
for timesheet in sheet . timesheet_ids :
toremove . append ( timesheet . id )
analytic_timesheet . unlink ( cr , uid , toremove , context = context )
2009-01-20 20:32:58 +00:00
return super ( hr_timesheet_sheet , self ) . unlink ( cr , uid , ids , context = context )
2011-06-16 13:03:31 +00:00
def onchange_employee_id ( self , cr , uid , ids , employee_id , context = None ) :
2011-06-17 12:59:52 +00:00
department_id = False
2013-03-14 15:06:14 +00:00
user_id = False
2011-06-15 10:04:11 +00:00
if employee_id :
2012-12-12 15:21:26 +00:00
empl_id = self . pool . get ( ' hr.employee ' ) . browse ( cr , uid , employee_id , context = context )
department_id = empl_id . department_id . id
user_id = empl_id . user_id . id
return { ' value ' : { ' department_id ' : department_id , ' user_id ' : user_id , } }
2011-06-15 10:04:11 +00:00
2012-11-12 09:54:24 +00:00
# ------------------------------------------------
# OpenChatter methods and notifications
# ------------------------------------------------
2012-12-20 10:00:05 +00:00
2012-12-20 11:02:42 +00:00
def _needaction_domain_get ( self , cr , uid , context = None ) :
2012-11-12 09:54:24 +00:00
emp_obj = self . pool . get ( ' hr.employee ' )
empids = emp_obj . search ( cr , uid , [ ( ' parent_id.user_id ' , ' = ' , uid ) ] , context = context )
2012-12-20 10:00:05 +00:00
if not empids :
return False
2012-11-12 09:54:24 +00:00
dom = [ ' & ' , ( ' state ' , ' = ' , ' confirm ' ) , ( ' employee_id ' , ' in ' , empids ) ]
return dom
2012-12-20 10:00:05 +00:00
2007-03-05 18:22:32 +00:00
2012-10-25 14:54:43 +00:00
class account_analytic_line ( osv . osv ) :
_inherit = " account.analytic.line "
2008-07-22 15:11:28 +00:00
2010-07-27 07:11:45 +00:00
def _get_default_date ( self , cr , uid , context = None ) :
if context is None :
context = { }
2012-10-25 14:54:43 +00:00
#get the default date (should be: today)
res = super ( account_analytic_line , self ) . _get_default_date ( cr , uid , context = context )
#if we got the dates from and to from the timesheet and if the default date is in between, we use the default
#but if the default isn't included in those dates, we use the date start of the timesheet as default
if context . get ( ' timesheet_date_from ' ) and context . get ( ' timesheet_date_to ' ) :
if context [ ' timesheet_date_from ' ] < = res < = context [ ' timesheet_date_to ' ] :
return res
return context . get ( ' timesheet_date_from ' )
#if we don't get the dates from the timesheet, we return the default value from super()
return res
2013-12-23 11:31:38 +00:00
class account_analytic_account ( osv . osv ) :
_inherit = " account.analytic.account "
def name_create ( self , cr , uid , name , context = None ) :
2013-12-23 12:24:33 +00:00
if context is None :
context = { }
2014-01-07 06:11:57 +00:00
group_template_required = self . pool [ ' res.users ' ] . has_group ( cr , uid , ' account_analytic_analysis.group_template_required ' )
2014-04-14 13:26:34 +00:00
if not context . get ( ' default_use_timesheets ' ) or group_template_required :
2013-12-23 11:31:38 +00:00
return super ( account_analytic_account , self ) . name_create ( cr , uid , name , context = context )
rec_id = self . create ( cr , uid , { self . _rec_name : name } , context )
return self . name_get ( cr , uid , [ rec_id ] , context ) [ 0 ]
2012-10-25 14:54:43 +00:00
class hr_timesheet_line ( osv . osv ) :
_inherit = " hr.analytic.timesheet "
2008-07-22 15:11:28 +00:00
2010-07-27 07:11:45 +00:00
def _sheet ( self , cursor , user , ids , name , args , context = None ) :
2008-07-22 15:11:28 +00:00
sheet_obj = self . pool . get ( ' hr_timesheet_sheet.sheet ' )
2011-11-14 12:20:42 +00:00
res = { } . fromkeys ( ids , False )
for ts_line in self . browse ( cursor , user , ids , context = context ) :
sheet_ids = sheet_obj . search ( cursor , user ,
2012-01-06 09:25:20 +00:00
[ ( ' date_to ' , ' >= ' , ts_line . date ) , ( ' date_from ' , ' <= ' , ts_line . date ) ,
2015-02-09 11:09:24 +00:00
( ' employee_id.user_id ' , ' = ' , ts_line . user_id . id ) ,
( ' state ' , ' in ' , [ ' draft ' , ' new ' ] ) ] ,
2012-01-06 09:25:20 +00:00
context = context )
2011-11-14 12:20:42 +00:00
if sheet_ids :
# [0] because only one sheet possible for an employee between 2 dates
res [ ts_line . id ] = sheet_obj . name_get ( cursor , user , sheet_ids , context = context ) [ 0 ]
2008-07-22 15:11:28 +00:00
return res
2011-11-14 12:20:42 +00:00
def _get_hr_timesheet_sheet ( self , cr , uid , ids , context = None ) :
ts_line_ids = [ ]
for ts in self . browse ( cr , uid , ids , context = context ) :
cr . execute ( """
SELECT l . id
FROM hr_analytic_timesheet l
INNER JOIN account_analytic_line al
ON ( l . line_id = al . id )
WHERE % ( date_to ) s > = al . date
AND % ( date_from ) s < = al . date
AND % ( user_id ) s = al . user_id
GROUP BY l . id """ , { ' date_from ' : ts.date_from,
' date_to ' : ts . date_to ,
' user_id ' : ts . employee_id . user_id . id , } )
ts_line_ids . extend ( [ row [ 0 ] for row in cr . fetchall ( ) ] )
return ts_line_ids
def _get_account_analytic_line ( self , cr , uid , ids , context = None ) :
ts_line_ids = self . pool . get ( ' hr.analytic.timesheet ' ) . search ( cr , uid , [ ( ' line_id ' , ' in ' , ids ) ] )
return ts_line_ids
2008-07-22 15:11:28 +00:00
_columns = {
2013-05-08 08:59:38 +00:00
' sheet_id ' : fields . function ( _sheet , string = ' Sheet ' , select = " 1 " ,
2012-10-02 12:11:03 +00:00
type = ' many2one ' , relation = ' hr_timesheet_sheet.sheet ' , ondelete = " cascade " ,
2011-11-14 12:20:42 +00:00
store = {
' hr_timesheet_sheet.sheet ' : ( _get_hr_timesheet_sheet , [ ' employee_id ' , ' date_from ' , ' date_to ' ] , 10 ) ,
' account.analytic.line ' : ( _get_account_analytic_line , [ ' user_id ' , ' date ' ] , 10 ) ,
2012-03-13 15:03:47 +00:00
' hr.analytic.timesheet ' : ( lambda self , cr , uid , ids , context = None : ids , None , 10 ) ,
2011-11-14 12:20:42 +00:00
} ,
) ,
2008-07-22 15:11:28 +00:00
}
2015-02-09 11:24:47 +00:00
def write ( self , cr , uid , ids , values , context = None ) :
if isinstance ( ids , ( int , long ) ) :
ids = [ ids ]
self . _check ( cr , uid , ids )
return super ( hr_timesheet_line , self ) . write ( cr , uid , ids , values , context = context )
2008-07-22 15:11:28 +00:00
def unlink ( self , cr , uid , ids , * args , * * kwargs ) :
2011-07-01 09:45:10 +00:00
if isinstance ( ids , ( int , long ) ) :
ids = [ ids ]
2008-07-22 15:11:28 +00:00
self . _check ( cr , uid , ids )
return super ( hr_timesheet_line , self ) . unlink ( cr , uid , ids , * args , * * kwargs )
def _check ( self , cr , uid , ids ) :
for att in self . browse ( cr , uid , ids ) :
if att . sheet_id and att . sheet_id . state not in ( ' draft ' , ' new ' ) :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' You cannot modify an entry in a confirmed timesheet. ' ) )
2008-07-22 15:11:28 +00:00
return True
2007-08-30 14:22:22 +00:00
2012-10-04 13:48:58 +00:00
def multi_on_change_account_id ( self , cr , uid , ids , account_ids , context = None ) :
2012-10-21 19:59:25 +00:00
return dict ( [ ( el , self . on_change_account_id ( cr , uid , ids , el , context . get ( ' user_id ' , uid ) ) ) for el in account_ids ] )
2012-10-04 13:48:58 +00:00
2007-03-05 18:22:32 +00:00
class hr_attendance ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_inherit = " hr.attendance "
2010-07-27 07:11:45 +00:00
def _get_default_date ( self , cr , uid , context = None ) :
if context is None :
context = { }
2008-07-22 15:11:28 +00:00
if ' name ' in context :
return context [ ' name ' ] + time . strftime ( ' % H: % M: % S ' )
return time . strftime ( ' % Y- % m- %d % H: % M: % S ' )
2011-11-14 12:20:42 +00:00
def _get_hr_timesheet_sheet ( self , cr , uid , ids , context = None ) :
attendance_ids = [ ]
for ts in self . browse ( cr , uid , ids , context = context ) :
cr . execute ( """
SELECT a . id
FROM hr_attendance a
INNER JOIN hr_employee e
INNER JOIN resource_resource r
ON ( e . resource_id = r . id )
ON ( a . employee_id = e . id )
2015-09-02 09:46:02 +00:00
LEFT JOIN res_users u
ON r . user_id = u . id
LEFT JOIN res_partner p
ON u . partner_id = p . id
WHERE % ( date_to ) s > = date_trunc ( ' day ' , a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) )
AND % ( date_from ) s < = date_trunc ( ' day ' , a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) )
2011-11-14 12:20:42 +00:00
AND % ( user_id ) s = r . user_id
GROUP BY a . id """ , { ' date_from ' : ts.date_from,
' date_to ' : ts . date_to ,
' user_id ' : ts . employee_id . user_id . id , } )
attendance_ids . extend ( [ row [ 0 ] for row in cr . fetchall ( ) ] )
return attendance_ids
2014-04-28 14:20:17 +00:00
def _get_attendance_employee_tz ( self , cr , uid , employee_id , date , context = None ) :
""" Simulate timesheet in employee timezone
2014-04-28 15:32:16 +00:00
Return the attendance date in string format in the employee
2014-04-28 14:20:17 +00:00
tz converted from utc timezone as we consider date of employee
timesheet is in employee timezone
"""
employee_obj = self . pool [ ' hr.employee ' ]
tz = False
if employee_id :
employee = employee_obj . browse ( cr , uid , employee_id , context = context )
tz = employee . user_id . partner_id . tz
2014-04-30 11:37:30 +00:00
if not date :
date = time . strftime ( DEFAULT_SERVER_DATETIME_FORMAT )
2014-04-28 14:20:17 +00:00
att_tz = timezone ( tz or ' utc ' )
attendance_dt = datetime . strptime ( date , DEFAULT_SERVER_DATETIME_FORMAT )
att_tz_dt = pytz . utc . localize ( attendance_dt )
att_tz_dt = att_tz_dt . astimezone ( att_tz )
# We take only the date omiting the hours as we compare with timesheet
# date_from which is a date format thus using hours would lead to
# be out of scope of timesheet
att_tz_date_str = datetime . strftime ( att_tz_dt , DEFAULT_SERVER_DATE_FORMAT )
return att_tz_date_str
2014-04-24 14:28:29 +00:00
def _get_current_sheet ( self , cr , uid , employee_id , date = False , context = None ) :
2014-04-28 14:20:17 +00:00
sheet_obj = self . pool [ ' hr_timesheet_sheet.sheet ' ]
2014-04-24 14:28:29 +00:00
if not date :
date = time . strftime ( DEFAULT_SERVER_DATETIME_FORMAT )
2014-04-28 14:20:17 +00:00
att_tz_date_str = self . _get_attendance_employee_tz (
cr , uid , employee_id ,
date = date , context = context )
sheet_ids = sheet_obj . search ( cr , uid ,
[ ( ' date_from ' , ' <= ' , att_tz_date_str ) ,
( ' date_to ' , ' >= ' , att_tz_date_str ) ,
( ' employee_id ' , ' = ' , employee_id ) ] ,
2014-04-28 15:32:16 +00:00
limit = 1 , context = context )
2014-04-24 14:28:29 +00:00
return sheet_ids and sheet_ids [ 0 ] or False
2010-07-27 07:11:45 +00:00
def _sheet ( self , cursor , user , ids , name , args , context = None ) :
2011-11-14 12:20:42 +00:00
res = { } . fromkeys ( ids , False )
for attendance in self . browse ( cursor , user , ids , context = context ) :
2014-04-28 14:20:17 +00:00
res [ attendance . id ] = self . _get_current_sheet (
cursor , user , attendance . employee_id . id , attendance . name ,
context = context )
2008-07-22 15:11:28 +00:00
return res
_columns = {
2011-07-01 23:41:24 +00:00
' sheet_id ' : fields . function ( _sheet , string = ' Sheet ' ,
2008-07-22 15:11:28 +00:00
type = ' many2one ' , relation = ' hr_timesheet_sheet.sheet ' ,
2011-11-14 12:20:42 +00:00
store = {
' hr_timesheet_sheet.sheet ' : ( _get_hr_timesheet_sheet , [ ' employee_id ' , ' date_from ' , ' date_to ' ] , 10 ) ,
2012-01-06 09:25:20 +00:00
' hr.attendance ' : ( lambda self , cr , uid , ids , context = None : ids , [ ' employee_id ' , ' name ' , ' day ' ] , 10 ) ,
2011-11-14 12:20:42 +00:00
} ,
)
2008-07-22 15:11:28 +00:00
}
_defaults = {
' name ' : _get_default_date ,
}
2010-07-21 12:39:48 +00:00
def create ( self , cr , uid , vals , context = None ) :
if context is None :
context = { }
2014-04-24 14:28:29 +00:00
sheet_id = context . get ( ' sheet_id ' ) or self . _get_current_sheet ( cr , uid , vals . get ( ' employee_id ' ) , vals . get ( ' name ' ) , context = context )
if sheet_id :
2014-04-28 14:20:17 +00:00
att_tz_date_str = self . _get_attendance_employee_tz (
cr , uid , vals . get ( ' employee_id ' ) ,
date = vals . get ( ' name ' ) , context = context )
2014-04-24 14:28:29 +00:00
ts = self . pool . get ( ' hr_timesheet_sheet.sheet ' ) . browse ( cr , uid , sheet_id , context = context )
2008-07-22 15:11:28 +00:00
if ts . state not in ( ' draft ' , ' new ' ) :
2014-04-24 14:28:29 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' You can not enter an attendance in a submitted timesheet. Ask your manager to reset it before adding attendance. ' ) )
2014-04-28 14:20:17 +00:00
elif ts . date_from > att_tz_date_str or ts . date_to < att_tz_date_str :
2014-04-24 14:28:29 +00:00
raise osv . except_osv ( _ ( ' User Error! ' ) , _ ( ' You can not enter an attendance date outside the current timesheet dates. ' ) )
return super ( hr_attendance , self ) . create ( cr , uid , vals , context = context )
2008-07-22 15:11:28 +00:00
def unlink ( self , cr , uid , ids , * args , * * kwargs ) :
2011-07-01 09:45:10 +00:00
if isinstance ( ids , ( int , long ) ) :
ids = [ ids ]
2008-07-22 15:11:28 +00:00
self . _check ( cr , uid , ids )
return super ( hr_attendance , self ) . unlink ( cr , uid , ids , * args , * * kwargs )
2010-07-27 07:11:45 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2010-07-21 12:39:48 +00:00
if context is None :
context = { }
2011-07-01 09:45:10 +00:00
if isinstance ( ids , ( int , long ) ) :
ids = [ ids ]
2008-07-22 15:11:28 +00:00
self . _check ( cr , uid , ids )
res = super ( hr_attendance , self ) . write ( cr , uid , ids , vals , context = context )
if ' sheet_id ' in context :
for attendance in self . browse ( cr , uid , ids , context = context ) :
if context [ ' sheet_id ' ] != attendance . sheet_id . id :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' User Error! ' ) , _ ( ' You cannot enter an attendance ' \
' date outside the current timesheet dates. ' ) )
2008-07-22 15:11:28 +00:00
return res
def _check ( self , cr , uid , ids ) :
for att in self . browse ( cr , uid , ids ) :
if att . sheet_id and att . sheet_id . state not in ( ' draft ' , ' new ' ) :
2012-08-07 11:06:16 +00:00
raise osv . except_osv ( _ ( ' Error! ' ) , _ ( ' You cannot modify an entry in a confirmed timesheet ' ) )
2008-07-22 15:11:28 +00:00
return True
2007-08-30 14:22:22 +00:00
2007-03-05 18:22:32 +00:00
class hr_timesheet_sheet_sheet_day ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " hr_timesheet_sheet.sheet.day "
2010-05-19 18:32:32 +00:00
_description = " Timesheets by Period "
2008-07-22 15:11:28 +00:00
_auto = False
_order = ' name '
_columns = {
' name ' : fields . date ( ' Date ' , readonly = True ) ,
' sheet_id ' : fields . many2one ( ' hr_timesheet_sheet.sheet ' , ' Sheet ' , readonly = True , select = " 1 " ) ,
2011-01-06 05:35:21 +00:00
' total_timesheet ' : fields . float ( ' Total Timesheet ' , readonly = True ) ,
2008-07-22 15:11:28 +00:00
' total_attendance ' : fields . float ( ' Attendance ' , readonly = True ) ,
' total_difference ' : fields . float ( ' Difference ' , readonly = True ) ,
}
2014-07-08 08:16:16 +00:00
_depends = {
' account.analytic.line ' : [ ' date ' , ' unit_amount ' ] ,
2014-07-08 13:32:38 +00:00
' hr.analytic.timesheet ' : [ ' line_id ' , ' sheet_id ' ] ,
' hr.attendance ' : [ ' action ' , ' name ' , ' sheet_id ' ] ,
2014-07-08 08:16:16 +00:00
}
2008-07-22 15:11:28 +00:00
def init ( self , cr ) :
cr . execute ( """ create or replace view hr_timesheet_sheet_sheet_day as
SELECT
id ,
name ,
sheet_id ,
total_timesheet ,
total_attendance ,
2009-09-22 05:19:11 +00:00
cast ( round ( cast ( total_attendance - total_timesheet as Numeric ) , 2 ) as Double Precision ) AS total_difference
2008-07-22 15:11:28 +00:00
FROM
( (
SELECT
MAX ( id ) as id ,
name ,
sheet_id ,
2015-02-27 10:55:45 +00:00
timezone ,
2008-07-22 15:11:28 +00:00
SUM ( total_timesheet ) as total_timesheet ,
2015-02-27 10:55:45 +00:00
CASE WHEN SUM ( orphan_attendances ) != 0
2008-07-22 15:11:28 +00:00
THEN ( SUM ( total_attendance ) +
CASE WHEN current_date < > name
THEN 1440
2015-02-27 10:55:45 +00:00
ELSE ( EXTRACT ( hour FROM current_time AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( timezone , ' UTC ' ) ) * 60 ) + EXTRACT ( minute FROM current_time AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( timezone , ' UTC ' ) )
2008-07-22 15:11:28 +00:00
END
)
ELSE SUM ( total_attendance )
END / 60 as total_attendance
FROM
( (
select
min ( hrt . id ) as id ,
2015-03-23 11:34:00 +00:00
p . tz as timezone ,
2008-07-22 15:11:28 +00:00
l . date : : date as name ,
s . id as sheet_id ,
sum ( l . unit_amount ) as total_timesheet ,
2015-02-27 10:55:45 +00:00
0 as orphan_attendances ,
2008-07-22 15:11:28 +00:00
0.0 as total_attendance
from
hr_analytic_timesheet hrt
2013-05-08 08:59:38 +00:00
JOIN account_analytic_line l ON l . id = hrt . line_id
LEFT JOIN hr_timesheet_sheet_sheet s ON s . id = hrt . sheet_id
2015-03-23 11:34:00 +00:00
JOIN hr_employee e ON s . employee_id = e . id
JOIN resource_resource r ON e . resource_id = r . id
LEFT JOIN res_users u ON r . user_id = u . id
LEFT JOIN res_partner p ON u . partner_id = p . id
2015-02-27 10:55:45 +00:00
group by l . date : : date , s . id , timezone
2008-07-22 15:11:28 +00:00
) union (
select
- min ( a . id ) as id ,
2015-02-27 10:55:45 +00:00
p . tz as timezone ,
2015-01-07 11:22:29 +00:00
( a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) ) : : date as name ,
2008-07-22 15:11:28 +00:00
s . id as sheet_id ,
0.0 as total_timesheet ,
2015-02-27 10:55:45 +00:00
SUM ( CASE WHEN a . action = ' sign_in ' THEN - 1 ELSE 1 END ) as orphan_attendances ,
2015-01-07 11:22:29 +00:00
SUM ( ( ( EXTRACT ( hour FROM ( a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) ) ) * 60 ) + EXTRACT ( minute FROM ( a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) ) ) ) * ( CASE WHEN a . action = ' sign_in ' THEN - 1 ELSE 1 END ) ) as total_attendance
2008-07-22 15:11:28 +00:00
from
hr_attendance a
2013-05-08 08:59:38 +00:00
LEFT JOIN hr_timesheet_sheet_sheet s
ON s . id = a . sheet_id
2015-01-07 11:22:29 +00:00
JOIN hr_employee e
ON a . employee_id = e . id
JOIN resource_resource r
ON e . resource_id = r . id
LEFT JOIN res_users u
ON r . user_id = u . id
LEFT JOIN res_partner p
ON u . partner_id = p . id
2008-07-22 15:11:28 +00:00
WHERE action in ( ' sign_in ' , ' sign_out ' )
2015-02-27 10:55:45 +00:00
group by ( a . name AT TIME ZONE ' UTC ' AT TIME ZONE coalesce ( p . tz , ' UTC ' ) ) : : date , s . id , timezone
2008-07-22 15:11:28 +00:00
) ) AS foo
2015-02-27 10:55:45 +00:00
GROUP BY name , sheet_id , timezone
2008-07-22 15:11:28 +00:00
) ) AS bar """ )
2007-08-30 14:22:22 +00:00
2007-03-05 18:22:32 +00:00
2007-03-06 09:55:17 +00:00
class hr_timesheet_sheet_sheet_account ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_name = " hr_timesheet_sheet.sheet.account "
2010-05-19 18:32:32 +00:00
_description = " Timesheets by Period "
2008-07-22 15:11:28 +00:00
_auto = False
_order = ' name '
_columns = {
2011-09-10 12:43:55 +00:00
' name ' : fields . many2one ( ' account.analytic.account ' , ' Project / Analytic Account ' , readonly = True ) ,
2008-07-22 15:11:28 +00:00
' sheet_id ' : fields . many2one ( ' hr_timesheet_sheet.sheet ' , ' Sheet ' , readonly = True ) ,
' total ' : fields . float ( ' Total Time ' , digits = ( 16 , 2 ) , readonly = True ) ,
' invoice_rate ' : fields . many2one ( ' hr_timesheet_invoice.factor ' , ' Invoice rate ' , readonly = True ) ,
2008-12-11 11:50:52 +00:00
}
2008-07-22 15:11:28 +00:00
2014-07-08 13:32:38 +00:00
_depends = {
' account.analytic.line ' : [ ' account_id ' , ' date ' , ' to_invoice ' , ' unit_amount ' , ' user_id ' ] ,
' hr.analytic.timesheet ' : [ ' line_id ' ] ,
' hr_timesheet_sheet.sheet ' : [ ' date_from ' , ' date_to ' , ' user_id ' ] ,
}
2008-07-22 15:11:28 +00:00
def init ( self , cr ) :
cr . execute ( """ create or replace view hr_timesheet_sheet_sheet_account as (
select
min ( hrt . id ) as id ,
l . account_id as name ,
s . id as sheet_id ,
sum ( l . unit_amount ) as total ,
l . to_invoice as invoice_rate
from
hr_analytic_timesheet hrt
left join ( account_analytic_line l
LEFT JOIN hr_timesheet_sheet_sheet s
ON ( s . date_to > = l . date
AND s . date_from < = l . date
AND s . user_id = l . user_id ) )
on ( l . id = hrt . line_id )
group by l . account_id , s . id , l . to_invoice
) """ )
2007-08-30 14:22:22 +00:00
2007-03-06 09:55:17 +00:00
2007-08-30 14:22:22 +00:00
2008-09-07 23:24:39 +00:00
2007-03-06 09:55:17 +00:00
class res_company ( osv . osv ) :
2008-07-22 15:11:28 +00:00
_inherit = ' res.company '
_columns = {
2008-09-07 23:24:39 +00:00
' timesheet_range ' : fields . selection (
2011-10-01 18:46:25 +00:00
[ ( ' day ' , ' Day ' ) , ( ' week ' , ' Week ' ) , ( ' month ' , ' Month ' ) ] , ' Timesheet range ' ,
help = " Periodicity on which you validate your timesheets. " ) ,
2010-07-13 13:38:02 +00:00
' timesheet_max_difference ' : fields . float ( ' Timesheet allowed difference(Hours) ' ,
help = " Allowed difference in hours between the sign in/out and the timesheet " \
2008-09-07 23:24:39 +00:00
" computation for one sheet. Set this to 0 if you do not want any control. " ) ,
2008-07-22 15:11:28 +00:00
}
_defaults = {
2010-09-16 05:59:56 +00:00
' timesheet_range ' : lambda * args : ' week ' ,
2008-07-22 15:11:28 +00:00
' timesheet_max_difference ' : lambda * args : 0.0
}
2007-08-30 14:22:22 +00:00
2014-04-15 10:54:19 +00:00
class hr_employee ( osv . osv ) :
'''
Employee
'''
2008-07-23 14:41:47 +00:00
2014-04-15 10:54:19 +00:00
_inherit = ' hr.employee '
_description = ' Employee '
def _timesheet_count ( self , cr , uid , ids , field_name , arg , context = None ) :
2014-05-07 14:17:25 +00:00
Sheet = self . pool [ ' hr_timesheet_sheet.sheet ' ]
return {
employee_id : Sheet . search_count ( cr , uid , [ ( ' employee_id ' , ' = ' , employee_id ) ] , context = context )
for employee_id in ids
}
2014-04-15 10:54:19 +00:00
_columns = {
2014-05-07 14:17:25 +00:00
' timesheet_count ' : fields . function ( _timesheet_count , type = ' integer ' , string = ' Timesheets ' ) ,
2014-04-15 10:54:19 +00:00
}
2008-07-23 14:41:47 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: