05/08 Updated code: fix some issues 3
This commit is contained in:
@@ -48,7 +48,9 @@ class SyncManager: ObservableObject {
|
||||
// ── Full Sync ─────────────────────────────────────────────────────────
|
||||
|
||||
func triggerSync() async {
|
||||
guard isOnline, let context = modelContext else { return }
|
||||
// Do not sync unless authenticated — avoids 401 loops before
|
||||
// restoreSession() completes on first launch.
|
||||
guard isOnline, let context = modelContext, AuthManager.shared.isAuthenticated else { return }
|
||||
isSyncing = true
|
||||
syncError = nil
|
||||
defer { isSyncing = false }
|
||||
@@ -116,8 +118,6 @@ class SyncManager: ObservableObject {
|
||||
// ── Outbox: Inspections ───────────────────────────────────────────────
|
||||
|
||||
private func processInspectionQueue(context: ModelContext) async {
|
||||
// Fetch all and filter in Swift to avoid #Predicate compound
|
||||
// string comparison issues across Xcode versions.
|
||||
guard let all = try? context.fetch(FetchDescriptor<LocalInspection>()) else { return }
|
||||
let pending = all
|
||||
.filter { $0.status == "completed" && $0.syncStatus == "pending" }
|
||||
@@ -135,10 +135,7 @@ class SyncManager: ObservableObject {
|
||||
inspection.syncStatus = "synced"
|
||||
inspection.status = "synced"
|
||||
|
||||
// ── Clear follow-up flag on parent ────────────────────────
|
||||
// Use parentLocalId (always set at creation) rather than
|
||||
// parentServerId (nil until parent syncs) so the badge clears
|
||||
// regardless of whether the parent has been synced yet.
|
||||
// Clear follow-up flag on parent.
|
||||
if let parentLocalId = inspection.parentLocalId {
|
||||
let allInspections = try? context.fetch(FetchDescriptor<LocalInspection>())
|
||||
if let parent = allInspections?.first(where: { $0.localId == parentLocalId }) {
|
||||
@@ -169,17 +166,16 @@ class SyncManager: ObservableObject {
|
||||
.filter { $0.syncStatus == "pending" }
|
||||
.sorted { $0.createdAt < $1.createdAt }
|
||||
|
||||
// Pre-fetch all LocalInspections once for the parent-failed guard below.
|
||||
// Pre-fetch all inspections to check parent sync status.
|
||||
let allInspections = (try? context.fetch(FetchDescriptor<LocalInspection>())) ?? []
|
||||
|
||||
for issue in pending {
|
||||
// Guard: if the parent inspection permanently failed to sync, submitting
|
||||
// this issue without an inspection_id would create an orphaned server
|
||||
// record. Skip the issue and mark it failed so the inspector can see
|
||||
// the error rather than losing the association silently.
|
||||
if let parentInspection = allInspections.first(where: {
|
||||
$0.localId == issue.inspectionLocalId
|
||||
}), parentInspection.syncStatus == "failed" {
|
||||
// Guard: if the parent inspection permanently failed to sync,
|
||||
// submitting this issue without an inspection_id would create an
|
||||
// orphaned server record. Mark it failed immediately instead.
|
||||
let parentId = issue.inspectionLocalId
|
||||
let parent = allInspections.first(where: { $0.localId == parentId })
|
||||
if parent?.syncStatus == "failed" {
|
||||
issue.syncStatus = "failed"
|
||||
issue.syncErrorMessage = "Parent inspection failed to sync — issue cannot be submitted."
|
||||
try? context.save()
|
||||
@@ -210,8 +206,6 @@ class SyncManager: ObservableObject {
|
||||
guard isOnline, let context = modelContext else { return }
|
||||
|
||||
do {
|
||||
// Sequential fetches avoid Swift 6 actor-isolation warnings
|
||||
// on Decodable structs used across async boundaries.
|
||||
let facilitiesData: FacilitiesResponseData =
|
||||
try await APIClient.shared.request("/api/v1/facilities")
|
||||
let templatesData: TemplatesResponseData =
|
||||
|
||||
Reference in New Issue
Block a user