-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ Enter how much powder you took out of the bag.
@@ -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 };
})();
diff --git a/src/PowderCoating.Web/wwwroot/js/inventory-ledger.js b/src/PowderCoating.Web/wwwroot/js/inventory-ledger.js
index fabe5f4..e667064 100644
--- a/src/PowderCoating.Web/wwwroot/js/inventory-ledger.js
+++ b/src/PowderCoating.Web/wwwroot/js/inventory-ledger.js
@@ -18,6 +18,7 @@ async function openUsageEdit(transactionId) {
document.getElementById('euTxnId').value = data.transactionId;
document.getElementById('euItemName').textContent = data.itemName || '—';
+ document.getElementById('euQuantity').value = data.quantity != null ? parseFloat(data.quantity).toFixed(4) : '';
document.getElementById('euDate').value = data.transactionDate;
document.getElementById('euNotes').value = data.notes || '';
@@ -54,6 +55,7 @@ document.getElementById('euSaveBtn').addEventListener('click', async () => {
const token = form.querySelector('input[name="__RequestVerificationToken"]')?.value;
const params = new URLSearchParams({
id: document.getElementById('euTxnId').value,
+ quantity: document.getElementById('euQuantity').value,
jobId: document.getElementById('euJobId').value,
notes: document.getElementById('euNotes').value,
transactionDate: document.getElementById('euDate').value,
diff --git a/src/PowderCoating.Web/wwwroot/js/log-material.js b/src/PowderCoating.Web/wwwroot/js/log-material.js
index 11afcbe..466d9ce 100644
--- a/src/PowderCoating.Web/wwwroot/js/log-material.js
+++ b/src/PowderCoating.Web/wwwroot/js/log-material.js
@@ -6,9 +6,64 @@
let _items = [];
let _jobPowderIds = new Set();
let _modal = null;
+ let _selectedItemId = 0;
+ let _entryMethod = 'used'; // 'used' | 'remaining'
+
+ // ── Mode toggle ───────────────────────────────────────────────────────────
+
+ window.lmSetMethod = function (method) {
+ _entryMethod = method;
+ const btnUsed = document.getElementById('lmBtnUsed');
+ const btnRemaining = document.getElementById('lmBtnRemaining');
+ const hintEl = document.getElementById('lmMethodHint');
+ const qtyLabel = document.getElementById('lmQtyLabel');
+
+ if (method === 'remaining') {
+ btnUsed.className = 'btn btn-outline-primary';
+ btnRemaining.className = 'btn btn-primary';
+ hintEl.textContent = 'Enter how much is LEFT in the bag — the system calculates what was used.';
+ qtyLabel.innerHTML = 'Weight Remaining in Bag *';
+ } else {
+ btnUsed.className = 'btn btn-primary';
+ btnRemaining.className = 'btn btn-outline-primary';
+ hintEl.textContent = 'Enter how much powder you took out of the bag.';
+ qtyLabel.innerHTML = 'Quantity Used *';
+ }
+ lmUpdatePreview();
+ };
+
+ // ── Live preview (always visible once qty + item are set) ─────────────────
+
+ function lmUpdatePreview() {
+ const computedDiv = document.getElementById('lmComputedUsed');
+ if (!_selectedItemId || !computedDiv) { computedDiv?.classList.add('d-none'); return; }
+ const item = _items.find(it => it.id === _selectedItemId);
+ const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
+ const qty = parseFloat(document.getElementById('lmQuantity').value) || 0;
+ if (qty <= 0) { computedDiv.classList.add('d-none'); return; }
+
+ const uom = item?.unitOfMeasure || '';
+ if (_entryMethod === 'remaining') {
+ const used = onHand - qty;
+ if (used <= 0) {
+ computedDiv.className = 'form-text fw-semibold text-danger';
+ computedDiv.textContent = 'Remaining cannot be ≥ current stock (' + onHand.toFixed(2) + ' ' + uom + ').';
+ } else {
+ computedDiv.className = 'form-text fw-semibold text-success';
+ computedDiv.textContent =
+ 'Will log ' + used.toFixed(2) + ' ' + uom + ' used — new balance: ' + qty.toFixed(2) + ' ' + uom;
+ }
+ } else {
+ const newBal = onHand - qty;
+ const col = newBal < 0 ? 'text-danger' : 'text-success';
+ computedDiv.className = 'form-text fw-semibold ' + col;
+ computedDiv.textContent =
+ 'Will log ' + qty.toFixed(2) + ' ' + uom + ' used — new balance: ' + newBal.toFixed(2) + ' ' + uom;
+ }
+ computedDiv.classList.remove('d-none');
+ }
// ── Combobox state ────────────────────────────────────────────────────────
- let _selectedItemId = 0;
function lmComboInput() {
const q = document.getElementById('lmItemSearch')?.value?.toLowerCase() || '';
@@ -16,7 +71,7 @@
lmComboShow();
_selectedItemId = 0;
document.getElementById('lmItemBalance').classList.add('d-none');
- lmOnQtyInput();
+ lmUpdatePreview();
}
function lmComboOpen() {
@@ -111,7 +166,7 @@
const balDiv = document.getElementById('lmItemBalance');
balDiv.textContent = 'Current stock: ' + qty.toFixed(2) + (uom ? ' ' + uom : '');
balDiv.classList.remove('d-none');
- lmOnQtyInput();
+ lmUpdatePreview();
};
window.lmComboInput = lmComboInput;
@@ -152,39 +207,14 @@
return String(s).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"');
}
- // ── Quantity / label logic ────────────────────────────────────────────────
-
- function lmOnQtyInput() {
- const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
- if (method !== 'remaining') {
- document.getElementById('lmComputedUsed').classList.add('d-none');
- return;
- }
- if (!_selectedItemId) {
- document.getElementById('lmComputedUsed').classList.add('d-none');
- return;
- }
- const item = _items.find(it => it.id === _selectedItemId);
- const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
- const remaining = parseFloat(document.getElementById('lmQuantity').value) || 0;
- const used = onHand - remaining;
- const computedDiv = document.getElementById('lmComputedUsed');
- computedDiv.textContent = 'Usage = ' + onHand.toFixed(2) + ' − ' + remaining.toFixed(2) + ' = ' + used.toFixed(2) + (item?.unitOfMeasure ? ' ' + item.unitOfMeasure : '');
- computedDiv.classList.remove('d-none');
- }
-
- window.lmUpdateQuantityLabel = function () {
- const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
- document.getElementById('lmQtyLabel').innerHTML =
- (method === 'remaining' ? 'Quantity Remaining' : 'Quantity Used') +
- ' *';
- lmOnQtyInput();
- };
+ // ── Kept for backward-compat with any inline onchange handlers that may exist ─
+ window.lmUpdateQuantityLabel = function () { lmUpdatePreview(); };
// ── Modal open / save ─────────────────────────────────────────────────────
window.openLogMaterialModal = function () {
_selectedItemId = 0;
+ _entryMethod = 'used';
document.getElementById('lmItemSearch').value = '';
document.getElementById('lmItemBalance').classList.add('d-none');
document.getElementById('lmQuantity').value = '';
@@ -193,8 +223,7 @@
document.getElementById('lmNotes').value = '';
document.getElementById('lmAlert').classList.add('d-none');
document.getElementById('lmSaveBtn').disabled = false;
- document.getElementById('lmMethodUsed').checked = true;
- window.lmUpdateQuantityLabel();
+ lmSetMethod('used');
lmComboClose();
if (_modal) _modal.show();
};
@@ -214,14 +243,14 @@
const qtyInput = parseFloat(document.getElementById('lmQuantity').value) || 0;
if (qtyInput <= 0) { showError('Please enter a quantity greater than zero.'); return; }
- const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
+ const item = _items.find(it => it.id === _selectedItemId);
+ const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
+
let quantityUsed = qtyInput;
- if (method === 'remaining') {
- const item = _items.find(it => it.id === _selectedItemId);
- const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
+ if (_entryMethod === 'remaining') {
quantityUsed = onHand - qtyInput;
if (quantityUsed <= 0) {
- showError('Remaining quantity cannot be equal to or greater than the current stock (' + onHand.toFixed(2) + ').');
+ showError('Remaining cannot be equal to or greater than the current stock (' + onHand.toFixed(2) + ').');
return;
}
}
@@ -269,9 +298,8 @@
_jobPowderIds = new Set(cfg.jobPowderIds || []);
_modal = new bootstrap.Modal(document.getElementById('logMaterialModal'));
- document.getElementById('lmQuantity').addEventListener('input', lmOnQtyInput);
+ document.getElementById('lmQuantity').addEventListener('input', lmUpdatePreview);
- // Close dropdown when clicking outside
document.addEventListener('click', function (e) {
if (!e.target.closest('#lmItemSearch') &&
!e.target.closest('#lmItemDropdown') &&