def month_links(self): """ Return month name with links to prev/next month """ pms = self.fdd - Interval('1m') nms = self.fdd + Interval('1m') pme = common.end_of_month(pms) nme = common.end_of_month(nms) return ' '.join \ (( self.month_link (pms, pme, '<<') , self.month , str (self.fdd.year) , self.month_link (nms, nme, '>>') ))
def consolidated_vacation \ (db, user, ctype = -1, date = None, vc = None, to_eoy = True) : """ Compute remaining vacation on the given date """ if date is None : date = Date ('.') if ctype == -1 : ctype = _get_ctype (db, user, date) if ctype == -1 : return vc = vc or get_vacation_correction (db, user, ctype, date) if not vc : return None ed = next_yearly_vacation_date (db, user, ctype, date) if not to_eoy : ed = min (ed, date + common.day) d = vc.date dyn = vac_get_user_dynamic (db, user, ctype, d) while dyn and dyn.valid_to and dyn.valid_to <= d : dyn = vac_next_user_dynamic (db, dyn) if dyn is None : return None vac = float (vc.days) msg = "vac_aliq None for user_dynamic%s" % dyn.id assert dyn.vac_aliq, msg va = db.vac_aliq.getnode (dyn.vac_aliq) assert va.name in ('Daily', 'Monthly') # Need to skip first period without a dyn user record # sd is the current start date for german aliquotation # We subtract 1 day to easily compare the day of the ending-date # with the day of the start date sd = d # This is used for corrections if the start day lies beyond 28 -- in # that case there are months that simply don't have that date. So we # must correct for this in months with less days. sd_day = 0 if dyn.valid_from > d : sd = d = dyn.valid_from while dyn and d < ed : if dyn.valid_from > d : # We want to check if the days that are lost here whenever a # jump in dyn user records occurs are OK for monthly aliqotation sd = d = dyn.valid_from continue assert not dyn.valid_to or dyn.valid_to > d eoy = Date ('%s-12-31' % d.year) msg = "vacation_yearly None for user_dynamic%s" % dyn.id assert dyn.vacation_yearly is not None, msg msg = ( "vac_aliq changes w/o absolute vac_corr for user_dynamic%s" % dyn.id ) assert dyn.vac_aliq == va.id, msg if dyn.valid_to and dyn.valid_to <= ed and dyn.valid_to < eoy : if va.name == 'Daily' : yd = float (common.ydays (dyn.valid_to)) vac += interval_days \ (dyn.valid_to - d) * dyn.vacation_yearly / yd else : md = month_diff (sd, dyn.valid_to) dy = sd_day or sd.day if dyn.valid_to.day < dy : md -= 1 # Example: sd = 2018-04-03 valid_to = 2018-06-01 # Need to set sd=2018-05-03, i.e. the next start # day before valid_to # Even more complex is the case where e.g. # sd = 2018-03-31 valid_to = 2018-05-01 # We set sd=2018-04-30 and sd_day=31 # Get last day of last month lm = dyn.valid_to - Interval ('%sd' % dyn.valid_to.day) em = common.end_of_month (lm) if dy > em.day : sd_day = sd.day sd = em else : sd = Date (lm.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 else : sd = Date (dyn.valid_to.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 d = dyn.valid_to vac += dyn.vacation_yearly * md / 12.0 dyn = vac_next_user_dynamic (db, dyn) elif eoy < ed : if va.name == 'Daily' : yd = float (common.ydays (eoy)) iv = eoy + common.day - d vac += interval_days (iv) * dyn.vacation_yearly / yd else : md = month_diff (sd, eoy) dy = sd_day or sd.day assert eoy.day >= dy if dy == 1 : md += 1 sd = eoy + common.day else : sd = Date (eoy.pretty ("%%Y-%%m-%s" % sd.day)) sd_day = 0 vac += dyn.vacation_yearly * md / 12.0 d = eoy + common.day if dyn.valid_to == d : dyn = vac_next_user_dynamic (db, dyn) else : if va.name == 'Daily' : yd = float (common.ydays (ed - common.day)) vac += interval_days (ed - d) * dyn.vacation_yearly / yd else : md = month_diff (sd, ed) dy = sd_day or sd.day if ed.day < dy : md -= 1 sd = ed vac += dyn.vacation_yearly * md / 12.0 d = ed return vac
def __init__(self, db, request): self.db = db = db._db now = Date('.') user = None dt = None department = None supervisor = None self.filterspec = request.filterspec self.request = request if request.filterspec: if 'first_day' in request.filterspec: dt = request.filterspec['first_day'] if 'user' in request.filterspec: user = request.filterspec['user'] if 'supervisor' in request.filterspec: supervisor = request.filterspec['supervisor'] if 'department' in request.filterspec: department = request.filterspec['department'] if not dt: som = common.start_of_month(now) eom = common.end_of_month(now) dt = common.pretty_range(som, eom) try: fd, ld = dt.split(';') except ValueError: fd = ld = dt self.fdd = fdd = Date(fd) self.ldd = ldd = Date(ld) self.month = month_name(self.fdd) if common.start_of_month(fdd) != common.start_of_month(ldd): self.ldd = ldd = common.end_of_month(fdd) dt = common.pretty_range(fdd, ldd) srt = [('+', a) for a in ('lastname', 'firstname')] self.users = users = [] if user: self.users = users = db.user.filter(user, {}, sort=srt) if supervisor: u = db.user.filter \ (None, dict (supervisor = supervisor), sort = srt) users.extend(u) if department: u = db.user.filter \ (None, dict (department = department), sort = srt) users.extend(u) valid = db.user_status.lookup('valid') if not self.users: users = db.user.filter(None, dict(status=valid), sort=srt) self.users = users else: users = db.user.filter(users, dict(status=valid), sort=srt) self.users = users acc = db.leave_status.lookup('accepted') flt = dict \ ( first_day = ';%s' % fd , last_day = '%s;' % ld , user = users , status = acc ) sp = ('user.lastname', 'user.firstname', 'first_day') srt = [('+', a) for a in sp] lvfirst = db.leave_submission.filter \ (None, dict (first_day = dt, user = users, status = acc)) lvlast = db.leave_submission.filter \ (None, dict (last_day = dt, user = users, status = acc)) lvperiod = db.leave_submission.filter(None, flt) lvs = dict.fromkeys(lvfirst + lvlast + lvperiod).keys() # Put them in a dict by user-id self.lvdict = {} for id in lvs: lv = db.leave_submission.getnode(id) if lv.user not in self.lvdict: self.lvdict[lv.user] = [] self.lvdict[lv.user].append(lv) # Get all absence records in the given time range, same algo as for if 'status' in flt: del flt['status'] abfirst = db.absence.filter \ (None, dict (first_day = dt, user = users)) ablast = db.absence.filter \ (None, dict (last_day = dt, user = users)) abperiod = db.absence.filter(None, flt) abs = dict.fromkeys(abfirst + ablast + abperiod).keys() # Put them in a dict by user-id self.abdict = {} for id in abs: ab = db.absence.getnode(id) if ab.user not in self.abdict: self.abdict[ab.user] = [] self.abdict[ab.user].append(ab) # Get public holidays srt = [('+', 'date')] ph = db.public_holiday.filter(None, dict(date=dt), sort=srt) # Index by location and sort by date self.by_location = {} for id in ph: holiday = db.public_holiday.getnode(id) for loc in holiday.locations: if loc not in self.by_location: self.by_location[loc] = [] self.by_location[loc].append(holiday) self.abs_v = db.absence_type.getnode(db.absence_type.lookup('V')) self.abs_a = db.absence_type.getnode(db.absence_type.lookup('A'))