Changeset 3090

Show
Ignore:
Timestamp:
11/30/06 22:47:26 (18 years ago)
Author:
jerome
Message:

Now pkinvoice works internally like pkrefund. Huge code
factorization is now possible (but will wait next
development cycle).

Location:
pykota/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pkinvoice

    r3083 r3090  
    4747    hasPIL = 1 
    4848 
    49 from pykota.tool import Percent, PyKotaToolError, PyKotaCommandLineError, crashed, N_ 
    50 from pykota.dumper import DumPyKota 
     49from pykota.tool import Percent, PyKotaTool, PyKotaToolError, PyKotaCommandLineError, crashed, N_ 
    5150 
    5251__doc__ = N_("""pkinvoice v%(__version__)s (c) %(__years__)s %(__author__)s 
     
    5655command line usage : 
    5756 
    58   pkinvoice [options] user1 user2 ... userN 
     57  pkinvoice [options] [filterexpr] 
    5958 
    6059options : 
     
    8685                       exposed. The default is 0.0, meaning no VAT 
    8786                       information will be included. 
     87   
     88 
     89  Use the filter expressions to extract only parts of the  
     90  datas. Allowed filters are of the form : 
     91                 
     92         key=value 
     93                          
     94  Allowed keys for now are :   
    8895                        
    89   -s | --start date    Sets the starting date for the print jobs invoiced. 
    90    
    91   -e | --end date      Sets the ending date for the print jobs invoiced. 
    92                         
    93   user1 through userN can use wildcards if needed. If no user argument is 
    94   used, a wildcard of '*' is assumed, meaning include all users. 
    95    
    96   Dates formatting with --start and --end : 
     96         username       User's name 
     97         printername    Printer's name 
     98         hostname       Client's hostname 
     99         jobid          Job's Id 
     100         billingcode    Job's billing code 
     101         start          Job's date of printing 
     102         end            Job's date of printing 
     103          
     104  Dates formatting with 'start' and 'end' filter keys : 
    97105   
    98106    YYYY : year boundaries 
     
    111119  date expression. The utility to be able to specify dates in the future is 
    112120  a question which remains to be answered :-) 
    113                                          
    114 examples :                        
    115  
    116   $ pkinvoice --unit EURO --output invoices.pdf --start=now-30 
     121   
     122  Contrary to other PyKota management tools, wildcard characters are not  
     123  expanded, so you can't use them. 
     124   
     125examples : 
     126 
     127  $ pkinvoice --unit EURO --output /tmp/invoices.pdf start=now-30 
    117128   
    118129  Will generate a PDF document containing invoices for all users 
     
    121132""")  
    122133         
    123 class PKInvoice(DumPyKota) :         
    124     """A class for pkinvoice.""" 
     134class PKInvoice(PyKotaTool) :         
     135    """A class for invoice generator.""" 
     136    validfilterkeys = [ "username", 
     137                        "printername", 
     138                        "hostname", 
     139                        "jobid", 
     140                        "billingcode", 
     141                        "start", 
     142                        "end", 
     143                      ] 
     144                       
    125145    def getPageSize(self, pgsize) : 
    126146        """Returns the correct page size or None if not found.""" 
     
    149169        self.ypos -= (size + 4) 
    150170         
    151     def pagePDF(self, invoicenumber, entry, vat, start, end, unitname) : 
     171    def pagePDF(self, invoicenumber, name, values, unit, vat) : 
    152172        """Generates a new page in the PDF document.""" 
    153         extractonly = { "username" : entry.Name } 
    154         if start : 
    155             extractonly["start"] = start 
    156         if end :     
    157             extractonly["end"] = end 
    158         records = self.storage.extractHistory(extractonly) 
    159         amount = vatamount = 0.0 
    160         vatamount = 0.0 
    161         if records : 
     173        amount = values["nbcredits"] 
     174        if amount : # is there's something due ? 
     175            ht = ((amount * 10000.0) / (100.0 + vat)) / 100.0 
     176            vatamount = amount - ht 
    162177            self.canvas.doForm("background") 
    163178            self.ypos = self.yorigine - (cm + 20) 
    164             records = self.summarizeDatas(records, "history", extractonly, True) 
    165             fieldnames = records[0] 
    166             fields = {} 
    167             for i in range(len(fieldnames)) : 
    168                 fields[fieldnames[i]] = i 
    169             numberofbytes = records[1][fields["jobsizebytes"]] 
    170             numberofpages = records[1][fields["jobsize"]] 
    171             amount = records[1][fields["jobprice"]] 
    172             if amount > 0.0 : 
    173                 # There's something due ! 
    174                 ht = ((amount * 10000.0) / (100.0 + vat)) / 100.0 
    175                 vatamount = amount - ht 
    176                 self.printVar(_("Invoice"), "#%s" % invoicenumber, 22) 
    177                 self.printVar(_("Username"), entry.Name, 22) 
    178                 self.ypos -= 20 
    179                 if start :  
    180                     self.printVar(_("Since"), start, 14) 
    181                 if end : 
    182                     self.printVar(_("Until"), end, 14) 
    183                 self.printVar(_("Edited on"), time.strftime("%c", time.localtime()), 14) 
    184                      
    185                 self.ypos -= 20 
    186                 # self.printVar(_("Number of bytes"), str(numberofbytes), 14) 
    187                 self.printVar(_("Number of pages printed"), str(numberofpages), 14) 
    188                 self.ypos -= 20 
    189                 self.printVar(_("Amount due"), "%.3f %s" % (amount, unitname), 22) 
    190                 if vat : 
    191                     self.ypos += 8 
    192                     self.printVar("%s (%.2f%%)" % (_("Included VAT"), vat), "%.3f %s" % (vatamount, unitname), 14) 
    193                 self.canvas.showPage() 
    194                 return 1 
     179            self.printVar(_("Invoice"), "#%s" % invoicenumber, 22) 
     180            self.printVar(_("Username"), name, 22) 
     181            self.ypos -= 20 
     182            self.printVar(_("Edited on"), time.strftime("%c", time.localtime()), 14) 
     183                 
     184            self.ypos -= 20 
     185            self.printVar(_("Number of jobs printed"), str(values["nbjobs"]), 18) 
     186            self.printVar(_("Number of pages printed"), str(values["nbpages"]), 18) 
     187            self.ypos -= 20 
     188            self.printVar(_("Amount due"), "%.3f %s" % (amount, unit), 18) 
     189            if vat : 
     190                self.ypos += 8 
     191                self.printVar("%s (%.2f%%)" % (_("Included VAT"), vat), "%.3f %s" % (vatamount, unit), 14) 
     192            self.canvas.showPage() 
     193            return 1 
    195194        return 0     
    196195         
     
    202201                                        pageCompression=1) 
    203202         
    204         c.setAuthor(pwd.getpwuid(os.geteuid())[0]) 
     203        c.setAuthor(self.originalUserName) 
    205204        c.setTitle("PyKota invoices") 
    206205        c.setSubject("Invoices generated with PyKota") 
    207          
    208206         
    209207        self.canvas.beginForm("background") 
     
    216214            try :     
    217215                imglogo = PIL.Image.open(logo) 
    218             except :     
     216            except IOError :     
    219217                self.printInfo("Unable to open image %s" % logo, "warn") 
    220218            else : 
     
    249247            sys.stdout.flush() 
    250248         
    251     def main(self, names, options) : 
     249    def genInvoices(self, peruser, logo, outfname, firstnumber, unit, vat) : 
     250        """Generates the invoices file.""" 
     251        if len(peruser) : 
     252            percent = Percent(self) 
     253            percent.setSize(len(peruser)) 
     254            if outfname != "-" : 
     255                percent.display("%s...\n" % _("Generating invoices")) 
     256                 
     257            self.initPDF(logo) 
     258            number = firstnumber 
     259            for (name, values) in peruser.items() : 
     260                number += self.pagePDF(number, name, values, unit, vat) 
     261                if outfname != "-" : 
     262                    percent.oneMore() 
     263                     
     264            if number > firstnumber : 
     265                self.endPDF(outfname) 
     266                 
     267            if outfname != "-" : 
     268                percent.done() 
     269         
     270    def main(self, arguments, options) : 
    252271        """Generate invoices.""" 
    253272        if not hasRL : 
     
    278297            self.printInfo(_("Invalid 'pagesize' option %s, defaulting to A4.") % options["pagesize"], "warn") 
    279298             
    280         if not names : 
    281             names = [ "*" ] 
     299        extractonly = {} 
     300        for filterexp in arguments : 
     301            if filterexp.strip() : 
     302                try : 
     303                    (filterkey, filtervalue) = [part.strip() for part in filterexp.split("=")] 
     304                    filterkey = filterkey.lower() 
     305                    if filterkey not in self.validfilterkeys : 
     306                        raise ValueError                 
     307                except ValueError :     
     308                    raise PyKotaCommandLineError, _("Invalid filter value [%s], see help.") % filterexp 
     309                else :     
     310                    extractonly.update({ filterkey : filtervalue }) 
    282311             
    283312        percent = Percent(self) 
    284         outfname = options["output"]     
     313        outfname = options["output"].strip() 
    285314        if outfname != "-" : 
    286315            percent.display("%s..." % _("Extracting datas")) 
    287         entries = self.storage.getMatchingUsers(",".join(names)) 
    288         percent.setSize(len(entries)) 
    289         if entries : 
    290             percent.display("\n%s\n" % _("Generating invoices")) 
    291             self.initPDF(options["logo"].strip()) 
    292             for entry in entries : 
    293                 number += self.pagePDF(number, entry, vat, options["start"], options["end"], options["unit"]) 
     316             
     317        username = extractonly.get("username")     
     318        if username : 
     319            user = self.storage.getUser(username) 
     320        else : 
     321            user = None 
     322             
     323        printername = extractonly.get("printername")     
     324        if printername : 
     325            printer = self.storage.getPrinter(printername) 
     326        else :     
     327            printer = None 
     328             
     329        start = extractonly.get("start") 
     330        end = extractonly.get("end") 
     331        (start, end) = self.storage.cleanDates(start, end) 
     332         
     333        jobs = self.storage.retrieveHistory(user=user,     
     334                                            printer=printer,  
     335                                            hostname=extractonly.get("hostname"), 
     336                                            billingcode=extractonly.get("billingcode"), 
     337                                            jobid=extractonly.get("jobid"), 
     338                                            start=start, 
     339                                            end=end, 
     340                                            limit=0) 
     341             
     342        peruser = {}                                     
     343        nbjobs = 0                                     
     344        nbpages = 0                                             
     345        nbcredits = 0.0 
     346        percent.setSize(len(jobs)) 
     347        if outfname != "-" : 
     348            percent.display("\n") 
     349        for job in jobs :                                     
     350            if job.JobSize and (job.JobAction not in ("DENY", "CANCEL", "REFUND")) : 
     351                nbpages += job.JobSize 
     352                nbcredits += job.JobPrice 
     353                counters = peruser.setdefault(job.UserName, { "nbjobs" : 0, "nbpages" : 0, "nbcredits" : 0.0 }) 
     354                counters["nbpages"] += job.JobSize 
     355                counters["nbcredits"] += job.JobPrice 
     356                counters["nbjobs"] += 1 
     357                nbjobs += 1 
    294358                if outfname != "-" : 
    295359                    percent.oneMore() 
    296                      
    297             if number > firstnumber : 
    298                 self.endPDF(outfname) 
    299              
    300360        if outfname != "-" : 
    301361            percent.done() 
     362        self.genInvoices(peruser, options["logo"].strip(), outfname, firstnumber, options["unit"], vat) 
     363        if outfname != "-" :     
     364            print _("Invoiced %i users for %i jobs, %i pages and %.3f credits") % (len(peruser), nbjobs, nbpages, nbcredits) 
    302365                      
    303366if __name__ == "__main__" :  
     
    311374                     "number" : "1", 
    312375                   } 
    313         short_options = "vho:u:V:p:l:n:s:e:" 
    314         long_options = ["help", "version", "start=", "end=", \ 
    315                         "unit=", "output=", \ 
     376        short_options = "vho:u:V:p:l:n:" 
     377        long_options = ["help", "version", "unit=", "output=", \ 
    316378                        "pagesize=", "logo=", "vat=", "number="] 
    317379         
     
    327389        options["version"] = options["v"] or options["version"] 
    328390         
    329         options["start"] = options["s"] or options["start"] 
    330         options["end"] = options["e"] or options["end"] 
    331391        options["vat"] = options["V"] or options["vat"] or defaults["vat"] 
    332392        options["unit"] = options["u"] or options["unit"] or defaults["unit"] 
  • pykota/trunk/NEWS

    r3086 r3090  
    2424    - 1.25alpha18 (2006-11-30) : 
    2525     
     26        - Make pkinvoice internally work like pkrefund. 
     27         
    2628        - Fixed a severe bug in the LDAP backend wrt the overcharging factor. 
    2729