---
name: evolution_jobinventory_uploads
description: "jobInventory item files use uploads subtype 'jobinventory'; inherits quote-item files via referenceId"
metadata: 
  node_type: memory
  type: project
  originSessionId: b5c24c09-8577-437f-8d3a-e484e25da0a4
---

Job-inventory line items can now have file attachments (Files tab in the jobeditinv item popup).

- New upload **subtype = `jobinventory`**, `sourceid = jobInventory.id`. Registered in `functions.php`: `userCanAccessSource` map (`'jobinventory' => 'mod_jc'`) and `uploadSubtypesForScreen` (`jobedit` set). Any new upload subtype must be added to BOTH or uploadsave.php returns 403 / category filter drops it.
- The Files tab ALSO shows the originating quote item's files, bridged by **`jobInventory.referenceId` → `quoteitems.id`** (subtype `quoteitem`). This is the standard job↔quote-item link (no qiid column; it's `referenceId`).
- Server: `itemModify.php` action `getJobInvFiles` (gated on `mod_jc`, unlike sibling `getJobInvBOM` which has no gate) renders a `dropzone_jobinv` uploader (id `jobinv_dropzone`) + `showUploadFiles()` lists. Populated via AJAX per row open by `jobItemGetFiles`/`initJobInvDropzone` appended to `jobeditinv.js` (wraps global `jobItemEdit`). Upload posts to `uploadsave.php` `pageupload` branch (echoes "done"); the dropzone `complete` refreshes the list in place (no page reload).
- The jobeditinv item popup is a single reused DOM element (not per-row); tabs use `smpd`/`menupd` + global `showdivspopupdiv()`. Quote screen popups are per-item (`moreItem$x`) and use the scoped `quoteItemTab()` instead.

Related: [[evolution_ajax_save_auth_gate]], [[portal_minified_no_build]] (n/a here — evolution has no JS build).
