Changeset 3341

Show
Ignore:
Timestamp:
02/18/08 23:43:01 (17 years ago)
Author:
jerome
Message:

pkinvoice now works new style.

Location:
pykota/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • pykota/trunk/bin/pkinvoice

    r3303 r3341  
    2121# 
    2222# 
     23 
     24"""An invoice generator for PyKota""" 
    2325 
    2426import sys 
     
    4547 
    4648import pykota.appinit 
    47 from pykota.utils import * 
    48  
     49from pykota.utils import run 
     50from pykota.commandline import PyKotaOptionParser, \ 
     51                               checkandset_pagesize, \ 
     52                               checkandset_positiveint, \ 
     53                               checkandset_percent 
     54from pykota.pdfutils import getPageSize 
    4955from pykota.errors import PyKotaToolError, PyKotaCommandLineError 
    5056from pykota.tool import Percent, PyKotaTool 
    5157 
    52 __doc__ = N_("""pkinvoice v%(__version__)s (c) %(__years__)s %(__author__)s 
    53  
    54 An invoice generator for PyKota. 
    55  
    56 command line usage : 
    57  
    58   pkinvoice [options] [filterexpr] 
    59  
    60 options : 
    61  
    62   -v | --version       Prints pkinvoice's version number then exits. 
    63   -h | --help          Prints this message then exits. 
    64    
    65   -l | --logo img      Use the image as the invoice's logo. The logo will 
    66                        be drawn at the center top of the page. The default 
    67                        logo is /usr/share/pykota/logos/pykota.jpeg 
    68                         
    69   -p | --pagesize sz   Sets sz as the page size. Most well known 
    70                        page sizes are recognized, like 'A4' or 'Letter' 
    71                        to name a few. The default size is A4. 
    72                         
    73   -n | --number N      Sets the number of the first invoice. This number 
    74                        will automatically be incremented for each invoice. 
    75                         
    76   -o | --output f.pdf  Defines the name of the invoice file which will 
    77                        be generated as a PDF document. If not set or 
    78                        set to '-', the PDF document is sent to standard 
    79                        output.  
    80                         
    81   -u | --unit u        Defines the name of the unit to use on the invoice.                        
    82                        The default unit is 'Credits', optionally translated 
    83                        to your native language if it is supported by PyKota. 
    84    
    85   -V | --vat p         Sets the percent value of the applicable VAT to be 
    86                        exposed. The default is 0.0, meaning no VAT 
    87                        information will be included. 
    88    
    89  
    90   Use the filter expressions to extract only parts of the  
    91   datas. Allowed filters are of the form : 
    92                  
    93          key=value 
    94                           
    95   Allowed keys for now are :   
    96                         
    97          username       User's name 
    98          printername    Printer's name 
    99          hostname       Client's hostname 
    100          jobid          Job's Id 
    101          billingcode    Job's billing code 
    102          start          Job's date of printing 
    103          end            Job's date of printing 
    104           
    105   Dates formatting with 'start' and 'end' filter keys : 
    106    
    107     YYYY : year boundaries 
    108     YYYYMM : month boundaries 
    109     YYYYMMDD : day boundaries 
    110     YYYYMMDDhh : hour boundaries 
    111     YYYYMMDDhhmm : minute boundaries 
    112     YYYYMMDDhhmmss : second boundaries 
    113     yesterday[+-NbDays] : yesterday more or less N days (e.g. : yesterday-15) 
    114     today[+-NbDays] : today more or less N days (e.g. : today-15) 
    115     tomorrow[+-NbDays] : tomorrow more or less N days (e.g. : tomorrow-15) 
    116     now[+-NbDays] : now more or less N days (e.g. now-15) 
    117  
    118   'now' and 'today' are not exactly the same since today represents the first 
    119   or last second of the day depending on if it's used in a start= or end= 
    120   date expression. The utility to be able to specify dates in the future is 
    121   a question which remains to be answered :-) 
    122    
    123   Contrary to other PyKota management tools, wildcard characters are not  
    124   expanded, so you can't use them. 
    125    
    126 examples : 
    127  
    128   $ pkinvoice --unit EURO --output /tmp/invoices.pdf start=now-30 
    129    
    130   Will generate a PDF document containing invoices for all users 
    131   who have spent some credits last month. Invoices will be done in 
    132   EURO.  No VAT information will be included. 
    133 """)  
    134          
    13558class PKInvoice(PyKotaTool) :         
    13659    """A class for invoice generator.""" 
     
    14467                      ] 
    14568                       
    146     def getPageSize(self, pgsize) : 
    147         """Returns the correct page size or None if not found.""" 
    148         try : 
    149             return getattr(pagesizes, pgsize.upper()) 
    150         except AttributeError :     
    151             try : 
    152                 return getattr(pagesizes, pgsize.lower()) 
    153             except AttributeError : 
    154                 pass 
    155                  
    15669    def printVar(self, label, value, size) : 
    15770        """Outputs a variable onto the PDF canvas. 
     
    18194            self.printVar(_("Username"), name, 22) 
    18295            self.ypos -= 20 
    183             self.printVar(_("Edited on"), time.strftime("%c", time.localtime()), 14) 
     96            datetime = time.strftime("%c", time.localtime()).decode(self.charset, "replace") 
     97            self.printVar(_("Edited on"), datetime, 14) 
    18498                 
    18599            self.ypos -= 20 
     
    279193            raise PyKotaCommandLineError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command.")) 
    280194         
    281         try :     
    282             vat = float(options["vat"]) 
    283             if not (0.0 <= vat < 100.0) : 
    284                 raise ValueError 
    285         except :     
    286             raise PyKotaCommandLineError, _("Incorrect value '%s' for the --vat command line option") % options["vat"] 
    287              
    288         try :     
    289             firstnumber = number = int(options["number"]) 
    290             if number <= 0 : 
    291                 raise ValueError 
    292         except :     
    293             raise PyKotaCommandLineError, _("Incorrect value '%s' for the --number command line option") % options["number"] 
    294              
    295         self.pagesize = self.getPageSize(options["pagesize"]) 
    296         if self.pagesize is None : 
    297             self.pagesize = self.getPageSize("a4") 
    298             self.printInfo(_("Invalid 'pagesize' option %s, defaulting to A4.") % options["pagesize"], "warn") 
     195        self.pagesize = getPageSize(options.pagesize) 
    299196             
    300197        extractonly = {} 
     
    312209             
    313210        percent = Percent(self) 
    314         outfname = options["output"].strip() 
     211        outfname = options.output.strip().encode(sys.getfilesystemencoding()) 
    315212        if outfname != "-" : 
    316213            percent.display("%s..." % _("Extracting datas")) 
     
    361258        if outfname != "-" : 
    362259            percent.done() 
    363         self.genInvoices(peruser, options["logo"].strip(), outfname, firstnumber, options["unit"], vat) 
     260        self.genInvoices(peruser,  
     261                         options.logo.strip().encode(sys.getfilesystemencoding()),  
     262                         outfname,  
     263                         options.number,  
     264                         options.unit or _("Credits"),  
     265                         options.vat) 
    364266        if outfname != "-" :     
    365             print _("Invoiced %i users for %i jobs, %i pages and %.3f credits") % (len(peruser), nbjobs, nbpages, nbcredits) 
     267            print _("Invoiced %i users for %i jobs, %i pages and %.3f credits") \ 
     268                % (len(peruser), nbjobs, nbpages, nbcredits) 
    366269                      
    367270if __name__ == "__main__" :  
    368     retcode = 0 
    369     try : 
    370         defaults = { "vat" : "0.0", 
    371                      "unit" : N_("Credits"), 
    372                      "output" : "-", 
    373                      "pagesize" : "a4", \ 
    374                      "logo" : "/usr/share/pykota/logos/pykota.jpeg", 
    375                      "number" : "1", 
    376                    } 
    377         short_options = "vho:u:V:p:l:n:" 
    378         long_options = ["help", "version", "unit=", "output=", \ 
    379                         "pagesize=", "logo=", "vat=", "number="] 
    380          
    381         # Initializes the command line tool 
    382         invoiceGenerator = PKInvoice(doc=__doc__) 
    383         invoiceGenerator.deferredInit() 
    384          
    385         # parse and checks the command line 
    386         (options, args) = invoiceGenerator.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=True) 
    387          
    388         # sets long options 
    389         options["help"] = options["h"] or options["help"] 
    390         options["version"] = options["v"] or options["version"] 
    391          
    392         options["vat"] = options["V"] or options["vat"] or defaults["vat"] 
    393         options["unit"] = options["u"] or options["unit"] or defaults["unit"] 
    394         options["output"] = options["o"] or options["output"] or defaults["output"] 
    395         options["pagesize"] = options["p"] or options["pagesize"] or defaults["pagesize"] 
    396         options["number"] = options["n"] or options["number"] or defaults["number"] 
    397         options["logo"] = options["l"] or options["logo"] 
    398         if options["logo"] is None : # Allows --logo="" to disable the logo entirely 
    399             options["logo"] = defaults["logo"]   
    400          
    401         if options["help"] : 
    402             invoiceGenerator.display_usage_and_quit() 
    403         elif options["version"] : 
    404             invoiceGenerator.display_version_and_quit() 
    405         else : 
    406             retcode = invoiceGenerator.main(args, options) 
    407     except KeyboardInterrupt :         
    408         logerr("\nInterrupted with Ctrl+C !\n") 
    409         retcode = -3 
    410     except PyKotaCommandLineError, msg :      
    411         logerr("%s : %s\n" % (sys.argv[0], msg)) 
    412         retcode = -2 
    413     except SystemExit :         
    414         pass 
    415     except : 
    416         try : 
    417             invoiceGenerator.crashed("pkinvoice failed") 
    418         except :     
    419             crashed("pkinvoice failed") 
    420         retcode = -1 
    421  
    422     try : 
    423         invoiceGenerator.storage.close() 
    424     except (TypeError, NameError, AttributeError) :     
    425         pass 
    426          
    427     sys.exit(retcode)     
     271    parser = PyKotaOptionParser(description=_("Invoice generator for PyKota."), 
     272                                usage="pkinvoice [options] [filterexpr]") 
     273    parser.add_option("-l", "--logo", 
     274                            dest="logo", 
     275                            default=u"/usr/share/pykota/logos/pykota.jpeg", 
     276                            help=_("The image to use as a logo. The logo will be drawn at the center top of the page. The default logo is %default")) 
     277    parser.add_option("-p", "--pagesize", 
     278                            type="string", 
     279                            action="callback", 
     280                            callback=checkandset_pagesize, 
     281                            dest="pagesize", 
     282                            default=u"A4", 
     283                            help=_("Set the size of the page. Most well known page sizes are recognized, like 'A4' or 'Letter' to name a few. The default page size is %default")) 
     284    parser.add_option("-n", "--number",                         
     285                            dest="number", 
     286                            type="int", 
     287                            action="callback", 
     288                            callback=checkandset_positiveint, 
     289                            default=1, 
     290                            help=_("Sets the number of the first invoice. This number will automatically be incremented for each invoice. The default value is %default")) 
     291    parser.add_option("-o", "--output", 
     292                            dest="output", 
     293                            type="string", 
     294                            default=u"-", 
     295                            help=_("The name of the file to which the PDF invoices will be written. If not set or set to '%default', the PDF document will be sent to the standard output.")) 
     296                             
     297    # TODO : due to Python's optparse.py bug #1498146 fixed in rev 46861 
     298    # TODO : we can't use 'default=_("Credits")' for this option 
     299    parser.add_option("-u", "--unit",                    
     300                            dest="unit", 
     301                            type="string", 
     302                            help=_("The name of the unit to use on the invoices. The default value is 'Credits' or its locale translation.")) 
     303                             
     304    parser.add_option("-V", "--vat",  
     305                            dest="vat", 
     306                            type="float", 
     307                            action="callback", 
     308                            callback=checkandset_percent, 
     309                            default=0.0, 
     310                            help=_("The value in percent of the applicable VAT to be exposed. The default is %default, meaning no VAT.")) 
     311                             
     312    parser.add_filterexpression("username", _("User's name"))                         
     313    parser.add_filterexpression("printername", _("Printer's name"))                         
     314    parser.add_filterexpression("hostname", _("Host's name"))                         
     315    parser.add_filterexpression("jobid", _("Job's id"))                         
     316    parser.add_filterexpression("billingcode", _("Job's billing code")) 
     317    parser.add_filterexpression("start", _("Job's date of printing"))                         
     318    parser.add_filterexpression("end", _("Job's date of printing"))                         
     319     
     320    parser.add_example('--unit EURO --output /tmp/invoices.pdf start=now-30',  
     321                       _("This would generate a PDF document containing invoices for all users who have spent some credits last month. Amounts would be in EURO and not VAT information would be included.")) 
     322                        
     323    run(parser, PKInvoice)                    
  • pykota/trunk/pykota/commandline.py

    r3340 r3341  
    6262        loginvalidparam(opt, value, option.default, \ 
    6363                        _("Value must be positive")) 
     64        setattr(optionparser.values, option.dest, option.default) 
     65    else :     
     66        setattr(optionparser.values, option.dest, value) 
     67 
     68def checkandset_percent(option, opt, value, optionparser) :     
     69    """Checks if an option argument is comprised between 0.0 included and 100.0 not included, and validates the option if it is the case.""" 
     70    if not (0.0 <= value < 100.0) : 
     71        loginvalidparam(opt, value, option.default, \ 
     72                        _("Value must be comprised between 0.0 included and 100.0 not included")) 
    6473        setattr(optionparser.values, option.dest, option.default) 
    6574    else :