Files
shanxia2.0/backend/app/services/db/weighing_logic.py
T
wuzilongandCursor bde19c0644 feat: 锁定执行中计划并按装卸明细差量归档库存,补齐派车日历数量与酸碱类型。
执行中的运输计划不再随意改单;库存流水记到装卸产品明细;手工派车日历区分酸碱并记录数量。同时收紧合同附件与子表的差量保存,并清理已废弃的 bak 备份目录。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-29 07:59:53 +08:00

134 lines
4.3 KiB
Python

"""地磅单联动业务逻辑 — 迁移自 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 weighing_weights_complete(gross_weight, gross_time, tare_weight, tare_time) -> bool:
"""毛重、皮重都大于 0,且各自有时间,才算过磅完成。"""
return (
(gross_weight or 0) > 0
and _has_weight_time(gross_time)
and (tare_weight or 0) > 0
and _has_weight_time(tare_time)
)
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(
weighing_weights_complete(
w.gross_weight, w.gross_weight_time, w.tare_weight, 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)