예제 #1
0
    def invoke(self, _clerk, server='%'):
        mod = Model(readable=readable)
        yesterday = Date("today") - 1
        mod["server"] = server
        cur = _clerk.storage.dbc.cursor()
        sql =\
            """
            SELECT u.username, p.name, s.name, t.traffic
            FROM sys_user u, sys_user_traffic t, sys_server s, sys_plan p
            WHERE u.ID=t.userID
              AND p.ID=u.planID
              AND s.ID=u.serverID
              AND t.whichday = '%s'
              AND s.name like '%s%%'
            ORDER BY traffic DESC
            LIMIT 20
            """ % (yesterday.toSQL(), mod["server"])
        cur.execute(sql)
        mod["each"] = [{
            "username": username,
            "plan": plan,
            "server": server,
            "traffic": traffic,
        } for username, plan, server, traffic in cur.fetchall()]

        cur.execute("""
            SELECT name FROM sys_server
            """)
        mod["servers"] = [{"server": row[0]} for row in cur.fetchall()]
        return mod
예제 #2
0
    def invoke(self, _clerk, server='%'):
        mod = Model(readable = readable)
        yesterday = Date("today")-1        
        mod["server"] = server
        cur = _clerk.storage.dbc.cursor()
        sql =\
            """
            SELECT u.username, p.name, s.name, t.traffic
            FROM sys_user u, sys_user_traffic t, sys_server s, sys_plan p
            WHERE u.ID=t.userID
              AND p.ID=u.planID
              AND s.ID=u.serverID
              AND t.whichday = '%s'
              AND s.name like '%s%%'
            ORDER BY traffic DESC
            LIMIT 20
            """ % (yesterday.toSQL(), mod["server"])
        cur.execute(sql)
        mod["each"] = [{
            "username":username,
            "plan": plan,
            "server":server,
            "traffic":traffic,
            } for username, plan, server,traffic in cur.fetchall()]

        cur.execute(
            """
            SELECT name FROM sys_server
            """)
        mod["servers"] = [{"server":row[0]} for row in cur.fetchall()]
        return mod
예제 #3
0
 def test_comparisons(self):
     assert DateTime("06/20/1950 08:30:00") \
            == "1950-6-20 8:30:00", "eq string compare"
     assert DateTime("01/01/2001 00:00:00") \
            == Date("01/01/2001"), "eq comparison"
     assert Date("2001-5-1") <= DateTime("5/1/2001 0:0:0"), \
            "le comparison"
     assert Date("5/1/2001") < DateTime("2001-5-1 00:00:01"), \
            "lt comparison"
예제 #4
0
    def test_postComment(self):
        n = self.c.store(Node(name="adsf"))
        self.p.input["node"] = n.ID
        self.p.input["content"] = "your ad here"
        self.assertRaises(weblib.Redirect, self.p.postComment)

        n = self.c.fetch(Node, ID=n.ID)
        assert len(n.comments) == 1
        assert n.comments[0].content == "your ad here"
        assert Date(n.comments[0].posted.toSQL()) == Date("today")
예제 #5
0
    def test_balance(self):
        acc = fakeAccount()
        nEv = duckbill.newEvent

        assert acc.balance() == 0
        acc.events << nEv("charge", posted="1/1/2001", amount=5)
        assert acc.balance() == 5
        assert acc.balance(Date("12/31/2000")) == 0
        assert acc.balance(Date("1/1/2001")) == 0
        assert acc.balance(Date("1/2/2001")) == 5
예제 #6
0
    def testVestingPreconditions(self):
        "make sure Event requires valid dates in order"
        e = Event(event="charge", amount="100")
        e.maturity=None; e.posted = "1/1/2002"
        self.assertRaises(AssertionError, e.percentVested, Date("1/1/2002"))

        e.posted = None; e.maturity = "1/1/2002"
        self.assertRaises(AssertionError, e.percentVested, Date("1/1/2002"))

        e.posted = "1/2/2002"; e.maturity = "1/1/2002"
        self.assertRaises(AssertionError, e.percentVested, Date("1/1/2002"))
