'wpdd_creator')); // If creator is selected, show their transactions if ($creator_id) { self::render_transactions($creator_id, $date_from, $date_to, $type_filter, true); } else { ?>

' . __('Creator not found.', 'wp-digital-download') . '

'; return; } // Fetch all transactions for this creator $transactions = array(); // Get earnings (sales) if ($type_filter === 'all' || $type_filter === 'earnings') { $earnings = $wpdb->get_results($wpdb->prepare( "SELECT e.*, o.order_number, o.customer_name, o.customer_email, p.post_title as product_name FROM {$wpdb->prefix}wpdd_creator_earnings e LEFT JOIN {$wpdb->prefix}wpdd_orders o ON e.order_id = o.id LEFT JOIN {$wpdb->posts} p ON e.product_id = p.ID WHERE e.creator_id = %d AND DATE(e.created_at) BETWEEN %s AND %s ORDER BY e.created_at DESC", $creator_id, $date_from, $date_to )); foreach ($earnings as $earning) { $transactions[] = array( 'date' => $earning->created_at, 'type' => 'earning', 'description' => sprintf(__('Sale: %s to %s', 'wp-digital-download'), $earning->product_name, $earning->customer_name), 'order_number' => $earning->order_number, 'gross_amount' => $earning->sale_amount, 'commission' => $earning->sale_amount - $earning->creator_earning, 'net_amount' => $earning->creator_earning, 'balance_change' => '+' . $earning->creator_earning, 'status' => $earning->payout_status, 'payout_id' => $earning->payout_id ); } } // Get payouts if ($type_filter === 'all' || $type_filter === 'payouts') { $payouts = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE creator_id = %d AND DATE(created_at) BETWEEN %s AND %s ORDER BY created_at DESC", $creator_id, $date_from, $date_to )); foreach ($payouts as $payout) { $transactions[] = array( 'date' => $payout->created_at, 'type' => 'payout', 'description' => sprintf(__('Payout to %s', 'wp-digital-download'), $payout->paypal_email), 'order_number' => $payout->transaction_id ?: 'N/A', 'gross_amount' => 0, 'commission' => 0, 'net_amount' => -$payout->amount, 'balance_change' => '-' . $payout->amount, 'status' => $payout->status, 'payout_id' => $payout->id ); } } // Get adjustments if ($type_filter === 'all' || $type_filter === 'adjustments') { $adjustments = $wpdb->get_results($wpdb->prepare( "SELECT a.*, u.display_name as adjusted_by_name FROM {$wpdb->prefix}wpdd_balance_adjustments a LEFT JOIN {$wpdb->users} u ON a.adjusted_by = u.ID WHERE a.creator_id = %d AND DATE(a.created_at) BETWEEN %s AND %s ORDER BY a.created_at DESC", $creator_id, $date_from, $date_to )); foreach ($adjustments as $adjustment) { $amount_change = $adjustment->adjustment_type === 'add' ? $adjustment->amount : -$adjustment->amount; $transactions[] = array( 'date' => $adjustment->created_at, 'type' => 'adjustment', 'description' => sprintf(__('Manual adjustment: %s (by %s)', 'wp-digital-download'), $adjustment->reason, $adjustment->adjusted_by_name), 'order_number' => 'ADJ-' . $adjustment->id, 'gross_amount' => 0, 'commission' => 0, 'net_amount' => $amount_change, 'balance_change' => ($amount_change >= 0 ? '+' : '') . $amount_change, 'status' => 'completed', 'payout_id' => null ); } } // Sort transactions by date usort($transactions, function($a, $b) { return strtotime($b['date']) - strtotime($a['date']); }); // Calculate running balance $current_balance = WPDD_Creator::get_creator_balance($creator_id); $running_balance = $current_balance; // Calculate balance by going backwards from current for ($i = 0; $i < count($transactions); $i++) { $transactions[$i]['running_balance'] = $running_balance; if ($i < count($transactions) - 1) { $running_balance -= floatval(str_replace('+', '', $transactions[$i]['balance_change'])); } } ?>

display_name); } else { _e('My Transaction History', 'wp-digital-download'); } ?>

to

()

