|
|
@@ -128,6 +128,7 @@ from app.services.pl_plan_service import (
|
|
|
apply_plan_site_feedback,
|
|
|
apply_vehicle_prefill_to_plan,
|
|
|
assert_contract_selectable_for_plan,
|
|
|
+ apply_plan_product_fields,
|
|
|
build_plan_product,
|
|
|
calc_plan_total_amount,
|
|
|
clear_draft_transport_for_plan,
|
|
|
@@ -1640,16 +1641,15 @@ def update_plan(
|
|
|
|
|
|
plan_type = payload.plan_type or plan.plan_type
|
|
|
|
|
|
- # 更新产品明细
|
|
|
+ # 更新产品明细(按 id upsert,保持 pl_plan_product.id 稳定)
|
|
|
if payload.products is not None:
|
|
|
- existing_products = (
|
|
|
+ existing_all = (
|
|
|
db.query(PlPlanProduct)
|
|
|
- .filter(
|
|
|
- PlPlanProduct.plan_id == id,
|
|
|
- PlPlanProduct.del_flag == 0,
|
|
|
- )
|
|
|
+ .filter(PlPlanProduct.plan_id == id)
|
|
|
.all()
|
|
|
)
|
|
|
+ existing_all_by_id = {row.id: row for row in existing_all}
|
|
|
+ existing_products = [row for row in existing_all if row.del_flag == 0]
|
|
|
old_hazard_product_ids = collect_hazard_product_ids(db, tenant_no, existing_products)
|
|
|
cert_by_product_id = {
|
|
|
row.product_id: (
|
|
|
@@ -1660,11 +1660,7 @@ def update_plan(
|
|
|
for row in existing_products
|
|
|
}
|
|
|
|
|
|
- db.query(PlPlanProduct).filter(
|
|
|
- PlPlanProduct.plan_id == id,
|
|
|
- PlPlanProduct.del_flag == 0,
|
|
|
- ).update({"del_flag": 1})
|
|
|
-
|
|
|
+ kept_ids: set[str] = set()
|
|
|
plan_products: list[PlPlanProduct] = []
|
|
|
for idx, prod in enumerate(payload.products):
|
|
|
is_toxic, is_explosive = resolve_hazard_flags_from_crm(
|
|
|
@@ -1689,17 +1685,36 @@ def update_plan(
|
|
|
"legal_use_cert_url": legal_use_cert,
|
|
|
}
|
|
|
)
|
|
|
- pp = build_plan_product(
|
|
|
- tenant_no=tenant_no,
|
|
|
- plan_id=id,
|
|
|
- plan_type=plan_type,
|
|
|
- prod=prod_payload,
|
|
|
- order_num=idx,
|
|
|
- user_id=user.id,
|
|
|
- dept_id=user.dept_id,
|
|
|
- )
|
|
|
- db.add(pp)
|
|
|
- plan_products.append(pp)
|
|
|
+ row_id = (prod.id or "").strip() or None
|
|
|
+ existing = existing_all_by_id.get(row_id) if row_id else None
|
|
|
+ if existing is not None:
|
|
|
+ apply_plan_product_fields(
|
|
|
+ existing,
|
|
|
+ plan_type=plan_type,
|
|
|
+ prod=prod_payload,
|
|
|
+ order_num=idx,
|
|
|
+ user_id=user.id,
|
|
|
+ )
|
|
|
+ kept_ids.add(existing.id)
|
|
|
+ plan_products.append(existing)
|
|
|
+ else:
|
|
|
+ pp = build_plan_product(
|
|
|
+ tenant_no=tenant_no,
|
|
|
+ plan_id=id,
|
|
|
+ plan_type=plan_type,
|
|
|
+ prod=prod_payload,
|
|
|
+ order_num=idx,
|
|
|
+ user_id=user.id,
|
|
|
+ dept_id=user.dept_id,
|
|
|
+ )
|
|
|
+ db.add(pp)
|
|
|
+ kept_ids.add(pp.id)
|
|
|
+ plan_products.append(pp)
|
|
|
+
|
|
|
+ for row in existing_products:
|
|
|
+ if row.id not in kept_ids:
|
|
|
+ row.del_flag = 1
|
|
|
+ row.update_by = user.id
|
|
|
|
|
|
new_hazard_product_ids = collect_hazard_product_ids(db, tenant_no, payload.products)
|
|
|
if old_hazard_product_ids != new_hazard_product_ids:
|