通过水准线路编码生成 daily 数据
This commit is contained in:
89
app/api/daily.py
Normal file
89
app/api/daily.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from fastapi import APIRouter, Depends, HTTPException, status
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from typing import Dict, Any
|
||||||
|
from ..core.database import get_db
|
||||||
|
from ..core.response_code import ResponseCode
|
||||||
|
from ..schemas.daily import LinecodeToDailyRequest
|
||||||
|
from ..services.daily import DailyDataService
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
router = APIRouter(prefix="/daily", tags=["日常数据管理"])
|
||||||
|
|
||||||
|
# 实例化服务类
|
||||||
|
daily_service = DailyDataService()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/create_from_linecode", response_model=Dict[str, Any])
|
||||||
|
def create_daily_data_from_linecode(
|
||||||
|
request: LinecodeToDailyRequest,
|
||||||
|
db: Session = Depends(get_db)
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
综合业务接口:通过水准线路编码生成 daily 数据
|
||||||
|
|
||||||
|
业务逻辑:
|
||||||
|
1. 在水准数据表(level_data)中查找符合 linecode 的记录,且 NYID 最大
|
||||||
|
2. 通过 NYID 查询沉降数据表(settlement_data)
|
||||||
|
3. 通过沉降数据的 point_id 查询观测点表(checkpoint),得到 section_id
|
||||||
|
4. 通过 section_id 查询断面表(section_data),得到 account_id
|
||||||
|
5. 整合这些数据,形成 daily 对象,插入到数据库表
|
||||||
|
|
||||||
|
返回:成功插入的记录数
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"开始处理 linecode={request.linecode} 的 daily 数据生成请求")
|
||||||
|
|
||||||
|
# 调用服务层方法
|
||||||
|
created_records = daily_service.create_daily_from_linecode(
|
||||||
|
db=db,
|
||||||
|
linecode=request.linecode,
|
||||||
|
account_id=request.account_id
|
||||||
|
)
|
||||||
|
|
||||||
|
if not created_records:
|
||||||
|
return {
|
||||||
|
"code": ResponseCode.SUCCESS,
|
||||||
|
"message": "没有生成任何 daily 记录",
|
||||||
|
"total": 0,
|
||||||
|
"data": []
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(f"成功生成 {len(created_records)} 条 daily 记录")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"code": ResponseCode.SUCCESS,
|
||||||
|
"message": f"成功生成 {len(created_records)} 条 daily 记录",
|
||||||
|
"total": len(created_records),
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"id": record.id,
|
||||||
|
"user_id": record.user_id,
|
||||||
|
"account_id": record.account_id,
|
||||||
|
"point_id": record.point_id,
|
||||||
|
"NYID": record.NYID,
|
||||||
|
"linecode": record.linecode,
|
||||||
|
"section_id": record.section_id,
|
||||||
|
"remaining": record.remaining,
|
||||||
|
"is_all": record.is_all
|
||||||
|
}
|
||||||
|
for record in created_records
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
except ValueError as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail=str(e)
|
||||||
|
)
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"生成 daily 数据失败:{str(e)}", exc_info=True)
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"生成 daily 数据失败:{str(e)}"
|
||||||
|
)
|
||||||
@@ -11,6 +11,7 @@ from .api.database import router as database_router
|
|||||||
from .api.task import router as task_router
|
from .api.task import router as task_router
|
||||||
from .api.comprehensive_data import router as comprehensive_data_router
|
from .api.comprehensive_data import router as comprehensive_data_router
|
||||||
from .api.export_excel import router as export_excel_router
|
from .api.export_excel import router as export_excel_router
|
||||||
|
from .api.daily import router as daily_router
|
||||||
from .utils.scheduler import task_scheduler
|
from .utils.scheduler import task_scheduler
|
||||||
|
|
||||||
# 初始化日志系统
|
# 初始化日志系统
|
||||||
@@ -70,6 +71,7 @@ app.include_router(database_router, prefix="/api")
|
|||||||
app.include_router(task_router, prefix="/api")
|
app.include_router(task_router, prefix="/api")
|
||||||
app.include_router(comprehensive_data_router, prefix="/api")
|
app.include_router(comprehensive_data_router, prefix="/api")
|
||||||
app.include_router(export_excel_router, prefix="/api")
|
app.include_router(export_excel_router, prefix="/api")
|
||||||
|
app.include_router(daily_router, prefix="/api")
|
||||||
# app.include_router(test_router, prefix="/api")
|
# app.include_router(test_router, prefix="/api")
|
||||||
|
|
||||||
# 根路径
|
# 根路径
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ class DailyData(Base):
|
|||||||
__tablename__ = "daily"
|
__tablename__ = "daily"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
||||||
user_id = Column(Integer, nullable=False, comment="用户id")
|
user_id = Column(Integer, default=1, nullable=False, comment="用户id")
|
||||||
account_id = Column(Integer, nullable=False, comment="账户id")
|
account_id = Column(Integer, nullable=False, comment="账户id")
|
||||||
point_id = Column(String(100), comment="测点id")
|
point_id = Column(String(100), comment="测点id")
|
||||||
NYID = Column(String(100), nullable=False, comment="期数id")
|
NYID = Column(String(100), nullable=False, comment="期数id")
|
||||||
linecode = Column(String(255), nullable=False, comment="水准线路编码")
|
linecode = Column(String(255), nullable=False, comment="水准线路编码")
|
||||||
section_id = Column(String(255), nullable=False, comment="所属断面id")
|
section_id = Column(String(255), nullable=False, comment="所属断面id")
|
||||||
remaining = Column(Integer, nullable=False, comment="剩余天数")
|
remaining = Column(Integer, nullable=False, comment="剩余天数")
|
||||||
user_id = Column(Integer, default=1, nullable=False, comment="用户id")
|
is_all = Column(Integer, default=0, nullable=False, comment="是否全量数据")
|
||||||
is_all = Column(Integer, default=1, nullable=False, comment="是否全量数据")
|
|
||||||
|
|||||||
22
app/schemas/daily.py
Normal file
22
app/schemas/daily.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class LinecodeToDailyRequest(BaseModel):
|
||||||
|
"""通过水准线路编码生成 daily 数据的请求模型"""
|
||||||
|
linecode: str = Field(..., description="水准线路编码")
|
||||||
|
account_id: Optional[int] = Field(None, description="账户ID(可选,如果沉降数据中有)")
|
||||||
|
|
||||||
|
class DailyDataResponse(BaseModel):
|
||||||
|
"""Daily 数据响应模型"""
|
||||||
|
id: int
|
||||||
|
user_id: int
|
||||||
|
account_id: int
|
||||||
|
point_id: Optional[str]
|
||||||
|
NYID: str
|
||||||
|
linecode: str
|
||||||
|
section_id: str
|
||||||
|
remaining: int
|
||||||
|
is_all: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
from_attributes = True
|
||||||
@@ -233,4 +233,115 @@ class DailyDataService(BaseService[DailyData]):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"获取account_id={account_id}的日常数据失败:{str(e)}", exc_info=True)
|
logger.error(f"获取account_id={account_id}的日常数据失败:{str(e)}", exc_info=True)
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
def create_daily_from_linecode(
|
||||||
|
self,
|
||||||
|
db: Session,
|
||||||
|
linecode: str,
|
||||||
|
account_id: Optional[int] = None
|
||||||
|
) -> List[DailyData]:
|
||||||
|
"""
|
||||||
|
通过水准线路编码生成 daily 数据
|
||||||
|
|
||||||
|
业务逻辑:
|
||||||
|
1. 在水准数据表(level_data)中查找符合 linecode 的记录,且 NYID 最大
|
||||||
|
2. 通过 NYID 查询沉降数据表(settlement_data)
|
||||||
|
3. 通过沉降数据的 point_id 查询观测点表(checkpoint),得到 section_id
|
||||||
|
4. 通过 section_id 查询断面表(section_data),得到 account_id
|
||||||
|
5. 整合这些数据,形成 daily 对象,插入到数据库表
|
||||||
|
|
||||||
|
Args:
|
||||||
|
db: 数据库会话
|
||||||
|
linecode: 水准线路编码
|
||||||
|
account_id: 可选的账户ID筛选条件
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
创建的 DailyData 记录列表
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.info(f"开始处理 linecode={linecode} 的 daily 数据生成请求")
|
||||||
|
|
||||||
|
from ..models.level_data import LevelData
|
||||||
|
from ..models.settlement_data import SettlementData
|
||||||
|
from ..models.checkpoint import Checkpoint
|
||||||
|
from ..models.section_data import SectionData
|
||||||
|
|
||||||
|
# 1. 在水准数据表中查找符合 linecode 的记录,且 NYID 最大
|
||||||
|
level_data_list = db.query(LevelData)\
|
||||||
|
.filter(LevelData.linecode == linecode)\
|
||||||
|
.all()
|
||||||
|
|
||||||
|
if not level_data_list:
|
||||||
|
raise ValueError(f"未找到 linecode={linecode} 对应的水准数据")
|
||||||
|
|
||||||
|
# 找到 NYID 最大的记录(将 String 转换为数字进行比较)
|
||||||
|
max_nyid = max(level_data_list, key=lambda x: int(x.NYID) if x.NYID.isdigit() else 0)
|
||||||
|
target_nyid = max_nyid.NYID
|
||||||
|
logger.info(f"找到最大 NYID: {target_nyid}")
|
||||||
|
|
||||||
|
# 2. 通过 NYID 查询沉降数据
|
||||||
|
settlement_data_list = db.query(SettlementData)\
|
||||||
|
.filter(SettlementData.NYID == target_nyid)\
|
||||||
|
.all()
|
||||||
|
|
||||||
|
if not settlement_data_list:
|
||||||
|
raise ValueError(f"未找到 NYID={target_nyid} 对应的沉降数据")
|
||||||
|
|
||||||
|
# 3. 遍历沉降数据,构建 daily 记录
|
||||||
|
daily_records = []
|
||||||
|
for settlement in settlement_data_list:
|
||||||
|
# 3.1 通过沉降数据的 point_id 查询观测点表,得到 section_id
|
||||||
|
checkpoint = db.query(Checkpoint)\
|
||||||
|
.filter(Checkpoint.point_id == settlement.point_id)\
|
||||||
|
.first()
|
||||||
|
if not checkpoint:
|
||||||
|
logger.warning(f"未找到 point_id={settlement.point_id} 对应的观测点,跳过该记录")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 3.2 通过 section_id 查询断面表,得到 account_id
|
||||||
|
section = db.query(SectionData)\
|
||||||
|
.filter(SectionData.section_id == checkpoint.section_id)\
|
||||||
|
.first()
|
||||||
|
if not section:
|
||||||
|
logger.warning(f"未找到 section_id={checkpoint.section_id} 对应的断面,跳过该记录")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 3.3 从断面数据中获取 account_id,作为 user_id
|
||||||
|
user_id = int(section.account_id) if section.account_id else None
|
||||||
|
if not user_id:
|
||||||
|
logger.warning(f"断面 section_id={checkpoint.section_id} 没有 account_id,跳过该记录")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 如果提供了 account_id 筛选条件,则只处理匹配的记录
|
||||||
|
if account_id is not None and user_id != account_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 3.4 构建 daily 记录
|
||||||
|
daily_record = DailyData(
|
||||||
|
user_id=user_id,
|
||||||
|
account_id=user_id,
|
||||||
|
point_id=settlement.point_id,
|
||||||
|
NYID=settlement.NYID,
|
||||||
|
linecode=linecode,
|
||||||
|
section_id=checkpoint.section_id,
|
||||||
|
remaining=0,
|
||||||
|
is_all=0
|
||||||
|
)
|
||||||
|
daily_records.append(daily_record)
|
||||||
|
|
||||||
|
if not daily_records:
|
||||||
|
logger.warning(f"没有生成任何 daily 记录")
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 4. 批量插入 daily 记录
|
||||||
|
created_records = self.batch_create_by_account_nyid(db, daily_records)
|
||||||
|
|
||||||
|
logger.info(f"成功生成 {len(created_records)} 条 daily 记录")
|
||||||
|
return created_records
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"生成 daily 数据失败:{str(e)}", exc_info=True)
|
||||||
|
raise
|
||||||
Reference in New Issue
Block a user