Files
WooNooW/includes/Api/Controllers/AffiliateAdminController.php

365 lines
13 KiB
PHP

<?php
namespace WooNooW\Api\Controllers;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WooNooW\Core\ModuleRegistry;
class AffiliateAdminController
{
private $namespace = 'woonoow/v1';
public function register_routes()
{
// List Affiliates
register_rest_route($this->namespace, '/admin/affiliates', [
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_affiliates'],
'permission_callback' => [$this, 'check_permission'],
]);
// Get Affiliate Balance (payable amount)
register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/balance', [
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_affiliate_balance'],
'permission_callback' => [$this, 'check_permission'],
]);
// Approve Affiliate
register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/approve', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'approve_affiliate'],
'permission_callback' => [$this, 'check_permission'],
]);
// Update Affiliate (commission rate)
register_rest_route($this->namespace, '/admin/affiliates/(?P<id>\d+)/update', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'update_affiliate'],
'permission_callback' => [$this, 'check_permission'],
]);
// List Referrals
register_rest_route($this->namespace, '/admin/affiliates/referrals', [
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_referrals'],
'permission_callback' => [$this, 'check_permission'],
]);
// List Payouts (for all affiliates)
register_rest_route($this->namespace, '/admin/affiliates/payouts', [
'methods' => WP_REST_Server::READABLE,
'callback' => [$this, 'get_payouts'],
'permission_callback' => [$this, 'check_permission'],
]);
// Create Payout
register_rest_route($this->namespace, '/admin/affiliates/payouts', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [$this, 'create_payout'],
'permission_callback' => [$this, 'check_permission'],
]);
}
public function check_permission()
{
return current_user_can('manage_woocommerce');
}
public function get_affiliates(WP_REST_Request $request)
{
global $wpdb;
$table = $wpdb->prefix . 'woonoow_affiliates';
$affiliates = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC", ARRAY_A);
// Add payable_balance to each affiliate
foreach ($affiliates as &$affiliate) {
$affiliate['payable_balance'] = (float) ($affiliate['total_earnings'] ?? 0) - (float) ($affiliate['paid_earnings'] ?? 0);
// Get user info
$user = get_userdata($affiliate['user_id']);
if ($user) {
$affiliate['user_email'] = $user->user_email;
$affiliate['user_name'] = $user->display_name;
}
}
return rest_ensure_response($affiliates);
}
public function get_affiliate_balance(WP_REST_Request $request)
{
global $wpdb;
$id = $request->get_param('id');
$table = $wpdb->prefix . 'woonoow_affiliates';
$affiliate = $wpdb->get_row($wpdb->prepare(
"SELECT id, user_id, referral_code, total_earnings, paid_earnings, total_referrals
FROM $table WHERE id = %d",
$id
));
if (!$affiliate) {
return new WP_REST_Response(['error' => 'Affiliate not found'], 404);
}
$user = get_userdata($affiliate->user_id);
return rest_ensure_response([
'id' => (int) $affiliate->id,
'user_id' => (int) $affiliate->user_id,
'user_name' => $user ? $user->display_name : 'Unknown',
'user_email' => $user ? $user->user_email : '',
'referral_code' => $affiliate->referral_code,
'total_earnings' => (float) $affiliate->total_earnings,
'paid_earnings' => (float) $affiliate->paid_earnings,
'payable_balance' => (float) $affiliate->total_earnings - (float) $affiliate->paid_earnings,
'total_referrals' => (int) $affiliate->total_referrals,
'approved_referrals' => $this->get_approved_referral_count($affiliate->id),
'pending_referrals' => $this->get_pending_referral_count($affiliate->id),
]);
}
private function get_approved_referral_count($affiliate_id)
{
global $wpdb;
return (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}woonoow_referrals WHERE affiliate_id = %d AND status = 'approved'",
$affiliate_id
));
}
private function get_pending_referral_count($affiliate_id)
{
global $wpdb;
return (int) $wpdb->get_var($wpdb->prepare(
"SELECT COUNT(*) FROM {$wpdb->prefix}woonoow_referrals WHERE affiliate_id = %d AND status = 'pending'",
$affiliate_id
));
}
public function approve_affiliate(WP_REST_Request $request)
{
global $wpdb;
$id = $request->get_param('id');
$table = $wpdb->prefix . 'woonoow_affiliates';
$wpdb->update(
$table,
['status' => 'active'],
['id' => $id]
);
// Trigger email notification for approval
$affiliate = $wpdb->get_row($wpdb->prepare("SELECT * FROM $table WHERE id = %d", $id));
if ($affiliate) {
$user = get_userdata($affiliate->user_id);
if ($user) {
do_action('woonoow/email/trigger', 'affiliate_application_approved', $user->user_email, [
'affiliate_name' => $user->display_name,
'referral_code' => $affiliate->referral_code
]);
}
}
return rest_ensure_response(['success' => true]);
}
public function update_affiliate(WP_REST_Request $request)
{
global $wpdb;
$id = $request->get_param('id');
$table = $wpdb->prefix . 'woonoow_affiliates';
$custom_rate = $request->get_param('custom_commission_rate');
// If rate is empty string or not provided, clear custom rate
if ($custom_rate === '' || $custom_rate === null || $custom_rate === false) {
$data = ['custom_commission_rate' => null];
} else {
$custom_rate = floatval($custom_rate);
if ($custom_rate < 0 || $custom_rate > 100) {
return new WP_REST_Response(['error' => 'Commission rate must be between 0 and 100'], 400);
}
$data = ['custom_commission_rate' => $custom_rate];
}
$result = $wpdb->update(
$table,
$data,
['id' => $id]
);
if ($result === false) {
return new WP_REST_Response(['error' => 'Failed to update affiliate'], 500);
}
return rest_ensure_response(['success' => true, 'custom_commission_rate' => $data['custom_commission_rate']]);
}
public function get_referrals(WP_REST_Request $request)
{
global $wpdb;
$table = $wpdb->prefix . 'woonoow_referrals';
// Add filter support
$where = "1=1";
$affiliate_id = $request->get_param('affiliate_id');
if ($affiliate_id) {
$where .= $wpdb->prepare(" AND affiliate_id = %d", $affiliate_id);
}
$status = $request->get_param('status');
if ($status) {
$where .= $wpdb->prepare(" AND status = %s", $status);
}
$date_start = $request->get_param('date_start');
if ($date_start) {
$where .= $wpdb->prepare(" AND created_at >= %s", $date_start . ' 00:00:00');
}
$date_end = $request->get_param('date_end');
if ($date_end) {
$where .= $wpdb->prepare(" AND created_at <= %s", $date_end . ' 23:59:59');
}
$order_id = $request->get_param('order_id');
if ($order_id) {
$where .= $wpdb->prepare(" AND order_id = %d", $order_id);
}
$referrals = $wpdb->get_results("SELECT * FROM $table WHERE $where ORDER BY created_at DESC", ARRAY_A);
// Enrich with affiliate info
$affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
foreach ($referrals as &$referral) {
$affiliate = $wpdb->get_row($wpdb->prepare(
"SELECT a.*, u.display_name as affiliate_name, u.user_email as affiliate_email
FROM $affiliates_table a
LEFT JOIN $wpdb->users u ON a.user_id = u.ID
WHERE a.id = %d",
$referral['affiliate_id']
));
if ($affiliate) {
$referral['affiliate_name'] = $affiliate->affiliate_name;
$referral['affiliate_email'] = $affiliate->affiliate_email;
}
}
return rest_ensure_response($referrals);
}
public function get_payouts(WP_REST_Request $request)
{
global $wpdb;
$table = $wpdb->prefix . 'woonoow_affiliate_payouts';
$affiliate_id = $request->get_param('affiliate_id');
$where = $affiliate_id ? $wpdb->prepare("WHERE affiliate_id = %d", $affiliate_id) : "";
$payouts = $wpdb->get_results("SELECT * FROM $table $where ORDER BY created_at DESC", ARRAY_A);
// Enrich with affiliate info
$affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
foreach ($payouts as &$payout) {
$affiliate = $wpdb->get_row($wpdb->prepare(
"SELECT a.*, u.display_name as affiliate_name, u.user_email as affiliate_email
FROM $affiliates_table a
LEFT JOIN $wpdb->users u ON a.user_id = u.ID
WHERE a.id = %d",
$payout['affiliate_id']
));
if ($affiliate) {
$payout['affiliate_name'] = $affiliate->affiliate_name;
$payout['affiliate_email'] = $affiliate->affiliate_email;
}
}
return rest_ensure_response($payouts);
}
public function create_payout(WP_REST_Request $request)
{
global $wpdb;
$payouts_table = $wpdb->prefix . 'woonoow_affiliate_payouts';
$affiliates_table = $wpdb->prefix . 'woonoow_affiliates';
$affiliate_id = absint($request->get_param('affiliate_id'));
$amount = floatval($request->get_param('amount'));
$method = sanitize_text_field($request->get_param('method') ?: 'bank_transfer');
$notes = '';
// Validate affiliate exists and get balance
$affiliate = $wpdb->get_row($wpdb->prepare(
"SELECT * FROM $affiliates_table WHERE id = %d",
$affiliate_id
));
if (!$affiliate) {
return new WP_REST_Response(['error' => 'Affiliate not found'], 404);
}
$payable_balance = (float) $affiliate->total_earnings - (float) $affiliate->paid_earnings;
if ($amount <= 0) {
return new WP_REST_Response(['error' => 'Amount must be greater than 0'], 400);
}
if ($amount > $payable_balance) {
return new WP_REST_Response([
'error' => 'Amount exceeds payable balance',
'payable_balance' => $payable_balance
], 400);
}
// Generate coupon for store_credit method
if ($method === 'store_credit') {
$user = get_userdata($affiliate->user_id);
if ($user) {
$coupon_code = 'CREDIT-' . strtoupper(wp_generate_password(8, false));
$coupon = new \WC_Coupon();
$coupon->set_code($coupon_code);
$coupon->set_discount_type('fixed_cart');
$coupon->set_amount($amount);
$coupon->set_email_restrictions([$user->user_email]);
$coupon->set_usage_limit(1);
$coupon->set_description('Store Credit for Affiliate Payout');
$coupon->save();
$notes = 'Generated Store Credit Coupon: ' . $coupon_code;
}
}
// Create payout record
$wpdb->insert($payouts_table, [
'affiliate_id' => $affiliate_id,
'amount' => $amount,
'currency' => get_woocommerce_currency(),
'method' => $method,
'status' => 'completed',
'notes' => $notes,
'completed_at' => current_time('mysql')
]);
$payout_id = $wpdb->insert_id;
// Update affiliate's paid_earnings
$wpdb->query($wpdb->prepare(
"UPDATE $affiliates_table SET paid_earnings = paid_earnings + %f WHERE id = %d",
$amount,
$affiliate_id
));
return rest_ensure_response([
'success' => true,
'id' => $payout_id,
'new_paid_earnings' => (float) $affiliate->paid_earnings + $amount,
'new_payable_balance' => $payable_balance - $amount,
'coupon_code' => $method === 'store_credit' ? $coupon_code : null
]);
}
}