Index: /pykota/trunk/README
===================================================================
--- /pykota/trunk/README (revision 926)
+++ /pykota/trunk/README (revision 927)
@@ -30,5 +30,5 @@
 Actual working features :
 
-        - Per printer user quotas.
+        - Per printer user and group quotas.
         
         - Automated email warning of users above quota to the
@@ -195,5 +195,6 @@
 Copy the conf/pykota.conf.sample sample configuration file to
 /etc/pykota.conf, and adapt this file to your own needs and 
-configuration.
+configuration. The installation script tries to do this for
+you if needed and you agreed to this action.
 
 Modify the PPD files for each printer on which you want to manage
@@ -249,7 +250,4 @@
     along with totals.
     
-WARNING : as of today, 2003-02-06, group quotas are not
-implemented.
-
 SECURITY : You should ensure that only the print quota administrator
            can run the warnpykota command, but this is actually not
Index: /pykota/trunk/TODO
===================================================================
--- /pykota/trunk/TODO (revision 873)
+++ /pykota/trunk/TODO (revision 927)
@@ -22,6 +22,4 @@
 TODO, in order of importance :
 
-        - Finalize the implementation of group quotas.
-        
         - Group administrators (think quotagrpdmins for disk quotas).
         
Index: /pykota/trunk/pykota/tool.py
===================================================================
--- /pykota/trunk/pykota/tool.py (revision 925)
+++ /pykota/trunk/pykota/tool.py (revision 927)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.33  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.32  2003/04/16 08:53:14  jalet
 # Printing can now be limited either by user's account balance or by
@@ -287,8 +290,83 @@
         self.sendMessage(adminmail, adminmail, "Subject: %s\n\n%s" % (subject, message))
         
+    def checkGroupPQuota(self, groupname, printername) :    
+        """Checks the group quota on a printer and deny or accept the job."""
+        printerid = self.storage.getPrinterId(printername)
+        groupid = self.storage.getGroupId(groupname)
+        limitby = self.storage.getGroupLimitBy(groupid)
+        if limitby == "balance" : 
+            balance = self.storage.getGroupBalance(groupid)
+            if balance is None :
+                policy = self.config.getPrinterPolicy(printername)
+                if policy in [None, "ALLOW"] :
+                    action = "POLICY_ALLOW"
+                else :    
+                    action = "POLICY_DENY"
+                self.logger.log_message(_("Unable to find group %s's account balance, applying default policy (%s) for printer %s") % (groupname, action, printername))
+            else :    
+                # TODO : there's no warning (no account balance soft limit)
+                if balance <= 0.0 :
+                    action = "DENY"
+                else :    
+                    action = "ALLOW"
+        else :
+            quota = self.storage.getGroupPQuota(groupid, printerid)
+            if quota is None :
+                # Unknown group or printer or combination
+                policy = self.config.getPrinterPolicy(printername)
+                if policy in [None, "ALLOW"] :
+                    action = "POLICY_ALLOW"
+                else :    
+                    action = "POLICY_DENY"
+                self.logger.log_message(_("Unable to match group %s on printer %s, applying default policy (%s)") % (groupname, printername, action))
+            else :    
+                pagecounter = quota["pagecounter"]
+                softlimit = quota["softlimit"]
+                hardlimit = quota["hardlimit"]
+                datelimit = quota["datelimit"]
+                if softlimit is not None :
+                    if pagecounter < softlimit :
+                        action = "ALLOW"
+                    else :    
+                        if hardlimit is None :
+                            # only a soft limit, this is equivalent to having only a hard limit
+                            action = "DENY"
+                        else :    
+                            if softlimit <= pagecounter < hardlimit :    
+                                now = DateTime.now()
+                                if datelimit is not None :
+                                    datelimit = DateTime.ISO.ParseDateTime(datelimit)
+                                else :
+                                    datelimit = now + self.config.getGraceDelay(printername)
+                                    self.storage.setGroupDateLimit(groupid, printerid, datelimit)
+                                if now < datelimit :
+                                    action = "WARN"
+                                else :    
+                                    action = "DENY"
+                            else :         
+                                action = "DENY"
+                else :        
+                    if hardlimit is not None :
+                        # no soft limit, only a hard one.
+                        if pagecounter < hardlimit :
+                            action = "ALLOW"
+                        else :      
+                            action = "DENY"
+                    else :
+                        # Both are unset, no quota, i.e. accounting only
+                        action = "ALLOW"
+        return action
+    
     def checkUserPQuota(self, username, printername) :
         """Checks the user quota on a printer and deny or accept the job."""