예제 #7
0
    def test_openBalance(self):

        assert Statement(self.acc).openBal == 0
        assert Statement(self.acc).closeBal == 0
        self.acc.events << duckbill.newEvent(
            "charge", amount=5, posted=DateTime("now"))
        assert Statement(self.acc).openBal == 0, \
                "Expected opening balance of 0, got %s" % Statement(self.acc).openBal
        assert Statement(self.acc, start=Date("today"), end=Date("today")+1).closeBal == 5, \
                "Expected closing balance of 5, got %s" \
                % Statement(self.acc, end=Date("today")+1).closeBal
예제 #8
0
 def check_today(self):
     """
     temporarily set time.time() to return 10/19/2001
     and test for today.
     """
     import time
     _time = time.time
     time.time = lambda: 1003539807.89
     try:
         assert Date("today") == Date("10/19/2001"), "wrong date"
     finally:
         time.time = _time
예제 #9
0
 def test_viewNode_comment(self):
     n = Node(name="abc")
     n.comments << Comment(content="a", posted=Date("today") - 1)
     n.comments << Comment(content="c", posted=Date("today") - 3)
     n.comments << Comment(content="b", posted=Date("today") - 2)
     self.c.store(n)
     self.p.input["ID"] = n.ID
     m = self.p.viewNode()
     self.assertEquals(3, len(m["comments"]))
     # and we want newest first:
     self.assertEquals(["a", "b", "c"],
                       [c["content"] for c in m["comments"]])
예제 #10
0
    def test_calcNextDue(self):
        """
        By default, calcNextDue should return one month after nextDue.
        """
        cyc = duckbill.Cyclic()
        cyc.nextDue = "1/1/2001"
        assert cyc.calcNextDue() == Date("2/1/2001"), \
               "expected 2/1/01, got: " + repr(cyc.calcNextDue())

        cyc.nextDue = "1/31/2001"
        assert cyc.calcNextDue() == Date("3/3/2001"), \
               "expected 3/3/01, got: " + repr(cyc.calcNextDue())
예제 #11
0
 def test_whenLastStatementPosted(self):
     """
     This should find the statement with the latest 'posted' time.
     """
     acc = fakeAccount()
     acc.opened = Date("1/1/2001")
     assert acc.whenLastStatementPosted() == Date("1/1/2001")
     assert len(acc.events) == 0
     acc.events << duckbill.newEvent("statement", posted="2/1/2001")
     acc.events << duckbill.newEvent("statement", posted="5/1/2001")
     acc.events << duckbill.newEvent("statement", posted="3/1/2001")
     acc.events << duckbill.newEvent("statement", posted="1/1/2001")
     assert acc.whenLastStatementPosted() == Date("5/1/2001")
예제 #12
0
def showchart(REQ, RES, CLERK):

    ## find the user's bandwidth plan
    assert REQ.has_key("username")
    username = REQ["username"]


    uobj = CLERK.fetch(User, username=username)
    limit = uobj.bandquota
    assert limit!=0, "bandquota should never be zero" # divide by 0 = bad

    ## create a list of the past 30 days
    last30days = []
    day = Date("today")
    for i in range(30):
        day -= 1
        last30days.append(day.toSQL())
    last30days.reverse()


    ## fetch last 30 entries
    ## (hopefully last 30 days, but some days could be missing)
    cur = CLERK.storage.dbc.cursor() #@TODO: fix this!!
    cur.execute(
        """
        SELECT t.whichday, t.traffic
        FROM sys_user u, sys_user_traffic t
        WHERE u.ID=t.userID
          AND u.username='******'
        ORDER BY t.whichday DESC
        LIMIT 30
        """ % username)
    hash = {}
    for (rawdate, traffic) in cur.fetchall():
        date = Date(rawdate).toSQL()
        hash[date] = traffic


    ## now get our actual 30 days, possibly with gaps:
    data = []
    for day in last30days:
        if hash.has_key(day):
            data.append(hash[day])
        else:
            data.append(None)

    # show the image:
    RES.contentType="image/png"
    chart = pid.PILCanvas(size=(250,100))
    LimitChart(250,100, limit, data).draw(chart)
    chart.save(file=RES, format="png")
