Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎉 Implemented display prices inclusive tax in course list, details page, cart page #1231

Open
wants to merge 16 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,27 @@ function TaxSettingGlobal() {
/>
</div>
<div css={styles.checkboxWrapper}>
<Show when={isTaxIncludedInPrice === TaxCollectionProcess.taxIsNotIncluded}>
<Controller
control={form.control}
name="show_price_with_tax"
render={(controllerProps) => {
return (
<div>
<FormCheckbox
{...controllerProps}
label={__('Display prices inclusive tax', 'tutor')}
labelCss={styles.checkboxLabel}
/>
<span css={styles.checkboxSubText}>
{__(
'Show prices with tax included, so customers see the final amount they’ll pay upfront',
'tutor',
)}
</span>
</div>
);
}}
/>
</Show>
<Controller
control={form.control}
name="show_price_with_tax"
render={(controllerProps) => {
return (
<div>
<FormCheckbox
{...controllerProps}
label={__('Display prices inclusive tax', 'tutor')}
labelCss={styles.checkboxLabel}
/>
<span css={styles.checkboxSubText}>
{__(
'Show prices with tax included, so customers see the final amount they’ll pay upfront',
'tutor',
)}
</span>
</div>
);
}}
/>
</div>
</div>
</Card>
Expand Down
6 changes: 6 additions & 0 deletions assets/scss/admin-dashboard/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@
.paypal_payment_gateway, .supported_payment_gateway, .stripe_payment_gateway, .manual_payment_gateway {
margin-bottom: 8px;
}

.table-dashboard-course-list{
.tutor-course-price-tax{
font-size: 12px;
}
}
6 changes: 5 additions & 1 deletion assets/scss/front/__archive.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,10 @@ table.course-single-gradebooks a {
line-height: 160%;
color: #757c8e;
}
.tutor-course-price-tax{
font-size: 12px;
font-weight: 500;
}
}

