From 66df8a0207d713ce6a1abf311d169b4f91c967ae Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 28 Feb 2026 19:20:33 +0000 Subject: [PATCH] v28 --- create_startup.php | 347 ++++++++++++++++++ dashboard.php | 4 +- db/migrations/12_detailed_startup_profile.sql | 24 ++ start_funding.php | 226 ------------ start_funding_round.php | 138 +++++++ startup_details.php | 208 +++++------ startups.php | 2 +- 7 files changed, 609 insertions(+), 340 deletions(-) create mode 100644 create_startup.php create mode 100644 db/migrations/12_detailed_startup_profile.sql delete mode 100644 start_funding.php create mode 100644 start_funding_round.php diff --git a/create_startup.php b/create_startup.php new file mode 100644 index 0000000..03650ab --- /dev/null +++ b/create_startup.php @@ -0,0 +1,347 @@ + 0) { + $stmt = db()->prepare("SELECT * FROM startups WHERE id = ? AND founder_id = ?"); + $stmt->execute([$startup_id, $_SESSION['user_id']]); + $existingStartup = $stmt->fetch(); +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + // Basic Info + $name = trim($_POST['name'] ?? ''); + $legal_name = trim($_POST['legal_name'] ?? ''); + $country = trim($_POST['country'] ?? ''); + $industry = trim($_POST['industry'] ?? ''); + $sub_industry = trim($_POST['sub_industry'] ?? ''); + $business_model = trim($_POST['business_model'] ?? ''); + $product_service = trim($_POST['product_service'] ?? ''); + $operational_stage = trim($_POST['operational_stage'] ?? ''); + + // Equity Structure + $total_shares = (int)($_POST['total_shares'] ?? 0); + $share_classes = trim($_POST['share_classes'] ?? ''); + $founder_ownership = trim($_POST['founder_ownership'] ?? ''); + $investor_ownership = trim($_POST['investor_ownership'] ?? ''); + $esop_percentage = (float)($_POST['esop_percentage'] ?? 0); + $convertible_instruments = trim($_POST['convertible_instruments'] ?? ''); + + // Current Financials + $current_cash_balance = (float)($_POST['current_cash_balance'] ?? 0); + $outstanding_debt = trim($_POST['outstanding_debt'] ?? ''); + $accounts_receivable_payable = trim($_POST['accounts_receivable_payable'] ?? ''); + $burn_rate = (float)($_POST['burn_rate'] ?? 0); + + // File Uploads + $upload_dir = 'assets/docs/financials/'; + if (!is_dir($upload_dir)) { + mkdir($upload_dir, 0775, true); + } + + $doc_fields = [ + 'doc_income_statements', + 'doc_balance_sheets', + 'doc_cash_flow_statements', + 'doc_revenue_breakdown', + 'doc_gross_margin', + 'doc_opex_breakdown' + ]; + + $uploaded_paths = []; + foreach ($doc_fields as $field) { + if (isset($_FILES[$field]) && $_FILES[$field]['error'] === UPLOAD_ERR_OK) { + $file_ext = pathinfo($_FILES[$field]['name'], PATHINFO_EXTENSION); + $file_name = uniqid($field . '_', true) . '.' . $file_ext; + $dest_path = $upload_dir . $file_name; + if (move_uploaded_file($_FILES[$field]['tmp_name'], $dest_path)) { + $uploaded_paths[$field] = $dest_path; + } else { + $error = "Failed to upload $field."; + break; + } + } elseif ($existingStartup && !empty($existingStartup[$field])) { + $uploaded_paths[$field] = $existingStartup[$field]; + } else { + $error = "The financial document for $field is mandatory."; + break; + } + } + + if (!$error) { + if (empty($name) || empty($legal_name) || empty($country) || empty($industry) || empty($business_model) || empty($product_service) || empty($operational_stage)) { + $error = "Please fill in all mandatory company information fields."; + } + } + + if (!$error) { + db()->beginTransaction(); + try { + // Compute AI Recommended Return Rate + $recommended_return_rate = $existingStartup['recommended_return_rate'] ?? 0.0; + + // Re-calculate only if it's a new startup or if financials changed significantly (simplified: always re-calc if it's a POST) + $prompt = "As a financial analyst, calculate a recommended annual dividend yield (interest percentage) based on this startup profile: + Name: {$name} + Industry: {$industry}/{$sub_industry} + Business Model: {$business_model} + Product: {$product_service} + Stage: {$operational_stage} + Cash Balance: £{$current_cash_balance} + Burn Rate: £{$burn_rate} + + Respond ONLY with a JSON object: {\"recommended_rate\": X.X}"; + + $aiResponse = LocalAIApi::createResponse([ + 'input' => [ + ['role' => 'system', 'content' => 'You are a financial analyst. Return JSON only.'], + ['role' => 'user', 'content' => $prompt], + ], + ]); + + if (!empty($aiResponse['success'])) { + $decoded = LocalAIApi::decodeJsonFromResponse($aiResponse); + $recommended_return_rate = (float)($decoded['recommended_rate'] ?? 5.0); + } + + if ($existingStartup) { + $stmt = db()->prepare("UPDATE startups SET + name = ?, legal_name = ?, country = ?, industry = ?, sub_industry = ?, business_model = ?, product_service = ?, operational_stage = ?, + total_shares = ?, share_classes = ?, founder_ownership = ?, investor_ownership = ?, esop_percentage = ?, convertible_instruments = ?, + current_cash_balance = ?, outstanding_debt = ?, accounts_receivable_payable = ?, burn_rate = ?, + doc_income_statements = ?, doc_balance_sheets = ?, doc_cash_flow_statements = ?, doc_revenue_breakdown = ?, doc_gross_margin = ?, doc_opex_breakdown = ?, + recommended_return_rate = ? + WHERE id = ? AND founder_id = ?"); + + $stmt->execute([ + $name, $legal_name, $country, $industry, $sub_industry, $business_model, $product_service, $operational_stage, + $total_shares, $share_classes, $founder_ownership, $investor_ownership, $esop_percentage, $convertible_instruments, + $current_cash_balance, $outstanding_debt, $accounts_receivable_payable, $burn_rate, + $uploaded_paths['doc_income_statements'], $uploaded_paths['doc_balance_sheets'], $uploaded_paths['doc_cash_flow_statements'], + $uploaded_paths['doc_revenue_breakdown'], $uploaded_paths['doc_gross_margin'], $uploaded_paths['doc_opex_breakdown'], + $recommended_return_rate, $existingStartup['id'], $_SESSION['user_id'] + ]); + $final_id = $existingStartup['id']; + } else { + $stmt = db()->prepare("INSERT INTO startups ( + name, legal_name, country, industry, sub_industry, business_model, product_service, operational_stage, + total_shares, share_classes, founder_ownership, investor_ownership, esop_percentage, convertible_instruments, + current_cash_balance, outstanding_debt, accounts_receivable_payable, burn_rate, + doc_income_statements, doc_balance_sheets, doc_cash_flow_statements, doc_revenue_breakdown, doc_gross_margin, doc_opex_breakdown, + founder_id, recommended_return_rate, status + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')"); + + $stmt->execute([ + $name, $legal_name, $country, $industry, $sub_industry, $business_model, $product_service, $operational_stage, + $total_shares, $share_classes, $founder_ownership, $investor_ownership, $esop_percentage, $convertible_instruments, + $current_cash_balance, $outstanding_debt, $accounts_receivable_payable, $burn_rate, + $uploaded_paths['doc_income_statements'], $uploaded_paths['doc_balance_sheets'], $uploaded_paths['doc_cash_flow_statements'], + $uploaded_paths['doc_revenue_breakdown'], $uploaded_paths['doc_gross_margin'], $uploaded_paths['doc_opex_breakdown'], + $_SESSION['user_id'], $recommended_return_rate + ]); + $final_id = db()->lastInsertId(); + } + + db()->commit(); + $success = "Startup profile saved successfully! Recommended return rate: " . number_format($recommended_return_rate, 2) . "%ற்றில்"; + header("refresh:2;url=startup_details.php?id=" . $final_id); + } catch (Exception $e) { + db()->rollBack(); + $error = "Error: " . $e->getMessage(); + } + } +} + +$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; +?> + + + + + + <?= $existingStartup ? 'Edit Profile' : 'Step 1: Setup Startup Profile' ?> — <?= htmlspecialchars($platformName) ?> + + + + + + +
+
+

+

+ +

+ + +
+ +
+ + + +
+ +
+ +
+ +

1. Basic Company Information

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+ +

2. Equity Structure Information

+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +

3. Mandatory Financials

+ +
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ +

Historical Financial Documentation (PDF/Images)

+
+ 'Income Statements', + 'doc_balance_sheets' => 'Balance Sheets', + 'doc_cash_flow_statements' => 'Cash Flow Statements', + 'doc_revenue_breakdown' => 'Revenue Breakdown', + 'doc_gross_margin' => 'Gross Margin Data', + 'doc_opex_breakdown' => 'OpEx Breakdown' + ]; + foreach ($doc_labels as $f_name => $label): + ?> +
+ + accept=".pdf,image/*"> + + Already uploaded + +
+ +
+ + + Cancel +
+ +
+
+ + + + + diff --git a/dashboard.php b/dashboard.php index 21b5eef..2666c0e 100644 --- a/dashboard.php +++ b/dashboard.php @@ -163,14 +163,14 @@ function number_get_formatted($num) {

My Ventures

- + Launch Startup + + Launch Startup

Ready to share your vision with the world?

- Start Your First Round + Start Your First Round
diff --git a/db/migrations/12_detailed_startup_profile.sql b/db/migrations/12_detailed_startup_profile.sql new file mode 100644 index 0000000..7d7c7f2 --- /dev/null +++ b/db/migrations/12_detailed_startup_profile.sql @@ -0,0 +1,24 @@ +-- Migration: Add detailed startup profile fields +ALTER TABLE startups +ADD COLUMN legal_name VARCHAR(255) AFTER name, +ADD COLUMN country VARCHAR(100) AFTER legal_name, +ADD COLUMN sub_industry VARCHAR(100) AFTER industry, +ADD COLUMN business_model TEXT AFTER sub_industry, +ADD COLUMN product_service TEXT AFTER business_model, +ADD COLUMN operational_stage VARCHAR(100) AFTER product_service, +ADD COLUMN total_shares BIGINT AFTER operational_stage, +ADD COLUMN share_classes TEXT AFTER total_shares, +ADD COLUMN founder_ownership TEXT AFTER share_classes, +ADD COLUMN investor_ownership TEXT AFTER founder_ownership, +ADD COLUMN esop_percentage DECIMAL(5,2) AFTER investor_ownership, +ADD COLUMN convertible_instruments TEXT AFTER esop_percentage, +ADD COLUMN current_cash_balance DECIMAL(15,2) AFTER convertible_instruments, +ADD COLUMN outstanding_debt TEXT AFTER current_cash_balance, +ADD COLUMN accounts_receivable_payable TEXT AFTER outstanding_debt, +ADD COLUMN burn_rate DECIMAL(15,2) AFTER accounts_receivable_payable, +ADD COLUMN doc_income_statements VARCHAR(255) AFTER financial_doc_path, +ADD COLUMN doc_balance_sheets VARCHAR(255) AFTER doc_income_statements, +ADD COLUMN doc_cash_flow_statements VARCHAR(255) AFTER doc_balance_sheets, +ADD COLUMN doc_revenue_breakdown VARCHAR(255) AFTER doc_cash_flow_statements, +ADD COLUMN doc_gross_margin VARCHAR(255) AFTER doc_revenue_breakdown, +ADD COLUMN doc_opex_breakdown VARCHAR(255) AFTER doc_gross_margin; diff --git a/start_funding.php b/start_funding.php deleted file mode 100644 index 19985db..0000000 --- a/start_funding.php +++ /dev/null @@ -1,226 +0,0 @@ - 0) { - $stmt = db()->prepare("SELECT * FROM startups WHERE id = ? AND founder_id = ?"); - $stmt->execute([$startup_id, $_SESSION['user_id']]); - $existingStartup = $stmt->fetch(); - - if (!$existingStartup) { - header("Location: startups.php"); - exit; - } - - // Check if there is already an active round - $stmt = db()->prepare("SELECT id FROM funding_rounds WHERE startup_id = ? AND status = 'Active'"); - $stmt->execute([$startup_id]); - if ($stmt->fetch()) { - header("Location: startup_details.php?id=" . $startup_id); - exit; - } -} - -if ($_SERVER['REQUEST_METHOD'] === 'POST') { - $name = trim($_POST['name'] ?? ''); - $description = trim($_POST['description'] ?? ''); - $industry = trim($_POST['industry'] ?? ''); - $equity_structure = trim($_POST['equity_structure'] ?? ''); - $target = (float)($_POST['funding_target'] ?? 0); - $status = $_POST['status'] ?? 'public'; - $founder_return_rate = isset($_POST['founder_return_rate']) && $_POST['founder_return_rate'] !== '' ? (float)$_POST['founder_return_rate'] : null; - - // Financial Document Upload - $financial_doc_path = ''; - if (isset($_FILES['financial_doc']) && $_FILES['financial_doc']['error'] === UPLOAD_ERR_OK) { - $upload_dir = 'assets/docs/financials/'; - if (!is_dir($upload_dir)) { - mkdir($upload_dir, 0775, true); - } - $file_ext = pathinfo($_FILES['financial_doc']['name'], PATHINFO_EXTENSION); - $file_name = uniqid('fin_', true) . '.' . $file_ext; - $dest_path = $upload_dir . $file_name; - - if (move_uploaded_file($_FILES['financial_doc']['tmp_name'], $dest_path)) { - $financial_doc_path = $dest_path; - } else { - $error = "Failed to upload financial documentation."; - } - } elseif (!$existingStartup) { - $error = "Financial documentation is mandatory for new startups."; - } - - if (!$error) { - if ((!$existingStartup && (empty($name) || empty($description) || empty($industry) || empty($equity_structure) || empty($financial_doc_path))) || $target < 50) { - $error = "Please fill in all required fields and upload financial documents. Minimum target is £50."; - } else { - // AI Calculation for Recommended Return Rate - $recommended_return_rate = 5.0; // Default fallback - - $prompt = "As a financial analyst for a startup investment platform, calculate a recommended annual dividend yield (interest percentage) for the following startup. - Startup Name: {$name} - Industry: {$industry} - Description: {$description} - Funding Target: £{$target} - Equity Structure: {$equity_structure} - - Respond ONLY with a JSON object containing a single key 'recommended_rate' with a numeric value (percentage). Example: {\"recommended_rate\": 8.5}"; - - $aiResponse = LocalAIApi::createResponse([ - 'input' => [['role' => 'system', 'content' => 'You are a professional financial analyst. Return JSON only.'], - ['role' => 'user', 'content' => $prompt], - ], - ]); - - if (!empty($aiResponse['success'])) { - $decoded = LocalAIApi::decodeJsonFromResponse($aiResponse); - if (isset($decoded['recommended_rate'])) { - $recommended_return_rate = (float)$decoded['recommended_rate']; - } - } - - db()->beginTransaction(); - try { - if ($existingStartup) { - // Update existing startup with new return rates if provided - $stmt = db()->prepare("UPDATE startups SET recommended_return_rate = ?, founder_return_rate = ? WHERE id = ?"); - $stmt->execute([$recommended_return_rate, $founder_return_rate, $existingStartup['id']]); - - // Create a new round - $stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')"); - $stmt->execute([$existingStartup['id'], $target]); - $final_id = $existingStartup['id']; - } else { - // 1. Insert startup with new fields - $stmt = db()->prepare("INSERT INTO startups (name, description, industry, equity_structure, financial_doc_path, founder_id, funding_target, status, recommended_return_rate, founder_return_rate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - $stmt->execute([$name, $description, $industry, $equity_structure, $financial_doc_path, $_SESSION['user_id'], $target, $status, $recommended_return_rate, $founder_return_rate]); - $new_startup_id = db()->lastInsertId(); - - // 2. Insert initial funding round - $stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')"); - $stmt->execute([$new_startup_id, $target]); - $final_id = $new_startup_id; - } - - db()->commit(); - $success = "Startup successfully listed with a recommended return rate of " . number_format($recommended_return_rate, 2) . "%!"; - header("refresh:3;url=startup_details.php?id=" . $final_id); - } catch (PDOException $e) { - db()->rollBack(); - $error = "Database error: " . $e->getMessage(); - } - } - } -} - -$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; -?> - - - - - - <?= $existingStartup ? 'Start New Round' : 'Launch Startup' ?> — <?= htmlspecialchars($platformName) ?> - - - - - - -
-

-

- -

- - -
- -
- - - -
- -
- -
- -
-
- - -
-
- - -
-
- -
- - -
- -
- - -
- -
- - - Upload revenue statements, projections, or balance sheets. -
- -
- - -
- - -
-
- - -
-
- - -
-
- - - Cancel -
- -
- - - diff --git a/start_funding_round.php b/start_funding_round.php new file mode 100644 index 0000000..9e72754 --- /dev/null +++ b/start_funding_round.php @@ -0,0 +1,138 @@ +prepare("SELECT * FROM startups WHERE id = ? AND founder_id = ?"); +$stmt->execute([$startup_id, $_SESSION['user_id']]); +$startup = $stmt->fetch(); + +if (!$startup) { + header("Location: dashboard.php"); + exit; +} + +// Check for existing active round +$stmt = db()->prepare("SELECT id FROM funding_rounds WHERE startup_id = ? AND status = 'Active'"); +$stmt->execute([$startup_id]); +if ($stmt->fetch()) { + header("Location: startup_details.php?id=" . $startup_id); + exit; +} + +$error = ''; +$success = ''; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $goal = (float)($_POST['funding_goal'] ?? 0); + $founder_rate = isset($_POST['founder_return_rate']) && $_POST['founder_return_rate'] !== '' ? (float)$_POST['founder_return_rate'] : null; + $status = $_POST['listing_status'] ?? 'public'; + + if ($goal < 100) { + $error = "Minimum funding goal is £100."; + } + + if (!$error) { + db()->beginTransaction(); + try { + // Update startup with round-specific settings + $stmt = db()->prepare("UPDATE startups SET status = ?, founder_return_rate = ? WHERE id = ?"); + $stmt->execute([$status, $founder_rate, $startup_id]); + + // Create the round + $stmt = db()->prepare("INSERT INTO funding_rounds (startup_id, funding_goal, status) VALUES (?, ?, 'Active')"); + $stmt->execute([$startup_id, $goal]); + + db()->commit(); + $success = "Funding round launched successfully!"; + header("refresh:2;url=startup_details.php?id=" . $startup_id); + } catch (Exception $e) { + db()->rollBack(); + $error = "Error: " . $e->getMessage(); + } + } +} + +$platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; +?> + + + + + + Step 2: Start Funding Round — <?= htmlspecialchars($platformName) ?> + + + + + + +
+
+

Step 2: Launch Funding Round

+

+ Set your investment targets and return rates for . +

+ + +
+ +
+ + + +
+ +
+ +
+
AI Recommended Return Rate
+
%
+
Based on your company profile and historical financials.
+
+ +
+
+ + +
+ +
+ + + + This is the annual return rate you propose to investors. It will be displayed alongside the platform recommendation. + +
+ +
+ + +
+ + + Cancel +
+ +
+
+ + + diff --git a/startup_details.php b/startup_details.php index e1e4b1b..b5a5dc4 100644 --- a/startup_details.php +++ b/startup_details.php @@ -164,6 +164,15 @@ if ($canSeeHistory) { + @@ -215,10 +224,11 @@ if ($canSeeHistory) {

-
- - Founded - +
+ + + () +
@@ -235,16 +245,77 @@ if ($canSeeHistory) {
-

About the Venture

-

+

About the Venture

+
+

Business Model

+

+
+
+

Product/Service

+

+
- -
-

Equity Structure

-

-
- +
+

Equity Structure

+
+
+
Total Shares
+
+
+
+
ESOP Pool
+
%
+
+
+
+
+
Founder Ownership
+
+
+
+
Investor Ownership
+
+
+
+
+
Convertible Instruments
+
+
+
+ +
+

Financial Position & Docs

+
+
+
Current Cash Balance
+
£
+
+
+
Monthly Burn Rate
+
£
+
+
+ +

Historical Documentation

+
+ $startup['doc_income_statements'], + 'Balance Sheets' => $startup['doc_balance_sheets'], + 'Cash Flow' => $startup['doc_cash_flow_statements'], + 'Revenue Breakdown' => $startup['doc_revenue_breakdown'], + 'Gross Margin' => $startup['doc_gross_margin'], + 'OpEx Breakdown' => $startup['doc_opex_breakdown'] + ]; + foreach ($docs as $label => $path): if ($path): + ?> + + + + +
+
@@ -255,7 +326,7 @@ if ($canSeeHistory) {
Platform Recommendation
%
-
Based on financial analysis & industry benchmarks
+
AI analysis based on uploaded financials
Founder's Proposal
@@ -270,25 +341,18 @@ if ($canSeeHistory) {
-

- Funding History -

+

Funding History

- -

No investment history available yet.

+

No investment history available yet.

-
- - - - - +
+
@@ -296,12 +360,7 @@ if ($canSeeHistory) {
-
- £ -
-
- -
+
£
@@ -309,66 +368,6 @@ if ($canSeeHistory) {
- -
-
-

Public Updates

- - - -
- - - - - - prepare("SELECT * FROM startup_updates WHERE startup_id = ? ORDER BY created_at DESC"); - $stmt->execute([$startup_id]); - $updates = $stmt->fetchAll(); - ?> - -

No updates have been posted yet.

- - -
-

-
- Posted on -
-

-
- - -
@@ -390,16 +389,10 @@ if ($canSeeHistory) {
Followers
-
Seed
+
Stage
- - - - View Financial Docs - - @@ -426,17 +419,14 @@ if ($canSeeHistory) { -
- This is your active funding round. Share the link with potential investors to reach your goal. -
-
+ - +
-
+ - +
@@ -446,8 +436,8 @@ if ($canSeeHistory) {

No Active Round

-

Ready to raise more capital?

- Start New Round +

Ready to raise capital?

+ Start New Round
@@ -476,14 +466,10 @@ if ($canSeeHistory) { - + \ No newline at end of file diff --git a/startups.php b/startups.php index a47f04a..4b345d7 100644 --- a/startups.php +++ b/startups.php @@ -178,7 +178,7 @@ if ($user['role'] === 'founder') {
View Details - +