diff --git a/app/Services/AnalysisService.php b/app/Services/AnalysisService.php index dcbe1a0..f53bd98 100644 --- a/app/Services/AnalysisService.php +++ b/app/Services/AnalysisService.php @@ -9,7 +9,6 @@ use App\Enums\PaymentType; use App\Enums\PayrollStatus; use App\Enums\PriceType; -use App\Enums\ProductStockQuality; use App\Enums\RawMaterialUnit; use App\Enums\Role; use App\Models\Attendance; @@ -21,13 +20,13 @@ use App\Models\Order; use App\Models\OrderItem; use App\Models\Payroll; -use App\Models\ProductPrice; use App\Models\ProductVariant; use App\Models\Purchase; use App\Models\RawMaterialPrice; use App\Models\User; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; class AnalysisService @@ -88,14 +87,14 @@ public function getAttendanceStats(?string $startDate, ?string $endDate, ?User $ $employees = Employee::whereHas( 'user', - fn($q) => $q + fn ($q) => $q ->where('is_active', true) ->whereHas( 'roles', - fn($r) => $r + fn ($r) => $r ->whereHas( 'permissions', - fn($p) => $p + fn ($p) => $p ->where('name', 'attendances.create') ) ) @@ -265,6 +264,10 @@ public function getRevenueByStockType(?string $startDate, ?string $endDate, ?Use $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $stockQualitySubquery = OrderItem::select('order_id') ->selectRaw('MIN(stock_quality) as stock_quality') ->groupBy('order_id'); @@ -323,6 +326,10 @@ public function getRevenueSummary(?string $startDate, ?string $endDate, ?User $u $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $stats = (clone $query) ->selectRaw('COUNT(*) as total_orders') ->selectRaw('COALESCE(SUM(total_amount), 0) as total_revenue') @@ -367,6 +374,10 @@ public function getMonthlyRevenue(?string $startDate, ?string $endDate, ?User $u $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $monthly = (clone $query) ->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month") ->selectRaw('COALESCE(SUM(total_amount), 0) as total') @@ -443,6 +454,10 @@ public function getMonthlyRevenueByChannel(?string $startDate, ?string $endDate, $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $monthly = (clone $query) ->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month") ->selectRaw("COALESCE(SUM(CASE WHEN channel = 'store' THEN total_amount ELSE 0 END), 0) as store") @@ -451,7 +466,7 @@ public function getMonthlyRevenueByChannel(?string $startDate, ?string $endDate, ->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')")) ->get() - ->map(fn($item) => [ + ->map(fn ($item) => [ 'month' => $item->month, 'store' => (int) $item->store, 'shopee' => (int) $item->shopee, @@ -470,12 +485,16 @@ public function getRevenueByPaymentType(?string $startDate, ?string $endDate, ?U $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $data = (clone $query) ->select('payment_type') ->selectRaw('COALESCE(SUM(total_amount), 0) as total') ->groupBy('payment_type') ->get() - ->map(fn($item) => [ + ->map(fn ($item) => [ 'payment_type' => $item->payment_type, 'label' => $item->payment_type->label(), 'total' => (int) $item->total, @@ -514,6 +533,10 @@ public function getExpenseSummary(?string $startDate, ?string $endDate, ?User $u $expenseQuery = Expense::query(); $this->applyDateFilter($expenseQuery, $startDate, $endDate, 'expenses.created_at'); + if ($user && $this->isCashierUser($user)) { + $expenseQuery->whereIn('created_by_id', $this->getCashierUserIds()); + } + $advanceQuery = EmployeeAdvance::where('status', EmployeeAdvanceStatus::REPAID); $this->applyDateFilter($advanceQuery, $startDate, $endDate, 'employee_advances.created_at'); @@ -589,6 +612,10 @@ public function getMonthlyExpense(?string $startDate, ?string $endDate, ?User $u $expenseMonthly = Expense::query(); $this->applyDateFilter($expenseMonthly, $startDate, $endDate, 'expenses.created_at'); + if ($user && $this->isCashierUser($user)) { + $expenseMonthly->whereIn('created_by_id', $this->getCashierUserIds()); + } + $expenseByMonth = (clone $expenseMonthly)->toBase() ->selectRaw("DATE_FORMAT(created_at, '%b %Y') as month") ->selectRaw('COALESCE(SUM(amount), 0) as expense') @@ -650,6 +677,10 @@ public function getBusyHours(?string $startDate, ?string $endDate, ?User $user = $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $hours = range(0, 23); $hourCounts = (clone $query) ->selectRaw('HOUR(created_at) as hour') @@ -675,6 +706,10 @@ public function getProfitMetrics(?string $startDate, ?string $endDate, ?User $us $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $stats = (clone $query) ->selectRaw('COUNT(*) as total_orders') ->selectRaw('COALESCE(SUM(total_amount), 0) as total_revenue') @@ -739,6 +774,10 @@ public function getTopCustomers(?string $startDate, ?string $endDate, ?User $use $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + return (clone $query)->toBase() ->join('customers', 'orders.customer_id', '=', 'customers.id') ->select('customers.name') @@ -760,6 +799,10 @@ public function getTopProducts(?string $startDate, ?string $endDate, ?User $user $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + return (clone $query)->toBase() ->join('order_items', 'orders.id', '=', 'order_items.order_id') ->join('product_variants', 'order_items.product_variant_id', '=', 'product_variants.id') @@ -783,6 +826,10 @@ public function getRevenueTrend(?string $startDate, ?string $endDate, ?User $use $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + return (clone $query) ->join('order_items', 'orders.id', '=', 'order_items.order_id') ->selectRaw('DATE(orders.created_at) as date') @@ -790,7 +837,7 @@ public function getRevenueTrend(?string $startDate, ?string $endDate, ?User $use ->groupBy(DB::raw('DATE(orders.created_at)')) ->orderBy(DB::raw('DATE(orders.created_at)')) ->get() - ->map(fn($item) => [ + ->map(fn ($item) => [ 'date' => $item->date, 'qty' => (int) $item->qty, ]) @@ -807,6 +854,10 @@ public function getMarketingSales(?string $startDate, ?string $endDate, ?User $u $query->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $query->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $orders = (clone $query) ->join('users', 'orders.marketing_id', '=', 'users.id') ->leftJoin('user_profiles', 'users.id', '=', 'user_profiles.user_id') @@ -850,6 +901,10 @@ public function getOrderStats(?string $startDate, ?string $endDate, ?User $user $baseQuery->where('orders.marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $baseQuery->whereIn('orders.created_by_id', $this->getCashierUserIds()); + } + $byChannel = collect(OrderChannel::values())->map(function ($channel) use ($baseQuery) { $count = (clone $baseQuery)->where('channel', $channel)->count(); $label = OrderChannel::from($channel)->label(); @@ -882,7 +937,7 @@ public function getOrderStats(?string $startDate, ?string $endDate, ?User $user ->groupBy('marketing_id') ->with('marketing:id') ->get() - ->map(fn($item) => [ + ->map(fn ($item) => [ 'name' => $item->marketing?->userProfile->full_name ?? '-', 'count' => $item->count, 'total' => (int) $item->total, @@ -925,6 +980,16 @@ private function isMarketingUser(User $user): bool ]); } + private function isCashierUser(User $user): bool + { + return $user->hasRole(Role::CASHIER->value); + } + + private function getCashierUserIds(): Collection + { + return User::whereHas('roles', fn ($q) => $q->where('name', Role::CASHIER->value))->pluck('id'); + } + private function isPurchaseVisible(User $user): bool { return $user->hasAnyRole([ diff --git a/app/Services/DashboardService.php b/app/Services/DashboardService.php index 6f98658..2e74ff2 100644 --- a/app/Services/DashboardService.php +++ b/app/Services/DashboardService.php @@ -17,6 +17,7 @@ use App\Models\User; use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Collection; class DashboardService { @@ -129,6 +130,10 @@ public function getRevenueSummary(?User $user = null): array $baseQuery->where('marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $baseQuery->whereIn('created_by_id', $this->getCashierUserIds()); + } + $stats = (clone $baseQuery) ->selectRaw('COUNT(*) as total_orders') ->selectRaw('COALESCE(SUM(total_amount), 0) as total_revenue') @@ -194,12 +199,24 @@ public function getExpenseSummary(?User $user = null): array ]; } - $expenseTotal = Expense::whereDate('created_at', $today) + $expenseQuery = Expense::whereDate('created_at', $today); + + if ($user && $this->isCashierUser($user)) { + $expenseQuery->whereIn('created_by_id', $this->getCashierUserIds()); + } + + $expenseTotal = $expenseQuery ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); - $advanceTotal = EmployeeAdvance::whereDate('created_at', $today) - ->disbursed() + $advanceQuery = EmployeeAdvance::whereDate('created_at', $today) + ->disbursed(); + + if ($user && $this->isCashierUser($user)) { + $advanceQuery->whereHas('employee.user', fn ($q) => $q->whereIn('id', $this->getCashierUserIds())); + } + + $advanceTotal = $advanceQuery ->selectRaw('COALESCE(SUM(amount), 0) as total') ->first(); @@ -219,6 +236,10 @@ public function getOrderStats(?User $user = null): array $baseQuery->where('marketing_id', $user->id); } + if ($user && $this->isCashierUser($user)) { + $baseQuery->whereIn('created_by_id', $this->getCashierUserIds()); + } + $byChannel = collect(OrderChannel::values())->map(function ($channel) use ($baseQuery) { $count = (clone $baseQuery)->where('channel', $channel)->count(); $label = OrderChannel::from($channel)->label(); @@ -330,6 +351,16 @@ private function isMarketingUser(User $user): bool ]); } + private function isCashierUser(User $user): bool + { + return $user->hasRole(Role::CASHIER->value); + } + + private function getCashierUserIds(): Collection + { + return User::whereHas('roles', fn ($q) => $q->where('name', Role::CASHIER->value))->pluck('id'); + } + private function applyMarketingFilter(Builder $query, User $user, string $column = 'marketing_id'): Builder { if ($this->isMarketingUser($user)) { diff --git a/resources/js/pages/admin/analysis/index.tsx b/resources/js/pages/admin/analysis/index.tsx index d779852..0e9073a 100644 --- a/resources/js/pages/admin/analysis/index.tsx +++ b/resources/js/pages/admin/analysis/index.tsx @@ -564,6 +564,10 @@ export default function Analysis({ return { statCards: 1, revenue: 4, revenueByChannel: 5, orderPie: 6, expense: 7, totalOrder: 8, revenueTrend: 9, marketingSales: 10, topSuppliers: 11, topProducts: 12, topCustomers: 13, busyHours: 14 }; } + if (hasRole('cashier')) { + return { statCards: 1, revenue: 2, revenueByChannel: 3, orderPie: 4, totalOrder: 5, topProducts: 6, topCustomers: 7 }; + } + if (hasRole('marketing')) { return { statCards: 1, revenue: 2, revenueByChannel: 3, orderPie: 4, totalOrder: 5, revenueTrend: 6, topProducts: 7, topCustomers: 8 }; }