예제 #13
0
    def testVesting(self):
        "ensure charges are slowly 'earned' over time"
        e = Event(event="charge",
                  amount="50",
                  posted="1/1/2000",
                  maturity="11/1/2000")
        assert e.percentVested(e.posted) == 0
        assert e.percentVested(e.posted - 1) == 0
        assert e.percentVested(e.maturity) == 100
        assert e.percentVested(e.maturity + 1) == 100

        #@TODO: paramaterize number of decimal places ?

        # In a single month, we're fully vested at the end of the month.
        # With a yearly charge, the vesting happens slowly over time.
        d = Decimal
        self.assertEquals(e.percentVested(Date("2/1/2000")), d('10.16'))
        self.assertEquals(e.percentVested(Date("5/1/2000")), d('39.67'))
        self.assertEquals(e.percentVested(Date("7/1/2000")), d('59.67'))
        self.assertEquals(e.percentVested(Date("10/1/2000")), d('89.84'))
        self.assertEquals(e.percentVested(Date("10/31/2000")), d('99.67'))
        self.assertEquals(e.percentVested(Date("11/1/2000")), d('100.00'))
        self.assertEquals(e.percentVested(Date("12/1/2000")), d('100.00'))

        # valueOn should multiply by amount
        e.amount = 200
        self.assertEquals(e.valueOn(Date("2/1/2000")), d('20.32'))
예제 #14
0
    def testReportWithTime(self):
        today = Date("today")
        yesterday = today - 1
        tomorrow = today + 1
        nextday = today + 2
        events = [
            chg(5, yesterday),
            pay(10, today),
            chg(3, tomorrow, tomorrow),
            chg(5, nextday, nextday)
        ]
        self.assertEquals(unearned(events, yesterday), 0)
        self.assertEquals(unearned(events, today), 5)
        self.assertEquals(unearned(events, tomorrow), 2)
        self.assertEquals(unearned(events, nextday), 0)

        c, p = chg(100, today, today + 30), pay(100, today)
        for x in range(-50, 0):
            day = today + x
            goal = 0
            actual = unearned([c, p], day)
            assert actual == goal, "%s vs %s on day %s" % (actual, goal, x)
        for x in range(0, 50):
            day = today + x
            goal = c.amount - c.valueOn(day)
            actual = unearned([c, p], day)
            assert actual == goal, "%s vs %s on day %s" % (actual, goal, x)
예제 #15
0
 def test_amountPastDue(self):
     acc = self.oldAccount()
     assert acc.amountPastDue(Date("today")) == 25
     assert acc.amountPastDue("today") == 25
     assert acc.amountPastDue("4/1/2002") == 15
     assert acc.amountPastDue("1/15/2002") == 10
     assert acc.amountPastDue("1/1/2002") == 0
예제 #16
0
def showchart(REQ, RES, CLERK):

    ## find the user's bandwidth plan
    assert REQ.has_key("username")
    username = REQ["username"]

    uobj = CLERK.fetch(User, username=username)
    limit = uobj.bandquota
    assert limit != 0, "bandquota should never be zero"  # divide by 0 = bad

    ## create a list of the past 30 days
    last30days = []
    day = Date("today")
    for i in range(30):
        day -= 1
        last30days.append(day.toSQL())
    last30days.reverse()

    ## fetch last 30 entries
    ## (hopefully last 30 days, but some days could be missing)
    cur = CLERK.storage.dbc.cursor()  #@TODO: fix this!!
    cur.execute("""
        SELECT t.whichday, t.traffic
        FROM sys_user u, sys_user_traffic t
        WHERE u.ID=t.userID
          AND u.username='******'
        ORDER BY t.whichday DESC
        LIMIT 30
        """ % username)
    hash = {}
    for (rawdate, traffic) in cur.fetchall():
        date = Date(rawdate).toSQL()
        hash[date] = traffic

    ## now get our actual 30 days, possibly with gaps:
    data = []
    for day in last30days:
        if hash.has_key(day):
            data.append(hash[day])
        else:
            data.append(None)

    # show the image:
    RES.contentType = "image/png"
    chart = pid.PILCanvas(size=(250, 100))
    LimitChart(250, 100, limit, data).draw(chart)
    chart.save(file=RES, format="png")
