|
|
|
@ -30,8 +30,9 @@ from comptabilite.tools import (
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import yaml
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
EXTENSES = 0
|
|
|
|
|
EXPENSES = 0
|
|
|
|
|
RECETTES = 1
|
|
|
|
|
|
|
|
|
|
X = 35
|
|
|
|
@ -79,37 +80,17 @@ class PDFDocument(object):
|
|
|
|
|
except yaml.YAMLError as exc:
|
|
|
|
|
print(exc)
|
|
|
|
|
|
|
|
|
|
def generate_spf_export(self, accounting_year):
|
|
|
|
|
""" Genère un document aux normes du SPF Finance. """
|
|
|
|
|
self.add_header()
|
|
|
|
|
self.add_title_spf(accounting_year)
|
|
|
|
|
self.add_recette_expenses(accounting_year)
|
|
|
|
|
self.add_annexes(accounting_year)
|
|
|
|
|
|
|
|
|
|
def generate_bill_paper(self, contract):
|
|
|
|
|
""" Génère une facture pour un contrat """
|
|
|
|
|
self.amount = 0
|
|
|
|
|
self.add_header(contract)
|
|
|
|
|
self.add_title_billing(contract)
|
|
|
|
|
self.add_prestations(contract)
|
|
|
|
|
self.add_conclusion(contract)
|
|
|
|
|
self.add_signature()
|
|
|
|
|
self.add_footer()
|
|
|
|
|
|
|
|
|
|
def add_vspace(self, height=None):
|
|
|
|
|
def add_vspace(self, height=COMMON_LINE_HEIGHT):
|
|
|
|
|
""" Passe à la ligne, la hauteur de la ligne étant passée en paramètre.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
height (int): hauteur de la ligne
|
|
|
|
|
height (int): hauteur de la ligne.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
self.y += height
|
|
|
|
|
|
|
|
|
|
# if y < 120;
|
|
|
|
|
# document.PageBreak()
|
|
|
|
@ -118,7 +99,7 @@ class PDFDocument(object):
|
|
|
|
|
def add_string(
|
|
|
|
|
self, x, string, font_family="Helvetica", font_decoration=None, font_size=10
|
|
|
|
|
):
|
|
|
|
|
if font_decoration is not None:
|
|
|
|
|
if font_decoration:
|
|
|
|
|
font_family += "-" + font_decoration
|
|
|
|
|
self.document.setFont(font_family, font_size)
|
|
|
|
|
self.document.drawString(x, self.y, string)
|
|
|
|
@ -127,7 +108,7 @@ class PDFDocument(object):
|
|
|
|
|
self,
|
|
|
|
|
x,
|
|
|
|
|
string,
|
|
|
|
|
height=None,
|
|
|
|
|
height=COMMON_LINE_HEIGHT,
|
|
|
|
|
font_family="Helvetica",
|
|
|
|
|
font_decoration=None,
|
|
|
|
|
font_size=10,
|
|
|
|
@ -140,6 +121,9 @@ class PDFDocument(object):
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
rect_height = 40
|
|
|
|
|
self.document.rect(X, self.y, RIGHT_X - X, -rect_height, fill=0)
|
|
|
|
@ -162,18 +146,380 @@ class PDFDocument(object):
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace(BIG_LINE_HEIGHT)
|
|
|
|
|
|
|
|
|
|
def add_title_billing(self, contract):
|
|
|
|
|
def download(self):
|
|
|
|
|
# Close the PDF object cleanly, and we're done.
|
|
|
|
|
self.document.showPage()
|
|
|
|
|
self.document.save()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SpfDocument(PDFDocument):
|
|
|
|
|
def generate(self, accounting_year):
|
|
|
|
|
""" Genère un document aux normes du SPF Finance.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_header()
|
|
|
|
|
self.add_title(accounting_year)
|
|
|
|
|
self.add_recette_expenses(accounting_year)
|
|
|
|
|
self.add_annexes(accounting_year)
|
|
|
|
|
|
|
|
|
|
def add_title(self, accounting_year):
|
|
|
|
|
""" Ajoute un titre au document.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_string(
|
|
|
|
|
130,
|
|
|
|
|
"Comptes simplifiés de l'exercice " + accounting_year,
|
|
|
|
|
font_decoration="Bold",
|
|
|
|
|
font_size=20,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace(DOUBLE_LINE_HEIGHT)
|
|
|
|
|
|
|
|
|
|
def add_recette_expenses(self, accounting_year):
|
|
|
|
|
""" Ajoute l'état des recettes et dépense pour une année comptable passée en paramètre.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_string(
|
|
|
|
|
X, "Etat recettes/dépenses (en €)", font_decoration="Oblique", font_size=14
|
|
|
|
|
)
|
|
|
|
|
self.__display_transactiontypes_table(accounting_year)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_annexes(self, accounting_year):
|
|
|
|
|
""" Ajoute les annexes au document PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "Annexes", font_decoration="Oblique", font_size=14)
|
|
|
|
|
self.add_evaluation_rules(accounting_year)
|
|
|
|
|
self.add_modification_evaluation_rules(accounting_year)
|
|
|
|
|
self.add_additional_information(accounting_year)
|
|
|
|
|
self.add_patrimony(accounting_year)
|
|
|
|
|
self.add_right_engagement(accounting_year)
|
|
|
|
|
|
|
|
|
|
def add_evaluation_rules(self, accounting_year):
|
|
|
|
|
""" Ajoute les règles d'évaluation au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "1. Résumé des règles d'évaluation")
|
|
|
|
|
rules_list = EvaluationRules.objects.filter(
|
|
|
|
|
Q(stop_date__year__lte=accounting_year) | Q(stop_date__isnull=True)
|
|
|
|
|
).exclude(start_date__year__gt=accounting_year)
|
|
|
|
|
if rules_list:
|
|
|
|
|
for rule in rules_list:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
rule.label + " : " + rule.explanation,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2, "Pas de règle d'évaluation.", font_size=9
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_modification_evaluation_rules(self, accounting_year):
|
|
|
|
|
""" Ajoute les modifications d'évaluation au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "2. Adaptation des règles d'évaluation")
|
|
|
|
|
rules_adaptation_list = EvaluationRulesAdaptation.objects.filter(
|
|
|
|
|
start_date__year=accounting_year
|
|
|
|
|
)
|
|
|
|
|
if rules_adaptation_list:
|
|
|
|
|
for line in rules_adaptation_list:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
line.label + " : " + line.information,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
"Pas d'adaptation des règles d'évaluation.",
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_additional_information(self, accounting_year):
|
|
|
|
|
""" Ajoute les informations complémentaires au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "3. Informations complémentaires")
|
|
|
|
|
annuality = Annuality.objects.filter(year__year=accounting_year)
|
|
|
|
|
complementary_informations = ComplementaryInformations.objects.filter(
|
|
|
|
|
annuality=annuality[0]
|
|
|
|
|
)
|
|
|
|
|
if complementary_informations:
|
|
|
|
|
for line in complementary_informations:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
line.label + " : " + line.information,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
"Pas d'informations complémentaires.",
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_patrimony(self, accounting_year):
|
|
|
|
|
""" Ajoute les informations du patrimoine au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "4. Etat du patrimoine")
|
|
|
|
|
|
|
|
|
|
annuality = Annuality.objects.filter(year__year=accounting_year)
|
|
|
|
|
tmp_compta_expenses = get_transactiontype_and_sum_for_spf_export(
|
|
|
|
|
accounting_year, EXPENSES
|
|
|
|
|
)
|
|
|
|
|
tmp_compta_recettes = get_transactiontype_and_sum_for_spf_export(
|
|
|
|
|
accounting_year, RECETTES
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assets_list = get_asset_liability_and_sump_spf(accounting_year, category=0)
|
|
|
|
|
for item in assets_list:
|
|
|
|
|
if item[0] == "Liquidité":
|
|
|
|
|
item[1] += (
|
|
|
|
|
annuality[0].opening_balance
|
|
|
|
|
+ tmp_compta_recettes["sum_total_transaction"]
|
|
|
|
|
- tmp_compta_expenses["sum_total_transaction"]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
liability_list = get_asset_liability_and_sump_spf(accounting_year, category=1)
|
|
|
|
|
|
|
|
|
|
self.__display_table_header("AVOIRS", "DETTES")
|
|
|
|
|
save = self.y
|
|
|
|
|
self.__display_table_two_column(1, assets_list)
|
|
|
|
|
longest_y = self.y
|
|
|
|
|
self.y = save
|
|
|
|
|
self.__display_table_two_column(2, liability_list)
|
|
|
|
|
|
|
|
|
|
if self.y > longest_y:
|
|
|
|
|
self.y = longest_y
|
|
|
|
|
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_right_engagement(self, accounting_year):
|
|
|
|
|
""" Ajoute les droits & engagements au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
X,
|
|
|
|
|
"5. Droits et engagements importants qui ne sont pas susceptibles d'être quantifiés",
|
|
|
|
|
)
|
|
|
|
|
# self.__display_table_header("DROITS", "ENGAGEMENT")
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2, "Pas de droits ou d'engagements.", font_size=9
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
def __display_transactiontypes_table(self, accounting_year):
|
|
|
|
|
""" Ajoute le table pour les recettes & dépenses d'une année comptable.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
expenses = get_transactiontype_and_sum_for_spf_export(accounting_year, EXPENSES)
|
|
|
|
|
recettes = get_transactiontype_and_sum_for_spf_export(accounting_year, RECETTES)
|
|
|
|
|
|
|
|
|
|
self.__display_table_header("DEPENSES", "RECETTES")
|
|
|
|
|
self.__display_transactiontype_table_body(
|
|
|
|
|
expenses,
|
|
|
|
|
recettes,
|
|
|
|
|
int(expenses["sum_total_transaction"]),
|
|
|
|
|
int(recettes["sum_total_transaction"]),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_table_header(self, title_left, title_right):
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.document.rect(X, self.y - 5, RIGHT_X - X, -COMMON_LINE_HEIGHT, fill=0)
|
|
|
|
|
self.add_string(INDENTED_X, title_left, font_decoration="Bold", font_size=9)
|
|
|
|
|
self.add_string(
|
|
|
|
|
MIDDLE + INDENTED_X, title_right, font_decoration="Bold", font_size=9
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_transactiontype_table_body(
|
|
|
|
|
self, expenses, recettes, totalexpenses, totalrecettes
|
|
|
|
|
):
|
|
|
|
|
for i in range(4):
|
|
|
|
|
self.__display_table_line(
|
|
|
|
|
expenses["transaction_type_info"][i]["label"],
|
|
|
|
|
int(expenses["transaction_type_info"][i]["sum_total_amount"]),
|
|
|
|
|
recettes["transaction_type_info"][i]["label"],
|
|
|
|
|
int(recettes["transaction_type_info"][i]["sum_total_amount"]),
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.document.rect(
|
|
|
|
|
X, self.y - 5, MIDDLE, 5 * -COMMON_LINE_HEIGHT
|
|
|
|
|
) # Séparation en deux
|
|
|
|
|
self.document.rect(
|
|
|
|
|
MIDDLE, self.y - 5, MIDDLE, 5 * -COMMON_LINE_HEIGHT
|
|
|
|
|
) # Séparation descriptif et montant recettes
|
|
|
|
|
self.y -= COMMON_LINE_HEIGHT
|
|
|
|
|
self.__display_table_line(
|
|
|
|
|
"Total des dépenses",
|
|
|
|
|
totalexpenses,
|
|
|
|
|
"Total des recettes",
|
|
|
|
|
totalrecettes,
|
|
|
|
|
font_decoration="Bold",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_key_part(self, column_number, key, font_decoration=None):
|
|
|
|
|
""" Ajoute dans la colonne d'un tableau (à deux colonnes) la clef d'un couple clef/valeur.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
column_number (int): numéro de la colonne du tableau
|
|
|
|
|
key (str): la clef à afficher
|
|
|
|
|
font_decoration (str): décoration de la police de carectères
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
space = INDENTED_X
|
|
|
|
|
else:
|
|
|
|
|
space = MIDDLE + INDENTED_X
|
|
|
|
|
self.add_string(space, key, font_decoration=font_decoration, font_size=9)
|
|
|
|
|
|
|
|
|
|
def __display_value_part(self, column_number, value):
|
|
|
|
|
""" Ajoute dans la colonne d'un tableau (à deux colonnes) la valeur d'un couple clef/valeur
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
column_number (int): numéro de la colonne du tableau
|
|
|
|
|
value (str): la valeur à afficher
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
space = MIDDLE + X - INDENT
|
|
|
|
|
else:
|
|
|
|
|
space = INDENTED_RIGHT_X
|
|
|
|
|
|
|
|
|
|
self.document.drawRightString(
|
|
|
|
|
space, self.y, str(locale.format("%d", int(value), grouping=True)),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_column(self, column_number, key, value, font_decoration):
|
|
|
|
|
self.__display_key_part(column_number, key, font_decoration)
|
|
|
|
|
self.__display_value_part(column_number, value)
|
|
|
|
|
|
|
|
|
|
def __display_table_line(self, key1, value1, key2, value2, font_decoration=None):
|
|
|
|
|
self.document.rect(X, self.y - 5, RIGHT_X - X, COMMON_LINE_HEIGHT, fill=0)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.__display_column(1, key1, value1, font_decoration)
|
|
|
|
|
self.__display_column(2, key2, value2, font_decoration)
|
|
|
|
|
|
|
|
|
|
def __display_table_two_column(self, column_number, list):
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
begin_rect_line = X
|
|
|
|
|
begin_rect_res = MIDDLE
|
|
|
|
|
begin_text = INDENTED_X
|
|
|
|
|
begin_res = MIDDLE + X - INDENT
|
|
|
|
|
else:
|
|
|
|
|
begin_rect_line = MIDDLE + X
|
|
|
|
|
begin_rect_res = MIDDLE * 2
|
|
|
|
|
begin_text = MIDDLE + INDENTED_X
|
|
|
|
|
begin_res = INDENTED_RIGHT_X
|
|
|
|
|
|
|
|
|
|
total = 0
|
|
|
|
|
locale.setlocale(locale.LC_ALL, "pt_br.utf-8")
|
|
|
|
|
|
|
|
|
|
for line in list:
|
|
|
|
|
self.document.rect(
|
|
|
|
|
begin_rect_line, self.y - 5, MIDDLE, COMMON_LINE_HEIGHT, fill=0
|
|
|
|
|
)
|
|
|
|
|
self.document.rect(
|
|
|
|
|
begin_rect_res, self.y - 5, X, COMMON_LINE_HEIGHT, fill=0
|
|
|
|
|
)
|
|
|
|
|
self.add_new_line(begin_text, line[0], font_size=9)
|
|
|
|
|
self.document.drawRightString(
|
|
|
|
|
begin_res, self.y, str(locale.format("%d", int(line[1]), grouping=True))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
total += int(line[1])
|
|
|
|
|
|
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BillPaper(PDFDocument):
|
|
|
|
|
|
|
|
|
|
def generate(self, contract):
|
|
|
|
|
""" Génère une facture pour un contrat
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.amount = 0
|
|
|
|
|
self.add_header(contract)
|
|
|
|
|
self.add_title(contract)
|
|
|
|
|
self.add_prestations(contract)
|
|
|
|
|
self.add_conclusion(contract)
|
|
|
|
|
self.add_signature()
|
|
|
|
|
self.add_footer()
|
|
|
|
|
|
|
|
|
|
def add_title(self, contract):
|
|
|
|
|
""" Génère le "titre" de la facture.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
res = contract.client.contact.count("i")
|
|
|
|
|
res += contract.client.contact.count("t")
|
|
|
|
|
res += contract.client.contact.count("l")
|
|
|
|
|
res += contract.client.contact.count("j")
|
|
|
|
|
res += contract.client.contact.count("f")
|
|
|
|
|
# res += contract.client.contact.count('r')
|
|
|
|
|
res = len(re.findall(r'[fijlt]', contract.client.contact))
|
|
|
|
|
print(res)
|
|
|
|
|
|
|
|
|
|
self.add_string(TITLED_X, "A l'attention de")
|
|
|
|
|
self.add_string(194.25, contract.client.contact, font_decoration="Bold")
|
|
|
|
@ -193,25 +539,14 @@ class PDFDocument(object):
|
|
|
|
|
self.add_string(200, contract.name, font_decoration="Bold")
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_title_spf(self, accounting_year):
|
|
|
|
|
""" Ajoute un titre au document.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable.
|
|
|
|
|
"""
|
|
|
|
|
self.add_string(
|
|
|
|
|
130,
|
|
|
|
|
"Comptes simplifiés de l'exercice " + accounting_year,
|
|
|
|
|
font_decoration="Bold",
|
|
|
|
|
font_size=20,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace(DOUBLE_LINE_HEIGHT)
|
|
|
|
|
|
|
|
|
|
def add_payement_informations(self, contract):
|
|
|
|
|
""" Génère les informations de payement.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
height = 40
|
|
|
|
@ -243,6 +578,9 @@ class PDFDocument(object):
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "Prestations", font_decoration="Bold")
|
|
|
|
|
total = self.draw_prestations_table(contract.get_prestation.all())
|
|
|
|
@ -256,7 +594,7 @@ class PDFDocument(object):
|
|
|
|
|
self.amount = total - contract.advance
|
|
|
|
|
self.document.drawRightString(INDENTED_RIGHT_X, self.y, str(self.amount))
|
|
|
|
|
|
|
|
|
|
def draw_colored_row(self, c=0.43, m=0.2, y=0, k=0):
|
|
|
|
|
def draw_colored_row(self, c=1, m=0, y=0, k=0.1):
|
|
|
|
|
""" Génère une ligne colorée. """
|
|
|
|
|
self.document.setFillColorCMYK(c, y, m, k)
|
|
|
|
|
self.document.rect(
|
|
|
|
@ -282,6 +620,9 @@ class PDFDocument(object):
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
total (int): somme totale des prestations.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.draw_colored_row()
|
|
|
|
|
self.add_vspace()
|
|
|
|
@ -315,7 +656,10 @@ class PDFDocument(object):
|
|
|
|
|
""" Génère le tableau des prestations.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
prestations_list (list): liste des prestations d'un contrat
|
|
|
|
|
prestations_list (list): liste des prestations d'un contrat.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.draw_prestations_table_header()
|
|
|
|
|
total = 0
|
|
|
|
@ -329,6 +673,9 @@ class PDFDocument(object):
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
contract (contract): instance de la class Contract.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
ne retourne rien.
|
|
|
|
|
"""
|
|
|
|
|
self.add_vspace(DOUBLE_LINE_HEIGHT)
|
|
|
|
|
self.document.rect(X, self.y, RIGHT_X - X, BIG_LINE_HEIGHT, fill=0)
|
|
|
|
@ -387,314 +734,14 @@ class PDFDocument(object):
|
|
|
|
|
self.add_new_line(INDENTED_X, "Facture payable au comptant.")
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X,
|
|
|
|
|
"""En cas de défaut de paiement à l'échéance, il est dû de plein droit et sans mise en demeure, un interêt fixé au taux de""",
|
|
|
|
|
"""En cas de défaut de paiement à l'échéance, il est dû de plein droit et sans mise en demeure, un interêt fixé au taux de""", # NOQA
|
|
|
|
|
)
|
|
|
|
|
self.add_new_line(INDENTED_X, "15% l'an.")
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X,
|
|
|
|
|
"""Tout réclamation, pour être admise, doit être faite dans les huit jours de la réception de la facture.""",
|
|
|
|
|
"""Tout réclamation, pour être admise, doit être faite dans les huit jours de la réception de la facture.""", # NOQA
|
|
|
|
|
)
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X,
|
|
|
|
|
"""En cas de litige concernant la présente facture, seuls les tribunaux de MONS seront compétents.""",
|
|
|
|
|
"""En cas de litige concernant la présente facture, seuls les tribunaux de MONS seront compétents.""", # NOQA
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def add_recette_expenses(self, accounting_year):
|
|
|
|
|
""" Ajoute l'état des recettes et dépense pour une année comptable passée en paramètre.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
"""
|
|
|
|
|
self.add_string(
|
|
|
|
|
X, "Etat recettes/dépenses (en €)", font_decoration="Oblique", font_size=14
|
|
|
|
|
)
|
|
|
|
|
self.__display_transactiontypes_table(accounting_year)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def __display_transactiontypes_table(self, accounting_year):
|
|
|
|
|
""" Ajoute le table pour les recettes & dépenses d'une année comptable.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
"""
|
|
|
|
|
extenses = get_transactiontype_and_sum_for_spf_export(accounting_year, EXTENSES)
|
|
|
|
|
recettes = get_transactiontype_and_sum_for_spf_export(accounting_year, RECETTES)
|
|
|
|
|
|
|
|
|
|
self.__display_table_header("DEPENSES", "RECETTES")
|
|
|
|
|
self.__display_transactiontype_table_body(
|
|
|
|
|
extenses,
|
|
|
|
|
recettes,
|
|
|
|
|
int(extenses["sum_total_transaction"]),
|
|
|
|
|
int(recettes["sum_total_transaction"]),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_table_header(self, title_left, title_right):
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.document.rect(X, self.y - 5, RIGHT_X - X, -COMMON_LINE_HEIGHT, fill=0)
|
|
|
|
|
self.add_string(INDENTED_X, title_left, font_decoration="Bold", font_size=9)
|
|
|
|
|
self.add_string(
|
|
|
|
|
MIDDLE + INDENTED_X, title_right, font_decoration="Bold", font_size=9
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_transactiontype_table_body(
|
|
|
|
|
self, extenses, recettes, totalexpenses, totalrecettes
|
|
|
|
|
):
|
|
|
|
|
for i in range(4):
|
|
|
|
|
self.__display_table_line(
|
|
|
|
|
extenses["transaction_type_info"][i]["label"],
|
|
|
|
|
int(extenses["transaction_type_info"][i]["sum_total_amount"]),
|
|
|
|
|
recettes["transaction_type_info"][i]["label"],
|
|
|
|
|
int(recettes["transaction_type_info"][i]["sum_total_amount"]),
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.document.rect(
|
|
|
|
|
X, self.y - 5, MIDDLE, 5 * -COMMON_LINE_HEIGHT
|
|
|
|
|
) # Séparation en deux
|
|
|
|
|
self.document.rect(
|
|
|
|
|
MIDDLE, self.y - 5, MIDDLE, 5 * -COMMON_LINE_HEIGHT
|
|
|
|
|
) # Séparation descriptif et montant recettes
|
|
|
|
|
self.y -= COMMON_LINE_HEIGHT
|
|
|
|
|
self.__display_table_line(
|
|
|
|
|
"Total des dépenses",
|
|
|
|
|
totalexpenses,
|
|
|
|
|
"Total des recettes",
|
|
|
|
|
totalrecettes,
|
|
|
|
|
font_decoration="Bold",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_key_part(self, column_number, key, font_decoration=None):
|
|
|
|
|
""" Ajoute dans la colonne d'un tableau (à deux colonnes) la clef d'un couple clef/valeur.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
column_number (int): numéro de la colonne du tableau
|
|
|
|
|
key (str): la clef à afficher
|
|
|
|
|
font_decoration (str): décoration de la police de carectères
|
|
|
|
|
"""
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
space = INDENTED_X
|
|
|
|
|
else:
|
|
|
|
|
space = MIDDLE + INDENTED_X
|
|
|
|
|
self.add_string(space, key, font_decoration=font_decoration, font_size=9)
|
|
|
|
|
|
|
|
|
|
def __display_value_part(self, column_number, value):
|
|
|
|
|
""" Ajoute dans la colonne d'un tableau (à deux colonnes) la valeur d'un couple clef/valeur
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
column_number (int): numéro de la colonne du tableau
|
|
|
|
|
value (str): la valeur à afficher
|
|
|
|
|
"""
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
space = MIDDLE + X - INDENT
|
|
|
|
|
else:
|
|
|
|
|
space = INDENTED_RIGHT_X
|
|
|
|
|
|
|
|
|
|
self.document.drawRightString(
|
|
|
|
|
space, self.y, str(locale.format("%d", int(value), grouping=True)),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def __display_column(self, column_number, key, value, font_decoration):
|
|
|
|
|
self.__display_key_part(column_number, key, font_decoration)
|
|
|
|
|
self.__display_value_part(column_number, value)
|
|
|
|
|
|
|
|
|
|
def __display_table_line(self, key1, value1, key2, value2, font_decoration=None):
|
|
|
|
|
locale.setlocale(locale.LC_ALL, "pt_br.utf-8")
|
|
|
|
|
self.document.rect(X, self.y - 5, RIGHT_X - X, COMMON_LINE_HEIGHT, fill=0)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
self.__display_column(1, key1, value1, font_decoration)
|
|
|
|
|
self.__display_column(2, key2, value2, font_decoration)
|
|
|
|
|
|
|
|
|
|
def add_annexes(self, accounting_year):
|
|
|
|
|
""" Ajoute les annexes au document PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "Annexes", font_decoration="Oblique", font_size=14)
|
|
|
|
|
self.add_evaluation_rules(accounting_year)
|
|
|
|
|
self.add_modification_evaluation_rules(accounting_year)
|
|
|
|
|
self.add_additional_information(accounting_year)
|
|
|
|
|
self.add_patrimony(accounting_year)
|
|
|
|
|
self.add_right_engagement(accounting_year)
|
|
|
|
|
|
|
|
|
|
def add_evaluation_rules(self, accounting_year):
|
|
|
|
|
""" Ajoute les règles d'évaluation au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "1. Résumé des règles d'évaluation")
|
|
|
|
|
rules_list = EvaluationRules.objects.filter(
|
|
|
|
|
Q(stop_date__year__lte=accounting_year) | Q(stop_date__isnull=True)
|
|
|
|
|
).exclude(start_date__year__gt=accounting_year)
|
|
|
|
|
if rules_list:
|
|
|
|
|
for rule in rules_list:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
rule.label + " : " + rule.explanation,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2, "Pas de règle d'évaluation.", font_size=9
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_modification_evaluation_rules(self, accounting_year):
|
|
|
|
|
""" Ajoute les modifications d'évaluation au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "2. Adaptation des règles d'évaluation")
|
|
|
|
|
rules_adaptation_list = EvaluationRulesAdaptation.objects.filter(
|
|
|
|
|
start_date__year=accounting_year
|
|
|
|
|
)
|
|
|
|
|
if rules_adaptation_list:
|
|
|
|
|
for line in rules_adaptation_list:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
line.label + " : " + line.information,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
"Pas d'adaptation des règles d'évaluation.",
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_additional_information(self, accounting_year):
|
|
|
|
|
""" Ajoute les informations complémentaires au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "3. Informations complémentaires")
|
|
|
|
|
annuality = Annuality.objects.filter(year__year=accounting_year)
|
|
|
|
|
complementary_informations = ComplementaryInformations.objects.filter(
|
|
|
|
|
annuality=annuality[0]
|
|
|
|
|
)
|
|
|
|
|
if complementary_informations:
|
|
|
|
|
for line in complementary_informations:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
line.label + " : " + line.information,
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2,
|
|
|
|
|
"Pas d'informations complémentaires.",
|
|
|
|
|
font_size=9,
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def add_patrimony(self, accounting_year):
|
|
|
|
|
""" Ajoute les informations du patrimoine au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(X, "4. Etat du patrimoine")
|
|
|
|
|
|
|
|
|
|
annuality = Annuality.objects.filter(year__year=accounting_year)
|
|
|
|
|
tmp_compta_extenses = get_transactiontype_and_sum_for_spf_export(
|
|
|
|
|
accounting_year, EXTENSES
|
|
|
|
|
)
|
|
|
|
|
tmp_compta_recettes = get_transactiontype_and_sum_for_spf_export(
|
|
|
|
|
accounting_year, RECETTES
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
assets_list = get_asset_liability_and_sump_spf(accounting_year, category=0)
|
|
|
|
|
for item in assets_list:
|
|
|
|
|
if item[0] == "Liquidité":
|
|
|
|
|
item[1] += (
|
|
|
|
|
annuality[0].opening_balance
|
|
|
|
|
+ tmp_compta_recettes["sum_total_transaction"]
|
|
|
|
|
- tmp_compta_extenses["sum_total_transaction"]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
liability_list = get_asset_liability_and_sump_spf(accounting_year, category=1)
|
|
|
|
|
|
|
|
|
|
self.__display_table_header("AVOIRS", "DETTES")
|
|
|
|
|
save = self.y
|
|
|
|
|
self.__display_table_two_column(1, assets_list)
|
|
|
|
|
longest_y = self.y
|
|
|
|
|
self.y = save
|
|
|
|
|
self.__display_table_two_column(2, liability_list)
|
|
|
|
|
|
|
|
|
|
if self.y > longest_y:
|
|
|
|
|
self.y = longest_y
|
|
|
|
|
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def __display_table_two_column(self, column_number, list):
|
|
|
|
|
if column_number == 1:
|
|
|
|
|
begin_rect_line = X
|
|
|
|
|
begin_rect_res = MIDDLE
|
|
|
|
|
begin_text = INDENTED_X
|
|
|
|
|
begin_res = MIDDLE + X - INDENT
|
|
|
|
|
else:
|
|
|
|
|
begin_rect_line = MIDDLE + X
|
|
|
|
|
begin_rect_res = MIDDLE * 2
|
|
|
|
|
begin_text = MIDDLE + INDENTED_X
|
|
|
|
|
begin_res = INDENTED_RIGHT_X
|
|
|
|
|
|
|
|
|
|
total = 0
|
|
|
|
|
locale.setlocale(locale.LC_ALL, "pt_br.utf-8")
|
|
|
|
|
|
|
|
|
|
for line in list:
|
|
|
|
|
self.document.rect(
|
|
|
|
|
begin_rect_line, self.y - 5, MIDDLE, COMMON_LINE_HEIGHT, fill=0
|
|
|
|
|
)
|
|
|
|
|
self.document.rect(
|
|
|
|
|
begin_rect_res, self.y - 5, X, COMMON_LINE_HEIGHT, fill=0
|
|
|
|
|
)
|
|
|
|
|
self.add_new_line(begin_text, line[0], font_size=9)
|
|
|
|
|
self.document.drawRightString(
|
|
|
|
|
begin_res, self.y, str(locale.format("%d", int(line[1]), grouping=True))
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
total += int(line[1])
|
|
|
|
|
|
|
|
|
|
return total
|
|
|
|
|
|
|
|
|
|
def add_right_engagement(self, accounting_year):
|
|
|
|
|
""" Ajoute les droits & engagements au PDF
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
accounting_year (int): année comptable
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Ne retourne rien
|
|
|
|
|
"""
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
X,
|
|
|
|
|
"5. Droits et engagements importants qui ne sont pas susceptibles d'être quantifiés",
|
|
|
|
|
)
|
|
|
|
|
# self.__display_table_header("DROITS", "ENGAGEMENT")
|
|
|
|
|
self.add_new_line(
|
|
|
|
|
INDENTED_X + INDENT * 2, "Pas de droits ou d'engagements.", font_size=9
|
|
|
|
|
)
|
|
|
|
|
self.add_vspace()
|
|
|
|
|
|
|
|
|
|
def download(self):
|
|
|
|
|
# Close the PDF object cleanly, and we're done.
|
|
|
|
|
self.document.showPage()
|
|
|
|
|
self.document.save()
|
|
|
|
|