+        # first we check any group the user is a member of
+        userid = self.storage.getUserId(username)
+        for groupname in self.storage.getUserGroupsNames(userid) :
+            action = self.checkGroupPQuota(groupname, printername)
+            if action in ("DENY", "POLICY_DENY") :
+                return action
+                
+        # then we check the user's own quota
         printerid = self.storage.getPrinterId(printername)
-        userid = self.storage.getUserId(username)
         limitby = self.storage.getUserLimitBy(userid)
         if limitby == "balance" : 
@@ -355,8 +433,31 @@
         return action
     
-    def warnGroupPQuota(self, username, printername=None) :
-        """Checks a user quota and send him a message if quota is exceeded on current printer."""
+    def warnGroupPQuota(self, groupname, printername=None) :
+        """Checks a group quota and send messages if quota is exceeded on current printer."""
         pname = printername or self.printername
-        raise PyKotaToolError, _("Group quotas are currently not implemented.")
+        admin = self.config.getAdmin(pname)
+        adminmail = self.config.getAdminMail(pname)
+        mailto = self.config.getMailTo(pname)
+        action = self.checkGroupPQuota(groupname, pname)
+        groupmembers = self.storage.getGroupMembersNames(groupname)
+        if action.startswith("POLICY_") :
+            action = action[7:]
+        if action == "DENY" :
+            adminmessage = _("Print Quota exceeded for group %s on printer %s") % (groupname, pname)
+            self.logger.log_message(adminmessage)
+            if mailto in [ "BOTH", "ADMIN" ] :
+                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage)
+            for username in groupmembers :
+                if mailto in [ "BOTH", "USER" ] :
+                    self.sendMessageToUser(admin, adminmail, username, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour group Print Quota is exceeded on printer %s.") % pname)
+        elif action == "WARN" :    
+            adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (groupname, pname)
+            self.logger.log_message(adminmessage)
+            if mailto in [ "BOTH", "ADMIN" ] :
+                self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage)
+            for username in groupmembers :
+                if mailto in [ "BOTH", "USER" ] :
+                    self.sendMessageToUser(admin, adminmail, username, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour group Print Quota is almost reached on printer %s.") % pname)
+        return action        
         
     def warnUserPQuota(self, username, printername=None) :
Index: /pykota/trunk/pykota/storages/sql.py
===================================================================
--- /pykota/trunk/pykota/storages/sql.py (revision 925)
+++ /pykota/trunk/pykota/storages/sql.py (revision 927)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.27  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.26  2003/04/16 08:53:14  jalet
 # Printing can now be limited either by user's account balance or by
@@ -196,4 +199,18 @@
             return [(record["id"], record["groupname"]) for record in result]
         
+    def getGroupMembersNames(self, groupname) :        
+        """Returns the list of user's names which are member of this group."""
+        groupid = self.getGroupId(groupname)
+        if groupid is None :
+            return []
+        else :
+            result = self.doQuery("SELECT DISTINCT username FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid))
+            return [record["username"] for record in (self.doParseResult(result) or [])]
+        
+    def getUserGroupsNames(self, userid) :        
+        """Returns the list of groups' names the user is a member of."""
+        result = self.doQuery("SELECT DISTINCT groupname FROM groups WHERE id IN (SELECT groupid FROM groupsmembers WHERE userid=%s)" % self.doQuote(userid))
+        return [record["groupname"] for record in (self.doParseResult(result) or [])]
+        
     def addPrinter(self, printername) :        
         """Adds a printer to the quota storage, returns its id."""
@@ -216,5 +233,7 @@
         if userid is None :    
             userid = self.addUser(username)
-        self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid)))
+        uqexists = (self.getUserPQuota(userid, printerid) is not None)    
+        if not uqexists : 
+            self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid)))
         return (userid, printerid)
         
@@ -223,6 +242,8 @@
         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)))
+            groupid = self.addGroup(groupname)
+        gqexists = (self.getGroupPQuota(groupid, printerid) is not None)    
+        if not gqexists : 
+            self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(printerid)))
         return (groupid, printerid)
         
