Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 1565)
+++ /pykota/trunk/pykota/tool.py (revision 1582)
@@ -22,4 +22,7 @@
 #
 # $Log$
+# Revision 1.109  2004/07/01 17:45:49  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.108  2004/06/24 23:09:30  jalet
 # Also prints read size on last block
@@ -475,4 +478,9 @@
         if self.debug :
             self.logger.log_message(message, "debug")
+            
+    def printError(self, message) :        
+        """Sends a message to standard error."""
+        sys.stderr.write("%s\n" % message)
+        sys.stderr.flush()
         
     def clean(self) :    
Index: /pykota/trunk/pykota/storages/sql.py
===================================================================
--- /pykota/trunk/pykota/storages/sql.py (revision 1531)
+++ /pykota/trunk/pykota/storages/sql.py (revision 1582)
@@ -22,4 +22,7 @@
 #
 # $Log$
+# Revision 1.43  2004/07/01 17:45:49  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.42  2004/06/08 17:44:43  jalet
 # Payment now gets deleted when the user is deleted
@@ -115,6 +118,7 @@
             printer.ident = fields.get("id")
             printer.Name = fields.get("printername", printername)
-            printer.PricePerJob = fields.get("priceperjob")
-            printer.PricePerPage = fields.get("priceperpage")
+            printer.PricePerJob = fields.get("priceperjob") or 0.0
+            printer.PricePerPage = fields.get("priceperpage") or 0.0
+            printer.Description = fields.get("description") or ""
             printer.Exists = 1
         return printer    
@@ -228,6 +232,7 @@
                     printer = StoragePrinter(self, record["printername"])
                     printer.ident = record.get("id")
-                    printer.PricePerJob = record.get("priceperjob")
-                    printer.PricePerPage = record.get("priceperpage")
+                    printer.PricePerJob = record.get("priceperjob") or 0.0
+                    printer.PricePerPage = record.get("priceperpage") or 0.0
+                    printer.Description = record.get("description") or ""
                     printer.Exists = 1
                     printers.append(printer)
@@ -313,4 +318,8 @@
         self.doModify("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE id=%s" % (self.doQuote(printer.PricePerPage), self.doQuote(printer.PricePerJob), self.doQuote(printer.ident)))
         
+    def writePrinterDescription(self, printer) :    
+        """Write the printer's description back into the storage."""
+        self.doModify("UPDATE printers SET description=%s WHERE id=%s" % (self.doQuote(printer.Description), self.doQuote(printer.ident)))
+        
     def writeUserLimitBy(self, user, limitby) :    
         """Sets the user's limiting factor."""
Index: /pykota/trunk/pykota/storages/ldapstorage.py
===================================================================
--- /pykota/trunk/pykota/storages/ldapstorage.py (revision 1534)
+++ /pykota/trunk/pykota/storages/ldapstorage.py (revision 1582)
@@ -22,4 +22,7 @@
 #
 # $Log$
+# Revision 1.71  2004/07/01 17:45:49  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.70  2004/06/10 20:50:25  jalet
 # Better log message
@@ -535,5 +538,5 @@
         """Extracts printer information given its name : returns first matching printer."""
         printer = StoragePrinter(self, printername)
-        result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob", "uniqueMember"], base=self.info["printerbase"])
+        result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob", "uniqueMember", "description"], base=self.info["printerbase"])
         if result :
             fields = result[0][1]       # take only first matching printer, ignore the rest
@@ -543,4 +546,5 @@
             printer.PricePerPage = float(fields.get("pykotaPricePerPage", [0.0])[0] or 0.0)
             printer.uniqueMember = fields.get("uniqueMember", [])
+            printer.Description = fields.get("description", [""])[0]
             printer.Exists = 1
         return printer    
@@ -700,5 +704,5 @@
         printers = []
         # see comment at the same place in pgstorage.py
