From 0e3df1f39dc487eeae87851abb30e431bebc1d61 Mon Sep 17 00:00:00 2001 From: wuzilong <704541015@qq.com> Date: Sat, 12 Sep 2026 21:20:55 +0800 Subject: [PATCH] feat(pl): expose deliveryTimes on plan list and contract-gap schemas Populate from delivery stops during attach/gap row build. Co-authored-by: Cursor --- backend/app/schemas/pl/plan.py | 10 ++++++++++ backend/app/services/pl_plan_contract_gap.py | 2 ++ backend/app/services/pl_plan_stop_service.py | 1 + 3 files changed, 13 insertions(+) diff --git a/backend/app/schemas/pl/plan.py b/backend/app/schemas/pl/plan.py index c259036c0..6ebeface1 100644 --- a/backend/app/schemas/pl/plan.py +++ b/backend/app/schemas/pl/plan.py @@ -420,6 +420,11 @@ class PlanWithProducts(PlanRead): alias="deliveryCustomerSummary", description="送货客户摘要(列表展示)", ) + delivery_times: list[str] = Field( + default_factory=list, + alias="deliveryTimes", + description="送货段送货时间去重升序 YYYY-MM-DD(列表展示)", + ) warnings: list[str] = Field(default_factory=list, description="保存告警(如数量不平衡)") can_copy_to_driver: bool = Field( default=False, @@ -705,6 +710,11 @@ class PlanContractGapRead(BaseModel): products: list[PlanProductRead] = Field(default_factory=list, description="产品明细") load: Optional["PlanLoadRead"] = Field(default=None, description="装货段") deliveries: list["PlanDeliveryRead"] = Field(default_factory=list, alias="deliveries", description="送货段列表") + delivery_times: list[str] = Field( + default_factory=list, + alias="deliveryTimes", + description="送货段送货时间去重升序 YYYY-MM-DD(列表展示)", + ) model_config = {"populate_by_name": True, "from_attributes": True} diff --git a/backend/app/services/pl_plan_contract_gap.py b/backend/app/services/pl_plan_contract_gap.py index dfea99b31..6441387a4 100644 --- a/backend/app/services/pl_plan_contract_gap.py +++ b/backend/app/services/pl_plan_contract_gap.py @@ -23,6 +23,7 @@ from app.schemas.pl.plan import ( PlanProductRead, ) from app.services.pl.plan_list_filters import build_plan_column_filters +from app.services.pl_plan_stop_service import collect_unique_delivery_date_strings from app.services.pl_data_scope import apply_pl_scope from app.services.pl_internal_customer import INTERNAL_CUSTOMER_NAMES, is_internal_customer_name from app.services.pl_plan_service import ( @@ -272,6 +273,7 @@ def build_plan_contract_gap_read( products=list(products or []), load=load_read, deliveries=deliveries, + deliveryTimes=collect_unique_delivery_date_strings(deliveries), ) diff --git a/backend/app/services/pl_plan_stop_service.py b/backend/app/services/pl_plan_stop_service.py index 9ff5b8c3a..521e6d5dc 100644 --- a/backend/app/services/pl_plan_stop_service.py +++ b/backend/app/services/pl_plan_stop_service.py @@ -470,6 +470,7 @@ def attach_plan_stops_to_item( plan_item.pickup_address = load_read.address if delivery_reads and (delivery_reads[0].address or "").strip(): plan_item.destination_address = delivery_reads[0].address + plan_item.delivery_times = collect_unique_delivery_date_strings(delivery_reads) def uses_multi_stop_payload(load: Optional[PlanLoadBody], deliveries: Optional[list[PlanDeliveryBody]]) -> bool: