Custom post type permalink returns bad url

get_permalink() (which is used by get_the_permalink() and the_permalink()) returns the “ugly” URL if the post is not published, e.g. draft or scheduled, but you can use the following function instead which temporarily sets the post status to publish so that we’d get the pretty URL.

function get_future_permalink( $id ) {
    if ( $post = get_post( $id ) ) {
        $post->post_status="publish";
        return get_permalink( $post );
    }
    return '';
}

So instead of get_permalink( 258 ), you’d use get_future_permalink( 258 ), where 258 is the post ID.