Delete app1.py
Browse files
app1.py
DELETED
@@ -1,439 +0,0 @@
|
|
1 |
-
import streamlit as st
|
2 |
-
import pandas as pd
|
3 |
-
import numpy as np
|
4 |
-
import plotly.express as px
|
5 |
-
import plotly.graph_objects as go
|
6 |
-
import os
|
7 |
-
from datetime import datetime, timedelta, date
|
8 |
-
import time
|
9 |
-
import json
|
10 |
-
import google.generativeai as genai
|
11 |
-
from google.generativeai.types import HarmCategory, HarmBlockThreshold
|
12 |
-
|
13 |
-
# Initialize page configuration
|
14 |
-
st.set_page_config(
|
15 |
-
page_title="StartupFinancePilot",
|
16 |
-
page_icon="💰",
|
17 |
-
layout="wide",
|
18 |
-
initial_sidebar_state="expanded"
|
19 |
-
)
|
20 |
-
|
21 |
-
# Custom CSS
|
22 |
-
st.markdown("""
|
23 |
-
<style>
|
24 |
-
.main-header {
|
25 |
-
font-size: 2.5rem;
|
26 |
-
color: #0066cc;
|
27 |
-
margin-bottom: 0.5rem;
|
28 |
-
}
|
29 |
-
.sub-header {
|
30 |
-
font-size: 1.5rem;
|
31 |
-
color: #5c5c5c;
|
32 |
-
margin-bottom: 1.5rem;
|
33 |
-
}
|
34 |
-
.metric-card {
|
35 |
-
background-color: #f8f9fa;
|
36 |
-
border-radius: 10px;
|
37 |
-
padding: 20px;
|
38 |
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
39 |
-
}
|
40 |
-
.metric-label {
|
41 |
-
font-size: 1rem;
|
42 |
-
color: #5c5c5c;
|
43 |
-
}
|
44 |
-
.metric-value {
|
45 |
-
font-size: 1.8rem;
|
46 |
-
color: #0066cc;
|
47 |
-
font-weight: bold;
|
48 |
-
}
|
49 |
-
.good-metric {
|
50 |
-
color: #28a745;
|
51 |
-
}
|
52 |
-
.warning-metric {
|
53 |
-
color: #ffc107;
|
54 |
-
}
|
55 |
-
.danger-metric {
|
56 |
-
color: #dc3545;
|
57 |
-
}
|
58 |
-
.advisor-card {
|
59 |
-
background-color: #f0f7ff;
|
60 |
-
border-radius: 10px;
|
61 |
-
padding: 20px;
|
62 |
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
63 |
-
margin-bottom: 20px;
|
64 |
-
}
|
65 |
-
.advice-text {
|
66 |
-
font-size: 1.1rem;
|
67 |
-
line-height: 1.6;
|
68 |
-
color: #333;
|
69 |
-
}
|
70 |
-
.insight-card {
|
71 |
-
background-color: #f0f8ff;
|
72 |
-
border-left: 4px solid #0066cc;
|
73 |
-
padding: 15px;
|
74 |
-
margin-bottom: 15px;
|
75 |
-
border-radius: 4px;
|
76 |
-
}
|
77 |
-
.ai-badge {
|
78 |
-
background-color: #0066cc;
|
79 |
-
color: white;
|
80 |
-
padding: 3px 10px;
|
81 |
-
border-radius: 10px;
|
82 |
-
font-size: 0.8rem;
|
83 |
-
margin-bottom: 10px;
|
84 |
-
display: inline-block;
|
85 |
-
}
|
86 |
-
.booking-card {
|
87 |
-
background-color: white;
|
88 |
-
border-radius: 10px;
|
89 |
-
padding: 20px;
|
90 |
-
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
91 |
-
margin-bottom: 20px;
|
92 |
-
}
|
93 |
-
.session-type {
|
94 |
-
font-size: 1.2rem;
|
95 |
-
font-weight: bold;
|
96 |
-
color: #0066cc;
|
97 |
-
}
|
98 |
-
.session-duration {
|
99 |
-
color: #5c5c5c;
|
100 |
-
font-size: 0.9rem;
|
101 |
-
}
|
102 |
-
.session-price {
|
103 |
-
font-size: 1.1rem;
|
104 |
-
font-weight: bold;
|
105 |
-
color: #28a745;
|
106 |
-
}
|
107 |
-
</style>
|
108 |
-
""", unsafe_allow_html=True)
|
109 |
-
|
110 |
-
# Constants
|
111 |
-
DEFAULT_GROWTH_RATE = 0.08 # 8% monthly growth
|
112 |
-
DEFAULT_BURN_RATE = 85000 # $85,000 monthly burn
|
113 |
-
ENGINEER_SALARY = 10000 # $10,000 monthly cost per engineer ($120K/year)
|
114 |
-
DEFAULT_MARKETING_BUDGET = 10000 # $10,000 monthly marketing budget
|
115 |
-
|
116 |
-
# Initialize session state variables
|
117 |
-
if 'booked_sessions' not in st.session_state:
|
118 |
-
st.session_state.booked_sessions = []
|
119 |
-
if 'chat_history' not in st.session_state:
|
120 |
-
st.session_state.chat_history = []
|
121 |
-
if 'audio_response' not in st.session_state:
|
122 |
-
st.session_state.audio_response = None
|
123 |
-
if 'insights_cache' not in st.session_state:
|
124 |
-
st.session_state.insights_cache = {}
|
125 |
-
if 'gemini_model' not in st.session_state:
|
126 |
-
st.session_state.gemini_model = None
|
127 |
-
|
128 |
-
# Sample data
|
129 |
-
@st.cache_data
|
130 |
-
def load_sample_data():
|
131 |
-
# TechHealth AI data
|
132 |
-
startup_data = {
|
133 |
-
"name": "TechHealth AI",
|
134 |
-
"stage": "Seed",
|
135 |
-
"founded": "18 months ago",
|
136 |
-
"employees": 12,
|
137 |
-
"last_funding": "$1.2M seed round 10 months ago",
|
138 |
-
"cash": 320000,
|
139 |
-
"burn_rate": 85000,
|
140 |
-
"revenue": 15000,
|
141 |
-
"growth_rate": 0.08
|
142 |
-
}
|
143 |
-
|
144 |
-
# Cash flow history
|
145 |
-
cash_flow_data = {
|
146 |
-
"Month": [f"Month {i}" for i in range(1, 11)],
|
147 |
-
"Revenue": [8000, 8500, 9200, 10000, 10800, 11700, 12600, 13600, 14700, 15800],
|
148 |
-
"Payroll": [60000, 60000, 62000, 62000, 65000, 65000, 70000, 70000, 75000, 75000],
|
149 |
-
"Marketing": [8000, 9000, 10000, 12000, 15000, 18000, 15000, 12000, 10000, 8000],
|
150 |
-
"Office": [5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000],
|
151 |
-
"Software": [3000, 3200, 3500, 3800, 4000, 4200, 4500, 4800, 5000, 5200],
|
152 |
-
"Travel": [2000, 1800, 2500, 3000, 4000, 4500, 3500, 3000, 2500, 2000],
|
153 |
-
"Legal": [1500, 1000, 800, 1200, 800, 2000, 1500, 1000, 3000, 1200],
|
154 |
-
"Misc": [1000, 1200, 1300, 1500, 1700, 1800, 2000, 2200, 2500, 2800]
|
155 |
-
}
|
156 |
-
|
157 |
-
# Add calculated fields
|
158 |
-
df = pd.DataFrame(cash_flow_data)
|
159 |
-
df["Total_Expenses"] = df[["Payroll", "Marketing", "Office", "Software", "Travel", "Legal", "Misc"]].sum(axis=1)
|
160 |
-
df["Net_Burn"] = df["Total_Expenses"] - df["Revenue"]
|
161 |
-
|
162 |
-
# Transaction data
|
163 |
-
transactions = pd.DataFrame([
|
164 |
-
{"Date": "2023-11-05", "Category": "Travel", "Vendor": "Caribbean Cruises", "Amount": 8500, "Description": "Team Retreat Planning", "Flag": "Suspicious"},
|
165 |
-
{"Date": "2023-11-12", "Category": "Marketing", "Vendor": "LuxuryGifts Inc", "Amount": 4200, "Description": "Client Appreciation", "Flag": "Suspicious"},
|
166 |
-
{"Date": "2023-11-22", "Category": "Office", "Vendor": "Premium Furniture", "Amount": 12000, "Description": "Office Upgrades", "Flag": "Suspicious"},
|
167 |
-
{"Date": "2023-11-28", "Category": "Consulting", "Vendor": "Strategic Vision LLC", "Amount": 7500, "Description": "Strategy Consulting", "Flag": "Suspicious"},
|
168 |
-
{"Date": "2023-12-05", "Category": "Software", "Vendor": "Personal Apple Store", "Amount": 3200, "Description": "Development Tools", "Flag": "Suspicious"},
|
169 |
-
{"Date": "2023-12-12", "Category": "Legal", "Vendor": "Anderson Brothers", "Amount": 5800, "Description": "Legal Services", "Flag": "Normal"},
|
170 |
-
{"Date": "2023-12-20", "Category": "Payroll", "Vendor": "November Payroll", "Amount": 75000, "Description": "Monthly Payroll", "Flag": "Normal"},
|
171 |
-
{"Date": "2023-12-22", "Category": "Marketing", "Vendor": "Google Ads", "Amount": 8000, "Description": "Ad Campaign", "Flag": "Normal"},
|
172 |
-
{"Date": "2023-12-25", "Category": "Office", "Vendor": "WeWork", "Amount": 5000, "Description": "Monthly Rent", "Flag": "Normal"},
|
173 |
-
{"Date": "2023-12-28", "Category": "Software", "Vendor": "AWS", "Amount": 5200, "Description": "Cloud Services", "Flag": "Normal"},
|
174 |
-
{"Date": "2024-01-05", "Category": "Travel", "Vendor": "Delta Airlines", "Amount": 1200, "Description": "Client Meeting Travel", "Flag": "Normal"},
|
175 |
-
{"Date": "2024-01-10", "Category": "Marketing", "Vendor": "Facebook Ads", "Amount": 4500, "Description": "Social Media Campaign", "Flag": "Normal"},
|
176 |
-
{"Date": "2024-01-15", "Category": "Software", "Vendor": "Atlassian", "Amount": 2800, "Description": "Development Tools", "Flag": "Normal"},
|
177 |
-
{"Date": "2024-01-20", "Category": "Payroll", "Vendor": "January Payroll", "Amount": 75000, "Description": "Monthly Payroll", "Flag": "Normal"},
|
178 |
-
{"Date": "2024-01-25", "Category": "Office", "Vendor": "WeWork", "Amount": 5000, "Description": "Monthly Rent", "Flag": "Normal"}
|
179 |
-
])
|
180 |
-
|
181 |
-
return startup_data, df, transactions
|
182 |
-
|
183 |
-
# Setup AI Services
|
184 |
-
def setup_genai():
|
185 |
-
"""Initialize and configure Google's Generative AI and list available models"""
|
186 |
-
try:
|
187 |
-
if 'GOOGLE_API_KEY' in st.secrets:
|
188 |
-
genai.configure(api_key=st.secrets['GOOGLE_API_KEY'])
|
189 |
-
|
190 |
-
# Get available models and select one for text generation
|
191 |
-
models = genai.list_models()
|
192 |
-
text_models = [m.name for m in models if 'generateContent' in m.supported_generation_methods]
|
193 |
-
|
194 |
-
if text_models:
|
195 |
-
# Use first available text generation model
|
196 |
-
model_name = text_models[0]
|
197 |
-
st.session_state.gemini_model = model_name
|
198 |
-
return True
|
199 |
-
else:
|
200 |
-
st.warning("No appropriate generative AI models available")
|
201 |
-
# Use a fallback model name for demonstration
|
202 |
-
st.session_state.gemini_model = "gemini-1.5-pro"
|
203 |
-
return False
|
204 |
-
else:
|
205 |
-
st.warning("Google API key not found in secrets. Using simulated AI responses.")
|
206 |
-
st.session_state.gemini_model = "gemini-1.5-pro"
|
207 |
-
return False
|
208 |
-
except Exception as e:
|
209 |
-
st.warning(f"Failed to initialize Gemini: {e}. Using simulated AI responses.")
|
210 |
-
st.session_state.gemini_model = "gemini-1.5-pro"
|
211 |
-
return False
|
212 |
-
|
213 |
-
def generate_ai_response(prompt, simulate=False):
|
214 |
-
"""Generate response from Gemini or simulate one if the API is unavailable"""
|
215 |
-
if simulate:
|
216 |
-
# Simulate AI response with predefined text based on keywords in prompt
|
217 |
-
time.sleep(1) # Simulate processing time
|
218 |
-
|
219 |
-
if "runway" in prompt.lower():
|
220 |
-
return "Based on your current spend rate of $85K/month and revenue growth of 8%, your runway is approximately 3.8 months. I recommend reducing non-essential expenses to extend runway to at least 6 months before your next fundraising round."
|
221 |
-
elif "hire" in prompt.lower() or "hiring" in prompt.lower():
|
222 |
-
return "Adding new hires at this stage would reduce your runway significantly. Consider contracting talent first or postponing hiring until after securing additional funding. Each new engineer costs $10K/month, reducing runway by approximately 3 weeks per hire."
|
223 |
-
elif "marketing" in prompt.lower():
|
224 |
-
return "Your current CAC to LTV ratio doesn't justify increasing marketing spend. Focus on optimizing current channels and improving conversion rates. Once unit economics improve, gradually increase marketing budget by no more than 20% per month."
|
225 |
-
elif "fundraising" in prompt.lower() or "investor" in prompt.lower():
|
226 |
-
return "With less than 4 months of runway, you should begin fundraising preparations immediately. Focus on demonstrating product-market fit and improving key metrics like MRR growth, user retention, and unit economics before approaching investors."
|
227 |
-
elif "suspicious" in prompt.lower() or "transaction" in prompt.lower():
|
228 |
-
return "I've identified several concerning transactions including a $8,500 travel expense and $12,000 in office upgrades. These discretionary expenses represent over 25% of a month's burn and should be reviewed with your finance team immediately."
|
229 |
-
else:
|
230 |
-
return "Based on your financial data, I recommend prioritizing runway extension and focusing on core metrics that demonstrate product-market fit. Consider reducing non-essential expenses by 15-20% to add 1-2 months to your runway before beginning fundraising conversations."
|
231 |
-
else:
|
232 |
-
try:
|
233 |
-
# Use the actual Gemini model
|
234 |
-
model = genai.GenerativeModel(st.session_state.gemini_model)
|
235 |
-
|
236 |
-
generation_config = {
|
237 |
-
"temperature": 0.7,
|
238 |
-
"top_p": 0.95,
|
239 |
-
"top_k": 40,
|
240 |
-
"max_output_tokens": 1024,
|
241 |
-
}
|
242 |
-
|
243 |
-
safety_settings = {
|
244 |
-
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_NONE,
|
245 |
-
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_NONE,
|
246 |
-
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_NONE,
|
247 |
-
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_NONE
|
248 |
-
}
|
249 |
-
|
250 |
-
response = model.generate_content(
|
251 |
-
prompt,
|
252 |
-
generation_config=generation_config,
|
253 |
-
safety_settings=safety_settings
|
254 |
-
)
|
255 |
-
|
256 |
-
return response.text
|
257 |
-
except Exception as e:
|
258 |
-
st.warning(f"Error generating AI response: {e}")
|
259 |
-
# Fall back to simulated response
|
260 |
-
return generate_ai_response(prompt, simulate=True)
|
261 |
-
|
262 |
-
# Financial modeling functions
|
263 |
-
def calculate_runway(initial_cash, monthly_burn, monthly_revenue, growth_rate, months=24):
|
264 |
-
"""Calculate runway based on current burn rate and revenue growth."""
|
265 |
-
dates = [datetime.now() + timedelta(days=30*i) for i in range(months)]
|
266 |
-
df = pd.DataFrame(index=dates, columns=['Cash', 'Revenue', 'Expenses', 'Net_Burn', 'Cumulative_Cash'])
|
267 |
-
|
268 |
-
current_cash = initial_cash
|
269 |
-
current_revenue = monthly_revenue
|
270 |
-
df.iloc[0, df.columns.get_loc('Cash')] = current_cash
|
271 |
-
df.iloc[0, df.columns.get_loc('Revenue')] = current_revenue
|
272 |
-
df.iloc[0, df.columns.get_loc('Expenses')] = monthly_burn
|
273 |
-
df.iloc[0, df.columns.get_loc('Net_Burn')] = monthly_burn - current_revenue
|
274 |
-
df.iloc[0, df.columns.get_loc('Cumulative_Cash')] = current_cash
|
275 |
-
|
276 |
-
runway_months = months
|
277 |
-
for i in range(1, months):
|
278 |
-
current_revenue = current_revenue * (1 + growth_rate)
|
279 |
-
net_burn = monthly_burn - current_revenue
|
280 |
-
current_cash = current_cash - net_burn
|
281 |
-
|
282 |
-
df.iloc[i, df.columns.get_loc('Cash')] = current_cash
|
283 |
-
df.iloc[i, df.columns.get_loc('Revenue')] = current_revenue
|
284 |
-
df.iloc[i, df.columns.get_loc('Expenses')] = monthly_burn
|
285 |
-
df.iloc[i, df.columns.get_loc('Net_Burn')] = net_burn
|
286 |
-
df.iloc[i, df.columns.get_loc('Cumulative_Cash')] = current_cash
|
287 |
-
|
288 |
-
if current_cash <= 0:
|
289 |
-
runway_months = i
|
290 |
-
break
|
291 |
-
|
292 |
-
return runway_months, df
|
293 |
-
|
294 |
-
def simulate_decision(initial_cash, monthly_burn, monthly_revenue, growth_rate,
|
295 |
-
new_expenses=0, new_hires=0, new_marketing=0, growth_impact=0):
|
296 |
-
"""Simulate the impact of a business decision on runway."""
|
297 |
-
# Calculate current runway
|
298 |
-
current_runway, current_df = calculate_runway(initial_cash, monthly_burn, monthly_revenue, growth_rate)
|
299 |
-
|
300 |
-
# Calculate additional expenses
|
301 |
-
additional_expenses = new_expenses + (new_hires * ENGINEER_SALARY) + new_marketing
|
302 |
-
|
303 |
-
# Calculate new runway
|
304 |
-
new_runway, new_df = calculate_runway(
|
305 |
-
initial_cash,
|
306 |
-
monthly_burn + additional_expenses,
|
307 |
-
monthly_revenue,
|
308 |
-
growth_rate + growth_impact
|
309 |
-
)
|
310 |
-
|
311 |
-
return current_runway, new_runway, current_df, new_df
|
312 |
-
|
313 |
-
def detect_suspicious_transactions(transactions_df):
|
314 |
-
"""AI-enhanced suspicious transaction detection."""
|
315 |
-
df = transactions_df.copy()
|
316 |
-
|
317 |
-
# Define thresholds for each category
|
318 |
-
category_thresholds = {
|
319 |
-
"Travel": 3000,
|
320 |
-
"Marketing": 10000,
|
321 |
-
"Office": 7000,
|
322 |
-
"Software": 6000,
|
323 |
-
"Consulting": 5000,
|
324 |
-
"Legal": 6000
|
325 |
-
}
|
326 |
-
|
327 |
-
# Define suspicious terms
|
328 |
-
suspicious_terms = ['luxury', 'cruise', 'premium', 'personal', 'gift']
|
329 |
-
|
330 |
-
# Add suspicious column
|
331 |
-
df['Suspicious'] = False
|
332 |
-
df['Reason'] = ""
|
333 |
-
df['Risk_Score'] = 0
|
334 |
-
|
335 |
-
# Check for suspicious patterns
|
336 |
-
for idx, row in df.iterrows():
|
337 |
-
reasons = []
|
338 |
-
risk_score = 0
|
339 |
-
|
340 |
-
# Check if amount exceeds category threshold
|
341 |
-
if row['Category'] in category_thresholds:
|
342 |
-
if row['Amount'] > category_thresholds[row['Category']]:
|
343 |
-
reasons.append(f"Amount exceeds typical spending for {row['Category']}")
|
344 |
-
risk_score += 30
|
345 |
-
|
346 |
-
# Higher risk for significantly exceeding threshold
|
347 |
-
excess_percentage = (row['Amount'] - category_thresholds[row['Category']]) / category_thresholds[row['Category']] * 100
|
348 |
-
if excess_percentage > 100: # More than double the threshold
|
349 |
-
risk_score += 20
|
350 |
-
|
351 |
-
# Check for suspicious vendors or descriptions
|
352 |
-
if any(term in str(row['Vendor']).lower() for term in suspicious_terms):
|
353 |
-
reasons.append(f"Vendor name contains suspicious term")
|
354 |
-
risk_score += 25
|
355 |
-
|
356 |
-
if any(term in str(row['Description']).lower() for term in suspicious_terms):
|
357 |
-
reasons.append(f"Description contains suspicious term")
|
358 |
-
risk_score += 20
|
359 |
-
|
360 |
-
# Check for rounded amounts (potential indicator of estimation/fabrication)
|
361 |
-
if row['Amount'] % 1000 == 0 and row['Amount'] > 3000:
|
362 |
-
reasons.append(f"Suspiciously round amount")
|
363 |
-
risk_score += 15
|
364 |
-
|
365 |
-
# Mark as suspicious if risk score is high enough
|
366 |
-
if risk_score >= 30:
|
367 |
-
df.at[idx, 'Suspicious'] = True
|
368 |
-
df.at[idx, 'Reason'] = "; ".join(reasons)
|
369 |
-
df.at[idx, 'Risk_Score'] = risk_score
|
370 |
-
|
371 |
-
# Sort by risk score
|
372 |
-
df = df.sort_values(by='Risk_Score', ascending=False)
|
373 |
-
|
374 |
-
return df
|
375 |
-
|
376 |
-
# Import page functions
|
377 |
-
from dashboard_page import render_financial_dashboard, get_runway_analysis, get_fundraising_readiness_analysis
|
378 |
-
from decision_simulator import render_decision_simulator, get_decision_analysis
|
379 |
-
from fund_monitoring import render_fund_monitoring, get_fraud_analysis
|
380 |
-
from financial_advisor import render_ai_financial_advisor, get_advisory_guidance, generate_voice_response
|
381 |
-
from book_session import render_book_session
|
382 |
-
|
383 |
-
# UI Components
|
384 |
-
def create_sidebar():
|
385 |
-
"""Create sidebar with company profile and filters."""
|
386 |
-
st.sidebar.title("StartupFinancePilot")
|
387 |
-
st.sidebar.image("https://img.freepik.com/premium-vector/business-finance-analytics-logo-design-vector-template_67715-552.jpg", width=150)
|
388 |
-
|
389 |
-
# Company profile
|
390 |
-
startup_data, _, _ = load_sample_data()
|
391 |
-
|
392 |
-
st.sidebar.header("Company Profile")
|
393 |
-
st.sidebar.write(f"**{startup_data['name']}**")
|
394 |
-
st.sidebar.write(f"Stage: {startup_data['stage']}")
|
395 |
-
st.sidebar.write(f"Founded: {startup_data['founded']}")
|
396 |
-
st.sidebar.write(f"Employees: {startup_data['employees']}")
|
397 |
-
st.sidebar.write(f"Last Funding: {startup_data['last_funding']}")
|
398 |
-
|
399 |
-
# AI Status
|
400 |
-
has_api = setup_genai()
|
401 |
-
ai_status = "🟢 Connected" if has_api else "🟡 Demo Mode"
|
402 |
-
st.sidebar.write(f"AI Status: {ai_status}")
|
403 |
-
if not has_api:
|
404 |
-
st.sidebar.info("Running in demo mode with simulated AI responses. Add GOOGLE_API_KEY to secrets for full functionality.")
|
405 |
-
|
406 |
-
# App navigation
|
407 |
-
st.sidebar.header("Navigation")
|
408 |
-
page = st.sidebar.radio("Go to", [
|
409 |
-
"Financial Dashboard",
|
410 |
-
"Decision Simulator",
|
411 |
-
"Fund Monitoring",
|
412 |
-
"AI Financial Advisor",
|
413 |
-
"Book a Session"
|
414 |
-
])
|
415 |
-
|
416 |
-
return page
|
417 |
-
|
418 |
-
# Main application
|
419 |
-
def main():
|
420 |
-
# Load sample data
|
421 |
-
startup_data, cash_flow_df, transactions_df = load_sample_data()
|
422 |
-
|
423 |
-
# Create sidebar and get selected page
|
424 |
-
page = create_sidebar()
|
425 |
-
|
426 |
-
# Render selected page
|
427 |
-
if page == "Financial Dashboard":
|
428 |
-
render_financial_dashboard(startup_data, cash_flow_df)
|
429 |
-
elif page == "Decision Simulator":
|
430 |
-
render_decision_simulator(startup_data)
|
431 |
-
elif page == "Fund Monitoring":
|
432 |
-
render_fund_monitoring(transactions_df)
|
433 |
-
elif page == "AI Financial Advisor":
|
434 |
-
render_ai_financial_advisor(startup_data)
|
435 |
-
elif page == "Book a Session":
|
436 |
-
render_book_session()
|
437 |
-
|
438 |
-
if __name__ == "__main__":
|
439 |
-
main()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|