def check_start_end_duration \
    (date, start, end, duration, new_values, dist = 0) :
    """
        either duration or both start/end must be set but not both
        of duration/end
        set duration from start/end if duration empty
        set end from start/duration if end empty
        Note: We are using naive times (with timezone 0) here, this
        means we can safely use date.pretty for converting back to
        string.
    """
    dstart = dend = None
    if dist :
        check_duration (dist)
    if start and ":" not in start :
        start = start + ":00"
    if end   and ":" not in end :
        end   = end   + ":00"
    if 'end' in new_values :
        if not start :
            attr = _ ('start')
            raise Reject, _ (''"%(attr)s must be specified") % locals ()
        if 'duration' in new_values :
            raise Reject, _ (''"Either specify duration or start/end")
        dstart, dend, sp, ep, dur = check_timestamps (start, end, date)
        duration                = dur
        new_values ['duration'] = duration
        new_values ['start']    = sp
        new_values ['end']      = ep
    else :
        check_duration (duration, 24)
        if 'duration' in new_values :
            new_values ['duration'] = duration
        if start :
            if 'start' in new_values or 'duration' in new_values :
                minutes = duration * 60
                hours   = int (duration % 60)
                minutes = minutes - hours * 60
                ds      = Date (start, offset = 0)
                t = (ds + Interval ('%d:%d' % (hours, minutes))).pretty \
                    (hour_format)
                if duration > 0 and t == '00:00' :
                    t = '24:00'
                dstart, dend, sp, ep, dur = check_timestamps (start, t, date)
                assert dur == duration
                new_values ['start'] = sp
                new_values ['end']   = ep
    if dist and dist < duration :
        duration -= dist
        if start :
            hours   = int (dist)
            minutes = (dist - hours) * 60
            if not dstart :
                dstart = Date (start, offset = 0)
            dstart = dstart + Interval ('%d:%d' % (hours, minutes))
            new_values ['start'] = dstart.pretty (hour_format)
        new_values ['duration']  = duration
    return dstart, dend
Exemple #2
0
 def testGranularity(self):
     ae = self.assertEqual
     ae(str(Date('2003-2-12', add_granularity=1)), '2003-02-12.23:59:59')
     ae(str(Date('2003-1-1.23:00', add_granularity=1)), '2003-01-01.23:00:59')
     ae(str(Date('2003', add_granularity=1)), '2003-12-31.23:59:59')
     ae(str(Date('2003-5', add_granularity=1)), '2003-05-31.23:59:59')
     ae(str(Date('2003-12', add_granularity=1)), '2003-12-31.23:59:59')
     ae(str(Interval('+1w', add_granularity=1)), '+ 14d')
     ae(str(Interval('-2m 3w', add_granularity=1)), '- 2m 14d')
Exemple #3
0
 def testCollision(self):
     # fake up an actual change
     self.action.classname = 'test'
     self.action.nodeid = '1'
     self.client.parsePropsFromForm = lambda: ({('test', '1'): {1: 1}}, [])
     self.failUnless(
         self.action.detectCollision(self.now, self.now + Interval("1d")))
     self.failIf(
         self.action.detectCollision(self.now, self.now - Interval("1d")))
     self.failIf(self.action.detectCollision(None, self.now))
Exemple #4
0
 def testIntervalSubtractYearBoundary(self):
     # force the transition over a year boundary
     now = Date('2003-01-01.00:00:00')
     then = now - Interval('2d')
     self.assertEqual(str(then), '2002-12-30.00:00:00')
     now = Date('2004-02-01.00:00:00')
     then = now - Interval('365d')
     self.assertEqual(str(then), '2003-02-01.00:00:00')
     now = Date('2005-02-01.00:00:00')
     then = now - Interval('365d')
     self.assertEqual(str(then), '2004-02-02.00:00:00')
Exemple #5
0
 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 '&nbsp'.join \
         (( self.month_link (pms, pme, '&lt;&lt;')
          , self.month
          , str (self.fdd.year)
          , self.month_link (nms, nme, '&gt;&gt;')
         ))
