Index: /pykota/trunk/README
===================================================================
--- /pykota/trunk/README (revision 887)
+++ /pykota/trunk/README (revision 900)
@@ -63,4 +63,7 @@
         - Special scripts included for a seamless integration of
           PyKota on Debian machines.
+          
+        - Complete job history is saved. This will allow more
+          complex reports in the future.
           
 All the command line tools accept the -h | --help command line option
Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 873)
+++ /pykota/trunk/pykota/tool.py (revision 900)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.30  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.29  2003/03/29 13:45:27  jalet
 # GPL paragraphs were incorrectly (from memory) copied into the sources.
@@ -276,5 +279,7 @@
     def checkUserPQuota(self, username, printername) :
         """Checks the user quota on a printer and deny or accept the job."""
-        quota = self.storage.getUserPQuota(username, printername)
+        printerid = self.storage.getPrinterId(printername)
+        userid = self.storage.getUserId(username)
+        quota = self.storage.getUserPQuota(userid, printerid)
         if quota is None :
             # Unknown user or printer or combination
@@ -304,5 +309,5 @@
                             else :
                                 datelimit = now + self.config.getGraceDelay(printername)
-                                self.storage.setDateLimit(username, printername, datelimit)
+                                self.storage.setUserDateLimit(userid, printerid, datelimit)
                             if now < datelimit :
                                 action = "WARN"
Index: /pykota/trunk/pykota/storages/sql.py
===================================================================
--- /pykota/trunk/pykota/storages/sql.py (revision 887)
+++ /pykota/trunk/pykota/storages/sql.py (revision 900)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.22  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.21  2003/04/08 20:38:08  jalet
 # The last job Id is saved now for each printer, this will probably
@@ -99,58 +102,134 @@
 class SQLStorage :    
     def getMatchingPrinters(self, printerpattern) :
-        """Returns the list of all printers tuples (name, pagecounter) which match a certain pattern for the printer name."""
+        """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern."""
         printerslist = []
         # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ...
         # but we don't because other storages semantics may be different, so every
         # storage should use fnmatch to match patterns and be storage agnostic
-        result = self.doQuery("SELECT printername, pagecounter FROM printers;")
+        result = self.doQuery("SELECT id, printername FROM printers;")
         result = self.doParseResult(result)
         if result is not None :
             for printer in result :
                 if fnmatch.fnmatchcase(printer["printername"], printerpattern) :
-                    printerslist.append((printer["printername"], printer["pagecounter"]))
+                    printerslist.append((printer["id"], printer["printername"]))
         return printerslist        
             
-    def addPrinter(self, printername) :        
-        """Adds a printer to the quota storage."""
-        self.doQuery("INSERT INTO printers (printername) VALUES (%s);" % self.doQuote(printername))
-        
-    def getPrinterUsers(self, printername) :        
+    def getPrinterId(self, printername) :        
+        """Returns a printerid given a printername."""
+        result = self.doQuery("SELECT id FROM printers WHERE printername=%s;" % self.doQuote(printername))
+        try :
+            return self.doParseResult(result)[0]["id"]
+        except TypeError :      # Not found    
+            return
+            
+    def getUserId(self, username) :
+        """Returns a userid given a username."""
+        result = self.doQuery("SELECT id FROM users WHERE username=%s;" % self.doQuote(username))
+        try :
+            return self.doParseResult(result)[0]["id"]
+        except TypeError :      # Not found
+            return
+            
+    def getGroupId(self, groupname) :
+        """Returns a groupid given a grupname."""
+        result = self.doQuery("SELECT id FROM groups WHERE groupname=%s;" % self.doQuote(groupname))
+        try :
+            return self.doParseResult(result)[0]["id"]
+        except TypeError :      # Not found
+            return
+            
+    def getJobHistoryId(self, jobid, userid, printerid) :        
+        """Returns the history line's id given a (jobid, userid, printerid)."""
+        result = self.doQuery("SELECT id FROM jobhistory WHERE jobid=%s AND userid=%s AND printerid=%s;" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid)))
+        try :
+            return self.doParseResult(result)[0]["id"]
+        except TypeError :      # Not found    
+            return
+            
+    def getPrinterUsers(self, printerid) :        
         """Returns the list of usernames which uses a given printer."""
