root / pykota / trunk / pykota / reporter.py @ 2064

Revision 2064, 10.5 kB (checked in by jalet, 19 years ago)

Fixes output when user has got a negative or nul overcharging factor.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2# -*- coding: ISO-8859-15 -*-
3#
4# PyKota : Print Quotas for CUPS and LPRng
5#
6# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20#
21# $Id$
22#
23# $Log$
24# Revision 1.12  2005/02/15 13:13:27  jalet
25# Fixes output when user has got a negative or nul overcharging factor.
26#
27# Revision 1.11  2005/02/13 22:02:29  jalet
28# Big database structure changes. Upgrade script is now included as well as
29# the new LDAP schema.
30# Introduction of the -o | --overcharge command line option to edpykota.
31# The output of repykota is more complete, but doesn't fit in 80 columns anymore.
32# Introduction of the new 'maxdenybanners' directive.
33#
34# Revision 1.10  2004/09/02 10:09:30  jalet
35# Fixed bug in LDAP user deletion code which didn't correctly delete the user's
36# pykotaLastJob entries.
37#
38# Revision 1.9  2004/07/01 17:45:49  jalet
39# Added code to handle the description field for printers
40#
41# Revision 1.8  2004/03/24 15:15:24  jalet
42# Began integration of Henrik Janhagen's work on quota-then-balance
43# and balance-then-quota
44#
45# Revision 1.7  2004/01/08 14:10:32  jalet
46# Copyright year changed.
47#
48# Revision 1.6  2003/12/27 16:49:25  uid67467
49# Should be ok now.
50#
51# Revision 1.4  2003/12/02 14:40:21  jalet
52# Some code refactoring.
53# New HTML reporter added, which is now used in the CGI script for web based
54# print quota reports. It will need some de-uglyfication though...
55#
56# Revision 1.3  2003/11/25 23:46:40  jalet
57# Don't try to verify if module name is valid, Python does this better than us.
58#
59# Revision 1.2  2003/10/07 09:07:28  jalet
60# Character encoding added to please latest version of Python
61#
62# Revision 1.1  2003/06/30 12:46:15  jalet
63# Extracted reporting code.
64#
65#
66#
67
68from mx import DateTime
69
70class PyKotaReporterError(Exception):
71    """An exception for Reporter related stuff."""
72    def __init__(self, message = ""):
73        self.message = message
74        Exception.__init__(self, message)
75    def __repr__(self):
76        return self.message
77    __str__ = __repr__
78   
79class BaseReporter :   
80    """Base class for all reports."""
81    def __init__(self, tool, printers, ugnames, isgroup) :
82        """Initialize local datas."""
83        self.tool = tool
84        self.printers = printers
85        self.ugnames = ugnames
86        self.isgroup = isgroup
87       
88    def getPrinterTitle(self, printer) :     
89        return (_("Report for %s quota on printer %s") % ((self.isgroup and "group") or "user", printer.Name)) + (" (%s)" % printer.Description)
90       
91    def getPrinterGraceDelay(self, printer) :   
92        return _("Pages grace time: %i days") % self.tool.config.getGraceDelay(printer.Name)
93       
94    def getPrinterPrices(self, printer) :   
95        return (_("Price per job: %.3f") % (printer.PricePerJob or 0.0), _("Price per page: %.3f") % (printer.PricePerPage or 0.0))
96           
97    def getReportHeader(self) :       
98        if self.isgroup :
99            return _("Group          overcharge   used    soft    hard    balance grace         total       paid warn")
100        else :   
101            return _("User           overcharge   used    soft    hard    balance grace         total       paid warn")
102           
103    def getPrinterRealPageCounter(self, printer) :       
104        msg = _("unknown")
105        if printer.LastJob.Exists :
106            try :
107                msg = "%9i" % printer.LastJob.PrinterPageCounter
108            except TypeError :     
109                pass
110        return _("Real : %s") % msg
111               
112    def getTotals(self, total, totalmoney) :           
113        return (_("Total : %9i") % (total or 0.0), ("%11s" % ("%7.2f" % (totalmoney or 0.0))[:11]))
114           
115    def getQuota(self, entry, quota) :
116        """Prints the quota information."""
117        lifepagecounter = int(quota.LifePageCounter or 0)
118        pagecounter = int(quota.PageCounter or 0)
119        balance = float(entry.AccountBalance or 0.0)
120        lifetimepaid = float(entry.LifeTimePaid or 0.0)
121        if not hasattr(entry, "OverCharge") :
122            overcharge = _("N/A")       # Not available for groups
123        else :   
124            overcharge = float(entry.OverCharge or 0.0)
125        if not hasattr(quota, "WarnCount") :   
126            warncount = _("N/A")        # Not available for groups
127        else :   
128            warncount = int(quota.WarnCount or 0)
129       
130        #balance
131        if entry.LimitBy and (entry.LimitBy.lower() == "balance") :   
132            if balance == 0.0 :
133                if entry.OverCharge > 0 :
134                    datelimit = "DENY"
135                    reached = "+B"
136                else :   
137                    # overcharging by a negative or nul factor means user is always allowed to print
138                    # TODO : do something when printer prices are negative as well !
139                    datelimit = ""
140                    reached = "-B"
141            elif balance < 0 :
142                datelimit = "DENY"
143                reached = "+B"
144            elif balance <= self.tool.config.getPoorMan() :
145                datelimit = "WARNING"
146                reached = "?B"
147            else :   
148                datelimit = ""
149                reached = "-B"
150
151        #balance-then-quota
152        elif entry.LimitBy and (entry.LimitBy.lower() == "balance-then-quota") :
153            if balance <= 0 :
154                if (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :
155                    datelimit = "DENY"
156                elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) :
157                    datelimit = "DENY"
158                elif quota.DateLimit is not None :
159                    now = DateTime.now()
160                    datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit)
161                    if now >= datelimit :
162                        datelimit = "QUOTA_DENY"
163                else :
164                    datelimit = ""
165                reached = ( ((datelimit == "DENY" ) and "+B") or "-Q")
166                datelimit = ( ((datelimit == "QUOTA_DENY") and "DENY") or datelimit)
167            elif balance <= self.tool.config.getPoorMan() :
168                if (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :
169                    datelimit = "WARNING"
170                elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) :
171                    datelimit = "WARNING"
172                elif quota.DateLimit is not None :
173                    now = DateTime.now()
174                    datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit)
175                    if now >= datelimit :
176                        datelimit = "QUOTA_DENY"
177                else :
178                    datelimit = ""
179                reached = ( ((datelimit == "WARNING" ) and "?B") or "+Q")
180                datelimit = ( ((datelimit == "QUOTA_DENY") and "WARNING") or datelimit)
181            else :
182                datelimit = ""
183                reached = "-B"
184
185        #Quota-then-balance
186        elif entry.LimitBy and (entry.LimitBy.lower() == "quota-then-balance") :
187            if (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :
188                datelimit = "DENY"
189            elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) :
190                datelimit = "DENY"
191            elif quota.DateLimit is not None :
192                now = DateTime.now()
193                datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit)
194                if now >= datelimit :
195                    datelimit = "DENY"
196            else :
197                datelimit = ""
198               
199            reached = (((quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) and "+") or "-") + "Q"
200
201            if (datelimit == "DENY") and (reached == "-Q") and (balance > self.tool.config.getPoorMan()) :
202                datelimit = ""
203                reached = "-B"
204            else :
205                reached = (((datelimit == "DENY") and (self.tool.config.getPoorMan() < balance ) and "-B") or reached)
206                if (datelimit == "DENY") and (self.tool.config.getPoorMan() < balance) :
207                    datelimit = ""
208                reached = (((datelimit == "DENY") and (0.0 < balance <= self.tool.config.getPoorMan()) and "?B") or reached)
209                datelimit = (((datelimit == "DENY") and (0.0 < balance <= self.tool.config.getPoorMan()) and "WARNING") or datelimit)
210
211        #Quota
212        else :
213            if (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) :   
214                datelimit = "DENY"
215            elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) :
216                datelimit = "DENY"
217            elif quota.DateLimit is not None :
218                now = DateTime.now()
219                datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit)
220                if now >= datelimit :
221                    datelimit = "DENY"
222            else :   
223                datelimit = ""
224            reached = (((quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) and "+") or "-") + "Q"
225           
226        strbalance = ("%5.2f" % balance)[:10]
227        strlifetimepaid = ("%6.2f" % lifetimepaid)[:10]
228        strovercharge = ("%5s" % overcharge)[:5]
229        strwarncount = ("%4s" % warncount)[:4]
230        return (lifepagecounter, lifetimepaid, entry.Name, reached, \
231                pagecounter, str(quota.SoftLimit), str(quota.HardLimit), \
232                strbalance, str(datelimit)[:10], lifepagecounter, \
233                strlifetimepaid, strovercharge, strwarncount)
234       
235def openReporter(tool, reporttype, printers, ugnames, isgroup) :
236    """Returns a reporter instance of the proper reporter."""
237    try :
238        exec "from pykota.reporters import %s as reporterbackend" % reporttype.lower()
239    except ImportError :
240        raise PyKotaReporterError, _("Unsupported reporter backend %s") % reporttype
241    else :   
242        return reporterbackend.Reporter(tool, printers, ugnames, isgroup)
Note: See TracBrowser for help on using the browser.