Assets Reference Public

Custom Fields & Fieldsets

Catalog & Setup Custom Fields & Fieldsets Custom Fields let you record data ERPat's built-in asset form doesn't have a box for — serial-adjacent details like IMEI, MAC address, OS…

Guide version: r1 Module version: 1.0.0 Updated: 2026-07-22 Estimated time: 11 min 2 views
Catalog & Setup

Custom Fields & Fieldsets

Custom Fields let you record data ERPat's built-in asset form doesn't have a box for — serial-adjacent details like IMEI, MAC address, OS version, or BIR property sticker number. Fields are defined once as a global catalog, bundled into Fieldsets, and a Category binds one fieldset — every asset in that category then shows those fields as an "Additional fields" section on its add/edit form.

ℹ️
Where it lives. Open Safekeep › Custom Fields (URL ams/custom_fields). It is a standalone page headed Custom Fields with two tabs: "Browse" (the field catalog) and "Fieldsets" (which loads the Fieldsets screen, ams/fieldsets, into the second tab). The Fieldsets tab is the only door — there is no separate Fieldsets item in the Safekeep sidebar.

Who can use this

IT AdminAsset custodian

Both screens are gated on the Assets module being enabled plus the single base permission asset ("Assets: Entries"). There are no separate create / update / delete permits here: anyone who can open Custom Fields or Fieldsets can also add, edit, and delete records. Plan role assignments accordingly — see Permissions & Roles.

How a custom field reaches an asset

Fields never attach to an asset directly. The chain is:

1 · Custom Field
Define the global field master (name, key, type, format).
2 · Fieldset
Bundle fields in order; set per-fieldset "Required".
3 · Category
Bind ONE fieldset in the Category form's "Fieldset" dropdown.
4 · Asset form
Assets in that category show the fields under "Additional fields".

On every save the system compiles the fieldset into a cached schema on the category, so the asset form (and the mobile API) always reads an up-to-date field list. An Asset Model can also carry a fieldset reference, but it is the category's bound fieldset that drives the "Additional fields" section on the asset form.

The values a user types are stored inside the asset record's meta JSON, keyed by each field's Field Key — see Adding & Editing Assets.

⚠️
Where you can see the values. Custom-field values are visible in exactly two places: the asset's Edit modal and the XLSX export of the asset list. The asset detail page does not display them. Don't expect auditors to read IMEI numbers off the detail page — hand them the export instead (Import, Export & Labels).

Part 1 — Custom Fields (Browse tab)

