update mit archiv
All checks were successful
release-tag / release-image (push) Successful in 2m6s

This commit is contained in:
2026-05-29 10:34:04 +02:00
parent 6aaa73b744
commit ba1019728d
4 changed files with 75 additions and 10 deletions

View File

@@ -7,18 +7,18 @@ DISCORD_APP_ID=ApplicationIDHere
DISCORD_GUILD_ID=OptionalTestGuildIDForFastCommandRegistration
# Public channel for sanitized order overview. Leave empty if only the internal team should see order posts.
DISCORD_PUBLIC_ORDER_CHANNEL_ID=PublicOrderChannelIDOptional
DISCORD_PUBLIC_ORDER_CHANNEL_ID=PublicOrderChannelIDOptional # 1509819718922670271
# Private/internal channel for team operations. The bot posts buttons and warehouse checks here.
DISCORD_INTERNAL_ORDER_CHANNEL_ID=PrivateTeamOrderChannelIDRequired
DISCORD_INTERNAL_ORDER_CHANNEL_ID=PrivateTeamOrderChannelIDRequired # 1509819679487688817
# Optional audit/log channel for admin traceability.
DISCORD_AUDIT_CHANNEL_ID=AuditLogChannelIDOptional
DISCORD_AUDIT_CHANNEL_ID=AuditLogChannelIDOptional # 1509819633551802409
# Comma-separated role IDs. Admin role can modify inventory and force status changes.
DISCORD_ADMIN_ROLE_IDS=123456789012345678,234567890123456789
DISCORD_ADMIN_ROLE_IDS=123456789012345678,234567890123456789 # 1509819305188003931
# Comma-separated role IDs. Team role can see internal orders, accept/decline, check warehouse.
DISCORD_TEAM_ROLE_IDS=345678901234567890
DISCORD_TEAM_ROLE_IDS=345678901234567890 # 1509819434330755233
DATABASE_PATH=orders.db

View File

@@ -69,7 +69,11 @@ Zeigt den Auftrag. Team/Admin sieht die interne Ansicht inklusive Lagerprüfung,
### `/auftrag_liste status:<optional> limit:<optional>`
Listet Aufträge. Team/Admin sieht zusätzlich interne Zuordnungen.
Listet nur aktive Aufträge. Standardmäßig werden `open`, `accepted`, `in_delivery` und `delivered` angezeigt. Abgeschlossene, abgelehnte und abgebrochene Aufträge erscheinen hier nicht mehr.
### `/auftrag_archiv status:<optional> limit:<optional>`
Listet archivierte Aufträge mit den Statuswerten `completed`, `declined` und `cancelled`. Team/Admin sieht zusätzlich interne Zuordnungen.
### `/auftrag_abschliessen id:<id>`

18
db.go
View File

