Fix pricelist sync upsert and refresh tests
This commit is contained in:
@@ -17,6 +17,7 @@ import (
|
||||
"git.mchus.pro/mchus/quoteforge/internal/repository"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
var ErrOffline = errors.New("database is offline")
|
||||
@@ -357,6 +358,18 @@ func (s *Service) SyncPricelists() (int, error) {
|
||||
// Check if pricelist already exists locally
|
||||
existing, _ := s.localDB.GetLocalPricelistByServerID(pl.ID)
|
||||
if existing != nil {
|
||||
existing.Source = pl.Source
|
||||
existing.Version = pl.Version
|
||||
existing.Name = pl.Notification
|
||||
existing.CreatedAt = pl.CreatedAt
|
||||
existing.SyncedAt = time.Now()
|
||||
if err := s.localDB.SaveLocalPricelist(existing); err != nil {
|
||||
if syncErr == nil {
|
||||
syncErr = fmt.Errorf("refresh existing pricelist %s: %w", pl.Version, err)
|
||||
}
|
||||
slog.Warn("failed to refresh existing local pricelist header", "version", pl.Version, "error", err)
|
||||
continue
|
||||
}
|
||||
// Backfill items for legacy/partial local caches where only pricelist metadata exists.
|
||||
if s.localDB.CountLocalPricelistItems(existing.ID) == 0 {
|
||||
itemCount, err := s.SyncPricelistItems(existing.ID)
|
||||
@@ -468,24 +481,29 @@ func (s *Service) syncNewPricelistSnapshot(localPL *localdb.LocalPricelist) (int
|
||||
}
|
||||
|
||||
if err := s.localDB.DB().Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Create(localPL).Error; err != nil {
|
||||
if err := tx.Clauses(clause.OnConflict{
|
||||
Columns: []clause.Column{{Name: "server_id"}},
|
||||
DoUpdates: clause.Assignments(map[string]interface{}{
|
||||
"source": localPL.Source,
|
||||
"version": localPL.Version,
|
||||
"name": localPL.Name,
|
||||
"created_at": localPL.CreatedAt,
|
||||
"synced_at": localPL.SyncedAt,
|
||||
"is_used": localPL.IsUsed,
|
||||
}),
|
||||
}).Create(localPL).Error; err != nil {
|
||||
return fmt.Errorf("save local pricelist: %w", err)
|
||||
}
|
||||
if len(localItems) == 0 {
|
||||
return nil
|
||||
if localPL.ID == 0 {
|
||||
if err := tx.Where("server_id = ?", localPL.ServerID).First(localPL).Error; err != nil {
|
||||
return fmt.Errorf("reload local pricelist: %w", err)
|
||||
}
|
||||
}
|
||||
for i := range localItems {
|
||||
localItems[i].PricelistID = localPL.ID
|
||||
}
|
||||
batchSize := 500
|
||||
for i := 0; i < len(localItems); i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > len(localItems) {
|
||||
end = len(localItems)
|
||||
}
|
||||
if err := tx.CreateInBatches(localItems[i:end], batchSize).Error; err != nil {
|
||||
return fmt.Errorf("save local pricelist items: %w", err)
|
||||
}
|
||||
if err := replaceLocalPricelistItemsTx(tx, localPL.ID, localItems); err != nil {
|
||||
return fmt.Errorf("save local pricelist items: %w", err)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
@@ -496,6 +514,27 @@ func (s *Service) syncNewPricelistSnapshot(localPL *localdb.LocalPricelist) (int
|
||||
return len(localItems), nil
|
||||
}
|
||||
|
||||
func replaceLocalPricelistItemsTx(tx *gorm.DB, pricelistID uint, items []localdb.LocalPricelistItem) error {
|
||||
if err := tx.Where("pricelist_id = ?", pricelistID).Delete(&localdb.LocalPricelistItem{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
batchSize := 500
|
||||
for i := 0; i < len(items); i += batchSize {
|
||||
end := i + batchSize
|
||||
if end > len(items) {
|
||||
end = len(items)
|
||||
}
|
||||
if err := tx.CreateInBatches(items[i:end], batchSize).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) backfillUsedPricelistItemCategories(pricelistRepo *repository.PricelistRepository, activeServerPricelistIDs []uint) {
|
||||
if s.localDB == nil || pricelistRepo == nil {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user