From 089863c406c4edd352b614996ceb591c95fb9062 Mon Sep 17 00:00:00 2001
From: ced <>
Date: Mon, 26 Mar 2007 13:52:53 +0000
Subject: [PATCH] HR_TIMESHEET_SHEET, CLIENT, KERNEL: improve
hr_timesheet_sheet, add context to one2many, improve error message for orm
bzr revid: ced-45596d43ab63775e008e5e629bebb06564ebbfa2
---
addons/hr/hr.py | 10 +-
addons/hr/hr_demo.xml | 40 ++---
addons/hr_timesheet/__terp__.py | 4 +-
addons/hr_timesheet/hr.analytic.timesheet.csv | 10 --
addons/hr_timesheet/hr_timesheet_demo.xml | 110 +++++++++++++
addons/hr_timesheet_sheet/__terp__.py | 2 +-
.../hr_timesheet_sheet/hr_timesheet_sheet.py | 147 +++++++++++++-----
.../hr_timesheet_sheet_demo.xml | 101 ++++++++++++
.../hr_timesheet_sheet_view.xml | 58 ++++++-
9 files changed, 401 insertions(+), 81 deletions(-)
delete mode 100644 addons/hr_timesheet/hr.analytic.timesheet.csv
create mode 100644 addons/hr_timesheet_sheet/hr_timesheet_sheet_demo.xml
diff --git a/addons/hr/hr.py b/addons/hr/hr.py
index 33a8edfb8d2..49eaba043f9 100644
--- a/addons/hr/hr.py
+++ b/addons/hr/hr.py
@@ -124,7 +124,7 @@ class hr_employee(osv.osv):
res = {'action':'action', 'employee_id':emp.id}
if dt:
res['name'] = dt
- att_id = self.pool.get('hr.attendance').create(cr, uid, res)
+ att_id = self.pool.get('hr.attendance').create(cr, uid, res, context=context)
return True
def sign_out(self, cr, uid, ids, context={}, dt=False, *args):
@@ -135,8 +135,8 @@ class hr_employee(osv.osv):
res = {'action':'sign_out', 'employee_id':emp.id}
if dt:
res['name'] = dt
- att_id = self.pool.get('hr.attendance').create(cr, uid, res)
- self.write(cr, uid, [emp.id], {'state':'absent'})
+ att_id = self.pool.get('hr.attendance').create(cr, uid, res, context=context)
+ self.write(cr, uid, [emp.id], {'state':'absent'}, context=context)
id = att_id
return id
@@ -153,8 +153,8 @@ class hr_employee(osv.osv):
res = {'action':'sign_in', 'employee_id':emp.id}
if dt:
res['name'] = dt
- id = self.pool.get('hr.attendance').create(cr, uid, res)
- self.write(cr, uid, [emp.id], {'state':'present'})
+ id = self.pool.get('hr.attendance').create(cr, uid, res, context=context)
+ self.write(cr, uid, [emp.id], {'state':'present'}, context=context)
return id
hr_employee()
diff --git a/addons/hr/hr_demo.xml b/addons/hr/hr_demo.xml
index f3b10528d39..81e55261eda 100644
--- a/addons/hr/hr_demo.xml
+++ b/addons/hr/hr_demo.xml
@@ -147,102 +147,102 @@
-
+
2005-05-04 08:21
sign_in
-
+
2005-05-04 11:51
sign_out
-
+
2005-05-04 12:47
sign_in
-
+
2005-05-04 19:53
sign_out
-
+
2005-05-05 07:32
sign_in
-
+
2005-05-05 12:32
sign_out
-
+
2005-05-05 14:01
sign_in
-
+
2005-05-05 17:21
sign_out
-
+
2005-05-06 09:10
sign_in
-
+
2005-05-06 12:42
sign_out
-
+
2005-05-06 13:10
sign_in
-
+
2005-05-06 18:34
sign_out
-
+
2005-05-07 08:21
sign_in
-
+
2005-05-07 18:21
sign_out
-
+
2005-05-08 08:21
sign_in
-
+
2005-05-08 12:54
sign_out
-
+
2005-05-08 13:32
sign_in
-
+
2005-05-08 19:31
sign_out
-
+
2005-05-26 07:10
sign_in
-
+
2005-05-26 12:34
sign_out
diff --git a/addons/hr_timesheet/__terp__.py b/addons/hr_timesheet/__terp__.py
index de0a42af991..617a7152031 100644
--- a/addons/hr_timesheet/__terp__.py
+++ b/addons/hr_timesheet/__terp__.py
@@ -5,9 +5,9 @@
"category" : "Generic Modules/Human Resources",
"website" : "http://tinyerp.com/module_hr.html",
"description": "Timesheet system, completly integrated with the cost accounting module. It allows you to set up a management by affair.",
- "depends" : ["account", "hr"],
+ "depends" : ["account", "hr", "base",],
"init_xml" : ["hr_timesheet_data.xml"],
- "demo_xml" : ["hr_timesheet_demo.xml","hr.analytic.timesheet.csv"],
+ "demo_xml" : ["hr_timesheet_demo.xml",],
"update_xml" : ["hr_timesheet_view.xml", "hr_timesheet_report.xml","hr_timesheet_wizard.xml"],
"active": False,
"installable": True
diff --git a/addons/hr_timesheet/hr.analytic.timesheet.csv b/addons/hr_timesheet/hr.analytic.timesheet.csv
deleted file mode 100644
index 33c9df12913..00000000000
--- a/addons/hr_timesheet/hr.analytic.timesheet.csv
+++ /dev/null
@@ -1,10 +0,0 @@
-amount,date,name,unit_amount,account_id,product_id,product_uom_id,user_id,journal_id,general_account_id
--240.0,2007-01-02,Letters,8.0,Administratif,DEV,Hour,admin,Timesheet Journal,%
--120.0,2007-01-03,Support by phone,4.0,Seagate P1,DEV,Hour,admin,Timesheet Journal,%
--120.0,2007-01-03,Support,4.0,Seagate P2,DEV,Hour,admin,Timesheet Journal,%
--240.0,2007-01-04,Repport on this,8.0,Seagate P1,DEV,Hour,admin,Timesheet Journal,%
--240.0,2007-01-05,Repport on that,8.0,Seagate P1,DEV,Hour,admin,Timesheet Journal,%
--240.0,2007-01-08,Phone support,8.0,Sednacom,DEV,Hour,admin,Timesheet Journal,%
--210.0,2007-01-09,Phone support on reporting engine,7.0,Camp To Camp,DEV,Hour,admin,Timesheet Journal,%
--240.0,2007-01-10,Quotation 234 done,8.0,Agrolait,DEV,Hour,demo,Timesheet Journal,%
--240.0,2007-01-11,Quotation 356,8.0,Agrolait,DEV,Hour,admin,Timesheet Journal,%
diff --git a/addons/hr_timesheet/hr_timesheet_demo.xml b/addons/hr_timesheet/hr_timesheet_demo.xml
index 78341e80161..1dfecf2f4b0 100644
--- a/addons/hr_timesheet/hr_timesheet_demo.xml
+++ b/addons/hr_timesheet/hr_timesheet_demo.xml
@@ -31,5 +31,115 @@
+
+
+ -240.0
+ 2005-05-04
+ Letters
+ 8.0
+
+
+
+
+
+
+
+
+ -120.0
+ 2005-05-05
+ Support by phone
+ 4.0
+
+
+
+
+
+
+
+
+ -120.0
+ 2005-05-05
+ Support
+ 4.0
+
+
+
+
+
+
+
+
+ -240.0
+ 2005-05-06
+ Repport on this
+ 8.0
+
+
+
+
+
+
+
+
+ -240.0
+ 2005-05-06
+ Repport on that
+ 8.0
+
+
+
+
+
+
+
+
+ -240.0
+ 2005-05-07
+ Phone support
+ 8.0
+
+
+
+
+
+
+
+
+ -210.0
+ 2005-05-08
+ Phone support on reporting engine
+ 7.0
+
+
+
+
+
+
+
+
+ -210.0
+ 2005-05-09
+ Quotation 234 done
+ 8.0
+
+
+
+
+
+
+
+
+ -210.0
+ 2005-05-10
+ Quotation 356
+ 8.0
+
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/__terp__.py b/addons/hr_timesheet_sheet/__terp__.py
index d63816f219d..5b0bd62b527 100644
--- a/addons/hr_timesheet_sheet/__terp__.py
+++ b/addons/hr_timesheet_sheet/__terp__.py
@@ -7,7 +7,7 @@
"description": "Timesheet by sheets",
"depends" : ["hr_timesheet", "hr_timesheet_project", "hr_timesheet_invoice"],
"init_xml" : [],
- "demo_xml" : [],
+ "demo_xml" : ["hr_timesheet_sheet_demo.xml",],
"update_xml" : ["hr_timesheet_sheet_view.xml", "hr_timesheet_workflow.xml"],
"active": False,
"installable": True
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
index 994b6f78a23..a4c6aa766a7 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet.py
@@ -161,46 +161,56 @@ class hr_timesheet_sheet(osv.osv):
return True
def date_today(self, cr, uid, ids, context):
- self.write(cr, uid, ids, {
- 'date_current': time.strftime('%Y-%m-%d')
- })
+ for sheet in self.browse(cr, uid, ids, context):
+ if DateTime.now() <= DateTime.strptime(sheet.date_from, '%Y-%m-%d'):
+ self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,})
+ elif DateTime.now() >= DateTime.strptime(sheet.date_to, '%Y-%m-%d'):
+ self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,})
+ else:
+ self.write(cr, uid, [sheet.id], {'date_current': time.strftime('%Y-%m-%d')})
return True
def date_previous(self, cr, uid, ids, context):
for sheet in self.browse(cr, uid, ids, context):
- self.write(cr, uid, [sheet.id], {
- 'date_current': (DateTime.strptime(sheet.date_current, '%Y-%m-%d') + DateTime.RelativeDateTime(days=-1)).strftime('%Y-%m-%d'),
- })
+ if DateTime.strptime(sheet.date_current, '%Y-%m-%d') <= DateTime.strptime(sheet.date_from, '%Y-%m-%d'):
+ self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,})
+ else:
+ self.write(cr, uid, [sheet.id], {
+ 'date_current': (DateTime.strptime(sheet.date_current, '%Y-%m-%d') + DateTime.RelativeDateTime(days=-1)).strftime('%Y-%m-%d'),
+ })
return True
def date_next(self, cr, uid, ids, context):
for sheet in self.browse(cr, uid, ids, context):
- self.write(cr, uid, [sheet.id], {
- 'date_current': (DateTime.strptime(sheet.date_current, '%Y-%m-%d') + DateTime.RelativeDateTime(days=1)).strftime('%Y-%m-%d'),
- })
+ if DateTime.strptime(sheet.date_current, '%Y-%m-%d') >= DateTime.strptime(sheet.date_to, '%Y-%m-%d'):
+ self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,})
+ else:
+ self.write(cr, uid, [sheet.id], {
+ 'date_current': (DateTime.strptime(sheet.date_current, '%Y-%m-%d') + DateTime.RelativeDateTime(days=1)).strftime('%Y-%m-%d'),
+ })
return True
def sign_in(self, cr, uid, ids, context):
emp_obj = self.pool.get('hr.employee')
emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
- success = emp_obj.sign_in(cr, uid, emp_id)
- self.pool.get('hr.attendance').write(cr, uid, [success], {'sheet_id': ids[0]})
+ context['sheet_id']=ids[0]
+ success = emp_obj.sign_in(cr, uid, emp_id, context=context)
return True
def sign_out(self, cr, uid, ids, context):
emp_obj = self.pool.get('hr.employee')
emp_id = emp_obj.search(cr, uid, [('user_id', '=', uid)])
- success = emp_obj.sign_out(cr, uid, emp_id)
- self.pool.get('hr.attendance').write(cr, uid, [success], {'sheet_id': ids[0]})
+ context['sheet_id']=ids[0]
+ success = emp_obj.sign_out(cr, uid, emp_id, context=context)
return True
_columns = {
'name': fields.char('Description', size=64, select=1),
'user_id': fields.many2one('res.users', 'User', required=True, select=1),
- 'date_from': fields.date('Date from', required=True, select=1),
- 'date_to': fields.date('Date to', required=True, select=1),
+ '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)]}),
'date_current': fields.date('Current date', required=True),
- 'timesheet_ids' : one2many_mod('hr.analytic.timesheet', 'sheet_id', 'Timesheets', domain=[('date','=',time.strftime('%Y-%m-%d'))], readonly=True, states={'draft':[('readonly',False)]}),
- 'attendances_ids' : one2many_mod2('hr.attendance', 'sheet_id', 'Attendances', readonly=True, states={'draft':[('readonly',False)]}),
- 'state' : fields.selection([('draft','Draft'),('confirm','Confirmed'),('done','Done')], 'state', select=True, required=True, readonly=True),
+ 'timesheet_ids' : one2many_mod('hr.analytic.timesheet', 'sheet_id', 'Timesheets', domain=[('date','=',time.strftime('%Y-%m-%d'))], readonly=True, states={'draft':[('readonly',False)],'new':[('readonly',False)]}),
+ 'attendances_ids' : one2many_mod2('hr.attendance', 'sheet_id', 'Attendances', readonly=True, states={'draft':[('readonly',False)],'new':[('readonly',False)]}),
+ 'state' : fields.selection([('new', 'New'),('draft','Draft'),('confirm','Confirmed'),('done','Done')], 'state', select=True, required=True, readonly=True),
'state_attendance' : fields.function(_state_attendance, method=True, type='selection', selection=[('absent', 'Absent'), ('present', 'Present'),('none','No employee defined')], string='Current state'),
'total_attendance_day': fields.function(_total_attendance_day, method=True, string='Total Attendance'),
'total_timesheet_day': fields.function(_total_timesheet_day, method=True, string='Total Timesheet'),
@@ -236,18 +246,50 @@ class hr_timesheet_sheet(osv.osv):
'date_from' : _default_date_from,
'date_current' : lambda *a: time.strftime('%Y-%m-%d'),
'date_to' : _default_date_to,
- 'state': lambda *a: 'draft'
+ 'state': lambda *a: 'new',
}
+ def create(self, cr, uid, vals, *args, **kwargs):
+ if 'state' in vals and vals['state'] == 'new':
+ vals['state']='draft'
+ cr.execute('select id from hr_timesheet_sheet_sheet where (date_from < %s and %s < date_to) or (date_from < %s and %s = %s and date_to <= %s)', (vals['date_from'], vals['date_from'], vals['date_to'], vals['date_to'], vals['date_from'], vals['date_to']))
+ if cr.fetchall():
+ raise osv.except_osv('Error !', 'A timesheet sheet already exists in this period')
+ return super(hr_timesheet_sheet, self).create(cr, uid, vals, *args, **kwargs)
hr_timesheet_sheet()
+def _get_current_sheet(self, cr, uid, context={}):
+ ts=self.pool.get('hr_timesheet_sheet.sheet')
+ ids = ts.search(cr, uid, [('user_id','=',uid),('state','=','draft'),('date_from','<=',time.strftime('%Y-%m-%d')), ('date_to','>=',time.strftime('%Y-%m-%d'))])
+ if ids:
+ return ids[0]
+ return False
+
+
class hr_timesheet_line(osv.osv):
- _inherit = "account.analytic.line"
+ _inherit = "hr.analytic.timesheet"
+
+ def _get_default_date(self, cr, uid, context={}):
+ if 'date' in context:
+ return context['date']
+ return time.strftime('%Y-%m-%d')
+
+ def _sheet_date(self, cr, uid, ids):
+ timesheet_lines = self.browse(cr, uid, ids)
+ for l in timesheet_lines:
+ if l.date < l.sheet_id.date_from:
+ return False
+ if l.date > l.sheet_id.date_to:
+ return False
+ return True
+
_columns = {
- 'sheet_id': fields.many2one('hr_timesheet_sheet.sheet', 'Sheet', ondelete='set null', relate=True)
+ 'sheet_id': fields.many2one('hr_timesheet_sheet.sheet', 'Sheet', ondelete='set null', required=True, relate=True)
}
- _default = {
- 'sheet_id': lambda *a: False
+ _defaults = {
+ 'sheet_id': _get_current_sheet,
+ 'date': _get_default_date,
}
+ _constraints = [(_sheet_date, 'Error: the timesheet line date must be in the sheet\'s dates', ['date'])]
def create(self, cr, uid, vals, *args, **kwargs):
if 'sheet_id' in vals:
ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, vals['sheet_id'])
@@ -269,24 +311,45 @@ hr_timesheet_line()
class hr_attendance(osv.osv):
_inherit = "hr.attendance"
+
+ def _get_default_date(self, cr, uid, context={}):
+ if 'name' in context:
+ return context['name'] + time.strftime(' %H:%M:%S')
+ return time.strftime('%Y-%m-%d %H:%M:%S')
+
+ def _sheet_date(self, cr, uid, ids):
+ attendances = self.browse(cr, uid, ids)
+ for att in attendances:
+ if att.name < att.sheet_id.date_from:
+ return False
+ if att.name > att.sheet_id.date_to:
+ return False
+ return True
+
_columns = {
- 'sheet_id': fields.many2one('hr_timesheet_sheet.sheet', 'Sheet', ondelete='set null', relate=True)
+ 'sheet_id': fields.many2one('hr_timesheet_sheet.sheet', 'Sheet', ondelete='set null', required=True, relate=True)
}
- _default = {
- 'sheet_id': lambda *a: False
+ _defaults = {
+ 'sheet_id': _get_current_sheet,
+ 'name': _get_default_date,
}
- def create(self, cr, uid, vals, *args, **kwargs):
+ _constraints = [(_sheet_date, 'Error: the attendance date must be in the sheet\'s dates', ['name'])]
+ def create(self, cr, uid, vals, context={}):
+ if 'sheet_id' in context:
+ vals['sheet_id']=context['sheet_id']
if 'sheet_id' in vals:
ts = self.pool.get('hr_timesheet_sheet.sheet').browse(cr, uid, vals['sheet_id'])
if ts.state<>'draft':
raise osv.except_osv('Error !', 'You can not modify an entry in a confirmed timesheet !')
- return super(hr_attendance,self).create(cr, uid, vals, *args, **kwargs)
+ return super(hr_attendance,self).create(cr, uid, vals, context=context)
def unlink(self, cr, uid, ids, *args, **kwargs):
self._check(cr, uid, ids)
return super(hr_attendance,self).unlink(cr, uid, ids,*args, **kwargs)
- def write(self, cr, uid, ids, *args, **kwargs):
+ def write(self, cr, uid, ids, vals, context={}):
+ if 'sheet_id' in context:
+ vals['sheet_id']=context['sheet_id']
self._check(cr, uid, ids)
- return super(hr_attendance,self).write(cr, uid, ids,*args, **kwargs)
+ return super(hr_attendance,self).write(cr, uid, ids, vals, context=context)
def _check(self, cr, uid, ids):
for att in self.browse(cr, uid, ids):
if att.sheet_id and att.sheet_id.state<>'draft':
@@ -307,7 +370,7 @@ class hr_timesheet_sheet_sheet_day(osv.osv):
def _total_attendance(self, cr, uid, ids, name, args, context):
result = {}
for day in self.browse(cr, uid, ids, context):
- cr.execute('select name,action from hr_attendance where name>=%s and name<=%s order by name', (day.name, day.name+' 23:59:59'))
+ cr.execute('select name,action from hr_attendance where name>=%s and name<=%s and sheet_id=%d order by name', (day.name, day.name+' 23:59:59', day.sheet_id))
attendences = cr.dictfetchall()
wh = 0
if attendences and attendences[0]['action'] == 'sign_out':
@@ -336,13 +399,14 @@ class hr_timesheet_sheet_sheet_day(osv.osv):
cr.execute("""create or replace view hr_timesheet_sheet_sheet_day as
(
select
- min(l.oid) as id,
+ min(hrt.id) as id,
l.date as name,
- l.sheet_id as sheet_id,
+ hrt.sheet_id as sheet_id,
sum(l.unit_amount) as total_timesheet
from
- account_analytic_line l
- group by l.date, l.sheet_id
+ hr_analytic_timesheet hrt
+ left join account_analytic_line l on (l.id = hrt.line_id)
+ group by l.date, hrt.sheet_id
) union (
select
min(a.oid) as id,
@@ -370,13 +434,14 @@ class hr_timesheet_sheet_sheet_account(osv.osv):
def init(self, cr):
cr.execute("""create or replace view hr_timesheet_sheet_sheet_account as (
select
- min(id) as id,
- account_id as name,
- sheet_id as sheet_id,
- sum(unit_amount) as total
+ min(hrt.id) as id,
+ l.account_id as name,
+ hrt.sheet_id as sheet_id,
+ sum(l.unit_amount) as total
from
- account_analytic_line
- group by account_id, sheet_id
+ hr_analytic_timesheet hrt
+ left join account_analytic_line l on (l.id = hrt.line_id)
+ group by l.account_id, hrt.sheet_id
)""")
hr_timesheet_sheet_sheet_account()
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_demo.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_demo.xml
new file mode 100644
index 00000000000..f91d5914a5d
--- /dev/null
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_demo.xml
@@ -0,0 +1,101 @@
+
+
+
+
+ Sheet 1
+
+ 2005-05-01
+ 2005-05-31
+ 2005-05-04
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
index b6a2779187d..3eb652d4f7b 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
@@ -56,7 +56,7 @@
-
+
@@ -65,7 +65,7 @@
-
+
@@ -200,5 +200,59 @@
+
+
+
+ hr.analytic.timesheet.tree
+ hr.analytic.timesheet
+ tree
+
+
+
+
+
+
+
+
+ hr.analytic.timesheet.form
+ hr.analytic.timesheet
+ form
+
+
+
+
+
+
+
+
+
+
+
+ hr.attendance.form
+ hr.attendance
+ form
+
+
+
+
+
+
+
+
+ hr.attendance.tree
+ hr.attendance
+ tree
+
+
+
+
+
+
+
+