'id', 'text' => 'ID', 'modal' => false, 'table' => false], ['key' => 'name', 'text' => 'Gerät', 'required' => true, 'modal' => ['type' => 'text']], ['key' => 'assetNumber', 'text' => 'Kennzeichen / Nr.', 'required' => true, 'modal' => ['type' => 'text']], ['key' => 'currentUser', 'text' => 'Akt. Mitarbeiter', 'modal' => false, 'table' => ['sortable' => false]], ['key' => 'currentSite', 'text' => 'Akt. Baustelle', 'modal' => false, 'table' => ['sortable' => false]], ['key' => 'borrowDate', 'text' => 'Ausgeliehen seit', 'modal' => false, 'table' => ['sortable' => false]], ['key' => 'location', 'text' => 'Lagerort', 'required' => true, 'modal' => ['type' => 'text']], ['key' => 'serviceDueDate', 'text' => 'Service fällig', 'required' => false, 'modal' => ['type' => 'datepicker']], ['key' => 'journal', 'text' => 'Historie', 'modal' => false, 'table' => ['sortable' => false, 'filter' => false]], ['key' => 'actions', 'text' => 'Aktionen', 'modal' => false, 'table' => ['filter' => false, 'sortable' => false]], ]; protected array $permissionCheck = ['WarehouseAdmin']; // Or a new permission protected function getAction() { $json = json_decode(file_get_contents('php://input'), true); $assets = AssetManagementModel::getAll([], $this->request->order); $assetIds = array_map(fn($asset) => $asset->id, $assets); if (empty($assetIds)) { self::returnJson(['rows' => [], 'pagination' => ['total_rows' => 0, 'total_pages' => 1, 'page' => 1, 'per_page' => 10, 'filtered_available' => 0]]); return; } // Get the latest open journal entry for each asset $journalEntries = AssetManagementJournalModel::getLatestOpenEntries($assetIds); $journalMap = []; foreach ($journalEntries as $entry) { // Only map it if it's not returned if ($entry->returnDate === null) { $journalMap[$entry->assetId] = $entry; } } $users = UserModel::search(['employee' => true]); $userMap = array_reduce($users, function ($carry, $user) { $carry[$user->id] = $user->name; return $carry; }, []); $rows = []; foreach ($assets as $asset) { $row = (array)$asset; $latestJournal = $journalMap[$asset->id] ?? null; $row['journalId'] = $latestJournal->id ?? null; $row['currentUser'] = $latestJournal ? ($userMap[$latestJournal->userId] ?? 'Unbekannt') : null; $row['currentUserId'] = $latestJournal->userId ?? null; $row['currentSite'] = $latestJournal->site ?? null; $row['borrowDate'] = $latestJournal->borrowDate ?? null; $rows[] = $row; } // Simple pagination/filtering after getting all data // For larger datasets, this should be done in the SQL query $totalRows = count($rows); $pagination = $json['pagination'] ?? ['page' => 1, 'per_page' => 10]; $paginatedRows = array_slice($rows, ($pagination['page'] - 1) * $pagination['per_page'], $pagination['per_page']); self::returnJson([ 'rows' => $paginatedRows, 'pagination' => [ 'page' => $pagination['page'], 'per_page' => $pagination['per_page'], 'total_rows' => $totalRows, 'total_pages' => ceil($totalRows / $pagination['per_page']) ] ]); } protected function suggestAssetNumberAction() { $lastAsset = AssetManagementModel::getOne([], ['order' => 'DESC', 'key' => 'id']); if (!$lastAsset || !preg_match('/XI(\d+)/', $lastAsset->assetNumber, $matches)) { $nextNumber = 1; } else { $nextNumber = intval($matches[1]) + 1; } $newAssetNumber = 'XI' . str_pad($nextNumber, 3, '0', STR_PAD_LEFT); self::returnJson(['success' => true, 'assetNumber' => $newAssetNumber]); } protected function borrowAction() { $post = json_decode(file_get_contents('php://input'), true); if (empty($post['assetId']) || empty($post['userId']) || empty($post['site']) || empty($post['reason'])) { self::sendError("Alle Felder sind erforderlich."); } AssetManagementJournalModel::create([ 'assetId' => $post['assetId'], 'userId' => $post['userId'], 'site' => $post['site'], 'borrowReason' => $post['reason'], 'borrowDate' => time(), 'createBy' => $this->user->id, 'create' => time(), ]); self::returnJson(['success' => true, 'message' => 'Gerät erfolgreich ausgeliehen.']); } protected function returnAction() { $post = json_decode(file_get_contents('php://input'), true); if (empty($post['journalId'])) { self::sendError("Journal-Eintrag nicht gefunden."); } $journalEntry = AssetManagementJournalModel::get($post['journalId']); if (!$journalEntry) { self::sendError("Journal-Eintrag nicht gefunden."); } $journalEntry->returnDate = time(); $journalEntry->returnReason = $post['reason'] ?? 'Zurückgegeben'; AssetManagementJournalModel::update((array)$journalEntry); self::returnJson(['success' => true, 'message' => 'Gerät erfolgreich zurückgegeben.']); } protected function getJournalAction() { if (empty($this->request->assetId)) self::sendError("Asset ID fehlt."); $entries = AssetManagementJournalModel::getAll(['assetId' => $this->request->assetId], null, 0, ['key' => 'borrowDate', 'order' => 'DESC']); // Enhance with user names $users = UserModel::search(['employee' => true]); $userMap = array_reduce($users, function ($carry, $user) { $carry[$user->id] = $user->name; return $carry; }, []); foreach ($entries as $entry) { $entry->userName = $userMap[$entry->userId] ?? 'Unbekannt'; } self::returnJson($entries); } }