Adding more functionality
This commit is contained in:
@@ -10,6 +10,10 @@ class WPDD_Admin_Payouts {
|
||||
add_action('admin_menu', array(__CLASS__, 'add_menu_page'));
|
||||
add_action('admin_post_wpdd_process_payout', array(__CLASS__, 'process_payout'));
|
||||
add_action('admin_post_wpdd_bulk_payouts', array(__CLASS__, 'process_bulk_payouts'));
|
||||
add_action('admin_post_wpdd_process_payout_request', array(__CLASS__, 'process_payout_request'));
|
||||
add_action('admin_post_wpdd_reject_payout_request', array(__CLASS__, 'reject_payout_request'));
|
||||
add_action('admin_post_wpdd_manual_payout', array(__CLASS__, 'process_manual_payout'));
|
||||
add_action('admin_post_wpdd_adjust_balance', array(__CLASS__, 'adjust_creator_balance'));
|
||||
add_action('admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'));
|
||||
}
|
||||
|
||||
@@ -50,6 +54,15 @@ class WPDD_Admin_Payouts {
|
||||
$currency = get_option('wpdd_currency', 'USD');
|
||||
$threshold = floatval(get_option('wpdd_payout_threshold', 0));
|
||||
|
||||
// Get payout requests (requested status)
|
||||
$payout_requests = $wpdb->get_results(
|
||||
"SELECT p.*, u.display_name, u.user_email
|
||||
FROM {$wpdb->prefix}wpdd_payouts p
|
||||
INNER JOIN {$wpdb->users} u ON p.creator_id = u.ID
|
||||
WHERE p.status = 'requested'
|
||||
ORDER BY p.created_at ASC"
|
||||
);
|
||||
|
||||
// Get payout history
|
||||
$query = "SELECT p.*, u.display_name, u.user_email
|
||||
FROM {$wpdb->prefix}wpdd_payouts p
|
||||
@@ -81,9 +94,172 @@ class WPDD_Admin_Payouts {
|
||||
<div class="notice notice-error is-dismissible">
|
||||
<p><?php _e('Error processing payout. Please try again.', 'wp-digital-download'); ?></p>
|
||||
</div>
|
||||
<?php elseif ($_GET['message'] === 'balance_adjusted') : ?>
|
||||
<div class="notice notice-success is-dismissible">
|
||||
<p><?php _e('Creator balance adjusted successfully.', 'wp-digital-download'); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($payout_requests)) : ?>
|
||||
<div class="wpdd-payout-requests" style="background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 4px; padding: 20px; margin: 20px 0;">
|
||||
<h2 style="margin-top: 0;"><?php _e('Payout Requests', 'wp-digital-download'); ?> <span class="count">(<?php echo count($payout_requests); ?>)</span></h2>
|
||||
<p><?php _e('Creators have requested the following payouts:', 'wp-digital-download'); ?></p>
|
||||
|
||||
<table class="wp-list-table widefat fixed striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php _e('Creator', 'wp-digital-download'); ?></th>
|
||||
<th><?php _e('Amount', 'wp-digital-download'); ?></th>
|
||||
<th><?php _e('PayPal Email', 'wp-digital-download'); ?></th>
|
||||
<th><?php _e('Request Date', 'wp-digital-download'); ?></th>
|
||||
<th><?php _e('Actions', 'wp-digital-download'); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($payout_requests as $request) : ?>
|
||||
<tr>
|
||||
<td>
|
||||
<strong><?php echo esc_html($request->display_name); ?></strong><br>
|
||||
<small><?php echo esc_html($request->user_email); ?></small>
|
||||
</td>
|
||||
<td><strong><?php echo wpdd_format_price($request->amount, $request->currency); ?></strong></td>
|
||||
<td><?php echo esc_html($request->paypal_email); ?></td>
|
||||
<td><?php echo esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($request->created_at))); ?></td>
|
||||
<td>
|
||||
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>" style="display: inline;">
|
||||
<input type="hidden" name="action" value="wpdd_process_payout_request">
|
||||
<input type="hidden" name="payout_id" value="<?php echo esc_attr($request->id); ?>">
|
||||
<?php wp_nonce_field('wpdd_process_payout_request_' . $request->id, 'wpdd_nonce'); ?>
|
||||
<button type="submit" class="button button-primary">
|
||||
<?php _e('Process Now', 'wp-digital-download'); ?>
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>" style="display: inline; margin-left: 5px;">
|
||||
<input type="hidden" name="action" value="wpdd_reject_payout_request">
|
||||
<input type="hidden" name="payout_id" value="<?php echo esc_attr($request->id); ?>">
|
||||
<?php wp_nonce_field('wpdd_reject_payout_request_' . $request->id, 'wpdd_nonce'); ?>
|
||||
<button type="submit" class="button button-secondary" onclick="return confirm('<?php _e('Are you sure you want to reject this payout request?', 'wp-digital-download'); ?>')">
|
||||
<?php _e('Reject', 'wp-digital-download'); ?>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Manual Actions Section -->
|
||||
<div class="wpdd-manual-actions" style="display: flex; gap: 20px; margin: 20px 0;">
|
||||
<!-- Manual Payout Form -->
|
||||
<div style="background: white; border: 1px solid #ddd; border-radius: 4px; padding: 20px; flex: 1;">
|
||||
<h3 style="margin-top: 0;"><?php _e('Manual Payout', 'wp-digital-download'); ?></h3>
|
||||
<p><?php _e('Process a payout for off-site sales or manual adjustments.', 'wp-digital-download'); ?></p>
|
||||
|
||||
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
|
||||
<input type="hidden" name="action" value="wpdd_manual_payout">
|
||||
<?php wp_nonce_field('wpdd_manual_payout', 'wpdd_nonce'); ?>
|
||||
|
||||
<table class="form-table" style="margin: 0;">
|
||||
<tr>
|
||||
<th><label for="creator_id"><?php _e('Creator', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<select name="creator_id" id="creator_id" required style="width: 100%;">
|
||||
<option value=""><?php _e('Select Creator', 'wp-digital-download'); ?></option>
|
||||
<?php
|
||||
$all_creators = get_users(array('role' => 'wpdd_creator'));
|
||||
foreach ($all_creators as $creator) :
|
||||
$paypal_email = get_user_meta($creator->ID, 'wpdd_paypal_email', true);
|
||||
?>
|
||||
<option value="<?php echo esc_attr($creator->ID); ?>" <?php echo empty($paypal_email) ? 'disabled' : ''; ?>>
|
||||
<?php echo esc_html($creator->display_name); ?>
|
||||
<?php echo empty($paypal_email) ? ' (' . __('No PayPal email', 'wp-digital-download') . ')' : ' (' . esc_html($paypal_email) . ')'; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="payout_amount"><?php _e('Amount', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<input type="number" name="payout_amount" id="payout_amount" step="0.01" min="0.01" required style="width: 150px;">
|
||||
<span><?php echo esc_html($currency); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="payout_reason"><?php _e('Reason/Note', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<textarea name="payout_reason" id="payout_reason" rows="3" style="width: 100%;" placeholder="<?php _e('e.g., Off-site sale, manual adjustment, etc.', 'wp-digital-download'); ?>"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="submit" style="margin: 15px 0 0 0;">
|
||||
<button type="submit" class="button button-primary">
|
||||
<?php _e('Process Manual Payout', 'wp-digital-download'); ?>
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Balance Adjustment Form -->
|
||||
<div style="background: white; border: 1px solid #ddd; border-radius: 4px; padding: 20px; flex: 1;">
|
||||
<h3 style="margin-top: 0;"><?php _e('Adjust Creator Balance', 'wp-digital-download'); ?></h3>
|
||||
<p><?php _e('Add or subtract funds from a creator\'s balance.', 'wp-digital-download'); ?></p>
|
||||
|
||||
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
|
||||
<input type="hidden" name="action" value="wpdd_adjust_balance">
|
||||
<?php wp_nonce_field('wpdd_adjust_balance', 'wpdd_nonce'); ?>
|
||||
|
||||
<table class="form-table" style="margin: 0;">
|
||||
<tr>
|
||||
<th><label for="adj_creator_id"><?php _e('Creator', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<select name="creator_id" id="adj_creator_id" required style="width: 100%;">
|
||||
<option value=""><?php _e('Select Creator', 'wp-digital-download'); ?></option>
|
||||
<?php foreach ($all_creators as $creator) : ?>
|
||||
<option value="<?php echo esc_attr($creator->ID); ?>">
|
||||
<?php echo esc_html($creator->display_name); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="adjustment_type"><?php _e('Type', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<select name="adjustment_type" id="adjustment_type" required>
|
||||
<option value="add"><?php _e('Add Funds', 'wp-digital-download'); ?></option>
|
||||
<option value="subtract"><?php _e('Subtract Funds', 'wp-digital-download'); ?></option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="adjustment_amount"><?php _e('Amount', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<input type="number" name="adjustment_amount" id="adjustment_amount" step="0.01" min="0.01" required style="width: 150px;">
|
||||
<span><?php echo esc_html($currency); ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label for="adjustment_reason"><?php _e('Reason/Note', 'wp-digital-download'); ?></label></th>
|
||||
<td>
|
||||
<textarea name="adjustment_reason" id="adjustment_reason" rows="3" style="width: 100%;" placeholder="<?php _e('e.g., Manual adjustment, refund, bonus, etc.', 'wp-digital-download'); ?>" required></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p class="submit" style="margin: 15px 0 0 0;">
|
||||
<button type="submit" class="button button-secondary">
|
||||
<?php _e('Adjust Balance', 'wp-digital-download'); ?>
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wpdd-payout-stats">
|
||||
<h2><?php _e('Pending Payouts', 'wp-digital-download'); ?></h2>
|
||||
|
||||
@@ -432,4 +608,241 @@ class WPDD_Admin_Payouts {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function process_payout_request() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('You do not have permission to perform this action.', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
$payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0;
|
||||
|
||||
if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_process_payout_request_' . $payout_id)) {
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
|
||||
exit;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Get the payout request
|
||||
$payout = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'",
|
||||
$payout_id
|
||||
));
|
||||
|
||||
if (!$payout) {
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Process via PayPal API
|
||||
$result = WPDD_PayPal_Payouts::process_payout($payout_id);
|
||||
|
||||
if ($result['success']) {
|
||||
// Update payout status
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wpdd_payouts',
|
||||
array(
|
||||
'status' => 'completed',
|
||||
'transaction_id' => $result['transaction_id'],
|
||||
'processed_by' => get_current_user_id(),
|
||||
'processed_at' => current_time('mysql')
|
||||
),
|
||||
array('id' => $payout_id),
|
||||
array('%s', '%s', '%d', '%s'),
|
||||
array('%d')
|
||||
);
|
||||
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success'));
|
||||
} else {
|
||||
// Update with error
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wpdd_payouts',
|
||||
array(
|
||||
'status' => 'failed',
|
||||
'notes' => $result['error']
|
||||
),
|
||||
array('id' => $payout_id),
|
||||
array('%s', '%s'),
|
||||
array('%d')
|
||||
);
|
||||
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function reject_payout_request() {
|
||||
if (!current_user_can('manage_options')) {
|
||||
wp_die(__('You do not have permission to perform this action.', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
$payout_id = isset($_POST['payout_id']) ? intval($_POST['payout_id']) : 0;
|
||||
|
||||
if (!$payout_id || !wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_reject_payout_request_' . $payout_id)) {
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
|
||||
exit;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Get the payout request
|
||||
$payout = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}wpdd_payouts WHERE id = %d AND status = 'requested'",
|
||||
$payout_id
|
||||
));
|
||||
|
||||
if (!$payout) {
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=error'));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Update status to failed/rejected
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wpdd_payouts',
|
||||
array(
|
||||
'status' => 'failed',
|
||||
'notes' => 'Request rejected by administrator',
|
||||
'processed_by' => get_current_user_id(),
|
||||
'processed_at' => current_time('mysql')
|
||||
),
|
||||
array('id' => $payout_id),
|
||||
array('%s', '%s', '%d', '%s'),
|
||||
array('%d')
|
||||
);
|
||||
|
||||
// Restore balance to creator
|
||||
update_user_meta($payout->creator_id, 'wpdd_creator_balance', $payout->amount);
|
||||
|
||||
wp_redirect(admin_url('edit.php?post_type=wpdd_product&page=wpdd-payouts&message=success'));
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function process_manual_payout() {
|
||||
if (!current_user_can('manage_options') ||
|
||||
!wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_manual_payout')) {
|
||||
wp_die(__('Security check failed', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
$creator_id = intval($_POST['creator_id']);
|
||||
$amount = floatval($_POST['payout_amount']);
|
||||
$reason = sanitize_textarea_field($_POST['payout_reason']);
|
||||
|
||||
if (!$creator_id || $amount <= 0) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$creator = get_userdata($creator_id);
|
||||
if (!$creator || !in_array('wpdd_creator', $creator->roles)) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$paypal_email = get_user_meta($creator_id, 'wpdd_paypal_email', true);
|
||||
if (empty($paypal_email)) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Create the payout record
|
||||
$result = $wpdb->insert(
|
||||
$wpdb->prefix . 'wpdd_payouts',
|
||||
array(
|
||||
'creator_id' => $creator_id,
|
||||
'amount' => $amount,
|
||||
'currency' => get_option('wpdd_currency', 'USD'),
|
||||
'paypal_email' => $paypal_email,
|
||||
'status' => 'pending',
|
||||
'payout_method' => 'manual',
|
||||
'notes' => $reason,
|
||||
'created_at' => current_time('mysql'),
|
||||
'processed_by' => get_current_user_id()
|
||||
),
|
||||
array('%d', '%f', '%s', '%s', '%s', '%s', '%s', '%s', '%d')
|
||||
);
|
||||
|
||||
if (!$result) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$payout_id = $wpdb->insert_id;
|
||||
|
||||
// Try to process via PayPal
|
||||
if (class_exists('WPDD_PayPal_Payouts')) {
|
||||
$paypal_result = WPDD_PayPal_Payouts::process_payout($payout_id);
|
||||
|
||||
if (!$paypal_result) {
|
||||
// Update status to failed
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'wpdd_payouts',
|
||||
array('status' => 'failed'),
|
||||
array('id' => $payout_id),
|
||||
array('%s'),
|
||||
array('%d')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
wp_redirect(add_query_arg('message', 'success', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function adjust_creator_balance() {
|
||||
if (!current_user_can('manage_options') ||
|
||||
!wp_verify_nonce($_POST['wpdd_nonce'], 'wpdd_adjust_balance')) {
|
||||
wp_die(__('Security check failed', 'wp-digital-download'));
|
||||
}
|
||||
|
||||
$creator_id = intval($_POST['creator_id']);
|
||||
$adjustment_type = sanitize_text_field($_POST['adjustment_type']);
|
||||
$amount = floatval($_POST['adjustment_amount']);
|
||||
$reason = sanitize_textarea_field($_POST['adjustment_reason']);
|
||||
|
||||
if (!$creator_id || $amount <= 0 || !in_array($adjustment_type, array('add', 'subtract'))) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
$creator = get_userdata($creator_id);
|
||||
if (!$creator || !in_array('wpdd_creator', $creator->roles)) {
|
||||
wp_redirect(add_query_arg('message', 'error', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get current balance
|
||||
$current_balance = floatval(get_user_meta($creator_id, 'wpdd_balance', true));
|
||||
|
||||
// Calculate new balance
|
||||
if ($adjustment_type === 'add') {
|
||||
$new_balance = $current_balance + $amount;
|
||||
} else {
|
||||
$new_balance = max(0, $current_balance - $amount); // Don't allow negative balance
|
||||
}
|
||||
|
||||
// Update the balance
|
||||
update_user_meta($creator_id, 'wpdd_balance', $new_balance);
|
||||
|
||||
// Create a record of this adjustment
|
||||
global $wpdb;
|
||||
$wpdb->insert(
|
||||
$wpdb->prefix . 'wpdd_balance_adjustments',
|
||||
array(
|
||||
'creator_id' => $creator_id,
|
||||
'adjustment_type' => $adjustment_type,
|
||||
'amount' => $amount,
|
||||
'previous_balance' => $current_balance,
|
||||
'new_balance' => $new_balance,
|
||||
'reason' => $reason,
|
||||
'adjusted_by' => get_current_user_id(),
|
||||
'created_at' => current_time('mysql')
|
||||
),
|
||||
array('%d', '%s', '%f', '%f', '%f', '%s', '%d', '%s')
|
||||
);
|
||||
|
||||
wp_redirect(add_query_arg('message', 'balance_adjusted', wp_get_referer()));
|
||||
exit;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user