File size: 15,927 Bytes
2e25654
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9dfbdce
2e25654
 
 
 
 
7d548ba
9dfbdce
 
 
7d548ba
 
e4c8441
2e25654
 
 
7d548ba
 
 
e4c8441
2e25654
5e029bf
 
7d548ba
 
 
e4c8441
2e25654
 
 
7d548ba
 
 
e4c8441
2e25654
 
7d548ba
 
 
e4c8441
5e029bf
 
7d548ba
2e25654
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7d548ba
5e029bf
2e25654
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
7d548ba
5e029bf
 
 
 
 
 
2e25654
 
 
 
 
 
 
5e029bf
 
 
 
 
 
 
7d548ba
5e029bf
9dfbdce
7d548ba
5e029bf
7d548ba
5e029bf
2e25654
 
 
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
 
 
5e029bf
 
 
 
 
 
 
 
 
 
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
 
 
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
 
5e029bf
 
 
 
 
 
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
5e029bf
 
 
 
2e25654
5e029bf
 
2e25654
5e029bf
 
7d548ba
5e029bf
 
7d548ba
5e029bf
7d548ba
2e25654
 
5e029bf
 
2e25654
5e029bf
 
2e25654
7d548ba
2e25654
 
5e029bf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
"""
Module pour la construction des contrats à partir des templates.
"""
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
from reportlab.platypus import Paragraph, Spacer

from contract_templates import ContractTemplates
from utils import ensure_default_supports, sanitize_text


