feat: 支持按权益名称导入用户
This commit is contained in:
@@ -35,7 +35,7 @@ from app.api.pagination import page_result
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
STUDENT_TEMPLATE_HEADERS = ["手机号", "姓名", "昵称", "每日聊天额度", "状态", "有效期"]
|
||||
STUDENT_TEMPLATE_HEADERS = ["手机号", "姓名", "昵称", "每日聊天额度", "状态", "有效期", "权益名称"]
|
||||
|
||||
|
||||
class AdminGenerateReportRequest(BaseModel):
|
||||
@@ -155,17 +155,7 @@ def download_user_import_template(
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: Admin = Depends(get_current_admin),
|
||||
) -> StreamingResponse:
|
||||
workbook = Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "学员导入模板"
|
||||
sheet.append(STUDENT_TEMPLATE_HEADERS)
|
||||
sheet.append(["13800000001", "张三", "三三", _default_daily_chat_limit(db), "启用", "2026-12-31 23:59:59"])
|
||||
sheet.append(["13800000002", "李四", "", "", "启用", ""])
|
||||
|
||||
widths = [18, 14, 14, 16, 12, 22]
|
||||
for index, width in enumerate(widths, start=1):
|
||||
sheet.column_dimensions[chr(64 + index)].width = width
|
||||
|
||||
workbook = _user_import_template_workbook(db)
|
||||
stream = BytesIO()
|
||||
workbook.save(stream)
|
||||
stream.seek(0)
|
||||
@@ -176,6 +166,32 @@ def download_user_import_template(
|
||||
)
|
||||
|
||||
|
||||
def _user_import_template_workbook(db: Session) -> Workbook:
|
||||
workbook = Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.title = "学员导入模板"
|
||||
sheet.append(STUDENT_TEMPLATE_HEADERS)
|
||||
available_plan = EntitlementService.list_plans(db)
|
||||
example_plan_name = available_plan[0].name if available_plan else ""
|
||||
sheet.append(
|
||||
[
|
||||
"13800000001",
|
||||
"张三",
|
||||
"三三",
|
||||
_default_daily_chat_limit(db),
|
||||
"启用",
|
||||
"2026-12-31 23:59:59",
|
||||
example_plan_name,
|
||||
]
|
||||
)
|
||||
sheet.append(["13800000002", "李四", "", "", "启用", "", ""])
|
||||
|
||||
widths = [18, 14, 14, 16, 12, 22, 22]
|
||||
for index, width in enumerate(widths, start=1):
|
||||
sheet.column_dimensions[chr(64 + index)].width = width
|
||||
return workbook
|
||||
|
||||
|
||||
@router.post("/user/import/excel")
|
||||
def import_users_excel(
|
||||
file: UploadFile = File(...),
|
||||
@@ -214,6 +230,7 @@ def import_users_excel(
|
||||
dailyChatLimit=_parse_optional_int(_excel_value(row, header_map, "每日聊天额度")),
|
||||
status=_parse_status(_excel_value(row, header_map, "状态")),
|
||||
expiredAt=_parse_optional_datetime(_excel_value(row, header_map, "有效期")),
|
||||
entitlementName=_cell_text(_excel_value(row, header_map, "权益名称")) or None,
|
||||
)
|
||||
students.append((row_number, item))
|
||||
except (ValueError, ValidationError) as exc:
|
||||
@@ -243,6 +260,11 @@ def _import_user_items(
|
||||
failed: list[dict] = list(initial_failures or [])
|
||||
seen: set[str] = set()
|
||||
default_daily_limit = _default_daily_chat_limit(db)
|
||||
entitlement_plans = {
|
||||
plan.name.strip(): plan
|
||||
for plan in EntitlementService.list_plans(db)
|
||||
if plan.name.strip()
|
||||
}
|
||||
|
||||
for row_number, item in students:
|
||||
phone = _normalize_phone(item.phone)
|
||||
@@ -264,6 +286,28 @@ def _import_user_items(
|
||||
updated += 1
|
||||
_apply_user_payload(user, item, default_daily_limit)
|
||||
db.add(user)
|
||||
db.flush()
|
||||
entitlement_name = (item.entitlementName or "").strip()
|
||||
entitlement_plan = entitlement_plans.get(entitlement_name)
|
||||
if entitlement_plan is not None:
|
||||
EntitlementService.assign_user_plan(
|
||||
db,
|
||||
user=user,
|
||||
plan_id=entitlement_plan.id,
|
||||
operated_by=current_admin.id,
|
||||
remark="用户批量导入按权益名称匹配",
|
||||
)
|
||||
else:
|
||||
EntitlementService.clear_user_plan(
|
||||
db,
|
||||
user=user,
|
||||
operated_by=current_admin.id,
|
||||
reason=(
|
||||
f"导入的权益名称不存在:{entitlement_name}"
|
||||
if entitlement_name
|
||||
else "导入时未填写权益名称"
|
||||
),
|
||||
)
|
||||
except ValueError as exc:
|
||||
failed.append({"row": row_number, "phone": item.phone, "reason": str(exc)})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user