- Fix: Marketing events now display in Staff notifications tab - Reorganize: Move Coupons to Marketing/Coupons for better organization - Add: Comprehensive email/phone validation with extensible filter hooks - Email validation with regex pattern (xxxx@xxxx.xx) - Phone validation with WhatsApp verification support - Filter hooks for external API integration (QuickEmailVerification, etc.) - Fix: Newsletter template routes now use centralized notification email builder - Add: Validation.php class for reusable validation logic - Add: VALIDATION_HOOKS.md documentation with integration examples - Add: NEWSLETTER_CAMPAIGN_PLAN.md architecture for future campaign system - Fix: API delete method call in Newsletter.tsx (delete -> del) - Remove: Duplicate EmailTemplates.tsx (using notification system instead) - Update: Newsletter controller to use centralized Validation class Breaking changes: - Coupons routes moved from /routes/Coupons to /routes/Marketing/Coupons - Legacy /coupons routes maintained for backward compatibility
209 lines
5.7 KiB
PHP
209 lines
5.7 KiB
PHP
<?php
|
|
/**
|
|
* Customer Settings Provider
|
|
*
|
|
* Provides customer-related settings including VIP qualification criteria.
|
|
*
|
|
* @package WooNooW
|
|
*/
|
|
|
|
namespace WooNooW\Compat;
|
|
|
|
class CustomerSettingsProvider {
|
|
|
|
/**
|
|
* Get customer settings
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function get_settings() {
|
|
return [
|
|
// General
|
|
'auto_register_members' => get_option('woonoow_auto_register_members', 'no') === 'yes',
|
|
'multiple_addresses_enabled' => get_option('woonoow_multiple_addresses_enabled', 'yes') === 'yes',
|
|
'wishlist_enabled' => get_option('woonoow_wishlist_enabled', 'yes') === 'yes',
|
|
|
|
// VIP Customer Qualification
|
|
'vip_min_spent' => floatval(get_option('woonoow_vip_min_spent', 1000)),
|
|
'vip_min_orders' => intval(get_option('woonoow_vip_min_orders', 10)),
|
|
'vip_timeframe' => get_option('woonoow_vip_timeframe', 'all'), // all, 30, 90, 365
|
|
'vip_require_both' => get_option('woonoow_vip_require_both', 'yes') === 'yes',
|
|
'vip_exclude_refunded' => get_option('woonoow_vip_exclude_refunded', 'yes') === 'yes',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Update customer settings
|
|
*
|
|
* @param array $settings
|
|
* @return bool
|
|
*/
|
|
public static function update_settings($settings) {
|
|
// General settings
|
|
if (array_key_exists('auto_register_members', $settings)) {
|
|
$value = !empty($settings['auto_register_members']) ? 'yes' : 'no';
|
|
update_option('woonoow_auto_register_members', $value);
|
|
}
|
|
|
|
if (array_key_exists('multiple_addresses_enabled', $settings)) {
|
|
$value = !empty($settings['multiple_addresses_enabled']) ? 'yes' : 'no';
|
|
update_option('woonoow_multiple_addresses_enabled', $value);
|
|
}
|
|
|
|
if (array_key_exists('wishlist_enabled', $settings)) {
|
|
$value = !empty($settings['wishlist_enabled']) ? 'yes' : 'no';
|
|
update_option('woonoow_wishlist_enabled', $value);
|
|
}
|
|
|
|
// VIP settings
|
|
if (isset($settings['vip_min_spent'])) {
|
|
update_option('woonoow_vip_min_spent', floatval($settings['vip_min_spent']));
|
|
}
|
|
|
|
if (isset($settings['vip_min_orders'])) {
|
|
update_option('woonoow_vip_min_orders', intval($settings['vip_min_orders']));
|
|
}
|
|
|
|
if (isset($settings['vip_timeframe'])) {
|
|
$timeframe = in_array($settings['vip_timeframe'], ['all', '30', '90', '365'])
|
|
? $settings['vip_timeframe']
|
|
: 'all';
|
|
update_option('woonoow_vip_timeframe', $timeframe);
|
|
}
|
|
|
|
if (array_key_exists('vip_require_both', $settings)) {
|
|
$value = !empty($settings['vip_require_both']) ? 'yes' : 'no';
|
|
update_option('woonoow_vip_require_both', $value);
|
|
}
|
|
|
|
if (array_key_exists('vip_exclude_refunded', $settings)) {
|
|
$value = !empty($settings['vip_exclude_refunded']) ? 'yes' : 'no';
|
|
update_option('woonoow_vip_exclude_refunded', $value);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Check if a customer is VIP based on current settings
|
|
*
|
|
* @param int $customer_id
|
|
* @return bool
|
|
*/
|
|
public static function is_vip_customer($customer_id) {
|
|
if (!$customer_id || $customer_id <= 0) {
|
|
return false;
|
|
}
|
|
|
|
$settings = self::get_settings();
|
|
|
|
// Build query args
|
|
$query_args = [
|
|
'customer_id' => $customer_id,
|
|
'status' => ['wc-completed', 'wc-processing'],
|
|
'limit' => -1, // Get all orders
|
|
];
|
|
|
|
// Apply timeframe filter
|
|
if ($settings['vip_timeframe'] !== 'all') {
|
|
$days = intval($settings['vip_timeframe']);
|
|
$query_args['date_created'] = '>' . date('Y-m-d', strtotime("-{$days} days"));
|
|
}
|
|
|
|
// Exclude refunded orders if setting is enabled
|
|
if ($settings['vip_exclude_refunded']) {
|
|
$query_args['status'] = array_diff($query_args['status'], ['wc-refunded']);
|
|
}
|
|
|
|
// Get orders
|
|
$orders = wc_get_orders($query_args);
|
|
|
|
// Calculate totals
|
|
$total_spent = 0;
|
|
$order_count = count($orders);
|
|
|
|
foreach ($orders as $order) {
|
|
$total_spent += floatval($order->get_total());
|
|
}
|
|
|
|
// Check qualification
|
|
$meets_spent = $total_spent >= $settings['vip_min_spent'];
|
|
$meets_orders = $order_count >= $settings['vip_min_orders'];
|
|
|
|
if ($settings['vip_require_both']) {
|
|
// Must meet both criteria
|
|
return $meets_spent && $meets_orders;
|
|
} else {
|
|
// Must meet at least one criterion
|
|
return $meets_spent || $meets_orders;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get VIP customer stats for a customer
|
|
*
|
|
* @param int $customer_id
|
|
* @return array
|
|
*/
|
|
public static function get_vip_stats($customer_id) {
|
|
if (!$customer_id || $customer_id <= 0) {
|
|
return [
|
|
'is_vip' => false,
|
|
'total_spent' => 0,
|
|
'order_count' => 0,
|
|
'meets_spent' => false,
|
|
'meets_orders' => false,
|
|
];
|
|
}
|
|
|
|
$settings = self::get_settings();
|
|
|
|
// Build query args
|
|
$query_args = [
|
|
'customer_id' => $customer_id,
|
|
'status' => ['wc-completed', 'wc-processing'],
|
|
'limit' => -1,
|
|
];
|
|
|
|
// Apply timeframe filter
|
|
if ($settings['vip_timeframe'] !== 'all') {
|
|
$days = intval($settings['vip_timeframe']);
|
|
$query_args['date_created'] = '>' . date('Y-m-d', strtotime("-{$days} days"));
|
|
}
|
|
|
|
// Exclude refunded if enabled
|
|
if ($settings['vip_exclude_refunded']) {
|
|
$query_args['status'] = array_diff($query_args['status'], ['wc-refunded']);
|
|
}
|
|
|
|
// Get orders
|
|
$orders = wc_get_orders($query_args);
|
|
|
|
// Calculate totals
|
|
$total_spent = 0;
|
|
$order_count = count($orders);
|
|
|
|
foreach ($orders as $order) {
|
|
$total_spent += floatval($order->get_total());
|
|
}
|
|
|
|
// Check criteria
|
|
$meets_spent = $total_spent >= $settings['vip_min_spent'];
|
|
$meets_orders = $order_count >= $settings['vip_min_orders'];
|
|
|
|
$is_vip = $settings['vip_require_both']
|
|
? ($meets_spent && $meets_orders)
|
|
: ($meets_spent || $meets_orders);
|
|
|
|
return [
|
|
'is_vip' => $is_vip,
|
|
'total_spent' => $total_spent,
|
|
'order_count' => $order_count,
|
|
'meets_spent' => $meets_spent,
|
|
'meets_orders' => $meets_orders,
|
|
'required_spent' => $settings['vip_min_spent'],
|
|
'required_orders' => $settings['vip_min_orders'],
|
|
];
|
|
}
|
|
}
|