Files
012-kaopeilian/backend/app/services/course_position_service.py
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

195 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
课程岗位分配服务
"""
from typing import List, Optional
from sqlalchemy import select, and_, delete, func
from sqlalchemy.orm import selectinload
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.logger import get_logger
from app.models.position_course import PositionCourse
from app.models.position import Position
from app.models.position_member import PositionMember
from app.schemas.course import CoursePositionAssignment, CoursePositionAssignmentInDB
from app.services.base_service import BaseService
logger = get_logger(__name__)
class CoursePositionService(BaseService[PositionCourse]):
"""课程岗位分配服务"""
def __init__(self):
super().__init__(PositionCourse)
async def get_course_positions(
self,
db: AsyncSession,
course_id: int,
course_type: Optional[str] = None
) -> List[CoursePositionAssignmentInDB]:
"""
获取课程的岗位分配列表
Args:
db: 数据库会话
course_id: 课程ID
course_type: 课程类型筛选
Returns:
岗位分配列表
"""
# 构建查询
conditions = [
PositionCourse.course_id == course_id,
PositionCourse.is_deleted == False
]
if course_type:
conditions.append(PositionCourse.course_type == course_type)
stmt = (
select(PositionCourse)
.options(selectinload(PositionCourse.position))
.where(and_(*conditions))
.order_by(PositionCourse.priority, PositionCourse.id)
)
result = await db.execute(stmt)
assignments = result.scalars().all()
# 转换为返回格式,并查询每个岗位的成员数量
result_list = []
for assignment in assignments:
# 查询岗位成员数量
member_count = 0
if assignment.position_id:
member_count_result = await db.execute(
select(func.count(PositionMember.id)).where(
and_(
PositionMember.position_id == assignment.position_id,
PositionMember.is_deleted == False
)
)
)
member_count = member_count_result.scalar() or 0
result_list.append(
CoursePositionAssignmentInDB(
id=assignment.id,
course_id=assignment.course_id,
position_id=assignment.position_id,
course_type=assignment.course_type,
priority=assignment.priority,
position_name=assignment.position.name if assignment.position else None,
position_description=assignment.position.description if assignment.position else None,
member_count=member_count
)
)
return result_list
async def batch_assign_positions(
self,
db: AsyncSession,
course_id: int,
assignments: List[CoursePositionAssignment],
user_id: int
) -> List[CoursePositionAssignmentInDB]:
"""
批量分配课程到岗位
Args:
db: 数据库会话
course_id: 课程ID
assignments: 岗位分配列表
user_id: 操作用户ID
Returns:
分配结果列表
"""
created_assignments = []
for assignment in assignments:
# 检查是否已存在注意Result 只能消费一次,需保存结果)
result = await db.execute(
select(PositionCourse).where(
PositionCourse.course_id == course_id,
PositionCourse.position_id == assignment.position_id,
PositionCourse.is_deleted == False,
)
)
existing_assignment = result.scalar_one_or_none()
if existing_assignment:
# 已存在则更新类型与优先级
existing_assignment.course_type = assignment.course_type
existing_assignment.priority = assignment.priority
# PositionCourse 未继承 AuditMixin不强制写入审计字段
created_assignments.append(existing_assignment)
else:
# 新建分配关系
new_assignment = PositionCourse(
course_id=course_id,
position_id=assignment.position_id,
course_type=assignment.course_type,
priority=assignment.priority,
)
db.add(new_assignment)
created_assignments.append(new_assignment)
await db.commit()
# 重新加载关联数据
for obj in created_assignments:
await db.refresh(obj)
logger.info("批量分配课程到岗位成功", course_id=course_id, count=len(assignments), user_id=user_id)
# 返回分配结果
return await self.get_course_positions(db, course_id)
async def remove_position_assignment(
self,
db: AsyncSession,
course_id: int,
position_id: int,
user_id: int
) -> bool:
"""
移除课程的岗位分配
Args:
db: 数据库会话
course_id: 课程ID
position_id: 岗位ID
user_id: 操作用户ID
Returns:
是否成功
"""
# 查找分配记录
stmt = select(PositionCourse).where(
PositionCourse.course_id == course_id,
PositionCourse.position_id == position_id,
PositionCourse.is_deleted == False
)
result = await db.execute(stmt)
assignment = result.scalar_one_or_none()
if assignment:
# 软删除
assignment.is_deleted = True
assignment.deleted_by = user_id
await db.commit()
logger.info(f"移除课程岗位分配成功", course_id=course_id, position_id=position_id, user_id=user_id)
return True
return False
# 创建服务实例
course_position_service = CoursePositionService()