Book_system/app/controllers/inventory.py
superlishunqin 29914a4178 0506
2025-05-06 12:01:11 +08:00

162 lines
5.8 KiB
Python

# app/controllers/inventory.py
from flask import Blueprint, render_template, request, jsonify, flash, redirect, url_for
from flask_login import login_required, current_user
from app.models.book import Book
from app.models.inventory import InventoryLog
from app.models.user import db
from app.utils.auth import admin_required
from datetime import datetime
inventory_bp = Blueprint('inventory', __name__, url_prefix='/inventory')
@inventory_bp.route('/')
@login_required
@admin_required
def inventory_list():
"""库存管理页面 - 只有管理员有权限进入"""
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
# 搜索功能
search = request.args.get('search', '')
query = Book.query
if search:
query = query.filter(
(Book.title.contains(search)) |
(Book.author.contains(search)) |
(Book.isbn.contains(search))
)
# 排序
sort = request.args.get('sort', 'id')
order = request.args.get('order', 'asc')
if order == 'desc':
query = query.order_by(getattr(Book, sort).desc())
else:
query = query.order_by(getattr(Book, sort))
pagination = query.paginate(page=page, per_page=per_page)
books = pagination.items
return render_template('inventory/list.html',
books=books,
pagination=pagination,
search=search,
sort=sort,
order=order)
@inventory_bp.route('/adjust/<int:book_id>', methods=['GET', 'POST'])
@login_required
@admin_required
def adjust_inventory(book_id):
"""调整图书库存"""
book = Book.query.get_or_404(book_id)
if request.method == 'POST':
change_type = request.form.get('change_type')
change_amount = int(request.form.get('change_amount', 0))
remark = request.form.get('remark', '')
if change_amount <= 0:
flash('调整数量必须大于0', 'danger')
return redirect(url_for('inventory.adjust_inventory', book_id=book_id))
# 计算库存变化
original_stock = book.stock
if change_type == 'in':
book.stock += change_amount
after_stock = book.stock
elif change_type == 'out':
if book.stock < change_amount:
flash('出库数量不能大于当前库存', 'danger')
return redirect(url_for('inventory.adjust_inventory', book_id=book_id))
book.stock -= change_amount
after_stock = book.stock
else:
flash('无效的操作类型', 'danger')
return redirect(url_for('inventory.adjust_inventory', book_id=book_id))
# 创建库存日志
log = InventoryLog(
book_id=book.id,
change_type=change_type,
change_amount=change_amount,
after_stock=after_stock,
operator_id=current_user.id,
remark=remark,
changed_at=datetime.now()
)
try:
db.session.add(log)
db.session.commit()
flash(f'图书《{book.title}》库存调整成功!原库存:{original_stock},现库存:{after_stock}', 'success')
return redirect(url_for('inventory.inventory_list'))
except Exception as e:
db.session.rollback()
flash(f'操作失败:{str(e)}', 'danger')
return redirect(url_for('inventory.adjust_inventory', book_id=book_id))
return render_template('inventory/adjust.html', book=book)
@inventory_bp.route('/logs')
@login_required
@admin_required
def inventory_logs():
"""查看库存变动日志"""
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
# 搜索和筛选
book_id = request.args.get('book_id', type=int)
change_type = request.args.get('change_type', '')
date_from = request.args.get('date_from', '')
date_to = request.args.get('date_to', '')
query = InventoryLog.query
if book_id:
query = query.filter_by(book_id=book_id)
if change_type:
query = query.filter_by(change_type=change_type)
if date_from:
query = query.filter(InventoryLog.changed_at >= datetime.strptime(date_from, '%Y-%m-%d'))
if date_to:
query = query.filter(InventoryLog.changed_at <= datetime.strptime(date_to + ' 23:59:59', '%Y-%m-%d %H:%M:%S'))
# 默认按时间倒序
query = query.order_by(InventoryLog.changed_at.desc())
pagination = query.paginate(page=page, per_page=per_page)
logs = pagination.items
# 获取所有图书用于筛选
books = Book.query.all()
# 如果特定 book_id 被指定,也获取该书的详细信息
book = Book.query.get(book_id) if book_id else None
return render_template('inventory/logs.html',
logs=logs,
pagination=pagination,
books=books,
book=book, # 添加这个变量
book_id=book_id,
change_type=change_type,
date_from=date_from,
date_to=date_to)
@inventory_bp.route('/book/<int:book_id>/logs')
@login_required
@admin_required
def book_inventory_logs(book_id):
"""查看特定图书的库存变动日志"""
book = Book.query.get_or_404(book_id)
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
logs = InventoryLog.query.filter_by(book_id=book_id) \
.order_by(InventoryLog.changed_at.desc()) \
.paginate(page=page, per_page=per_page)
return render_template('inventory/book_logs.html',
book=book,
logs=logs.items,
pagination=logs)