Files
PowderCoatingLogix/src/PowderCoating.Web/wwwroot/js/inventory-ledger.js
T
spouliot 87bbf158a4 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>
2026-06-03 14:31:02 -04:00

85 lines
3.4 KiB
JavaScript

// inventory-ledger.js — Edit Usage Record modal logic
async function openUsageEdit(transactionId) {
const modal = new bootstrap.Modal(document.getElementById('editUsageModal'));
const loading = document.getElementById('editUsageLoading');
const form = document.getElementById('editUsageForm');
const saveBtn = document.getElementById('euSaveBtn');
loading.classList.remove('d-none');
form.classList.add('d-none');
saveBtn.disabled = true;
modal.show();
try {
const resp = await fetch(`/Inventory/GetUsageForEdit?id=${transactionId}`);
if (!resp.ok) throw new Error('Failed to load usage record.');
const data = await resp.json();
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 || '';
const jobSel = document.getElementById('euJobId');
jobSel.innerHTML = '<option value="">— No job —</option>';
(data.jobs || []).forEach(j => {
const opt = document.createElement('option');
opt.value = j.id;
opt.textContent = `${j.jobNumber}${j.customerName}`;
if (j.id === data.jobId) opt.selected = true;
jobSel.appendChild(opt);
});
loading.classList.add('d-none');
form.classList.remove('d-none');
saveBtn.disabled = false;
} catch (e) {
loading.innerHTML = `<div class="text-danger"><i class="bi bi-exclamation-triangle me-1"></i>${e.message}</div>`;
}
}
document.getElementById('euSaveBtn').addEventListener('click', async () => {
const form = document.getElementById('editUsageForm');
if (!form.reportValidity()) return;
const saveBtn = document.getElementById('euSaveBtn');
const spinner = document.getElementById('euSaveBtnSpinner');
const btnText = document.getElementById('euSaveBtnText');
saveBtn.disabled = true;
spinner.classList.remove('d-none');
btnText.textContent = 'Saving…';
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,
__RequestVerificationToken: token || ''
});
try {
const resp = await fetch('/Inventory/EditUsageTransaction', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params.toString()
});
const result = await resp.json();
if (result.success) {
bootstrap.Modal.getInstance(document.getElementById('editUsageModal')).hide();
location.reload();
} else {
throw new Error('Save failed.');
}
} catch (e) {
saveBtn.disabled = false;
spinner.classList.add('d-none');
btnText.textContent = 'Save Changes';
alert('Error saving changes: ' + e.message);
}
});