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
Beispiel #2
0
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)
Beispiel #3
0
def deny_adr (db, cl, nodeid, new_values) :
    reject_attributes (_, new_values, 'adr')
Beispiel #4
0
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')
Beispiel #7
0
def set_ext_msg(db, cl, nodeid, new_values):
    common.reject_attributes(_, new_values, 'ext_tracker', 'key', 'ext_id')