Commits

Anonymous committed 5b05f16

user: lablinux
branch 'default'
added .hgignore
added __init__.py
added contacts/__init__.py
added contacts/models.py
added contacts/tests.py
added contacts/urls.py
added contacts/views.py
added django_wsgi.py
added fees/__init__.py
added fees/models.py
added fees/tests.py
added fees/urls.py
added fees/views.py
added home/__init__.py
added home/models.py
added home/tests.py
added home/urls.py
added home/views.py
added invoices/__init__.py
added invoices/models.py
added invoices/printpdf.py
added invoices/templatetags/__init__.py
added invoices/templatetags/currency.py
added invoices/templatetags/formatnumber.py
added invoices/tests.py
added invoices/urls.py
added invoices/views.py
added items/__init__.py
added items/models.py
added items/tests.py
added items/urls.py
added items/views.py
added lib/__init__.py
added lib/context_processors.py
added lib/userprofile.py
added locale/en/LC_MESSAGES/django.mo
added locale/en/LC_MESSAGES/django.po
added locale/it/LC_MESSAGES/django.mo
added locale/it/LC_MESSAGES/django.po
added manage.py
added media/css/application.css
added media/css/pdf.css
added media/css/style.css
added media/css/style_old.css
added media/icons/add.png
added media/icons/delete.png
added media/icons/personaldata.png
added media/icons/rubrica.gif
added media/icons/rubrica.png
added media/images/black.png
added media/images/headerbg.gif
added media/images/img01.jpg
added media/images/white.png
added media/js/jquery-1.4.1.min.js
added media/js/jquery-ui-1.8.custom.min.js
added payterms/__init__.py
added payterms/models.py
added payterms/tests.py
added payterms/urls.py
added payterms/views.py
added profiles/__init__.py
added profiles/models.py
added profiles/tests.py
added profiles/urls.py
added profiles/views.py
added settings.py
added templates/base.html
added templates/contacts/ajax.html
added templates/contacts/index.html
added templates/crud/new.html
added templates/crud/update.html
added templates/debug.html
added templates/fees/ajax_list.html
added templates/fees/index.html
added templates/home/index.html
added templates/invoices/_item.html
added templates/invoices/index.html
added templates/invoices/new2.html
added templates/invoices/pdf.html
added templates/invoices/pdf2.html
added templates/invoices/status.html
added templates/invoices/update.html
added templates/items/ajax.html
added templates/items/ajax_list.html
added templates/items/index.html
added templates/items/indexpdf.html
added templates/items/new.html
added templates/items/update.html
added templates/payterms/ajax.html
added templates/payterms/index.html
added templates/profiles/index.html
added templates/registration/login.html
added templates/registration/logout.html
added test/invoice_test.py
added urls.py
added utility.py
added views.py

Comments (0)

Files changed (98)

+syntax: glob
+*.pyc
+*.pyo 
+*.po~
+*.html~
+*.py~
Empty file added.

contacts/__init__.py

Empty file added.

contacts/models.py

+from django.db import models
+from django.contrib.auth.models import User
+from django.contrib import admin
+from django.forms import ModelForm
+from django.utils.translation import ugettext as _
+
+TYPE_CONTACT = (
+    (u'C', _('Customer')),
+    (u'S', _('Supplier')),
+    (u'P', _('Peronal')),
+    (u'G', _('Generic')),
+)
+
+class Contacts(models.Model):
+    name            = models.CharField(max_length=80, verbose_name=_("Name"))
+    surname         = models.CharField(max_length=50, blank=True,  verbose_name=_("Surname"))
+    address         = models.CharField(max_length=80, verbose_name=_("Address"))
+    zipcode         = models.CharField(max_length=10, verbose_name=_("Zip Code"))
+    town            = models.CharField(max_length=50, verbose_name=_("Town"))
+    province        = models.CharField(max_length=2, verbose_name=_("Province"))
+    phone           = models.CharField(max_length=30, blank=True, verbose_name=_("Phone"))
+    mobilephone     = models.CharField(max_length=30, blank=True, verbose_name=_("Mobile phone"))
+    email           = models.CharField(max_length=30, blank=True, verbose_name=_("Email"))
+    tp_contacts     = models.CharField(max_length=1, choices=TYPE_CONTACT, verbose_name=_("Type of contact"))
+    vatnumber       = models.CharField(max_length=11, blank=True, verbose_name=_("VAT number"))
+    personalId      = models.CharField(max_length=50, blank=True, verbose_name=_("Code for personal identification"))
+    user            = models.ForeignKey(User)
+    
+    def __unicode__(self):
+        return u"%s, %s" %(self.name, self.surname)
+        
+    class Meta:
+        verbose_name_plural = "Contacts"
+        verbose_name  = "Contact" 
+
+
+class ContactsAdmin(admin.ModelAdmin):
+    list_display = ('name', 'surname', 'address', 'zipcode', 'town','province')
+    list_filter = ['name', 'surname']
+    search_fields = ['name', 'surname']
+
+admin.site.register(Contacts, ContactsAdmin)
+
+
+class ContactsForm(ModelForm):
+    class Meta:
+        model = Contacts
+        fields = ['name', \
+                  'surname', \
+                  'address', \
+                  'zipcode', \
+                  'town', \
+                  'province', \
+                  'phone', \
+                  'mobilephone', \
+                  'email', \
+                  'tp_contacts',
+                  'vatnumber', \
+                  'personalId', ]
+        
+
+

contacts/tests.py

+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+
+urlpatterns = patterns('contacts.views' ,
+    url(r'^/$'                     , 'index'  , name='contacts-index'),
+    url(r'^/update/(?P<id>\d+)/$'   , 'update' , name='contacts-update'),
+    url(r'^/new/$'                 , 'new'    , name='contacts-new'),
+    url(r'^/delete/(?P<id>\d+)/$'   , 'delete' , name='contacts-delete'),
+    url(r'^/ajax/(?P<id>\d+)/$'    , 'ajax' , name='contacts-ajax'),
+)

contacts/views.py

+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.contrib.auth.decorators import login_required
+from contacts.models import Contacts, ContactsForm
+from django.utils.translation import ugettext as _
+#from django.contrib.auth.models import User
+import utility
+
+
+from django import forms
+
+#class MyForm(forms.Form):
+#    def __init__(self, uid=0, *args, **kwargs):
+#        super(MyForm, self).__init__(*args, **kwargs)
+#        self.fields['contacts'] = forms.ChoiceField(choices=get_choices(uid))
+
+#def get_choices(userid=0):
+#    contacts = Contacts.objects.filter(user=userid)
+#    return [(contact.id,contact.name) for contact in contacts]
+
+
+@login_required
+def ajax(request, id=None):
+    contact = Contacts.objects.get(id=id)
+    return render_to_response('contacts/ajax.html' ,
+                             {'contact'    : contact,} ,
+                               context_instance=RequestContext(request))
+
+@login_required
+def index(request):
+    contacts = Contacts.objects.filter(user=request.user.id)
+    return render_to_response('contacts/index.html' ,
+                             {'contacts'    : contacts,} ,
+                               context_instance=RequestContext(request))
+
+@login_required
+def update(request, id=None):
+    return utility.update(Contacts, ContactsForm, request, id, 'contacts-index', 'crud/update.html', title=_('Update contact'))
+
+@login_required
+def new(request):
+    return utility.new(ContactsForm, request, 'contacts-index', 'crud/new.html', title=_('New contact'))
+
+@login_required
+def delete(request, id=None):
+    return utility.delete(Contacts, request, id, 'contacts-index')
+
+
+import os
+os.environ['DJANGO_SETTINGS_MODULE'] = 'oweb.settings'
+
+import django.core.handlers.wsgi
+
+application = django.core.handlers.wsgi.WSGIHandler()

fees/__init__.py