The Browse tab is the global catalog of reusable field definitions. It is a searchable DataTable with a refresh button and XLS export, sorted ascending by Name. The header button — labeled simply "Custom Field" (plus-circle icon; note it's the noun, not "Add Custom Field") — opens the add modal.

List columns

ColumnMeaningNotes
NameThe field's display label.Shown as the field label on the asset form.
Field KeyThe stable snake_case storage key.Rendered in code style; this is the map key inside the asset's meta JSON.
Field TypeThe input element type.One of the 8 element types below (e.g. "Text", "Dropdown (select)").
Format / ValidationThe validation rule string.Default ANY (no extra validation).
Required"Yes" / "No".The default required flag — the working required-ness is set per row inside a Fieldset (see below).
Primary (identifying) field"Yes" / "No".Marks the field as an identifying attribute of the asset.
Created byAuthor.Profile link.
Options (☰)Row actions.Pencil = edit (opens the same modal pre-filled); × = delete with confirmation.

The Custom Field form

Add and edit share one modal (posts to ams/custom_fields/save) with a single footer Save button. On success you'll see the toast "The record has been saved."

FieldMeaningRequiredNotes
Name The label users see on the asset form. Required Text, autofocus. Enforced client-side ("This field is required.") and server-side.
Field Key The permanent storage key inside the asset's meta JSON. No Placeholder auto_generated_from_name. Help text: "Stable snake_case key stored in the asset's meta JSON. Leave blank to derive it from the name." Whatever you type is slugified to lowercase snake_case; left blank, it is derived from Name (e.g. "MAC Address" → mac_address).
Field Type Which input element the asset form renders. No (defaults to "Text") Select2 dropdown of the 8 element types below.
Format / Validation An intended validation rule for the entered value. No (defaults to ANY) Free text; the placeholder shows the accepted grammar: ANY | NUMERIC | DATE | EMAIL | URL | regex:/.../. The rule is stored and carried into the compiled schema, but it is not enforced when an asset is saved today (see "Validation on the asset form" below).
Field Values / Options The choice list for choice-type fields. No Textarea; placeholder "One option per line (for select / checkbox / radio)."; help text "Used only by select, checkbox and radio fields. One option per line." (Pipe | separators are also accepted.)
Help Text A hint stored with the field. No Plain text. It is carried into the compiled schema, but the asset form does not currently display it under the input.
Options (checkbox group) Six behavior flags. No See the flags table below. Only Display to user is ticked by default on new fields.

The 8 field types

Type labelRenders on the asset form asUses "Field Values / Options"?
TextSingle-line text input.No
TextareaSingle-line text input (currently the same as Text — no multi-line box yet).No
NumberNumeric input.No
DateText input with a date picker.No
Dropdown (select)Single-choice dropdown (with a "-" blank option).Yes — one option per line
CheckboxSingle-choice dropdown (currently the same as Dropdown).Yes — one option per line
RadioSingle-choice dropdown (currently the same as Dropdown).Yes — one option per line
Yes / No (boolean)A single checkbox.No
ℹ️
The 8 types are simplified into 5 inputs when the asset form renders them: Dropdown (select), Checkbox, and Radio all currently render as the same single-choice dropdown built from the options list, and Textarea renders as a single-line text input. Pick the type by the data you're storing, but don't expect multi-select checkboxes or radio buttons on the form today.
????
The header "Field Type" is reused with different meanings on three Safekeep screens: here it means the input element type; on Status Labels it means the deploy meta-type; on Depreciations it means Amount vs Percentage. Same words, three vocabularies — the Glossary keeps them apart.

The Options flags — which ones actually do something

FlagDefaultEffect today
RequiredUncheckedInformational only. It shows as the "Required" Yes/No column on the Browse list, but it is not what the asset form enforces — and it doesn't even pre-fill the Fieldset builder (new rows always start unchecked). The working required flag is the per-row "Required" checkbox inside the Fieldset builder.
Primary (identifying) fieldUncheckedCarried into the compiled field schema as the field's primary marker and shown as a Yes/No list column.
UniqueUncheckedStored, not used — saved to the field record but not carried into the compiled schema; no runtime effect on the asset form yet.
EncryptedUncheckedStored, not used — same: no encryption is applied to the stored value today.
Show in emailUncheckedStored, not used — no email currently reads this flag.
Display to userChecked (new fields)Stored, not used — not carried into the compiled schema; it does not hide the field from anyone yet.
⚠️
Four flags are placeholders. Unique, Encrypted, Show in email, and Display to user are saved with the field but the compiled schema the asset form reads only carries key / label / type / required / primary / options / help / format — so ticking them changes nothing visible today. Don't rely on "Encrypted" for sensitive values yet.

Validation on the asset form

When an asset is saved, each custom field is validated against its compiled definition. The exact error messages, with %s replaced by the field's name:

"%s is required." — a fieldset-required field was left blank.
"%s must be a number." — a Number-type field received a non-numeric value.

Those two checks — required and numeric — are the only runtime validations. The Format / Validation rule (NUMERIC | DATE | EMAIL | URL | regex:/.../) is stored with the field but not applied when an asset is saved today.

Behind the scenes, every save or delete of a custom field immediately re-syncs the compiled schema of every category using it, so asset forms never show a stale field definition.


Part 2 — Fieldsets

A fieldset is an ordered, required-aware bundle of custom fields — think of it as the template of extra fields for one kind of asset (e.g. a "Laptops" fieldset with IMEI-style identifiers, OS version, and RAM). You reach it via the Fieldsets tab on the Custom Fields page (which loads ams/fieldsets into the tab).

List columns

ColumnMeaningNotes
NameThe fieldset's name.Sorted ascending by default.
NotesFree-text notes.Line breaks preserved.
Custom FieldsHow many fields are bound.A live count of bound, non-deleted fields.
Created byAuthor.Profile link.
Options (☰)Row actions.Pencil = edit; × = delete with confirmation.

The header button — labeled "Fieldset" (plus-circle icon) — opens a large modal.

The Fieldset form (with the field builder)

????
Purpose: bundle custom fields, in display order, for one kind of asset.
Who: anyone with the asset permission.
Preconditions: the custom fields you want to bundle already exist on the Browse tab.
  1. Name the fieldset

    Name is the only required field (client- and server-side). Notes is an optional textarea.

  2. Build the field list

    The Custom Fields builder table has columns "Custom Field" | "Required" | (remove). Click "Add" (plus-circle) to append a row: a dropdown of every custom field shown as Name (field_key) with a "-" blank option, a per-row Required checkbox, and a red × to remove the row. Blank rows are skipped on save.

  3. Order the rows

    Row order is the display order on the asset form. The help text under the table says it all: "Bind custom fields to this fieldset; row order sets the display order. Categories using this fieldset are recompiled automatically."

  4. Save

    Click Save. The system replaces the fieldset's bindings with exactly the rows you submitted and immediately recompiles the cached schema of every category bound to this fieldset — the asset form picks up the change on its next open.

⚠️
Known quirk — Required checkboxes can mis-save. When the builder has a mix of checked and unchecked "Required" rows, the required flags can land on the wrong rows if an unchecked row comes before a checked one (the form submits only the checked boxes, and they're re-matched by position). Until this is fixed: after saving, reopen the fieldset and verify each row's Required checkbox — or keep all required fields at the top of the list.

Attaching a fieldset to a category

Open Categories (Safekeep → Categories), edit a category, and pick the fieldset in its "Fieldset" dropdown. From then on, every asset in that category shows the fieldset's fields under the "Additional fields" heading on the add/edit asset modal, in row order, with the per-fieldset Required flags enforced.

What the compiled schema keeps per field: key, label, type, required, primary, options, help, and format. Element types are simplified for rendering — text/textarea stay text-like, number and date stay themselves, and select/checkbox/radio all render from the options list; the format rule is included only when it isn't ANY.

ℹ️
Where the values live. Entered values are stored in the asset's meta JSON, keyed by Field Key. They appear in the Edit modal and the XLSX export only — never on the asset detail page. If you rename a field but keep its Field Key, old values stay attached. If the key changes, previously stored values stop being surfaced — and because saving an asset rebuilds its meta JSON from the current field list, the old-key values are dropped for good the next time anyone saves that asset. Treat Field Key as permanent once assets carry data.

Deleting fields and fieldsets

There are no in-use protections on either screen — every delete is an immediate soft delete after the confirmation prompt, and it always succeeds with the toast "The record has been deleted." (The message "The record is in use, you can't delete the record!" exists in the code but is effectively never shown here.)

????️
Deleting a custom field

The field is removed from the catalog and immediately dropped from the compiled schema of every category whose fieldset used it — the asset form stops showing it. Values already saved in asset meta JSON remain stored (but unsurfaced) until each asset is next saved, when its meta is rebuilt without them.

????️
Deleting a fieldset

The fieldset AND all its field bindings are soft-deleted, and every category bound to it is recompiled to an empty schema — assets in those categories silently lose their entire "Additional fields" section. Stored meta values disappear from the Edit modal and are wiped from the JSON the next time each asset is saved.

Nothing warns you. Deleting a fieldset that live categories depend on is one click plus a generic confirmation — there is no "this fieldset is used by N categories" check. Before deleting, check which categories bind it and rebind or export first.

See also

Was this guide helpful?

Report a content problem