Exemple #6
0
    def iv_filter(self, ids):
        """ Filter invoices for 

            - invoice belongs to a running subscription
            - invoice is in the correct self.invoice_group
            - correct interval: We do not want to send invoices before
              the interval of the invoice_template has expired after
              sending the last invoice (last_sent < now - interval)
              where interval is in months
        """
        db = self.db
        retval = []
        for id in ids:
            iv = self.db.invoice.getnode(id)
            abo = self.db.abo.getnode(iv['abo'])
            if abo['end']:
                continue
            grp = self.db.abo_price.get(abo['aboprice'], 'invoice_group')
            if grp != self.invoice_group:
                continue
            ivt = self.get_iv_template(iv)
            interval = ivt['interval']
            if iv['last_sent'] > self.now - Interval('%dm' % interval):
                continue
            retval.append(iv)
        return retval
Exemple #7
0
 def create_daily_records (self) :
     self.set_request ()
     request         = self.request
     filterspec      = request.filterspec
     columns         = request.columns
     assert (request.classname == 'daily_record')
     start, end      = common.date_range (self.db, filterspec)
     self.start      = start
     self.end        = end
     max             = start + Interval ('31d')
     if end > max :
         msg = \
             ( "Error: Interval may not exceed one month: %s"
             % ' to '.join ([i.pretty (common.ymd) for i in (start, end)])
             )
         end = max
         request.filterspec ['date'] = common.pretty_range (start, end)
         url = request.indexargs_url \
             ( ''
             , { ':action'        : 'search'
               , ':template'      : 'edit'
               , ':sort'          : 'date'
               , ':group'         : 'user'
               , ':filter'        : ','.join (request.filterspec.keys ())
               , ':startwith'     : '0'
               , ':error_message' : msg
               }
             )
         raise Redirect, url
     if 'user' in filterspec :
         self.user = filterspec ['user'][0]
     else :
         self.user = self.db.getuid ()
     vacation.create_daily_recs (self.db, self.user, start, end)
     self.db.commit ()
Exemple #8
0
def next_week (db, request) :
    try :
        db  = db._db
    except AttributeError :
        pass
    start, end = common.date_range (db, request.filterspec)
    n_start = end     + Interval ('1d')
    n_end   = n_start + Interval ('6d')
    date    = common.pretty_range (n_start, n_end)
    return \
        '''javascript:
            if(submit_once()) {
              document.forms.edit_daily_record ['date'].value = '%s';
              document.edit_daily_record.submit ();
            }
        ''' % date
Exemple #9
0
def check_range(db, nodeid, uid, first_day, last_day):
    """ Check length of range and if there are any records in the given
        time-range for this user. This means either the first day of an
        existing record is inside the new range or the last day is
        inside the new range or the first day is lower than the first
        day *and* the last day is larger (new interval is contained in
        existing interval).
    """
    if first_day > last_day:
        raise Reject(_("First day may not be after last day"))
    if (last_day - first_day) > Interval('30d'):
        raise Reject(_("Max. 30 days for single leave submission"))
    range = common.pretty_range(first_day, last_day)
    both = (first_day.pretty(';%Y-%m-%d'), last_day.pretty('%Y-%m-%d;'))
    stati = [
        x for x in db.leave_status.getnodeids(retired=False)
        if db.leave_status.get(x, 'name') not in ('declined', 'cancelled')
    ]
    for f, l in ((range, None), (None, range), both):
        d = dict(user=uid, status=stati)
        if f:
            d['first_day'] = f
        if l:
            d['last_day'] = l
        r = [x for x in db.leave_submission.filter(None, d) if x != nodeid]
        if r:
            raise Reject \
                (_ ("You already have vacation requests in this time range"))
Exemple #10
0
def init(instance):
    reg = instance.registerUtil
    reg('valid_wps', vacation.valid_wps)
    reg('valid_leave_wps', vacation.valid_leave_wps)
    reg('valid_leave_projects', vacation.valid_leave_projects)
    reg('leave_days', leave_days)
    reg('user_leave_submissions', user_leave_submissions)
    reg('approve_leave_submissions', approve_leave_submissions)
    reg('approve_leave_submissions_hr', approve_leave_submissions_hr)
    reg('Leave_Buttons', Leave_Buttons)
    reg('remaining_until', remaining_until)
    reg('remaining_vacation', remaining_vacation)
    reg('consolidated_vacation', consolidated_vacation)
    reg('vacation_with_status', vacation_with_status)
    reg('flexitime_with_status', flexitime_with_status)
    reg('vacation_time_sum', vacation.vacation_time_sum)
    reg('get_vacation_correction', vacation.get_vacation_correction)
    reg('year', Interval('1y'))
    reg('day', common.day)
    reg('eoy_vacation', eoy_vacation)
    reg('Leave_Display', Leave_Display)
    reg('month_name', month_name)
    reg('flexi_alliquot', vacation.flexi_alliquot)
    reg('flexi_remain', vacation.flexi_remain)
    reg('avg_hours_per_week_this_year', avg_hours)
    reg('get_current_ctype', vacation.get_current_ctype)
    action = instance.registerAction
    action('new_leave', New_Leave_Action)
