package main import ( "database/sql" "fmt" "log" "golang.org/x/crypto/bcrypt" _ "modernc.org/sqlite" ) func InitDB(filepath string) *sql.DB { db, err := sql.Open("sqlite", filepath) if err != nil { log.Fatal(err) } if err = db.Ping(); err != nil { log.Fatal(err) } createTables(db) return db } func createTables(db *sql.DB) { queries := []string{ `CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL, is_admin BOOLEAN NOT NULL DEFAULT 0 )`, `CREATE TABLE IF NOT EXISTS schedules ( id INTEGER PRIMARY KEY AUTOINCREMENT, day_of_week INTEGER NOT NULL, start_time TEXT NOT NULL, end_time TEXT NOT NULL, type TEXT NOT NULL, title TEXT NOT NULL )`, `CREATE TABLE IF NOT EXISTS time_entries ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, schedule_id INTEGER NOT NULL, date TEXT NOT NULL, type TEXT NOT NULL, start_time TEXT NOT NULL, end_time TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, FOREIGN KEY (schedule_id) REFERENCES schedules(id) )`, } for _, query := range queries { if _, err := db.Exec(query); err != nil { log.Fatal(err) } } // Create default admin user (password: admin123) hash, _ := bcrypt.GenerateFromPassword([]byte("admin123"), bcrypt.DefaultCost) _, err := db.Exec(` INSERT OR IGNORE INTO users (id, username, password, is_admin) VALUES (?, ?, ?, ?)`, 1, "admin", string(hash), true, ) if err != nil { log.Fatal(err) } } func GetUserByUsername(db *sql.DB, username string) (*User, error) { user := &User{} err := db.QueryRow("SELECT id, username, password, is_admin FROM users WHERE username = ?", username). Scan(&user.ID, &user.Username, &user.Password, &user.IsAdmin) if err != nil { return nil, err } return user, nil } func CreateUser(db *sql.DB, username, hashedPassword string, isAdmin bool) error { _, err := db.Exec("INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)", username, hashedPassword, isAdmin) return err } func GetAllUsers(db *sql.DB) ([]User, error) { rows, err := db.Query("SELECT id, username, is_admin FROM users") if err != nil { return nil, err } defer rows.Close() var users []User for rows.Next() { var u User if err := rows.Scan(&u.ID, &u.Username, &u.IsAdmin); err != nil { continue } users = append(users, u) } return users, nil } func CreateSchedule(db *sql.DB, schedule *Schedule) error { _, err := db.Exec("INSERT INTO schedules (day_of_week, start_time, end_time, type, title) VALUES (?, ?, ?, ?, ?)", schedule.DayOfWeek, schedule.StartTime, schedule.EndTime, schedule.Type, schedule.Title) return err } func GetAllSchedules(db *sql.DB) ([]Schedule, error) { rows, err := db.Query("SELECT id, day_of_week, start_time, end_time, type, title FROM schedules ORDER BY day_of_week, start_time") if err != nil { return nil, err } defer rows.Close() var schedules []Schedule for rows.Next() { var s Schedule if err := rows.Scan(&s.ID, &s.DayOfWeek, &s.StartTime, &s.EndTime, &s.Type, &s.Title); err != nil { continue } schedules = append(schedules, s) } return schedules, nil } func DeleteSchedule(db *sql.DB, id int) error { _, err := db.Exec("DELETE FROM schedules WHERE id = ?", id) return err } func CreateTimeEntry(db *sql.DB, entry *TimeEntry) error { _, err := db.Exec("INSERT INTO time_entries (user_id, schedule_id, date, type, start_time, end_time) VALUES (?, ?, ?, ?, ?, ?)", entry.UserID, entry.ScheduleID, entry.Date, entry.Type, entry.StartTime, entry.EndTime) return err } // func CreateTimeEntry(db *sql.DB, entry *TimeEntry) error { // _, err := db.Exec("INSERT INTO time_entries (user_id, schedule_id, date, type) VALUES (?, ?, ?, ?)", // entry.UserID, entry.ScheduleID, entry.Date, entry.Type) // return err // } func GetTimeEntriesByUser(db *sql.DB, userID int) ([]TimeEntry, error) { rows, err := db.Query("SELECT id, user_id, schedule_id, date, type, created_at FROM time_entries WHERE user_id = ? ORDER BY date DESC, created_at DESC", userID) if err != nil { return nil, err } defer rows.Close() var entries []TimeEntry for rows.Next() { var e TimeEntry if err := rows.Scan(&e.ID, &e.UserID, &e.ScheduleID, &e.Date, &e.Type, &e.CreatedAt); err != nil { continue } entries = append(entries, e) } return entries, nil } func GetAllTimeEntries(db *sql.DB) ([]TimeEntry, error) { rows, err := db.Query(` SELECT te.id, te.user_id, te.schedule_id, te.date, te.type, te.start_time, te.end_time, te.created_at, u.username FROM time_entries te JOIN users u ON te.user_id = u.id ORDER BY te.date DESC, te.created_at DESC `) if err != nil { return nil, err } defer rows.Close() var entries []TimeEntry for rows.Next() { var e TimeEntry if err := rows.Scan(&e.ID, &e.UserID, &e.ScheduleID, &e.Date, &e.Type, &e.StartTime, &e.EndTime, &e.CreatedAt, &e.Username); err != nil { continue } entries = append(entries, e) } return entries, nil } // func GetAllTimeEntries(db *sql.DB) ([]TimeEntry, error) { // rows, err := db.Query("SELECT id, user_id, schedule_id, date, type, created_at FROM time_entries ORDER BY date DESC, created_at DESC") // if err != nil { // return nil, err // } // defer rows.Close() // var entries []TimeEntry // for rows.Next() { // var e TimeEntry // if err := rows.Scan(&e.ID, &e.UserID, &e.ScheduleID, &e.Date, &e.Type, &e.CreatedAt); err != nil { // continue // } // entries = append(entries, e) // } // return entries, nil // } func GetWeeklyHours(db *sql.DB) ([]WeeklyHours, error) { rows, err := db.Query(` SELECT te.user_id, u.username, CAST(strftime('%W', te.date) AS INTEGER) as week, CAST(strftime('%Y', te.date) AS INTEGER) as year, SUM( (CAST(substr(te.end_time, 1, 2) AS REAL) + CAST(substr(te.end_time, 4, 2) AS REAL) / 60.0) - (CAST(substr(te.start_time, 1, 2) AS REAL) + CAST(substr(te.start_time, 4, 2) AS REAL) / 60.0) ) as total_hours FROM time_entries te JOIN users u ON te.user_id = u.id GROUP BY te.user_id, u.username, week, year ORDER BY year DESC, week DESC, u.username `) if err != nil { return nil, err } defer rows.Close() var hours []WeeklyHours for rows.Next() { var h WeeklyHours if err := rows.Scan(&h.UserID, &h.Username, &h.Week, &h.Year, &h.TotalHours); err != nil { continue } hours = append(hours, h) } return hours, nil } func DeleteUser(db *sql.DB, id int) error { if id == 1 { return fmt.Errorf("cannot delete admin user") } _, err := db.Exec("DELETE FROM users WHERE id = ?", id) return err } func DeleteTimeEntriesByUserAndWeek(db *sql.DB, userID int, year int, week int) error { query := ` DELETE FROM time_entries WHERE user_id = ? AND CAST(strftime('%W', date) AS INTEGER) = ? AND CAST(strftime('%Y', date) AS INTEGER) = ? ` _, err := db.Exec(query, userID, week, year) return err } func CheckUserHasEntriesForWeek(db *sql.DB, userID int, year int, week int) (bool, error) { // Berechne die Daten der Woche dates := calculateWeekDates(year, week) // Hole alle Daten als Liste var dateList []string for _, date := range dates.Dates { dateList = append(dateList, date) } // Prüfe ob Einträge existieren query := ` SELECT COUNT(*) FROM time_entries WHERE user_id = ? AND date IN (?, ?, ?, ?, ?) ` var count int err := db.QueryRow(query, userID, dateList[0], dateList[1], dateList[2], dateList[3], dateList[4]).Scan(&count) if err != nil { return false, err } return count > 0, nil }