Automation & Reminders
Everything the module does without being asked: the four dashboard widgets that surface equipment without anybody opening the Safekeep menu, the topbar shortcut, the sixteen scheduled jobs that prepare the monthly close, keep the register honest and chase people about acceptances, returns, warranties, repairs and audits — and the settings that decide when each of them speaks.
module_assets, Settings → Manage Modules → Assets under the
Safekeep category) and the base asset permission — see
Getting Started and
Permissions & Roles. The scheduled jobs run per company and
are enabled by default as soon as the module is on.
Dashboard widgets
The module offers four widgets in the Dashboard's widget palette. Each is a compact, read-only list with paging and a refresh control, and its rows link straight to the record they are about.
| Widget | Shows | Offered to | On by default? |
|---|---|---|---|
| Assets assigned to me | Everything currently endorsed to you. | Staff and client portal | Yes, both |
| Waiting for my acceptance | Handovers released to you — or to somebody you are caretaker for — that nobody has signed for yet. You can accept or reject straight from the row. | Staff | Yes |
| My endorsements | The handover documents you are the recipient or the caretaker on, whatever stage each has reached — your personal paperwork trail. | Staff and client portal | No |
| Assets needing attention | Equipment with something outstanding against it. | Staff | No |
Accepting equipment handed to you needs no permission at all, so the acceptance queue is offered on basic Assets access. Requiring the custody permission would have hidden it from exactly the people it exists for.
The two original widgets are described in detail below.
Widget key assets_assigned_to_me. Available on both staff
and client dashboards and included in the default widget set for both — most users
see it without doing anything.
Widget key assets_attention. Staff only and
not in the default palette — an admin or staff user must add it to a custom
dashboard themselves.
"Assets assigned to me"
Panel heading: an archive icon plus "Assets assigned to me". It lists every asset whose
current holder (issued_to) is the logged-in user — in Safekeep vocabulary, every
asset currently endorsed to you. Default sort: Due date ascending, so the return
you owe soonest is on top.
| Column | What it shows |
|---|---|
| Title | The asset's title, as a link to the asset view page
(ams/assets/view/…). |
| Asset Tag | The asset's tag. |
| Category | The asset's category. |
| Status | The endorsement status chip: Assigned Acknowledged Return requested Returned — or "-" when none. |
| Due date | The endorsement's return-by date (due_at). |
"Assets needing attention"
Panel heading: a warning-triangle icon plus "Assets needing attention". This is the custodian's radar: it lists every asset that meets at least one of three conditions, each rendered as a colored chip in the Status column (one asset can carry several chips at once). Default sort: Due date ascending.
due_at) is today or
in the past, and the asset has not been returned yet.asset_warranty_reminder_days setting,
defaulting to 30.| Column | What it shows |
|---|---|
| Title | Asset title, linking to the asset view page. |
| Endorsed to | The current holder's name, or "-" if the asset is unassigned. |
| Status | The attention chip(s) listed above — an asset can show more than one. |
| Due date | The endorsement's return-by date. |
| Warranty expiry date | The asset's warranty expiry date. |
| Next Audit | The asset's next scheduled audit date — see Audit Campaigns. |
Like the first widget, there are no in-place actions — click the title to act on the asset from its detail page. The same three buckets have report-style counterparts: the Audit due tab of Asset Reports covers audits (with a wider 30-day look-ahead), and the three reminder cron jobs below notify holders about the same conditions.
Adding a widget to a dashboard
-
Open (or create) a custom dashboard
"Assets assigned to me" already sits in the default dashboard for both staff and clients. To place either widget yourself, use a custom dashboard: on the Dashboard page, open the "…" menu at the top right and choose "Add new dashboard" (a small modal asks for a title and a color). Saving drops you straight into the new dashboard's edit screen. Existing custom dashboards are opened via the colored dots beside that menu.
-
Enter edit mode
On an existing custom dashboard, the same "…" menu offers "Edit dashboard". The edit screen shows the widget palette in a fixed panel on the left — a search box plus every widget available to you. (The palette's "Add widget" button builds a brand-new custom widget; you don't need it to place the shipped Assets widgets.)
-
Place the Assets widget
If the dashboard is empty, click "Add row" and pick a column layout first. Then find "Assets assigned to me" or "Assets needing attention" in the palette, drag it into a row, and press "Save" (or "Save & show"). The widgets only appear in the palette while the Assets module is enabled and you hold the
assetpermission — and "Assets needing attention" is offered to staff dashboards only.
Topbar icon
The module ships one topbar shortcut: an archive icon with the tooltip "Assets" that
simply navigates to ams/assets (the Asset
Registry). It has no dropdown, no badge, and no unread count — it is a plain link.
asset permission. There is currently no My Preferences control for hiding
topbar shortcuts (that preference field is disabled in the UI).
Cron jobs
The module ships sixteen scheduled jobs, all discovered by ERPat's Advanced Cron runtime, enabled by default, and run per company. They fall into three kinds: reminders that chase a person about something outstanding, preparation jobs that do work ahead of time so a person finds it waiting, and reconciliation jobs that check the system against itself and report what they find without changing anything.
Every one of them stops running when the Assets module is switched off, and none of them needs anything configured before it works.
| Job | Slug | Schedule | What it does | Who gets notified | Notification message |
|---|---|---|---|---|---|
| Compute asset depreciation | compute_asset_depreciation |
Monthly — the 1st of the month at 01:10 | The monthly open, in three steps. It opens a financial book for every asset that should have one and does not; then, where auto-prepare is on, it prepares and calculates last month's depreciation run and leaves it in draft with its totals struck; then it refreshes the older per-asset "current value" figure from the book. An asset with no cost or no usable purchase date is skipped, never guessed at. It never posts — what you find on the 1st is a run waiting for a person to review, approve and post. | Nobody — no notification is raised; output is visible only in the cron run log. | — |
| Remind about due asset estimate reviews | remind_asset_estimate_review |
Monthly — the 1st of the month at 06:00 | Finds financial books whose useful life and residual value have gone a full cycle without anybody confirming them, and asks for a review. A life set once and never revisited quietly becomes a fiction. Confirm it with Mark reviewed, or request an estimate change — see the annual estimate review. | The recipients configured for the asset notification category, resolved from the asset the book belongs to. | "A depreciation estimate is due for review" |
| Remind about pending asset sanitization | remind_asset_sanitization_pending |
Daily at 07:40 | Chases approved disposals whose data wipe has not been
recorded, so equipment does not sit in a cupboard — or leave the building — still
holding its data. The gap between nudges about the same disposal is a setting
(asset_sanitization_reminder_days, 3 by default). |
The recipients configured for the asset notification category, resolved from the asset being disposed of. | "An asset needs its data destroyed before disposal" |
| Reconcile asset finance books | reconcile_asset_finance_books |
Daily at 02:40 | Re-derives every book's balances from its posted depreciation lines and compares them with the stored figures. A balance with a single writer should never drift — but "should never" is not "cannot", and a direct database fix or a restored backup can put them out of step silently. Reports only; it never rewrites a balance. It can also lock posted periods that have aged past the configured limit, closing them to further correction. | Nobody — differences are written to the run log and the audit log, and only when there is something to report. | — |
| Remind asset return due | remind_asset_return_due |
Daily at 07:00 | Finds endorsed assets whose return-by date (due_at) is within the next
3 days or already past, and that have not been returned. Assets with no holder
are skipped. |
The asset holder (the "Endorsed to" user) only. | "An asset assigned to you is due to be returned" |
| Remind asset warranty expiry | remind_asset_warranty_expiry |
Daily at 07:30 | Finds assets whose warranty expiry date falls between today and today + 30
days (already-expired warranties are excluded). The 30-day window is
hardcoded in the job — it does not read the
asset_warranty_reminder_days setting the widget uses. Unassigned assets
are skipped. |
The asset holder only. | "An asset's warranty is about to expire" |
| Remind asset audit due | remind_asset_audit_due |
Weekly — Monday at 08:00 | Finds assets whose Next Audit date is within the next 7 days or already overdue. Unassigned assets are skipped — audits on unassigned assets surface only via the Audit due report and the attention widget. | The asset holder only. | "An asset assigned to you is due for audit" |
| Prepare scheduled asset audits | prepare_asset_audit_campaigns |
Daily at 05:00 | Reads the company's audit policy and opens a draft campaign for each schedule that has come due. Draft, not counting: freezing a scope fixes exactly what is being counted, and an automatic job should not make that decision on its own. Each schedule and period opens exactly one campaign no matter how often the job runs. | Nobody — it creates a campaign, it does not announce one. | — |
| Remind about due asset audits | remind_asset_audit_campaign_due |
Daily at 08:30 | Tells the lead and the assigned auditors when a campaign is approaching its date or has passed it. At most one reminder a day per campaign. Changing a campaign's due date earns a fresh reminder, which is what somebody expects after rescheduling. | The lead auditor and every assigned auditor. | "An asset audit is due" |
| Reconcile asset custody projection | reconcile_asset_custody_projection |
Daily at 01:45 | Compares each asset's summary columns against its custody records and reports any
disagreement. A cache with one writer should never drift, but "should never" is not
"cannot" — a direct database fix, a restored backup or a half-applied migration can
all put them out of step silently. Reports only by default; repairing
automatically is a setting (asset_custody_reconcile_autofix) an
administrator turns on deliberately, after seeing what it would change. |
Nobody — findings land in the data-quality queue and the run log. | — |
| Remind: confirm receipt of assets | remind_asset_acceptance_due |
Daily at 07:15 | Chases people who were issued equipment but have not confirmed receipt, as the acceptance deadline approaches. Until they confirm, the chain of custody has a gap exactly where an auditor looks: the company says they have the laptop and they have never said so. | The holder, or the primary caretaker / accountable owner when the recipient is not a person. | "Please confirm receipt of your equipment" |
| Remind: overdue asset returns | remind_asset_return_overdue |
Daily at 07:10 | Equipment past its return date and still out. Distinct from "return due" above,
which warns three days ahead: this fires only once the date has actually passed. How
long past due counts as overdue is a setting
(asset_return_overdue_grace_days, 0 by default). |
The holder AND whoever is accountable — both, because telling only the person who has not returned it is how it stays out for another month. | "Equipment is overdue for return" |
| Remind about due asset maintenance | remind_asset_maintenance_due |
Daily at 07:45 | Chases a scheduled repair a few days before its date. A scheduled repair nobody
remembers is a scheduled repair that does not happen. The lead time is a setting
(asset_maintenance_due_reminder_days, 3 by default), and rescheduling
a work order earns a fresh reminder — a new date is a new thing to be reminded
about. |
The technician assigned to the work and the person holding the equipment. | "Scheduled maintenance is due" |
| Validate caretaker rosters | validate_asset_caretaker_rosters |
Daily at 06:15 | Finds branches, departments and projects whose named caretaker has left or been deactivated. Nothing errors when that happens: the roster still names them and the equipment still counts as covered, so it is normally discovered during an audit months later — which is exactly when it costs the most. Raised once per gap, never re-raised nightly until somebody acts. | The people who can appoint a replacement, and the affected establishment's own contacts. | "A caretaker needs to be replaced" |
| Sync Helpdesk ticket states | sync_asset_issue_ticket_states |
Every 15 minutes | Notices when a Helpdesk agent has closed a ticket raised from a fault report, and moves the fault on to awaiting the holder's confirmation — so somebody is actually asked whether the equipment got fixed. Without it a fault would stay "ticket open" forever and the asset would keep counting as broken. Costs one small query per tick and needs nothing installed on the Helpdesk side. | The person who reported the fault, or the current holder. | "Please confirm the repair worked" |
| Score asset data quality | score_asset_data_quality |
Daily at 02:20 | Marks every asset against the completeness table and writes the number back — the figure the Overview, the workbench and the data-quality report all read. It scores; it never fixes. Nothing here changes a type, an identifier, a tag or a custody record: every repair in this module is an operator action attributed to a person, because "the nightly job corrected it" is not an answer anybody can audit. | Nobody — the result is the number on the dashboard, not a message. | — |
The two finance reminders behave the same way. An estimate review is chased once per review cycle, and a pending sanitization once every few days rather than daily — both stamp the record they chased, so a follow-up cannot become a drumbeat.
Running a job manually
Administrators can list, dry-run, or trigger any of these jobs from the ERPat CLI without waiting for the schedule:
php erpat cron:list # see all jobs + schedules
php erpat cron:dry-run compute_asset_depreciation # simulate, no writes
php erpat cron:run compute_asset_depreciation
php erpat cron:run remind_asset_return_due
php erpat cron:run remind_asset_warranty_expiry
php erpat cron:run remind_asset_audit_dueA manual cron:run of the depreciation job is the quickest way to populate the
"Current value" and "Computed at" columns of the Depreciation schedule report
right after you attach depreciation profiles — otherwise they show "-" until the 1st of the
next month.
Settings
Everything the jobs above read — how many days ahead a reminder fires, how long a grace period runs, whether a reconciliation job may repair what it finds — is set on the module's own Settings page, and so is everything else the module enforces.
Every knob that previously had no screen at all now has one: the warranty reminder window and the audit cadence used to be changeable only in the database, and both are ordinary fields today. Full reference: Setup Hub & Settings.
The settings that most directly change this page's behaviour — when somebody is chased, and how often — are these:
| Group | Setting | Effect on the jobs above | Default |
|---|---|---|---|
| Notifications | Return reminder lead time | How many days before a return is due the reminder starts. | 3 days |
| Notifications | Acceptance reminder lead time | How soon after release somebody is chased to confirm receipt. | 1 day |
| Notifications | Overdue escalation delay | How long an overdue return waits before it is escalated. | 2 days |
| Notifications | Escalation recipients | Who is copied on an escalation, on top of the people directly involved. | — |
| Custody | Overdue grace period | How long past the due date still counts as merely late. | 0 days |
| Custody | Repair custody drift automatically | Whether the nightly consistency check may correct what it finds, or only report it. | Off — report only |
| Maintenance | Warranty reminder window | How many days before cover ends the reminder goes out. | 30 days |
| Maintenance | Maintenance reminder window | How many days before scheduled work falls due. | 3 days |
| Audits | Audit cadence | The default interval between counts, and therefore what "due" means. | 90 days |
| Audits | Reminder and escalation windows | How early a campaign is chased, and how long overdue before it escalates. | 3 / 3 days |
| Disposal | Sanitization reminder gap | How often a pending data wipe is chased. | Every 3 days |
| Accounting | Prepare next period automatically | Whether the monthly job leaves a draft depreciation run waiting. | On |
| Accounting | Automatic locking | How long after posting a period is closed to further correction. | 30 days |
| General | Overview cache | How long the dashboard figures are held before being recomputed. | 5 minutes |
In-app notifications
The reminder jobs and every custody transition deliver through the standard ERPat notification pipeline: an in-app notification plus an email, each subject to the recipient's own per-event preferences. Twenty-six events are declared in all. For the three oldest reminders the recipient is always the asset's current holder; everything added since also reaches the primary caretaker and the accountable owner, because a caretaker never appears as the holder and would otherwise never hear about equipment they signed for.
| Event | Notification text (quoted) | Sent by |
|---|---|---|
asset_return_due |
"An asset assigned to you is due to be returned" | Remind asset return due (daily, 07:00) |
asset_warranty_expiring |
"An asset's warranty is about to expire" | Remind asset warranty expiry (daily, 07:30) |
asset_audit_due |
"An asset assigned to you is due for audit" | Remind asset audit due (weekly, Monday 08:00) |
asset_endorsement_pending_approval |
"An endorsement is waiting for your approval" | Submitting a document that needs approval |
asset_endorsement_approved |
"Your endorsement was approved" | An approver approving it |
asset_released_for_acceptance |
"Equipment is waiting for you to confirm receipt" | Releasing an endorsement |
asset_acceptance_due |
"Please confirm receipt of your equipment" | Remind: confirm receipt (daily, 07:15) |
asset_endorsement_accepted |
"An endorsement was accepted" | The recipient confirming receipt |
asset_endorsement_rejected |
"An endorsement was refused" | A refusal, or an approver sending it back |
asset_transfer_pending |
"Equipment is being transferred to you" | Starting a transfer the new holder must confirm |
asset_return_overdue |
"Equipment is overdue for return" | Remind: overdue returns (daily, 07:10) |
mentioned_on_an_asset |
"You were mentioned in an asset comment" | Somebody mentions you by name in a comment on an asset. |
asset_caretaker_reassignment_required |
"Equipment needs a new caretaker" | The named caretaker of a branch, department or project has left or been deactivated. |
asset_issue_reported |
"An issue was reported on an asset" | A fault is reported against equipment. |
asset_issue_severe |
"A serious issue was reported on an asset" | The fault reported is a serious one. |
asset_ticket_created |
"A Helpdesk ticket was raised for your report" | A fault you reported was escalated into a Helpdesk ticket. |
asset_issue_resolved_pending_verification |
"An asset issue is waiting for your confirmation" | A repair is marked done and somebody must confirm it actually worked. |
asset_issue_reopened |
"An asset issue was reopened" | A confirmation failed, or the fault came back, and the issue is open again. |
asset_maintenance_due |
"Scheduled maintenance is coming up" | Scheduled maintenance is approaching its date. |
asset_audit_campaign_assigned |
"You have been assigned to an asset audit" | You have been named as an auditor on a campaign. |
asset_audit_discrepancy |
"An asset audit found a discrepancy" | A count found something that does not match the register. |
asset_audit_campaign_overdue |
"An asset audit is due" | A campaign is approaching its date or has passed it. |
asset_estimate_review_due |
"A depreciation estimate is due for review" | A useful life and residual value have gone a full cycle without being confirmed. |
asset_disposal_pending_approval |
"An asset disposal is awaiting approval" | A disposal is waiting for somebody to approve or refuse it. |
asset_sanitization_required |
"An asset needs its data destroyed before disposal" | An approved disposal is waiting on its data being destroyed. |
asset_disposed |
"An asset has been disposed of" | An asset has been signed out of the register for good. |