Index: pykota/trunk/bin/edpykota
===================================================================
--- pykota/trunk/bin/edpykota (revision 2344)
+++ pykota/trunk/bin/edpykota (revision 2452)
@@ -100,4 +100,5 @@
                        
   -n | --noquota       Doesn't set a quota but only does accounting.
+                       This is the same as --limitby noquota.
   
   -r | --reset         Resets the actual page counter for the user
@@ -112,8 +113,13 @@
                        by its account balance or by its page quota.
                        The default value is 'quota'. Allowed values
-                       are 'quota' 'balance' 'quota-then-balance' and
-                       'balance-then-quota'.
-                       WARNING : quota-then-balance and balance-then-quota
-                       are not yet implemented.
+                       are 'quota' 'balance' 'noquota' 'noprint' 
+                       and 'nochange' :
+                       
+                         - quota : limit by number of pages per printer.
+                         - balance : limit by number of credits in account.
+                         - noquota : no limit, accounting still done.
+                         - nochange : no limit, accounting not done. 
+                         - noprint : printing is denied. 
+                       NB : nochange and noprint are not supported for groups.
                        
   -b | --balance b     Sets the user's account balance to b.                     
@@ -125,4 +131,8 @@
                        Groups don't have a real balance, but the
                        sum of their users' account balance.
+                       
+  -C | --comment txt   Defines some informational text to be associated
+                       with a change to an user's account balance.
+                       Only meaningful if -b | --balance is also used.
                        
   -S | --softlimit sl  Sets the quota soft limit to sl pages.                       
@@ -237,4 +247,19 @@
         
         softlimit = hardlimit = None
+        
+        if options["noquota"] :
+            options["limitby"] = "noquota"
+            
+        limitby = options["limitby"]
+        if limitby :
+            limitby = limitby.strip().lower()
+        if limitby :
+            if limitby not in ('quota', 'balance', 'noquota', \
+                                        'noprint', 'nochange') :
+                raise PyKotaToolError, _("Invalid limitby value %s") % options["limitby"]
+            if limitby in ('noquota', 'nochange') :    
+                options["noquota"] = 1
+            if (limitby in ('nochange', 'noprint')) and options["groups"] :    
+                raise PyKotaToolError, _("Invalid limitby value %s") % options["limitby"]
 
         used = options["used"]
@@ -288,10 +313,4 @@
                     charges = [charges[0], None]
                     
-        limitby = options["limitby"]
-        if limitby :
-            limitby = limitby.strip().lower()
-        if limitby and (limitby not in ('quota', 'balance', 'quota-then-balance', 'balance-then-quota')) :    
-            raise PyKotaToolError, _("Invalid limitby value %s") % options["limitby"]
-            
         if options["ingroups"] :    
             groupnames = [gname.strip() for gname in options["ingroups"].split(',')]
@@ -474,9 +493,9 @@
                                     newbalance = float(entry.AccountBalance or 0.0) + balancevalue
                                     newlifetimepaid = float(entry.LifeTimePaid or 0.0) + balancevalue
-                                    entry.setAccountBalance(newbalance, newlifetimepaid)
+                                    entry.setAccountBalance(newbalance, newlifetimepaid, options["comment"])
                                 else :
                                     diff = balancevalue - float(entry.AccountBalance or 0.0)
                                     newlifetimepaid = float(entry.LifeTimePaid or 0.0) + diff
-                                    entry.setAccountBalance(balancevalue, newlifetimepaid)
+                                    entry.setAccountBalance(balancevalue, newlifetimepaid, options["comment"])
                                 changed[entry.Name]["balance"] = balance
                                 
@@ -506,7 +525,13 @@
         defaults = { \
                      "printer" : "*", \
+                     "comment" : "", \
                    }
-        short_options = "vhdo:c:l:b:i:naugrp:P:S:H:G:RU:"
-        long_options = ["help", "version", "overcharge=", "charge=", "delete", "limitby=", "balance=", "ingroups=", "noquota", "add", "users", "groups", "reset", "hardreset", "prototype=", "printer=", "softlimit=", "hardlimit=", "pgroups=", "used="]
+        short_options = "vhdo:c:C:l:b:i:naugrp:P:S:H:G:RU:"
+        long_options = ["help", "version", "comment=", \
+                        "overcharge=", "charge=", "delete", "limitby=", \
+                        "balance=", "ingroups=", "noquota", "add", "users", \
+                        "groups", "reset", "hardreset", "prototype=", \
+                        "printer=", "softlimit=", "hardlimit=", "pgroups=", \
+                        "used="]
         
         # Initializes the command line tool
@@ -538,4 +563,5 @@
         options["used"] = options["U"] or options["used"]
         options["overcharge"] = options["o"] or options["overcharge"]
