131 lines
3.6 KiB
Python
131 lines
3.6 KiB
Python
"""运输计划 · 工厂现场链接(与地磅出入库单解耦)"""
|
|
from __future__ import annotations
|
|
|
|
import secrets
|
|
from dataclasses import dataclass
|
|
from datetime import date, datetime
|
|
from decimal import Decimal
|
|
from typing import Optional
|
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.utils import generate_uuid
|
|
from app.models.pl_models import (
|
|
PlPlan,
|
|
PlPlanProduct,
|
|
PlTransport,
|
|
PlTransportSiteLink,
|
|
)
|
|
from app.services.db.mappers import parse_date_str
|
|
from app.services.pl_dibang_bridge_service import (
|
|
_plan_type_to_business_type,
|
|
_product_quantity,
|
|
resolve_partner_company,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class TransportSiteLinkResult:
|
|
plan_product_id: str
|
|
product_name: str
|
|
site_link_id: str
|
|
plan_no: str
|
|
business_type: str
|
|
|
|
|
|
def _normalize_plan_date(plan: PlPlan) -> date:
|
|
plan_date = plan.plan_date
|
|
if isinstance(plan_date, datetime):
|
|
return plan_date.date()
|
|
if isinstance(plan_date, str):
|
|
parsed = parse_date_str(plan_date)
|
|
return parsed or date.today()
|
|
if isinstance(plan_date, date):
|
|
return plan_date
|
|
return date.today()
|
|
|
|
|
|
def revoke_site_links_for_transport(
|
|
db: Session,
|
|
*,
|
|
tenant_no: str,
|
|
transport_id: str,
|
|
user_id: Optional[str],
|
|
) -> None:
|
|
"""调整运输时作废旧现场链接。"""
|
|
rows = (
|
|
db.query(PlTransportSiteLink)
|
|
.filter(
|
|
PlTransportSiteLink.tenant_no == tenant_no,
|
|
PlTransportSiteLink.transport_id == transport_id,
|
|
PlTransportSiteLink.del_flag == 0,
|
|
)
|
|
.all()
|
|
)
|
|
for row in rows:
|
|
row.del_flag = 1
|
|
row.update_by = user_id
|
|
if rows:
|
|
db.flush()
|
|
|
|
|
|
def sync_site_links_for_transport(
|
|
db: Session,
|
|
*,
|
|
tenant_no: str,
|
|
plan: PlPlan,
|
|
products: list[PlPlanProduct],
|
|
transport: PlTransport,
|
|
user_id: Optional[str],
|
|
dept_id: str,
|
|
) -> list[TransportSiteLinkResult]:
|
|
"""入库/出库安排运输:按产品生成现场链接(不写 db_inbound_outbound)。"""
|
|
business_type = _plan_type_to_business_type(plan.plan_type)
|
|
if not business_type:
|
|
return []
|
|
|
|
partner = resolve_partner_company(plan, plan.plan_type)
|
|
if not partner:
|
|
raise ValueError("无法解析往来单位,请检查合同供方/需方信息")
|
|
|
|
plan_date = _normalize_plan_date(plan)
|
|
license_plate = (transport.license_plate or plan.license_plate or "").strip()
|
|
plan_no = (plan.plan_no or "").strip()
|
|
|
|
results: list[TransportSiteLinkResult] = []
|
|
for product in products:
|
|
token = secrets.token_urlsafe(32)[:64]
|
|
row = PlTransportSiteLink(
|
|
id=generate_uuid(),
|
|
tenant_no=tenant_no,
|
|
transport_id=transport.id,
|
|
plan_id=plan.id,
|
|
plan_product_id=product.id,
|
|
site_access_token=token,
|
|
business_type=business_type,
|
|
partner_company=partner,
|
|
product_id=product.product_id,
|
|
product=product.product_name,
|
|
specification=product.model,
|
|
quantity=Decimal(str(_product_quantity(product))),
|
|
vehicle_no=license_plate,
|
|
plan_no=plan_no or None,
|
|
plan_date=plan_date,
|
|
remark=f"运输计划 {plan_no}",
|
|
create_by=user_id,
|
|
create_dept_id=dept_id,
|
|
)
|
|
db.add(row)
|
|
results.append(
|
|
TransportSiteLinkResult(
|
|
plan_product_id=product.id,
|
|
product_name=product.product_name or "",
|
|
site_link_id=row.id,
|
|
plan_no=plan_no,
|
|
business_type=business_type,
|
|
)
|
|
)
|
|
|
|
db.flush()
|
|
return results
|