@@ -178,16 +178,32 @@ func scanOrder(scanner interface{ Scan(dest ...any) error }) (*Order, error) {
}
func (s *Store) ListOrders(status string, limit int) ([]Order, error) {
return s.listOrders(status, limit, false)
}
func (s *Store) ListArchivedOrders(status string, limit int) ([]Order, error) {
return s.listOrders(status, limit, true)
}
func (s *Store) listOrders(status string, limit int, archived bool) ([]Order, error) {
if limit <= 0 || limit > 50 {
limit = 10
}
query := `SELECT id, submitter_id, submitter_name, acceptor_id, acceptor_name, commodity, quality, quantity_amount, quantity_unit, deadline, delivery_place, max_budget_auec, status, public_channel_id, public_message_id, internal_channel_id, internal_message_id, thread_id, created_at, updated_at, last_feedback FROM orders`
args := []any{}
if status != "" {
query += ` WHERE status=?`
args = append(args, status)
} else if archived {
query += ` WHERE status IN (?, ?, ?)`
args = append(args, StatusCompleted, StatusDeclined, StatusCancelled)
} else {
query += ` WHERE status NOT IN (?, ?, ?)`
args = append(args, StatusCompleted, StatusDeclined, StatusCancelled)
}
query += ` ORDER BY created_at DESC LIMIT ?`
query += ` ORDER BY updated_at DESC LIMIT ?`
args = append(args, limit)
rows, err := s.db.Query(query, args...)
if err != nil {

View File

@@ -58,7 +58,8 @@ func (b *Bot) registerCommands() error {
},
},
{Name: "auftrag_status", Description: "Zeigt einen Auftrag", Options: []*discordgo.ApplicationCommandOption{{Name: "id", Description: "Auftrags-ID", Type: discordgo.ApplicationCommandOptionInteger, Required: true}}},
{Name: "auftrag_liste", Description: "Listet Aufträge", Options: []*discordgo.ApplicationCommandOption{{Name: "status", Description: "Optionaler Status", Type: discordgo.ApplicationCommandOptionString, Required: false, Choices: statusChoices()}, {Name: "limit", Description: "Maximal 50", Type: discordgo.ApplicationCommandOptionInteger, Required: false, MinValue: ptrFloat(1), MaxValue: float64(50)}}},
{Name: "auftrag_liste", Description: "Listet aktive Aufträge", Options: []*discordgo.ApplicationCommandOption{{Name: "status", Description: "Optionaler aktiver Status", Type: discordgo.ApplicationCommandOptionString, Required: false, Choices: activeStatusChoices()}, {Name: "limit", Description: "Maximal 50", Type: discordgo.ApplicationCommandOptionInteger, Required: false, MinValue: ptrFloat(1), MaxValue: float64(50)}}},
{Name: "auftrag_archiv", Description: "Listet abgeschlossene, abgelehnte und abgebrochene Aufträge", Options: []*discordgo.ApplicationCommandOption{{Name: "status", Description: "Optionaler Archiv-Status", Type: discordgo.ApplicationCommandOptionString, Required: false, Choices: archivedStatusChoices()}, {Name: "limit", Description: "Maximal 50", Type: discordgo.ApplicationCommandOptionInteger, Required: false, MinValue: ptrFloat(1), MaxValue: float64(50)}}},
{Name: "auftrag_abschliessen", Description: "Markiert einen Auftrag als abgeschlossen", Options: []*discordgo.ApplicationCommandOption{{Name: "id", Description: "Auftrags-ID", Type: discordgo.ApplicationCommandOptionInteger, Required: true}}},
{Name: "auftrag_status_setzen", Description: "Admin/Team: setzt den Status eines Auftrags", Options: []*discordgo.ApplicationCommandOption{{Name: "id", Description: "Auftrags-ID", Type: discordgo.ApplicationCommandOptionInteger, Required: true}, {Name: "status", Description: "Neuer Status", Type: discordgo.ApplicationCommandOptionString, Required: true, Choices: statusChoices()}, {Name: "notiz", Description: "Interne Notiz", Type: discordgo.ApplicationCommandOptionString, Required: false}}},
{Name: "auftrag_abbrechen", Description: "Bricht einen Auftrag ab", Options: []*discordgo.ApplicationCommandOption{{Name: "id", Description: "Auftrags-ID", Type: discordgo.ApplicationCommandOptionInteger, Required: true}, {Name: "grund", Description: "Optionaler Grund", Type: discordgo.ApplicationCommandOptionString, Required: false}}},
@@ -81,6 +82,18 @@ func statusChoices() []*discordgo.ApplicationCommandOptionChoice {
return []*discordgo.ApplicationCommandOptionChoice{{Name: StatusOpen, Value: StatusOpen}, {Name: StatusAccepted, Value: StatusAccepted}, {Name: StatusInDelivery, Value: StatusInDelivery}, {Name: StatusDelivered, Value: StatusDelivered}, {Name: StatusCompleted, Value: StatusCompleted}, {Name: StatusDeclined, Value: StatusDeclined}, {Name: StatusCancelled, Value: StatusCancelled}}
}
func activeStatusChoices() []*discordgo.ApplicationCommandOptionChoice {
return []*discordgo.ApplicationCommandOptionChoice{{Name: StatusOpen, Value: StatusOpen}, {Name: StatusAccepted, Value: StatusAccepted}, {Name: StatusInDelivery, Value: StatusInDelivery}, {Name: StatusDelivered, Value: StatusDelivered}}
}
func archivedStatusChoices() []*discordgo.ApplicationCommandOptionChoice {
return []*discordgo.ApplicationCommandOptionChoice{{Name: StatusCompleted, Value: StatusCompleted}, {Name: StatusDeclined, Value: StatusDeclined}, {Name: StatusCancelled, Value: StatusCancelled}}
}
func isArchivedStatus(status string) bool {
return status == StatusCompleted || status == StatusDeclined || status == StatusCancelled
}
func (b *Bot) onInteraction(s *discordgo.Session, i *discordgo.InteractionCreate) {
switch i.Type {
case discordgo.InteractionApplicationCommand:
@@ -103,6 +116,8 @@ func (b *Bot) handleCommand(s *discordgo.Session, i *discordgo.InteractionCreate
b.cmdStatus(s, i, optInt(i, "id"))
case "auftrag_liste":
b.cmdList(s, i)
case "auftrag_archiv":
b.cmdArchive(s, i)
case "auftrag_abschliessen":
b.cmdFinish(s, i, optInt(i, "id"))
case "auftrag_status_setzen":
@@ -186,15 +201,45 @@ func (b *Bot) cmdStatus(s *discordgo.Session, i *discordgo.InteractionCreate, id
}
func (b *Bot) cmdList(s *discordgo.Session, i *discordgo.InteractionCreate) {
b.cmdListOrders(s, i, false)
}
func (b *Bot) cmdArchive(s *discordgo.Session, i *discordgo.InteractionCreate) {
b.cmdListOrders(s, i, true)
}
func (b *Bot) cmdListOrders(s *discordgo.Session, i *discordgo.InteractionCreate, archived bool) {
status := optString(i, "status")
limit := int(optIntDefault(i, "limit", 10))
orders, err := b.store.ListOrders(status, limit)
if status != "" && isArchivedStatus(status) != archived {
if archived {
b.replyEphemeral(s, i, "`/auftrag_archiv` zeigt nur completed, declined und cancelled. Aktive Aufträge findest du mit `/auftrag_liste`.")
} else {
b.replyEphemeral(s, i, "`/auftrag_liste` zeigt nur aktive Aufträge. Abgeschlossene/abgelehnte/abgebrochene Aufträge findest du mit `/auftrag_archiv`.")
}
return
}
var (
orders []Order
err error
)
if archived {
orders, err = b.store.ListArchivedOrders(status, limit)
} else {
orders, err = b.store.ListOrders(status, limit)
}
if err != nil {
b.replyEphemeral(s, i, err.Error())
return
}
if len(orders) == 0 {
b.replyEphemeral(s, i, "Keine Aufträge gefunden.")
if archived {
b.replyEphemeral(s, i, "Keine archivierten Aufträge gefunden.")
} else {
b.replyEphemeral(s, i, "Keine aktiven Aufträge gefunden.")
}
return
}
var lines []string