Duplicate Tenant Detection
Status: Proposed Owner: @bilal Last Updated: 2026-02-15
Detect returning or known tenants when creating a new tenant record.
Trigger
On tenant creation, before save, check for soft-deleted tenants matching:
- Phone (exact, E.164 normalised)
- Email (exact, lowercase)
- Match on either field, not both required
Scope
- Same property — “Returning tenant” (lived here before)
- Same organisation — “Known tenant” (lived at another property)
Warning UI
┌──────────────────────────────────────────────────┐
│ This person was previously a tenant │
├──────────────────────────────────────────────────┤
│ Name: John Smith │
│ Previous property: 123 High Street │
│ Tenancy: 15 Mar 2023 → 20 Dec 2024 │
│ Issues reported: 7 (2 unresolved at move-out) │
│ Priority: HIGH │
├──────────────────────────────────────────────────┤
│ [Restore Previous] [Create New Anyway] [Cancel] │
└──────────────────────────────────────────────────┘
Actions
| Action | Behaviour |
|---|---|
| Restore Previous | Set deletedAt: null, update propertyId, status → active |
| Create New Anyway | New tenant record, no link to history |
| Cancel | Close modal |
Priority Flag Behaviour
| Previous Priority | Behaviour |
|---|---|
| NORMAL | Standard warning |
| HIGH | Warning highlighted amber |
| CRITICAL | Red highlight, require confirmation checkbox |
Edge Cases
| Case | Handling |
|---|---|
| Multiple matches | Show most recent first |
| Active match (not deleted) | Error: “Tenant already exists at [property]“ |
| Phone + email match different records | Show both |
| Restoring to different property | Update propertyId |
Not in Scope (V1)
- Fuzzy name matching
- Blacklist/block functionality
- Cross-organisation matching
Implementation
- New GraphQL query
duplicateTenantCheck - Frontend modal component
- Restore mutation (extend
updateTenantto handledeletedAt: null) - Snapshot
openIssueCounton soft-delete (new field)