From e7b0fae1b39c96c59a1d2d9184af6d0c3f797fdf Mon Sep 17 00:00:00 2001 From: Satyam-Rastogi Date: Mon, 11 May 2026 18:56:04 +0530 Subject: [PATCH] Gross, Net Profit calculate --- src/data/mockStore.jsx | 24 ++++++ src/pages/owner/OwnerProjectDetail.jsx | 107 ++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 9 deletions(-) diff --git a/src/data/mockStore.jsx b/src/data/mockStore.jsx index 0382e58..f10e536 100644 --- a/src/data/mockStore.jsx +++ b/src/data/mockStore.jsx @@ -2011,6 +2011,8 @@ const MOCK_PROJECTS = [ spent: 22500, variancePercent: -50.0, margin: 0.40, + commission: 4500, + additionalExpenses: 1200, startDate: '2026-01-20', endDate: '2026-03-05', completionPercentage: 55, @@ -2084,6 +2086,8 @@ const MOCK_PROJECTS = [ spent: 8500, variancePercent: 0, margin: 0.35, + commission: 850, + additionalExpenses: 350, startDate: '2025-11-15', endDate: '2025-12-10', completionPercentage: 100, @@ -2130,6 +2134,8 @@ const MOCK_PROJECTS = [ spent: 18400, variancePercent: -42.5, margin: 0.30, + commission: 3200, + additionalExpenses: 900, startDate: '2026-01-06', endDate: '2026-02-28', completionPercentage: 42, @@ -2202,6 +2208,8 @@ const MOCK_PROJECTS = [ spent: 62300, variancePercent: 13.3, margin: -0.13, + commission: 5500, + additionalExpenses: 3800, startDate: '2025-12-01', endDate: '2026-02-28', completionPercentage: 78, @@ -2285,6 +2293,8 @@ const MOCK_PROJECTS = [ spent: 14200, variancePercent: -49.3, margin: 0.25, + commission: 2800, + additionalExpenses: 600, startDate: '2026-01-06', endDate: '2026-02-20', completionPercentage: 38, @@ -2355,6 +2365,8 @@ const MOCK_PROJECTS = [ spent: 5600, variancePercent: -69.7, margin: 0.38, + commission: 1850, + additionalExpenses: 450, startDate: '2026-02-03', endDate: '2026-03-15', completionPercentage: 22, @@ -2404,6 +2416,8 @@ const MOCK_PROJECTS = [ spent: 48000, variancePercent: -61.6, margin: 0.35, + commission: 12500, + additionalExpenses: 2800, startDate: '2026-01-27', endDate: '2026-04-15', completionPercentage: 32, @@ -2495,6 +2509,8 @@ const MOCK_PROJECTS = [ spent: 91500, variancePercent: 22.0, margin: -0.22, + commission: 7500, + additionalExpenses: 4200, startDate: '2025-11-18', endDate: '2026-02-28', completionPercentage: 88, @@ -2542,6 +2558,8 @@ const MOCK_PROJECTS = [ budget: 42000, spent: 25800, margin: 0.28, + commission: 4200, + additionalExpenses: 1100, startDate: '2026-01-13', endDate: '2026-03-10', completionPercentage: 50, @@ -2587,6 +2605,8 @@ const MOCK_PROJECTS = [ budget: 35000, spent: 35000, margin: 0.30, + commission: 3500, + additionalExpenses: 800, startDate: '2025-09-15', endDate: '2025-10-28', completionPercentage: 100, @@ -2632,6 +2652,8 @@ const MOCK_PROJECTS = [ budget: 95000, spent: 68400, margin: 0.20, + commission: 9500, + additionalExpenses: 5200, startDate: '2025-12-08', endDate: '2026-03-20', completionPercentage: 62, @@ -2685,6 +2707,8 @@ const MOCK_PROJECTS = [ budget: 58000, spent: 22600, margin: 0.32, + commission: 5800, + additionalExpenses: 1500, startDate: '2026-01-13', endDate: '2026-04-01', completionPercentage: 28, diff --git a/src/pages/owner/OwnerProjectDetail.jsx b/src/pages/owner/OwnerProjectDetail.jsx index 1a61d7d..2f52522 100644 --- a/src/pages/owner/OwnerProjectDetail.jsx +++ b/src/pages/owner/OwnerProjectDetail.jsx @@ -12,7 +12,7 @@ import { ArrowLeft, CheckCircle, Clock, AlertTriangle, PauseCircle, ShieldAlert, FileText, DollarSign, GitPullRequest, AlertCircle, Activity, Milestone, Shield, ChevronRight, Phone, MessageSquare, Mail, AlertOctagon, TrendingUp, Key, Zap, Camera, Plus, Map, User, Crosshair, Image as ImageIcon, MapPin, - Upload, Trash2, Eye, Pencil, X as XIcon, FolderOpen, Download, File, StickyNote, Banknote, ChevronLeft, ChevronDown as ChevronDownIcon + Upload, Trash2, Eye, Pencil, X as XIcon, FolderOpen, Download, File, StickyNote, Banknote, ChevronLeft, ChevronDown as ChevronDownIcon, Info } from 'lucide-react'; import ChangeOrderDrawer from '../../components/owner/ChangeOrderDrawer'; import InvoiceDetailModal from '../../components/owner/InvoiceDetailModal'; @@ -220,6 +220,18 @@ const OwnerProjectDetail = () => { projects.find(p => p.id === projectId && p.ownerId === user?.id) , [projects, projectId, user]); + const profitMetrics = useMemo(() => { + if (!project) return { totalCosts: 0, commission: 0, additionalExp: 0, grossProfit: 0, netProfit: 0, grossMargin: 0, netMargin: 0 }; + const totalCosts = Number(project.actualCost ?? project.spent) || 0; + const commission = Number(project.commission) || 0; + const additionalExp = Number(project.additionalExpenses) || 0; + const gross = totalReceived - totalCosts; + const net = gross - commission - additionalExp; + const grossMargin = totalReceived > 0 ? (gross / totalReceived) * 100 : 0; + const netMargin = totalReceived > 0 ? (net / totalReceived) * 100 : 0; + return { totalCosts, commission, additionalExp, grossProfit: gross, netProfit: net, grossMargin, netMargin }; + }, [project, totalReceived]); + if (!project) { return (
@@ -905,22 +917,99 @@ const OwnerProjectDetail = () => { {/* PAYMENTS TAB */} {activeTab === 'payments' && (
- {/* Summary Row */} -
+ {/* Financial Summary Row */} +
{formatCurrency(totalReceived)}
Total Received
-
{payments.length}
-
Payments
+
{formatCurrency(profitMetrics.totalCosts)}
+
Total Costs
-
- {payments.length > 0 ? [...payments].sort((a, b) => b.date.localeCompare(a.date))[0].date : '—'} -
-
Latest Payment
+
{formatCurrency(profitMetrics.commission)}
+
Commission
+ +
{formatCurrency(profitMetrics.additionalExp)}
+
Addl. Expenses
+
+
+ + {/* Profit Summary Cards */} +
+ {/* Gross Profit */} + = 0 ? "rgba(57, 255, 20, 0.12)" : "rgba(255, 0, 60, 0.12)"} + innerClassName="!p-5" + > +
+
+ = 0 ? NEON_GREEN : NEON_RED} /> +

Gross Profit

+
+
+ +
+

Gross Profit Formula

+

Total Received − Total Actual Costs

+
+

{formatCurrency(totalReceived)} − {formatCurrency(profitMetrics.totalCosts)}

+

= {formatCurrency(profitMetrics.grossProfit)}

+
+
+
+
+
= 0 ? NEON_GREEN : NEON_RED}`}> + {profitMetrics.grossProfit >= 0 ? '+' : ''}{formatCurrency(profitMetrics.grossProfit)} +
+
+ = 0 + ? 'text-green-600 dark:text-[#39ff14] bg-green-50 dark:bg-[#39ff14]/10 border border-green-200 dark:border-[#39ff14]/20' + : 'text-red-600 dark:text-[#ff003c] bg-red-50 dark:bg-[#ff003c]/10 border border-red-200 dark:border-[#ff003c]/20' + }`}> + {profitMetrics.grossMargin >= 0 ? '+' : ''}{profitMetrics.grossMargin.toFixed(1)}% margin + +
+
+ + {/* Net Profit */} + = 0 ? "rgba(57, 255, 20, 0.12)" : "rgba(255, 0, 60, 0.12)"} + innerClassName="!p-5" + > +
+
+ = 0 ? NEON_GREEN : NEON_RED} /> +

Net Profit

+
+
+ +
+

Net Profit Formula

+

Gross Profit − Commission − Addl. Expenses

+
+

{formatCurrency(profitMetrics.grossProfit)} − {formatCurrency(profitMetrics.commission)} − {formatCurrency(profitMetrics.additionalExp)}

+

= {formatCurrency(profitMetrics.netProfit)}

+
+
+
+
+
= 0 ? NEON_GREEN : NEON_RED}`}> + {profitMetrics.netProfit >= 0 ? '+' : ''}{formatCurrency(profitMetrics.netProfit)} +
+
+ = 0 + ? 'text-green-600 dark:text-[#39ff14] bg-green-50 dark:bg-[#39ff14]/10 border border-green-200 dark:border-[#39ff14]/20' + : 'text-red-600 dark:text-[#ff003c] bg-red-50 dark:bg-[#ff003c]/10 border border-red-200 dark:border-[#ff003c]/20' + }`}> + {profitMetrics.netMargin >= 0 ? '+' : ''}{profitMetrics.netMargin.toFixed(1)}% margin + +
+
{/* Payments Table */}