source: ccsd/private/modules/ccs_rurallink_billing.py @ 1253

Last change on this file since 1253 was 1253, checked in by ijm1, 6 years ago

Made the nightly and half hourly functions actually call back when they are supposed to. Also added code to purchase data correctly

  • Property svn:keywords set to Id
File size: 4.8 KB
Line 
1# Copyright (C) 2006  Rural Link Ltd.
2#
3# This file is an extension to crcnetd - CRCnet Configuration System Daemon
4#
5# RuralLink Billing Module - Provides logic for manipulating customer accounts
6#                            according to the Rural Link business rules.
7#
8# Author:       Matt Brown <matt@crc.net.nz>
9#               Ivan Meredith <ivan@ivan.net.nz>
10# Version:      $Id$
11#
12# No usage or redistribution rights are granted for this file unless
13# otherwise confirmed in writing by the copyright holder.
14from crcnetd._utils.ccsd_common import *
15from crcnetd._utils.ccsd_log import *
16from crcnetd._utils.ccsd_events import *
17from crcnetd._utils.ccsd_session import getSession, getSessionE
18from crcnetd._utils.ccsd_server import exportViaXMLRPC, registerResource, \
19        registerRecurring, registerHalfHourly, registerDailyAt
20from crcnetd._utils.ccsd_ca import ccs_ca, getCertificateParameters, \
21        CERT_PARAM_NAMES, REVOKE_SUPERSEDED
22from datetime import *
23ccs_mod_type = CCSD_SERVER
24
25def updateRadius():
26    """
27    Should this function be here or just consolidate into checkUsage(), ill figure
28    out later, for now this is fine.
29    """
30    session = getSession(ADMIN_SESSION_ID)
31
32    sql = "SELECT FROM update_customer_state()"
33
34    session.execute(sql, ())
35
36def checkUsage():
37    """
38    Checks each customers usage, and if usage is greater than the cap,
39    do the cap action
40    """
41    #Update the customer_states before checking data used.
42    updateRadius()
43   
44    session = getSession(ADMIN_SESSION_ID)
45   
46    sql = "SELECT DISTINCT * FROM customer_state WHERE used_mb > cap_at_mb"
47
48    res = session.query(sql, ())
49    for state in res:
50        doCapAction(state)
51
52@registerHalfHourly()
53def updateStatus():
54    """
55    This is the function that is run every 30 mins to update the state
56    table with the data done for the last 30mins.
57    """
58    checkUsage()
59
60def doRollover(type):
61    """
62    Performs the nightly rollover check.
63    """
64   
65    session = getSession(ADMIN_SESSION_ID)
66   
67    sql = "SELECT * FROM rollover WHERE cap_period=%s"
68
69    res = session.query(sql, (type))
70
71    for ro in res:
72        #Generate the billing records
73        sql = "INSERT INTO billing_record(contact_id, record_date, " \
74            "description, amount, quantity) VALUES (%s,CURRENT_TIMESTAMP, " \
75            "%s, %s,1);"
76
77        session.execute(sql, (ro["contact_id"],ro["plan_name"], ro["price"]))
78       
79        #Update the customer state.
80        sql = "UPDATE customer_state SET plan_start=CURRENT_TIMESTAMP, "\
81            "cap_at_mb=%s, used_mb=0, radius_plan=%s WHERE contact_id=%s"
82
83        session.execute(sql, (ro["included_mb"], ro["contact_id"], \
84            ro["radius_plan"]))
85
86@registerDailyAt((00,30,00))
87def updateNightly():
88    """
89    This function is called every night and does checks do see if caps need
90    rolling over etc.
91    """
92    #If its the start of the month, its time to bill them for a new
93    #month
94    if datetime.now().day == 1:
95        doRollover("monthy")
96    #Monday = 0 ... Sunday = 6
97    if datetime.now().weekday() == 1:
98        doRollover("weekly")
99   
100   
101    #do all daily rollovers
102    doRollover("daily")
103   
104   
105def doCapAction(customer):
106    """
107    Supported actions at the moment are:
108        Throttling.
109        Top up.
110    """
111    session = getSession(ADMIN_SESSION_ID)
112
113    sql = "SELECT cap_action, cap_param, cap_price FROM billing_plan" \
114        " WHERE plan_id=%s"
115
116    res = session.query(sql, (customer["plan_id"]))
117   
118    if res[0]["cap_action"] == "throttle":
119        sql = "UPDATE customer_state SET radius_plan=%s WHERE contact_id=%s"
120        session.execute(sql,(res[0]["cap_param"], customer["contact_id"]))
121    elif res[0]["cap_action"] == "purchase":
122        cap_at_mb = customer["cap_at_mb"]
123        used_mb = customer["used_mb"]
124       
125        # If for some reason they manage to go over the cap + 1 unit of
126        # cap_param we want to keep selling them data until the cap is
127        # higher than there current data.
128        while cap_at_mb < used_mb:
129            sql = "UPDATE customer_state SET cap_at_mb=cap_at_mb+%s " \
130                "WHERE contact_id=%s"
131            session.execute(sql,(res[0]["cap_param"], customer["contact_id"]))
132           
133            sql = "INSERT INTO billing_record (contact_id, record_date, " \
134                "description, amount, quantity) VALUES (%%s, CURRENT_TIMESTAMP, " \
135                "'%sGB data pack', %%s, 1)" % (res[0]["cap_param"]/1024)
136            session.execute(sql, (customer["contact_id"], res[0]["cap_price"]))
137            cap_at_mb += res[0]["cap_param"]
138   
139def generateInvoice(contact_id):
140    """
141    Generates an invoice for all bills in the database that havent been
142    assigned an invoice number.
143    """
144
145def emailInvoiceTo(contact_id, invoice_id):
146    """
147    Emails an invoice to a customer.
148    """
Note: See TracBrowser for help on using the repository browser.