|
1 | 1 | package database |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "database/sql" |
4 | 5 | "log" |
| 6 | + "fmt" |
5 | 7 | "strings" |
| 8 | + "time" |
6 | 9 |
|
7 | 10 | _ "github.com/glebarez/go-sqlite" |
8 | 11 | "github.com/itemplus/backend/internal/config" |
| 12 | + "github.com/itemplus/backend/internal/services" |
9 | 13 | "github.com/jmoiron/sqlx" |
10 | 14 | ) |
11 | 15 |
|
@@ -61,6 +65,35 @@ func createTables() { |
61 | 65 | `CREATE INDEX IF NOT EXISTS idx_users_apple_sub ON users(apple_sub)`, |
62 | 66 | `CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)`, |
63 | 67 |
|
| 68 | + // Label templates |
| 69 | + `CREATE TABLE IF NOT EXISTS label_templates ( |
| 70 | + id INTEGER PRIMARY KEY AUTOINCREMENT, |
| 71 | + system_key TEXT UNIQUE, |
| 72 | + name TEXT NOT NULL, |
| 73 | + description TEXT, |
| 74 | + target TEXT NOT NULL, |
| 75 | + dpi INTEGER NOT NULL DEFAULT 600, |
| 76 | + width_mm INTEGER NOT NULL, |
| 77 | + height_mm INTEGER NOT NULL, |
| 78 | + gap_mm REAL NOT NULL DEFAULT 3, |
| 79 | + speed INTEGER NOT NULL DEFAULT 4, |
| 80 | + density INTEGER NOT NULL DEFAULT 8, |
| 81 | + direction INTEGER NOT NULL DEFAULT 1, |
| 82 | + reference_x INTEGER NOT NULL DEFAULT 0, |
| 83 | + reference_y INTEGER NOT NULL DEFAULT 0, |
| 84 | + shift_x INTEGER NOT NULL DEFAULT 0, |
| 85 | + shift_y INTEGER NOT NULL DEFAULT 0, |
| 86 | + copies_default INTEGER NOT NULL DEFAULT 1, |
| 87 | + is_default BOOLEAN DEFAULT 0, |
| 88 | + is_system BOOLEAN DEFAULT 0, |
| 89 | + is_active BOOLEAN DEFAULT 1, |
| 90 | + tspl_template TEXT NOT NULL, |
| 91 | + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
| 92 | + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP |
| 93 | + )`, |
| 94 | + `CREATE INDEX IF NOT EXISTS idx_label_templates_target ON label_templates(target)`, |
| 95 | + `CREATE INDEX IF NOT EXISTS idx_label_templates_active ON label_templates(is_active)`, |
| 96 | + |
64 | 97 | // Device Sessions |
65 | 98 | `CREATE TABLE IF NOT EXISTS device_sessions ( |
66 | 99 | id INTEGER PRIMARY KEY AUTOINCREMENT, |
@@ -117,6 +150,69 @@ func createTables() { |
117 | 150 | DB.MustExec(sql) |
118 | 151 | } |
119 | 152 |
|
| 153 | + if _, err := DB.Exec("ALTER TABLE label_templates ADD COLUMN dpi INTEGER NOT NULL DEFAULT 600"); err != nil && !strings.Contains(strings.ToLower(err.Error()), "duplicate column") { |
| 154 | + log.Fatalf("Could not migrate label_templates.dpi: %v", err) |
| 155 | + } |
| 156 | + |
| 157 | + ensureDefaultLabelTemplates() |
| 158 | +} |
| 159 | + |
| 160 | +func ensureDefaultLabelTemplates() { |
| 161 | + now := time.Now().UTC().Format(time.RFC3339) |
| 162 | + defaults := services.DefaultLabelTemplates() |
| 163 | + |
| 164 | + if _, err := DB.Exec( |
| 165 | + `UPDATE label_templates |
| 166 | + SET tspl_template = REPLACE(tspl_template, 'PRINT {{copies}}', 'PRINT 1'), |
| 167 | + updated_at = ? |
| 168 | + WHERE is_system = 1 AND tspl_template LIKE '%PRINT {{copies}}%'`, |
| 169 | + now, |
| 170 | + ); err != nil { |
| 171 | + log.Printf("Could not normalize legacy system label templates: %v", err) |
| 172 | + } |
| 173 | + |
| 174 | + allowedKeys := make([]string, 0, len(defaults)) |
| 175 | + for _, def := range defaults { |
| 176 | + allowedKeys = append(allowedKeys, def.SystemKey) |
| 177 | + } |
| 178 | + |
| 179 | + if len(allowedKeys) > 0 { |
| 180 | + placeholders := strings.TrimSuffix(strings.Repeat("?,", len(allowedKeys)), ",") |
| 181 | + args := make([]interface{}, 0, len(allowedKeys)) |
| 182 | + for _, key := range allowedKeys { |
| 183 | + args = append(args, key) |
| 184 | + } |
| 185 | + query := fmt.Sprintf("DELETE FROM label_templates WHERE is_system = 1 AND system_key NOT IN (%s)", placeholders) |
| 186 | + if _, err := DB.Exec(query, args...); err != nil { |
| 187 | + log.Printf("Could not cleanup legacy system label templates: %v", err) |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + for _, def := range defaults { |
| 192 | + var existingID int |
| 193 | + err := DB.Get(&existingID, "SELECT id FROM label_templates WHERE system_key = ?", def.SystemKey) |
| 194 | + if err == nil { |
| 195 | + continue |
| 196 | + } |
| 197 | + if err != sql.ErrNoRows { |
| 198 | + log.Printf("Could not query label template %s: %v", def.SystemKey, err) |
| 199 | + continue |
| 200 | + } |
| 201 | + |
| 202 | + _, err = DB.Exec( |
| 203 | + `INSERT INTO label_templates ( |
| 204 | + system_key, name, description, target, dpi, width_mm, height_mm, gap_mm, speed, density, direction, |
| 205 | + reference_x, reference_y, shift_x, shift_y, copies_default, is_default, is_system, is_active, |
| 206 | + tspl_template, created_at, updated_at |
| 207 | + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, 1, ?, ?, ?)`, |
| 208 | + def.SystemKey, def.Name, def.Description, def.Target, def.DPI, def.WidthMM, def.HeightMM, def.GapMM, def.Speed, def.Density, |
| 209 | + def.Direction, def.ReferenceX, def.ReferenceY, def.ShiftX, def.ShiftY, def.CopiesDefault, def.IsDefault, |
| 210 | + def.TSPLTemplate, now, now, |
| 211 | + ) |
| 212 | + if err != nil { |
| 213 | + log.Printf("Could not insert default label template %s: %v", def.SystemKey, err) |
| 214 | + } |
| 215 | + } |
120 | 216 | } |
121 | 217 |
|
122 | 218 | func realmTables(p string) []string { |
|
0 commit comments