feat(notifications): add admin notification acknowledgement on booking state changes
- Add AcknowledgePendingBookingNotification helper for acknowledging notifications - ConfirmBookingHandler: acknowledge pending notification when booking confirmed - Cancel handlers: acknowledge pending notification and only create cancelled_booking notification if booking was not in pending status - Add user_notification_preferences table with email, sms, push enabled flags - Update cancellation logic to check original status before creating notifications
This commit is contained in:
@@ -2,6 +2,7 @@ package bookings
|
||||
|
||||
import (
|
||||
"crussell/db"
|
||||
"crussell/handlers/notifications"
|
||||
"crussell/mw"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
@@ -1459,6 +1460,11 @@ func ConfirmBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := notifications.AcknowledgePendingBookingNotification(tx, r.Context(), bookingID); err != nil {
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Update service overrides individually
|
||||
if len(req.ServiceOverrides) > 0 {
|
||||
// First, verify all service IDs belong to this booking
|
||||
@@ -1574,6 +1580,19 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer tx.Rollback(r.Context())
|
||||
|
||||
// Get current status before updating
|
||||
var originalStatus string
|
||||
err = tx.QueryRow(r.Context(), "SELECT status FROM bookings WHERE id = $1 AND user_id = $2", bookingID, userID).Scan(&originalStatus)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
http.Error(w, "Booking not found or access denied", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Failed to get booking status %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Update booking status instead of deleting
|
||||
query := `
|
||||
UPDATE bookings
|
||||
@@ -1592,18 +1611,26 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Create admin notification for cancelled booking
|
||||
notificationQuery := `
|
||||
INSERT INTO admin_notifications (reason, booking_id, user_id)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
_, err = tx.Exec(r.Context(), notificationQuery, "cancelled_booking", bookingID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create admin notification for booking %s: %v", bookingID, err)
|
||||
// Acknowledge pending notification if exists
|
||||
if err := notifications.AcknowledgePendingBookingNotification(tx, r.Context(), bookingID); err != nil {
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Only notify on cancellation if booking was confirmed (not pending)
|
||||
if originalStatus == "confirmed" {
|
||||
notificationQuery := `
|
||||
INSERT INTO admin_notifications (reason, booking_id, user_id)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
_, err = tx.Exec(r.Context(), notificationQuery, "cancelled_booking", bookingID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create admin notification for booking %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(r.Context()); err != nil {
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
@@ -1628,18 +1655,39 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer tx.Rollback(r.Context())
|
||||
|
||||
// Create admin notification BEFORE deleting the booking
|
||||
notificationQuery := `
|
||||
INSERT INTO admin_notifications (reason, booking_id, user_id)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
_, err = tx.Exec(r.Context(), notificationQuery, "cancelled_booking", bookingID, userID)
|
||||
// Get current status before deleting
|
||||
var originalStatus string
|
||||
err = tx.QueryRow(r.Context(), "SELECT status FROM bookings WHERE id = $1 AND user_id = $2", bookingID, userID).Scan(&originalStatus)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create admin notification for booking %s: %v", bookingID, err)
|
||||
if err == sql.ErrNoRows {
|
||||
http.Error(w, "Booking not found or access denied", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Failed to get booking status %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Acknowledge pending notification if exists
|
||||
if err := notifications.AcknowledgePendingBookingNotification(tx, r.Context(), bookingID); err != nil {
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Only notify on cancellation if booking was not pending (e.g. confirmed, in_progress)
|
||||
if originalStatus != "pending" {
|
||||
notificationQuery := `
|
||||
INSERT INTO admin_notifications (reason, booking_id, user_id)
|
||||
VALUES ($1, $2, $3)
|
||||
`
|
||||
_, err = tx.Exec(r.Context(), notificationQuery, "cancelled_booking", bookingID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to create admin notification for booking %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Now delete the booking
|
||||
query := "DELETE FROM bookings WHERE id = $1 AND user_id = $2"
|
||||
result, err := tx.Exec(r.Context(), query, bookingID, userID)
|
||||
|
||||
Reference in New Issue
Block a user