.list-item-button,
Expand Down Expand Up @@ -1473,4 +1477,4 @@ table.course-single-gradebooks a {
*/
.list-item-button .edd-has-js.edd-no-js {
display: none !important;
}
}
57 changes: 48 additions & 9 deletions classes/Course.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,20 @@ class Course extends Tutor_Base {
*
* @since 3.0.0
*/
const COURSE_PRICE_TYPE_META = '_tutor_course_price_type';
const COURSE_PRICE_META = 'tutor_course_price';
const COURSE_SALE_PRICE_META = 'tutor_course_sale_price';
const COURSE_PRICE_TYPE_META = '_tutor_course_price_type';
const COURSE_PRICE_META = 'tutor_course_price';
const COURSE_SALE_PRICE_META = 'tutor_course_sale_price';
const COURSE_SELLING_OPTION_META = 'tutor_course_selling_option';

/**
* Selling option constants
*
* @since 3.0.0
*/
const SELLING_OPTION_ONE_TIME = 'one_time';
const SELLING_OPTION_SUBSCRIPTION = 'subscription';
const SELLING_OPTION_BOTH = 'both';


/**
* Additional course meta info
Expand Down Expand Up @@ -314,6 +325,34 @@ private function is_valid_video_source_type( string $source_type ): bool {
return in_array( $source_type, $supported_types, true );
}

/**
* Get course selling options.
*
* @since 3.0.0
*
* @return array
*/
public static function get_selling_options() {
return array(
self::SELLING_OPTION_ONE_TIME,
self::SELLING_OPTION_SUBSCRIPTION,
self::SELLING_OPTION_BOTH,
);
}

/**
* Get course selling option
*
* @since 3.0.0
*
* @param int $course_id course id.
*
* @return string
*/
public static function get_selling_option( $course_id ) {
return get_post_meta( $course_id, self::COURSE_SELLING_OPTION_META, true );
}

/**
* Validate video source
*
Expand Down Expand Up @@ -1252,12 +1291,12 @@ public function enqueue_course_builder_assets() {
);
}

$data['dashboard_url'] = $dashboard_url;
$data['backend_course_list_url'] = get_admin_url( null, '?page=tutor' );
$data['frontend_course_list_url'] = tutor_utils()->tutor_dashboard_url( 'my-courses' );
$data['timezones'] = tutor_global_timezone_lists();
$data['difficulty_levels'] = $difficulty_levels;
$data['wp_rest_nonce'] = wp_create_nonce( 'wp_rest' );
$data['dashboard_url'] = $dashboard_url;
$data['backend_course_list_url'] = get_admin_url( null, '?page=tutor' );
$data['frontend_course_list_url'] = tutor_utils()->tutor_dashboard_url( 'my-courses' );
$data['timezones'] = tutor_global_timezone_lists();
$data['difficulty_levels'] = $difficulty_levels;
$data['wp_rest_nonce'] = wp_create_nonce( 'wp_rest' );

$data = apply_filters( 'tutor_course_builder_localized_data', $data );

Expand Down
3 changes: 2 additions & 1 deletion classes/Tutor.php
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,8 @@ final class Tutor {
/**
* Course List
*
* @var $course_list
* @var Course_List
*
* @since 2.0.0
*/
public $course_list;
Expand Down
26 changes: 22 additions & 4 deletions classes/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use Tutor\Cache\TutorCache;
use Tutor\Ecommerce\Ecommerce;
use Tutor\Ecommerce\Tax;
use Tutor\Helpers\HttpHelper;
use Tutor\Helpers\QueryHelper;
use Tutor\Models\QuizModel;
Expand Down Expand Up @@ -803,7 +804,7 @@
"SELECT count(umeta_id)
FROM {$wpdb->usermeta}
WHERE user_id = %d
AND meta_key IN ('{$in_ids}')

Check failure on line 807 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable $in_ids at AND meta_key IN ('{$in_ids}')&#10;
",
$user_id
)
Expand Down Expand Up @@ -896,7 +897,7 @@
WHERE comment_type = %s
AND comment_approved = %s
AND user_id = %d
AND comment_post_ID IN({$assignment_ids_str});

Check failure on line 900 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable $assignment_ids_str at AND comment_post_ID IN({$assignment_ids_str});&#10;
",
'tutor_assignment',
'submitted',
Expand Down Expand Up @@ -1207,6 +1208,7 @@
* Such as Calculate discount by regular price and sale price
*
* @since 1.3.1
* @since 3.0.0 tax support added for monetized by tutor.
*
* @param int $course_id courrse ID.
*
Expand All @@ -1223,8 +1225,25 @@
$monetize_by = $this->get_option( 'monetize_by' );

