diff --git a/create_startup.php b/create_startup.php index 057a98b..13e802a 100644 --- a/create_startup.php +++ b/create_startup.php @@ -126,7 +126,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { cofounder_equity_pct = ?, cofounder_equity_type = ?, cofounder_responsibilities = ?, desired_cofounder_experience = ?, cofounder_commitment = ?, other_partnership_details = ?, current_cash_balance = ?, burn_rate = ?, doc_income_statements = ?, doc_balance_sheets = ?, doc_cash_flow_statements = ?, doc_revenue_breakdown = ?, doc_gross_margin = ?, - recommended_return_rate = ?, recommended_return_reasoning = ?, founder_return_rate = ? + recommended_return_rate = ?, recommended_return_reasoning = ?, founder_return_rate = ?, repayment_term = ? WHERE id = ? AND founder_id = ?"); $stmt->execute([ @@ -135,7 +135,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $current_cash_balance, $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'], - $recommended_return_rate, $recommended_return_reasoning, $founder_return_rate, + $recommended_return_rate, $recommended_return_reasoning, $founder_return_rate, $repayment_term, $existingStartup['id'], $_SESSION['user_id'] ]); $final_id = $existingStartup['id']; @@ -145,7 +145,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { cofounder_equity_pct, cofounder_equity_type, cofounder_responsibilities, desired_cofounder_experience, cofounder_commitment, other_partnership_details, current_cash_balance, burn_rate, doc_income_statements, doc_balance_sheets, doc_cash_flow_statements, doc_revenue_breakdown, doc_gross_margin, - founder_id, recommended_return_rate, recommended_return_reasoning, founder_return_rate, status + founder_id, recommended_return_rate, recommended_return_reasoning, founder_return_rate, repayment_term, status ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'private')"); $stmt->execute([ @@ -290,6 +290,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+
+ + " min="1" max="60" required style="width: 100%; padding: 12px; border-radius: 8px; background: #222; border: 1px solid var(--accent-color); color: #fff; font-size: 16px; font-weight: 700;"> + The duration over which you will repay the investment plus interest. +
Your proposed annual dividend yield. The platform also computes a recommendation based on your financials. diff --git a/dashboard.php b/dashboard.php index c0ddad0..3a192c9 100644 --- a/dashboard.php +++ b/dashboard.php @@ -6,6 +6,8 @@ if (!isset($_SESSION['user_id'])) { } require_once __DIR__ . '/db/config.php'; +require_once __DIR__ . "/sync_funding.php"; +syncRepayments(); $stmt = db()->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); @@ -17,14 +19,12 @@ if (!$user) { exit; } -// Security: Check if verified if ($user['verified'] == 0) { session_destroy(); header("Location: login.php?error=not_verified"); exit; } -// Check if onboarding is complete if ($user['role'] === 'founder' && $user['onboarding_completed'] == 0) { header("Location: founder_onboarding.php"); exit; @@ -32,10 +32,7 @@ if ($user['role'] === 'founder' && $user['onboarding_completed'] == 0) { $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby'; -// Identify Trending Startups (Top 3 in followers or funding) $trendingIds = []; - -// Top 3 Followed $stmt = db()->prepare(" SELECT s.id FROM startups s @@ -48,7 +45,6 @@ $stmt->execute(); $topFollowed = $stmt->fetchAll(PDO::FETCH_COLUMN); $trendingIds = array_merge($trendingIds, $topFollowed); -// Top 3 Funded (Total) $stmt = db()->prepare(" SELECT id FROM startups @@ -59,9 +55,15 @@ $stmt->execute(); $topFunded = $stmt->fetchAll(PDO::FETCH_COLUMN); $trendingIds = array_unique(array_merge($trendingIds, $topFunded)); -// Fetch user's data based on role $myStartups = []; $myInvestments = []; +$repaymentSummary = [ + 'total_raised' => 0, + 'total_obligation' => 0, + 'monthly_outgoing' => 0, + 'active_investors' => 0, + 'next_payment_date' => null +]; if ($user['role'] === 'founder') { $stmt = db()->prepare(" @@ -73,6 +75,21 @@ if ($user['role'] === 'founder') { "); $stmt->execute([$_SESSION['user_id']]); $myStartups = $stmt->fetchAll(); + + // Repayment Summary Calculation + $stmt = db()->prepare(" + SELECT + SUM(i.amount) as total_raised, + SUM(i.total_return) as total_obligation, + SUM(CASE WHEN i.status = 'approved' THEN i.monthly_dividend ELSE 0 END) as monthly_outgoing, + COUNT(DISTINCT CASE WHEN i.status = 'approved' THEN i.investor_id END) as active_investors, + MIN(CASE WHEN i.status = 'approved' THEN i.next_payment_date END) as next_payment_date + FROM investments i + JOIN startups s ON i.startup_id = s.id + WHERE s.founder_id = ? + "); + $stmt->execute([$_SESSION['user_id']]); + $repaymentSummary = $stmt->fetch(); } else { $stmt = db()->prepare("SELECT i.*, s.name as startup_name FROM investments i JOIN startups s ON i.startup_id = s.id WHERE i.investor_id = ? ORDER BY i.created_at DESC"); $stmt->execute([$_SESSION['user_id']]); @@ -104,8 +121,6 @@ function number_get_formatted($num) { .profile-link-card:hover { transform: translateY(-2px); } - - /* Modal Styles */ .modal { display: none; position: fixed; @@ -117,6 +132,26 @@ function number_get_formatted($num) { background-color: rgba(0,0,0,0.9); backdrop-filter: blur(4px); } + .repayment-stat-card { + background: rgba(255,255,255,0.03); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: 20px; + text-align: left; + } + .repayment-stat-label { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--text-secondary); + font-weight: 700; + margin-bottom: 8px; + } + .repayment-stat-value { + font-size: 20px; + font-weight: 900; + color: #fff; + } @@ -167,6 +202,35 @@ function number_get_formatted($num) {

Your command center for the next big thing.

+ + +
+

Funding & Repayment Overview

+
+
+
Total Raised
+
£
+
+
+
Total Obligation
+
£
+
+
+
Monthly Outgoing
+
£
+
+
+
Active Investors
+
+
+
+
Next Due Date
+
+
+
+
+ +
@@ -433,7 +497,6 @@ function updateRound(roundId, status) { } } -// Close modal when clicking outside window.onclick = function(event) { const modal = document.getElementById('wallet-modal'); if (event.target == modal) { @@ -443,4 +506,4 @@ window.onclick = function(event) { - \ No newline at end of file + diff --git a/db/migrations/20_repayment_system.sql b/db/migrations/20_repayment_system.sql new file mode 100644 index 0000000..c539717 --- /dev/null +++ b/db/migrations/20_repayment_system.sql @@ -0,0 +1,16 @@ +-- Migration: Repayment and Dividend System + +-- 1. Add repayment_term to startups table +ALTER TABLE startups ADD COLUMN repayment_term INT DEFAULT 12 AFTER founder_return_rate; + +-- 2. Update investments table with locked terms and payment tracking +ALTER TABLE investments +ADD COLUMN interest_rate DECIMAL(5, 2) AFTER amount, +ADD COLUMN repayment_term INT AFTER interest_rate, +ADD COLUMN total_return DECIMAL(15, 2) AFTER repayment_term, +ADD COLUMN monthly_dividend DECIMAL(15, 2) AFTER total_return, +ADD COLUMN paid_amount DECIMAL(15, 2) DEFAULT 0.00 AFTER monthly_dividend, +ADD COLUMN next_payment_date DATE AFTER paid_amount; + +-- 3. Update status enum in investments table +ALTER TABLE investments MODIFY COLUMN status ENUM('pending', 'approved', 'rejected', 'completed') DEFAULT 'pending'; diff --git a/discover.php b/discover.php index f0f94ff..1a529da 100644 --- a/discover.php +++ b/discover.php @@ -209,13 +209,13 @@ $browseStartups = $stmt->fetchAll(); $isFollowing = in_array($s['id'], $followedStartups); ?>
-
-
+
+
-
-
by
+
+
by
-

