v2.0: 3-Raum-System - Hauptraum, Saal A, Saal B mit 18 Tischen, Raum-Buchungen, API-Doku
This commit is contained in:
@@ -0,0 +1,616 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reservation-system/backend/internal/models"
|
||||
"time"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
conn *sql.DB
|
||||
}
|
||||
|
||||
func New(dbPath string) (*DB, error) {
|
||||
conn, err := sql.Open("sqlite3", dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := conn.Ping(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
db := &DB{conn: conn}
|
||||
if err := db.Migrate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func (db *DB) Migrate() error {
|
||||
schema := `
|
||||
CREATE TABLE IF NOT EXISTS rooms (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
capacity INTEGER NOT NULL DEFAULT 0,
|
||||
color TEXT DEFAULT '#3b82f6',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tables (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
room_id INTEGER NOT NULL,
|
||||
x INTEGER DEFAULT 0,
|
||||
y INTEGER DEFAULT 0,
|
||||
width INTEGER DEFAULT 100,
|
||||
height INTEGER DEFAULT 100,
|
||||
max_guests INTEGER NOT NULL,
|
||||
shape TEXT DEFAULT 'rect',
|
||||
status TEXT DEFAULT 'active',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reservations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
table_id INTEGER NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
time_from TEXT NOT NULL,
|
||||
time_to TEXT NOT NULL,
|
||||
guests INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
source TEXT DEFAULT 'manual',
|
||||
notes TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (table_id) REFERENCES tables(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS room_bookings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
room_id INTEGER NOT NULL,
|
||||
date TEXT NOT NULL,
|
||||
time_from TEXT NOT NULL,
|
||||
time_to TEXT NOT NULL,
|
||||
guests INTEGER NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
event_type TEXT,
|
||||
notes TEXT,
|
||||
status TEXT DEFAULT 'confirmed',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (room_id) REFERENCES rooms(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS table_merges (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
parent_table_id INTEGER NOT NULL,
|
||||
child_table_id INTEGER NOT NULL,
|
||||
merged_name TEXT,
|
||||
active BOOLEAN DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (parent_table_id) REFERENCES tables(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (child_table_id) REFERENCES tables(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS email_config (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
host TEXT NOT NULL,
|
||||
port INTEGER DEFAULT 993,
|
||||
user TEXT NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
ssl BOOLEAN DEFAULT 1,
|
||||
folder TEXT DEFAULT 'INBOX'
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
is_admin BOOLEAN DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_reservations_date ON reservations(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_reservations_table ON reservations(table_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_tables_room ON tables(room_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_reservations_time ON reservations(time_from, time_to);
|
||||
CREATE INDEX IF NOT EXISTS idx_room_bookings_date ON room_bookings(date);
|
||||
CREATE INDEX IF NOT EXISTS idx_room_bookings_room ON room_bookings(room_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_room_bookings_time ON room_bookings(time_from, time_to);
|
||||
`
|
||||
|
||||
_, err := db.conn.Exec(schema)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) Close() error {
|
||||
return db.conn.Close()
|
||||
}
|
||||
|
||||
// Room Methods
|
||||
func (db *DB) CreateRoom(room *models.Room) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO rooms (name, capacity, color) VALUES (?, ?, ?)",
|
||||
room.Name, room.Capacity, room.Color,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
room.ID = int(id)
|
||||
room.CreatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetRooms() ([]models.Room, error) {
|
||||
rows, err := db.conn.Query("SELECT id, name, capacity, color, created_at FROM rooms ORDER BY name")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var rooms []models.Room
|
||||
for rows.Next() {
|
||||
var r models.Room
|
||||
if err := rows.Scan(&r.ID, &r.Name, &r.Capacity, &r.Color, &r.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rooms = append(rooms, r)
|
||||
}
|
||||
return rooms, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetRoom(id int) (*models.Room, error) {
|
||||
var r models.Room
|
||||
err := db.conn.QueryRow(
|
||||
"SELECT id, name, capacity, color, created_at FROM rooms WHERE id = ?",
|
||||
id,
|
||||
).Scan(&r.ID, &r.Name, &r.Capacity, &r.Color, &r.CreatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func (db *DB) UpdateRoom(room *models.Room) error {
|
||||
_, err := db.conn.Exec(
|
||||
"UPDATE rooms SET name = ?, capacity = ?, color = ? WHERE id = ?",
|
||||
room.Name, room.Capacity, room.Color, room.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) DeleteRoom(id int) error {
|
||||
_, err := db.conn.Exec("DELETE FROM rooms WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Table Methods
|
||||
func (db *DB) CreateTable(table *models.Table) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO tables (room_id, x, y, width, height, max_guests, shape, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
table.RoomID, table.X, table.Y, table.Width, table.Height, table.MaxGuests, table.Shape, table.Status,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
table.ID = int(id)
|
||||
table.CreatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetTablesByRoom(roomID int) ([]models.Table, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT t.id, t.room_id, t.x, t.y, t.width, t.height, t.max_guests, t.shape, t.status, t.created_at, r.name as room_name
|
||||
FROM tables t
|
||||
JOIN rooms r ON t.room_id = r.id
|
||||
WHERE t.room_id = ? AND t.status = 'active'
|
||||
ORDER BY t.id`, roomID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var tables []models.Table
|
||||
for rows.Next() {
|
||||
var t models.Table
|
||||
if err := rows.Scan(&t.ID, &t.RoomID, &t.X, &t.Y, &t.Width, &t.Height, &t.MaxGuests, &t.Shape, &t.Status, &t.CreatedAt, &t.RoomName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tables = append(tables, t)
|
||||
}
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetAllTables() ([]models.Table, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT t.id, t.room_id, t.x, t.y, t.width, t.height, t.max_guests, t.shape, t.status, t.created_at, r.name as room_name
|
||||
FROM tables t
|
||||
JOIN rooms r ON t.room_id = r.id
|
||||
WHERE t.status = 'active'
|
||||
ORDER BY t.room_id, t.id`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var tables []models.Table
|
||||
for rows.Next() {
|
||||
var t models.Table
|
||||
if err := rows.Scan(&t.ID, &t.RoomID, &t.X, &t.Y, &t.Width, &t.Height, &t.MaxGuests, &t.Shape, &t.Status, &t.CreatedAt, &t.RoomName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tables = append(tables, t)
|
||||
}
|
||||
return tables, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetTable(id int) (*models.Table, error) {
|
||||
var t models.Table
|
||||
err := db.conn.QueryRow(`
|
||||
SELECT t.id, t.room_id, t.x, t.y, t.width, t.height, t.max_guests, t.shape, t.status, t.created_at, r.name as room_name
|
||||
FROM tables t
|
||||
JOIN rooms r ON t.room_id = r.id
|
||||
WHERE t.id = ?`, id).Scan(&t.ID, &t.RoomID, &t.X, &t.Y, &t.Width, &t.Height, &t.MaxGuests, &t.Shape, &t.Status, &t.CreatedAt, &t.RoomName)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &t, err
|
||||
}
|
||||
|
||||
func (db *DB) UpdateTable(table *models.Table) error {
|
||||
_, err := db.conn.Exec(
|
||||
"UPDATE tables SET room_id = ?, x = ?, y = ?, width = ?, height = ?, max_guests = ?, shape = ? WHERE id = ?",
|
||||
table.RoomID, table.X, table.Y, table.Width, table.Height, table.MaxGuests, table.Shape, table.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) DeleteTable(id int) error {
|
||||
_, err := db.conn.Exec("UPDATE tables SET status = 'deleted' WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Reservation Methods
|
||||
func (db *DB) CreateReservation(r *models.Reservation) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO reservations (table_id, date, time_from, time_to, guests, name, phone, email, source, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
r.TableID, r.Date, r.TimeFrom, r.TimeTo, r.Guests, r.Name, r.Phone, r.Email, r.Source, r.Notes,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
r.ID = int(id)
|
||||
r.CreatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetReservationsByDate(date string) ([]models.Reservation, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT r.id, r.table_id, r.date, r.time_from, r.time_to, r.guests, r.name, r.phone, r.email, r.source, r.notes, r.created_at, r.table_id as table_name
|
||||
FROM reservations r
|
||||
WHERE r.date = ?
|
||||
ORDER BY r.time_from`, date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var reservations []models.Reservation
|
||||
for rows.Next() {
|
||||
var res models.Reservation
|
||||
if err := rows.Scan(&res.ID, &res.TableID, &res.Date, &res.TimeFrom, &res.TimeTo, &res.Guests, &res.Name, &res.Phone, &res.Email, &res.Source, &res.Notes, &res.CreatedAt, &res.TableName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reservations = append(reservations, res)
|
||||
}
|
||||
return reservations, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetReservationsByTable(tableID int, date string) ([]models.Reservation, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT id, table_id, date, time_from, time_to, guests, name, phone, email, source, notes, created_at
|
||||
FROM reservations
|
||||
WHERE table_id = ? AND date = ?
|
||||
ORDER BY time_from`, tableID, date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var reservations []models.Reservation
|
||||
for rows.Next() {
|
||||
var res models.Reservation
|
||||
if err := rows.Scan(&res.ID, &res.TableID, &res.Date, &res.TimeFrom, &res.TimeTo, &res.Guests, &res.Name, &res.Phone, &res.Email, &res.Source, &res.Notes, &res.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
reservations = append(reservations, res)
|
||||
}
|
||||
return reservations, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetReservation(id int) (*models.Reservation, error) {
|
||||
var r models.Reservation
|
||||
err := db.conn.QueryRow(`
|
||||
SELECT id, table_id, date, time_from, time_to, guests, name, phone, email, source, notes, created_at
|
||||
FROM reservations WHERE id = ?`, id).Scan(&r.ID, &r.TableID, &r.Date, &r.TimeFrom, &r.TimeTo, &r.Guests, &r.Name, &r.Phone, &r.Email, &r.Source, &r.Notes, &r.CreatedAt)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func (db *DB) UpdateReservation(r *models.Reservation) error {
|
||||
_, err := db.conn.Exec(
|
||||
"UPDATE reservations SET table_id = ?, date = ?, time_from = ?, time_to = ?, guests = ?, name = ?, phone = ?, email = ?, notes = ? WHERE id = ?",
|
||||
r.TableID, r.Date, r.TimeFrom, r.TimeTo, r.Guests, r.Name, r.Phone, r.Email, r.Notes, r.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) DeleteReservation(id int) error {
|
||||
_, err := db.conn.Exec("DELETE FROM reservations WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Room Booking Methods (NEW)
|
||||
func (db *DB) CreateRoomBooking(rb *models.RoomBooking) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO room_bookings (room_id, date, time_from, time_to, guests, name, phone, email, event_type, notes, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
rb.RoomID, rb.Date, rb.TimeFrom, rb.TimeTo, rb.Guests, rb.Name, rb.Phone, rb.Email, rb.EventType, rb.Notes, rb.Status,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
rb.ID = int(id)
|
||||
rb.CreatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetRoomBookingsByRoom(roomID int) ([]models.RoomBooking, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT rb.id, rb.room_id, rb.date, rb.time_from, rb.time_to, rb.guests, rb.name, rb.phone, rb.email, rb.event_type, rb.notes, rb.status, rb.created_at, r.name as room_name
|
||||
FROM room_bookings rb
|
||||
JOIN rooms r ON rb.room_id = r.id
|
||||
WHERE rb.room_id = ?
|
||||
ORDER BY rb.date DESC, rb.time_from`, roomID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var bookings []models.RoomBooking
|
||||
for rows.Next() {
|
||||
var b models.RoomBooking
|
||||
if err := rows.Scan(&b.ID, &b.RoomID, &b.Date, &b.TimeFrom, &b.TimeTo, &b.Guests, &b.Name, &b.Phone, &b.Email, &b.EventType, &b.Notes, &b.Status, &b.CreatedAt, &b.RoomName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bookings = append(bookings, b)
|
||||
}
|
||||
return bookings, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetRoomBookingsByDate(date string) ([]models.RoomBooking, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT rb.id, rb.room_id, rb.date, rb.time_from, rb.time_to, rb.guests, rb.name, rb.phone, rb.email, rb.event_type, rb.notes, rb.status, rb.created_at, r.name as room_name
|
||||
FROM room_bookings rb
|
||||
JOIN rooms r ON rb.room_id = r.id
|
||||
WHERE rb.date = ?
|
||||
ORDER BY rb.time_from`, date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var bookings []models.RoomBooking
|
||||
for rows.Next() {
|
||||
var b models.RoomBooking
|
||||
if err := rows.Scan(&b.ID, &b.RoomID, &b.Date, &b.TimeFrom, &b.TimeTo, &b.Guests, &b.Name, &b.Phone, &b.Email, &b.EventType, &b.Notes, &b.Status, &b.CreatedAt, &b.RoomName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bookings = append(bookings, b)
|
||||
}
|
||||
return bookings, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetRoomBooking(id int) (*models.RoomBooking, error) {
|
||||
var rb models.RoomBooking
|
||||
err := db.conn.QueryRow(`
|
||||
SELECT rb.id, rb.room_id, rb.date, rb.time_from, rb.time_to, rb.guests, rb.name, rb.phone, rb.email, rb.event_type, rb.notes, rb.status, rb.created_at, r.name as room_name
|
||||
FROM room_bookings rb
|
||||
JOIN rooms r ON rb.room_id = r.id
|
||||
WHERE rb.id = ?`, id).Scan(&rb.ID, &rb.RoomID, &rb.Date, &rb.TimeFrom, &rb.TimeTo, &rb.Guests, &rb.Name, &rb.Phone, &rb.Email, &rb.EventType, &rb.Notes, &rb.Status, &rb.CreatedAt, &rb.RoomName)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &rb, err
|
||||
}
|
||||
|
||||
func (db *DB) UpdateRoomBooking(rb *models.RoomBooking) error {
|
||||
_, err := db.conn.Exec(
|
||||
"UPDATE room_bookings SET room_id = ?, date = ?, time_from = ?, time_to = ?, guests = ?, name = ?, phone = ?, email = ?, event_type = ?, notes = ?, status = ? WHERE id = ?",
|
||||
rb.RoomID, rb.Date, rb.TimeFrom, rb.TimeTo, rb.Guests, rb.Name, rb.Phone, rb.Email, rb.EventType, rb.Notes, rb.Status, rb.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) DeleteRoomBooking(id int) error {
|
||||
_, err := db.conn.Exec("DELETE FROM room_bookings WHERE id = ?", id)
|
||||
return err
|
||||
}
|
||||
|
||||
// Availability Checks
|
||||
func (db *DB) CheckAvailability(tableID int, date, timeFrom, timeTo string) (bool, error) {
|
||||
var count int
|
||||
err := db.conn.QueryRow(`
|
||||
SELECT COUNT(*) FROM reservations
|
||||
WHERE table_id = ? AND date = ?
|
||||
AND (
|
||||
(time_from < ? AND time_to > ?) OR
|
||||
(time_from < ? AND time_to > ?) OR
|
||||
(time_from >= ? AND time_to <= ?)
|
||||
)`, tableID, date, timeTo, timeFrom, timeTo, timeFrom, timeFrom, timeTo).Scan(&count)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count == 0, nil
|
||||
}
|
||||
|
||||
func (db *DB) CheckRoomAvailability(roomID int, date, timeFrom, timeTo string) (bool, error) {
|
||||
var count int
|
||||
err := db.conn.QueryRow(`
|
||||
SELECT COUNT(*) FROM room_bookings
|
||||
WHERE room_id = ? AND date = ? AND status = 'confirmed'
|
||||
AND (
|
||||
(time_from < ? AND time_to > ?) OR
|
||||
(time_from < ? AND time_to > ?) OR
|
||||
(time_from >= ? AND time_to <= ?)
|
||||
)`, roomID, date, timeTo, timeFrom, timeTo, timeFrom, timeFrom, timeTo).Scan(&count)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return count == 0, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetTableMerges(parentTableID int) ([]models.TableMerge, error) {
|
||||
rows, err := db.conn.Query(`
|
||||
SELECT id, parent_table_id, child_table_id, merged_name, active, created_at
|
||||
FROM table_merges
|
||||
WHERE parent_table_id = ? AND active = 1`, parentTableID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var merges []models.TableMerge
|
||||
for rows.Next() {
|
||||
var m models.TableMerge
|
||||
if err := rows.Scan(&m.ID, &m.ParentTableID, &m.ChildTableID, &m.MergedName, &m.Active, &m.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merges = append(merges, m)
|
||||
}
|
||||
return merges, nil
|
||||
}
|
||||
|
||||
func (db *DB) UnmergeTables(mergeID int) error {
|
||||
var childID int
|
||||
err := db.conn.QueryRow("SELECT child_table_id FROM table_merges WHERE id = ?", mergeID).Scan(&childID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.conn.Exec("UPDATE table_merges SET active = 0 WHERE id = ?", mergeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = db.conn.Exec("UPDATE tables SET status = 'active' WHERE id = ?", childID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (db *DB) GetEmailConfig() (*models.EmailConfig, error) {
|
||||
var cfg models.EmailConfig
|
||||
err := db.conn.QueryRow("SELECT id, host, port, user, password, ssl, folder FROM email_config LIMIT 1").Scan(
|
||||
&cfg.ID, &cfg.Host, &cfg.Port, &cfg.Username, &cfg.Password, &cfg.SSL, &cfg.Folder,
|
||||
)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &cfg, err
|
||||
}
|
||||
|
||||
func (db *DB) SaveEmailConfig(cfg *models.EmailConfig) error {
|
||||
if cfg.ID > 0 {
|
||||
_, err := db.conn.Exec(
|
||||
"UPDATE email_config SET host = ?, port = ?, user = ?, password = ?, ssl = ?, folder = ? WHERE id = ?",
|
||||
cfg.Host, cfg.Port, &cfg.Username, cfg.Password, cfg.SSL, cfg.Folder, cfg.ID,
|
||||
)
|
||||
return err
|
||||
}
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO email_config (host, port, user, password, ssl, folder) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
cfg.Host, cfg.Port, cfg.Username, cfg.Password, cfg.SSL, cfg.Folder,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
cfg.ID = int(id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetUserByUsername(username string) (*models.User, error) {
|
||||
var u models.User
|
||||
err := db.conn.QueryRow("SELECT id, username, password, is_admin FROM users WHERE username = ?", username).Scan(
|
||||
&u.ID, &u.Username, &u.Password, &u.IsAdmin,
|
||||
)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return &u, err
|
||||
}
|
||||
|
||||
func (db *DB) CreateUser(user *models.User) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO users (username, password, is_admin) VALUES (?, ?, ?)",
|
||||
user.Username, user.Password, user.IsAdmin,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
user.ID = int(id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *DB) GetMergedTablesFor(parentTableID int) ([]int, error) {
|
||||
rows, err := db.conn.Query("SELECT child_table_id FROM table_merges WHERE parent_table_id = ? AND active = 1", parentTableID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var ids []int
|
||||
for rows.Next() {
|
||||
var id int
|
||||
if err := rows.Scan(&id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ids = append(ids, id)
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (db *DB) GetTotalGuestsForDate(date string) (int, error) {
|
||||
var total int
|
||||
err := db.conn.QueryRow("SELECT COALESCE(SUM(guests), 0) FROM reservations WHERE date = ?", date).Scan(&total)
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (db *DB) CreateTableMerge(merge *models.TableMerge) error {
|
||||
result, err := db.conn.Exec(
|
||||
"INSERT INTO table_merges (parent_table_id, child_table_id, merged_name, active) VALUES (?, ?, ?, ?)",
|
||||
merge.ParentTableID, merge.ChildTableID, merge.MergedName, merge.Active,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
id, _ := result.LastInsertId()
|
||||
merge.ID = int(id)
|
||||
merge.CreatedAt = time.Now()
|
||||
|
||||
// Mark child table as merged
|
||||
_, err = db.conn.Exec("UPDATE tables SET status = 'merged' WHERE id = ?", merge.ChildTableID)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user