lösche leere Lager
All checks were successful
release-tag / release-image (push) Successful in 2m6s

This commit is contained in:
2026-05-29 11:22:51 +02:00
parent 72a12ff960
commit bcc75dc571
2 changed files with 49 additions and 9 deletions

View File

@@ -172,3 +172,11 @@ SQLite wird mit WAL-Modus und `busy_timeout` betrieben, damit kleine produktive
- Führe den Bot als systemd-Service oder Container aus.
- Aktiviere Monitoring für Logs und Neustarts.
- Teste DMs: Manche Nutzer blockieren DMs von Servermitgliedern; der Bot loggt solche Fehler, kann sie aber nicht erzwingen.
## Lagerbestand bei 0
Wenn ein Lagerbestand durch `/lager_remove` oder `/lager_add` mit `modus:setzen` auf `0` fällt, wird der Lagerdatensatz automatisch gelöscht. Das Auditlog zeigt weiterhin die Änderung als `alter Wert → neuer Wert`, z. B. `2 → 0`.
Zusätzlich verhindert die Lagerlogik negative Bestände. Wenn mehr entfernt wird als vorhanden ist, antwortet der Bot mit einem Fehler und ändert den Bestand nicht.
`/lager_liste` und die interne Lagerprüfung berücksichtigen nur Bestände größer als `0`, sodass alte Nullbestände nicht mehr angezeigt werden.

50
db.go
View File

@@ -309,19 +309,36 @@ func nullableOrderID(id int64) any {
func (s *Store) UpsertInventory(item InventoryItem, delta bool) (*InventoryItem, error) {
now := time.Now().UTC()
item.Name = strings.TrimSpace(item.Name)
item.Location = strings.TrimSpace(item.Location)
item.NormalizedName = normalizeName(item.Name)
tx, err := s.db.Begin()
if err != nil {
return nil, err
}
defer tx.Rollback()
var existing InventoryItem
err = tx.QueryRow(`SELECT id, name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at FROM inventory WHERE normalized_name=? AND quality=? AND quantity_unit=? AND location=?`, item.NormalizedName, item.Quality, item.QuantityUnit, item.Location).Scan(&existing.ID, &existing.Name, &existing.NormalizedName, &existing.Quality, &existing.QuantityAmount, &existing.QuantityUnit, &existing.Location, &existing.Note, &existing.UpdatedByID, &existing.UpdatedByName, &existing.CreatedAt, &existing.UpdatedAt)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return nil, err
}
var result InventoryItem
if errors.Is(err, sql.ErrNoRows) {
_, err = tx.Exec(`INSERT INTO inventory(name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, item.Name, item.NormalizedName, item.Quality, item.QuantityAmount, item.QuantityUnit, item.Location, item.Note, item.UpdatedByID, item.UpdatedByName, now, now)
if item.QuantityAmount <= 0 {
return nil, errors.New("kein ausreichender Lagerbestand vorhanden")
}
res, err := tx.Exec(`INSERT INTO inventory(name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, item.Name, item.NormalizedName, item.Quality, item.QuantityAmount, item.QuantityUnit, item.Location, item.Note, item.UpdatedByID, item.UpdatedByName, now, now)
if err != nil {
return nil, err
}
id, _ := res.LastInsertId()
result = item
result.ID = id
result.CreatedAt = now
result.UpdatedAt = now
} else {
newQty := item.QuantityAmount
if delta {
@@ -330,18 +347,33 @@ func (s *Store) UpsertInventory(item InventoryItem, delta bool) (*InventoryItem,
if newQty < 0 {
return nil, errors.New("lagerbestand darf nicht negativ werden")
}
_, err = tx.Exec(`UPDATE inventory SET name=?, quantity_amount=?, note=?, updated_by_id=?, updated_by_name=?, updated_at=? WHERE id=?`, item.Name, newQty, item.Note, item.UpdatedByID, item.UpdatedByName, now, existing.ID)
}
if err != nil {
return nil, err
result = existing
result.Name = item.Name
result.QuantityAmount = newQty
result.Note = item.Note
result.UpdatedByID = item.UpdatedByID
result.UpdatedByName = item.UpdatedByName
result.UpdatedAt = now
if newQty == 0 {
if _, err := tx.Exec(`DELETE FROM inventory WHERE id=?`, existing.ID); err != nil {
return nil, err
}
} else {
if _, err := tx.Exec(`UPDATE inventory SET name=?, quantity_amount=?, note=?, updated_by_id=?, updated_by_name=?, updated_at=? WHERE id=?`, item.Name, newQty, item.Note, item.UpdatedByID, item.UpdatedByName, now, existing.ID); err != nil {
return nil, err
}
}
}
if err := addEventTx(tx, 0, item.UpdatedByID, item.UpdatedByName, EventInventoryChanged, fmt.Sprintf("Lager %s Q%d %s %s", item.Name, item.Quality, formatAmount(item.QuantityAmount), item.QuantityUnit)); err != nil {
return nil, err
}
if err := tx.Commit(); err != nil {
return nil, err
}
return s.GetInventoryByKey(item.NormalizedName, item.Quality, item.QuantityUnit, item.Location)
return &result, nil
}
func (s *Store) GetInventoryByKey(normalized string, quality int, unit, location string) (*InventoryItem, error) {
@@ -361,10 +393,10 @@ func (s *Store) ListInventory(query string, limit int) ([]InventoryItem, error)
if limit <= 0 || limit > 50 {
limit = 20
}
q := `SELECT id, name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at FROM inventory`
q := `SELECT id, name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at FROM inventory WHERE quantity_amount > 0`
args := []any{}
if strings.TrimSpace(query) != "" {
q += ` WHERE normalized_name LIKE ? OR location LIKE ?`
q += ` AND (normalized_name LIKE ? OR location LIKE ?)`
like := "%" + normalizeName(query) + "%"
args = append(args, like, like)
}
@@ -387,7 +419,7 @@ func (s *Store) ListInventory(query string, limit int) ([]InventoryItem, error)
}
func (s *Store) FindInventoryForOrder(o *Order) ([]InventoryMatch, float64, error) {
rows, err := s.db.Query(`SELECT id, name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at FROM inventory WHERE normalized_name=? AND quality>=? AND quantity_unit=? ORDER BY quality DESC, quantity_amount DESC`, normalizeName(o.Commodity), o.Quality, o.QuantityUnit)
rows, err := s.db.Query(`SELECT id, name, normalized_name, quality, quantity_amount, quantity_unit, location, note, updated_by_id, updated_by_name, created_at, updated_at FROM inventory WHERE normalized_name=? AND quality>=? AND quantity_unit=? AND quantity_amount > 0 ORDER BY quality DESC, quantity_amount DESC`, normalizeName(o.Commodity), o.Quality, o.QuantityUnit)
if err != nil {
return nil, 0, err
}