Plugin Directory

Changeset 3469742


Ignore:
Timestamp:
02/25/2026 09:46:47 PM (5 weeks ago)
Author:
Elliotvs
Message:

7.5.0

Location:
woo-coupon-usage/trunk
Files:
1 added
39 edited

Legend:

Unmodified
Added
Removed
  • woo-coupon-usage/trunk/css/admin-affiliate-users-table.css

    r3462634 r3469742  
    2222}
    2323.wcusage-avatar {
    24     border-radius: 50%;
    25     width: 40px;
    26     height: 40px;
    27     object-fit: cover;
    28     display: inline-block;
     24    border-radius: 50% !important;
     25    width: 40px !important;
     26    height: 40px !important;
     27    object-fit: cover !important;
     28    display: inline-block !important;
     29    vertical-align: middle;
     30    box-shadow: 0 1px 3px rgba(0,0,0,0.12);
    2931}
    3032.wcusage-idcell {
     
    165167    vertical-align: middle;
    166168}
     169.wp-list-table.mlausers tbody td,
     170.wp-list-table.mlausers thead th {
     171    vertical-align: middle !important;
     172}
    167173/* On smaller screens, stack avatar above the ID */
    168174@media screen and (max-width: 1500px) {
     
    175181    }
    176182}
     183
     184/* =========================================================
     185   MLA Users Table column widths
     186   ========================================================= */
     187.wp-list-table .column-mla_sub_affiliates {
     188    width: 120px;
     189    text-align: center;
     190}
     191.wp-list-table .column-mla_payouts {
     192    width: 160px;
     193    text-align: center;
     194}
     195.wp-list-table .column-mla_tiers {
     196    width: 110px;
     197    text-align: center;
     198}
     199.wp-list-table .column-view_mla_affiliate {
     200    width: 160px;
     201    text-align: center;
     202}
     203th.column-mla_sub_affiliates,
     204th.column-mla_payouts,
     205th.column-mla_tiers,
     206th.column-view_mla_affiliate {
     207    text-align: center;
     208}
     209
     210/* =========================================================
     211   MLA Users Table — ID cell & checkbox overrides
     212   (must win over admin-style.css padding: 22px 5px !important)
     213   ========================================================= */
     214.wp-list-table.mlausers .column-cb {
     215    width: 40px !important;
     216}
     217.wp-list-table.mlausers .column-ID {
     218    vertical-align: middle !important;
     219}
     220.wp-list-table.mlausers td.column-ID {
     221    vertical-align: middle !important;
     222}
     223.wp-list-table.mlausers .wcusage-idcell {
     224    display: flex;
     225    align-items: center;
     226    justify-content: center;
     227    gap: 8px;
     228}
     229.wp-list-table.mlausers .wcusage-avatar {
     230    border-radius: 50% !important;
     231    width: 40px !important;
     232    height: 40px !important;
     233    object-fit: cover !important;
     234    display: inline-block !important;
     235    vertical-align: middle !important;
     236    flex-shrink: 0;
     237}
  • woo-coupon-usage/trunk/css/admin-style.css

    r3462634 r3469742  
    16341634.wp-list-table.referrals th,
    16351635.wp-list-table.affiliateusers th,
     1636.wp-list-table.mlausers th,
    16361637.wp-list-table.affiliatecoupons th {
    16371638    text-align: center;
     
    16441645.wp-list-table.referrals th a,
    16451646.wp-list-table.affiliateusers th a,
     1647.wp-list-table.mlausers th a,
    16461648.wp-list-table.affiliatecoupons td a {
    16471649    display: inline-block;
     
    16701672.wp-list-table.referrals tr:hover,
    16711673.wp-list-table.affiliateusers tr:hover,
     1674.wp-list-table.mlausers tr:hover,
    16721675.wp-list-table.affiliatecoupons tr:hover {
    16731676    background: #f4fcfc;
     
    16811684.wp-list-table.referrals td,
    16821685.wp-list-table.affiliateusers td, .wp-list-table.affiliateusers th,
     1686.wp-list-table.mlausers td, .wp-list-table.mlausers th,
    16831687.wp-list-table.affiliatecoupons td {
    16841688    width: auto;
     
    16911695.wp-list-table.referrals tr td,
    16921696.wp-list-table.affiliateusers tr td, .wp-list-table.affiliateusers tr th,
     1697.wp-list-table.mlausers tr td, .wp-list-table.mlausers tr th,
    16931698.wp-list-table.registration tr td {
    16941699    border-bottom: 1px solid #cfcfcf;
     
    16961701}
    16971702
     1703.wp-list-table.mlausers tr td.check-column,
     1704.wp-list-table.mlausers tr th.check-column {
     1705    width: 40px !important;
     1706    padding: 6px 0 6px 8px !important;
     1707    vertical-align: middle !important;
     1708}
     1709.wp-list-table.mlausers tr td.column-ID {
     1710    vertical-align: middle !important;
     1711}
     1712
    16981713.wp-list-table.registration .action1.column-action1 {
    16991714    padding: 10px;
     
    17021717.admin_page_wcusage_activity .column-id, .payout .column-id {
    17031718    width: 55px;
     1719}
     1720
     1721/* Activity Log Filters */
     1722.wcusage-activity-filters {
     1723    display: flex;
     1724    flex-wrap: wrap;
     1725    align-items: center;
     1726    gap: 6px;
     1727    padding: 6px 0;
     1728}
     1729.wcusage-activity-filters input[type="text"],
     1730.wcusage-activity-filters input[type="date"],
     1731.wcusage-activity-filters select {
     1732    height: 32px;
     1733    vertical-align: middle;
     1734}
     1735.wcusage-activity-date-label {
     1736    font-size: 13px;
     1737    line-height: 32px;
     1738    margin: 0 2px 0 4px;
     1739}
     1740.admin_page_wcusage_activity .column-event {
     1741    text-align: left !important;
     1742}
     1743@media screen and (min-width: 540px) {
     1744    .admin_page_wcusage_activity .column-user_id {
     1745        width: 250px;
     1746        max-width: 100%;
     1747    }
    17041748}
    17051749
     
    17501794        margin: 15px 0;
    17511795    }
     1796
     1797/* PRO Modules Search */
     1798.wcu-pro-modules-search-wrap {
     1799    position: relative;
     1800    display: inline-flex;
     1801    align-items: center;
     1802    margin-bottom: 16px;
     1803    margin-top: 4px;
     1804}
     1805
     1806.wcu-pro-modules-search-icon {
     1807    position: absolute;
     1808    left: 9px;
     1809    top: 50%;
     1810    transform: translateY(-50%);
     1811    color: #777;
     1812    font-size: 18px;
     1813    pointer-events: none;
     1814}
     1815
     1816#wcu-pro-modules-search {
     1817    padding: 7px 12px 7px 34px !important;
     1818    font-size: 14px !important;
     1819    border: 1px solid #c3c4c7 !important;
     1820    border-radius: 6px !important;
     1821    width: 280px !important;
     1822    max-width: 100% !important;
     1823    box-shadow: none !important;
     1824    outline: none !important;
     1825    background: #fff !important;
     1826    line-height: 1.4 !important;
     1827}
     1828
     1829#wcu-pro-modules-search:focus {
     1830    border-color: #2271b1 !important;
     1831    box-shadow: 0 0 0 1px #2271b1 !important;
     1832}
     1833
     1834#wcu-pro-modules-no-results {
     1835    color: #555;
     1836    font-style: italic;
     1837    margin-bottom: 12px;
     1838    margin-top: -8px;
     1839}
    17521840
    17531841.pro-details {
     
    30673155
    30683156.wcu-loading-loader {
     3157    margin: 25px auto 0 auto;
    30693158    width: 40px;
    30703159    height: 40px;
    3071     margin: 25px auto 0 auto;
     3160    border: 3px solid rgba(0, 0, 0, 0.08);
     3161    border-top-color: #3498db;
     3162    border-radius: 50%;
     3163    animation: wcu-spin 0.8s ease-in-out infinite;
     3164    box-sizing: border-box;
     3165}
     3166
     3167@keyframes wcu-spin {
     3168    to {
     3169        transform: rotate(360deg);
     3170    }
     3171}
     3172
     3173.wcu-loading-loader-text {
     3174    margin: 14px auto 0 auto;
     3175    font-weight: 600;
     3176    font-size: 14px;
     3177    text-align: center;
     3178    color: #7f8c8d;
     3179    letter-spacing: 0.3px;
     3180    width: auto;
     3181}
     3182
     3183.wcu-loading-loader-subtext {
     3184    margin: 6px auto 0 auto;
     3185    font-weight: 400;
     3186    font-size: 12.5px;
     3187    text-align: center;
     3188    color: #b0b0b0;
     3189    width: auto;
     3190    max-width: 400px;
     3191    line-height: 1.5;
     3192}
     3193
     3194.wcu-loading-loader-subtext a {
     3195    color: #b0b0b0;
     3196    text-decoration: underline;
     3197}
     3198
     3199.wcu-loading-image {
     3200    display: flex;
     3201    flex-direction: column;
     3202    align-items: center;
     3203    justify-content: center;
     3204    padding: 30px 20px;
     3205}
     3206
     3207.wcu-loading-image.wcu-loading-stats {
     3208    align-items: flex-start;
     3209    padding: 30px 0;
     3210}
     3211
     3212.wcu-loading-image.wcu-loading-stats .wcu-loading-loader {
     3213    margin-left: 0;
     3214}
     3215
     3216.wcu-loading-image.wcu-loading-stats .wcu-loading-loader-text,
     3217.wcu-loading-image.wcu-loading-stats .wcu-loading-loader-subtext {
     3218    text-align: left;
     3219    margin-left: 0;
    30723220}
    30733221
  • woo-coupon-usage/trunk/css/admin-view-affiliate.css

    r3450056 r3469742  
    611611}
    612612
     613/* Copy link button hover */
     614.wcusage-tab-content .wcusage-copy-link-button {
     615    cursor: pointer;
     616    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.1s ease;
     617}
     618.wcusage-tab-content .wcusage-copy-link-button:hover {
     619    background: #007cba !important;
     620    border-color: #007cba !important;
     621    color: #fff;
     622    transform: translateY(-1px);
     623    box-shadow: 0 2px 6px rgba(0, 124, 186, 0.35);
     624}
     625.wcusage-tab-content .wcusage-copy-link-button:hover i {
     626    color: #fff;
     627}
     628.wcusage-tab-content .wcusage-copy-link-button:active {
     629    transform: translateY(0);
     630    box-shadow: none;
     631}
     632
    613633/* Ensure all tables inside tab content fill container width on large screens */
    614634.wcusage-tab-content table.wp-list-table { width: 100%; }
     
    10251045    background: #005a87;
    10261046    border-color: #005a87;
     1047    color: #fff;
    10271048    transform: translateY(-1px);
    10281049    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
     
    11091130}
    11101131
     1132/* Mobile header layout */
     1133@media (max-width: 782px) {
     1134    /* Stack the heading block so it takes full width */
     1135    .wp-heading-inline {
     1136        display: flex !important;
     1137        flex-direction: column;
     1138        align-items: center;
     1139        text-align: center;
     1140        width: 100%;
     1141        margin-bottom: 12px !important;
     1142    }
     1143
     1144    /* Center the avatar */
     1145    .wcusage-user-avatar {
     1146        margin: 0 0 8px 0 !important;
     1147    }
     1148
     1149    /* Dashboard buttons: wrap and center beneath avatar/name */
     1150    .wp-heading-inline .wcusage-preview-button {
     1151        margin: 6px 0 0 0 !important;
     1152        width: 100%;
     1153        text-align: center;
     1154        justify-content: center;
     1155        display: inline-flex;
     1156        box-sizing: border-box;
     1157    }
     1158
     1159    /* Right-side container: un-float and center below the heading */
     1160    .wcusage-view-affiliate-header-actions {
     1161        float: none !important;
     1162        display: flex;
     1163        flex-direction: column;
     1164        align-items: center;
     1165        width: 100%;
     1166        margin-bottom: 16px;
     1167    }
     1168
     1169    .wcusage-view-affiliate-header-actions .wcusage-back-button {
     1170        width: 100%;
     1171        justify-content: center;
     1172        text-align: center;
     1173        margin: 0 !important;
     1174    }
     1175
     1176    .wcusage-view-affiliate-header-actions .wcusage-delete-dropdown {
     1177        margin-top: 8px !important;
     1178        display: flex;
     1179        justify-content: center;
     1180        width: 100%;
     1181    }
     1182}
     1183
    11111184/* User Avatar Styling */
    11121185.wcusage-user-avatar {
     
    11441217}
    11451218
     1219/* Mobile tab dropdown */
     1220.wcusage-tab-select-wrapper {
     1221    display: none;
     1222}
     1223@media (max-width: 782px) {
     1224    .wcusage-tabs {
     1225        display: none !important;
     1226    }
     1227    .wcusage-tab-select-wrapper {
     1228        display: block;
     1229        width: 100%;
     1230        margin-bottom: 16px;
     1231    }
     1232    .wcusage-tab-select {
     1233        width: 100%;
     1234        box-sizing: border-box;
     1235        padding: 15px 16px;
     1236        text-align: center;
     1237        font-size: 20px !important;
     1238        font-weight: 500;
     1239        border: 2px solid #007cba;
     1240        border-radius: 6px;
     1241        background: #fff;
     1242        color: #23282d;
     1243        appearance: none;
     1244        -webkit-appearance: none;
     1245        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%23007cba' d='M6 8L0 0h12z'/%3E%3C/svg%3E");
     1246        background-repeat: no-repeat;
     1247        background-position: right 12px center;
     1248        background-size: 10px;
     1249        cursor: pointer;
     1250    }
     1251    .wcusage-tab-select:focus {
     1252        outline: none;
     1253        box-shadow: 0 0 0 2px rgba(0,124,186,0.25);
     1254    }
     1255}
     1256
    11461257/* --- Mobile overflow fixes: ensure tabs and tables can scroll horizontally --- */
    11471258/* Tabs: always allow horizontal scroll if needed */
     
    12391350    border-radius: 3px;
    12401351}
     1352
  • woo-coupon-usage/trunk/css/style.css

    r3462634 r3469742  
    16351635
    16361636.wcu-mla-network-button {
    1637     margin: 2px 0 7px 0 !important;
     1637    font-size: 12px !important;
     1638    margin: 4px 0 7px 0 !important;
    16381639    padding: 2px 5px 2px 5px !important;
    16391640    text-decoration: none !important;
  • woo-coupon-usage/trunk/inc/admin/admin-activity.php

    r3415640 r3469742  
    1313<link rel="stylesheet" href="<?php echo esc_url(WCUSAGE_UNIQUE_PLUGIN_URL) .'fonts/font-awesome/css/all.min.css'; ?>" crossorigin="anonymous">
    1414
    15 <style>@media screen and (min-width: 540px) { .column-user_id { width: 250px; max-width: 100%; } }</style>
    16 <style>@media screen and (min-width: 540px) { .column-event { text-align: left !important; } }</style>
    17 
    1815<!-- Output Page -->
    1916<div class="wrap plugin-settings">
     
    2219
    2320    <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
     21
     22    <br/><br/>
    2423
    2524    <?php
     
    4948
    5049    <div style="margin-top: -30px;">
    51         <input type="hidden" name="page" value="<?php echo esc_html( $_GET['page'] ); ?>" />
    52         <?php $ListTable->display() ?>
     50        <form method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
     51            <input type="hidden" name="page" value="<?php echo esc_attr( sanitize_text_field( wp_unslash( $_GET['page'] ) ) ); ?>" />
     52            <?php $ListTable->display(); ?>
     53        </form>
    5354    </div>
    5455
  • woo-coupon-usage/trunk/inc/admin/admin-dashboard.php

    r3462634 r3469742  
    374374    }
    375375    $support_items = array(
     376        array('label' => 'Support Forum', 'url' => 'https://wordpress.org/support/plugin/woo-coupon-usage/#new-topic-0', 'icon' => 'fa-solid fa-comments', 'external' => true),
    376377        array('label' => 'Documentation', 'url' => 'https://couponaffiliates.com/docs?utm_campaign=plugin&utm_source=dashboard-header&utm_medium=button', 'icon' => 'fa-solid fa-book', 'external' => true),
    377378        array('label' => 'Roadmap', 'url' => 'https://roadmap.couponaffiliates.com/roadmap', 'icon' => 'fa-solid fa-list', 'external' => true),
    378379        array('label' => 'Updates', 'url' => '#', 'icon' => 'fa-solid fa-sync', 'external' => false, 'id' => 'show-changelog'),
    379         array('label' => 'Email Us', 'url' => admin_url('admin.php?page=wcusage-contact'), 'icon' => 'fa-solid fa-circle-question', 'external' => !wcu_fs()->can_use_premium_code()),
    380         array('label' => 'Support Forum', 'url' => 'https://wordpress.org/support/plugin/woo-coupon-usage/#new-topic-0', 'icon' => 'fa-solid fa-comments', 'external' => true),
    381380    );
    382381    ?>
  • woo-coupon-usage/trunk/inc/admin/admin-menu.php

    r3454163 r3469742  
    252252
    253253add_filter( 'submenu_file', 'wcusage_admin_submenu_filter' );
    254 // JavaScript solution to highlight parent menu on view affiliate page
     254// JavaScript solution to highlight parent menu on view affiliate page and MLA pages
    255255function wcusage_admin_menu_highlight_script() {
    256     if ( isset( $_GET['page'] ) && $_GET['page'] === 'wcusage_view_affiliate' ) {
     256    if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array('wcusage_view_affiliate'), true ) ) {
    257257        ?>
    258258    <script type="text/javascript">
  • woo-coupon-usage/trunk/inc/admin/admin-orders-box.php

    r3438708 r3469742  
    238238        delete_post_meta( $order_id, 'wcusage_stats' );
    239239        delete_post_meta( $order_id, 'wcusage_total_commission' );
     240        delete_post_meta( $order_id, 'wcusage_fixed_order_commission' );
     241        delete_post_meta( $order_id, 'wcu_mla_commission' );
    240242        $url = remove_query_arg( 'refresh_stats' );
    241243        wp_safe_redirect( $url );
     
    286288    echo "<a href='" . esc_url( $getinfo['uniqueurl'] ) . "' target='_blank' style='color: #07bbe3;' title='" . esc_html__( 'View the affiliate dashboard for this affiliate coupon.', 'woo-coupon-usage' ) . "'>" . esc_html__( 'View Dashboard', 'woo-coupon-usage' ) . "</a>";
    287289    echo "</p>";
    288     $wcusage_field_mla_enable = wcusage_get_setting_value( 'wcusage_field_mla_enable', '0' );
    289     if ( $wcusage_field_mla_enable && wcu_fs()->can_use_premium_code() && !wcusage_coupon_disable_commission( $coupon_id ) ) {
    290         $get_parents = get_user_meta( $getinfo['theuserid'], 'wcu_ml_affiliate_parents', true );
    291         if ( !empty( $get_parents ) && is_array( $get_parents ) ) {
    292             echo "<p><strong>MLA Commission:</strong>";
    293             foreach ( $get_parents as $key => $parent_id ) {
    294                 $parent_user_info = get_user_by( 'ID', $parent_id );
    295                 $parent_user_name = $parent_user_info->user_login;
    296                 $parent_user_id = $parent_user_info->ID;
    297                 $coupon_info = wcusage_get_coupon_info( $coupon_code );
    298                 $coupon_id = $coupon_info[2];
    299                 $parent_commission = wcusage_mla_get_commission_from_tier(
    300                     $getinfo['thecommissionnum'],
    301                     $key,
    302                     1,
    303                     $order_id,
    304                     $coupon_code
    305                 );
    306                 echo "<br/>(" . esc_html( $key ) . ") <a href='" . esc_url( admin_url( "admin.php?page=wcusage_view_affiliate&user_id=" . $parent_user_id ) ) . "' target='_blank' style='color: #07bbe3;'>" . esc_html( $parent_user_name ) . "</a>: " . wp_kses_post( wcusage_format_price( esc_html( $parent_commission ) ) );
    307             }
    308             echo "</p>";
     290    if ( wcu_fs()->can_use_premium_code() ) {
     291        $wcusage_field_mla_enable = wcusage_get_setting_value( 'wcusage_field_mla_enable', '0' );
     292        if ( $wcusage_field_mla_enable && !wcusage_coupon_disable_commission( $coupon_id ) ) {
     293            $get_parents = get_user_meta( $getinfo['theuserid'], 'wcu_ml_affiliate_parents', true );
     294            if ( !empty( $get_parents ) && is_array( $get_parents ) ) {
     295                // Try to read stored MLA commission from order meta (persisted at order time)
     296                $order_obj = wc_get_order( $order_id );
     297                $stored_mla_raw = ( $order_obj ? $order_obj->get_meta( 'wcu_mla_commission', true ) : '' );
     298                $stored_mla = ( is_string( $stored_mla_raw ) ? json_decode( $stored_mla_raw, true ) : $stored_mla_raw );
     299                $needs_mla_meta_save = false;
     300                echo "<p><strong>MLA Commission:</strong>";
     301                foreach ( $get_parents as $key => $parent_id ) {
     302                    $parent_user_info = get_user_by( 'ID', $parent_id );
     303                    $parent_user_name = ( $parent_user_info ? $parent_user_info->user_login : '#' . $parent_id );
     304                    $parent_user_id = ( $parent_user_info ? $parent_user_info->ID : $parent_id );
     305                    // Use stored commission if available, otherwise recalculate and flag for saving
     306                    if ( is_array( $stored_mla ) && isset( $stored_mla[$key]['commission'] ) ) {
     307                        $parent_commission = (float) $stored_mla[$key]['commission'];
     308                    } else {
     309                        $coupon_info = wcusage_get_coupon_info( $coupon_code );
     310                        $coupon_id = $coupon_info[2];
     311                        $parent_commission = wcusage_mla_get_commission_from_tier(
     312                            $getinfo['thecommissionnum'],
     313                            $key,
     314                            1,
     315                            $order_id,
     316                            $coupon_code,
     317                            0,
     318                            $parent_user_id
     319                        );
     320                        // Collect recalculated data so we can persist it
     321                        $tier_rates = ( function_exists( 'wcusage_mla_get_tier_rates' ) ? wcusage_mla_get_tier_rates( $key, $parent_user_id ) : array() );
     322                        if ( !is_array( $stored_mla ) ) {
     323                            $stored_mla = array();
     324                        }
     325                        $stored_mla[$key] = array(
     326                            'parent_id'  => (int) $parent_user_id,
     327                            'commission' => round( (float) $parent_commission, 2 ),
     328                            'rates'      => $tier_rates,
     329                        );
     330                        $needs_mla_meta_save = true;
     331                    }
     332                    echo "<br/>(" . esc_html( $key ) . ") <a href='" . esc_url( admin_url( "admin.php?page=wcusage_view_affiliate&user_id=" . $parent_user_id ) ) . "' target='_blank' style='color: #07bbe3;'>" . esc_html( $parent_user_name ) . "</a>: " . wp_kses_post( wcusage_format_price( esc_html( $parent_commission ) ) );
     333                }
     334                echo "</p>";
     335                // Persist recalculated MLA data for old orders so it won't recalculate again
     336                if ( $needs_mla_meta_save && $order_obj && !empty( $stored_mla ) ) {
     337                    $order_obj->update_meta_data( 'wcu_mla_commission', json_encode( $stored_mla ) );
     338                    $order_obj->save_meta_data();
     339                }
     340            }
    309341        }
    310342    }
  • woo-coupon-usage/trunk/inc/admin/admin-orders-list.php

    r3438708 r3469742  
    181181        $coupon_id = wcusage_get_coupon_id( $coupon_code );
    182182        // Commission
     183        // Prefer the saved stats meta (which stores the full combined commission including
     184        // fixed-order and fixed-product amounts), falling back to a full recalculation.
     185        $wcusage_stats = wcusage_order_meta( $order_id, 'wcusage_stats', true );
    183186        $wcusage_total_commission = wcusage_order_meta( $order_id, 'wcusage_total_commission' );
    184         if ( !$wcusage_total_commission || $update ) {
     187        if ( !$update && is_array( $wcusage_stats ) && !empty( $wcusage_stats['commission'] ) ) {
     188            // wcusage_stats['commission'] = full all_commission (percent + fixed_order + fixed_product)
     189            $commission = (float) $wcusage_stats['commission'];
     190        } elseif ( !$wcusage_total_commission || $update ) {
    185191            if ( $update ) {
    186192                $order_data = wcusage_calculate_order_data(
  • woo-coupon-usage/trunk/inc/admin/admin-page.php

    r3454163 r3469742  
    668668}
    669669
     670/**
     671 * MLA Users Admin Page
     672 */
     673function wcusage_mla_users_page_html() {
     674    require_once plugin_dir_path(__FILE__) . 'class-mla-users-table.php';
     675    wcusage_mla_users_page();
     676}
     677
     678
     679
  • woo-coupon-usage/trunk/inc/admin/admin-pro-details.php

    r3462634 r3469742  
    2828  });
    2929  </script>
    30 
    31 <div id="pro-details" class="pro-details">
    3230
    3331  <?php if(!$ispro) { ?>
     
    8987  <?php } ?>
    9088
    91 <h1 style="margin-bottom: 0px;">PRO <?php echo esc_html__( 'Modules & Features', 'woo-coupon-usage' ); ?>:</h1>
     89<h1 style="margin-bottom: 0px; width: 100%;">PRO <?php echo esc_html__( 'Modules & Features', 'woo-coupon-usage' ); ?>:</h1>
     90
     91<div style="clear: both;"></div>
    9292
    9393<br/>
    9494
    9595<p><?php echo esc_html__( 'The below section includes a list of most of the modules and features included in the Pro plan. However other smaller features and customisations can be found throughout the settings page.', 'woo-coupon-usage' ); ?></p>
     96
     97<br/>
     98
     99<div class="wcu-pro-modules-search-wrap">
     100  <input type="text" id="wcu-pro-modules-search" placeholder="<?php echo esc_attr__( 'Search modules...', 'woo-coupon-usage' ); ?>" autocomplete="off" />
     101</div>
     102<p id="wcu-pro-modules-no-results" style="display:none;"><?php echo esc_html__( 'No modules found matching your search.', 'woo-coupon-usage' ); ?></p>
     103
     104<div id="pro-details" class="pro-details">
    96105
    97106<div style="flex-basis: 100%; height: 0;"></div>
     
    671680</script>
    672681
     682<!-- Module Search Filter -->
     683<script>
     684jQuery(document).ready(function($) {
     685  var $search = $('#wcu-pro-modules-search');
     686  if (!$search.length) return;
     687  $search.on('input', function() {
     688    var term = $.trim($(this).val()).toLowerCase();
     689    var $boxes = $('.pro-details .wcu-addons-box');
     690    var visible = 0;
     691    $boxes.each(function() {
     692      var title = $(this).data('module-title') || '';
     693      var desc  = $(this).data('module-desc')  || '';
     694      if (!term || title.indexOf(term) !== -1 || desc.indexOf(term) !== -1) {
     695        $(this).show();
     696        visible++;
     697      } else {
     698        $(this).hide();
     699      }
     700    });
     701    if (visible === 0 && term) {
     702      $('#wcu-pro-modules-no-results').show();
     703    } else {
     704      $('#wcu-pro-modules-no-results').hide();
     705    }
     706  });
     707});
     708</script>
     709
    673710<!-- Break the flexbox -->
    674711<div style="flex-basis: 100%; height: 0;"></div>
     
    722759  </script>
    723760<?php } ?>
    724   <div class="wcu-addons-box wcu-addons-box-<?php echo esc_attr($id); ?>">
     761  <div class="wcu-addons-box wcu-addons-box-<?php echo esc_attr($id); ?>" data-module-title="<?php echo esc_attr(strtolower($title)); ?>" data-module-desc="<?php echo esc_attr(strtolower(wp_strip_all_tags($text))); ?>">
    725762
    726763    <span><i class="<?php echo esc_html($icon); ?>"
  • woo-coupon-usage/trunk/inc/admin/admin-view-affiliate.php

    r3454163 r3469742  
    1 <?php
    2 
     1<?php
    32if ( !defined( 'ABSPATH' ) ) {
    43    exit;
     
    152151    }
    153152}
     153// Handle MLA per-user commission rates save
     154$wcusage_field_mla_per_user_group_rates = wcusage_get_setting_value( 'wcusage_field_mla_per_user_group_rates', '0' );
     155if ( $wcusage_field_mla_per_user_group_rates && isset( $_POST['wcusage_mla_user_rates_save'] ) && isset( $_POST['_wpnonce'] ) ) {
     156    if ( wp_verify_nonce( $_POST['_wpnonce'], 'wcusage_save_mla_user_rates_' . $user_id ) ) {
     157        // Save the enable toggle
     158        $custom_enabled = ( isset( $_POST['wcu_mla_custom_rates_enabled'] ) ? '1' : '0' );
     159        update_user_meta( $user_id, 'wcu_mla_custom_rates_enabled', $custom_enabled );
     160        // Only save tier fields when enabled
     161        $mla_tiersnumber = wcusage_get_setting_value( 'wcusage_field_mla_number_tiers', '5' );
     162        for ($i = 1; $i <= $mla_tiersnumber; $i++) {
     163            $tier_key = 'T' . $i;
     164            $tier_fields = array('wcu_mla_tier_percent_' . $tier_key, 'wcu_mla_tier_order_percent_' . $tier_key, 'wcu_mla_tier_fixed_' . $tier_key);
     165            foreach ( $tier_fields as $field ) {
     166                if ( isset( $_POST[$field] ) ) {
     167                    $value = sanitize_text_field( $_POST[$field] );
     168                    if ( $value === '' || $value === null ) {
     169                        delete_user_meta( $user_id, $field );
     170                    } else {
     171                        update_user_meta( $user_id, $field, $value );
     172                    }
     173                }
     174            }
     175        }
     176        echo '<div class="notice notice-success"><p>' . esc_html__( 'MLA commission rates updated successfully.', 'woo-coupon-usage' ) . '</p></div>';
     177    }
     178}
    154179// Handle individual delete actions (same options as Coupon Affiliate Users page)
    155180if ( isset( $_POST['wcusage_delete_action'] ) && isset( $_POST['wcusage_user_id'] ) ) {
     
    213238?>
    214239
    215     <!--- Font Awesome -->
    216     <link rel="stylesheet" href="<?php
     240<!--- Font Awesome -->
     241<link rel="stylesheet" href="<?php
    217242echo esc_url( WCUSAGE_UNIQUE_PLUGIN_URL ) . 'fonts/font-awesome/css/all.min.css';
    218243?>" crossorigin="anonymous">
     
    267292);
    268293wp_localize_script( 'wcusage-admin-view-affiliate', 'WCUAdminAffiliateView', array(
    269     'ajax_url'        => admin_url( 'admin-ajax.php' ),
    270     'user_id'         => $user_id,
    271     'per_page'        => 20,
    272     'coupon_nonce'    => wp_create_nonce( 'wcusage_coupon_nonce' ),
    273     'currency_symbol' => get_woocommerce_currency_symbol(),
    274     'nonce_referrals' => wp_create_nonce( 'wcusage_affiliate_referrals' ),
    275     'nonce_visits'    => wp_create_nonce( 'wcusage_affiliate_visits' ),
    276     'nonce_payouts'   => wp_create_nonce( 'wcusage_affiliate_payouts' ),
    277     'nonce_activity'  => wp_create_nonce( 'wcusage_affiliate_activity' ),
     294    'ajax_url'                   => admin_url( 'admin-ajax.php' ),
     295    'user_id'                    => $user_id,
     296    'per_page'                   => 20,
     297    'coupon_nonce'               => wp_create_nonce( 'wcusage_coupon_nonce' ),
     298    'currency_symbol'            => get_woocommerce_currency_symbol(),
     299    'nonce_referrals'            => wp_create_nonce( 'wcusage_affiliate_referrals' ),
     300    'nonce_visits'               => wp_create_nonce( 'wcusage_affiliate_visits' ),
     301    'nonce_payouts'              => wp_create_nonce( 'wcusage_affiliate_payouts' ),
     302    'nonce_activity'             => wp_create_nonce( 'wcusage_affiliate_activity' ),
     303    'nonce_add_sub_affiliate'    => wp_create_nonce( 'wcusage_add_sub_affiliate_nonce' ),
     304    'nonce_remove_sub_affiliate' => wp_create_nonce( 'wcusage_remove_sub_affiliate_nonce' ),
    278305) );
    279306?>
     
    328355            style="margin-left: 15px; font-size: 12px; padding: 5px 10px;" target="_blank">
    329356                <?php
    330 echo esc_html__( 'View affiliate dashboard as user', 'woo-coupon-usage' );
    331 ?>
    332                 <i class="fas fa-external-link-alt" style="margin-left: 5px; font-size: 12px;"></i>
     357echo esc_html__( 'View affiliate dashboard', 'woo-coupon-usage' );
     358?>
     359                <i class="fas fa-external-link-alt" style="margin-left: 5px; font-size: 12px; height: 12px; margin-top: 5px;"></i>
    333360            </a>
     361            <?php
     362$wcusage_tracking_enable = wcusage_get_setting_value( 'wcusage_field_tracking_enable', '0' );
     363?>
     364            <?php
     365?>
    334366        </h1>
    335 
    336     <a href="<?php
    337 echo esc_url( admin_url( 'admin.php?page=wcusage_affiliates' ) );
    338 ?>" class="page-title-action wcusage-back-button"
    339     style="float: right;">
    340             <i class="fas fa-arrow-left" style="margin-right: 5px;"></i>
    341             <?php
    342 echo esc_html__( 'Back to Affiliates', 'woo-coupon-usage' );
    343 ?>
    344         </a>
    345367
    346368        <?php
     
    348370$delete_nonce = wp_create_nonce( 'wcusage_delete_user_' . $user_id );
    349371?>
    350         <div class="wcusage-delete-dropdown" style="">
    351             <button type="button" class="wcusage-delete-btn" data-user-id="<?php
     372        <div class="wcusage-view-affiliate-header-actions" style="float: right; display: flex; flex-direction: column; align-items: flex-end; gap: 6px;">
     373            <a href="<?php
     374echo esc_url( admin_url( 'admin.php?page=wcusage_affiliates' ) );
     375?>" class="page-title-action wcusage-back-button">
     376                <i class="fas fa-arrow-left" style="margin-right: 5px;"></i>
     377                <?php
     378echo esc_html__( 'Back to Affiliates', 'woo-coupon-usage' );
     379?>
     380            </a>
     381            <div class="wcusage-delete-dropdown" style="margin-top: 5px;">
     382                <button type="button" class="wcusage-delete-btn" data-user-id="<?php
    352383echo esc_attr( $user_id );
    353384?>" title="<?php
    354385echo esc_attr__( 'Delete Options', 'woo-coupon-usage' );
    355386?>">
    356                 <span class="dashicons dashicons-trash"></span>
    357             </button>
    358             <div class="wcusage-delete-menu" style="display: none;">
    359                 <a href="#" class="wcusage-delete-option" data-action="delete_user" data-user-id="<?php
     387                    <span class="dashicons dashicons-trash"></span>
     388                </button>
     389                <div class="wcusage-delete-menu" style="display: none;">
     390                    <a href="#" class="wcusage-delete-option" data-action="delete_user" data-user-id="<?php
    360391echo esc_attr( $user_id );
    361392?>" data-nonce="<?php
     
    364395echo esc_html__( 'Delete User', 'woo-coupon-usage' );
    365396?></a>
    366                 <a href="#" class="wcusage-delete-option" data-action="delete_user_coupons" data-user-id="<?php
     397                    <a href="#" class="wcusage-delete-option" data-action="delete_user_coupons" data-user-id="<?php
    367398echo esc_attr( $user_id );
    368399?>" data-nonce="<?php
     
    371402echo esc_html__( 'Delete User & Coupons', 'woo-coupon-usage' );
    372403?></a>
    373                 <a href="#" class="wcusage-delete-option" data-action="unassign_coupons" data-user-id="<?php
     404                    <a href="#" class="wcusage-delete-option" data-action="unassign_coupons" data-user-id="<?php
    374405echo esc_attr( $user_id );
    375406?>" data-nonce="<?php
     
    378409echo esc_html__( 'Unassign Coupons', 'woo-coupon-usage' );
    379410?></a>
    380                 <a href="#" class="wcusage-delete-option" data-action="delete_coupons" data-user-id="<?php
     411                    <a href="#" class="wcusage-delete-option" data-action="delete_coupons" data-user-id="<?php
    381412echo esc_attr( $user_id );
    382413?>" data-nonce="<?php
     
    385416echo esc_html__( 'Delete Coupons', 'woo-coupon-usage' );
    386417?></a>
     418                </div>
    387419            </div>
    388420        </div>
     
    407439                        <i class="fas fa-shopping-cart" style="margin-right: 8px;"></i>
    408440                        <?php
    409 echo esc_html__( 'Referrals', 'woo-coupon-usage' );
     441echo esc_html__( 'Referred Orders', 'woo-coupon-usage' );
    410442?>
    411443                    </a>
     
    477509                            <i class="fas fa-shopping-cart" style="color: #007cba; margin-right: 10px;"></i>
    478510                            <?php
    479 echo esc_html__( 'Latest Referrals', 'woo-coupon-usage' );
     511echo esc_html__( 'Referred Orders', 'woo-coupon-usage' );
    480512?>
    481513                        </h3>
     
    551583
    552584                    <!-- Payouts Tab -->
     585                    <?php
     586if ( $wcusage_tracking_enable ) {
     587    ?>
    553588                    <div id="tab-payouts" class="tab-content <?php
    554 echo ( $current_tab === 'payouts' ? 'active' : '' );
    555 ?>">
     589    echo ( $current_tab === 'payouts' ? 'active' : '' );
     590    ?>">
    556591                        <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
    557592                            <i class="fas fa-dollar-sign" style="color: #007cba; margin-right: 10px;"></i>
    558593                            <?php
    559 echo esc_html__( 'Payout History', 'woo-coupon-usage' );
    560 ?>
     594    echo esc_html__( 'Payout History', 'woo-coupon-usage' );
     595    ?>
    561596                        </h3>
    562597                        <div class="wcusage-filters" id="wcusage-payouts-filters" style="margin: 0 0 15px; display:flex; gap:8px; align-items: center;">
    563598                            <label>
    564599                                <?php
    565 echo esc_html__( 'From', 'woo-coupon-usage' );
    566 ?>
     600    echo esc_html__( 'From', 'woo-coupon-usage' );
     601    ?>
    567602                                <input type="date" id="payouts-start-date" />
    568603                            </label>
    569604                            <label>
    570605                                <?php
    571 echo esc_html__( 'To', 'woo-coupon-usage' );
    572 ?>
     606    echo esc_html__( 'To', 'woo-coupon-usage' );
     607    ?>
    573608                                <input type="date" id="payouts-end-date" />
    574609                            </label>
    575610                            <button class="button" id="payouts-apply-filters"><?php
    576 echo esc_html__( 'Filter', 'woo-coupon-usage' );
    577 ?></button>
     611    echo esc_html__( 'Filter', 'woo-coupon-usage' );
     612    ?></button>
    578613                        </div>
    579614                        <div id="wcusage-payouts-table-container">
    580615                            <?php
    581 wcusage_display_affiliate_payouts(
    582     $user_id,
    583     1,
    584     20,
    585     '',
    586     ''
    587 );
    588 ?>
     616    wcusage_display_affiliate_payouts(
     617        $user_id,
     618        1,
     619        20,
     620        '',
     621        ''
     622    );
     623    ?>
    589624                        </div>
    590625                    </div>
     626                    <?php
     627}
     628?>
    591629
    592630                    <!-- Activity Tab -->
     
    633671
    634672                    <?php
    635 if ( $wcusage_field_mla_enable && $wcusage_premium_active && function_exists( 'wcusage_get_ml_sub_affiliates' ) && function_exists( 'wcusage_get_network_chart_item' ) ) {
     673if ( wcu_fs()->can_use_premium_code__premium_only() && $wcusage_field_mla_enable && function_exists( 'wcusage_get_ml_sub_affiliates' ) && function_exists( 'wcusage_get_network_chart_item' ) ) {
    636674    ?>
    637675                    <!-- MLA Tab -->
     
    639677    echo ( $current_tab === 'mla' ? 'active' : '' );
    640678    ?>">
    641                         <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
    642                             <i class="fa-solid fa-network-wired" style="color: #007cba; margin-right: 10px;"></i>
     679
     680                        <?php
     681    // Get MLA data
     682    $mla_sub_affiliates = wcusage_get_ml_sub_affiliates( $user_id );
     683    $mla_total_commission = 0;
     684    if ( function_exists( 'wcusage_mla_total_earnings' ) ) {
     685        $mla_total_commission = wcusage_mla_total_earnings( $user_id );
     686    }
     687    $mla_unpaid = (float) get_user_meta( $user_id, 'wcu_ml_unpaid_commission', true );
     688    // Get parent affiliates
     689    $mla_get_parents = get_user_meta( $user_id, 'wcu_ml_affiliate_parents', true );
     690    if ( !is_array( $mla_get_parents ) ) {
     691        $mla_get_parents = array();
     692    }
     693    // Determine active MLA sub-tab
     694    $mla_subtab = ( isset( $_GET['mla_subtab'] ) ? sanitize_text_field( $_GET['mla_subtab'] ) : 'mla-overview' );
     695    ?>
     696
     697                        <!-- MLA Sub-tabs -->
     698                        <h3 class="nav-tab-wrapper wcusage-mla-subtabs">
     699                            <a href="#mla-subtab-overview" class="nav-tab <?php
     700    echo ( $mla_subtab === 'mla-overview' ? 'nav-tab-active' : '' );
     701    ?>" data-mla-subtab="mla-overview">
     702                                <i class="fas fa-chart-line" style="margin-right: 6px;"></i>
     703                                <?php
     704    echo esc_html__( 'Overview', 'woo-coupon-usage' );
     705    ?>
     706                            </a>
     707                            <a href="#mla-subtab-network" class="nav-tab <?php
     708    echo ( $mla_subtab === 'mla-network' ? 'nav-tab-active' : '' );
     709    ?>" data-mla-subtab="mla-network">
     710                                <i class="fa-solid fa-network-wired" style="margin-right: 6px;"></i>
     711                                <?php
     712    echo esc_html__( 'Network Tree', 'woo-coupon-usage' );
     713    ?>
     714                            </a>
     715                            <a href="#mla-subtab-tiers" class="nav-tab <?php
     716    echo ( $mla_subtab === 'mla-tiers' ? 'nav-tab-active' : '' );
     717    ?>" data-mla-subtab="mla-tiers">
     718                                <i class="fas fa-layer-group" style="margin-right: 6px;"></i>
     719                                <?php
     720    echo esc_html__( 'Tiers', 'woo-coupon-usage' );
     721    ?>
     722                            </a>
    643723                            <?php
    644     echo esc_html__( 'MLA Network', 'woo-coupon-usage' );
     724    $wcusage_field_mla_per_user_group_rates_tab = wcusage_get_setting_value( 'wcusage_field_mla_per_user_group_rates', '0' );
     725    if ( $wcusage_field_mla_per_user_group_rates_tab ) {
     726        ?>
     727                            <a href="#mla-subtab-rates" class="nav-tab <?php
     728        echo ( $mla_subtab === 'mla-rates' ? 'nav-tab-active' : '' );
     729        ?>" data-mla-subtab="mla-rates">
     730                                <i class="fas fa-sliders-h" style="margin-right: 6px;"></i>
     731                                <?php
     732        echo esc_html__( 'Commission Rates', 'woo-coupon-usage' );
     733        ?>
     734                            </a>
     735                            <?php
     736    }
    645737    ?>
    646738                        </h3>
    647                         <?php
    648     // Build network for this affiliate similar to MLA dashboard
    649     $sub_affiliates = wcusage_get_ml_sub_affiliates( $user_id );
    650     if ( empty( $sub_affiliates ) ) {
    651         echo '<p>' . esc_html__( "This affiliate doesn't currently have any sub-affiliates.", 'woo-coupon-usage' ) . '</p>';
     739
     740                        <!-- MLA Sub-tab Content -->
     741                        <div class="wcusage-mla-subtab-content">
     742
     743                            <!-- MLA Overview Sub-tab -->
     744                            <div id="mla-subtab-overview" class="mla-subtab-panel <?php
     745    echo ( $mla_subtab === 'mla-overview' ? 'active' : '' );
     746    ?>">
     747                                <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
     748                                    <i class="fas fa-chart-line" style="color: #007cba; margin-right: 10px;"></i>
     749                                    <?php
     750    echo esc_html__( 'MLA Statistics Overview', 'woo-coupon-usage' );
     751    ?>
     752                                </h3>
     753
     754                                <div class="wcusage-stats-grid">
     755                                    <div class="wcusage-stat-box">
     756                                        <div class="stat-value"><?php
     757    echo esc_html( count( $mla_sub_affiliates ) );
     758    ?></div>
     759                                        <div class="stat-label"><?php
     760    echo esc_html__( 'Sub-Affiliates', 'woo-coupon-usage' );
     761    ?></div>
     762                                    </div>
     763                                    <div class="wcusage-stat-box">
     764                                        <div class="stat-value"><?php
     765    echo wcusage_format_price( $mla_total_commission );
     766    ?></div>
     767                                        <div class="stat-label"><?php
     768    echo esc_html__( 'Total MLA Commission', 'woo-coupon-usage' );
     769    ?></div>
     770                                    </div>
     771                                    <div class="wcusage-stat-box">
     772                                        <div class="stat-value"><?php
     773    echo wcusage_format_price( $mla_unpaid );
     774    ?></div>
     775                                        <div class="stat-label"><?php
     776    echo esc_html__( 'Unpaid MLA Commission', 'woo-coupon-usage' );
     777    ?></div>
     778                                    </div>
     779                                </div>
     780
     781                                <!-- Sub-Affiliates List -->
     782                                <div class="wcusage-mla-section-header">
     783                                    <h3><?php
     784    echo esc_html__( 'Sub-Affiliates', 'woo-coupon-usage' );
     785    ?></h3>
     786                                    <button type="button" id="wcusage-add-sub-affiliate-toggle" class="button">
     787                                        <span class="dashicons dashicons-plus-alt2" style="vertical-align: middle; margin-right: 4px;"></span>
     788                                        <?php
     789    echo esc_html__( 'Add New Sub-Affiliate', 'woo-coupon-usage' );
     790    ?>
     791                                    </button>
     792                                </div>
     793
     794                                <!-- Add Sub-Affiliate Form (hidden by default) -->
     795                                <div id="wcusage-add-sub-affiliate-form" class="wcusage-add-sub-affiliate-form" style="display:none;">
     796                                    <p class="wcusage-add-sub-affiliate-desc">
     797                                        <?php
     798    echo esc_html__( 'Search for an existing user who does not already have a parent affiliate. Select them and click Add.', 'woo-coupon-usage' );
     799    ?>
     800                                    </p>
     801                                    <div class="wcusage-add-sub-affiliate-row">
     802                                        <input
     803                                            type="text"
     804                                            id="wcusage-sub-affiliate-search"
     805                                            class="regular-text"
     806                                            placeholder="<?php
     807    echo esc_attr__( 'Search by username or email…', 'woo-coupon-usage' );
     808    ?>"
     809                                            autocomplete="off"
     810                                        />
     811                                        <input type="hidden" id="wcusage-sub-affiliate-id" value="" />
     812                                        <button type="button" id="wcusage-add-sub-affiliate-submit" class="button button-primary" disabled>
     813                                            <?php
     814    echo esc_html__( 'Add Sub-Affiliate', 'woo-coupon-usage' );
     815    ?>
     816                                        </button>
     817                                        <span class="spinner wcusage-add-sub-spinner"></span>
     818                                    </div>
     819                                    <p id="wcusage-add-sub-affiliate-msg" class="wcusage-add-sub-msg" style="display:none;"></p>
     820                                    <input type="hidden" id="wcusage-parent-affiliate-id" value="<?php
     821    echo esc_attr( $user_id );
     822    ?>" />
     823                                </div>
     824
     825                                <?php
     826    // Build a lookup: user_id => WP_User object + pre-fetched meta
     827    $mla_sub_map = array();
     828    // id => ['user' => obj, 'parents' => array, 'tier_num' => int]
     829    foreach ( $mla_sub_affiliates as $sub_user ) {
     830        $sub_parents = get_user_meta( $sub_user->ID, 'wcu_ml_affiliate_parents', true );
     831        if ( !is_array( $sub_parents ) ) {
     832            $sub_parents = array();
     833        }
     834        // tier_num relative to the viewed affiliate
     835        $t_key = array_search( (string) $user_id, array_map( 'strval', $sub_parents ) );
     836        $t_num = ( $t_key !== false ? (int) str_replace( 'T', '', $t_key ) : 0 );
     837        $mla_sub_map[$sub_user->ID] = array(
     838            'user'          => $sub_user,
     839            'parents'       => $sub_parents,
     840            'tier_num'      => $t_num,
     841            'direct_parent' => ( isset( $sub_parents['T1'] ) ? (int) $sub_parents['T1'] : 0 ),
     842        );
     843    }
     844    // Build children map: parent_id => [child_id, ...]
     845    $mla_children_map = array();
     846    foreach ( $mla_sub_map as $sid => $sdata ) {
     847        $pid = $sdata['direct_parent'];
     848        $mla_children_map[$pid][] = $sid;
     849    }
     850    // Recursive row renderer
     851    function wcusage_render_mla_sub_rows(
     852        $parent_id,
     853        $mla_sub_map,
     854        $mla_children_map,
     855        $root_user_id,
     856        $depth = 0
     857    ) {
     858        if ( empty( $mla_children_map[$parent_id] ) ) {
     859            return;
     860        }
     861        foreach ( $mla_children_map[$parent_id] as $sid ) {
     862            $sdata = $mla_sub_map[$sid];
     863            $sub_user = $sdata['user'];
     864            $sub_user_info = get_userdata( $sid );
     865            $sub_parents = $sdata['parents'];
     866            $t_num = $sdata['tier_num'];
     867            // tier key relative to root_user_id
     868            $sub_tier_key = array_search( (string) $root_user_id, array_map( 'strval', $sub_parents ) );
     869            // Coupons & commission
     870            $sub_coupons = wcusage_get_users_coupons_ids( $sid );
     871            $sub_coupon_names = array();
     872            $sub_commission = 0;
     873            foreach ( $sub_coupons as $sub_coupon_id ) {
     874                $sub_coupon_names[] = get_the_title( $sub_coupon_id );
     875                if ( function_exists( 'wcusage_mla_get_total_commission_earned_tier' ) && $sub_tier_key !== false ) {
     876                    $sub_commission += wcusage_mla_get_total_commission_earned_tier( $sub_coupon_id, $sub_tier_key );
     877                }
     878            }
     879            $tier_colors = array(
     880                1 => '#2271b1',
     881                2 => '#6f42c1',
     882                3 => '#0f7a6b',
     883                4 => '#d63638',
     884                5 => '#e87c0c',
     885            );
     886            $badge_color = ( isset( $tier_colors[$t_num] ) ? $tier_colors[$t_num] : '#50575e' );
     887            $indent_px = $depth * 28;
     888            ?>
     889                                        <tr class="wcusage-mla-tree-row">
     890                                            <td>
     891                                                <div class="wcusage-mla-user-cell" style="padding-left:<?php
     892            echo esc_attr( $indent_px );
     893            ?>px;">
     894                                                    <?php
     895            if ( $depth > 0 ) {
     896                ?>
     897                                                        <span class="wcusage-mla-indent-connector"></span>
     898                                                    <?php
     899            }
     900            ?>
     901                                                    <?php
     902            echo get_avatar(
     903                $sid,
     904                28,
     905                'identicon',
     906                '',
     907                array(
     908                    'style' => 'border-radius:50%;vertical-align:middle;margin-right:10px;flex-shrink:0;',
     909                )
     910            );
     911            ?>
     912                                                    <span class="wcusage-mla-user-info">
     913                                                        <strong><?php
     914            echo esc_html( $sub_user_info->user_login );
     915            ?></strong>
     916                                                        <small><?php
     917            echo esc_html( $sub_user_info->user_email );
     918            ?></small>
     919                                                    </span>
     920                                                </div>
     921                                            </td>
     922                                            <td style="text-align:center;">
     923                                                <span class="wcusage-mla-tier-pill" style="background:<?php
     924            echo esc_attr( $badge_color );
     925            ?>;"><?php
     926            echo esc_html( sprintf( __( 'T%s', 'woo-coupon-usage' ), $t_num ) );
     927            ?></span>
     928                                            </td>
     929                                            <td><?php
     930            echo esc_html( implode( ', ', $sub_coupon_names ) );
     931            ?></td>
     932                                            <td><?php
     933            echo wcusage_format_price( $sub_commission );
     934            ?></td>
     935                                            <td>
     936                                                <a href="<?php
     937            echo esc_url( admin_url( 'admin.php?page=wcusage_view_affiliate&user_id=' . $sid . '&tab=mla' ) );
     938            ?>" class="button button-small"><?php
     939            echo esc_html__( 'View User', 'woo-coupon-usage' );
     940            ?></a>
     941                                                <?php
     942            if ( $sub_tier_key === 'T1' ) {
     943                ?>
     944                                                <button type="button"
     945                                                    class="button button-small wcusage-remove-sub-affiliate"
     946                                                    data-sub-id="<?php
     947                echo esc_attr( $sid );
     948                ?>"
     949                                                    data-sub-name="<?php
     950                echo esc_attr( $sub_user_info->user_login );
     951                ?>"
     952                                                    data-parent-id="<?php
     953                echo esc_attr( $root_user_id );
     954                ?>"
     955                                                ><?php
     956                echo esc_html__( 'Remove', 'woo-coupon-usage' );
     957                ?></button>
     958                                                <?php
     959            }
     960            ?>
     961                                            </td>
     962                                        </tr>
     963                                        <?php
     964            // Recurse into this sub's children
     965            wcusage_render_mla_sub_rows(
     966                $sid,
     967                $mla_sub_map,
     968                $mla_children_map,
     969                $root_user_id,
     970                $depth + 1
     971            );
     972        }
     973    }
     974
     975    ?>
     976                                <?php
     977    if ( empty( $mla_sub_affiliates ) ) {
     978        ?>
     979                                    <p><?php
     980        echo esc_html__( "This affiliate doesn't currently have any sub-affiliates.", 'woo-coupon-usage' );
     981        ?></p>
     982                                <?php
    652983    } else {
     984        ?>
     985                                    <table class="wp-list-table widefat fixed wcusage-mla-tiered-table">
     986                                        <thead>
     987                                            <tr>
     988                                                <th><?php
     989        echo esc_html__( 'User', 'woo-coupon-usage' );
     990        ?></th>
     991                                                <th style="width:60px;text-align:center;"><?php
     992        echo esc_html__( 'Tier', 'woo-coupon-usage' );
     993        ?></th>
     994                                                <th style="width:120px;"><?php
     995        echo esc_html__( 'Coupons', 'woo-coupon-usage' );
     996        ?></th>
     997                                                <th style="width:160px;"><?php
     998        echo esc_html__( 'Earned', 'woo-coupon-usage' );
     999        ?></th>
     1000                                                <th style="width:220px;"><?php
     1001        echo esc_html__( 'Actions', 'woo-coupon-usage' );
     1002        ?></th>
     1003                                            </tr>
     1004                                        </thead>
     1005                                        <tbody>
     1006                                            <?php
     1007        wcusage_render_mla_sub_rows(
     1008            $user_id,
     1009            $mla_sub_map,
     1010            $mla_children_map,
     1011            $user_id,
     1012            0
     1013        );
     1014        ?>
     1015                                        </tbody>
     1016                                    </table>
     1017                                <?php
     1018    }
     1019    ?>
     1020                            </div>
     1021
     1022                            <!-- MLA Network Tree Sub-tab -->
     1023                            <div id="mla-subtab-network" class="mla-subtab-panel <?php
     1024    echo ( $mla_subtab === 'mla-network' ? 'active' : '' );
     1025    ?>">
     1026                                <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
     1027                                    <i class="fa-solid fa-network-wired" style="color: #007cba; margin-right: 10px;"></i>
     1028                                    <?php
     1029    echo esc_html__( 'MLA Network Tree', 'woo-coupon-usage' );
     1030    ?>
     1031                                </h3>
     1032                                <?php
     1033    if ( empty( $mla_sub_affiliates ) ) {
     1034        echo '<p>' . esc_html__( "This affiliate doesn't currently have any sub-affiliates in their MLA network.", 'woo-coupon-usage' ) . '</p>';
     1035    } elseif ( function_exists( 'wcusage_get_network_chart_item' ) ) {
    6531036        $network_array = '';
    6541037        // Root node (self)
    6551038        $network_array .= wcusage_get_network_chart_item( $user_id, $user_id, $user_id );
    6561039        $coupon_ids = array();
    657         foreach ( $sub_affiliates as $user ) {
    658             $this_user_id = $user->ID;
    659             $get_parents = get_user_meta( $this_user_id, 'wcu_ml_affiliate_parents', true );
    660             if ( !$get_parents ) {
    661                 $get_parents = array();
     1040        foreach ( $mla_sub_affiliates as $mla_user ) {
     1041            $this_user_id = $mla_user->ID;
     1042            $mla_parents = get_user_meta( $this_user_id, 'wcu_ml_affiliate_parents', true );
     1043            if ( !$mla_parents ) {
     1044                $mla_parents = array();
    6621045            }
    6631046            $this_users_coupons = wcusage_get_users_coupons_ids( $this_user_id );
     
    6651048                $coupon_ids[] = $this_users_coupon_id;
    6661049            }
    667             $super_affiliate = ( empty( $get_parents ) ? 1 : 0 );
    668             if ( !empty( $this_users_coupons ) && is_array( $get_parents ) ) {
    669                 $get_parents = array_reverse( $get_parents );
    670                 $x = end( $get_parents );
     1050            $super_affiliate = ( empty( $mla_parents ) ? 1 : 0 );
     1051            if ( !empty( $this_users_coupons ) && is_array( $mla_parents ) ) {
     1052                $mla_parents = array_reverse( $mla_parents );
     1053                $x = end( $mla_parents );
    6711054                // Link to top-most parent
    6721055                if ( !$super_affiliate ) {
     
    6771060        $network_array = rtrim( $network_array, ',' );
    6781061        $wcusage_color_tab = wcusage_get_setting_value( 'wcusage_field_color_tab', '#333' );
     1062        // Merge network data into existing WCUAdminAffiliateView object without overwriting other keys
     1063        wp_add_inline_script( 'wcusage-admin-view-affiliate', 'if(window.WCUAdminAffiliateView){WCUAdminAffiliateView.mla_network_array=' . wp_json_encode( $network_array ) . ';}', 'after' );
    6791064        $mla_network_text = wcusage_get_setting_value( 'wcusage_field_mla_network_text', '' );
    6801065        if ( $mla_network_text ) {
     
    6821067        }
    6831068        ?>
    684                             <style>
    685                                 #mla_chart_div .google-visualization-orgchart-linebottom { border-bottom: 2px solid <?php
    686         echo esc_attr( $wcusage_color_tab );
    687         ?> !important; }
    688                                 #mla_chart_div .google-visualization-orgchart-lineleft { border-left: 2px solid <?php
    689         echo esc_attr( $wcusage_color_tab );
    690         ?> !important; }
    691                                 #mla_chart_div .google-visualization-orgchart-lineright { border-right: 2px solid <?php
    692         echo esc_attr( $wcusage_color_tab );
    693         ?> !important; }
    694                                 #mla_chart_div .google-visualization-orgchart-linetop { border-top: 2px solid <?php
    695         echo esc_attr( $wcusage_color_tab );
    696         ?> !important; }
    697                                 /* Remove blue faded background on org chart nodes */
    698                                 #mla_chart_div .google-visualization-orgchart-node,
    699                                 #mla_chart_div .google-visualization-orgchart-node > div {
    700                                     background: transparent !important;
    701                                     box-shadow: none !important;
    702                                     -webkit-box-shadow: none !important;
    703                                 }
    704                                 #mla_chart_div .google-visualization-orgchart-node { border: 1px solid #dddddd !important; }
    705                                 #mla_chart_div { overflow: auto; white-space: nowrap; padding-bottom: 8px; }
    706                             </style>
    707                             <div id="mla_chart_div"></div>
    708                             <script type="text/javascript">
    709                                 (function(){
    710                                     var drawn = false;
    711                                     window.WCU_MLA_draw = function(){
    712                                         if (drawn) return; // draw only once per load
    713                                         function _draw(){
    714                                             try{
    715                                                 var data = new google.visualization.DataTable();
    716                                                 data.addColumn('string', 'Name');
    717                                                 data.addColumn('string', 'Manager');
    718                                                 data.addColumn('string', 'ToolTip');
    719                                                 data.addRows([ <?php
    720         echo $network_array;
    721         ?> ]);
    722                                                 var chart = new google.visualization.OrgChart(document.getElementById('mla_chart_div'));
    723                                                 chart.draw(data, {allowHtml:true});
    724                                                 drawn = true;
    725                                             }catch(e){ /* ignore until ready */ }
    726                                         }
    727                                         if (window.google && window.google.charts) {
    728                                             if (google.visualization && google.visualization.OrgChart) {
    729                                                 _draw();
    730                                             } else {
    731                                                 google.charts.load('current', {packages:["orgchart"]});
    732                                                 google.charts.setOnLoadCallback(_draw);
    733                                             }
    734                                         }
    735                                     };
    736                                 })();
    737 
    738                                 // Enable click-drag horizontal scroll on the chart area
    739                                 jQuery(function(){
    740                                     var slider = document.querySelector('#mla_chart_div');
    741                                     if (!slider) return;
    742                                     var mouseDown = false, startX = 0, scrollLeft = 0;
    743                                     function startDragging(e){ mouseDown = true; startX = e.pageX - slider.offsetLeft; scrollLeft = slider.scrollLeft; }
    744                                     function stopDragging(){ mouseDown = false; }
    745                                     slider.addEventListener('mousemove', function(e){ if(!mouseDown) return; e.preventDefault(); var x = e.pageX - slider.offsetLeft; var scroll = x - startX; slider.scrollLeft = scrollLeft - scroll; });
    746                                     slider.addEventListener('mousedown', startDragging, false);
    747                                     slider.addEventListener('mouseup', stopDragging, false);
    748                                     slider.addEventListener('mouseleave', stopDragging, false);
    749                                 });
    750                             </script>
     1069                                    <div id="mla_chart_div"></div>
     1070                                    <?php
     1071    } else {
     1072        echo '<p>' . esc_html__( 'MLA network chart functions are not available.', 'woo-coupon-usage' ) . '</p>';
     1073    }
     1074    ?>
     1075                            </div>
     1076
     1077                            <!-- MLA Tiers Sub-tab -->
     1078                            <div id="mla-subtab-tiers" class="mla-subtab-panel <?php
     1079    echo ( $mla_subtab === 'mla-tiers' ? 'active' : '' );
     1080    ?>">
     1081                                <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
     1082                                    <i class="fas fa-layer-group" style="color: #007cba; margin-right: 10px;"></i>
     1083                                    <?php
     1084    echo esc_html__( 'Commission Per Tier', 'woo-coupon-usage' );
     1085    ?>
     1086                                </h3>
     1087
     1088                                <?php
     1089    $tiersnumber = wcusage_get_setting_value( 'wcusage_field_mla_number_tiers', '5' );
     1090    ?>
     1091                                <table class="wp-list-table widefat fixed striped">
     1092                                    <thead>
     1093                                        <tr>
     1094                                            <th><?php
     1095    echo esc_html__( 'Tier', 'woo-coupon-usage' );
     1096    ?></th>
     1097                                            <th><?php
     1098    echo esc_html__( 'Sub-Affiliates', 'woo-coupon-usage' );
     1099    ?></th>
     1100                                            <th><?php
     1101    echo esc_html__( 'Earned', 'woo-coupon-usage' );
     1102    ?></th>
     1103                                        </tr>
     1104                                    </thead>
     1105                                    <tbody>
     1106                                        <?php
     1107    for ($i = 1; $i <= $tiersnumber; $i++) {
     1108        $tier_key = 'T' . $i;
     1109        // Count sub-affiliates in this tier
     1110        $tier_count = 0;
     1111        $tier_commission = 0;
     1112        foreach ( $mla_sub_affiliates as $sub ) {
     1113            $sub_parents = get_user_meta( $sub->ID, 'wcu_ml_affiliate_parents', true );
     1114            if ( is_array( $sub_parents ) ) {
     1115                $sub_tier = array_search( $user_id, $sub_parents );
     1116                if ( $sub_tier === $tier_key ) {
     1117                    $tier_count++;
     1118                    // Calculate commission from this sub-affiliate's coupons for this tier
     1119                    $sub_coupons = wcusage_get_users_coupons_ids( $sub->ID );
     1120                    foreach ( $sub_coupons as $sub_coupon_id ) {
     1121                        if ( function_exists( 'wcusage_mla_get_total_commission_earned_tier' ) ) {
     1122                            $tier_commission += wcusage_mla_get_total_commission_earned_tier( $sub_coupon_id, $tier_key );
     1123                        }
     1124                    }
     1125                }
     1126            }
     1127        }
     1128        ?>
     1129                                            <tr>
     1130                                                <td><strong><?php
     1131        echo esc_html( sprintf( __( 'Tier %d', 'woo-coupon-usage' ), $i ) );
     1132        ?></strong></td>
     1133                                                <td><?php
     1134        echo esc_html( $tier_count );
     1135        ?></td>
     1136                                                <td><?php
     1137        echo wcusage_format_price( $tier_commission );
     1138        ?></td>
     1139                                            </tr>
     1140                                        <?php
     1141    }
     1142    ?>
     1143                                    </tbody>
     1144                                </table>
     1145                            </div>
     1146
     1147                            <!-- MLA Commission Rates Sub-tab -->
    7511148                            <?php
    752     }
    753     ?>
     1149    if ( wcusage_get_setting_value( 'wcusage_field_mla_per_user_group_rates', '0' ) ) {
     1150        ?>
     1151                            <div id="mla-subtab-rates" class="mla-subtab-panel <?php
     1152        echo ( $mla_subtab === 'mla-rates' ? 'active' : '' );
     1153        ?>">
     1154                                <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;">
     1155                                    <i class="fas fa-sliders-h" style="color: #007cba; margin-right: 10px;"></i>
     1156                                    <?php
     1157        echo esc_html__( 'Per-User MLA Commission Rates', 'woo-coupon-usage' );
     1158        ?>
     1159                                </h3>
     1160
     1161                                <p style="background: #f0f6fc; border-left: 4px solid #72aee6; padding: 10px 14px; margin: 0 0 20px 0;">
     1162                                    <strong><?php
     1163        echo esc_html__( 'Rate Override Priority:', 'woo-coupon-usage' );
     1164        ?></strong>
     1165                                    <?php
     1166        echo esc_html__( 'Per User > Per Group > Global. Leave fields empty to use group or global rates.', 'woo-coupon-usage' );
     1167        ?>
     1168                                </p>
     1169
     1170                                <?php
     1171        // Check if user has group rates
     1172        $user_data = get_userdata( $user_id );
     1173        $user_group_name = '';
     1174        if ( $user_data && !empty( $user_data->roles ) ) {
     1175            foreach ( $user_data->roles as $role ) {
     1176                if ( $role === 'coupon_affiliate' || strpos( $role, 'coupon_affiliate_' ) === 0 ) {
     1177                    global $wp_roles;
     1178                    $user_group_name = ( isset( $wp_roles->roles[$role]['name'] ) ? $wp_roles->roles[$role]['name'] : $role );
     1179                    break;
     1180                }
     1181            }
     1182        }
     1183        if ( $user_group_name ) {
     1184            echo '<p style="margin-bottom: 15px;"><span class="dashicons dashicons-groups" style="color: #646970;"></span> ';
     1185            echo sprintf( esc_html__( 'This user belongs to the group: %s', 'woo-coupon-usage' ), '<strong>' . esc_html( $user_group_name ) . '</strong>' );
     1186            echo '</p>';
     1187        }
     1188        $mla_tiersnumber = wcusage_get_setting_value( 'wcusage_field_mla_number_tiers', '5' );
     1189        $options_check = get_option( 'wcusage_options' );
     1190        ?>
     1191
     1192                                <form method="post" action="">
     1193                                    <?php
     1194        wp_nonce_field( 'wcusage_save_mla_user_rates_' . $user_id );
     1195        ?>
     1196                                    <input type="hidden" name="wcusage_mla_user_rates_save" value="1" />
     1197
     1198                                    <?php
     1199        $user_custom_rates_enabled = get_user_meta( $user_id, 'wcu_mla_custom_rates_enabled', true );
     1200        ?>
     1201                                    <label style="display: flex; align-items: center; gap: 8px; margin-bottom: 18px; font-weight: 600; font-size: 14px; cursor: pointer;">
     1202                                        <input type="checkbox" name="wcu_mla_custom_rates_enabled" id="wcu_mla_custom_rates_enabled_user" value="1" <?php
     1203        checked( $user_custom_rates_enabled, '1' );
     1204        ?> style="width: 16px; height: 16px;" />
     1205                                        <?php
     1206        echo esc_html__( 'Enable Custom MLA Commission Rates', 'woo-coupon-usage' );
     1207        ?>
     1208                                    </label>
     1209                                    <div id="wcu-mla-user-rates-table">
     1210                                    <table class="wp-list-table widefat fixed striped" style="max-width: 800px;">
     1211                                        <thead>
     1212                                            <tr>
     1213                                                <th style="width: 80px;"><?php
     1214        echo esc_html__( 'Tier', 'woo-coupon-usage' );
     1215        ?></th>
     1216                                                <th><?php
     1217        echo esc_html__( '% of Affiliate Earnings', 'woo-coupon-usage' );
     1218        ?></th>
     1219                                                <th><?php
     1220        echo esc_html__( '% of Order Total', 'woo-coupon-usage' );
     1221        ?></th>
     1222                                                <th><?php
     1223        echo sprintf( esc_html__( '%s Fixed Amount', 'woo-coupon-usage' ), ( function_exists( 'wcusage_get_currency_symbol' ) ? wcusage_get_currency_symbol() : '$' ) );
     1224        ?></th>
     1225                                                <th style="width: 120px;"><?php
     1226        echo esc_html__( 'Source', 'woo-coupon-usage' );
     1227        ?></th>
     1228                                            </tr>
     1229                                        </thead>
     1230                                        <tbody>
     1231                                        <?php
     1232        for ($i = 1; $i <= $mla_tiersnumber; $i++) {
     1233            $tier_key = 'T' . $i;
     1234            $user_tier_percent = get_user_meta( $user_id, 'wcu_mla_tier_percent_' . $tier_key, true );
     1235            $user_tier_order_percent = get_user_meta( $user_id, 'wcu_mla_tier_order_percent_' . $tier_key, true );
     1236            $user_tier_fixed = get_user_meta( $user_id, 'wcu_mla_tier_fixed_' . $tier_key, true );
     1237            // Determine which source is active
     1238            $effective_rates = ( function_exists( 'wcusage_mla_get_tier_rates' ) ? wcusage_mla_get_tier_rates( $tier_key, $user_id ) : array(
     1239                'percent'       => 0,
     1240                'order_percent' => 0,
     1241                'fixed'         => 0,
     1242            ) );
     1243            // Determine Source label — must mirror wcusage_mla_get_tier_rates() priority logic
     1244            $source_label = '<span style="color: #646970;">' . esc_html__( 'Global', 'woo-coupon-usage' ) . '</span>';
     1245            // Check if group rates are active (priority 2)
     1246            if ( $user_data && !empty( $user_data->roles ) ) {
     1247                foreach ( $user_data->roles as $role ) {
     1248                    if ( $role === 'coupon_affiliate' || strpos( $role, 'coupon_affiliate_' ) === 0 ) {
     1249                        $gp = ( isset( $options_check['wcusage_field_mla_tier_percent_' . $tier_key . '_' . $role] ) ? $options_check['wcusage_field_mla_tier_percent_' . $tier_key . '_' . $role] : '' );
     1250                        $gop = ( isset( $options_check['wcusage_field_mla_tier_order_percent_' . $tier_key . '_' . $role] ) ? $options_check['wcusage_field_mla_tier_order_percent_' . $tier_key . '_' . $role] : '' );
     1251                        $gf = ( isset( $options_check['wcusage_field_mla_tier_fixed_' . $tier_key . '_' . $role] ) ? $options_check['wcusage_field_mla_tier_fixed_' . $tier_key . '_' . $role] : '' );
     1252                        $has_group_rates = $gp !== '' || $gop !== '' || $gf !== '';
     1253                        $group_flag_exists = isset( $options_check['wcusage_field_mla_custom_rates_enabled_' . $role] );
     1254                        $group_flag_enabled = $group_flag_exists && ($options_check['wcusage_field_mla_custom_rates_enabled_' . $role] === '1' || $options_check['wcusage_field_mla_custom_rates_enabled_' . $role] === 1);
     1255                        if ( $has_group_rates && (!$group_flag_exists || $group_flag_enabled) ) {
     1256                            $source_label = '<span style="color: #6f42c1; font-weight: 600;">' . esc_html__( 'Group', 'woo-coupon-usage' ) . '</span>';
     1257                            break;
     1258                        }
     1259                    }
     1260                }
     1261            }
     1262            // Check if user rates are active (priority 1 — overrides group)
     1263            $has_user_rate = $user_tier_percent !== '' || $user_tier_order_percent !== '' || $user_tier_fixed !== '';
     1264            if ( $has_user_rate ) {
     1265                $user_flag_exists = metadata_exists( 'user', $user_id, 'wcu_mla_custom_rates_enabled' );
     1266                $user_flag_val = get_user_meta( $user_id, 'wcu_mla_custom_rates_enabled', true );
     1267                $user_flag_enabled = $user_flag_val === '1' || $user_flag_val === 1 || $user_flag_val === true;
     1268                if ( !$user_flag_exists || $user_flag_enabled ) {
     1269                    $source_label = '<span style="color: #2271b1; font-weight: 600;">' . esc_html__( 'User', 'woo-coupon-usage' ) . '</span>';
     1270                }
     1271            }
     1272            ?>
     1273                                            <tr>
     1274                                                <td><strong><?php
     1275            echo sprintf( esc_html__( 'Tier %d', 'woo-coupon-usage' ), $i );
     1276            ?></strong></td>
     1277                                                <td>
     1278                                                    <input type="number" step="0.1" name="wcu_mla_tier_percent_<?php
     1279            echo esc_attr( $tier_key );
     1280            ?>" value="<?php
     1281            echo esc_attr( $user_tier_percent );
     1282            ?>" class="small-text" placeholder="<?php
     1283            echo esc_attr( $effective_rates['percent'] );
     1284            ?>" style="width: 80px;" />
     1285                                                </td>
     1286                                                <td>
     1287                                                    <input type="number" step="0.1" name="wcu_mla_tier_order_percent_<?php
     1288            echo esc_attr( $tier_key );
     1289            ?>" value="<?php
     1290            echo esc_attr( $user_tier_order_percent );
     1291            ?>" class="small-text" placeholder="<?php
     1292            echo esc_attr( $effective_rates['order_percent'] );
     1293            ?>" style="width: 80px;" />
     1294                                                </td>
     1295                                                <td>
     1296                                                    <input type="number" step="0.01" name="wcu_mla_tier_fixed_<?php
     1297            echo esc_attr( $tier_key );
     1298            ?>" value="<?php
     1299            echo esc_attr( $user_tier_fixed );
     1300            ?>" class="small-text" placeholder="<?php
     1301            echo esc_attr( $effective_rates['fixed'] );
     1302            ?>" style="width: 80px;" />
     1303                                                </td>
     1304                                                <td><?php
     1305            echo wp_kses_post( $source_label );
     1306            ?></td>
     1307                                            </tr>
     1308                                        <?php
     1309        }
     1310        ?>
     1311                                        </tbody>
     1312                                    </table>
     1313
     1314                                    <p style="margin-top: 10px; color: #646970; font-size: 12px;">
     1315                                        <span class="dashicons dashicons-info" style="font-size: 14px; width: 14px; height: 14px;"></span>
     1316                                        <?php
     1317        echo esc_html__( 'Placeholder values show the currently active rate from either group or global settings. Clear a field to revert to the inherited rate.', 'woo-coupon-usage' );
     1318        ?>
     1319                                    </p>
     1320                                    </div><!-- #wcu-mla-user-rates-table -->
     1321                                    <script>
     1322                                    (function(){
     1323                                        var cb = document.getElementById('wcu_mla_custom_rates_enabled_user');
     1324                                        var tbl = document.getElementById('wcu-mla-user-rates-table');
     1325                                        function toggle(){ tbl.style.display = cb.checked ? '' : 'none'; }
     1326                                        cb.addEventListener('change', toggle);
     1327                                        toggle();
     1328                                    })();
     1329                                    </script>
     1330
     1331                                    <p class="submit" style="margin-top: 15px;">
     1332                                        <input type="submit" class="button button-primary" value="<?php
     1333        echo esc_attr__( 'Save Commission Rates', 'woo-coupon-usage' );
     1334        ?>" />
     1335                                    </p>
     1336                                </form>
     1337                            </div>
     1338                            <?php
     1339    }
     1340    // end per-user/per-group rates check
     1341    ?>
     1342
     1343                        </div><!-- .wcusage-mla-subtab-content -->
     1344
    7541345                    </div>
    7551346                    <?php
     
    11841775    <?php
    11851776        $wcusage_field_payout_pending_enable = wcusage_get_setting_value( 'wcusage_field_payout_pending_enable', '1' );
     1777        $wcusage_tracking_enable = wcusage_get_setting_value( 'wcusage_field_tracking_enable', '0' );
    11861778        ?>
    11871779    <h3><?php
     
    16422234        ?></td>
    16432235                    <td><?php
    1644         echo esc_html( wc_get_order_status_name( $order->get_status() ) );
    1645         ?></td>
     2236        $order_status = $order->get_status();
     2237        $order_status_class = '';
     2238        switch ( $order_status ) {
     2239            case 'completed':
     2240                $order_status_class = 'status-completed';
     2241                break;
     2242            case 'processing':
     2243                $order_status_class = 'status-processing';
     2244                break;
     2245            case 'on-hold':
     2246                $order_status_class = 'status-on-hold';
     2247                break;
     2248            case 'cancelled':
     2249            case 'refunded':
     2250            case 'failed':
     2251                $order_status_class = 'status-cancelled';
     2252                break;
     2253            default:
     2254                $order_status_class = 'status-processing';
     2255                break;
     2256        }
     2257        ?><span class="order-status <?php
     2258        echo esc_attr( $order_status_class );
     2259        ?>"><?php
     2260        echo esc_html( wc_get_order_status_name( $order_status ) );
     2261        ?></span></td>
    16462262                </tr>
    16472263            <?php
     
    20372653        // Get coupon title
    20382654        $coupon_title = '';
    2039         if ( $payout->couponid ) {
     2655        $is_mla_payout = empty( $payout->couponid ) || intval( $payout->couponid ) === 0;
     2656        if ( !$is_mla_payout ) {
    20402657            $coupon_title = get_the_title( $payout->couponid );
    20412658        }
     
    20612678        echo esc_html( $payout->id );
    20622679        ?></td>
    2063                     <td><?php
    2064         echo esc_html( $coupon_title );
    2065         ?></td>
     2680                    <td>
     2681                        <?php
     2682        if ( $is_mla_payout ) {
     2683            ?>
     2684                            <span class="order-status" style="background:#e8d5f5;color:#5b2c8d;"><?php
     2685            echo esc_html__( 'MLA', 'woo-coupon-usage' );
     2686            ?></span>
     2687                        <?php
     2688        } else {
     2689            ?>
     2690                            <?php
     2691            echo esc_html( $coupon_title );
     2692            ?>
     2693                        <?php
     2694        }
     2695        ?>
     2696                    </td>
    20662697                    <td><?php
    20672698        echo wcusage_format_price( $payout->amount );
  • woo-coupon-usage/trunk/inc/admin/class-activity-list-table.php

    r3415640 r3469742  
    4040            $user = get_userdata( $item[$column_name] );
    4141            if($user) {
    42                 return '<a href="'. esc_url( admin_url('admin.php?page=wcusage_view_affiliate&user_id=' . $item[$column_name]) ) .'" title="'.$user->user_login.'" target="_blank">'.$user->first_name.' '.$user->last_name.'</a>';
     42                return '<a href="'. esc_url( admin_url('admin.php?page=wcusage_view_affiliate&user_id=' . absint( $item[$column_name] )) ) .'" title="'. esc_attr( $user->user_login ) .'" target="_blank">'. esc_html( $user->first_name ) .' '. esc_html( $user->last_name ) .'</a>';
    4343            } else {
    4444                return 'Guest';
     
    9292    }
    9393
     94    /**
     95     * Get the list of available event types for the filter dropdown.
     96     */
     97    public static function get_event_types() {
     98        return array(
     99            'referral'                                  => __( 'Referral', 'woo-coupon-usage' ),
     100            'registration'                              => __( 'Registration', 'woo-coupon-usage' ),
     101            'registration_accept'                       => __( 'Registration Accepted', 'woo-coupon-usage' ),
     102            'mla_invite'                                => __( 'MLA Invite', 'woo-coupon-usage' ),
     103            'direct_link_domain'                        => __( 'Direct Link Domain', 'woo-coupon-usage' ),
     104            'payout_request'                            => __( 'Payout Request', 'woo-coupon-usage' ),
     105            'payout_paid'                               => __( 'Payout Paid', 'woo-coupon-usage' ),
     106            'payout_reversed'                           => __( 'Payout Reversed', 'woo-coupon-usage' ),
     107            'new_campaign'                              => __( 'New Campaign', 'woo-coupon-usage' ),
     108            'commission_added'                          => __( 'Commission Added', 'woo-coupon-usage' ),
     109            'commission_removed'                        => __( 'Commission Removed', 'woo-coupon-usage' ),
     110            'mla_commission_added'                      => __( 'MLA Commission Added', 'woo-coupon-usage' ),
     111            'mla_commission_removed'                    => __( 'MLA Commission Removed', 'woo-coupon-usage' ),
     112            'manual_unpaid_commission_edit'              => __( 'Manual Unpaid Commission Edit', 'woo-coupon-usage' ),
     113            'manual_pending_commission_edit'             => __( 'Manual Pending Commission Edit', 'woo-coupon-usage' ),
     114            'manual_processing_commission_edit'          => __( 'Manual Processing Commission Edit', 'woo-coupon-usage' ),
     115            'manual_coupon_commission_edit'              => __( 'Manual Coupon Commission Edit', 'woo-coupon-usage' ),
     116            'manual_coupon_commission_fixed_order_edit'  => __( 'Manual Fixed Order Commission Edit', 'woo-coupon-usage' ),
     117            'manual_coupon_commission_fixed_product_edit'=> __( 'Manual Fixed Product Commission Edit', 'woo-coupon-usage' ),
     118            'reward_earned'                             => __( 'Reward Earned', 'woo-coupon-usage' ),
     119            'reward_earned_bonus_amount'                => __( 'Reward Bonus Amount', 'woo-coupon-usage' ),
     120            'reward_earned_commission_increase'         => __( 'Reward Commission Increase', 'woo-coupon-usage' ),
     121            'reward_earned_email_sent'                  => __( 'Reward Email Sent', 'woo-coupon-usage' ),
     122            'reward_earned_role_assigned'               => __( 'Reward Role Assigned', 'woo-coupon-usage' ),
     123        );
     124    }
     125
     126    /**
     127     * Display the filters above the table.
     128     */
     129    function extra_tablenav( $which ) {
     130        if ( $which !== 'top' ) {
     131            return;
     132        }
     133
     134        $event_type  = isset( $_GET['event_type'] )  ? sanitize_text_field( wp_unslash( $_GET['event_type'] ) )  : '';
     135        $search_user = isset( $_GET['search_user'] )  ? sanitize_text_field( wp_unslash( $_GET['search_user'] ) )  : '';
     136        $date_from   = isset( $_GET['date_from'] )    ? sanitize_text_field( wp_unslash( $_GET['date_from'] ) )    : '';
     137        $date_to     = isset( $_GET['date_to'] )      ? sanitize_text_field( wp_unslash( $_GET['date_to'] ) )      : '';
     138        $search_term = isset( $_GET['s'] )             ? sanitize_text_field( wp_unslash( $_GET['s'] ) )             : '';
     139
     140        $event_types = self::get_event_types();
     141        ?>
     142        <div class="wcusage-activity-filters alignleft actions">
     143
     144            <input type="text" name="s" placeholder="<?php esc_attr_e( 'Search events...', 'woo-coupon-usage' ); ?>" value="<?php echo esc_attr( $search_term ); ?>" style="width:160px;" />
     145
     146            <select name="event_type">
     147                <option value=""><?php esc_html_e( 'All Event Types', 'woo-coupon-usage' ); ?></option>
     148                <?php foreach ( $event_types as $key => $label ) : ?>
     149                    <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $event_type, $key ); ?>><?php echo esc_html( $label ); ?></option>
     150                <?php endforeach; ?>
     151            </select>
     152
     153            <input type="text" name="search_user" placeholder="<?php esc_attr_e( 'Search user...', 'woo-coupon-usage' ); ?>" value="<?php echo esc_attr( $search_user ); ?>" style="width:140px;" />
     154
     155            <label class="wcusage-activity-date-label"><?php esc_html_e( 'From:', 'woo-coupon-usage' ); ?></label>
     156            <input type="date" name="date_from" value="<?php echo esc_attr( $date_from ); ?>" style="width:145px;" />
     157
     158            <label class="wcusage-activity-date-label"><?php esc_html_e( 'To:', 'woo-coupon-usage' ); ?></label>
     159            <input type="date" name="date_to" value="<?php echo esc_attr( $date_to ); ?>" style="width:145px;" />
     160
     161            <?php submit_button( __( 'Filter', 'woo-coupon-usage' ), 'action', 'filter_action', false ); ?>
     162
     163            <?php
     164            // Show reset link when any filter is active
     165            if ( $event_type || $search_user || $date_from || $date_to || $search_term ) :
     166            ?>
     167                <a href="<?php echo esc_url( admin_url( 'admin.php?page=wcusage_activity' ) ); ?>" class="button" style="margin-left:4px;"><?php esc_html_e( 'Reset', 'woo-coupon-usage' ); ?></a>
     168            <?php endif; ?>
     169
     170        </div>
     171        <?php
     172    }
     173
    94174    function prepare_items() {
    95175
    96         global $wpdb; //This is used only if making any database queries
     176        global $wpdb;
    97177
    98178        $per_page = 100;
     
    108188        $table_name = $wpdb->prefix . 'wcusage_activity';
    109189
    110         if (isset($_GET['status'])) {
    111             $sql = $wpdb->prepare("SELECT * FROM $table_name WHERE status = %s ORDER BY id DESC", sanitize_text_field($_GET['status'])); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
     190        // Build WHERE clauses from filters
     191        $where = array();
     192        $values = array();
     193
     194        // Event type filter (validated against known event types)
     195        if ( ! empty( $_GET['event_type'] ) ) {
     196            $event_type = sanitize_text_field( wp_unslash( $_GET['event_type'] ) );
     197            $allowed_event_types = array_keys( self::get_event_types() );
     198            if ( in_array( $event_type, $allowed_event_types, true ) ) {
     199                $where[] = 'a.event = %s';
     200                $values[] = $event_type;
     201            }
     202        }
     203
     204        // User search filter (search by name, username, or email)
     205        if ( ! empty( $_GET['search_user'] ) ) {
     206            $search_user = sanitize_text_field( wp_unslash( $_GET['search_user'] ) );
     207            // Look up matching user IDs from the users table
     208            $users_table = $wpdb->users;
     209            $usermeta_table = $wpdb->usermeta;
     210            $like = '%' . $wpdb->esc_like( $search_user ) . '%';
     211            $user_ids = $wpdb->get_col( $wpdb->prepare(
     212                "SELECT DISTINCT u.ID FROM $users_table u
     213                 LEFT JOIN $usermeta_table um_fn ON (u.ID = um_fn.user_id AND um_fn.meta_key = 'first_name')
     214                 LEFT JOIN $usermeta_table um_ln ON (u.ID = um_ln.user_id AND um_ln.meta_key = 'last_name')
     215                 WHERE u.user_login LIKE %s
     216                 OR u.user_email LIKE %s
     217                 OR u.display_name LIKE %s
     218                 OR um_fn.meta_value LIKE %s
     219                 OR um_ln.meta_value LIKE %s", // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
     220                $like, $like, $like, $like, $like
     221            ) );
     222            if ( ! empty( $user_ids ) ) {
     223                $placeholders = implode( ',', array_fill( 0, count( $user_ids ), '%d' ) );
     224                $where[] = "a.user_id IN ($placeholders)";
     225                $values = array_merge( $values, $user_ids );
     226            } else {
     227                // No users matched – force empty result
     228                $where[] = '1 = 0';
     229            }
     230        }
     231
     232        // Date from filter (validated as YYYY-MM-DD)
     233        if ( ! empty( $_GET['date_from'] ) ) {
     234            $date_from = sanitize_text_field( wp_unslash( $_GET['date_from'] ) );
     235            if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_from ) ) {
     236                $where[] = 'a.date >= %s';
     237                $values[] = $date_from . ' 00:00:00';
     238            }
     239        }
     240
     241        // Date to filter (validated as YYYY-MM-DD)
     242        if ( ! empty( $_GET['date_to'] ) ) {
     243            $date_to = sanitize_text_field( wp_unslash( $_GET['date_to'] ) );
     244            if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date_to ) ) {
     245                $where[] = 'a.date <= %s';
     246                $values[] = $date_to . ' 23:59:59';
     247            }
     248        }
     249
     250        // Search term filter (searches event info text)
     251        if ( ! empty( $_GET['s'] ) ) {
     252            $search_term = sanitize_text_field( wp_unslash( $_GET['s'] ) );
     253            $like = '%' . $wpdb->esc_like( $search_term ) . '%';
     254            $where[] = '(a.info LIKE %s OR a.event LIKE %s)';
     255            $values[] = $like;
     256            $values[] = $like;
     257        }
     258
     259        // Build the SQL
     260        $where_sql = '';
     261        if ( ! empty( $where ) ) {
     262            $where_sql = 'WHERE ' . implode( ' AND ', $where );
     263        }
     264
     265        // Sorting
     266        $orderby = 'a.id';
     267        $order = 'DESC';
     268        if ( ! empty( $_GET['orderby'] ) ) {
     269            $allowed_orderby = array( 'date', 'id' );
     270            $request_orderby = sanitize_text_field( wp_unslash( $_GET['orderby'] ) );
     271            if ( in_array( $request_orderby, $allowed_orderby, true ) ) {
     272                $orderby = 'a.' . $request_orderby;
     273            }
     274        }
     275        if ( ! empty( $_GET['order'] ) ) {
     276            $request_order = strtoupper( sanitize_text_field( wp_unslash( $_GET['order'] ) ) );
     277            if ( in_array( $request_order, array( 'ASC', 'DESC' ), true ) ) {
     278                $order = $request_order;
     279            }
     280        }
     281
     282        // Count query
     283        $count_sql = "SELECT COUNT(*) FROM $table_name a $where_sql"; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
     284        if ( ! empty( $values ) ) {
     285            $total_items = (int) $wpdb->get_var( $wpdb->prepare( $count_sql, $values ) ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
    112286        } else {
    113             $sql = "SELECT * FROM $table_name ORDER BY id DESC"; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
    114         }
    115         $data = $wpdb->get_results($sql, ARRAY_A); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter       
    116 
     287            $total_items = (int) $wpdb->get_var( $count_sql ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
     288        }
     289
     290        // Data query with pagination
    117291        $current_page = $this->get_pagenum();
    118 
    119         $total_items = count($data);
    120 
    121         $data = array_slice($data,(($current_page-1)*$per_page),$per_page);
     292        $offset = ( $current_page - 1 ) * $per_page;
     293
     294        $data_sql = "SELECT a.* FROM $table_name a $where_sql ORDER BY $orderby $order LIMIT %d OFFSET %d"; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
     295        $data_values = array_merge( $values, array( $per_page, $offset ) );
     296        $data = $wpdb->get_results( $wpdb->prepare( $data_sql, $data_values ), ARRAY_A ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter
    122297
    123298        $this->items = $data;
    124299
    125300        $this->set_pagination_args( array(
    126             'total_items' => $total_items,                  //WE have to calculate the total number of items
    127             'per_page'    => $per_page,                     //WE have to determine how many items to show on a page
    128             'total_pages' => ceil($total_items/$per_page)   //WE have to calculate the total number of pages
     301            'total_items' => $total_items,
     302            'per_page'    => $per_page,
     303            'total_pages' => ceil( $total_items / $per_page ),
    129304        ) );
    130305
  • woo-coupon-usage/trunk/inc/admin/class-coupons-table.php

    r3462634 r3469742  
    784784function wcusage_save_coupon_data() {
    785785    check_ajax_referer( 'wcusage_coupon_nonce', 'nonce' );
     786
     787    if ( ! current_user_can( 'manage_woocommerce' ) ) {
     788        wp_send_json_error( array( 'message' => 'Permission denied.' ) );
     789        return;
     790    }
    786791   
    787792    $coupon_id = intval( $_POST['coupon_id'] );
     
    822827        'wcu_text_unpaid_commission'            => floatval( wp_unslash( $_POST['wcu_text_unpaid_commission'] ) ),
    823828        'wcu_text_pending_payment_commission'   => floatval( wp_unslash( $_POST['wcu_text_pending_payment_commission'] ) ),
     829        'wcu_text_pending_order_commission'     => floatval( wp_unslash( $_POST['wcu_text_pending_order_commission'] ) ),
    824830    );
    825831
     
    838844    if(!isset($_POST['wcu_text_pending_payment_commission']) || $_POST['wcu_text_pending_payment_commission'] == '') {
    839845        $meta['wcu_text_pending_payment_commission'] = "0";
     846    }
     847    if(!isset($_POST['wcu_text_pending_order_commission']) || $_POST['wcu_text_pending_order_commission'] == '') {
     848        $meta['wcu_text_pending_order_commission'] = "0";
    840849    }
    841850
     
    846855        unset( $meta['wcu_text_unpaid_commission'] );
    847856        unset( $meta['wcu_text_pending_payment_commission'] );
     857        unset( $meta['wcu_text_pending_order_commission'] );
    848858    }
    849859   
  • woo-coupon-usage/trunk/inc/admin/settings/admin-options.php

    r3462634 r3469742  
    16601660        }
    16611661        // Affiliate users table styles and scripts
    1662         if ( isset( $_GET['page'] ) && $_GET['page'] == 'wcusage_affiliates' ) {
     1662        if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array('wcusage_affiliates', 'wcusage_mla_users'), true ) ) {
    16631663            $css_path = WCUSAGE_UNIQUE_PLUGIN_PATH . 'css/admin-affiliate-users-table.css';
    16641664            $css_ver = ( file_exists( $css_path ) ? filemtime( $css_path ) : '1.0.0' );
     
    16681668                array(),
    16691669                $css_ver
     1670            );
     1671            $users_css_path = WCUSAGE_UNIQUE_PLUGIN_PATH . 'css/admin-affiliate-users.css';
     1672            $users_css_ver = ( file_exists( $users_css_path ) ? filemtime( $users_css_path ) : '1.0.0' );
     1673            wp_enqueue_style(
     1674                'wcusage-admin-affiliate-users',
     1675                WCUSAGE_UNIQUE_PLUGIN_URL . 'css/admin-affiliate-users.css',
     1676                array('wcusage-admin-affiliate-users-table'),
     1677                $users_css_ver
    16701678            );
    16711679            $js_path = WCUSAGE_UNIQUE_PLUGIN_PATH . 'js/admin-affiliate-users-table.js';
  • woo-coupon-usage/trunk/inc/admin/settings/options-notifications.php

    r3454163 r3469742  
    479479
    480480            <?php echo wcusage_email_merge_tags(array("name", "sub-affiliate-user", "sub-affiliate-tier", "sub-affiliate-commission", "sub-affiliate-commission-fixed")); ?>
     481
     482          </div>
     483
     484        </div>
     485
     486        <div class="wcu-setting-email-notification-box">
     487
     488          <!--
     489          ********************
     490          ** [Parent Email] New Sub-Affiliate Registration
     491          ********************
     492          -->
     493          <?php wcusage_setting_toggle_option('wcusage_field_email_mla_sub_reg_notify_enable', 1, esc_html__( 'New Sub-Affiliate Registration', 'woo-coupon-usage' ), '0px'); ?>
     494
     495          <i><?php echo esc_html__( 'Send an email to the MLA parent affiliate when a new sub-affiliate registers via their invite link, including the application details and a link to approve or decline from their MLA dashboard.', 'woo-coupon-usage' ); ?></i>
     496
     497          <br/><br/><p><span class="fa-solid fa-circle-user"></span> <strong><?php echo esc_html__( 'Recipient', 'woo-coupon-usage' ); ?>:</strong> <?php echo esc_html__( 'Parent Affiliate User', 'woo-coupon-usage' ); ?></p>
     498
     499          <br/><p><span class="fa-solid fa-envelope-open-text"></span> <strong><?php echo esc_html__( 'Email Customizer', 'woo-coupon-usage' ); ?>:</strong> <button type="button" class="wcu-showhide-button" id="wcu_show_email_mla_sub_reg_notify_customise">Show <span class="fa-solid fa-arrow-down"></span></button></p>
     500
     501          <?php echo wcu_admin_settings_showhide_toggle("wcu_show_email_mla_sub_reg_notify_customise", "wcu_email_mla_sub_reg_notify_customise", "Show", "Hide"); ?>
     502          <div id="wcu_email_mla_sub_reg_notify_customise" style="display: none;">
     503
     504            <br/>
     505
     506            <!-- Email Notification Subject -->
     507            <?php wcusage_setting_text_option('wcusage_field_email_mla_sub_reg_notify_subject', esc_html__( "New Sub-Affiliate Registration: {sub-affiliate-user}", "woo-coupon-usage" ), esc_html__( 'Email Notification Subject', 'woo-coupon-usage' ), '0px'); ?>
     508
     509            <br/>
     510
     511            <!-- Email Notification Message -->
     512            <?php
     513            $email_mla_sub_reg_notify_message = "Hello {name},"
     514            . "<br/><br/>A new affiliate has registered via your invite link and is pending your approval:"
     515            . "<br/><br/><strong>Username:</strong> {username}"
     516            . "<br/><strong>Name:</strong> {sub-affiliate-name}"
     517            . "<br/><strong>Email:</strong> {sub-affiliate-email}"
     518            . "<br/><strong>Coupon:</strong> {coupon}"
     519            . "<br/><strong>Website:</strong> {website}"
     520            . "<br/><strong>Referrer:</strong> {referrer}"
     521            . "<br/><strong>Promote:</strong> {promote}"
     522            . "<br/>{custom-fields}"
     523            . "<br/><br/>Review and approve or decline this registration from your MLA dashboard:"
     524            . "<br/><br/>{dashboardurl}";
     525            wcusage_setting_tinymce_option('wcusage_field_email_mla_sub_reg_notify_message', $email_mla_sub_reg_notify_message, esc_html__( 'Email Notification Message', 'woo-coupon-usage' ), '0px');
     526            ?>
     527
     528            <br/>
     529
     530            <?php echo wcusage_email_merge_tags(array("name", "username", "sub-affiliate-name", "sub-affiliate-email", "coupon", "website", "referrer", "promote", "custom-fields", "dashboardurl")); ?>
    481531
    482532          </div>
     
    920970              break;
    921971          case "sub-affiliate-user":
    922               echo "<p>- <strong>{sub-affiliate-user}</strong> ".esc_html__( 'to the sub-affiliate username.', 'woo-coupon-usage' )."</p>";
     972              echo "<p>- <strong>{sub-affiliate-user}</strong> ".esc_html__( 'to show the sub-affiliate username.', 'woo-coupon-usage' )."</p>";
     973              break;
     974          case "sub-affiliate-email":
     975              echo "<p>- <strong>{sub-affiliate-email}</strong> ".esc_html__( 'to show the sub-affiliate email address.', 'woo-coupon-usage' )."</p>";
     976              break;
     977          case "sub-affiliate-name":
     978              echo "<p>- <strong>{sub-affiliate-name}</strong> ".esc_html__( 'to show the sub-affiliate display name.', 'woo-coupon-usage' )."</p>";
    923979              break;
    924980          case "custom-fields":
  • woo-coupon-usage/trunk/inc/admin/settings/options-payouts.php

    r3454163 r3469742  
    283283       <br/><br/><hr/>
    284284
    285        <h3 id="wcu-setting-header-payouts-scheduled"><span class="dashicons dashicons-admin-generic" style="margin-top: 2px;"></span> <?php echo esc_html__( 'Pending Commission', 'woo-coupon-usage' ); ?>:</h3>
    286 
    287        <p><?php echo esc_html__( 'Pending Commission allows affiliates to track commission from orders that are not yet completed, but displayed on the dashboard.', 'woo-coupon-usage' ); ?></p>
     285       <h3 id="wcu-setting-header-payouts-scheduled"><span class="dashicons dashicons-admin-generic" style="margin-top: 2px;"></span> <?php echo esc_html__( 'Processing Commission', 'woo-coupon-usage' ); ?>:</h3>
     286
     287       <p><?php echo esc_html__( 'Processing Commission allows affiliates to track commission from orders that are not yet completed, but displayed on the dashboard.', 'woo-coupon-usage' ); ?></p>
    288288       
    289289       <p><?php echo esc_html__( 'This is useful for showing withheld commission, which would convert it to "unpaid commission" once the order is completed, which they can then request payouts for.', 'woo-coupon-usage' ); ?></p>
    290290
    291        <p><?php echo esc_html__( 'The "Pending Commission" will be displayed in the "Payouts" tab as a small notice just above the "Unpaid Commission" amount.', 'woo-coupon-usage' ); ?></p>
     291       <p><?php echo esc_html__( 'The "Processing Commission" will be displayed in the "Payouts" tab as a small notice just above the "Unpaid Commission" amount.', 'woo-coupon-usage' ); ?></p>
    292292
    293293       <br/>
    294294
    295         <?php wcusage_setting_toggle_option('wcusage_field_payout_pending_enable', 1, esc_html__( 'Enable "Pending Commission" tracking.', 'woo-coupon-usage' ), '0px'); ?>
    296         <i><?php echo esc_html__( 'When enabled, "Pending Commission" will be tracked and shown on the payouts tab for statuses that are set to show on the dashboard but not completed yet (not granted unpaid commission).', 'woo-coupon-usage' ); ?></i><br/>
     295        <?php wcusage_setting_toggle_option('wcusage_field_payout_pending_enable', 1, esc_html__( 'Enable "Processing Commission" tracking.', 'woo-coupon-usage' ), '0px'); ?>
     296        <i><?php echo esc_html__( 'When enabled, "Processing Commission" will be tracked and shown on the payouts tab for statuses that are set to show on the dashboard but not completed yet (not granted unpaid commission).', 'woo-coupon-usage' ); ?></i><br/>
    297297       
    298298       <br/><hr/>
  • woo-coupon-usage/trunk/inc/admin/tools/quick-edit-coupon.php

    r3454163 r3469742  
    135135                                </div>
    136136                            </div>
     137                            <?php $wcu_processing_commission = (float) get_post_meta( $coupon_id, 'wcu_text_pending_order_commission', true ); ?>
     138                            <?php if ( $wcu_processing_commission > 0 ) : ?>
     139                            <div class="form-row">
     140                                <div class="form-field" <?php if ( ! wcu_fs()->can_use_premium_code() ) { ?>style="opacity: 0.5; pointer-events: none;"<?php } ?>>
     141                                    <label for="wcu_text_pending_order_commission_<?php echo esc_attr( $coupon_id ); ?>"><?php esc_html_e( 'Processing Commission', 'woo-coupon-usage' ); ?><?php if ( ! wcu_fs()->can_use_premium_code() ) { ?> (PRO)<?php } ?></label>
     142                                    <input type="number" id="wcu_text_pending_order_commission_<?php echo esc_attr( $coupon_id ); ?>" step="0.01" value="<?php echo esc_attr( $wcu_processing_commission ); ?>">
     143                                </div>
     144                            </div>
     145                            <?php endif; ?>
    137146                        </div>
    138147                    </div>
  • woo-coupon-usage/trunk/inc/dashboard/tab-latest-orders.php

    r3462634 r3469742  
    188188            $wcusage_show_commission = 0;
    189189        }
     190        // Always show commission column on MLA dashboard (it shows what the parent earned)
     191        if ( $type == "mla" ) {
     192            $wcusage_show_commission = 1;
     193        }
    190194        $wcusage_show_orders_table_status_totals = wcusage_get_setting_value( 'wcusage_field_show_orders_table_status_totals', '1' );
    191195        $option_coupon_orders = wcusage_get_setting_value( 'wcusage_field_orders', '15' );
     
    439443        }
    440444        ?>
    441 
    442       }
    443445
    444446    }
     
    755757                        $totalordersexcl = $calculateorder['totalordersexcl'];
    756758                        $totalcommission = $calculateorder['totalcommission'];
    757                         if ( $type == "mla" ) {
    758                             $totalcommission = wcusage_mla_get_commission_from_tier(
    759                                 $totalcommission,
    760                                 $tier,
    761                                 '1',
    762                                 $orderid,
    763                                 $coupon_code
    764                             );
     759                        $wcusage_field_mla_enable = wcusage_get_setting_value( 'wcusage_field_mla_enable', '0' );
     760                        if ( $wcusage_field_mla_enable && $type == "mla" ) {
     761                            // Try stored MLA commission from order meta (persisted at order time)
     762                            $stored_mla = wcusage_order_meta( $orderid, 'wcu_mla_commission', true );
     763                            if ( is_array( $stored_mla ) && isset( $stored_mla[$tier]['commission'] ) ) {
     764                                $totalcommission = (float) $stored_mla[$tier]['commission'];
     765                            } else {
     766                                // Fallback: recalculate (for orders before this feature was added)
     767                                $totalcommission = wcusage_mla_get_commission_from_tier(
     768                                    $totalcommission,
     769                                    $tier,
     770                                    '1',
     771                                    $orderid,
     772                                    $coupon_code,
     773                                    0,
     774                                    $user_id
     775                                );
     776                                // Persist the recalculated value so it won't recalculate again next time
     777                                $tier_rates = ( function_exists( 'wcusage_mla_get_tier_rates' ) ? wcusage_mla_get_tier_rates( $tier, $user_id ) : array() );
     778                                if ( !is_array( $stored_mla ) ) {
     779                                    $stored_mla = array();
     780                                }
     781                                $stored_mla[$tier] = array(
     782                                    'parent_id'  => (int) $user_id,
     783                                    'commission' => round( (float) $totalcommission, 2 ),
     784                                    'rates'      => $tier_rates,
     785                                );
     786                                $mla_order_obj = wc_get_order( $orderid );
     787                                if ( $mla_order_obj ) {
     788                                    $mla_order_obj->update_meta_data( 'wcu_mla_commission', json_encode( $stored_mla ) );
     789                                    $mla_order_obj->save_meta_data();
     790                                }
     791                            }
    765792                        }
    766793                        $combined_totalcommission += (float) $totalcommission;
  • woo-coupon-usage/trunk/inc/functions/functions-activity.php

    r3358053 r3469742  
    202202      $event_message = "Unpaid commission removed from '".esc_html($coupon_name)."':" . " " . wp_kses_post($info);
    203203      break;
     204    case 'mla_commission_added':
     205      $coupon_info = wcusage_get_coupon_info_by_id($event_id);
     206      $coupon_name = $coupon_info[3];
     207      $info = html_entity_decode($info, ENT_QUOTES, 'UTF-8');
     208      if (preg_match('/#(\d+)/', $info, $matches)) {
     209        $order_id = $matches[1];
     210        $order_link = '<a href="'.esc_url(get_edit_post_link($order_id)).'" target="_blank">#'.$order_id.'</a>';
     211        $info = str_replace('#'.$order_id, $order_link, $info);
     212      }
     213      $event_message = "MLA unpaid commission added to '" . esc_html($coupon_name) . "':" . " " . wp_kses_post($info);
     214      break;
     215    case 'mla_commission_removed':
     216      $coupon_info = wcusage_get_coupon_info_by_id($event_id);
     217      $coupon_name = $coupon_info[3];
     218      $info = html_entity_decode($info, ENT_QUOTES, 'UTF-8');
     219      if (preg_match('/#(\d+)/', $info, $matches)) {
     220        $order_id = $matches[1];
     221        $order_link = '<a href="'.esc_url(get_edit_post_link($order_id)).'" target="_blank">#'.$order_id.'</a>';
     222        $info = str_replace('#'.$order_id, $order_link, $info);
     223      }
     224      $event_message = "MLA unpaid commission removed from '" . esc_html($coupon_name) . "':" . " " . wp_kses_post($info);
     225      break;
    204226    case 'manual_unpaid_commission_edit':
    205227      $coupon_info = wcusage_get_coupon_info_by_id($event_id);
     
    211233      $coupon_name = $coupon_info[3];
    212234      $event_message = "Pending commission edited for coupon '".esc_html($coupon_name)."':" . " " . wp_kses_post($info);
     235      break;
     236    case 'manual_processing_commission_edit':
     237      $coupon_info = wcusage_get_coupon_info_by_id($event_id);
     238      $coupon_name = $coupon_info[3];
     239      $event_message = "Processing commission edited for coupon '".esc_html($coupon_name)."':" . " " . wp_kses_post($info);
    213240      break;
    214241    case 'manual_coupon_commission_edit':
     
    279306      'wcu_text_unpaid_commission' => 'manual_unpaid_commission_edit',
    280307      'wcu_text_pending_commission' => 'manual_pending_commission_edit',
     308      'wcu_text_pending_order_commission' => 'manual_processing_commission_edit',
    281309      'wcu_text_coupon_commission' => 'manual_coupon_commission_edit',
    282310      'wcu_text_coupon_commission_fixed_order' => 'manual_coupon_commission_fixed_order_edit',
     
    298326      'wcu_text_unpaid_commission' => 'manual_unpaid_commission_edit',
    299327      'wcu_text_pending_commission' => 'manual_pending_commission_edit',
     328      'wcu_text_pending_order_commission' => 'manual_processing_commission_edit',
    300329      'wcu_text_coupon_commission' => 'manual_coupon_commission_edit',
    301330      'wcu_text_coupon_commission_fixed_order' => 'manual_coupon_commission_fixed_order_edit',
     
    317346              if($meta_key == 'wcu_text_unpaid_commission'
    318347              || $meta_key == 'wcu_text_pending_commission'
     348              || $meta_key == 'wcu_text_pending_order_commission'
    319349              || $meta_key == 'wcu_text_coupon_commission_fixed_order'
    320350              || $meta_key == 'wcu_text_coupon_commission_fixed_product')
  • woo-coupon-usage/trunk/inc/functions/functions-all-time.php

    r3462634 r3469742  
    546546
    547547  <p class="wcu-loading-loader-subtext" style="text-align:center; margin-top: 8px;"><?php
    548     echo esc_html__( "The page will relaod automatically when it is complete.", "woo-coupon-usage" );
     548    echo esc_html__( "The page will reload automatically when it is complete.", "woo-coupon-usage" );
    549549    ?></p>
    550550       
  • woo-coupon-usage/trunk/inc/functions/functions-calculate-order.php

    r3462634 r3469742  
    8080        $never_update_commission_meta = wcusage_get_setting_value( 'wcusage_field_enable_never_update_commission_meta', '0' );
    8181        if ( $never_update_commission_meta ) {
    82             if ( $item == "wcusage_commission_summary" || $item == "wcusage_total_commission" || $item == "wcusage_product_commission" || $item == "wcusage_currency_conversion" ) {
     82            if ( $item == "wcusage_commission_summary" || $item == "wcusage_total_commission" || $item == "wcusage_product_commission" || $item == "wcusage_currency_conversion" || $item == "wcu_mla_commission" ) {
    8383                if ( wcusage_order_meta( $order_id, $item ) ) {
    8484                    return;
     
    105105            $never_update_commission_meta = wcusage_get_setting_value( 'wcusage_field_enable_never_update_commission_meta', '0' );
    106106            if ( $never_update_commission_meta ) {
    107                 if ( $key == "wcusage_commission_summary" || $key == "wcusage_total_commission" || $key == "wcusage_product_commission" || $key == "wcusage_currency_conversion" ) {
     107                if ( $key == "wcusage_commission_summary" || $key == "wcusage_total_commission" || $key == "wcusage_product_commission" || $key == "wcusage_currency_conversion" || $key == "wcu_mla_commission" ) {
    108108                    if ( wcusage_order_meta( $order_id, $key ) ) {
    109109                        continue;
     
    352352                wcusage_delete_order_meta( $orderid, 'wcusage_commission_summary' );
    353353                wcusage_delete_order_meta( $orderid, 'wcusage_stats' );
     354                wcusage_delete_order_meta( $orderid, 'wcu_mla_commission' );
    354355            }
    355356            $get_affstats = wcusage_order_meta( $orderid, 'wcusage_stats', true );
     
    12321233                            }
    12331234                        }
     1235                        // Store fixed_order_commission separately so it is available when reading from meta-cache
     1236                        $meta_fixed_order_commission = wcusage_order_meta( $orderid, 'wcusage_fixed_order_commission', true );
     1237                        if ( $fixed_order_commission || $meta_fixed_order_commission !== '' ) {
     1238                            if ( $meta_fixed_order_commission === '' || !$never_update_commission_meta ) {
     1239                                if ( $save_order_commission_meta ) {
     1240                                    $meta_data['wcusage_fixed_order_commission'] = $fixed_order_commission;
     1241                                }
     1242                            }
     1243                        }
    12341244                        if ( $save_order_commission_meta ) {
    12351245                            $meta_data['wcusage_commission_summary'] = $commission_summary;
     
    12471257                        wcusage_delete_order_meta( $orderid, 'wcusage_product_commission' );
    12481258                    }
     1259                    if ( !$never_update_commission_meta ) {
     1260                        wcusage_delete_order_meta( $orderid, 'wcusage_fixed_order_commission' );
     1261                    }
    12491262                }
    12501263            } else {
    12511264                $totalcommission = wcusage_order_meta( $orderid, 'wcusage_total_commission', true );
    12521265                $fixed_product_commission_total = wcusage_order_meta( $orderid, 'wcusage_product_commission', true );
     1266                $fixed_order_commission = wcusage_order_meta( $orderid, 'wcusage_fixed_order_commission', true );
     1267                if ( $fixed_order_commission === '' ) {
     1268                    $fixed_order_commission = 0;
     1269                }
    12531270                $commission_summary = wcusage_order_meta( $orderid, 'wcusage_commission_summary', true );
    12541271            }
     
    12781295            if ( $current_fixed_product_commission_total ) {
    12791296                $fixed_product_commission_total = wcusage_order_meta( $orderid, 'wcusage_product_commission', true );
     1297            }
     1298            $current_fixed_order_commission = wcusage_order_meta( $orderid, 'wcusage_fixed_order_commission', true );
     1299            if ( $current_fixed_order_commission !== '' ) {
     1300                $fixed_order_commission = (float) $current_fixed_order_commission;
    12801301            }
    12811302            if ( $current_commission_summary ) {
  • woo-coupon-usage/trunk/inc/functions/functions-coupon-orders.php

    r3438708 r3469742  
    187187            delete_post_meta($order_id, 'wcusage_pending_commission');
    188188
     189            // Clear MLA commission so it gets recalculated fresh (unless "Never update saved commission" is enabled)
     190            $never_update_commission_meta = wcusage_get_setting_value('wcusage_field_enable_never_update_commission_meta', '0');
     191            if ( ! $never_update_commission_meta ) {
     192                wcusage_delete_order_meta( $order_id, 'wcu_mla_commission' );
     193            }
     194
    189195            // Check and add if pending (this handles the logic)
    190196            if( function_exists('wcusage_check_and_add_pending_commission') ) {
  • woo-coupon-usage/trunk/inc/functions/functions-dashboard.php

    r3454163 r3469742  
    334334        ?></option>
    335335  <?php
     336        $wcusage_show_months_table = ( isset( $wcusage_show_months_table ) ? $wcusage_show_months_table : wcusage_get_setting_value( 'wcusage_field_show_months_table', '1' ) );
     337        $wcusage_field_show_order_tab = ( isset( $wcusage_field_show_order_tab ) ? $wcusage_field_show_order_tab : wcusage_get_setting_value( 'wcusage_field_show_order_tab', '1' ) );
     338        $wcusage_field_urls_enable = ( isset( $wcusage_field_urls_enable ) ? $wcusage_field_urls_enable : wcusage_get_setting_value( 'wcusage_field_urls_enable', '1' ) );
     339        $wcusage_field_urls_tab_enable = ( isset( $wcusage_field_urls_tab_enable ) ? $wcusage_field_urls_tab_enable : wcusage_get_setting_value( 'wcusage_field_urls_tab_enable', '1' ) );
     340        $wcusage_field_creatives_enable = ( isset( $wcusage_field_creatives_enable ) ? $wcusage_field_creatives_enable : wcusage_get_setting_value( 'wcusage_field_creatives_enable', '1' ) );
     341        $wcusage_field_payouts_enable = ( isset( $wcusage_field_payouts_enable ) ? $wcusage_field_payouts_enable : wcusage_get_setting_value( 'wcusage_field_payouts_enable', '1' ) );
     342        $wcusage_field_rates_enable = ( isset( $wcusage_field_rates_enable ) ? $wcusage_field_rates_enable : wcusage_get_setting_value( 'wcusage_field_rates_enable', '0' ) );
     343        $wcusage_field_bonuses_enable = ( isset( $wcusage_field_bonuses_enable ) ? $wcusage_field_bonuses_enable : wcusage_get_setting_value( 'wcusage_field_bonuses_enable', '0' ) );
     344        $wcusage_field_bonuses_tab_enable = ( isset( $wcusage_field_bonuses_tab_enable ) ? $wcusage_field_bonuses_tab_enable : wcusage_get_setting_value( 'wcusage_field_bonuses_tab_enable', '1' ) );
     345        $wcusage_field_show_settings_tab_show = ( isset( $wcusage_field_show_settings_tab_show ) ? $wcusage_field_show_settings_tab_show : wcusage_get_setting_value( 'wcusage_field_show_settings_tab_show', '1' ) );
     346        $option_coupon_orders = ( isset( $option_coupon_orders ) ? $option_coupon_orders : wcusage_get_setting_value( 'wcusage_field_orders', '10' ) );
    336347        if ( $wcusage_show_months_table == '1' ) {
    337348            ?>
  • woo-coupon-usage/trunk/inc/functions/functions-general.php

    r3462634 r3469742  
    6262      || $post_id == $mla_dashboard_page
    6363      || is_account_page()
     64      || get_query_var( 'affiliate_portal' )
    6465      || ( !is_admin() && isset($_SERVER['REQUEST_URI']) && strpos( $_SERVER['REQUEST_URI'], $wcusage_portal_slug ) !== false ) ) {
    6566
     
    8485          });
    8586        }
    86         // WP Compress
    87         if ( is_plugin_active( 'wp-compress-image-optimizer/wp-compress.php' ) ) {
    88           // Disable JavaScript optimization
    89           add_filter('wpc_js_exclude', function($exclude_list) {
    90             if (!is_array($exclude_list)) {
    91               $exclude_list = array();
    92             }
    93             $exclude_list[] = 'woo-coupon-usage';
    94             $exclude_list[] = 'wcusage';
    95             $exclude_list[] = 'jquery.cookie';
    96             $exclude_list[] = 'portal.js';
    97             $exclude_list[] = 'tab-settings';
    98             $exclude_list[] = 'dark-mode';
    99             return $exclude_list;
    100           });
    101           // Disable CSS optimization
    102           add_filter('wpc_css_exclude', function($exclude_list) {
    103             if (!is_array($exclude_list)) {
    104               $exclude_list = array();
    105             }
    106             $exclude_list[] = 'woo-coupon-usage';
    107             $exclude_list[] = 'wcusage';
    108             return $exclude_list;
    109           });
    110           // Disable page caching
    111           add_filter('wpc_disable_caching', '__return_true');
    112           // Disable minification
    113           add_filter('wpc_disable_minify', '__return_true');
    114           // Disable lazy load
    115           add_filter('wpc_disable_lazyload', '__return_true');
    116         }
    11787
    11888      }
    11989    }
     90  }
     91}
     92
     93/**
     94 * Fix WP Compress conflicts on affiliate dashboard and portal pages.
     95 * Hooked on template_redirect (earlier than wp_head) so WP Compress
     96 * filters are registered before it processes the page.
     97 */
     98add_action( 'template_redirect', 'wcusage_fix_wp_compress', 1 );
     99if( !function_exists( 'wcusage_fix_wp_compress' ) ) {
     100  function wcusage_fix_wp_compress() {
     101    if ( ! is_plugin_active( 'wp-compress-image-optimizer/wp-compress.php' ) ) {
     102      return;
     103    }
     104    if ( is_admin() ) {
     105      return;
     106    }
     107
     108    $post_id = get_the_ID();
     109    $dashboard_page = wcusage_get_setting_value('wcusage_dashboard_page', '');
     110    $mla_dashboard_page = wcusage_get_setting_value('wcusage_mla_dashboard_page', '');
     111    $wcusage_portal_slug = wcusage_get_setting_value('wcusage_portal_slug', 'affiliate-portal');
     112
     113    $is_affiliate_page = (
     114      get_query_var( 'affiliate_portal' )
     115      || $post_id == $dashboard_page
     116      || $post_id == $mla_dashboard_page
     117      || is_account_page()
     118      || ( isset($_SERVER['REQUEST_URI']) && strpos( $_SERVER['REQUEST_URI'], $wcusage_portal_slug ) !== false )
     119    );
     120
     121    if ( ! $is_affiliate_page ) {
     122      return;
     123    }
     124
     125    // Disable JavaScript optimization
     126    add_filter('wpc_js_exclude', function($exclude_list) {
     127      if (!is_array($exclude_list)) {
     128        $exclude_list = array();
     129      }
     130      $exclude_list[] = 'woo-coupon-usage';
     131      $exclude_list[] = 'wcusage';
     132      $exclude_list[] = 'jquery.cookie';
     133      $exclude_list[] = 'portal.js';
     134      $exclude_list[] = 'tab-settings';
     135      $exclude_list[] = 'dark-mode';
     136      return $exclude_list;
     137    });
     138    // Disable CSS optimization
     139    add_filter('wpc_css_exclude', function($exclude_list) {
     140      if (!is_array($exclude_list)) {
     141        $exclude_list = array();
     142      }
     143      $exclude_list[] = 'woo-coupon-usage';
     144      $exclude_list[] = 'wcusage';
     145      return $exclude_list;
     146    });
     147    // Disable page caching
     148    add_filter('wpc_disable_caching', '__return_true');
     149    // Disable minification
     150    add_filter('wpc_disable_minify', '__return_true');
     151    // Disable lazy load
     152    add_filter('wpc_disable_lazyload', '__return_true');
    120153  }
    121154}
  • woo-coupon-usage/trunk/inc/functions/functions-new-order.php

    r3420154 r3469742  
    101101                    $coupon_info = wcusage_get_coupon_info( $lifetimeaffiliate );
    102102                    $coupon_user_id = $coupon_info[1];
    103                     $meta_data = wcusage_update_ml_affiliate_parents( $meta_data, $coupon_user_id, $order );
     103                    $paidcommission = ( isset( $calculateorder['totalcommission'] ) ? $calculateorder['totalcommission'] : 0 );
     104                    $meta_data = wcusage_update_ml_affiliate_parents(
     105                        $meta_data,
     106                        $coupon_user_id,
     107                        $order,
     108                        $lifetimeaffiliate,
     109                        $paidcommission
     110                    );
    104111                } elseif ( $affiliatereferrer ) {
    105112                    $calculateorder = wcusage_calculate_order_data(
     
    137144                    $coupon_info = wcusage_get_coupon_info( $affiliatereferrer );
    138145                    $coupon_user_id = $coupon_info[1];
     146                    $paidcommission = ( isset( $calculateorder['totalcommission'] ) ? $calculateorder['totalcommission'] : 0 );
    139147                    $user_parents = get_user_meta( $coupon_user_id, 'wcu_ml_affiliate_parents', true );
    140                     $meta_data = wcusage_update_ml_affiliate_parents( $meta_data, $coupon_user_id, $order );
     148                    $meta_data = wcusage_update_ml_affiliate_parents(
     149                        $meta_data,
     150                        $coupon_user_id,
     151                        $order,
     152                        $affiliatereferrer,
     153                        $paidcommission
     154                    );
    141155                } else {
    142156                    // Coupons
     
    182196                            $coupon_info = wcusage_get_coupon_info( $coupon_code );
    183197                            $coupon_user_id = $coupon_info[1];
    184                             $meta_data = wcusage_update_ml_affiliate_parents( $meta_data, $coupon_user_id, $order );
     198                            $paidcommission = ( isset( $calculateorder['totalcommission'] ) ? $calculateorder['totalcommission'] : 0 );
     199                            $meta_data = wcusage_update_ml_affiliate_parents(
     200                                $meta_data,
     201                                $coupon_user_id,
     202                                $order,
     203                                $coupon_code,
     204                                $paidcommission
     205                            );
    185206                        }
    186207                    }
     
    218239    3
    219240);
    220 /*
    221  * On order completed delete wcusage_all_updated
    222  *
    223  * @param int $order_id
    224  *
    225  */
    226 function wcusage_on_new_order_delete_all_updated_meta(  $order_id  ) {
    227     wcusage_delete_order_meta( $order_id, 'wcusage_all_updated' );
    228 }
    229 
    230 add_action(
    231     'woocommerce_order_status_completed',
    232     'wcusage_on_new_order_delete_all_updated_meta',
    233     10,
    234     1
    235 );
     241// NOTE: The wcusage_all_updated flag is intentionally NOT deleted on order completion.
     242// Deleting it on 'woocommerce_order_status_completed' caused double-counting because
     243// woocommerce_order_status_changed fires after that hook, sees no flag, and re-adds
     244// the order to the all-time stats a second time. The flag is only cleared by the
     245// $remove_order path when an order moves from a counted status to a non-counted one.
    236246/* Update MLA Parents When New Order Placed */
    237 function wcusage_update_ml_affiliate_parents(  $meta_data, $coupon_user_id, $order  ) {
     247function wcusage_update_ml_affiliate_parents(
     248    $meta_data,
     249    $coupon_user_id,
     250    $order,
     251    $coupon_code = '',
     252    $paidcommission = 0
     253) {
    238254}
    239255
  • woo-coupon-usage/trunk/inc/functions/functions-refund.php

    r2994178 r3469742  
    7070  wcusage_delete_order_meta($order_id, 'wcusage_commission_summary');
    7171  wcusage_delete_order_meta($order_id, 'wcusage_total_commission');
     72  wcusage_delete_order_meta($order_id, 'wcu_mla_commission');
    7273
    7374}
  • woo-coupon-usage/trunk/inc/functions/functions-urls.php

    r3462634 r3469742  
    4040
    4141    if ( headers_sent() && ! $httponly && ! wp_doing_ajax() ) {
    42         $script = "var date = new Date(" . ($expire * 1000) . ");
    43         var expires = '; expires=' + date.toUTCString();
    44         document.cookie = '" . $name . "=" . $value . "' + expires + '; path=" . $path . "; domain=" . $domain . "; samesite=Lax" . ($secure ? "; secure" : "") . "';";
    45         wp_add_inline_script( 'jquery-core', $script );
     42        // Headers already sent - use JavaScript fallback to set cookies.
     43        // Outputting script directly in footer instead of using wp_add_inline_script which won't work at this timing.
     44        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
     45        // phpcs:ignore WordPress.Security.EscapeOutput.UnsafePrintingFunction
     46        add_action(
     47            'wp_footer',
     48            function() use ( $name, $value, $expire, $path, $domain, $secure ) {
     49                ?>
     50                <script type="text/javascript">
     51                (function() {
     52                    var date = new Date(<?php echo absint( $expire * 1000 ); ?>);
     53                    var expires = '; expires=' + date.toUTCString();
     54                    document.cookie = '<?php echo esc_js( $name ); ?>=<?php echo esc_js( $value ); ?>' + expires + '; path=<?php echo esc_js( $path ); ?>; domain=<?php echo esc_js( $domain ); ?>; samesite=Lax<?php echo $secure ? '; secure' : ''; ?>';
     55                })();
     56                </script>
     57                <?php
     58            },
     59            999
     60        );
    4661    } elseif ( PHP_VERSION_ID < 70300 ) {
    4762        setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly );
  • woo-coupon-usage/trunk/inc/functions/functions-user-coupons.php

    r3462634 r3469742  
    339339                    if ( $wcu_text_unpaid_commission_confirm ) {
    340340                        if ( isset( $_POST['wcu_text_unpaid_commission'] ) ) {
    341                             $wcu_text_unpaid_commission = sanitize_text_field( $_POST['wcu_text_unpaid_commission'] );
     341                            $wcu_text_unpaid_commission = floatval( wp_unslash( $_POST['wcu_text_unpaid_commission'] ) );
    342342                            update_post_meta( $post_id, 'wcu_text_unpaid_commission', $wcu_text_unpaid_commission );
    343343                        }
    344344                        if ( isset( $_POST['wcu_text_pending_payment_commission'] ) ) {
    345                             $wcu_text_pending_payment_commission = sanitize_text_field( $_POST['wcu_text_pending_payment_commission'] );
     345                            $wcu_text_pending_payment_commission = floatval( wp_unslash( $_POST['wcu_text_pending_payment_commission'] ) );
    346346                            update_post_meta( $post_id, 'wcu_text_pending_payment_commission', $wcu_text_pending_payment_commission );
     347                        }
     348                        if ( isset( $_POST['wcu_text_pending_order_commission'] ) ) {
     349                            $wcu_text_pending_order_commission = floatval( wp_unslash( $_POST['wcu_text_pending_order_commission'] ) );
     350                            update_post_meta( $post_id, 'wcu_text_pending_order_commission', $wcu_text_pending_order_commission );
    347351                        }
    348352                        update_post_meta( $post_id, 'wcu_text_unpaid_commission_confirm', 0 );
  • woo-coupon-usage/trunk/inc/registration/class-registrations-list-table.php

    r3454163 r3469742  
    162162                    return '<span class="dashicons dashicons-warning" style="color: orange;"></span> ' . esc_html__( 'Pending', 'woo-coupon-usage' );
    163163                }
     164          if($status == "parent_approved") {
     165            $parent_approver_id = get_user_meta( absint($item['userid']), 'wcu_mla_parent_approver_id', true );
     166            $parent_approver_name = '';
     167            if ( $parent_approver_id ) {
     168              $parent_approver = get_userdata( absint($parent_approver_id) );
     169              $parent_approver_name = $parent_approver ? ' (' . esc_html( $parent_approver->user_login ) . ')' : '';
     170            }
     171            return '<span class="dashicons dashicons-thumbs-up" style="color: #2271b1;"></span> ' . esc_html__( 'MLA Parent Approved', 'woo-coupon-usage' ) . esc_html( $parent_approver_name );
     172          }
    164173          if($status == "declined") {
    165174                    return '<span class="dashicons dashicons-dismiss" style="color: red;"></span> ' . esc_html__( 'Declined', 'woo-coupon-usage' );
     
    176185                    ?>
    177186
    178           <?php if($status == "pending") { ?>
     187          <?php if($status == "pending" || $status == "parent_approved") { ?>
    179188
    180189                    <form method="post" id="submitregister">
     
    183192
    184193            <?php wp_nonce_field( 'admin_affiliate_register_form' ); ?>
     194
     195            <?php if ( $status === 'parent_approved' ) : ?>
     196              <p style="color: #2271b1; font-size: 12px; margin: 0 0 4px 0;"><span class="dashicons dashicons-thumbs-up" style="font-size:14px;vertical-align:middle;"></span> <?php echo esc_html__( 'MLA parent has approved this application.', 'woo-coupon-usage' ); ?></p>
     197            <?php endif; ?>
    185198
    186199                    <button type="submit" name="submitregisteraccept" class="payout-action payout-action-accepted" title="<?php echo esc_html__( 'Accept Application', 'woo-coupon-usage' ); ?>">
  • woo-coupon-usage/trunk/inc/registration/registration-admin.php

    r3462634 r3469742  
    451451    ?>"><?php
    452452    echo esc_html__( 'Pending', 'woo-coupon-usage' );
     453    ?></a>
     454    &#xb7;
     455    <a href="<?php
     456    echo esc_url( admin_url( 'admin.php?page=wcusage_registrations&status=parent_approved' ) );
     457    ?>" style="<?php
     458    if ( $statussearch == 'parent_approved' ) {
     459        ?>font-weight: bold;<?php
     460    }
     461    ?>"><?php
     462    echo esc_html__( 'MLA Parent Approved', 'woo-coupon-usage' );
    453463    ?></a>
    454464    &#xb7;
  • woo-coupon-usage/trunk/inc/registration/registration-ajax.php

    r3438708 r3469742  
    134134        ) );
    135135        error_log( 'CA: Failed to store registration data for user ID: ' . $userid );
     136    }
     137    // MLA: Set parent affiliate relationship if the user registered via an MLA invite link.
     138    $wcusage_field_mla_enable = wcusage_get_setting_value( 'wcusage_field_mla_enable', '0' );
     139    if ( $wcusage_field_mla_enable ) {
     140        $mla_cookie = wcusage_get_cookie_value( 'wcusage_referral_mla' );
     141        $mla_cookie = str_replace( '%20', ' ', $mla_cookie );
     142        $mla_referral = ( function_exists( 'wcusage_get_mla_referral_value' ) ? wcusage_get_mla_referral_value() : '' );
     143        $mla_username = ( $mla_referral ? $mla_referral : $mla_cookie );
     144        if ( $mla_username ) {
     145            $mla_user = get_user_by( 'login', $mla_username );
     146            $this_user = get_user_by( 'id', $userid );
     147            if ( $mla_user && $this_user ) {
     148                if ( function_exists( 'wcusage_mla_add_parent_to_user' ) ) {
     149                    wcusage_mla_add_parent_to_user( $mla_user->ID, $this_user->ID );
     150                }
     151                if ( function_exists( 'wcusage_install_mlainvite_data' ) ) {
     152                    wcusage_install_mlainvite_data(
     153                        $mla_user->ID,
     154                        $this_user->user_email,
     155                        'pending',
     156                        1
     157                    );
     158                }
     159                // Notify MLA parent about the new sub-affiliate registration.
     160                do_action(
     161                    'wcusage_hook_mla_sub_registration_new',
     162                    $mla_user->ID,
     163                    $this_user->ID,
     164                    $couponcode
     165                );
     166            }
     167        }
    136168    }
    137169    // Determine whether this submission should be auto-accepted.
  • woo-coupon-usage/trunk/inc/registration/registration-form.php

    r3462634 r3469742  
    472472                        if ( $enable_captcha == "1" && !empty( $wcusage_registration_recaptcha_key ) && $wcusage_registration_recaptcha_key != "" ) {
    473473                            ?>
    474             <p>
    475474            <div class="captcha_wrapper">
    476475                <div class="g-recaptcha" data-sitekey="<?php
     
    478477                            ?>"></div>
    479478            </div>
    480             </p>
    481479            <?php
    482480                        }
     
    487485                        if ( $enable_captcha == "2" && !empty( $wcusage_registration_turnstile_key ) && $wcusage_registration_turnstile_key != "" ) {
    488486                            ?>
    489             <p>
    490487            <div class="captcha_wrapper">
    491488                <div class="cf-turnstile" data-sitekey="<?php
     
    493490                            ?>"></div>
    494491            </div>
    495             </p>
    496492            <?php
    497493                        }
     
    836832                    $thiscoupon = false;
    837833                }
    838                 if ( $count <= 0 && !$thiscoupon->is_valid() ) {
     834                if ( $count <= 0 && (!$thiscoupon || !$thiscoupon->is_valid()) ) {
    839835                    if ( !isset( $_SESSION['wcu_registration_token'] ) || is_admin() ) {
    840836                        // Add User If Admin Post
     
    903899                                );
    904900                            }
     901                            // Notify MLA parent about the new sub-affiliate registration.
     902                            do_action(
     903                                'wcusage_hook_mla_sub_registration_new',
     904                                $mla_user->ID,
     905                                $this_user->ID,
     906                                $couponcode
     907                            );
    905908                        }
    906909                        $alreadyexists = 0;
  • woo-coupon-usage/trunk/inc/widget/js/floating-widget-popup.js

    r3321450 r3469742  
    3535            }
    3636        }
     37    }
     38   
     39    // Load captcha script dynamically for registration form in the widget
     40    function loadCaptchaScript(captchaData) {
     41        if (!captchaData || !captchaData.type) {
     42            return;
     43        }
     44       
     45        if (captchaData.type === 'recaptcha') {
     46            // Check if reCAPTCHA script is already loaded
     47            if (typeof grecaptcha !== 'undefined') {
     48                // Script already loaded, just render the widget
     49                renderRecaptcha();
     50                return;
     51            }
     52            var script = document.createElement('script');
     53            script.src = 'https://www.google.com/recaptcha/api.js?onload=wcusageRecaptchaCallback&render=explicit';
     54            script.async = true;
     55            script.defer = true;
     56            window.wcusageRecaptchaCallback = function() {
     57                renderRecaptcha();
     58            };
     59            document.head.appendChild(script);
     60        } else if (captchaData.type === 'turnstile') {
     61            // Check if Turnstile script is already loaded
     62            if (typeof turnstile !== 'undefined') {
     63                // Script already loaded, just render the widget
     64                renderTurnstile(captchaData.site_key);
     65                return;
     66            }
     67            var script = document.createElement('script');
     68            script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?onload=wcusageTurnstileCallback&render=explicit';
     69            script.async = true;
     70            script.defer = true;
     71            window.wcusageTurnstileCallback = function() {
     72                renderTurnstile(captchaData.site_key);
     73            };
     74            document.head.appendChild(script);
     75        }
     76    }
     77   
     78    // Render reCAPTCHA widgets in the popup
     79    function renderRecaptcha() {
     80        if (typeof grecaptcha === 'undefined') {
     81            return;
     82        }
     83        $('.wcusage-floating-popup .g-recaptcha').each(function() {
     84            var el = this;
     85            // Only render if not already rendered
     86            if ($(el).children().length === 0) {
     87                grecaptcha.render(el, {
     88                    'sitekey': $(el).data('sitekey')
     89                });
     90            }
     91        });
     92    }
     93   
     94    // Render Turnstile widgets in the popup
     95    function renderTurnstile(siteKey) {
     96        if (typeof turnstile === 'undefined') {
     97            return;
     98        }
     99        $('.wcusage-floating-popup .cf-turnstile').each(function() {
     100            var el = this;
     101            // Only render if not already rendered
     102            if ($(el).children().length === 0) {
     103                turnstile.render(el, {
     104                    sitekey: siteKey || $(el).data('sitekey')
     105                });
     106            }
     107        });
    37108    }
    38109   
     
    75146                    // Initialize premium features if available
    76147                    initializePremiumFeatures();
     148                   
     149                    // Load captcha scripts if registration form is displayed
     150                    if (response.data.captcha) {
     151                        loadCaptchaScript(response.data.captcha);
     152                    }
    77153                } else {
    78154                    var errorMsg = response && response.data ? response.data : wcusage_floating_widget.error_text;
  • woo-coupon-usage/trunk/inc/widget/widget-ajax.php

    r3321450 r3469742  
    99 */
    1010
     11/**
     12 * Get captcha configuration data for the floating widget.
     13 * Returns the captcha type and site key so the popup JS can load the appropriate script dynamically.
     14 */
     15function wcusage_get_widget_captcha_data() {
     16    $enable_captcha = wcusage_get_setting_value('wcusage_registration_enable_captcha', '');
     17    if ($enable_captcha == '1') {
     18        $site_key = wcusage_get_setting_value('wcusage_registration_recaptcha_key', '');
     19        if (!empty($site_key)) {
     20            return array(
     21                'type' => 'recaptcha',
     22                'site_key' => $site_key
     23            );
     24        }
     25    } elseif ($enable_captcha == '2') {
     26        $site_key = wcusage_get_setting_value('wcusage_registration_turnstile_key', '');
     27        if (!empty($site_key)) {
     28            return array(
     29                'type' => 'turnstile',
     30                'site_key' => $site_key
     31            );
     32        }
     33    }
     34    return null;
     35}
     36
    1137// AJAX handler for popup content (updated to include settings)
    1238add_action('wp_ajax_wcusage_floating_widget_content', 'wcusage_floating_widget_ajax_content');
     
    3258            // Show registration form for non-logged in users
    3359            $content = wcusage_widget_registration_form($settings);
    34             wp_send_json_success(array(
     60            $response_data = array(
    3561                'content' => $content,
    3662                'settings' => $settings
    37             ));
     63            );
     64            // Include captcha data so the popup JS can load scripts dynamically
     65            $captcha_data = wcusage_get_widget_captcha_data();
     66            if ($captcha_data) {
     67                $response_data['captcha'] = $captcha_data;
     68            }
     69            wp_send_json_success($response_data);
    3870            return;
    3971        }
     
    5082            // Show registration form for logged-in users without coupons
    5183            $content = wcusage_widget_registration_form($settings);
    52             wp_send_json_success(array(
     84            $response_data = array(
    5385                'content' => $content,
    5486                'settings' => $settings
    55             ));
     87            );
     88            // Include captcha data so the popup JS can load scripts dynamically
     89            $captcha_data = wcusage_get_widget_captcha_data();
     90            if ($captcha_data) {
     91                $response_data['captcha'] = $captcha_data;
     92            }
     93            wp_send_json_success($response_data);
    5694            return;
    5795        }
  • woo-coupon-usage/trunk/js/admin-coupons.js

    r3462634 r3469742  
    139139            wcu_text_coupon_commission_fixed_product: $row.find('#wcu_text_coupon_commission_fixed_product_' + couponId).val(),
    140140            wcu_text_unpaid_commission: $row.find('#wcu_text_unpaid_commission_' + couponId).val(),
    141             wcu_text_pending_payment_commission: $row.find('#wcu_text_pending_payment_commission_' + couponId).val()
     141            wcu_text_pending_payment_commission: $row.find('#wcu_text_pending_payment_commission_' + couponId).val(),
     142            wcu_text_pending_order_commission: $row.find('#wcu_text_pending_order_commission_' + couponId).val() || '0'
    142143        };
    143144
  • woo-coupon-usage/trunk/js/admin-view-affiliate.js

    r3358053 r3469742  
    44
    55jQuery(document).ready(function($) {
     6    // Mobile tab dropdown — inject <select> before the tab bar
     7    (function() {
     8        var $tabs = $('.wcusage-tabs');
     9        if (!$tabs.length) { return; }
     10
     11        // Build the select element from the existing nav-tab links
     12        var $select = $('<select class="wcusage-tab-select" aria-label="Navigate tabs"></select>');
     13        $tabs.find('.nav-tab').each(function() {
     14            var $tab  = $(this);
     15            var href  = $tab.attr('href');
     16            var label = $tab.text().trim();
     17            var $opt  = $('<option></option>').val(href).text(label);
     18            if ($tab.hasClass('nav-tab-active')) { $opt.prop('selected', true); }
     19            if ($tab.hasClass('wcusage-tab-disabled')) { $opt.prop('disabled', true); }
     20            $select.append($opt);
     21        });
     22
     23        var $wrapper = $('<div class="wcusage-tab-select-wrapper"></div>').append($select);
     24        $tabs.before($wrapper);
     25
     26        $select.on('change', function() {
     27            var href  = $(this).val();
     28            var $link = $tabs.find('.nav-tab[href="' + href + '"]');
     29            if ($link.length) { $link.trigger('click'); }
     30        });
     31    })();
     32
    633    // Tab switching functionality
    734    $('.wcusage-tabs .nav-tab').on('click', function(e) {
     
    2552            try { window.WCU_MLA_draw(); } catch(e) {}
    2653        }
     54
     55        // Sync mobile dropdown
     56        $('.wcusage-tab-select').val('#' + tabId);
    2757
    2858        // Update URL without page reload
     
    4373        $('.wcusage-tab-content > div').removeClass('active');
    4474        $('#tab-' + tab).addClass('active');
     75
     76        // Sync mobile dropdown
     77        $('.wcusage-tab-select').val('#tab-' + tab);
    4578
    4679        // If MLA tab is now active, ensure chart draws
     
    276309    });
    277310});
     311
  • woo-coupon-usage/trunk/readme.txt

    r3462682 r3469742  
    66Requires PHP: 7.0
    77Tested up to: 6.9
    8 Stable tag: 7.4.0
     8Stable tag: 7.5.0
    99License: GPLv3
    1010License URI: https://www.gnu.org/licenses/gpl-3.0.html
     
    276276== Changelog ==
    277277
     278= Version 7.5.0 - 25th February 2026 =
     279- New: (PRO) Added a new option to set per-group and per-user MLA commission rates, which will override the default MLA commission rates for that user.
     280- New: (PRO) Added a new option to display a "Rates" tab on the MLA affiliate dashboard, which will show the commission rates for each tier of their MLA network, and also show any custom rates that have been set for that user.
     281- New: (PRO) Added a new "MLA Users" admin page listing all users that are part of the multi-level affiliate system, with their affiliate details and stats.
     282- New: (PRO) On the "View Affiliate" page, in the "MLA" tab, added lots more details and statistics about the affiliates sub-affiliates, including their total stats, recent orders, and more. Also added a way to easily remove sub-affiliates or add new sub-affiliates to the affiliate from this tab.
     283- New: (PRO) If QR codes are enabled, it will now also show the QR code generator for the MLA invite referral links on the MLA dashboard.
     284- New: (PRO) Added an option to show a "Sub-Affiliate Registrations" section on the MLA dashboard, that allows the parent affiliate to view and manage the affiliate applications from their sub-affiliates. They will also receive email notifications when they get new sub-affiliate applications, and can approve/reject them from the MLA dashboard.
     285- New: (PRO) On the affiliate page, if the payout information totals (processing, unpaid, pending, paid) do not match the "total commission", added a "unaccounted commission" row with a message explaining why that may be the case.
     286- Improvement: (PRO) Added extra columns to the Affiliate Groups admin page, showing each group's commission rates, assigned template coupon, and enabled payout methods.
     287- Improvement: (PRO) Added a field when editing coupons to modify the "processing commission" amount.
     288- Improvement: Added filters to the admin activity log page.
     289- Improvement: (PRO) On the MLA affiliate dashboard, added pagination to the "Your latest invites" section.
     290- Improvement: (PRO) Renamed "Pending Commission" to "Processing Commission" across the plugin for less confusion with the "Pending" status for payouts.
     291- Tweak: (PRO) On the "View Affiliate" page, the "Payouts" tab and the "Unpaid" column in the coupons table are now only shown when the payout tracking setting is enabled.
     292- Tweak: MLA unpaid commission changes are now added to the activity log.
     293- Tweak: Updated the JS method for setting cookies when headers have already been sent, to be more reliable in some cases.
     294- Tweak: reCAPTCHA and Turnstile now load on the floating widget registration form if enabled.
     295- Tweak: Made some design improvements on mobile to the view affiliate page.
     296- Tweak: Added a search field to the "PRO Modules" settings tab.
     297- Fix: Fixed an issue where the affiliate registration form would incorrectly show a "coupon already exists" error when submitting with a new coupon code, due to a compatibility issue with newer versions of WooCommerce.
     298- Fix: Fixed some issues with per-group fixed commission not showing visually in some cases.
     299- Fix: Fixed Turnstile rendering twice in some cases.
     300- Fix: Fixed PHP warnings for undefined variables in the mobile dropdown menu section of the affiliate dashboard.
     301- Fix: Fixed a bug where referred orders could be counted twice in the coupon all-time statistics.
     302- Fix: (PRO) Fixed payout request button not working in some cases when invoice uploads are not enabled, due to a missing JavaScript validation function.
     303- Fix: (PRO) Fixed processing commission being added twice for some orders due to an HPOS compatibility issue.
     304- Fix: Potential fix for issues with the WP Compress plugin.
     305- Fix: (PRO) Fixed a bug where affiliate bonuses with a "Once Per Month" (or other period) trigger could become permanently locked if the reward date meta was missing, preventing the bonus from ever being awarded again.
     306- Fix: (PRO) Fixed a bug where removing all affiliate group restrictions from a bonus would not clear the saved restriction, causing affiliates to be silently excluded from earning the bonus.
     307
    278308= Version 7.4.0 - 14th February 2026 =
    279309- New: Added new "referral welcome popups" functionality.
  • woo-coupon-usage/trunk/woo-coupon-usage.php

    r3462634 r3469742  
    55* Plugin URI: https://couponaffiliates.com
    66* Description: The most powerful affiliate plugin for WooCommerce. Track commission, generate referral URLs, assign affiliate coupons, and display detailed stats.
    7 * Version: 7.4.0
     7* Version: 7.5.0
    88* Author: Elliot Sowersby, RelyWP
    99* Author URI: https://couponaffiliates.com/
Note: See TracChangeset for help on using the changeset viewer.