Units
A unit is the physical piece of equipment installed at a customer's site — the specific compressor, the specific chiller, with its own serial number, its own warranty clock, and its own service history. Units are the thing techs work on.
Unit vs. device model
Units and device models look similar, but the split matters:
| Device Model | Unit | |
|---|---|---|
| What it is | A spec sheet — Mitsubishi MSZ-GL09NA, with capacity, refrigerant, cut sheet | A specific installed instance of that model |
| Owns | Manufacturer, device type, defaults | Customer, location, serial number, install date |
| Lifespan | One per model number | Many per device model |
When you create a unit, you pick a device model. The model gives the unit its category (Split AC, Heat Pump, etc.) and its manufacturer, plus access to any model-level checklists. The unit then carries the operational data: when it was installed, who owns it now, where it lives, what's gone wrong with it.
Customer assignment
A unit can exist without a customer (for example, a warehouse stock item before sale), but the moment you want to dispatch a work order against it, it needs a customer. A unit belongs to exactly one customer at a time. To move a unit from one customer to another, use the customer transfer flow on the unit edit page — this preserves the unit's history while updating ownership.
Warranty
Each unit has an installed_at date and a warranty_months value (an integer). The warranty expiry is computed on the fly:
warranty_expires_at = installed_at + warranty_months months
Because this is a computed property, you never store an expiry date directly. Change the install date or the warranty length and the expiry recomputes the next time you load the unit. This makes warranty status reliable even if a tech moves the install date later as part of cleanup.
Maintenance frequency
The maintenance_frequency field determines how often a unit needs preventive service. The available choices are:
| Value (UI label) | Interval |
|---|---|
| None | No schedule (excluded from the maintenance pipeline) |
| Every month | 1 month |
| Every 2 months | 2 months |
| Quarterly | 3 months |
| Semi annual | 6 months |
| Annual | 12 months |
| Every 2 years | 24 months |
Combined with the maintained_at date, this drives the maintenance reminder system: when a unit's frequency interval has elapsed since the last maintenance, it shows up in the "due" list. The default for a new unit is the device model's default, falling back to Annual.
A unit with no maintenance frequency set (or None) never appears in the maintenance pipeline. This is intentional — equipment that's not under a service contract shouldn't generate noise.
QR codes
Every unit can be assigned a QR code that, when scanned, opens the unit's public page. The QR code is identified by a GUID (qr_code_guid) so the URL looks like /u/<guid> — opaque, non-guessable, and stable for the life of the unit. See QR Codes & Public Unit URLs for the full flow.
QR codes can also exist independently — you can print a batch of blank labels, then assign them later by scanning. A QR code without a unit is just a label waiting for an assignment.
Linked units (ties)
Two or more units can be tied together to form a linked group. The link is bidirectional and transitive: if A is tied to B and B is tied to C, then A, B, and C are all in the same group. The system enforces:
- Both units must belong to the same customer.
- A unit cannot be tied to itself.
- Duplicate ties are silently no-ops.
Ties don't change dispatch — a work order against unit A doesn't auto-include unit B. The tie is an advisory — it tells the dispatcher "these go together," and it makes the unit list show a group indicator. Treat it like a hint, not a constraint.
Service history
Every work order against a unit appears in that unit's service history. This becomes useful as units age: looking at a unit and seeing "5 repairs in 18 months" tells you it's a candidate for replacement. The history view is the unit's edit page, scrolled past the form.