Update from Git Manager GUI
This commit is contained in:
@@ -177,7 +177,6 @@ public class DatabaseManager {
|
||||
// ─────────────────────────── Tabellen erstellen ────────────────────────
|
||||
|
||||
private void createTables() {
|
||||
// close_comment ist jetzt von Anfang an in der CREATE-Anweisung enthalten
|
||||
String sql = """
|
||||
CREATE TABLE IF NOT EXISTS tickets (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
@@ -198,7 +197,8 @@ public class DatabaseManager {
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
claimed_at TIMESTAMP NULL,
|
||||
closed_at TIMESTAMP NULL,
|
||||
close_comment VARCHAR(500) NULL
|
||||
close_comment VARCHAR(500) NULL,
|
||||
player_deleted BOOLEAN DEFAULT FALSE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
""";
|
||||
try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) {
|
||||
@@ -210,11 +210,9 @@ public class DatabaseManager {
|
||||
|
||||
/**
|
||||
* Ergänzt fehlende Spalten in bestehenden Datenbanken automatisch.
|
||||
* Wichtig für Server, die das Plugin bereits installiert hatten bevor
|
||||
* close_comment existierte.
|
||||
*/
|
||||
private void ensureColumns() {
|
||||
// close_comment hinzufügen, falls nicht vorhanden
|
||||
// close_comment hinzufügen
|
||||
String checkSql = """
|
||||
SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
@@ -225,20 +223,34 @@ public class DatabaseManager {
|
||||
Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery(checkSql);
|
||||
if (rs.next() && rs.getInt(1) == 0) {
|
||||
// Spalte existiert nicht → hinzufügen
|
||||
stmt.execute("ALTER TABLE tickets ADD COLUMN close_comment VARCHAR(500) NULL");
|
||||
plugin.getLogger().info("[TicketSystem] Spalte 'close_comment' wurde zur Datenbank hinzugefügt.");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Fehler bei ensureColumns(): " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
// player_deleted Spalte prüfen
|
||||
String checkSqlDel = """
|
||||
SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE()
|
||||
AND TABLE_NAME = 'tickets'
|
||||
AND COLUMN_NAME = 'player_deleted'
|
||||
""";
|
||||
try (Connection conn = getConnection();
|
||||
Statement stmt = conn.createStatement()) {
|
||||
ResultSet rs = stmt.executeQuery(checkSqlDel);
|
||||
if (rs.next() && rs.getInt(1) == 0) {
|
||||
stmt.execute("ALTER TABLE tickets ADD COLUMN player_deleted BOOLEAN DEFAULT FALSE");
|
||||
plugin.getLogger().info("[TicketSystem] Spalte 'player_deleted' wurde hinzugefügt.");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Fehler bei ensureColumns(player_deleted): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────── CRUD ──────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Speichert ein neues Ticket in der DB und gibt die generierte ID zurück.
|
||||
*/
|
||||
public int createTicket(Ticket ticket) {
|
||||
if (useMySQL) {
|
||||
String sql = """
|
||||
@@ -282,13 +294,14 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Claimt ein Ticket (Status → CLAIMED).
|
||||
*/
|
||||
// ─── FIX: player_deleted wird beim Claimen zurückgesetzt, damit der Spieler
|
||||
// sein Ticket wieder sieht, sobald ein Supporter es annimmt. ───────
|
||||
public boolean claimTicket(int ticketId, UUID claimerUUID, String claimerName) {
|
||||
if (useMySQL) {
|
||||
String sql = """
|
||||
UPDATE tickets SET status = 'CLAIMED', claimer_uuid = ?, claimer_name = ?, claimed_at = NOW()
|
||||
UPDATE tickets
|
||||
SET status = 'CLAIMED', claimer_uuid = ?, claimer_name = ?,
|
||||
claimed_at = NOW(), player_deleted = FALSE
|
||||
WHERE id = ? AND status = 'OPEN'
|
||||
""";
|
||||
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
@@ -307,6 +320,7 @@ public class DatabaseManager {
|
||||
t.setClaimerUUID(claimerUUID);
|
||||
t.setClaimerName(claimerName);
|
||||
t.setClaimedAt(new Timestamp(System.currentTimeMillis()));
|
||||
t.setPlayerDeleted(false); // FIX: Sichtbarkeit für den Spieler wiederherstellen
|
||||
dataConfig.set("tickets." + ticketId, t);
|
||||
try {
|
||||
dataConfig.save(dataFile);
|
||||
@@ -318,9 +332,6 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schließt ein Ticket (Status → CLOSED).
|
||||
*/
|
||||
public boolean closeTicket(int ticketId, String closeComment) {
|
||||
if (useMySQL) {
|
||||
String sql = """
|
||||
@@ -352,9 +363,36 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Löscht ein Ticket anhand der ID.
|
||||
*/
|
||||
// ─── Soft Delete Methode ────────────────────────────────────────────────
|
||||
public boolean markAsPlayerDeleted(int id) {
|
||||
if (useMySQL) {
|
||||
String sql = "UPDATE tickets SET player_deleted = TRUE WHERE id = ?";
|
||||
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setInt(1, id);
|
||||
return ps.executeUpdate() > 0;
|
||||
} catch (SQLException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Fehler beim Markieren als gelöscht: " + e.getMessage(), e);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (dataConfig.contains("tickets." + id)) {
|
||||
Ticket t = (Ticket) dataConfig.get("tickets." + id);
|
||||
if (t != null) {
|
||||
t.setPlayerDeleted(true);
|
||||
dataConfig.set("tickets." + id, t);
|
||||
try {
|
||||
dataConfig.save(dataFile);
|
||||
backupDataFile();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
plugin.getLogger().severe("Fehler beim Speichern (Soft Delete): " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean deleteTicket(int id) {
|
||||
if (useMySQL) {
|
||||
String sql = "DELETE FROM tickets WHERE id = ?";
|
||||
@@ -384,13 +422,14 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Leitet ein Ticket an einen anderen Supporter weiter (Status → FORWARDED).
|
||||
*/
|
||||
// ─── FIX: player_deleted wird beim Weiterleiten zurückgesetzt, damit der
|
||||
// Spieler sein Ticket wieder sieht, sobald es weitergeleitet wird. ──
|
||||
public boolean forwardTicket(int ticketId, UUID toUUID, String toName) {
|
||||
if (useMySQL) {
|
||||
String sql = """
|
||||
UPDATE tickets SET status = 'FORWARDED', forwarded_to_uuid = ?, forwarded_to_name = ?
|
||||
UPDATE tickets
|
||||
SET status = 'FORWARDED', forwarded_to_uuid = ?, forwarded_to_name = ?,
|
||||
player_deleted = FALSE
|
||||
WHERE id = ? AND status != 'CLOSED'
|
||||
""";
|
||||
try (Connection conn = getConnection(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
@@ -408,6 +447,7 @@ public class DatabaseManager {
|
||||
t.setStatus(TicketStatus.FORWARDED);
|
||||
t.setForwardedToUUID(toUUID);
|
||||
t.setForwardedToName(toName);
|
||||
t.setPlayerDeleted(false); // FIX: Sichtbarkeit für den Spieler wiederherstellen
|
||||
dataConfig.set("tickets." + ticketId, t);
|
||||
try {
|
||||
dataConfig.save(dataFile);
|
||||
@@ -421,9 +461,6 @@ public class DatabaseManager {
|
||||
|
||||
// ─────────────────────────── Abfragen ──────────────────────────────────
|
||||
|
||||
/**
|
||||
* Gibt alle Tickets mit einem bestimmten Status zurück.
|
||||
*/
|
||||
public List<Ticket> getTicketsByStatus(TicketStatus... statuses) {
|
||||
List<Ticket> list = new ArrayList<>();
|
||||
if (statuses.length == 0) return list;
|
||||
@@ -452,9 +489,6 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt alle Tickets zurück (alle Status).
|
||||
*/
|
||||
public List<Ticket> getAllTickets() {
|
||||
List<Ticket> list = new ArrayList<>();
|
||||
if (useMySQL) {
|
||||
@@ -475,9 +509,6 @@ public class DatabaseManager {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt ein einzelnes Ticket anhand der ID zurück.
|
||||
*/
|
||||
public Ticket getTicketById(int id) {
|
||||
if (useMySQL) {
|
||||
String sql = "SELECT * FROM tickets WHERE id = ?";
|
||||
@@ -497,9 +528,6 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Anzahl offener Tickets (OPEN) – für Join-Benachrichtigung.
|
||||
*/
|
||||
public int countOpenTickets() {
|
||||
if (useMySQL) {
|
||||
String sql = "SELECT COUNT(*) FROM tickets WHERE status = 'OPEN'";
|
||||
@@ -522,9 +550,6 @@ public class DatabaseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Anzahl offener Tickets eines bestimmten Spielers.
|
||||
*/
|
||||
public int countOpenTicketsByPlayer(UUID uuid) {
|
||||
if (useMySQL) {
|
||||
String sql = "SELECT COUNT(*) FROM tickets WHERE creator_uuid = ? AND status IN ('OPEN', 'CLAIMED', 'FORWARDED')";
|
||||
@@ -553,9 +578,6 @@ public class DatabaseManager {
|
||||
|
||||
// ─────────────────────────── Archivierung ──────────────────────────────
|
||||
|
||||
/**
|
||||
* Archiviert alle geschlossenen Tickets in eine separate Datei.
|
||||
*/
|
||||
public int archiveClosedTickets() {
|
||||
List<Ticket> all = getAllTickets();
|
||||
List<Ticket> toArchive = new ArrayList<>();
|
||||
@@ -705,11 +727,6 @@ public class DatabaseManager {
|
||||
|
||||
// ─────────────────────────── Mapping ───────────────────────────────────
|
||||
|
||||
/**
|
||||
* Liest eine Zeile aus dem ResultSet und erstellt ein Ticket-Objekt.
|
||||
* close_comment wird mit try-catch abgesichert, damit ältere Datenbanken
|
||||
* ohne diese Spalte nicht abstürzen.
|
||||
*/
|
||||
private Ticket mapRow(ResultSet rs) throws SQLException {
|
||||
Ticket t = new Ticket();
|
||||
t.setId(rs.getInt("id"));
|
||||
@@ -727,15 +744,10 @@ public class DatabaseManager {
|
||||
t.setClaimedAt(rs.getTimestamp("claimed_at"));
|
||||
t.setClosedAt(rs.getTimestamp("closed_at"));
|
||||
|
||||
// ── BUGFIX: close_comment mit try-catch absichern ──────────────────
|
||||
// Wenn die Spalte in einer alten DB noch nicht existiert, wird der
|
||||
// Fehler ignoriert statt die gesamte Ticket-Liste leer zu lassen.
|
||||
try {
|
||||
String closeComment = rs.getString("close_comment");
|
||||
if (closeComment != null) t.setCloseComment(closeComment);
|
||||
} catch (SQLException ignored) {
|
||||
// Spalte existiert noch nicht – ensureColumns() ergänzt sie beim nächsten Start
|
||||
}
|
||||
} catch (SQLException ignored) { }
|
||||
|
||||
String claimerUUID = rs.getString("claimer_uuid");
|
||||
if (claimerUUID != null) {
|
||||
@@ -747,6 +759,10 @@ public class DatabaseManager {
|
||||
t.setForwardedToUUID(UUID.fromString(fwdUUID));
|
||||
t.setForwardedToName(rs.getString("forwarded_to_name"));
|
||||
}
|
||||
|
||||
// Mapping des Soft Delete Flags
|
||||
t.setPlayerDeleted(rs.getBoolean("player_deleted"));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -773,6 +789,7 @@ public class DatabaseManager {
|
||||
if (t.getForwardedToUUID() != null) obj.put("forwardedToUUID", t.getForwardedToUUID().toString());
|
||||
if (t.getForwardedToName() != null) obj.put("forwardedToName", t.getForwardedToName());
|
||||
if (t.getCloseComment() != null) obj.put("closeComment", t.getCloseComment());
|
||||
obj.put("playerDeleted", t.isPlayerDeleted());
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -798,6 +815,7 @@ public class DatabaseManager {
|
||||
if (obj.get("forwardedToUUID") != null) t.setForwardedToUUID(UUID.fromString((String) obj.get("forwardedToUUID")));
|
||||
if (obj.get("forwardedToName") != null) t.setForwardedToName((String) obj.get("forwardedToName"));
|
||||
if (obj.get("closeComment") != null) t.setCloseComment((String) obj.get("closeComment"));
|
||||
if (obj.containsKey("playerDeleted")) t.setPlayerDeleted((Boolean) obj.get("playerDeleted"));
|
||||
return t;
|
||||
} catch (Exception e) {
|
||||
if (plugin != null) plugin.getLogger().severe("Fehler beim Parsen eines Tickets: " + e.getMessage());
|
||||
|
||||
Reference in New Issue
Block a user