|
@@ -117,6 +117,7 @@ from app.services.pl_plan_print_service import get_delivery_slip_print_context
|
|
|
from app.services.pl_plan_stop_service import (
|
|
from app.services.pl_plan_stop_service import (
|
|
|
attach_plan_stops_to_item,
|
|
attach_plan_stops_to_item,
|
|
|
collect_stop_qty_warnings,
|
|
collect_stop_qty_warnings,
|
|
|
|
|
+ collect_unique_delivery_date_strings,
|
|
|
load_plan_stops_grouped,
|
|
load_plan_stops_grouped,
|
|
|
replace_plan_stops,
|
|
replace_plan_stops,
|
|
|
sync_plan_legacy_from_stops,
|
|
sync_plan_legacy_from_stops,
|
|
@@ -383,6 +384,8 @@ def _filters_from_params(params: dict, *, db: Session, tenant_no: str) -> list:
|
|
|
license_plate=_param_get(params, "licensePlate", "license_plate"),
|
|
license_plate=_param_get(params, "licensePlate", "license_plate"),
|
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
|
|
|
+ delivery_time_from=_param_get(params, "deliveryTimeFrom", "delivery_time_from"),
|
|
|
|
|
+ delivery_time_to=_param_get(params, "deliveryTimeTo", "delivery_time_to"),
|
|
|
cert_upload_status=_param_get(params, "certUploadStatus", "cert_upload_status"),
|
|
cert_upload_status=_param_get(params, "certUploadStatus", "cert_upload_status"),
|
|
|
hazard_cert_ready=_param_get(params, "hazardCertReady", "hazard_cert_ready"),
|
|
hazard_cert_ready=_param_get(params, "hazardCertReady", "hazard_cert_ready"),
|
|
|
hazard_cert_ready_in=_param_get(
|
|
hazard_cert_ready_in=_param_get(
|
|
@@ -431,6 +434,12 @@ def list_plans(
|
|
|
license_plate: Optional[str] = Query(default=None, alias="licensePlate", description="车牌号"),
|
|
license_plate: Optional[str] = Query(default=None, alias="licensePlate", description="车牌号"),
|
|
|
plan_date_from: Optional[date] = Query(default=None, alias="planDateFrom", description="计划日期开始"),
|
|
plan_date_from: Optional[date] = Query(default=None, alias="planDateFrom", description="计划日期开始"),
|
|
|
plan_date_to: Optional[date] = Query(default=None, alias="planDateTo", description="计划日期结束"),
|
|
plan_date_to: Optional[date] = Query(default=None, alias="planDateTo", description="计划日期结束"),
|
|
|
|
|
+ delivery_time_from: Optional[date] = Query(
|
|
|
|
|
+ default=None, alias="deliveryTimeFrom", description="送货时间开始"
|
|
|
|
|
+ ),
|
|
|
|
|
+ delivery_time_to: Optional[date] = Query(
|
|
|
|
|
+ default=None, alias="deliveryTimeTo", description="送货时间结束"
|
|
|
|
|
+ ),
|
|
|
has_hazard_product: Optional[int] = Query(
|
|
has_hazard_product: Optional[int] = Query(
|
|
|
default=None,
|
|
default=None,
|
|
|
alias="hasHazardProduct",
|
|
alias="hasHazardProduct",
|
|
@@ -505,6 +514,8 @@ def list_plans(
|
|
|
licensePlate=license_plate,
|
|
licensePlate=license_plate,
|
|
|
planDateFrom=plan_date_from,
|
|
planDateFrom=plan_date_from,
|
|
|
planDateTo=plan_date_to,
|
|
planDateTo=plan_date_to,
|
|
|
|
|
+ deliveryTimeFrom=delivery_time_from,
|
|
|
|
|
+ deliveryTimeTo=delivery_time_to,
|
|
|
certUploadStatus=cert_upload_status,
|
|
certUploadStatus=cert_upload_status,
|
|
|
hazardCertReady=hazard_cert_ready,
|
|
hazardCertReady=hazard_cert_ready,
|
|
|
)
|
|
)
|
|
@@ -633,6 +644,7 @@ PLAN_EXPORT_COLUMNS = [
|
|
|
ExportColumn(title="计划编号", field="planNo"),
|
|
ExportColumn(title="计划编号", field="planNo"),
|
|
|
ExportColumn(title="跟进状态", field="followStatus"),
|
|
ExportColumn(title="跟进状态", field="followStatus"),
|
|
|
ExportColumn(title="计划日期", field="planDate"),
|
|
ExportColumn(title="计划日期", field="planDate"),
|
|
|
|
|
+ ExportColumn(title="送货时间", field="deliveryTimes"),
|
|
|
ExportColumn(title="单据类型", field="planType"),
|
|
ExportColumn(title="单据类型", field="planType"),
|
|
|
ExportColumn(title="供方", field="supplierName"),
|
|
ExportColumn(title="供方", field="supplierName"),
|
|
|
ExportColumn(title="需方", field="customerName"),
|
|
ExportColumn(title="需方", field="customerName"),
|
|
@@ -703,6 +715,8 @@ class PlanExportBody(BaseModel):
|
|
|
license_plate: Optional[str] = Field(default=None, alias="licensePlate")
|
|
license_plate: Optional[str] = Field(default=None, alias="licensePlate")
|
|
|
plan_date_from: Optional[date] = Field(default=None, alias="planDateFrom")
|
|
plan_date_from: Optional[date] = Field(default=None, alias="planDateFrom")
|
|
|
plan_date_to: Optional[date] = Field(default=None, alias="planDateTo")
|
|
plan_date_to: Optional[date] = Field(default=None, alias="planDateTo")
|
|
|
|
|
+ delivery_time_from: Optional[date] = Field(default=None, alias="deliveryTimeFrom")
|
|
|
|
|
+ delivery_time_to: Optional[date] = Field(default=None, alias="deliveryTimeTo")
|
|
|
has_hazard_product: Optional[int] = Field(default=None, alias="hasHazardProduct")
|
|
has_hazard_product: Optional[int] = Field(default=None, alias="hasHazardProduct")
|
|
|
cert_upload_status: Optional[str] = Field(default=None, alias="certUploadStatus")
|
|
cert_upload_status: Optional[str] = Field(default=None, alias="certUploadStatus")
|
|
|
hazard_cert_ready: Optional[int] = Field(default=None, alias="hazardCertReady")
|
|
hazard_cert_ready: Optional[int] = Field(default=None, alias="hazardCertReady")
|
|
@@ -771,6 +785,8 @@ def export_plans(
|
|
|
sheet_title = "计划归档"
|
|
sheet_title = "计划归档"
|
|
|
filename_stem = f"计划归档_{date_str}"
|
|
filename_stem = f"计划归档_{date_str}"
|
|
|
else:
|
|
else:
|
|
|
|
|
+ plan_ids = [plan.id for plan in plans]
|
|
|
|
|
+ stops_by_plan = load_plan_stops_grouped(db, tenant_no, plan_ids)
|
|
|
items = []
|
|
items = []
|
|
|
for plan in plans:
|
|
for plan in plans:
|
|
|
data = PlanWithProducts.model_validate(plan).model_dump(by_alias=True)
|
|
data = PlanWithProducts.model_validate(plan).model_dump(by_alias=True)
|
|
@@ -778,6 +794,9 @@ def export_plans(
|
|
|
data["planDate"] = str(data["planDate"])[:10]
|
|
data["planDate"] = str(data["planDate"])[:10]
|
|
|
if data.get("erpEntered") is not None:
|
|
if data.get("erpEntered") is not None:
|
|
|
data["erpEntered"] = "是" if int(data["erpEntered"]) else "否"
|
|
data["erpEntered"] = "是" if int(data["erpEntered"]) else "否"
|
|
|
|
|
+ _load_read, delivery_reads = stops_by_plan.get(plan.id, (None, []))
|
|
|
|
|
+ times = collect_unique_delivery_date_strings(delivery_reads)
|
|
|
|
|
+ data["deliveryTimes"] = " / ".join(times) if times else ""
|
|
|
items.append(data)
|
|
items.append(data)
|
|
|
cols = filter_export_columns(PLAN_EXPORT_COLUMNS, body.columns)
|
|
cols = filter_export_columns(PLAN_EXPORT_COLUMNS, body.columns)
|
|
|
sheet_title = "计划列表"
|
|
sheet_title = "计划列表"
|
|
@@ -884,6 +903,8 @@ def list_contract_gaps(
|
|
|
),
|
|
),
|
|
|
plan_date_from: Optional[date] = Query(default=None, alias="planDateFrom"),
|
|
plan_date_from: Optional[date] = Query(default=None, alias="planDateFrom"),
|
|
|
plan_date_to: Optional[date] = Query(default=None, alias="planDateTo"),
|
|
plan_date_to: Optional[date] = Query(default=None, alias="planDateTo"),
|
|
|
|
|
+ delivery_time_from: Optional[date] = Query(default=None, alias="deliveryTimeFrom"),
|
|
|
|
|
+ delivery_time_to: Optional[date] = Query(default=None, alias="deliveryTimeTo"),
|
|
|
plan_type: Optional[str] = Query(default=None, alias="planType"),
|
|
plan_type: Optional[str] = Query(default=None, alias="planType"),
|
|
|
follow_status: Optional[str] = Query(default=None, alias="followStatus"),
|
|
follow_status: Optional[str] = Query(default=None, alias="followStatus"),
|
|
|
q: Optional[str] = Query(
|
|
q: Optional[str] = Query(
|
|
@@ -901,6 +922,8 @@ def list_contract_gaps(
|
|
|
customerKeyword=customer_keyword,
|
|
customerKeyword=customer_keyword,
|
|
|
planDateFrom=plan_date_from,
|
|
planDateFrom=plan_date_from,
|
|
|
planDateTo=plan_date_to,
|
|
planDateTo=plan_date_to,
|
|
|
|
|
+ deliveryTimeFrom=delivery_time_from,
|
|
|
|
|
+ deliveryTimeTo=delivery_time_to,
|
|
|
planType=plan_type,
|
|
planType=plan_type,
|
|
|
followStatus=follow_status,
|
|
followStatus=follow_status,
|
|
|
)
|
|
)
|
|
@@ -915,6 +938,8 @@ def list_contract_gaps(
|
|
|
customer_keyword=_param_get(params, "customerKeyword", "customer_keyword"),
|
|
customer_keyword=_param_get(params, "customerKeyword", "customer_keyword"),
|
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
|
|
|
+ delivery_time_from=_param_get(params, "deliveryTimeFrom", "delivery_time_from"),
|
|
|
|
|
+ delivery_time_to=_param_get(params, "deliveryTimeTo", "delivery_time_to"),
|
|
|
plan_type=_param_get(params, "planType", "plan_type"),
|
|
plan_type=_param_get(params, "planType", "plan_type"),
|
|
|
plan_type_in=_param_get(params, "planTypeIn", "plan_type_in"),
|
|
plan_type_in=_param_get(params, "planTypeIn", "plan_type_in"),
|
|
|
follow_status=_param_get(params, "followStatus", "followStatusIn", "follow_status"),
|
|
follow_status=_param_get(params, "followStatus", "followStatusIn", "follow_status"),
|
|
@@ -929,6 +954,7 @@ def list_contract_gaps(
|
|
|
CONTRACT_GAP_EXPORT_COLUMNS = [
|
|
CONTRACT_GAP_EXPORT_COLUMNS = [
|
|
|
ExportColumn(title="计划编号", field="planNo"),
|
|
ExportColumn(title="计划编号", field="planNo"),
|
|
|
ExportColumn(title="计划日期", field="planDate"),
|
|
ExportColumn(title="计划日期", field="planDate"),
|
|
|
|
|
+ ExportColumn(title="送货时间", field="deliveryTimes"),
|
|
|
ExportColumn(title="单据类型", field="planType"),
|
|
ExportColumn(title="单据类型", field="planType"),
|
|
|
ExportColumn(title="跟进状态", field="followStatus"),
|
|
ExportColumn(title="跟进状态", field="followStatus"),
|
|
|
ExportColumn(title="供方", field="supplierName"),
|
|
ExportColumn(title="供方", field="supplierName"),
|
|
@@ -943,6 +969,8 @@ class ContractGapExportBody(BaseModel):
|
|
|
customer_keyword: Optional[str] = Field(default=None, alias="customerKeyword")
|
|
customer_keyword: Optional[str] = Field(default=None, alias="customerKeyword")
|
|
|
plan_date_from: Optional[date] = Field(default=None, alias="planDateFrom")
|
|
plan_date_from: Optional[date] = Field(default=None, alias="planDateFrom")
|
|
|
plan_date_to: Optional[date] = Field(default=None, alias="planDateTo")
|
|
plan_date_to: Optional[date] = Field(default=None, alias="planDateTo")
|
|
|
|
|
+ delivery_time_from: Optional[date] = Field(default=None, alias="deliveryTimeFrom")
|
|
|
|
|
+ delivery_time_to: Optional[date] = Field(default=None, alias="deliveryTimeTo")
|
|
|
q: Optional[str] = None
|
|
q: Optional[str] = None
|
|
|
ids: Optional[List[str]] = None
|
|
ids: Optional[List[str]] = None
|
|
|
columns: Optional[List[str]] = None
|
|
columns: Optional[List[str]] = None
|
|
@@ -969,6 +997,12 @@ def export_contract_gaps(
|
|
|
customer_keyword=_param_get(params, "customerKeyword", "customer_keyword"),
|
|
customer_keyword=_param_get(params, "customerKeyword", "customer_keyword"),
|
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
plan_date_from=_param_get(params, "planDateFrom", "plan_date_from"),
|
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
plan_date_to=_param_get(params, "planDateTo", "plan_date_to"),
|
|
|
|
|
+ delivery_time_from=_param_get(
|
|
|
|
|
+ params, "deliveryTimeFrom", "delivery_time_from"
|
|
|
|
|
+ ),
|
|
|
|
|
+ delivery_time_to=_param_get(
|
|
|
|
|
+ params, "deliveryTimeTo", "delivery_time_to"
|
|
|
|
|
+ ),
|
|
|
plan_type=_param_get(params, "planType", "plan_type"),
|
|
plan_type=_param_get(params, "planType", "plan_type"),
|
|
|
plan_type_in=_param_get(params, "planTypeIn", "plan_type_in"),
|
|
plan_type_in=_param_get(params, "planTypeIn", "plan_type_in"),
|
|
|
follow_status=_param_get(
|
|
follow_status=_param_get(
|
|
@@ -995,6 +1029,9 @@ def export_contract_gaps(
|
|
|
data["gapType"] = "仅缺需方合同"
|
|
data["gapType"] = "仅缺需方合同"
|
|
|
else:
|
|
else:
|
|
|
data["gapType"] = ""
|
|
data["gapType"] = ""
|
|
|
|
|
+ times = data.get("deliveryTimes") or []
|
|
|
|
|
+ if isinstance(times, list):
|
|
|
|
|
+ data["deliveryTimes"] = " / ".join(str(t) for t in times) if times else ""
|
|
|
for k, v in list(data.items()):
|
|
for k, v in list(data.items()):
|
|
|
if hasattr(v, "isoformat"):
|
|
if hasattr(v, "isoformat"):
|
|
|
data[k] = str(v)[:19]
|
|
data[k] = str(v)[:19]
|