Assets - edmozley/freeitsm GitHub Wiki

Assets

Folder: asset-management/ Colour: Green #107c10

IT asset management with VMware vCenter and Microsoft Intune integration. Tracks the estate from physical and virtual machines down to user-asset assignments.

The Users tab turns that last part around: rather than asking which person an asset belongs to, it shows everything one person holds and produces a handover document for them to sign โ€” with the layout yours to design. See Who holds what, and handover documents.

Assets Tab

Searchable asset list with user assignments (many-to-many โ€” one machine can have multiple users, one user can be assigned to multiple machines). Asset detail panel shows hardware specs, network adapters, disks, GPU, TPM, BitLocker state, installed software, and (when matched) Intune device data.

QR Labels

Every asset can carry an asset tag (the number you write on kit โ€” LT0001) and a printable QR label. Print one from the asset, or Ctrl/Shift-click several in the list and print a batch onto standard label stock โ€” straight from the browser, with no PDF step, and with the codes generated inside your own install rather than by an outside service.

Scanning a label with any phone camera opens a phone-shaped page for that asset โ€” what it is, who has it, serial, warranty, last seen โ€” and lets you change its status and location on the spot, which turns an asset audit into something you do while walking round rather than something you write down and type up afterwards.

Asset tags are unique per company, so two companies on one install can each run their own LT0001. For durable labels there's a CSV export for a print house, and for companies that buy pre-printed sequential tags there's Assets โ†’ Assign tags: scan the manufacturer's serial, scan the tag, save, repeat.

See the dedicated QR asset labels page for printing, scanning and both tagging directions โ€” plus the Developer Guide for why the code encodes neither the tag nor the asset id, and why per-company uniqueness cannot be a unique index.

Check-In / Check-Out

Assigning a user to an asset records a check-out (with an optional expected return date shown as "Due back"); removing them records a check-in. A Custody button on the asset opens the full check-out/check-in trail โ€” who held it, when, the due-back date, and which analyst actioned it โ€” stored in asset_checkout_log.

Which company an asset belongs to

On a multi-company install, Key info shows the asset's Company, and changing it moves the asset. Add asset asks which company it is for. See Moving an asset between companies.

Location, Procurement & Warranty

Each asset can be placed in the physical location hierarchy (see Settings โ†’ Locations below; on a multi-company install a location can be shared by every company) and carry purchase date, cost, supplier, order number and warranty expiry โ€” all editable inline on the detail panel and shown in the table view. Every change is logged to asset history.

Supplier is normalised โ€” it's a dropdown of suppliers from the shared registry, chosen in Settings โ†’ Suppliers (see below), not free text.

Table View (table.php)

Full-screen spreadsheet-style alternative to the split-pane Assets tab. Built for power users who want to slice, sort and export the estate rather than drill into one asset at a time. Reachable from the Table button in the module nav (between Assets and Dashboard).

The Table view supports saved views: save the columns, sort and filters under a name, share it with a team or everyone, and set one as the view the table opens with.