Exemple #11
0
    def testOffsetRandom(self):
        ae = self.assertEqual
        # XXX unsure of the usefulness of these, they're pretty random
        date = Date('2000-01-01') + Interval('- 2y 2m')
        ae(str(date), '1997-11-01.00:00:00')
        date = Date('2000-01-01 - 2y 2m')
        ae(str(date), '1997-11-01.00:00:00')
        date = Date('2000-01-01') + Interval('2m')
        ae(str(date), '2000-03-01.00:00:00')
        date = Date('2000-01-01 + 2m')
        ae(str(date), '2000-03-01.00:00:00')

        date = Date('2000-01-01') + Interval('60d')
        ae(str(date), '2000-03-01.00:00:00')
        date = Date('2001-01-01') + Interval('60d')
        ae(str(date), '2001-03-02.00:00:00')
Exemple #12
0
    def dr_freeze_last_frozen (db, userid, itemid) :
        """User is allowed to edit freeze record if not frozen at the
           given date.

           Check that no daily_record_freeze is active after date
        """
        df = db.daily_record_freeze.getnode (itemid)
        return not frozen (db, df.user, df.date + Interval ('1d'))
Exemple #13
0
 def testIntervalSubtractMonthBoundary(self):
     # force the transition over a month boundary
     now = Date('2003-11-01.00:00:00')
     then = now - Interval('2d')
     self.assertEqual(str(then), '2003-10-30.00:00:00')
     now = Date('2004-02-29.00:00:00')
     then = now - Interval('1d')
     self.assertEqual(str(then), '2004-02-28.00:00:00')
     now = Date('2003-03-01.00:00:00')
     then = now - Interval('1d')
     self.assertEqual(str(then), '2003-02-28.00:00:00')
     now = Date('2003-03-01.00:00:00')
     then = now - Interval('59d')
     self.assertEqual(str(then), '2003-01-01.00:00:00')
     now = Date('2004-02-29.00:00:00')
     then = now - Interval('59d')
     self.assertEqual(str(then), '2004-01-01.00:00:00')
Exemple #14
0
 def testIntervalInit(self):
     ae = self.assertEqual
     ae(str(Interval('3y')), '+ 3y')
     ae(str(Interval('2 y 1 m')), '+ 2y 1m')
     ae(str(Interval('1m 25d')), '+ 1m 25d')
     ae(str(Interval('-2w 3 d ')), '- 17d')
     ae(str(Interval(' - 1 d 2:50 ')), '- 1d 2:50')
     ae(str(Interval(' 14:00 ')), '+ 14:00')
     ae(str(Interval(' 0:04:33 ')), '+ 0:04:33')
     ae(str(Interval(8.*3600)), '+ 8:00')
Exemple #15
0
def weeksum (db, drid, format = None) :
    start, end = common.week_from_date (db.daily_record.get (drid, 'date'))
    user       = db.daily_record.get (drid, 'user')
    d   = start
    sum = 0.
    while d <= end :
        dr   = db.daily_record.filter \
            (None, dict (date = common.pretty_range (d, d), user = user))
        if len (dr) == 0 :
            d = d + Interval ('1d')
            continue
        assert (len (dr) == 1)
        dr   = dr [0]
        sum += daysum (db, dr)
        d    = d + Interval ('1d')
    if format :
        return format % sum
    return sum
