Dispensing Vet
This commit is contained in:
+50
-5
@@ -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);
|
||||
|
||||
@@ -228,6 +228,11 @@
|
||||
<input type="text" id="dispenseAnimal">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="dispenseVet" id="dispenseVetLabel">Prescribing Vet</label>
|
||||
<input type="text" id="dispenseVet" placeholder="Vet's name">
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="margin-top: 18px; padding: 12px; background: #f9fafb; border: 1px solid #d9e2ec; border-radius: 6px;">
|
||||
<label style="display: inline-flex; align-items: center; gap: 8px; margin-bottom: 0; font-weight: 600;">
|
||||
<input type="checkbox" id="dispensePrintEnabled">
|
||||
|
||||
@@ -317,6 +317,7 @@ function renderDispensingTable(rows) {
|
||||
const info = getVariantInfoById(row.drug_variant_id);
|
||||
const quantityText = `${row.quantity} ${info.unit || 'units'}`;
|
||||
const animal = row.animal_name || '-';
|
||||
const vet = row.prescribing_vet || '-';
|
||||
const notes = row.notes || '-';
|
||||
const allocations = formatDispenseAllocation(row);
|
||||
|
||||
@@ -328,6 +329,7 @@ function renderDispensingTable(rows) {
|
||||
<td>${escapeHtml(info.strength || '-')}</td>
|
||||
<td>${escapeHtml(quantityText)}</td>
|
||||
<td>${escapeHtml(animal)}</td>
|
||||
<td>${escapeHtml(vet)}</td>
|
||||
<td>${escapeHtml(allocations)}</td>
|
||||
<td>${escapeHtml(notes)}</td>
|
||||
</tr>
|
||||
@@ -344,6 +346,7 @@ function renderDispensingTable(rows) {
|
||||
<th>Strength</th>
|
||||
<th>Quantity</th>
|
||||
<th>Animal</th>
|
||||
<th>Prescribing Vet</th>
|
||||
<th>Batch Allocation</th>
|
||||
<th>Notes</th>
|
||||
</tr>
|
||||
@@ -530,6 +533,7 @@ function applyCurrentFilters() {
|
||||
info.drugName || '',
|
||||
info.strength || '',
|
||||
row.animal_name || '',
|
||||
row.prescribing_vet || '',
|
||||
row.notes || '',
|
||||
formatDispenseAllocation(row)
|
||||
].join(' ').toLowerCase();
|
||||
|
||||
@@ -710,8 +710,6 @@ footer {
|
||||
}
|
||||
|
||||
#dispenseModal .form-actions {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
margin-top: 16px;
|
||||
padding-top: 14px;
|
||||
background: var(--white);
|
||||
|
||||
Reference in New Issue
Block a user