feat: implement role-based data scoping for dashboard and analysis services to restrict non-privileged access

This commit is contained in:
Yoga Pangestu 2026-06-29 10:28:22 +07:00
parent 0ff6b59ca9
commit 5220f373f3
2 changed files with 143 additions and 70 deletions

View File

@ -23,21 +23,27 @@ class AnalysisService
{ {
public function getAttendance(): array public function getAttendance(): array
{ {
$totalEmployees = Employee::query()->count(); /** @var \App\Models\User|null $user */
$today = Carbon::today(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$present = Attendance::query() $employeeQuery = Employee::query();
->where('attendance_date', $today) $attendanceQuery = Attendance::query()->where('attendance_date', Carbon::today());
->distinct('employee_id') $leaveRequestQuery = LeaveRequest::query()
->count('employee_id');
$onLeave = LeaveRequest::query()
->approved() ->approved()
->where('start_date', '<=', $today) ->where('start_date', '<=', Carbon::today())
->where('end_date', '>=', $today) ->where('end_date', '>=', Carbon::today());
->distinct('employee_id')
->count('employee_id');
if (!$isSuper) {
$employeeId = $user?->employee?->id;
$employeeQuery->where('id', $employeeId);
$attendanceQuery->where('employee_id', $employeeId);
$leaveRequestQuery->where('employee_id', $employeeId);
}
$totalEmployees = $employeeQuery->count();
$present = $attendanceQuery->distinct('employee_id')->count('employee_id');
$onLeave = $leaveRequestQuery->distinct('employee_id')->count('employee_id');
$absent = max(0, $totalEmployees - $present - $onLeave); $absent = max(0, $totalEmployees - $present - $onLeave);
return [ return [
@ -114,10 +120,20 @@ public function getMyAttendance(User $user, ?Carbon $startDate = null, ?Carbon $
public function getCashOverview(): array public function getCashOverview(): array
{ {
$totalBalance = CashAccount::query()->sum('balance'); /** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$summary = CashTransaction::query() $totalBalanceQuery = CashAccount::query();
->whereDate('created_at', Carbon::today()) $transactionQuery = CashTransaction::query()->whereDate('created_at', Carbon::today());
if (!$isSuper) {
$transactionQuery->where('created_by_id', $user->id);
$totalBalanceQuery->whereHas('transactions', fn ($q) => $q->where('created_by_id', $user->id));
}
$totalBalance = $totalBalanceQuery->sum('balance');
$summary = $transactionQuery
->selectRaw(" ->selectRaw("
COUNT(*) as total_transactions, COUNT(*) as total_transactions,
COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE 0 END), 0) as total_deposit, COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE 0 END), 0) as total_deposit,
@ -135,8 +151,13 @@ public function getCashOverview(): array
public function getTopSuppliers(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getTopSuppliers(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
return Purchase::query() return Purchase::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('purchases.created_by_id', $user->id))
->join('suppliers', 'purchases.supplier_id', '=', 'suppliers.id') ->join('suppliers', 'purchases.supplier_id', '=', 'suppliers.id')
->selectRaw('suppliers.name, SUM(purchases.total) as total_amount, COUNT(purchases.id) as purchase_count') ->selectRaw('suppliers.name, SUM(purchases.total) as total_amount, COUNT(purchases.id) as purchase_count')
->groupBy('suppliers.id', 'suppliers.name') ->groupBy('suppliers.id', 'suppliers.name')
@ -153,14 +174,15 @@ public function getTopSuppliers(?Carbon $startDate = null, ?Carbon $endDate = nu
public function getTopCustomers(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getTopCustomers(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
return Order::query() return Order::query()
->completed() ->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->join('customers', 'orders.customer_id', '=', 'customers.id') ->join('customers', 'orders.customer_id', '=', 'customers.id')
->selectRaw('customers.name, SUM(orders.total_amount) as total_amount, COUNT(orders.id) as order_count') ->selectRaw('customers.name, SUM(orders.total_amount) as total_amount, COUNT(orders.id) as order_count')
@ -178,22 +200,23 @@ public function getTopCustomers(?Carbon $startDate = null, ?Carbon $endDate = nu
public function getRevenueSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getRevenueSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$revenueSummary = Order::query() $revenueSummary = Order::query()
->completed() ->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, COUNT(*) as total_orders, AVG(total_amount) as avg_order') ->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, COUNT(*) as total_orders, AVG(total_amount) as avg_order')
->first(); ->first();
$totalMarketplaceFees = Order::query() $totalMarketplaceFees = Order::query()
->completed() ->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereNotNull('marketplace_settings_snapshot') ->whereNotNull('marketplace_settings_snapshot')
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->get() ->get()
@ -211,16 +234,17 @@ public function getRevenueSummary(?Carbon $startDate = null, ?Carbon $endDate =
public function getMonthlyRevenue(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getMonthlyRevenue(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$query = Order::query()->completed() $query = Order::query()->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)); ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id));
$feeQuery = Order::query()->completed() $feeQuery = Order::query()->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereNotNull('marketplace_settings_snapshot'); ->whereNotNull('marketplace_settings_snapshot');
if ($startDate && $endDate) { if ($startDate && $endDate) {
@ -277,23 +301,30 @@ public function getMonthlyRevenue(?Carbon $startDate = null, ?Carbon $endDate =
public function getExpenseSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getExpenseSummary(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$purchase = Purchase::query() $purchase = Purchase::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('purchases.created_by_id', $user->id))
->selectRaw('COALESCE(SUM(total), 0) as total') ->selectRaw('COALESCE(SUM(total), 0) as total')
->first(); ->first();
$expenses = Expense::query() $expenses = Expense::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('expenses.created_by_id', $user->id))
->selectRaw('COALESCE(SUM(amount), 0) as total') ->selectRaw('COALESCE(SUM(amount), 0) as total')
->first(); ->first();
$employeeAdvance = EmployeeAdvance::query() $employeeAdvance = EmployeeAdvance::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
->selectRaw('COALESCE(SUM(amount), 0) as total') ->selectRaw('COALESCE(SUM(amount), 0) as total')
->first(); ->first();
$purchaseTotal = (int) ($purchase->total ?? 0); $purchaseTotal = (int) ($purchase->total ?? 0);
if (auth()->user()?->hasRole(Role::ADMIN_TOKO->value)) { if ($user?->hasRole(Role::ADMIN_TOKO->value)) {
$purchaseTotal = 0; $purchaseTotal = 0;
} }
$expenseTotal = (int) ($expenses->total ?? 0); $expenseTotal = (int) ($expenses->total ?? 0);
@ -309,8 +340,13 @@ public function getExpenseSummary(?Carbon $startDate = null, ?Carbon $endDate =
public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$purchases = Purchase::query() $purchases = Purchase::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('purchases.created_by_id', $user->id))
->selectRaw("DATE_FORMAT(purchases.created_at, '%Y-%m') as month_key, COALESCE(SUM(total), 0) as total") ->selectRaw("DATE_FORMAT(purchases.created_at, '%Y-%m') as month_key, COALESCE(SUM(total), 0) as total")
->groupBy('month_key') ->groupBy('month_key')
->orderBy('month_key') ->orderBy('month_key')
@ -318,6 +354,7 @@ public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate =
$expenses = Expense::query() $expenses = Expense::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('expenses.created_by_id', $user->id))
->selectRaw("DATE_FORMAT(expenses.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount), 0) as total") ->selectRaw("DATE_FORMAT(expenses.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount), 0) as total")
->groupBy('month_key') ->groupBy('month_key')
->orderBy('month_key') ->orderBy('month_key')
@ -325,6 +362,7 @@ public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate =
$advances = EmployeeAdvance::query() $advances = EmployeeAdvance::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
->selectRaw("DATE_FORMAT(employee_advances.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount), 0) as total") ->selectRaw("DATE_FORMAT(employee_advances.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount), 0) as total")
->groupBy('month_key') ->groupBy('month_key')
->orderBy('month_key') ->orderBy('month_key')
@ -352,7 +390,7 @@ public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate =
$monthLabel = $current->locale('id')->translatedFormat('M Y'); $monthLabel = $current->locale('id')->translatedFormat('M Y');
$purchaseAmount = (int) ($purchases->firstWhere('month_key', $key)->total ?? 0); $purchaseAmount = (int) ($purchases->firstWhere('month_key', $key)->total ?? 0);
if (auth()->user()?->hasRole(Role::ADMIN_TOKO->value)) { if ($user?->hasRole(Role::ADMIN_TOKO->value)) {
$purchaseAmount = 0; $purchaseAmount = 0;
} }
$expenseAmount = (int) ($expenses->firstWhere('month_key', $key)->total ?? 0); $expenseAmount = (int) ($expenses->firstWhere('month_key', $key)->total ?? 0);
@ -374,13 +412,14 @@ public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate =
public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$orderQuery = Order::query()->completed() $orderQuery = Order::query()->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)); ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id));
if ($startDate && $endDate) { if ($startDate && $endDate) {
$orderQuery->whereBetween('orders.created_at', [$startDate, $endDate]); $orderQuery->whereBetween('orders.created_at', [$startDate, $endDate]);
} }
@ -407,6 +446,8 @@ public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = n
$itemsData = OrderItem::query() $itemsData = OrderItem::query()
->join('orders', 'order_items.order_id', '=', 'orders.id') ->join('orders', 'order_items.order_id', '=', 'orders.id')
->where('orders.status', OrderStatus::COMPLETED) ->where('orders.status', OrderStatus::COMPLETED)
->when(!$isSuper && $isMarketing, fn ($q) => $q->where('orders.marketing_id', $user->id))
->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('orders.created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->selectRaw(' ->selectRaw('
SUM(order_items.quantity) as total_qty, SUM(order_items.quantity) as total_qty,
@ -422,6 +463,8 @@ public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = n
->join('orders', 'order_items.order_id', '=', 'orders.id') ->join('orders', 'order_items.order_id', '=', 'orders.id')
->leftJoin('cutting_result_prices', 'order_items.product_variant_id', '=', 'cutting_result_prices.product_variant_id') ->leftJoin('cutting_result_prices', 'order_items.product_variant_id', '=', 'cutting_result_prices.product_variant_id')
->where('orders.status', OrderStatus::COMPLETED) ->where('orders.status', OrderStatus::COMPLETED)
->when(!$isSuper && $isMarketing, fn ($q) => $q->where('orders.marketing_id', $user->id))
->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('orders.created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->selectRaw('COALESCE(SUM(order_items.quantity * cutting_result_prices.cost_per_unit), 0) as total_hpp') ->selectRaw('COALESCE(SUM(order_items.quantity * cutting_result_prices.cost_per_unit), 0) as total_hpp')
->value('total_hpp'); ->value('total_hpp');
@ -431,18 +474,21 @@ public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = n
// Expenses // Expenses
$purchaseTotal = Purchase::query() $purchaseTotal = Purchase::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('purchases.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('purchases.created_by_id', $user->id))
->sum('total'); ->sum('total');
if (auth()->user()?->hasRole(Role::ADMIN_TOKO->value)) { if ($user?->hasRole(Role::ADMIN_TOKO->value)) {
$purchaseTotal = 0; $purchaseTotal = 0;
} }
$expenseTotal = Expense::query() $expenseTotal = Expense::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('expenses.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('expenses.created_by_id', $user->id))
->sum('amount'); ->sum('amount');
$advanceTotal = EmployeeAdvance::query() $advanceTotal = EmployeeAdvance::query()
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
->when(!$isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
->sum('amount'); ->sum('amount');
$totalExpenses = (int) $purchaseTotal + (int) $expenseTotal + (int) $advanceTotal; $totalExpenses = (int) $purchaseTotal + (int) $expenseTotal + (int) $advanceTotal;
@ -527,13 +573,14 @@ public function getProductStock(): array
public function getBusyHours(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getBusyHours(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$hourlyData = Order::query() $hourlyData = Order::query()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->selectRaw('HOUR(orders.created_at) as hour, COUNT(*) as order_count') ->selectRaw('HOUR(orders.created_at) as hour, COUNT(*) as order_count')
->groupBy('hour') ->groupBy('hour')
@ -554,17 +601,18 @@ public function getBusyHours(?Carbon $startDate = null, ?Carbon $endDate = null)
public function getTopProducts(?Carbon $startDate = null, ?Carbon $endDate = null): array public function getTopProducts(?Carbon $startDate = null, ?Carbon $endDate = null): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
return OrderItem::query() return OrderItem::query()
->join('orders', 'order_items.order_id', '=', 'orders.id') ->join('orders', 'order_items.order_id', '=', 'orders.id')
->join('product_variants', 'order_items.product_variant_id', '=', 'product_variants.id') ->join('product_variants', 'order_items.product_variant_id', '=', 'product_variants.id')
->join('products', 'product_variants.product_id', '=', 'products.id') ->join('products', 'product_variants.product_id', '=', 'products.id')
->where('orders.status', OrderStatus::COMPLETED) ->where('orders.status', OrderStatus::COMPLETED)
->when($isMarketing, fn ($q) => $q->where('orders.marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('orders.marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('orders.created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('orders.created_by_id', $user->id))
->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate])) ->when($startDate && $endDate, fn ($q) => $q->whereBetween('orders.created_at', [$startDate, $endDate]))
->selectRaw("CONCAT(products.name, ' - ', product_variants.name) as full_name, SUM(order_items.quantity) as total_qty, SUM(order_items.subtotal) as total_revenue") ->selectRaw("CONCAT(products.name, ' - ', product_variants.name) as full_name, SUM(order_items.quantity) as total_qty, SUM(order_items.subtotal) as total_revenue")
->groupBy('order_items.product_variant_id', 'products.name', 'product_variants.name') ->groupBy('order_items.product_variant_id', 'products.name', 'product_variants.name')

View File

@ -60,21 +60,28 @@ public function canCheckInForUser(User $user): bool
public function getAttendance(): array public function getAttendance(): array
{ {
$totalEmployees = Employee::query()->count(); /** @var \App\Models\User|null $user */
$today = Carbon::today(); /** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$present = Attendance::query() $employeeQuery = Employee::query();
->where('attendance_date', $today) $attendanceQuery = Attendance::query()->where('attendance_date', Carbon::today());
->distinct('employee_id') $leaveRequestQuery = LeaveRequest::query()
->count('employee_id');
$onLeave = LeaveRequest::query()
->approved() ->approved()
->where('start_date', '<=', $today) ->where('start_date', '<=', Carbon::today())
->where('end_date', '>=', $today) ->where('end_date', '>=', Carbon::today());
->distinct('employee_id')
->count('employee_id');
if (!$isSuper) {
$employeeId = $user?->employee?->id;
$employeeQuery->where('id', $employeeId);
$attendanceQuery->where('employee_id', $employeeId);
$leaveRequestQuery->where('employee_id', $employeeId);
}
$totalEmployees = $employeeQuery->count();
$present = $attendanceQuery->distinct('employee_id')->count('employee_id');
$onLeave = $leaveRequestQuery->distinct('employee_id')->count('employee_id');
$absent = max(0, $totalEmployees - $present - $onLeave); $absent = max(0, $totalEmployees - $present - $onLeave);
return [ return [
@ -88,10 +95,20 @@ public function getAttendance(): array
public function getCashOverview(): array public function getCashOverview(): array
{ {
$totalBalance = CashAccount::query()->sum('balance'); /** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$summary = CashTransaction::query() $totalBalanceQuery = CashAccount::query();
->whereDate('created_at', Carbon::today()) $transactionQuery = CashTransaction::query()->whereDate('created_at', Carbon::today());
if (!$isSuper) {
$transactionQuery->where('created_by_id', $user->id);
$totalBalanceQuery->whereHas('transactions', fn ($q) => $q->where('created_by_id', $user->id));
}
$totalBalance = $totalBalanceQuery->sum('balance');
$summary = $transactionQuery
->selectRaw(" ->selectRaw("
COUNT(*) as total_transactions, COUNT(*) as total_transactions,
COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE 0 END), 0) as total_deposit, COALESCE(SUM(CASE WHEN type = 'deposit' THEN amount ELSE 0 END), 0) as total_deposit,
@ -109,22 +126,23 @@ public function getCashOverview(): array
public function getRevenueSummary(): array public function getRevenueSummary(): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$revenueSummary = Order::query() $revenueSummary = Order::query()
->completed() ->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereDate('created_at', Carbon::today()) ->whereDate('created_at', Carbon::today())
->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, COUNT(*) as total_orders, AVG(total_amount) as avg_order') ->selectRaw('SUM(total_amount) as total_revenue, SUM(discount) as total_discount, COUNT(*) as total_orders, AVG(total_amount) as avg_order')
->first(); ->first();
$totalMarketplaceFees = Order::query() $totalMarketplaceFees = Order::query()
->completed() ->completed()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereNotNull('marketplace_settings_snapshot') ->whereNotNull('marketplace_settings_snapshot')
->whereDate('created_at', Carbon::today()) ->whereDate('created_at', Carbon::today())
->get() ->get()
@ -143,24 +161,30 @@ public function getRevenueSummary(): array
public function getExpenseSummary(): array public function getExpenseSummary(): array
{ {
$today = Carbon::today(); $today = Carbon::today();
/** @var \App\Models\User|null $user */
$user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$purchase = Purchase::query() $purchase = Purchase::query()
->whereDate('created_at', $today) ->whereDate('created_at', $today)
->when(!$isSuper, fn ($q) => $q->where('created_by_id', $user->id))
->selectRaw('COALESCE(SUM(total), 0) as total') ->selectRaw('COALESCE(SUM(total), 0) as total')
->first(); ->first();
$expenses = Expense::query() $expenses = Expense::query()
->whereDate('created_at', $today) ->whereDate('created_at', $today)
->when(!$isSuper, fn ($q) => $q->where('created_by_id', $user->id))
->selectRaw('COALESCE(SUM(amount), 0) as total') ->selectRaw('COALESCE(SUM(amount), 0) as total')
->first(); ->first();
$employeeAdvance = EmployeeAdvance::query() $employeeAdvance = EmployeeAdvance::query()
->whereDate('created_at', $today) ->whereDate('created_at', $today)
->when(!$isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
->selectRaw('COALESCE(SUM(amount), 0) as total') ->selectRaw('COALESCE(SUM(amount), 0) as total')
->first(); ->first();
$purchaseTotal = (int) ($purchase->total ?? 0); $purchaseTotal = (int) ($purchase->total ?? 0);
if (auth()->user()?->hasRole(Role::ADMIN_TOKO->value)) { if ($user?->hasRole(Role::ADMIN_TOKO->value)) {
$purchaseTotal = 0; $purchaseTotal = 0;
} }
$expenseTotal = (int) ($expenses->total ?? 0); $expenseTotal = (int) ($expenses->total ?? 0);
@ -176,13 +200,14 @@ public function getExpenseSummary(): array
public function getOrderStats(): array public function getOrderStats(): array
{ {
/** @var \App\Models\User|null $user */
$user = auth()->user(); $user = auth()->user();
$isSuper = $user?->hasAnyRole(['developer', 'owner', 'direktur']) ?? false;
$isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false; $isMarketing = $user?->hasAnyRole(['marketing-offline', 'marketing-online']) ?? false;
$isCashier = $user?->hasRole('cashier') ?? false;
$byChannel = Order::query() $byChannel = Order::query()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereDate('created_at', Carbon::today()) ->whereDate('created_at', Carbon::today())
->selectRaw('channel, COUNT(*) as count, SUM(total_amount) as total') ->selectRaw('channel, COUNT(*) as count, SUM(total_amount) as total')
->groupBy('channel') ->groupBy('channel')
@ -195,8 +220,8 @@ public function getOrderStats(): array
]); ]);
$byPaymentType = Order::query() $byPaymentType = Order::query()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereDate('created_at', Carbon::today()) ->whereDate('created_at', Carbon::today())
->selectRaw('payment_type, COUNT(*) as count, SUM(total_amount) as total') ->selectRaw('payment_type, COUNT(*) as count, SUM(total_amount) as total')
->groupBy('payment_type') ->groupBy('payment_type')
@ -209,8 +234,8 @@ public function getOrderStats(): array
]); ]);
$byMarketing = Order::query() $byMarketing = Order::query()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereNotNull('marketing_id') ->whereNotNull('marketing_id')
->whereDate('orders.created_at', Carbon::today()) ->whereDate('orders.created_at', Carbon::today())
->join('users', 'orders.marketing_id', '=', 'users.id') ->join('users', 'orders.marketing_id', '=', 'users.id')
@ -227,8 +252,8 @@ public function getOrderStats(): array
]); ]);
$byStatus = Order::query() $byStatus = Order::query()
->when($isMarketing, fn ($q) => $q->where('marketing_id', $user->id)) ->when(!$isSuper && $isMarketing, fn ($q) => $q->where('marketing_id', $user->id))
->when($isCashier, fn ($q) => $q->where('created_by_id', $user->id)) ->when(!$isSuper && !$isMarketing, fn ($q) => $q->where('created_by_id', $user->id))
->whereDate('created_at', Carbon::today()) ->whereDate('created_at', Carbon::today())
->selectRaw('status, COUNT(*) as count') ->selectRaw('status, COUNT(*) as count')
->groupBy('status') ->groupBy('status')