ChronoFlow/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs
2025-06-12 13:41:27 +02:00

520 lines
20 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Data.Sqlite;
using ChronoFlow.Model;
using ChronoFlow.Security;
namespace ChronoFlow.Persistence
{
public interface IZeiterfassungsRepository
{
Task<List<Zeiteintrag>> GetEintraegeFuerMitarbeiterAsync(string mitarbeiterName);
Task UpdateStatusUndKommentarAsync(int id, bool erledigt, string mitarbeiterKommentar);
}
public class SqliteZeiterfassungsService : IZeiterfassungsRepository
{
private readonly string _dbPath = "chrono_data.sb";
public SqliteZeiterfassungsService()
{
if (!File.Exists(_dbPath))
ErstelleDatenbank();
// IMMER prüfen, auch nach neuem Erstellen
PrüfeUndErweitereDatenbank();
}
private void ErstelleDatenbank()
{
Console.WriteLine("🛠️ ErstelleDatenbank wurde aufgerufen!");
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd1 = connection.CreateCommand();
cmd1.CommandText = @"
CREATE TABLE IF NOT EXISTS Zeiteintraege (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Mitarbeiter TEXT NOT NULL,
Startzeit TEXT NOT NULL,
Endzeit TEXT NOT NULL,
Projekt TEXT,
Kommentar TEXT,
Erledigt INTEGER,
MitarbeiterKommentar TEXT
);";
cmd1.ExecuteNonQuery();
var cmd2 = connection.CreateCommand();
cmd2.CommandText = @"
CREATE TABLE IF NOT EXISTS Benutzer (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Username TEXT NOT NULL,
Password TEXT NOT NULL,
Role TEXT NOT NULL,
Mitarbeitennummer TEXT,
Abteilung TEXT,
MussPasswortAendern INTEGER DEFAULT 1
);";
cmd2.ExecuteNonQuery();
}
public void ErstelleNeuenBenutzer(User benutzer)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
INSERT INTO Benutzer (Username, Password, Role, Mitarbeitennummer, Abteilung, MussPasswortAendern)
VALUES ($Username, $Password, $Role, $Mitarbeiternummer, $Abteilung, $MussPasswortAendern);
";
cmd.Parameters.AddWithValue("$Username", benutzer.Username);
cmd.Parameters.AddWithValue("$Password", benutzer.Password);
cmd.Parameters.AddWithValue("$Role", benutzer.Role);
cmd.Parameters.AddWithValue("$Mitarbeiternummer", benutzer.Mitarbeiternummer ?? "");
cmd.Parameters.AddWithValue("$Abteilung", benutzer.Abteilung ?? "");
cmd.Parameters.AddWithValue("$MussPasswortAendern", benutzer.MussPasswortAendern ? 1 : 0);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"✅ Neuer Benutzer '{benutzer.Username}' wurde gespeichert (Rows affected: {rowsAffected}).");
}
private void PrüfeUndErweitereDatenbank()
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
AddColumnIfMissing(connection, "Benutzer", "Mitarbeitennummer", "TEXT");
AddColumnIfMissing(connection, "Benutzer", "Abteilung", "TEXT");
AddColumnIfMissing(connection, "Benutzer", "MussPasswortAendern", "INTEGER DEFAULT 1");
}
private void AddColumnIfMissing(SqliteConnection connection, string tableName, string columnName, string columnType)
{
var checkCmd = connection.CreateCommand();
checkCmd.CommandText = $"PRAGMA table_info({tableName});";
using var reader = checkCmd.ExecuteReader();
bool columnExists = false;
while (reader.Read())
{
var existingColumnName = reader.GetString(1);
if (existingColumnName.Equals(columnName, StringComparison.OrdinalIgnoreCase))
{
columnExists = true;
break;
}
}
if (!columnExists)
{
var alterCmd = connection.CreateCommand();
alterCmd.CommandText = $"ALTER TABLE {tableName} ADD COLUMN {columnName} {columnType};";
alterCmd.ExecuteNonQuery();
Console.WriteLine($"✅ Spalte '{columnName}' in Tabelle '{tableName}' hinzugefügt.");
}
}
public void ErstelleStandardAdmin()
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var checkCmd = connection.CreateCommand();
checkCmd.CommandText = "SELECT COUNT(*) FROM Benutzer WHERE Username = 'admin';";
var count = Convert.ToInt32(checkCmd.ExecuteScalar());
if (count == 0)
{
var hashedPassword = PasswordHasher.HashPassword("admin");
var insertCmd = connection.CreateCommand();
insertCmd.CommandText = @"
INSERT INTO Benutzer (Username, Password, Role, Mitarbeitennummer, Abteilung, MussPasswortAendern)
VALUES ('admin', $Password, 'Admin', '0001', 'IT', 1);
";
insertCmd.Parameters.AddWithValue("$Password", hashedPassword);
insertCmd.ExecuteNonQuery();
Console.WriteLine("✅ Standard-Admin erfolgreich eingefügt.");
}
else
{
Console.WriteLine(" Standard-Admin existiert bereits kein neuer Eintrag erstellt.");
}
}
public List<User> LadeAlleBenutzer()
{
var benutzerListe = new List<User>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT Id, Username, Password, Role, Mitarbeitennummer, Abteilung, MussPasswortAendern FROM Benutzer;";
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
benutzerListe.Add(new User
{
Id = reader.GetInt32(0),
Username = reader.GetString(1),
Password = reader.GetString(2),
Role = reader.GetString(3),
Mitarbeiternummer = reader.IsDBNull(4) ? "" : reader.GetString(4),
Abteilung = reader.IsDBNull(5) ? "" : reader.GetString(5),
MussPasswortAendern = reader.GetInt32(6) == 1,
OriginalUsername = reader.GetString(1)
});
}
return benutzerListe;
}
public void UpdateBenutzer(User benutzer)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Benutzer
SET Username = $NewUsername,
Password = $Password,
Role = $Role,
Mitarbeitennummer = $Mitarbeiternummer,
Abteilung = $Abteilung,
MussPasswortAendern = $MussPasswortAendern
WHERE Username = $OriginalUsername;
";
cmd.Parameters.AddWithValue("$NewUsername", benutzer.Username);
cmd.Parameters.AddWithValue("$Password", benutzer.Password);
cmd.Parameters.AddWithValue("$Role", benutzer.Role);
cmd.Parameters.AddWithValue("$Mitarbeiternummer", benutzer.Mitarbeiternummer ?? "");
cmd.Parameters.AddWithValue("$Abteilung", benutzer.Abteilung ?? "");
cmd.Parameters.AddWithValue("$MussPasswortAendern", benutzer.MussPasswortAendern ? 1 : 0);
cmd.Parameters.AddWithValue("$OriginalUsername", benutzer.OriginalUsername);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"✏ Benutzer aktualisiert: {benutzer.Username} (Rows affected: {rowsAffected})");
}
public void LoescheBenutzer(string username)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "DELETE FROM Benutzer WHERE Username = $Username;";
cmd.Parameters.AddWithValue("$Username", username);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"❌ Benutzer gelöscht: {username} (Rows affected: {rowsAffected})");
}
public List<string> LadeAlleMitarbeiterNamen()
{
var namen = new List<string>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT Username FROM Benutzer WHERE Role = 'Mitarbeiter';";
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
namen.Add(reader.GetString(0));
}
return namen;
}
public void SpeichereEintrag(Zeiteintrag eintrag)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
INSERT INTO Zeiteintraege
(Mitarbeiter, Startzeit, Endzeit, Projekt, Kommentar, Erledigt, MitarbeiterKommentar)
VALUES ($Mitarbeiter, $Startzeit, $Endzeit, $Projekt, $Kommentar, $Erledigt, $MitarbeiterKommentar);
";
cmd.Parameters.AddWithValue("$Mitarbeiter", eintrag.Mitarbeiter);
cmd.Parameters.AddWithValue("$Startzeit", eintrag.Startzeit.ToString("o"));
cmd.Parameters.AddWithValue("$Endzeit", eintrag.Endzeit.ToString("o"));
cmd.Parameters.AddWithValue("$Projekt", eintrag.Projekt ?? "");
cmd.Parameters.AddWithValue("$Kommentar", eintrag.Kommentar ?? "");
cmd.Parameters.AddWithValue("$Erledigt", eintrag.Erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$MitarbeiterKommentar", eintrag.MitarbeiterKommentar ?? "");
cmd.ExecuteNonQuery();
Console.WriteLine($"✅ Zeiteintrag für {eintrag.Mitarbeiter} gespeichert.");
}
public List<Zeiteintrag> LadeAlleZeiteintraege()
{
var eintraege = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM Zeiteintraege;";
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
eintraege.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
});
}
return eintraege;
}
public void UpdateProjekt(Zeiteintrag projekt)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Zeiteintraege
SET Projekt = $Projekt,
Kommentar = $Kommentar,
Startzeit = $Startzeit,
Endzeit = $Endzeit,
Mitarbeiter = $Mitarbeiter,
Erledigt = $Erledigt
WHERE Id = $Id;
";
cmd.Parameters.AddWithValue("$Projekt", projekt.Projekt);
cmd.Parameters.AddWithValue("$Kommentar", projekt.Kommentar ?? "");
cmd.Parameters.AddWithValue("$Startzeit", projekt.Startzeit.ToString("o"));
cmd.Parameters.AddWithValue("$Endzeit", projekt.Endzeit.ToString("o"));
cmd.Parameters.AddWithValue("$Mitarbeiter", projekt.Mitarbeiter);
cmd.Parameters.AddWithValue("$Erledigt", projekt.Erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$Id", projekt.Id);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"✏ Projekt aktualisiert (Id={projekt.Id}, Rows affected: {rowsAffected})");
}
public void LoescheProjekt(int id)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "DELETE FROM Zeiteintraege WHERE Id = $Id;";
cmd.Parameters.AddWithValue("$Id", id);
int rows = cmd.ExecuteNonQuery();
Console.WriteLine($"❌ Projekt gelöscht (Id: {id}, Rows: {rows})");
}
public void UpdateProjektStatus(int id, bool erledigt)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Zeiteintraege
SET Erledigt = $Erledigt
WHERE Id = $Id;
";
cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$Id", id);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"✅ Projektstatus aktualisiert (Id={id}, Erledigt={erledigt}, Rows affected: {rowsAffected})");
}
public List<Zeiteintrag> LadeAbgeschlosseneProjekte()
{
var abgeschlossene = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM Zeiteintraege WHERE Erledigt = 1;";
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
abgeschlossene.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
});
}
return abgeschlossene;
}
public List<Zeiteintrag> LadeLetzteProjekte(int anzahl = 3)
{
var projekte = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
SELECT * FROM Zeiteintraege
ORDER BY Id DESC
LIMIT $Anzahl;
";
cmd.Parameters.AddWithValue("$Anzahl", anzahl);
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
projekte.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
});
}
return projekte;
}
public List<Zeiteintrag> LadeOffeneProjekte()
{
var offene = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT * FROM Zeiteintraege WHERE Erledigt = 0;";
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
offene.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
});
}
return offene;
}
public void ResetBenutzerPasswort(string username)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
connection.Open();
var hashedDefault = PasswordHasher.HashPassword("changeme");
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Benutzer
SET Password = $Password,
MussPasswortAendern = 1
WHERE Username = $Username;
";
cmd.Parameters.AddWithValue("$Password", hashedDefault);
cmd.Parameters.AddWithValue("$Username", username);
int rowsAffected = cmd.ExecuteNonQuery();
Console.WriteLine($"🔒 Passwort für Benutzer '{username}' zurückgesetzt (Rows affected: {rowsAffected})");
}
public async Task<List<Zeiteintrag>> GetEintraegeFuerMitarbeiterAsync(string mitarbeiterName)
{
var eintraege = new List<Zeiteintrag>();
using var connection = new SqliteConnection($"Data Source={_dbPath}");
await connection.OpenAsync();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
SELECT * FROM Zeiteintraege
WHERE Mitarbeiter = $Mitarbeiter;
";
cmd.Parameters.AddWithValue("$Mitarbeiter", mitarbeiterName);
using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
eintraege.Add(new Zeiteintrag
{
Id = reader.GetInt32(0),
Mitarbeiter = reader.GetString(1),
Startzeit = DateTime.Parse(reader.GetString(2)),
Endzeit = DateTime.Parse(reader.GetString(3)),
Projekt = reader.GetString(4),
Kommentar = reader.GetString(5),
Erledigt = Convert.ToInt32(reader["Erledigt"]) == 1,
MitarbeiterKommentar = reader.GetString(7)
});
}
return eintraege;
}
public async Task UpdateStatusUndKommentarAsync(int id, bool erledigt, string mitarbeiterKommentar)
{
using var connection = new SqliteConnection($"Data Source={_dbPath}");
await connection.OpenAsync();
var cmd = connection.CreateCommand();
cmd.CommandText = @"
UPDATE Zeiteintraege
SET Erledigt = $Erledigt,
MitarbeiterKommentar = $Kommentar
WHERE Id = $Id;
";
cmd.Parameters.AddWithValue("$Erledigt", erledigt ? 1 : 0);
cmd.Parameters.AddWithValue("$Kommentar", mitarbeiterKommentar ?? "");
cmd.Parameters.AddWithValue("$Id", id);
int rowsAffected = await cmd.ExecuteNonQueryAsync();
Console.WriteLine($"✏ Zeiteintrag (Id={id}) aktualisiert: erledigt={erledigt}, kommentar gesetzt.");
}
}
}