root / pykota / trunk / bin / pkbcodes @ 3080

Revision 3052, 8.8 kB (checked in by jerome, 18 years ago)

Now pkprinters reroutes CUPS print queues through PyKota or
through CUPS only when adding or deleting printers in the
database.
Fixed some display uglyness in case no entry was found.

  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota Billing Codes manager
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003, 2004, 2005, 2006 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22#
23# $Id$
24#
25#
26
27import os
28import sys
29import pwd
30
31from pykota.tool import Percent, PyKotaTool, PyKotaCommandLineError, crashed, N_
32from pykota.storage import StorageBillingCode
33
34__doc__ = N_("""pkbcodes v%(__version__)s (c) %(__years__)s %(__author__)s
35
36A billing codes Manager for PyKota.
37
38command line usage :
39
40  pkbcodes [options] code1 code2 code3 ... codeN
41
42options :
43
44  -v | --version       Prints pkbcodes version number then exits.
45  -h | --help          Prints this message then exits.
46 
47  -a | --add           Adds billing codes if they don't exist in PyKota's
48                       database. If they exist, they are modified
49                       unless -s|--skipexisting is also used.
50
51  -d | --delete        Deletes billing codes from PyKota's database.
52                       NB : the history entries with this billing code
53                       are not deleted, voluntarily.
54
55  -D | --description d Adds a textual description to billing codes.
56
57  -l | --list          List informations about the billing codes.
58
59  -r | --reset         Resets the billing codes' balance and page counters
60                       to 0.
61
62  -s | --skipexisting  In combination with the --add option above, tells
63                       pkbcodes to not modify existing billing codes.
64
65  code1 through codeN can contain wildcards if the --add option
66  is not set.
67
68examples :                             
69
70  $ pkbcodes --add -D "My project" myproj
71
72  Will create the myproj billing code with "My project"
73  as the description.
74
75  $ pkbcodes --delete "*"
76
77  This will completely delete all the billing codes, but without
78  removing any matching job from the history. USE WITH CARE ANYWAY !
79 
80  $ pkbcodes --list "my*"
81 
82  This will list all billing codes which name begins with 'my'.
83""")
84       
85class PKBcodes(PyKotaTool) :       
86    """A class for a billing codes manager."""
87    def modifyBillingCode(self, billingcode, reset, description) :
88        """Modifies a billing code."""
89        if reset :
90            billingcode.reset()   
91        if description is not None : # NB : "" is allowed !
92            billingcode.setDescription(description)
93       
94    def main(self, names, options) :
95        """Manage billing codes."""
96        if (not self.config.isAdmin) and (not options["list"]) :
97            raise PyKotaCommandLineError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
98           
99        if not options["list"] :   
100            percent = Percent(self)
101           
102        if not options["add"] :
103            if not options["list"] :
104                percent.display("%s..." % _("Extracting datas"))
105            if not names :      # NB : can't happen for --delete because it's catched earlier
106                names = ["*"]
107            billingcodes = self.storage.getMatchingBillingCodes(",".join(names))
108            if not billingcodes :
109                if not options["list"] :
110                    percent.display("\n")
111                raise PyKotaCommandLineError, _("There's no billingcode matching %s") % " ".join(names)
112            if not options["list"] :   
113                percent.setSize(len(billingcodes))
114                       
115        if options["list"] :
116            for billingcode in billingcodes :
117                print "%s [%s] %s %s %s %.2f %s" % \
118                      (billingcode.BillingCode, billingcode.Description, \
119                       billingcode.PageCounter, \
120                       _("pages"), \
121                       _("and"), \
122                       billingcode.Balance, \
123                       _("credits"))
124        elif options["delete"] :   
125            percent.display("\n%s..." % _("Deletion"))
126            self.storage.deleteManyBillingCodes(billingcodes)
127            percent.display("\n")
128        else :
129            reset = options["reset"]
130            description = options["description"]
131            if description :
132                description = options["description"].strip()
133            skipexisting = options["skipexisting"]       
134           
135            self.storage.beginTransaction()
136            try :
137                if options["add"] :   
138                    percent.display("%s...\n" % _("Creation"))
139                    percent.setSize(len(names))
140                    for bname in names :
141                        billingcode = StorageBillingCode(self.storage, bname)
142                        self.modifyBillingCode(billingcode, reset, description)
143                        oldbillingcode = self.storage.addBillingCode(billingcode)
144                        if oldbillingcode is not None :
145                            if skipexisting :
146                                self.logdebug(_("Billing code [%s] already exists, skipping.") % bname)
147                            else :   
148                                self.logdebug(_("Billing code [%s] already exists, will be modified.") % bname)
149                                self.modifyBillingCode(oldbillingcode, reset, description)
150                                oldbillingcode.save()
151                        percent.oneMore()
152                else :       
153                    percent.display("\n%s...\n" % _("Modification"))
154                    for billingcode in billingcodes :
155                        self.modifyBillingCode(billingcode, reset, description)
156                        billingcode.save()   
157                        percent.oneMore()
158            except :                   
159                self.storage.rollbackTransaction()
160                raise
161            else :   
162                self.storage.commitTransaction()
163                       
164        if not options["list"] :
165            percent.done()
166                     
167if __name__ == "__main__" : 
168    retcode = 0
169    try :
170        short_options = "hvaD:dlrs"
171        long_options = ["help", "version", "add", "description=", "delete", "list", "reset", "skipexisting"]
172       
173        # Initializes the command line tool
174        manager = PKBcodes(doc=__doc__)
175        manager.deferredInit()
176       
177        # parse and checks the command line
178        (options, args) = manager.parseCommandline(sys.argv[1:], short_options, long_options)
179       
180        # sets long options
181        options["help"] = options["h"] or options["help"]
182        options["version"] = options["v"] or options["version"]
183        options["add"] = options["a"] or options["add"]
184        options["description"] = options["D"] or options["description"]
185        options["delete"] = options["d"] or options["delete"] 
186        options["list"] = options["l"] or options["list"]
187        options["reset"] = options["r"] or options["reset"]
188        options["skipexisting"] = options["s"] or options["skipexisting"]
189       
190        if options["help"] :
191            manager.display_usage_and_quit()
192        elif options["version"] :
193            manager.display_version_and_quit()
194        elif (options["delete"] and (options["add"] or options["reset"] or options["description"])) \
195           or (options["skipexisting"] and not options["add"]) \
196           or (options["list"] and (options["add"] or options["delete"] or options["reset"] or options["description"])) :
197            raise PyKotaCommandLineError, _("incompatible options, see help.")
198        elif (not args) and (options["add"] or options["delete"]) :   
199            raise PyKotaCommandLineError, _("You have to pass billing codes on the command line")
200        else :
201            retcode = manager.main(args, options)
202    except KeyboardInterrupt :       
203        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
204        retcode = -3
205    except PyKotaCommandLineError, msg :   
206        sys.stderr.write("%s : %s\n" % (sys.argv[0], msg))
207        retcode = -2
208    except SystemExit :       
209        pass
210    except :
211        try :
212            manager.crashed("pkbcodes failed")
213        except :   
214            crashed("pkbcodes failed")
215        retcode = -1
216
217    try :
218        manager.storage.close()
219    except (TypeError, NameError, AttributeError) :   
220        pass
221       
222    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.