Dispensing Vet

This commit is contained in:
2026-04-26 16:02:42 -04:00
parent 9ec27e245a
commit 05a093afd3
6 changed files with 64 additions and 7 deletions
+50 -5
View File
@@ -318,6 +318,15 @@ function setupEventListeners() {
});
});
const vetInput = document.getElementById('dispenseVet');
if (vetInput) {
vetInput.addEventListener('input', () => {
const pos = vetInput.selectionStart;
vetInput.value = toTitleCase(vetInput.value);
vetInput.setSelectionRange(pos, pos);
});
}
if (variantForm) variantForm.addEventListener('submit', handleAddVariant);
if (editVariantForm) editVariantForm.addEventListener('submit', handleEditVariant);
if (dispenseForm) dispenseForm.addEventListener('submit', handleDispenseDrug);
@@ -1432,6 +1441,20 @@ async function updateBatchInfo() {
const drugOfVariant = allDrugs.find(d => (d.variants || []).some(v => v.id === variantId));
if (drugOfVariant) await ensureDrugDetailLoaded(drugOfVariant.id);
populateDispensePackSelect(getVariantById(variantId));
const vetLabel = document.getElementById('dispenseVetLabel');
const vetInputEl = document.getElementById('dispenseVet');
if (vetLabel && vetInputEl) {
const isControlled = drugOfVariant ? drugOfVariant.is_controlled : false;
vetLabel.textContent = isControlled ? 'Prescribing Vet *' : 'Prescribing Vet';
vetLabel.style.color = isControlled ? '#d32f2f' : '';
vetInputEl.placeholder = isControlled ? "Vet's name (required)" : "Vet's name";
}
} else {
const vetLabel = document.getElementById('dispenseVetLabel');
const vetInputEl = document.getElementById('dispenseVet');
if (vetLabel) { vetLabel.textContent = 'Prescribing Vet'; vetLabel.style.color = ''; }
if (vetInputEl) vetInputEl.placeholder = "Vet's name";
}
updateDispenseModeUi();
@@ -1817,6 +1840,7 @@ async function handleDispenseDrug(e) {
const requestedPackIdValue = document.getElementById('dispensePackSelect').value;
const requestedPackCountValue = document.getElementById('dispensePackCount').value;
const animalName = document.getElementById('dispenseAnimal').value;
const vetName = document.getElementById('dispenseVet')?.value.trim() || '';
const notes = document.getElementById('dispenseNotes').value;
const printEnabled = document.getElementById('dispensePrintEnabled')?.checked;
const dosage = document.getElementById('dispenseDosage')?.value.trim() || '';
@@ -1825,6 +1849,7 @@ async function handleDispenseDrug(e) {
const selectedPackId = requestedPackIdValue ? parseInt(requestedPackIdValue, 10) : null;
const selectedPackCount = requestedPackCountValue ? parseFloat(requestedPackCountValue) : null;
const variant = getVariantById(variantId);
const drugForVariant = allDrugs.find(d => (d.variants || []).some(v => v.id === variantId));
const legacyStockOnly = isLegacyDispenseSelected();
const selectedPack = variant && selectedPackId
? getActivePacksForVariant(variant).find(pack => pack.id === selectedPackId)
@@ -1940,10 +1965,17 @@ async function handleDispenseDrug(e) {
requested_pack_count: dispenseMode === 'pack' ? selectedPackCount : null,
dispense_source: dispenseSource,
animal_name: animalName || null,
prescribing_vet: vetName || null,
notes: notes || null,
allocations
};
if (drugForVariant && drugForVariant.is_controlled && !vetName) {
showToast('Prescribing vet name is required for controlled drugs.', 'warning');
document.getElementById('dispenseVet')?.focus();
return;
}
try {
const response = await apiCall('/dispense', {
method: 'POST',
@@ -2608,6 +2640,12 @@ async function showDrugHistory(drugId) {
<span class="history-label">User:</span>
<span class="history-value">${escapeHtml(item.user_name)}</span>
</div>
${item.prescribing_vet ? `
<div class="history-row">
<span class="history-label">Prescribing Vet:</span>
<span class="history-value">${escapeHtml(item.prescribing_vet)}</span>
</div>
` : ''}
${item.notes ? `
<div class="history-row">
<span class="history-label">Notes:</span>
@@ -2796,6 +2834,10 @@ function escapeHtml(text) {
return div.innerHTML;
}
function toTitleCase(str) {
return str.replace(/\S+/g, word => word.charAt(0).toUpperCase() + word.slice(1));
}
async function openReportsPage() {
const dropdown = document.getElementById('userDropdown');
if (dropdown) dropdown.style.display = 'none';
@@ -3600,10 +3642,10 @@ async function handleBarcodeScan(raw) {
return;
}
_applyBarcodeScanToLines(mapping, lot, expiryStr);
await _applyBarcodeScanToLines(mapping, lot, expiryStr);
}
function _applyBarcodeScanToLines(mapping, lot, expiryStr) {
async function _applyBarcodeScanToLines(mapping, lot, expiryStr) {
const container = document.getElementById('deliveryLinesContainer');
if (!container) return;
@@ -3637,17 +3679,17 @@ function _applyBarcodeScanToLines(mapping, lot, expiryStr) {
}) || null;
if (emptyLine) {
_populateDeliveryLine(emptyLine, mapping, lot, expiryStr);
await _populateDeliveryLine(emptyLine, mapping, lot, expiryStr);
return;
}
// 3. Append a new line
appendDeliveryLine();
const newLine = container.querySelector('.delivery-line:last-child');
if (newLine) _populateDeliveryLine(newLine, mapping, lot, expiryStr);
if (newLine) await _populateDeliveryLine(newLine, mapping, lot, expiryStr);
}
function _populateDeliveryLine(line, mapping, lot, expiryStr) {
async function _populateDeliveryLine(line, mapping, lot, expiryStr) {
const drugSelect = line.querySelector('.delivery-drug-select');
const variantSelect = line.querySelector('.delivery-variant-select');
const packSelect = line.querySelector('.delivery-pack-select');
@@ -3660,6 +3702,9 @@ function _populateDeliveryLine(line, mapping, lot, expiryStr) {
drugSelect.value = String(mapping.drug_id);
}
// Ensure drug detail (with packs) is loaded before trying to populate pack select
await ensureDrugDetailLoaded(mapping.drug_id);
if (variantSelect) {
const drug = allDrugs.find(d => d.id === mapping.drug_id) || null;
variantSelect.innerHTML = buildDeliveryVariantOptions(drug, mapping.drug_variant_id);