Make full sync push pending and pull projects/configurations
This commit is contained in:
@@ -182,14 +182,23 @@ func (h *SyncHandler) SyncPricelists(c *gin.Context) {
|
||||
|
||||
// SyncAllResponse represents result of full sync
|
||||
type SyncAllResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
ComponentsSynced int `json:"components_synced"`
|
||||
PricelistsSynced int `json:"pricelists_synced"`
|
||||
Duration string `json:"duration"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
PendingPushed int `json:"pending_pushed"`
|
||||
ComponentsSynced int `json:"components_synced"`
|
||||
PricelistsSynced int `json:"pricelists_synced"`
|
||||
ProjectsImported int `json:"projects_imported"`
|
||||
ProjectsUpdated int `json:"projects_updated"`
|
||||
ProjectsSkipped int `json:"projects_skipped"`
|
||||
ConfigurationsImported int `json:"configurations_imported"`
|
||||
ConfigurationsUpdated int `json:"configurations_updated"`
|
||||
ConfigurationsSkipped int `json:"configurations_skipped"`
|
||||
Duration string `json:"duration"`
|
||||
}
|
||||
|
||||
// SyncAll syncs both components and pricelists
|
||||
// SyncAll performs full bidirectional sync:
|
||||
// - push pending local changes (projects/configurations) to server
|
||||
// - pull components, pricelists, projects, and configurations from server
|
||||
// POST /api/sync/all
|
||||
func (h *SyncHandler) SyncAll(c *gin.Context) {
|
||||
if !h.checkOnline() {
|
||||
@@ -201,7 +210,18 @@ func (h *SyncHandler) SyncAll(c *gin.Context) {
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
var componentsSynced, pricelistsSynced int
|
||||
var pendingPushed, componentsSynced, pricelistsSynced int
|
||||
|
||||
// Push local pending changes first (projects/configurations)
|
||||
pendingPushed, err := h.syncService.PushPendingChanges()
|
||||
if err != nil {
|
||||
slog.Error("pending push failed during full sync", "error", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"error": "Pending changes push failed: " + err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Sync components
|
||||
mariaDB, err := h.connMgr.GetDB()
|
||||
@@ -231,17 +251,54 @@ func (h *SyncHandler) SyncAll(c *gin.Context) {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"error": "Pricelist sync failed: " + err.Error(),
|
||||
"pending_pushed": pendingPushed,
|
||||
"components_synced": componentsSynced,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
projectsResult, err := h.syncService.ImportProjectsToLocal()
|
||||
if err != nil {
|
||||
slog.Error("project import failed during full sync", "error", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"error": "Project import failed: " + err.Error(),
|
||||
"pending_pushed": pendingPushed,
|
||||
"components_synced": componentsSynced,
|
||||
"pricelists_synced": pricelistsSynced,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
configsResult, err := h.syncService.ImportConfigurationsToLocal()
|
||||
if err != nil {
|
||||
slog.Error("configuration import failed during full sync", "error", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"error": "Configuration import failed: " + err.Error(),
|
||||
"pending_pushed": pendingPushed,
|
||||
"components_synced": componentsSynced,
|
||||
"pricelists_synced": pricelistsSynced,
|
||||
"projects_imported": projectsResult.Imported,
|
||||
"projects_updated": projectsResult.Updated,
|
||||
"projects_skipped": projectsResult.Skipped,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, SyncAllResponse{
|
||||
Success: true,
|
||||
Message: "Full sync completed successfully",
|
||||
ComponentsSynced: componentsSynced,
|
||||
PricelistsSynced: pricelistsSynced,
|
||||
Duration: time.Since(startTime).String(),
|
||||
Success: true,
|
||||
Message: "Full sync completed successfully",
|
||||
PendingPushed: pendingPushed,
|
||||
ComponentsSynced: componentsSynced,
|
||||
PricelistsSynced: pricelistsSynced,
|
||||
ProjectsImported: projectsResult.Imported,
|
||||
ProjectsUpdated: projectsResult.Updated,
|
||||
ProjectsSkipped: projectsResult.Skipped,
|
||||
ConfigurationsImported: configsResult.Imported,
|
||||
ConfigurationsUpdated: configsResult.Updated,
|
||||
ConfigurationsSkipped: configsResult.Skipped,
|
||||
Duration: time.Since(startTime).String(),
|
||||
})
|
||||
h.syncService.RecordSyncHeartbeat()
|
||||
}
|
||||
@@ -396,6 +453,9 @@ func (h *SyncHandler) GetUsersStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Keep current client heartbeat fresh so app version is available in the table.
|
||||
h.syncService.RecordSyncHeartbeat()
|
||||
|
||||
users, err := h.syncService.ListUserSyncStatuses(threshold)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
||||
Reference in New Issue
Block a user