Fixora Manual, as shipped in the download
Fixora — User Manual
Assets, preventive maintenance and work orders, on your own server. Version 3.1.4 [src: app/controllers/api.php:17].
About this manual
Every statement here was written by reading Fixora's own source, and each one carries the file it came from in a bracketed src marker. Paths are relative to the folder this docs directory sits in. If a sentence disagrees with the application, the application is right and this manual has a bug — the markers exist so you can check rather than take our word for it.
Nothing is described that the code does not do. Where something is deliberately limited, that is said plainly rather than left out.
What Fixora is
Assets, preventive-maintenance schedules, and work orders that move through a small enforced state machine [src: app/controllers/mcp.php:52].
Everything a buyer would want to audit lives in one engine as pure, testable functions, alongside the write paths the controllers actually use — so the test suite exercises the real insert and update code on both database engines [src: app/src/Maintenance.php:3].
Money is integer cents [src: app/src/Maintenance.php:10], and maintenance dates are plain calendar dates in your business timezone, because a service happens on a business day rather than at an instant [src: app/src/Maintenance.php:8].
Preventive maintenance, and the absence of a cron
Next due is last done plus the interval, computed when you look at it — the source is explicit that there is deliberately no cron dependency [src: app/src/Maintenance.php:9].
Nothing can be missed because a scheduled task failed to run, and an installation switched off for a fortnight shows exactly what fell due while it was off.
An email is different: something has to send it. The optional daily digest — PM overdue or due soon, and parts at their minimum, to your notification address — goes when cron/pm-digest.php runs or when you press Send the PM digest now in Settings [src: app/controllers/app.php:100]. It is off until switched on, sent only when there is something on it, and at most once a day [src: app/controllers/app.php:116].
Two triggers, and the one that comes first wins
A schedule can be driven by days, by a meter reading, or by both [src: app/src/Maintenance.php:112].
- By days: overdue when the date has passed, due-soon inside your window, otherwise fine. Exactly on the window boundary still counts as due-soon [src: app/src/Maintenance.php:78].
- By usage: units remaining is the last-done reading plus the interval, minus the current reading [src: app/src/Maintenance.php:89]. The due-soon window is 10% of the interval, rounded up, never less than one unit [src: app/src/Maintenance.php:95], and zero remaining counts as due now [src: app/src/Maintenance.php:100].
Where both apply, the status becomes whichever is worse — the trigger that comes first wins [src: app/src/Maintenance.php:113]. The row also tells you which one drove it: days, usage, or both [src: app/src/Maintenance.php:116].
A schedule with no meter, or no usage interval, behaves exactly as a date-only schedule [src: app/src/Maintenance.php:114].
Meters only move forward
A reading below the current one is refused, and the reasoning is worth having [src: app/controllers/mcp.php:55]:
A meter that goes backwards means the device was swapped or the number was mistyped, and correcting that rebases the preventive-maintenance baselines. Ask a person to do it in the app.
So a mistyped reading is not something an automation quietly fixes. It is a decision with consequences for every schedule hanging off that meter, and it is handed back to a human.
Work orders
Four statuses [src: app/src/Maintenance.php:23], four priorities [src: app/src/Maintenance.php:22], and two types — corrective and preventive [src: app/src/Maintenance.php:21].
The transitions are enforced [src: app/src/Maintenance.php:27]:
| From | May move to |
|---|---|
open | in-progress, done, cancelled |
in-progress | open (paused), done, cancelled |
done | open — the source calls it an honest-mistake reopen |
cancelled | nothing — terminal |
Note the asymmetry, which is deliberate: a job marked done by mistake can be reopened, but a cancelled one cannot [src: app/src/Maintenance.php:29].
Priority, on every door
The priorities are low, medium, high and urgent [src: app/src/Maintenance.php:22], and every door agrees.
The technician's "My jobs" list puts urgent first, then high, medium and low [src: app/controllers/v3.php:885]; before 3.1.4 it ordered by critical, a value the product never stores, so urgent work sank to the bottom beside low. The agent tools offer exactly the four values [src: app/controllers/mcp.php:65], [src: app/controllers/mcp.php:118], and the REST API refuses anything else with 422, reading critical as urgent [src: app/controllers/api.php:67]; before 3.1.4 an unknown value was filed as medium with no error. The browser form can only send the four.
Costs
Labour is minutes times the hourly rate in cents, divided by 60, rounded half up [src: app/src/Maintenance.php:234] — integer arithmetic throughout, with zero or negative inputs giving zero rather than a negative cost [src: app/src/Maintenance.php:236].
A work order's total is that labour plus its parts cost, with parts floored at zero [src: app/src/Maintenance.php:243].
Users and roles
Three roles [src: app/controllers/v3.php:27]. The source names what stays with the owner: an interval is a budget decision, and lengthening one is a risk decision [src: app/controllers/v3.php:24]; and deleting is reserved because a work order is the maintenance record a machine is judged by [src: app/controllers/v3.php:25].
| Permission | viewer | member | admin |
|---|---|---|---|
.view permissions | yes | yes | yes |
audit.view | yes | yes | yes |
wo.create / wo.advance / wo.edit | — | yes | yes |
meter.record | — | yes | yes |
part.consume | — | yes | yes |
photo.upload | — | yes | yes |
pm.complete | — | yes | yes |
| schedules, settings, team, deletion | — | — | yes |
The audit trail is not the viewer's
The viewer's grants are listed one by one — assets, parts, PM, reports and work orders [src: app/controllers/v3.php:32] — so the audit trail is not among them. Before 3.1.4 the viewer held the wildcard *.view, which matched audit.view as well.
Backups follow the model
Fixora's database backup downloads are permission-gated, requiring the settings permission [src: app/controllers/api.php:332], as are the restore page and the scheduled-backup token. A viewer cannot download the database.
The API and agent access
Three tools write — creating a work order, advancing its status, and recording a meter reading [src: app/controllers/mcp.php:58].
The instructions warn an agent about the hyphen in in-progress [src: app/controllers/mcp.php:53], which is the kind of detail that otherwise costs a round trip, and about the forward-only meter rule [src: app/controllers/mcp.php:55].
They state the priority values the product stores: low, medium, high and urgent [src: app/controllers/mcp.php:54].
What Fixora does not do
It does not need a cron job [src: app/src/Maintenance.php:9]. Due-ness is computed on view; only the optional daily email digest needs something to run it.
It does not let a meter go backwards [src: app/controllers/mcp.php:55], and it does not let an agent correct one.
It does not let a cancelled work order be reopened [src: app/src/Maintenance.php:29].
It does not accept a priority it does not have from the API or an agent [src: app/controllers/api.php:67]; the browser form cannot send one.