Compare commits
2 Commits
fa192247fe
...
511e8ebde4
| Author | SHA1 | Date | |
|---|---|---|---|
| 511e8ebde4 | |||
| 1a82776657 |
@@ -133,6 +133,17 @@ class LabelPrintResponse(BaseModel):
|
|||||||
success: bool
|
success: bool
|
||||||
message: str
|
message: str
|
||||||
|
|
||||||
|
class NotesVariables(BaseModel):
|
||||||
|
animal_name: str
|
||||||
|
notes: str
|
||||||
|
|
||||||
|
class NotesPrintRequest(BaseModel):
|
||||||
|
variables: NotesVariables
|
||||||
|
|
||||||
|
class NotesPrintResponse(BaseModel):
|
||||||
|
success: bool
|
||||||
|
message: str
|
||||||
|
|
||||||
# Authentication Routes
|
# Authentication Routes
|
||||||
@router.post("/auth/register", response_model=TokenResponse)
|
@router.post("/auth/register", response_model=TokenResponse)
|
||||||
def register(user_data: UserCreate, db: Session = Depends(get_db)):
|
def register(user_data: UserCreate, db: Session = Depends(get_db)):
|
||||||
@@ -575,5 +586,66 @@ def print_label(label_request: LabelPrintRequest, current_user: User = Depends(g
|
|||||||
detail=f"Error sending label print request: {str(e)}"
|
detail=f"Error sending label print request: {str(e)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Notes printing endpoint
|
||||||
|
@router.post("/notes/print", response_model=NotesPrintResponse)
|
||||||
|
def print_notes(notes_request: NotesPrintRequest, current_user: User = Depends(get_current_user)):
|
||||||
|
"""
|
||||||
|
Print notes by publishing an MQTT message
|
||||||
|
|
||||||
|
This endpoint publishes a notes print request to the MQTT broker,
|
||||||
|
which will be picked up by the label printing service.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Get notes template configuration from environment
|
||||||
|
import os
|
||||||
|
template_id = os.getenv("NOTES_TEMPLATE_ID", "notes_template")
|
||||||
|
label_size = os.getenv("LABEL_SIZE", "29x90")
|
||||||
|
test_mode = os.getenv("LABEL_TEST", "false").lower() == "true"
|
||||||
|
|
||||||
|
# Capitalize text fields for better presentation
|
||||||
|
variables = notes_request.variables.dict()
|
||||||
|
variables["animal_name"] = capitalize_label_text(variables["animal_name"])
|
||||||
|
variables["notes"] = capitalize_label_text(variables["notes"])
|
||||||
|
|
||||||
|
# Convert the request to the MQTT message format
|
||||||
|
mqtt_message = {
|
||||||
|
"template_id": template_id,
|
||||||
|
"label_size": label_size,
|
||||||
|
"variables": variables,
|
||||||
|
"test": test_mode
|
||||||
|
}
|
||||||
|
|
||||||
|
# Publish to MQTT and wait for response
|
||||||
|
success, response = publish_label_print_with_response(mqtt_message, timeout=10.0)
|
||||||
|
|
||||||
|
print(f"Notes print result: success={success}, response={response}")
|
||||||
|
|
||||||
|
if success:
|
||||||
|
result = NotesPrintResponse(
|
||||||
|
success=True,
|
||||||
|
message=response.get("message", "Notes printed successfully")
|
||||||
|
)
|
||||||
|
print(f"Returning success response: {result}")
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
# Return error details from printer
|
||||||
|
# Check both 'message' and 'error' fields for error details
|
||||||
|
if response:
|
||||||
|
error_msg = response.get("message") or response.get("error", "Unknown error")
|
||||||
|
else:
|
||||||
|
error_msg = "No response from printer"
|
||||||
|
result = NotesPrintResponse(
|
||||||
|
success=False,
|
||||||
|
message=f"Print failed: {error_msg}"
|
||||||
|
)
|
||||||
|
print(f"Returning error response: {result}")
|
||||||
|
return result
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=500,
|
||||||
|
detail=f"Error sending notes print request: {str(e)}"
|
||||||
|
)
|
||||||
|
|
||||||
# Include router with /api prefix
|
# Include router with /api prefix
|
||||||
app.include_router(router)
|
app.include_router(router)
|
||||||
|
|||||||
@@ -172,14 +172,17 @@ function setupEventListeners() {
|
|||||||
const dispenseForm = document.getElementById('dispenseForm');
|
const dispenseForm = document.getElementById('dispenseForm');
|
||||||
const prescribeForm = document.getElementById('prescribeForm');
|
const prescribeForm = document.getElementById('prescribeForm');
|
||||||
const editForm = document.getElementById('editForm');
|
const editForm = document.getElementById('editForm');
|
||||||
|
const printNotesForm = document.getElementById('printNotesForm');
|
||||||
const addModal = document.getElementById('addModal');
|
const addModal = document.getElementById('addModal');
|
||||||
const addVariantModal = document.getElementById('addVariantModal');
|
const addVariantModal = document.getElementById('addVariantModal');
|
||||||
const editVariantModal = document.getElementById('editVariantModal');
|
const editVariantModal = document.getElementById('editVariantModal');
|
||||||
const dispenseModal = document.getElementById('dispenseModal');
|
const dispenseModal = document.getElementById('dispenseModal');
|
||||||
const prescribeModal = document.getElementById('prescribeModal');
|
const prescribeModal = document.getElementById('prescribeModal');
|
||||||
const editModal = document.getElementById('editModal');
|
const editModal = document.getElementById('editModal');
|
||||||
|
const printNotesModal = document.getElementById('printNotesModal');
|
||||||
const addDrugBtn = document.getElementById('addDrugBtn');
|
const addDrugBtn = document.getElementById('addDrugBtn');
|
||||||
const dispenseBtn = document.getElementById('dispenseBtn');
|
const dispenseBtn = document.getElementById('dispenseBtn');
|
||||||
|
const printNotesBtn = document.getElementById('printNotesBtn');
|
||||||
const cancelAddBtn = document.getElementById('cancelAddBtn');
|
const cancelAddBtn = document.getElementById('cancelAddBtn');
|
||||||
const cancelVariantBtn = document.getElementById('cancelVariantBtn');
|
const cancelVariantBtn = document.getElementById('cancelVariantBtn');
|
||||||
const cancelEditVariantBtn = document.getElementById('cancelEditVariantBtn');
|
const cancelEditVariantBtn = document.getElementById('cancelEditVariantBtn');
|
||||||
@@ -202,8 +205,10 @@ function setupEventListeners() {
|
|||||||
if (dispenseForm) dispenseForm.addEventListener('submit', handleDispenseDrug);
|
if (dispenseForm) dispenseForm.addEventListener('submit', handleDispenseDrug);
|
||||||
if (prescribeForm) prescribeForm.addEventListener('submit', handlePrescribeDrug);
|
if (prescribeForm) prescribeForm.addEventListener('submit', handlePrescribeDrug);
|
||||||
if (editForm) editForm.addEventListener('submit', handleEditDrug);
|
if (editForm) editForm.addEventListener('submit', handleEditDrug);
|
||||||
|
if (printNotesForm) printNotesForm.addEventListener('submit', handlePrintNotes);
|
||||||
|
|
||||||
if (addDrugBtn) addDrugBtn.addEventListener('click', () => openModal(addModal));
|
if (addDrugBtn) addDrugBtn.addEventListener('click', () => openModal(addModal));
|
||||||
|
if (printNotesBtn) printNotesBtn.addEventListener('click', () => openModal(printNotesModal));
|
||||||
if (dispenseBtn) dispenseBtn.addEventListener('click', () => {
|
if (dispenseBtn) dispenseBtn.addEventListener('click', () => {
|
||||||
updateDispenseDrugSelect();
|
updateDispenseDrugSelect();
|
||||||
openModal(dispenseModal);
|
openModal(dispenseModal);
|
||||||
@@ -216,6 +221,9 @@ function setupEventListeners() {
|
|||||||
if (cancelPrescribeBtn) cancelPrescribeBtn.addEventListener('click', () => closeModal(prescribeModal));
|
if (cancelPrescribeBtn) cancelPrescribeBtn.addEventListener('click', () => closeModal(prescribeModal));
|
||||||
if (cancelEditBtn) cancelEditBtn.addEventListener('click', closeEditModal);
|
if (cancelEditBtn) cancelEditBtn.addEventListener('click', closeEditModal);
|
||||||
|
|
||||||
|
const cancelPrintNotesBtn = document.getElementById('cancelPrintNotesBtn');
|
||||||
|
if (cancelPrintNotesBtn) cancelPrintNotesBtn.addEventListener('click', () => closeModal(printNotesModal));
|
||||||
|
|
||||||
const closeHistoryBtn = document.getElementById('closeHistoryBtn');
|
const closeHistoryBtn = document.getElementById('closeHistoryBtn');
|
||||||
if (closeHistoryBtn) closeHistoryBtn.addEventListener('click', () => closeModal(document.getElementById('historyModal')));
|
if (closeHistoryBtn) closeHistoryBtn.addEventListener('click', () => closeModal(document.getElementById('historyModal')));
|
||||||
|
|
||||||
@@ -770,6 +778,63 @@ async function handlePrescribeDrug(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle print notes form submission
|
||||||
|
async function handlePrintNotes(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const animalName = document.getElementById('notesAnimalName').value.trim();
|
||||||
|
const notes = document.getElementById('notesContent').value.trim();
|
||||||
|
|
||||||
|
if (!animalName || !notes) {
|
||||||
|
showToast('Please fill in all required fields', 'warning');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Send notes to print endpoint
|
||||||
|
const notesData = {
|
||||||
|
variables: {
|
||||||
|
animal_name: animalName,
|
||||||
|
notes: notes
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await apiCall('/notes/print', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(notesData)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
throw new Error(error.detail || 'Notes printing request failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
console.log('Notes print result:', result);
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
// Printing failed
|
||||||
|
const isError = result.message && (
|
||||||
|
result.message.includes('not found') ||
|
||||||
|
result.message.includes('error') ||
|
||||||
|
result.message.includes('failed')
|
||||||
|
);
|
||||||
|
const toastType = isError ? 'error' : 'warning';
|
||||||
|
showToast(result.message, toastType, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printing succeeded
|
||||||
|
showToast('Notes printed successfully!', 'success');
|
||||||
|
|
||||||
|
document.getElementById('printNotesForm').reset();
|
||||||
|
closeModal(document.getElementById('printNotesModal'));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error printing notes:', error);
|
||||||
|
showToast('Failed to print notes: ' + error.message, 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Delete variant
|
// Delete variant
|
||||||
async function deleteVariant(variantId) {
|
async function deleteVariant(variantId) {
|
||||||
if (!confirm('Are you sure you want to delete this variant?')) return;
|
if (!confirm('Are you sure you want to delete this variant?')) return;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<h2>Current Inventory</h2>
|
<h2>Current Inventory</h2>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
|
<button id="printNotesBtn" class="btn btn-primary btn-small">📝 Print Notes</button>
|
||||||
<button id="addDrugBtn" class="btn btn-primary btn-small">➕ Add Drug</button>
|
<button id="addDrugBtn" class="btn btn-primary btn-small">➕ Add Drug</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
@@ -429,6 +430,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Print Notes Modal -->
|
||||||
|
<div id="printNotesModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<span class="close">×</span>
|
||||||
|
<h2>Print Notes</h2>
|
||||||
|
<form id="printNotesForm" novalidate>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="notesAnimalName">Animal Name/ID *</label>
|
||||||
|
<input type="text" id="notesAnimalName" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="notesContent">Notes *</label>
|
||||||
|
<textarea id="notesContent" rows="6" placeholder="Enter notes to print..." required></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" class="btn btn-primary">Print Notes</button>
|
||||||
|
<button type="button" class="btn btn-secondary" id="cancelPrintNotesBtn">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
|
|||||||
@@ -252,7 +252,9 @@ label {
|
|||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="number"],
|
input[type="number"],
|
||||||
input[type="password"],
|
input[type="password"],
|
||||||
select {
|
input[type="date"],
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
@@ -262,10 +264,17 @@ select {
|
|||||||
transition: border-color 0.2s;
|
transition: border-color 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="text"]:focus,
|
input[type="text"]:focus,
|
||||||
input[type="number"]:focus,
|
input[type="number"]:focus,
|
||||||
input[type="password"]:focus,
|
input[type="password"]:focus,
|
||||||
select:focus {
|
input[type="date"]:focus,
|
||||||
|
select:focus,
|
||||||
|
textarea:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: var(--secondary-color);
|
border-color: var(--secondary-color);
|
||||||
box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
|
box-shadow: 0 0 5px rgba(52, 152, 219, 0.3);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ password_file /mosquitto/config/pwfile
|
|||||||
# Logging
|
# Logging
|
||||||
log_dest stdout
|
log_dest stdout
|
||||||
log_timestamp true
|
log_timestamp true
|
||||||
log_type all
|
#log_type all
|
||||||
|
|
||||||
# Performance
|
# Performance
|
||||||
max_connections -1
|
max_connections -1
|
||||||
|
|||||||
Reference in New Issue
Block a user