Sort, search and filter

  • Click a column header to sort โ€” cycles ascending โ†’ descending โ†’ ascending. Active sort column's arrow highlights in blue.
  • Funnel icon on each header opens an Excel-style dropdown listing the distinct values in that column with row counts and an inline search box. Untick a value to hide rows that have it; tick again to show. Select all and Clear shortcuts at the top.
  • Cascading filters โ€” the distinct-values list for one column is narrowed by whatever other column filters are active, so the dropdown only shows values that actually appear in the rows still visible (matching Excel's behaviour exactly).
  • Global search box at the top matches the typed term as a substring across every visible column (so hiding a column also takes it out of search scope).
  • Reset button clears every filter, the search box and the sort in one click.

Customise columns

The default visible set is Hostname, Type, Status, Manufacturer, Model, OS, Assigned users and Last seen. Click the Columns button on the toolbar to open a drawer with:

  • A checkbox per column for show/hide.
  • Drag handles (โ‹ฎโ‹ฎ) to reorder. Drag-reorder also works directly on the table headers themselves.

The available hidden-by-default columns include Feature release, Build, Service tag, CPU, CPU speed, Memory, BIOS and First seen. Visible columns, column order and sort direction persist per analyst โ€” saved against the account via user_preferences (key: asset_table_v1) so the layout follows the user across browsers. Search and active filters are deliberately transient session state.

Export

  • CSV โ€” UTF-8 with a byte-order mark so Excel opens it cleanly; embedded commas, quotes and newlines properly escaped. Exports the current view (visible columns, after filters / search / sort).
  • PDF โ€” landscape A4, blue header band, company logo on the top left, "{visible} of {total} โ€” {timestamp}" subhead. Text is selectable (not a rasterised screenshot) because it's generated with jsPDF + autotable, the same library and approach the morning-checks module uses.

Click-through โ€” click any row to jump to that asset's detail in the split-pane view.

Extensibility

The whole feature is driven by a single COLUMNS catalogue at the top of assets/js/asset-table.js. Adding a future asset field is two lines (append to that array, ensure api/assets/get_assets.php returns the field) and sort, filter, search, CSV and PDF will all pick it up automatically โ€” no per-column wiring.

Design decision: client-side

All filtering / sorting / searching happens in JS against the data loaded once from get_assets.php. We chose this over server-side AJAX after debating it: at FreeITSM's realistic scale (< 10k assets per install), instant filter / sort beats round-tripping the server per keystroke, and the Excel-style per-column distinct-values filter is much cleaner against an in-memory dataset. If a customer ever lands with 20k+ assets and the page feels sluggish we'd add server-side mode then, triggered automatically by row count rather than as an admin-facing toggle.

Servers Tab (servers/)

Virtual machine inventory synced from the VMware vCenter REST API and, since 3.1.0, from any number of Proxmox VE and VMware Cloud Director servers (PR #167). A Source column says which; Sync hypervisors syncs them all. How it works: Proxmox and Cloud Director โ€” Developer Guide.

  • Displays VM name, guest OS, IP, host, cluster, CPU, memory, disk
  • Clickable rows open a detail modal with the raw vCenter JSON for that VM
  • Stores all API response data in servers.raw_data so future fields can be surfaced without re-syncing

Sync flow

  1. The settings page stores the vCenter credentials (encrypted at rest)
  2. api/assets/get_vcenter.php authenticates with the vCenter REST API
  3. Fetches hosts, clusters, and VMs โ€” including guest identity and filesystems
  4. Builds host / cluster maps by querying the VMs per host and per cluster
  5. Stores everything, including the raw JSON, in the servers table

Dashboard (dashboard/)

Per-analyst customisable Chart.js dashboard.

  • 13 pre-built widgets (bar, pie, doughnut) covering OS, manufacturer, model, memory, GPU, TPM, BitLocker, etc.
  • Each analyst picks widgets for their own dashboard
  • Status filtering on supported widgets
  • Drag-and-drop reordering

Intune Integration

Pulls all managed devices from Microsoft Intune (via Microsoft Graph /deviceManagement/managedDevices) into the intune_devices table and links them to assets by hostname. Unknown hostnames auto-create stub assets so nothing is dropped.

  • The asset detail panel shows an extra Intune tab when a device matches
  • Sync runs as a background worker with a live progress bar in the settings page
  • Reporting โ†’ Intune Dashboard provides curated analytics on top of this data

PowerShell Inventory Agent

scripts/Invoke-AssetInventory.ps1 runs on Windows machines and posts to two external API endpoints:

  • api/external/system-info/submit/ โ€” hardware, disks, network, GPU, TPM, BitLocker, installed software
  • api/external/device-manager/submit/ โ€” Windows Device Manager devices (category, name, driver manufacturer, driver version, status), displayed grouped by device class on the asset detail screen

Both endpoints authenticate with an API key generated at Software โ†’ Settings โ†’ API Keys.

See The inventory agent for running it, rolling it out as a scheduled task, what it collects, and what to do when FreeITSM is behind a self-signed certificate.

Is this asset still reporting?

Every agent report stamps First seen and Last seen on the asset, and both are shown on the Key info tab alongside how long ago that was โ€” "20.08.2026 16:29 ยท 21 days ago", in your own timezone. Once a machine has gone more than seven days without reporting the relative phrase turns amber, which is the same seven days the Watchtower dashboard counts as "not seen".

An asset that no agent will ever report โ€” a television, a SIM card, anything added by hand โ€” says Never reported rather than showing a blank, so the two cases are distinguishable at a glance.

Last seen is also a column in the Table view, visible by default and sortable; sort it ascending and the machines that stopped reporting come to the top. First seen is available in the column picker.

From the Watchtower Assets card, the "N assets not seen in 7+ days" line is a link: it opens the asset table filtered to exactly those machines, with a banner saying so and a Show all link back out.

Drives

The Storage section of an asset's Key info tab lists two things:

  • the volumes โ€” C:, D:, their labels, how full they are
  • the Drives underneath them โ€” the physical disks, each with its model, serial number, capacity, media type and interface

They are separate because one drive can carry several volumes and one volume can span several drives. The serial is the useful part: it is what a warranty claim and a disposal certificate both ask for, and nothing else in FreeITSM records it. A drive that reports no serial โ€” common with USB enclosures and virtual disks โ€” says No serial reported.

The Drives panel is hidden entirely on an asset that has none, so a hand-entered asset does not carry an empty section around. Drives need System โ†’ Database Verification to have been run on this version; until then the rest of the agent's report still lands normally.

Also available over the API as GET /api/v1/assets/{id}/physical-disks.

Hiding drives you don't want to see

Windows reports mounted virtual disks through the same class as real hardware, so most machines carry a ~31 MB Microsoft Virtual Disk beside their actual drive. One is a curiosity; six hundred is a panel nobody reads.

Hover a drive card and press Hide. The dialog offers to take the rest with it โ€” "Also hide the other 49 drives like this, across every asset" โ€” with the count worked out live and scoped to the companies you can see. A Show hidden (n) link appears in the Drives header whenever something is being withheld.

Hiding is a display choice. The drive stays in the database and stays in the REST API; all that changes is whether the asset screen draws it.

Rules describe the drive, not the row. A rule matches on the model and the exact size, and there are no wildcards โ€” a drive with the same model at a different size stays visible until you hide that one as well. That is deliberate: a rule tuned to the data in front of you behaves unpredictably on data nobody has seen yet. It also has to work this way, because the inventory agent deletes and reinserts every drive row on every report, so anything remembered against a row would be forgotten by the next run.

Show is broader than Hide: it clears every rule that could be hiding that drive, estate-wide ones included. The dialog tells you when that is about to bring other drives back before you confirm.

Tickets raised against an asset

Every asset has a Tickets tab listing what has been reported against it โ€” open first, then history. It is populated by linking equipment to a ticket, from the ticket's Affected equipment section or by a requester choosing their own device in the portal. See Linking equipment to tickets.

Settings

  • vCenter: server URL, username, password (all encrypted at rest)
  • Microsoft Intune: tenant ID, client ID, client secret, verify-SSL toggle (sensitive values encrypted)
  • Sync button: kicks off the Intune device-import background worker
  • Warranty alerts: choose where to surface assets whose warranty has expired or is expiring within a configurable number of days โ€” a red card on the Watchtower dashboard, events on the Calendar (auto-synced into a "Warranty" category), both, or off. Calendar events are regenerated whenever a warranty date changes or the setting is saved, so they stay in step without a cron job
  • Suppliers: the asset supplier is normalised against the shared suppliers registry (the same one the Contracts module uses) via a supplies_assets flag. The tab searches the registry and toggles which suppliers are available for assets, and can quick-add a new supplier by name (creating a minimal registry row you can flesh out later in Contracts). Only flagged, active suppliers appear in the asset supplier dropdown
  • Locations: build an arbitrary-depth physical location hierarchy (adjacency-list tree in asset_locations) โ€” nest as deep or shallow as you like and each branch is independent (e.g. UK โ€บ London โ€บ Office 1 alongside a flat Datacentre). Add a sub-location from any node, rename, re-parent (with cycle protection), collapse/expand branches, and delete (blocked while a location still has children). On a multi-company install, someone with access to every company can mark a location Shared with every company - see Shared asset locations

Help

Interactive guide at asset-management/help.php covering asset overview, detail screen, inventory script deployment, collected data, server management, and dashboard widgets.

Key Tables

Table Purpose
assets Core asset record (incl. asset_tag + qr_token โ€” see QR asset labels)
user_assets Many-to-many user assignments
servers vCenter-synced VM inventory (incl. raw_data JSON)
intune_devices Intune-synced managed devices
asset_disks, asset_network_adapters Inventory detail tables
asset_physical_disks The physical drives behind the volumes โ€” model, serial, capacity, media type, interface
asset_disk_hide_rules Drives you have chosen not to display; matched on model + exact size, never on a disk row id
asset_software, software_inventory Installed software
asset_devices Windows Device Manager enumeration
asset_checkout_log Check-out / check-in custody trail
asset_locations Physical location hierarchy (adjacency-list tree)
suppliers Shared supplier registry (with Contracts); supplies_assets flags availability for assets

On a phone

Assets is mobile-friendly โ€” the list, the asset itself, the Devices/Software tabs, the History and Custody trails, and the table view, dashboard, settings and Servers pages. See Mobile: Assets.

Right-click an asset

Right-clicking any asset in the list opens a menu of the things most often done to one piece of equipment, without opening it:

  • Status, Type and Location โ€” submenus of everything configured, with a tick against the current value, so the menu says what it is as well as what it could be
  • Add to a contract โ€” the picker from Equipment covered by a contract
  • Assign to somebody
  • Print label
  • Copy asset tag / Copy serial number โ€” shown only when the asset has one

๐Ÿ”‘ Right-clicking selects the asset first, so the detail panel and the menu can never disagree about which machine is being changed.

Every entry goes through the same endpoints the detail panel uses, so validation, the audit trail and the warranty-calendar sync come with them rather than being reimplemented. The menu itself reuses .ticket-context-menu from inbox.css, which this page already loads.