-        result = self.doQuery("SELECT DISTINCT username FROM users WHERE id IN (SELECT userid FROM userpquota WHERE printerid IN (SELECT printerid FROM printers WHERE printername=%s)) ORDER BY username;" % self.doQuote(printername))
+        result = self.doQuery("SELECT DISTINCT id, username FROM users WHERE id IN (SELECT userid FROM userpquota WHERE printerid=%s) ORDER BY username;" % self.doQuote(printerid))
         result = self.doParseResult(result)
         if result is None :
             return []
         else :    
-            return [record["username"] for record in result]
-        
-    def getPrinterGroups(self, printername) :        
+            return [(record["id"], record["username"]) for record in result]
+        
+    def getPrinterGroups(self, printerid) :        
         """Returns the list of groups which uses a given printer."""
-        result = self.doQuery("SELECT DISTINCT groupname FROM groups WHERE id IN (SELECT groupid FROM grouppquota WHERE printerid IN (SELECT printerid FROM printers WHERE printername=%s));" % self.doQuote(printername))
+        result = self.doQuery("SELECT DISTINCT id, groupname FROM groups WHERE id IN (SELECT groupid FROM grouppquota WHERE printerid=%s);" % self.doQuote(printerid))
         result = self.doParseResult(result)
         if result is None :
             return []
         else :    
-            return [record["groupname"] for record in result]
-        
-    def getUserId(self, username) :
-        """Returns a userid given a username."""
-        result = self.doQuery("SELECT id FROM users WHERE username=%s;" % self.doQuote(username))
-        try :
-            return self.doParseResult(result)[0]["id"]
-        except TypeError :      # Not found
-            return
-            
-    def getPrinterId(self, printername) :        
-        """Returns a printerid given a printername."""
-        result = self.doQuery("SELECT id FROM printers WHERE printername=%s;" % self.doQuote(printername))
-        try :
-            return self.doParseResult(result)[0]["id"]
+            return [(record["id"], record["groupname"]) for record in result]
+        
+    def addPrinter(self, printername) :        
+        """Adds a printer to the quota storage, returns its id."""
+        self.doQuery("INSERT INTO printers (printername) VALUES (%s);" % self.doQuote(printername))
+        return self.getPrinterId(printername)
+        
+    def addUser(self, username) :        
+        """Adds a user to the quota storage, returns its id."""
+        self.doQuery("INSERT INTO users (username) VALUES (%s);" % self.doQuote(username))
+        return self.getUserId(username)
+        
+    def addGroup(self, groupname) :        
+        """Adds a group to the quota storage, returns its id."""
+        self.doQuery("INSERT INTO groups (groupname) VALUES (%s);" % self.doQuote(groupname))
+        return self.getGroupId(groupname)
+        
+    def addUserPQuota(self, username, printerid) :
+        """Initializes a user print quota on a printer, adds the user to the quota storage if needed."""
+        userid = self.getUserId(username)     
+        if userid is None :    
+            userid = self.addUser(username)
+        self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s);" % (self.doQuote(userid), self.doQuote(printerid)))
+        return (userid, printerid)
+        
+    def addGroupPQuota(self, groupname, printerid) :
+        """Initializes a group print quota on a printer, adds the group to the quota storage if needed."""
+        groupid = self.getGroupId(groupname)     
+        if groupid is None :    
+            groupid = self.addUser(groupname)
+        self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s);" % (self.doQuote(groupid), self.doQuote(printerid)))
+        return (groupid, printerid)
+        
+    def setUserPQuota(self, userid, printerid, softlimit, hardlimit) :
+        """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid)."""
+        self.doQuery("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE userid=%s AND printerid=%s;" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userid), self.doQuote(printerid)))
+        
+    def resetUserPQuota(self, userid, printerid) :    
+        """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged."""
+        self.doQuery("UPDATE userpquota SET pagecounter=0, datelimit=NULL WHERE userid=%s AND printerid=%s;" % (self.doQuote(userid), self.doQuote(printerid)))
+        
+    def updateUserPQuota(self, userid, printerid, pagecount) :
+        """Updates the used user Quota information given (userid, printerid) and a job size in pages."""
+        self.doQuery("UPDATE userpquota SET lifepagecounter=lifepagecounter+(%s), pagecounter=pagecounter+(%s) WHERE userid=%s AND printerid=%s;" % (self.doQuote(pagecount), self.doQuote(pagecount), self.doQuote(userid), self.doQuote(printerid)))
+        
+    def getUserPQuota(self, userid, printerid) :
+        """Returns the Print Quota information for a given (userid, printerid)."""
+        result = self.doQuery("SELECT lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s;" % (self.doQuote(userid), self.doQuote(printerid)))
+        try :
+            return self.doParseResult(result)[0]
         except TypeError :      # Not found    
             return
