from flask import Blueprint, jsonify, request # .material -> .base refactor checked from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt from app.utils.decorators import permission_required from app.services.auth_service import AuthService from app.services.trans_service import TransService import traceback trans_bp = Blueprint('transactions', __name__, url_prefix='/transactions') # ============================================================================== # 辅助函数:获取当前用户的完整权限列表(基于角色查询) # ============================================================================== def get_current_user_permissions(): """ 返回当前用户拥有的所有权限码列表(包括菜单和元素) 此函数根据角色查询数据库得到权限。 """ claims = get_jwt() user_role = claims.get('role') if not user_role: return [] # 超级管理员返回所有字段权限 if user_role == 'super_admin': return ['*'] perm_dict = AuthService.get_user_permissions(user_role) # 合并菜单和元素权限 perms = perm_dict.get('menus', []) + perm_dict.get('elements', []) return perms def filter_item_by_permissions(item_dict, user_permissions, prefix='op_records'): """ 根据用户权限过滤 item 字典,无权限的字段值置为 None """ # 字段名到权限码的映射(与前端 permissionMap 保持一致) field_to_perm = { 'borrow_no': f'{prefix}:borrow_no', 'borrower_name': f'{prefix}:borrower_name', 'sku': f'{prefix}:sku', 'borrow_time': f'{prefix}:borrow_time', 'return_time': f'{prefix}:return_time', 'status': f'{prefix}:status', 'expected_return_time': f'{prefix}:expected_return_time', 'return_location': f'{prefix}:return_location', 'borrow_signature': f'{prefix}:borrow_signature', 'return_signature': f'{prefix}:return_signature', } # 如果用户是超级管理员且有 '*',则不过滤 if '*' in user_permissions: return item_dict for field, perm_code in field_to_perm.items(): if field in item_dict and perm_code not in user_permissions: item_dict[field] = None return item_dict # --- 借库接口 --- @trans_bp.route('/borrow', methods=['POST']) @jwt_required() @permission_required('op_borrow:operation') def create_borrow(): data = request.get_json() # 数据清洗:移除用户没有权限的字段 user_permissions = get_current_user_permissions() # 超级管理员不过滤 if '*' not in user_permissions: field_to_perm = { 'borrow_no': 'op_records:borrow_no', 'borrower_name': 'op_records:borrower_name', 'sku': 'op_records:sku', 'borrow_time': 'op_records:borrow_time', 'return_time': 'op_records:return_time', 'status': 'op_records:status', 'expected_return_time': 'op_records:expected_return_time', 'return_location': 'op_records:return_location', 'borrow_signature': 'op_records:borrow_signature', 'return_signature': 'op_records:return_signature', } for field in list(data.keys()): perm_code = field_to_perm.get(field) if perm_code and perm_code not in user_permissions: data.pop(field, None) try: no = TransService.create_borrow(data) return jsonify({'code': 200, 'msg': '借用成功', 'data': {'borrow_no': no}}) except Exception as e: return jsonify({'code': 400, 'msg': str(e)}), 400 # --- 还库辅助:扫码查找借出记录 --- @trans_bp.route('/return/scan', methods=['GET']) @jwt_required() @permission_required('op_return') def scan_borrowed_item(): barcode = request.args.get('barcode') if not barcode: return jsonify({'code': 400, 'msg': '无条码'}), 400 res = TransService.scan_for_return(barcode) if res: return jsonify({'code': 200, 'data': res}) else: return jsonify({'code': 404, 'msg': '未找到该物品的未还记录'}), 404 # --- 还库提交 --- @trans_bp.route('/return', methods=['POST']) @jwt_required() @permission_required('op_return:operation') def submit_return(): data = request.get_json() # 数据清洗:移除用户没有权限的字段 user_permissions = get_current_user_permissions() # 超级管理员不过滤 if '*' not in user_permissions: field_to_perm = { 'borrow_no': 'op_records:borrow_no', 'borrower_name': 'op_records:borrower_name', 'sku': 'op_records:sku', 'borrow_time': 'op_records:borrow_time', 'return_time': 'op_records:return_time', 'status': 'op_records:status', 'expected_return_time': 'op_records:expected_return_time', 'return_location': 'op_records:return_location', 'borrow_signature': 'op_records:borrow_signature', 'return_signature': 'op_records:return_signature', } for field in list(data.keys()): perm_code = field_to_perm.get(field) if perm_code and perm_code not in user_permissions: data.pop(field, None) user = get_jwt_identity() # 库管 try: TransService.process_return(data, operator_name=user) return jsonify({'code': 200, 'msg': '还库成功'}) except Exception as e: return jsonify({'code': 400, 'msg': str(e)}), 400 # --- 记录列表 --- @trans_bp.route('/records', methods=['GET']) @jwt_required() @permission_required('op_records') def get_records(): status = request.args.get('status', 'all') page = int(request.args.get('page', 1)) keyword = request.args.get('keyword', '') res = TransService.get_records(page=page, limit=10, status=status, keyword=keyword) # 字段级脱敏 user_permissions = get_current_user_permissions() if res.get('items'): res['items'] = [filter_item_by_permissions(item, user_permissions, 'op_records') for item in res['items']] return jsonify({'code': 200, 'data': res})