def new_invoice(db, cl, nodeid, new_values):
    common.require_attributes(_, cl, nodeid, new_values, 'abo')
    abo_id = new_values.get('abo', None)
    abo = db.abo.getnode(abo_id)
    abo_price = db.abo_price.getnode(abo['aboprice'])
    abo_type = db.abo_type.getnode(abo_price['abotype'])
    common.reject_attributes \
        ( _
        , new_values
        , 'balance_open'
        , 'n_sent'
        , 'last_sent'
        , 'payer'
        , 'subscriber'
        , 'send_it'
        , 'period_start'
        , 'period_end'
        , 'invoice_no'
        , 'payment'
        , 'invoice_group'
        )
    if 'amount' not in new_values:
        new_values['amount'] = abo['amount']
    if 'currency' not in new_values:
        new_values['currency'] = abo_price['currency']
    new_values['balance_open'] = new_values['amount']
    new_values['open'] = new_values['balance_open'] > 0
    new_values['n_sent'] = 0
    new_values['payer'] = abo['payer']
    new_values['subscriber'] = abo['subscriber']
    new_values['send_it'] = False
    if not len(abo['invoices']):
        start = abo['begin']
    else:
        maxinv = abo_max_invoice(db, abo)
        start = maxinv['period_end'] + Interval('1d')
    end = start + Interval('%dm' % abo_type['period'])
    end = end - Interval('1d')
    new_values['period_start'] = start
    new_values['period_end'] = end
    new_values['invoice_no'] = "R%s%s" % (abo_id, end.pretty('%m%y'))
Exemple #17
0
 def testCollision(self):
     # fake up an actual change
     self.action.classname = 'test'
     self.action.nodeid = '1'
     self.client.parsePropsFromForm = lambda: ({
         ('test', '1'): {
             "prop1": "1"
         }
     }, [])
     props = self.action.detectCollision(self.now,
                                         self.now + Interval("1d"))
     self.assertTrue(props)
     self.action.handleCollision(props)
     self.assertEqual(
         self.client._error_message[0],
         'Edit Error: someone else has edited this test '
         '(prop1). View <a target="_blank" href="test1">their '
         'changes</a> in a new window.')
     self.assertFalse(
         self.action.detectCollision(self.now, self.now - Interval("1d")))
     self.assertFalse(self.action.detectCollision(None, self.now))
def check_alarm (db, cl, nodeid, old_values) :
    m = cl.getnode (nodeid)
    s = db.sensor.getnode (m.sensor)
    now = Date ('.')
    for a_id in db.alarm.filter (None, dict (sensor = s.id)) :
        a = db.alarm.getnode (a_id)
        # default 1h for timeout
        timeout = Interval ((a.timeout or 0) * 60 or '01:00:00')
        if not a.last_triggered or a.last_triggered + timeout < now :
            if a.is_lower and m.val < a.val :
                notify (db, a, s, m, now, a.is_lower)
            if not a.is_lower and m.val > a.val :
                notify (db, a, s, m, now, a.is_lower)
Exemple #19
0
 def testIntervalInitDate(self):
     ae = self.assertEqual
     now = Date('.')
     now.hour = now.minute = now.second = 0
     then = now + Interval('2d')
     ae((Interval(str(then))), Interval('- 2d'))
     then = now - Interval('2d')
     ae(Interval(str(then)), Interval('+ 2d'))
Exemple #20
0
 def testDateSubtract(self):
     # These are thoroughly broken right now.
     i = Date('2003-03-15.00:00:00') - Date('2003-03-10.00:00:00')
     self.assertEqual(i, Interval('5d'))
     i = Date('2003-02-01.00:00:00') - Date('2003-03-01.00:00:00')
     self.assertEqual(i, Interval('-28d'))
     i = Date('2003-03-01.00:00:00') - Date('2003-02-01.00:00:00')
     self.assertEqual(i, Interval('28d'))
     i = Date('2003-03-03.00:00:00') - Date('2003-02-01.00:00:00')
     self.assertEqual(i, Interval('30d'))
     i = Date('2003-03-03.00:00:00') - Date('2002-02-01.00:00:00')
     self.assertEqual(i, Interval('395d'))
     i = Date('2003-03-03.00:00:00') - Date('2003-04-01.00:00:00')
     self.assertEqual(i, Interval('-29d'))
     i = Date('2003-03-01.00:00:00') - Date('2003-02-01.00:00:00')
     self.assertEqual(i, Interval('28d'))
     # force the transition over a year boundary
     i = Date('2003-01-01.00:00:00') - Date('2002-01-01.00:00:00')
     self.assertEqual(i, Interval('365d'))
     i = Date('1952-01-01') - Date('1953-01-01')
     self.assertEqual(i, Interval('-366d'))
     i = Date('1953-01-01') - Date('1952-01-01')
     self.assertEqual(i, Interval('366d'))
