[MERGE] hr_attendance: removed some wizard and added widget to sign in/sign out

bzr revid: nicolas.vanhoren@openerp.com-20120907084438-bnxmscn1zt8u0aex
This commit is contained in:
niv-openerp
2012-09-07 10:44:38 +02:00
19 changed files with 161 additions and 347 deletions
+5 -1
View File
@@ -43,7 +43,6 @@ actions(Sign in/Sign out) performed by them.
'wizard/hr_attendance_bymonth_view.xml',
'wizard/hr_attendance_byweek_view.xml',
'wizard/hr_attendance_error_view.xml',
'wizard/hr_attendance_sign_in_out_view.xml',
],
'demo': ['hr_attendance_demo.xml'],
'test': [
@@ -53,5 +52,10 @@ actions(Sign in/Sign out) performed by them.
'installable': True,
'auto_install': False,
'certificate': '0063495605613',
#web
"js": ["static/src/js/attendance.js"],
'qweb' : ["static/src/xml/attendance.xml"],
'css' : ["static/src/css/slider.css"],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+17 -22
View File
@@ -122,30 +122,25 @@ class hr_employee(osv.osv):
res = cr.fetchone()
return not (res and (res[0]>=(dt or time.strftime('%Y-%m-%d %H:%M:%S'))))
def attendance_action_change(self, cr, uid, ids, type='action', context=None, dt=False, *args):
obj_attendance = self.pool.get('hr.attendance')
id = False
warning_sign = 'sign'
res = {}
def attendance_action_change(self, cr, uid, ids, context=None):
if context is None:
context = {}
action_date = context.get('action_date', False)
action = context.get('action', False)
hr_attendance = self.pool.get('hr.attendance')
warning_sign = {'sign_in': _('Sign In'), 'sign_out': _('Sign Out')}
for employee in self.browse(cr, uid, ids, context=context):
if not action:
if employee.state == 'present': action = 'sign_out'
if employee.state == 'absent': action = 'sign_in'
#Special case when button calls this method: type=context
if isinstance(type, dict):
type = type.get('type','action')
if type == 'sign_in':
warning_sign = "Sign In"
elif type == 'sign_out':
warning_sign = "Sign Out"
for emp in self.read(cr, uid, ids, ['id'], context=context):
if not self._action_check(cr, uid, emp['id'], dt, context):
raise osv.except_osv(_('Warning!'), _('You tried to %s with a date anterior to another event !\nTry to contact the administrator to correct attendances.')%(warning_sign,))
if not self._action_check(cr, uid, employee.id, action_date, context):
raise osv.except_osv(_('Warning'), _('You tried to %s with a date anterior to another event !\nTry to contact the HR Manager to correct attendances.')%(warning_sign[action],))
res = {'action': type, 'employee_id': emp['id']}
if dt:
res['name'] = dt
id = obj_attendance.create(cr, uid, res, context=context)
if type != 'action':
return id
vals = {'action': action, 'employee_id': employee.id}
if action_date:
vals['name'] = action_date
hr_attendance.create(cr, uid, vals, context=context)
return True
hr_employee()
+4 -2
View File
@@ -127,8 +127,8 @@
<label for="state"/>
<div>
<field name="state" class="oe_inline"/> -
<button class="oe_link" name="attendance_action_change" states="present" string="Sign Out" type="object" context="{'type':'sign_out'}" groups="base.group_hr_user"/>
<button class="oe_link" name="attendance_action_change" states="absent" string="Sign In" type="object" context="{'type':'sign_in'}" groups="base.group_hr_user"/>
<button class="oe_link" name="attendance_action_change" states="present" string="Sign Out" type="object" groups="base.group_hr_manager"/>
<button class="oe_link" name="attendance_action_change" states="absent" string="Sign In" type="object" groups="base.group_hr_manager"/>
</div>
</field>
</field>
@@ -136,3 +136,5 @@
</data>
</openerp>
@@ -0,0 +1,27 @@
.openerp .oe_attendance_status {
height: 32px;
width: 32px;
display: inline-block;
}
.openerp .oe_attendance_signin {
float:left;
height: 32px;
width: 32px;
background: url(/hr_attendance/static/src/img/emp-in32.png);
cursor: pointer;
}
.openerp .oe_attendance_status.oe_attendance_signed .oe_attendance_signin {
display: none;
}
.openerp .oe_attendance_signout {
float:right;
height: 32px;
width: 32px;
background: url(/hr_attendance/static/src/img/emp-out32.png);
cursor: pointer;
}
.openerp .oe_attendance_status.oe_attendance_nosigned .oe_attendance_signout {
display: none;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

@@ -0,0 +1,75 @@
openerp.hr_attendance = function (instance) {
var QWeb = instance.web.qweb;
var _t = instance.web._t;
var _lt = instance.web._lt;
var tips = {
"true": _lt("You are currently signed in. Click here to sign out."),
"false": _lt("You are currently signed out. Click here to sign in."),
}
instance.hr_attendance.AttendanceSlider = instance.web.Widget.extend({
template: 'AttendanceSlider',
init: function (parent) {
this._super(parent);
this.set({"signed_in": false});
},
start: function() {
var self = this;
var tmp = function() {
this.$el.toggleClass("oe_attendance_nosigned", ! this.get("signed_in"));
this.$el.toggleClass("oe_attendance_signed", this.get("signed_in"));
this.$el.attr("title", tips["" + this.get("signed_in")].toString());
};
this.on("change:signed_in", this, tmp);
_.bind(tmp, this)();
this.$(".oe_attendance_signin").click(function() {
self.do_update_attendance();
});
this.$(".oe_attendance_signout").click(function() {
self.do_update_attendance();
});
return this.check_attendance();
},
do_update_attendance: function () {
var self = this;
var hr_employee = new instance.web.DataSet(self, 'hr.employee');
hr_employee.call('attendance_action_change', [
[self.employee.id]
]).done(function (result) {
self.set({"signed_in": ! self.get("signed_in")});
});
},
check_attendance: function () {
var self = this;
self.employee = false;
this.$el.hide();
var employee = new instance.web.DataSetSearch(self, 'hr.employee', self.session.user_context, [
['user_id', '=', self.session.uid]
]);
return employee.read_slice(['id', 'name', 'state']).pipe(function (res) {
if (_.isEmpty(res))
return;
self.$el.show();
self.employee = res[0];
self.set({"signed_in": self.employee.state !== "absent"});
});
},
});
instance.web.UserMenu.include({
do_update: function () {
this._super();
var self = this;
this.update_promise = this.update_promise.then(function () {
if (self.attendanceslider)
return;
self.attendanceslider = new instance.hr_attendance.AttendanceSlider(self);
self.attendanceslider.prependTo(instance.webclient.$('.oe_systray'));
});
},
});
}
@@ -0,0 +1,13 @@
<template>
<t t-name="AttendanceSlider">
<div class="oe_attendance_status oe_attendance_nosigned" title=" ">
<div class="oe_attendance_signin"></div>
<div class="oe_attendance_signout"></div>
</div>
</t>
</template>
@@ -1,16 +1,8 @@
-
In order to test attendance process in OpenERP, I entry of SignIn of employee.
-
!python {model: hr.sign.in.out}: |
context.update({'emp_id': [ref('hr.employee_al')]}) #TOFIX: emp_ids instead of 'emp_id'
-
!record {model: hr.sign.in.out, id: employee_sign_in}:
{}
-
Employee Signs In.
-
!python {model: hr.sign.in.out}: |
self.si_check(cr, uid, [ref("employee_sign_in")], context=context)
!python {model: hr.employee}: |
self.attendance_action_change(cr, uid, [ref("hr.employee_al")], context=context)
-
I check that Employee is "Present".
-
@@ -19,10 +11,10 @@
-
After few seconds, employee sign's out.
-
!python {model: hr.sign.in.out}: |
!python {model: hr.employee}: |
import time
time.sleep(2)
self.so_check(cr, uid, [ref("employee_sign_in")], context=context)
self.attendance_action_change(cr, uid, [ref("hr.employee_al")], context=context)
-
I check that Employee is "Absent".
-
+1 -2
View File
@@ -19,9 +19,8 @@
#
##############################################################################
import hr_attendance_sign_in_out
import hr_attendance_error
import hr_attendance_byweek
import hr_attendance_bymonth
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,184 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 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/>.
#
##############################################################################
import time
from osv import osv, fields
from tools.translate import _
class hr_si_so_ask(osv.osv_memory):
_name = 'hr.sign.in.out.ask'
_description = 'Ask for Sign In Out'
_columns = {
'name': fields.char('Employees name', size=32, required=True, readonly=True),
'last_time': fields.datetime('Your last sign out', required=True),
'emp_id': fields.many2one('hr.employee', 'Empoyee ID', readonly=True),
}
def _get_empname(self, cr, uid, context=None):
emp_id = context.get('emp_id', self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context))
if emp_id:
employee = self.pool.get('hr.employee').browse(cr, uid, emp_id, context=context)[0].name
return employee
return ''
def _get_empid(self, cr, uid, context=None):
emp_id = context.get('emp_id', self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context))
if emp_id:
return emp_id[0]
return False
_defaults = {
'name': _get_empname,
'emp_id': _get_empid,
}
def sign_in(self, cr, uid, ids, context=None):
data = self.read(cr, uid, ids, [], context=context)[0]
data['emp_id'] = data['emp_id'] and data['emp_id'][0]
return self.pool.get('hr.sign.in.out').sign_in(cr, uid, data, context)
def sign_out(self, cr, uid, ids, context=None):
data = self.read(cr, uid, ids, [], context=context)[0]
data['emp_id'] = data['emp_id'] and data['emp_id'][0]
return self.pool.get('hr.sign.in.out').sign_out(cr, uid, data, context)
hr_si_so_ask()
class hr_sign_in_out(osv.osv_memory):
_name = 'hr.sign.in.out'
_description = 'Sign In Sign Out'
_columns = {
'name': fields.char('Employees name', size=32, required=True, readonly=True),
'state': fields.char('Current state', size=32, required=True, readonly=True),
'emp_id': fields.many2one('hr.employee', 'Empoyee ID', readonly=True),
}
def _get_empid(self, cr, uid, context=None):
emp_id = context.get('emp_id', self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context))
if emp_id:
employee = self.pool.get('hr.employee').browse(cr, uid, emp_id, context=context)[0]
return {'name': employee.name, 'state': employee.state, 'emp_id': emp_id[0]}
return {}
def default_get(self, cr, uid, fields_list, context=None):
res = super(hr_sign_in_out, self).default_get(cr, uid, fields_list, context=context)
res_emp = self._get_empid(cr, uid, context=context)
res.update(res_emp)
return res
def si_check(self, cr, uid, ids, context=None):
obj_model = self.pool.get('ir.model.data')
att_obj = self.pool.get('hr.attendance')
data = self.read(cr, uid, ids, [], context=context)[0]
data['emp_id'] = data['emp_id'] and data['emp_id'][0]
emp_id = data['emp_id']
att_id = att_obj.search(cr, uid, [('employee_id', '=', emp_id)], limit=1, order='name desc')
last_att = att_obj.browse(cr, uid, att_id, context=context)
if last_att:
last_att = last_att[0]
cond = not last_att or last_att.action == 'sign_out'
if cond:
return self.sign_in(cr, uid, data, context)
else:
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_hr_attendance_so_ask')], context=context)
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'name': _('Sign in / Sign out'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'hr.sign.in.out.ask',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'context': context,
'target': 'new',
}
def so_check(self, cr, uid, ids, context=None):
obj_model = self.pool.get('ir.model.data')
att_obj = self.pool.get('hr.attendance')
data = self.read(cr, uid, ids, [], context=context)[0]
data['emp_id'] = data['emp_id'] and data['emp_id'][0]
emp_id = data['emp_id']
att_id = att_obj.search(cr, uid, [('employee_id', '=', emp_id),('action', '!=', 'action')], limit=1, order='name desc')
last_att = att_obj.browse(cr, uid, att_id, context=context)
if last_att:
last_att = last_att[0]
if not att_id and not last_att:
model_data_ids = obj_model.search(cr, uid, [('model','=','ir.ui.view'),('name','=','view_hr_attendance_message')], context=context)
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'name': _('Sign in / Sign out'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'hr.sign.in.out',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'context': context,
'target': 'new',
}
cond = last_att and last_att['action'] == 'sign_in'
if cond:
return self.sign_out(cr, uid, data, context)
else:
model_data_ids = obj_model.search(cr, uid, [('model','=','ir.ui.view'),('name','=','view_hr_attendance_si_ask')], context=context)
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id']
return {
'name': _('Sign in / Sign out'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'hr.sign.in.out.ask',
'views': [(resource_id,'form')],
'type': 'ir.actions.act_window',
'target': 'new',
}
def sign_in(self, cr, uid, data, context=None):
if context is None:
context = {}
emp_id = data['emp_id']
if 'last_time' in data:
if data['last_time'] > time.strftime('%Y-%m-%d %H:%M:%S'):
raise osv.except_osv(_('User Error!'), _('The sign-out date must be in the past.'))
self.pool.get('hr.attendance').create(cr, uid, {'name': data['last_time'], 'action': 'sign_out',
'employee_id': emp_id}, context=context)
try:
self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_in')
except:
raise osv.except_osv(_('User Error!'), _('A sign-in must be right after a sign-out!'))
return {'type': 'ir.actions.act_window_close'} # To do: Return Success message
def sign_out(self, cr, uid, data, context=None):
emp_id = data['emp_id']
if 'last_time' in data:
if data['last_time'] > time.strftime('%Y-%m-%d %H:%M:%S'):
raise osv.except_osv(_('User Error!'), _('The sign-in date must be in the past.'))
self.pool.get('hr.attendance').create(cr, uid, {'name':data['last_time'], 'action':'sign_in', 'employee_id':emp_id}, context=context)
try:
self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_out')
except:
raise osv.except_osv(_('User Error!'), _('A sign-out must be right after a sign-in.'))
return {'type': 'ir.actions.act_window_close'} # To do: Return Success message
hr_sign_in_out()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_hr_attendance_sigh_in_out" model="ir.ui.view">
<field name="name">hr.sign.in.out.form</field>
<field name="model">hr.sign.in.out</field>
<field name="arch" type="xml">
<form string="Sign in / Sign out" version="7.0">
<group>
<separator colspan="4" string="Sign in / Sign out"/>
<label colspan="4" nolabel="1" string="If you need your staff to sign in when they arrive at work and sign out again at the end of the day, OpenERP allows you to manage this with this tool. If each employee has been linked to a system user, then they can encode their time with this action button."/>
<newline/>
</group>
<group colspan="4" >
<field name="name" />
<field name="state" />
</group>
<footer>
<button string="Sign in" name="si_check" type="object" class="oe_highlight"/>
<button string="Sign out" name="so_check" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="view_hr_attendance_message" model="ir.ui.view">
<field name="name">hr.sign.in.out.form</field>
<field name="model">hr.sign.in.out</field>
<field name="arch" type="xml">
<form string="Sign in / Sign out" version="7.0">
<separator string="Sign-out Entry Must Follow Sign-in." colspan="4" />
</form>
</field>
</record>
<record id="action_hr_attendance_sigh_in_out" model="ir.actions.act_window">
<field name="name">Sign in / Sign out</field>
<field name="res_model">hr.sign.in.out</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_hr_attendance_sigh_in_out"/>
<field name="target">new</field>
<field name="help">Sign in / Sign out. In some companies, staff have to sign in when they arrive at work and sign out again at the end of the day. If each employee has been linked to a system user, then they can encode their time with this action button.</field>
</record>
<menuitem action="action_hr_attendance_sigh_in_out" id="menu_hr_attendance_sigh_in_out"
parent="menu_hr_attendance" sequence="4"/>
<record id="view_hr_attendance_so_ask" model="ir.ui.view">
<field name="name">hr.sign.in.out.ask.form</field>
<field name="model">hr.sign.in.out.ask</field>
<field name="arch" type="xml">
<form string="hr.sign.out.ask" version="7.0">
<header>
<button string="Sign in" name="sign_in" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</header>
<group colspan="4" >
<separator string="You did not sign out the last time. Please enter the date and time you signed out." colspan="4" />
<field name="name" />
<field name="last_time" string="Your last sign out" />
</group>
</form>
</field>
</record>
<record id="view_hr_attendance_si_ask" model="ir.ui.view">
<field name="name">hr.sign.in.out.ask.form</field>
<field name="model">hr.sign.in.out.ask</field>
<field name="arch" type="xml">
<form string="hr.sign.in.out.ask" version="7.0">
<header>
<button string="Sign out" name="sign_out" type="object" class="oe_highlight"/>
or
<button string="Cancel" class="oe_link" special="cancel" />
</header>
<group colspan="4" >
<separator string="You did not sign in the last time. Please enter the date and time you signed in." colspan="4" />
<field name="name" />
<field name="last_time" string="Your last sign in" />
</group>
</form>
</field>
</record>
</data>
</openerp>
@@ -91,7 +91,7 @@ class hr_so_project(osv.osv_memory):
emp_obj = self.pool.get('hr.employee')
for data in self.browse(cr, uid, ids, context=context):
emp_id = data.emp_id.id
emp_obj.attendance_action_change(cr, uid, [emp_id], type='sign_out', dt=data.date)
emp_obj.attendance_action_change(cr, uid, [emp_id], {'action':'sign_out', 'action_date':data.date})
self._write(cr, uid, data, emp_id, context=context)
return {'type': 'ir.actions.act_window_close'}
@@ -99,7 +99,7 @@ class hr_so_project(osv.osv_memory):
emp_obj = self.pool.get('hr.employee')
for data in self.browse(cr, uid, ids, context=context):
emp_id = data.emp_id.id
emp_obj.attendance_action_change(cr, uid, [emp_id], type='action', dt=data.date)
emp_obj.attendance_action_change(cr, uid, [emp_id], {'action':'action', 'action_date':data.date})
self._write(cr, uid, data, emp_id, context=context)
return {'type': 'ir.actions.act_window_close'}
@@ -156,7 +156,7 @@ class hr_si_project(osv.osv_memory):
emp_obj = self.pool.get('hr.employee')
for data in self.browse(cr, uid, ids, context=context):
emp_id = data.emp_id.id
emp_obj.attendance_action_change(cr, uid, [emp_id], type = 'sign_in' ,dt=data.date or False)
emp_obj.attendance_action_change(cr, uid, [emp_id], {'action':'sign_in', 'action_date':data.date})
return {'type': 'ir.actions.act_window_close'}
def default_get(self, cr, uid, fields_list, context=None):
@@ -312,31 +312,12 @@ class hr_timesheet_sheet(osv.osv):
self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,}, context=context)
return True
def check_sign(self, cr, uid, ids, typ, context=None):
sheet = self.browse(cr, uid, ids, context=context)[0]
if not sheet.date_current == time.strftime('%Y-%m-%d'):
raise osv.except_osv(_('Error!'), _('You cannot sign in/sign out from other date than today.'))
return True
def sign(self, cr, uid, ids, typ, context=None):
self.check_sign(cr, uid, ids, typ, context=context)
sign_obj = self.pool.get('hr.sign.in.out')
sheet = self.browse(cr, uid, ids, context=context)[0]
context['emp_id'] = [sheet.employee_id.id]
sign_id = sign_obj.create(cr, uid, {}, context=context)
methods = {'sign_in': sign_obj.si_check,
'sign_out': sign_obj.so_check}
wizard_result = methods[typ](cr, uid, [sign_id], context=context)
if wizard_result.get('type', False) == 'ir.actions.act_window_close':
return True # ensure we do not close the main window !
wizard_result['nodestroy'] = True # do not destroy the main window !
return wizard_result
def sign_in(self, cr, uid, ids, context=None):
return self.sign(cr, uid, ids, 'sign_in', context=context)
def sign_out(self, cr, uid, ids, context=None):
return self.sign(cr, uid, ids, 'sign_out', context=context)
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)
_columns = {
'name': fields.char('Note', size=64, select=1,
@@ -2,12 +2,12 @@
<openerp>
<data noupdate="1">
<record id="sheet1" model="hr_timesheet_sheet.sheet">
<!-- <record id="sheet1" model="hr_timesheet_sheet.sheet">
<field name="name">Sheet 1</field>
<field name="user_id" ref="base.user_root"/>
<field name="employee_id" ref="hr.employee_fp" />
<field eval="time.strftime('%Y-%m-%d')" name="date_current"/>
</record>
-->
</data>
</openerp>
@@ -92,9 +92,9 @@
</tree>
</field>
<group>
<div align="right">
<button name="sign_in" string="Sign In" type="object" icon="terp-gtk-jump-to-ltr"/>
<button name="sign_out" string="Sign Out" type="object" icon="terp-gtk-jump-to-rtl"/>
<div align="right" groups="base.group_hr_manager">
<button name="attendance_action_change" attrs="{'invisible': [('state_attendance', '=', 'present')]}" type="object" string="Sign In"/>
<button name="attendance_action_change" attrs="{'invisible': ['|', ('state_attendance','=',False), ('state_attendance', '=', 'absent')]}" type="object" string="Sign Out"/>
</div>
</group>
</group>
@@ -26,7 +26,7 @@
Now, at the time of login, I create Attendances and perform "Sign In" action.
-
!python {model: hr_timesheet_sheet.sheet}: |
self.sign_in(cr, uid, [ref('hr_timesheet_sheet_sheet_deddk0')], {})
self.attendance_action_change(cr, uid, [ref('hr_timesheet_sheet_sheet_deddk0')], {})
task_work = self.search(cr, uid, [("name","=","Quentin Paolinon")],context)[0]
task_ids = self.browse(cr, uid, task_work, context)
assert task_ids.state == "draft", "I State In Timesheet"