예제 #17
0
def parseQif(infile):
    """
    Parse a qif file and return a list of entries.
    infile should be open file-like object (supporting readline() ).
    """

    inItem = False

    items = []
    curItem = QifItem()
    line = infile.readline()
    while line != '':
        if line[0] == '\n':  # blank line
            pass
        elif line[0] == '^':  # end of item
            # save the item
            items.append(curItem)
            curItem = QifItem()
        elif line[0] == 'D':
            curItem.date = fmtDate(
                Date(line[1:-1].replace("' ", "/200").replace(" ", "")))
        elif line[0] == 'T':
            curItem.amount = line[1:-1]
        elif line[0] == "U":
            pass  # same as T
        elif line[0] == "N":
            curItem.num = line[1:-1]
        elif line[0] == 'C':
            curItem.cleared = line[1:-1]
        elif line[0] == 'P':
            curItem.payee = line[1:-1]
        elif line[0] == 'M':
            curItem.memo = line[1:-1]
        elif line[0] == 'A':
            curItem.address = line[1:-1]
        elif line[0] == 'L':
            curItem.category = line[1:-1]
        elif line[0] == 'S':
            try:
                curItem.categoryInSplit.append(";" + line[1:-1])
            except AttributeError:
                curItem.categoryInSplit = line[1:-1]
        elif line[0] == 'E':
            try:
                curItem.memoInSplit.append(";" + line[1:-1])
            except AttributeError:
                curItem.memoInSplit = line[1:-1]
        elif line[0] == '$':
            try:
                curItem.amountInSplit.append(";" + line[1:-1])
            except AttributeError:
                curItem.amountInSplit = line[1:-1]
        else:
            # don't recognise this line; ignore it
            print >> sys.stderr, "Skipping unknown line:\n", line

        line = infile.readline()
    return items
예제 #18
0
 def amountPastDue(self, dueDate="today"):
     """
     Given a dueDate, return the amount past due.
     This may be less than the total balance.
     """
     d = dueDate
     if not isinstance(d, Date):
         d = Date(dueDate)
     res = 0
     for e in self.aging():
         if e.posted < dueDate:
             res += e.value
     return res
예제 #19
0
    def test_eventsBetween(self):
        acc = fakeAccount()
        then = Date("1/1/2001")
        now = Date("5/1/2001") # not really :)

        # start with nothing.
        assert len(acc.eventsBetween(then, now)) == 0

        # include the front date:        
        acc.events << duckbill.newEvent("payment", posted="1/1/2001")
        assert len(acc.eventsBetween(then, now)) == 1, "start"

        # exclude the end date:
        acc.events << duckbill.newEvent("note", posted="5/1/2001")
        assert len(acc.eventsBetween(then, now)) == 1, "end"

        # include the middle:
        acc.events << duckbill.newEvent("charge", posted="2/1/2001")
        acc.events << duckbill.newEvent("credit", posted="4/1/2001")
        l = len(acc.eventsBetween(then, now))
        assert l == 3, \
                "middle should have 3 events, actually has %d" % l
예제 #20
0
    def toDuckbill(self):
        """
        Returns a duckbill Account with the appropriate
        Subscriptions and Events. 
        """
        a = Account(fname=self.fname,
                    lname=self.lname,
                    email=self.email,
                    company=self.company,
                    phone=self.phone,
                    address1=self.addr1,
                    address2=self.addr2,
                    city=self.city,
                    state=self.state,
                    postal=self.postal,
                    countryCD=self.country,
                    account=self.username,
                    nextDue=Date("today") + 30,
                    brand=self.brand)

        s = Subscription(
            username=self.username,
            service=self.plan,
            rate=self.calcRate(),
            cycLen=self.cycLen,

            # thirty day free trial
            nextDue=Date("today") + 30)

        e = Event(event="note",
                  posted=Date("today"),
                  amount=0,
                  note="30 day free trial")

        a.subscriptions << s
        a.events << e

        return a
