75 lines
4.6 KiB
Python
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, '计划产品已有库存流水,不能移除')
|