fix: 平衡报工归属拆分并约束唯一性

This commit is contained in:
souplearn
2026-07-25 06:33:12 +08:00
parent 6065ab031d
commit 4c0cbc9815
5 changed files with 283 additions and 27 deletions
+73 -1
View File
@@ -2,8 +2,10 @@ from datetime import date, datetime
from decimal import Decimal
from types import SimpleNamespace
from sqlalchemy import BigInteger, create_engine, select
import pytest
from sqlalchemy import BigInteger, create_engine, inspect, select
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import raiseload, selectinload, sessionmaker
from app.database import Base
@@ -203,6 +205,31 @@ def test_short_shared_report_rounding_residual_keeps_aggregate_night_total():
assert all(row.effective_minutes == round(row.day_minutes + row.overtime_minutes + row.night_minutes, 2) for row in rows)
def test_item_split_fields_keep_original_totals_after_rounding_residual():
item = _item(
good_qty=1,
defect_qty=1,
scrap_qty=1,
changeover_count=1,
process_unit_price_yuan=1,
)
report = _report(datetime(2026, 7, 25, 6, 0), datetime(2026, 7, 28, 6, 0), item)
rows = build_report_allocation_drafts(report)
assert [row.allocation_date for row in rows] == [
date(2026, 7, 25),
date(2026, 7, 26),
date(2026, 7, 27),
]
assert [row.effective_minutes for row in rows] == [1340, 1340, 1340]
assert round(sum(row.good_qty for row in rows), 2) == 1
assert round(sum(row.defect_qty for row in rows), 2) == 1
assert round(sum(row.scrap_qty for row in rows), 2) == 1
assert round(sum(row.changeover_count for row in rows), 2) == 1
assert round(sum(row.reference_wage for row in rows), 2) == 1
def test_items_sharing_same_started_at_split_the_segment_minutes():
started_at = datetime(2026, 7, 25, 8, 0)
first_item = _item(id=1, good_qty=10, started_at=started_at)
@@ -660,6 +687,51 @@ def _sqlite_db():
return SessionLocal()
def test_report_allocation_schema_has_unique_report_item_date_key():
engine = create_engine("sqlite+pysqlite:///:memory:", future=True)
Base.metadata.create_all(engine)
inspector = inspect(engine)
unique_column_sets = [
tuple(constraint["column_names"])
for constraint in inspector.get_unique_constraints("production_report_allocations")
]
unique_column_sets.extend(
tuple(index["column_names"])
for index in inspector.get_indexes("production_report_allocations")
if index.get("unique")
)
assert ("report_id", "report_item_id", "allocation_date") in unique_column_sets
def test_report_allocation_rejects_duplicate_report_item_date_key():
db = _sqlite_db()
try:
first = ProductionReportAllocation(
report_id=1,
report_item_id=1,
attendance_point_name="总厂",
employee_phone="13800000000",
allocation_date=date(2026, 7, 25),
)
duplicate = ProductionReportAllocation(
report_id=1,
report_item_id=1,
attendance_point_name="总厂",
employee_phone="13800000000",
allocation_date=date(2026, 7, 25),
)
db.add(first)
db.flush()
db.add(duplicate)
with pytest.raises(IntegrityError):
db.flush()
finally:
db.close()
def test_report_out_skips_unloaded_allocations_without_lazy_load():
db = _sqlite_db()
try:
+4 -2
View File
@@ -861,10 +861,12 @@ def test_approved_allocations_query_requires_approved_unvoided_matching_point_an
report_item_id=104,
attendance_point_name="二厂",
),
_db_report(id=5),
_db_item(id=105, report_id=5),
_db_allocation(
id=1005,
report_id=1,
report_item_id=101,
report_id=5,
report_item_id=105,
attendance_point_name="二厂",
),
_db_allocation(id=1006, report_id=1, report_item_id=102),