Empty file added.
+from django.db import models
+from django.contrib.auth.models import User
+from django.contrib import admin
+from django.forms import ModelForm
+from django.utils.translation import ugettext as _
+
+class Fees(models.Model):
+    """
+    in italian "Tasse e tributi"
+    Every item can have more fees. Evry fee have a applystep to calculate the fee
+    The step '0' is the gross
+    """
+    code = models.CharField(blank=True, unique=True, max_length=15, verbose_name=_("Code"))
+    description = models.CharField(max_length=80, verbose_name=_("Description"))
+    percentage = models.FloatField(verbose_name=_("Percentage"))
+    #applystep = models.SmallIntegerField(verbose_name=_("Apply to step"))
+    #step = models.SmallIntegerField(verbose_name=_("Step"))
+    user = models.ForeignKey(User)
+    
+    def __unicode__(self):
+        return u"%s, %s" %(self.description, self.percentage)
+        
+    class Meta:
+        verbose_name_plural = _("Fees")
+        verbose_name  = _("Fee")
+
+    def save(self):
+        super(Fees, self).save()
+        if self.code == None or self.code == '':
+            self.code = "code_%d" % self.id
+            super(Fees, self).save()
+
+class FeesAdmin(admin.ModelAdmin):
+    list_display = ('description', 'percentage',)
+    list_filter = ['description',]
+    search_fields = ['description',]
+
+admin.site.register(Fees, FeesAdmin)
+
+
+class FeesForm(ModelForm):
+    class Meta:
+        model = Fees
+        fields = ['code', \
+                  'description', \
+                  'percentage',  ]
+        
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+
+urlpatterns = patterns('fees.views' ,
+    url(r'^/$'                     , 'index'  , name='fees-index'),
+    url(r'^/update/(?P<id>\d+)/$'   , 'update' , name='fees-update'),
+    url(r'^/new/$'                 , 'new'    , name='fees-new'),
+    url(r'^/delete/(?P<id>\d+)/$'   , 'delete' , name='fees-delete'),
+    url(r'^/ajax_list/(?P<idx>\d+)/(?P<id>\d+)/$' , 'ajax_list'   , name='fees-ajax-list'),    
+    url(r'^/ajax_list/(?P<idx>\d+)/$' , 'ajax_list'   , name='fees-ajax-list'),
+
+)
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+from django.contrib.auth.decorators import login_required
+from fees.models import Fees, FeesForm
+from django import forms
+import utility
+
+def get_choices(userid=None):
+    fees = Fees.objects.filter(user=userid)
+    return [(fee.id,fee.description[0:30]) for fee in fees]
+
+class formFee(forms.Form):
+    def __init__(self, uid=None, nameField=None, *args, **kwargs):
+        super(formFee, self).__init__(*args, **kwargs)
+        self.fields['Fee'] = forms.ChoiceField(choices=get_choices(uid))
+        self.fields['Fee_descr'] = forms.CharField(label="additional info")
+
+@login_required
+def ajax_list(request, idx=None, id=None):
+    form = formFee(uid=request.user.id)
+    return render_to_response('fees/ajax_list.html' , 
+                             {'form' : form,
+                              'idx' : idx, 
+                              'id' : int(id)} ,
+                               context_instance=RequestContext(request))
+        
+@login_required
+def index(request):
+    fees = Fees.objects.filter(user=request.user.id)
+    return render_to_response('fees/index.html' , 
+                             {'fees'    : fees,} ,
+                               context_instance=RequestContext(request))
+
+@login_required
+def update(request, id=None):
+    return utility.update(Fees, FeesForm, request, id, 'fees-index', 'crud/update.html')
+
+@login_required
+def new(request):
+    return utility.new(FeesForm, request, 'fees-index', 'crud/new.html')
+
+@login_required
+def delete(request, id=None):
+    return utility.delete(Fees, request, id, 'fees-index')
+
+

home/__init__.py

Empty file added.
+from django.db import models
+
+# Create your models here.
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('home.views' ,
+    url(r'^/$', 'index',  name='home-index'),
+)
+from django.shortcuts import render_to_response
+from django.template import RequestContext
+
+def index(request):
+    if request.method == 'POST':
+        reqout = []
+        reqout.append(request.REQUEST['firstname'])
+        reqout.append(request.REQUEST['lastname'])
+        #for r in request.REQUEST:
+        #    reqout.append(r)
+        return render_to_response('home/index.html' ,
+                                 {'reqout' : reqout,} ,
+                                   context_instance=RequestContext(request))
+    else:
+         return render_to_response('home/index.html' ,
+                                 {} ,
+                                   context_instance=RequestContext(request))

invoices/__init__.py

Empty file added.

invoices/models.py

+# -*- coding: iso-8859-1 -*-
+from django.db  import models
+from django.contrib.auth.models import User
+from items.models import Items
+from contacts.models import Contacts
+from payterms.models import Payterms
+from django.contrib import admin
+from django.forms  import ModelForm
+from django.db.models import Max
+from datetime import datetime
+from django.utils.translation import ugettext as _
+from datetime import datetime
+
+from settings import MEDIA_URL_USER_DOCS
+
+INVOICE_STATUS = (
+    (u'D', _('Draft') ),
+    (u'I', _('Issue') ),
+    (u'P', _('Paid') ),
+)
+
+def content_file_name(instance, filename):
+    return '/'.join([MEDIA_URL_USER_DOCS, '1' , filename])
+
+class InvoiceHeaders(models.Model):
+    issuer = models.ForeignKey(Contacts, related_name='invoices_issuer', limit_choices_to={"tp_contacts":"P", })
+    customer = models.ForeignKey(Contacts, related_name='invoices_custumer', limit_choices_to={"tp_contacts":"C", })
+    payterm = models.ForeignKey(Payterms, related_name='invoices_payterm')
+    user = models.ForeignKey(User)
+    pdf = models.FileField(upload_to=content_file_name)
+    findrandomnumber = models.CharField(unique=True,max_length=56)
+
+    number = models.PositiveIntegerField(null=True, blank=True, verbose_name = _("Number issue"))
+    yearissue = models.PositiveIntegerField(null=True, blank=True, verbose_name = _("Year issue"))
+    dateissue = models.DateField(null=True, blank=True, verbose_name = _("Date issue"))
+    status = models.CharField(max_length=1, choices=INVOICE_STATUS, verbose_name=_("status"))
+
+    issuer_name = models.CharField(max_length = 80, verbose_name = _("My Name"))
+    issuer_surname = models.CharField(max_length = 80, verbose_name = _("My Surname"))
+    issuer_address = models.CharField(max_length = 80, verbose_name = _("My Address"))
+    issuer_zipcode = models.CharField(max_length = 10, verbose_name = _("My Zip Code"))
+    issuer_town = models.CharField(max_length = 50, verbose_name = _("My Town"))
+    issuer_province = models.CharField(max_length = 2, verbose_name = _("My Province"))
+    issuer_vatnumber = models.CharField(max_length = 11, verbose_name = _("My VAT number"))
+
+    customer_name = models.CharField(max_length = 80, verbose_name = _("Customer Name"))
+    customer_surname = models.CharField(max_length = 80, verbose_name = _("Customer Surname"))
+    customer_address = models.CharField(max_length = 80, verbose_name = _("Customer Address"))
+    customer_zipcode = models.CharField(max_length = 10, verbose_name = _("Customer Zip Code"))
+    customer_town = models.CharField(max_length = 50, verbose_name = _("Customer Town"))
+    customer_province = models.CharField(max_length = 2, verbose_name = _("Customer Province"))
+    customer_vatnumber = models.CharField(null=True,  blank=True,  max_length = 11, verbose_name = _("Customer VAT number"))
+
+    pay_term01 = models.CharField(null=True, blank=True, max_length = 80, verbose_name = _("Payterm 1"))
+    pay_term02 = models.CharField(null=True, blank=True, max_length = 80, verbose_name = _("Payterm 2"))
+    pay_term03 = models.CharField(null=True, blank=True, max_length = 80, verbose_name = _("Payterm 3"))
+
+
+    def __unicode__(self):
+        return u"%s - %s, %s" %(self.number, self.dateissue, self.customer_name)
+
+    class Meta:
+        verbose_name_plural = _('Invoice Headers')
+        verbose_name  = _('Invoice Header')
+        unique_together = (('number', 'yearissue', 'user'),)
+
+
+
+    def nextnumber(self, uid = None, year = None):
+        return self.maxnumber(uid = uid, year = year) + 1
+
+    def maxnumber(self, uid = None, year = None):
+        if uid == None:
+            return -1
+        if year == None:
+               year = datetime.now().year
+        maxnum = InvoiceHeaders.objects.filter(user = uid).filter(dateissue__year = year).aggregate(Max('number'))
+        num = maxnum['number__max']
+        if num:
+            return num
+        else:
+            return 0
+
+    def save(self, number=None, dateissue=None):
+        #force = False
+        if self.status == 'I' and self.dateissue == None:
+            if dateissue == None:
+                self.dateissue = datetime.today()
+                self.yearissue = datetime.today().year()
+            else:
+                self.dateissue = dateissue
+                self.yearissue = dateissue[0:4]
+            if number == None:
+                self.number = self.nextnumber(uid = self.user, year = self.dateissue.year )
+            else:
+                self.number = number
+        #if InvoiceHeaders.objects.filter(dateissue__year=form['date'].data[6:10]).filter(number=form['number'].data):
+        #    return False
+        #    self.error = '%s : %s / %s' %( _('ErrdupKey'), form['date'].data[6:10], form['number'].data)
+
+        self.issuer_name = self.issuer.name
+        self.issuer_surname = self.issuer.surname
+        self.issuer_address = self.issuer.address
+        self.issuer_zipcode = self.issuer.zipcode
+        self.issuer_town = self.issuer.town
+        self.issuer_province = self.issuer.province
+        self.issuer_vatnumber = self.issuer.vatnumber
+
+        self.customer_name = self.customer.name
+        self.customer_surname = self.customer.surname
+        self.customer_address = self.customer.address
+        self.customer_zipcode = self.customer.zipcode
+        self.customer_town = self.customer.town
+        self.customer_province = self.customer.province
+        self.customer_vatnumber = self.customer.vatnumber
+
+        self.pay_term01 = self.payterm.description1
+        self.pay_term02 = self.payterm.description2
+        self.pay_term03 = self.payterm.description3
+
+        super(InvoiceHeaders, self).save()
+
+        #if force:
+        #for ib in self.invoicebodies_set.all():
+        #    ib.save() #force=force)
+
+class InvoiceHeadersModel(ModelForm):
+    class Meta:
+        model = InvoiceHeaders
+
+class InvoiceHeadersAdmin(admin.ModelAdmin):
+    list_display = ('number', 'dateissue', 'customer_name', 'customer_surname')
+    list_filter = ['dateissue', 'customer_name', 'customer_surname']
+    search_fields = ['dateissue', 'customer_name', 'customer_surname']
+
+admin.site.register(InvoiceHeaders, InvoiceHeadersAdmin)
+
+
+class InvoiceBodies(models.Model):
+    item = models.ForeignKey(Items)
+    header = models.ForeignKey(InvoiceHeaders)
+
+    unitprice = models.FloatField(null=True, verbose_name=_('Unit price'))
+    unitmeasurement = models.CharField(null=True, max_length=80, verbose_name=_("Unit measure"))
+    description =  models.CharField(null=True, max_length=80, verbose_name=_("Description"))
+    extraDescription =  models.CharField(null=True, max_length = 80, verbose_name = _("Extra Description"))
+    quantity  = models.FloatField(null=True, verbose_name = 'Quantity')
+
+
+    def __unicode__(self):
+        return '%s:  %s ' %( _("Extra Description"), self.extraDescription,)
+
+    class Meta:
+        verbose_name_plural = _("Invoice Bodies ")
+        verbose_name  = _("Invoice Body ")
+
+    def save(self): #, force=None):
+        self.unitprice = self.item.unitprice
+        self.unitmeasurement = self.item.unitmeasurement
+        self.description = self.item.description
+
+        super(InvoiceBodies, self).save()
+
+        # cancello i fees legati al body per ricaricarli
+        self.invoicebodiesfees_set.all().delete()
+        for fee in self.item.fees.values():
+            ibs = InvoiceBodiesFees()
+            ibs.body = self
+            ibs.description = fee['description']
+            ibs.percentage = fee['percentage']
+            ibs.save()
+
+class InvoiceBodiesAdmin(admin.ModelAdmin):
+    list_display = ('extraDescription', )
+    list_filter = ['extraDescription', ]
+    search_fields = ['extraDescription', ]
+
+admin.site.register(InvoiceBodies, InvoiceBodiesAdmin)
+
+
+
+class InvoiceBodiesFees(models.Model):
+    body = models.ForeignKey(InvoiceBodies)
+
+    description = models.CharField(max_length=80, verbose_name=_("Description"))
+    percentage = models.FloatField(verbose_name=_("Percentage"))
+
+    def __unicode__(self):
+        return u"%s" %self.description