예제 #21
0
    def testCycle(self):
        cyc = duckbill.Cyclic()
        assert cyc.cycLen == 'month', "should be month by default"
        assert repr(cyc.get_cycle()) == 'MonthlyCycle()'
        cyc.cycLen = "year"
        assert cyc.cycLen == 'year', "should be year now"
        assert repr(cyc.get_cycle()) == 'YearlyCycle()'
        cyc.nextDue = ("1/1/2001")
        assert cyc.get_cycle().nextDue() == Date("1/1/2002")

        
        # just to make sure:
        sub = duckbill.Subscription()
        sub.cycLen = "year"
        assert repr(sub.cycle) == 'YearlyCycle()'
예제 #22
0
    def test_monthlyTraffic(self):

        arbdate = Date("2/29/2004")
        startdate = Date("1/29/2004")

        user = User()

        # this one is out of range:
        user.usage << Usage(whichday=startdate - 1, traffic=1 * GIGA)

        # this one is cool:
        user.usage << Usage(whichday=startdate, traffic=2 * GIGA)

        # these are good:
        user.usage << Usage(whichday=arbdate - 3, traffic=4 * GIGA)
        user.usage << Usage(whichday=arbdate - 2, traffic=8 * GIGA)
        user.usage << Usage(whichday=arbdate - 1, traffic=16 * GIGA)

        # this one is in the "future", since it
        # won't be recorded until "tonight":
        user.usage << Usage(whichday=arbdate, traffic=32 * GIGA)

        self.assertEquals(self.bwg.monthlyTraffic(user, arbdate),
                          (2 + 4 + 8 + 16) * GIGA)
예제 #23
0
def makeStatement(acc):
    """
    generate a statement for the person....
    """
    total = 0
    stmt=""
    name = (acc.fname + " " + acc.lname).strip()
    stmt += "\n"
    stmt += "Account: " + acc.account + "\n"
    stmt += "-" * 70 + "\n"
    es = acc.events
    es.sort()
    for e in es:
        if e.posted > Date("today"):
            continue # allow future posting of charges (eg, lifetime account)
        stmt += "%s  %-50s%8s\n" % (e.posted.toDate().toUS(), e.note, e.value)
        total += e.value
    stmt += ("-" * 70) + "\n"
    stmt += "%70s\n" % ("total: " +str(total))
    return (acc.fname, name, acc.email, stmt, total)
예제 #24
0
    def separate_ages(self, events, binsize=15, maxbins=4):
        """
        separates an account's aged receivables into bins
        """
        # generate maxbins bins, oldest first:
        bins = []
        for x in range(0, maxbins):
            bins.append(Date("today") - (binsize * x))
        bins.reverse()

        # separate values according to dates
        # (note that this ignores anything posted in the future)
        # (but then there should never be anything in the future)
        vals = [0] * len(bins)
        for evt in events:
            for i in range(len(bins)):
                islastbin = (i == len(bins) - 1)
                if (evt.posted <= bins[i]) or (islastbin):
                    vals[i] += evt.value
                    break
        return vals
