package models import ( "database/sql" "fmt" "log" "net/url" "strconv" "time" ) type SameBookingError struct{} func (e SameBookingError) Error() string { return "the same booking already exists!" } type Booking struct { CardUID string `json:"card_uid"` GeraetID int16 `json:"geraet_id"` CheckInOut int16 `json:"check_in_out"` Timestamp time.Time `json:"timestamp"` CounterId int `json:"counter_id"` } var DB *sql.DB func (b *Booking) New(card_uid string, geraet_id int16, check_in_out int16) Booking { return Booking{ CardUID: card_uid, GeraetID: geraet_id, CheckInOut: check_in_out, } } func (b *Booking) FromUrlParams(params url.Values) Booking { var booking Booking if _check_in_out, err := strconv.Atoi(params.Get("check_in_out")); err == nil { booking.CheckInOut = int16(_check_in_out) } if _geraet_id, err := strconv.Atoi(params.Get("geraet_id")); err == nil { booking.GeraetID = int16(_geraet_id) } booking.CardUID = params.Get("card_uid") return booking } func (b Booking) Verify() bool { if b.CardUID == "" || b.GeraetID == 0 || b.CheckInOut == 0 { return false } return true } func (b *Booking) Insert() error { if !checkLastBooking(*b) { return SameBookingError{} } stmt, err := DB.Prepare((`INSERT INTO anwesenheit (card_uid, geraet_id, check_in_out) VALUES ($1, $2, $3) RETURNING counter_id, timestamp`)) if err != nil { return err } err = stmt.QueryRow(b.CardUID, b.GeraetID, b.CheckInOut).Scan(&b.CounterId, &b.Timestamp) if err != nil { return err } return nil } func (b *Booking) GetBookingById(booking_id int) (Booking, error) { var booking Booking qStr, err := DB.Prepare((`SELECT counter_id, timestamp, card_uid, geraet_id, check_in_out FROM anwesenheit WHERE counter_id = $1`)) if err != nil { return booking, err } err = qStr.QueryRow(booking_id).Scan(&booking.CounterId, &booking.Timestamp, &booking.CardUID, &booking.GeraetID, &booking.CheckInOut) if err != nil { return booking, err } if !booking.Verify() { fmt.Printf("Booking verification failed") return booking, nil } return booking, nil } func (b *Booking) GetBookingsByCardID(card_id string) ([]Booking, error) { qStr, err := DB.Prepare((`SELECT counter_id, timestamp, card_uid, geraet_id, check_in_out FROM anwesenheit WHERE card_uid = $1`)) if err != nil { return nil, err } defer qStr.Close() var bookings []Booking rows, err := qStr.Query(card_id) if err == sql.ErrNoRows { return bookings, err } if err != nil { return nil, err } defer rows.Close() for rows.Next() { var booking Booking if err := rows.Scan(&booking.CounterId, &booking.Timestamp, &booking.CardUID, &booking.GeraetID, &booking.CheckInOut); err != nil { return bookings, err } bookings = append(bookings, booking) } if err = rows.Err(); err != nil { return bookings, err } return bookings, nil } func (b Booking) Save() { qStr, err := DB.Prepare((`UPDATE "anwesenheit" SET "id" = $1, "card_uid" = $2, "reader_id" = $3, "booking_type" = $4 WHERE "id" = $1;`)) if err != nil { log.Fatalf("Error preparing query: %v", err) return } _, err = qStr.Query(b.CounterId, b.CardUID, b.GeraetID, b.CheckInOut) if err != nil { log.Fatalf("Error executing query: %v", err) return } } func (b *Booking) Update(nb Booking) { if b.CheckInOut != nb.CheckInOut && nb.CheckInOut != 0 { b.CheckInOut = nb.CheckInOut } if b.CardUID != nb.CardUID && nb.CardUID != "" { b.CardUID = nb.CardUID } if b.GeraetID != nb.GeraetID && nb.GeraetID != 0 { b.GeraetID = nb.GeraetID } } func checkLastBooking(b Booking) bool { var check_in_out int stmt, err := DB.Prepare((`SELECT check_in_out FROM "anwesenheit" WHERE "card_uid" = $1 ORDER BY "timestamp" DESC LIMIT 1;`)) if err != nil { log.Fatalf("Error preparing query: %v", err) return false } err = stmt.QueryRow(b.CardUID).Scan(&check_in_out) if err == sql.ErrNoRows { return true } if err != nil { log.Println("Error checking last booking: ", err) return false } if int16(check_in_out) == b.CheckInOut { return false } return true }