def new_daily_record (db, cl, nodeid, new_values) : """ Only create a daily_record if a user_dynamic record exists for the user. If a new daily_record is created, we check the date provided: If hours, minutes, seconds are all zero we think the time was entered in UTC and do no conversion. If one is non-zero, we get the timezone from the user information and re-encode the date as UTC -- this effectively makes the date a 'naive' date. Then we nullify hour, minute, second of the date. After that, we check that there is no duplicate daily_record with the same date for this user. """ uid = db.getuid () common.require_attributes (_, cl, nodeid, new_values, 'user', 'date') user = new_values ['user'] ttby = db.user.get (user, 'timetracking_by') uname = db.user.get (user, 'username') if ( uid != user and uid != ttby and not common.user_has_role (db, uid, 'controlling', 'admin') ) : raise Reject, _ \ ("Only user, Timetracking by user, " "and Controlling may create daily records" ) common.reject_attributes (_, new_values, 'time_record') # the following is allowed for the admin (import!) if uid != '1' : common.reject_attributes (_, new_values, 'status') date = new_values ['date'] date.hour = date.minute = date.second = 0 new_values ['date'] = date dyn = user_dynamic.get_user_dynamic (db, user, date) if not dyn and uid != '1' : raise Reject, \ _ ("No dynamic user data for %(uname)s, %(date)s") % locals () if uid != '1' and not dyn.booking_allowed : raise Reject, _ \ ("Booking not allowed for %(uname)s, %(date)s") % locals () if frozen (db, user, date) : raise Reject, _ ("Frozen: %(uname)s, %(date)s") % locals () if db.daily_record.filter \ (None, {'date' : date.pretty ('%Y-%m-%d'), 'user' : user}) : raise Reject, _ ("Duplicate record: date = %(date)s, user = %(user)s") \ % new_values new_values ['time_record'] = [] if 'status' not in new_values : new_values ['status'] = db.daily_record_status.lookup ('open') new_values ['tr_duration_ok'] = None
def new_submission(db, cl, nodeid, new_values): """ Check that new leave submission is allowed and has sensible parameters """ common.reject_attributes(_, new_values, 'approval_hr', 'comment_cancel') uid = db.getuid() st_subm = db.leave_status.lookup('submitted') if 'user' not in new_values: user = new_values['user'] = uid else: user = new_values['user'] common.require_attributes \ (_, cl, nodeid, new_values, 'first_day', 'last_day', 'user') first_day = new_values['first_day'] last_day = new_values['last_day'] fix_dates(new_values) if 'time_wp' not in new_values: wps = vacation.valid_leave_wps \ ( db , user , last_day , [('-', 'project.is_vacation'), ('-', 'project.approval_hr')] ) if wps: new_values['time_wp'] = wps[0] common.require_attributes(_, cl, nodeid, new_values, 'time_wp') if freeze.frozen(db, user, first_day): raise Reject(_("Frozen")) comment = new_values.get('comment') check_range(db, None, user, first_day, last_day) check_wp(db, new_values['time_wp'], user, first_day, last_day, comment) is_admin = (uid == '1') if 'status' in new_values and new_values[ 'status'] != st_subm and not is_admin: raise Reject(_('Initial status must be "submitted"')) if 'status' not in new_values: new_values['status'] = st_subm if (user != uid and not (is_admin or common.user_has_role(db, uid, 'HR-vacation'))): raise Reject \ (_ ("Only special role may create submission for other user")) vacation.create_daily_recs(db, user, first_day, last_day) if vacation.leave_days(db, user, first_day, last_day) == 0: raise Reject(_("Vacation request for 0 days")) check_dr_status(db, user, first_day, last_day, 'open') check_dyn_user_params(db, user, first_day, last_day)
def deny_adr (db, cl, nodeid, new_values) : reject_attributes (_, new_values, 'adr')
def check_submission(db, cl, nodeid, new_values): """ Check that changes to a leave submission are ok. We basically allow changes of first_day, last_day, and time_wp in status 'open'. The user must never change. The status transitions are bound to certain roles. Note that this auditor is called *after* it has been verified that a requested state change is at least possible (although we still have to check the role). """ common.reject_attributes(_, new_values, 'user', 'approval_hr') old = cl.getnode(nodeid) uid = db.getuid() user = old.user old_status = db.leave_status.get(old.status, 'name') if old_status != 'accepted': common.reject_attributes(_, new_values, 'comment_cancel') new_status = db.leave_status.get \ (new_values.get ('status', old.status), 'name') if old_status != 'open': common.reject_attributes \ (_, new_values, 'first_day', 'last_day', 'time_wp', 'comment') fix_dates(new_values) first_day = new_values.get('first_day', cl.get(nodeid, 'first_day')) last_day = new_values.get('last_day', cl.get(nodeid, 'last_day')) if freeze.frozen(db, user, first_day): raise Reject(_("Frozen")) time_wp = new_values.get('time_wp', cl.get(nodeid, 'time_wp')) comment = new_values.get('comment', cl.get(nodeid, 'comment')) check_range(db, nodeid, user, first_day, last_day) check_wp(db, time_wp, user, first_day, last_day, comment) if old_status in ('open', 'submitted'): vacation.create_daily_recs(db, user, first_day, last_day) if 'first_day' in new_values or 'last_day' in new_values: if vacation.leave_days(db, user, first_day, last_day) == 0: raise Reject(_("Vacation request for 0 days")) check_dyn_user_params(db, user, first_day, last_day) if old_status in ('open', 'submitted'): check_dr_status(db, user, first_day, last_day, 'open') if old_status in ('accepted', 'cancel requested'): check_dr_status(db, user, first_day, last_day, 'leave') if old_status != new_status: if (old_status == 'accepted' and new_status == 'cancel requested'): common.require_attributes \ (_, cl, nodeid, new_values, 'comment_cancel') # Allow special HR role to do any (possible) state changes # Except for approval of own records if (common.user_has_role(db, uid, 'HR-vacation') and (uid != user or new_status not in ('accepted', 'declined', 'cancelled'))): ok = True else: ok = False tp = db.time_project.getnode \ (db.time_wp.get (old.time_wp, 'project')) if not ok and uid == user: if old_status == 'open' and new_status == 'submitted': ok = True if (old_status == 'accepted' and new_status == 'cancel requested'): ok = True if old_status == 'submitted' and new_status == 'open': ok = True if old_status == 'open' and new_status == 'cancelled': ok = True elif not ok: clearer = common.tt_clearance_by(db, user) dyn = user_dynamic.get_user_dynamic(db, user, first_day) ctype = dyn.contract_type hr_only = vacation.need_hr_approval \ (db, tp, user, ctype, first_day, last_day, old_status) if (uid != user and ((uid in clearer and not hr_only) or common.user_has_role(db, uid, 'HR-leave-approval'))): if (old_status == 'submitted' and new_status in ('accepted', 'declined')): ok = True if (old_status == 'cancel requested' and (new_status == 'cancelled' or new_status == 'accepted')): ok = True if not ok: raise Reject(_("Permission denied"))
def new_time_record (db, cl, nodeid, new_values) : """ auditor on time_record """ uid = db.getuid () travel = False common.require_attributes (_, cl, nodeid, new_values, 'daily_record') common.reject_attributes (_, new_values, 'dist', 'tr_duration') check_generated (new_values) dr = db.daily_record.getnode (new_values ['daily_record']) uname = db.user.get (dr.user, 'username') if dr.status != db.daily_record_status.lookup ('open') and uid != '1' : raise Reject, _ ('Editing of time records only for status "open"') if frozen (db, dr.user, dr.date) : date = dr.date raise Reject, _ ("Frozen: %(uname)s, %(date)s") % locals () start = new_values.get ('start', None) end = new_values.get ('end', None) duration = new_values.get ('duration', None) wpid = new_values.get ('wp') ttby = db.user.get (dr.user, 'timetracking_by') if ( uid != dr.user and uid != ttby and not common.user_has_role (db, uid, 'controlling', 'admin') and not leave_wp (db, dr, wpid, start, end, duration) and not vacation_wp (db, wpid) ) : raise Reject, _ \ ( ("Only %(uname)s, Timetracking by, and Controlling " "may create time records" ) % locals () ) dynamic = user_dynamic.get_user_dynamic (db, dr.user, dr.date) date = dr.date.pretty (common.ymd) if not dynamic : if uid != '1' : raise Reject, _ \ ("No dynamic user data for %(uname)s, %(date)s") % locals () else : if not dynamic.booking_allowed and uid != '1' : raise Reject, _ \ ("Booking not allowed for %(uname)s, %(date)s") % locals () if not (dr.weekend_allowed or dynamic.weekend_allowed) and uid != '1' : wday = gmtime (dr.date.timestamp ())[6] if wday in (5, 6) : raise Reject, _ ('No weekend booking allowed') dstart, dend = check_start_end_duration \ (dr.date, start, end, duration, new_values) # set default work location for new time record by work location ID # for ID reference values check file initial_data.py or use endpoint # /work_location in the web interface if 'work_location' not in new_values : new_values ['work_location'] = '2' # set default values according to selected work package if 'wp' in new_values and new_values ['wp'] : wp = new_values ['wp'] # overwrite work location default if default specified in time category correct_work_location (db, wp, new_values) travel = travel or db.time_wp.get (wp, 'travel') if 'time_activity' in new_values and new_values ['time_activity'] : act = new_values ['time_activity'] travel = travel or db.time_activity.get (act, 'travel') duration = new_values.get ('duration', None) ls = Date (db.user.get (dr.user, 'lunch_start') or '12:00') ls.year = dr.date.year ls.month = dr.date.month ls.day = dr.date.day ld = db.user.get (dr.user, 'lunch_duration') or 1 hours = int (ld) minutes = (ld - hours) * 60 le = ls + Interval ('%d:%d' % (hours, minutes)) if not travel and duration > 6 and start and dstart < ls and dend > ls : newrec = { 'daily_record' : new_values ['daily_record'] , 'start' : le.pretty (hour_format) } dur1 = (ls - dstart).as_seconds () / 3600. dur2 = duration - dur1 if end : dur2 -= ld newrec ['duration'] = dur2 for attr in 'wp', 'time_activity', 'work_location' : if attr in new_values and new_values [attr] : newrec [attr] = new_values [attr] new_values ['end'] = ls.pretty (hour_format) new_values ['duration'] = dur1 if dur2 > 0 : db.time_record.create (** newrec)
def check_payment(db, cl, nodeid, new_values): common.require_attributes \ (_, cl, nodeid, new_values, 'amount', 'date_payed', 'receipt_no') common.reject_attributes(_, new_values, 'invoice')
def set_ext_msg(db, cl, nodeid, new_values): common.reject_attributes(_, new_values, 'ext_tracker', 'key', 'ext_id')