fix: 平衡报工归属拆分并约束唯一性
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user