mivita/app/Services/BusinessPlan/BusinessUserRepository.php
2025-08-12 18:01:59 +02:00

198 lines
No EOL
5.9 KiB
PHP

<?php
namespace App\Services\BusinessPlan;
use App\User;
use App\Models\UserBusinessStructure;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use Illuminate\Support\Facades\Log;
/**
* Repository für effiziente Datenbankabfragen im Business-Kontext
* Löst N+1 Probleme durch optimierte Eager Loading Strategien
*/
class BusinessUserRepository
{
private $startDate;
private $endDate;
private $month;
private $year;
public function __construct(int $month, int $year)
{
$this->month = $month;
$this->year = $year;
$date = Carbon::parse($year.'-'.$month.'-1');
$this->startDate = $date->format('Y-m-d H:i:s');
$this->endDate = $date->endOfMonth()->format('Y-m-d H:i:s');
}
/**
* Lädt Root-User mit optimiertem Eager Loading und Caching
*/
public function getRootUsers(): Collection
{
$cacheKey = "root_users_{$this->month}_{$this->year}";
return cache()->remember($cacheKey, 3600, function() {
\Log::info("BusinessUserRepository: Loading root users from database (cache miss)");
return User::with([
'account',
'user_level',
'userBusiness' => function($query) {
$query->where('month', $this->month)
->where('year', $this->year);
}
])
->select('users.*')
->where('users.deleted_at', '=', null)
->where('users.id', '!=', 1)
->where('users.admin', '<', 4)
->where('users.m_level', '!=', null)
->where('users.m_sponsor', '=', null)
->where('users.payment_account', '!=', null)
->where('users.active_date', '<=', $this->endDate)
->get();
});
}
/**
* Lädt User ohne Parent-Zuordnung (Lazy Loading für Memory-Effizienz)
*/
public function getParentlessUsers(array $excludeUserIds = []): LazyCollection
{
$query = User::with([
'account',
'user_level',
'userBusiness' => function($query) {
$query->where('month', $this->month)
->where('year', $this->year);
}
])
->select('users.*')
->where('users.deleted_at', '=', null)
->where('users.id', '!=', 1)
->where('users.admin', '<', 4)
->where('users.payment_account', '!=', null)
->where('users.active_date', '<=', $this->endDate);
if (!empty($excludeUserIds)) {
$query->whereNotIn('users.id', $excludeUserIds);
}
return $query->lazy(100);
}
/**
* Lädt einen einzelnen User mit Relations und Caching
*/
public function getUserWithRelations(int $userId): ?User
{
$cacheKey = "user_relations_{$userId}_{$this->month}_{$this->year}";
return cache()->remember($cacheKey, 1800, function() use ($userId) {
\Log::debug("BusinessUserRepository: Loading user {$userId} with relations (cache miss)");
return User::with([
'account',
'user_level',
'userBusiness' => function($query) {
$query->where('month', $this->month)
->where('year', $this->year);
}
])->find($userId);
});
}
/**
* Lädt Sponsor für einen User
*/
public function getSponsorForUser(int $userId): ?User
{
$user = $this->getUserWithRelations($userId);
if (!$user || !$user->m_sponsor) {
return null;
}
return $this->getUserWithRelations($user->m_sponsor);
}
/**
* Prüft ob gespeicherte Struktur existiert (mit Caching)
*/
public function getStoredStructure(): ?UserBusinessStructure
{
$cacheKey = "stored_structure_{$this->month}_{$this->year}";
return cache()->remember($cacheKey, 7200, function() {
\Log::debug("BusinessUserRepository: Loading stored structure (cache miss)");
$structure = UserBusinessStructure::where('year', $this->year)
->where('month', $this->month)
->first();
return ($structure && $structure->completed) ? $structure : null;
});
}
/**
* Lädt User-IDs aus gespeicherter Struktur
*/
public function getUserIdsFromStoredStructure(UserBusinessStructure $structure): array
{
$userIds = [];
if ($structure->structure) {
$this->extractUserIdsFromStructure((array) $structure->structure, $userIds);
}
if ($structure->parentless) {
foreach ($structure->parentless as $item) {
$userIds[] = $item->user_id;
}
}
return array_unique($userIds);
}
/**
* Rekursive Extraktion von User-IDs aus Struktur
*/
private function extractUserIdsFromStructure(array $structure, array &$userIds): void
{
foreach ($structure as $item) {
$userIds[] = $item->user_id;
if (isset($item->parents) && is_array($item->parents)) {
$this->extractUserIdsFromStructure($item->parents, $userIds);
}
}
}
/**
* Batch-Loading für User-Kollektionen
*/
public function loadUsersInBatches(array $userIds, int $batchSize = 100): \Generator
{
$chunks = array_chunk($userIds, $batchSize);
foreach ($chunks as $chunk) {
yield User::with([
'account',
'user_level',
'userBusiness' => function($query) {
$query->where('month', $this->month)
->where('year', $this->year);
}
])
->whereIn('id', $chunk)
->get()
->keyBy('id');
}
}
}