예제 #25
0
    def test_encryption(self):
        c = EncryptedCard(owner='fred tempy', expire='1/1/2000', number='1234')
        assert not c.isEncrypted()
        assert c.owner == 'fred tempy'
        assert str(c).startswith("-----BEGIN PGP MESSAGE-----"), str(c)
        assert not c.isEncrypted()

        s = str(c)
        del c

        c = EncryptedCard(s)
        assert c.isEncrypted()
        # new instance should fail since it's encrypted:
        self.assertRaises(AttributeError, getattr, c, "owner")

        # witthout the right passphrase, it should still fail
        self.assertRaises(Exception, c.decrypt, "not-the-pass-phrase")
        self.assertRaises(AttributeError, getattr, c, "owner")

        # but if we have the passphrase, all is well:
        c.decrypt("encrypted card test")
        assert not c.isEncrypted()
        assert c.owner == 'fred tempy'
        assert c.number == '1234'
        assert c.expire == Date("1/1/2000")

        def gpgsame(a, b):
            A = a.split("==")[0]
            B = b.split("==")[0]

        #@TODO: I'd like this to be the same all the time,
        #but it isn't... need to nail down when exactly the
        #cipher should be regenerated...
        #import pdb; pdb.set_trace()
        #assert gpgsame(str(c), s), str(c) +  "\n##VS##\n" + s
        c.owner = 'wanda tempy'
        assert not gpgsame(str(c), s)

        # just to be safe, prevent decrypting twice:
        self.assertRaises(Exception, c.decrypt, "encrypted card test")
예제 #26
0
    def check_usage(self):
        period = PythonicRange(Date("today")-10, Date("today"))
        usr = User()

        # zero by default:
        assert usr.trafficUsed(period) == 0

        # sum the data:
        usr.usage << Usage(whichday=Date("today")-1, traffic=1*GIGA)
        usr.usage << Usage(whichday=Date("today")-2, traffic=1*GIGA)        
        assert usr.trafficUsed(period) == 2 * GIGA

        # ignore data out of range (note: it's a PythonicRange)
        usr.usage << Usage(whichday=Date("today"), traffic=1*GIGA)
        usr.usage << Usage(whichday=Date("today")-32, traffic=1*GIGA)        
        assert usr.trafficUsed(period) == 2 * GIGA
예제 #27
0
dbc = clerk.storage.dbc

from cornerhost import User
from cornerhost import config
uclerk = config.makeClerk()

#@TODO: get rid of this completely (use duckbill.Grace instead)
# (this is just a hard-coded list)
try:
    from graced import GRACED, gracedUntil
except Exception, e:
    GRACED = []
    gracedUntil = []

for who, until in gracedUntil:
    if Date("today") <= until:
        GRACED.append(who)

try:
    PASTDUE_MAIL_TEMPLATE = open("pastdue.msg").read()
except:
    print "create a file called pastdue.msg that has your email template in it."
    sys.exit()


def makemail(account, email, fname, lname, total, pastdue, brand):
    cap = brand.title()
    return PASTDUE_MAIL_TEMPLATE % locals()


if __name__ == "__main__":
예제 #28
0
def daysInLastMonth():
    return daysInMonthPriorTo(Date("today"))
예제 #29
0
def unearned(events, cutoff=Date("today")):
    a = Account()
    for e in events:
        a.events << e
    return a.unearnedIncome(cutoff)
예제 #30
0
#!/usr/bin/python2.5
from duckbill import *
import duckbill.config
from pytypes import Date
import sys

CLERK = duckbill.config.makeClerk()

try:
    cutoff = Date(sys.argv[1])
except:
    print "usage: unearned.py DATE|today"
    sys.exit()

# cache the data:
subs = CLERK.match(Subscription)
evts = CLERK.match(Event)
print "cached."

sum = 0
for a in CLERK.match(Account):
    sum += a.unearnedIncome(cutoff)

print "unearned income on %s was %s" % (cutoff.toUS(), sum)
예제 #31
0
 def check_daysInYear(self):
     assert Date("1/1/1999").daysInYear() == 365
     assert Date("1/1/2000").daysInYear() == 366  # leap year
     assert Date("1/1/2001").daysInYear() == 365
예제 #32
0
 def check_daysInMonth(self):
     assert Date("1/1/2001").daysInMonth() == 31
     assert Date("2/1/2001").daysInMonth() == 28
     assert Date("2/1/2000").daysInMonth() == 29
예제 #33
0
 def check_repr(self):
     d = Date('1/1/2001')
     assert repr(d) == "Date('01/01/2001')", "wrong __repr__"