updated database deployment and views

This commit is contained in:
Quality System Admin
2025-10-12 00:22:45 +03:00
parent a84c881e71
commit aaf6f2b32f
6 changed files with 563 additions and 12 deletions

View File

@@ -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)})

View File

@@ -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()">&times;</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()">&times;</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 %}

View File

@@ -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()