From 1fe00a8ba3cb143ec94c3337ef4515c796b40f0b Mon Sep 17 00:00:00 2001 From: dxc Date: Fri, 27 Feb 2026 15:11:10 +0800 Subject: [PATCH] feat: Add field permission checks to outbound and transaction APIs Co-authored-by: aider (openai/DeepSeek-V3.2-Thinking) --- inventory-backend/app/api/v1/outbound.py | 38 +++++++++++++++++++ inventory-backend/app/api/v1/transactions.py | 40 ++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/inventory-backend/app/api/v1/outbound.py b/inventory-backend/app/api/v1/outbound.py index c2564c7..32c1ed9 100644 --- a/inventory-backend/app/api/v1/outbound.py +++ b/inventory-backend/app/api/v1/outbound.py @@ -143,6 +143,44 @@ def create_outbound(): if not data.get('consumer_name') or not data.get('signature_path'): return jsonify({'code': 400, 'msg': '领用人及签名信息缺失'}), 400 + # 数据清洗:移除用户没有权限的字段 + user_permissions = get_current_user_permissions() + # 超级管理员不过滤 + if 'outbound_list:*' not in user_permissions: + # 字段名到权限码的映射(与前端 permissionMap 保持一致) + field_to_perm = { + 'outbound_no': 'outbound_list:outbound_no', + 'outbound_time': 'outbound_list:outbound_time', + 'outbound_type': 'outbound_list:outbound_type', + 'total_amount': 'outbound_list:total_amount', + 'consumer_name': 'outbound_list:consumer_name', + 'operator_name': 'outbound_list:operator_name', + 'remark': 'outbound_list:remark', + 'signature_path': 'outbound_list:signature_path', + # 明细字段 + 'sku': 'outbound_list:sku', + 'name': 'outbound_list:name', + 'material_type': 'outbound_list:material_type', + 'category': 'outbound_list:category', + 'spec_model': 'outbound_list:spec_model', + 'quantity': 'outbound_list:quantity', + 'unit_price': 'outbound_list:unit_price', + 'price': 'outbound_list:unit_price', # 兼容 price 字段 + 'subtotal': 'outbound_list:subtotal', + } + # 清洗顶层字段 + 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) + # 清洗 items 中的每个商品字段 + if 'items' in data and isinstance(data['items'], list): + for item in data['items']: + for field in list(item.keys()): + perm_code = field_to_perm.get(field) + if perm_code and perm_code not in user_permissions: + item.pop(field, None) + try: # ★ [修改] 调用批量创建服务 outbound_no = OutboundService.create_outbound_batch(data, operator_name=final_operator) diff --git a/inventory-backend/app/api/v1/transactions.py b/inventory-backend/app/api/v1/transactions.py index 3654d3e..acbef7d 100644 --- a/inventory-backend/app/api/v1/transactions.py +++ b/inventory-backend/app/api/v1/transactions.py @@ -61,6 +61,26 @@ def filter_item_by_permissions(item_dict, user_permissions, prefix='op_records') @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}}) @@ -90,6 +110,26 @@ def scan_borrowed_item(): @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)