ComptaInde/billing/views.py

292 lines
11 KiB
Python

from django.shortcuts import render
from django.template import RequestContext
from django.http import HttpResponse
from django.db.models import Sum
from reportlab.pdfgen import canvas
from reportlab.lib.colors import Color, black, blue, red
from reportlab.lib.pagesizes import A4
# from PIL import Image
import os
from django.conf import settings
from datetime import date
from comptabilite.facture_config import loadFactureConfig
from .models import (
Client,
Contract,
Prestation,
)
def contract_listing(request):
"""
Renvoie la liste de tous les contrats.
"""
contract_list = Contract.objects.all()
context = {'contract_list': contract_list}
return render(request, 'billing/contract/listing.html', context)
def contract_detail(request, contractid):
"""
Renvoie toutes les informations relatives à un contrat, en ce y compris les prestations
relatives à celui-ci.
"""
contract = Contract.objects.get(pk=contractid)
prestation_list = contract.get_prestation.all()
prestation_count = prestation_list.count()
total = list(contract.get_prestation.all().aggregate(Sum('total_amount')).values())[0]
context = {'contract': contract,
'prestation_list': prestation_list,
'prestation_count': prestation_count,
'total': total}
return render(request, 'billing/contract/detail.html', context)
def client_listing(request):
"""
Renvoie la liste de tous les clients.
"""
client_list = Client.objects.all()
context = {'client_list': client_list}
return render(request, 'billing/client/listing.html', context)
def prestation_listing(request):
"""
Renvoie la liste de toutes les prestations.
"""
prestation_list = Prestation.objects.all()
context = {'prestation_list': prestation_list}
return render(request, 'billing/prestation/listing.html', context)
Y = 841.89
X = 35
RIGHT_X = 595.27 - X
TITLED_X = 125
INDENTED_X = X + 5
INDENTED_RIGHT_X = RIGHT_X - 5
PRESTATION_COLUMN_2 = INDENTED_X + 65
PRESTATION_COLUMN_3 = INDENTED_X + 400
PRESTATION_COLUMN_4 = INDENTED_X + 455
COMMON_LINE_HEIGHT = -15
DOUBLE_LINE_HEIGHT = COMMON_LINE_HEIGHT * 2
BIG_LINE_HEIGHT = COMMON_LINE_HEIGHT * 3
HUGE_LINE_HEIGHT = COMMON_LINE_HEIGHT * 4
class MyDocument(object):
# Create the PDF object, using the response object as its "file."
# http://www.reportlab.com/docs/reportlab-userguide.pdf
# canvas.rect(x, y, width, height, stroke=1, fill=0)
# localhost:8000/billing/contract/pdf/2
def __init__(self, response):
# Create the PDF object, using the response object as its "file."
self.document = canvas.Canvas(response, pagesize=A4)
self.y = Y - X
def newline(self, height=None):
"""
Passe à la ligne, la hauteur de la ligne étant passée en paramètre.
"""
if height == DOUBLE_LINE_HEIGHT:
self.y += DOUBLE_LINE_HEIGHT
elif height == BIG_LINE_HEIGHT:
self.y += BIG_LINE_HEIGHT
elif height == HUGE_LINE_HEIGHT:
self.y += HUGE_LINE_HEIGHT
else:
self.y += COMMON_LINE_HEIGHT
# if y < 120;
# document.PageBreak()
# y = 790
def drawString(self, x, string, font_family="Helvetica", font_decoration=None, font_size=10):
font = font_family
if font_decoration is not None:
font += "-" + font_decoration
self.document.setFont(font, font_size)
self.document.drawString(x, self.y, string)
def drawNewLine(self, x, string, height=None, font_family="Helvetica", font_decoration=None, font_size=10):
self.newline(height)
self.drawString(x, string, font_family, font_decoration, font_size)
def header(self, info, contract):
"""
Génère le header de la facture.
"""
# self.document.rect(X, 735, 525, 70, fill=0)
self.drawNewLine(INDENTED_X, info['NAME'])
self.document.drawRightString(RIGHT_X, self.y, "N° de Référence : " + str(contract.reference))
self.drawNewLine(INDENTED_X, info['ADDRESS'])
self.drawNewLine(INDENTED_X, info['CITY'])
self.drawNewLine(INDENTED_X, info['GSM'])
self.newline(DOUBLE_LINE_HEIGHT)
def title(self, contract):
"""
Génère le "titre" de la facture.
"""
theString = "A l'attention de"
self.drawString(TITLED_X, "A l'attention de")
self.drawString(194, contract.client.contact, font_decoration="Bold")
self.drawString(194 + (len(contract.client.contact) * 5.2), " pour la")
self.drawNewLine(TITLED_X, contract.client.name, font_decoration="Bold")
self.drawNewLine(TITLED_X, contract.client.address)
self.drawNewLine(TITLED_X, str(contract.client.postal_code) + " " + contract.client.city)
self.newline()
self.drawNewLine(TITLED_X, "Concernant la/le")
self.drawString(200, contract.name, font_decoration="Bold")
self.newline()
def payementInformation(self, info, contract):
"""
Génère les informations de payement.
"""
self.newline()
height = 40
self.document.rect(X, self.y - height, RIGHT_X - X, height, fill=0)
self.drawNewLine(INDENTED_X, "N° Entreprise : " + info['COMPANY_NUMBER'])
self.document.drawRightString(INDENTED_RIGHT_X, self.y, "Votre N° Entreprise : " + contract.client.company_number)
self.drawNewLine(INDENTED_X, "N° de compte : " + info['BANK'] + " - " + info['ACCOUNT'])
self.newline(DOUBLE_LINE_HEIGHT)
def prestations(self, contract):
"""
Génère l'affichage des prestations : tableau, liste des prestations, …
"""
self.drawNewLine(X, "Prestations", font_decoration="Bold")
total = self.drawPrestationsTable(contract.get_prestation.all())
self.newline(DOUBLE_LINE_HEIGHT)
self.document.setFont("Helvetica", 10)
self.document.drawRightString(INDENTED_X + 445, self.y, "Acompte")
self.document.drawRightString(INDENTED_RIGHT_X, self.y, str(contract.advance))
self.newline()
self.document.setFont("Helvetica-Bold", 10)
self.document.drawRightString(INDENTED_X + 445, self.y, "Solde à payer")
self.document.drawRightString(INDENTED_RIGHT_X, self.y, str(total - contract.advance))
def drawColoredRow(self):
"""
Génère une ligne colorée.
"""
self.document.setFillColorCMYK(0.43,0.2,0,0)
self.document.rect(X, self.y - 4, RIGHT_X - X, COMMON_LINE_HEIGHT, fill=True, stroke=False)
self.document.setFillColorCMYK(0,0,0,1)
def drawHeaderPrestationsTable(self):
"""
Génère le header de la table des prestations.
"""
self.drawColoredRow()
self.newline()
self.document.setFillColorCMYK(0,0,0,1)
self.drawString(INDENTED_X, "Date")
self.drawString(PRESTATION_COLUMN_2, "Libellé")
self.drawString(INDENTED_X + 365, "Nbre")
self.drawString(INDENTED_X + 420, "Prix Unit.")
self.document.setFont("Helvetica-Bold", 10)
self.document.drawRightString(INDENTED_X + 510, self.y, "Total")
def drawFooterPrestationTable(self, total):
"""
Génère le footer de la table des prestations.
"""
self.drawColoredRow()
self.newline()
self.document.setFont("Helvetica-Bold", 10)
self.document.drawRightString(INDENTED_X + 445, self.y, "Total")
self.document.drawRightString(INDENTED_RIGHT_X, self.y, str(total))
def displayPrestation(self, prestation, total):
"""
Affiche une ligne de prestations dans le tableau.
"""
# self.newline()
total += prestation.total_amount
self.drawNewLine(INDENTED_X, str(prestation.date))
self.drawString(PRESTATION_COLUMN_2, prestation.label)
self.document.drawRightString(PRESTATION_COLUMN_3, self.y, str(prestation.unit))
# self.document.drawRightString(INDENTED_X + 400, self.y, str(prestation.unit))
self.document.drawRightString(PRESTATION_COLUMN_4, self.y, str(prestation.unit_price))
# self.document.drawRightString(INDENTED_X + 455, self.y, str(prestation.unit_price))
self.document.drawRightString(INDENTED_RIGHT_X, self.y, str(prestation.total_amount))
return total
def drawPrestationsTable(self, prestation_list):
"""
Génère le tableau des prestations.
"""
self.drawHeaderPrestationsTable()
total = 0
for prestation in prestation_list:
total = self.displayPrestation(prestation, total)
self.drawFooterPrestationTable(total)
return total
def conclusion(self, info, contract):
"""
Affiche la conclusion de la facture.
"""
self.newline(DOUBLE_LINE_HEIGHT)
self.document.rect(X, self.y, RIGHT_X - X, BIG_LINE_HEIGHT, fill=0)
self.drawNewLine(INDENTED_X, "Merci de bien vouloir payer sur le compte ")
self.drawString(INDENTED_X + 185, info['BANK'] + " : " + info['ACCOUNT'], font_decoration="Bold")
self.newline(COMMON_LINE_HEIGHT)
self.drawString(INDENTED_X, "Avec la référence :")
self.drawString(INDENTED_X + 85, "\"" + str(contract.reference) + "\"", font_decoration="Bold")
def addSignature(self):
"""
Génère la signature.
"""
self.newline(BIG_LINE_HEIGHT)
self.document.drawRightString(RIGHT_X, self.y, "Rebecq, le " + date.today().strftime('%d-%m-%Y'))
self.newline(COMMON_LINE_HEIGHT)
url = os.path.join(settings.STATICFILES_DIRS[0], 'img/signature.png')
self.newline(DOUBLE_LINE_HEIGHT)
im = self.document.drawImage(url, INDENTED_X + 340, self.y, width=180, height=39)
# im.hAlign = 'CENTER'
def download(self):
# Close the PDF object cleanly, and we're done.
self.document.showPage()
self.document.save()
def contract_export(request, contractid):
"""
Génere une fichier PDF pour fournir au client.
"""
info = loadFactureConfig(request)
contract = Contract.objects.get(pk=contractid)
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="facture_' + str(contract.reference) + '.pdf"'
document = MyDocument(response)
document.header(info, contract)
document.title(contract)
document.payementInformation(info, contract)
document.prestations(contract)
document.conclusion(info, contract)
document.addSignature()
document.download()
return response