<?php
|
namespace JVBase\rest\routes;
|
|
use JVBase\importers\JaneAppClientImporter;
|
use JVBase\managers\JaneSalesImporter;
|
use JVBase\managers\MagicLinkManager;
|
use JVBase\rest\RestRouteManager;
|
use WP_REST_Request;
|
use WP_REST_Response;
|
use WP_Error;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
/**
|
* REST API routes for referral system
|
*/
|
class ReferralRoutes extends RestRouteManager
|
{
|
protected string $referrals_table;
|
protected string $rewards_table;
|
protected $wpdb;
|
|
public function __construct()
|
{
|
$this->route = 'referrals';
|
$this->cache_name = 'referrals';
|
parent::__construct();
|
|
global $wpdb;
|
$this->wpdb = $wpdb;
|
$this->referrals_table = $wpdb->prefix . BASE . 'referrals';
|
$this->rewards_table = $wpdb->prefix . BASE . 'referral_rewards';
|
|
add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
|
}
|
|
public function registerRoutes(): void
|
{
|
/**
|
* Main referrals endpoint
|
* GET: List referrals with filters
|
* POST: Perform actions (invite, consulted, treated, remove, resend)
|
*/
|
register_rest_route($this->namespace, "/{$this->route}", [
|
[
|
'methods' => 'GET',
|
'callback' => [$this, 'getReferrals'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'user' => ['type' => 'integer', 'sanitize_callback' => 'absint'],
|
'status' => ['type' => 'string', 'enum' => ['all', 'pending', 'consulted', 'treated', 'unused', 'registered', 'completed']],
|
'date_start' => ['type' => 'string'],
|
'date_end' => ['type' => 'string'],
|
'limit' => ['type' => 'integer', 'default' => 50],
|
'offset' => ['type' => 'integer', 'default' => 0],
|
'format' => ['type' => 'string', 'enum' => ['simple', 'formatted'], 'default' => 'formatted'],
|
'search' => ['type' => 'string']
|
]
|
],
|
[
|
'methods' => 'POST',
|
'callback' => [$this, 'handleAction'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'action' => [
|
'required' => true,
|
'type' => 'string',
|
'enum' => ['invite', 'consulted', 'treated', 'remove', 'resend']
|
]
|
]
|
]
|
]);
|
|
/**
|
* Referral code endpoint
|
* GET: Get user's referral code
|
* POST: Validate a referral code
|
*/
|
register_rest_route($this->namespace, "/{$this->route}/code", [
|
[
|
'methods' => 'GET',
|
'callback' => [$this, 'getCode'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'user' => ['type' => 'integer', 'sanitize_callback' => 'absint']
|
]
|
],
|
[
|
'methods' => 'POST',
|
'callback' => [$this, 'validateCode'],
|
'permission_callback' => '__return_true', // Public endpoint
|
'args' => [
|
'code' => ['required' => true, 'type' => 'string']
|
]
|
]
|
]);
|
|
/**
|
* Stats endpoint
|
* GET: Get user's referral statistics
|
*/
|
register_rest_route($this->namespace, "/{$this->route}/stats", [
|
'methods' => 'GET',
|
'callback' => [$this, 'getStats'],
|
'permission_callback' => [$this, 'checkPermission'],
|
'args' => [
|
'user' => ['type' => 'integer', 'sanitize_callback' => 'absint'],
|
]
|
]);
|
|
/**
|
* Settings endpoint (admin only)
|
*/
|
register_rest_route($this->namespace, "/{$this->route}/settings", [
|
[
|
'methods' => 'GET',
|
'callback' => [$this, 'getSettings'],
|
'permission_callback' => [$this, 'checkAdminPermission']
|
],
|
[
|
'methods' => 'POST',
|
'callback' => [$this, 'updateSettings'],
|
'permission_callback' => [$this, 'checkAdminPermission']
|
]
|
]);
|
|
/**
|
* CSV Upload endpoints (admin only)
|
*/
|
register_rest_route($this->namespace, "/{$this->route}/upload-clients", [
|
'methods' => 'POST',
|
'callback' => [$this, 'handleClientUpload'],
|
'permission_callback' => [$this, 'checkAdminPermission']
|
]);
|
|
register_rest_route($this->namespace, "/{$this->route}/upload-sales", [
|
'methods' => 'POST',
|
'callback' => [$this, 'handleSalesUpload'],
|
'permission_callback' => [$this, 'checkAdminPermission']
|
]);
|
}
|
|
/**
|
* GET /referrals
|
* Get referrals with optional filters
|
* - User gets their own referrals
|
* - Admin with no user param gets all referrals
|
*/
|
public function getReferrals(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = $request->get_param('user');
|
|
// Determine scope
|
if (!$user_id) {
|
$current_user_id = get_current_user_id();
|
$is_admin = current_user_can('manage_options');
|
if ($is_admin) {
|
// Admin with no user param = get all referrals
|
return $this->getAllReferrals($request);
|
}
|
$user_id = $current_user_id;
|
}
|
|
|
// Get user's referrals
|
$args = [
|
'status' => $request->get_param('status') ?? 'all',
|
'limit' => $request->get_param('limit') ?? 50,
|
'offset' => $request->get_param('offset') ?? 0,
|
'date_start' => $request->get_param('date_start'),
|
'date_end' => $request->get_param('date_end'),
|
];
|
|
$cache_key = "ref_{$user_id}_" . md5(serialize($args));
|
// Check headers for 304 Not Modified
|
$cache_check = $this->checkHeaders($request, $cache_key);
|
if ($cache_check instanceof WP_REST_Response) {
|
return $cache_check; // Returns 304 if not modified
|
}
|
|
$referrals = JVB()->referrals()->getUserReferrals($user_id, $args);
|
|
$data = [
|
'items' => $referrals,
|
'total' => count($referrals)
|
];
|
|
// Create response with cache headers
|
$response = $this->success($data);
|
|
// Add ETag and Last-Modified headers
|
return $this->addCacheHeaders($response, $cache_key, $data);
|
}
|
|
/**
|
* POST /referrals
|
* Handle various referral actions based on 'action' parameter
|
*/
|
public function handleAction(WP_REST_Request $request): WP_REST_Response
|
{
|
$action = $request->get_param('action');
|
|
return match($action) {
|
'invite' => $this->actionInvite($request),
|
'consulted' => $this->actionUpdateStatus($request, 'consulted'),
|
'treated' => $this->actionUpdateStatus($request, 'treated'),
|
'remove' => $this->actionRemove($request),
|
'resend' => $this->actionResend($request),
|
default => $this->error('Invalid action', 'invalid_action', 400)
|
};
|
}
|
|
/**
|
* Action: Send batch referral invitations
|
*/
|
protected function actionInvite(WP_REST_Request $request): WP_REST_Response
|
{
|
$data = $request->get_params();
|
error_log('Send Referral Invitations:'.print_r($data, true));
|
$user = absint($request->get_param('user'));
|
if (!$this->checkUser($user)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'No user found'
|
]);
|
}
|
$subject = sanitize_text_field($request->get_param('subject'));
|
$message = sanitize_textarea_field($request->get_param('message'));
|
$invitations = $request->get_param('invite');
|
|
// Validate invitation format
|
foreach ($invitations as $key => $invite) {
|
if (!array_key_exists('name', $invite) || !array_key_exists('email', $invite)) {
|
unset($invitations[$key]);
|
} else {
|
$temp = [
|
'name' => sanitize_text_field($invite['name']),
|
'email' => sanitize_email($invite['email'])
|
];
|
$invitations[$key] = $temp;
|
}
|
}
|
|
$operationID = sanitize_text_field($request->get_param('id'));
|
$operation = JVB()->queue()->queueOperation(
|
'referral_invite',
|
$user,
|
[
|
'subject' => $subject,
|
'message' => $message,
|
'invitations' => $invitations
|
],
|
[
|
'operation_id' => $operationID
|
]
|
);
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Queued for Processing',
|
'operation' => $operationID
|
]);
|
}
|
|
/**
|
* Action: Update referral status (admin only)
|
*/
|
protected function actionUpdateStatus(WP_REST_Request $request, string $status): WP_REST_Response
|
{
|
if (!current_user_can('manage_options')) {
|
return $this->error('Admin permission required', 'unauthorized', 403);
|
}
|
|
$referral_id = $request->get_param('referral_id');
|
if (!$referral_id) {
|
return $this->error('referral_id required', 'missing_id', 400);
|
}
|
|
$referral = $this->wpdb->get_row($this->wpdb->prepare(
|
"SELECT * FROM {$this->referrals_table} WHERE id = %d",
|
$referral_id
|
));
|
|
if (!$referral) {
|
return $this->error('Referral not found', 'not_found', 404);
|
}
|
|
// Update status
|
$update_data = ['status' => $status];
|
$update_data["{$status}_at"] = current_time('mysql');
|
|
if ($status === 'treated') {
|
$update_data['treatment_count'] = ($referral->treatment_count ?? 0) + 1;
|
}
|
|
$updated = $this->wpdb->update(
|
$this->referrals_table,
|
$update_data,
|
['id' => $referral_id],
|
array_fill(0, count($update_data), '%s'),
|
['%d']
|
);
|
|
|
|
if ($updated) {
|
// Also create rewards if treated
|
if ($status === 'treated') {
|
$this->createRewards($referral);
|
}
|
}
|
|
$this->cache->clear();
|
|
return $this->success(['message' => "Referral marked as {$status}"]);
|
}
|
|
/**
|
* Action: Remove referral
|
*/
|
protected function actionRemove(WP_REST_Request $request): WP_REST_Response
|
{
|
$referral_id = $request->get_param('referral_id');
|
if (!$referral_id) {
|
return $this->error('referral_id required', 'missing_id', 400);
|
}
|
|
$referral = $this->wpdb->get_row($this->wpdb->prepare(
|
"SELECT * FROM {$this->referrals_table} WHERE id = %d",
|
$referral_id
|
));
|
|
if (!$referral) {
|
return $this->error('Referral not found', 'not_found', 404);
|
}
|
|
// Check ownership
|
$current_user_id = get_current_user_id();
|
if ($referral->referrer_id != $current_user_id && !current_user_can('manage_options')) {
|
return $this->error('Unauthorized', 'unauthorized', 403);
|
}
|
|
// Can only remove pending referrals
|
if ($referral->status !== 'pending') {
|
return $this->error('Can only remove pending referrals', 'invalid_status', 400);
|
}
|
|
$this->wpdb->delete($this->referrals_table, ['id' => $referral_id], ['%d']);
|
$this->cache->clear();
|
|
return $this->success(['message' => 'Referral removed']);
|
}
|
|
/**
|
* Action: Resend invitation
|
*/
|
protected function actionResend(WP_REST_Request $request): WP_REST_Response
|
{
|
$referral_id = $request->get_param('referral_id');
|
if (!$referral_id) {
|
return $this->error('referral_id required', 'missing_id', 400);
|
}
|
|
$current_user_id = get_current_user_id();
|
$referral = $this->wpdb->get_row($this->wpdb->prepare(
|
"SELECT * FROM {$this->referrals_table} WHERE id = %d AND referrer_id = %d",
|
$referral_id,
|
$current_user_id
|
));
|
|
if (!$referral) {
|
return $this->error('Referral not found', 'not_found', 404);
|
}
|
|
// Check rate limit (once per week)
|
$transient_key = 'referral_last_invite_' . md5($referral->referee_email);
|
$last_invite = get_transient($transient_key);
|
|
if ($last_invite && (time() - $last_invite) < WEEK_IN_SECONDS) {
|
return $this->error(
|
'Can only resend once per week',
|
'rate_limit',
|
429
|
);
|
}
|
|
// Resend via referral manager
|
$result = JVB()->referrals()->sendReferralInvitation(
|
$current_user_id,
|
$referral->referee_email,
|
$referral->referee_name,
|
sprintf('Reminder: Join %s', get_bloginfo('name')),
|
'Just a friendly reminder about my invitation!'
|
);
|
|
if (is_wp_error($result)) {
|
return $this->error($result->get_error_message(), 'send_failed', 500);
|
}
|
|
// Set rate limit
|
set_transient($transient_key, time(), WEEK_IN_SECONDS);
|
|
return $this->success(['message' => 'Invitation resent']);
|
}
|
|
/**
|
* GET /referrals/code
|
* Get user's referral code
|
*/
|
public function getCode(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = $request->get_param('user') ?? get_current_user_id();
|
|
// Check permission
|
if ($user_id != get_current_user_id() && !current_user_can('manage_options')) {
|
return $this->error('Unauthorized', 'unauthorized', 403);
|
}
|
|
$code = JVB()->referrals()->getUserReferralCode($user_id);
|
|
if (is_wp_error($code)) {
|
return $this->error($code->get_error_message(), 'code_error', 400);
|
}
|
|
return $this->success([
|
'code' => $code,
|
'share_url' => home_url('/?ref=' . $code)
|
]);
|
}
|
|
/**
|
* POST /referrals/code
|
* Validate a referral code
|
*/
|
public function validateCode(WP_REST_Request $request): WP_REST_Response
|
{
|
$code = strtoupper(sanitize_text_field($request->get_param('code')));
|
|
if (empty($code)) {
|
return $this->error('Code required', 'missing_code', 400);
|
}
|
|
$referrer = JVB()->referrals()->getUserByReferralCode($code);
|
|
if (!$referrer) {
|
return $this->error('Invalid referral code', 'invalid_code', 404);
|
}
|
|
// Check self-referral
|
if (is_user_logged_in() && get_current_user_id() === $referrer->ID) {
|
return $this->error('Cannot use your own referral code', 'self_referral', 400);
|
}
|
|
return $this->success([
|
'valid' => true,
|
'code' => $code,
|
'referrer_name' => $referrer->display_name
|
]);
|
}
|
|
/**
|
* GET /referrals/stats
|
* Get user's referral statistics
|
*/
|
public function getStats(WP_REST_Request $request): WP_REST_Response
|
{
|
$user_id = $request->get_param('user');
|
|
$cache_key = "stats_{$user_id}";
|
|
// Check for 304 Not Modified
|
$cache_check = $this->checkHeaders($request, $cache_key);
|
if ($cache_check instanceof WP_REST_Response) {
|
return $cache_check;
|
}
|
|
$stats = JVB()->referrals()->getUserStats($user_id);
|
|
$response = $this->success(['items' => [$stats]]);
|
|
// Add cache headers (5 minutes for stats)
|
return $this->addCacheHeaders($response, $cache_key, $stats, 5 * MINUTE_IN_SECONDS);
|
}
|
|
/**
|
* GET /referrals/settings
|
*/
|
public function getSettings(WP_REST_Request $request): WP_REST_Response
|
{
|
$settings = JVB()->referrals()->getRewardSettings();
|
return $this->success(['settings' => $settings]);
|
}
|
|
/**
|
* POST /referrals/settings
|
*/
|
public function updateSettings(WP_REST_Request $request): WP_REST_Response
|
{
|
$settings = [
|
'referrer_reward_type' => $request->get_param('referrer_reward_type') ?? 'fixed',
|
'referrer_reward_amount' => floatval($request->get_param('referrer_reward_amount') ?? 25),
|
'referrer_reward_applies_to' => $request->get_param('referrer_reward_applies_to') ?? 'per_user',
|
'referee_reward_type' => $request->get_param('referee_reward_type') ?? 'percentage',
|
'referee_reward_amount' => floatval($request->get_param('referee_reward_amount') ?? 20),
|
'referee_reward_applies_to' => $request->get_param('referee_reward_applies_to') ?? 'first_order'
|
];
|
|
update_option(BASE . 'referral_settings', $settings);
|
$this->cache->clear();
|
|
return $this->success([
|
'message' => 'Settings updated',
|
'settings' => $settings
|
]);
|
}
|
|
/**
|
* Helper: Get all referrals (admin only)
|
*/
|
protected function getAllReferrals(WP_REST_Request $request): WP_REST_Response
|
{
|
$where = ['1=1'];
|
$where_params = [];
|
|
$status = $request->get_param('status');
|
if ($status && $status !== 'all') {
|
$where[] = 'status = %s';
|
$where_params[] = $status;
|
}
|
|
if ($date_start = $request->get_param('date_start')) {
|
$where[] = 'referred_at >= %s';
|
$where_params[] = $date_start;
|
}
|
|
if ($date_end = $request->get_param('date_end')) {
|
$where[] = 'referred_at <= %s';
|
$where_params[] = $date_end;
|
}
|
|
$search = $request->get_param('search');
|
if (!empty($search)) {
|
$search_term = '%' . $this->wpdb->esc_like($search) . '%';
|
$where[] = '(r.referee_name LIKE %s OR r.referee_email LIKE %s OR r.referral_code LIKE %s OR u.display_name LIKE %s OR ru.display_name LIKE %s OR ru.user_email LIKE %s)';
|
$where_params[] = $search_term;
|
$where_params[] = $search_term;
|
$where_params[] = $search_term;
|
$where_params[] = $search_term;
|
$where_params[] = $search_term;
|
$where_params[] = $search_term;
|
}
|
|
$limit = $request->get_param('limit') ?? 50;
|
$offset = $request->get_param('offset') ?? 0;
|
|
$where_params[] = $limit;
|
$where_params[] = $offset;
|
|
$query = "SELECT r.*, u.display_name as referrer_name
|
FROM {$this->referrals_table} r
|
LEFT JOIN {$this->wpdb->users} u ON r.referrer_id = u.ID
|
WHERE " . implode(' AND ', $where) . "
|
ORDER BY referred_at DESC
|
LIMIT %d OFFSET %d";
|
|
$items = $this->wpdb->get_results($this->wpdb->prepare($query, $where_params));
|
|
error_log('All Referrals result: '.print_r($items, true));
|
return $this->success([
|
'items' => $items,
|
'total' => count($items)
|
]);
|
}
|
|
/**
|
* Helper: Create rewards for completed referral
|
*/
|
protected function createRewards(object $referral): void
|
{
|
$settings = JVB()->referrals()->getRewardSettings();
|
|
// Referrer reward
|
$this->wpdb->insert(
|
$this->rewards_table,
|
[
|
'referral_id' => $referral->id,
|
'user_id' => $referral->referrer_id,
|
'reward_type' => 'referrer',
|
'amount' => $settings['referrer_reward_amount'],
|
'reward_calculation' => $settings['referrer_reward_type'],
|
'status' => 'available',
|
'created_at' => current_time('mysql')
|
],
|
['%d', '%d', '%s', '%f', '%s', '%s', '%s']
|
);
|
|
// Referee reward
|
if ($referral->referee_id) {
|
$this->wpdb->insert(
|
$this->rewards_table,
|
[
|
'referral_id' => $referral->id,
|
'user_id' => $referral->referee_id,
|
'reward_type' => 'referee',
|
'amount' => $settings['referee_reward_amount'],
|
'reward_calculation' => $settings['referee_reward_type'],
|
'status' => 'available',
|
'created_at' => current_time('mysql')
|
],
|
['%d', '%d', '%s', '%f', '%s', '%s', '%s']
|
);
|
}
|
}
|
|
/**
|
* Check admin permission
|
*/
|
public function checkAdminPermission(WP_REST_Request $request): bool
|
{
|
return current_user_can('manage_options') && parent::checkPermission($request);
|
}
|
|
/**
|
* Process queued referral operations
|
*/
|
public function processOperation(WP_Error|array $result, object $operation, array $data): array|WP_Error
|
{
|
if ($operation->type !== 'referral_invite') {
|
return $result;
|
}
|
|
$result = JVB()->referrals()->sendBatchReferralInvitations(
|
$operation->user_id,
|
$data['invitations'],
|
$data['subject'],
|
$data['message']
|
);
|
if ($result['success']) {
|
$this->cache->clear();
|
}
|
|
// Build summary message
|
$textResult = 'Sent invitations. ';
|
$textResult .= 'Success: ' . count($result['result']['success']) . '. ';
|
$textResult .= 'Failed: ' . count($result['result']['failed']) . '.';
|
|
return [
|
'success' => true,
|
'message' => $textResult,
|
'details' => [
|
'successful' => $result['result']['success'],
|
'failed' => $result['result']['failed'],
|
'total' => count($data['invitations'])
|
]
|
];
|
}
|
|
/**
|
* Handle client CSV upload
|
*/
|
public function handleClientUpload(WP_REST_Request $request): WP_REST_Response
|
{
|
// Access files from $_FILES directly for REST API uploads
|
if (empty($_FILES['file'])) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'No file uploaded'
|
], 400);
|
}
|
|
$file = $_FILES['file'];
|
|
// Check for upload errors
|
if ($file['error'] !== UPLOAD_ERR_OK) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File upload error: ' . $file['error']
|
], 400);
|
}
|
|
// Validate file type
|
$allowed_types = ['text/csv', 'application/vnd.ms-excel', 'text/plain'];
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
$mime_type = finfo_file($finfo, $file['tmp_name']);
|
finfo_close($finfo);
|
|
if (!in_array($mime_type, $allowed_types) && !in_array($file['type'], $allowed_types)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File must be a CSV'
|
], 400);
|
}
|
|
// Validate file size (10MB max)
|
if ($file['size'] > 10 * 1024 * 1024) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File size exceeds 10MB limit'
|
], 400);
|
}
|
|
// Import using JaneAppClientImporter
|
$importer = new JaneAppClientImporter();
|
$default_role = get_option(BASE . 'referral_role', JVB_USER);
|
|
$options = [
|
'update_existing' => true,
|
'send_welcome_email' => false,
|
'create_users' => true,
|
'default_role' => $default_role
|
];
|
|
$result = $importer->importFromCSV($file['tmp_name'], $options);
|
|
if (is_wp_error($result)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => $result->get_error_message()
|
], 500);
|
}
|
|
// Build detailed message
|
$message = sprintf(
|
'Import complete: %d created, %d updated, %d skipped',
|
$result['created'],
|
$result['updated'],
|
$result['skipped']
|
);
|
|
$details = [];
|
if (!empty($result['skipped_details'])) {
|
$details = $result['skipped_details'];
|
}
|
|
// Clear cache
|
$this->cache->clear();
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => $message,
|
'stats' => $result,
|
'skipped_details' => $details
|
]);
|
}
|
|
/**
|
* Handle sales CSV upload
|
*/
|
public function handleSalesUpload(WP_REST_Request $request): WP_REST_Response
|
{
|
// Access files from $_FILES directly for REST API uploads
|
if (empty($_FILES['file'])) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'No file uploaded'
|
], 400);
|
}
|
|
$file = $_FILES['file'];
|
|
// Check for upload errors
|
if ($file['error'] !== UPLOAD_ERR_OK) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File upload error: ' . $file['error']
|
], 400);
|
}
|
|
// Validate file type
|
$allowed_types = ['text/csv', 'application/vnd.ms-excel', 'text/plain'];
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
$mime_type = finfo_file($finfo, $file['tmp_name']);
|
finfo_close($finfo);
|
|
if (!in_array($mime_type, $allowed_types) && !in_array($file['type'], $allowed_types)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File must be a CSV'
|
], 400);
|
}
|
|
// Validate file size (10MB max)
|
if ($file['size'] > 10 * 1024 * 1024) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => 'File size exceeds 10MB limit'
|
], 400);
|
}
|
|
// Import using JaneSalesImporter
|
$importer = new JaneSalesImporter();
|
$options = [
|
'skip_existing' => true
|
];
|
|
$result = $importer->importFromCSV($file['tmp_name'], $options);
|
|
if (is_wp_error($result)) {
|
return new WP_REST_Response([
|
'success' => false,
|
'message' => $result->get_error_message()
|
], 500);
|
}
|
|
// Clear cache
|
$this->cache->clear();
|
|
return new WP_REST_Response([
|
'success' => true,
|
'message' => 'Sales imported successfully',
|
'stats' => $result
|
]);
|
}
|
}
|