147 lines
4.7 KiB
Python
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
|