feat: 报工提交和审核刷新超额快照

This commit is contained in:
souplearn
2026-07-25 20:44:22 +08:00
parent 1ed48314be
commit b203b782de
4 changed files with 356 additions and 5 deletions
+2
View File
@@ -41,6 +41,7 @@ from app.services.misc_work import is_misc_product
from app.services.mold_locks import release_session_locks
from app.services.report_allocations import refresh_report_allocations
from app.services.report_lifecycle import purge_expired_voided_reports
from app.services.report_over_limit import CHECK_SOURCE_SUBMIT, refresh_report_over_limit_snapshot
from app.services.reporting_window import REPORTING_EXPIRED_DETAIL, is_reporting_expired
from app.services.serializers import equipment_option, product_option, report_out
from app.services.work_schedule import get_work_schedule_config
@@ -460,6 +461,7 @@ def submit_report(
db.add(report)
db.flush()
refresh_report_allocations(db, report, schedule=schedule, commit=False)
refresh_report_over_limit_snapshot(db, report, source=CHECK_SOURCE_SUBMIT, checked_at=submitted_at)
db.commit()
saved = _get_report_or_404(db, report.id)
+2
View File
@@ -36,6 +36,7 @@ from app.services.report_lifecycle import (
purge_expired_voided_reports,
restore_voided_report,
)
from app.services.report_over_limit import CHECK_SOURCE_REVIEW, refresh_report_over_limit_snapshot
from app.services.serializers import report_out
from app.services.work_schedule import WorkScheduleConfig, get_work_schedule_config
from app.timezone import now
@@ -532,6 +533,7 @@ def approve_report(
_apply_metrics(report, schedule)
refresh_report_allocations(db, report, schedule=schedule, commit=False)
reviewed_at = now()
refresh_report_over_limit_snapshot(db, report, source=CHECK_SOURCE_REVIEW, checked_at=reviewed_at)
was_pending = report.status == ReportStatus.pending
report.status = ReportStatus.approved
report.reviewer_phone = user.phone
+55 -3
View File
@@ -3,6 +3,7 @@ from __future__ import annotations
import logging
import re
from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal, InvalidOperation, ROUND_HALF_UP
from sqlalchemy import func, select, text
@@ -12,6 +13,7 @@ from sqlalchemy.orm import Session
from app.models import Product, ProductionReport, ProductionReportItem, ReportStatus
from app.services.cleaning import is_cleaning_item
from app.services.misc_work import is_misc_item
from app.timezone import now
logger = logging.getLogger(__name__)
@@ -288,9 +290,7 @@ def evaluate_report_item_over_limit(
current_order = parse_process_order(getattr(item, "process_name", None))
if current_order is None:
return OverLimitResult(
status=OVER_LIMIT_STATUS_UNCHECKABLE,
over_limit_type=OVER_LIMIT_TYPE_UNCHECKABLE,
reason="非数字工序,无法校验超额",
status=OVER_LIMIT_STATUS_NOT_CHECKED,
batch_no=batch_no,
current_report_qty=report_qty,
)
@@ -383,3 +383,55 @@ def evaluate_report_item_over_limit(
current_cumulative_qty=current_cumulative_qty,
current_report_qty=report_qty,
)
def _apply_result_to_item(
item: ProductionReportItem,
result: OverLimitResult,
*,
source: str,
checked_at: datetime,
) -> None:
item.over_limit_status = result.status
item.over_limit_type = result.over_limit_type
item.over_limit_reason = result.reason
item.over_limit_checked_at = checked_at
item.over_limit_check_source = source
item.over_limit_batch_no = result.batch_no
item.over_limit_product_gross_weight_kg = result.product_gross_weight_kg
item.over_limit_issued_weight_kg = result.issued_weight_kg
item.over_limit_max_reportable_qty = result.max_reportable_qty
item.over_limit_previous_good_qty = result.previous_good_qty
item.over_limit_current_cumulative_qty = result.current_cumulative_qty
item.over_limit_current_report_qty = result.current_report_qty
def refresh_report_over_limit_snapshot(
db: Session,
report: ProductionReport,
source: str,
*,
checked_at: datetime | None = None,
) -> None:
timestamp = checked_at or now()
exceeded_count = 0
uncheckable_count = 0
for item in list(getattr(report, "items", []) or []):
result = evaluate_report_item_over_limit(db, report, item)
_apply_result_to_item(item, result, source=source, checked_at=timestamp)
if result.status == OVER_LIMIT_STATUS_EXCEEDED:
exceeded_count += 1
elif result.status == OVER_LIMIT_STATUS_UNCHECKABLE:
uncheckable_count += 1
report.has_over_limit = exceeded_count > 0
if exceeded_count and uncheckable_count:
report.over_limit_summary = f"{exceeded_count}项超额,{uncheckable_count}项无法校验"
elif exceeded_count:
report.over_limit_summary = f"{exceeded_count}项超额"
elif uncheckable_count:
report.over_limit_summary = f"{uncheckable_count}项无法校验"
else:
report.over_limit_summary = None
db.flush()