Fix material usage logging: remaining weight mode, edit modal, and consolidate duplicate logic

- InventoryController: extract RecordInventoryUsageAsync helper; both LogUsage
  (scan page) and LogMaterial (jobs modal, moved from JobsController) call it —
  no more duplicate save/GL logic across two controllers
- Log Material modal: replace radio buttons with prominent toggle buttons so the
  active mode (Amount Used vs Amount Remaining) is always visually obvious; add
  always-visible preview line showing exactly what will be logged before saving
- Edit Usage modal: add quantity field (pre-populated from existing transaction)
  with delta adjustment to InventoryItem.QuantityOnHand on save; include
  completed/terminal jobs in the dropdown so entries can be corrected after a
  job is marked done
- Scan page job picker: include jobs completed within the last 7 days (marked
  with '(completed)') so usage can be logged after a job is finished

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 14:31:02 -04:00
parent f453a95f28
commit 87bbf158a4
6 changed files with 262 additions and 177 deletions
@@ -353,6 +353,11 @@
<label class="form-label fw-semibold">Powder Item</label>
<p id="euItemName" class="form-control-plaintext text-muted"></p>
</div>
<div class="mb-3">
<label for="euQuantity" class="form-label fw-semibold">Amount Used <small class="text-muted fw-normal" id="euQuantityUom"></small></label>
<input type="number" id="euQuantity" name="quantity" class="form-control" min="0.001" step="any" required />
<div class="form-text">Adjusts the inventory balance by the difference from the original entry.</div>
</div>
<div class="mb-3">
<label for="euJobId" class="form-label fw-semibold">Job <span class="text-muted fw-normal">(optional)</span></label>
<select id="euJobId" name="jobId" class="form-select">
+14 -11
View File
@@ -1158,21 +1158,24 @@
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Entry Method</label>
<div class="d-flex gap-3">
<div class="form-check">
<input class="form-check-input" type="radio" name="lmEntryMethod" id="lmMethodUsed" value="used" checked onchange="lmUpdateQuantityLabel()">
<label class="form-check-label" for="lmMethodUsed">Amount Used</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="lmEntryMethod" id="lmMethodRemaining" value="remaining" onchange="lmUpdateQuantityLabel()">
<label class="form-check-label" for="lmMethodRemaining">Amount Remaining</label>
</div>
<div class="btn-group w-100" role="group">
<button type="button" id="lmBtnUsed" class="btn btn-primary"
onclick="lmSetMethod('used')">
<i class="bi bi-droplet me-1"></i>Amount Used
</button>
<button type="button" id="lmBtnRemaining" class="btn btn-outline-primary"
onclick="lmSetMethod('remaining')">
<i class="bi bi-droplet-half me-1"></i>Amount Remaining
</button>
</div>
<div class="form-text">
<span id="lmMethodHint">Enter how much powder you took out of the bag.</span>
</div>
</div>
<div class="mb-3">
<label id="lmQtyLabel" class="form-label fw-semibold">Quantity Used <span class="text-danger">*</span></label>
<input type="number" id="lmQuantity" class="form-control" min="0" step="0.01" placeholder="0.00">
<div id="lmComputedUsed" class="form-text text-muted d-none"></div>
<div id="lmComputedUsed" class="form-text fw-semibold d-none"></div>
</div>
<div class="mb-3">
<label class="form-label fw-semibold">Reason</label>
@@ -3311,7 +3314,7 @@
const inventoryItems = @Html.Raw(ViewBag.InventoryItemsForModal ?? "[]");
const jobPowderIds = @Html.Raw(ViewBag.JobPowderIds ?? "[]");
const jobId = @Model.Id;
const logUrl = '@Url.Action("LogMaterial", "Jobs")';
const logUrl = '@Url.Action("LogMaterial", "Inventory")';
const token = document.querySelector('input[name="__RequestVerificationToken"]')?.value ?? '';
window.__logMaterial = { inventoryItems, jobPowderIds, jobId, logUrl, token };
})();