class ContractBuilder:
    """
    Classe responsable de la construction des contrats complets à partir des templates.
    """
    
    @staticmethod
    def get_styles():
        """
        Retourne les styles pour le document PDF.
        Version corrigée pour éviter les conflits de styles.
        
        Returns:
            dict: Dictionnaire des styles
        """
        styles = getSampleStyleSheet()
        
        # Modifier les styles existants plutôt que d'en ajouter de nouveaux
        # ou utiliser des noms différents pour éviter les conflits
        
        # Ajouter un style personnalisé pour le titre
        styles.add(ParagraphStyle(name='ContractTitle', 
                                 fontName='VeraBd', 
                                 fontSize=14, 
                                 alignment=TA_CENTER,
                                 spaceAfter=12))
        
        # Ajouter un style personnalisé pour les sous-titres
        styles.add(ParagraphStyle(name='ContractSubtitle', 
                                 fontName='VeraBd', 
                                 fontSize=12, 
                                 spaceAfter=10,
                                 alignment=TA_CENTER))
        
        # Ajouter un style personnalisé pour le texte normal
        styles.add(ParagraphStyle(name='ContractText', 
                                 fontName='Vera', 
                                 fontSize=10, 
                                 alignment=TA_JUSTIFY,
                                 spaceAfter=6))
        
        # Ajouter un style personnalisé pour les articles
        styles.add(ParagraphStyle(name='ContractArticle', 
                                 fontName='VeraBd', 
                                 fontSize=11, 
                                 spaceAfter=8))
        
        # Ajouter un style personnalisé pour les sous-articles
        styles.add(ParagraphStyle(name='ContractSubArticle', 
                                 fontName='VeraBd', 
                                 fontSize=10, 
                                 spaceAfter=6))
        
        return styles
    
    @staticmethod
    def build_contract_elements(contract_type, is_free, author_type, author_info, 
                               work_description, image_description, supports, 
                               additional_rights, remuneration, is_exclusive):
        """
        Construit tous les éléments du contrat.
        
        Args:
            contract_type (list): Liste des types de contrats sélectionnés
            is_free (bool): True si la cession est gratuite, False sinon
            author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
            author_info (dict): Informations sur l'auteur
            work_description (str): Description de l'œuvre
            image_description (str): Description de l'image
            supports (list): Liste des supports sélectionnés
            additional_rights (list): Liste des droits supplémentaires sélectionnés
            remuneration (str): Modalités de rémunération
            is_exclusive (bool): True si la cession est exclusive, False sinon
            
        Returns:
            list: Liste des éléments du contrat pour ReportLab
        """
        # Obtenir les styles
        styles = ContractBuilder.get_styles()
        
        # Initialiser la liste des éléments
        elements = []
        
        # 1. Titre du contrat
        title = ContractTemplates.get_title(contract_type)
        elements.append(Paragraph(title, styles['ContractTitle']))
        elements.append(Spacer(1, 15))
        
        # 2. Préambule
        preamble_text = ContractTemplates.get_preamble_text(contract_type, author_type, author_info)
        paragraphs = preamble_text.split('\n\n')
        for i, paragraph in enumerate(paragraphs):
            if paragraph.strip():
                # Si c'est un titre comme "PRÉAMBULE" ou "ENTRE LES SOUSSIGNÉS"
                if paragraph.isupper() and len(paragraph) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubtitle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                
                # Ajouter un espace plus grand après les titres
                if paragraph.isupper() and len(paragraph) < 50:
                    elements.append(Spacer(1, 10))
                else:
                    elements.append(Spacer(1, 6))
        
        # 3. Article 1 - Objet
        object_clause = ContractTemplates.get_object_clause(
            contract_type, 
            sanitize_text(work_description), 
            sanitize_text(image_description)
        )
        
        # Traitement de l'article objet
        paragraphs = object_clause.split('\n\n')
        for i, paragraph in enumerate(paragraphs):
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "1.1 Œuvre concernée")
                elif paragraph.strip().startswith("1.") and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        
        # Compteur d'articles
        article_num = 2
        
        # 4. Article 2 - Droits cédés (pour contrat droits d'auteur)
        if "Auteur (droits d'auteur)" in contract_type:
            rights_clause = ContractTemplates.get_author_rights_clause(is_free, is_exclusive, additional_rights)
            paragraphs = rights_clause.split('\n\n')
            for paragraph in paragraphs:
                if paragraph.strip():
                    # Si c'est un titre d'article (commence par "ARTICLE")
                    if paragraph.startswith("ARTICLE"):
                        elements.append(Paragraph(paragraph, styles['ContractArticle']))
                    # Si c'est un sous-titre (comme "2.1 Nature de la cession")
                    elif paragraph.strip().startswith("2.") and len(paragraph.split("\n")[0]) < 50:
                        elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                    else:
                        elements.append(Paragraph(paragraph, styles['ContractText']))
                    elements.append(Spacer(1, 6))
            article_num += 1
        
        # 5. Article sur les droits à l'image (pour contrat droit à l'image)
        if "Image (droit à l'image)" in contract_type:
            image_rights_article_num = article_num if "Auteur (droits d'auteur)" not in contract_type else article_num
            image_clause = ContractTemplates.get_image_rights_clause(is_free, is_exclusive)
            # Remplacer le numéro d'article si nécessaire
            if image_rights_article_num != 3:
                image_clause = image_clause.replace("ARTICLE 3", f"ARTICLE {image_rights_article_num}")
                # Aussi remplacer les sous-titres 3.x par le bon numéro
                image_clause = image_clause.replace("3.1", f"{image_rights_article_num}.1")
                image_clause = image_clause.replace("3.2", f"{image_rights_article_num}.2")
                image_clause = image_clause.replace("3.3", f"{image_rights_article_num}.3")
                image_clause = image_clause.replace("3.4", f"{image_rights_article_num}.4")
            
            paragraphs = image_clause.split('\n\n')
            for paragraph in paragraphs:
                if paragraph.strip():
                    # Si c'est un titre d'article (commence par "ARTICLE")
                    if paragraph.startswith("ARTICLE"):
                        elements.append(Paragraph(paragraph, styles['ContractArticle']))
                    # Si c'est un sous-titre (comme "3.1 Objet de l'autorisation")
                    elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                        elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                    else:
                        elements.append(Paragraph(paragraph, styles['ContractText']))
                    elements.append(Spacer(1, 6))
            article_num += 1
        
        # 6. Article - Durée et territoire
        duration_clause = ContractTemplates.get_duration_territory_clause(article_num)
        paragraphs = duration_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "4.1 Durée")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 7. Article - Supports d'exploitation
        final_supports = ensure_default_supports(supports)
        supports_clause = ContractTemplates.get_supports_clause(article_num, final_supports)
        paragraphs = supports_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "5.1 Supports autorisés")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 8. Article - Rémunération
        remuneration_clause = ContractTemplates.get_remuneration_clause(article_num, is_free, sanitize_text(remuneration))
        paragraphs = remuneration_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "6.1 Cession à titre gratuit")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 9. Article - Garanties
        warranties_clause = ContractTemplates.get_warranties_clause(article_num, contract_type)
        paragraphs = warranties_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "7.1 Garanties de l'Auteur")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 10. Article - Résiliation
        termination_clause = ContractTemplates.get_termination_clause(article_num)
        paragraphs = termination_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "8.1 Résiliation pour inexécution")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 11. Article - Dispositions diverses
        other_clauses = ContractTemplates.get_other_clauses(article_num, contract_type)
        paragraphs = other_clauses.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "9.1 Clause de non-dénigrement")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        article_num += 1
        
        # 12. Article - Loi applicable
        law_clause = ContractTemplates.get_applicable_law_clause(article_num)
        paragraphs = law_clause.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                # Si c'est un titre d'article (commence par "ARTICLE")
                if paragraph.startswith("ARTICLE"):
                    elements.append(Paragraph(paragraph, styles['ContractArticle']))
                # Si c'est un sous-titre (comme "10.1 Loi applicable")
                elif paragraph.strip()[0].isdigit() and "." in paragraph.strip()[:3] and len(paragraph.split("\n")[0]) < 50:
                    elements.append(Paragraph(paragraph, styles['ContractSubArticle']))
                else:
                    elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 6))
        
        # 13. Signatures
        elements.append(Spacer(1, 30))
        signatures = ContractTemplates.get_signatures_template(contract_type)
        paragraphs = signatures.split('\n\n')
        for paragraph in paragraphs:
            if paragraph.strip():
                elements.append(Paragraph(paragraph, styles['ContractText']))
                elements.append(Spacer(1, 8))
        
        return elements