Aug 17 - Update for customer inspector contract scope
This commit is contained in:
@@ -513,6 +513,53 @@ class SyncManager: ObservableObject {
|
||||
try await upsertAreas(for: apiFacility.id, facility: localFacility, context: context)
|
||||
}
|
||||
|
||||
// ── Prune facilities the server no longer returns ────────────
|
||||
// /api/v1/facilities is already scoped to what this user may see,
|
||||
// but cached rows were never removed — so a facility survived
|
||||
// locally after the inspector's contract was unassigned, after it
|
||||
// was deactivated, or after a different user signed in on the same
|
||||
// iPad. Every picker derives its CONTRACT list from these rows, so
|
||||
// one stale facility keeps a whole contract in the Start
|
||||
// Inspection picker forever. (Templates were already pruned this
|
||||
// way below; facilities were the gap.)
|
||||
//
|
||||
// Safe because we only reach here after BOTH requests succeeded —
|
||||
// a failed sync throws before this point and deletes nothing.
|
||||
let returnedFacilityIds = Set(uniqueFacilities.map { $0.id })
|
||||
|
||||
// Work that has not reached the server yet still needs its
|
||||
// facility row: ExecuteInspectionView and MyInspectionsView resolve
|
||||
// the name by serverId and would otherwise show "Unknown Facility"
|
||||
// on a draft the inspector is midway through. Keep those rows but
|
||||
// mark them unavailable so no NEW work can be started against them;
|
||||
// they are pruned on a later sync once the work has been submitted.
|
||||
let localInspections = try context.fetch(FetchDescriptor<LocalInspection>())
|
||||
let localIssues = try context.fetch(FetchDescriptor<LocalIssue>())
|
||||
var inUseFacilityIds = Set(
|
||||
localInspections
|
||||
.filter { $0.syncStatus != "synced" }
|
||||
.map { $0.facilityServerId }
|
||||
)
|
||||
// Device-created issues too: their facilityNameCache is nil until
|
||||
// the server round-trips, and the issue DETAIL view has no cache
|
||||
// fallback — it would read "Unknown Facility" outright.
|
||||
inUseFacilityIds.formUnion(
|
||||
localIssues
|
||||
.filter { $0.syncStatus != "synced" }
|
||||
.map { $0.facilityServerId }
|
||||
)
|
||||
|
||||
for existing in existingFacilities {
|
||||
guard !returnedFacilityIds.contains(existing.serverId) else { continue }
|
||||
if inUseFacilityIds.contains(existing.serverId) {
|
||||
// Retained for display only. The pickers filter on
|
||||
// isActive, so it cannot be chosen for new work.
|
||||
existing.isActive = false
|
||||
} else {
|
||||
context.delete(existing) // cascades to its areas
|
||||
}
|
||||
}
|
||||
|
||||
let existingTemplates = try context.fetch(FetchDescriptor<LocalTemplate>())
|
||||
let templateMap = Dictionary(
|
||||
existingTemplates.map { ($0.serverId, $0) },
|
||||
|
||||
Reference in New Issue
Block a user