def get_valid_contract(self, cr, uid, ids, date, context=None): res = {} _query_ = """ SELECT employee_id, min(id), count(*) FROM hr_contract WHERE employee_id in (%(employee)s) AND ( SELECT CASE WHEN not date_end is Null THEN (date_start, date_end) overlaps (DATE '%(date)s', DATE '%(date)s') ELSE date_start <= DATE '%(date)s' END ) GROUP BY employee_id """ % { 'employee': ','.join(map(str, ids)), 'date': tu.dt2s(date), } cr.execute(_query_) emp_con = cr.fetchall() for (emp_id, con_id, c) in emp_con: if c > 1: raise RuntimeError('More than one contract at same time for' ' employee with id=%i' % emp_id) else: res[emp_id] = con_id return res
def _get_holidays(self, cr, uid, ids, field_name, arg, context=None): """ Generate list of attendance associated to the this journal. """ res = {} data = self.read(cr, uid, ids, ['employee_id', 'date', 'turn_start', 'turn_end'], context=context) for d in data: turn_start = d['turn_start'] turn_end = d['turn_end'] employee_id = d['employee_id'][0] date = d['date'] _id = d['id'] if turn_start: date_start, date_end = turn_start, turn_end else: date_start, date_end = date, tu.dt2s(tu.d(date) + tu.timedelta(days=1)) sql_req= """ SELECT H.id AS func_id FROM hr_holidays as H WHERE (H.employee_id = %d OR H.employee_id is Null) AND (H.date_from, H.date_to) OVERLAPS ('%s'::timestamp, '%s'::timestamp) """ % (employee_id, date_start, date_end) cr.execute(sql_req) sql_res = cr.fetchall() if len(sql_res) > 0: res[_id] = map(lambda (i,): i, sql_res) else: res[_id] = [] return res
def compute(self, cr, uid, ids, context=None): lines_to_compute = [] for payroll in self.browse(cr, uid, ids, context=context): if payroll.state == "draft": self.pool.get("hr.aa.journal").build( cr, uid, tu.dt2s(tu.d(payroll.date_from)), tu.dt2s(tu.d(payroll.date_to)), context=context ) lines_to_compute += [l.id for l in payroll.line_ids] import cProfile cProfile.runctx( 'self.pool.get("hr.aa.payroll.line").compute(cr, uid, lines_to_compute)', {"self": self, "cr": cr, "uid": uid, "lines_to_compute": lines_to_compute}, None, "/tmp/compute.pstats", ) return True
def _get_day_end(self, cr, uid, ids, field_name, arg, context=None): res = {} dtc = lambda sd: tu.dt(sd.sign_out_id.name) for day in self.browse(cr, uid, ids): if day.attendance_ids: res[day.id] = tu.dt2s(max(map(lambda i: tu.dt(i.name), day.attendance_ids))) else: res[day.id] = False return res
def _get_turn_date(self, cr, uid, ids, field_name, arg, context=None): res = self._get_turn_start(cr, uid, ids, field_name, arg, context=context) if not res: return False for k in res: if res[k]: res[k] = tu.dt2s( tu.datetime.combine(tu.dt(res[k]).date(), tu.time(0))) return res
def get_valid_holidays(self, cr, uid, ids, date, context=None): res = {} _query_ = """ SELECT employee_id, id, state FROM hr_holidays WHERE employee_id in (%(employee)s) AND ( SELECT CASE WHEN not date_to is Null THEN (date_from, date_to) overlaps (DATE '%(date)s', DATE '%(date)s') ELSE date_from <= DATE '%(date)s' END ) UNION SELECT E.e, H.id, H.state FROM hr_holidays as H, (VALUES %(employee_x)s) as E(e) WHERE H.employee_id is Null AND ( SELECT CASE WHEN not H.date_to is Null THEN (H.date_from, H.date_to) overlaps (DATE '%(date)s', DATE '%(date)s') ELSE H.date_from <= DATE '%(date)s' END ) """ % { 'employee': ','.join(map(str, ids)), 'employee_x': '(' + '),('.join(map(str, ids)) + ')', 'date': tu.dt2s(date), } cr.execute(_query_) emp_hol = cr.fetchall() for (emp_id, hol_id, state) in emp_hol: if not emp_id in res: res[emp_id] = { 'draft': [], 'confirm': [], 'refuse': [], 'validate': [], 'cancel': [] } res[emp_id][state].append(hol_id) return res
def _inv_attendance(self, cr, uid, ids, field_name, value, arg, context=None): """ Store attendance from a journal. Assign employee id and set the correct datetime. """ jou_id = ids for no_se, att_id, val in value: if val: # Who is the associated journal? if jou_id == 0: if not isinstance(ids, int): raise osv.except_osv(_('Error'), _('I expect process attendance just for one journal')) jou_id = ids jou = self.browse(cr, uid, jou_id) # Check date if not out of turn time. if not jou._date_overlaps(tu.dt(val['name']))[jou.id]: an = tu.datetime.combine(tu.d(jou.date).date(), tu.dt(val['name']).time()) if not jou._date_overlaps(an)[jou.id]: an = tu.datetime.combine(tu.d(jou.date).date() + tu.timedelta(days=1), tu.dt(val['name']).time()) val['name'] = tu.dt2s(an) if not (jou._date_overlaps(tu.dt(val['name']))): raise osv.except_osv(_('Error'), _('Attendance don\'t belong to this journal')) # Sort entries att_ids = [] values = [] for no_se, att_id, val in value: if val: att_ids.append(att_id) values.append(val) att_ids.sort() values.sort(key=lambda i: i['name']) attval = dict(zip(att_ids, values)) # Store new or modification for att_id, val in zip(att_ids, values): if val: if att_id == 0: val['employee_id'] = jou.employee_id.id self.pool.get('hr.attendance').create(cr, uid, val) else: self.pool.get('hr.attendance').write(cr, uid, att_id, val) # Delete entries for no_se, att_id, val in value: if not val: self.pool.get('hr.attendance').unlink(cr, uid, att_id)
def get_valid_holidays(self, cr, uid, ids, date, context=None): res = {} _query_ = """ SELECT employee_id, id, state FROM hr_holidays WHERE employee_id in (%(employee)s) AND ( SELECT CASE WHEN not date_to is Null THEN (date_from, date_to) overlaps (DATE '%(date)s', DATE '%(date)s') ELSE date_from <= DATE '%(date)s' END ) UNION SELECT E.e, H.id, H.state FROM hr_holidays as H, (VALUES %(employee_x)s) as E(e) WHERE H.employee_id is Null AND ( SELECT CASE WHEN not H.date_to is Null THEN (H.date_from, H.date_to) overlaps (DATE '%(date)s', DATE '%(date)s') ELSE H.date_from <= DATE '%(date)s' END ) """ % { 'employee': ','.join(map(str, ids)), 'employee_x': '(' + '),('.join(map(str, ids)) + ')', 'date': tu.dt2s(date), } cr.execute(_query_) emp_hol = cr.fetchall() for (emp_id, hol_id, state) in emp_hol: if not emp_id in res: res[emp_id] = {'draft': [], 'confirm': [], 'refuse': [], 'validate': [], 'cancel': []} res[emp_id][state].append(hol_id) return res
def _get_turn_start(self, cr, uid, ids, field_name, arg, context=None): res = {} for journal in self.browse(cr, uid, ids): if journal.turn_id: wd_l = [ str(tu.d(journal.date).weekday()), '' ] ts = filter(lambda i: i.dayofweek in wd_l, journal.turn_id.timesheet_id) if len(ts) == 1: res[journal.id] = tu.dt2s(tu.d(journal.date) + tu.timedelta(hours=ts[0].hour_from)) elif len(ts) > 1: raise osv.except_osv(_('Error'), _('Overlaped turn for the journal %s.') % journal.name) else: res[journal.id] = False else: res[journal.id] = False return res
def build(self, cr, uid, date_from, date_to, context=None): emp_pool = self.pool.get('hr.employee') con_pool = self.pool.get('hr.contract') journal_ids = [] for time in tu.daterange(tu.dt(date_from), tu.dt(date_to) + tu.timedelta(days=1)): journal_date = tu.dt2s(time) emp_ids = emp_pool.search(cr, uid, [], context=context) con_ids = emp_pool.get_valid_contract(cr, uid, emp_ids, time) for (emp_id, con_id) in con_ids.items(): emp = emp_pool.browse(cr, uid, emp_id, context=context) con = con_pool.browse(cr, uid, con_id, context=context) contract_hours = ( str(time.weekday()) in [ ts.dayofweek for ts in con.turn_id.timesheet_id ] ) * con.working_hours_per_day journal = { 'name': emp.name + time.strftime(' (%d/%m/%Y)'), 'date': journal_date, 'employee_id': emp_id, 'turn_id': con.turn_id.id, 'department_id': con.department_id.id, 'contract_hours': contract_hours, } jids = self.search(cr, uid, [ ('employee_id', '=', journal['employee_id']), ('date', '=', journal['date']), ]) if len(jids) == 0: journal_ids.append(self.create(cr, uid, journal, context=context)) else: logger.notifyChannel('hr.aa.journal', netsvc.LOG_INFO, 'Yet exists journal \'%s\'' % journal['name']) self.compute(cr, uid, journal_ids, context=context) return len(journal_ids)
def _get_turn_start(self, cr, uid, ids, field_name, arg, context=None): res = {} conts = self._get_contract(cr, uid, ids, 'contract', None, context=context) items = conts.items() if len(items) == 0: return False att_ids, con_ids = tuple(map(list, zip(*items))) cons = self.pool.get('hr.contract').browse(cr, uid, con_ids) atts = self.pool.get('hr.attendance').browse(cr, uid, att_ids) for (att, cont) in zip(atts, cons): turns = [ (tu.dt(att.date) + tu.timedelta(days = int(i.dayofweek) - tu.dt(att.date).weekday(), hours=i.hour_from), tu.dt(att.date) + tu.timedelta(days = int(i.dayofweek) - tu.dt(att.date).weekday(), hours=i.hour_to + 24*(i.hour_to < i.hour_from))) for i in cont.turn_id.timesheet_id ] turns = filter(lambda (f,t): f - tu.timedelta(hours=6) <= tu.dt(att.datetime) and tu.dt(att.datetime) <= t + tu.timedelta(hours=6), turns) if len(turns) > 0: res[att.id] = tu.dt2s(turns[0][0]) else: res[att.id] = False return res
def load_attendances(self, cr, uid, ids=None, clean_at_end = None, complete_attendance = None, create_unknown_employee = None, ignore_sign_inout = None, tolerance = None, context=None): AC = AttendanceCreator(cr, uid, context=context) card_err = {} empl_err = {} empl_id = {} err = [] c = 0 emp_obj=self.pool.get('hr.employee') empl_ids = emp_obj.search(cr,uid,[]) empl_ids = emp_obj.browse(cr,uid,empl_ids) for empl in empl_ids: empl_id[empl.matricule]=empl.matricule if ids==None: ids = self.search(cr, uid, []) from datetime import datetime import csv DEBUGFILE = open('/tmp/clock.%s.csv' % datetime.today(), 'w') DEBUGCSV = csv.writer(DEBUGFILE) for clock in self.browse(cr, uid, ids): C = clock_class[clock.model](clock.uri, timeout=clock.timeout) uri=clock.uri uri = uri.replace('/','').split(':') assert(len(uri) == 3) assert(uri[0] == 'udp') server_address = uri[1] server_port = int(uri[2]) template="""<?xml version="1.0" standalone="no"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body> <GetAttLog> <ArgComKey xsi:type="xsd:integer">0</ArgComKey> <Arg> <PIN xsi:type="xsd:integer">ALL</PIN> </Arg> </GetAttLog> </SOAP-ENV:Body> </SOAP-ENV:Envelope>""" headers = {'Content-type':'text/xml', 'SOAPAction':'uri:zksoftware'} logger.notifyChannel('server-address', netsvc.LOG_DEBUG,server_address) logger.notifyChannel('server-port', netsvc.LOG_DEBUG,server_port) connection = httplib.HTTPConnection(server_address, server_port) connection.request("POST", "/iWsService", template,headers) response = connection.getresponse() dom = parseString(response.read()) print dom logs=[] # if not C.connect(): # err.append("Can't connect with clock '%s'." % clock.name) # continue for node in dom.getElementsByTagName('Row'): items={} for rows in node.childNodes: for elements in node.childNodes: for value in elements.childNodes: items[elements.nodeName]=value.toxml() logs.append(items) n=1 for log in logs: n=n+1 logger.notifyChannel('wizard.clock_reader', netsvc.LOG_DEBUG, 'Item: %i'%n) for key, value in log.iteritems() : if key=='Status': action=value if key=='WorkCode': workcode=value if key=='Verified': method=value if key=='PIN': card_id=int(value) if key=='DateTime': dt=value if action==0: action='sign_in' else: action='sign_out' # for n, card_id, method, action, dt in C.attendances(): DEBUGCSV.writerow((n,card_id, workcode, action, dt)) # assert isinstance(dt, tu.datetime) # Verifico que esta tarjeta no me haya traido problemas # previamente. if card_id in card_err: logger.notifyChannel('wizard.clock_reader', netsvc.LOG_DEBUG, '_read_clock: Card %i in the black list.'%card_id) continue # Verificar si un empleado usa esa tarjeta if not card_id in empl_id: try: empl_id[card_id] = AC.employee_id(card_id) except MultipleAssignedCardError, m: card_err[card_id] = str(m) continue except NotAssignedCardError, m: if setSome(create_unknown_employee, clock.create_unknown_employee): empl_id[card_id] = AC.create_employee(card_id) else: card_err[card_id] = str(m) continue # Verifico que este empleado no me haya traido problemas # previamente. logger.notifyChannel('wizard.clock_reader', netsvc.LOG_DEBUG, '_read_clock: Employee %i in the black list.' % empl_id[card_id]) continue # Si esta todo bien con el empleado, cargo la asistencia. if AC.exists_attendance(empl_id[card_id], dt, action): logger.notifyChannel('clock_reader.clock', netsvc.LOG_DEBUG, 'read: Attendance %i:%s:%s(%s) yet loaded.' % (empl_id[card_id], tu.dt2s(dt), action, method)) continue # Ignore action if setSome(ignore_sign_inout, clock.ignore_sign_inout): cr.execute(""" select A1.name, A1.action from hr_attendance as A1 left outer join hr_attendance as A2 on A1.employee_id=A2.employee_id AND A1.name < A2.name where A2.name is Null and A1.employee_id = %i """ % empl_id[card_id]) action = cr.fetchall() if action==0: action='sign_in' else: action='sign_out' # if len(action) == 1: # action=action[0] # action = _negative_action[action[1]] # else: # action='sign_in' r = AC.create_attendance(empl_id[card_id], dt, action, method, tolerance=setSome(tolerance, clock.tolerance), complete_attendance=setSome(complete_attendance, clock.complete_attendance)) if r != AttendanceCreator.ERROR: c = c + 1 else: logger.notifyChannel('clock_reader.clock', netsvc.LOG_INFO, 'read: Append employee %s to the black list.' % str(empl_id[card_id])) empl_err[empl_id[card_id]] = str(m)
def _get_date(self, cr, uid, ids, field_name, arg, context=None): res = map(lambda a: (a.id, tu.dt2s(tu.datetime.combine(tu.dt(a.name).date(),tu.time(0)))), self.browse(cr, uid, ids)) return dict(res)