- Add boxes_crates database table with BIGINT IDs and 8-digit auto-numbered box_numbers - Implement boxes CRUD operations (add, edit, update, delete, delete_multiple) - Create boxes route handlers with POST actions for all operations - Add boxes.html template with 3-panel layout matching warehouse locations module - Implement barcode generation and printing with JsBarcode and QZ Tray integration - Add browser print fallback for when QZ Tray is not available - Simplify create box form to single button with auto-generation - Fix JavaScript null reference errors with proper element validation - Convert tuple data to dictionaries for Jinja2 template compatibility - Register boxes blueprint in Flask app initialization
102 lines
3.4 KiB
Python
102 lines
3.4 KiB
Python
"""
|
|
Boxes Management Routes
|
|
"""
|
|
from flask import Blueprint, render_template, session, redirect, url_for, request, flash
|
|
from app.modules.warehouse.boxes import (
|
|
get_all_boxes, add_box, update_box, delete_box, delete_multiple_boxes,
|
|
get_box_by_id, get_box_stats, ensure_boxes_table
|
|
)
|
|
from app.modules.warehouse.warehouse import get_all_locations
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
boxes_bp = Blueprint('boxes', __name__, url_prefix='/warehouse/boxes')
|
|
|
|
|
|
@boxes_bp.route('/', methods=['GET', 'POST'])
|
|
def manage_boxes():
|
|
"""Manage warehouse boxes page"""
|
|
if 'user_id' not in session:
|
|
return redirect(url_for('main.login'))
|
|
|
|
# Ensure table exists
|
|
ensure_boxes_table()
|
|
|
|
message = None
|
|
message_type = 'info'
|
|
|
|
if request.method == 'POST':
|
|
action = request.form.get('action', '')
|
|
user_id = session.get('user_id', 'System')
|
|
|
|
# Add new box (auto-numbered)
|
|
if action == 'add_box':
|
|
success, msg = add_box(created_by=user_id)
|
|
message = msg
|
|
message_type = 'success' if success else 'danger'
|
|
|
|
# Update box status or location
|
|
elif action == 'edit_box':
|
|
box_id = request.form.get('box_id', '')
|
|
status = request.form.get('status', '')
|
|
location_id = request.form.get('location_id', '')
|
|
|
|
location_id = int(location_id) if location_id and location_id.isdigit() else None
|
|
|
|
success, msg = update_box(box_id, status=status if status else None, location_id=location_id)
|
|
message = msg
|
|
message_type = 'success' if success else 'danger'
|
|
|
|
# Change status
|
|
elif action == 'toggle_status':
|
|
box_id = request.form.get('box_id', '')
|
|
current_status = request.form.get('current_status', 'open')
|
|
new_status = 'closed' if current_status == 'open' else 'open'
|
|
|
|
success, msg = update_box(box_id, status=new_status)
|
|
message = msg
|
|
message_type = 'success' if success else 'danger'
|
|
|
|
# Delete single box
|
|
elif action == 'delete_box':
|
|
box_id = request.form.get('box_id', '')
|
|
success, msg = delete_box(box_id)
|
|
message = msg
|
|
message_type = 'success' if success else 'danger'
|
|
|
|
# Delete multiple boxes
|
|
elif action == 'delete_multiple':
|
|
box_ids = request.form.get('delete_ids', '')
|
|
success, msg = delete_multiple_boxes(box_ids)
|
|
message = msg
|
|
message_type = 'success' if success else 'danger'
|
|
|
|
# Get data and convert tuples to dictionaries
|
|
boxes_data = get_all_boxes()
|
|
boxes = []
|
|
for box_tuple in boxes_data:
|
|
boxes.append({
|
|
'id': box_tuple[0],
|
|
'box_number': box_tuple[1],
|
|
'status': box_tuple[2],
|
|
'location_code': box_tuple[3],
|
|
'created_at': box_tuple[4],
|
|
'updated_at': box_tuple[5],
|
|
'created_by': box_tuple[6],
|
|
'location_id': box_tuple[7]
|
|
})
|
|
|
|
locations = get_all_locations()
|
|
stats = get_box_stats()
|
|
|
|
return render_template(
|
|
'modules/warehouse/boxes.html',
|
|
boxes=boxes,
|
|
locations=locations,
|
|
stats=stats,
|
|
message=message,
|
|
message_type=message_type
|
|
)
|
|
|