invoices/printpdf.py

+from reportlab.pdfgen import canvas
+from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
+from reportlab.platypus import *
+from reportlab.lib import colors
+from reportlab.lib.units import cm
+from cStringIO import StringIO
+import utility
+
+from django.utils.translation import ugettext as _
+
+class printPDF():
+    def __init__(self, iheader=None, ibodies=None):
+        self.iheader=iheader
+        self.ibodies = ibodies
+
+    def generate(self,  path_to_save=None):
+        buffer = StringIO()
+        styles = getSampleStyleSheet()
+        styles.add(ParagraphStyle(name='Pop', fontName='Times-Roman', fontSize=12, leading=1), alias='pop')
+        styles.add(ParagraphStyle(name='PopBold', fontName='Times-Bold', fontSize=13, leading=1), alias='popbold')
+        styles.add(ParagraphStyle(name='PopLitle', fontName='Times-Roman', fontSize=8, leading=1), alias='poplitle')
+        
+        c = canvas.Canvas(buffer)
+                
+        headingstyle = styles['Pop']
+        # my info
+        p = Paragraph("%s %s" %(self.iheader.my_name, self.iheader.my_surname), headingstyle)
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 3 * cm, 26 * cm)
+
+        p = Paragraph(self.iheader.my_address, headingstyle)
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 3 * cm, 25.5 * cm)
+        
+        p = Paragraph("%s %s (%s)" %(self.iheader.my_zipcode, self.iheader.my_town, self.iheader.my_province), headingstyle) 
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 3 * cm, 25 * cm)
+        
+        p = Paragraph("%s %s" %(_('vat'),  self.iheader.my_vatnumber), headingstyle)
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 3 * cm, 24.5 * cm)
+
+        # custumer info
+        p = Paragraph("%s %s" %(self.iheader.costumer_name, self.iheader.costumer_surname), headingstyle) 
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 13 * cm, 25 * cm)
+
+        p = Paragraph(self.iheader.costumer_address, headingstyle)
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 13 * cm, 24.5 * cm)
+        
+        p = Paragraph("%s %s (%s)" %(self.iheader.costumer_zipcode, self.iheader.costumer_town, self.iheader.costumer_province), headingstyle)
+        p.wrapOn(c, 6 * cm, 0 * cm)
+        p.drawOn(c, 13 * cm, 24 * cm)
+    
+        if len(self.iheader.costumer_vatnumber) > 0:
+            p = Paragraph("p. iva %s" %(self.iheader.costumer_vatnumber), headingstyle)
+            p.wrapOn(c, 6 * cm, 0 * cm)
+            p.drawOn(c, 13 * cm, 23.5 * cm)
+
+        if self.iheader.status == 'D':
+            p = Paragraph("DRAFT" , headingstyle)
+            p.wrapOn(c, 7.2 * cm, 8 * cm)
+            p.drawOn(c, 8 * cm, 22 * cm)
+        else:
+            p = Paragraph("%s %s %d %s %s" %(_('Invoice'), _('#') ,self.iheader.number, _('of'), utility.date_ita(self.iheader.dateissue) ), styles['PopBold'])
+            p.wrapOn(c, 7.2 * cm, 8 * cm)
+            p.drawOn(c, 8 * cm, 22 * cm)
+
+        row = 18
+        elements = []
+        styles = getSampleStyleSheet()
+        data = []
+        for ibody in self.ibodies:
+            dataRow = [ibody.description]
+            dataRow.append('%19.2f' %ibody.total)
+            dataRow.append(' %9.2f ' %ibody.unitprice)
+            dataRow.append('* %9.2f' %ibody.amount)
+            #p = Paragraph(ibody.description, styles['Pop'])
+            #p.wrapOn(c, 15 * cm, 0 * cm)
+            #p.drawOn(c, 2 * cm, row * cm)
+
+            #p = Paragraph('%19.2f' %ibody.total, styles['Pop'])
+            #p.wrapOn(c, 0 * cm, 0 * cm)
+            #p.drawOn(c, 12 * cm, row  * cm)
+            
+            #outData = ''
+            #outData += ' %9.2f ' %ibody.unitprice 
+            #outData += ' * %9.2f' %ibody.amount 
+            #outData += '(%s)' %ibody.unitmeasurement 
+            #p = Paragraph(outData, styles['PopLitle'])
+            #p.wrapOn(c, 90 * cm, 90 * cm)
+            #p.drawOn(c, 15 * cm, row * cm)
+            
+            
+            if ibody.vat_total > 0:
+              dataRow.append(_('Vat'))
+              dataRow.append(ibody.vat)
+              dataRow.append(ibody.vat_total)
+              #outData = '%s %s%s %8.2f ' %(_('Vat'),  ibody.vat, '%', ibody.vat_total)
+              #row-=0.3
+              #p = Paragraph(outData, styles['PopLitle'])
+              #p.wrapOn(c, 90 * cm, 90 * cm)
+              #p.drawOn(c, 15 * cm, row * cm)
+            if ibody.contribution_total != 0:
+              dataRow.append(_('Contribution'))
+              dataRow.append(ibody.contribution)
+              dataRow.append(ibody.contribution_total)
+              #outData = '%s %s%s %8.2f'  %(_('Contribution'),  ibody.contribution, '%', ibody.contribution_total)
+              #row-=0.3
+              #p = Paragraph(outData, styles['PopLitle'])
+              #p.wrapOn(c, 90 * cm, 90 * cm)
+              #p.drawOn(c, 15 * cm, row * cm)
+            if ibody.taxdeduced_total != 0:
+              dataRow.append(_('Tax deduced'))
+              dataRow.append(ibody.taxdeduced)
+              dataRow.append(ibody.taxdeduced_total)
+              #outData = '%s %s%s %8.2f ' %(_('Tax deduced'),  ibody.taxdeduced, '%', ibody.taxdeduced_total)
+              #row-=0.3
+              #p = Paragraph(outData, styles['PopLitle'])
+              #p.wrapOn(c, 90 * cm, 90 * cm)
+              #p.drawOn(c, 15 * cm, row * cm)
+
+            #row -= 1.5
+            data.append(dataRow)
+        ts = [('ALIGN', (1,1), (-1,-1), 'CENTER'),
+             ('LINEABOVE', (0,0), (-1,0), 1, colors.purple),
+             ('LINEBELOW', (0,0), (-1,0), 1, colors.purple),
+             ('FONT', (0,0), (-1,0), 'Times-Bold'),
+             ('LINEABOVE', (0,-1), (-1,-1), 1, colors.purple),
+             ('LINEBELOW', (0,-1), (-1,-1), 0.5, colors.purple,
+              1, None, None, 4,1),
+             ('LINEBELOW', (0,-1), (-1,-1), 1, colors.red),
+             ('FONT', (0,-1), (-1,-1), 'Times-Bold')]
+            
+        table = Table(data, style=ts)
+        elements.append(table)
+
+        f=Frame(10,10,550,800)
+        f.addFromList(table,c)
+
+        c.showPage()
+        c.save()
+        
+        
+        pdf = buffer.getvalue()
+        buffer.close()
+        
+        if path_to_save:
+            f = file("path_to_save", "wb")
+            f.write(pdf)
+            f.close()
+
+        return pdf