Exemple #21
0
    def testOffsetAdd(self):
        ae = self.assertEqual
        date = Date('2000-02-28.23:59:59') + Interval('00:00:01')
        ae(str(date), '2000-02-29.00:00:00')
        date = Date('2001-02-28.23:59:59') + Interval('00:00:01')
        ae(str(date), '2001-03-01.00:00:00')

        date = Date('2000-02-28.23:58:59') + Interval('00:01:01')
        ae(str(date), '2000-02-29.00:00:00')
        date = Date('2001-02-28.23:58:59') + Interval('00:01:01')
        ae(str(date), '2001-03-01.00:00:00')

        date = Date('2000-02-28.22:58:59') + Interval('01:01:01')
        ae(str(date), '2000-02-29.00:00:00')
        date = Date('2001-02-28.22:58:59') + Interval('01:01:01')
        ae(str(date), '2001-03-01.00:00:00')

        date = Date('2000-02-28.22:58:59') + Interval('00:00:3661')
        ae(str(date), '2000-02-29.00:00:00')
        date = Date('2001-02-28.22:58:59') + Interval('00:00:3661')
        ae(str(date), '2001-03-01.00:00:00')
        date = Date('2001-03-01.00:00:00') + Interval('150y')
        ae(str(date), '2151-03-01.00:00:00')
Exemple #22
0
    def testSorting(self):
        ae = self.assertEqual
        i1 = Interval('1y')
        i2 = Interval('1d')
        l = [i1, i2]; l.sort()
        ae(l, [i2, i1])
        l = [i2, i1]; l.sort()
        ae(l, [i2, i1])
        i1 = Interval('- 2d')
        i2 = Interval('1d')
        l = [i1, i2]; l.sort()
        ae(l, [i1, i2])

        i1 = Interval("1:20")
        i2 = Interval("2d")
        i3 = Interval("3:30")
        l = [i1, i2, i3]; l.sort()
        ae(l, [i1, i3, i2])
Exemple #23
0
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
Exemple #24
0
 def testIntervalSub(self):
     ae = self.assertEqual
     ae(str(Interval('1y') - Interval('- 1y')), '+ 2y')
     ae(str(Interval('1y') - Interval('- 1m')), '+ 1y 1m')
     ae(str(Interval('1y') - Interval('- 2:40')), '+ 1y 2:40')
     ae(str(Interval('1y') - Interval('1y')), '00:00')
     ae(str(Interval('1y') - Interval('1m')), '+ 11m')
     ae(str(Interval('1:00') - Interval('- 1:00')), '+ 2:00')
     ae(str(Interval('0:50') - Interval('- 0:50')), '+ 1:40')
     ae(str(Interval('1:50') - Interval('1:50')), '00:00')
     ae(str(Interval('1:59:59') - Interval('- 00:00:01')), '+ 2:00')
     ae(str(Interval('2:00') - Interval('00:00:01')), '+ 1:59:59')
Exemple #25
0
class Freeze_Action (Action, autosuper) :

    user_required_msg = ''"User is required"
    user_invalid_msg  = ''"Invalid User"
    def get_user (self) :
        self.request = templating.HTMLRequest (self.client)
        user         = self.request.form ['user'].value
        if not user :
            raise Reject, self._ (self.user_required_msg)
        try :
            self.user = self.db.user.lookup (user)
        except KeyError :
            raise Reject, self._ (self.user_invalid_msg)
        return self.user
    # end def get_user

    def handle (self) :
        if not self.request.form ['date'].value :
            raise Reject, self._ ("Date is required")
        self.date  = Date (self.request.form ['date'].value)
        msg = []
        for u in self.users :
            date = self.date
            dyn  = user_dynamic.get_user_dynamic (self.db, u, date)
            if not dyn :
                dyn = user_dynamic.find_user_dynamic \
                    (self.db, u, date, direction = '-')
                if dyn :
                    # there must be a valid_to date, otherwise
                    # get_user_dynamic would have found something above
                    date = dyn.valid_to - common.day
                    assert (date < self.date)
            if dyn :
                try :
                    self.db.daily_record_freeze.create \
                        (date = date, user = u, frozen = 1)
                except Reject, cause :
                    msg.append ((str (cause), u))
        self.db.commit ()
        if msg :
            msg.sort ()
            old   = None
            o_u   = None
            count = 1
            new_m = []
            msg.append ((None, None))
            for m, u in msg :
                if m == old :
                    count += 1
                else :
                    if old :
                        if count > 1 :
                            new_m.append ('%s (%d)' % (old, count))
                        else :
                            new_m.append \
                                ( '%s (%s)'
                                % (old, self.db.user.get (o_u, 'username'))
                                )
                    count = 1
                    old   = m
                    o_u   = u
            msg = new_m [:10]
            msg = '@ok_message=Warning: ' + '<br>Warning: '.join (msg) + '&'
        else :
            msg = ''
        url = \
            ( 'daily_record_freeze?'
            + msg
            + ':columns=id,date,user,frozen,balance,validity_date'
            + '&:sort=user,date&:filter=creation'
            + '&:pagesize=200&:startwith=0&creation=%s%%3B'
            ) % (Date ('.') - Interval ('00:05'))
        raise Redirect, url
