diff --git a/admin/categories.php b/admin/categories.php
index 9a9b2445..d9bb8a01 100644
--- a/admin/categories.php
+++ b/admin/categories.php
@@ -113,6 +113,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
} else {
echo 'btn-default';
} ?>">Contact Note Type
+ Asset Note Type
@@ -1213,6 +1235,80 @@ if (isset($_GET['asset_id'])) {
+ ">
+
+
+
+
+
+
+ | Type |
+ Note |
+ By |
+ Created |
+ Action |
+
+
+
+
+
+
+ | = $asset_note_type ?> |
+ = $asset_note ?> |
+ = $note_by ?> |
+ = $asset_note_created_at ?> |
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
diff --git a/agent/modals/asset/asset.php b/agent/modals/asset/asset.php
index ec3eca77..3419d3ca 100644
--- a/agent/modals/asset/asset.php
+++ b/agent/modals/asset/asset.php
@@ -218,6 +218,22 @@ $sql_related_software = mysqli_query(
$software_count = mysqli_num_rows($sql_related_software);
+// Related Notes
+$sql_related_notes = mysqli_query($mysqli, "SELECT * FROM asset_notes
+ LEFT JOIN users ON asset_note_created_by = user_id
+ WHERE asset_note_asset_id = $asset_id
+ AND asset_note_archived_at IS NULL
+ ORDER BY asset_note_created_at DESC"
+);
+$note_count = mysqli_num_rows($sql_related_notes);
+
+// Note type icons, read from the categories list
+$note_type_icons = array();
+$sql_note_type_icons = mysqli_query($mysqli, "SELECT category_name, category_icon FROM categories WHERE category_type = 'asset_note_type'");
+while ($row = mysqli_fetch_assoc($sql_note_type_icons)) {
+ $note_type_icons[escapeHtml($row['category_name'])] = escapeHtml($row['category_icon']);
+}
+
if (isset($_GET['client_id'])) {
$client_url = "client_id=$client_id&";
} else {
@@ -293,6 +309,13 @@ ob_start();
Files (= $file_count ?>)
+
+
+
+ Notes (= $note_count ?>)
+
+
+
@@ -913,6 +936,47 @@ ob_start();
+
+
+
+
+
+
+ | Type |
+ Note |
+ By |
+ Created |
+
+
+
+
+
+ | = $asset_note_type ?> |
+ = $asset_note ?> |
+ = $note_by ?> |
+ = $asset_note_created_at ?> |
+
+
+
+
+
+
+
+
+
diff --git a/agent/modals/asset/asset_note_add.php b/agent/modals/asset/asset_note_add.php
new file mode 100644
index 00000000..85bb3413
--- /dev/null
+++ b/agent/modals/asset/asset_note_add.php
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+$type created for $asset_name";
+
+ redirect();
+
+}
+
+if (isset($_GET['archive_asset_note'])) {
+
+ validateCSRFToken();
+
+ enforceUserPermission('module_support', 2);
+
+ $asset_note_id = intval($_GET['archive_asset_note']);
+
+ // Get Asset Name and Client ID for logging and alert message
+ $sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
+ $row = mysqli_fetch_assoc($sql);
+ $asset_note_type = escapeSql($row['asset_note_type']);
+ $asset_name = escapeSql($row['asset_name']);
+ $client_id = intval($row['asset_client_id']);
+ $asset_id = intval($row['asset_id']);
+
+ enforceClientAccess();
+
+ mysqli_query($mysqli,"UPDATE asset_notes SET asset_note_archived_at = NOW() WHERE asset_note_id = $asset_note_id");
+
+ logAudit("Asset", "Edit", "$session_name archived note $asset_note_type for $asset_name", $client_id, $asset_id);
+
+ flashAlert("Note $asset_note_type archived", 'error');
+
+ redirect();
+
+}
+
+if (isset($_GET['restore_asset_note'])) {
+
+ validateCSRFToken();
+
+ enforceUserPermission('module_support', 2);
+
+ $asset_note_id = intval($_GET['restore_asset_note']);
+
+ // Get Asset Name and Client ID for logging and alert message
+ $sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
+ $row = mysqli_fetch_assoc($sql);
+ $asset_note_type = escapeSql($row['asset_note_type']);
+ $asset_name = escapeSql($row['asset_name']);
+ $client_id = intval($row['asset_client_id']);
+ $asset_id = intval($row['asset_id']);
+
+ enforceClientAccess();
+
+ mysqli_query($mysqli,"UPDATE asset_notes SET asset_note_archived_at = NULL WHERE asset_note_id = $asset_note_id");
+
+ logAudit("Asset", "Edit", "$session_name restored note $asset_note_type for $asset_name", $client_id, $asset_id);
+
+ flashAlert("Note $asset_note_type restored");
+
+ redirect();
+
+}
+
+if (isset($_GET['delete_asset_note'])) {
+
+ validateCSRFToken();
+
+ enforceUserPermission('module_support', 3);
+
+ $asset_note_id = intval($_GET['delete_asset_note']);
+
+ // Get Asset Name and Client ID for logging and alert message
+ $sql = mysqli_query($mysqli,"SELECT asset_note_type, asset_id, asset_name, asset_client_id FROM asset_notes LEFT JOIN assets ON asset_id = asset_note_asset_id WHERE asset_note_id = $asset_note_id");
+ $row = mysqli_fetch_assoc($sql);
+ $asset_note_type = escapeSql($row['asset_note_type']);
+ $asset_name = escapeSql($row['asset_name']);
+ $client_id = intval($row['asset_client_id']);
+ $asset_id = intval($row['asset_id']);
+
+ enforceClientAccess();
+
+ mysqli_query($mysqli,"DELETE FROM asset_notes WHERE asset_note_id = $asset_note_id");
+
+ logAudit("Asset", "Edit", "$session_name deleted $asset_note_type note for $asset_name", $client_id, $asset_id);
+
+ flashAlert("Note $asset_note_type deleted.", 'error');
+
+ redirect();
+
+}
+
if (isset($_POST['bulk_assign_asset_tags'])) {
validateCSRFToken();
diff --git a/scripts/setup_cli.php b/scripts/setup_cli.php
index a6654cb7..a1fc8eb8 100644
--- a/scripts/setup_cli.php
+++ b/scripts/setup_cli.php
@@ -360,6 +360,14 @@ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Meeting', cat
mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'In Person', category_description = 'In person visit or on-site interaction', category_icon = 'fa-people-arrows', category_type = 'contact_note_type', category_order = 4"); // 4
mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Note', category_description = 'General note or internal comment', category_icon = 'fa-sticky-note', category_type = 'contact_note_type', category_order = 5"); // 5
+// Asset note types
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Maintenance', category_description = 'Routine or scheduled maintenance performed on the asset', category_icon = 'fa-tools', category_type = 'asset_note_type', category_order = 1"); // 1
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Repair', category_description = 'Repair work or hardware replacement', category_icon = 'fa-wrench', category_type = 'asset_note_type', category_order = 2"); // 2
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Configuration', category_description = 'Configuration or settings change made to the asset', category_icon = 'fa-sliders-h', category_type = 'asset_note_type', category_order = 3"); // 3
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Upgrade', category_description = 'Hardware or software upgrade', category_icon = 'fa-arrow-circle-up', category_type = 'asset_note_type', category_order = 4"); // 4
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Inspection', category_description = 'Physical inspection or audit of the asset', category_icon = 'fa-clipboard-check', category_type = 'asset_note_type', category_order = 5"); // 5
+mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Note', category_description = 'General note or internal comment', category_icon = 'fa-sticky-note', category_type = 'asset_note_type', category_order = 6"); // 6
+
// Rack Types
mysqli_query($mysqli, "INSERT INTO categories SET category_name = '2-Post Open Frame', category_description = 'Two-post open frame rack for patch panels and lightweight equipment', category_type = 'rack_type', category_order = 1"); // 1
mysqli_query($mysqli, "INSERT INTO categories SET category_name = '4-Post Open Frame', category_description = 'Four-post open frame rack for servers and heavier equipment', category_type = 'rack_type', category_order = 2"); // 2
diff --git a/setup/index.php b/setup/index.php
index f7040f5d..ab3becf2 100644
--- a/setup/index.php
+++ b/setup/index.php
@@ -608,6 +608,14 @@ if (isset($_POST['add_company_settings'])) {
mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'In Person', category_description = 'In person visit or on-site interaction', category_icon = 'fa-people-arrows', category_type = 'contact_note_type', category_order = 4"); // 4
mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Note', category_description = 'General note or internal comment', category_icon = 'fa-sticky-note', category_type = 'contact_note_type', category_order = 5"); // 5
+ // Asset note types
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Maintenance', category_description = 'Routine or scheduled maintenance performed on the asset', category_icon = 'fa-tools', category_type = 'asset_note_type', category_order = 1"); // 1
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Repair', category_description = 'Repair work or hardware replacement', category_icon = 'fa-wrench', category_type = 'asset_note_type', category_order = 2"); // 2
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Configuration', category_description = 'Configuration or settings change made to the asset', category_icon = 'fa-sliders-h', category_type = 'asset_note_type', category_order = 3"); // 3
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Upgrade', category_description = 'Hardware or software upgrade', category_icon = 'fa-arrow-circle-up', category_type = 'asset_note_type', category_order = 4"); // 4
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Inspection', category_description = 'Physical inspection or audit of the asset', category_icon = 'fa-clipboard-check', category_type = 'asset_note_type', category_order = 5"); // 5
+ mysqli_query($mysqli, "INSERT INTO categories SET category_name = 'Note', category_description = 'General note or internal comment', category_icon = 'fa-sticky-note', category_type = 'asset_note_type', category_order = 6"); // 6
+
// Rack Types
mysqli_query($mysqli, "INSERT INTO categories SET category_name = '2-Post Open Frame', category_description = 'Two-post open frame rack for patch panels and lightweight equipment', category_type = 'rack_type', category_order = 1"); // 1
mysqli_query($mysqli, "INSERT INTO categories SET category_name = '4-Post Open Frame', category_description = 'Four-post open frame rack for servers and heavier equipment', category_type = 'rack_type', category_order = 2"); // 2