-        result = self.doSearch("(&(objectClass=pykotaPrinter)(|%s))" % "".join(["(pykotaPrinterName=%s)(%s=%s)" % (pname, self.info["printerrdn"], pname) for pname in printerpattern.split(",")]), ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob", "uniqueMember"], base=self.info["printerbase"])
+        result = self.doSearch("(&(objectClass=pykotaPrinter)(|%s))" % "".join(["(pykotaPrinterName=%s)(%s=%s)" % (pname, self.info["printerrdn"], pname) for pname in printerpattern.split(",")]), ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob", "uniqueMember", "description"], base=self.info["printerbase"])
         if result :
             for (printerid, fields) in result :
@@ -709,4 +713,5 @@
                 printer.PricePerPage = float(fields.get("pykotaPricePerPage", [0.0])[0] or 0.0)
                 printer.uniqueMember = fields.get("uniqueMember", [])
+                printer.Description = fields.get("description", [""])[0]
                 printer.Exists = 1
                 printers.append(printer)
@@ -895,4 +900,11 @@
                    "pykotaPricePerPage" : str(printer.PricePerPage),
                    "pykotaPricePerJob" : str(printer.PricePerJob),
+                 }
+        self.doModify(printer.ident, fields)
+        
+    def writePrinterDescription(self, printer) :    
+        """Write the printer's description back into the storage."""
+        fields = {
+                   "description" : str(printer.Description),
                  }
         self.doModify(printer.ident, fields)
Index: /pykota/trunk/pykota/reporter.py
===================================================================
--- /pykota/trunk/pykota/reporter.py (revision 1418)
+++ /pykota/trunk/pykota/reporter.py (revision 1582)
@@ -22,4 +22,7 @@
 #
 # $Log$
+# Revision 1.9  2004/07/01 17:45:49  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.8  2004/03/24 15:15:24  jalet
 # Began integration of Henrik Janhagen's work on quota-then-balance
@@ -70,5 +73,5 @@
         
     def getPrinterTitle(self, printer) :     
-        return _("Report for %s quota on printer %s") % ((self.isgroup and "group") or "user", printer.Name)
+        return (_("Report for %s quota on printer %s") % ((self.isgroup and "group") or "user", printer.Name)) + (" (%s)" % printer.Description)
         
     def getPrinterGraceDelay(self, printer) :    
@@ -100,5 +103,5 @@
         balance = float(entry.AccountBalance or 0.0)
         lifetimepaid = float(entry.LifeTimePaid or 0.0)
-	
+        
         #balance
         if entry.LimitBy and (entry.LimitBy.lower() == "balance") :    
Index: /pykota/trunk/pykota/storage.py
===================================================================
--- /pykota/trunk/pykota/storage.py (revision 1523)
+++ /pykota/trunk/pykota/storage.py (revision 1582)
@@ -22,4 +22,7 @@
 #
 # $Log$
+# Revision 1.56  2004/07/01 17:45:49  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.55  2004/06/05 22:18:04  jalet
 # Now catches some exceptions earlier.
@@ -317,4 +320,5 @@
         self.PricePerPage = None
         self.PricePerJob = None
+        self.Description = None
         
     def __getattr__(self, name) :    
@@ -353,4 +357,12 @@
             self.PricePerJob = float(priceperjob)
         self.parent.writePrinterPrices(self)
+        
+    def setDescription(self, description = None) :    
+        """Sets the printer's prices."""
+        if description is None :
+            description = self.Description
+        else :    
+            self.Description = str(description)
+        self.parent.writePrinterDescription(self)
         
     def delete(self) :    
Index: /pykota/trunk/cgi-bin/printquota.cgi
===================================================================
--- /pykota/trunk/cgi-bin/printquota.cgi (revision 1525)
+++ /pykota/trunk/cgi-bin/printquota.cgi (revision 1582)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.30  2004/07/01 17:45:48  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.29  2004/06/06 21:07:55  jalet
 # Improved CGI script to allow history on printers and hostnames.
@@ -189,7 +192,7 @@
         for printer in printers :
             if printer.Name in selectednames :
-                message += '<option value="%s" selected="selected">%s</option>' % (printer.Name, printer.Name)
+                message += '<option value="%s" selected="selected">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
             else :
-                message += '<option value="%s">%s</option>' % (printer.Name, printer.Name)
+                message += '<option value="%s">%s (%s)</option>' % (printer.Name, printer.Name, printer.Description)
         message += '</select></td></tr></table>'
         return message
Index: /pykota/trunk/bin/pkprinters
===================================================================
--- /pykota/trunk/bin/pkprinters (revision 1546)
+++ /pykota/trunk/bin/pkprinters (revision 1582)
@@ -24,4 +24,7 @@
 #
 # $Log$
+# Revision 1.12  2004/07/01 17:45:47  jalet
+# Added code to handle the description field for printers
+#
 # Revision 1.11  2004/06/18 13:34:48  jalet
 # Now all tracebacks include PyKota's version number
@@ -87,4 +90,6 @@
                        
   -d | --delete        Deletes printers from the quota storage.
+  
+  -D | --description   Adds a textual description to printers.
                        
   -c | --charge p[,j]  Sets the price per page and per job to charge.
@@ -122,5 +127,5 @@
 examples :                              
 
-  $ pkprinters --add --charge 0.05,0.1 hp2100 hp2200 hp8000
+  $ pkprinters --add -D "HP Printer" --charge 0.05,0.1 hp2100 hp2200 hp8000
   
   Will create three printers named hp2100, hp2200 and hp8000.
@@ -128,6 +133,7 @@
   per job will be set at 0.1 unit. Units are in your own currency,
   or whatever you want them to mean.
-  If any of these printers already exists, it is not modified at
-  all.
+  All of their descriptions will be set to the string "HP Printer".
+  If any of these printers already exists, it will also be modified 
+  unless the -s|--skipexisting command line option is also used.
             
   $ pkprinters --delete "*"
@@ -191,7 +197,7 @@
                 if printer.Exists :
                     if options["skipexisting"] :
-                        self.logger.log_message(_("Printer %s already exists, skipping.") % printer.Name, "warn")
+                        self.printError(_("Printer %s already exists, skipping.") % printer.Name)
                     else :    
-                        self.logger.log_message(_("Printer %s already exists, will be modified.") % printer.Name, "warn")
+                        self.printError(_("Printer %s already exists, will be modified.") % printer.Name)
                         printers.append(printer)
                 else :
@@ -216,10 +222,12 @@
                 if parents : 
                     parents = "%s %s" % (_("in"), parents)
-                print "%s (%s + #*%s) %s" % \
-                      (printer.Name, printer.PricePerJob, \
+                print "%s [%s] (%s + #*%s) %s" % \
+                      (printer.Name, printer.Description, printer.PricePerJob, \
                        printer.PricePerPage, parents)
             else :    
                 if options["charge"] :
                     printer.setPrices(perpage, perjob)    
+                if options["description"] is not None :
+                    printer.setDescription(options["description"].strip())
                 if options["groups"] :    
                     for pgroup in printersgroups :
@@ -232,6 +240,6 @@
     retcode = 0
     try :
-        short_options = "hvac:dg:lrs"
-        long_options = ["help", "version", "add", "charge=", "delete", "groups=", "list", "remove", "skipexisting"]
+        short_options = "hvac:D:dg:lrs"
+        long_options = ["help", "version", "add", "charge=", "description=", "delete", "groups=", "list", "remove", "skipexisting"]
         
         # Initializes the command line tool
@@ -246,4 +254,5 @@
         options["add"] = options["a"] or options["add"]
         options["charge"] = options["c"] or options["charge"]
+        options["description"] = options["D"] or options["description"]
         options["delete"] = options["d"] or options["delete"] 
         options["groups"] = options["g"] or options["groups"]
@@ -256,7 +265,7 @@
         elif options["version"] :
             manager.display_version_and_quit()
-        elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"])) \
+        elif (options["delete"] and (options["add"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) \
            or (options["skipexisting"] and not options["add"]) \
-           or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"])) :
+           or (options["list"] and (options["add"] or options["delete"] or options["groups"] or options["charge"] or options["remove"] or options["description"])) :
             raise PyKotaToolError, _("incompatible options, see help.")
         elif options["remove"] and not options["groups"] :    