-            
-    def getPrinterPageCounter(self, printername) :
-        """Returns the last page counter value for a printer given its name."""
-        result = self.doQuery("SELECT pagecounter, lastjobid, lastusername FROM printers WHERE printername=%s;" % self.doQuote(printername))
+        
+    def setUserDateLimit(self, userid, printerid, datelimit) :
+        """Sets the limit date for a soft limit to become an hard one given (userid, printerid)."""
+        self.doQuery("UPDATE userpquota SET datelimit=%s::TIMESTAMP WHERE userid=%s AND printerid=%s;" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(userid), self.doQuote(printerid)))
+        
+    def addJobToHistory(self, jobid, userid, printerid, pagecounter, action) :
+        """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester)."""
+        self.doQuery("INSERT INTO jobhistory (jobid, userid, printerid, pagecounter, action) VALUES (%s, %s, %s, %s, %s);" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid), self.doQuote(pagecounter), self.doQuote(action)))
+        return self.getJobHistoryId(jobid, userid, printerid) # in case jobid is not sufficient
+    
+    def updateJobSizeInHistory(self, historyid, jobsize) :
+        """Updates a job size in the history given the history line's id."""
+        self.doQuery("UPDATE jobhistory SET jobsize=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(historyid)))
+    
+    def getPrinterPageCounter(self, printerid) :
+        """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id."""
+        result = self.doQuery("SELECT jobhistory.id, jobid, userid, username, pagecounter FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1;" % self.doQuote(printerid))
         try :
             return self.doParseResult(result)[0]
@@ -158,55 +237,2 @@
             return
         
-    def updatePrinterPageCounter(self, printername, username, pagecount, jobid) :
-        """Updates the last page counter information for a printer given its name, last username, pagecount and jobid."""
-        return self.doQuery("UPDATE printers SET pagecounter=%s, lastusername=%s, lastjobid=%s WHERE printername=%s;" % (self.doQuote(pagecount), self.doQuote(username), self.doQuote(jobid), self.doQuote(printername)))
-        
-    def addUserPQuota(self, username, printername) :
-        """Initializes a user print quota on a printer, adds the printer and the user to the quota storage if needed."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if printerid is None :    
-            self.addPrinter(printername)        # should we still add it ?
-        if userid is None :    
-            self.doQuery("INSERT INTO users (username) VALUES (%s);" % self.doQuote(username))
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            return self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s);" % (self.doQuote(userid), self.doQuote(printerid)))
-        
-    def getUPIds(self, username, printername) :    
-        """Returns a tuple (userid, printerid) given a username and a printername."""
-        return (self.getUserId(username), self.getPrinterId(printername))
-        
-    def getUserPQuota(self, username, printername) :
-        """Returns the Print Quota information for a given (username, printername)."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            result = self.doQuery("SELECT lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s;" % (self.doQuote(userid), self.doQuote(printerid)))
-            try :
-                return self.doParseResult(result)[0]
-            except TypeError :      # Not found    
-                pass
-        
-    def setUserPQuota(self, username, printername, softlimit, hardlimit) :
-        """Sets soft and hard limits for a user quota on a specific printer given (username, printername)."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            self.doQuery("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE userid=%s AND printerid=%s;" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userid), self.doQuote(printerid)))
-        
-    def resetUserPQuota(self, username, printername) :    
-        """Resets the page counter to zero. Life time page counter is kept unchanged."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            self.doQuery("UPDATE userpquota SET pagecounter=0, datelimit=NULL WHERE userid=%s AND printerid=%s;" % (self.doQuote(userid), self.doQuote(printerid)))
-        
-    def setDateLimit(self, username, printername, datelimit) :
-        """Sets the limit date for a soft limit to become an hard one given (username, printername)."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            self.doQuery("UPDATE userpquota SET datelimit=%s::TIMESTAMP WHERE userid=%s AND printerid=%s;" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(userid), self.doQuote(printerid)))
-        
-    def updateUserPQuota(self, username, printername, pagecount) :
-        """Updates the used user Quota information given (username, printername) and a job size in pages."""
-        (userid, printerid) = self.getUPIds(username, printername)
-        if (userid is not None) and (printerid is not None) :
-            self.doQuery("UPDATE userpquota SET lifepagecounter=lifepagecounter+(%s), pagecounter=pagecounter+(%s) WHERE userid=%s AND printerid=%s;" % (self.doQuote(pagecount), self.doQuote(pagecount), self.doQuote(userid), self.doQuote(printerid)))
-        
Index: /pykota/trunk/pykota/storage.py
===================================================================
--- /pykota/trunk/pykota/storage.py (revision 873)
+++ /pykota/trunk/pykota/storage.py (revision 900)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.11  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.10  2003/03/29 13:45:27  jalet
 # GPL paragraphs were incorrectly (from memory) copied into the sources.
@@ -71,62 +74,4 @@
         return self.message
     __str__ = __repr__
-    
-class BaseStorage :    
-    """Base class for all storages."""
-    def getMatchingPrinters(self, printerpattern) :
-        """Returns the list of all printers tuples (name, pagecounter) which match a certain pattern for the printer name."""
-        pass
-            
-    def addPrinter(self, printername) :        
-        """Adds a printer to the quota storage."""
-        pass
-        
-    def getPrinterUsers(self, printername) :        
-        """Returns the list of usernames which uses a given printer."""
-        pass
-        
-    def getPrinterGroups(self, printername) :        
-        """Returns the list of groups which uses a given printer."""
-        pass
-        
-    def getPrinterPageCounter(self, printername) :
-        """Returns the last page counter value for a printer given its name."""
-        pass
-        
-    def updatePrinterPageCounter(self, printername, username, pagecount) :
-        """Updates the last page counter information for a printer given its name, last username and pagecount."""
-        pass
-        
-    def addUserPQuota(self, username, printername) :
-        """Initializes a user print quota on a printer, adds the printer and the user to the quota storage if needed."""
-        pass
-        
-    def getUPIds(self, username, printername) :    
-        """Returns a tuple (userid, printerid) given a username and a printername."""
-        pass
-        
-    def getUserPQuota(self, username, printername) :
-        """Returns the Print Quota information for a given (username, printername)."""
-        pass
-        
-    def setUserPQuota(self, username, printername, softlimit, hardlimit) :
-        """Sets soft and hard limits for a user quota on a specific printer given (username, printername)."""
-        pass
-        
-    def resetUserPQuota(self, username, printername) :    
-        """Resets the page counter to zero. Life time page counter is kept unchanged."""
-        pass
-        
-    def setDateLimit(self, username, printername, datelimit) :
-        """Sets the limit date for a soft limit to become an hard one given (username, printername)."""
-        pass
-        
-    def updateUserPQuota(self, username, printername, pagecount) :
-        """Updates the used user Quota information given (username, printername) and a job size in pages."""
-        pass
-        
-    def buyUserPQuota(self, username, printername, pagebought) :
-        """Buys pages for a given (username, printername)."""
-        pass
         
 def openConnection(config, asadmin=0) :
Index: /pykota/trunk/bin/warnpykota
===================================================================
--- /pykota/trunk/bin/warnpykota (revision 895)
+++ /pykota/trunk/bin/warnpykota (revision 900)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.15  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.14  2003/04/08 21:31:39  jalet
 # (anything or 0) = anything !!! Go back to school Jerome !
@@ -134,13 +137,13 @@
     def main(self, options) :
         """Warn users or groups over print quota."""
-        printernames = self.storage.getMatchingPrinters(options["printer"])
-        if not printernames :
+        printers = self.storage.getMatchingPrinters(options["printer"])
+        if not printers :
             raise PyKotaToolError, _("There's no printer matching %s") % options["printer"]
-        for (printer, printerpagecounter) in printernames :
+        for (printerid, printer) in printers :
             if options["groups"] :
-                for name in self.storage.getPrinterGroups(printer) :
+                for (ident, name) in self.storage.getPrinterGroups(printerid) :
                     self.warnGroupPQuota(name, printer)
             else :
-                for name in self.storage.getPrinterUsers(printer) :
+                for (ident, name) in self.storage.getPrinterUsers(printerid) :
                     self.warnUserPQuota(name, printer)
                      
Index: /pykota/trunk/bin/edpykota
===================================================================
--- /pykota/trunk/bin/edpykota (revision 895)
+++ /pykota/trunk/bin/edpykota (revision 900)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.33  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.32  2003/04/08 21:31:39  jalet
 # (anything or 0) = anything !!! Go back to school Jerome !
@@ -232,11 +235,11 @@
     def main(self, names, options) :
         """Edit user or group quotas."""
-        printernames = self.storage.getMatchingPrinters(options["printer"])
-        if not printernames :
+        printers = self.storage.getMatchingPrinters(options["printer"])
+        if not printers :
             pname = options["printer"]
             if options["add"] and pname :
                 if self.isValidName(pname) :
-                    self.storage.addPrinter(pname)
-                    printernames = [ (pname, 0) ]
+                    printerid = self.storage.addPrinter(pname)
+                    printers = [ (printerid, pname) ]
                 else :    
                     raise PyKotaToolError, _("Invalid printer name %s") % pname
@@ -263,11 +266,11 @@
             else :    
                 names = [ "*" ] # all users
-        for (printer, printerpagecounter) in printernames :
+        for (printerid, printer) in printers :
             if options["prototype"] :
                 if options["groups"] :
-                    prototype = self.storage.getGroupPQuota(options["prototype"], printer)
+                    prototype = self.storage.getGroupPQuota(self.storage.getGroupId(options["prototype"]), printerid)
                 else :     
                     # default is user quota edition
-                    prototype = self.storage.getUserPQuota(options["prototype"], printer)
+                    prototype = self.storage.getUserPQuota(self.storage.getUserId(options["prototype"]), printerid)
                 if prototype is None :
                     self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (options["prototype"], printer))
@@ -283,18 +286,18 @@
                 if softlimit is not None :
                     self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer))
-            if (not options["reset"] and not options["noquota"]) and ((hardlimit is None) or (softlimit is None)) :
+            if (not options["reset"] and not options["noquota"] and not options["prototype"]) and ((hardlimit is None) or (softlimit is None)) :
                 raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.")
             if options["add"] :    
-                allnames = names
+                allidnames = [(None, n) for n in names]
             else :   
                 if options["groups"] :    
-                    allnames = self.storage.getPrinterGroups(printer)
+                    allidnames = self.storage.getPrinterGroups(printerid)
                 else :    
-                    allnames = self.storage.getPrinterUsers(printer)
-            for name in [n for n in allnames if self.matchString(n, names)]:
+                    allidnames = self.storage.getPrinterUsers(printerid)
+            for (ident, name) in [(i, n) for (i, n) in allidnames if self.matchString(n, names)]:
                 if options["groups"] :
-                    quota = self.storage.getGroupPQuota(name, printer)
+                    quota = self.storage.getGroupPQuota(ident, printerid)
                 else :
-                    quota = self.storage.getUserPQuota(name, printer)
+                    quota = self.storage.getUserPQuota(ident, printerid)
                 if quota is None :
                     # not found
@@ -306,12 +309,12 @@
                         if options["groups"] :
                             if self.isValidName(name) :
-                                self.storage.addGroupPQuota(name, printer)
-                                quota = self.storage.getGroupPQuota(name, printer)
+                                (ident, printerid) = self.storage.addGroupPQuota(name, printerid)
+                                quota = self.storage.getGroupPQuota(ident, printerid)
                             else :    
                                 self.logger.log_message(_("Invalid group name %s") % name)
                         else :
                             if self.isValidName(name) :
-                                self.storage.addUserPQuota(name, printer)
-                                quota = self.storage.getUserPQuota(name, printer)
+                                (ident, printerid) = self.storage.addUserPQuota(name, printerid)
+                                quota = self.storage.getUserPQuota(ident, printerid)
                             else :    
                                 self.logger.log_message(_("Invalid user name %s") % name)
@@ -320,13 +323,15 @@
                 else :    
                     if options["groups"] :
-                        if options["noquota"] or ((softlimit is not None) and (hardlimit is not None)) :
-                            self.storage.setGroupPQuota(name, printer, softlimit, hardlimit)
+                        if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
+                            self.storage.setGroupPQuota(ident, printerid, softlimit, hardlimit)
                         if options["reset"] :
-                            self.storage.resetGroupPQuota(name, printer)
+                            self.storage.resetGroupPQuota(ident, printerid)
+                        self.warnGroupPQuota(name, printer)    
                     else :
-                        if options["noquota"] or ((softlimit is not None) and (hardlimit is not None)) :
-                            self.storage.setUserPQuota(name, printer, softlimit, hardlimit)
+                        if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) :
+                            self.storage.setUserPQuota(ident, printerid, softlimit, hardlimit)
                         if options["reset"] :
-                            self.storage.resetUserPQuota(name, printer)
+                            self.storage.resetUserPQuota(ident, printerid)
+                        self.warnUserPQuota(name, printer)    
                      
 if __name__ == "__main__" : 
Index: /pykota/trunk/bin/pykota
===================================================================
--- /pykota/trunk/bin/pykota (revision 887)
+++ /pykota/trunk/bin/pykota (revision 900)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.17  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.16  2003/04/08 20:38:08  jalet
 # The last job Id is saved now for each printer, this will probably
@@ -151,4 +154,5 @@
         # can't get actual page counter, assume printer is off, but warns in log
         kotafilter.logger.log_message("%s" % msg, "warn")
+        counterbeforejob = None
         printerIsOff = 1
     else :    
@@ -156,41 +160,52 @@
         
     # Get the last page counter and last username from the Quota Storage backend
-    pgc = kotafilter.storage.getPrinterPageCounter(kotafilter.printername)    
-    if pgc is None :
+    printerid = kotafilter.storage.getPrinterId(kotafilter.printername)
+    if printerid is None :
         # The printer is unknown from the Quota Storage perspective
         # we let the job pass through, but log a warning message
         kotafilter.logger.log_message(_("Printer %s not registered in the PyKota system") % kotafilter.printername, "warn")
     else :    
-        # get last values from Quota Storage
-        (lastpagecounter, lastjobid, lastusername) = (pgc["pagecounter"], pgc["lastjobid"], pgc["lastusername"])
-        
-        # if printer is off then we assume the correct counter value is the last one
-        if printerIsOff :
-            counterbeforejob = lastpagecounter
+        userid = kotafilter.storage.getUserId(username)
+        if userid is None :
+            # The user is unknown from the Quota Storage perspective
+            # we let the job pass through, but log a warning message
+            kotafilter.logger.log_message(_("User %s not registered in the PyKota system") % username, "warn")
+        else :
+            pgc = kotafilter.storage.getPrinterPageCounter(printerid)    
+            if pgc is None :
+                # The printer hasn't been used yet, from PyKota's point of view
+                lasthistoryid = None
+                lastjobid = jobid
+                lastuserid = userid
+                lastusername = username
+                lastpagecounter = counterbeforejob
+            else :    
+                # get last values from Quota Storage
+                (lasthistoryid, lastjobid, lastuserid, lastusername, lastpagecounter) = (pgc["id"], pgc["jobid"], pgc["userid"], pgc["username"], pgc["pagecounter"])
+                
+            # if printer is off then we assume the correct counter value is the last one
+            if printerIsOff :
+                counterbeforejob = lastpagecounter
+                
+            # Update the quota for the previous user on this printer according 
+            # to the job size (difference between actual counter and latest one from storage)
+            jobsize = (counterbeforejob - lastpagecounter)    
+            if jobsize >= 0 :
+                kotafilter.storage.updateUserPQuota(lastuserid, printerid, jobsize)
+                kotafilter.storage.updateJobSizeInHistory(lasthistoryid, jobsize)
+                kotafilter.warnUserPQuota(lastusername)
+            else :    
+                kotafilter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastusername, kotafilter.printername), "error")
+                
+            # Is the current user allowed to print at all ?
+            action = kotafilter.warnUserPQuota(username)
             
-        # Update the last page counter and last username in the Quota Storage backend
-        # set them to current user and 
-        kotafilter.storage.updatePrinterPageCounter(kotafilter.printername, username, counterbeforejob, jobid)
-        
-        # Was the printer ever used ?
-        if (lastpagecounter is None) or (lastusername is None) :
-            lastusername = username
-            lastpagecounter = counterbeforejob
+            # adds the current job to history    
+            kotafilter.storage.addJobToHistory(jobid, kotafilter.storage.getUserId(username), printerid, counterbeforejob, action)
             
-        # Update the quota for the previous user on this printer according 
-        # to the job size (difference between actual counter and latest one from storage)
-        jobsize = (counterbeforejob - lastpagecounter)    
-        if jobsize >= 0 :
-            kotafilter.storage.updateUserPQuota(lastusername, kotafilter.printername, jobsize)
-            kotafilter.warnUserPQuota(lastusername)
-        else :    
-            kotafilter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, kotafilter.printername, lastusername), "error")
-            
-        # Is the current user allowed to print at all ?
-        # if no then die, else proceed.
-        action = kotafilter.warnUserPQuota(username)
-        if action == "DENY" :
-            # No, just die cleanly
-            return 1
+            # if not allowed to print then die, else proceed.
+            if action == "DENY" :
+                # No, just die cleanly
+                return 1
         
     # pass the job untouched to the underlying layer
Index: /pykota/trunk/bin/repykota
===================================================================
--- /pykota/trunk/bin/repykota (revision 895)
+++ /pykota/trunk/bin/repykota (revision 900)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.21  2003/04/10 21:47:20  jalet
+# Job history added. Upgrade script neutralized for now !
+#
 # Revision 1.20  2003/04/08 21:31:39  jalet
 # (anything or 0) = anything !!! Go back to school Jerome !
@@ -149,8 +152,8 @@
     def main(self, options) :
         """Print Quota reports generator."""
-        printernames = self.storage.getMatchingPrinters(options["printer"])
-        if not printernames :
+        printers = self.storage.getMatchingPrinters(options["printer"])
+        if not printers :
             raise PyKotaToolError, _("There's no printer matching %s") % options["printer"]
-        for (printer, printerpagecounter) in printernames :
+        for (printerid, printer) in printers :
             print _("*** Report for %s quota on printer %s") % ((options["users"] and "user") or "group", printer)
             print _("Pages grace time: %idays") % self.config.getGraceDelay(printer)
@@ -159,6 +162,6 @@
                 print _("Group            used     soft     hard   grace        total")
                 print "------------------------------------------------------------"
-                for name in self.storage.getPrinterGroups(printer) :
-                    quota = self.storage.getGroupPQuota(name, printer) 
+                for name in self.storage.getPrinterGroups(printerid) :
+                    quota = self.storage.getGroupPQuota(ident, printerid) 
                     total += self.printQuota(name, quota)
             else :
@@ -166,13 +169,14 @@
                 print _("User             used     soft     hard   grace        total")
                 print "------------------------------------------------------------"
-                for name in self.storage.getPrinterUsers(printer) :
-                    quota = self.storage.getUserPQuota(name, printer)
+                for (ident, name) in self.storage.getPrinterUsers(printerid) :
+                    quota = self.storage.getUserPQuota(ident, printerid)
                     total += self.printQuota(name, quota)
             if total :        
                 print (" " * 43) + (_("Total : %9i") % total)
+            printerpagecounter = self.storage.getPrinterPageCounter(printerid)
             if printerpagecounter is None :    
                 msg = _("unknown")
             else :
-                msg = "%9i" % printerpagecounter
+                msg = "%9i" % printerpagecounter["pagecounter"]
             print (" " * 44) + (_("Real : %s") % msg)
             print        
Index: /pykota/trunk/initscripts/README.postgresql
===================================================================
--- /pykota/trunk/initscripts/README.postgresql (revision 887)
+++ /pykota/trunk/initscripts/README.postgresql (revision 900)
@@ -93,4 +93,4 @@
   1.03, YOU HAVE TO RUN the upgrade-1.01-to-1.03.sh shell script.
   NOT LAUNCHING THIS SCRIPT WILL CAUSE PYKOTA TO STOP WORKING !
-  Please don't run this script if your version of PyKota is already
-  1.03 or higher.
+  Please don't run this script if your existing version of PyKota is 
+  already 1.03 or higher.
Index: /pykota/trunk/initscripts/pykota-postgresql.sql
===================================================================
--- /pykota/trunk/initscripts/pykota-postgresql.sql (revision 897)
+++ /pykota/trunk/initscripts/pykota-postgresql.sql (revision 900)
@@ -20,4 +20,7 @@
 --
 -- $Log$
+-- Revision 1.10  2003/04/10 21:47:20  jalet
+-- Job history added. Upgrade script neutralized for now !
+--
 -- Revision 1.9  2003/04/09 20:11:29  jalet
 -- Added a field to save the action taken for this job (Allow, Deny)
@@ -93,8 +96,5 @@
 --
 CREATE TABLE printers(id SERIAL PRIMARY KEY NOT NULL,
-                      printername TEXT UNIQUE NOT NULL,
-                      lastjobid TEXT,
-                      lastusername TEXT,
-                      pagecounter INT4 DEFAULT 0);
+                      printername TEXT UNIQUE NOT NULL);
                     
 --
@@ -111,5 +111,5 @@
                         
 --
--- Create the job history table for u
+-- Create the job history table
 --
 CREATE TABLE jobhistory(id SERIAL PRIMARY KEY NOT NULL,
@@ -117,6 +117,7 @@
                         userid INT4 REFERENCES users(id),
                         printerid INT4 REFERENCES printers(id),
+                        pagecounter INT4 DEFAULT 0,
+                        jobsize INT4,
                         action TEXT,
-                        jobsize INT4,
                         jobdate TIMESTAMP DEFAULT now());
                         
@@ -145,4 +146,6 @@
 GRANT SELECT, UPDATE ON users_id_seq, groups_id_seq, printers_id_seq, userpquota_id_seq, grouppquota_id_seq, jobhistory_id_seq TO pykotaadmin;
 GRANT SELECT, UPDATE ON printers, userpquota, grouppquota TO pykotauser;
-GRANT SELECT ON users, groups, groupsmembers, jobhistory TO pykotauser;
+GRANT SELECT ON users, groups, groupsmembers TO pykotauser;
+GRANT SELECT, INSERT, UPDATE ON jobhistory TO pykotauser;
+GRANT SELECT, UPDATE ON jobhistory_id_seq TO pykotauser;
 
Index: /pykota/trunk/initscripts/upgrade-1.01-to-1.03.sh
===================================================================
--- /pykota/trunk/initscripts/upgrade-1.01-to-1.03.sh (revision 888)
+++ /pykota/trunk/initscripts/upgrade-1.01-to-1.03.sh (revision 900)
@@ -5,16 +5,22 @@
 echo WARNING : If unsure press Ctrl+C NOW TO STOP, else press ENTER TO PROCEED
 read
-echo -n Update begins...
-pg_dump -D -N -U postgres -f pykotadb-full.dump pykota >update.messages 2>update.errors
-pg_dump -a -D -N -U postgres -f pykotadb.dump pykota >>update.messages 2>>update.errors
-dropdb pykota >>update.messages 2>>update.errors
-dropuser pykotaadmin >>update.messages 2>>update.errors
-dropuser pykotauser >>update.messages 2>>update.errors
-psql -U postgres template1 -f pykota-postgresql.sql >>update.messages 2>>update.errors
-psql -U postgres pykota -f pykotadb.dump >>update.messages 2>>update.errors
-echo
-echo Done !
-echo Check the files update.messages and update.errors to see if all is OK.
-echo NOTICE messages are normal and expected. In case other message types
-echo are found in update.errors, please file a bug report and restore
-echo your database from pykotadb-full.dump
+
+echo This script does not work at all yet !
+echo Please be patient so that I can write a safe upgrade script
+echo of completely drop your existing database to start anew
+echo with this version of PyKota.
+
+#echo -n Update begins...
+#pg_dump -D -N -U postgres -f pykotadb-full.dump pykota >upgrade.messages 2>upgrade.errors
+#pg_dump -a -D -N -U postgres -f pykotadb.dump pykota >>upgrade.messages 2>>upgrade.errors
+#dropdb pykota >>upgrade.messages 2>>upgrade.errors
+#dropuser pykotaadmin >>upgrade.messages 2>>upgrade.errors
+#dropuser pykotauser >>upgrade.messages 2>>upgrade.errors
+#psql -U postgres template1 -f pykota-postgresql.sql >>upgrade.messages 2>>upgrade.errors
+#psql -U postgres pykota -f pykotadb.dump >>upgrade.messages 2>>upgrade.errors
+#echo
+#echo Done !
+#echo Check the files upgrade.messages and upgrade.errors to see if all is OK.
+#echo NOTICE messages are normal and expected. In case other message types
+#echo are found in upgrade.errors, please file a bug report and restore
+#echo your database from pykotadb-full.dump
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 899)
+++ /pykota/trunk/NEWS (revision 900)
@@ -24,8 +24,8 @@
     - 1.03alpha :
     
-        - IMPORTANT : DataBase schema has changed, YOU HAVE TO
-          UPGRADE using the upgrade-1.01-to-1.03.sh script.
-          Please read initscripts/README first and then 
-          read initscripts/README.postgresql
+        - IMPORTANT : DataBase schema has changed.
+          DON'T TRY TO UPGRADE AN EXISTING PYKOTA INSTALLATION !
+          The upgrade script will be finalized ASAP, be patient,
+          or drop your old quota database to start anew.
           
         - The installation script now allows to install the sample
@@ -38,5 +38,9 @@
         - The job history is now kept, this will allow per-period
           reports in the future.
-        
+          
+        - After having modified the quota for an user with edpykota,
+          a quota check is done to eventually warn the user/admin about
+          a quota which is too low to print.
+          
     - 1.02 :
     
