where('business_id', $businessId) ->where('type', 'sell') ->where('status', 'final') ->where('transaction_date', '>=', $startDate->copy()->startOfDay()) ->where('transaction_date', '<=', $endDate->copy()->endOfDay()); $this->applyLocationFilter($query, $locationIds); $this->assignmentScope->applyToQuery($query, null, [ 'holding_entity_id' => 'transactions.holding_entity_id', 'location_id' => 'transactions.location_id', ]); return (float) $query->sum('final_total'); } /** * @param array $entityLocationMap * @return array */ public function entitySalesBatch( int $businessId, array $entityIds, array $entityLocationMap, Carbon $startDate, Carbon $endDate ): array { if (empty($entityIds) || ! Schema::hasTable('transactions')) { return []; } $results = array_fill_keys($entityIds, 0.0); if (Schema::hasColumn('transactions', 'holding_entity_id')) { $query = DB::table('transactions') ->select('holding_entity_id', DB::raw('SUM(final_total) as total')) ->where('business_id', $businessId) ->where('type', 'sell') ->where('status', 'final') ->whereIn('holding_entity_id', $entityIds) ->where('transaction_date', '>=', $startDate->copy()->startOfDay()) ->where('transaction_date', '<=', $endDate->copy()->endOfDay()) ->groupBy('holding_entity_id'); $this->assignmentScope->applyToQuery($query, null, [ 'holding_entity_id' => 'transactions.holding_entity_id', 'location_id' => 'transactions.location_id', ]); foreach ($query->get() as $row) { $results[(int) $row->holding_entity_id] = (float) $row->total; } return $results; } foreach ($entityIds as $entityId) { $locationId = (int) ($entityLocationMap[$entityId] ?? 0); if ($locationId <= 0) { continue; } $query = DB::table('transactions') ->where('business_id', $businessId) ->where('type', 'sell') ->where('status', 'final') ->where('location_id', $locationId) ->where('transaction_date', '>=', $startDate->copy()->startOfDay()) ->where('transaction_date', '<=', $endDate->copy()->endOfDay()); $this->assignmentScope->applyToQuery($query, null, [ 'location_id' => 'transactions.location_id', ]); $results[$entityId] = (float) $query->sum('final_total'); } return $results; } /** * @return array */ public function monthlySalesSeries(int $businessId, Carbon $endDate, int $months = 6): array { if (! Schema::hasTable('transactions')) { return array_fill(0, $months, 0.0); } $start = $endDate->copy()->startOfMonth()->subMonths($months - 1)->startOfDay(); $end = $endDate->copy()->endOfMonth()->endOfDay(); $query = DB::table('transactions') ->selectRaw('DATE_FORMAT(transaction_date, "%Y-%m") as month_key, SUM(final_total) as total') ->where('business_id', $businessId) ->where('type', 'sell') ->where('status', 'final') ->where('transaction_date', '>=', $start) ->where('transaction_date', '<=', $end) ->groupBy('month_key'); $this->assignmentScope->applyToQuery($query, null, [ 'holding_entity_id' => 'transactions.holding_entity_id', 'location_id' => 'transactions.location_id', ]); $byMonth = $query->pluck('total', 'month_key')->all(); $series = []; for ($i = $months - 1; $i >= 0; $i--) { $key = $endDate->copy()->startOfMonth()->subMonths($i)->format('Y-m'); $series[] = (float) ($byMonth[$key] ?? 0); } return $series; } /** * @return array */ public function monthlyCountSeries( int $businessId, string $table, string $dateColumn, Carbon $endDate, int $months = 6 ): array { if (! Schema::hasTable($table) || ! Schema::hasColumn($table, $dateColumn)) { return array_fill(0, $months, 0); } $start = $endDate->copy()->startOfMonth()->subMonths($months - 1)->startOfDay(); $end = $endDate->copy()->endOfMonth()->endOfDay(); $byMonth = DB::table($table) ->selectRaw('DATE_FORMAT('.$dateColumn.', "%Y-%m") as month_key, COUNT(*) as total') ->where('business_id', $businessId) ->where($dateColumn, '>=', $start) ->where($dateColumn, '<=', $end) ->groupBy('month_key') ->pluck('total', 'month_key') ->all(); $series = []; for ($i = $months - 1; $i >= 0; $i--) { $key = $endDate->copy()->startOfMonth()->subMonths($i)->format('Y-m'); $series[] = (int) ($byMonth[$key] ?? 0); } return $series; } protected function applyLocationFilter($query, ?array $locationIds): void { if ($locationIds === null) { $locationIds = $this->assignmentScope->allowedLocationIds(); } if ($locationIds !== null && ! empty($locationIds)) { $query->whereIn('location_id', $locationIds); } } }