' . __('Sale', 'wp-digital-download'); break; case 'payout': $type_badge = ' ' . __('Payout', 'wp-digital-download'); break; case 'adjustment': $type_badge = ' ' . __('Adjustment', 'wp-digital-download'); break; } echo $type_badge; ?> 0 ? wpdd_format_price($transaction['gross_amount']) : '-'; ?> 0 ? wpdd_format_price($transaction['commission']) : '-'; ?> = 0 ? '+' : '') . wpdd_format_price(abs($transaction['net_amount'])); ?>
get_results($wpdb->prepare( "SELECT e.*, o.order_number, o.customer_name, o.customer_email, p.post_title as product_name FROM {$wpdb->prefix}wpdd_creator_earnings e LEFT JOIN {$wpdb->prefix}wpdd_orders o ON e.order_id = o.id LEFT JOIN {$wpdb->posts} p ON e.product_id = p.ID WHERE e.creator_id = %d AND DATE(e.created_at) BETWEEN %s AND %s ORDER BY e.created_at DESC", $creator_id, $date_from, $date_to )); foreach ($earnings as $earning) { $transactions[] = array( 'date' => $earning->created_at, 'type' => 'earning', 'description' => sprintf(__('Sale: %s to %s', 'wp-digital-download'), $earning->product_name, $earning->customer_name), 'order_number' => $earning->order_number, 'gross_amount' => $earning->sale_amount, 'commission' => $earning->sale_amount - $earning->creator_earning, 'net_amount' => $earning->creator_earning, 'balance_change' => '+' . $earning->creator_earning, 'status' => $earning->payout_status, 'payout_id' => $earning->payout_id ); } } // Get payouts if ($type_filter === 'all' || $type_filter === 'payouts') { $payouts = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE creator_id = %d AND DATE(created_at) BETWEEN %s AND %s ORDER BY created_at DESC", $creator_id, $date_from, $date_to )); foreach ($payouts as $payout) { $transactions[] = array( 'date' => $payout->created_at, 'type' => 'payout', 'description' => sprintf(__('Payout to %s', 'wp-digital-download'), $payout->paypal_email), 'order_number' => $payout->transaction_id ?: 'N/A', 'gross_amount' => 0, 'commission' => 0, 'net_amount' => -$payout->amount, 'balance_change' => '-' . $payout->amount, 'status' => $payout->status, 'payout_id' => $payout->id ); } } // Get adjustments if ($type_filter === 'all' || $type_filter === 'adjustments') { $adjustments = $wpdb->get_results($wpdb->prepare( "SELECT a.*, u.display_name as adjusted_by_name FROM {$wpdb->prefix}wpdd_balance_adjustments a LEFT JOIN {$wpdb->users} u ON a.adjusted_by = u.ID WHERE a.creator_id = %d AND DATE(a.created_at) BETWEEN %s AND %s ORDER BY a.created_at DESC", $creator_id, $date_from, $date_to )); foreach ($adjustments as $adjustment) { $amount_change = $adjustment->adjustment_type === 'add' ? $adjustment->amount : -$adjustment->amount; $transactions[] = array( 'date' => $adjustment->created_at, 'type' => 'adjustment', 'description' => sprintf(__('Manual adjustment: %s (by %s)', 'wp-digital-download'), $adjustment->reason, $adjustment->adjusted_by_name), 'order_number' => 'ADJ-' . $adjustment->id, 'gross_amount' => 0, 'commission' => 0, 'net_amount' => $amount_change, 'balance_change' => ($amount_change >= 0 ? '+' : '') . $amount_change, 'status' => 'completed', 'payout_id' => null ); } } // Sort transactions by date usort($transactions, function($a, $b) { return strtotime($b['date']) - strtotime($a['date']); }); // Calculate running balance $current_balance = WPDD_Creator::get_creator_balance($creator_id); $running_balance = $current_balance; // Calculate balance by going backwards from current for ($i = 0; $i < count($transactions); $i++) { $transactions[$i]['running_balance'] = $running_balance; if ($i < count($transactions) - 1) { $running_balance -= floatval(str_replace('+', '', $transactions[$i]['balance_change'])); } } return $transactions; } private static function handle_export_request($creator_id, $transactions, $date_from, $date_to, $format) { $creator = get_userdata($creator_id); if ($format === 'csv') { self::export_csv($transactions, $creator, $date_from, $date_to); } elseif ($format === 'pdf') { self::export_pdf($transactions, $creator, $date_from, $date_to); } } private static function export_csv($transactions, $creator, $date_from, $date_to) { $filename = sprintf('transactions_%s_%s_to_%s.csv', sanitize_title($creator->display_name), $date_from, $date_to ); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=' . $filename); $output = fopen('php://output', 'w'); // Add BOM for Excel UTF-8 compatibility fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); // Header row fputcsv($output, array( 'Date', 'Type', 'Description', 'Order/Reference', 'Gross Amount', 'Commission', 'Net Amount', 'Running Balance', 'Status' )); // Data rows foreach ($transactions as $transaction) { fputcsv($output, array( date('Y-m-d H:i:s', strtotime($transaction['date'])), ucfirst($transaction['type']), $transaction['description'], $transaction['order_number'], $transaction['gross_amount'] > 0 ? number_format($transaction['gross_amount'], 2) : '', $transaction['commission'] > 0 ? number_format($transaction['commission'], 2) : '', number_format(abs($transaction['net_amount']), 2) . ($transaction['net_amount'] < 0 ? ' (Debit)' : ''), number_format($transaction['running_balance'], 2), ucfirst($transaction['status']) )); } fclose($output); exit; } private static function export_pdf($transactions, $creator, $date_from, $date_to) { // Create a clean PDF-ready HTML document $filename = sprintf('transactions_%s_%s_to_%s.pdf', sanitize_title($creator->display_name), $date_from, $date_to ); // Set headers for PDF display/download header('Content-Type: text/html; charset=utf-8'); header('Content-Disposition: inline; filename=' . $filename); header('X-Robots-Tag: noindex, nofollow'); ?> <?php printf(__('Transaction History - %s', 'wp-digital-download'), $creator->display_name); ?>

display_name); ?>

ID)); ?>

= 0 ? '+' : '') . wpdd_format_price(abs($transaction['net_amount'])); ?>