+

...

-
- - - - £ + +
+
+
Rate
+
%
+
+
+
Term
+
Mo
+
+
+ +
+ + £ Raised
@@ -298,4 +308,4 @@ document.querySelectorAll('.follow-btn').forEach(btn => { - \ No newline at end of file + diff --git a/funding_rounds.php b/funding_rounds.php index d8f5775..1eb890e 100644 --- a/funding_rounds.php +++ b/funding_rounds.php @@ -104,18 +104,18 @@ $activeRounds = $stmt->fetchAll(); £ Secured %
-
+
-
Platform Yield
-
%
+
Return Rate
+
%
-
Founder Yield
-
+
Term
+
Months
@@ -137,4 +137,4 @@ $activeRounds = $stmt->fetchAll(); - \ No newline at end of file + diff --git a/invest.php b/invest.php index 069e73c..aea4b3e 100644 --- a/invest.php +++ b/invest.php @@ -43,8 +43,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $investor_id = $_SESSION['user_id']; $remaining = $startup['funding_goal'] - $startup['funding_raised']; - if ($amount <= 0) { - $error = "Please enter a valid investment amount."; + if ($amount < 50) { + $error = "Minimum investment is £50."; } elseif ($amount > $investor_balance) { $error = "Insufficient funds in your money pot. Please add funds first."; } elseif ($amount > $remaining) { @@ -52,11 +52,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } else { db()->beginTransaction(); try { + // Repayment & Dividend Logic + $interest_rate = (float)($startup['founder_return_rate'] ?? 0); + $repayment_term = (int)($startup['repayment_term'] ?? 12); + if ($repayment_term <= 0) $repayment_term = 12; + + $total_return = $amount + ($amount * ($interest_rate / 100)); + $monthly_dividend = $total_return / $repayment_term; + + // First payment is one month after investment date + $next_payment_date = date('Y-m-d', strtotime('+1 month')); + // 1. Create investment record $equity_pct = 0.00; // Mock logic for equity - $stmt = db()->prepare("INSERT INTO investments (startup_id, investor_id, funding_round_id, amount, equity_pct, status) VALUES (?, ?, ?, ?, ?, 'approved')"); - $stmt->execute([$startupId, $investor_id, $startup['round_id'], $amount, $equity_pct]); + $stmt = db()->prepare("INSERT INTO investments ( + startup_id, investor_id, funding_round_id, amount, interest_rate, repayment_term, total_return, monthly_dividend, next_payment_date, equity_pct, status + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'approved')"); + $stmt->execute([ + $startupId, $investor_id, $startup['round_id'], $amount, + $interest_rate, $repayment_term, $total_return, $monthly_dividend, $next_payment_date, + $equity_pct + ]); // 2. Update funding_rounds raised amount $stmt = db()->prepare("UPDATE funding_rounds SET funding_raised = funding_raised + ? WHERE id = ?"); @@ -76,7 +93,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $stmt->execute([$amount, $startup['founder_id']]); db()->commit(); - $success = "Investment of £" . number_format($amount, 2) . " confirmed successfully! Funds moved to the founder's pot."; + $success = "Investment of £" . number_format($amount, 2) . " confirmed successfully! Repayment schedule: £" . number_format($monthly_dividend, 2) . "/month for $repayment_term months."; header("refresh:3;url=portfolio.php"); } catch (Exception $e) { db()->rollBack(); @@ -129,18 +146,16 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
- Funding Goal - £ + Interest Rate + %
- Already Raised - £ + Repayment Term + Months
-
- Remaining + Remaining Allocation + £
@@ -148,8 +163,9 @@ $platformName = defined('PLATFORM_NAME') ? PLATFORM_NAME : 'Gatsby';
- +

The minimum investment is £50. Terms are locked upon confirmation.

- + \ No newline at end of file diff --git a/portfolio.php b/portfolio.php index 46ea260..3a1969d 100644 --- a/portfolio.php +++ b/portfolio.php @@ -1,5 +1,7 @@ fetchAll(); $totalInvested = 0; foreach ($myInvestments as $inv) { - if ($inv['status'] === 'approved') { + if ($inv['status'] === 'approved' || $inv['status'] === 'completed') { $totalInvested += $inv['amount']; } } @@ -43,7 +45,30 @@ foreach ($myInvestments as $inv) {