Fix sync errors for duplicate projects and add modal scrolling

Root cause: Projects with duplicate (code, variant) pairs fail to sync
due to unique constraint on server. Example: multiple "OPS-1934" projects
with variant="Dell" where one already exists on server.

Fixes:
1. Sync service now detects duplicate (code, variant) on server and links
   local project to existing server project instead of failing
2. Local repair checks for duplicate (code, variant) pairs and deduplicates
   by appending UUID suffix to variant
3. Modal now scrollable with fixed header/footer (max-h-90vh)

This allows users to sync projects that were created offline with
conflicting codes/variants without losing data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 21:25:22 +03:00
parent 8be424aa1c
commit 1606143b9f
3 changed files with 48 additions and 9 deletions
+17 -1
View File
@@ -1088,7 +1088,9 @@ func (l *LocalDB) RepairPendingChanges() (int, []string, error) {
return repaired, remainingErrors, nil
}
// repairProjectChange validates and fixes project data
// repairProjectChange validates and fixes project data.
// Note: This only validates local data. Server-side conflicts (like duplicate code+variant)
// are handled by sync service layer with deduplication logic.
func (l *LocalDB) repairProjectChange(change *PendingChange) error {
project, err := l.GetProjectByUUID(change.EntityUUID)
if err != nil {
@@ -1123,6 +1125,20 @@ func (l *LocalDB) repairProjectChange(change *PendingChange) error {
modified = true
}
// Check for local duplicates with same (code, variant)
var duplicate LocalProject
err = l.db.Where("code = ? AND variant = ? AND uuid != ?", project.Code, project.Variant, project.UUID).
First(&duplicate).Error
if err == nil {
// Found local duplicate - deduplicate by appending UUID suffix to variant
if project.Variant == "" {
project.Variant = project.UUID[:8]
} else {
project.Variant = project.Variant + "-" + project.UUID[:8]
}
modified = true
}
if modified {
if err := l.SaveProject(project); err != nil {
return fmt.Errorf("saving repaired project: %w", err)