From 10183dabc27dee7be8ecb4beab11edb934122330 Mon Sep 17 00:00:00 2001 From: wuzilong <704541015@qq.com> Date: Sun, 13 Sep 2026 09:29:03 +0800 Subject: [PATCH] feat(backend): expose pound QR items on driver transport page Enrich inventory links with business type/partner and attach poundQrcodeItems for the public driver footer button. Co-authored-by: Cursor --- backend/app/api/pl/plan.py | 2 + backend/app/api/pl/public_transport.py | 12 ++++ backend/app/api/pl/transport.py | 29 ++++++++++ backend/app/schemas/pl/transport.py | 13 +++++ backend/app/services/db/pound_qr_public.py | 55 +++++++++++++++++++ .../app/services/pl_inventory_link_read.py | 4 ++ backend/tests/test_pound_qr_label_items.py | 5 ++ 7 files changed, 120 insertions(+) create mode 100644 backend/tests/test_pound_qr_label_items.py diff --git a/backend/app/api/pl/plan.py b/backend/app/api/pl/plan.py index 547870305..e047c95e5 100644 --- a/backend/app/api/pl/plan.py +++ b/backend/app/api/pl/plan.py @@ -2141,6 +2141,8 @@ def get_plan_arrange_info( plan_no=plan.plan_no or "", stop_type=link.stop_type, stop_id=link.stop_id, + business_type=(inventory.business_type if inventory else None), + partner_company=(inventory.partner_company if inventory else None), ) ) diff --git a/backend/app/api/pl/public_transport.py b/backend/app/api/pl/public_transport.py index 60c5c483b..29ab9a0b2 100644 --- a/backend/app/api/pl/public_transport.py +++ b/backend/app/api/pl/public_transport.py @@ -496,6 +496,17 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa ) ] + pound_items = [] + if plan: + from app.services.db.pound_qr_public import build_pound_qrcode_items_for_plan + + pound_items = build_pound_qrcode_items_for_plan( + db, + tenant_no=transport.tenant_no, + plan_id=plan.id, + transport_id=transport.id, + ) + return PublicTransportPageRead( plan_no=plan.plan_no if plan else transport.transport_no, plan_date=_format_plan_date(plan.plan_date if plan else None), @@ -527,6 +538,7 @@ def _build_public_page(db: Session, transport: PlTransport) -> PublicTransportPa feedback_time=transport.feedback_time, plan_voided=plan_voided, plan_archived=plan_archived, + pound_qrcode_items=pound_items, ) diff --git a/backend/app/api/pl/transport.py b/backend/app/api/pl/transport.py index 720d4aec0..78eb449bf 100644 --- a/backend/app/api/pl/transport.py +++ b/backend/app/api/pl/transport.py @@ -1002,6 +1002,25 @@ def arrange_transport( user_id=user.id, dept_id=user.dept_id or "", ) + inv_ids = [ + (item.db_inventory_id or "").strip() + for item in link_results + if (item.db_inventory_id or "").strip() + ] + inv_by_id: dict = {} + if inv_ids: + from app.models.db_models import DbInboundOutbound + + inv_rows = ( + db.query(DbInboundOutbound) + .filter( + DbInboundOutbound.id.in_(inv_ids), + DbInboundOutbound.tenant_no == tenant_no, + DbInboundOutbound.del_flag == 0, + ) + .all() + ) + inv_by_id = {row.id: row for row in inv_rows} inventory_records = [ build_transport_inventory_link_read( db, @@ -1011,6 +1030,16 @@ def arrange_transport( db_inventory_id=item.db_inventory_id, batch_no=item.batch_no, plan_no=item.plan_no, + business_type=( + inv_by_id[item.db_inventory_id].business_type + if item.db_inventory_id in inv_by_id + else None + ), + partner_company=( + inv_by_id[item.db_inventory_id].partner_company + if item.db_inventory_id in inv_by_id + else None + ), ) for item in link_results ] diff --git a/backend/app/schemas/pl/transport.py b/backend/app/schemas/pl/transport.py index 457e9e435..749adc989 100644 --- a/backend/app/schemas/pl/transport.py +++ b/backend/app/schemas/pl/transport.py @@ -95,6 +95,16 @@ class TransportInventoryLinkRead(BaseModel): plan_no: str = Field(alias="planNo") stop_type: Optional[str] = Field(default=None, alias="stopType") stop_id: Optional[str] = Field(default=None, alias="stopId") + business_type: Optional[str] = Field(default=None, alias="businessType") + partner_company: Optional[str] = Field(default=None, alias="partnerCompany") + model_config = {"populate_by_name": True} + + +class PublicPoundQrcodeItemRead(BaseModel): + inventory_id: str = Field(alias="inventoryId") + business_type: str = Field(alias="businessType") + partner_company: str = Field(alias="partnerCompany") + label: str model_config = {"populate_by_name": True} @@ -421,6 +431,9 @@ class PublicTransportPageRead(BaseModel): feedback_time: Optional[datetime] = Field(default=None, alias="feedbackTime") plan_voided: bool = Field(default=False, alias="planVoided") plan_archived: bool = Field(default=False, alias="planArchived") + pound_qrcode_items: list[PublicPoundQrcodeItemRead] = Field( + default_factory=list, alias="poundQrcodeItems" + ) model_config = {"populate_by_name": True} diff --git a/backend/app/services/db/pound_qr_public.py b/backend/app/services/db/pound_qr_public.py index af13d614b..9daaa91ef 100644 --- a/backend/app/services/db/pound_qr_public.py +++ b/backend/app/services/db/pound_qr_public.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Any, Optional from app.schemas.db.public_inventory import PublicPoundQrRead +from app.schemas.pl.transport import PublicPoundQrcodeItemRead from app.services.db.mappers import inventory_date_to_api @@ -28,3 +29,57 @@ def build_public_pound_qr_read(row: Any, *, quantity_unit: Optional[str] = None) quantity_unit=unit, remarks=(row.remark or None) if getattr(row, "remark", None) else None, ) + + +def build_pound_qrcode_items_for_plan( + db, + *, + tenant_no: str, + plan_id: str, + transport_id: str, +) -> list[PublicPoundQrcodeItemRead]: + from app.models.db_models import DbInboundOutbound + from app.models.pl_models import PlTransportDbLink + + links = ( + db.query(PlTransportDbLink) + .filter( + PlTransportDbLink.tenant_no == tenant_no, + PlTransportDbLink.plan_id == plan_id, + PlTransportDbLink.transport_id == transport_id, + PlTransportDbLink.del_flag == 0, + ) + .all() + ) + items: list[PublicPoundQrcodeItemRead] = [] + seen: set[str] = set() + for link in links: + inv_id = (link.db_inventory_id or "").strip() + if not inv_id or inv_id in seen: + continue + if not (link.db_purchase_plan_id or "").strip(): + continue + inv = ( + db.query(DbInboundOutbound) + .filter( + DbInboundOutbound.id == inv_id, + DbInboundOutbound.tenant_no == tenant_no, + DbInboundOutbound.del_flag == 0, + ) + .first() + ) + if not inv: + continue + seen.add(inv_id) + bt = (inv.business_type or "").strip() + pc = (inv.partner_company or "").strip() + items.append( + PublicPoundQrcodeItemRead( + inventory_id=inv.id, + business_type=bt, + partner_company=pc, + label=build_pound_qr_label(bt, pc), + ) + ) + return items + diff --git a/backend/app/services/pl_inventory_link_read.py b/backend/app/services/pl_inventory_link_read.py index 3a1a963f5..628908490 100644 --- a/backend/app/services/pl_inventory_link_read.py +++ b/backend/app/services/pl_inventory_link_read.py @@ -15,6 +15,8 @@ def build_transport_inventory_link_read( plan_no: str, stop_type: str | None = None, stop_id: str | None = None, + business_type: str | None = None, + partner_company: str | None = None, ) -> TransportInventoryLinkRead: del db # 现场链接已迁至 pl_transport_site_link return TransportInventoryLinkRead( @@ -26,4 +28,6 @@ def build_transport_inventory_link_read( plan_no=plan_no, stop_type=stop_type, stop_id=stop_id, + business_type=business_type, + partner_company=partner_company, ) diff --git a/backend/tests/test_pound_qr_label_items.py b/backend/tests/test_pound_qr_label_items.py new file mode 100644 index 000000000..29b42ccbd --- /dev/null +++ b/backend/tests/test_pound_qr_label_items.py @@ -0,0 +1,5 @@ +from app.services.db.pound_qr_public import build_pound_qr_label + + +def test_label_join(): + assert " · " in build_pound_qr_label("出库", "A")