Files
shanxia2.0/backend/app/services/pl_child_references.py
T

75 lines
4.6 KiB
Python

"""Deletion guards for stable logistics child identities."""
import json
from fastapi import HTTPException
from sqlalchemy import inspect
from app.models import pl_models as m
def _exists(db, model, tenant_no, *filters):
return db.query(model.id).filter(model.tenant_no == tenant_no, model.del_flag == 0, *filters).first() is not None
def assert_stop_products_removable(db, tenant_no, plan_id, stop_type, stop_id, rows):
if not rows:
return
ids = {row.id for row in rows}
if any(any(getattr(row, field, None) is not None for field in
('inbound_qty', 'inbound_price', 'inbound_amount', 'outbound_qty', 'outbound_price', 'outbound_amount'))
or bool(getattr(row, 'archive_remark', None)) for row in rows):
raise HTTPException(409, '段产品已有归档数据,不能移除')
if _exists(db, m.PlPlanProductBrandQty, tenant_no, m.PlPlanProductBrandQty.stop_product_id.in_(ids)):
raise HTTPException(409, '段产品已有归档品牌,不能移除')
# Older installations may not have enabled the optional snapshot table.
from app.models.pl_mobile_stop_meta import PlPlanStopProductMeta
if inspect(db.connection()).has_table(PlPlanStopProductMeta.__tablename__):
if _exists(db, PlPlanStopProductMeta, tenant_no, PlPlanStopProductMeta.stop_product_id.in_(ids)):
raise HTTPException(409, '段产品已有业务快照,不能移除')
for model in (m.PlTransportDriverStopFeedback, m.PlTransportSiteStopFeedback):
feedbacks = db.query(model).filter(model.tenant_no == tenant_no, model.plan_id == plan_id,
model.stop_type == stop_type, model.stop_id == stop_id,
model.del_flag == 0).all()
for feedback in feedbacks:
try:
values = json.loads(feedback.product_feedbacks or '[]')
except (ValueError, TypeError):
raise HTTPException(409, '停靠段回传数据无法核对,不能移除产品')
if not isinstance(values, list):
raise HTTPException(409, '停靠段回传数据无法核对,不能移除产品')
if any(isinstance(value, dict) and (value.get('stopProductId') or value.get('stop_product_id')) in ids for value in values):
raise HTTPException(409, '段产品已有司机或现场回传,不能移除')
ppids = {row.plan_product_id for row in rows if row.plan_product_id}
if ppids and _exists(db, m.PlTransportDbLink, tenant_no,
m.PlTransportDbLink.plan_id == plan_id, m.PlTransportDbLink.stop_type == stop_type,
m.PlTransportDbLink.stop_id == stop_id, m.PlTransportDbLink.plan_product_id.in_(ppids)):
raise HTTPException(409, '段产品已关联地磅单,不能移除')
def assert_stop_removable(db, tenant_no, plan_id, stop_type, stop_id, rows):
assert_stop_products_removable(db, tenant_no, plan_id, stop_type, stop_id, rows)
for model in (m.PlTransportDriverStopFeedback, m.PlTransportSiteStopFeedback, m.PlTransportDbLink):
if _exists(db, model, tenant_no, model.plan_id == plan_id, model.stop_type == stop_type, model.stop_id == stop_id):
raise HTTPException(409, '停靠段已有回传或地磅关联,不能移除')
def assert_plan_products_removable(db, tenant_no, plan_id, rows, ignored_stop_ids=None):
if not rows:
return
ids = {row.id for row in rows}
for model in (m.PlPlanLoadProduct, m.PlPlanDeliveryProduct, m.PlPlanProductBrandQty,
m.PlInboundOrderItem, m.PlOutboundOrderItem, m.PlTransportProductFeedback,
m.PlTransportProductBrandQty, m.PlTransportDbLink, m.PlTransportSiteLink):
filters = [model.plan_product_id.in_(ids)]
if model in (m.PlPlanLoadProduct, m.PlPlanDeliveryProduct) and ignored_stop_ids:
filters.append(~model.id.in_(ignored_stop_ids))
if _exists(db, model, tenant_no, *filters):
raise HTTPException(409, '计划产品已有段产品、归档、回传或出入库关联,不能移除')
if any(any(getattr(row, name, None) is not None for name in
('inbound_qty', 'outbound_qty')) for row in rows):
raise HTTPException(409, '计划产品已有归档数量,不能移除')
product_ids = {row.product_id for row in rows}
if _exists(db, m.PlInventoryTransaction, tenant_no, m.PlInventoryTransaction.plan_id == plan_id,
m.PlInventoryTransaction.product_id.in_(product_ids)):
raise HTTPException(409, '计划产品已有库存流水,不能移除')