Changeset 3469742
- Timestamp:
- 02/25/2026 09:46:47 PM (5 weeks ago)
- Location:
- woo-coupon-usage/trunk
- Files:
-
- 1 added
- 39 edited
-
css/admin-affiliate-users-table.css (modified) (3 diffs)
-
css/admin-style.css (modified) (9 diffs)
-
css/admin-view-affiliate.css (modified) (5 diffs)
-
css/style.css (modified) (1 diff)
-
inc/admin/admin-activity.php (modified) (3 diffs)
-
inc/admin/admin-dashboard.php (modified) (1 diff)
-
inc/admin/admin-menu.php (modified) (1 diff)
-
inc/admin/admin-orders-box.php (modified) (2 diffs)
-
inc/admin/admin-orders-list.php (modified) (1 diff)
-
inc/admin/admin-page.php (modified) (1 diff)
-
inc/admin/admin-pro-details.php (modified) (4 diffs)
-
inc/admin/admin-view-affiliate.php (modified) (22 diffs)
-
inc/admin/class-activity-list-table.php (modified) (3 diffs)
-
inc/admin/class-coupons-table.php (modified) (4 diffs)
-
inc/admin/class-mla-users-table.php (added)
-
inc/admin/settings/admin-options.php (modified) (2 diffs)
-
inc/admin/settings/options-notifications.php (modified) (2 diffs)
-
inc/admin/settings/options-payouts.php (modified) (1 diff)
-
inc/admin/tools/quick-edit-coupon.php (modified) (1 diff)
-
inc/dashboard/tab-latest-orders.php (modified) (3 diffs)
-
inc/functions/functions-activity.php (modified) (5 diffs)
-
inc/functions/functions-all-time.php (modified) (1 diff)
-
inc/functions/functions-calculate-order.php (modified) (6 diffs)
-
inc/functions/functions-coupon-orders.php (modified) (1 diff)
-
inc/functions/functions-dashboard.php (modified) (1 diff)
-
inc/functions/functions-general.php (modified) (2 diffs)
-
inc/functions/functions-new-order.php (modified) (4 diffs)
-
inc/functions/functions-refund.php (modified) (1 diff)
-
inc/functions/functions-urls.php (modified) (1 diff)
-
inc/functions/functions-user-coupons.php (modified) (1 diff)
-
inc/registration/class-registrations-list-table.php (modified) (3 diffs)
-
inc/registration/registration-admin.php (modified) (1 diff)
-
inc/registration/registration-ajax.php (modified) (1 diff)
-
inc/registration/registration-form.php (modified) (6 diffs)
-
inc/widget/js/floating-widget-popup.js (modified) (2 diffs)
-
inc/widget/widget-ajax.php (modified) (3 diffs)
-
js/admin-coupons.js (modified) (1 diff)
-
js/admin-view-affiliate.js (modified) (4 diffs)
-
readme.txt (modified) (2 diffs)
-
woo-coupon-usage.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
woo-coupon-usage/trunk/css/admin-affiliate-users-table.css
r3462634 r3469742 22 22 } 23 23 .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); 29 31 } 30 32 .wcusage-idcell { … … 165 167 vertical-align: middle; 166 168 } 169 .wp-list-table.mlausers tbody td, 170 .wp-list-table.mlausers thead th { 171 vertical-align: middle !important; 172 } 167 173 /* On smaller screens, stack avatar above the ID */ 168 174 @media screen and (max-width: 1500px) { … … 175 181 } 176 182 } 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 } 203 th.column-mla_sub_affiliates, 204 th.column-mla_payouts, 205 th.column-mla_tiers, 206 th.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 1634 1634 .wp-list-table.referrals th, 1635 1635 .wp-list-table.affiliateusers th, 1636 .wp-list-table.mlausers th, 1636 1637 .wp-list-table.affiliatecoupons th { 1637 1638 text-align: center; … … 1644 1645 .wp-list-table.referrals th a, 1645 1646 .wp-list-table.affiliateusers th a, 1647 .wp-list-table.mlausers th a, 1646 1648 .wp-list-table.affiliatecoupons td a { 1647 1649 display: inline-block; … … 1670 1672 .wp-list-table.referrals tr:hover, 1671 1673 .wp-list-table.affiliateusers tr:hover, 1674 .wp-list-table.mlausers tr:hover, 1672 1675 .wp-list-table.affiliatecoupons tr:hover { 1673 1676 background: #f4fcfc; … … 1681 1684 .wp-list-table.referrals td, 1682 1685 .wp-list-table.affiliateusers td, .wp-list-table.affiliateusers th, 1686 .wp-list-table.mlausers td, .wp-list-table.mlausers th, 1683 1687 .wp-list-table.affiliatecoupons td { 1684 1688 width: auto; … … 1691 1695 .wp-list-table.referrals tr td, 1692 1696 .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, 1693 1698 .wp-list-table.registration tr td { 1694 1699 border-bottom: 1px solid #cfcfcf; … … 1696 1701 } 1697 1702 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 1698 1713 .wp-list-table.registration .action1.column-action1 { 1699 1714 padding: 10px; … … 1702 1717 .admin_page_wcusage_activity .column-id, .payout .column-id { 1703 1718 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 } 1704 1748 } 1705 1749 … … 1750 1794 margin: 15px 0; 1751 1795 } 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 } 1752 1840 1753 1841 .pro-details { … … 3067 3155 3068 3156 .wcu-loading-loader { 3157 margin: 25px auto 0 auto; 3069 3158 width: 40px; 3070 3159 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; 3072 3220 } 3073 3221 -
woo-coupon-usage/trunk/css/admin-view-affiliate.css
r3450056 r3469742 611 611 } 612 612 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 613 633 /* Ensure all tables inside tab content fill container width on large screens */ 614 634 .wcusage-tab-content table.wp-list-table { width: 100%; } … … 1025 1045 background: #005a87; 1026 1046 border-color: #005a87; 1047 color: #fff; 1027 1048 transform: translateY(-1px); 1028 1049 box-shadow: 0 2px 6px rgba(0,0,0,0.3); … … 1109 1130 } 1110 1131 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 1111 1184 /* User Avatar Styling */ 1112 1185 .wcusage-user-avatar { … … 1144 1217 } 1145 1218 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 1146 1257 /* --- Mobile overflow fixes: ensure tabs and tables can scroll horizontally --- */ 1147 1258 /* Tabs: always allow horizontal scroll if needed */ … … 1239 1350 border-radius: 3px; 1240 1351 } 1352 -
woo-coupon-usage/trunk/css/style.css
r3462634 r3469742 1635 1635 1636 1636 .wcu-mla-network-button { 1637 margin: 2px 0 7px 0 !important; 1637 font-size: 12px !important; 1638 margin: 4px 0 7px 0 !important; 1638 1639 padding: 2px 5px 2px 5px !important; 1639 1640 text-decoration: none !important; -
woo-coupon-usage/trunk/inc/admin/admin-activity.php
r3415640 r3469742 13 13 <link rel="stylesheet" href="<?php echo esc_url(WCUSAGE_UNIQUE_PLUGIN_URL) .'fonts/font-awesome/css/all.min.css'; ?>" crossorigin="anonymous"> 14 14 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 18 15 <!-- Output Page --> 19 16 <div class="wrap plugin-settings"> … … 22 19 23 20 <h1><?php echo esc_html( get_admin_page_title() ); ?></h1> 21 22 <br/><br/> 24 23 25 24 <?php … … 49 48 50 49 <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> 53 54 </div> 54 55 -
woo-coupon-usage/trunk/inc/admin/admin-dashboard.php
r3462634 r3469742 374 374 } 375 375 $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), 376 377 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), 377 378 array('label' => 'Roadmap', 'url' => 'https://roadmap.couponaffiliates.com/roadmap', 'icon' => 'fa-solid fa-list', 'external' => true), 378 379 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),381 380 ); 382 381 ?> -
woo-coupon-usage/trunk/inc/admin/admin-menu.php
r3454163 r3469742 252 252 253 253 add_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 255 255 function 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 ) ) { 257 257 ?> 258 258 <script type="text/javascript"> -
woo-coupon-usage/trunk/inc/admin/admin-orders-box.php
r3438708 r3469742 238 238 delete_post_meta( $order_id, 'wcusage_stats' ); 239 239 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' ); 240 242 $url = remove_query_arg( 'refresh_stats' ); 241 243 wp_safe_redirect( $url ); … … 286 288 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>"; 287 289 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 } 309 341 } 310 342 } -
woo-coupon-usage/trunk/inc/admin/admin-orders-list.php
r3438708 r3469742 181 181 $coupon_id = wcusage_get_coupon_id( $coupon_code ); 182 182 // 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 ); 183 186 $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 ) { 185 191 if ( $update ) { 186 192 $order_data = wcusage_calculate_order_data( -
woo-coupon-usage/trunk/inc/admin/admin-page.php
r3454163 r3469742 668 668 } 669 669 670 /** 671 * MLA Users Admin Page 672 */ 673 function 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 28 28 }); 29 29 </script> 30 31 <div id="pro-details" class="pro-details">32 30 33 31 <?php if(!$ispro) { ?> … … 89 87 <?php } ?> 90 88 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> 92 92 93 93 <br/> 94 94 95 95 <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"> 96 105 97 106 <div style="flex-basis: 100%; height: 0;"></div> … … 671 680 </script> 672 681 682 <!-- Module Search Filter --> 683 <script> 684 jQuery(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 673 710 <!-- Break the flexbox --> 674 711 <div style="flex-basis: 100%; height: 0;"></div> … … 722 759 </script> 723 760 <?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))); ?>"> 725 762 726 763 <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 3 2 if ( !defined( 'ABSPATH' ) ) { 4 3 exit; … … 152 151 } 153 152 } 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' ); 155 if ( $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 } 154 179 // Handle individual delete actions (same options as Coupon Affiliate Users page) 155 180 if ( isset( $_POST['wcusage_delete_action'] ) && isset( $_POST['wcusage_user_id'] ) ) { … … 213 238 ?> 214 239 215 <!--- Font Awesome -->216 <link rel="stylesheet" href="<?php240 <!--- Font Awesome --> 241 <link rel="stylesheet" href="<?php 217 242 echo esc_url( WCUSAGE_UNIQUE_PLUGIN_URL ) . 'fonts/font-awesome/css/all.min.css'; 218 243 ?>" crossorigin="anonymous"> … … 267 292 ); 268 293 wp_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' ), 278 305 ) ); 279 306 ?> … … 328 355 style="margin-left: 15px; font-size: 12px; padding: 5px 10px;" target="_blank"> 329 356 <?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>357 echo 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> 333 360 </a> 361 <?php 362 $wcusage_tracking_enable = wcusage_get_setting_value( 'wcusage_field_tracking_enable', '0' ); 363 ?> 364 <?php 365 ?> 334 366 </h1> 335 336 <a href="<?php337 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 <?php342 echo esc_html__( 'Back to Affiliates', 'woo-coupon-usage' );343 ?>344 </a>345 367 346 368 <?php … … 348 370 $delete_nonce = wp_create_nonce( 'wcusage_delete_user_' . $user_id ); 349 371 ?> 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 374 echo 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 378 echo 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 352 383 echo esc_attr( $user_id ); 353 384 ?>" title="<?php 354 385 echo esc_attr__( 'Delete Options', 'woo-coupon-usage' ); 355 386 ?>"> 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="<?php387 <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 360 391 echo esc_attr( $user_id ); 361 392 ?>" data-nonce="<?php … … 364 395 echo esc_html__( 'Delete User', 'woo-coupon-usage' ); 365 396 ?></a> 366 <a href="#" class="wcusage-delete-option" data-action="delete_user_coupons" data-user-id="<?php397 <a href="#" class="wcusage-delete-option" data-action="delete_user_coupons" data-user-id="<?php 367 398 echo esc_attr( $user_id ); 368 399 ?>" data-nonce="<?php … … 371 402 echo esc_html__( 'Delete User & Coupons', 'woo-coupon-usage' ); 372 403 ?></a> 373 <a href="#" class="wcusage-delete-option" data-action="unassign_coupons" data-user-id="<?php404 <a href="#" class="wcusage-delete-option" data-action="unassign_coupons" data-user-id="<?php 374 405 echo esc_attr( $user_id ); 375 406 ?>" data-nonce="<?php … … 378 409 echo esc_html__( 'Unassign Coupons', 'woo-coupon-usage' ); 379 410 ?></a> 380 <a href="#" class="wcusage-delete-option" data-action="delete_coupons" data-user-id="<?php411 <a href="#" class="wcusage-delete-option" data-action="delete_coupons" data-user-id="<?php 381 412 echo esc_attr( $user_id ); 382 413 ?>" data-nonce="<?php … … 385 416 echo esc_html__( 'Delete Coupons', 'woo-coupon-usage' ); 386 417 ?></a> 418 </div> 387 419 </div> 388 420 </div> … … 407 439 <i class="fas fa-shopping-cart" style="margin-right: 8px;"></i> 408 440 <?php 409 echo esc_html__( 'Referr als', 'woo-coupon-usage' );441 echo esc_html__( 'Referred Orders', 'woo-coupon-usage' ); 410 442 ?> 411 443 </a> … … 477 509 <i class="fas fa-shopping-cart" style="color: #007cba; margin-right: 10px;"></i> 478 510 <?php 479 echo esc_html__( ' Latest Referrals', 'woo-coupon-usage' );511 echo esc_html__( 'Referred Orders', 'woo-coupon-usage' ); 480 512 ?> 481 513 </h3> … … 551 583 552 584 <!-- Payouts Tab --> 585 <?php 586 if ( $wcusage_tracking_enable ) { 587 ?> 553 588 <div id="tab-payouts" class="tab-content <?php 554 echo ( $current_tab === 'payouts' ? 'active' : '' );555 ?>">589 echo ( $current_tab === 'payouts' ? 'active' : '' ); 590 ?>"> 556 591 <h3 style="color: #23282d; font-size: 22px; font-weight: 600; margin-bottom: 25px; border-bottom: 2px solid #007cba; padding-bottom: 10px;"> 557 592 <i class="fas fa-dollar-sign" style="color: #007cba; margin-right: 10px;"></i> 558 593 <?php 559 echo esc_html__( 'Payout History', 'woo-coupon-usage' );560 ?>594 echo esc_html__( 'Payout History', 'woo-coupon-usage' ); 595 ?> 561 596 </h3> 562 597 <div class="wcusage-filters" id="wcusage-payouts-filters" style="margin: 0 0 15px; display:flex; gap:8px; align-items: center;"> 563 598 <label> 564 599 <?php 565 echo esc_html__( 'From', 'woo-coupon-usage' );566 ?>600 echo esc_html__( 'From', 'woo-coupon-usage' ); 601 ?> 567 602 <input type="date" id="payouts-start-date" /> 568 603 </label> 569 604 <label> 570 605 <?php 571 echo esc_html__( 'To', 'woo-coupon-usage' );572 ?>606 echo esc_html__( 'To', 'woo-coupon-usage' ); 607 ?> 573 608 <input type="date" id="payouts-end-date" /> 574 609 </label> 575 610 <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> 578 613 </div> 579 614 <div id="wcusage-payouts-table-container"> 580 615 <?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 ?> 589 624 </div> 590 625 </div> 626 <?php 627 } 628 ?> 591 629 592 630 <!-- Activity Tab --> … … 633 671 634 672 <?php 635 if ( $wcusage_field_mla_enable && $wcusage_premium_active && function_exists( 'wcusage_get_ml_sub_affiliates' ) && function_exists( 'wcusage_get_network_chart_item' ) ) {673 if ( 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' ) ) { 636 674 ?> 637 675 <!-- MLA Tab --> … … 639 677 echo ( $current_tab === 'mla' ? 'active' : '' ); 640 678 ?>"> 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> 643 723 <?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 } 645 737 ?> 646 738 </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 652 983 } 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' ) ) { 653 1036 $network_array = ''; 654 1037 // Root node (self) 655 1038 $network_array .= wcusage_get_network_chart_item( $user_id, $user_id, $user_id ); 656 1039 $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(); 662 1045 } 663 1046 $this_users_coupons = wcusage_get_users_coupons_ids( $this_user_id ); … … 665 1048 $coupon_ids[] = $this_users_coupon_id; 666 1049 } 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 ); 671 1054 // Link to top-most parent 672 1055 if ( !$super_affiliate ) { … … 677 1060 $network_array = rtrim( $network_array, ',' ); 678 1061 $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' ); 679 1064 $mla_network_text = wcusage_get_setting_value( 'wcusage_field_mla_network_text', '' ); 680 1065 if ( $mla_network_text ) { … … 682 1067 } 683 1068 ?> 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 --> 751 1148 <?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 754 1345 </div> 755 1346 <?php … … 1184 1775 <?php 1185 1776 $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' ); 1186 1778 ?> 1187 1779 <h3><?php … … 1642 2234 ?></td> 1643 2235 <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> 1646 2262 </tr> 1647 2263 <?php … … 2037 2653 // Get coupon title 2038 2654 $coupon_title = ''; 2039 if ( $payout->couponid ) { 2655 $is_mla_payout = empty( $payout->couponid ) || intval( $payout->couponid ) === 0; 2656 if ( !$is_mla_payout ) { 2040 2657 $coupon_title = get_the_title( $payout->couponid ); 2041 2658 } … … 2061 2678 echo esc_html( $payout->id ); 2062 2679 ?></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> 2066 2697 <td><?php 2067 2698 echo wcusage_format_price( $payout->amount ); -
woo-coupon-usage/trunk/inc/admin/class-activity-list-table.php
r3415640 r3469742 40 40 $user = get_userdata( $item[$column_name] ); 41 41 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>'; 43 43 } else { 44 44 return 'Guest'; … … 92 92 } 93 93 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 94 174 function prepare_items() { 95 175 96 global $wpdb; //This is used only if making any database queries176 global $wpdb; 97 177 98 178 $per_page = 100; … … 108 188 $table_name = $wpdb->prefix . 'wcusage_activity'; 109 189 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 112 286 } else { 113 $ sql = "SELECT * FROM $table_name ORDER BY id DESC"; // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter114 } 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 117 291 $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 122 297 123 298 $this->items = $data; 124 299 125 300 $this->set_pagination_args( array( 126 'total_items' => $total_items, //WE have to calculate the total number of items127 'per_page' => $per_page, //WE have to determine how many items to show on a page128 'total_pages' => ceil( $total_items/$per_page) //WE have to calculate the total number of pages301 'total_items' => $total_items, 302 'per_page' => $per_page, 303 'total_pages' => ceil( $total_items / $per_page ), 129 304 ) ); 130 305 -
woo-coupon-usage/trunk/inc/admin/class-coupons-table.php
r3462634 r3469742 784 784 function wcusage_save_coupon_data() { 785 785 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 } 786 791 787 792 $coupon_id = intval( $_POST['coupon_id'] ); … … 822 827 'wcu_text_unpaid_commission' => floatval( wp_unslash( $_POST['wcu_text_unpaid_commission'] ) ), 823 828 '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'] ) ), 824 830 ); 825 831 … … 838 844 if(!isset($_POST['wcu_text_pending_payment_commission']) || $_POST['wcu_text_pending_payment_commission'] == '') { 839 845 $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"; 840 849 } 841 850 … … 846 855 unset( $meta['wcu_text_unpaid_commission'] ); 847 856 unset( $meta['wcu_text_pending_payment_commission'] ); 857 unset( $meta['wcu_text_pending_order_commission'] ); 848 858 } 849 859 -
woo-coupon-usage/trunk/inc/admin/settings/admin-options.php
r3462634 r3469742 1660 1660 } 1661 1661 // 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 ) ) { 1663 1663 $css_path = WCUSAGE_UNIQUE_PLUGIN_PATH . 'css/admin-affiliate-users-table.css'; 1664 1664 $css_ver = ( file_exists( $css_path ) ? filemtime( $css_path ) : '1.0.0' ); … … 1668 1668 array(), 1669 1669 $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 1670 1678 ); 1671 1679 $js_path = WCUSAGE_UNIQUE_PLUGIN_PATH . 'js/admin-affiliate-users-table.js'; -
woo-coupon-usage/trunk/inc/admin/settings/options-notifications.php
r3454163 r3469742 479 479 480 480 <?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")); ?> 481 531 482 532 </div> … … 920 970 break; 921 971 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>"; 923 979 break; 924 980 case "custom-fields": -
woo-coupon-usage/trunk/inc/admin/settings/options-payouts.php
r3454163 r3469742 283 283 <br/><br/><hr/> 284 284 285 <h3 id="wcu-setting-header-payouts-scheduled"><span class="dashicons dashicons-admin-generic" style="margin-top: 2px;"></span> <?php echo esc_html__( 'P ending Commission', 'woo-coupon-usage' ); ?>:</h3>286 287 <p><?php echo esc_html__( 'P ending 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> 288 288 289 289 <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> 290 290 291 <p><?php echo esc_html__( 'The "P ending 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> 292 292 293 293 <br/> 294 294 295 <?php wcusage_setting_toggle_option('wcusage_field_payout_pending_enable', 1, esc_html__( 'Enable "P ending Commission" tracking.', 'woo-coupon-usage' ), '0px'); ?>296 <i><?php echo esc_html__( 'When enabled, "P ending 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/> 297 297 298 298 <br/><hr/> -
woo-coupon-usage/trunk/inc/admin/tools/quick-edit-coupon.php
r3454163 r3469742 135 135 </div> 136 136 </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; ?> 137 146 </div> 138 147 </div> -
woo-coupon-usage/trunk/inc/dashboard/tab-latest-orders.php
r3462634 r3469742 188 188 $wcusage_show_commission = 0; 189 189 } 190 // Always show commission column on MLA dashboard (it shows what the parent earned) 191 if ( $type == "mla" ) { 192 $wcusage_show_commission = 1; 193 } 190 194 $wcusage_show_orders_table_status_totals = wcusage_get_setting_value( 'wcusage_field_show_orders_table_status_totals', '1' ); 191 195 $option_coupon_orders = wcusage_get_setting_value( 'wcusage_field_orders', '15' ); … … 439 443 } 440 444 ?> 441 442 }443 445 444 446 } … … 755 757 $totalordersexcl = $calculateorder['totalordersexcl']; 756 758 $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 } 765 792 } 766 793 $combined_totalcommission += (float) $totalcommission; -
woo-coupon-usage/trunk/inc/functions/functions-activity.php
r3358053 r3469742 202 202 $event_message = "Unpaid commission removed from '".esc_html($coupon_name)."':" . " " . wp_kses_post($info); 203 203 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; 204 226 case 'manual_unpaid_commission_edit': 205 227 $coupon_info = wcusage_get_coupon_info_by_id($event_id); … … 211 233 $coupon_name = $coupon_info[3]; 212 234 $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); 213 240 break; 214 241 case 'manual_coupon_commission_edit': … … 279 306 'wcu_text_unpaid_commission' => 'manual_unpaid_commission_edit', 280 307 'wcu_text_pending_commission' => 'manual_pending_commission_edit', 308 'wcu_text_pending_order_commission' => 'manual_processing_commission_edit', 281 309 'wcu_text_coupon_commission' => 'manual_coupon_commission_edit', 282 310 'wcu_text_coupon_commission_fixed_order' => 'manual_coupon_commission_fixed_order_edit', … … 298 326 'wcu_text_unpaid_commission' => 'manual_unpaid_commission_edit', 299 327 'wcu_text_pending_commission' => 'manual_pending_commission_edit', 328 'wcu_text_pending_order_commission' => 'manual_processing_commission_edit', 300 329 'wcu_text_coupon_commission' => 'manual_coupon_commission_edit', 301 330 'wcu_text_coupon_commission_fixed_order' => 'manual_coupon_commission_fixed_order_edit', … … 317 346 if($meta_key == 'wcu_text_unpaid_commission' 318 347 || $meta_key == 'wcu_text_pending_commission' 348 || $meta_key == 'wcu_text_pending_order_commission' 319 349 || $meta_key == 'wcu_text_coupon_commission_fixed_order' 320 350 || $meta_key == 'wcu_text_coupon_commission_fixed_product') -
woo-coupon-usage/trunk/inc/functions/functions-all-time.php
r3462634 r3469742 546 546 547 547 <p class="wcu-loading-loader-subtext" style="text-align:center; margin-top: 8px;"><?php 548 echo esc_html__( "The page will rel aod automatically when it is complete.", "woo-coupon-usage" );548 echo esc_html__( "The page will reload automatically when it is complete.", "woo-coupon-usage" ); 549 549 ?></p> 550 550 -
woo-coupon-usage/trunk/inc/functions/functions-calculate-order.php
r3462634 r3469742 80 80 $never_update_commission_meta = wcusage_get_setting_value( 'wcusage_field_enable_never_update_commission_meta', '0' ); 81 81 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" ) { 83 83 if ( wcusage_order_meta( $order_id, $item ) ) { 84 84 return; … … 105 105 $never_update_commission_meta = wcusage_get_setting_value( 'wcusage_field_enable_never_update_commission_meta', '0' ); 106 106 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" ) { 108 108 if ( wcusage_order_meta( $order_id, $key ) ) { 109 109 continue; … … 352 352 wcusage_delete_order_meta( $orderid, 'wcusage_commission_summary' ); 353 353 wcusage_delete_order_meta( $orderid, 'wcusage_stats' ); 354 wcusage_delete_order_meta( $orderid, 'wcu_mla_commission' ); 354 355 } 355 356 $get_affstats = wcusage_order_meta( $orderid, 'wcusage_stats', true ); … … 1232 1233 } 1233 1234 } 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 } 1234 1244 if ( $save_order_commission_meta ) { 1235 1245 $meta_data['wcusage_commission_summary'] = $commission_summary; … … 1247 1257 wcusage_delete_order_meta( $orderid, 'wcusage_product_commission' ); 1248 1258 } 1259 if ( !$never_update_commission_meta ) { 1260 wcusage_delete_order_meta( $orderid, 'wcusage_fixed_order_commission' ); 1261 } 1249 1262 } 1250 1263 } else { 1251 1264 $totalcommission = wcusage_order_meta( $orderid, 'wcusage_total_commission', true ); 1252 1265 $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 } 1253 1270 $commission_summary = wcusage_order_meta( $orderid, 'wcusage_commission_summary', true ); 1254 1271 } … … 1278 1295 if ( $current_fixed_product_commission_total ) { 1279 1296 $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; 1280 1301 } 1281 1302 if ( $current_commission_summary ) { -
woo-coupon-usage/trunk/inc/functions/functions-coupon-orders.php
r3438708 r3469742 187 187 delete_post_meta($order_id, 'wcusage_pending_commission'); 188 188 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 189 195 // Check and add if pending (this handles the logic) 190 196 if( function_exists('wcusage_check_and_add_pending_commission') ) { -
woo-coupon-usage/trunk/inc/functions/functions-dashboard.php
r3454163 r3469742 334 334 ?></option> 335 335 <?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' ) ); 336 347 if ( $wcusage_show_months_table == '1' ) { 337 348 ?> -
woo-coupon-usage/trunk/inc/functions/functions-general.php
r3462634 r3469742 62 62 || $post_id == $mla_dashboard_page 63 63 || is_account_page() 64 || get_query_var( 'affiliate_portal' ) 64 65 || ( !is_admin() && isset($_SERVER['REQUEST_URI']) && strpos( $_SERVER['REQUEST_URI'], $wcusage_portal_slug ) !== false ) ) { 65 66 … … 84 85 }); 85 86 } 86 // WP Compress87 if ( is_plugin_active( 'wp-compress-image-optimizer/wp-compress.php' ) ) {88 // Disable JavaScript optimization89 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 optimization102 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 caching111 add_filter('wpc_disable_caching', '__return_true');112 // Disable minification113 add_filter('wpc_disable_minify', '__return_true');114 // Disable lazy load115 add_filter('wpc_disable_lazyload', '__return_true');116 }117 87 118 88 } 119 89 } 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 */ 98 add_action( 'template_redirect', 'wcusage_fix_wp_compress', 1 ); 99 if( !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'); 120 153 } 121 154 } -
woo-coupon-usage/trunk/inc/functions/functions-new-order.php
r3420154 r3469742 101 101 $coupon_info = wcusage_get_coupon_info( $lifetimeaffiliate ); 102 102 $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 ); 104 111 } elseif ( $affiliatereferrer ) { 105 112 $calculateorder = wcusage_calculate_order_data( … … 137 144 $coupon_info = wcusage_get_coupon_info( $affiliatereferrer ); 138 145 $coupon_user_id = $coupon_info[1]; 146 $paidcommission = ( isset( $calculateorder['totalcommission'] ) ? $calculateorder['totalcommission'] : 0 ); 139 147 $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 ); 141 155 } else { 142 156 // Coupons … … 182 196 $coupon_info = wcusage_get_coupon_info( $coupon_code ); 183 197 $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 ); 185 206 } 186 207 } … … 218 239 3 219 240 ); 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. 236 246 /* Update MLA Parents When New Order Placed */ 237 function wcusage_update_ml_affiliate_parents( $meta_data, $coupon_user_id, $order ) { 247 function wcusage_update_ml_affiliate_parents( 248 $meta_data, 249 $coupon_user_id, 250 $order, 251 $coupon_code = '', 252 $paidcommission = 0 253 ) { 238 254 } 239 255 -
woo-coupon-usage/trunk/inc/functions/functions-refund.php
r2994178 r3469742 70 70 wcusage_delete_order_meta($order_id, 'wcusage_commission_summary'); 71 71 wcusage_delete_order_meta($order_id, 'wcusage_total_commission'); 72 wcusage_delete_order_meta($order_id, 'wcu_mla_commission'); 72 73 73 74 } -
woo-coupon-usage/trunk/inc/functions/functions-urls.php
r3462634 r3469742 40 40 41 41 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 ); 46 61 } elseif ( PHP_VERSION_ID < 70300 ) { 47 62 setcookie( $name, $value, $expire, $path, $domain, $secure, $httponly ); -
woo-coupon-usage/trunk/inc/functions/functions-user-coupons.php
r3462634 r3469742 339 339 if ( $wcu_text_unpaid_commission_confirm ) { 340 340 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'] ) ); 342 342 update_post_meta( $post_id, 'wcu_text_unpaid_commission', $wcu_text_unpaid_commission ); 343 343 } 344 344 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'] ) ); 346 346 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 ); 347 351 } 348 352 update_post_meta( $post_id, 'wcu_text_unpaid_commission_confirm', 0 ); -
woo-coupon-usage/trunk/inc/registration/class-registrations-list-table.php
r3454163 r3469742 162 162 return '<span class="dashicons dashicons-warning" style="color: orange;"></span> ' . esc_html__( 'Pending', 'woo-coupon-usage' ); 163 163 } 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 } 164 173 if($status == "declined") { 165 174 return '<span class="dashicons dashicons-dismiss" style="color: red;"></span> ' . esc_html__( 'Declined', 'woo-coupon-usage' ); … … 176 185 ?> 177 186 178 <?php if($status == "pending" ) { ?>187 <?php if($status == "pending" || $status == "parent_approved") { ?> 179 188 180 189 <form method="post" id="submitregister"> … … 183 192 184 193 <?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; ?> 185 198 186 199 <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 451 451 ?>"><?php 452 452 echo esc_html__( 'Pending', 'woo-coupon-usage' ); 453 ?></a> 454 · 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' ); 453 463 ?></a> 454 464 · -
woo-coupon-usage/trunk/inc/registration/registration-ajax.php
r3438708 r3469742 134 134 ) ); 135 135 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 } 136 168 } 137 169 // Determine whether this submission should be auto-accepted. -
woo-coupon-usage/trunk/inc/registration/registration-form.php
r3462634 r3469742 472 472 if ( $enable_captcha == "1" && !empty( $wcusage_registration_recaptcha_key ) && $wcusage_registration_recaptcha_key != "" ) { 473 473 ?> 474 <p>475 474 <div class="captcha_wrapper"> 476 475 <div class="g-recaptcha" data-sitekey="<?php … … 478 477 ?>"></div> 479 478 </div> 480 </p>481 479 <?php 482 480 } … … 487 485 if ( $enable_captcha == "2" && !empty( $wcusage_registration_turnstile_key ) && $wcusage_registration_turnstile_key != "" ) { 488 486 ?> 489 <p>490 487 <div class="captcha_wrapper"> 491 488 <div class="cf-turnstile" data-sitekey="<?php … … 493 490 ?>"></div> 494 491 </div> 495 </p>496 492 <?php 497 493 } … … 836 832 $thiscoupon = false; 837 833 } 838 if ( $count <= 0 && !$thiscoupon->is_valid() ) {834 if ( $count <= 0 && (!$thiscoupon || !$thiscoupon->is_valid()) ) { 839 835 if ( !isset( $_SESSION['wcu_registration_token'] ) || is_admin() ) { 840 836 // Add User If Admin Post … … 903 899 ); 904 900 } 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 ); 905 908 } 906 909 $alreadyexists = 0; -
woo-coupon-usage/trunk/inc/widget/js/floating-widget-popup.js
r3321450 r3469742 35 35 } 36 36 } 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 }); 37 108 } 38 109 … … 75 146 // Initialize premium features if available 76 147 initializePremiumFeatures(); 148 149 // Load captcha scripts if registration form is displayed 150 if (response.data.captcha) { 151 loadCaptchaScript(response.data.captcha); 152 } 77 153 } else { 78 154 var errorMsg = response && response.data ? response.data : wcusage_floating_widget.error_text; -
woo-coupon-usage/trunk/inc/widget/widget-ajax.php
r3321450 r3469742 9 9 */ 10 10 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 */ 15 function 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 11 37 // AJAX handler for popup content (updated to include settings) 12 38 add_action('wp_ajax_wcusage_floating_widget_content', 'wcusage_floating_widget_ajax_content'); … … 32 58 // Show registration form for non-logged in users 33 59 $content = wcusage_widget_registration_form($settings); 34 wp_send_json_success(array(60 $response_data = array( 35 61 'content' => $content, 36 62 '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); 38 70 return; 39 71 } … … 50 82 // Show registration form for logged-in users without coupons 51 83 $content = wcusage_widget_registration_form($settings); 52 wp_send_json_success(array(84 $response_data = array( 53 85 'content' => $content, 54 86 '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); 56 94 return; 57 95 } -
woo-coupon-usage/trunk/js/admin-coupons.js
r3462634 r3469742 139 139 wcu_text_coupon_commission_fixed_product: $row.find('#wcu_text_coupon_commission_fixed_product_' + couponId).val(), 140 140 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' 142 143 }; 143 144 -
woo-coupon-usage/trunk/js/admin-view-affiliate.js
r3358053 r3469742 4 4 5 5 jQuery(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 6 33 // Tab switching functionality 7 34 $('.wcusage-tabs .nav-tab').on('click', function(e) { … … 25 52 try { window.WCU_MLA_draw(); } catch(e) {} 26 53 } 54 55 // Sync mobile dropdown 56 $('.wcusage-tab-select').val('#' + tabId); 27 57 28 58 // Update URL without page reload … … 43 73 $('.wcusage-tab-content > div').removeClass('active'); 44 74 $('#tab-' + tab).addClass('active'); 75 76 // Sync mobile dropdown 77 $('.wcusage-tab-select').val('#tab-' + tab); 45 78 46 79 // If MLA tab is now active, ensure chart draws … … 276 309 }); 277 310 }); 311 -
woo-coupon-usage/trunk/readme.txt
r3462682 r3469742 6 6 Requires PHP: 7.0 7 7 Tested up to: 6.9 8 Stable tag: 7. 4.08 Stable tag: 7.5.0 9 9 License: GPLv3 10 10 License URI: https://www.gnu.org/licenses/gpl-3.0.html … … 276 276 == Changelog == 277 277 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 278 308 = Version 7.4.0 - 14th February 2026 = 279 309 - New: Added new "referral welcome popups" functionality. -
woo-coupon-usage/trunk/woo-coupon-usage.php
r3462634 r3469742 5 5 * Plugin URI: https://couponaffiliates.com 6 6 * Description: The most powerful affiliate plugin for WooCommerce. Track commission, generate referral URLs, assign affiliate coupons, and display detailed stats. 7 * Version: 7. 4.07 * Version: 7.5.0 8 8 * Author: Elliot Sowersby, RelyWP 9 9 * Author URI: https://couponaffiliates.com/
Note: See TracChangeset
for help on using the changeset viewer.