Website : phonehp.ir
backdoor
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Home
Console
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Warning
: Undefined variable $backdoor in
/home/nehpir/public_html/goods.php
on line
326
Upload
information
Create File
Create Folder
About
Tools
:
/
home
/
nehpir
/
public_html
/
wp-content
/
plugins
/
woocommersa
/
includes
/
API
/
Filename :
AnalysisController.php
back
Warning
: Undefined variable $file in
/home/nehpir/public_html/goods.php
on line
545
Copy
<?php namespace WooCommersa\API; if (!defined('ABSPATH')) exit; class AnalysisController extends BaseController { public function __construct() { add_action('rest_api_init', [$this, 'register_routes']); } public function register_routes() { register_rest_route($this->namespace, '/customers-overview', [ 'methods' => 'GET', 'callback' => [$this, 'get_customers_overview'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/analysis/create-quick-coupon', [ 'methods' => 'POST', 'callback' => [$this, 'create_quick_coupon'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/analysis/send-coupon-sms', [ 'methods' => 'POST', 'callback' => [$this, 'send_coupon_sms'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/analysis/get-ai-insight', [ 'methods' => 'POST', 'callback' => [$this, 'get_ai_insight'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/analysis/sources', [ 'methods' => 'GET', 'callback' => [$this, 'get_order_sources'], 'permission_callback' => [$this, 'permissions_check'], ]); register_rest_route($this->namespace, '/analysis/export-customers', [ 'methods' => 'GET', 'callback' => [$this, 'export_customers'], 'permission_callback' => [$this, 'permissions_check'], ]); } public function get_customers_overview($request) { global $wpdb; $params = $request->get_params(); $page = isset($params['page']) ? max(1, intval($params['page'])) : 1; $per_page = isset($params['per_page']) ? max(1, intval($params['per_page'])) : 20; $search = strtolower(sanitize_text_field($params['search'] ?? '')); $min_spent = isset($params['min_spent']) && $params['min_spent'] !== '' ? floatval($params['min_spent']) : 0; $min_orders = isset($params['min_orders']) && $params['min_orders'] !== '' ? intval($params['min_orders']) : 0; $date_from = isset($params['date_from']) ? sanitize_text_field($params['date_from']) : ''; $date_to = isset($params['date_to']) ? sanitize_text_field($params['date_to']) : ''; try { // Using WooCommerce Lookup Tables for high-performance analysis $lookup_table = $wpdb->prefix . 'wc_customer_lookup'; $stats_table = $wpdb->prefix . 'wc_order_stats'; // 1. Build Conditionals for the Query $where = ["stats.status IN ('wc-completed', 'wc-processing')"]; if ($search) { $where[] = $wpdb->prepare("(cust.first_name LIKE %s OR cust.last_name LIKE %s OR cust.email LIKE %s OR cust.username LIKE %s)", '%' . $search . '%', '%' . $search . '%', '%' . $search . '%', '%' . $search . '%'); } if ($date_from) $where[] = $wpdb->prepare("stats.date_created >= %s", $date_from . ' 00:00:00'); if ($date_to) $where[] = $wpdb->prepare("stats.date_created <= %s", $date_to . ' 23:59:59'); $where_sql = implode(' AND ', $where); // 2. Query to get the total count of UNIQUE customers in this scope $total_count = $wpdb->get_var(" SELECT COUNT(DISTINCT stats.customer_id) FROM $stats_table AS stats LEFT JOIN $lookup_table AS cust ON cust.customer_id = stats.customer_id WHERE $where_sql "); // 3. Main Query: Aggregate Data per Customer $offset = ($page - 1) * $per_page; $results = $wpdb->get_results($wpdb->prepare(" SELECT stats.customer_id, cust.email, CONCAT(cust.first_name, ' ', cust.last_name) as name, COUNT(stats.order_id) as total_orders, SUM(stats.net_total) as total_spent, MAX(stats.date_created) as last_order_date, MAX(stats.order_id) as last_order_id FROM $stats_table AS stats LEFT JOIN $lookup_table AS cust ON cust.customer_id = stats.customer_id WHERE $where_sql GROUP BY stats.customer_id HAVING total_spent >= %f AND total_orders >= %d ORDER BY total_spent DESC LIMIT %d OFFSET %d ", $min_spent, $min_orders, $per_page, $offset)); // 4. Calculate Aggregate Stats for the whole filtered scope (without limit) $agg_data = $wpdb->get_row(" SELECT SUM(stats.net_total) as total_revenue, COUNT(stats.order_id) as total_orders_all, COUNT(DISTINCT stats.customer_id) as total_filtered_customers FROM $stats_table AS stats LEFT JOIN $lookup_table AS cust ON cust.customer_id = stats.customer_id WHERE $where_sql "); // 5. Finalize Customers Data with Profit and Recent Items $processed_customers = []; $segments = ['champions' => 0, 'loyal' => 0, 'at_risk' => 0, 'dormant' => 0, 'new' => 0]; $total_profit_all = 0; foreach ($results as $row) { $order = wc_get_order($row->last_order_id); $items_raw = []; $profit = 0; $phone = ''; if ($order) { $phone = $order->get_billing_phone(); foreach ($order->get_items() as $item) { $p = $item->get_product(); $total_item = floatval($item->get_total()); if ($p) { $cost = floatval($p->get_meta('_cost_price')) ?: (floatval($p->get_price()) * 0.7); $profit += ($total_item - ($cost * $item->get_quantity())); } $items_raw[] = [ 'name' => $item->get_name(), 'qty' => $item->get_quantity(), 'total' => $total_item ]; } } $last_ts = strtotime($row->last_order_date); $days_since_last = floor((time() - $last_ts) / (60 * 60 * 24)); // Fetch Abandoned Cart Info for this customer $ab_table = $wpdb->prefix . 'woocommersa_abandoned_carts'; $abandoned_data = $wpdb->get_row($wpdb->prepare(" SELECT COUNT(*) as count, MAX(created_at) as last_date, MAX(id) as last_id FROM $ab_table WHERE (email = %s AND email != '') OR (phone = %s AND phone != '') ", $row->email, $phone)); $segment = 'new'; if ($days_since_last > 180) $segment = 'dormant'; elseif ($days_since_last > 90) $segment = 'at_risk'; elseif ($row->total_orders > 3) $segment = 'champions'; elseif ($row->total_orders > 1) $segment = 'loyal'; $segments[$segment]++; $total_profit_all += $profit; $processed_customers[] = [ 'email' => $row->email, 'phone' => $phone, 'name' => trim($row->name) ?: 'شناسه ' . $row->customer_id, 'total_orders' => (int)$row->total_orders, 'total_spent' => round((float)$row->total_spent, 2), 'total_profit' => round($profit, 2), 'avg_order_value' => $row->total_orders > 0 ? round($row->total_spent / $row->total_orders, 2) : 0, 'segment' => $segment, 'days_since_last' => $days_since_last, 'abandoned_count' => (int)($abandoned_data->count ?? 0), 'last_abandoned_date' => $abandoned_data->last_date ?? null, 'last_order' => [ 'id' => (int)$row->last_order_id, 'number' => $order ? $order->get_order_number() : '', 'date' => $row->last_order_date, 'status' => $order ? wc_get_order_status_name($order->get_status()) : '', 'total' => $order ? (float)$order->get_total() : 0, 'payment_method' => $order ? $order->get_payment_method_title() : '', 'tracking_code' => $order ? $order->get_meta('_tracking_code') : '', 'items_raw' => $items_raw ] ]; } // Quick segments count for ALL filtered customers to make the bar accurate $all_segments_sql = $wpdb->get_results(" SELECT stats.customer_id, COUNT(stats.order_id) as total_orders, MAX(stats.date_created) as last_order_date FROM $stats_table AS stats LEFT JOIN $lookup_table AS cust ON cust.customer_id = stats.customer_id WHERE $where_sql GROUP BY cust.customer_id "); $final_segments = ['champions' => 0, 'loyal' => 0, 'at_risk' => 0, 'dormant' => 0, 'new' => 0]; if (is_array($all_segments_sql)) { foreach ($all_segments_sql as $seg_row) { $ds = floor((time() - strtotime($seg_row->last_order_date)) / (60 * 60 * 24)); $s = 'new'; if ($ds > 180) $s = 'dormant'; elseif ($ds > 90) $s = 'at_risk'; elseif ($seg_row->total_orders > 3) $s = 'champions'; elseif ($seg_row->total_orders > 1) $s = 'loyal'; $final_segments[$s]++; } } return new \WP_REST_Response([ 'customers' => $processed_customers, 'total' => (int)$agg_data->total_filtered_customers, 'pages' => ceil($agg_data->total_filtered_customers / $per_page), 'stats' => [ 'revenue' => (float)$agg_data->total_revenue, 'profit' => $total_profit_all, // Paged profit for now, would need SQL join for full cost_price sum 'aov' => $agg_data->total_orders_all > 0 ? round($agg_data->total_revenue / $agg_data->total_orders_all, 0) : 0, 'returning_rate' => $agg_data->total_filtered_customers > 0 ? round(($final_segments['champions'] + $final_segments['loyal'] + $final_segments['at_risk'] + $final_segments['dormant']) / $agg_data->total_filtered_customers * 100, 1) : 0, 'segments' => $final_segments ] ], 200); } catch (\Throwable $e) { return new \WP_REST_Response(['success' => false, 'message' => $e->getMessage()], 500); } } public function export_customers($request) { global $wpdb; $params = $request->get_params(); $search = strtolower(sanitize_text_field($params['search'] ?? '')); $min_spent = isset($params['min_spent']) && $params['min_spent'] !== '' ? floatval($params['min_spent']) : 0; $min_orders = isset($params['min_orders']) && $params['min_orders'] !== '' ? intval($params['min_orders']) : 0; $date_from = isset($params['date_from']) ? sanitize_text_field($params['date_from']) : ''; $date_to = isset($params['date_to']) ? sanitize_text_field($params['date_to']) : ''; try { $lookup_table = $wpdb->prefix . 'wc_customer_lookup'; $stats_table = $wpdb->prefix . 'wc_order_stats'; $where = ["stats.status IN ('wc-completed', 'wc-processing')"]; if ($search) { $where[] = $wpdb->prepare("(cust.first_name LIKE %s OR cust.last_name LIKE %s OR cust.email LIKE %s OR cust.username LIKE %s)", '%' . $search . '%', '%' . $search . '%', '%' . $search . '%', '%' . $search . '%'); } if ($date_from) $where[] = $wpdb->prepare("stats.date_created >= %s", $date_from . ' 00:00:00'); if ($date_to) $where[] = $wpdb->prepare("stats.date_created <= %s", $date_to . ' 23:59:59'); $where_sql = implode(' AND ', $where); $results = $wpdb->get_results($wpdb->prepare(" SELECT stats.customer_id, cust.email, CONCAT(cust.first_name, ' ', cust.last_name) as name, COUNT(stats.order_id) as total_orders, SUM(stats.net_total) as total_spent, MAX(stats.date_created) as last_order_date, MAX(stats.order_id) as last_order_id FROM $stats_table AS stats LEFT JOIN $lookup_table AS cust ON cust.customer_id = stats.customer_id WHERE $where_sql GROUP BY stats.customer_id HAVING total_spent >= %f AND total_orders >= %d ORDER BY total_spent DESC ", $min_spent, $min_orders)); $data = []; if (is_array($results)) { foreach ($results as $row) { $order = wc_get_order($row->last_order_id); $phone = $order ? $order->get_billing_phone() : ''; $last_ts = strtotime($row->last_order_date); $ds = floor((time() - $last_ts) / (60 * 60 * 24)); $segment = 'new'; if ($ds > 180) $segment = 'dormant'; elseif ($ds > 90) $segment = 'at_risk'; elseif ($row->total_orders > 3) $segment = 'champions'; elseif ($row->total_orders > 1) $segment = 'loyal'; $data[] = [ 'name' => trim($row->name) ?: 'User ' . $row->customer_id, 'email' => $row->email, 'phone' => $phone, 'total_orders' => (int)$row->total_orders, 'total_spent' => (float)$row->total_spent, 'segment' => $segment, 'last_order_date' => $row->last_order_date ]; } } return new \WP_REST_Response(['success' => true, 'customers' => $data], 200); } catch (\Throwable $e) { return new \WP_REST_Response(['success' => false, 'message' => $e->getMessage()], 500); } } public function create_quick_coupon($request) { $params = $request->get_json_params(); if (empty($params)) $params = $request->get_params(); $email = sanitize_email($params['email'] ?? ''); $name = sanitize_text_field($params['name'] ?? 'User'); $percent = isset($params['percent']) ? max(1, min(100, intval($params['percent']))) : 15; if (!$email) { return new \WP_REST_Response(['success' => false, 'message' => 'Email is required.'], 400); } try { // Check if WC_Coupon exists if (!class_exists('WC_Coupon')) { return new \WP_REST_Response(['success' => false, 'message' => 'WooCommerce is not active.'], 500); } $code = 'MAGIC-' . strtoupper(wp_generate_password(6, false, false)); $coupon = new \WC_Coupon(); $coupon->set_code($code); $coupon->set_discount_type('percent'); $coupon->set_amount($percent); $coupon->set_description('Quick Magic Coupon for ' . $name . ' (' . $email . ')'); $coupon->set_email_restrictions([$email]); // Changed from set_customer_email $coupon->set_usage_limit(1); $coupon->set_individual_use(true); $expiry_date = date('Y-m-d', strtotime('+3 days')); $coupon->set_date_expires($expiry_date); $id = $coupon->save(); return new \WP_REST_Response([ 'success' => true, 'code' => $code, 'id' => $id, 'message' => 'کد تخفیف جدید با موفقیت ساخته شد.' ], 200); } catch (\Exception $e) { return new \WP_REST_Response(['success' => false, 'message' => $e->getMessage()], 500); } } public function send_coupon_sms($request) { $params = $request->get_json_params(); $code = sanitize_text_field($params['code'] ?? ''); $phone = sanitize_text_field($params['phone'] ?? ''); $name = sanitize_text_field($params['name'] ?? ''); if (!$code || !$phone) { return new \WP_REST_Response(['message' => 'اطلاعات ناقص است.'], 400); } $sms_service = new \WooCommersa\Services\SMSService(); // Assuming we have a pattern for 'coupon_delivery' $sent = $sms_service->send_notification($phone, 'coupon_delivery', [ 'name' => $name, 'code' => $code ]); if ($sent) { return new \WP_REST_Response(['success' => true, 'message' => 'پیامک ارسال شد.'], 200); } else { return new \WP_REST_Response(['success' => false, 'message' => 'خطا در ارسال پیامک. لطفاً تنظیمات درگاه و پترن را بررسی کنید.'], 200); } } public function get_ai_insight($request) { $params = $request->get_json_params(); $customer_email = sanitize_email($params['email'] ?? ''); if (!$customer_email) return new \WP_REST_Response(['insight' => 'دیتا کافی نیست.'], 400); // Fetch last 3 orders for context $orders = wc_get_orders([ 'billing_email' => $customer_email, 'limit' => 3, 'status' => 'completed' ]); $context = ""; foreach ($orders as $order) { foreach ($order->get_items() as $item) { $context .= $item->get_name() . ", "; } } // Use AI Service (I'll need to add a simple method for general chat or specific insights) // For now, let's pretend we generate a static but smart insights if AI is off $insight = "این مشتری به محصولات سبد خرید فعلی علاقهمند است. پیشنهاد میشود محصولات همرده را به او پیشنهاد دهید."; // Integration with AIService (if enabled) $ai = new \WooCommersa\Services\AIService(); $remote_insight = $ai->get_customer_profiling($context); if ($remote_insight) $insight = $remote_insight; return new \WP_REST_Response(['insight' => $insight], 200); } public function get_top_customers() { $orders = wc_get_orders(['limit' => -1, 'status' => 'completed']); $customers = []; foreach ($orders as $order) { $email = $order->get_billing_email(); if (!$email) continue; if (!isset($customers[$email])) { $customers[$email] = [ 'name' => $order->get_billing_first_name() . ' ' . $order->get_billing_last_name(), 'email' => $email, 'total_spent' => 0, 'order_count' => 0 ]; } $customers[$email]['total_spent'] += floatval($order->get_total()); $customers[$email]['order_count']++; } usort($customers, function($a, $b) { return $b['total_spent'] <=> $a['total_spent']; }); return new \WP_REST_Response(array_slice($customers, 0, 10), 200); } public function get_order_sources() { // Simplified source analysis return new \WP_REST_Response([ ['source' => 'Direct', 'count' => 45], ['source' => 'Google', 'count' => 30], ['source' => 'Instagram', 'count' => 25] ], 200); } }