package localdb import ( "database/sql/driver" "encoding/json" "errors" "time" ) // AppSetting stores application settings in local SQLite type AppSetting struct { Key string `gorm:"primaryKey" json:"key"` Value string `gorm:"not null" json:"value"` UpdatedAt time.Time `json:"updated_at"` } func (AppSetting) TableName() string { return "app_settings" } // LocalConfigItem represents an item in a configuration type LocalConfigItem struct { LotName string `json:"lot_name"` Quantity int `json:"quantity"` UnitPrice float64 `json:"unit_price"` } // LocalConfigItems is a slice of LocalConfigItem that can be stored as JSON type LocalConfigItems []LocalConfigItem func (c LocalConfigItems) Value() (driver.Value, error) { return json.Marshal(c) } func (c *LocalConfigItems) Scan(value interface{}) error { if value == nil { *c = make(LocalConfigItems, 0) return nil } var bytes []byte switch v := value.(type) { case []byte: bytes = v case string: bytes = []byte(v) default: return errors.New("type assertion failed for LocalConfigItems") } return json.Unmarshal(bytes, c) } func (c LocalConfigItems) Total() float64 { var total float64 for _, item := range c { total += item.UnitPrice * float64(item.Quantity) } return total } // LocalConfiguration stores configurations in local SQLite type LocalConfiguration struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` UUID string `gorm:"uniqueIndex;not null" json:"uuid"` ServerID *uint `json:"server_id"` // ID on MariaDB server, NULL if local only CurrentVersionID *string `gorm:"index" json:"current_version_id,omitempty"` IsActive bool `gorm:"default:true;index" json:"is_active"` Name string `gorm:"not null" json:"name"` Items LocalConfigItems `gorm:"type:text" json:"items"` // JSON stored as text in SQLite TotalPrice *float64 `json:"total_price"` CustomPrice *float64 `json:"custom_price"` Notes string `json:"notes"` IsTemplate bool `gorm:"default:false" json:"is_template"` ServerCount int `gorm:"default:1" json:"server_count"` PriceUpdatedAt *time.Time `gorm:"type:timestamp" json:"price_updated_at,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` SyncedAt *time.Time `json:"synced_at"` SyncStatus string `gorm:"default:'local'" json:"sync_status"` // 'local', 'synced', 'modified' OriginalUserID uint `json:"original_user_id"` // UserID from MariaDB for reference OriginalUsername string `gorm:"not null;default:'';index" json:"original_username"` CurrentVersion *LocalConfigurationVersion `gorm:"foreignKey:CurrentVersionID;references:ID" json:"current_version,omitempty"` Versions []LocalConfigurationVersion `gorm:"foreignKey:ConfigurationUUID;references:UUID" json:"versions,omitempty"` } func (LocalConfiguration) TableName() string { return "local_configurations" } // LocalConfigurationVersion stores immutable full snapshots for each configuration version type LocalConfigurationVersion struct { ID string `gorm:"primaryKey" json:"id"` ConfigurationUUID string `gorm:"not null;index:idx_lcv_config_created,priority:1;index:idx_lcv_config_version,priority:1;uniqueIndex:idx_lcv_config_version_unique,priority:1" json:"configuration_uuid"` VersionNo int `gorm:"not null;index:idx_lcv_config_version,sort:desc,priority:2;uniqueIndex:idx_lcv_config_version_unique,priority:2" json:"version_no"` 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"` } func (LocalConfigurationVersion) TableName() string { return "local_configuration_versions" } // LocalPricelist stores cached pricelists from server type LocalPricelist struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` ServerID uint `gorm:"not null" json:"server_id"` // ID on MariaDB server Version string `gorm:"uniqueIndex;not null" json:"version"` Name string `json:"name"` CreatedAt time.Time `json:"created_at"` SyncedAt time.Time `json:"synced_at"` IsUsed bool `gorm:"default:false" json:"is_used"` // Used by any local configuration } func (LocalPricelist) TableName() string { return "local_pricelists" } // LocalPricelistItem stores pricelist items type LocalPricelistItem struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` PricelistID uint `gorm:"not null;index" json:"pricelist_id"` LotName string `gorm:"not null" json:"lot_name"` Price float64 `gorm:"not null" json:"price"` } func (LocalPricelistItem) TableName() string { return "local_pricelist_items" } // LocalComponent stores cached components for offline search type LocalComponent struct { LotName string `gorm:"primaryKey" json:"lot_name"` LotDescription string `json:"lot_description"` Category string `json:"category"` Model string `json:"model"` CurrentPrice *float64 `json:"current_price"` SyncedAt time.Time `json:"synced_at"` } func (LocalComponent) TableName() string { return "local_components" } // PendingChange stores changes that need to be synced to the server type PendingChange struct { ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` EntityType string `gorm:"not null;index" json:"entity_type"` // "configuration", "project", "specification" EntityUUID string `gorm:"not null;index" json:"entity_uuid"` Operation string `gorm:"not null" json:"operation"` // "create", "update", "rollback", "deactivate", "reactivate", "delete" Payload string `gorm:"type:text" json:"payload"` // JSON snapshot of the entity CreatedAt time.Time `gorm:"not null" json:"created_at"` Attempts int `gorm:"default:0" json:"attempts"` // Retry count for sync LastError string `gorm:"type:text" json:"last_error,omitempty"` } func (PendingChange) TableName() string { return "pending_changes" }