get_charset_collate(); $results = array(); // Check if creator_earnings table exists and has correct structure $table_name = $wpdb->prefix . 'wpdd_creator_earnings'; $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name; if (!$table_exists) { $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, creator_id bigint(20) NOT NULL, order_id bigint(20) NOT NULL, product_id bigint(20) NOT NULL, sale_amount decimal(10,2) NOT NULL, commission_rate decimal(5,2) NOT NULL, creator_earning decimal(10,2) NOT NULL, payout_id bigint(20) DEFAULT NULL, payout_status varchar(20) DEFAULT 'pending', available_at datetime DEFAULT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY creator_id (creator_id), KEY order_id (order_id), KEY product_id (product_id), KEY payout_id (payout_id), KEY payout_status (payout_status) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); $results[] = "Created table: $table_name"; } else { // Check if payout_id and payout_status columns exist $columns = $wpdb->get_results("SHOW COLUMNS FROM $table_name"); $has_payout_id = false; $has_payout_status = false; $has_available_at = false; foreach ($columns as $column) { if ($column->Field == 'payout_id') $has_payout_id = true; if ($column->Field == 'payout_status') $has_payout_status = true; if ($column->Field == 'available_at') $has_available_at = true; } if (!$has_payout_id) { $wpdb->query("ALTER TABLE $table_name ADD COLUMN payout_id bigint(20) DEFAULT NULL"); $wpdb->query("ALTER TABLE $table_name ADD KEY payout_id (payout_id)"); $results[] = "Added payout_id column to $table_name"; } if (!$has_payout_status) { $wpdb->query("ALTER TABLE $table_name ADD COLUMN payout_status varchar(20) DEFAULT 'pending'"); $wpdb->query("ALTER TABLE $table_name ADD KEY payout_status (payout_status)"); $results[] = "Added payout_status column to $table_name"; } if (!$has_available_at) { $wpdb->query("ALTER TABLE $table_name ADD COLUMN available_at datetime DEFAULT NULL"); $wpdb->query("ALTER TABLE $table_name ADD KEY available_at (available_at)"); $results[] = "Added available_at column to $table_name"; // Update existing pending earnings with available_at dates $holding_days = intval(get_option('wpdd_earnings_holding_days', 15)); $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET available_at = DATE_ADD(created_at, INTERVAL %d DAY) WHERE payout_status = 'pending' AND available_at IS NULL", $holding_days ) ); $results[] = "Updated pending earnings with available_at dates"; } $results[] = "Table exists: $table_name"; } // Check if balance_adjustments table exists $table_name = $wpdb->prefix . 'wpdd_balance_adjustments'; if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { $sql = "CREATE TABLE IF NOT EXISTS $table_name ( id bigint(20) NOT NULL AUTO_INCREMENT, creator_id bigint(20) NOT NULL, adjustment_type varchar(20) NOT NULL, amount decimal(10,2) NOT NULL, previous_balance decimal(10,2) NOT NULL, new_balance decimal(10,2) NOT NULL, reason text NOT NULL, adjusted_by bigint(20) NOT NULL, created_at datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY creator_id (creator_id), KEY adjusted_by (adjusted_by) ) $charset_collate;"; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); dbDelta($sql); $results[] = "Created table: $table_name"; } else { $results[] = "Table exists: $table_name"; } // Check existing orders and add missing earnings records $completed_orders = $wpdb->get_results( "SELECT o.*, p.post_author as creator_id FROM {$wpdb->prefix}wpdd_orders o INNER JOIN {$wpdb->posts} p ON o.product_id = p.ID WHERE o.status = 'completed'" ); $results[] = "Found " . count($completed_orders) . " completed orders"; // Process each order to ensure earnings are recorded $added_earnings = 0; foreach ($completed_orders as $order) { // Check if earning already recorded $existing = $wpdb->get_var($wpdb->prepare( "SELECT id FROM {$wpdb->prefix}wpdd_creator_earnings WHERE order_id = %d", $order->id )); if (!$existing && $order->amount > 0) { $commission_rate = floatval(get_option('wpdd_commission_rate', 0)); $creator_share = $order->amount * (1 - ($commission_rate / 100)); // Insert earning record $wpdb->insert( $wpdb->prefix . 'wpdd_creator_earnings', array( 'creator_id' => $order->creator_id, 'order_id' => $order->id, 'product_id' => $order->product_id, 'sale_amount' => $order->amount, 'commission_rate' => $commission_rate, 'creator_earning' => $creator_share, 'payout_status' => 'pending', 'created_at' => $order->purchase_date ), array('%d', '%d', '%d', '%f', '%f', '%f', '%s', '%s') ); $added_earnings++; } } if ($added_earnings > 0) { $results[] = "Added $added_earnings missing earning records"; } // Recalculate all creator balances based on UNPAID earnings only $creators = get_users(array('role' => 'wpdd_creator')); foreach ($creators as $creator) { // Calculate available earnings only (not pending or already paid) $available_earnings = $wpdb->get_var($wpdb->prepare( "SELECT SUM(creator_earning) FROM {$wpdb->prefix}wpdd_creator_earnings WHERE creator_id = %d AND payout_status = 'available'", $creator->ID )); // Calculate balance adjustments $total_adjustments = $wpdb->get_var($wpdb->prepare( "SELECT SUM(CASE WHEN adjustment_type = 'add' THEN amount WHEN adjustment_type = 'subtract' THEN -amount ELSE 0 END) FROM {$wpdb->prefix}wpdd_balance_adjustments WHERE creator_id = %d", $creator->ID )); $available_earnings = floatval($available_earnings); $total_adjustments = floatval($total_adjustments); $balance = $available_earnings + $total_adjustments; // Update creator balance update_user_meta($creator->ID, 'wpdd_creator_balance', $balance); // Get total earnings for display $total_earnings = $wpdb->get_var($wpdb->prepare( "SELECT SUM(creator_earning) FROM {$wpdb->prefix}wpdd_creator_earnings WHERE creator_id = %d", $creator->ID )); // Get paid out amount $paid_out = $wpdb->get_var($wpdb->prepare( "SELECT SUM(creator_earning) FROM {$wpdb->prefix}wpdd_creator_earnings WHERE creator_id = %d AND payout_status = 'paid'", $creator->ID )); $results[] = sprintf( "Updated balance for %s: Total Earnings: $%.2f, Paid Out: $%.2f, Adjustments: $%.2f, Current Balance: $%.2f", $creator->display_name, floatval($total_earnings), floatval($paid_out), $total_adjustments, $balance ); } return $results; } // Add admin page to run this check add_action('admin_menu', function() { add_submenu_page( 'edit.php?post_type=wpdd_product', 'Tools', 'Tools', 'manage_options', 'wpdd-tools', function() { $active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'system'; ?>

