06/11 Fix some errors: submission datetime incorrect; inspection & issue not linked, etc
This commit is contained in:
@@ -310,25 +310,56 @@ class SyncManager: ObservableObject {
|
||||
.filter { $0.syncStatus == "pending" }
|
||||
.sorted { $0.createdAt < $1.createdAt }
|
||||
|
||||
// Pre-fetch all inspections to check parent sync status.
|
||||
// Pre-fetch all inspections to check parent sync status AND to resolve
|
||||
// the parent's serverId. The allInspections array is the same set of
|
||||
// objects that processInspectionQueue updated (serverId written in-memory
|
||||
// this same triggerSync pass), so looking up serverId here is reliable.
|
||||
// issue.inspection?.serverId is NOT reliable — it navigates a @Relationship
|
||||
// that SwiftData may have loaded as a separate object instance before
|
||||
// processInspectionQueue wrote the serverId back, leaving it nil even
|
||||
// when the parent inspection already synced successfully this same pass.
|
||||
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. 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()
|
||||
syncError = "Issue \(issue.localId.prefix(8))\u{2026} blocked: parent inspection did not sync."
|
||||
continue
|
||||
let parentLocalId = issue.inspectionLocalId
|
||||
let parent = allInspections.first(where: { $0.localId == parentLocalId })
|
||||
|
||||
// ── Parent inspection status guards ───────────────────────────
|
||||
if let parent {
|
||||
switch parent.syncStatus {
|
||||
case "failed":
|
||||
// Parent permanently failed — this issue can never be linked.
|
||||
// Mark it failed immediately rather than creating an orphaned
|
||||
// server record with no inspection_id.
|
||||
issue.syncStatus = "failed"
|
||||
issue.syncErrorMessage = "Parent inspection failed to sync — issue cannot be submitted."
|
||||
try? context.save()
|
||||
syncError = "Issue \(issue.localId.prefix(8))\u{2026} blocked: parent inspection did not sync."
|
||||
continue
|
||||
|
||||
case "synced":
|
||||
// Parent has a serverId — proceed and link correctly.
|
||||
break
|
||||
|
||||
default:
|
||||
// Parent is still "pending" (draft or awaiting submission).
|
||||
// Submitting now would create a server issue with no
|
||||
// inspection_id — the issue and inspection appear unlinked
|
||||
// on the web. Defer until the next triggerSync() pass, by
|
||||
// which point processInspectionQueue will have synced the
|
||||
// parent and assigned it a serverId.
|
||||
continue
|
||||
}
|
||||
}
|
||||
// parent == nil means inspectionLocalId == "" (standalone issue) — submit without inspection_id.
|
||||
|
||||
// Resolve the parent's server ID. Safe to force-unwrap serverId
|
||||
// here — the switch above guarantees parent.syncStatus == "synced"
|
||||
// when parent is non-nil, so serverId is always set at this point.
|
||||
let inspectionServerId = parent?.serverId
|
||||
|
||||
do {
|
||||
let issueId = try await APIClient.shared.submitIssue(issue)
|
||||
let issueId = try await APIClient.shared.submitIssue(issue, inspectionServerId: inspectionServerId)
|
||||
issue.serverId = issueId
|
||||
issue.syncStatus = "synced"
|
||||
// Photos are now represented by photoServerPaths on the server.
|
||||
|
||||
Reference in New Issue
Block a user