Exemple #26
0
def approvals_pending (db, request, userlist) :
    try :
        db  = db._db
    except AttributeError :
        pass
    pending   = {}
    submitted = db.daily_record_status.lookup ('submitted')
    spec      = copy (request.filterspec)
    filter    = request.filterspec
    editdict  = {':template' : 'edit', ':filter' : 'user,date'}
    now       = Date ('.')
    for u in userlist :
        find_user   = dict (user = u, status = submitted)
        fdate       = None
        last_frozen = db.daily_record_freeze.filter \
            ( None
            , dict (user = u, date = now.pretty (';%Y-%m-%d'), frozen = True)
            , group = [('-', 'date')]
            )
        if last_frozen :
            fdate = db.daily_record_freeze.get (last_frozen [0], 'date') \
                  + common.day
            find_user ['date'] = fdate.pretty ('%Y-%m-%d;')
        dr_per_user = db.daily_record.filter (None, find_user)
        pending [u] = {}
        if dr_per_user :
            earliest = latest = None
            for p in dr_per_user :
                date = db.daily_record.get (p, 'date')
                week, year = common.weekno_year_from_day (date)
                if not earliest or date < earliest :
                    earliest = date
                if not latest   or date > latest :
                    latest   = date
                start, end = common.week_from_date (date)
                if fdate and start < fdate :
                    start = fdate
                filter ['date'] = common.pretty_range (start, end)
                filter ['user'] = u
                pending [u][(year, week)] = \
                    [ None
                    , request.indexargs_url ('', editdict)
                    , 'todo'
                    ]
            interval = latest - earliest
            for k in pending [u].iterkeys () :
                if interval < Interval ('31d') :
                    filter ['date'] = common.pretty_range (earliest, latest)
                    pending [u][k][0] = request.indexargs_url ('', editdict)
                else :
                    pending [u][k][0] = pending [u][k][1]
        else :
            dyn = user_dynamic.last_user_dynamic (db, u)
            if dyn and (not dyn.valid_to or not fdate or dyn.valid_to > fdate) :
                date = now
                if dyn.valid_to and dyn.valid_to < date :
                    date = dyn.valid_to
                week, year = common.weekno_year_from_day (date)
                start, end = common.week_from_date (date)
                if fdate and start < fdate :
                    start = fdate
                if dyn.valid_to and dyn.valid_to < end :
                    end   = dyn.valid_to
                filter ['date'] = common.pretty_range (start, end)
                filter ['user'] = u
                url = request.indexargs_url ('', editdict)
                pending [u][(year, week)] = [url, url, 'done']
    request.filterspec = spec
    return pending
Exemple #27
0
 def testDivision(self):
     ae = self.assertEqual
     ae(str(Interval('1y')/2), '+ 6m')
     ae(str(Interval('1:00')/2), '+ 0:30')
     ae(str(Interval('00:01')/2), '+ 0:00:30')
Exemple #28
0
 def ae(spec, pretty):
     self.assertEqual(Interval(spec).pretty(), pretty)
