feat: enhance revenue analysis by adding payroll and expense calculations
This commit is contained in:
parent
78c432eaa0
commit
0aae00a96b
@ -7,6 +7,7 @@
|
|||||||
use App\Enums\OrderChannel;
|
use App\Enums\OrderChannel;
|
||||||
use App\Enums\OrderStatus;
|
use App\Enums\OrderStatus;
|
||||||
use App\Enums\PaymentType;
|
use App\Enums\PaymentType;
|
||||||
|
use App\Enums\PayrollStatus;
|
||||||
use App\Enums\RawMaterialUnit;
|
use App\Enums\RawMaterialUnit;
|
||||||
use App\Enums\Role;
|
use App\Enums\Role;
|
||||||
use App\Models\Attendance;
|
use App\Models\Attendance;
|
||||||
@ -16,6 +17,7 @@
|
|||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use App\Models\LeaveRequest;
|
use App\Models\LeaveRequest;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\Payroll;
|
||||||
use App\Models\Purchase;
|
use App\Models\Purchase;
|
||||||
use App\Models\PurchaseItem;
|
use App\Models\PurchaseItem;
|
||||||
use App\Models\RestockItem;
|
use App\Models\RestockItem;
|
||||||
@ -260,12 +262,28 @@ public function getRevenueSummary(?string $startDate, ?string $endDate, ?User $u
|
|||||||
->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs')
|
->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
$payrollQuery = Payroll::where('status', PayrollStatus::PAID);
|
||||||
|
$this->applyDateFilter($payrollQuery, $startDate, $endDate, 'paid_at');
|
||||||
|
$payrollTotal = (int) $payrollQuery->sum('total_amount');
|
||||||
|
|
||||||
|
$expenseQuery = Expense::query();
|
||||||
|
$this->applyDateFilter($expenseQuery, $startDate, $endDate, 'expenses.created_at');
|
||||||
|
$expenseTotal = (int) $expenseQuery->sum('amount');
|
||||||
|
|
||||||
|
$totalRevenue = (int) $stats->total_revenue;
|
||||||
|
$totalCogs = (int) $stats->total_cogs;
|
||||||
|
$gross = $totalRevenue - $totalCogs;
|
||||||
|
$net = $gross - $payrollTotal - $expenseTotal;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'total_revenue' => (int) $stats->total_revenue,
|
'total_revenue' => $totalRevenue,
|
||||||
'total_discount' => (int) $stats->total_discount,
|
'total_discount' => (int) $stats->total_discount,
|
||||||
'total_deduction' => (int) $stats->total_deduction,
|
'total_deduction' => (int) $stats->total_deduction,
|
||||||
'cogs' => (int) $stats->total_cogs,
|
'cogs' => $totalCogs,
|
||||||
'net' => (int) $stats->total_revenue - (int) $stats->total_cogs,
|
'gross' => $gross,
|
||||||
|
'net' => $net,
|
||||||
|
'payroll_total' => $payrollTotal,
|
||||||
|
'expense_total' => $expenseTotal,
|
||||||
'total_orders' => (int) $stats->total_orders,
|
'total_orders' => (int) $stats->total_orders,
|
||||||
'avg_order' => $stats->total_orders > 0 ? (int) ($stats->total_revenue / $stats->total_orders) : 0,
|
'avg_order' => $stats->total_orders > 0 ? (int) ($stats->total_revenue / $stats->total_orders) : 0,
|
||||||
];
|
];
|
||||||
@ -283,23 +301,68 @@ public function getMonthlyRevenue(?string $startDate, ?string $endDate, ?User $u
|
|||||||
$monthly = (clone $query)
|
$monthly = (clone $query)
|
||||||
->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month")
|
->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month")
|
||||||
->selectRaw('COALESCE(SUM(total_amount), 0) as total')
|
->selectRaw('COALESCE(SUM(total_amount), 0) as total')
|
||||||
->selectRaw('COALESCE(SUM(total_amount) - SUM(cogs), 0) as net')
|
|
||||||
->selectRaw('COALESCE(SUM(discount), 0) as discount')
|
->selectRaw('COALESCE(SUM(discount), 0) as discount')
|
||||||
->selectRaw('COALESCE(SUM(nego_price), 0) as deduction')
|
->selectRaw('COALESCE(SUM(nego_price), 0) as deduction')
|
||||||
->selectRaw('COALESCE(SUM(cogs), 0) as cogs')
|
->selectRaw('COALESCE(SUM(cogs), 0) as cogs')
|
||||||
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"), DB::raw("DATE_FORMAT(created_at, '%b %Y')"))
|
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"), DB::raw("DATE_FORMAT(created_at, '%b %Y')"))
|
||||||
->orderBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"))
|
->orderBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"))
|
||||||
->get()
|
->get()
|
||||||
->map(fn ($item) => [
|
->keyBy('month');
|
||||||
'month' => $item->month,
|
|
||||||
'total' => (int) $item->total,
|
|
||||||
'net' => (int) $item->net,
|
|
||||||
'discount' => (int) $item->discount,
|
|
||||||
'deduction' => (int) $item->deduction,
|
|
||||||
'cogs' => (int) $item->cogs,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $monthly->values()->toArray();
|
$payrollMonthly = Payroll::where('status', PayrollStatus::PAID);
|
||||||
|
$this->applyDateFilter($payrollMonthly, $startDate, $endDate, 'paid_at');
|
||||||
|
|
||||||
|
$payrollByMonth = (clone $payrollMonthly)->toBase()
|
||||||
|
->selectRaw("DATE_FORMAT(paid_at, '%b %Y') as month")
|
||||||
|
->selectRaw('COALESCE(SUM(total_amount), 0) as payroll')
|
||||||
|
->groupBy(DB::raw("DATE_FORMAT(paid_at, '%Y-%m')"), DB::raw("DATE_FORMAT(paid_at, '%b %Y')"))
|
||||||
|
->get()
|
||||||
|
->keyBy('month');
|
||||||
|
|
||||||
|
$expenseMonthly = Expense::query();
|
||||||
|
$this->applyDateFilter($expenseMonthly, $startDate, $endDate, 'expenses.created_at');
|
||||||
|
|
||||||
|
$expenseByMonth = (clone $expenseMonthly)->toBase()
|
||||||
|
->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month")
|
||||||
|
->selectRaw('COALESCE(SUM(amount), 0) as expense')
|
||||||
|
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"), DB::raw("DATE_FORMAT(created_at, '%b %Y')"))
|
||||||
|
->get()
|
||||||
|
->keyBy('month');
|
||||||
|
|
||||||
|
$allMonths = [];
|
||||||
|
foreach ([$monthly, $payrollByMonth, $expenseByMonth] as $data) {
|
||||||
|
foreach ($data as $month => $row) {
|
||||||
|
if (! array_key_exists($month, $allMonths)) {
|
||||||
|
$allMonths[$month] = $month;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
foreach ($allMonths as $month => $_) {
|
||||||
|
$total = (int) ($monthly[$month]->total ?? 0);
|
||||||
|
$discount = (int) ($monthly[$month]->discount ?? 0);
|
||||||
|
$deduction = (int) ($monthly[$month]->deduction ?? 0);
|
||||||
|
$cogs = (int) ($monthly[$month]->cogs ?? 0);
|
||||||
|
$payroll = (int) ($payrollByMonth[$month]->payroll ?? 0);
|
||||||
|
$expense = (int) ($expenseByMonth[$month]->expense ?? 0);
|
||||||
|
$gross = $total - $cogs;
|
||||||
|
$net = $gross - $payroll - $expense;
|
||||||
|
|
||||||
|
$result[] = [
|
||||||
|
'month' => $month,
|
||||||
|
'total' => $total,
|
||||||
|
'gross' => $gross,
|
||||||
|
'net' => $net,
|
||||||
|
'discount' => $discount,
|
||||||
|
'deduction' => $deduction,
|
||||||
|
'cogs' => $cogs,
|
||||||
|
'payroll' => $payroll,
|
||||||
|
'expense' => $expense,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMonthlyRevenueByChannel(?string $startDate, ?string $endDate, ?User $user = null): array
|
public function getMonthlyRevenueByChannel(?string $startDate, ?string $endDate, ?User $user = null): array
|
||||||
@ -541,8 +604,16 @@ public function getProfitMetrics(?string $startDate, ?string $endDate, ?User $us
|
|||||||
->join('order_items', 'orders.id', '=', 'order_items.order_id')
|
->join('order_items', 'orders.id', '=', 'order_items.order_id')
|
||||||
->sum('order_items.quantity');
|
->sum('order_items.quantity');
|
||||||
|
|
||||||
|
$payrollQuery = Payroll::where('status', PayrollStatus::PAID);
|
||||||
|
$this->applyDateFilter($payrollQuery, $startDate, $endDate, 'paid_at');
|
||||||
|
$payrollTotal = (int) $payrollQuery->sum('total_amount');
|
||||||
|
|
||||||
|
$expenseQuery = Expense::query();
|
||||||
|
$this->applyDateFilter($expenseQuery, $startDate, $endDate, 'expenses.created_at');
|
||||||
|
$expenseTotal = (int) $expenseQuery->sum('amount');
|
||||||
|
|
||||||
$grossProfit = $stats->total_revenue - $stats->hpp;
|
$grossProfit = $stats->total_revenue - $stats->hpp;
|
||||||
$netProfit = $grossProfit;
|
$netProfit = $grossProfit - $payrollTotal - $expenseTotal;
|
||||||
$profitMargin = $stats->total_revenue > 0 ? round(($netProfit / $stats->total_revenue) * 100, 1) : 0;
|
$profitMargin = $stats->total_revenue > 0 ? round(($netProfit / $stats->total_revenue) * 100, 1) : 0;
|
||||||
$aov = $stats->total_orders > 0 ? (int) ($stats->total_revenue / $stats->total_orders) : 0;
|
$aov = $stats->total_orders > 0 ? (int) ($stats->total_revenue / $stats->total_orders) : 0;
|
||||||
$itemsPerTransaction = $stats->total_orders > 0 ? round($totalProductsSold / $stats->total_orders, 1) : 0;
|
$itemsPerTransaction = $stats->total_orders > 0 ? round($totalProductsSold / $stats->total_orders, 1) : 0;
|
||||||
@ -556,6 +627,8 @@ public function getProfitMetrics(?string $startDate, ?string $endDate, ?User $us
|
|||||||
'profit_margin' => $profitMargin,
|
'profit_margin' => $profitMargin,
|
||||||
'aov' => $aov,
|
'aov' => $aov,
|
||||||
'items_per_transaction' => $itemsPerTransaction,
|
'items_per_transaction' => $itemsPerTransaction,
|
||||||
|
'payroll_total' => $payrollTotal,
|
||||||
|
'expense_total' => $expenseTotal,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
use App\Enums\OrderChannel;
|
use App\Enums\OrderChannel;
|
||||||
use App\Enums\OrderStatus;
|
use App\Enums\OrderStatus;
|
||||||
use App\Enums\PaymentType;
|
use App\Enums\PaymentType;
|
||||||
|
use App\Enums\PayrollStatus;
|
||||||
use App\Enums\Role;
|
use App\Enums\Role;
|
||||||
use App\Models\Attendance;
|
use App\Models\Attendance;
|
||||||
use App\Models\Employee;
|
use App\Models\Employee;
|
||||||
@ -12,6 +13,7 @@
|
|||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use App\Models\LeaveRequest;
|
use App\Models\LeaveRequest;
|
||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
|
use App\Models\Payroll;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
@ -135,12 +137,27 @@ public function getRevenueSummary(?User $user = null): array
|
|||||||
->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs')
|
->selectRaw('COALESCE(SUM(cogs), 0) as total_cogs')
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
|
$payrollTotal = (int) Payroll::where('status', PayrollStatus::PAID)
|
||||||
|
->whereDate('paid_at', $today)
|
||||||
|
->sum('total_amount');
|
||||||
|
|
||||||
|
$expenseTotal = (int) Expense::whereDate('created_at', $today)
|
||||||
|
->sum('amount');
|
||||||
|
|
||||||
|
$totalRevenue = (int) $stats->total_revenue;
|
||||||
|
$totalCogs = (int) $stats->total_cogs;
|
||||||
|
$gross = $totalRevenue - $totalCogs;
|
||||||
|
$net = $gross - $payrollTotal - $expenseTotal;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'total_revenue' => (int) $stats->total_revenue,
|
'total_revenue' => $totalRevenue,
|
||||||
'total_discount' => (int) $stats->total_discount,
|
'total_discount' => (int) $stats->total_discount,
|
||||||
'total_cogs' => (int) $stats->total_cogs,
|
'total_cogs' => $totalCogs,
|
||||||
'total_deduction' => (int) $stats->total_deduction,
|
'total_deduction' => (int) $stats->total_deduction,
|
||||||
'net' => (int) $stats->total_revenue - (int) $stats->total_cogs,
|
'gross' => $gross,
|
||||||
|
'net' => $net,
|
||||||
|
'payroll_total' => $payrollTotal,
|
||||||
|
'expense_total' => $expenseTotal,
|
||||||
'total_orders' => (int) $stats->total_orders,
|
'total_orders' => (int) $stats->total_orders,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,7 @@ @theme {
|
|||||||
--color-chart-3: var(--chart-3);
|
--color-chart-3: var(--chart-3);
|
||||||
--color-chart-4: var(--chart-4);
|
--color-chart-4: var(--chart-4);
|
||||||
--color-chart-5: var(--chart-5);
|
--color-chart-5: var(--chart-5);
|
||||||
|
--color-chart-6: var(--chart-6);
|
||||||
|
|
||||||
--color-sidebar: var(--sidebar);
|
--color-sidebar: var(--sidebar);
|
||||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
@ -89,6 +90,7 @@ :root {
|
|||||||
--chart-3: oklch(0.666 0.179 58.318);
|
--chart-3: oklch(0.666 0.179 58.318);
|
||||||
--chart-4: oklch(0.555 0.163 48.998);
|
--chart-4: oklch(0.555 0.163 48.998);
|
||||||
--chart-5: oklch(0.473 0.137 46.201);
|
--chart-5: oklch(0.473 0.137 46.201);
|
||||||
|
--chart-6: oklch(0.696 0.17 162.48);
|
||||||
--radius: 0.625rem;
|
--radius: 0.625rem;
|
||||||
--sidebar: oklch(0.985 0 0);
|
--sidebar: oklch(0.985 0 0);
|
||||||
--sidebar-foreground: oklch(0.145 0 0);
|
--sidebar-foreground: oklch(0.145 0 0);
|
||||||
@ -125,6 +127,7 @@ .dark {
|
|||||||
--chart-3: oklch(0.666 0.179 58.318);
|
--chart-3: oklch(0.666 0.179 58.318);
|
||||||
--chart-4: oklch(0.555 0.163 48.998);
|
--chart-4: oklch(0.555 0.163 48.998);
|
||||||
--chart-5: oklch(0.473 0.137 46.201);
|
--chart-5: oklch(0.473 0.137 46.201);
|
||||||
|
--chart-6: oklch(0.696 0.17 162.48);
|
||||||
--sidebar: oklch(0.205 0 0);
|
--sidebar: oklch(0.205 0 0);
|
||||||
--sidebar-foreground: oklch(0.985 0 0);
|
--sidebar-foreground: oklch(0.985 0 0);
|
||||||
--sidebar-primary: oklch(0.769 0.188 70.08);
|
--sidebar-primary: oklch(0.769 0.188 70.08);
|
||||||
@ -183,6 +186,7 @@ @theme inline {
|
|||||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||||
--color-sidebar: var(--sidebar);
|
--color-sidebar: var(--sidebar);
|
||||||
--color-chart-5: var(--chart-5);
|
--color-chart-5: var(--chart-5);
|
||||||
|
--color-chart-6: var(--chart-6);
|
||||||
--color-chart-4: var(--chart-4);
|
--color-chart-4: var(--chart-4);
|
||||||
--color-chart-3: var(--chart-3);
|
--color-chart-3: var(--chart-3);
|
||||||
--color-chart-2: var(--chart-2);
|
--color-chart-2: var(--chart-2);
|
||||||
|
|||||||
@ -86,17 +86,23 @@ type AnalysisProps = {
|
|||||||
total_discount: number;
|
total_discount: number;
|
||||||
total_deduction: number;
|
total_deduction: number;
|
||||||
cogs: number;
|
cogs: number;
|
||||||
|
gross: number;
|
||||||
net: number;
|
net: number;
|
||||||
|
payroll_total: number;
|
||||||
|
expense_total: number;
|
||||||
total_orders: number;
|
total_orders: number;
|
||||||
avg_order: number;
|
avg_order: number;
|
||||||
};
|
};
|
||||||
monthlyRevenue: Array<{
|
monthlyRevenue: Array<{
|
||||||
month: string;
|
month: string;
|
||||||
total: number;
|
total: number;
|
||||||
|
gross: number;
|
||||||
net: number;
|
net: number;
|
||||||
discount: number;
|
discount: number;
|
||||||
deduction: number;
|
deduction: number;
|
||||||
cogs: number;
|
cogs: number;
|
||||||
|
payroll: number;
|
||||||
|
expense: number;
|
||||||
}>;
|
}>;
|
||||||
monthlyRevenueByChannel: Array<{
|
monthlyRevenueByChannel: Array<{
|
||||||
month: string;
|
month: string;
|
||||||
@ -135,6 +141,8 @@ type AnalysisProps = {
|
|||||||
profit_margin: number;
|
profit_margin: number;
|
||||||
aov: number;
|
aov: number;
|
||||||
items_per_transaction: number;
|
items_per_transaction: number;
|
||||||
|
payroll_total: number;
|
||||||
|
expense_total: number;
|
||||||
};
|
};
|
||||||
topSuppliers: Array<{
|
topSuppliers: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
@ -195,12 +203,16 @@ const revenueChartConfig = {
|
|||||||
label: 'Total',
|
label: 'Total',
|
||||||
color: 'var(--chart-1)',
|
color: 'var(--chart-1)',
|
||||||
},
|
},
|
||||||
net: {
|
gross: {
|
||||||
label: 'Bersih',
|
label: 'Keuntungan Kotor',
|
||||||
color: 'var(--chart-2)',
|
color: 'var(--chart-2)',
|
||||||
},
|
},
|
||||||
|
net: {
|
||||||
|
label: 'Keuntungan Bersih',
|
||||||
|
color: 'var(--chart-6)',
|
||||||
|
},
|
||||||
deduction: {
|
deduction: {
|
||||||
label: 'Potongan',
|
label: 'Potongan Nego',
|
||||||
color: 'var(--chart-3)',
|
color: 'var(--chart-3)',
|
||||||
},
|
},
|
||||||
discount: {
|
discount: {
|
||||||
@ -213,7 +225,7 @@ const revenueChartConfig = {
|
|||||||
},
|
},
|
||||||
} satisfies ChartConfig;
|
} satisfies ChartConfig;
|
||||||
|
|
||||||
const revenueKeys = ['total', 'net', 'deduction', 'discount', 'cogs'] as const;
|
const revenueKeys = ['total', 'deduction', 'discount', 'cogs', 'gross', 'net'] as const;
|
||||||
|
|
||||||
const expenseChartConfig = {
|
const expenseChartConfig = {
|
||||||
total: {
|
total: {
|
||||||
@ -225,7 +237,7 @@ const expenseChartConfig = {
|
|||||||
color: 'var(--chart-2)',
|
color: 'var(--chart-2)',
|
||||||
},
|
},
|
||||||
expense: {
|
expense: {
|
||||||
label: 'Pengeluaran',
|
label: 'Pengeluaran Toko',
|
||||||
color: 'var(--chart-3)',
|
color: 'var(--chart-3)',
|
||||||
},
|
},
|
||||||
advance: {
|
advance: {
|
||||||
@ -638,9 +650,9 @@ export default function Analysis({
|
|||||||
{revenueKeys.filter((key) => {
|
{revenueKeys.filter((key) => {
|
||||||
if (hasAnyRole(['owner', 'developer'])) return true;
|
if (hasAnyRole(['owner', 'developer'])) return true;
|
||||||
if (hasRole('cashier')) return key === 'total' || key === 'discount' || key === 'deduction' || key === 'cogs';
|
if (hasRole('cashier')) return key === 'total' || key === 'discount' || key === 'deduction' || key === 'cogs';
|
||||||
return key === 'total' || key === 'discount' || key === 'deduction' || key === 'net' || key === 'cogs';
|
return key === 'total' || key === 'discount' || key === 'deduction' || key === 'cogs' || key === 'gross' || key === 'net';
|
||||||
}).map((key) => {
|
}).map((key) => {
|
||||||
const value = key === 'total' ? revenueSummary.total_revenue : key === 'discount' ? revenueSummary.total_discount : key === 'net' ? revenueSummary.net : key === 'cogs' ? revenueSummary.cogs : revenueSummary.total_deduction;
|
const value = key === 'total' ? revenueSummary.total_revenue : key === 'discount' ? revenueSummary.total_discount : key === 'net' ? revenueSummary.net : key === 'gross' ? revenueSummary.gross : key === 'cogs' ? revenueSummary.cogs : revenueSummary.total_deduction;
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={key}
|
key={key}
|
||||||
@ -909,7 +921,7 @@ export default function Analysis({
|
|||||||
<Card className="py-0" style={{ order: sectionOrder.revenueTrend ?? 99 }}>
|
<Card className="py-0" style={{ order: sectionOrder.revenueTrend ?? 99 }}>
|
||||||
<CardHeader className="flex flex-col items-stretch border-b p-0! sm:flex-row">
|
<CardHeader className="flex flex-col items-stretch border-b p-0! sm:flex-row">
|
||||||
<div className="flex flex-1 flex-col justify-center gap-1 px-6 pt-4 pb-3 sm:py-0!">
|
<div className="flex flex-1 flex-col justify-center gap-1 px-6 pt-4 pb-3 sm:py-0!">
|
||||||
<CardTitle>Trend Pendapatan</CardTitle>
|
<CardTitle>Trend Penjualan</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col sm:flex-row">
|
<div className="flex flex-col sm:flex-row">
|
||||||
{revenueTrendKeys.map((key) => {
|
{revenueTrendKeys.map((key) => {
|
||||||
|
|||||||
@ -51,6 +51,10 @@ type DashboardProps = {
|
|||||||
total_discount: number;
|
total_discount: number;
|
||||||
total_cogs: number;
|
total_cogs: number;
|
||||||
total_deduction: number;
|
total_deduction: number;
|
||||||
|
gross: number;
|
||||||
|
net: number;
|
||||||
|
payroll_total: number;
|
||||||
|
expense_total: number;
|
||||||
total_orders: number;
|
total_orders: number;
|
||||||
};
|
};
|
||||||
expenseSummary: {
|
expenseSummary: {
|
||||||
@ -341,9 +345,21 @@ export default function Dashboard({
|
|||||||
mainValue={`Rp${formatRupiah(revenueSummary.total_revenue)}`}
|
mainValue={`Rp${formatRupiah(revenueSummary.total_revenue)}`}
|
||||||
subLabel={`${revenueSummary.total_orders} transaksi selesai`}
|
subLabel={`${revenueSummary.total_orders} transaksi selesai`}
|
||||||
items={[
|
items={[
|
||||||
|
{
|
||||||
|
label: 'Kotor',
|
||||||
|
value: `Rp${formatRupiah(revenueSummary.gross)}`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: 'Bersih',
|
label: 'Bersih',
|
||||||
value: `Rp${formatRupiah(revenueSummary.total_revenue - revenueSummary.total_cogs)}`,
|
value: `Rp${formatRupiah(revenueSummary.net)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Gaji',
|
||||||
|
value: `Rp${formatRupiah(revenueSummary.payroll_total)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Pengeluaran',
|
||||||
|
value: `Rp${formatRupiah(revenueSummary.expense_total)}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Potongan',
|
label: 'Potongan',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user