# Hire Support — Missing Info, Site Moves, History, Maps, Prices & Plant Specs

**Folders:** `CRUD/missing_info/`, `CRUD/site_move/`, `CRUD/history/`, `CRUD/maps/`, `CRUD/prices/`, `CRUD/plant_specifications/`

Six modules that all hang off the [Hire List](hire-list.md) — chasing what's missing from a hire, moving kit between sites, searching past hires, seeing where machines are, what to charge, and what the machines can do.

> Documented to the format set by [sites.md](sites.md).

---

## Missing Info — `CRUD/missing_info/` (13 files)

![Missing PO](../screenshots/hiresup__missing_po.png)

The chasing screens. Each finds hires with a gap and links to an edit form to fill it. This is the operational counterpart to the [monthly invoice check](invoice-review.md) — you can't bill accurately until these are clear.

| Chase page | What's missing | Edit form |
|---|---|---|
| `missing_PO.php` | Purchase order | `missing_info_updates/missing_info_update_PO.php` |
| `missing_PODs.php` | Proof of delivery | `..._update_PODs.php` |
| `missing_fuel.php` | Fuel on return | `..._update_fuel.php` |
| `missing_buckets.php` | Bucket/attachment detail | `..._update_buckets.php` |
| `missing_drivers.php` | Driver name | `..._update_drivers.php` |
| `missing_rates.php` | Hire/transport rate | `..._update_rates.php` |

![Missing Fuel](../screenshots/hiresup__missing_fuel.png)

`check_missing_PO.php` is a JSON endpoint used to test a single hire.

> The edit forms are large (600–1,200 lines each) and share the hire-edit shape used in `hire_updates/`. The **driver-clearing rule** applies here too: `missing_info_update_drivers.php` uses `hire_driver_for_job_type()`, so switching a hire to a non-operated job type clears the driver.

> `missing_PO.php` links a PO document by filename — `/CRUD/customers/POs/<purchase_order>.pdf`. See [customers.md](customers.md#purchase-orders).

## Site Moves — `CRUD/site_move/` (6 files)

![Site Moves](../screenshots/hiresup__site_move.png)

Moving a machine from one site to another without ending the hire.

| Page | Purpose |
|---|---|
| `site_move_index.php` | All site moves |
| `site_move_create.php` | Raise a move |
| `site_move_read.php` | View one (`?id_hire_list=`) — includes a POD image carousel |
| `site_move_update.php` | Edit a move (1,611 lines) |
| `site_move_delete.php` | Remove a move |
| `site_move_site_update_json.php` | AJAX site change |

![Site Move Detail](../screenshots/hiresup__site_move_read.png)

The hire-edit variants for site moves (`update_move_sd/op/standing/XH`) live in [hire-list.md](hire-list.md#editing-a-hire--hire_updates).

## History — `CRUD/history/` (5 files)

![History](../screenshots/hiresup__history.png)

Search past hires. `history.php` is the search screen, `server_processing.php` its DataTables server-side source (which builds the PO link by filename). `update_history.php`, `update_history_op.php` and `update_history_site_move.php` edit a historic hire.

## Maps — `CRUD/maps/` (6 files)

![Live Locations](../screenshots/hiresup__live_map.png)

`live_locations.php` plots every on-hire machine using the site's stored lat/long (see [sites.md](sites.md)). `data.php` and `data_missing_locations.php` feed it; `update_actions/update_locations.php` and `update_single_location.php` write coordinates back.

> `update_single_location.php` was **unauthenticated** until the [endpoint sweep](../security-audit-2026-07.md#unauthenticated-endpoint-sweep-2026-07-21-during-the-module-review) — anyone could move any site's coordinates. Now guarded.

## Prices — `CRUD/prices/` (9 files)

![Prices](../screenshots/hiresup__prices.png)

The hire price list, plus **per-customer overrides**:

| Page | Purpose |
|---|---|
| `prices_index.php` | The price list |
| `prices_create.php` / `prices_update.php` / `prices_read.php` / `prices_delete.php` | Maintain a price |
| `prices_create_customer_override.php` / `_update_` / `_delete_` | Customer-specific pricing |
| `get_customer_prices.php` | Price lookup used by the hire forms |

The hire and off-hire screens show which price applied — "Customer price in use", "Using standard matrix price", or "No price for selected additions".

## Plant Specifications — `CRUD/plant_specifications/` (12 files)

![Plant Specs](../screenshots/hiresup__plantspecs.png)

Specification sheets per machine model — lift charts, dimensions and working ranges.

| Page | Purpose |
|---|---|
| `plantspecs_index.php` | Spec sheets |
| `plantspecs_create.php` / `_update.php` / `_delete.php` | Maintain a spec |
| `model_index.php` / `model_create.php` / `model_update.php` / `model_delete.php` | The model catalogue |
| `upload_spec_document.php` | Upload a spec document (linked from [uploads](../../CRUD/uploads.php)) |
| `plant_lift_charts/`, `plant_lift_dimensions/`, `plant_lift_workrange/` | Per-type document uploaders |

![Models](../screenshots/hiresup__models.png)

---

## Known issues

Reviewed 2026-07-21.

| # | Issue | Status |
|---|---|---|
| 1 | **`site_move_read.php` was completely broken** — `Fatal error: Cannot redeclare getImagesForHireID()`. The page declares its own copy of a function that already exists in `CRUD/functions/functions_images.php`, which it loads via `functions_loader.php` on line 11. The local copy was also **wrong**: it used a relative path resolving to `/PODs/POD_images/` instead of `/CRUD/PODs/POD_images/`, and returned relative URLs. | **Fixed** — local duplicate removed; the page now uses the shared version (the same one the live `documents_panel.php` uses). Page went from a 288-byte fatal to 37.9 KB |
| 2 | **A dormant function collision.** 12 files under `reports/invoice_monthly_reports/month_reports/` each declare `number_of_working_days()`, which also exists in `CRUD/functions/holidays2.php`. They don't clash today **only because `holidays.php` and `holidays2.php` are never included by anything** — `functions_loader.php` doesn't load them. Adding either to the loader would instantly fatal 12 report pages. Worse, `holidays2.php`'s copy has **bank holidays hardcoded for 2019–2020 only**, while the report copies are current and typed. | **Open** — recommend deleting `holidays.php` and `holidays2.php`: unreferenced, obsolete data, and a live trap |
| 3 | `maps/maps_add_lat_long_pc.php` fatals with `Class "Database" not found` — it never includes `database.php`. It is also unreferenced. | **Open** — confirmed dead, safe to delete |
| 4 | Unreferenced: the three `plant_lift_*/upload_*.php` uploaders. They render fine, so they look **live but unlinked**. | **Open** — likely need links, not deletion |

**Everything else was clean** — no PHP errors across the other 28 tested pages. The 302s and short 200s were correct validation ("No hire record specified for update.", "Missing model ID.").
