Files
shanxia2.0/backend/app/services/pl_transport_resource_snapshot_service.py
T
2026-06-30 23:44:22 +08:00

147 lines
4.7 KiB
Python

"""运输计划 - 安排运输时车辆/人员/证件资源快照"""
from __future__ import annotations
from datetime import datetime
from typing import Optional
from fastapi import HTTPException
from sqlalchemy.orm import Session
from app.models.pl_models import PlPersonnel, PlVehicle
from app.schemas.pl.base_data import CertRead
from app.schemas.pl.resource_snapshot import (
SnapshotCertRead,
SnapshotPersonnelRow,
TransportResourceSnapshot,
)
from app.services.pl_cert_service import certs_to_read, list_owner_certs
from app.services.pl_personnel_service import (
build_personnel_summary,
load_vehicle_personnel_rows,
)
def _cert_to_snapshot(cert: CertRead) -> SnapshotCertRead:
return SnapshotCertRead(
id=cert.id,
cert_id=cert.cert_id or cert.id,
vehicle_part=cert.vehicle_part,
cert_name=cert.cert_name,
cert_no=cert.cert_no,
expire_date=cert.expire_date,
remind_days=cert.remind_days,
attachment_urls=cert.attachment_urls,
owner_type=cert.owner_type,
owner_id=cert.owner_id,
status=cert.status,
)
def build_transport_resource_snapshot(
db: Session,
tenant_no: str,
vehicle_id: str,
*,
selected_driver_id: Optional[str] = None,
) -> TransportResourceSnapshot:
"""读取车辆当前主数据,生成安排运输用整包快照。"""
vehicle = (
db.query(PlVehicle)
.filter(
PlVehicle.id == vehicle_id,
PlVehicle.tenant_no == tenant_no,
PlVehicle.del_flag == 0,
)
.first()
)
if not vehicle:
raise HTTPException(status_code=400, detail="车辆不存在")
vehicle_certs = certs_to_read(list_owner_certs(db, tenant_no, "vehicle", vehicle.id))
link_rows = load_vehicle_personnel_rows(db, tenant_no, vehicle_id)
personnel_list: list[SnapshotPersonnelRow] = []
summary_links: list[tuple[str, str, int]] = []
for row in link_rows:
personnel: Optional[PlPersonnel] = None
if row.personnel_id:
personnel = (
db.query(PlPersonnel)
.filter(
PlPersonnel.id == row.personnel_id,
PlPersonnel.tenant_no == tenant_no,
PlPersonnel.del_flag == 0,
)
.first()
)
person_certs: list[SnapshotCertRead] = []
if row.personnel_id:
person_certs = [
_cert_to_snapshot(c)
for c in certs_to_read(
list_owner_certs(db, tenant_no, "personnel", row.personnel_id)
)
]
personnel_list.append(
SnapshotPersonnelRow(
personnel_id=row.personnel_id,
personnel_name=row.personnel_name,
phone_no=row.phone_no or (personnel.phone_no if personnel else None),
age=row.age if row.age is not None else (personnel.age if personnel else None),
id_card_no=personnel.id_card_no if personnel else None,
role=row.role,
is_default=row.is_default,
remark=row.remark,
cert_list=person_certs,
)
)
summary_links.append((row.personnel_name, row.role, row.is_default))
personnel_summary, _ = build_personnel_summary(summary_links)
return TransportResourceSnapshot(
snapshotted_at=datetime.now(),
vehicle_id=vehicle.id,
vehicle_type=vehicle.vehicle_type,
carrier_id=vehicle.carrier_id,
carrier_name=vehicle.carrier_name,
license_plate=vehicle.license_plate,
trailer_no=vehicle.trailer_no,
load_capacity=vehicle.load_capacity,
vehicle_status=vehicle.vehicle_status,
cert_list=[_cert_to_snapshot(c) for c in vehicle_certs],
personnel_list=personnel_list,
personnel_summary=personnel_summary or None,
selected_driver_id=selected_driver_id,
)
def apply_resource_snapshot_json(
*,
plan,
transport=None,
snapshot: TransportResourceSnapshot,
) -> None:
"""将快照 JSON 写入计划/运输单,并同步标量冗余字段。"""
json_str = snapshot.model_dump_json(by_alias=True)
plan.trailer_no = snapshot.trailer_no
plan.resource_snapshot = json_str
if snapshot.personnel_summary:
plan.personnel_summary = snapshot.personnel_summary
if transport is not None:
transport.trailer_no = snapshot.trailer_no
transport.resource_snapshot = json_str
def clear_resource_snapshot(*, plan, transport=None) -> None:
plan.trailer_no = None
plan.resource_snapshot = None
plan.personnel_summary = None
if transport is not None:
transport.trailer_no = None
transport.resource_snapshot = None