updated database deployment and views
This commit is contained in:
@@ -2755,18 +2755,24 @@ def update_location():
|
||||
from app.warehouse import update_location
|
||||
try:
|
||||
data = request.get_json()
|
||||
print(f"DEBUG: Received update request data: {data}")
|
||||
|
||||
location_id = data.get('location_id')
|
||||
location_code = data.get('location_code')
|
||||
size = data.get('size')
|
||||
description = data.get('description')
|
||||
|
||||
print(f"DEBUG: Extracted values - ID: {location_id}, Code: {location_code}, Size: {size}, Description: {description}")
|
||||
|
||||
if not location_id or not location_code:
|
||||
return jsonify({'success': False, 'error': 'Location ID and code are required'})
|
||||
|
||||
result = update_location(location_id, location_code, size, description)
|
||||
print(f"DEBUG: Update result: {result}")
|
||||
return jsonify(result)
|
||||
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Update route exception: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)})
|
||||
|
||||
@warehouse_bp.route('/delete_location', methods=['POST'])
|
||||
@@ -2774,15 +2780,20 @@ def delete_location():
|
||||
from app.warehouse import delete_location_by_id
|
||||
try:
|
||||
data = request.get_json()
|
||||
print(f"DEBUG: Received delete request data: {data}")
|
||||
|
||||
location_id = data.get('location_id')
|
||||
print(f"DEBUG: Extracted location_id: {location_id} (type: {type(location_id)})")
|
||||
|
||||
if not location_id:
|
||||
return jsonify({'success': False, 'error': 'Location ID is required'})
|
||||
|
||||
result = delete_location_by_id(location_id)
|
||||
print(f"DEBUG: Delete result: {result}")
|
||||
return jsonify(result)
|
||||
|
||||
except Exception as e:
|
||||
print(f"DEBUG: Delete route exception: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)})
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
{% block title %}Create Warehouse Locations{% endblock %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/warehouse.css') }}">
|
||||
{% endblock %}
|
||||
|
||||
@@ -400,20 +401,72 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Edit button functionality
|
||||
editButton.addEventListener('click', function() {
|
||||
console.log('Edit button clicked', selectedLocation);
|
||||
if (selectedLocation) {
|
||||
openEditModal(selectedLocation);
|
||||
} else {
|
||||
showNotification('❌ No location selected', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
// Delete button functionality
|
||||
deleteButton.addEventListener('click', function() {
|
||||
console.log('Delete button clicked', selectedLocation);
|
||||
if (selectedLocation) {
|
||||
openDeleteModal(selectedLocation);
|
||||
} else {
|
||||
showNotification('❌ No location selected', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize QZ Tray
|
||||
initializeQZTray();
|
||||
|
||||
// Handle edit form submission
|
||||
document.getElementById('edit-form').addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const formData = new FormData(this);
|
||||
const data = {
|
||||
location_id: parseInt(formData.get('location_id')),
|
||||
location_code: formData.get('location_code'),
|
||||
size: formData.get('size') ? parseInt(formData.get('size')) : null,
|
||||
description: formData.get('description') || null
|
||||
};
|
||||
|
||||
console.log('Attempting to update location:', data);
|
||||
|
||||
// Send update request
|
||||
fetch("{{ url_for('warehouse.update_location') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => {
|
||||
console.log('Update response status:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(result => {
|
||||
console.log('Update result:', result);
|
||||
if (result.success) {
|
||||
showNotification('✅ Location updated successfully!', 'success');
|
||||
closeEditModal();
|
||||
// Reload page to show changes
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} else {
|
||||
showNotification('❌ Error updating location: ' + result.error, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showNotification('❌ Error updating location: ' + error.message, 'error');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Print barcode function with enhanced QZ Tray support
|
||||
@@ -437,7 +490,7 @@ async function printLocationBarcode() {
|
||||
printStatus.textContent = 'Generating label...';
|
||||
|
||||
// Generate PDF for the 4x8cm label
|
||||
const response = await fetch('/generate_location_label_pdf', {
|
||||
const response = await fetch("{{ url_for('warehouse.generate_location_label_pdf') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -569,22 +622,31 @@ document.getElementById('edit-form').addEventListener('submit', function(e) {
|
||||
|
||||
const formData = new FormData(this);
|
||||
const data = {
|
||||
location_id: formData.get('location_id'),
|
||||
location_id: parseInt(formData.get('location_id')),
|
||||
location_code: formData.get('location_code'),
|
||||
size: formData.get('size'),
|
||||
description: formData.get('description')
|
||||
size: formData.get('size') ? parseInt(formData.get('size')) : null,
|
||||
description: formData.get('description') || null
|
||||
};
|
||||
|
||||
console.log('Attempting to update location:', data);
|
||||
|
||||
// Send update request
|
||||
fetch('/update_location', {
|
||||
fetch("{{ url_for('warehouse.update_location') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(response => {
|
||||
console.log('Update response status:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(result => {
|
||||
console.log('Update result:', result);
|
||||
if (result.success) {
|
||||
showNotification('✅ Location updated successfully!', 'success');
|
||||
closeEditModal();
|
||||
@@ -600,6 +662,46 @@ document.getElementById('edit-form').addEventListener('submit', function(e) {
|
||||
});
|
||||
});
|
||||
|
||||
// Handle delete confirmation
|
||||
function confirmDelete() {
|
||||
const locationId = document.getElementById('delete-confirm-id').textContent;
|
||||
|
||||
console.log('Attempting to delete location ID:', locationId);
|
||||
|
||||
// Send delete request
|
||||
fetch("{{ url_for('warehouse.delete_location') }}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
location_id: parseInt(locationId)
|
||||
})
|
||||
})
|
||||
.then(response => {
|
||||
console.log('Delete response status:', response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(result => {
|
||||
console.log('Delete result:', result);
|
||||
if (result.success) {
|
||||
showNotification('✅ Location deleted successfully!', 'success');
|
||||
closeDeleteModal();
|
||||
// Reload page to show changes
|
||||
setTimeout(() => window.location.reload(), 1000);
|
||||
} else {
|
||||
showNotification('❌ Error deleting location: ' + result.error, 'error');
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
showNotification('❌ Error deleting location: ' + error.message, 'error');
|
||||
});
|
||||
}
|
||||
|
||||
// Handle delete confirmation
|
||||
function confirmDelete() {
|
||||
const locationId = document.getElementById('delete-confirm-id').textContent;
|
||||
@@ -644,4 +746,271 @@ window.addEventListener('click', function(event) {
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Edit Location Modal -->
|
||||
<div id="edit-modal" class="modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Edit Location</h3>
|
||||
<span class="close" onclick="closeEditModal()">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="edit-form">
|
||||
<input type="hidden" id="edit-location-id" name="location_id">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-location-code">Location Code:</label>
|
||||
<input type="text" id="edit-location-code" name="location_code" maxlength="12" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-size">Size:</label>
|
||||
<input type="number" id="edit-size" name="size">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="edit-description">Description:</label>
|
||||
<input type="text" id="edit-description" name="description" maxlength="250">
|
||||
</div>
|
||||
|
||||
<div class="modal-buttons">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeEditModal()">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Update Location</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Location Modal -->
|
||||
<div id="delete-modal" class="modal" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3>Delete Location</h3>
|
||||
<span class="close" onclick="closeDeleteModal()">×</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to delete this location?</p>
|
||||
<div class="delete-info">
|
||||
<strong>ID:</strong> <span id="delete-confirm-id"></span><br>
|
||||
<strong>Code:</strong> <span id="delete-confirm-code"></span><br>
|
||||
<strong>Size:</strong> <span id="delete-confirm-size"></span><br>
|
||||
<strong>Description:</strong> <span id="delete-confirm-description"></span>
|
||||
</div>
|
||||
<p style="color: #d32f2f; font-weight: bold;">This action cannot be undone!</p>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<button type="button" class="btn btn-secondary" onclick="closeDeleteModal()">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" onclick="confirmDelete()">Delete Location</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
/* Modal Styles */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: var(--app-overlay-bg, rgba(0, 0, 0, 0.5));
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--app-card-bg, #f8fafc);
|
||||
color: var(--app-card-text, #1e293b);
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||
animation: modalFadeIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes modalFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20px 25px;
|
||||
border-bottom: 1px solid #cbd5e1;
|
||||
background-color: var(--app-card-bg, #f8fafc);
|
||||
}
|
||||
|
||||
.modal-header h3 {
|
||||
margin: 0;
|
||||
font-size: 1.3em;
|
||||
font-weight: 600;
|
||||
color: var(--app-card-text, #1e293b);
|
||||
}
|
||||
|
||||
.close {
|
||||
color: var(--app-card-text, #1e293b);
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: #e11d48;
|
||||
background-color: #f1f5f9;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
padding: 25px;
|
||||
background-color: var(--app-card-bg, #f8fafc);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
color: var(--app-label-text, #334155);
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 12px 15px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 6px;
|
||||
background-color: var(--app-input-bg, #e2e8f0);
|
||||
color: var(--app-input-text, #1e293b);
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
transition: border-color 0.2s ease;
|
||||
}
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
border-color: #3b82f6;
|
||||
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
||||
}
|
||||
|
||||
.modal-buttons {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
justify-content: flex-end;
|
||||
padding: 20px 25px;
|
||||
border-top: 1px solid #cbd5e1;
|
||||
background-color: var(--app-card-bg, #f8fafc);
|
||||
}
|
||||
|
||||
.modal-buttons .btn {
|
||||
padding: 10px 20px;
|
||||
border-radius: 6px;
|
||||
font-weight: 600;
|
||||
min-width: 100px;
|
||||
transition: all 0.2s ease;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-buttons .btn-primary {
|
||||
background: #1e293b;
|
||||
color: #f8fafc;
|
||||
}
|
||||
|
||||
.modal-buttons .btn-primary:hover {
|
||||
background: #0f172a;
|
||||
}
|
||||
|
||||
.modal-buttons .btn-secondary {
|
||||
background: #e11d48;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.modal-buttons .btn-secondary:hover {
|
||||
background: #be185d;
|
||||
}
|
||||
|
||||
.delete-info {
|
||||
background-color: #fef3c7;
|
||||
border: 1px solid #f59e0b;
|
||||
padding: 15px;
|
||||
border-radius: 6px;
|
||||
margin: 15px 0;
|
||||
border-left: 4px solid #f59e0b;
|
||||
color: var(--app-card-text, #1e293b);
|
||||
}
|
||||
|
||||
.delete-info strong {
|
||||
color: var(--text-color, #333);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color, #007bff);
|
||||
color: white;
|
||||
border: 2px solid var(--primary-color, #007bff);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--primary-hover-color, #0056b3);
|
||||
border-color: var(--primary-hover-color, #0056b3);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--secondary-color, #6c757d);
|
||||
color: white;
|
||||
border: 2px solid var(--secondary-color, #6c757d);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--secondary-hover-color, #545b62);
|
||||
border-color: var(--secondary-hover-color, #545b62);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: var(--danger-color, #dc3545);
|
||||
color: white;
|
||||
border: 2px solid var(--danger-color, #dc3545);
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background-color: var(--danger-hover-color, #c82333);
|
||||
border-color: var(--danger-hover-color, #c82333);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -89,7 +89,7 @@ def delete_locations_by_ids(ids_str):
|
||||
cursor = conn.cursor()
|
||||
deleted = 0
|
||||
for id in ids:
|
||||
cursor.execute("DELETE FROM warehouse_locations WHERE id = ?", (id,))
|
||||
cursor.execute("DELETE FROM warehouse_locations WHERE id = %s", (id,))
|
||||
if cursor.rowcount:
|
||||
deleted += 1
|
||||
conn.commit()
|
||||
@@ -226,20 +226,20 @@ def update_location(location_id, location_code, size, description):
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Check if location exists
|
||||
cursor.execute("SELECT id FROM warehouse_locations WHERE id = ?", (location_id,))
|
||||
cursor.execute("SELECT id FROM warehouse_locations WHERE id = %s", (location_id,))
|
||||
if not cursor.fetchone():
|
||||
conn.close()
|
||||
return {"success": False, "error": "Location not found"}
|
||||
|
||||
# Check if location code already exists for different location
|
||||
cursor.execute("SELECT id FROM warehouse_locations WHERE location_code = ? AND id != ?", (location_code, location_id))
|
||||
cursor.execute("SELECT id FROM warehouse_locations WHERE location_code = %s AND id != %s", (location_code, location_id))
|
||||
if cursor.fetchone():
|
||||
conn.close()
|
||||
return {"success": False, "error": "Location code already exists"}
|
||||
|
||||
# Update location
|
||||
cursor.execute(
|
||||
"UPDATE warehouse_locations SET location_code = ?, size = ?, description = ? WHERE id = ?",
|
||||
"UPDATE warehouse_locations SET location_code = %s, size = %s, description = %s WHERE id = %s",
|
||||
(location_code, size if size else None, description, location_id)
|
||||
)
|
||||
conn.commit()
|
||||
@@ -250,6 +250,8 @@ def update_location(location_id, location_code, size, description):
|
||||
except Exception as e:
|
||||
print(f"Error updating location: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
print(f"Error updating location: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def delete_location_by_id(location_id):
|
||||
"""Delete a warehouse location by ID"""
|
||||
@@ -258,14 +260,14 @@ def delete_location_by_id(location_id):
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Check if location exists
|
||||
cursor.execute("SELECT location_code FROM warehouse_locations WHERE id = ?", (location_id,))
|
||||
cursor.execute("SELECT location_code FROM warehouse_locations WHERE id = %s", (location_id,))
|
||||
location = cursor.fetchone()
|
||||
if not location:
|
||||
conn.close()
|
||||
return {"success": False, "error": "Location not found"}
|
||||
|
||||
# Delete location
|
||||
cursor.execute("DELETE FROM warehouse_locations WHERE id = ?", (location_id,))
|
||||
cursor.execute("DELETE FROM warehouse_locations WHERE id = %s", (location_id,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user