invoices/templatetags/__init__.py

+

invoices/templatetags/currency.py

+from django import template
+from django.utils.translation import ugettext
+from django.utils.safestring import mark_safe
+import locale
+locale.setlocale(locale.LC_ALL, '')
+
+register = template.Library()
+ 
+ 
+@register.filter()
+def currency(value):
+    
+    try:
+        return mark_safe(  '%s %s' %(locale.currency(value, symbol=False, grouping=True), ugettext('currency')) )
+    except:
+        return '-err-'
+

invoices/templatetags/formatnumber.py

+# -*- coding: iso-8859-1 -*-
+from django import template
+from django.utils.translation import ugettext
+from django.utils.safestring import mark_safe
+import locale
+locale.setlocale(locale.LC_ALL, '')
+
+register = template.Library()
+ 
+ 
+@register.filter()
+def currency(value):
+    try:
+        return mark_safe(  '%s %s' %(locale.currency(value, symbol=False, grouping=True), ugettext('currency')) )
+    except:
+        return '-err-'
+
+
+

invoices/tests.py

+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+from django.conf.urls.defaults import *
+from django.conf import settings
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('invoices.views' ,
+    url(r'^/$', 'index',  name='invoices-index'),
+    url(r'^/new/$', 'new',  name='invoices-new'),
+    url(r'^/update/(?P<id>\d+)/$', 'update',  name='invoices-update'),
+    url(r'^/status/(?P<id>\d+)/$', 'status',  name='invoices-status'),
+    url(r'^/issue/(?P<id>\d+)/$', 'issue',  name='invoices-issue'),
+    url(r'^/payd/(?P<id>\d+)/$', 'payd',  name='invoices-payd'),
+    url(r'^/pdfhtml/(?P<id>\d+)/$', 'pdfhtml',  name='invoices-pdfhtml'),
+    url(r'^/additem/$', 'additem',  name='invoices-additem'),
+    url(r'^/download/(?P<id>\d+)/$', 'download',  name='invoices-download'),
+    url(r'^/getit/(?P<findrandomnumber>\w{56})/$', 'getit',  name='invoices-getit'),
+    #url(r'^/ajaxgetit/(?P<findrandomnumber>\w{56})/$', 'ajaxgetit',  name='invoices-ajaxgetit'),
+)
+
+if settings.DEBUG:
+    urlpatterns += patterns('invoices.views',
+        url(r'^/delete/(?P<id>\d+)/$'            , 'delete' , name='invoices-delete'),
+    )
+
+##url(r'^/pdf/(?P<id>\d+)/$', 'pdf',  name='invoicehes-pdf'),
+##url(r'^/update/(?P<id>\d)/$'            , 'update' , name='invoicehes-update'),

invoices/views.py

