| @@ -16,8 +16,12 @@ | ||
| 16 | 16 | * @var string $status |
| 17 | 17 | * @var array $action_buttons |
| 18 | 18 | * @var bool $is_grace_period |
| 19 | 19 | * @var int $grace_remaining |
| 20 | + * @var float $price Renewal total, after any discount that recurs. | |
| 21 | + * @var float $price_excl_tax Renewal subtotal before discount and tax. | |
| 22 | + * @var float $tax Tax on the discounted renewal amount. | |
| 23 | + * @var float $discount Discount that applies to each renewal. 0 when none recurs. | |
| 20 | 24 | * |
| 21 | 25 | * This template can be overridden by copying it to <your_theme>/subscription/myaccount/single.php |
| 22 | 26 | * |
| 23 | 27 | * @package SpringDevs\Subscription |
| @@ -45,8 +49,14 @@ | ||
| 45 | 49 | display: flex; |
| 46 | 50 | flex-wrap: wrap; |
| 47 | 51 | gap: 10px; |
| 48 | 52 | } |
| 53 | + .product-name .subscrpt-plan-term { | |
| 54 | + display: block; | |
| 55 | + margin-top: 4px; | |
| 56 | + font-size: 13px; | |
| 57 | + color: #6b7280; | |
| 58 | + } | |
| 49 | 59 | </style> |
| 50 | 60 | <table class="woocommerce-table woocommerce-table--order-details shop_table order_details subscription_details"> |
| 51 | 61 | <tbody> |
| 52 | 62 | <tr> |
| @@ -56,9 +66,9 @@ | ||
| 56 | 66 | <tr> |
| 57 | 67 | <td><?php esc_html_e( 'Status', 'subscription' ); ?></td> |
| 58 | 68 | <td> |
| 59 | 69 | <?php if ( $is_grace_period && $grace_remaining > 0 ) : ?> |
| 60 | - <span class="subscrpt-active grace-active"> | |
| 70 | + <span class="subscrpt-legacy-status subscrpt-legacy-status--active grace-active"> | |
| 61 | 71 | Active |
| 62 | 72 | |
| 63 | 73 | <?php |
| 64 | 74 | $grace_remaining_text = sprintf( |
| @@ -71,9 +81,9 @@ | ||
| 71 | 81 | <span class="dashicons dashicons-warning"></span> |
| 72 | 82 | </span> |
| 73 | 83 | </span> |
| 74 | 84 | <?php else : ?> |
| 75 | - <span class="subscrpt-<?php echo esc_attr( strtolower( $status ) ); ?>"> | |
| 85 | + <span class="subscrpt-legacy-status subscrpt-legacy-status--<?php echo esc_attr( strtolower( $status ) ); ?>"> | |
| 76 | 86 | <?php echo esc_html( $verbose_status ); ?> |
| 77 | 87 | </span> |
| 78 | 88 | <?php endif; ?> |
| 79 | 89 | </td> |
| @@ -98,8 +108,10 @@ | ||
| 98 | 108 | if ( 'null' == $trial || 'off' === $trial_mode ) { |
| 99 | 109 | esc_html_e( 'Start date', 'subscription' ); |
| 100 | 110 | } elseif ( 'extended' === $trial_mode ) { |
| 101 | 111 | esc_html_e( 'Trial End & Subscription Start', 'subscription' ); |
| 112 | + } elseif ( ! Helper::has_next_payment( $status ) ) { | |
| 113 | + esc_html_e( 'Trial End', 'subscription' ); | |
| 102 | 114 | } else { |
| 103 | 115 | esc_html_e( 'Trial End & First Billing', 'subscription' ); |
| 104 | 116 | } |
| 105 | 117 | ?> |
| @@ -105,9 +117,9 @@ | ||
| 105 | 117 | ?> |
| 106 | 118 | </td> |
| 107 | 119 | <td><?php echo esc_html( $start_date ); ?></td> |
| 108 | 120 | </tr> |
| 109 | - <?php if ( null == $trial || in_array( $trial_mode, array( 'off', 'extended' ), true ) ) : ?> | |
| 121 | + <?php if ( ( null == $trial || in_array( $trial_mode, array( 'off', 'extended' ), true ) ) && get_post_meta( $id, '_subscrpt_next_date', true ) && Helper::has_next_payment( $status ) ) : ?> | |
| 110 | 122 | <tr> |
| 111 | 123 | <td> |
| 112 | 124 | <?php |
| 113 | 125 | esc_html_e( 'Next payment date', 'subscription' ); |
| @@ -199,11 +211,14 @@ | ||
| 199 | 211 | |
| 200 | 212 | <!-- Access Duration Information for Split Payments --> |
| 201 | 213 | <?php if ( 'split_payment' === $payment_type && $max_payments > 0 ) : ?> |
| 202 | 214 | <?php |
| 203 | - $access_ends_timing = get_post_meta( $product_id, '_subscrpt_access_ends_timing', true ) ?: 'after_full_duration'; | |
| 204 | - $custom_duration_time = get_post_meta( $product_id, '_subscrpt_custom_access_duration_time', true ) ?: 1; | |
| 205 | - $custom_duration_type = get_post_meta( $product_id, '_subscrpt_custom_access_duration_type', true ) ?: 'months'; | |
| 215 | + // Plan subscriptions store access-ends on the subscription; classic ones on | |
| 216 | + // the product. Prefer the subscription meta, fall back to the product. | |
| 217 | + $access_ends_timing = get_post_meta( $id, '_subscrpt_access_ends_timing', true ); | |
| 218 | + $access_ends_timing = $access_ends_timing ? $access_ends_timing : ( get_post_meta( $product_id, '_subscrpt_access_ends_timing', true ) ?: 'after_full_duration' ); | |
| 219 | + $custom_duration_time = get_post_meta( $id, '_subscrpt_custom_access_duration_time', true ) ?: ( get_post_meta( $product_id, '_subscrpt_custom_access_duration_time', true ) ?: 1 ); | |
| 220 | + $custom_duration_type = get_post_meta( $id, '_subscrpt_custom_access_duration_type', true ) ?: ( get_post_meta( $product_id, '_subscrpt_custom_access_duration_type', true ) ?: 'months' ); | |
| 206 | 221 | |
| 207 | 222 | // Calculate access end date if Pro version is available |
| 208 | 223 | $access_end_date_string = null; |
| 209 | 224 | if ( function_exists( 'subscrpt_pro_activated' ) && subscrpt_pro_activated() ) { |
| @@ -296,8 +311,14 @@ | ||
| 296 | 311 | <tr class="order_item"> |
| 297 | 312 | <td class="product-name"> |
| 298 | 313 | <a href="<?php echo esc_html( $product_link ); ?>"><?php echo esc_html( $product_name ); ?></a> |
| 299 | 314 | <strong class="product-quantity">× <?php echo esc_html( $order_item->get_quantity() ); ?></strong> |
| 315 | + <?php | |
| 316 | + $plan_label = function_exists( 'subscrpt_get_subscription_plan_label' ) ? subscrpt_get_subscription_plan_label( $id ) : ''; | |
| 317 | + if ( $plan_label ) : | |
| 318 | + ?> | |
| 319 | + <span class="subscrpt-plan-term"><?php printf( /* translators: %s: plan name. */ esc_html__( 'Plan: %s', 'subscription' ), esc_html( $plan_label ) ); ?></span> | |
| 320 | + <?php endif; ?> | |
| 300 | 321 | </td> |
| 301 | 322 | <td class="product-total"> |
| 302 | 323 | <span class="woocommerce-Price-amount amount"> |
| 303 | 324 | <?php |
| @@ -318,8 +339,24 @@ | ||
| 318 | 339 | </span> |
| 319 | 340 | </td> |
| 320 | 341 | </tr> |
| 321 | 342 | |
| 343 | + <?php if ( ! empty( $discount ) && $discount > 0 ) : ?> | |
| 344 | + <tr class="subscrpt-recurring-discount"> | |
| 345 | + <th scope="row"><?php esc_html_e( 'Discount', 'subscription' ); ?>:</th> | |
| 346 | + <td> | |
| 347 | + <span class="woocommerce-Price-amount amount"> | |
| 348 | + <?php | |
| 349 | + printf( | |
| 350 | + '-%s', | |
| 351 | + wp_kses_post( wc_price( $discount, array( 'currency' => $order->get_currency() ) ) ) | |
| 352 | + ); | |
| 353 | + ?> | |
| 354 | + </span> | |
| 355 | + </td> | |
| 356 | + </tr> | |
| 357 | + <?php endif; ?> | |
| 358 | + | |
| 322 | 359 | <?php if ( $tax > 0 ) : ?> |
| 323 | 360 | <tr> |
| 324 | 361 | <th scope="row"><?php esc_html_e( 'Tax', 'subscription' ); ?>:</th> |
| 325 | 362 | <td> |
| @@ -343,13 +380,28 @@ | ||
| 343 | 380 | |
| 344 | 381 | <?php do_action( 'subscrpt_after_subscription_totals', (int) $id ); ?> |
| 345 | 382 | |
| 346 | 383 | <!-- Show related subscription orders --> |
| 384 | +<?php | |
| 385 | +/* | |
| 386 | + * Sequence number within this subscription: 1 = first (parent) order, then each | |
| 387 | + * renewal in order. Helper::get_related_orders() returns newest-first, so the | |
| 388 | + * map is built from the reversed list. Relations whose order no longer exists | |
| 389 | + * are skipped here as well, keeping the numbering gapless with the rendered rows. | |
| 390 | + */ | |
| 391 | +$related_order_seq = []; | |
| 392 | +foreach ( array_reverse( $related_orders ) as $subscrpt_relation ) { | |
| 393 | + if ( isset( $related_order_seq[ $subscrpt_relation->order_id ] ) || ! wc_get_order( $subscrpt_relation->order_id ) ) { | |
| 394 | + continue; | |
| 395 | + } | |
| 396 | + $related_order_seq[ $subscrpt_relation->order_id ] = count( $related_order_seq ) + 1; | |
| 397 | +} | |
| 398 | +?> | |
| 347 | 399 | <h2><?php echo esc_html_e( 'Related Orders', 'subscription' ); ?></h2> |
| 348 | 400 | <table class="woocommerce-table woocommerce-table--order-details shop_table order_details"> |
| 349 | 401 | <thead> |
| 350 | 402 | <tr> |
| 351 | - <th class="order-number"><?php echo esc_html_e( 'Order', 'subscription' ); ?></th> | |
| 403 | + <th class="order-number"><?php echo esc_html_e( '#', 'subscription' ); ?></th> | |
| 352 | 404 | <th class="order-type"><?php echo esc_html_e( 'Type', 'subscription' ); ?></th> |
| 353 | 405 | <th class="order-date"><?php echo esc_html_e( 'Date', 'subscription' ); ?></th> |
| 354 | 406 | <th class="order-status"><?php echo esc_html_e( 'Status', 'subscription' ); ?></th> |
| 355 | 407 | <th class="order-total"><?php echo esc_html_e( 'Total', 'subscription' ); ?></th> |
| @@ -385,10 +437,14 @@ | ||
| 385 | 437 | ?> |
| 386 | 438 | |
| 387 | 439 | <tr class="order_item"> |
| 388 | 440 | <td class="order-number"> |
| 389 | - <a href="<?php echo esc_url( wc_get_endpoint_url( 'view-order', $order_id, wc_get_page_permalink( 'myaccount' ) ) ); ?>"> | |
| 390 | - #<?php echo esc_html( $order_id ); ?> | |
| 441 | + <?php | |
| 442 | + // translators: %s: WooCommerce order number. | |
| 443 | + $order_number_label = sprintf( __( 'Order #%s', 'subscription' ), $order->get_order_number() ); | |
| 444 | + ?> | |
| 445 | + <a href="<?php echo esc_url( wc_get_endpoint_url( 'view-order', $order_id, wc_get_page_permalink( 'myaccount' ) ) ); ?>" title="<?php echo esc_attr( $order_number_label ); ?>" aria-label="<?php echo esc_attr( $order_number_label ); ?>"> | |
| 446 | + <?php echo esc_html( number_format_i18n( $related_order_seq[ $order_id ] ?? 0 ) ); ?> | |
| 391 | 447 | </a> |
| 392 | 448 | </td> |
| 393 | 449 | <td class="order-type"> |
| 394 | 450 | <?php echo esc_html( $order_type_label ); ?> |