Locations
A location is a physical place where an asset lives — a site, a building, a floor,
a room. Locations form a small hierarchy (rendered as a Parent > Child breadcrumb),
and once defined they appear as a Location dropdown on the asset form, as a column and
filter in the Asset Registry, and as the anchor point of
Asset Groups.
ams/assets) and click the "Location" tab next to "Browse" and
"Models". The tab loads the list via AJAX (direct URL:
ams/locations). The tab is shown only to users who hold the
location permission.
asset_ prefix. Unlike most of the module, the
Locations permissions are the bare keys location ("Assets: Locations"),
location_create, location_update and location_delete —
listed under the "Safekeep" categories in Roles. When searching the Roles screen, look for
"Assets: Locations", not "asset_location". See
Permissions & Roles for the full table.
What a location is
Each location is a simple named place with an optional description and an optional parent:
- Title
- The place name (e.g. Head Office, Floor 2, Server Room). Everywhere the location is displayed, ERPat prepends its ancestors, so what you actually see is the full path — Head Office > Floor 2 > Server Room.
- Description
- Free-text notes about the place (address details, access instructions, remarks). Entered with a rich-text editor.
- Parent
- The location this one sits inside. Leave it "-" for a top-level site.
Hierarchy depth and breadcrumbs
Locations use the same tree rules as Categories: a location may carry up to three parent layers, so the deepest practical tree is about four levels (e.g. Site > Building > Floor > Room). If you try to save a location under a parent that already sits more than three levels deep, the save is rejected with the message:
Wherever a location is displayed — the Locations list itself, the registry's Location column,
dropdowns, Asset Groups — it renders as the full breadcrumbed path joined with
">", built from up to three ancestors (e.g.
Head Office > Floor 2 > Room 5).
The Locations list
The tab shows a searchable DataTable of every location, sorted by the first column descending,
with a table refresh button and an Excel quick-export of all data columns. At the top is
the "Add location" button (plus-circle icon), shown only if you hold
location_create.
List columns
| Column | Header | Notes |
|---|---|---|
| Title | "Title" | Rendered as the full parent path, e.g. Head Office > Floor 2 > Server Room. Default sort column. |
| Description | "Description" | The location's notes (line breaks preserved). |
| Date created | "Date created" | The stored creation timestamp, displayed exactly as saved — a raw UTC value, not converted to your local timezone. |
| Created by | "Created by" | Profile link to the user who created the record (opens a new tab). |
| Options | (bars icon) | Pencil = edit (tooltip "Edit location", needs location_update); × = delete (needs location_delete, asks for delete confirmation). |
The Add / Edit form
Adding and editing use the same modal (ams/locations/modal_form), opened by
"Add location" or the row's pencil icon. The footer holds a single "Save" button
(check-circle icon); the × to close is in the modal header. Saving shows the toast
"The record has been saved."
Field reference
| Field | Name | Type | Required | Notes |
|---|---|---|---|---|
| "Title" | title |
Text | Yes (client-side; message "This field is required.") | Autofocused when the modal opens. Required-ness is enforced in the browser only — the server validates just the record id. |
| "Description" | description |
Rich-text textarea | No | Free-text notes. |
| "Parent" | parent_id |
Select2 dropdown | No (default "-") | Lists every other location by its full breadcrumbed path; the record being edited is excluded. Saving under a parent deeper than 3 layers fails with "Maximum of 3 layers parenting only". |
This is exactly the Category form minus the Fieldset dropdown — locations have no fieldset binding and never affect an asset's custom fields.
Where locations appear
Once created, a location surfaces in these places:
| Place | How it appears |
|---|---|
| Asset Registry (Browse tab) | Column "Location" (breadcrumbed path), and a "Location" dropdown in the registry's Filters modal (alongside Category, Status and Issued to). |
| Add / Edit asset modal | Optional "Location" Select2 dropdown (first option is the hardcoded "- Select Location -"). Changing it on an existing asset is change-logged on the asset's activity feed, e.g. "Location updated from A to B". |
| Asset detail page | The sub-title strip shows "Location: …" when the asset has one. |
| Export Assets | A "Location" filter dropdown in the export modal, and a "Location" column in the exported assets.xlsx. |
| Print asset labels | A "Location" filter (with Category) that scopes which assets get QR label pages. |
| Import | An imported Location name is matched case-insensitively against existing locations, and auto-created as a new top-level location if no match exists. |
| Asset Groups | Each group can be pinned to one location via the group form's "Location" dropdown; the groups list shows the full breadcrumbed path in its "Location" column. |
Deleting a location — no protections
Deleting is an unconditional soft delete: the × icon asks for confirmation, then removes the record with the toast "The record has been deleted." There is no in-use check — ERPat will happily delete a location that assets, asset groups, or child locations still point at. (The failure message "The record is in use, you can't delete the record!" exists in the product but is effectively never shown here, because the delete always succeeds.)
-" in the registry's Location column, and the detail page's
"Location: …" strip stops appearing. Child locations are not deleted with
their parent — they remain, and the deleted ancestor's name still shows up in their
breadcrumbs (paths are built without re-checking whether an ancestor was deleted).
Practical guidance: how granular should locations be?
Model the tree on how you actually search for and audit equipment. The 4-level cap maps neatly onto Site → Building → Floor → Room:
Two levels is plenty: Makati HQ > Server Room, Makati HQ > Reception. Don't create rooms you'll never filter by.
Top level = branch/site (Cebu Branch, Davao Branch), then floor or department-area beneath. Keeps registry filters one click deep.
Use all four: Laguna Plant > Building B > Mezzanine > Cage 3. Stop at the level a physical audit walk actually covers.
- Keep locations physical. "IT Department" is an org unit, not a place — use Categories and Groups for logical bundles, locations for where things are.
- Name for the breadcrumb. Child titles don't need to repeat the parent — the path is always shown, so name the room Room 5, not Head Office Room 5.
- Match your import data. The importer matches location names case-insensitively and creates missing ones as top-level entries — so build the tree before a big import, or you'll get flat duplicates to clean up.
- Audit by location. A location-filtered label print run (one QR sheet per room) plus a walk-through with the audit modal is the cheapest physical inventory you can do.
SOP: Build a location tree
Who: a user with
location + location_create (typically the IT admin).Preconditions: the Assets module is enabled (see Getting Started).
-
Open the Location tab
Go to Safekeep → Assets and click the "Location" tab.
-
Create the top-level sites first
Click "Add location", enter the Title (e.g. Head Office), leave Parent as "-", and Save. Repeat for every site/branch.
-
Add children under each site
Add floors, then rooms, picking the correct Parent each time. Remember the depth limit — going past three parent layers is rejected with "Maximum of 3 layers parenting only".
-
Point assets at the locations
Edit each asset (or set the Location during creation / import) and choose the location from the dropdown. The registry's Location column and filter now light up.