+# -*- coding: iso-8859-1 -*-
+from django.shortcuts import render_to_response, get_object_or_404
+from django.http import HttpResponseRedirect, HttpResponse
+from django.template import RequestContext
+from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
+from django import forms
+from django.conf import settings
+from django.contrib.auth.models import User
+from django.utils.translation import ugettext as _
+from django.core.files import File
+
+from invoices.models  import InvoiceHeaders, InvoiceBodies, InvoiceHeadersModel #invoicehesForm, , InvoiceBodiesForm
+from contacts.models import Contacts
+from payterms.models import Payterms
+from items.models import Items
+
+from settings import MEDIA_ROOT, MEDIA_URL_USER_DOCS
+
+from datetime import datetime, timedelta
+from calendar import monthrange
+#from os import mkdir, chdir
+from time import time
+from hashlib import sha224
+from os.path import normpath
+import utility
+
+def get_choicesContacts(userid=None, typeUser=None):
+    contacts = Contacts.objects.filter(user=userid).filter(tp_contacts=typeUser)
+    return [(contact.id,contact.name) for contact in contacts]
+
+def get_choicesPayterms(userid=None):
+    payterms = Payterms.objects.filter(user=userid)
+    return [(payterm.id,"%s - %s - %s" %(payterm.description1[0:10],payterm.description2[0:10] , payterm.description3[0:10])) for payterm in payterms]
+
+class formInvoice(forms.Form):
+    def __init__(self, uid=None, *args, **kwargs):
+        super(formInvoice, self).__init__(*args, **kwargs)
+        if uid!=None:
+            self.fields['Issuer'] = forms.ChoiceField(choices=get_choicesContacts(uid, 'P'))
+            self.fields['Custumer'] = forms.ChoiceField(choices=get_choicesContacts(uid, 'C'))
+            self.fields['Payterm'] = forms.ChoiceField(choices=get_choicesPayterms(uid))
+            #self.fields['Item'] = forms.ChoiceField(choices=get_choicesItems(uid))
+            #self.fields['Item_descr'] = forms.CharField(label="additiona info")
+
+class FormNewInvoice(forms.Form):
+    number = forms.IntegerField(label='number')
+    date = forms.DateField(label="issue date", input_formats=['%d/%m/%Y'])
+
+def getit(request, findrandomnumber=None):
+    i = InvoiceHeaders.objects.filter(findrandomnumber=findrandomnumber)[0]
+    nomefile = normpath(MEDIA_ROOT +  i.pdf.name.split('media')[1])
+    f = open(normpath(MEDIA_ROOT +  i.pdf.name.split('media')[1]), 'rb')
+    stream = f.readlines()
+    f.close()
+    #invoiceheader = InvoiceHeaders.objects.get(id=id)
+    #invoiceheader.pdf.open()
+    #stream = invoiceheader.pdf.readlines()
+    #invoiceheader.pdf.close()
+    return HttpResponse(stream, mimetype='application/pdf')
+
+
+@login_required
+def index(request):
+    invoices = InvoiceHeaders.objects.filter(user=request.user.id).order_by('-status', 'number')
+    return render_to_response('invoices/index.html' ,
+                              {'invoices' : invoices,
+                              'current_site' : request.META['HTTP_HOST'],
+                              'current_path' : request.META['PATH_INFO'],
+                              'r' : request.path , },
+                               context_instance=RequestContext(request))
+@login_required
+def pdfhtml(request, id=None):
+    pdfHtml = _generate_pdf(id)
+    return HttpResponse(pdfHtml.getvalue(), mimetype='application/pdf')
+
+    #return HttpResponse("PDF ERROR! %s" % pdf.err)
+
+    response = render_to_response('invoices/pdf.html' ,  \
+                              {'invoiceheader' : invoiceheader, \
+                              'invoicebody' : invoicebody,} , \
+                               context_instance=RequestContext(request))
+
+    return render_to_response('invoices/pdf.html' ,  \
+                              {'invoiceheader' : invoiceheader, 'invoicebody' : invoicebody,} , \
+                               context_instance=RequestContext(request))
+
+
+@login_required
+def status(request, id=None):
+
+    #from django.core.files.uploadedfile import InMemoryUploadedFile
+    from django.core.files.base import ContentFile
+
+    invoiceheader = InvoiceHeaders.objects.get(id=id)
+    error = None
+    mydate = datetime.now()
+    mydate = mydate - timedelta(days=mydate.day)
+    dateissue = "%s/%s/%s" %(monthrange(mydate.year,  mydate.month)[1] , mydate.month, mydate.year)
+    number = invoiceheader.nextnumber (uid=request.user.id, year=mydate.year)
+    number_next = None
+
+    if request.method == 'POST':
+        form = FormNewInvoice(request.POST)
+        if form.is_valid():
+            dataDb =  "%s-%s-%s" %(form['date'].data[6:10], form['date'].data[3:5] ,form['date'].data[0:2])
+            dateissue = form['date'].data
+            #number_next = invoiceheader.nextnumber (uid=request.user.id)
+            number = form['number'].data
+            #if InvoiceHeaders.objects.filter(dateissue__year=form['date'].data[6:10]).filter(number=form['number'].data):
+            #    error = '%s : %s / %s' %( _('ErrdupKey'), form['date'].data[6:10], form['number'].data)
+            #else:
+            invoiceheader.status = 'I'
+            invoiceheader.save(number = number, dateissue = dataDb)
+            filename = '%s-%s.pdf' %(invoiceheader.dateissue, invoiceheader.number )
+            pdfInvoice = _generate_pdf(id)
+            #file = InMemoryUploadedFile(pdfInvoice, "pdf", filename, None, pdfInvoice.tell(), None)
+            #invoiceheader.pdf.save(file.name, file)
+
+            #content = File(file=pdfInvoice.getvalue(), name=filename)
+            #pdfInvoice.name = filename
+            #content = File({'name': filename, 'content':pdfInvoice})
+
+            invoiceheader.pdf.save(filename, ContentFile(pdfInvoice.getvalue()))
+            invoiceheader.findrandomnumber=sha224( "%f-%s"%(time(),filename) ).hexdigest()
+
+            invoiceheader.save()
+            #pathDocs = '%s/%s' %(MEDIA_URL_USER_DOCS,invoiceheader.user.id)
+            #try:
+            #    chdir(pathDocs)
+            #except:
+            #    mkdir(pathDocs)
+            #f = open(invoiceheader.pdf.path,  'wb')
+            #f.write(pdfInvoice.getvalue())
+            #f.flush()
+            #f.close()
+
+            #f = open('%s/%s' %(pathDocs, 'to.txt'), 'w')
+            #f.write(invoiceheader.pdf.path)
+            #f.write('\n\r')
+            #f.write('/'.join([MEDIA_URL_USER_DOCS, '%s' %request.user.id, 'filename']))
+            #f.write('\n\r')
+            #f.write(MEDIA_URL_USER_DOCS)
+            #f.write(pdfInvoice.getvalue())
+            #f.flush()
+            #f.close()
+
+            return HttpResponseRedirect(reverse ('invoices-index'))
+    #else:
+
+    form = FormNewInvoice({'number': number,
+                           'date': dateissue})
+    return render_to_response('invoices/status.html' ,
+                             {'invoiceheader' : invoiceheader,
+                              'form': form,
+                              'number_next': number_next ,
+                              'error': error} ,
+                                   context_instance=RequestContext(request))
+
+@login_required
+def issue(request,  id=None):
+    invoiceheader = InvoiceHeaders.objects.get(id=id)
+    invoiceheader.status = 'I'
+    invoiceheader.save()
+    return HttpResponseRedirect(reverse ('invoices-index'))
+
+@login_required
+def payd(request,  id=None):
+    invoiceheader = InvoiceHeaders.objects.get(id=id)
+    invoiceheader.status = 'P'
+    invoiceheader.save()
+    return HttpResponseRedirect(reverse ('invoices-index'))
+
+@login_required
+def download(request, id=None):
+    i = InvoiceHeaders.objects.get(id=id)
+    nomefile = normpath(MEDIA_ROOT +  i.pdf.name.split('media')[1])
+    f = open(normpath(MEDIA_ROOT +  i.pdf.name.split('media')[1]), 'rb')
+    stream = f.readlines()
+    f.close()
+    #invoiceheader = InvoiceHeaders.objects.get(id=id)
+    #invoiceheader.pdf.open()
+    #stream = invoiceheader.pdf.readlines()
+    #invoiceheader.pdf.close()
+    return HttpResponse(stream, mimetype='application/pdf')
+
+
+@login_required
+def new(request):
+    error = ''
+    if request.method == 'POST':
+        itemFound = False
+        for id in range(1, int(request.REQUEST['numberitem']) + 1):
+            if request.REQUEST.get('Item_%s' %id):
+                itemFound = True
+                break
+        if itemFound:
+            user = User.objects.get(id = request.user.id)
+            issuer =  Contacts.objects.get(id = int(request.REQUEST['Issuer']) )
+            customer = Contacts.objects.get(id = int(request.REQUEST['Custumer']) )
+            payterm = Payterms.objects.get(id = int(request.REQUEST['Payterm']) )
+            ihd = InvoiceHeaders()
+            ihd.user = user
+            ihd.issuer = issuer
+            ihd.payterm = payterm
+            ihd.customer = customer
+            ihd.status = 'D'
+            ihd.findrandomnumber=sha224( "%f"%(time()) ).hexdigest()
+
+            ihd.save()
+
+            for id in range(1, int(request.REQUEST['numberitem']) + 1):
+                if request.REQUEST.get('Item_%s' %id):
+                    ibd = InvoiceBodies()
+                    ibd.header = ihd
+                    ibd.quantity = float(request.REQUEST['Item_qta_%s' %id].replace(',','.'))
+                    items = Items.objects.get(id = int(request.REQUEST['Item_%s' %id]) )
+                    ibd.item = items
+                    ibd.extraDescription = request.REQUEST['Item_descr_%s' %id].strip()
+                    ibd.save()
+            return HttpResponseRedirect(reverse ('invoices-index'))
+        else:
+            error = _('Item is obbligatory')
+
+    form = formInvoice(uid=request.user.id) # An unbound form
+    custumer_selected = 3
+    return render_to_response('invoices/new2.html' ,
+                            {'form': form,
+                             'custumer_selected' : custumer_selected ,
+                             'error' : error, },
+                             context_instance=RequestContext(request))
+@login_required
+def update(request, id=None):
+    error = ''
+    invoice = get_object_or_404(InvoiceHeaders, id=id, user=request.user.id)
+    if request.method == 'POST':
+        itemFound = False
+        for id in range(1, int(request.REQUEST['numberitem']) + 1):
+            if request.REQUEST.get('Item_%s' %id):
+                itemFound = True
+                break
+        if itemFound:
+            for body in invoice.invoicebodies_set.all():
+                body.delete()
+
+            user = User.objects.get(id = request.user.id)
+            issuer =  Contacts.objects.get(id = int(request.REQUEST['Issuer']) )
+            customer = Contacts.objects.get(id = int(request.REQUEST['Custumer']) )
+            payterm = Payterms.objects.get(id = int(request.REQUEST['Payterm']) )
+            invoice.user = user
+            invoice.issuer = issuer
+            invoice.payterm = payterm
+            invoice.customer = customer
+
+            invoice.save()
+
+            for id in range(1, int(request.REQUEST['numberitem']) + 1):
+                if request.REQUEST.get('Item_%s' %id):
+                    ibd = InvoiceBodies()
+                    ibd.header = invoice
+                    ibd.quantity = float(request.REQUEST['Item_qta_%s' %id].replace(',','.'))
+                    items = Items.objects.get(id = int(request.REQUEST['Item_%s' %id]) )
+                    ibd.item = items
+                    ibd.extraDescription = request.REQUEST['Item_descr_%s' %id]
+                    ibd.save()
+
+            return HttpResponseRedirect(reverse ('invoices-index'))
+        else:
+            error = _('Item is obbligatory')
+
+    form = formInvoice(uid=request.user.id) # An unbound form
+    issuer_id = invoice.issuer_id
+    customer_id = invoice.customer_id
+    return render_to_response('invoices/update.html' ,
+                             {'form': form,
+                              'invoice' : invoice,
+                              'issuer_id' : issuer_id,
+                              'error' : error,
+                              'customer_id' : customer_id,
+                              'r' : request.path , },
+                               context_instance=RequestContext(request))
+
+def sendemail():
+    from django.core.mail import EmailMessage
+    email = EmailMessage('prova oweb', 'link fattura ...',to=['m_casari@yahoo.com'])
+    email.send()
+
+def delete(request, id=None):
+    return utility.delete(InvoiceHeaders, request, id, 'invoices-index')
+
+def additem(request):
+    if request.is_ajax():
+        q = request.GET.get( 'q' )
+        if q is not None:
+            form = formInvoice(uid=q) # An unbound form
+            return render_to_response('invoices/_item.html' ,
+                                    {'form': form,} ,
+                                       context_instance=RequestContext(request))
+
+def _generate_pdf(id=None):
+    from django.template.loader import get_template
+    from django.template import Context
+    from cStringIO import StringIO
+    import ho.pisa as pisa
+    invoiceheader = InvoiceHeaders.objects.get(pk=id)
+    bodies = []
+    gros = 0
+    net = 0
+    taxtotal = 0
+    taxes = {}
+    for body in invoiceheader.invoicebodies_set.values():
+        body['tax'] = []
+        body['net'] = 0
+        tax = 0
+        body['gros'] = body['unitprice'] * body['quantity']
+        for fees in InvoiceBodies.objects.get(pk=body['id']).invoicebodiesfees_set.all():
+            body['tax'].append({'name':fees.description, 'value':( body['gros'] / 100 ) * fees.percentage} )
+            if taxes.has_key(fees.description):
+                taxes[fees.description] += ( body['gros'] / 100 ) * fees.percentage
+            else:
+                taxes[fees.description] = ( body['gros'] / 100 ) * fees.percentage
+            print taxes
+            tax += ( body['gros'] / 100 ) * fees.percentage
+        gros += body['gros']
+        body['net'] = body['gros'] + tax
+        taxtotal += tax
+        bodies.append(body)
+    net = gros + taxtotal
+    template = get_template('invoices/pdf.html')
+    context = Context({'invoiceheader' : invoiceheader, \
+                       'bodies' : bodies, \
+                       'gros' : gros, \
+                       'tax' : taxtotal, \
+                       'taxes' : taxes, \
+                       'net' : net, \
+                       'MEDIA_ROOT' : MEDIA_ROOT})
+    html = template.render(context)
+    result = StringIO()
+    pdf = pisa.pisaDocument(StringIO(html.encode("utf8")), result)
+    return result
+
+    ##f = open('%s/%s-%s-%s.pdf' %(MEDIA_ROOT,invoiceheader.user.id,invoiceheader.dateissue,invoiceheader.number), 'w')
+    #if invoiceheader.number:
+    #    pathDocs = '%s/%s' %(MEDIA_URL_USER_DOCS,invoiceheader.user.id)
+    #    try:
+    #        chdir(pathDocs)
+    #    except:
+    #        mkdir(pathDocs)
+    #    #result.seek(0)
+    #    f = open('%s/%s-%s.pdf' %(pathDocs, invoiceheader.dateissue, invoiceheader.number ), 'wb')
+    #    f.write(result.getvalue())
+    #    f.flush()
+    #    f.close()
+
+
+    ##f.write(result.getvalue())
+    ##f.flush()
+    ##f.close()
+    ##if not pdf.err:
+    ##    f = open('%s/workfile.pdf' %MEDIA_ROOT, 'w')
+    ##    f.write(result.getvalue())
+    ##    f.flush()
+    ##    f.close()
+
+    #    return HttpResponse(result.getvalue(), mimetype='application/pdf')
+
+    #return HttpResponse("PDF ERROR! %s" % pdf.err)
+
+    #response = render_to_response('invoices/pdf.html' ,  \
+    #                          {'invoiceheader' : invoiceheader, \
+    #                          'invoicebody' : invoicebody,} , \
+    #                           context_instance=RequestContext(request))
+
+    #return render_to_response('invoices/pdf.html' ,  \
+    #                          {'invoiceheader' : invoiceheader, 'invoicebody' : invoicebody,} , \
+    #                           context_instance=RequestContext(request))

