Files
MobilityOps/backend/tests/test_data_quality.py
NuklearRabbit 81e3fd63bd
MobilityOps acceptance / backend (push) Failing after 19s
MobilityOps acceptance / frontend (push) Successful in 25s
MobilityOps acceptance / e2e (push) Skipped
M54: harden operations and demo resilience
2026-08-24 03:31:03 +02:00

1421 lines
56 KiB
Python

from concurrent.futures import ThreadPoolExecutor
from datetime import UTC, datetime, timedelta
from threading import Barrier
from sqlalchemy import delete, select, text
from app.core.db import SessionLocal
from app.models.audit import AuditEvent
from app.models.booking import Booking
from app.models.customer import Customer
from app.models.data_quality import DataQualityIssue
from app.models.idempotency import IdempotencyRecord
from app.models.inspection import Inspection
from app.models.maintenance import MaintenanceRecord
from app.models.outbox import OutboxEvent
from app.models.vehicle import Vehicle
from app.schemas import CurrentUser, RegisterReturnRequest, ResolveOdometerRegressionRequest
from app.services.data_quality import (
open_odometer_regression_issue,
resolve_odometer_regression,
)
from app.services.returns import register_vehicle_return
def _activate_booking(vehicle_ref: str, start_odometer_km: int) -> str:
db = SessionLocal()
try:
vehicle = db.scalar(select(Vehicle).where(Vehicle.public_ref == vehicle_ref))
booking = db.scalar(
select(Booking).where(Booking.vehicle_id == vehicle.id, Booking.status == "returned")
)
booking.status = "active"
booking.start_odometer_km = start_odometer_km
booking.end_odometer_km = None
db.commit()
return booking.public_ref
finally:
db.close()
def _cleanup_odometer_scenario(vehicle_id, customer_id) -> None:
"""Remove one isolated DQ-03 scenario in foreign-key-safe order."""
with SessionLocal() as db:
booking_ids = db.scalars(select(Booking.id).where(Booking.vehicle_id == vehicle_id)).all()
issue_ids = db.scalars(
select(DataQualityIssue.id).where(DataQualityIssue.entity_id == vehicle_id)
).all()
audit_entity_ids = [vehicle_id, *booking_ids, *issue_ids]
if audit_entity_ids:
db.execute(delete(AuditEvent).where(AuditEvent.entity_id.in_(audit_entity_ids)))
if booking_ids:
db.execute(
delete(IdempotencyRecord).where(IdempotencyRecord.booking_id.in_(booking_ids))
)
db.execute(delete(OutboxEvent).where(OutboxEvent.aggregate_id.in_(booking_ids)))
db.execute(delete(DataQualityIssue).where(DataQualityIssue.entity_id == vehicle_id))
db.execute(delete(Inspection).where(Inspection.vehicle_id == vehicle_id))
db.execute(delete(MaintenanceRecord).where(MaintenanceRecord.vehicle_id == vehicle_id))
db.execute(delete(Booking).where(Booking.vehicle_id == vehicle_id))
db.execute(delete(Vehicle).where(Vehicle.id == vehicle_id))
db.execute(delete(Customer).where(Customer.id == customer_id))
db.commit()
def test_list_includes_all_five_rule_types(ops_client):
response = ops_client.get("/api/v1/data-quality/issues")
assert response.status_code == 200
issues = response.json()
rule_types = {i["rule_type"] for i in issues}
assert rule_types == {
"possible_duplicate_customer",
"missing_required_field",
"odometer_regression",
"booking_overlap",
"vehicle_status_conflict",
}
def test_scan_is_idempotent_once_seeded(ops_client):
# The session fixture already ran a scan as part of seeding; running again
# must not create duplicate open issues for the same (rule_type, entity).
response = ops_client.post("/api/v1/data-quality/scan")
assert response.status_code == 200
assert response.json()["created"] == {}
def test_scan_detects_imported_maintenance_odometer_regression(ops_client):
with SessionLocal() as db:
vehicle = Vehicle(
public_ref="MO-DQ-SCAN",
make="Synthetic",
model="Scanner",
model_year=2026,
registration_number="DQ-SCAN-01",
location="Brussels",
operational_status="available",
odometer_km=20_000,
next_service_km=30_000,
active=True,
version=1,
)
db.add(vehicle)
db.flush()
vehicle_id = vehicle.id
db.add_all(
[
MaintenanceRecord(
public_ref="MAINT-DQ-SCAN-A",
vehicle_id=vehicle.id,
occurred_at=datetime(2045, 1, 1, tzinfo=UTC),
odometer_km=20_000,
category="inspection",
summary="Synthetic scan baseline",
),
MaintenanceRecord(
public_ref="MAINT-DQ-SCAN-B",
vehicle_id=vehicle.id,
occurred_at=datetime(2045, 2, 1, tzinfo=UTC),
odometer_km=19_000,
category="inspection",
summary="Synthetic imported regression",
),
]
)
db.commit()
try:
response = ops_client.post("/api/v1/data-quality/scan")
assert response.status_code == 200
assert response.json()["created"]["odometer_regression"] >= 1
issues = ops_client.get(
"/api/v1/data-quality/issues",
params={"status": "open", "rule_type": "odometer_regression"},
).json()
issue = next(item for item in issues if item["entity_ref"] == "MO-DQ-SCAN")
assert issue["evidence"]["source_type"] == "maintenance"
assert issue["evidence"]["correctable_booking_refs"] == []
# A later imported regression must enrich the existing open issue instead of
# being silently dropped by the generic check-then-return scanner path.
with SessionLocal() as db:
db.add(
MaintenanceRecord(
public_ref="MAINT-DQ-SCAN-C",
vehicle_id=vehicle_id,
occurred_at=datetime(2045, 3, 1, tzinfo=UTC),
odometer_km=18_000,
category="inspection",
summary="Second synthetic imported regression",
)
)
db.commit()
rescanned = ops_client.post("/api/v1/data-quality/scan")
assert rescanned.status_code == 200
enriched = ops_client.get(f"/api/v1/data-quality/issues/{issue['public_ref']}").json()
later_refs = {signal["params"]["later_ref"] for signal in enriched["evidence"]["signals"]}
assert {"MAINT-DQ-SCAN-B", "MAINT-DQ-SCAN-C"}.issubset(later_refs)
finally:
with SessionLocal() as db:
db.execute(delete(DataQualityIssue).where(DataQualityIssue.entity_id == vehicle_id))
db.execute(delete(MaintenanceRecord).where(MaintenanceRecord.vehicle_id == vehicle_id))
db.execute(delete(Vehicle).where(Vehicle.id == vehicle_id))
db.commit()
def test_scan_requires_operations_manager(employee_client):
response = employee_client.post("/api/v1/data-quality/scan")
assert response.status_code == 403
def test_list_issues_requires_operations_manager(employee_client):
response = employee_client.get("/api/v1/data-quality/issues")
assert response.status_code == 403
def test_manager_can_assign_prioritised_quality_work_and_filter_it(ops_client):
assignee = next(user for user in ops_client.get("/api/v1/users").json() if user["active"])
open_issues = ops_client.get("/api/v1/data-quality/issues", params={"status": "open"}).json()
refs = [issue["public_ref"] for issue in open_issues[:2]]
due_at = "2030-01-15T12:00:00+00:00"
updated = ops_client.post(
"/api/v1/data-quality/issues/bulk-work",
json={
"issue_refs": refs,
"assigned_to_ref": assignee["public_ref"],
"due_at": due_at,
},
)
assert updated.status_code == 200
assert {issue["public_ref"] for issue in updated.json()["updated"]} == set(refs)
assert all(
issue["assigned_to_ref"] == assignee["public_ref"] for issue in updated.json()["updated"]
)
filtered = ops_client.get(
"/api/v1/data-quality/issues",
params={"status": "open", "assigned_to_ref": assignee["public_ref"]},
).json()
assert set(refs).issubset({issue["public_ref"] for issue in filtered})
audits = ops_client.get("/api/v1/audit", params={"action": "data_quality_work_updated"}).json()
assert len(audits) >= 2
cleared = ops_client.post(
"/api/v1/data-quality/issues/bulk-work",
json={"issue_refs": refs, "clear_assignment": True},
)
assert cleared.status_code == 200
assert all(issue["assigned_to_ref"] is None for issue in cleared.json()["updated"])
def test_employee_cannot_assign_quality_work(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/bulk-work",
json={"issue_refs": ["DQ-DEMO-OVERLAP"], "clear_assignment": True},
)
assert response.status_code == 403
def test_issue_page_preserves_severity_filter_and_limits_results(ops_client):
response = ops_client.get(
"/api/v1/data-quality/issues",
params={"severity": "high", "page": 1, "page_size": 25},
)
assert response.status_code == 200
body = response.json()
assert len(body["items"]) <= 25
assert all(issue["severity"] == "high" for issue in body["items"])
assert body["total"] >= len(body["items"])
def test_get_issue_requires_operations_manager(employee_client):
response = employee_client.get("/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE")
assert response.status_code == 403
def test_defer_requires_operations_manager(employee_client):
response = employee_client.post("/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/defer")
assert response.status_code == 403
def test_reject_requires_operations_manager(employee_client):
response = employee_client.post("/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/reject")
assert response.status_code == 403
def test_s2_duplicate_customer_issue_detail(ops_client):
response = ops_client.get("/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE")
assert response.status_code == 200
body = response.json()
assert body["entity_ref"] == "CUS-0012"
assert body["entity_snapshot"]["public_ref"] == "CUS-0012"
assert [s["public_ref"] for s in body["related_snapshots"]] == ["CUS-0178"]
def test_s4_booking_overlap_issue_detail(ops_client):
response = ops_client.get("/api/v1/data-quality/issues/DQ-DEMO-OVERLAP")
assert response.status_code == 200
body = response.json()
assert body["entity_ref"] == "MO-016"
assert set(body["evidence"]["related_refs"]) == {"BK-DEMO-OVERLAP-A", "BK-DEMO-OVERLAP-B"}
def test_defer_then_reject_are_rejected_on_closed_issue(ops_client):
issues = ops_client.get(
"/api/v1/data-quality/issues",
params={"rule_type": "missing_required_field", "status": "open"},
).json()
target = issues[0]["public_ref"]
deferred = ops_client.post(f"/api/v1/data-quality/issues/{target}/defer")
assert deferred.status_code == 200
assert deferred.json()["status"] == "deferred"
again = ops_client.post(f"/api/v1/data-quality/issues/{target}/reject")
assert again.status_code == 409
assert again.json()["error"]["code"] == "ISSUE_NOT_OPEN"
def test_merge_customers_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE/merge-customers",
json={"survivor_ref": "CUS-0012"},
)
assert response.status_code == 403
def test_merge_customers_rejects_unrelated_survivor(ops_client):
response = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE/merge-customers",
json={"survivor_ref": "CUS-0099"},
)
assert response.status_code == 422
assert response.json()["error"]["code"] == "INVALID_SURVIVOR"
def test_merge_customers_s2_scenario_rewires_and_audits(ops_client):
before_bookings = ops_client.get(
"/api/v1/bookings", params={"vehicle_ref": "MO-001"}
) # warm the client session; irrelevant vehicle, just a cheap authenticated call
assert before_bookings.status_code == 200
response = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE/merge-customers",
json={"survivor_ref": "CUS-0012", "field_overrides": {"city": "Turnhout"}},
)
assert response.status_code == 200
body = response.json()
assert body["survivor_ref"] == "CUS-0012"
assert body["loser_ref"] == "CUS-0178"
issue = ops_client.get("/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE").json()
assert issue["status"] == "resolved"
audit_events = ops_client.get("/api/v1/audit", params={"action": "customer_merged"}).json()
assert len(audit_events) >= 1
# Already-resolved issue cannot be merged again.
replay = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-DUPLICATE/merge-customers",
json={"survivor_ref": "CUS-0012"},
)
assert replay.status_code == 409
def test_overlap_related_snapshots_are_typed_as_bookings_not_vehicles(ops_client):
body = ops_client.get("/api/v1/data-quality/issues/DQ-DEMO-OVERLAP").json()
assert len(body["related_snapshots"]) == 2
for snap in body["related_snapshots"]:
assert snap["entity_type"] == "booking"
assert snap["public_ref"] in {"BK-DEMO-OVERLAP-A", "BK-DEMO-OVERLAP-B"}
assert "starts_at" in snap and "ends_at" in snap
def _first_open(ops_client, rule_type: str) -> dict:
issues = ops_client.get(
"/api/v1/data-quality/issues", params={"rule_type": rule_type, "status": "open"}
).json()
assert issues, f"expected at least one open {rule_type} issue"
return issues[0]
def test_provide_fields_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-ATTENTION/provide-fields",
json={"fields": {"registration_number": "TST-001"}},
)
assert response.status_code == 403
def test_provide_fields_rejects_wrong_rule_type(ops_client):
response = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/provide-fields",
json={"fields": {"make": "Test"}},
)
assert response.status_code == 409
assert response.json()["error"]["code"] == "NOT_A_MISSING_FIELD_ISSUE"
def test_provide_fields_rejects_disallowed_field(ops_client):
target = _first_open(ops_client, "missing_required_field")
detail = ops_client.get(f"/api/v1/data-quality/issues/{target['public_ref']}").json()
disallowed = "city" if detail["entity_type"] == "customer" else "next_service_km"
response = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/provide-fields",
json={"fields": {disallowed: "anything"}},
)
assert response.status_code == 422
assert response.json()["error"]["code"] == "INVALID_FIELD"
def test_provide_fields_resolves_a_vehicle_missing_field_issue(ops_client):
issues = ops_client.get(
"/api/v1/data-quality/issues",
params={"rule_type": "missing_required_field", "status": "open"},
).json()
target = next(i for i in issues if i["entity_type"] == "vehicle")
response = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/provide-fields",
json={
"fields": {
"registration_number": "TST-999",
"make": "TestMake",
"model": "TestModel",
"location": "Depot",
}
},
)
assert response.status_code == 200
assert response.json()["status"] == "resolved"
vehicle = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
assert vehicle["registration_number"] == "TST-999"
def test_vehicle_entity_snapshot_includes_registration_number(ops_client):
"""The snapshot used to omit registration_number entirely, so the 'provide missing
fields' form always showed it blank -- even for a vehicle whose plate was actually
on file, and even when a *different* field was the genuinely missing one."""
issues = ops_client.get(
"/api/v1/data-quality/issues",
params={"rule_type": "missing_required_field", "status": "open"},
).json()
target = next(i for i in issues if i["entity_type"] == "vehicle")
vehicle = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
detail = ops_client.get(f"/api/v1/data-quality/issues/{target['public_ref']}").json()
assert detail["entity_snapshot"]["registration_number"] == vehicle["registration_number"]
def test_resolve_overlap_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/resolve-overlap",
json={"booking_ref": "BK-DEMO-OVERLAP-A"},
)
assert response.status_code == 403
def test_resolve_overlap_rejects_unrelated_booking(ops_client):
response = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/resolve-overlap",
json={"booking_ref": "BK-DEMO-RETURN"},
)
assert response.status_code == 422
assert response.json()["error"]["code"] == "INVALID_BOOKING_REFERENCE"
def test_resolve_overlap_blocks_one_booking_and_resolves(ops_client):
response = ops_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-OVERLAP/resolve-overlap",
json={"booking_ref": "BK-DEMO-OVERLAP-A", "note": "Blocked the later commitment."},
)
assert response.status_code == 200
assert response.json()["status"] == "resolved"
booking = ops_client.get("/api/v1/bookings/BK-DEMO-OVERLAP-A").json()
assert booking["status"] == "blocked"
def test_status_recommendation_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-STATUS/status-recommendation"
)
assert response.status_code == 403
def test_apply_recommended_status_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-DEMO-STATUS/apply-recommended-status",
json={"recommendation_token": "irrelevant"},
)
assert response.status_code == 403
def test_status_recommendation_preview_does_not_mutate_anything(ops_client):
target = _first_open(ops_client, "vehicle_status_conflict")
vehicle_before = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
preview_response = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/status-recommendation"
)
assert preview_response.status_code == 200
preview = preview_response.json()
assert preview["current_status"] == vehicle_before["operational_status"]
assert preview["recommendation_token"]
assert "facts" in preview
# Calling preview again (as the UI would on every open) must still not mutate.
ops_client.post(f"/api/v1/data-quality/issues/{target['public_ref']}/status-recommendation")
issue_after = ops_client.get(f"/api/v1/data-quality/issues/{target['public_ref']}").json()
vehicle_after = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
assert issue_after["status"] == "open"
assert vehicle_after["operational_status"] == vehicle_before["operational_status"]
def test_apply_recommended_status_resolves_conflict(ops_client):
targets = ops_client.get(
"/api/v1/data-quality/issues",
params={"rule_type": "vehicle_status_conflict", "status": "open"},
).json()
target = None
preview = None
for candidate in targets:
candidate_preview = ops_client.post(
f"/api/v1/data-quality/issues/{candidate['public_ref']}/status-recommendation"
).json()
if candidate_preview["safe_to_apply"]:
target = candidate
preview = candidate_preview
break
assert target is not None and preview is not None
assert preview["safe_to_apply"] is True
assert preview["manual_review_required"] is False
response = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/apply-recommended-status",
json={"recommendation_token": preview["recommendation_token"]},
)
assert response.status_code == 200
body = response.json()
assert body["issue"]["status"] == "resolved"
assert body["applied_status"] == preview["recommended_status"]
assert body["reason_code"] == preview["recommendation_code"]
vehicle = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
assert vehicle["operational_status"] == body["applied_status"]
def test_apply_recommended_status_rejects_stale_token(ops_client):
target = _first_open(ops_client, "vehicle_status_conflict")
response = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/apply-recommended-status",
json={"recommendation_token": "not-a-real-token"},
)
assert response.status_code == 409
assert response.json()["error"]["code"] == "RECOMMENDATION_STALE"
def test_resolve_odometer_regression_requires_operations_manager(employee_client):
response = employee_client.post(
"/api/v1/data-quality/issues/DQ-0007/resolve-odometer-regression",
json={"decision": "retain_canonical"},
)
assert response.status_code == 403
def test_resolve_odometer_regression_correction_below_canonical_is_rejected_then_retained(
ops_client,
):
target = _first_open(ops_client, "odometer_regression")
vehicle_before = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
too_low = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/resolve-odometer-regression",
json={
"decision": "correct_reading",
"booking_ref": "BK-DEMO-RETURN",
"corrected_odometer_km": max(vehicle_before["odometer_km"] - 100, 0),
},
)
assert too_low.status_code == 422
assert too_low.json()["error"]["code"] in (
"CORRECTION_BELOW_CANONICAL",
"INVALID_BOOKING_REFERENCE",
)
# The rejected attempt must not have resolved or mutated anything.
still_open = ops_client.get(f"/api/v1/data-quality/issues/{target['public_ref']}").json()
assert still_open["status"] == "open"
retained = ops_client.post(
f"/api/v1/data-quality/issues/{target['public_ref']}/resolve-odometer-regression",
json={"decision": "retain_canonical", "note": "Submitted reading treated as erroneous."},
)
assert retained.status_code == 200
assert retained.json()["status"] == "resolved"
vehicle_after = ops_client.get(f"/api/v1/vehicles/{target['entity_ref']}").json()
assert vehicle_after["odometer_km"] == vehicle_before["odometer_km"]
def test_resolve_odometer_regression_correct_reading_updates_canonical(ops_client):
# Create a live return regression to prove the complete correction chain updates
# both persisted representations of that reading (booking + return inspection).
booking_ref = _activate_booking("MO-018", start_odometer_km=12000)
vehicle_before = ops_client.get("/api/v1/vehicles/MO-018").json()
low_reading = vehicle_before["odometer_km"] - 200
returned = ops_client.post(
f"/api/v1/bookings/{booking_ref}/return",
json={
"end_odometer_km": low_reading,
"fuel_level_percent": 50,
"cleanliness_ok": True,
"damage_reported": False,
"technical_warning": False,
},
headers={"Idempotency-Key": "test-dq-odometer-correct-001"},
)
assert returned.status_code == 201
issue_ref = returned.json()["quality_issue_ref"]
inspection_ref = returned.json()["inspection_ref"]
assert issue_ref is not None
corrected = vehicle_before["odometer_km"] + 500
response = ops_client.post(
f"/api/v1/data-quality/issues/{issue_ref}/resolve-odometer-regression",
json={
"decision": "correct_reading",
"booking_ref": booking_ref,
"corrected_odometer_km": corrected,
},
)
assert response.status_code == 200
assert response.json()["status"] == "resolved"
vehicle = ops_client.get("/api/v1/vehicles/MO-018").json()
assert vehicle["odometer_km"] == corrected
booking = ops_client.get(f"/api/v1/bookings/{booking_ref}").json()
assert booking["end_odometer_km"] == corrected
with SessionLocal() as db:
inspection = db.scalar(select(Inspection).where(Inspection.public_ref == inspection_ref))
assert inspection is not None
assert inspection.odometer_km == corrected
def test_correcting_one_of_two_regressions_keeps_the_other_open(ops_client):
with SessionLocal() as db:
customer = Customer(
public_ref="CUS-DQ-MULTI",
first_name="Synthetic",
last_name="Multi",
email="dq-multi@example.test",
)
vehicle = Vehicle(
public_ref="MO-DQ-MULTI",
make="Synthetic",
model="Multi",
model_year=2026,
registration_number="DQ-MULTI",
location="Brussels",
operational_status="available",
odometer_km=1_000,
next_service_km=2_000,
active=True,
version=1,
)
db.add_all([customer, vehicle])
db.flush()
bookings: list[Booking] = []
inspections: list[Inspection] = []
for index, reading in enumerate((900, 800), start=1):
booking = Booking(
public_ref=f"BK-DQ-MULTI-{index}",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=datetime(2046, index, 1, tzinfo=UTC),
ends_at=datetime(2046, index, 2, tzinfo=UTC),
status="returned",
start_odometer_km=reading - 10,
end_odometer_km=reading,
requirements_complete=True,
)
db.add(booking)
db.flush()
inspection = Inspection(
public_ref=f"INSP-DQ-M-{index}",
booking_id=booking.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=reading,
completed_at=booking.ends_at,
)
db.add(inspection)
db.flush()
open_odometer_regression_issue(
db,
vehicle=vehicle,
reading_ref=inspection.public_ref,
reading_km=reading,
canonical_km=vehicle.odometer_km,
source_type="return",
related_refs=[booking.public_ref, inspection.public_ref],
correctable_booking_refs=[booking.public_ref],
public_ref="DQ-MULTI-SOURCE" if index == 1 else None,
)
bookings.append(booking)
inspections.append(inspection)
booking_refs = [booking.public_ref for booking in bookings]
vehicle_id = vehicle.id
customer_id = customer.id
db.commit()
try:
first = ops_client.post(
"/api/v1/data-quality/issues/DQ-MULTI-SOURCE/resolve-odometer-regression",
json={
"decision": "correct_reading",
"booking_ref": booking_refs[0],
"corrected_odometer_km": 1_100,
},
)
assert first.status_code == 200, first.text
assert first.json()["status"] == "open"
assert first.json()["evidence"]["correctable_booking_refs"] == [booking_refs[1]]
second = ops_client.post(
"/api/v1/data-quality/issues/DQ-MULTI-SOURCE/resolve-odometer-regression",
json={
"decision": "correct_reading",
"booking_ref": booking_refs[1],
"corrected_odometer_km": 1_200,
},
)
assert second.status_code == 200, second.text
assert second.json()["status"] == "resolved"
with SessionLocal() as db:
persisted = db.scalars(
select(Inspection)
.where(Inspection.vehicle_id == vehicle_id)
.order_by(Inspection.public_ref)
).all()
assert [item.odometer_km for item in persisted] == [1_100, 1_200]
finally:
with SessionLocal() as db:
db.execute(delete(DataQualityIssue).where(DataQualityIssue.entity_id == vehicle_id))
db.execute(delete(Inspection).where(Inspection.vehicle_id == vehicle_id))
db.execute(delete(Booking).where(Booking.vehicle_id == vehicle_id))
db.execute(delete(Vehicle).where(Vehicle.id == vehicle_id))
db.execute(delete(Customer).where(Customer.id == customer_id))
db.commit()
def test_retained_regression_is_suppressed_until_source_reading_changes(ops_client):
with SessionLocal() as db:
vehicle = Vehicle(
public_ref="MO-DQ-RETAIN",
make="Synthetic",
model="Retain",
model_year=2026,
registration_number="DQ-RETAIN",
location="Brussels",
operational_status="available",
odometer_km=20_000,
next_service_km=30_000,
active=True,
version=1,
)
db.add(vehicle)
db.flush()
vehicle_id = vehicle.id
db.add_all(
[
MaintenanceRecord(
public_ref="MAINT-DQ-RET-A",
vehicle_id=vehicle.id,
occurred_at=datetime(2047, 1, 1, tzinfo=UTC),
odometer_km=20_000,
category="inspection",
summary="Retain baseline",
),
MaintenanceRecord(
public_ref="MAINT-DQ-RET-B",
vehicle_id=vehicle.id,
occurred_at=datetime(2047, 2, 1, tzinfo=UTC),
odometer_km=19_000,
category="inspection",
summary="Retained source reading",
),
]
)
db.commit()
try:
assert ops_client.post("/api/v1/data-quality/scan").status_code == 200
issue = next(
item
for item in ops_client.get(
"/api/v1/data-quality/issues",
params={"status": "open", "rule_type": "odometer_regression"},
).json()
if item["entity_ref"] == "MO-DQ-RETAIN"
)
retained = ops_client.post(
f"/api/v1/data-quality/issues/{issue['public_ref']}/resolve-odometer-regression",
json={"decision": "retain_canonical", "note": "Verified source entry"},
)
assert retained.status_code == 200
assert retained.json()["status"] == "resolved"
assert ops_client.post("/api/v1/data-quality/scan").status_code == 200
with SessionLocal() as db:
assert (
db.scalar(
select(DataQualityIssue).where(
DataQualityIssue.entity_id == vehicle_id,
DataQualityIssue.status == "open",
)
)
is None
)
changed = db.scalar(
select(MaintenanceRecord).where(MaintenanceRecord.public_ref == "MAINT-DQ-RET-B")
)
changed.odometer_km = 18_999
db.commit()
assert ops_client.post("/api/v1/data-quality/scan").status_code == 200
reopened = next(
item
for item in ops_client.get(
"/api/v1/data-quality/issues",
params={"status": "open", "rule_type": "odometer_regression"},
).json()
if item["entity_ref"] == "MO-DQ-RETAIN"
)
assert reopened["evidence"]["reopened_from"] == issue["public_ref"]
finally:
with SessionLocal() as db:
db.execute(delete(DataQualityIssue).where(DataQualityIssue.entity_id == vehicle_id))
db.execute(delete(MaintenanceRecord).where(MaintenanceRecord.vehicle_id == vehicle_id))
db.execute(delete(Vehicle).where(Vehicle.id == vehicle_id))
db.commit()
def test_live_return_retained_as_canonical_is_not_reopened_by_scan(ops_client):
now = datetime.now(UTC)
with SessionLocal() as db:
customer = Customer(
public_ref="CUS-DQ-LIVE-RET",
first_name="Synthetic",
last_name="Retained return",
email="dq-live-retain@example.test",
)
vehicle = Vehicle(
public_ref="MO-DQ-LIVE-RET",
make="Synthetic",
model="Retained return",
model_year=2026,
registration_number="DQ-LIVE-RET",
location="Brussels",
operational_status="rented",
odometer_km=20_000,
next_service_km=30_000,
active=True,
version=1,
)
db.add_all([customer, vehicle])
db.flush()
booking = Booking(
public_ref="BK-DQ-LIVE-RET",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=now - timedelta(days=2),
ends_at=now + timedelta(days=1),
status="active",
start_odometer_km=19_500,
end_odometer_km=None,
requirements_complete=True,
)
db.add_all(
[
booking,
MaintenanceRecord(
public_ref="MNT-DQ-LIVE-RET",
vehicle_id=vehicle.id,
occurred_at=now - timedelta(days=3),
odometer_km=20_000,
category="inspection",
summary="Synthetic canonical baseline",
),
]
)
vehicle_id = vehicle.id
customer_id = customer.id
db.commit()
try:
returned = ops_client.post(
"/api/v1/bookings/BK-DQ-LIVE-RET/return",
json={
"end_odometer_km": 19_000,
"fuel_level_percent": 50,
"cleanliness_ok": True,
"damage_reported": False,
"technical_warning": False,
},
headers={"Idempotency-Key": "test-dq-live-retain-001"},
)
assert returned.status_code == 201, returned.text
issue_ref = returned.json()["quality_issue_ref"]
inspection_ref = returned.json()["inspection_ref"]
assert issue_ref is not None
retained = ops_client.post(
f"/api/v1/data-quality/issues/{issue_ref}/resolve-odometer-regression",
json={"decision": "retain_canonical", "note": "Source reading verified as wrong."},
)
assert retained.status_code == 200, retained.text
assert retained.json()["status"] == "resolved"
assert retained.json()["evidence"]["retained_odometer_fingerprints"] == [
{
"source_type": "return",
"later_ref": inspection_ref,
"later_km": 19_000,
}
]
scanned = ops_client.post("/api/v1/data-quality/scan")
assert scanned.status_code == 200, scanned.text
with SessionLocal() as db:
issues = db.scalars(
select(DataQualityIssue)
.where(
DataQualityIssue.entity_id == vehicle_id,
DataQualityIssue.rule_type == "odometer_regression",
)
.order_by(DataQualityIssue.detected_at)
).all()
assert [(issue.public_ref, issue.status) for issue in issues] == [
(issue_ref, "resolved")
]
finally:
_cleanup_odometer_scenario(vehicle_id, customer_id)
def test_scanned_return_regression_can_correct_booking_all_inspections_and_vehicle(ops_client):
now = datetime.now(UTC)
with SessionLocal() as db:
customer = Customer(
public_ref="CUS-DQ-SCAN-RET",
first_name="Synthetic",
last_name="Scanned return",
email="dq-scan-return@example.test",
)
vehicle = Vehicle(
public_ref="MO-DQ-SCAN-RET",
make="Synthetic",
model="Scanned return",
model_year=2026,
registration_number="DQ-SCAN-RET",
location="Brussels",
operational_status="available",
odometer_km=20_000,
next_service_km=30_000,
active=True,
version=1,
)
db.add_all([customer, vehicle])
db.flush()
booking = Booking(
public_ref="BK-DQ-SCAN-RET",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=now - timedelta(days=3),
ends_at=now - timedelta(hours=12),
status="returned",
start_odometer_km=19_500,
end_odometer_km=18_500,
requirements_complete=True,
)
db.add(booking)
db.flush()
db.add_all(
[
MaintenanceRecord(
public_ref="MNT-DQ-SCAN-RET",
vehicle_id=vehicle.id,
occurred_at=now - timedelta(days=4),
odometer_km=20_000,
category="inspection",
summary="Synthetic canonical baseline",
),
Inspection(
public_ref="INSP-DQ-SCAN-R1",
booking_id=booking.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=19_000,
completed_at=now - timedelta(days=1),
),
Inspection(
public_ref="INSP-DQ-SCAN-R2",
booking_id=booking.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=18_500,
completed_at=now - timedelta(hours=12),
),
]
)
vehicle_id = vehicle.id
customer_id = customer.id
db.commit()
try:
scanned = ops_client.post("/api/v1/data-quality/scan")
assert scanned.status_code == 200, scanned.text
issue = next(
item
for item in ops_client.get(
"/api/v1/data-quality/issues",
params={"status": "open", "rule_type": "odometer_regression"},
).json()
if item["entity_ref"] == "MO-DQ-SCAN-RET"
)
assert issue["evidence"]["correctable_booking_refs"] == ["BK-DQ-SCAN-RET"]
later_refs = {signal["params"]["later_ref"] for signal in issue["evidence"]["signals"]}
assert later_refs == {"INSP-DQ-SCAN-R1", "INSP-DQ-SCAN-R2"}
corrected = ops_client.post(
f"/api/v1/data-quality/issues/{issue['public_ref']}/resolve-odometer-regression",
json={
"decision": "correct_reading",
"booking_ref": "BK-DQ-SCAN-RET",
"corrected_odometer_km": 20_500,
},
)
assert corrected.status_code == 200, corrected.text
assert corrected.json()["status"] == "resolved"
with SessionLocal() as db:
persisted_vehicle = db.get(Vehicle, vehicle_id)
persisted_booking = db.scalar(
select(Booking).where(Booking.public_ref == "BK-DQ-SCAN-RET")
)
assert persisted_booking is not None
persisted_inspections = db.scalars(
select(Inspection)
.where(Inspection.booking_id == persisted_booking.id, Inspection.type == "return")
.order_by(Inspection.public_ref)
).all()
assert persisted_vehicle is not None
assert persisted_vehicle.odometer_km == 20_500
assert persisted_booking.end_odometer_km == 20_500
assert [inspection.odometer_km for inspection in persisted_inspections] == [
20_500,
20_500,
]
finally:
_cleanup_odometer_scenario(vehicle_id, customer_id)
def test_resolver_and_concurrent_return_finish_without_deadlock_or_lost_evidence():
now = datetime.now(UTC)
with SessionLocal() as db:
customer = Customer(
public_ref="CUS-DQ-RACE",
first_name="Synthetic",
last_name="Race",
email="dq-race@example.test",
)
vehicle = Vehicle(
public_ref="MO-DQ-RACE",
make="Synthetic",
model="Race",
model_year=2026,
registration_number="DQ-RACE",
location="Brussels",
operational_status="rented",
odometer_km=20_000,
next_service_km=30_000,
active=True,
version=1,
)
db.add_all([customer, vehicle])
db.flush()
corrected_booking = Booking(
public_ref="BK-DQ-RACE-OLD",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=now - timedelta(days=4),
ends_at=now - timedelta(days=3),
status="returned",
start_odometer_km=19_500,
end_odometer_km=19_000,
requirements_complete=True,
)
concurrent_booking = Booking(
public_ref="BK-DQ-RACE-NEW",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=now - timedelta(days=1),
ends_at=now + timedelta(days=1),
status="active",
start_odometer_km=19_000,
end_odometer_km=None,
requirements_complete=True,
)
db.add_all([corrected_booking, concurrent_booking])
db.flush()
old_inspection = Inspection(
public_ref="INSP-DQ-RACE-OLD",
booking_id=corrected_booking.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=19_000,
completed_at=corrected_booking.ends_at,
)
db.add(old_inspection)
db.flush()
issue = open_odometer_regression_issue(
db,
vehicle=vehicle,
reading_ref=old_inspection.public_ref,
reading_km=19_000,
canonical_km=20_000,
source_type="return",
related_refs=[corrected_booking.public_ref, old_inspection.public_ref],
correctable_booking_refs=[corrected_booking.public_ref],
public_ref="DQ-ODO-RACE",
)
assert issue is not None
vehicle_id = vehicle.id
customer_id = customer.id
db.commit()
actor = CurrentUser(
public_ref="USR-DQ-RACE",
display_name="DQ Race Manager",
role="operations_manager",
)
start = Barrier(2)
def correct_existing_reading() -> str:
with SessionLocal() as db:
db.execute(text("SET LOCAL lock_timeout = '5s'"))
start.wait(timeout=5)
resolved = resolve_odometer_regression(
db,
"DQ-ODO-RACE",
ResolveOdometerRegressionRequest(
decision="correct_reading",
booking_ref="BK-DQ-RACE-OLD",
corrected_odometer_km=20_500,
),
actor,
)
return resolved.status
def return_other_booking() -> dict:
with SessionLocal() as db:
db.execute(text("SET LOCAL lock_timeout = '5s'"))
start.wait(timeout=5)
_status, response = register_vehicle_return(
db,
"BK-DQ-RACE-NEW",
RegisterReturnRequest(
end_odometer_km=18_000,
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
),
"test-dq-resolve-return-race-001",
actor,
)
return response
try:
with ThreadPoolExecutor(max_workers=2) as executor:
correction_future = executor.submit(correct_existing_reading)
return_future = executor.submit(return_other_booking)
correction_status = correction_future.result(timeout=15)
return_result = return_future.result(timeout=15)
assert correction_status in {"open", "resolved"}
assert return_result["quality_issue_ref"] is not None
with SessionLocal() as db:
persisted_vehicle = db.get(Vehicle, vehicle_id)
bookings = {
booking.public_ref: booking
for booking in db.scalars(
select(Booking).where(Booking.vehicle_id == vehicle_id)
).all()
}
old_inspections = db.scalars(
select(Inspection).where(Inspection.booking_id == bookings["BK-DQ-RACE-OLD"].id)
).all()
open_issues = db.scalars(
select(DataQualityIssue).where(
DataQualityIssue.entity_id == vehicle_id,
DataQualityIssue.rule_type == "odometer_regression",
DataQualityIssue.status == "open",
)
).all()
assert persisted_vehicle is not None
assert persisted_vehicle.odometer_km == 20_500
assert bookings["BK-DQ-RACE-OLD"].end_odometer_km == 20_500
assert [inspection.odometer_km for inspection in old_inspections] == [20_500]
assert bookings["BK-DQ-RACE-NEW"].status == "returned"
assert bookings["BK-DQ-RACE-NEW"].end_odometer_km == 18_000
assert len(open_issues) == 1
assert open_issues[0].evidence_json["correctable_booking_refs"] == ["BK-DQ-RACE-NEW"]
later_refs = {
signal["params"]["later_ref"] for signal in open_issues[0].evidence_json["signals"]
}
assert later_refs == {return_result["inspection_ref"]}
finally:
_cleanup_odometer_scenario(vehicle_id, customer_id)
def test_early_return_uses_inspection_time_without_duplicate_booking_regression(ops_client):
with SessionLocal() as db:
customer = Customer(
public_ref="CUS-DQ-EARLY",
first_name="Synthetic",
last_name="Early",
email="dq-early@example.test",
)
vehicle = Vehicle(
public_ref="MO-DQ-EARLY",
make="Synthetic",
model="Early",
model_year=2026,
registration_number="DQ-EARLY",
location="Brussels",
operational_status="available",
odometer_km=200,
next_service_km=10_000,
active=True,
version=1,
)
db.add_all([customer, vehicle])
db.flush()
early = Booking(
public_ref="BK-DQ-EARLY-A",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=datetime(2048, 1, 1, tzinfo=UTC),
ends_at=datetime(2048, 3, 1, tzinfo=UTC),
status="returned",
start_odometer_km=90,
end_odometer_km=100,
requirements_complete=True,
)
later = Booking(
public_ref="BK-DQ-EARLY-B",
customer_id=customer.id,
vehicle_id=vehicle.id,
starts_at=datetime(2048, 1, 10, tzinfo=UTC),
ends_at=datetime(2048, 2, 1, tzinfo=UTC),
status="returned",
start_odometer_km=100,
end_odometer_km=200,
requirements_complete=True,
)
db.add_all([early, later])
db.flush()
db.add_all(
[
Inspection(
public_ref="INSP-DQ-EARLY-A",
booking_id=early.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=100,
completed_at=datetime(2048, 1, 2, tzinfo=UTC),
),
Inspection(
public_ref="INSP-DQ-EARLY-B",
booking_id=later.id,
vehicle_id=vehicle.id,
type="return",
fuel_level_percent=50,
cleanliness_ok=True,
damage_reported=False,
technical_warning=False,
odometer_km=200,
completed_at=datetime(2048, 2, 1, tzinfo=UTC),
),
]
)
vehicle_id = vehicle.id
customer_id = customer.id
db.commit()
try:
assert ops_client.post("/api/v1/data-quality/scan").status_code == 200
with SessionLocal() as db:
assert (
db.scalar(
select(DataQualityIssue).where(
DataQualityIssue.entity_id == vehicle_id,
DataQualityIssue.rule_type == "odometer_regression",
)
)
is None
)
finally:
with SessionLocal() as db:
db.execute(delete(DataQualityIssue).where(DataQualityIssue.entity_id == vehicle_id))
db.execute(delete(Inspection).where(Inspection.vehicle_id == vehicle_id))
db.execute(delete(Booking).where(Booking.vehicle_id == vehicle_id))
db.execute(delete(Vehicle).where(Vehicle.id == vehicle_id))
db.execute(delete(Customer).where(Customer.id == customer_id))
db.commit()
def test_manual_scan_records_audit_event(ops_client):
scan = ops_client.post("/api/v1/data-quality/scan")
assert scan.status_code == 200
events = ops_client.get("/api/v1/audit", params={"action": "data_quality_scan_run"}).json()
assert len(events) >= 1
assert "created" in events[0]["metadata"]
def _reset_demo(ops_client) -> None:
# /api/v1/demo/reset deletes the session cookie (the reset recreates the users
# table, so the old session's user id no longer exists) -- the caller must log back
# in before making any further authenticated call with the same client.
response = ops_client.post("/api/v1/demo/reset")
assert response.status_code == 200, response.text
login_response = ops_client.post("/api/v1/demo/login", json={"role": "operations_manager"})
assert login_response.status_code == 200, login_response.text
def _resolve_overlap_issue(ops_client, *, booking_to_block: str) -> None:
overlap = _first_open(ops_client, "booking_overlap")
response = ops_client.post(
f"/api/v1/data-quality/issues/{overlap['public_ref']}/resolve-overlap",
json={"booking_ref": booking_to_block},
)
assert response.status_code == 200, response.text
assert response.json()["status"] == "resolved"
def _first_open_for_vehicle(ops_client, rule_type: str, vehicle_ref: str) -> dict:
issues = ops_client.get(
"/api/v1/data-quality/issues", params={"rule_type": rule_type, "status": "open"}
).json()
match = next((i for i in issues if i["entity_ref"] == vehicle_ref), None)
assert match, f"expected an open {rule_type} issue for {vehicle_ref}"
return match
def _apply_status_recommendation(ops_client, public_ref: str) -> dict:
preview = ops_client.post(
f"/api/v1/data-quality/issues/{public_ref}/status-recommendation"
).json()
apply_response = ops_client.post(
f"/api/v1/data-quality/issues/{public_ref}/apply-recommended-status",
json={"recommendation_token": preview["recommendation_token"]},
)
assert apply_response.status_code == 200, apply_response.text
return apply_response.json()
def test_mo_016_status_conflict_recommendation_is_order_independent(ops_client):
# MO-016 carries both a booking_overlap (DQ-DEMO-OVERLAP) and a vehicle_status_conflict
# (DQ-DEMO-STATUS) issue at once. Order independence does NOT mean "the same final
# vehicle status regardless of order" -- resolving the overlap first genuinely removes
# the conflict, so there is correctly nothing left to apply. What must hold in either
# order: the recommendation always reflects the real, current facts (never a stale
# "was some other issue open" proxy), and nothing unsafe is ever applied (never
# "rented", never a status change once the underlying condition has already resolved
# itself). See docs/fleet-ops-correction/current-gap-audit.md §6-7 and
# vehicle-status-decision-table.md.
# Order A: resolve the booking overlap first. The status-conflict issue's own
# recommendation must now correctly report that the conflict is gone -- nothing unsafe
# should be auto-applied, and the vehicle (never touched) stays exactly as it was.
_reset_demo(ops_client)
_resolve_overlap_issue(ops_client, booking_to_block="BK-DEMO-OVERLAP-B")
status_issue_a = _first_open_for_vehicle(ops_client, "vehicle_status_conflict", "MO-016")
preview_a = ops_client.post(
f"/api/v1/data-quality/issues/{status_issue_a['public_ref']}/status-recommendation"
).json()
assert preview_a["recommendation_code"] == "vehicle.no_conflict"
assert preview_a["recommended_status"] is None
assert preview_a["safe_to_apply"] is False
vehicle_a = ops_client.get("/api/v1/vehicles/MO-016").json()
assert vehicle_a["operational_status"] == "available"
# Order B: resolve the status conflict first, while the overlap is still open -- the
# conflict genuinely still exists, so the evaluator must still detect it and safely
# resolve it (never "rented").
_reset_demo(ops_client)
status_issue_b = _first_open_for_vehicle(ops_client, "vehicle_status_conflict", "MO-016")
result_b = _apply_status_recommendation(ops_client, status_issue_b["public_ref"])
assert result_b["applied_status"] != "rented"
vehicle_b_mid = ops_client.get("/api/v1/vehicles/MO-016").json()
assert vehicle_b_mid["operational_status"] == result_b["applied_status"]
# Resolving the now-redundant overlap afterwards must not itself change the vehicle's
# status as a side effect.
_resolve_overlap_issue(ops_client, booking_to_block="BK-DEMO-OVERLAP-B")
vehicle_b = ops_client.get("/api/v1/vehicles/MO-016").json()
assert vehicle_b["operational_status"] == result_b["applied_status"]
assert vehicle_b["operational_status"] != "rented"
_reset_demo(ops_client)
def test_rejected_issue_recurrence_links_to_prior_decision(ops_client):
# Reject an open vehicle_status_conflict issue without changing the vehicle, so the
# next scan re-detects the same unresolved condition -- it must not silently vanish
# or reopen the old row, but the new issue should stay linked to the rejection.
target = _first_open(ops_client, "vehicle_status_conflict")
rejected = ops_client.post(f"/api/v1/data-quality/issues/{target['public_ref']}/reject")
assert rejected.status_code == 200
rescan = ops_client.post("/api/v1/data-quality/scan")
assert rescan.status_code == 200
assert rescan.json()["created"].get("vehicle_status_conflict", 0) >= 1
reopened = ops_client.get(
"/api/v1/data-quality/issues",
params={"rule_type": "vehicle_status_conflict", "status": "open"},
).json()
match = next(
(i for i in reopened if i["evidence"].get("reopened_from") == target["public_ref"]), None
)
assert match is not None, "expected a new issue linked back to the rejected one"
assert match["evidence"]["previous_decision"] == "rejected"
def test_scan_public_refs_are_collision_resistant() -> None:
from app.services.data_quality import _new_scan_ref
refs = {_new_scan_ref("DQ-SCAN") for _ in range(1000)}
assert len(refs) == 1000
assert all(ref.startswith("DQ-SCAN-") and len(ref) == 18 for ref in refs)