refactor(import): API 层支持导入策略参数
- /preview 端点接收 mode 参数,update 模式下 DB 重复行不视为错误 - /execute 端点接收 mode 参数传递给 service 层 - execute 仅导入 status 为 success/update 的行,error 行不再被提交
This commit is contained in:
@ -47,9 +47,16 @@ def download_template():
|
|||||||
@jwt_required()
|
@jwt_required()
|
||||||
@permission_required('material_list:operation')
|
@permission_required('material_list:operation')
|
||||||
def preview_import():
|
def preview_import():
|
||||||
"""Dry-Run 预览 + 验证(不写入数据库)"""
|
"""Dry-Run 预览 + 验证(不写入数据库)
|
||||||
|
|
||||||
|
FormData:
|
||||||
|
type: 'material' | 'bom'
|
||||||
|
file: Excel 文件
|
||||||
|
mode: 'skip' (默认) | 'update' — update 模式下 DB 重复行显示为「将被更新」而非错误
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
import_type = request.form.get('type', 'material').strip()
|
import_type = request.form.get('type', 'material').strip()
|
||||||
|
mode = request.form.get('mode', 'skip').strip()
|
||||||
file = request.files.get('file')
|
file = request.files.get('file')
|
||||||
if not file:
|
if not file:
|
||||||
return jsonify({'code': 400, 'msg': '请上传文件'}), 400
|
return jsonify({'code': 400, 'msg': '请上传文件'}), 400
|
||||||
@ -60,11 +67,11 @@ def preview_import():
|
|||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
if import_type == 'material':
|
if import_type == 'material':
|
||||||
results = preview_material(BytesIO(file_stream))
|
results = preview_material(BytesIO(file_stream), mode=mode)
|
||||||
else:
|
else:
|
||||||
results = preview_bom(BytesIO(file_stream))
|
results = preview_bom(BytesIO(file_stream))
|
||||||
|
|
||||||
success_count = sum(1 for r in results if r['status'] == 'success')
|
success_count = sum(1 for r in results if r['status'] in ('success', 'update'))
|
||||||
error_count = sum(1 for r in results if r['status'] == 'error')
|
error_count = sum(1 for r in results if r['status'] == 'error')
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
@ -85,24 +92,33 @@ def preview_import():
|
|||||||
@jwt_required()
|
@jwt_required()
|
||||||
@permission_required('material_list:operation')
|
@permission_required('material_list:operation')
|
||||||
def execute_import():
|
def execute_import():
|
||||||
"""确认导入执行(事务保护)"""
|
"""确认导入执行
|
||||||
|
|
||||||
|
Body:
|
||||||
|
type: 'material' | 'bom'
|
||||||
|
rows: 待导入行列表
|
||||||
|
mode: 'skip' (跳过重复,默认) | 'update' (覆盖更新已有记录)
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
data = request.get_json() or {}
|
data = request.get_json() or {}
|
||||||
import_type = data.get('type', 'material').strip()
|
import_type = data.get('type', 'material').strip()
|
||||||
rows = data.get('rows', [])
|
rows = data.get('rows', [])
|
||||||
|
mode = data.get('mode', 'skip').strip()
|
||||||
|
|
||||||
if not rows:
|
if not rows:
|
||||||
return jsonify({'code': 400, 'msg': '导入数据不能为空'}), 400
|
return jsonify({'code': 400, 'msg': '导入数据不能为空'}), 400
|
||||||
if import_type not in ('material', 'bom'):
|
if import_type not in ('material', 'bom'):
|
||||||
return jsonify({'code': 400, 'msg': 'type 必须为 material 或 bom'}), 400
|
return jsonify({'code': 400, 'msg': 'type 必须为 material 或 bom'}), 400
|
||||||
|
if mode not in ('skip', 'update'):
|
||||||
|
return jsonify({'code': 400, 'msg': 'mode 必须为 skip 或 update'}), 400
|
||||||
|
|
||||||
# 仅导入状态为 success 的行
|
# 仅导入状态为 success 或 update 的行,error 行不参与导入
|
||||||
valid_rows = [r for r in rows if r.get('status') == 'success']
|
valid_rows = [r for r in rows if r.get('status') in ('success', 'update')]
|
||||||
if not valid_rows:
|
if not valid_rows:
|
||||||
return jsonify({'code': 400, 'msg': '没有可导入的有效数据(全部为error状态)'}), 400
|
return jsonify({'code': 400, 'msg': '没有可导入的有效数据'}), 400
|
||||||
|
|
||||||
if import_type == 'material':
|
if import_type == 'material':
|
||||||
result = execute_material_import(valid_rows)
|
result = execute_material_import(valid_rows, mode=mode)
|
||||||
else:
|
else:
|
||||||
result = execute_bom_import(valid_rows)
|
result = execute_bom_import(valid_rows)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user