Upload 10 files
Browse files- app.py +19 -0
- config.py +84 -0
- contract_builder.py +174 -0
- contract_previewer.py +173 -0
- contract_templates.py +423 -0
- interface.py +359 -0
- pdf_generator-py.py +165 -0
- readme.md +84 -0
- requirements.txt +2 -0
- utils.py +122 -0
app.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from interface import create_interface
|
3 |
+
from pdf_generator import generate_pdf
|
4 |
+
from contract_previewer import preview_contract
|
5 |
+
|
6 |
+
# Point d'entrée principal de l'application
|
7 |
+
def main():
|
8 |
+
"""
|
9 |
+
Point d'entrée principal de l'application.
|
10 |
+
Crée l'interface Gradio et lance l'application.
|
11 |
+
"""
|
12 |
+
# Création de l'interface Gradio avec injection des fonctions de génération et prévisualisation
|
13 |
+
demo = create_interface(generate_pdf, preview_contract)
|
14 |
+
|
15 |
+
# Lancement de l'application
|
16 |
+
demo.launch()
|
17 |
+
|
18 |
+
if __name__ == "__main__":
|
19 |
+
main()
|
config.py
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Fichier de configuration contenant les constantes et paramètres utilisés dans l'application.
|
3 |
+
"""
|
4 |
+
|
5 |
+
# Informations sur le cessionnaire (Tellers)
|
6 |
+
TELLERS_INFO = {
|
7 |
+
"nom": "Tellers",
|
8 |
+
"forme_juridique": "société par actions simplifiée unipersonnelle",
|
9 |
+
"capital": "1000 €",
|
10 |
+
"rcs": "932 553 266 R.C.S. Lyon",
|
11 |
+
"siege": "12 RUE DE LA PART-DIEU, 69003 LYON"
|
12 |
+
}
|
13 |
+
|
14 |
+
# Options pour les différents types de contrats
|
15 |
+
CONTRACT_TYPES = [
|
16 |
+
"Auteur (droits d'auteur)",
|
17 |
+
"Image (droit à l'image)"
|
18 |
+
]
|
19 |
+
|
20 |
+
# Options pour le mode de cession
|
21 |
+
CESSION_MODES = [
|
22 |
+
"Gratuite",
|
23 |
+
"Onéreuse"
|
24 |
+
]
|
25 |
+
|
26 |
+
# Options pour les droits supplémentaires (cession onéreuse uniquement)
|
27 |
+
ADDITIONAL_RIGHTS = [
|
28 |
+
"distribution - droit de distribuer l'original ou les copies de l'œuvre au public",
|
29 |
+
"usage - droit d'utiliser l'œuvre pour les besoins du cessionnaire",
|
30 |
+
"adaptation - droit de modifier, transformer, traduire l'œuvre",
|
31 |
+
"pret - droit de mettre l'œuvre à disposition pour un usage temporaire",
|
32 |
+
"location - droit de mettre l'œuvre à disposition contre rémunération",
|
33 |
+
"suite - droit de percevoir un pourcentage lors de reventes (œuvres graphiques/plastiques uniquement)"
|
34 |
+
]
|
35 |
+
|
36 |
+
# Options pour le type d'auteur
|
37 |
+
AUTHOR_TYPES = [
|
38 |
+
"Personne physique",
|
39 |
+
"Personne morale"
|
40 |
+
]
|
41 |
+
|
42 |
+
# Options pour la civilité
|
43 |
+
CIVILITY_OPTIONS = [
|
44 |
+
"M.",
|
45 |
+
"Mme"
|
46 |
+
]
|
47 |
+
|
48 |
+
# Options pour les supports d'exploitation
|
49 |
+
SUPPORTS_OPTIONS = [
|
50 |
+
"Réseaux sociaux (Facebook, Instagram, Twitter, etc.)",
|
51 |
+
"Applications mobiles",
|
52 |
+
"Plateformes de diffusion vidéo (YouTube, Twitch, etc.)",
|
53 |
+
"Supports imprimés (catalogues, flyers, affiches)",
|
54 |
+
"Présentations lors d'événements",
|
55 |
+
"Publicités en ligne",
|
56 |
+
"Plateformes tierces (marketplaces, sites partenaires)",
|
57 |
+
"Emails et newsletters"
|
58 |
+
]
|
59 |
+
|
60 |
+
# Supports toujours inclus (obligatoires)
|
61 |
+
DEFAULT_SUPPORTS = [
|
62 |
+
"site web",
|
63 |
+
"Discord"
|
64 |
+
]
|
65 |
+
|
66 |
+
# Paramètres PDF
|
67 |
+
PDF_CONFIG = {
|
68 |
+
"page_size": "A4",
|
69 |
+
"margin_right": 25, # mm
|
70 |
+
"margin_left": 25, # mm
|
71 |
+
"margin_top": 20, # mm
|
72 |
+
"margin_bottom": 20, # mm
|
73 |
+
"font_main": "Helvetica",
|
74 |
+
"font_bold": "Helvetica-Bold",
|
75 |
+
"font_size_title": 14,
|
76 |
+
"font_size_subtitle": 12,
|
77 |
+
"font_size_normal": 10,
|
78 |
+
"font_size_article": 11
|
79 |
+
}
|
80 |
+
|
81 |
+
# Durée et territoire par défaut
|
82 |
+
DEFAULT_DURATION = "un (1) an"
|
83 |
+
DEFAULT_RENEWAL = "renouvellement par tacite reconduction pour des périodes successives d'un (1) an"
|
84 |
+
DEFAULT_TERRITORY = "monde entier"
|
contract_builder.py
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Module pour la construction des contrats à partir des templates.
|
3 |
+
"""
|
4 |
+
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
5 |
+
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
|
6 |
+
from reportlab.platypus import Paragraph, Spacer
|
7 |
+
|
8 |
+
from contract_templates import ContractTemplates
|
9 |
+
from utils import ensure_default_supports, sanitize_text
|
10 |
+
|
11 |
+
|
12 |
+
class ContractBuilder:
|
13 |
+
"""
|
14 |
+
Classe responsable de la construction des contrats complets à partir des templates.
|
15 |
+
"""
|
16 |
+
|
17 |
+
@staticmethod
|
18 |
+
def get_styles():
|
19 |
+
"""
|
20 |
+
Retourne les styles pour le document PDF.
|
21 |
+
|
22 |
+
Returns:
|
23 |
+
dict: Dictionnaire des styles
|
24 |
+
"""
|
25 |
+
styles = getSampleStyleSheet()
|
26 |
+
styles.add(ParagraphStyle(name='Titre',
|
27 |
+
fontName='Helvetica-Bold',
|
28 |
+
fontSize=14,
|
29 |
+
alignment=TA_CENTER,
|
30 |
+
spaceAfter=12))
|
31 |
+
styles.add(ParagraphStyle(name='Sous-titre',
|
32 |
+
fontName='Helvetica-Bold',
|
33 |
+
fontSize=12,
|
34 |
+
spaceAfter=10))
|
35 |
+
styles.add(ParagraphStyle(name='Normal',
|
36 |
+
fontName='Helvetica',
|
37 |
+
fontSize=10,
|
38 |
+
alignment=TA_JUSTIFY,
|
39 |
+
spaceAfter=6))
|
40 |
+
styles.add(ParagraphStyle(name='Article',
|
41 |
+
fontName='Helvetica-Bold',
|
42 |
+
fontSize=11,
|
43 |
+
spaceAfter=8))
|
44 |
+
return styles
|
45 |
+
|
46 |
+
@staticmethod
|
47 |
+
def build_contract_elements(contract_type, is_free, author_type, author_info,
|
48 |
+
work_description, image_description, supports,
|
49 |
+
additional_rights, remuneration, is_exclusive):
|
50 |
+
"""
|
51 |
+
Construit tous les éléments du contrat.
|
52 |
+
|
53 |
+
Args:
|
54 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
55 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
56 |
+
author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
|
57 |
+
author_info (dict): Informations sur l'auteur
|
58 |
+
work_description (str): Description de l'œuvre
|
59 |
+
image_description (str): Description de l'image
|
60 |
+
supports (list): Liste des supports sélectionnés
|
61 |
+
additional_rights (list): Liste des droits supplémentaires sélectionnés
|
62 |
+
remuneration (str): Modalités de rémunération
|
63 |
+
is_exclusive (bool): True si la cession est exclusive, False sinon
|
64 |
+
|
65 |
+
Returns:
|
66 |
+
list: Liste des éléments du contrat pour ReportLab
|
67 |
+
"""
|
68 |
+
# Obtenir les styles
|
69 |
+
styles = ContractBuilder.get_styles()
|
70 |
+
|
71 |
+
# Initialiser la liste des éléments
|
72 |
+
elements = []
|
73 |
+
|
74 |
+
# 1. Titre du contrat
|
75 |
+
title = ContractTemplates.get_title(contract_type)
|
76 |
+
elements.append(Paragraph(title, styles['Titre']))
|
77 |
+
elements.append(Spacer(1, 10))
|
78 |
+
|
79 |
+
# 2. Préambule
|
80 |
+
preamble_text = ContractTemplates.get_preamble_text(contract_type, author_type, author_info)
|
81 |
+
for paragraph in preamble_text.split('\n\n'):
|
82 |
+
if paragraph.strip():
|
83 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
84 |
+
elements.append(Spacer(1, 6))
|
85 |
+
|
86 |
+
# 3. Article 1 - Objet
|
87 |
+
object_clause = ContractTemplates.get_object_clause(
|
88 |
+
contract_type,
|
89 |
+
sanitize_text(work_description),
|
90 |
+
sanitize_text(image_description)
|
91 |
+
)
|
92 |
+
elements.append(Paragraph(object_clause, styles['Article']))
|
93 |
+
elements.append(Spacer(1, 10))
|
94 |
+
|
95 |
+
# Compteur d'articles
|
96 |
+
article_num = 2
|
97 |
+
|
98 |
+
# 4. Article 2 - Droits cédés (pour contrat droits d'auteur)
|
99 |
+
if "Auteur (droits d'auteur)" in contract_type:
|
100 |
+
rights_clause = ContractTemplates.get_author_rights_clause(is_free, is_exclusive, additional_rights)
|
101 |
+
for paragraph in rights_clause.split('\n\n'):
|
102 |
+
if paragraph.strip():
|
103 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
104 |
+
elements.append(Spacer(1, 6))
|
105 |
+
article_num += 1
|
106 |
+
|
107 |
+
# 5. Article sur les droits à l'image (pour contrat droit à l'image)
|
108 |
+
if "Image (droit à l'image)" in contract_type:
|
109 |
+
image_rights_article_num = article_num if "Auteur (droits d'auteur)" not in contract_type else article_num
|
110 |
+
image_clause = ContractTemplates.get_image_rights_clause(is_free, is_exclusive)
|
111 |
+
image_clause = image_clause.replace("Article 2", f"Article {image_rights_article_num}")
|
112 |
+
for paragraph in image_clause.split('\n\n'):
|
113 |
+
if paragraph.strip():
|
114 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
115 |
+
elements.append(Spacer(1, 6))
|
116 |
+
article_num += 1
|
117 |
+
|
118 |
+
# 6. Article - Durée et territoire
|
119 |
+
duration_clause = ContractTemplates.get_duration_territory_clause(article_num)
|
120 |
+
for paragraph in duration_clause.split('\n\n'):
|
121 |
+
if paragraph.strip():
|
122 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
123 |
+
elements.append(Spacer(1, 6))
|
124 |
+
article_num += 1
|
125 |
+
|
126 |
+
# 7. Article - Supports d'exploitation
|
127 |
+
final_supports = ensure_default_supports(supports)
|
128 |
+
supports_clause = ContractTemplates.get_supports_clause(article_num, final_supports)
|
129 |
+
for paragraph in supports_clause.split('\n\n'):
|
130 |
+
if paragraph.strip():
|
131 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
132 |
+
elements.append(Spacer(1, 6))
|
133 |
+
article_num += 1
|
134 |
+
|
135 |
+
# 8. Article - Rémunération
|
136 |
+
remuneration_clause = ContractTemplates.get_remuneration_clause(article_num, is_free, sanitize_text(remuneration))
|
137 |
+
for paragraph in remuneration_clause.split('\n\n'):
|
138 |
+
if paragraph.strip():
|
139 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
140 |
+
elements.append(Spacer(1, 6))
|
141 |
+
article_num += 1
|
142 |
+
|
143 |
+
# 9. Article - Garanties
|
144 |
+
warranties_clause = ContractTemplates.get_warranties_clause(article_num, contract_type)
|
145 |
+
for paragraph in warranties_clause.split('\n\n'):
|
146 |
+
if paragraph.strip():
|
147 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
148 |
+
elements.append(Spacer(1, 6))
|
149 |
+
article_num += 1
|
150 |
+
|
151 |
+
# 10. Article - Résiliation
|
152 |
+
termination_clause = ContractTemplates.get_termination_clause(article_num)
|
153 |
+
for paragraph in termination_clause.split('\n\n'):
|
154 |
+
if paragraph.strip():
|
155 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
156 |
+
elements.append(Spacer(1, 6))
|
157 |
+
article_num += 1
|
158 |
+
|
159 |
+
# 11. Article - Loi applicable
|
160 |
+
law_clause = ContractTemplates.get_applicable_law_clause(article_num)
|
161 |
+
for paragraph in law_clause.split('\n\n'):
|
162 |
+
if paragraph.strip():
|
163 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
164 |
+
elements.append(Spacer(1, 6))
|
165 |
+
|
166 |
+
# 12. Signatures
|
167 |
+
elements.append(Spacer(1, 20))
|
168 |
+
signatures = ContractTemplates.get_signatures_template(contract_type)
|
169 |
+
for paragraph in signatures.split('\n\n'):
|
170 |
+
if paragraph.strip():
|
171 |
+
elements.append(Paragraph(paragraph, styles['Normal']))
|
172 |
+
elements.append(Spacer(1, 8))
|
173 |
+
|
174 |
+
return elements
|
contract_previewer.py
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Module pour la prévisualisation des contrats avant génération du PDF.
|
3 |
+
"""
|
4 |
+
from contract_templates import ContractTemplates
|
5 |
+
from utils import ensure_default_supports, sanitize_text
|
6 |
+
|
7 |
+
|
8 |
+
def preview_contract(contract_type, is_free, author_type, author_info,
|
9 |
+
work_description, image_description, supports,
|
10 |
+
additional_rights, remuneration, is_exclusive):
|
11 |
+
"""
|
12 |
+
Génère un aperçu du contrat sous forme de texte.
|
13 |
+
|
14 |
+
Args:
|
15 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
16 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
17 |
+
author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
|
18 |
+
author_info (dict): Informations sur l'auteur
|
19 |
+
work_description (str): Description de l'œuvre
|
20 |
+
image_description (str): Description de l'image
|
21 |
+
supports (list): Liste des supports sélectionnés
|
22 |
+
additional_rights (list): Liste des droits supplémentaires sélectionnés
|
23 |
+
remuneration (str): Modalités de rémunération
|
24 |
+
is_exclusive (bool): True si la cession est exclusive, False sinon
|
25 |
+
|
26 |
+
Returns:
|
27 |
+
str: Aperçu du contrat
|
28 |
+
"""
|
29 |
+
is_free = (is_free == "Gratuite")
|
30 |
+
|
31 |
+
# Ajouter les supports par défaut
|
32 |
+
final_supports = ensure_default_supports(supports)
|
33 |
+
|
34 |
+
# Initialiser l'aperçu avec le titre
|
35 |
+
apercu = ContractTemplates.get_title(contract_type) + "\n\n"
|
36 |
+
|
37 |
+
# Ajouter le préambule
|
38 |
+
apercu += ContractTemplates.get_preamble_text(contract_type, author_type, author_info)
|
39 |
+
|
40 |
+
# Article 1 - Objet
|
41 |
+
apercu += "Article 1 – OBJET\n"
|
42 |
+
if "Auteur (droits d'auteur)" in contract_type:
|
43 |
+
apercu += f"L'Auteur déclare être le créateur et titulaire exclusif des droits d'auteur sur l'œuvre suivante : {sanitize_text(work_description)}.\n"
|
44 |
+
|
45 |
+
if "Image (droit à l'image)" in contract_type:
|
46 |
+
apercu += f"Le Modèle autorise l'utilisation et l'exploitation de son image telle qu'elle apparaît dans les photographies/vidéos suivantes : {sanitize_text(image_description)}.\n"
|
47 |
+
|
48 |
+
apercu += "Par le présent contrat, "
|
49 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
50 |
+
apercu += "l'Auteur cède au Cessionnaire certains droits sur son œuvre, et le Modèle autorise l'exploitation de son image, dans les conditions définies ci-après.\n\n"
|
51 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
52 |
+
apercu += "l'Auteur cède au Cessionnaire certains droits sur son œuvre dans les conditions définies ci-après.\n\n"
|
53 |
+
else:
|
54 |
+
apercu += "le Modèle autorise l'exploitation de son image dans les conditions définies ci-après.\n\n"
|
55 |
+
|
56 |
+
# Compteur d'articles
|
57 |
+
article_num = 2
|
58 |
+
|
59 |
+
# Article 2 - Droits cédés pour l'Auteur
|
60 |
+
if "Auteur (droits d'auteur)" in contract_type:
|
61 |
+
apercu += "Article 2 – ÉTENDUE DES DROITS CÉDÉS\n"
|
62 |
+
apercu += "L'Auteur cède au Cessionnaire, "
|
63 |
+
|
64 |
+
if is_exclusive:
|
65 |
+
apercu += "à titre exclusif, "
|
66 |
+
else:
|
67 |
+
apercu += "à titre non exclusif, "
|
68 |
+
|
69 |
+
if is_free:
|
70 |
+
apercu += "gratuitement et pour la durée précisée à l'article 3, les droits patrimoniaux suivants :\n\n"
|
71 |
+
apercu += "- Le droit de reproduction\n"
|
72 |
+
apercu += "- Le droit de représentation\n\n"
|
73 |
+
else:
|
74 |
+
apercu += "pour la durée précisée à l'article 3 et moyennant la rémunération précisée à l'article approprié, les droits patrimoniaux suivants :\n\n"
|
75 |
+
|
76 |
+
# Droits de base
|
77 |
+
apercu += "- Le droit de reproduction\n"
|
78 |
+
apercu += "- Le droit de représentation\n"
|
79 |
+
|
80 |
+
# Droits supplémentaires pour les cessions onéreuses
|
81 |
+
if "distribution" in additional_rights:
|
82 |
+
apercu += "- Le droit de distribution\n"
|
83 |
+
|
84 |
+
if "usage" in additional_rights:
|
85 |
+
apercu += "- Le droit d'usage\n"
|
86 |
+
|
87 |
+
if "adaptation" in additional_rights:
|
88 |
+
apercu += "- Le droit d'adaptation\n"
|
89 |
+
|
90 |
+
if "pret" in additional_rights:
|
91 |
+
apercu += "- Le droit de prêt\n"
|
92 |
+
|
93 |
+
if "location" in additional_rights:
|
94 |
+
apercu += "- Le droit de location\n"
|
95 |
+
|
96 |
+
if "suite" in additional_rights:
|
97 |
+
apercu += "- Le droit de suite (pour œuvres graphiques et plastiques)\n"
|
98 |
+
|
99 |
+
apercu += "\n"
|
100 |
+
|
101 |
+
# Clause d'exclusivité
|
102 |
+
if is_exclusive:
|
103 |
+
apercu += "Pendant la durée de la présente cession, l'Auteur s'engage à ne pas céder les mêmes droits à des tiers et à ne pas exploiter lui-même l'œuvre selon les modalités cédées au Cessionnaire.\n\n"
|
104 |
+
else:
|
105 |
+
apercu += "La présente cession étant non exclusive, l'Auteur conserve le droit d'exploiter l'œuvre et de céder les mêmes droits à des tiers.\n\n"
|
106 |
+
|
107 |
+
article_num += 1
|
108 |
+
|
109 |
+
# Article pour les droits à l'image
|
110 |
+
if "Image (droit à l'image)" in contract_type:
|
111 |
+
image_article_num = article_num if "Auteur (droits d'auteur)" in contract_type else 2
|
112 |
+
apercu += f"Article {image_article_num} – AUTORISATION D'EXPLOITATION DE L'IMAGE\n"
|
113 |
+
|
114 |
+
apercu += "Le Modèle autorise le Cessionnaire à fixer, reproduire et communiquer au public son image. "
|
115 |
+
apercu += "Cette autorisation est consentie "
|
116 |
+
|
117 |
+
if is_exclusive:
|
118 |
+
apercu += "à titre exclusif, "
|
119 |
+
else:
|
120 |
+
apercu += "à titre non exclusif, "
|
121 |
+
|
122 |
+
if is_free:
|
123 |
+
apercu += "gratuitement, "
|
124 |
+
else:
|
125 |
+
apercu += "moyennant la rémunération précisée à l'article approprié, "
|
126 |
+
|
127 |
+
apercu += "pour la durée et sur le territoire mentionnés ci-après.\n\n"
|
128 |
+
|
129 |
+
apercu += "Le Cessionnaire s'engage expressément à ne pas porter atteinte à la dignité, à l'honneur ou à la réputation du Modèle. "
|
130 |
+
apercu += "Les parties s'engagent mutuellement à ne pas tenir de propos dénigrants l'une envers l'autre.\n\n"
|
131 |
+
|
132 |
+
if is_exclusive:
|
133 |
+
apercu += "Le Modèle s'engage à ne pas autoriser l'exploitation de son image à des tiers pendant la durée du présent contrat.\n\n"
|
134 |
+
else:
|
135 |
+
apercu += "La présente autorisation étant non exclusive, le Modèle conserve le droit d'autoriser l'exploitation de son image à des tiers.\n\n"
|
136 |
+
|
137 |
+
article_num += 1
|
138 |
+
|
139 |
+
# Suite des articles (résumés pour l'aperçu)
|
140 |
+
apercu += f"Article {article_num} – DURÉE ET TERRITOIRE\n"
|
141 |
+
apercu += "Durée : 1 an, renouvelable par tacite reconduction\n"
|
142 |
+
apercu += "Territoire : monde entier\n\n"
|
143 |
+
|
144 |
+
article_num += 1
|
145 |
+
apercu += f"Article {article_num} – SUPPORTS D'EXPLOITATION\n"
|
146 |
+
supports_str = ", ".join(final_supports)
|
147 |
+
apercu += f"Supports autorisés : {supports_str}\n\n"
|
148 |
+
|
149 |
+
article_num += 1
|
150 |
+
apercu += f"Article {article_num} – RÉMUNÉRATION\n"
|
151 |
+
if is_free:
|
152 |
+
apercu += "La présente cession est consentie à titre gratuit.\n\n"
|
153 |
+
else:
|
154 |
+
apercu += f"Rémunération : {sanitize_text(remuneration)}\n\n"
|
155 |
+
|
156 |
+
# Aperçu des articles restants
|
157 |
+
article_num += 1
|
158 |
+
apercu += f"Article {article_num} – GARANTIES\n"
|
159 |
+
article_num += 1
|
160 |
+
apercu += f"Article {article_num} – RÉSILIATION\n"
|
161 |
+
article_num += 1
|
162 |
+
apercu += f"Article {article_num} – LOI APPLICABLE ET JURIDICTION COMPÉTENTE\n\n"
|
163 |
+
|
164 |
+
apercu += "Fait à ________________, le ________________\n\n"
|
165 |
+
|
166 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
167 |
+
apercu += "L'Auteur et Modèle Le Cessionnaire"
|
168 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
169 |
+
apercu += "L'Auteur Le Cessionnaire"
|
170 |
+
else:
|
171 |
+
apercu += "Le Modèle Le Cessionnaire"
|
172 |
+
|
173 |
+
return apercu
|
contract_templates.py
ADDED
@@ -0,0 +1,423 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Templates des différentes sections de contrats.
|
3 |
+
Ce module contient tous les textes de base pour les différentes sections des contrats.
|
4 |
+
"""
|
5 |
+
|
6 |
+
from config import TELLERS_INFO, DEFAULT_DURATION, DEFAULT_RENEWAL, DEFAULT_TERRITORY
|
7 |
+
|
8 |
+
|
9 |
+
class ContractTemplates:
|
10 |
+
"""Classe contenant tous les templates pour la génération des contrats."""
|
11 |
+
|
12 |
+
@staticmethod
|
13 |
+
def get_title(contract_type):
|
14 |
+
"""
|
15 |
+
Retourne le titre du contrat en fonction du type.
|
16 |
+
|
17 |
+
Args:
|
18 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
19 |
+
|
20 |
+
Returns:
|
21 |
+
str: Titre du contrat
|
22 |
+
"""
|
23 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
24 |
+
return "CONTRAT DE CESSION DE DROITS D'AUTEUR ET DE DROITS À L'IMAGE"
|
25 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
26 |
+
return "CONTRAT DE CESSION DE DROITS D'AUTEUR"
|
27 |
+
else:
|
28 |
+
return "CONTRAT DE CESSION DE DROITS À L'IMAGE"
|
29 |
+
|
30 |
+
@staticmethod
|
31 |
+
def get_preamble_text(contract_type, author_type, author_info):
|
32 |
+
"""
|
33 |
+
Retourne le texte du préambule du contrat.
|
34 |
+
|
35 |
+
Args:
|
36 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
37 |
+
author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
|
38 |
+
author_info (dict): Informations sur l'auteur
|
39 |
+
|
40 |
+
Returns:
|
41 |
+
str: Texte du préambule
|
42 |
+
"""
|
43 |
+
# Partie commune à tous les contrats
|
44 |
+
preamble = "ENTRE LES SOUSSIGNÉS :\n\n"
|
45 |
+
|
46 |
+
# Informations sur l'auteur/modèle
|
47 |
+
if author_type == "Personne physique":
|
48 |
+
gentille = author_info.get("gentille", "M.")
|
49 |
+
nom = author_info.get("nom", "")
|
50 |
+
prenom = author_info.get("prenom", "")
|
51 |
+
date_naissance = author_info.get("date_naissance", "")
|
52 |
+
nationalite = author_info.get("nationalite", "")
|
53 |
+
adresse = author_info.get("adresse", "")
|
54 |
+
contact = author_info.get("contact", "")
|
55 |
+
|
56 |
+
preamble += f"{gentille} {prenom} {nom}"
|
57 |
+
if date_naissance:
|
58 |
+
preamble += f", né(e) le {date_naissance}"
|
59 |
+
if nationalite:
|
60 |
+
preamble += f", de nationalité {nationalite}"
|
61 |
+
preamble += f", domicilié(e) au {adresse}"
|
62 |
+
if contact:
|
63 |
+
preamble += f", joignable à {contact}"
|
64 |
+
else:
|
65 |
+
# Personne morale
|
66 |
+
nom_societe = author_info.get("nom_societe", "")
|
67 |
+
statut = author_info.get("statut", "")
|
68 |
+
rcs = author_info.get("rcs", "")
|
69 |
+
siege = author_info.get("siege", "")
|
70 |
+
contact = author_info.get("contact", "")
|
71 |
+
|
72 |
+
preamble += f"La société {nom_societe}, {statut}, immatriculée sous le numéro {rcs}, dont le siège social est situé {siege}"
|
73 |
+
if contact:
|
74 |
+
preamble += f", joignable à {contact}"
|
75 |
+
|
76 |
+
# Dénomination en fonction du type de contrat
|
77 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
78 |
+
preamble += ", ci-après dénommé(e) \"l'Auteur et le Modèle\"\n\n"
|
79 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
80 |
+
preamble += ", ci-après dénommé(e) \"l'Auteur\"\n\n"
|
81 |
+
else:
|
82 |
+
preamble += ", ci-après dénommé(e) \"le Modèle\"\n\n"
|
83 |
+
|
84 |
+
# Informations sur Tellers (bénéficiaire)
|
85 |
+
preamble += f"{TELLERS_INFO['nom']}, {TELLERS_INFO['forme_juridique']} au capital de {TELLERS_INFO['capital']}, "
|
86 |
+
preamble += f"immatriculée sous le numéro {TELLERS_INFO['rcs']}, et dont le siège social est situé au : "
|
87 |
+
preamble += f"{TELLERS_INFO['siege']}, ci-après dénommée \"le Cessionnaire\"\n\n"
|
88 |
+
|
89 |
+
# Introduction commune
|
90 |
+
preamble += "IL A ÉTÉ CONVENU CE QUI SUIT :\n\n"
|
91 |
+
|
92 |
+
return preamble
|
93 |
+
|
94 |
+
@staticmethod
|
95 |
+
def get_object_clause(contract_type, work_description, image_description):
|
96 |
+
"""
|
97 |
+
Retourne la clause d'objet du contrat.
|
98 |
+
|
99 |
+
Args:
|
100 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
101 |
+
work_description (str): Description de l'œuvre
|
102 |
+
image_description (str): Description de l'image
|
103 |
+
|
104 |
+
Returns:
|
105 |
+
str: Clause d'objet
|
106 |
+
"""
|
107 |
+
object_clause = "Article 1 – OBJET\n\n"
|
108 |
+
|
109 |
+
if "Auteur (droits d'auteur)" in contract_type:
|
110 |
+
object_clause += f"L'Auteur déclare être le créateur et titulaire exclusif des droits d'auteur sur l'œuvre suivante : {work_description}. "
|
111 |
+
|
112 |
+
if "Image (droit à l'image)" in contract_type:
|
113 |
+
object_clause += f"Le Modèle autorise l'utilisation et l'exploitation de son image telle qu'elle apparaît dans les photographies/vidéos suivantes : {image_description}. "
|
114 |
+
|
115 |
+
object_clause += "\nPar le présent contrat, "
|
116 |
+
|
117 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
118 |
+
object_clause += "l'Auteur cède au Cessionnaire certains droits sur son œuvre, et le Modèle autorise l'exploitation de son image, dans les conditions définies ci-après."
|
119 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
120 |
+
object_clause += "l'Auteur cède au Cessionnaire certains droits sur son œuvre dans les conditions définies ci-après."
|
121 |
+
else:
|
122 |
+
object_clause += "le Modèle autorise l'exploitation de son image dans les conditions définies ci-après."
|
123 |
+
|
124 |
+
return object_clause
|
125 |
+
|
126 |
+
@staticmethod
|
127 |
+
def get_author_rights_clause(is_free, is_exclusive, additional_rights):
|
128 |
+
"""
|
129 |
+
Retourne la clause des droits cédés pour le droit d'auteur.
|
130 |
+
|
131 |
+
Args:
|
132 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
133 |
+
is_exclusive (bool): True si la cession est exclusive, False sinon
|
134 |
+
additional_rights (list): Liste des droits supplémentaires sélectionnés
|
135 |
+
|
136 |
+
Returns:
|
137 |
+
str: Clause des droits cédés
|
138 |
+
"""
|
139 |
+
rights_clause = "Article 2 – ÉTENDUE DES DROITS CÉDÉS\n\n"
|
140 |
+
|
141 |
+
# Texte de base pour tous les contrats de droits d'auteur
|
142 |
+
rights_clause += "L'Auteur cède au Cessionnaire, "
|
143 |
+
|
144 |
+
if is_exclusive:
|
145 |
+
rights_clause += "à titre exclusif, "
|
146 |
+
else:
|
147 |
+
rights_clause += "à titre non exclusif, "
|
148 |
+
|
149 |
+
if is_free:
|
150 |
+
rights_clause += f"gratuitement et pour la durée précisée à l'article 3, les droits patrimoniaux suivants :\n\n"
|
151 |
+
|
152 |
+
# Droits limités pour cession gratuite
|
153 |
+
rights_clause += "- Le droit de reproduction : l'Auteur autorise le Cessionnaire à reproduire ou faire reproduire l'œuvre "
|
154 |
+
rights_clause += "par tous procédés techniques connus ou inconnus à ce jour, sur tous supports et en tous formats.\n\n"
|
155 |
+
|
156 |
+
rights_clause += "- Le droit de représentation : l'Auteur autorise le Cessionnaire à communiquer l'œuvre au public "
|
157 |
+
rights_clause += "par tous procédés connus ou inconnus à ce jour, notamment par diffusion en ligne sur Internet, "
|
158 |
+
rights_clause += "présentation publique, projection, ou tout autre moyen."
|
159 |
+
else:
|
160 |
+
rights_clause += f"pour la durée précisée à l'article 3 et moyennant la rémunération précisée à l'article approprié, les droits patrimoniaux suivants :\n\n"
|
161 |
+
|
162 |
+
# Droits de base (toujours présents)
|
163 |
+
rights_clause += "- Le droit de reproduction : l'Auteur autorise le Cessionnaire à reproduire ou faire reproduire l'œuvre "
|
164 |
+
rights_clause += "par tous procédés techniques connus ou inconnus à ce jour, sur tous supports et en tous formats.\n\n"
|
165 |
+
|
166 |
+
rights_clause += "- Le droit de représentation : l'Auteur autorise le Cessionnaire à communiquer l'œuvre au public "
|
167 |
+
rights_clause += "par tous procédés connus ou inconnus à ce jour, notamment par diffusion en ligne sur Internet, "
|
168 |
+
rights_clause += "présentation publique, projection, ou tout autre moyen.\n\n"
|
169 |
+
|
170 |
+
# Droits supplémentaires pour les cessions onéreuses
|
171 |
+
if "distribution" in additional_rights:
|
172 |
+
rights_clause += "- Le droit de distribution : l'Auteur autorise le Cessionnaire à distribuer l'original de l'œuvre "
|
173 |
+
rights_clause += "ou ses copies au public par la vente ou tout autre transfert de propriété.\n\n"
|
174 |
+
|
175 |
+
if "usage" in additional_rights:
|
176 |
+
rights_clause += "- Le droit d'usage : l'Auteur autorise le Cessionnaire à utiliser l'œuvre pour les besoins "
|
177 |
+
rights_clause += "propres du Cessionnaire ou de ses clients, dans un cadre correspondant à l'objet du présent contrat.\n\n"
|
178 |
+
|
179 |
+
if "adaptation" in additional_rights:
|
180 |
+
rights_clause += "- Le droit d'adaptation : l'Auteur autorise le Cessionnaire à modifier, transformer, arranger, "
|
181 |
+
rights_clause += "traduire l'œuvre ou à l'incorporer à d'autres œuvres, dans le respect du droit moral de l'Auteur.\n\n"
|
182 |
+
|
183 |
+
if "pret" in additional_rights:
|
184 |
+
rights_clause += "- Le droit de prêt : l'Auteur autorise le Cessionnaire à mettre l'œuvre à disposition pour un "
|
185 |
+
rights_clause += "usage déterminé et pour une durée limitée, sans contrepartie financière directe.\n\n"
|
186 |
+
|
187 |
+
if "location" in additional_rights:
|
188 |
+
rights_clause += "- Le droit de location : l'Auteur autorise le Cessionnaire à mettre à disposition l'œuvre pour "
|
189 |
+
rights_clause += "un usage temporaire et en échange d'une contrepartie économique.\n\n"
|
190 |
+
|
191 |
+
if "suite" in additional_rights:
|
192 |
+
rights_clause += "- Le droit de suite (pour œuvres graphiques et plastiques uniquement) : l'Auteur et le Cessionnaire "
|
193 |
+
rights_clause += "reconnaissent l'existence du droit de suite permettant à l'auteur de percevoir un pourcentage sur le "
|
194 |
+
rights_clause += "produit de toute revente de l'œuvre, conformément aux dispositions légales en vigueur.\n\n"
|
195 |
+
|
196 |
+
# Clause d'exclusivité ou non-exclusivité
|
197 |
+
if is_exclusive:
|
198 |
+
rights_clause += "Pendant la durée de la présente cession, l'Auteur s'engage à ne pas céder les mêmes droits à des tiers "
|
199 |
+
rights_clause += "et à ne pas exploiter lui-même l'œuvre selon les modalités cédées au Cessionnaire. Cette exclusivité "
|
200 |
+
rights_clause += "constitue un élément substantiel du présent contrat, sans lequel le Cessionnaire n'aurait pas contracté."
|
201 |
+
else:
|
202 |
+
rights_clause += "La présente cession étant non exclusive, l'Auteur conserve le droit d'exploiter l'œuvre et de céder "
|
203 |
+
rights_clause += "les mêmes droits à des tiers, sous réserve de ne pas nuire à l'exploitation des droits cédés au Cessionnaire."
|
204 |
+
|
205 |
+
return rights_clause
|
206 |
+
|
207 |
+
@staticmethod
|
208 |
+
def get_image_rights_clause(is_free, is_exclusive):
|
209 |
+
"""
|
210 |
+
Retourne la clause des droits cédés pour le droit à l'image.
|
211 |
+
|
212 |
+
Args:
|
213 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
214 |
+
is_exclusive (bool): True si la cession est exclusive, False sinon
|
215 |
+
|
216 |
+
Returns:
|
217 |
+
str: Clause des droits à l'image
|
218 |
+
"""
|
219 |
+
image_clause = "Article 2 – AUTORISATION D'EXPLOITATION DE L'IMAGE\n\n"
|
220 |
+
|
221 |
+
image_clause += "Le Modèle autorise expressément le Cessionnaire à fixer, reproduire et communiquer au public son image telle que décrite à l'article 1. "
|
222 |
+
image_clause += "Cette autorisation comprend le droit de reproduire et de représenter l'image sur tous supports et par tous moyens, connus ou inconnus à ce jour. "
|
223 |
+
image_clause += "Cette autorisation est consentie "
|
224 |
+
|
225 |
+
if is_exclusive:
|
226 |
+
image_clause += "à titre exclusif, "
|
227 |
+
else:
|
228 |
+
image_clause += "à titre non exclusif, "
|
229 |
+
|
230 |
+
if is_free:
|
231 |
+
image_clause += "gratuitement, "
|
232 |
+
else:
|
233 |
+
image_clause += "moyennant la rémunération précisée à l'article approprié, "
|
234 |
+
|
235 |
+
image_clause += f"pour la durée et sur le territoire mentionnés ci-après.\n\n"
|
236 |
+
|
237 |
+
# Restrictions d'utilisation pour le droit à l'image
|
238 |
+
image_clause += "Le Cessionnaire s'engage expressément à ne pas porter atteinte à la dignité, à l'honneur ou à la réputation du Modèle. "
|
239 |
+
image_clause += "Les images ne pourront pas être utilisées dans un contexte diffamatoire, pornographique, ou contraire aux bonnes mœurs. "
|
240 |
+
image_clause += "Les parties s'engagent mutuellement à ne pas tenir de propos dénigrants l'une envers l'autre.\n\n"
|
241 |
+
|
242 |
+
# Clause d'exclusivité pour le droit à l'image
|
243 |
+
if is_exclusive:
|
244 |
+
image_clause += "Le Modèle s'engage à ne pas autoriser l'exploitation de son image, telle que décrite à l'article 1, "
|
245 |
+
image_clause += "à des tiers pendant la durée du présent contrat. Cette exclusivité constitue un élément substantiel du "
|
246 |
+
image_clause += "présent contrat, sans lequel le Cessionnaire n'aurait pas contracté."
|
247 |
+
else:
|
248 |
+
image_clause += "La présente autorisation étant non exclusive, le Modèle conserve le droit d'autoriser l'exploitation "
|
249 |
+
image_clause += "de son image à des tiers, sous réserve de ne pas nuire à l'exploitation des droits autorisés au Cessionnaire."
|
250 |
+
|
251 |
+
return image_clause
|
252 |
+
|
253 |
+
@staticmethod
|
254 |
+
def get_duration_territory_clause(article_num):
|
255 |
+
"""
|
256 |
+
Retourne la clause de durée et territoire.
|
257 |
+
|
258 |
+
Args:
|
259 |
+
article_num (int): Numéro de l'article
|
260 |
+
|
261 |
+
Returns:
|
262 |
+
str: Clause de durée et territoire
|
263 |
+
"""
|
264 |
+
duration_clause = f"Article {article_num} – DURÉE ET TERRITOIRE\n\n"
|
265 |
+
|
266 |
+
duration_clause += f"La présente cession est consentie pour une durée de {DEFAULT_DURATION} à compter de la date de signature du présent contrat. "
|
267 |
+
duration_clause += f"Elle se renouvellera automatiquement par {DEFAULT_RENEWAL}, "
|
268 |
+
duration_clause += "sauf dénonciation par l'une des parties par lettre recommandée avec accusé de réception au moins trois (3) mois avant l'expiration de la période en cours.\n\n"
|
269 |
+
duration_clause += f"La cession est consentie pour le {DEFAULT_TERRITORY}, compte tenu de la nature numérique des services fournis par le Cessionnaire, "
|
270 |
+
duration_clause += "susceptibles d'être accessibles à l'échelle mondiale."
|
271 |
+
|
272 |
+
return duration_clause
|
273 |
+
|
274 |
+
@staticmethod
|
275 |
+
def get_supports_clause(article_num, supports):
|
276 |
+
"""
|
277 |
+
Retourne la clause des supports d'exploitation.
|
278 |
+
|
279 |
+
Args:
|
280 |
+
article_num (int): Numéro de l'article
|
281 |
+
supports (list): Liste des supports sélectionnés
|
282 |
+
|
283 |
+
Returns:
|
284 |
+
str: Clause des supports
|
285 |
+
"""
|
286 |
+
supports_clause = f"Article {article_num} – SUPPORTS D'EXPLOITATION\n\n"
|
287 |
+
|
288 |
+
# Formatage de la liste des supports
|
289 |
+
supports_str = ", ".join(supports)
|
290 |
+
|
291 |
+
supports_clause += f"Le Cessionnaire est autorisé à exploiter l'œuvre et/ou l'image sur les supports suivants : {supports_str}.\n\n"
|
292 |
+
supports_clause += "Cette liste est limitative et le Cessionnaire s'engage à ne pas utiliser l'œuvre et/ou l'image sur d'autres supports "
|
293 |
+
supports_clause += "sans l'autorisation préalable et écrite du Cédant."
|
294 |
+
|
295 |
+
return supports_clause
|
296 |
+
|
297 |
+
@staticmethod
|
298 |
+
def get_remuneration_clause(article_num, is_free, remuneration):
|
299 |
+
"""
|
300 |
+
Retourne la clause de rémunération.
|
301 |
+
|
302 |
+
Args:
|
303 |
+
article_num (int): Numéro de l'article
|
304 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
305 |
+
remuneration (str): Modalités de rémunération
|
306 |
+
|
307 |
+
Returns:
|
308 |
+
str: Clause de rémunération
|
309 |
+
"""
|
310 |
+
remuneration_clause = f"Article {article_num} – RÉMUNÉRATION\n\n"
|
311 |
+
|
312 |
+
if is_free:
|
313 |
+
remuneration_clause += "La présente cession est consentie à titre gratuit. "
|
314 |
+
remuneration_clause += "Aucune rémunération n'est due par le Cessionnaire. "
|
315 |
+
remuneration_clause += "Le Cédant déclare être pleinement informé de la portée de cette gratuité et y consentir expressément."
|
316 |
+
else:
|
317 |
+
remuneration_clause += f"En contrepartie de la présente cession, le Cessionnaire versera au Cédant la rémunération suivante : {remuneration}.\n\n"
|
318 |
+
remuneration_clause += "Cette rémunération inclut tout montant dû au titre de l'ensemble des droits cédés, tels que définis dans le présent contrat. "
|
319 |
+
remuneration_clause += "Le Cédant reconnaît que cette rémunération est conforme aux usages de la profession et proportionnée à l'exploitation prévue de l'œuvre."
|
320 |
+
|
321 |
+
return remuneration_clause
|
322 |
+
|
323 |
+
@staticmethod
|
324 |
+
def get_warranties_clause(article_num, contract_type):
|
325 |
+
"""
|
326 |
+
Retourne la clause de garanties.
|
327 |
+
|
328 |
+
Args:
|
329 |
+
article_num (int): Numéro de l'article
|
330 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
331 |
+
|
332 |
+
Returns:
|
333 |
+
str: Clause de garanties
|
334 |
+
"""
|
335 |
+
warranties_clause = f"Article {article_num} – GARANTIES\n\n"
|
336 |
+
|
337 |
+
if "Auteur (droits d'auteur)" in contract_type:
|
338 |
+
warranties_clause += "L'Auteur garantit au Cessionnaire qu'il est bien titulaire des droits cédés et que l'œuvre n'enfreint pas les droits de tiers. "
|
339 |
+
warranties_clause += "L'Auteur garantit notamment que l'œuvre est originale et qu'il détient l'intégralité des droits de propriété intellectuelle sur celle-ci. "
|
340 |
+
warranties_clause += "Il garantit le Cessionnaire contre toute revendication, recours ou action que pourrait former toute personne physique ou morale "
|
341 |
+
warranties_clause += "estimant avoir des droits sur l'œuvre ou sur tout élément de celle-ci.\n\n"
|
342 |
+
|
343 |
+
if "Image (droit à l'image)" in contract_type:
|
344 |
+
warranties_clause += "Le Modèle garantit qu'il est libre de consentir à la présente autorisation et que son image n'est pas liée "
|
345 |
+
warranties_clause += "à d'autres engagements exclusifs incompatibles avec le présent contrat. "
|
346 |
+
warranties_clause += "Le Modèle garantit le Cessionnaire contre tout recours ou action que pourraient former des tiers à cet égard.\n\n"
|
347 |
+
|
348 |
+
warranties_clause += "Le Cessionnaire s'engage à mentionner le nom de l'Auteur lors de toute exploitation de l'œuvre, "
|
349 |
+
warranties_clause += "sauf lorsque cela est techniquement impossible ou inapproprié compte tenu du support d'exploitation."
|
350 |
+
|
351 |
+
return warranties_clause
|
352 |
+
|
353 |
+
@staticmethod
|
354 |
+
def get_termination_clause(article_num):
|
355 |
+
"""
|
356 |
+
Retourne la clause de résiliation.
|
357 |
+
|
358 |
+
Args:
|
359 |
+
article_num (int): Numéro de l'article
|
360 |
+
|
361 |
+
Returns:
|
362 |
+
str: Clause de résiliation
|
363 |
+
"""
|
364 |
+
termination_clause = f"Article {article_num} – RÉSILIATION\n\n"
|
365 |
+
|
366 |
+
termination_clause += "Le présent contrat pourra être résilié de plein droit par l'une des parties en cas d'inexécution "
|
367 |
+
termination_clause += "par l'autre partie de l'une de ses obligations. "
|
368 |
+
termination_clause += "Cette résiliation ne deviendra effective que trois mois après l'envoi par la partie plaignante "
|
369 |
+
termination_clause += "d'une lettre recommandée avec accusé de réception, exposant les motifs de la plainte, "
|
370 |
+
termination_clause += "à moins que, dans ce délai, la partie défaillante n'ait satisfait à ses obligations ou "
|
371 |
+
termination_clause += "n'ait apporté la preuve d'un empêchement consécutif à un cas de force majeure.\n\n"
|
372 |
+
|
373 |
+
termination_clause += "L'exercice de cette faculté de résiliation ne dispense pas la partie défaillante de remplir "
|
374 |
+
termination_clause += "les obligations contractées jusqu'à la date de prise d'effet de la résiliation et ce, "
|
375 |
+
termination_clause += "sous réserve des dommages éventuellement subis par la partie plaignante du fait de la résiliation anticipée du contrat."
|
376 |
+
|
377 |
+
return termination_clause
|
378 |
+
|
379 |
+
@staticmethod
|
380 |
+
def get_applicable_law_clause(article_num):
|
381 |
+
"""
|
382 |
+
Retourne la clause de loi applicable.
|
383 |
+
|
384 |
+
Args:
|
385 |
+
article_num (int): Numéro de l'article
|
386 |
+
|
387 |
+
Returns:
|
388 |
+
str: Clause de loi applicable
|
389 |
+
"""
|
390 |
+
law_clause = f"Article {article_num} – LOI APPLICABLE ET JURIDICTION COMPÉTENTE\n\n"
|
391 |
+
|
392 |
+
law_clause += "Le présent contrat est soumis à la loi française.\n\n"
|
393 |
+
law_clause += "En cas de litige sur l'interprétation ou l'exécution du présent contrat, les parties s'efforceront de résoudre leur différend à l'amiable. "
|
394 |
+
law_clause += "À défaut d'accord amiable dans un délai de trente (30) jours à compter de la notification du différend par l'une des parties à l'autre, "
|
395 |
+
law_clause += "tout litige sera soumis aux tribunaux compétents de Lyon, auxquels il est fait expressément attribution de compétence, "
|
396 |
+
law_clause += "y compris en cas de référé, d'appel en garantie ou de pluralité de défendeurs."
|
397 |
+
|
398 |
+
return law_clause
|
399 |
+
|
400 |
+
@staticmethod
|
401 |
+
def get_signatures_template(contract_type):
|
402 |
+
"""
|
403 |
+
Retourne le template des signatures.
|
404 |
+
|
405 |
+
Args:
|
406 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
407 |
+
|
408 |
+
Returns:
|
409 |
+
str: Template des signatures
|
410 |
+
"""
|
411 |
+
signatures = "\n\nFait à ________________, le ________________\n\n"
|
412 |
+
|
413 |
+
# Adapter la signature en fonction du type de contrat
|
414 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
415 |
+
signatures += "L'Auteur et Modèle Le Cessionnaire"
|
416 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
417 |
+
signatures += "L'Auteur Le Cessionnaire"
|
418 |
+
else:
|
419 |
+
signatures += "Le Modèle Le Cessionnaire"
|
420 |
+
|
421 |
+
signatures += "\n\n(Signature précédée de la mention « Lu et approuvé »)"
|
422 |
+
|
423 |
+
return signatures
|
interface.py
ADDED
@@ -0,0 +1,359 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Module définissant l'interface utilisateur Gradio et l'arbre de décision du formulaire.
|
3 |
+
"""
|
4 |
+
import gradio as gr
|
5 |
+
from utils import collect_author_info
|
6 |
+
from config import (CONTRACT_TYPES, CESSION_MODES, ADDITIONAL_RIGHTS,
|
7 |
+
AUTHOR_TYPES, CIVILITY_OPTIONS, SUPPORTS_OPTIONS)
|
8 |
+
|
9 |
+
|
10 |
+
def create_interface(generate_pdf_fn, preview_contract_fn):
|
11 |
+
"""
|
12 |
+
Crée l'interface utilisateur Gradio avec l'arbre de décision pour le formulaire.
|
13 |
+
|
14 |
+
Args:
|
15 |
+
generate_pdf_fn: Fonction pour générer le PDF
|
16 |
+
preview_contract_fn: Fonction pour prévisualiser le contrat
|
17 |
+
|
18 |
+
Returns:
|
19 |
+
gr.Blocks: L'interface Gradio configurée
|
20 |
+
"""
|
21 |
+
with gr.Blocks(title="Générateur de Contrats de Cession") as demo:
|
22 |
+
gr.Markdown("# Générateur de Contrats de Cession de Droits")
|
23 |
+
gr.Markdown("Cet outil vous permet de générer des contrats de cession de droits d'auteur et/ou de droits à l'image adaptés à votre situation.")
|
24 |
+
|
25 |
+
# Organisation en onglets
|
26 |
+
with gr.Tabs():
|
27 |
+
with gr.TabItem("Formulaire"):
|
28 |
+
# ===== ÉTAPE 1: TYPE DE CONTRAT =====
|
29 |
+
gr.Markdown("### 1. Type de contrat")
|
30 |
+
gr.Markdown("Cette première étape détermine le type de contrat à générer en fonction de la nature de l'œuvre.")
|
31 |
+
type_contrat = gr.CheckboxGroup(
|
32 |
+
CONTRACT_TYPES,
|
33 |
+
label="Quel type de contrat souhaitez-vous établir?",
|
34 |
+
value=["Auteur (droits d'auteur)"],
|
35 |
+
info="Sélectionnez 'Auteur' pour une œuvre protégée par le droit d'auteur, 'Image' pour l'utilisation de l'image d'une personne, ou les deux si nécessaire."
|
36 |
+
)
|
37 |
+
|
38 |
+
# ===== ÉTAPE 2: MODE DE CESSION =====
|
39 |
+
gr.Markdown("### 2. Mode de cession")
|
40 |
+
gr.Markdown("Le mode de cession détermine si la cession est gratuite ou onéreuse, ce qui influencera les droits cédés et les clauses applicables.")
|
41 |
+
type_cession = gr.Radio(
|
42 |
+
CESSION_MODES,
|
43 |
+
label="La cession se fait-elle à titre gratuit ou onéreux?",
|
44 |
+
value="Gratuite",
|
45 |
+
info="Une cession gratuite limite les droits cédés (reproduction et représentation uniquement). Une cession onéreuse permet d'étendre ces droits."
|
46 |
+
)
|
47 |
+
|
48 |
+
# ===== ÉTAPE 2.1: DROITS CÉDÉS (uniquement si onéreux) =====
|
49 |
+
with gr.Group(visible=False) as groupe_droits:
|
50 |
+
gr.Markdown("### 2.1 Droits cédés supplémentaires")
|
51 |
+
gr.Markdown("""
|
52 |
+
Pour une cession onéreuse, vous pouvez céder des droits supplémentaires en plus des droits de base:
|
53 |
+
- Le droit de reproduction et le droit de représentation sont toujours inclus
|
54 |
+
- Sélectionnez les droits supplémentaires que vous souhaitez céder
|
55 |
+
""")
|
56 |
+
droits_cedes = gr.CheckboxGroup(
|
57 |
+
ADDITIONAL_RIGHTS,
|
58 |
+
label="Sélectionnez les droits supplémentaires à céder",
|
59 |
+
info="Chaque droit sélectionné sera ajouté dans le contrat avec sa définition juridique précise."
|
60 |
+
)
|
61 |
+
|
62 |
+
# ===== ÉTAPE 2.2: EXCLUSIVITÉ (uniquement si onéreux) =====
|
63 |
+
with gr.Group(visible=False) as groupe_exclusivite:
|
64 |
+
gr.Markdown("### 2.2 Exclusivité")
|
65 |
+
gr.Markdown("""
|
66 |
+
L'exclusivité est une clause importante qui détermine si le cédant peut réutiliser ou céder à d'autres les mêmes droits pendant la durée du contrat.
|
67 |
+
""")
|
68 |
+
exclusivite = gr.Checkbox(
|
69 |
+
label="Souhaitez-vous établir une clause d'exclusivité?",
|
70 |
+
value=False,
|
71 |
+
info="Si coché, le cédant ne pourra pas céder les mêmes droits à d'autres personnes ni les utiliser lui-même pendant la durée du contrat."
|
72 |
+
)
|
73 |
+
|
74 |
+
# ===== ÉTAPE 3: INFORMATIONS SUR L'AUTEUR/MODÈLE =====
|
75 |
+
gr.Markdown("### 3. Informations sur l'auteur/modèle")
|
76 |
+
gr.Markdown("Ces informations identifient précisément le cédant dans le contrat.")
|
77 |
+
auteur_type = gr.Radio(
|
78 |
+
AUTHOR_TYPES,
|
79 |
+
label="L'auteur/modèle est-il une personne physique ou morale?",
|
80 |
+
value="Personne physique",
|
81 |
+
info="Une personne morale est une entreprise ou une association. Pour les personnes morales, assurez-vous qu'elles détiennent bien les droits (œuvre collective, logiciel, ou cession obtenue)."
|
82 |
+
)
|
83 |
+
|
84 |
+
# Champs pour personne physique (visibles par défaut)
|
85 |
+
with gr.Group() as groupe_personne_physique:
|
86 |
+
gentille = gr.Radio(
|
87 |
+
CIVILITY_OPTIONS,
|
88 |
+
label="Civilité",
|
89 |
+
value="M."
|
90 |
+
)
|
91 |
+
nom = gr.Textbox(
|
92 |
+
label="Nom",
|
93 |
+
placeholder="Nom de famille"
|
94 |
+
)
|
95 |
+
prenom = gr.Textbox(
|
96 |
+
label="Prénom",
|
97 |
+
placeholder="Prénom"
|
98 |
+
)
|
99 |
+
date_naissance = gr.Textbox(
|
100 |
+
label="Date de naissance (facultatif)",
|
101 |
+
placeholder="JJ/MM/AAAA"
|
102 |
+
)
|
103 |
+
nationalite = gr.Textbox(
|
104 |
+
label="Nationalité",
|
105 |
+
placeholder="Ex: française"
|
106 |
+
)
|
107 |
+
adresse = gr.Textbox(
|
108 |
+
label="Adresse complète",
|
109 |
+
placeholder="Numéro, rue, code postal, ville"
|
110 |
+
)
|
111 |
+
contact_physique = gr.Textbox(
|
112 |
+
label="Moyen de contact (email, téléphone)",
|
113 |
+
placeholder="Email et/ou téléphone"
|
114 |
+
)
|
115 |
+
|
116 |
+
# Champs pour personne morale (masqués par défaut)
|
117 |
+
with gr.Group(visible=False) as groupe_personne_morale:
|
118 |
+
nom_societe = gr.Textbox(
|
119 |
+
label="Nom de la société",
|
120 |
+
placeholder="Dénomination sociale"
|
121 |
+
)
|
122 |
+
statut = gr.Textbox(
|
123 |
+
label="Statut juridique",
|
124 |
+
placeholder="Ex: SARL, SAS, EURL, etc."
|
125 |
+
)
|
126 |
+
rcs = gr.Textbox(
|
127 |
+
label="Numéro RCS",
|
128 |
+
placeholder="Ex: 123 456 789 R.C.S. Paris"
|
129 |
+
)
|
130 |
+
siege = gr.Textbox(
|
131 |
+
label="Adresse du siège social",
|
132 |
+
placeholder="Adresse complète du siège"
|
133 |
+
)
|
134 |
+
contact_morale = gr.Textbox(
|
135 |
+
label="Moyen de contact (email, téléphone)",
|
136 |
+
placeholder="Email et/ou téléphone"
|
137 |
+
)
|
138 |
+
|
139 |
+
# ===== ÉTAPE 4: DESCRIPTION DE L'ŒUVRE (si contrat droits d'auteur) =====
|
140 |
+
with gr.Group() as groupe_description_oeuvre:
|
141 |
+
gr.Markdown("### 4. Description de l'œuvre")
|
142 |
+
gr.Markdown("""
|
143 |
+
Décrivez précisément l'œuvre concernée. Cette description sera intégrée dans le contrat pour identifier sans ambiguïté l'objet de la cession.
|
144 |
+
""")
|
145 |
+
description_oeuvre = gr.Textbox(
|
146 |
+
label="Description de l'œuvre",
|
147 |
+
placeholder="Titre, format, dimensions, support, technique utilisée, date de création, etc.",
|
148 |
+
lines=5,
|
149 |
+
info="Plus la description est précise, plus le contrat sera sécurisé juridiquement."
|
150 |
+
)
|
151 |
+
|
152 |
+
# ===== ÉTAPE 5: DESCRIPTION DE L'IMAGE (si contrat droit à l'image) =====
|
153 |
+
with gr.Group(visible=False) as groupe_description_image:
|
154 |
+
gr.Markdown("### 5. Description des images")
|
155 |
+
gr.Markdown("""
|
156 |
+
Décrivez précisément les images ou vidéos concernées par la cession du droit à l'image.
|
157 |
+
""")
|
158 |
+
description_image = gr.Textbox(
|
159 |
+
label="Description des images/vidéos",
|
160 |
+
placeholder="Ex: Séance photo réalisée le [date] à [lieu], comprenant X photographies où apparaît [nom du modèle]",
|
161 |
+
lines=5,
|
162 |
+
info="Précisez le contexte, la date et le lieu de prise de vue, le nombre d'images concernées, etc."
|
163 |
+
)
|
164 |
+
|
165 |
+
# ===== ÉTAPE 6: SUPPORTS D'EXPLOITATION =====
|
166 |
+
gr.Markdown("### 6. Supports d'exploitation")
|
167 |
+
gr.Markdown("""
|
168 |
+
Sélectionnez les supports sur lesquels l'œuvre ou l'image pourra être exploitée.
|
169 |
+
Le site web et Discord de Tellers sont automatiquement inclus.
|
170 |
+
""")
|
171 |
+
supports = gr.CheckboxGroup(
|
172 |
+
SUPPORTS_OPTIONS,
|
173 |
+
label="Sur quels supports les droits seront-ils exploités?",
|
174 |
+
value=["Réseaux sociaux (Facebook, Instagram, Twitter, etc.)"],
|
175 |
+
info="Vous pouvez sélectionner plusieurs supports. Le site web et Discord de Tellers sont toujours inclus."
|
176 |
+
)
|
177 |
+
|
178 |
+
# ===== ÉTAPE 7: RÉMUNÉRATION (uniquement si onéreux) =====
|
179 |
+
with gr.Group(visible=False) as groupe_remuneration:
|
180 |
+
gr.Markdown("### 7. Rémunération")
|
181 |
+
gr.Markdown("""
|
182 |
+
Pour une cession onéreuse, précisez les modalités de rémunération.
|
183 |
+
Cela peut être un montant forfaitaire ou proportionnel aux recettes.
|
184 |
+
""")
|
185 |
+
remuneration = gr.Textbox(
|
186 |
+
label="Modalités de rémunération",
|
187 |
+
placeholder="Ex: 500€ versés à la signature, 5% des recettes versés trimestriellement",
|
188 |
+
lines=3,
|
189 |
+
info="La rémunération doit être précise pour être juridiquement valable: montant, date(s) de paiement, modalités."
|
190 |
+
)
|
191 |
+
|
192 |
+
# ===== BOUTONS D'ACTION =====
|
193 |
+
gr.Markdown("### Génération du contrat")
|
194 |
+
with gr.Row():
|
195 |
+
preview_btn = gr.Button("Prévisualiser le contrat", variant="secondary")
|
196 |
+
generate_btn = gr.Button("Générer le contrat PDF", variant="primary")
|
197 |
+
|
198 |
+
# ===== ONGLET PRÉVISUALISATION =====
|
199 |
+
with gr.TabItem("Prévisualisation"):
|
200 |
+
apercu_contrat = gr.Textbox(
|
201 |
+
label="Aperçu du contrat",
|
202 |
+
lines=25,
|
203 |
+
max_lines=50,
|
204 |
+
interactive=False
|
205 |
+
)
|
206 |
+
|
207 |
+
# ===== ONGLET TÉLÉCHARGEMENT =====
|
208 |
+
with gr.TabItem("Téléchargement"):
|
209 |
+
pdf_output = gr.File(label="Contrat de cession prêt à télécharger")
|
210 |
+
|
211 |
+
# ===== DÉFINITION DES INTERACTIONS CONDITIONNELLES =====
|
212 |
+
|
213 |
+
# 1. Visibilité des champs en fonction du type de contrat
|
214 |
+
def update_groups_type_contrat(type_selection):
|
215 |
+
"""Met à jour la visibilité des champs selon le type de contrat sélectionné."""
|
216 |
+
show_auteur = "Auteur (droits d'auteur)" in type_selection
|
217 |
+
show_image = "Image (droit à l'image)" in type_selection
|
218 |
+
|
219 |
+
return {
|
220 |
+
groupe_description_oeuvre: gr.update(visible=show_auteur),
|
221 |
+
groupe_description_image: gr.update(visible=show_image)
|
222 |
+
}
|
223 |
+
|
224 |
+
type_contrat.change(
|
225 |
+
fn=update_groups_type_contrat,
|
226 |
+
inputs=type_contrat,
|
227 |
+
outputs=[groupe_description_oeuvre, groupe_description_image]
|
228 |
+
)
|
229 |
+
|
230 |
+
# 2. Visibilité des champs en fonction du type de cession (gratuite/onéreuse)
|
231 |
+
def update_groups_type_cession(cession_type):
|
232 |
+
"""Met à jour la visibilité des champs selon le type de cession sélectionné."""
|
233 |
+
is_onereux = cession_type == "Onéreuse"
|
234 |
+
return {
|
235 |
+
groupe_droits: gr.update(visible=is_onereux),
|
236 |
+
groupe_exclusivite: gr.update(visible=is_onereux),
|
237 |
+
groupe_remuneration: gr.update(visible=is_onereux)
|
238 |
+
}
|
239 |
+
|
240 |
+
type_cession.change(
|
241 |
+
fn=update_groups_type_cession,
|
242 |
+
inputs=type_cession,
|
243 |
+
outputs=[groupe_droits, groupe_exclusivite, groupe_remuneration]
|
244 |
+
)
|
245 |
+
|
246 |
+
# 3. Changement de formulaire selon le type d'auteur (physique/morale)
|
247 |
+
def update_groups_type_auteur(auteur_type_val):
|
248 |
+
"""Met à jour la visibilité des champs selon le type d'auteur sélectionné."""
|
249 |
+
is_physique = auteur_type_val == "Personne physique"
|
250 |
+
return {
|
251 |
+
groupe_personne_physique: gr.update(visible=is_physique),
|
252 |
+
groupe_personne_morale: gr.update(visible=not is_physique)
|
253 |
+
}
|
254 |
+
|
255 |
+
auteur_type.change(
|
256 |
+
fn=update_groups_type_auteur,
|
257 |
+
inputs=auteur_type,
|
258 |
+
outputs=[groupe_personne_physique, groupe_personne_morale]
|
259 |
+
)
|
260 |
+
|
261 |
+
# 4. Prévisualisation du contrat
|
262 |
+
def handle_preview(type_contrat_val, type_cession_val, auteur_type_val,
|
263 |
+
gentille_val, nom_val, prenom_val, date_naissance_val, nationalite_val, adresse_val, contact_physique_val,
|
264 |
+
nom_societe_val, statut_val, rcs_val, siege_val, contact_morale_val,
|
265 |
+
description_oeuvre_val, description_image_val, supports_val, droits_cedes_val, remuneration_val, exclusivite_val):
|
266 |
+
"""Gère la prévisualisation du contrat."""
|
267 |
+
# Collecter les informations sur l'auteur/modèle
|
268 |
+
is_physical_person = (auteur_type_val == "Personne physique")
|
269 |
+
|
270 |
+
data = {
|
271 |
+
"gentille": gentille_val,
|
272 |
+
"nom": nom_val,
|
273 |
+
"prenom": prenom_val,
|
274 |
+
"date_naissance": date_naissance_val,
|
275 |
+
"nationalite": nationalite_val,
|
276 |
+
"adresse": adresse_val,
|
277 |
+
"contact_physique": contact_physique_val,
|
278 |
+
"nom_societe": nom_societe_val,
|
279 |
+
"statut": statut_val,
|
280 |
+
"rcs": rcs_val,
|
281 |
+
"siege": siege_val,
|
282 |
+
"contact_morale": contact_morale_val
|
283 |
+
}
|
284 |
+
|
285 |
+
auteur_info = collect_author_info(is_physical_person, data)
|
286 |
+
|
287 |
+
# Est-ce que la cession est gratuite ?
|
288 |
+
est_gratuit = (type_cession_val == "Gratuite")
|
289 |
+
|
290 |
+
# Générer l'aperçu du contrat
|
291 |
+
apercu = preview_contract_fn(
|
292 |
+
type_contrat_val, est_gratuit, auteur_type_val, auteur_info,
|
293 |
+
description_oeuvre_val, description_image_val, supports_val,
|
294 |
+
droits_cedes_val, remuneration_val, exclusivite_val
|
295 |
+
)
|
296 |
+
|
297 |
+
return apercu
|
298 |
+
|
299 |
+
preview_btn.click(
|
300 |
+
fn=handle_preview,
|
301 |
+
inputs=[
|
302 |
+
type_contrat, type_cession, auteur_type,
|
303 |
+
gentille, nom, prenom, date_naissance, nationalite, adresse, contact_physique,
|
304 |
+
nom_societe, statut, rcs, siege, contact_morale,
|
305 |
+
description_oeuvre, description_image, supports, droits_cedes, remuneration, exclusivite
|
306 |
+
],
|
307 |
+
outputs=apercu_contrat
|
308 |
+
)
|
309 |
+
|
310 |
+
# 5. Génération du PDF
|
311 |
+
def handle_generate_pdf(type_contrat_val, type_cession_val, auteur_type_val,
|
312 |
+
gentille_val, nom_val, prenom_val, date_naissance_val, nationalite_val, adresse_val, contact_physique_val,
|
313 |
+
nom_societe_val, statut_val, rcs_val, siege_val, contact_morale_val,
|
314 |
+
description_oeuvre_val, description_image_val, supports_val, droits_cedes_val, remuneration_val, exclusivite_val):
|
315 |
+
"""Gère la génération du PDF."""
|
316 |
+
# Collecter les informations sur l'auteur/modèle
|
317 |
+
is_physical_person = (auteur_type_val == "Personne physique")
|
318 |
+
|
319 |
+
data = {
|
320 |
+
"gentille": gentille_val,
|
321 |
+
"nom": nom_val,
|
322 |
+
"prenom": prenom_val,
|
323 |
+
"date_naissance": date_naissance_val,
|
324 |
+
"nationalite": nationalite_val,
|
325 |
+
"adresse": adresse_val,
|
326 |
+
"contact_physique": contact_physique_val,
|
327 |
+
"nom_societe": nom_societe_val,
|
328 |
+
"statut": statut_val,
|
329 |
+
"rcs": rcs_val,
|
330 |
+
"siege": siege_val,
|
331 |
+
"contact_morale": contact_morale_val
|
332 |
+
}
|
333 |
+
|
334 |
+
auteur_info = collect_author_info(is_physical_person, data)
|
335 |
+
|
336 |
+
# Est-ce que la cession est gratuite ?
|
337 |
+
est_gratuit = (type_cession_val == "Gratuite")
|
338 |
+
|
339 |
+
# Générer le PDF
|
340 |
+
pdf_path = generate_pdf_fn(
|
341 |
+
type_contrat_val, est_gratuit, auteur_type_val, auteur_info,
|
342 |
+
description_oeuvre_val, description_image_val, supports_val,
|
343 |
+
droits_cedes_val, remuneration_val, exclusivite_val
|
344 |
+
)
|
345 |
+
|
346 |
+
return pdf_path
|
347 |
+
|
348 |
+
generate_btn.click(
|
349 |
+
fn=handle_generate_pdf,
|
350 |
+
inputs=[
|
351 |
+
type_contrat, type_cession, auteur_type,
|
352 |
+
gentille, nom, prenom, date_naissance, nationalite, adresse, contact_physique,
|
353 |
+
nom_societe, statut, rcs, siege, contact_morale,
|
354 |
+
description_oeuvre, description_image, supports, droits_cedes, remuneration, exclusivite
|
355 |
+
],
|
356 |
+
outputs=pdf_output
|
357 |
+
)
|
358 |
+
|
359 |
+
return demo
|
pdf_generator-py.py
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Module pour la génération des contrats en format PDF.
|
3 |
+
"""
|
4 |
+
import io
|
5 |
+
from reportlab.pdfgen import canvas
|
6 |
+
from reportlab.lib.pagesizes import A4
|
7 |
+
from reportlab.lib.units import mm
|
8 |
+
from reportlab.platypus import SimpleDocTemplate
|
9 |
+
from reportlab.pdfbase import pdfform
|
10 |
+
from reportlab.lib.colors import black
|
11 |
+
|
12 |
+
from config import PDF_CONFIG
|
13 |
+
from contract_builder import ContractBuilder
|
14 |
+
from utils import create_temp_file, ensure_default_supports
|
15 |
+
|
16 |
+
|
17 |
+
def generate_pdf(contract_type, is_free, author_type, author_info,
|
18 |
+
work_description, image_description, supports,
|
19 |
+
additional_rights, remuneration, is_exclusive):
|
20 |
+
"""
|
21 |
+
Génère un PDF du contrat avec des champs interactifs.
|
22 |
+
|
23 |
+
Args:
|
24 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
25 |
+
is_free (bool): True si la cession est gratuite, False sinon
|
26 |
+
author_type (str): Type d'auteur ("Personne physique" ou "Personne morale")
|
27 |
+
author_info (dict): Informations sur l'auteur
|
28 |
+
work_description (str): Description de l'œuvre
|
29 |
+
image_description (str): Description de l'image
|
30 |
+
supports (list): Liste des supports sélectionnés
|
31 |
+
additional_rights (list): Liste des droits supplémentaires sélectionnés
|
32 |
+
remuneration (str): Modalités de rémunération
|
33 |
+
is_exclusive (bool): True si la cession est exclusive, False sinon
|
34 |
+
|
35 |
+
Returns:
|
36 |
+
str: Chemin vers le fichier PDF généré
|
37 |
+
"""
|
38 |
+
# Conversion des paramètres
|
39 |
+
is_free_bool = (is_free == "Gratuite")
|
40 |
+
is_exclusive_bool = bool(is_exclusive)
|
41 |
+
|
42 |
+
# Ajouter les supports par défaut
|
43 |
+
final_supports = ensure_default_supports(supports)
|
44 |
+
|
45 |
+
# Créer un nom de fichier temporaire pour le PDF
|
46 |
+
output_filename = create_temp_file(prefix="contrat_cession_", suffix=".pdf")
|
47 |
+
|
48 |
+
# Générer le contenu du contrat
|
49 |
+
contract_elements = ContractBuilder.build_contract_elements(
|
50 |
+
contract_type, is_free_bool, author_type, author_info,
|
51 |
+
work_description, image_description, final_supports,
|
52 |
+
additional_rights, remuneration, is_exclusive_bool
|
53 |
+
)
|
54 |
+
|
55 |
+
# Créer un document PDF
|
56 |
+
buffer = io.BytesIO()
|
57 |
+
doc = SimpleDocTemplate(buffer, pagesize=A4,
|
58 |
+
rightMargin=PDF_CONFIG['margin_right']*mm,
|
59 |
+
leftMargin=PDF_CONFIG['margin_left']*mm,
|
60 |
+
topMargin=PDF_CONFIG['margin_top']*mm,
|
61 |
+
bottomMargin=PDF_CONFIG['margin_bottom']*mm)
|
62 |
+
|
63 |
+
# Construire le document avec tous les éléments
|
64 |
+
doc.build(contract_elements)
|
65 |
+
|
66 |
+
# Ajouter des champs interactifs pour les signatures
|
67 |
+
buffer.seek(0)
|
68 |
+
buffer_champs = io.BytesIO()
|
69 |
+
|
70 |
+
p = canvas.Canvas(buffer_champs, pagesize=A4)
|
71 |
+
form = p.acroForm
|
72 |
+
|
73 |
+
# Déterminer le nom du cédant en fonction du type de contrat
|
74 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
75 |
+
cedant_label = "l'Auteur et Modèle"
|
76 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
77 |
+
cedant_label = "l'Auteur"
|
78 |
+
else:
|
79 |
+
cedant_label = "le Modèle"
|
80 |
+
|
81 |
+
# Champ pour le lieu (position sur dernière page)
|
82 |
+
form.textfield(name='lieu', tooltip='Lieu de signature',
|
83 |
+
x=80, y=140, width=100, height=15,
|
84 |
+
borderWidth=0, forceBorder=True)
|
85 |
+
|
86 |
+
# Champ pour la date
|
87 |
+
form.textfield(name='date', tooltip='Date de signature',
|
88 |
+
x=230, y=140, width=100, height=15,
|
89 |
+
borderWidth=0, forceBorder=True)
|
90 |
+
|
91 |
+
# Champ pour la mention "Lu et approuvé" du cédant
|
92 |
+
form.textfield(name='mention_cedant', tooltip='Mention "Lu et approuvé"',
|
93 |
+
x=70, y=95, width=150, height=15,
|
94 |
+
borderWidth=0, forceBorder=True)
|
95 |
+
|
96 |
+
# Champ pour la mention "Lu et approuvé" du cessionnaire
|
97 |
+
form.textfield(name='mention_cessionnaire', tooltip='Mention "Lu et approuvé"',
|
98 |
+
x=350, y=95, width=150, height=15,
|
99 |
+
borderWidth=0, forceBorder=True)
|
100 |
+
|
101 |
+
# Champs pour les signatures
|
102 |
+
form.textfield(name='signature_cedant', tooltip=f'Signature de {cedant_label}',
|
103 |
+
x=70, y=60, width=150, height=30,
|
104 |
+
borderWidth=0, forceBorder=True)
|
105 |
+
|
106 |
+
form.textfield(name='signature_cessionnaire', tooltip='Signature du Cessionnaire',
|
107 |
+
x=350, y=60, width=150, height=30,
|
108 |
+
borderWidth=0, forceBorder=True)
|
109 |
+
|
110 |
+
# Ajouter des champs pour le paraphe sur chaque page
|
111 |
+
# Ces champs sont placés en bas de chaque page pour permettre le paraphe
|
112 |
+
page_count = doc.page_count
|
113 |
+
for page in range(1, page_count):
|
114 |
+
p.showPage() # Aller à la page suivante
|
115 |
+
form.textfield(name=f'paraphe_cedant_{page}', tooltip=f'Paraphe {cedant_label} - page {page}',
|
116 |
+
x=70, y=30, width=50, height=20,
|
117 |
+
borderWidth=0, forceBorder=True)
|
118 |
+
form.textfield(name=f'paraphe_cessionnaire_{page}', tooltip=f'Paraphe Cessionnaire - page {page}',
|
119 |
+
x=350, y=30, width=50, height=20,
|
120 |
+
borderWidth=0, forceBorder=True)
|
121 |
+
|
122 |
+
# Finaliser et sauvegarder le PDF
|
123 |
+
p.save()
|
124 |
+
|
125 |
+
# Sauvegarder le PDF dans un fichier temporaire
|
126 |
+
with open(output_filename, 'wb') as f:
|
127 |
+
f.write(buffer.getvalue())
|
128 |
+
f.write(buffer_champs.getvalue())
|
129 |
+
|
130 |
+
return output_filename
|
131 |
+
|
132 |
+
|
133 |
+
def add_interactive_fields(pdf_path, contract_type):
|
134 |
+
"""
|
135 |
+
Ajoute des champs interactifs à un PDF existant.
|
136 |
+
|
137 |
+
Args:
|
138 |
+
pdf_path (str): Chemin vers le PDF
|
139 |
+
contract_type (list): Liste des types de contrats sélectionnés
|
140 |
+
|
141 |
+
Returns:
|
142 |
+
str: Chemin vers le PDF avec champs interactifs
|
143 |
+
"""
|
144 |
+
# Ce code peut être utilisé si on veut ajouter des champs à un PDF existant
|
145 |
+
# plutôt que de les créer en même temps
|
146 |
+
output_filename = create_temp_file(prefix="contrat_interactif_", suffix=".pdf")
|
147 |
+
|
148 |
+
p = canvas.Canvas(output_filename, pagesize=A4)
|
149 |
+
form = p.acroForm
|
150 |
+
|
151 |
+
# Déterminer le nom du cédant en fonction du type de contrat
|
152 |
+
if "Auteur (droits d'auteur)" in contract_type and "Image (droit à l'image)" in contract_type:
|
153 |
+
cedant_label = "l'Auteur et Modèle"
|
154 |
+
elif "Auteur (droits d'auteur)" in contract_type:
|
155 |
+
cedant_label = "l'Auteur"
|
156 |
+
else:
|
157 |
+
cedant_label = "le Modèle"
|
158 |
+
|
159 |
+
# Ajouter des champs similaires à ceux de la fonction generate_pdf
|
160 |
+
# Ici, on assume que le PDF a une structure similaire
|
161 |
+
|
162 |
+
# Sauvegarder le PDF
|
163 |
+
p.save()
|
164 |
+
|
165 |
+
return output_filename
|
readme.md
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Générateur de Contrats de Cession de Droits
|
2 |
+
|
3 |
+
Ce projet propose un générateur interactif de contrats de cession de droits d'auteur et de droits à l'image, conçu pour Tellers. L'application génère automatiquement des contrats juridiquement rigoureux adaptés aux besoins spécifiques de chaque situation.
|
4 |
+
|
5 |
+
## Structure du projet
|
6 |
+
|
7 |
+
Le projet est organisé de manière modulaire pour une meilleure séparation des responsabilités :
|
8 |
+
|
9 |
+
- `app.py` - Point d'entrée principal de l'application
|
10 |
+
- `interface.py` - Définition de l'interface utilisateur Gradio
|
11 |
+
- `config.py` - Configuration et constantes du projet
|
12 |
+
- `utils.py` - Fonctions utilitaires
|
13 |
+
- `contract_templates.py` - Templates des différentes sections de contrats
|
14 |
+
- `contract_builder.py` - Construction du contrat à partir des templates
|
15 |
+
- `contract_previewer.py` - Prévisualisation du contrat
|
16 |
+
- `pdf_generator.py` - Génération du PDF final avec champs interactifs
|
17 |
+
|
18 |
+
## Fonctionnalités
|
19 |
+
|
20 |
+
- Création de contrats de cession de droits d'auteur
|
21 |
+
- Création de contrats de droit à l'image
|
22 |
+
- Génération de contrats combinés (droits d'auteur + droits à l'image)
|
23 |
+
- Adaptation automatique des clauses selon le type de cession (gratuit/onéreux)
|
24 |
+
- Gestion des clauses d'exclusivité
|
25 |
+
- Support pour les auteurs personnes physiques ou morales
|
26 |
+
- Prévisualisation du contrat avant génération
|
27 |
+
- Export au format PDF avec champs interactifs pour les signatures et paraphes
|
28 |
+
|
29 |
+
## Arbre de décision du formulaire
|
30 |
+
|
31 |
+
1. **Type de contrat**
|
32 |
+
- Droits d'auteur
|
33 |
+
- Droit à l'image
|
34 |
+
- Les deux
|
35 |
+
|
36 |
+
2. **Mode de cession**
|
37 |
+
- Gratuite (limite les droits à la reproduction et représentation)
|
38 |
+
- Onéreuse (permet d'étendre les droits et l'exclusivité)
|
39 |
+
|
40 |
+
3. **Droits supplémentaires** (si cession onéreuse)
|
41 |
+
- Distribution
|
42 |
+
- Usage
|
43 |
+
- Adaptation
|
44 |
+
- Prêt
|
45 |
+
- Location
|
46 |
+
- Droit de suite (œuvres graphiques et plastiques)
|
47 |
+
|
48 |
+
4. **Exclusivité** (si cession onéreuse)
|
49 |
+
- Avec exclusivité
|
50 |
+
- Sans exclusivité
|
51 |
+
|
52 |
+
5. **Informations sur l'auteur/modèle**
|
53 |
+
- Personne physique (civilité, nom, prénom, etc.)
|
54 |
+
- Personne morale (société, statut juridique, RCS, etc.)
|
55 |
+
|
56 |
+
6. **Description de l'œuvre/image**
|
57 |
+
- Description précise de l'œuvre (si droits d'auteur)
|
58 |
+
- Description précise des images/vidéos (si droit à l'image)
|
59 |
+
|
60 |
+
7. **Supports d'exploitation**
|
61 |
+
- Multiples options (réseaux sociaux, applications, etc.)
|
62 |
+
- Site web et Discord toujours inclus
|
63 |
+
|
64 |
+
8. **Rémunération** (si cession onéreuse)
|
65 |
+
- Modalités de paiement (montant, échéancier, etc.)
|
66 |
+
|
67 |
+
## Déploiement sur Hugging Face Spaces
|
68 |
+
|
69 |
+
1. Créez un nouveau Space sur Hugging Face (https://huggingface.co/spaces/new)
|
70 |
+
2. Sélectionnez "Gradio" comme type d'application
|
71 |
+
3. Téléchargez tous les fichiers Python (.py) et requirements.txt
|
72 |
+
4. L'application sera automatiquement déployée et accessible via l'URL de votre Space
|
73 |
+
|
74 |
+
## PDF interactifs générés
|
75 |
+
|
76 |
+
Les PDF générés par l'application comprennent :
|
77 |
+
- Des champs de texte pour le lieu et la date de signature
|
78 |
+
- Des champs pour la mention "Lu et approuvé"
|
79 |
+
- Des champs de signature pour le cédant et le cessionnaire
|
80 |
+
- Des champs pour les paraphes sur chaque page
|
81 |
+
|
82 |
+
## Notes légales
|
83 |
+
|
84 |
+
Les contrats générés par cet outil sont conçus selon les principes juridiques français applicables aux cessions de droits d'auteur (Code de la propriété intellectuelle) et aux droits à l'image. Pour des situations spécifiques ou complexes, il est recommandé de consulter un professionnel du droit.
|
requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
gradio==4.10.0
|
2 |
+
reportlab==4.0.4
|
utils.py
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Fonctions utilitaires utilisées dans l'application.
|
3 |
+
"""
|
4 |
+
import os
|
5 |
+
import tempfile
|
6 |
+
import re
|
7 |
+
from config import DEFAULT_SUPPORTS
|
8 |
+
|
9 |
+
|
10 |
+
def collect_author_info(is_physical_person, data):
|
11 |
+
"""
|
12 |
+
Collecte les informations sur l'auteur/modèle selon son type.
|
13 |
+
|
14 |
+
Args:
|
15 |
+
is_physical_person (bool): True si l'auteur est une personne physique, False sinon
|
16 |
+
data (dict): Dictionnaire contenant les données du formulaire
|
17 |
+
|
18 |
+
Returns:
|
19 |
+
dict: Les informations formatées sur l'auteur/modèle
|
20 |
+
"""
|
21 |
+
author_info = {}
|
22 |
+
|
23 |
+
if is_physical_person:
|
24 |
+
# Personne physique
|
25 |
+
author_info = {
|
26 |
+
"gentille": data.get("gentille", "M."),
|
27 |
+
"nom": data.get("nom", ""),
|
28 |
+
"prenom": data.get("prenom", ""),
|
29 |
+
"date_naissance": data.get("date_naissance", ""),
|
30 |
+
"nationalite": data.get("nationalite", ""),
|
31 |
+
"adresse": data.get("adresse", ""),
|
32 |
+
"contact": data.get("contact_physique", "")
|
33 |
+
}
|
34 |
+
else:
|
35 |
+
# Personne morale
|
36 |
+
author_info = {
|
37 |
+
"nom_societe": data.get("nom_societe", ""),
|
38 |
+
"statut": data.get("statut", ""),
|
39 |
+
"rcs": data.get("rcs", ""),
|
40 |
+
"siege": data.get("siege", ""),
|
41 |
+
"contact": data.get("contact_morale", "")
|
42 |
+
}
|
43 |
+
|
44 |
+
return author_info
|
45 |
+
|
46 |
+
|
47 |
+
def ensure_default_supports(selected_supports):
|
48 |
+
"""
|
49 |
+
S'assure que les supports par défaut sont inclus dans la liste des supports sélectionnés.
|
50 |
+
|
51 |
+
Args:
|
52 |
+
selected_supports (list): Liste des supports sélectionnés par l'utilisateur
|
53 |
+
|
54 |
+
Returns:
|
55 |
+
list: Liste des supports incluant les supports par défaut
|
56 |
+
"""
|
57 |
+
# Création d'une copie de la liste pour ne pas modifier l'original
|
58 |
+
supports = selected_supports.copy() if selected_supports else []
|
59 |
+
|
60 |
+
# Vérification que les supports par défaut sont inclus
|
61 |
+
for default_support in DEFAULT_SUPPORTS:
|
62 |
+
# Vérification que le support n'est pas déjà présent sous une forme quelconque
|
63 |
+
if not any(default_support.lower() in support.lower() for support in supports):
|
64 |
+
supports.append(default_support)
|
65 |
+
|
66 |
+
return supports
|
67 |
+
|
68 |
+
|
69 |
+
def sanitize_text(text):
|
70 |
+
"""
|
71 |
+
Nettoie le texte pour éviter les problèmes d'affichage dans le PDF.
|
72 |
+
|
73 |
+
Args:
|
74 |
+
text (str): Texte à nettoyer
|
75 |
+
|
76 |
+
Returns:
|
77 |
+
str: Texte nettoyé
|
78 |
+
"""
|
79 |
+
if not text:
|
80 |
+
return ""
|
81 |
+
|
82 |
+
# Remplace les caractères spéciaux qui pourraient poser problème
|
83 |
+
text = re.sub(r'[^\x00-\x7F]+', ' ', text)
|
84 |
+
|
85 |
+
# Limite la longueur des lignes pour éviter les débordements
|
86 |
+
text = '\n'.join(line if len(line) < 80 else line[:77] + '...'
|
87 |
+
for line in text.split('\n'))
|
88 |
+
|
89 |
+
return text
|
90 |
+
|
91 |
+
|
92 |
+
def create_temp_file(prefix="contrat_", suffix=".pdf"):
|
93 |
+
"""
|
94 |
+
Crée un fichier temporaire.
|
95 |
+
|
96 |
+
Args:
|
97 |
+
prefix (str): Préfixe du nom du fichier
|
98 |
+
suffix (str): Suffixe du nom du fichier
|
99 |
+
|
100 |
+
Returns:
|
101 |
+
str: Chemin vers le fichier temporaire
|
102 |
+
"""
|
103 |
+
temp_dir = tempfile.gettempdir()
|
104 |
+
filename = f"{prefix}{tempfile.NamedTemporaryFile().name}{suffix}"
|
105 |
+
return os.path.join(temp_dir, os.path.basename(filename))
|
106 |
+
|
107 |
+
|
108 |
+
def format_supports_list(supports):
|
109 |
+
"""
|
110 |
+
Formate la liste des supports pour l'affichage dans le contrat.
|
111 |
+
|
112 |
+
Args:
|
113 |
+
supports (list): Liste des supports
|
114 |
+
|
115 |
+
Returns:
|
116 |
+
str: Liste des supports formatée
|
117 |
+
"""
|
118 |
+
if not supports:
|
119 |
+
return "site web et Discord de Tellers"
|
120 |
+
|
121 |
+
# Formate la liste des supports en une chaîne lisible
|
122 |
+
return ", ".join(supports)
|