A small IT asset inventory system built around a nested folder tree, matching the project brief: Go + html/template + Bootstrap 5 + vanilla JS, SQLite storage (WAL, FKs, migrations), embedded templates/static assets, single compiled binary. - AJAX-driven inventory tree: lazy-loaded folder expansion with per-user persisted expand state, drag-and-drop move for folders/assets, safe delete-with-relocate-or-cascade confirmation, search with breadcrumbs. - Assets: CRUD, duplicate, move, auto-generated IT-000001-style IDs, CSV import (with optional folder auto-create) and export. - Admin-defined item types with custom fields (text/long_text/number/date/ boolean/dropdown/url/ip_address). - Configurable statuses, session-based auth (bcrypt, secure cookies), admin/user roles, user management. - CLI: serve, version, database migrate, database backup; /healthz; graceful shutdown; Dockerfile/docker-compose/systemd unit; Go test suite.
65 lines
1.6 KiB
Go
65 lines
1.6 KiB
Go
package assets
|
|
|
|
import (
|
|
"context"
|
|
|
|
"inventree/internal/models"
|
|
)
|
|
|
|
// Search performs a global, case-insensitive substring search across asset
|
|
// ID, name, notes, folder name, item type name, assigned username, and
|
|
// custom field values, returning fully-loaded assets (with folder path and
|
|
// custom fields) ready for display with breadcrumbs.
|
|
func (s *Store) Search(ctx context.Context, query string, limit int) ([]models.Asset, error) {
|
|
if query == "" {
|
|
return nil, nil
|
|
}
|
|
if limit <= 0 || limit > 200 {
|
|
limit = 50
|
|
}
|
|
like := "%" + query + "%"
|
|
|
|
rows, err := s.db.QueryContext(ctx, `
|
|
SELECT DISTINCT a.id
|
|
FROM assets a
|
|
LEFT JOIN folders fo ON fo.id = a.folder_id
|
|
LEFT JOIN users au ON au.id = a.assigned_user_id
|
|
JOIN item_types it ON it.id = a.item_type_id
|
|
WHERE a.asset_id LIKE ? COLLATE NOCASE
|
|
OR a.name LIKE ? COLLATE NOCASE
|
|
OR a.notes LIKE ? COLLATE NOCASE
|
|
OR fo.name LIKE ? COLLATE NOCASE
|
|
OR it.name LIKE ? COLLATE NOCASE
|
|
OR au.username LIKE ? COLLATE NOCASE
|
|
OR EXISTS (SELECT 1 FROM custom_field_values v WHERE v.asset_id = a.id AND v.value LIKE ? COLLATE NOCASE)
|
|
ORDER BY a.name COLLATE NOCASE ASC
|
|
LIMIT ?`,
|
|
like, like, like, like, like, like, like, limit)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var ids []int64
|
|
for rows.Next() {
|
|
var id int64
|
|
if err := rows.Scan(&id); err != nil {
|
|
rows.Close()
|
|
return nil, err
|
|
}
|
|
ids = append(ids, id)
|
|
}
|
|
rows.Close()
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var out []models.Asset
|
|
for _, id := range ids {
|
|
a, err := s.Get(ctx, id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, *a)
|
|
}
|
|
return out, nil
|
|
}
|