WP Digital Download - Tools

🔧 Database Check & Repair

Database check completed!

'; echo '

Results:

'; echo ''; } ?>

This tool will:

📊 System Status

Quick overview of your plugin status:

PayPal: ' . ($paypal_configured ? '✓ Configured' : '✗ Not Configured') . '

'; if ($paypal_configured) { echo '

Client ID: ' . substr($paypal_client_id, 0, 10) . '...

'; } // PayPal Mode $paypal_mode = get_option('wpdd_paypal_mode', 'sandbox'); echo '

PayPal Mode: ' . ucfirst(esc_html($paypal_mode)) . '

'; // Currency $currency = get_option('wpdd_currency', 'USD'); echo '

Currency: ' . esc_html($currency) . '

'; // Commission Rate $commission = get_option('wpdd_commission_rate', 0); echo '

Platform Commission: ' . floatval($commission) . '%

'; // Holding Period $holding = get_option('wpdd_earnings_holding_days', 15); echo '

Earnings Hold: ' . intval($holding) . ' days

'; // Product Count $products = wp_count_posts('wpdd_product'); echo '

Products: ' . intval($products->publish) . ' published

'; // Creator Count $creators = count(get_users(array('role' => 'wpdd_creator'))); echo '

Creators: ' . $creators . '

'; ?>

🔍 Settings Debug Info

If settings are resetting, check these values:

' . esc_html($setting) . ':
' . esc_html($display_value ?: '(empty)') . '
'; } ?>

🔑 License Tools

Manage and regenerate license keys for completed orders.

✅ License generated successfully for order #' . $order_id . ': ' . esc_html($result) . '

'; } else { echo '

⚠️ License generation completed for order #' . $order_id . '. Check error logs if no license was created.

'; } } // Handle bulk license generation if (isset($_POST['generate_all_missing']) && wp_verify_nonce($_POST['_wpnonce'], 'wpdd_generate_all_licenses')) { $orders_without_licenses = $wpdb->get_results(" SELECT o.id FROM {$wpdb->prefix}wpdd_orders o LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID LEFT JOIN {$wpdb->prefix}wpdd_licenses l ON o.id = l.order_id WHERE o.status = 'completed' AND l.id IS NULL AND p.post_type = 'wpdd_product' "); $generated = 0; foreach ($orders_without_licenses as $order) { $result = WPDD_License_Manager::generate_license_for_order($order->id); if ($result) { $generated++; } } echo '

