4.2 KiB
Data-quality rules
Run rules after seed/import, after relevant commands and through an explicit scan service. Rules must be deterministic and explainable.
DQ-01 Possible duplicate customer
Signals and example weights:
- exact normalized email: 60;
- exact normalized phone: 50;
- exact postal code: 10;
- strong normalized full-name similarity: up to 30.
Open an issue at score >= 70. Store individual signals; do not expose a mysterious AI-only confidence.
Resolution:
- merge into selected survivor;
- reject as not duplicate;
- defer.
Merge rewires booking references, preserves the loser as a tombstone and audits before/after values.
DQ-02 Missing required field
Required for active customers: first name, last name and at least one of email or phone. Required for active vehicles: registration number, make, model and location.
Resolution: POST /provide-fields accepts only the fields the entity type actually
requires (rejects anything else), applies them, and re-runs the same missing-field check.
The issue resolves only once nothing required remains missing; a partial submission
updates the record and its evidence but leaves the issue open.
DQ-03 Odometer regression
Flag a newly recorded checkout, return-inspection or maintenance reading below the canonical odometer. The deterministic import scan compares booking, inspection and maintenance readings in chronological order. A return inspection's actual completion time is authoritative over the booking's planned end, so an early return cannot be mistaken for a later regression. Never lower the canonical value automatically.
When another regression is recorded while the vehicle already has an open DQ-03 issue, append the new source reference and signal to that issue. Do not silently discard the new evidence and do not open parallel issues for the same vehicle.
Resolution: POST /resolve-odometer-regression offers exactly two bounded decisions —
retain_canonical (the submitted reading is treated as erroneous; canonical is
untouched) or correct_reading. The correction option is offered only for an explicitly
named, correctable booking reading; checkout-only and maintenance-only issues can only
retain the canonical value. A corrected return updates the booking, its related return
inspection and the vehicle's canonical odometer in one transaction. A
correct_reading value below the current canonical is rejected, since it would not
resolve the regression, not silently applied. When one open issue contains several
source readings, correcting one removes only that booking/inspection evidence and keeps
the issue open until every remaining signal has received a bounded decision.
DQ-04 Booking overlap
Flag overlapping reserved or active bookings for one vehicle. Normal write APIs reject new overlaps; the seed/import path may create one controlled legacy conflict.
Resolution: POST /resolve-overlap blocks one of the two named overlapping bookings
(minimal safe resolution, not a scheduling calendar) and re-verifies no
reserved/active overlap remains among the issue's related bookings before resolving.
DQ-05 Vehicle status conflict
Examples:
- status
availablewhile an active booking exists; - status
rentedwithout an active booking; - status
availablewhile critical open quality issue exists; - status
maintenancewith an active booking.
Resolution: POST /apply-recommended-status computes a recommendation from one
authoritative function mirroring the conditions above, applies it, and re-runs the same
function to confirm the conflict is actually gone before resolving.
Lifecycle
Detection is idempotent by (rule_type, entity_type, entity_id) while open. Source-aware
rules additionally store stable evidence identity. For DQ-03 this is the tuple
(source_type, later_ref, later_km): an explicit retain_canonical decision suppresses
only that exact fact on later scans. A changed reading or a different source is actionable
again. Resolved issues remain historical. Reintroduced evidence creates a new issue whose
evidence carries reopened_from (the prior issue's reference) and previous_decision
(its resolved status), so a repeat problem is never presented as if no decision was ever
made.