package infra import ( "database/sql" "fmt" "net/http" "time" ) // CRUDDeleteHandler retorna un http.HandlerFunc que borra un registro por id. // Si el recurso es SoftDelete, hace UPDATE deleted_at en vez de DELETE real. // Responde 204 sin body si el borrado es exitoso. 404 si el registro no existe. func CRUDDeleteHandler(res CRUDResource, db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") if id == "" { HTTPErrorResponse(w, HTTPError{Status: http.StatusBadRequest, Code: "missing_id", Message: "id path parameter is required"}) return } // Verificar que existe existsSQL := fmt.Sprintf("SELECT 1 FROM %s WHERE id = ?", res.Table) if res.SoftDelete { existsSQL += " AND deleted_at IS NULL" } var dummy int if err := db.QueryRow(existsSQL, id).Scan(&dummy); err != nil { if err == sql.ErrNoRows { HTTPErrorResponse(w, HTTPError{Status: http.StatusNotFound, Code: "not_found", Message: fmt.Sprintf("%s %q not found", res.Name, id)}) return } HTTPErrorResponse(w, HTTPError{Status: http.StatusInternalServerError, Code: "db_error", Message: err.Error()}) return } var err error if res.SoftDelete { now := time.Now().UTC().Format(time.RFC3339Nano) _, err = db.Exec(fmt.Sprintf("UPDATE %s SET deleted_at = ?, updated_at = ? WHERE id = ?", res.Table), now, now, id) } else { _, err = db.Exec(fmt.Sprintf("DELETE FROM %s WHERE id = ?", res.Table), id) } if err != nil { HTTPErrorResponse(w, HTTPError{Status: http.StatusInternalServerError, Code: "db_error", Message: err.Error()}) return } w.WriteHeader(http.StatusNoContent) } }