"""地磅单联动业务逻辑 — 迁移自 simple-dibang-xiaoshou weighing._process_weighing_business_logic。""" from __future__ import annotations from datetime import datetime from sqlalchemy import or_ from sqlalchemy.orm import Session from app.models.db_models import DbInboundOutbound, DbPurchasePlan, DbWeighingSlip def _has_weight_time(value: datetime | str | None) -> bool: if value is None: return False if isinstance(value, datetime): return True return bool(str(value).strip()) def process_weighing_business_logic(db: Session, weighing: DbWeighingSlip) -> None: """ 处理地磅单的业务逻辑: 1. 更新计划单的已执行量(单位:kg) 2. 更新出入库单的状态 3. 重新计算地磅单的 executed_quantity(按创建时间顺序累计) """ plan_ids_to_process: set[str] = set() inventory_ids_to_process: set[str] = set() if weighing.purchase_plan_id: plan_ids_to_process.add(weighing.purchase_plan_id) if weighing.inbound_outbound_id: inventory_ids_to_process.add(weighing.inbound_outbound_id) if weighing.plan_no: plans = ( db.query(DbPurchasePlan) .filter( DbPurchasePlan.plan_no == weighing.plan_no, DbPurchasePlan.del_flag == 0, DbPurchasePlan.tenant_no == weighing.tenant_no, ) .all() ) for plan in plans: plan_ids_to_process.add(plan.id) for plan_id in plan_ids_to_process: plan = db.query(DbPurchasePlan).filter(DbPurchasePlan.id == plan_id).one_or_none() if not plan: continue plan_weighings = ( db.query(DbWeighingSlip) .filter( DbWeighingSlip.is_voided == 0, DbWeighingSlip.del_flag == 0, DbWeighingSlip.tenant_no == plan.tenant_no, or_( DbWeighingSlip.plan_no == plan.plan_no, DbWeighingSlip.purchase_plan_id == plan.id, ), ) .order_by(DbWeighingSlip.create_time.asc()) .all() ) total_executed = sum(w.net_weight for w in plan_weighings if w.net_weight) plan.executed_quantity = total_executed planned_quantity_kg = plan.planned_quantity * 1000 if total_executed >= planned_quantity_kg: plan.execution_status = "已入库" if plan.business_type == "入库" else "已出库" elif total_executed > 0: plan.execution_status = "入库中" if plan.business_type == "入库" else "出库中" else: plan.execution_status = "待入库" if plan.business_type == "入库" else "待出库" db.commit() db.refresh(plan) cumulative_executed = 0.0 for slip in plan_weighings: cumulative_executed += slip.net_weight if slip.net_weight else 0.0 slip.executed_quantity = cumulative_executed db.commit() for inventory_id in inventory_ids_to_process: inventory = ( db.query(DbInboundOutbound) .filter(DbInboundOutbound.id == inventory_id) .one_or_none() ) if not inventory: continue related_weighings = ( db.query(DbWeighingSlip) .filter( DbWeighingSlip.inbound_outbound_id == inventory_id, DbWeighingSlip.is_voided == 0, DbWeighingSlip.del_flag == 0, ) .all() ) all_complete = ( len(related_weighings) > 0 and all( _has_weight_time(w.gross_weight_time) and _has_weight_time(w.tare_weight_time) for w in related_weighings ) ) if all_complete: inventory.status = "已完成" else: inventory.status = ( "待入库" if inventory.business_type == "入库" else "待出库" ) db.commit() db.refresh(inventory)