Drop qt_users dependency for configs and track app version
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package appmeta
|
||||
|
||||
import "sync/atomic"
|
||||
|
||||
var appVersion atomic.Value
|
||||
|
||||
func init() {
|
||||
appVersion.Store("dev")
|
||||
}
|
||||
|
||||
// SetVersion configures the running application version string.
|
||||
func SetVersion(v string) {
|
||||
if v == "" {
|
||||
v = "dev"
|
||||
}
|
||||
appVersion.Store(v)
|
||||
}
|
||||
|
||||
// Version returns the running application version string.
|
||||
func Version() string {
|
||||
if v, ok := appVersion.Load().(string); ok && v != "" {
|
||||
return v
|
||||
}
|
||||
return "dev"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func ConfigurationToLocal(cfg *models.Configuration) *LocalConfiguration {
|
||||
CreatedAt: cfg.CreatedAt,
|
||||
UpdatedAt: time.Now(),
|
||||
SyncStatus: "pending",
|
||||
OriginalUserID: cfg.UserID,
|
||||
OriginalUserID: derefUint(cfg.UserID),
|
||||
OriginalUsername: cfg.OwnerUsername,
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ func LocalToConfiguration(local *LocalConfiguration) *models.Configuration {
|
||||
|
||||
cfg := &models.Configuration{
|
||||
UUID: local.UUID,
|
||||
UserID: local.OriginalUserID,
|
||||
OwnerUsername: local.OriginalUsername,
|
||||
Name: local.Name,
|
||||
Items: items,
|
||||
@@ -76,10 +75,21 @@ func LocalToConfiguration(local *LocalConfiguration) *models.Configuration {
|
||||
if local.ServerID != nil {
|
||||
cfg.ID = *local.ServerID
|
||||
}
|
||||
if local.OriginalUserID != 0 {
|
||||
userID := local.OriginalUserID
|
||||
cfg.UserID = &userID
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func derefUint(v *uint) uint {
|
||||
if v == nil {
|
||||
return 0
|
||||
}
|
||||
return *v
|
||||
}
|
||||
|
||||
// PricelistToLocal converts models.Pricelist to LocalPricelist
|
||||
func PricelistToLocal(pl *models.Pricelist) *LocalPricelist {
|
||||
name := pl.Notification
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/quoteforge/internal/appmeta"
|
||||
"github.com/glebarez/sqlite"
|
||||
uuidpkg "github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
@@ -238,6 +239,7 @@ func (l *LocalDB) DeactivateConfiguration(uuid string) error {
|
||||
VersionNo: maxVersion + 1,
|
||||
Data: snapshot,
|
||||
ChangeNote: ¬e,
|
||||
AppVersion: appmeta.Version(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if err := tx.Create(version).Error; err != nil {
|
||||
|
||||
@@ -103,6 +103,7 @@ func backfillConfigurationVersions(tx *gorm.DB) error {
|
||||
VersionNo: 1,
|
||||
Data: snapshot,
|
||||
ChangeNote: ¬e,
|
||||
AppVersion: "backfill",
|
||||
CreatedAt: chooseNonZeroTime(cfg.CreatedAt, time.Now()),
|
||||
}
|
||||
if err := tx.Create(&version).Error; err != nil {
|
||||
|
||||
@@ -94,6 +94,7 @@ type LocalConfigurationVersion struct {
|
||||
Data string `gorm:"type:text;not null" json:"data"`
|
||||
ChangeNote *string `json:"change_note,omitempty"`
|
||||
CreatedBy *string `json:"created_by,omitempty"`
|
||||
AppVersion string `gorm:"size:64" json:"app_version,omitempty"`
|
||||
CreatedAt time.Time `gorm:"not null;autoCreateTime;index:idx_lcv_config_created,sort:desc,priority:2" json:"created_at"`
|
||||
Configuration *LocalConfiguration `gorm:"foreignKey:ConfigurationUUID;references:UUID" json:"configuration,omitempty"`
|
||||
}
|
||||
|
||||
@@ -42,8 +42,9 @@ func (c ConfigItems) Total() float64 {
|
||||
type Configuration struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
UUID string `gorm:"size:36;uniqueIndex;not null" json:"uuid"`
|
||||
UserID uint `gorm:"not null" json:"user_id"` // Legacy owner field (kept for backward compatibility)
|
||||
UserID *uint `json:"user_id,omitempty"` // Legacy field, no longer required for ownership
|
||||
OwnerUsername string `gorm:"size:100;not null;default:'';index" json:"owner_username"`
|
||||
AppVersion string `gorm:"size:64" json:"app_version,omitempty"`
|
||||
Name string `gorm:"size:200;not null" json:"name"`
|
||||
Items ConfigItems `gorm:"type:json;not null" json:"items"`
|
||||
TotalPrice *float64 `gorm:"type:decimal(12,2)" json:"total_price"`
|
||||
|
||||
@@ -19,7 +19,7 @@ func (r *ConfigurationRepository) Create(config *models.Configuration) error {
|
||||
|
||||
func (r *ConfigurationRepository) GetByID(id uint) (*models.Configuration, error) {
|
||||
var config models.Configuration
|
||||
err := r.db.Preload("User").First(&config, id).Error
|
||||
err := r.db.First(&config, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -28,7 +28,7 @@ func (r *ConfigurationRepository) GetByID(id uint) (*models.Configuration, error
|
||||
|
||||
func (r *ConfigurationRepository) GetByUUID(uuid string) (*models.Configuration, error) {
|
||||
var config models.Configuration
|
||||
err := r.db.Preload("User").Where("uuid = ?", uuid).First(&config).Error
|
||||
err := r.db.Where("uuid = ?", uuid).First(&config).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -47,12 +47,11 @@ func (r *ConfigurationRepository) ListByUser(ownerUsername string, offset, limit
|
||||
var configs []models.Configuration
|
||||
var total int64
|
||||
|
||||
ownerScope := "owner_username = ? OR (COALESCE(owner_username, '') = '' AND user_id IN (SELECT id FROM qt_users WHERE username = ?))"
|
||||
ownerScope := "owner_username = ?"
|
||||
|
||||
r.db.Model(&models.Configuration{}).Where(ownerScope, ownerUsername, ownerUsername).Count(&total)
|
||||
r.db.Model(&models.Configuration{}).Where(ownerScope, ownerUsername).Count(&total)
|
||||
err := r.db.
|
||||
Preload("User").
|
||||
Where(ownerScope, ownerUsername, ownerUsername).
|
||||
Where(ownerScope, ownerUsername).
|
||||
Order("created_at DESC").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
@@ -67,7 +66,6 @@ func (r *ConfigurationRepository) ListTemplates(offset, limit int) ([]models.Con
|
||||
|
||||
r.db.Model(&models.Configuration{}).Where("is_template = ?", true).Count(&total)
|
||||
err := r.db.
|
||||
Preload("User").
|
||||
Where("is_template = ?", true).
|
||||
Order("created_at DESC").
|
||||
Offset(offset).
|
||||
@@ -84,7 +82,6 @@ func (r *ConfigurationRepository) ListAll(offset, limit int) ([]models.Configura
|
||||
|
||||
r.db.Model(&models.Configuration{}).Count(&total)
|
||||
err := r.db.
|
||||
Preload("User").
|
||||
Order("created_at DESC").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/quoteforge/internal/appmeta"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/localdb"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/models"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/services/sync"
|
||||
@@ -820,6 +821,7 @@ func (s *LocalConfigurationService) appendVersionTx(
|
||||
Data: snapshot,
|
||||
ChangeNote: &changeNote,
|
||||
CreatedBy: createdByPtr,
|
||||
AppVersion: appmeta.Version(),
|
||||
}
|
||||
|
||||
if err := tx.Create(version).Error; err != nil {
|
||||
@@ -915,6 +917,7 @@ func (s *LocalConfigurationService) rollbackToVersion(configurationUUID string,
|
||||
Data: target.Data,
|
||||
ChangeNote: &changeNote,
|
||||
CreatedBy: stringPtrOrNil(userID),
|
||||
AppVersion: appmeta.Version(),
|
||||
}
|
||||
|
||||
if err := tx.Create(version).Error; err != nil {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/quoteforge/internal/appmeta"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/db"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/localdb"
|
||||
"git.mchus.pro/mchus/quoteforge/internal/models"
|
||||
@@ -605,15 +606,10 @@ func (s *Service) ensureConfigurationOwner(mariaDB *gorm.DB, cfg *models.Configu
|
||||
return fmt.Errorf("owner username is empty")
|
||||
}
|
||||
|
||||
userID, err := models.EnsureDBUser(mariaDB, ownerUsername)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userID == 0 {
|
||||
return fmt.Errorf("resolved user ID is 0 for owner %q", ownerUsername)
|
||||
}
|
||||
|
||||
cfg.UserID = userID
|
||||
// user_id is legacy and no longer used for ownership in local-first mode.
|
||||
// Keep it NULL on writes; ownership is represented by owner_username.
|
||||
cfg.UserID = nil
|
||||
cfg.AppVersion = appmeta.Version()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user