✅ Generated ' . $generated . ' license keys out of ' . count($orders_without_licenses) . ' eligible orders.

'; } // Get orders without license keys for software products $orders_without_licenses = $wpdb->get_results(" SELECT o.*, p.post_title as product_name, pm_type.meta_value as product_type, pm_git.meta_value as git_repository FROM {$wpdb->prefix}wpdd_orders o LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID LEFT JOIN {$wpdb->prefix}wpdd_licenses l ON o.id = l.order_id LEFT JOIN {$wpdb->postmeta} pm_type ON (p.ID = pm_type.post_id AND pm_type.meta_key = '_wpdd_product_type') LEFT JOIN {$wpdb->postmeta} pm_git ON (p.ID = pm_git.post_id AND pm_git.meta_key = '_wpdd_git_repository') WHERE o.status = 'completed' AND l.id IS NULL AND p.post_type = 'wpdd_product' AND (pm_type.meta_value = 'software_license' OR pm_git.meta_value IS NOT NULL) ORDER BY o.id DESC "); ?>

Orders Missing License Keys

Order ID Order Number Product Product Type Customer Email Date Action
id; ?> order_number); ?> product_name); ?> git_repository)): ?>
Git: git_repository); ?>
product_type ?: 'digital_download'); ?> customer_email); ?> purchase_date)); ?>

✅ All eligible software orders have license keys assigned.


🔍 License Statistics

get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_licenses"); $active_licenses = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_licenses WHERE status = 'active'"); $expired_licenses = $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_licenses WHERE expires_at IS NOT NULL AND expires_at < NOW()"); $software_orders = $wpdb->get_var(" SELECT COUNT(*) FROM {$wpdb->prefix}wpdd_orders o LEFT JOIN {$wpdb->posts} p ON o.product_id = p.ID LEFT JOIN {$wpdb->postmeta} pm_type ON (p.ID = pm_type.post_id AND pm_type.meta_key = '_wpdd_product_type') LEFT JOIN {$wpdb->postmeta} pm_git ON (p.ID = pm_git.post_id AND pm_git.meta_key = '_wpdd_git_repository') WHERE o.status = 'completed' AND p.post_type = 'wpdd_product' AND (pm_type.meta_value = 'software_license' OR pm_git.meta_value IS NOT NULL) "); $missing_licenses = count($orders_without_licenses); ?>

Total Licenses

Active Licenses

Missing Licenses

0): ?>
⚠️ Notice: license(s) have expired.

📧 Email Test

Test your email configuration by sending a test email.

', 'Content-Type: text/html; charset=UTF-8' ); // Configure SMTP if enabled if ($smtp_enabled) { add_action('phpmailer_init', 'wpdd_configure_smtp'); } // Send email $sent = wp_mail($to_email, $subject, nl2br($message), $headers); if ($sent) { echo '

✅ Test email sent successfully to ' . esc_html($to_email) . '

'; } else { global $phpmailer; $error_info = ''; if (isset($phpmailer) && is_object($phpmailer) && !empty($phpmailer->ErrorInfo)) { $error_info = $phpmailer->ErrorInfo; } echo '

❌ Failed to send test email. ' . esc_html($error_info) . '

'; } } else { echo '

Please enter a valid email address.

'; } } ?>

Email address to send the test email to.


📋 Current Email Configuration

SMTP Enabled:
From Email:
From Name:
SMTP Host:
SMTP Port:
SMTP Encryption:
SMTP Username:

📨 Email Logs

View the last 100 emails sent by the plugin.

prefix . 'wpdd_email_logs'; // Check if table exists if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) { echo '

Email logs table not found. It will be created when the first email is sent.

'; } else { // Get email logs $logs = $wpdb->get_results( "SELECT * FROM $table_name ORDER BY sent_at DESC LIMIT 100" ); if (empty($logs)) { echo '

No email logs found.

'; } else { ?>
Date/Time To Subject Status Type Actions
sent_at); ?> to_email); ?> subject); ?> status == 'sent') : ?> ✅ Sent ❌ Failed email_type); ?>
isSMTP(); $phpmailer->Host = get_option('wpdd_smtp_host'); $phpmailer->Port = get_option('wpdd_smtp_port', 587); $phpmailer->SMTPAuth = true; $phpmailer->Username = get_option('wpdd_smtp_username'); $phpmailer->Password = get_option('wpdd_smtp_password'); $phpmailer->SMTPSecure = get_option('wpdd_smtp_encryption', 'tls'); $phpmailer->From = get_option('wpdd_from_email', get_option('admin_email')); $phpmailer->FromName = get_option('wpdd_from_name', get_bloginfo('name')); }