fix: remove 3 dead code blocks (UserCancelBookingHandler, AdminGetInProgressBookingHandler, processImage)
This commit is contained in:
@@ -23,107 +23,6 @@ import (
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
// UserCancelBookingHandler allows an authenticated user to cancel a booking they own.
|
||||
// The update is performed in a transaction with notification handling.
|
||||
func UserCancelBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
bookingID := chi.URLParam(r, "id")
|
||||
if bookingID == "" || !validators.IsValidID(bookingID) {
|
||||
http.Error(w, "Booking not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := r.Context().Value(mw.UserIDKey).(string)
|
||||
if !ok || userID == "" {
|
||||
http.Error(w, "Authentication required", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
tx, err := db.Conn.Begin(r.Context())
|
||||
if err != nil {
|
||||
log.Printf("Failed to start transaction: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := tx.Rollback(r.Context()); err != nil && err.Error() != "tx is closed" {
|
||||
slog.Error("failed to rollback transaction", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// 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 errors.Is(err, pgx.ErrNoRows) {
|
||||
http.Error(w, "Booking not cancellable", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Failed to get booking status %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
res, err := tx.Exec(r.Context(), `
|
||||
UPDATE bookings
|
||||
SET status = 'client_cancelled', updated_at = $1
|
||||
WHERE id = $2 AND user_id = $3 AND status IN ('pending', 'confirmed', 'in_progress')
|
||||
`, clock.Now(), bookingID, userID)
|
||||
if err != nil {
|
||||
log.Printf("Failed to cancel booking %s: %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
rowsAffected := res.RowsAffected()
|
||||
if rowsAffected == 0 {
|
||||
http.Error(w, "Booking not cancellable", http.StatusNotFound)
|
||||
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
|
||||
}
|
||||
|
||||
if _, err := tx.Exec(r.Context(), `
|
||||
DELETE FROM booking_edit_requests WHERE booking_id = $1
|
||||
`, bookingID); err != nil {
|
||||
log.Printf("ALERT: failed to delete edit requests: %v", err)
|
||||
}
|
||||
if _, err := tx.Exec(r.Context(), `
|
||||
DELETE FROM time_blockers WHERE description = $1
|
||||
`, fmt.Sprintf("RESERVATION:edit_request:%s", bookingID)); err != nil {
|
||||
log.Printf("ALERT: failed to delete time_blocker: %v", err)
|
||||
}
|
||||
if _, err := tx.Exec(r.Context(), `
|
||||
DELETE FROM admin_notifications WHERE booking_id = $1 AND reason = 'edit_requested'
|
||||
`, bookingID); err != nil {
|
||||
log.Printf("ALERT: failed to delete edit_requested notification: %v", err)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(r.Context()); err != nil {
|
||||
log.Printf("Failed to commit user cancel: %v, %v", bookingID, err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
type AdminCancelBookingRequest struct {
|
||||
ForgiveFees *bool `json:"forgive_fees,omitempty"`
|
||||
ForgiveNoShow *bool `json:"forgive_noshow,omitempty"`
|
||||
@@ -305,63 +204,6 @@ func AdminCancelBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// AdminGetInProgressBookingHandler returns the booking that is currently in progress.
|
||||
// It joins the bookings table with users to populate the UserSummary in the returned Booking.
|
||||
func AdminGetInProgressBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var b Booking
|
||||
var userID, fullName string
|
||||
|
||||
err := db.Conn.QueryRow(r.Context(), `
|
||||
SELECT
|
||||
b.id,
|
||||
b.start_time,
|
||||
b.status,
|
||||
b.notes,
|
||||
b.created_at,
|
||||
b.updated_at,
|
||||
b.created_by,
|
||||
u.id,
|
||||
u.fn
|
||||
FROM bookings b
|
||||
LEFT JOIN users u ON b.user_id = u.id
|
||||
WHERE b.status = 'in_progress'
|
||||
ORDER BY b.start_time
|
||||
LIMIT 1
|
||||
`).Scan(
|
||||
&b.ID,
|
||||
&b.StartTime,
|
||||
&b.Status,
|
||||
&b.Notes,
|
||||
&b.CreatedAt,
|
||||
&b.UpdatedAt,
|
||||
&b.CreatedBy,
|
||||
&userID,
|
||||
&fullName,
|
||||
)
|
||||
if err != nil {
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
http.Error(w, "No in-progress booking found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
log.Printf("Failed to fetch in-progress booking: %v", err)
|
||||
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Populate the UserSummary field
|
||||
b.User = &UserSummary{
|
||||
ID: userID,
|
||||
FullName: fullName,
|
||||
FirstName: "", // not available here
|
||||
LastName: "", // not available here
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(b); err != nil {
|
||||
log.Printf("Failed to encode booking response: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
type AdminCreateBookingForUserRequest struct {
|
||||
UserID string `json:"user_id" validate:"required"`
|
||||
StartTime time.Time `json:"start_time" validate:"required"`
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/kovidgoyal/imaging"
|
||||
)
|
||||
|
||||
const MaxInputLength = 256
|
||||
@@ -44,26 +43,6 @@ func mimeTypeForField(fieldName string) string {
|
||||
}
|
||||
}
|
||||
|
||||
// processImage strips metadata and auto-orients the image
|
||||
//nolint:unused
|
||||
func processImage(data []byte, quality int) ([]byte, error) {
|
||||
// Decode the image - this automatically applies EXIF orientation
|
||||
// and strips all metadata (EXIF, GPS, etc.)
|
||||
img, err := imaging.Decode(bytes.NewReader(data), imaging.AutoOrientation(true))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode image: %w", err)
|
||||
}
|
||||
|
||||
// Encode to JPEG without any metadata
|
||||
var buf bytes.Buffer
|
||||
err = imaging.Encode(&buf, img, imaging.JPEG, imaging.JPEGQuality(quality))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to encode image: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// validateInputLength returns an error if input exceeds max length
|
||||
|
||||
func validateInputLength(input string) error {
|
||||
|
||||
Reference in New Issue
Block a user