def html_calendar (request) :
    """returns a html calendar.

    `request`  the roundup.request object
               - @template : name of the template
               - form      : name of the form to store back the date
               - property  : name of the property of the form to store
                             back the date
               - date      : current date
               - display   : when browsing, specifies year and month

    html will simply be a table.
    """
    #print request.form
    date_str  = request.form.getfirst ("date", ".")
    display   = request.form.getfirst ("display", date_str)
    template  = request.form.getfirst ("@template", "calendar")
    form      = request.form.getfirst ("form")
    property  = request.form.getfirst ("property")
    curr_date = Date (date_str) # to highlight
    display   = Date (display)  # to show
    year      = display.year
    month     = display.month
    day       = display.day

    # for navigation
    date_prev_month = display + Interval ("-1m")
    date_next_month = display + Interval ("+1m")
    date_prev_year  = display + Interval ("-1y")
    date_next_year  = display + Interval ("+1y")

    res      = []
    res.append ("""<table class="calendar">""")

    base_link = "%s?@template=%s&property=%s&form=%s&date=%s" % \
                (request.classname, template, property, form, curr_date)

    # navigation
    # month
    res.append (""" <tr>""")
    res.append ("""  <td>""")
    res.append ("""   <table width="100%" class="calendar_nav">""")
    res.append ("""    <tr>""")
    link = base_link + "&display=%s" % date_prev_month
    res.append ("""     <td><a href="%s">&lt;</a></td>""" % link)
    res.append ("""     <td>%s</td>""" % calendar.month_name [month])
    link = base_link + "&display=%s" % date_next_month
    res.append ("""     <td><a href="%s">&gt;</a></td>""" % link)
    # spacer
    res.append ("""     <td width="100%"></td>""")
    # year
    link = base_link + "&display=%s" % date_prev_year
    res.append ("""     <td><a href="%s">&lt;</a></td>""" % link)
    res.append ("""     <td>%s</td>""" % year)
    link = base_link + "&display=%s" % date_next_year
    res.append ("""     <td><a href="%s">&gt;</a></td>""" % link)
    res.append ("""    </tr>""")
    res.append ("""   </table>""")
    res.append ("""  </td>""")
    res.append (""" </tr>""")

    # the calendar
    res.append (""" <tr>""")
    res.append ("""  <td>""")
    res.append ("""   <table class="calendar_display">""")
    res.append ("""    <tr class="weekdays">""")
    for day_ in calendar.weekheader (3).split () :
        res.append \
               ("""     <td>%s</td>""" % day_)
    res.append ("""    </tr>""")

    for week_ in calendar.monthcalendar (year, month) :
        res.append \
               ("""    <tr>""")
        for day_ in week_ :
            link = "javascript:form[field].value = '%d-%02d-%02d'; " \
                              "window.close ();" % (year, month, day_)
            #print curr_date, day_, month, year
            if day_  == curr_date.day   and \
               month == curr_date.month and \
               year  == curr_date.year :
                # highlight
                style = "today"
            else :
                style = ""
            if day_ :
                res.append \
               ("""     <td class="%s"><a href="%s">%s</a></td>""" %
                          (style, link, day_))
            else :
                res.append \
               ("""     <td></td>""")
        res.append \
               ("""    </tr>""")
    res.append ("""   </table>""")
    res.append ("""  </tb>""")
    res.append (""" </tr>""")
    res.append ("""</table>""")
    return "\n".join (res)
Exemple #30
0
    def testOffsetSub(self):
        ae = self.assertEqual
        date = Date('2000-12-01') - Interval('- 1d')

        date = Date('2000-01-01') - Interval('- 2y 2m')
        ae(str(date), '2002-03-01.00:00:00')
        date = Date('2000-01-01') - Interval('2m')
        ae(str(date), '1999-11-01.00:00:00')

        date = Date('2000-03-01') - Interval('60d')
        ae(str(date), '2000-01-01.00:00:00')
        date = Date('2001-03-02') - Interval('60d')
        ae(str(date), '2001-01-01.00:00:00')

        date = Date('2000-02-29.00:00:00') - Interval('00:00:01')
        ae(str(date), '2000-02-28.23:59:59')
        date = Date('2001-03-01.00:00:00') - Interval('00:00:01')
        ae(str(date), '2001-02-28.23:59:59')

        date = Date('2000-02-29.00:00:00') - Interval('00:01:01')
        ae(str(date), '2000-02-28.23:58:59')
        date = Date('2001-03-01.00:00:00') - Interval('00:01:01')
        ae(str(date), '2001-02-28.23:58:59')

        date = Date('2000-02-29.00:00:00') - Interval('01:01:01')
        ae(str(date), '2000-02-28.22:58:59')
        date = Date('2001-03-01.00:00:00') - Interval('01:01:01')
        ae(str(date), '2001-02-28.22:58:59')

        date = Date('2000-02-29.00:00:00') - Interval('00:00:3661')
        ae(str(date), '2000-02-28.22:58:59')
        date = Date('2001-03-01.00:00:00') - Interval('00:00:3661')
        ae(str(date), '2001-02-28.22:58:59')
        date = Date('2001-03-01.00:00:00') - Interval('150y')
        ae(str(date), '1851-03-01.00:00:00')