Add manual Log Material modal to job details page
PC users were blocked to QR scan only for logging material usage. Now a "Log Material" button opens an inline modal with: - Inventory item dropdown (name + unit of measure, current stock shown on select) - Entry method toggle: "Amount Used" or "Amount Remaining" (computes used = onHand - remaining) - Reason: Job Usage or Waste/Spillage - Notes field Submits via AJAX to Jobs/LogMaterial (new POST action) which mirrors the InventoryController.LogUsage flow — updates QuantityOnHand, creates InventoryTransaction, posts GL entries (DR COGS / CR Inventory). QR scan button retained as icon. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1016,9 +1016,12 @@
|
||||
<span class="badge bg-primary rounded-pill ms-1">@materialsUsed.Count</span>
|
||||
}
|
||||
<i class="bi bi-chevron-down collapse-chevron ms-1" style="transition:transform .2s;"></i>
|
||||
<span class="ms-auto">
|
||||
<a asp-controller="Inventory" asp-action="Scan" class="btn btn-sm btn-outline-primary" onclick="event.stopPropagation();">
|
||||
<i class="bi bi-qr-code-scan me-1"></i>Log Material
|
||||
<span class="ms-auto d-flex gap-2">
|
||||
<button type="button" class="btn btn-sm btn-outline-primary" onclick="event.stopPropagation(); openLogMaterialModal();">
|
||||
<i class="bi bi-plus-circle me-1"></i>Log Material
|
||||
</button>
|
||||
<a asp-controller="Inventory" asp-action="Scan" class="btn btn-sm btn-outline-secondary" onclick="event.stopPropagation();" title="Scan QR code">
|
||||
<i class="bi bi-qr-code-scan"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
@@ -1028,7 +1031,7 @@
|
||||
{
|
||||
<div class="card-body text-muted text-center py-3 small">
|
||||
<i class="bi bi-droplet me-1"></i>No materials have been logged for this job yet.
|
||||
Use the QR label on an inventory item to log usage.
|
||||
Click <strong>Log Material</strong> above or scan the QR label on an inventory item.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
@@ -1089,6 +1092,65 @@
|
||||
</div><!-- /collapseMaterials -->
|
||||
</div>
|
||||
|
||||
<!-- Log Material Modal -->
|
||||
<div class="modal fade" id="logMaterialModal" tabindex="-1" aria-labelledby="logMaterialModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="logMaterialModalLabel">
|
||||
<i class="bi bi-droplet-half me-2 text-primary"></i>Log Material Usage
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Inventory Item <span class="text-danger">*</span></label>
|
||||
<select id="lmInventoryItem" class="form-select">
|
||||
<option value="">-- Select item --</option>
|
||||
</select>
|
||||
<div id="lmItemBalance" class="form-text text-muted d-none"></div>
|
||||
</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>
|
||||
</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>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Reason</label>
|
||||
<select id="lmTransactionType" class="form-select">
|
||||
<option value="JobUsage">Job Usage</option>
|
||||
<option value="Waste">Waste / Spillage</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-semibold">Notes</label>
|
||||
<textarea id="lmNotes" class="form-control" rows="2" placeholder="Optional"></textarea>
|
||||
</div>
|
||||
<div id="lmAlert" class="alert alert-permanent d-none"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="lmSaveBtn" onclick="lmSave()">
|
||||
<i class="bi bi-check-circle me-1"></i>Log Usage
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Part Intake Modal -->
|
||||
@{
|
||||
var intakeExpectedCount = Model.Items?.Sum(i => (int)i.Quantity) ?? 0;
|
||||
@@ -3082,6 +3144,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
<!-- Log Material Modal JS -->
|
||||
<script src="/js/log-material.js"></script>
|
||||
<script>
|
||||
(function () {
|
||||
const inventoryItems = @Html.Raw(ViewBag.InventoryItemsForModal ?? "[]");
|
||||
const jobId = @Model.Id;
|
||||
const logUrl = '@Url.Action("LogMaterial", "Jobs")';
|
||||
const token = document.querySelector('input[name="__RequestVerificationToken"]')?.value ?? '';
|
||||
window.__logMaterial = { inventoryItems, jobId, logUrl, token };
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Save as Template Modal -->
|
||||
<div class="modal fade" id="saveTemplateModal" tabindex="-1" aria-labelledby="saveTemplateModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
|
||||
Reference in New Issue
Block a user