items/__init__.py

Empty file added.
+from django.db import models
+from django.contrib.auth.models import User
+from django.contrib import admin
+from django.forms import ModelForm
+from django.utils.translation import ugettext as _
+from fees.models import Fees
+
+class Items(models.Model):
+    unitprice = models.FloatField(verbose_name=_('Unit price'))
+    unitmeasurement = models.CharField(max_length=80, verbose_name=_("Unit measure"))
+    description =  models.CharField(max_length=80, verbose_name=_("Description"))
+    #vat = models.FloatField(verbose_name=_('Vat'))
+    #contribution = models.FloatField(verbose_name=_('Contribution'))
+    #taxdeduced = models.FloatField(verbose_name=_('Tax deduced'))
+    fees = models.ManyToManyField(Fees)
+    user = models.ForeignKey(User)
+
+    def __unicode__(self):
+        return u'%s' %self.description
+    
+    class Meta:
+        verbose_name_plural = "Items"
+        verbose_name  = "Item" 
+        
+class ItemsAdmin(admin.ModelAdmin):
+    list_display = ('description', 'user')
+    list_filter = ['description', 'user']
+    search_fields = ['description', 'user']
+
+admin.site.register(Items, ItemsAdmin)
+
+class ItemsForm(ModelForm):
+    class Meta:
+        model = Items
+        fields = ['unitprice','unitmeasurement', 'description',]
+
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
+# -*- coding: iso-8859-1 -*-
+from django.conf.urls.defaults import *
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('items.views' ,
+    url(r'^(?P<tipo>\.pdf|\.pdf2|\.pdf3|\.pdf4)?/$'    , 'index'  , name='items-index'),
+    url(r'^/update/(?P<id>\d+)/$'            , 'update' , name='items-update'),
+    url(r'^/new/$'                          , 'new'    , name='items-new'),
+    url(r'^/delete/(?P<id>\d+)/$'            , 'delete' , name='items-delete'),
+    #url(r'^/ajax/(?P<id>\d+)/(?P<idx>\d+)/(?P<qta>\d+)/$'  , 'ajax'   , name='items-ajax'),
+    url(r'^/ajax/(?P<id>\d+)/(?P<idx>\d+)/(?P<qta>\d+\.*\d*)/$'  , 'ajax'   , name='items-ajax'),
+    #url(r'^/ajax_list/(?P<idx>\d+)/(?P<id>\d+)/(?P<extdesct>[a-zA-Z0-9_ ]+)/(?P<qta>\d+)/$'  , 'ajax_list' , name='items-ajax-list'),
+    url(r'^/ajax_list/(?P<idx>\d+)/(?P<id>\d+)/(?P<extdesct>[a-zA-Z0-9_()\[\]\.\,<>\!\@\# ]+)/(?P<qta>\d+\.*\d*)/$'  , 'ajax_list' , name='items-ajax-list'),
+    #url(r'^/ajax_list/(?P<idx>\d+)/(?P<id>\d+)/(?P<qta>\d+)/$'  , 'ajax_list' , name='items-ajax-list'),
+    url(r'^/ajax_list/(?P<idx>\d+)/(?P<id>\d+)/(?P<qta>\d+\.*\d*)/$'  , 'ajax_list' , name='items-ajax-list'),
+    url(r'^/pippo/$'                          , 'pippo'    , name='items-pippo'),
+) 
+from django.shortcuts import render_to_response, get_object_or_404
+from django.http import HttpResponseRedirect, HttpResponse
+from django.template import RequestContext, Context
+from django.template.loader import get_template
+from django.core.urlresolvers  import reverse
+from django.contrib.auth.decorators import login_required
+from items.models import Items, ItemsForm
+from fees.models import Fees
+from django.contrib.auth.models import User
+from django import forms
+
+def get_choicesItems(userid=None):
+    items = Items.objects.filter(user=userid)
+    return [(item.id,item.description[0:30]) for item in items]
+
+class formItem(forms.Form):
+    def __init__(self, uid=None, nameField=None, *args, **kwargs):
+        super(formItem, self).__init__(*args, **kwargs)
+        self.fields['Item'] = forms.ChoiceField(choices=get_choicesItems(uid))
+        self.fields['Item_descr'] = forms.CharField(label="additiona info")
+
+import ho.pisa 
+import cStringIO
+#from reportlab.pdfgen import canvas
+
+import utility
+
+@login_required
+def ajax_list(request, idx=0, id=0, extdesct='' ,qta=0):
+    form = formItem(uid=request.user.id) # An unbound for
+    #if id > 0:
+    #    item = Items.objects.get(pk=id)
+    #else:
+    item={'id':0}
+    if extdesct:
+        extdesct = extdesct.strip()
+    return render_to_response('items/ajax_list.html' , 
+                             {'form' : form,
+                              'item' : item,
+                              'idx' : idx, 
+                              'id' : int(id), 
+                              'extdesct' : extdesct, 
+                              'qta' : qta ,} ,
+                               context_instance=RequestContext(request))
+
+@login_required
+def ajax(request, id=None, idx=None, qta=None):
+    item = Items.objects.get(id=id)
+    return render_to_response('items/ajax.html' , 
+                             {'item' : item,
+                             'idx' : idx,
+                             'qta' : qta, } ,
+                              context_instance=RequestContext(request))
+
+@login_required
+def index(request, tipo = None):
+
+    items = Items.objects.filter(user=request.user.id)
+
+    #response = render_to_response('items/index.html' , RequestContext(request, {'items' : items, }) )
+    response = render_to_response('items/index.html', {'items' : items, }, context_instance=RequestContext(request))
+    
+    if tipo == '.pdf2':
+        file_pdf = cStringIO.StringIO()
+        ho.pisa.CreatePDF(unicode(response, encoding='utf-8'), file_pdf)
+        return HttpResponse(file_pdf.getvalue(), content_type = "application/pdf")
+     
+    if tipo == '.pdf':
+        return render_to_response('items/indexpdf.html' , RequestContext(request, {'items' : items, }) )
+        #return render_to_pdf('items/indexpdf.html',{'pagesize':'A4', \
+        #                                          'title':'Items',  \
+        #                                          'items' : items,})          
+    if tipo == '.pdf3':
+        response = HttpResponse(mimetype='application/pdf')
+        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
+
+        # Create the PDF object, using the response object as its "file."
+        p = canvas.Canvas(response)
+
+        # Draw things on the PDF. Here's where the PDF generation happens.
+        # See the ReportLab documentation for the full list of functionality.
+        p.drawString(100, 100, "Hello world.")
+
+        # Close the PDF object cleanly, and we're done.
+        p.showPage()
+        p.save()
+        return response
+
+    if tipo == '.pdf4':
+        # Create the HttpResponse object with the appropriate PDF headers.
+        response = HttpResponse(mimetype='application/pdf')
+        response['Content-Disposition'] = 'attachment; filename=somefilename.pdf'
+
+        buffer = cStringIO.StringIO()
+
+        # Create the PDF object, using the StringIO object as its "file."
+        p = canvas.Canvas(buffer)
+        #, \
+        #                  #pagesize = A4, \
+        #                  #pagesize = eval('landscape(A4)'), \
+        #                  bottomup = 0)
+
+        # Draw things on the PDF. Here's where the PDF generation happens.
+        # See the ReportLab documentation for the full list of functionality.
+        p.drawString(100, 100, "Hello world 100,100.")
+        p.drawString(300, 100, "Hello world 300,100.")
+        p.drawString(400, 100, "Hello world 400.100.")
+        p.drawString(400, 500, "Hello world 400.500.")
+        # Close the PDF object cleanly.
+
+        p.showPage()
+        p.save()
+
+        # Get the value of the StringIO buffer and write it to the response.
+        pdf = buffer.getvalue()
+        buffer.close()
+        response.write(pdf)
+        return response
+
+    
+    return response
+    
+
+@login_required      
+def update(request, id=None):
+    item = get_object_or_404(Items, id=id, user=request.user.id)
+    form = ItemsForm(request.POST or None ,instance=item)
+    if request.method == 'POST':
+        if form.is_valid():
+            obj_model_form = form.save(commit=False)
+            obj_model_form.user = User.objects.get(id=request.user.id)
+            obj_model_form.save()
+        
+            for fee in item.fees.values(): # delete the fee connected to item
+                item.fees.remove(fee['id'])
+                
+            for id in range(1, int(request.REQUEST['numberfee']) + 1):
+                try:
+                    fee = Fees.objects.get(id = int(request.REQUEST['Fee_%s' %id]) )
+                    obj_model_form.fees.add(fee)
+                    obj_model_form.save()
+                except KeyError:
+                    None
+                    
+            return HttpResponseRedirect(reverse ('items-index'))
+
+    return render_to_response('items/update.html' , 
+                              {'form': form,
+                               'item': item, } ,
+                               context_instance=RequestContext(request))
+    #return utility.update(Items, ItemsForm, request, id, 'items-index', 'crud/update.html')
+
+#@login_required  
+#def new(request):
+#    return utility.new(ItemsForm, request, 'items-index', 'crud/new.html')
+
+@login_required
+def new(request):
+    form = ItemsForm(request.POST or None)
+    if request.method == 'POST':
+        if form.is_valid():
+            obj_model_form = form.save(commit=False)
+            obj_model_form.user = User.objects.get(id=request.user.id)
+            obj_model_form.save()
+            
+            for id in range(1, int(request.REQUEST['numberfee']) + 1):
+                try:
+                    fee = Fees.objects.get(id = int(request.REQUEST['Fee_%s' %id]) )
+                    obj_model_form.fees.add(fee)
+                    obj_model_form.save()
+                except KeyError:
+                    None
+            
+            return HttpResponseRedirect(reverse ('items-index'))
+
+    return render_to_response( 'items/new.html' , 
+                              {'form' : form,
+                               'title' : 'New Item', } ,
+                               context_instance=RequestContext(request))
+
+@login_required  
+def delete(request, id=None):
+    return utility.delete(Items, request, id, 'items-index')
+    
+
+def render_to_pdf(template_src, context_dict):
+    template = get_template(template_src)
+    context = Context(context_dict)
+    html  = template.render(context)
+    result = cStringIO.StringIO()
+    pdf = ho.pisa.pisaDocument(cStringIO.StringIO(html.encode("utf-8")), result)
+    if not pdf.err:
+        return HttpResponse(result.getvalue(), mimetype='application/pdf')
+    return HttpResponse('We had some errors<pre>%s</pre>' % cgi.escape(html))
+    
+
+def pippo(request):
+    return HttpResponse("ciccio;pasticcio", mimetype='application/csv')
+from django.contrib import auth
+
+#from django.contrib.auth.models import User
+from profiles.models  import ProfileUser
+
+class ProfilingUser(object):
+    def process_request(self, request):
+        from django.contrib.auth import get_user
+        u = get_user(request)
+        p = ProfileUser.objects.filter(user=u)
+        if not(p):
+            ProfileUser(user=u, language='en').save()
+        return None
+
+