Index: /pykota/trunk/man/edpykota.1
===================================================================
--- /pykota/trunk/man/edpykota.1 (revision 1578)
+++ /pykota/trunk/man/edpykota.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH EDPYKOTA "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH EDPYKOTA "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 edpykota \- manual page for edpykota 1.19alpha28_unofficial
Index: /pykota/trunk/man/pkprinters.1
===================================================================
--- /pykota/trunk/man/pkprinters.1 (revision 1578)
+++ /pykota/trunk/man/pkprinters.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH PKPRINTERS "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH PKPRINTERS "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 pkprinters \- manual page for pkprinters 1.19alpha28_unofficial
@@ -26,4 +26,7 @@
 \fB\-d\fR | \fB\-\-delete\fR
 Deletes printers from the quota storage.
+.TP
+\fB\-D\fR | \fB\-\-description\fR
+Adds a textual description to printers.
 .TP
 \fB\-c\fR | \fB\-\-charge\fR p[,j]
@@ -65,5 +68,5 @@
 examples :
 .IP
-\f(CW$ pkprinters --add --charge 0.05,0.1 hp2100 hp2200 hp8000\fR
+\f(CW$ pkprinters --add -D "HP Printer" --charge 0.05,0.1 hp2100 hp2200 hp8000\fR
 .IP
 Will create three printers named hp2100, hp2200 and hp8000.
@@ -71,6 +74,7 @@
 per job will be set at 0.1 unit. Units are in your own currency,
 or whatever you want them to mean.
-If any of these printers already exists, it is not modified at
-all.
+All of their descriptions will be set to the string "HP Printer".
+If any of these printers already exists, it will also be modified
+unless the \fB\-s\fR|--skipexisting command line option is also used.
 .IP
 \f(CW$ pkprinters --delete "*"\fR
Index: /pykota/trunk/man/pykotme.1
===================================================================
--- /pykota/trunk/man/pykotme.1 (revision 1578)
+++ /pykota/trunk/man/pykotme.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH PYKOTME "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH PYKOTME "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 pykotme \- manual page for pykotme 1.19alpha28_unofficial
Index: /pykota/trunk/man/pkhint.1
===================================================================
--- /pykota/trunk/man/pkhint.1 (revision 1578)
+++ /pykota/trunk/man/pkhint.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH PKHINT "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH PKHINT "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 pkhint \- manual page for pkhint 1.19alpha28_unofficial
Index: /pykota/trunk/man/repykota.1
===================================================================
--- /pykota/trunk/man/repykota.1 (revision 1578)
+++ /pykota/trunk/man/repykota.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH REPYKOTA "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH REPYKOTA "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 repykota \- manual page for repykota 1.19alpha28_unofficial
Index: /pykota/trunk/man/warnpykota.1
===================================================================
--- /pykota/trunk/man/warnpykota.1 (revision 1578)
+++ /pykota/trunk/man/warnpykota.1 (revision 1582)
@@ -1,4 +1,4 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.33.
-.TH WARNPYKOTA "1" "June 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
+.TH WARNPYKOTA "1" "July 2004" "C@LL - Conseil Internet & Logiciels Libres" "User Commands"
 .SH NAME
 warnpykota \- manual page for warnpykota 1.19alpha28_unofficial
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 1578)
+++ /pykota/trunk/NEWS (revision 1582)
@@ -24,4 +24,9 @@
     - 1.19alpha28 :
     
+        - The description field for printers can now be set,
+          and is displayed in reports.
+          
+        - Fixed a small problem in SQL backend code.
+          
         - Improved pkhint
         
