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