lib/context_processors.py

+def url( request ):
+    return { 'path' : request.path.split('/')[1] } 

lib/userprofile.py

+from django.contrib import auth
+
+from profiles.models  import ProfileUser
+
+class ProfilingUser(object):
+    def process_request(self, request):
+        from django.contrib.auth import get_user
+        try:
+            u = get_user(request)
+            p = ProfileUser.objects.filter(user=u)
+            if not(p):
+                p = ProfileUser(user=u, language='en')
+                p.save()
+            lang_code = p.language
+            request.session['django_language'] = lang_code
+        except:
+            None
+        return None
+
+        
+
+    

locale/en/LC_MESSAGES/django.mo

Binary file added.

locale/en/LC_MESSAGES/django.po

+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-02-04 23:03+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: contacts/models.py:8
+msgid "Customer"
+msgstr ""
+
+#: contacts/models.py:9
+msgid "Supplier"
+msgstr ""
+
+#: contacts/models.py:10
+msgid "Peronal"
+msgstr ""
+
+#: contacts/models.py:11
+msgid "Generic"
+msgstr ""
+
+#: contacts/models.py:15 templates/contacts/index.html:32
+msgid "Name"
+msgstr ""
+
+#: contacts/models.py:16 templates/contacts/index.html:33
+msgid "Surname"
+msgstr ""
+
+#: contacts/models.py:17
+msgid "Address"
+msgstr ""
+
+#: contacts/models.py:18
+msgid "Zip Code"
+msgstr ""
+
+#: contacts/models.py:19
+msgid "Town"
+msgstr ""
+
+#: contacts/models.py:20
+msgid "Province"
+msgstr ""
+
+#: contacts/models.py:21
+msgid "Phone"
+msgstr ""
+
+#: contacts/models.py:22
+msgid "Mobile phone"
+msgstr ""
+
+#: contacts/models.py:23
+msgid "Email"
+msgstr ""
+
+#: contacts/models.py:24
+msgid "Type of contact"
+msgstr ""
+
+#: contacts/models.py:25
+msgid "VAT number"
+msgstr ""
+
+#: contacts/models.py:26
+msgid "Code for personal identification"
+msgstr ""
+
+#: contacts/views.py:38
+msgid "Update contact"
+msgstr ""
+
+#: contacts/views.py:42
+msgid "New contact"
+msgstr ""
+
+#: fees/models.py:13
+msgid "Code"
+msgstr ""
+
+#: fees/models.py:14 invoices/models.py:145 invoices/models.py:185
+#: items/models.py:11 templates/fees/index.html:9
+#: templates/invoices/pdf.html:127 templates/invoices/pdf2.html:120
+#: templates/items/index.html:9 templates/items/indexpdf.html:64
+#: templates/items/indexpdf.html.py:68
+msgid "Description"
+msgstr ""
+
+#: fees/models.py:15 invoices/models.py:186 templates/fees/index.html:10
+msgid "Percentage"
+msgstr ""
+
+#: fees/models.py:24 templates/base.html:43 templates/base.html.py:45
+#: templates/fees/index.html:3
+msgid "Fees"
+msgstr ""
+
+#: fees/models.py:25
+msgid "Fee"
+msgstr ""
+
+#: invoices/models.py:17
+msgid "Draft"
+msgstr ""
+
+#: invoices/models.py:18
+msgid "Issue"
+msgstr ""
+
+#: invoices/models.py:19
+msgid "Paid"
+msgstr ""
+
+#: invoices/models.py:33
+msgid "Number issue"
+msgstr ""
+
+#: invoices/models.py:34
+msgid "Year issue"
+msgstr ""
+
+#: invoices/models.py:35
+msgid "Date issue"
+msgstr ""
+
+#: invoices/models.py:36
+msgid "status"
+msgstr ""
+
+#: invoices/models.py:38
+msgid "My Name"
+msgstr ""
+
+#: invoices/models.py:39
+msgid "My Surname"
+msgstr ""
+
+#: invoices/models.py:40
+msgid "My Address"
+msgstr ""
+
+#: invoices/models.py:41
+msgid "My Zip Code"
+msgstr ""
+
+#: invoices/models.py:42
+msgid "My Town"
+msgstr ""
+
+#: invoices/models.py:43
+msgid "My Province"
+msgstr ""
+
+#: invoices/models.py:44
+msgid "My VAT number"
+msgstr ""
+
+#: invoices/models.py:46
+msgid "Customer Name"
+msgstr ""
+
+#: invoices/models.py:47
+msgid "Customer Surname"
+msgstr ""
+
+#: invoices/models.py:48
+msgid "Customer Address"
+msgstr ""
+
+#: invoices/models.py:49
+msgid "Customer Zip Code"
+msgstr ""
+
+#: invoices/models.py:50
+msgid "Customer Town"
+msgstr ""
+
+#: invoices/models.py:51
+msgid "Customer Province"
+msgstr ""
+
+#: invoices/models.py:52
+msgid "Customer VAT number"
+msgstr ""
+
+#: invoices/models.py:54
+msgid "Payterm 1"
+msgstr ""
+
+#: invoices/models.py:55
+msgid "Payterm 2"
+msgstr ""
+
+#: invoices/models.py:56
+msgid "Payterm 3"
+msgstr ""
+
+#: invoices/models.py:63
+msgid "Invoice Headers"
+msgstr ""
+
+#: invoices/models.py:64
+msgid "Invoice Header"
+msgstr ""
+
+#: invoices/models.py:143 items/models.py:9 templates/items/indexpdf.html:65
+#: templates/items/indexpdf.html.py:67
+msgid "Unit price"
+msgstr ""
+
+#: invoices/models.py:144 items/models.py:10
+msgid "Unit measure"
+msgstr ""
+
+#: invoices/models.py:146 invoices/models.py:151
+msgid "Extra Description"
+msgstr ""
+
+#: invoices/models.py:154
+msgid "Invoice Bodies "
+msgstr ""
+
+#: invoices/models.py:155
+msgid "Invoice Body "
+msgstr ""
+
+#: invoices/printpdf.py:39 templates/invoices/pdf2.html:107
+#: templates/invoices/pdf2.html.py:114
+msgid "vat"
+msgstr ""
+
+#: invoices/printpdf.py:66 templates/invoices/pdf.html:104
+#: templates/invoices/pdf2.html:97
+msgid "Invoice"
+msgstr ""
+
+#: invoices/printpdf.py:66 templates/invoices/pdf.html:104
+#: templates/invoices/pdf2.html:97
+msgid "#"
+msgstr ""
+
+#: invoices/printpdf.py:66 templates/invoices/pdf.html:104
+#: templates/invoices/pdf2.html:97
+msgid "of"
+msgstr ""
+
+#: invoices/printpdf.py:97 templates/items/indexpdf.html:69
+msgid "Vat"
+msgstr ""
+
+#: invoices/printpdf.py:106 templates/items/indexpdf.html:70
+msgid "Contribution"
+msgstr ""
+
+#: invoices/printpdf.py:115
+msgid "Tax deduced"
+msgstr ""
+
+#: invoices/views.py:223 invoices/views.py:269
+msgid "Item is obbligatory"
+msgstr ""
+
+#: invoices/templatetags/currency.py:14 templates/invoices/pdf.html:152
+#: templates/invoices/pdf2.html:150
+msgid "currency"
+msgstr "$"
+
+#: payterms/models.py:8
+msgid "line 1"
+msgstr ""
+
+#: payterms/models.py:9
+msgid "line 2"
+msgstr ""
+
+#: payterms/models.py:10
+msgid "line 3"
+msgstr ""
+
+#: profiles/views.py:28
+msgid "Check and confirm password"
+msgstr ""
+
+#: profiles/views.py:30
+msgid "Password is too short, min 8 charater"
+msgstr ""
+
+#: templates/base.html:35 templates/base.html.py:67 templates/base.html:69
+#: templates/invoices/index.html:3 templates/invoices/new2.html:3
+#: templates/invoices/status.html:3 templates/invoices/update.html:3
+msgid "Invoices"
+msgstr ""
+
+#: templates/base.html:49 templates/base.html.py:51
+#: templates/items/index.html:3 templates/items/new.html:3
+#: templates/items/update.html:3
+msgid "Items"
+msgstr ""
+
+#: templates/base.html:55 templates/base.html.py:57
+#: templates/contacts/index.html:3
+msgid "Contacts"
+msgstr ""
+
+#: templates/base.html:61 templates/base.html.py:63
+#: templates/payterms/index.html:3
+msgid "Payment terms"
+msgstr ""
+
+#: templates/base.html:73
+msgid "Login"
+msgstr ""
+
+#: templates/base.html:75
+msgid "Logout"
+msgstr ""
+
+#: templates/base.html:78
+msgid "Profile"
+msgstr ""
+
+#: templates/contacts/index.html:34 templates/fees/index.html:11
+#: templates/items/index.html:11 templates/payterms/index.html:13
+msgid "update"
+msgstr ""
+
+#: templates/contacts/index.html:35 templates/fees/index.html:12
+#: templates/invoices/index.html:54 templates/items/index.html:12
+#: templates/payterms/index.html:14
+msgid "delete"
+msgstr ""
+
+#: templates/contacts/index.html:41 templates/fees/index.html:17
+#: templates/invoices/index.html:71 templates/items/index.html:17
+#: templates/payterms/index.html:19
+msgid "new"
+msgstr ""
+
+#: templates/crud/new.html:27 templates/crud/update.html:10
+#: templates/invoices/new2.html:148 templates/items/new.html:48
+msgid "Save"
+msgstr ""
+
+#: templates/invoices/_item.html:11 templates/items/ajax.html:7
+msgid "Quantity "
+msgstr ""
+
+#: templates/invoices/index.html:15
+msgid "link to invoice #"
+msgstr ""
+
+#: templates/invoices/index.html:28 templates/invoices/status.html:8
+msgid "Number"
+msgstr ""
+
+#: templates/invoices/index.html:35
+msgid "Date Issue"
+msgstr ""
+
+#: templates/invoices/index.html:42
+msgid "Custumer"
+msgstr ""
+
+#: templates/invoices/index.html:43 templates/invoices/status.html:42
+msgid "Status"
+msgstr ""
+
+#: templates/invoices/index.html:46
+msgid "Get It"
+msgstr ""
+
+#: templates/invoices/index.html:52
+msgid "Update"
+msgstr ""
+
+#: templates/invoices/index.html:53 templates/invoices/index.html.py:57
+msgid "pdf"
+msgstr ""
+
+#: templates/invoices/new2.html:141
+msgid "Add items"
+msgstr ""
+
+#: templates/invoices/pdf.html:106 templates/invoices/pdf2.html:99
+msgid "DRAFT"
+msgstr ""
+
+#: templates/invoices/pdf.html:114 templates/invoices/pdf.html.py:121
+msgid "pvat"
+msgstr "vat"
+
+#: templates/invoices/pdf.html:128 templates/invoices/pdf2.html:121
+#: templates/items/ajax.html:5
+msgid "Price"
+msgstr ""
+
+#: templates/invoices/pdf.html:129 templates/invoices/pdf2.html:122
+msgid "Amount"
+msgstr ""
+
+#: templates/invoices/pdf.html:130 templates/invoices/pdf.html.py:152
+msgid "before tax"
+msgstr "Before tax"
+
+#: templates/invoices/pdf.html:156 templates/invoices/pdf2.html:125
+#: templates/invoices/pdf2.html.py:156
+msgid "Net"
+msgstr ""
+
+#: templates/invoices/pdf2.html:123 templates/invoices/pdf2.html.py:150
+msgid "Gros"
+msgstr ""
+
+#: templates/invoices/pdf2.html:124
+msgid "Tax"
+msgstr ""
+
+#: templates/invoices/status.html:19
+msgid "Date"
+msgstr ""
+
+#: templates/invoices/status.html:28
+msgid "Costumer name"
+msgstr ""
+
+#: templates/invoices/status.html:30
+msgid "Costumer surname"
+msgstr ""
+
+#: templates/invoices/status.html:32
+msgid "Costumer address"
+msgstr ""
+
+#: templates/invoices/status.html:34
+msgid "Costumer zipcode"
+msgstr ""
+
+#: templates/invoices/status.html:36
+msgid "Costumer town"
+msgstr ""
+
+#: templates/invoices/status.html:38
+msgid "Costumer provinve"
+msgstr ""
+
+#: templates/invoices/status.html:40
+msgid "Costumer vat"
+msgstr ""
+
+#: templates/items/ajax.html:6
+msgid "Unit"
+msgstr ""
+
+#: templates/items/ajax_list.html:38
+msgid "suplementary description "
+msgstr ""
+
+#: templates/items/index.html:10 templates/items/indexpdf.html:66
+msgid "Unit measurement"
+msgstr ""
+
+#: templates/items/indexpdf.html:59
+msgid "List of items"
+msgstr ""
+
+#: templates/items/indexpdf.html:71
+msgid "Tax Deduced"
+msgstr ""
+
+#: templates/items/new.html:44
+msgid "add fee"
+msgstr ""