+        options["comment"] = options["C"] or options["comment"] or defaults["comment"]
         
         if options["help"] :
@@ -553,4 +579,6 @@
         elif options["groups"] and (options["balance"] or options["ingroups"] or options["used"] or options["overcharge"]) :
             raise PyKotaToolError, _("incompatible options, see help.")
+        elif options["comment"] and not options["balance"] :    
+            raise PyKotaToolError, _("incompatible options, see help.")
         else :
             retcode = editor.main(args, options)
Index: pykota/trunk/bin/repykota
===================================================================
--- pykota/trunk/bin/repykota (revision 2344)
+++ pykota/trunk/bin/repykota (revision 2452)
@@ -55,4 +55,7 @@
   -g | --groups        Generates a report on group quota instead of users.
   
+  -i | --ingroups g1[,g2...]  Only lists users who are members of these
+                              groups. Reserved to PyKota Administrators.
+  
   -P | --printer p     Report quotas on this printer only. Actually p can
                        use wildcards characters to select only
@@ -92,7 +95,21 @@
                 # no username, means all usernames
                 ugnames = [ "*" ]
+                
+            if options["ingroups"] :
+                groupsnames = options["ingroups"].split(",")
+                groups = [self.storage.getGroup(gname) for gname in groupsnames]
+                members = {}
+                for group in groups :
+                    if not group.Exists :
+                        self.printInfo("Group %s doesn't exist." % group.Name, "warn")
+                    else :    
+                        for user in self.storage.getGroupMembers(group) :
+                            members[user.Name] = user
+                ugnames = [ m for m in members.keys() if self.matchString(m, ugnames) ]
         else :        
-            # not the root user
             # reports only the current user
+            if options["ingroups"] :
+                raise PyKotaToolError, _("Option --ingroups is reserved to PyKota Administrators.")
+                
             username = pwd.getpwuid(os.geteuid())[0]
             if options["groups"] :
@@ -118,6 +135,6 @@
                      "printer" : "*", \
                    }
-        short_options = "vhugP:"
-        long_options = ["help", "version", "users", "groups", "printer="]
+        short_options = "vhugi:P:"
+        long_options = ["help", "version", "users", "groups", "ingroups=", "printer="]
         
         # Initializes the command line tool
@@ -134,4 +151,5 @@
         options["groups"] = options["g"] or options["groups"]
         options["printer"] = options["P"] or options["printer"] or defaults["printer"]
+        options["ingroups"] = options["i"] or options["ingroups"]
         
         if options["help"] :
Index: pykota/trunk/bin/cupspykota
===================================================================
--- pykota/trunk/bin/cupspykota (revision 2449)
+++ pykota/trunk/bin/cupspykota (revision 2452)
@@ -823,4 +823,9 @@
         
         if self.Action != "DENY" :
+            if self.User.LimitBy == "noprint" :
+                self.printInfo(_("User %s is not allowed to print at this time.") % self.UserName, "warn")
+                self.Action = "DENY"
+                
+        if self.Action != "DENY" :
             # If printing is still allowed at this time, we
             # need to extract the billing code information from the database.
@@ -841,7 +846,10 @@
             # No need to do this if the job is denied, this way we
             # save some database queries.
-            self.logdebug("Checking user %s print quota entry on printer %s" \
+            if self.User.LimitBy in ('noquota', 'nochange') :
+                self.logdebug("User %s is allowed to print with no limit, no need to check quota." % self.UserName)
+            else :
+                self.logdebug("Checking user %s print quota entry on printer %s" \
                                     % (self.UserName, self.PrinterName))
-            self.Action = self.warnUserPQuota(self.UserPQuota)
+                self.Action = self.warnUserPQuota(self.UserPQuota)
             
         # exports some new environment variables
@@ -912,7 +920,12 @@
             self.printInfo(_("Job size : %i") % self.JobSize)
             
-            # update the quota for the current user on this printer 
-            self.printInfo(_("Updating user %s's quota on printer %s") % (self.UserName, self.PrinterName))
-            self.JobPrice = self.UserPQuota.increasePagesUsage(self.JobSize)
+            if self.User.LimitBy == "nochange" :
+                # no need to update the quota for the current user on this printer
+                self.printInfo(_("User %s's quota on printer %s won't be modified") % (self.UserName, self.PrinterName))
+                self.JobPrice = self.UserPQuota.computeJobPrice(self.JobSize)
+            else :
+                # update the quota for the current user on this printer 
+                self.printInfo(_("Updating user %s's quota on printer %s") % (self.UserName, self.PrinterName))
+                self.JobPrice = self.UserPQuota.increasePagesUsage(self.JobSize)
             
             # adds the current job to history    
