Forráskód Böngészése

feat(backend): add public pound-qr endpoint by inventory id

Expose a read-only payload for the shared weighbridge QR card without auth.

Co-authored-by: Cursor <cursoragent@cursor.com>
wuzilong 1 hónapja
szülő
commit
87ed40512c

+ 14 - 0
backend/app/api/db/public_inventory.py

@@ -19,6 +19,7 @@ from app.models.db_models import DbInboundOutbound
 from app.models.pl_models import PlPlan, PlTransportDbLink
 from app.schemas.db.public_inventory import PublicInventoryFeedback, PublicInventoryPageRead
 from app.services.db.mappers import inventory_date_to_api
+from app.services.db.pound_qr_public import build_public_pound_qr_read
 
 router = APIRouter(prefix="/public/db/inventory", tags=["地磅-出入库现场公共"])
 
@@ -97,6 +98,19 @@ def _build_public_page(db: Session, inventory: DbInboundOutbound) -> PublicInven
     )
 
 
+@router.get("/{inventory_id}/pound-qr")
+def get_public_pound_qr(inventory_id: str, db: Session = Depends(get_db)):
+    row = (
+        db.query(DbInboundOutbound)
+        .filter(DbInboundOutbound.id == inventory_id, DbInboundOutbound.del_flag == 0)
+        .first()
+    )
+    if not row:
+        raise HTTPException(status_code=404, detail="链接无效或单据不存在")
+    read = build_public_pound_qr_read(row, quantity_unit="吨")
+    return success_response(read.model_dump(by_alias=True))
+
+
 @router.get("/{token}")
 def get_public_inventory(token: str, db: Session = Depends(get_db)):
     inventory = _get_inventory_by_token(db, token)

+ 14 - 0
backend/app/schemas/db/public_inventory.py

@@ -34,3 +34,17 @@ class PublicInventoryPageRead(BaseModel):
 class InventorySiteUrlRead(BaseModel):
     site_url: str = Field(alias="siteUrl")
     model_config = {"populate_by_name": True}
+
+
+class PublicPoundQrRead(BaseModel):
+    id: str
+    date: Optional[str] = None
+    business_type: str = Field(alias="businessType")
+    vehicle_no: str = Field(alias="vehicleNo")
+    partner_company: str = Field(alias="partnerCompany")
+    product: str
+    specification: Optional[str] = None
+    quantity: float
+    quantity_unit: str = Field(default="吨", alias="quantityUnit")
+    remarks: Optional[str] = None
+    model_config = {"populate_by_name": True}

+ 30 - 0
backend/app/services/db/pound_qr_public.py

@@ -0,0 +1,30 @@
+from __future__ import annotations
+
+from typing import Any, Optional
+
+from app.schemas.db.public_inventory import PublicPoundQrRead
+from app.services.db.mappers import inventory_date_to_api
+
+
+def build_pound_qr_label(business_type: str, partner_company: str) -> str:
+    bt = (business_type or "").strip()
+    pc = (partner_company or "").strip()
+    if bt and pc:
+        return f"{bt} · {pc}"
+    return bt or pc or "磅单"
+
+
+def build_public_pound_qr_read(row: Any, *, quantity_unit: Optional[str] = None) -> PublicPoundQrRead:
+    unit = (quantity_unit or "").strip() or "吨"
+    return PublicPoundQrRead(
+        id=row.id,
+        date=inventory_date_to_api(row.date) or None,
+        business_type=(row.business_type or "").strip() or "",
+        vehicle_no=(row.vehicle_no or "").strip(),
+        partner_company=(row.partner_company or "").strip(),
+        product=(row.product or "").strip(),
+        specification=(row.specification or None),
+        quantity=float(row.quantity or 0),
+        quantity_unit=unit,
+        remarks=(row.remark or None) if getattr(row, "remark", None) else None,
+    )

+ 50 - 0
backend/tests/test_public_db_pound_qr.py

@@ -0,0 +1,50 @@
+"""公开磅单二维码只读接口。"""
+from datetime import date
+from types import SimpleNamespace
+
+from fastapi.testclient import TestClient
+
+from app.main import app
+from app.services.db.pound_qr_public import (
+    build_pound_qr_label,
+    build_public_pound_qr_read,
+)
+
+client = TestClient(app)
+
+
+def test_build_pound_qr_label():
+    assert build_pound_qr_label("出库", "合肥德泽") == "出库 · 合肥德泽"
+    assert build_pound_qr_label("入库", "") == "入库"
+    assert build_pound_qr_label("", "安庆山峡") == "安庆山峡"
+
+
+def test_build_public_pound_qr_read_maps_fields():
+    row = SimpleNamespace(
+        id="inv-1",
+        date=date(2026, 9, 12),
+        business_type="出库",
+        vehicle_no="皖AM8516",
+        partner_company="合肥德泽化工科技有限公司",
+        product="30% 工业硫酸",
+        specification="30%",
+        quantity=10.0,
+        remark="注意安全",
+    )
+    read = build_public_pound_qr_read(row, quantity_unit="吨")
+    dump = read.model_dump(by_alias=True)
+    assert dump["id"] == "inv-1"
+    assert dump["date"] == "2026-09-12"
+    assert dump["businessType"] == "出库"
+    assert dump["vehicleNo"] == "皖AM8516"
+    assert dump["partnerCompany"] == "合肥德泽化工科技有限公司"
+    assert dump["product"] == "30% 工业硫酸"
+    assert dump["specification"] == "30%"
+    assert dump["quantity"] == 10.0
+    assert dump["quantityUnit"] == "吨"
+    assert dump["remarks"] == "注意安全"
+
+
+def test_pound_qr_missing_returns_404():
+    resp = client.get("/api/public/db/inventory/__missing_pound_qr_id__/pound-qr")
+    assert resp.status_code == 404