c18d382ee77d764a6e72be992ef64337e5cdbe09
[raven.git] / apps / gacks / gacksbilling.py
1 import logging
2 import time
3 import gacksaccount
4 import gacksinvoice
5 import gackspolicy
6 from gacksinvoice import GacksInvoiceManager, STATE_PENDING, STATE_AGGREGATED, KIND_CYCLE_CHARGE, KIND_SLOT_CHARGE, KIND_CYCLE_AGGREGATE
7 from gackstime import GacksTime
8
9 glo_logger_name = "gacksapi"
10
11 def set_logger_name(x):
12     global glo_logger_name
13     glo_logger_name = x
14
15 class GacksBilling:
16    def __init__(self, accounts, invoices, policies, resources):
17        self.accounts = accounts
18        self.invoices = invoices
19        self.policies = policies
20        self.resources = resources
21
22    def mylogger(self):
23        return logging.getLogger(glo_logger_name)
24
25    def bill_membership(self):
26        self.mylogger().info("doing bill_membship")
27
28        accounts = self.accounts.get_accounts()
29        for acct in accounts:
30             policy = self.policies.get_policy(acct.level, None)
31             if policy is None:
32                 continue
33
34             self.invoices.bill_membership(acct, policy)
35
36    def auto_renew(self):
37        self.mylogger().info("doing auto-renew")
38
39        time_threshold = time.time() - 48*60*60*10
40        inv = self.invoices.get_invoice_prime({"account_id": "_GRP_",
41                                               "start_date": time_threshold,
42                                               "kind_id": [KIND_CYCLE_CHARGE, KIND_SLOT_CHARGE, KIND_CYCLE_AGGREGATE]},
43                                              lookup_objects=True)
44
45        handlers = []
46        for resource in self.resources.resources:
47            handler = resource.get_handler_obj()
48            if handler is not None:
49                handlers.append(handler)
50
51        for charge in inv.charges:
52            account_name = charge.account_name
53            for handler in handlers:
54                handler.renewSlice(account_name, 30)
55
56    def terminate_or_renew_service(self):
57        self.mylogger().info("doing terminate_or_renew_service")
58
59        accounts = self.accounts.get_accounts()
60        for acct in accounts:
61             if acct.serviceStartDate <= 0:
62                 # no service start date, it's probably an old account, leave it alone
63                 continue
64
65             policy = self.policies.get_policy(acct.level, None)
66
67             if not policy:
68                 self.mylogger().warning("couldn't find policy for %s" % acct.name)
69                 continue
70
71             if policy.term <= 0:
72                 self.mylogger().info("term is zero or less for %s" % acct.name)
73                 continue
74
75             # compute when the service term should have ended
76             endDate = GacksTime.month_delta(acct.serviceStartDate, policy.term)
77
78             # if it has ended, then we need to either renew it or terminate it
79             if (endDate < time.time()):
80                 if acct.autoRenew:
81                     self.mylogger().info("renewing service on %s from %s to %s" % (acct.name, time.ctime(acct.serviceStartDate), time.ctime(endDate)))
82                     acct.serviceStartDate = endDate
83                     acct.commit()
84                 else:
85                     self.mylogger().info("terminating service on %s. Expired on %s" % (acct.name, time.ctime(endDate)))
86                     acct.level = "default"
87                     acct.commit()
88             else:
89                 self.mylogger().info("service on %s is still active (until %s)" % (acct.name, time.ctime(endDate)))
90
91    def do_nightly(self):
92         self.mylogger().info("doing do_nightly")
93
94         # terminate any accounts that it is time to terminate
95         self.terminate_or_renew_service()
96
97         # do monthly service fees
98         self.bill_membership()
99
100         # throw away any STATE_AGGREGATED charges older than 48 hours
101         self.invoices.prune_charges(STATE_AGGREGATED, 48*60*60)
102
103         # apply pending charges to nightly invoices
104         self.invoices.apply_invoices()
105
106         # auto-renew slices
107         self.auto_renew()
108
109