if ( $this->is_monetize_by_tutor() ) {
$prices['regular_price'] = (float) get_post_meta( $course_id, Course::COURSE_PRICE_META, true );
$prices['sale_price'] = (float) get_post_meta( $course_id, Course::COURSE_SALE_PRICE_META, true );
$regular_price = (float) get_post_meta( $course_id, Course::COURSE_PRICE_META, true );
$sale_price = (float) get_post_meta( $course_id, Course::COURSE_SALE_PRICE_META, true );

$display_price = $sale_price ? $sale_price : $regular_price;
$show_price_with_tax = Tax::show_price_with_tax();
$user_logged_in = is_user_logged_in();

$tax_amount = 0;
if ( $show_price_with_tax && is_numeric( $display_price ) && ! Tax::is_tax_included_in_price() ) {
$tax_rate = $user_logged_in ? Tax::get_user_tax_rate() : 0;
$tax_amount = Tax::calculate_tax( $display_price, $tax_rate );
$display_price += $tax_amount;
}

$prices['regular_price'] = $regular_price;
$prices['sale_price'] = $sale_price;
$prices['display_price'] = $display_price;
$prices['tax_amount'] = $tax_amount;
$prices['show_price_with_tax'] = $user_logged_in && $show_price_with_tax;
} else {
$product_id = $this->get_course_product_id( $course_id );
if ( $product_id ) {
Expand Down Expand Up @@ -1305,7 +1324,7 @@
AND post_type = %s
AND post_parent = %d
AND post_author = %d
{$status_clause};

Check failure on line 1327 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable $status_clause at {$status_clause};&#10;
",
'tutor_enrolled',
$course_id,
Expand Down Expand Up @@ -1338,7 +1357,7 @@
$user_id = $this->get_user_id( $user_id );

// Delete Quiz submissions.
$attempts = \Tutor\Models\QuizModel::get_quiz_attempts_by_course_ids( $start = 0, $limit = 99999999, $course_ids = array( $course_id ), $search_filter = '', $course_filter = '', $date_filter = '', $order_filter = '', $user_id = $user_id, false, true );

Check failure on line 1360 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Assignments must be the first block of code on a line

if ( is_array( $attempts ) ) {
$attempt_ids = array_map(
Expand Down Expand Up @@ -1516,7 +1535,7 @@
ON topic.ID = items.post_parent
WHERE topic.post_parent = %d
AND items.post_status = %s
" . ( $post_type ? " AND items.post_type='{$post_type}' " : '' ) . '

Check failure on line 1538 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found $post_type

Check failure on line 1538 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found ?

Check failure on line 1538 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found interpolated variable $post_type at &quot; AND items.post_type='{$post_type}' &quot;

Check failure on line 1538 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Use placeholders and $wpdb-&gt;prepare(); found :
ORDER BY topic.menu_order ASC,
items.menu_order ASC;
',
Expand Down Expand Up @@ -1686,8 +1705,8 @@
public function playtime_string( $seconds ) {
$sign = ( ( $seconds < 0 ) ? '-' : '' );
$seconds = round( abs( $seconds ) );
$H = (int) floor( $seconds / 3600 );

Check failure on line 1708 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Variable &quot;$H&quot; is not in valid snake_case format, try &quot;$h&quot;
$M = (int) floor( ( $seconds - ( 3600 * $H ) ) / 60 );

Check failure on line 1709 in classes/Utils.php

View workflow job for this annotation

GitHub Actions / WPCS

Variable &quot;$M&quot; is not in valid snake_case format, try &quot;$m&quot;
$S = (int) round( $seconds - ( 3600 * $H ) - ( 60 * $M ) );
return $sign . ( $H ? $H . ':' : '' ) . ( $H ? str_pad( $M, 2, '0', STR_PAD_LEFT ) : intval( $M ) ) . ':' . str_pad( $S, 2, 0, STR_PAD_LEFT );
}
Expand Down Expand Up @@ -10245,11 +10264,10 @@
'post_status' => 'inherit',
);

$media_id = wp_insert_attachment( $attachment, $uploaded['file'] );
$media_id = wp_insert_attachment( $attachment, $uploaded['file'] );
$attach_data = wp_generate_attachment_metadata( $media_id, $uploaded['file'] );
wp_update_attachment_metadata( $media_id, $attach_data );


return (object) array(
'id' => $media_id,
'url' => $uploaded['url'],
Expand Down
11 changes: 11 additions & 0 deletions ecommerce/Tax.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ public static function is_tax_included_in_price() {
return (bool) self::get_setting( 'is_tax_included_in_price' );
}

/**
* Show price with tax in course list and details.
*
* @since 3.0.0
*
* @return bool
*/
public static function show_price_with_tax() {
return (bool) self::get_setting( 'show_price_with_tax' );
}

/**
* Get tax type.
*
Expand Down
19 changes: 11 additions & 8 deletions includes/tutor-general-functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,7 @@ function tutor_get_manual_payment_gateways() {
if ( ! function_exists( 'tutor_get_course_formatted_price_html' ) ) {
/**
* Get course formatted price
* Only for monetized by tutor.
*
* @since 3.0.0
*
Expand All @@ -1511,22 +1512,24 @@ function tutor_get_manual_payment_gateways() {
* @return string|void
*/
function tutor_get_course_formatted_price_html( $course_id, $echo = true ) {
$regular_price = get_post_meta( $course_id, Course::COURSE_PRICE_META, true );
$sale_price = get_post_meta( $course_id, Course::COURSE_SALE_PRICE_META, true );
$price_data = tutor_utils()->get_raw_course_price( $course_id );

if ( ! $regular_price ) {
if ( ! $price_data->regular_price ) {
return;
}
ob_start();
?>
<div>
<?php if ( $sale_price ) : ?>
<span><?php tutor_print_formatted_price( $sale_price ); ?></span>
<del><?php tutor_print_formatted_price( $regular_price ); ?></del>
<div class="list-item-price tutor-item-price">
<?php if ( $price_data->sale_price ) : ?>
<span><?php tutor_print_formatted_price( $price_data->display_price ); ?></span>
<del><?php tutor_print_formatted_price( $price_data->regular_price ); ?></del>
<?php else : ?>
<span><?php tutor_print_formatted_price( $regular_price ); ?></span>
<span><?php tutor_print_formatted_price( $price_data->display_price ); ?></span>
<?php endif; ?>
</div>
<?php if ( $price_data->show_price_with_tax ) : ?>
<div class="tutor-course-price-tax tutor-color-muted"><?php esc_html_e( 'Incl. tax', 'tutor' ); ?></div>
<?php endif; ?>
<?php
$content = apply_filters( 'tutor_course_formatted_price', ob_get_clean() );
if ( $echo ) {
Expand Down
11 changes: 4 additions & 7 deletions templates/dashboard/my-courses.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
$paged = Input::get( 'current_page', 1, Input::TYPE_INT );
$offset = $per_page * ( $paged - 1 );

$results = CourseModel::get_courses_by_instructor( $current_user_id, $status, $offset, $per_page );
$results = CourseModel::get_courses_by_instructor( $current_user_id, $status, $offset, $per_page );
$show_course_delete = true;
if ( ! current_user_can( 'administrator' ) && ! tutor_utils()->get_option( 'instructor_can_delete_course' ) ) {
$show_course_delete = false;
Expand Down Expand Up @@ -95,7 +95,7 @@
$course_students = tutor_utils()->count_enrolled_users_by_course();
$is_main_instructor = CourseModel::is_main_instructor( $post->ID );
?>

<div id="<?php echo esc_attr( $row_id ); ?>" class="tutor-card tutor-course-card tutor-mycourse-<?php the_ID(); ?>">
<a href="<?php echo esc_url( get_the_permalink() ); ?>" class="tutor-d-block">
<div class="tutor-ratio tutor-ratio-16x9">
Expand Down Expand Up @@ -158,9 +158,6 @@
<div class="tutor-card-footer">
<div class="tutor-d-flex tutor-align-center tutor-justify-between">
<div class="tutor-d-flex tutor-align-center">
<span class="tutor-fs-7 tutor-fw-medium tutor-color-muted tutor-mr-4">
<?php esc_html_e( 'Price:', 'tutor' ); ?>
</span>
<span class="tutor-fs-7 tutor-fw-medium tutor-color-black">
<?php
$price = tutor_utils()->get_course_price();
Expand All @@ -181,9 +178,9 @@
<span class="tutor-icon-kebab-menu" area-hidden="true"></span>
</button>
<div id="table-dashboard-course-list-<?php echo esc_attr( $post->ID ); ?>" class="tutor-dropdown tutor-dropdown-dark tutor-text-left">

<!-- Submit Action -->
<?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_DRAFT ) ) ) : ?>
<?php if ( tutor()->has_pro && in_array( $post->post_status, array( CourseModel::STATUS_DRAFT ), true ) ) : ?>
<?php
$params = http_build_query(
array(
Expand Down
Loading
Loading