Fix API compatibility and add user/role/permission and asset import/export
This commit is contained in:
403
backend_new/app/services/maintenance_service.py
Normal file
403
backend_new/app/services/maintenance_service.py
Normal file
@@ -0,0 +1,403 @@
|
||||
"""
|
||||
维修管理业务服务层
|
||||
"""
|
||||
from typing import List, Optional, Dict, Any
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
from app.crud.maintenance import maintenance_record
|
||||
from app.crud.asset import asset
|
||||
from app.schemas.maintenance import (
|
||||
MaintenanceRecordCreate,
|
||||
MaintenanceRecordUpdate,
|
||||
MaintenanceRecordStart,
|
||||
MaintenanceRecordComplete
|
||||
)
|
||||
from app.core.exceptions import NotFoundException, BusinessException
|
||||
|
||||
|
||||
class MaintenanceService:
|
||||
"""维修管理服务类"""
|
||||
|
||||
async def get_record(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int
|
||||
) -> Dict[str, Any]:
|
||||
"""获取维修记录详情"""
|
||||
# 使用selectinload预加载关联数据,避免N+1查询
|
||||
from app.models.maintenance import MaintenanceRecord
|
||||
from app.models.asset import Asset
|
||||
from app.models.user import User
|
||||
from app.models.brand_supplier import Supplier
|
||||
|
||||
obj = db.query(
|
||||
MaintenanceRecord
|
||||
).options(
|
||||
selectinload(MaintenanceRecord.asset.of_type(Asset)),
|
||||
selectinload(MaintenanceRecord.report_user.of_type(User)),
|
||||
selectinload(MaintenanceRecord.maintenance_user.of_type(User)),
|
||||
selectinload(MaintenanceRecord.vendor.of_type(Supplier))
|
||||
).filter(
|
||||
MaintenanceRecord.id == record_id
|
||||
).first()
|
||||
|
||||
if not obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
return self._load_relations(db, obj)
|
||||
|
||||
def get_records(
|
||||
self,
|
||||
db: Session,
|
||||
skip: int = 0,
|
||||
limit: int = 20,
|
||||
asset_id: Optional[int] = None,
|
||||
status: Optional[str] = None,
|
||||
fault_type: Optional[str] = None,
|
||||
priority: Optional[str] = None,
|
||||
maintenance_type: Optional[str] = None,
|
||||
keyword: Optional[str] = None
|
||||
) -> tuple:
|
||||
"""获取维修记录列表"""
|
||||
items, total = maintenance_record.get_multi(
|
||||
db=db,
|
||||
skip=skip,
|
||||
limit=limit,
|
||||
asset_id=asset_id,
|
||||
status=status,
|
||||
fault_type=fault_type,
|
||||
priority=priority,
|
||||
maintenance_type=maintenance_type,
|
||||
keyword=keyword
|
||||
)
|
||||
|
||||
# 加载关联信息
|
||||
items_with_relations = [self._load_relations(db, item) for item in items]
|
||||
|
||||
return items_with_relations, total
|
||||
|
||||
async def create_record(
|
||||
self,
|
||||
db: Session,
|
||||
obj_in: MaintenanceRecordCreate,
|
||||
report_user_id: int,
|
||||
creator_id: int
|
||||
):
|
||||
"""创建维修记录"""
|
||||
# 验证资产存在
|
||||
asset_obj = asset.get(db, obj_in.asset_id)
|
||||
if not asset_obj:
|
||||
raise NotFoundException("资产")
|
||||
|
||||
# 生成维修单号
|
||||
record_code = await self._generate_record_code(db)
|
||||
|
||||
# 创建维修记录
|
||||
db_obj = maintenance_record.create(
|
||||
db=db,
|
||||
obj_in=obj_in,
|
||||
record_code=record_code,
|
||||
asset_code=asset_obj.asset_code,
|
||||
report_user_id=report_user_id,
|
||||
creator_id=creator_id
|
||||
)
|
||||
|
||||
# 如果资产状态不是维修中,则更新状态
|
||||
if asset_obj.status != "maintenance":
|
||||
from app.services.asset_service import asset_service
|
||||
from app.schemas.asset import AssetStatusTransition
|
||||
|
||||
try:
|
||||
await asset_service.change_asset_status(
|
||||
db=db,
|
||||
asset_id=asset_obj.id,
|
||||
status_transition=AssetStatusTransition(
|
||||
new_status="maintenance",
|
||||
remark=f"报修: {record_code}"
|
||||
),
|
||||
operator_id=report_user_id
|
||||
)
|
||||
except Exception as e:
|
||||
# 状态更新失败不影响维修记录创建
|
||||
pass
|
||||
|
||||
return self._load_relations(db, db_obj)
|
||||
|
||||
def update_record(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int,
|
||||
obj_in: MaintenanceRecordUpdate,
|
||||
updater_id: int
|
||||
):
|
||||
"""更新维修记录"""
|
||||
db_obj = maintenance_record.get(db, record_id)
|
||||
if not db_obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
# 已完成的维修记录不能更新
|
||||
if db_obj.status == "completed":
|
||||
raise BusinessException("已完成的维修记录不能更新")
|
||||
|
||||
return maintenance_record.update(db, db_obj, obj_in, updater_id)
|
||||
|
||||
async def start_maintenance(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int,
|
||||
start_in: MaintenanceRecordStart,
|
||||
maintenance_user_id: int
|
||||
):
|
||||
"""开始维修"""
|
||||
db_obj = maintenance_record.get(db, record_id)
|
||||
if not db_obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
# 检查状态
|
||||
if db_obj.status != "pending":
|
||||
raise BusinessException("只有待处理状态的维修记录可以开始维修")
|
||||
|
||||
# 验证维修类型
|
||||
if start_in.maintenance_type == "vendor_repair" and not start_in.vendor_id:
|
||||
raise BusinessException("外部维修必须指定维修供应商")
|
||||
|
||||
# 开始维修
|
||||
db_obj = maintenance_record.start_maintenance(
|
||||
db=db,
|
||||
db_obj=db_obj,
|
||||
maintenance_type=start_in.maintenance_type,
|
||||
maintenance_user_id=maintenance_user_id,
|
||||
vendor_id=start_in.vendor_id
|
||||
)
|
||||
|
||||
return self._load_relations(db, db_obj)
|
||||
|
||||
async def complete_maintenance(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int,
|
||||
complete_in: MaintenanceRecordComplete,
|
||||
maintenance_user_id: int
|
||||
):
|
||||
"""完成维修"""
|
||||
db_obj = maintenance_record.get(db, record_id)
|
||||
if not db_obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
# 检查状态
|
||||
if db_obj.status != "in_progress":
|
||||
raise BusinessException("只有维修中的记录可以完成")
|
||||
|
||||
# 完成维修
|
||||
db_obj = maintenance_record.complete_maintenance(
|
||||
db=db,
|
||||
db_obj=db_obj,
|
||||
maintenance_result=complete_in.maintenance_result,
|
||||
maintenance_cost=complete_in.maintenance_cost,
|
||||
replaced_parts=complete_in.replaced_parts,
|
||||
images=complete_in.images
|
||||
)
|
||||
|
||||
# 恢复资产状态
|
||||
from app.services.asset_service import asset_service
|
||||
from app.schemas.asset import AssetStatusTransition
|
||||
|
||||
try:
|
||||
await asset_service.change_asset_status(
|
||||
db=db,
|
||||
asset_id=db_obj.asset_id,
|
||||
status_transition=AssetStatusTransition(
|
||||
new_status=complete_in.asset_status,
|
||||
remark=f"维修完成: {db_obj.record_code}"
|
||||
),
|
||||
operator_id=maintenance_user_id
|
||||
)
|
||||
except Exception as e:
|
||||
# 状态更新失败不影响维修记录完成
|
||||
pass
|
||||
|
||||
return self._load_relations(db, db_obj)
|
||||
|
||||
def cancel_maintenance(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int
|
||||
):
|
||||
"""取消维修"""
|
||||
db_obj = maintenance_record.get(db, record_id)
|
||||
if not db_obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
# 检查状态
|
||||
if db_obj.status == "completed":
|
||||
raise BusinessException("已完成的维修记录不能取消")
|
||||
|
||||
# 取消维修
|
||||
db_obj = maintenance_record.cancel_maintenance(db, db_obj)
|
||||
|
||||
# 恢复资产状态
|
||||
asset_obj = asset.get(db, db_obj.asset_id)
|
||||
if asset_obj and asset_obj.status == "maintenance":
|
||||
from app.services.asset_service import asset_service
|
||||
from app.schemas.asset import AssetStatusTransition
|
||||
|
||||
try:
|
||||
# 根据维修前的状态恢复
|
||||
target_status = "in_stock" # 默认恢复为库存中
|
||||
asset_service.change_asset_status(
|
||||
db=db,
|
||||
asset_id=asset_obj.id,
|
||||
status_transition=AssetStatusTransition(
|
||||
new_status=target_status,
|
||||
remark=f"取消维修: {db_obj.record_code}"
|
||||
),
|
||||
operator_id=db_obj.report_user_id or 0
|
||||
)
|
||||
except Exception as e:
|
||||
# 状态更新失败不影响维修记录取消
|
||||
pass
|
||||
|
||||
return self._load_relations(db, db_obj)
|
||||
|
||||
def delete_record(
|
||||
self,
|
||||
db: Session,
|
||||
record_id: int
|
||||
) -> bool:
|
||||
"""删除维修记录"""
|
||||
db_obj = maintenance_record.get(db, record_id)
|
||||
if not db_obj:
|
||||
raise NotFoundException("维修记录")
|
||||
|
||||
# 只能删除待处理或已取消的记录
|
||||
if db_obj.status not in ["pending", "cancelled"]:
|
||||
raise BusinessException("只能删除待处理或已取消的维修记录")
|
||||
|
||||
return maintenance_record.delete(db, record_id)
|
||||
|
||||
def get_asset_records(
|
||||
self,
|
||||
db: Session,
|
||||
asset_id: int,
|
||||
skip: int = 0,
|
||||
limit: int = 50
|
||||
) -> List:
|
||||
"""获取资产的维修记录"""
|
||||
# 验证资产存在
|
||||
if not asset.get(db, asset_id):
|
||||
raise NotFoundException("资产")
|
||||
|
||||
records = maintenance_record.get_by_asset(db, asset_id, skip, limit)
|
||||
return [self._load_relations(db, record) for record in records]
|
||||
|
||||
def get_statistics(
|
||||
self,
|
||||
db: Session,
|
||||
asset_id: Optional[int] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""获取维修统计信息"""
|
||||
return maintenance_record.get_statistics(db, asset_id)
|
||||
|
||||
def _load_relations(
|
||||
self,
|
||||
db: Session,
|
||||
obj
|
||||
) -> Dict[str, Any]:
|
||||
"""加载维修记录关联信息"""
|
||||
from app.models.asset import Asset
|
||||
from app.models.user import User
|
||||
from app.models.brand_supplier import Supplier
|
||||
|
||||
result = {
|
||||
"id": obj.id,
|
||||
"record_code": obj.record_code,
|
||||
"asset_id": obj.asset_id,
|
||||
"asset_code": obj.asset_code,
|
||||
"fault_description": obj.fault_description,
|
||||
"fault_type": obj.fault_type,
|
||||
"report_user_id": obj.report_user_id,
|
||||
"report_time": obj.report_time,
|
||||
"priority": obj.priority,
|
||||
"maintenance_type": obj.maintenance_type,
|
||||
"vendor_id": obj.vendor_id,
|
||||
"maintenance_cost": float(obj.maintenance_cost) if obj.maintenance_cost else None,
|
||||
"start_time": obj.start_time,
|
||||
"complete_time": obj.complete_time,
|
||||
"maintenance_user_id": obj.maintenance_user_id,
|
||||
"maintenance_result": obj.maintenance_result,
|
||||
"replaced_parts": obj.replaced_parts,
|
||||
"status": obj.status,
|
||||
"images": obj.images,
|
||||
"remark": obj.remark,
|
||||
"created_at": obj.created_at,
|
||||
"updated_at": obj.updated_at
|
||||
}
|
||||
|
||||
# 加载资产信息
|
||||
if obj.asset_id:
|
||||
asset_obj = db.query(Asset).filter(Asset.id == obj.asset_id).first()
|
||||
if asset_obj:
|
||||
result["asset"] = {
|
||||
"id": asset_obj.id,
|
||||
"asset_code": asset_obj.asset_code,
|
||||
"asset_name": asset_obj.asset_name,
|
||||
"status": asset_obj.status
|
||||
}
|
||||
|
||||
# 加载报修人信息
|
||||
if obj.report_user_id:
|
||||
report_user = db.query(User).filter(User.id == obj.report_user_id).first()
|
||||
if report_user:
|
||||
result["report_user"] = {
|
||||
"id": report_user.id,
|
||||
"real_name": report_user.real_name,
|
||||
"username": report_user.username
|
||||
}
|
||||
|
||||
# 加载维修人员信息
|
||||
if obj.maintenance_user_id:
|
||||
maintenance_user = db.query(User).filter(User.id == obj.maintenance_user_id).first()
|
||||
if maintenance_user:
|
||||
result["maintenance_user"] = {
|
||||
"id": maintenance_user.id,
|
||||
"real_name": maintenance_user.real_name,
|
||||
"username": maintenance_user.username
|
||||
}
|
||||
|
||||
# 加载供应商信息
|
||||
if obj.vendor_id:
|
||||
vendor = db.query(Supplier).filter(Supplier.id == obj.vendor_id).first()
|
||||
if vendor:
|
||||
result["vendor"] = {
|
||||
"id": vendor.id,
|
||||
"supplier_name": vendor.supplier_name,
|
||||
"contact_person": vendor.contact_person,
|
||||
"contact_phone": vendor.contact_phone
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
async def _generate_record_code(self, db: Session) -> str:
|
||||
"""生成维修单号"""
|
||||
from datetime import datetime
|
||||
import random
|
||||
import string
|
||||
|
||||
# 日期部分
|
||||
date_str = datetime.now().strftime("%Y%m%d")
|
||||
|
||||
# 序号部分(4位随机数)
|
||||
sequence = "".join(random.choices(string.digits, k=4))
|
||||
|
||||
# 组合单号: MT202501240001
|
||||
record_code = f"MT{date_str}{sequence}"
|
||||
|
||||
# 检查是否重复,如果重复则重新生成
|
||||
while maintenance_record.get_by_code(db, record_code):
|
||||
sequence = "".join(random.choices(string.digits, k=4))
|
||||
record_code = f"MT{date_str}{sequence}"
|
||||
|
||||
return record_code
|
||||
|
||||
|
||||
# 创建全局实例
|
||||
maintenance_service = MaintenanceService()
|
||||
Reference in New Issue
Block a user