Navada25 commited on
Commit
404da36
·
verified ·
1 Parent(s): 0a0ec2a

Update document_templates.py with stock analysis features

Browse files
Files changed (1) hide show
  1. document_templates.py +833 -0
document_templates.py ADDED
@@ -0,0 +1,833 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Document Template Generation System for NAVADA
2
+ """
3
+ Business document template generation with customizable formats
4
+ for different startup stages and investor needs.
5
+ """
6
+
7
+ import io
8
+ import json
9
+ import datetime
10
+ from typing import Dict, Any, List, Optional
11
+ from reportlab.lib.pagesizes import letter, A4
12
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
13
+ from reportlab.lib.units import inch
14
+ from reportlab.platypus import (
15
+ SimpleDocTemplate, Paragraph, Spacer, PageBreak,
16
+ Table, TableStyle, Image, KeepTogether, ListFlowable, ListItem
17
+ )
18
+ from reportlab.lib import colors
19
+ from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT, TA_JUSTIFY
20
+ from reportlab.pdfgen import canvas
21
+ from reportlab.lib.utils import ImageReader
22
+ import pandas as pd
23
+
24
+ class DocumentTemplateGenerator:
25
+ """Generate professional business documents for startups."""
26
+
27
+ def __init__(self):
28
+ self.styles = self._create_custom_styles()
29
+ self.templates = {
30
+ 'business_case': self.generate_business_case,
31
+ 'pitch_deck': self.generate_pitch_deck_outline,
32
+ 'financial_model': self.generate_financial_model_template,
33
+ 'investor_memo': self.generate_investor_memo,
34
+ 'executive_summary': self.generate_executive_summary,
35
+ 'market_analysis': self.generate_market_analysis,
36
+ 'competitive_analysis': self.generate_competitive_analysis,
37
+ 'go_to_market': self.generate_go_to_market_strategy,
38
+ 'risk_assessment': self.generate_risk_assessment,
39
+ 'term_sheet': self.generate_term_sheet_template
40
+ }
41
+
42
+ def _create_custom_styles(self):
43
+ """Create custom paragraph styles for professional documents."""
44
+ styles = getSampleStyleSheet()
45
+
46
+ # Title style
47
+ styles.add(ParagraphStyle(
48
+ name='CustomTitle',
49
+ parent=styles['Title'],
50
+ fontSize=24,
51
+ textColor=colors.HexColor('#1a1a1a'),
52
+ spaceAfter=30,
53
+ alignment=TA_CENTER
54
+ ))
55
+
56
+ # Heading styles
57
+ styles.add(ParagraphStyle(
58
+ name='CustomHeading1',
59
+ parent=styles['Heading1'],
60
+ fontSize=18,
61
+ textColor=colors.HexColor('#2c3e50'),
62
+ spaceAfter=16,
63
+ spaceBefore=12,
64
+ leftIndent=0,
65
+ fontName='Helvetica-Bold'
66
+ ))
67
+
68
+ styles.add(ParagraphStyle(
69
+ name='CustomHeading2',
70
+ parent=styles['Heading2'],
71
+ fontSize=14,
72
+ textColor=colors.HexColor('#34495e'),
73
+ spaceAfter=12,
74
+ spaceBefore=8,
75
+ leftIndent=10,
76
+ fontName='Helvetica-Bold'
77
+ ))
78
+
79
+ # Body text
80
+ styles.add(ParagraphStyle(
81
+ name='CustomBodyText',
82
+ parent=styles['BodyText'],
83
+ fontSize=11,
84
+ textColor=colors.HexColor('#2c3e50'),
85
+ alignment=TA_JUSTIFY,
86
+ spaceAfter=12,
87
+ leading=16
88
+ ))
89
+
90
+ # Bullet points
91
+ styles.add(ParagraphStyle(
92
+ name='CustomBullet',
93
+ parent=styles['BodyText'],
94
+ fontSize=11,
95
+ leftIndent=20,
96
+ bulletIndent=10,
97
+ spaceAfter=8
98
+ ))
99
+
100
+ return styles
101
+
102
+ def generate_business_case(self, startup_data: Dict[str, Any]) -> bytes:
103
+ """Generate a comprehensive business case document."""
104
+ buffer = io.BytesIO()
105
+ doc = SimpleDocTemplate(
106
+ buffer,
107
+ pagesize=A4,
108
+ rightMargin=72,
109
+ leftMargin=72,
110
+ topMargin=72,
111
+ bottomMargin=72
112
+ )
113
+
114
+ story = []
115
+
116
+ # Cover Page
117
+ story.append(Paragraph(
118
+ f"<b>BUSINESS CASE</b><br/><br/>{startup_data.get('company_name', 'Your Startup')}",
119
+ self.styles['CustomTitle']
120
+ ))
121
+ story.append(Spacer(1, 0.5*inch))
122
+
123
+ # Date
124
+ story.append(Paragraph(
125
+ f"Prepared: {datetime.datetime.now().strftime('%B %d, %Y')}",
126
+ self.styles['Normal']
127
+ ))
128
+ story.append(PageBreak())
129
+
130
+ # Executive Summary
131
+ story.append(Paragraph("EXECUTIVE SUMMARY", self.styles['CustomHeading1']))
132
+ story.append(Paragraph(
133
+ startup_data.get('executive_summary',
134
+ 'This business case outlines the strategic rationale, market opportunity, '
135
+ 'and financial projections for our venture. We address a significant market '
136
+ 'gap with an innovative solution that delivers measurable value to our target customers.'),
137
+ self.styles['CustomBodyText']
138
+ ))
139
+ story.append(Spacer(1, 0.3*inch))
140
+
141
+ # Problem Statement
142
+ story.append(Paragraph("1. PROBLEM STATEMENT", self.styles['CustomHeading1']))
143
+ story.append(Paragraph(
144
+ startup_data.get('problem_statement',
145
+ 'The market currently faces significant challenges that create opportunities '
146
+ 'for innovative solutions. Our research indicates substantial unmet needs '
147
+ 'in our target segment.'),
148
+ self.styles['CustomBodyText']
149
+ ))
150
+
151
+ # Market Pain Points
152
+ pain_points = startup_data.get('pain_points', [
153
+ 'Inefficient current solutions',
154
+ 'High costs for existing alternatives',
155
+ 'Poor user experience',
156
+ 'Lack of integration capabilities'
157
+ ])
158
+
159
+ story.append(Paragraph("Key Pain Points:", self.styles['CustomHeading2']))
160
+ for point in pain_points:
161
+ story.append(Paragraph(f"• {point}", self.styles['CustomBullet']))
162
+ story.append(Spacer(1, 0.3*inch))
163
+
164
+ # Proposed Solution
165
+ story.append(Paragraph("2. PROPOSED SOLUTION", self.styles['CustomHeading1']))
166
+ story.append(Paragraph(
167
+ startup_data.get('solution',
168
+ 'Our solution leverages cutting-edge technology and deep market insights '
169
+ 'to deliver a superior alternative that addresses all identified pain points.'),
170
+ self.styles['CustomBodyText']
171
+ ))
172
+
173
+ # Value Proposition
174
+ story.append(Paragraph("Value Proposition:", self.styles['CustomHeading2']))
175
+ value_props = startup_data.get('value_proposition', [
176
+ '10x improvement in efficiency',
177
+ '50% cost reduction',
178
+ 'Seamless user experience',
179
+ 'Full integration with existing systems'
180
+ ])
181
+
182
+ for prop in value_props:
183
+ story.append(Paragraph(f"• {prop}", self.styles['CustomBullet']))
184
+ story.append(Spacer(1, 0.3*inch))
185
+
186
+ # Market Analysis
187
+ story.append(Paragraph("3. MARKET ANALYSIS", self.styles['CustomHeading1']))
188
+
189
+ # Market Size Table
190
+ market_data = [
191
+ ['Market Segment', 'TAM', 'SAM', 'SOM (Year 3)'],
192
+ ['Primary Market',
193
+ startup_data.get('tam', '$50B'),
194
+ startup_data.get('sam', '$5B'),
195
+ startup_data.get('som', '$100M')],
196
+ ['Growth Rate', '15% CAGR', '20% CAGR', '50% YoY'],
197
+ ]
198
+
199
+ market_table = Table(market_data, colWidths=[2.5*inch, 1.5*inch, 1.5*inch, 1.5*inch])
200
+ market_table.setStyle(TableStyle([
201
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#34495e')),
202
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
203
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
204
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
205
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
206
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
207
+ ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#ecf0f1')),
208
+ ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#bdc3c7'))
209
+ ]))
210
+
211
+ story.append(market_table)
212
+ story.append(Spacer(1, 0.3*inch))
213
+
214
+ # Financial Projections
215
+ story.append(Paragraph("4. FINANCIAL PROJECTIONS", self.styles['CustomHeading1']))
216
+
217
+ financial_data = [
218
+ ['Metric', 'Year 1', 'Year 2', 'Year 3', 'Year 5'],
219
+ ['Revenue', '$500K', '$2.5M', '$10M', '$50M'],
220
+ ['Gross Margin', '60%', '65%', '70%', '75%'],
221
+ ['EBITDA', '-$1M', '-$500K', '$2M', '$15M'],
222
+ ['Cash Flow', '-$1.5M', '-$200K', '$1.5M', '$12M'],
223
+ ]
224
+
225
+ financial_table = Table(financial_data, colWidths=[1.8*inch, 1.2*inch, 1.2*inch, 1.2*inch, 1.2*inch])
226
+ financial_table.setStyle(TableStyle([
227
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#27ae60')),
228
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
229
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
230
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
231
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
232
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
233
+ ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#e8f8f5')),
234
+ ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#27ae60'))
235
+ ]))
236
+
237
+ story.append(financial_table)
238
+ story.append(Spacer(1, 0.3*inch))
239
+
240
+ # Implementation Timeline
241
+ story.append(Paragraph("5. IMPLEMENTATION TIMELINE", self.styles['CustomHeading1']))
242
+
243
+ phases = startup_data.get('timeline', [
244
+ {'phase': 'Phase 1: MVP Development', 'duration': '3 months',
245
+ 'deliverables': 'Core product features, initial user testing'},
246
+ {'phase': 'Phase 2: Market Launch', 'duration': '2 months',
247
+ 'deliverables': 'Go-to-market execution, first customers'},
248
+ {'phase': 'Phase 3: Scale', 'duration': '6 months',
249
+ 'deliverables': 'Product refinement, team expansion, Series A'},
250
+ ])
251
+
252
+ for phase in phases:
253
+ story.append(Paragraph(f"<b>{phase['phase']}</b> ({phase['duration']})",
254
+ self.styles['CustomHeading2']))
255
+ story.append(Paragraph(f"Deliverables: {phase['deliverables']}",
256
+ self.styles['CustomBodyText']))
257
+
258
+ story.append(Spacer(1, 0.3*inch))
259
+
260
+ # Risk Assessment
261
+ story.append(Paragraph("6. RISK ASSESSMENT", self.styles['CustomHeading1']))
262
+
263
+ risks = startup_data.get('risks', [
264
+ {'risk': 'Market Risk', 'impact': 'High', 'mitigation': 'Extensive customer validation and pivoting capability'},
265
+ {'risk': 'Technical Risk', 'impact': 'Medium', 'mitigation': 'Experienced team and proven technology stack'},
266
+ {'risk': 'Competitive Risk', 'impact': 'Medium', 'mitigation': 'First-mover advantage and strong IP protection'},
267
+ {'risk': 'Financial Risk', 'impact': 'High', 'mitigation': 'Conservative burn rate and multiple funding sources'},
268
+ ])
269
+
270
+ risk_data = [['Risk Type', 'Impact', 'Mitigation Strategy']]
271
+ for risk in risks:
272
+ risk_data.append([risk['risk'], risk['impact'], risk['mitigation']])
273
+
274
+ risk_table = Table(risk_data, colWidths=[1.5*inch, 1*inch, 3.5*inch])
275
+ risk_table.setStyle(TableStyle([
276
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#e74c3c')),
277
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
278
+ ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
279
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
280
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
281
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
282
+ ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#fadbd8')),
283
+ ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#e74c3c'))
284
+ ]))
285
+
286
+ story.append(risk_table)
287
+ story.append(PageBreak())
288
+
289
+ # Investment Requirements
290
+ story.append(Paragraph("7. INVESTMENT REQUIREMENTS", self.styles['CustomHeading1']))
291
+
292
+ funding_need = startup_data.get('funding_need', '$2M')
293
+ use_of_funds = startup_data.get('use_of_funds', [
294
+ {'category': 'Product Development', 'allocation': '40%', 'amount': '$800K'},
295
+ {'category': 'Sales & Marketing', 'allocation': '30%', 'amount': '$600K'},
296
+ {'category': 'Operations', 'allocation': '20%', 'amount': '$400K'},
297
+ {'category': 'Reserve', 'allocation': '10%', 'amount': '$200K'},
298
+ ])
299
+
300
+ story.append(Paragraph(
301
+ f"<b>Total Funding Required:</b> {funding_need}",
302
+ self.styles['CustomBodyText']
303
+ ))
304
+ story.append(Spacer(1, 0.2*inch))
305
+
306
+ story.append(Paragraph("Use of Funds:", self.styles['CustomHeading2']))
307
+
308
+ funds_data = [['Category', 'Allocation', 'Amount']]
309
+ for fund in use_of_funds:
310
+ funds_data.append([fund['category'], fund['allocation'], fund['amount']])
311
+
312
+ funds_table = Table(funds_data, colWidths=[2.5*inch, 1.5*inch, 1.5*inch])
313
+ funds_table.setStyle(TableStyle([
314
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#3498db')),
315
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
316
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
317
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
318
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
319
+ ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
320
+ ('BACKGROUND', (0, 1), (-1, -1), colors.HexColor('#ebf5fb')),
321
+ ('GRID', (0, 0), (-1, -1), 1, colors.HexColor('#3498db'))
322
+ ]))
323
+
324
+ story.append(funds_table)
325
+ story.append(Spacer(1, 0.3*inch))
326
+
327
+ # Expected Returns
328
+ story.append(Paragraph("Expected Returns:", self.styles['CustomHeading2']))
329
+ story.append(Paragraph(
330
+ f"• Target IRR: {startup_data.get('target_irr', '35%')}<br/>"
331
+ f"• Exit Timeline: {startup_data.get('exit_timeline', '5-7 years')}<br/>"
332
+ f"• Exit Multiple: {startup_data.get('exit_multiple', '10x')}<br/>",
333
+ self.styles['CustomBodyText']
334
+ ))
335
+
336
+ # Conclusion
337
+ story.append(Paragraph("8. CONCLUSION", self.styles['CustomHeading1']))
338
+ story.append(Paragraph(
339
+ startup_data.get('conclusion',
340
+ 'This business case demonstrates a compelling opportunity with strong '
341
+ 'fundamentals, clear market demand, and a capable team. The financial '
342
+ 'projections show a path to profitability and significant returns for investors. '
343
+ 'We are positioned to capture a meaningful share of a large and growing market.'),
344
+ self.styles['CustomBodyText']
345
+ ))
346
+
347
+ # Next Steps
348
+ story.append(Paragraph("Next Steps:", self.styles['CustomHeading2']))
349
+ next_steps = startup_data.get('next_steps', [
350
+ 'Finalize investment terms',
351
+ 'Complete due diligence process',
352
+ 'Execute growth strategy',
353
+ 'Achieve key milestones'
354
+ ])
355
+
356
+ for step in next_steps:
357
+ story.append(Paragraph(f"• {step}", self.styles['CustomBullet']))
358
+
359
+ # Build PDF
360
+ doc.build(story)
361
+ buffer.seek(0)
362
+ return buffer.getvalue()
363
+
364
+ def generate_pitch_deck_outline(self, startup_data: Dict[str, Any]) -> bytes:
365
+ """Generate a pitch deck outline document."""
366
+ buffer = io.BytesIO()
367
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
368
+ story = []
369
+
370
+ # Title
371
+ story.append(Paragraph(
372
+ f"<b>PITCH DECK OUTLINE</b><br/><br/>{startup_data.get('company_name', 'Your Startup')}",
373
+ self.styles['CustomTitle']
374
+ ))
375
+ story.append(PageBreak())
376
+
377
+ # Slide structure
378
+ slides = [
379
+ {
380
+ 'number': '1',
381
+ 'title': 'Title Slide',
382
+ 'content': [
383
+ 'Company name and logo',
384
+ 'Tagline/Value proposition',
385
+ 'Contact information'
386
+ ],
387
+ 'tips': 'Keep it clean and professional. First impressions matter.'
388
+ },
389
+ {
390
+ 'number': '2',
391
+ 'title': 'Problem',
392
+ 'content': [
393
+ 'Clear problem statement',
394
+ 'Who experiences this problem',
395
+ 'Current solutions and their shortcomings',
396
+ 'Market pain points'
397
+ ],
398
+ 'tips': 'Make it relatable. Use real examples and stories.'
399
+ },
400
+ {
401
+ 'number': '3',
402
+ 'title': 'Solution',
403
+ 'content': [
404
+ 'Your unique solution',
405
+ 'Key features and benefits',
406
+ 'Product demo or screenshots',
407
+ 'Technology advantage'
408
+ ],
409
+ 'tips': 'Show, don\'t just tell. Use visuals and demos when possible.'
410
+ },
411
+ {
412
+ 'number': '4',
413
+ 'title': 'Market Opportunity',
414
+ 'content': [
415
+ 'TAM, SAM, SOM analysis',
416
+ 'Market growth trends',
417
+ 'Target customer segments',
418
+ 'Geographic expansion potential'
419
+ ],
420
+ 'tips': 'Use credible sources. Show bottom-up market sizing.'
421
+ },
422
+ {
423
+ 'number': '5',
424
+ 'title': 'Business Model',
425
+ 'content': [
426
+ 'Revenue streams',
427
+ 'Pricing strategy',
428
+ 'Customer acquisition cost (CAC)',
429
+ 'Lifetime value (LTV)',
430
+ 'Unit economics'
431
+ ],
432
+ 'tips': 'Be specific about how you make money. Show proven metrics if available.'
433
+ },
434
+ {
435
+ 'number': '6',
436
+ 'title': 'Traction',
437
+ 'content': [
438
+ 'Key metrics and KPIs',
439
+ 'Customer testimonials',
440
+ 'Revenue growth',
441
+ 'User growth',
442
+ 'Partnerships'
443
+ ],
444
+ 'tips': 'Use charts and graphs. Show month-over-month growth.'
445
+ },
446
+ {
447
+ 'number': '7',
448
+ 'title': 'Competition',
449
+ 'content': [
450
+ 'Competitive landscape',
451
+ 'Your unique advantages',
452
+ 'Barriers to entry',
453
+ 'Positioning matrix'
454
+ ],
455
+ 'tips': 'Be honest about competition. Show why you\'ll win.'
456
+ },
457
+ {
458
+ 'number': '8',
459
+ 'title': 'Go-to-Market Strategy',
460
+ 'content': [
461
+ 'Customer acquisition channels',
462
+ 'Sales strategy',
463
+ 'Marketing plan',
464
+ 'Partnership strategy'
465
+ ],
466
+ 'tips': 'Show you understand your customers and how to reach them.'
467
+ },
468
+ {
469
+ 'number': '9',
470
+ 'title': 'Team',
471
+ 'content': [
472
+ 'Founder backgrounds',
473
+ 'Key team members',
474
+ 'Advisory board',
475
+ 'Key investors'
476
+ ],
477
+ 'tips': 'Highlight relevant experience and past successes.'
478
+ },
479
+ {
480
+ 'number': '10',
481
+ 'title': 'Financial Projections',
482
+ 'content': [
483
+ '3-5 year revenue projections',
484
+ 'Path to profitability',
485
+ 'Key assumptions',
486
+ 'Burn rate and runway'
487
+ ],
488
+ 'tips': 'Be realistic but ambitious. Show key drivers of growth.'
489
+ },
490
+ {
491
+ 'number': '11',
492
+ 'title': 'The Ask',
493
+ 'content': [
494
+ 'Funding amount',
495
+ 'Use of funds',
496
+ 'Milestones to be achieved',
497
+ 'Expected timeline'
498
+ ],
499
+ 'tips': 'Be specific about what you need and what you\'ll accomplish.'
500
+ },
501
+ {
502
+ 'number': '12',
503
+ 'title': 'Contact/Q&A',
504
+ 'content': [
505
+ 'Contact details',
506
+ 'Website and social media',
507
+ 'Next steps',
508
+ 'Q&A prompt'
509
+ ],
510
+ 'tips': 'End with a clear call to action.'
511
+ }
512
+ ]
513
+
514
+ for slide in slides:
515
+ story.append(Paragraph(
516
+ f"<b>Slide {slide['number']}: {slide['title']}</b>",
517
+ self.styles['CustomHeading1']
518
+ ))
519
+
520
+ story.append(Paragraph("Content:", self.styles['CustomHeading2']))
521
+ for item in slide['content']:
522
+ story.append(Paragraph(f"• {item}", self.styles['CustomBullet']))
523
+
524
+ story.append(Paragraph("💡 Tips:", self.styles['CustomHeading2']))
525
+ story.append(Paragraph(slide['tips'], self.styles['CustomBodyText']))
526
+
527
+ story.append(Spacer(1, 0.3*inch))
528
+
529
+ # Build PDF
530
+ doc.build(story)
531
+ buffer.seek(0)
532
+ return buffer.getvalue()
533
+
534
+ def generate_financial_model_template(self, startup_data: Dict[str, Any]) -> bytes:
535
+ """Generate a financial model template document."""
536
+ buffer = io.BytesIO()
537
+ doc = SimpleDocTemplate(buffer, pagesize=A4)
538
+ story = []
539
+
540
+ # Title
541
+ story.append(Paragraph(
542
+ f"<b>FINANCIAL MODEL TEMPLATE</b><br/><br/>{startup_data.get('company_name', 'Your Startup')}",
543
+ self.styles['CustomTitle']
544
+ ))
545
+ story.append(PageBreak())
546
+
547
+ # Revenue Model
548
+ story.append(Paragraph("REVENUE MODEL", self.styles['CustomHeading1']))
549
+
550
+ # Add revenue assumptions table
551
+ revenue_assumptions = [
552
+ ['Parameter', 'Year 1', 'Year 2', 'Year 3', 'Notes'],
553
+ ['Customer Acquisition', '100', '500', '2000', 'Based on marketing spend'],
554
+ ['Avg. Revenue/Customer', '$500', '$600', '$750', 'Price increases with value'],
555
+ ['Churn Rate', '10%', '8%', '5%', 'Improving retention'],
556
+ ['Upsell Rate', '20%', '30%', '40%', 'Product expansion']
557
+ ]
558
+
559
+ revenue_table = Table(revenue_assumptions)
560
+ revenue_table.setStyle(TableStyle([
561
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#2ecc71')),
562
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
563
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
564
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
565
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
566
+ ('GRID', (0, 0), (-1, -1), 1, colors.grey)
567
+ ]))
568
+
569
+ story.append(revenue_table)
570
+ story.append(Spacer(1, 0.3*inch))
571
+
572
+ # Cost Structure
573
+ story.append(Paragraph("COST STRUCTURE", self.styles['CustomHeading1']))
574
+
575
+ cost_structure = [
576
+ ['Cost Category', 'Year 1', 'Year 2', 'Year 3', '% of Revenue'],
577
+ ['Personnel', '$500K', '$1.5M', '$3M', '30-40%'],
578
+ ['Marketing', '$200K', '$750K', '$2M', '20-25%'],
579
+ ['Technology', '$150K', '$300K', '$500K', '5-10%'],
580
+ ['Operations', '$100K', '$250K', '$500K', '5-10%'],
581
+ ['G&A', '$50K', '$200K', '$500K', '5%']
582
+ ]
583
+
584
+ cost_table = Table(cost_structure)
585
+ cost_table.setStyle(TableStyle([
586
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#e74c3c')),
587
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
588
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
589
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
590
+ ('FONTSIZE', (0, 0), (-1, 0), 10),
591
+ ('GRID', (0, 0), (-1, -1), 1, colors.grey)
592
+ ]))
593
+
594
+ story.append(cost_table)
595
+
596
+ # Build PDF
597
+ doc.build(story)
598
+ buffer.seek(0)
599
+ return buffer.getvalue()
600
+
601
+ def generate_investor_memo(self, startup_data: Dict[str, Any]) -> bytes:
602
+ """Generate an investor memorandum."""
603
+ buffer = io.BytesIO()
604
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
605
+ story = []
606
+
607
+ # Title Page
608
+ story.append(Paragraph(
609
+ "<b>INVESTMENT MEMORANDUM</b>",
610
+ self.styles['CustomTitle']
611
+ ))
612
+ story.append(Spacer(1, 0.3*inch))
613
+ story.append(Paragraph(
614
+ f"{startup_data.get('company_name', 'Your Startup')}",
615
+ self.styles['CustomTitle']
616
+ ))
617
+ story.append(Spacer(1, 0.5*inch))
618
+ story.append(Paragraph(
619
+ "CONFIDENTIAL - NOT FOR DISTRIBUTION",
620
+ self.styles['Normal']
621
+ ))
622
+ story.append(Paragraph(
623
+ f"Prepared: {datetime.datetime.now().strftime('%B %Y')}",
624
+ self.styles['Normal']
625
+ ))
626
+ story.append(PageBreak())
627
+
628
+ # Investment Highlights
629
+ story.append(Paragraph("INVESTMENT HIGHLIGHTS", self.styles['CustomHeading1']))
630
+
631
+ highlights = startup_data.get('highlights', [
632
+ 'Large and growing addressable market ($50B+ TAM)',
633
+ 'Proven business model with strong unit economics',
634
+ 'Experienced team with relevant domain expertise',
635
+ 'Clear path to profitability within 24 months',
636
+ 'Strategic partnerships with industry leaders',
637
+ 'Proprietary technology with defensible moat'
638
+ ])
639
+
640
+ for highlight in highlights:
641
+ story.append(Paragraph(f"✓ {highlight}", self.styles['CustomBullet']))
642
+
643
+ story.append(Spacer(1, 0.3*inch))
644
+
645
+ # Investment Terms
646
+ story.append(Paragraph("INVESTMENT TERMS", self.styles['CustomHeading1']))
647
+
648
+ terms_data = [
649
+ ['Parameter', 'Terms'],
650
+ ['Round Type', startup_data.get('round_type', 'Series A')],
651
+ ['Target Raise', startup_data.get('target_raise', '$10M')],
652
+ ['Pre-Money Valuation', startup_data.get('pre_money', '$40M')],
653
+ ['Minimum Investment', startup_data.get('minimum', '$250K')],
654
+ ['Use of Funds', 'Product (40%), Sales (30%), Ops (20%), Reserve (10%)'],
655
+ ['Expected Close', startup_data.get('close_date', 'Q2 2024')]
656
+ ]
657
+
658
+ terms_table = Table(terms_data, colWidths=[2*inch, 4*inch])
659
+ terms_table.setStyle(TableStyle([
660
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#3498db')),
661
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
662
+ ('ALIGN', (0, 0), (-1, -1), 'LEFT'),
663
+ ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
664
+ ('GRID', (0, 0), (-1, -1), 1, colors.grey)
665
+ ]))
666
+
667
+ story.append(terms_table)
668
+
669
+ # Build PDF
670
+ doc.build(story)
671
+ buffer.seek(0)
672
+ return buffer.getvalue()
673
+
674
+ def generate_executive_summary(self, startup_data: Dict[str, Any]) -> bytes:
675
+ """Generate an executive summary document."""
676
+ buffer = io.BytesIO()
677
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
678
+ story = []
679
+
680
+ # Header
681
+ story.append(Paragraph(
682
+ f"<b>EXECUTIVE SUMMARY</b><br/><br/>{startup_data.get('company_name', 'Your Startup')}",
683
+ self.styles['CustomTitle']
684
+ ))
685
+ story.append(Spacer(1, 0.5*inch))
686
+
687
+ # Company Overview
688
+ story.append(Paragraph("Company Overview", self.styles['CustomHeading1']))
689
+ story.append(Paragraph(
690
+ startup_data.get('overview',
691
+ 'We are building the next generation platform that transforms how businesses '
692
+ 'operate in the digital economy. Our solution addresses critical pain points '
693
+ 'with innovative technology and a customer-centric approach.'),
694
+ self.styles['CustomBodyText']
695
+ ))
696
+ story.append(Spacer(1, 0.2*inch))
697
+
698
+ # Mission & Vision
699
+ story.append(Paragraph("Mission & Vision", self.styles['CustomHeading1']))
700
+ story.append(Paragraph(
701
+ f"<b>Mission:</b> {startup_data.get('mission', 'To democratize access to advanced technology solutions')}",
702
+ self.styles['CustomBodyText']
703
+ ))
704
+ story.append(Paragraph(
705
+ f"<b>Vision:</b> {startup_data.get('vision', 'To become the global leader in our category by 2030')}",
706
+ self.styles['CustomBodyText']
707
+ ))
708
+ story.append(Spacer(1, 0.2*inch))
709
+
710
+ # Key Metrics
711
+ story.append(Paragraph("Key Metrics", self.styles['CustomHeading1']))
712
+
713
+ metrics = [
714
+ ['Metric', 'Current', 'Target (12mo)'],
715
+ ['ARR', '$2M', '$10M'],
716
+ ['Customers', '50', '200'],
717
+ ['NPS Score', '72', '80+'],
718
+ ['Gross Margin', '65%', '75%']
719
+ ]
720
+
721
+ metrics_table = Table(metrics)
722
+ metrics_table.setStyle(TableStyle([
723
+ ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#27ae60')),
724
+ ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
725
+ ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
726
+ ('GRID', (0, 0), (-1, -1), 1, colors.grey)
727
+ ]))
728
+
729
+ story.append(metrics_table)
730
+
731
+ # Build PDF
732
+ doc.build(story)
733
+ buffer.seek(0)
734
+ return buffer.getvalue()
735
+
736
+ def generate_market_analysis(self, startup_data: Dict[str, Any]) -> bytes:
737
+ """Generate a market analysis report."""
738
+ # Implementation similar to above templates
739
+ pass
740
+
741
+ def generate_competitive_analysis(self, startup_data: Dict[str, Any]) -> bytes:
742
+ """Generate a competitive analysis document."""
743
+ # Implementation similar to above templates
744
+ pass
745
+
746
+ def generate_go_to_market_strategy(self, startup_data: Dict[str, Any]) -> bytes:
747
+ """Generate a go-to-market strategy document."""
748
+ # Implementation similar to above templates
749
+ pass
750
+
751
+ def generate_risk_assessment(self, startup_data: Dict[str, Any]) -> bytes:
752
+ """Generate a risk assessment document."""
753
+ # Implementation similar to above templates
754
+ pass
755
+
756
+ def generate_term_sheet_template(self, startup_data: Dict[str, Any]) -> bytes:
757
+ """Generate a term sheet template."""
758
+ buffer = io.BytesIO()
759
+ doc = SimpleDocTemplate(buffer, pagesize=letter)
760
+ story = []
761
+
762
+ # Title
763
+ story.append(Paragraph(
764
+ "<b>TERM SHEET</b>",
765
+ self.styles['CustomTitle']
766
+ ))
767
+ story.append(Spacer(1, 0.2*inch))
768
+ story.append(Paragraph(
769
+ f"{startup_data.get('company_name', 'Your Startup, Inc.')}",
770
+ self.styles['CustomTitle']
771
+ ))
772
+ story.append(Spacer(1, 0.3*inch))
773
+ story.append(Paragraph(
774
+ f"Series {startup_data.get('series', 'A')} Preferred Stock Financing",
775
+ self.styles['Normal']
776
+ ))
777
+ story.append(Spacer(1, 0.5*inch))
778
+
779
+ # Terms
780
+ terms = [
781
+ ('Issuer', startup_data.get('company_name', 'Company, Inc.')),
782
+ ('Investors', startup_data.get('lead_investor', 'Lead Investor') + ' and other investors'),
783
+ ('Amount Raised', startup_data.get('amount', '$10,000,000')),
784
+ ('Pre-Money Valuation', startup_data.get('pre_money', '$40,000,000')),
785
+ ('Post-Money Valuation', startup_data.get('post_money', '$50,000,000')),
786
+ ('Price Per Share', startup_data.get('price_per_share', '$1.00')),
787
+ ('Liquidation Preference', '1x non-participating'),
788
+ ('Dividend', '8% cumulative dividend'),
789
+ ('Anti-Dilution', 'Weighted average broad-based'),
790
+ ('Voting Rights', '1 vote per share, vote together with common'),
791
+ ('Board Composition', '5 members: 2 founders, 2 investors, 1 independent'),
792
+ ('Protective Provisions', 'Standard Series A provisions'),
793
+ ('Registration Rights', 'Standard demand and piggyback rights'),
794
+ ('Right of First Refusal', 'Company and investors'),
795
+ ('Drag Along', 'Standard drag along provisions'),
796
+ ('Vesting', 'Founders: 4 years with 1-year cliff'),
797
+ ('Employee Pool', '15% post-financing'),
798
+ ('Closing', startup_data.get('closing', '30 days from signing'))
799
+ ]
800
+
801
+ for term, value in terms:
802
+ story.append(Paragraph(
803
+ f"<b>{term}:</b> {value}",
804
+ self.styles['CustomBodyText']
805
+ ))
806
+ story.append(Spacer(1, 0.1*inch))
807
+
808
+ # Legal Notice
809
+ story.append(Spacer(1, 0.5*inch))
810
+ story.append(Paragraph(
811
+ "This term sheet is non-binding except for confidentiality, exclusivity, and governing law provisions.",
812
+ self.styles['Italic']
813
+ ))
814
+
815
+ # Build PDF
816
+ doc.build(story)
817
+ buffer.seek(0)
818
+ return buffer.getvalue()
819
+
820
+ def list_available_templates(self) -> List[str]:
821
+ """Return list of available document templates."""
822
+ return list(self.templates.keys())
823
+
824
+ def generate_document(self, template_type: str, startup_data: Dict[str, Any]) -> bytes:
825
+ """Generate a document based on the specified template type."""
826
+ if template_type not in self.templates:
827
+ raise ValueError(f"Unknown template type: {template_type}")
828
+
829
+ return self.templates[template_type](startup_data)
830
+
831
+
832
+ # Export the class
833
+ __all__ = ['DocumentTemplateGenerator']