WooCommerce

<?php
/**
 * Client wants only logged in users to see prices and buy non-sale items while allowing all users to see prices and buy
 * on sale items
 */

/**
 *
 * filters woocommerce_is_purchasable for not onsale items
 *
 * @param $new_cart
 *
 * @return mixed
 */
function prefix_hack_for_on_sale_only( $purchasable, $product ) {
	if ( ! is_admin() && ! is_user_logged_in() && ! $product->is_on_sale() ) {
		return false;
	}
	return $purchasable;
}
add_filter('woocommerce_is_purchasable', 'prefix_hack_for_on_sale_only', 1, 2 );

/**
 * Output account link for non-sale products when user is not logged in
 *
 * @return bool|string
 */
function prefix_login_for_prices() {

	if ( ! class_exists('WooCommerce') )
		return false;

	global $product;

	$login = false;

	if ( ! is_user_logged_in() && ! $product->is_purchasable() ) {

		remove_filter('woocommerce_is_purchasable', 'prefix_hack_for_on_sale_only', 1 );

		$login_url = wc_get_account_endpoint_url( 'dashboard' );

		if ( is_singular( 'product' ) ) {
			$login_url = add_query_arg( 'redirect_to', urlencode( get_permalink() ), $login_url );
		}

		if ( $product->is_purchasable() ) {
			$login = sprintf(
				'<a href="%1$s">%2$s</a>',
				esc_url( $login_url ),
				esc_html__( 'Sign in to view price', 'text-domain' )
			);
		}

		add_filter('woocommerce_is_purchasable', 'prefix_hack_for_on_sale_only', 1, 2 );

	}

	return $login;
}