@@ -234,4 +255,12 @@
         """Returns the current account balance for a given user."""
         result = self.doQuery("SELECT balance FROM users WHERE id=%s" % self.doQuote(userid))
+        try :
+            return self.doParseResult(result)[0]["balance"]
+        except TypeError :      # Not found    
+            return
+        
+    def getGroupBalance(self, groupid) :    
+        """Returns the current account balance for a given group, as the sum of each of its users' account balance."""
+        result = self.doQuery("SELECT SUM(balance) AS balance FROM users WHERE id in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid))
         try :
             return self.doParseResult(result)[0]["balance"]
@@ -273,7 +302,15 @@
         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 setGroupPQuota(self, groupid, printerid, softlimit, hardlimit) :
+        """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid)."""
+        self.doQuery("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(groupid), 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 resetGroupPQuota(self, groupid, printerid) :    
+        """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged."""
+        self.doQuery("UPDATE grouppquota SET pagecounter=0, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid)))
         
     def updateUserPQuota(self, userid, printerid, pagecount) :
@@ -293,7 +330,28 @@
             return
         
+    def getGroupPQuota(self, groupid, printerid) :
+        """Returns the Print Quota information for a given (groupid, printerid)."""
+        result = self.doQuery("SELECT softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid)))
+        try :
+            grouppquota = self.doParseResult(result)[0]
+        except TypeError :    
+            return
+        else :    
+            result = self.doQuery("SELECT SUM(lifepagecounter) as lifepagecounter, SUM(pagecounter) as pagecounter FROM userpquota WHERE printerid=%s AND userid in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % (self.doQuote(printerid), self.doQuote(groupid)))
+            try :
+                result = self.doParseResult(result)[0]
+            except TypeError :      # Not found    
+                return
+            else :    
+                grouppquota.update({"lifepagecounter": result["lifepagecounter"], "pagecounter": result["pagecounter"]})
+                return grouppquota
+        
     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 setGroupDateLimit(self, groupid, printerid, datelimit) :
+        """Sets the limit date for a soft limit to become an hard one given (groupid, printerid)."""
+        self.doQuery("UPDATE grouppquota SET datelimit=%s::TIMESTAMP WHERE groupid=%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(groupid), self.doQuote(printerid)))
         
     def addJobToHistory(self, jobid, userid, printerid, pagecounter, action) :
@@ -314,4 +372,14 @@
             return
         
+    def addUserToGroup(self, userid, groupid) :    
+        """Adds an user to a group."""
+        result = self.doQuery("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(groupid), self.doQuote(userid)))
+        try :
+            mexists = self.doParseResult(result)[0]["mexists"]
+        except TypeError :    
+            mexists = 0
+        if not mexists :    
+            self.doQuery("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(userid)))
+        
     def deleteUser(self, userid) :    
         """Completely deletes an user from the Quota Storage."""
Index: /pykota/trunk/pykota/version.py
===================================================================
--- /pykota/trunk/pykota/version.py (revision 883)
+++ /pykota/trunk/pykota/version.py (revision 927)
@@ -21,5 +21,5 @@
 #
 
-__version__ = "1.03alpha-unofficial"
+__version__ = "1.03beta-unofficial"
 
 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS."""
Index: /pykota/trunk/bin/warnpykota
===================================================================
--- /pykota/trunk/bin/warnpykota (revision 900)
+++ /pykota/trunk/bin/warnpykota (revision 927)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.16  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.15  2003/04/10 21:47:20  jalet
 # Job history added. Upgrade script neutralized for now !
@@ -175,6 +178,4 @@
         elif options["users"] and options["groups"] :    
             raise PyKotaToolError, _("incompatible options, see help.")
-        elif options["groups"] :    
-            raise PyKotaToolError, _("option --groups is currently not implemented.")
         elif args :    
             raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args)
Index: /pykota/trunk/bin/edpykota
===================================================================
--- /pykota/trunk/bin/edpykota (revision 924)
+++ /pykota/trunk/bin/edpykota (revision 927)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.41  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.40  2003/04/16 08:22:09  jalet
 # More strict error detection.
@@ -340,5 +343,5 @@
         if not names :    
             if options["add"] and not printeradded :
-                raise PyKotaToolError, _("You have to pass user names on the command line")
+                raise PyKotaToolError, _("You have to pass user or group names on the command line")
             else :    
                 names = [ "*" ] # all users
@@ -366,4 +369,9 @@
         if limitby and (limitby not in ('quota', 'balance')) :    
             raise PyKotaToolError, _("Invalid limitby value %s" % options["limitby"])
+            
+        if options["ingroups"] :    
+            groupnames = [gname.strip() for gname in options["ingroups"].split(',')]
+        else :    
+            groupnames = []
             
         for (printerid, printer) in printers :
@@ -393,5 +401,5 @@
                 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 not options["prototype"] and not options["limitby"] and not options["balance"] and not options["delete"] and not options["charge"]) and ((hardlimit is None) or (softlimit is None)) :
+            if (not options["ingroups"] and not options["reset"] and not options["noquota"] and not options["prototype"] and not options["limitby"] and not options["balance"] and not options["delete"] and not options["charge"]) and ((hardlimit is None) or (softlimit is None)) :
                 raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.")
             if options["add"] :    
@@ -458,4 +466,8 @@
                                 else :
                                     self.storage.setUserBalance(ident, balancevalue)
+                            for groupname in groupnames :        
+                                groupid = self.storage.getGroupId(groupname)
+                                if groupid is not None :
+                                    self.storage.addUserToGroup(ident, groupid)
                             self.warnUserPQuota(name, printer)    
                      
@@ -506,6 +518,4 @@
         elif options["groups"] and (options["balance"] or options["ingroups"]) :
             raise PyKotaToolError, _("incompatible options, see help.")
-        elif options["groups"] :    
-            raise PyKotaToolError, _("option --groups is currently not implemented.")
         else :
             sys.exit(editor.main(args, options))
Index: /pykota/trunk/bin/repykota
===================================================================
--- /pykota/trunk/bin/repykota (revision 915)
+++ /pykota/trunk/bin/repykota (revision 927)
@@ -23,4 +23,7 @@
 #
 # $Log$
+# Revision 1.26  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.25  2003/04/15 11:30:57  jalet
 # More work done on money print charging.
@@ -177,5 +180,5 @@
                 print _("Group            used     soft     hard   grace        total")
                 print "------------------------------------------------------------"
-                for name in self.storage.getPrinterGroups(printerid) :
+                for (ident, name) in self.storage.getPrinterGroups(printerid) :
                     quota = self.storage.getGroupPQuota(ident, printerid) 
                     total += self.printQuota(name, quota)
@@ -200,6 +203,6 @@
         """Prints the quota information."""
         if quota is not None :
-            lifepagecounter = quota["lifepagecounter"]
-            pagecounter = quota["pagecounter"]
+            lifepagecounter = quota["lifepagecounter"] or 0
+            pagecounter = quota["pagecounter"] or 0
             softlimit = quota["softlimit"]
             hardlimit = quota["hardlimit"]
@@ -244,6 +247,4 @@
         elif options["users"] and options["groups"] :    
             raise PyKotaToolError, _("incompatible options, see help.")
-        elif options["groups"] :    
-            raise PyKotaToolError, _("option --groups is currently not implemented.")
         elif args :    
             raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args)
Index: /pykota/trunk/NEWS
===================================================================
--- /pykota/trunk/NEWS (revision 926)
+++ /pykota/trunk/NEWS (revision 927)
@@ -22,4 +22,8 @@
 PyKota NEWS :
 
+    - 1.03beta :
+    
+        - Group quotas seem to work now !
+        
     - 1.03alpha :
     
Index: /pykota/trunk/po/en/pykota.po
===================================================================
--- /pykota/trunk/po/en/pykota.po (revision 925)
+++ /pykota/trunk/po/en/pykota.po (revision 927)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.18  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.17  2003/04/16 08:53:14  jalet
 # Printing can now be limited either by user's account balance or by
@@ -253,5 +256,5 @@
 msgstr ""
 
-msgid "You have to pass user names on the command line"
+msgid "You have to pass user or group names on the command line"
 msgstr ""
 
@@ -279,2 +282,24 @@
 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s"
 msgstr ""
+
+msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s"
+msgstr ""
+
+msgid "Unable to match group %s on printer %s, applying default policy (%s)"
+msgstr ""
+
+msgid "Print Quota exceeded for group %s on printer %s"
+msgstr ""
+
+msgid ""
+"You are not allowed to print anymore because\n"
+"your group Print Quota is exceeded on printer %s."
+msgstr ""
+
+msgid "Print Quota soft limit exceeded for group %s on printer %s"
+msgstr ""
+
+msgid ""
+"You will soon be forbidden to print anymore because\n"
+"your group Print Quota is almost reached on printer %s."
+msgstr ""
Index: /pykota/trunk/po/fr/pykota.po
===================================================================
--- /pykota/trunk/po/fr/pykota.po (revision 925)
+++ /pykota/trunk/po/fr/pykota.po (revision 927)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.16  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.15  2003/04/16 08:53:14  jalet
 # Printing can now be limited either by user's account balance or by
@@ -261,6 +264,6 @@
 msgstr "R� : %s"
 
-msgid "You have to pass user names on the command line"
-msgstr "Vous devez passer des noms d'utilisateur sur la ligne de commande"
+msgid "You have to pass user or group names on the command line"
+msgstr "Vous devez passer des noms d'utilisateurs ou de groupes sur la ligne de commande"
 
 msgid "unknown"
@@ -287,2 +290,28 @@
 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s"
 msgstr "Impossible de trouver le solde du compte de l'utilisateur %s, action par d�ut (%s) appliqu�sur l'imprimante %s"
+
+msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s"
+msgstr "Impossible de trouver le solde du compte du groupe %s, action par d�ut (%s) appliqu�sur l'imprimante %s"
+
+msgid "Unable to match group %s on printer %s, applying default policy (%s)"
+msgstr "Impossible de trouver le groupe %s sur l'imprimante %s, action par d�ut (%s) appliqu�
+
+msgid "Print Quota exceeded for group %s on printer %s"
+msgstr "D�ssement de Quota d'impression pour le groupe %s sur l'imprimante %s"
+
+msgid ""
+"You are not allowed to print anymore because\n"
+"your group Print Quota is exceeded on printer %s."
+msgstr ""
+"Vous n'�s plus autoris� imprimer car\n"
+"le Quota d'Impression de votre groupe est d�ss�ur l'imprimante %s."
+
+msgid "Print Quota soft limit exceeded for group %s on printer %s"
+msgstr "Limite souple de Quota d'Impression d�ss�pour le groupe %s sur l'imprimante %s"
+
+msgid ""
+"You will soon be forbidden to print anymore because\n"
+"your group Print Quota is almost reached on printer %s."
+msgstr ""
+"Vous n'aurez bient�lus le droit d'imprimer car\n"
+"le Quota d'Impression de votre groupe sur l'imprimante %s est presque atteint."
Index: /pykota/trunk/po/pykota.pot
===================================================================
--- /pykota/trunk/po/pykota.pot (revision 925)
+++ /pykota/trunk/po/pykota.pot (revision 927)
@@ -21,4 +21,7 @@
 #
 # $Log$
+# Revision 1.18  2003/04/16 12:35:49  jalet
+# Groups quota work now !
+#
 # Revision 1.17  2003/04/16 08:53:14  jalet
 # Printing can now be limited either by user's account balance or by
@@ -253,5 +256,5 @@
 msgstr ""
 
-msgid "You have to pass user names on the command line"
+msgid "You have to pass user or group names on the command line"
 msgstr ""
 
@@ -279,2 +282,24 @@
 msgid "Unable to find user %s's account balance, applying default policy (%s) for printer %s"
 msgstr ""
+
+msgid "Unable to find group %s's account balance, applying default policy (%s) for printer %s"
+msgstr ""
+
+msgid "Unable to match group %s on printer %s, applying default policy (%s)"
+msgstr ""
+
+msgid "Print Quota exceeded for group %s on printer %s"
+msgstr ""
+
+msgid ""
+"You are not allowed to print anymore because\n"
+"your group Print Quota is exceeded on printer %s."
+msgstr ""
+
+msgid "Print Quota soft limit exceeded for group %s on printer %s"
+msgstr ""
+
+msgid ""
+"You will soon be forbidden to print anymore because\n"
+"your group Print Quota is almost reached on printer %s."
+msgstr ""
