diff --git a/application/AssetManagement/AssetManagementController.php b/application/AssetManagement/AssetManagementController.php index b51e86be2..0411e996c 100644 --- a/application/AssetManagement/AssetManagementController.php +++ b/application/AssetManagement/AssetManagementController.php @@ -7,7 +7,7 @@ class AssetManagementController extends TTCrud // Simplified columns for better layout, details are in the 'assetDetails' slot protected array $columns = [ - ['key' => 'assetDetails', 'text' => 'Gerät', 'modal' => false, 'table' => ['sortable' => false, 'filter' => ['type' => 'search', 'key' => 'name|assetNumber|description']]], + ['key' => 'assetDetails', 'text' => 'Gerät', 'modal' => false, 'table' => ['filter' => 'search']], ['key' => 'currentUser', 'text' => 'Status', 'modal' => false, 'table' => ['sortable' => false, 'filter' => false]], ['key' => 'location', 'text' => 'Lagerort', 'required' => true, 'modal' => ['type' => 'text'], 'table' => ['filter' => 'search']], ['key' => 'serviceDueDate', 'text' => 'Service fällig', 'required' => false, 'modal' => ['type' => 'date'], 'table' => ['filter' => 'date']], diff --git a/application/AssetManagement/AssetManagementModel.php b/application/AssetManagement/AssetManagementModel.php index 6cb2ffd57..ac7fa3ca6 100644 --- a/application/AssetManagement/AssetManagementModel.php +++ b/application/AssetManagement/AssetManagementModel.php @@ -11,4 +11,120 @@ class AssetManagementModel extends TTCrudBaseModel { public ?int $mustReturnDate; public int $create; public int $createBy; -} + + /** + * Retrieves all assets based on a filter, with special handling for 'assetDetails'. + * + * @param array $filter The filter criteria. If 'assetDetails' is present, it will perform a multi-field search. + * @param int|null $limit The maximum number of records to return. + * @param int $offset The starting offset for the records. + * @param array $order The ordering criteria. + * @return array An array of AssetManagementModel objects. + */ + public static function getAll($filter = [], $limit = null, $offset = 0, $order = ["key" => null]): array { + $db = self::getDB(); + $table = self::getFullyQualifiedTable(); + $customFilterSql = ''; + + // Check if the intelligent 'assetDetails' filter is being used. + if (!empty($filter['assetDetails'])) { + $searchTerms = explode(' ', $filter['assetDetails']); + $searchConditions = []; + + foreach ($searchTerms as $term) { + if (empty(trim($term))) continue; + $escapedTerm = $db->real_escape_string($term); + // For each term, search in name, assetNumber, and description. + $searchConditions[] = "(`name` LIKE '%$escapedTerm%' OR `assetNumber` LIKE '%$escapedTerm%' OR `description` LIKE '%$escapedTerm%')"; + } + + if (!empty($searchConditions)) { + // All search terms must be found (AND logic). + $customFilterSql = ' AND (' . implode(' AND ', $searchConditions) . ')'; + } + // Remove the 'assetDetails' key to prevent errors in the standard filter generation. + } + unset($filter['assetDetails']); + + $sqlFilter = self::getSQLFilter($filter); + + if ($sqlFilter === '') { + if ($customFilterSql !== '') { + // If the base filter is empty but a custom filter exists, start with WHERE. + $sqlFilter = 'WHERE' . ltrim($customFilterSql, ' AND'); + } + } else { + // If a base filter already exists, just append the custom one. + $sqlFilter .= $customFilterSql; + } + + $sql = "SELECT * FROM $table $sqlFilter"; + + $sql .= $order['key'] === null ? " ORDER BY `id` ASC" : " ORDER BY `" . $order['key'] . "` " . $order['order']; + $sql .= $limit === null ? "" : " LIMIT " . $limit . " OFFSET " . $offset; + + try { + $result = $db->query($sql); + } catch (Exception $e) { + echo $sql; + die($e->getMessage()); + } + + $rows = []; + $class = get_called_class(); + while ($row = $result->fetch_assoc()) { + $rows[] = new $class($row); + } + + return $rows; + } + + /** + * Counts assets based on a filter, with special handling for 'assetDetails'. + * + * @param array $filter The filter criteria. If 'assetDetails' is present, it will perform a multi-field count. + * @return int The total count of matching records. + */ + public static function count($filter = []): int { + $db = self::getDB(); + $table = self::getFullyQualifiedTable(); + $customFilterSql = ''; + + // Check if the intelligent 'assetDetails' filter is being used. + if (!empty($filter['assetDetails'])) { + $searchTerms = explode(' ', $filter['assetDetails']); + $searchConditions = []; + + foreach ($searchTerms as $term) { + if (empty(trim($term))) continue; + $escapedTerm = $db->real_escape_string($term); + // For each term, search in name, assetNumber, and description. + $searchConditions[] = "(`name` LIKE '%$escapedTerm%' OR `assetNumber` LIKE '%$escapedTerm%' OR `description` LIKE '%$escapedTerm%')"; + } + + if (!empty($searchConditions)) { + // All search terms must be found (AND logic). + $customFilterSql = ' AND (' . implode(' AND ', $searchConditions) . ')'; + } + // Remove the 'assetDetails' key to prevent errors in the standard filter generation. + } + unset($filter['assetDetails']); + + $sqlFilter = self::getSQLFilter($filter); + + if ($sqlFilter === '') { + if ($customFilterSql !== '') { + // If the base filter is empty but a custom filter exists, start with WHERE. + $sqlFilter = 'WHERE' . ltrim($customFilterSql, ' AND'); + } + } else { + // If a base filter already exists, just append the custom one. + $sqlFilter .= $customFilterSql; + } + + $sql = "SELECT COUNT(*) as count FROM $table $sqlFilter"; + $result = $db->query($sql); + + return $result->fetch_assoc()['count']; + } +} \ No newline at end of file