feat: Move customer registration to site-level setting

Moved 'Register as site member' from order-level to site-level setting

Frontend Changes:
1. Customer Settings - Added new General section
   - Auto-register customers as site members toggle
   - Clear description of functionality
   - Saved to backend via existing API

2. OrderForm - Removed checkbox
   - Removed registerAsMember state
   - Removed checkbox UI
   - Removed register_as_member from payload
   - Backend now uses site setting

Backend Changes:
1. CustomerSettingsProvider.php
   - Added auto_register_members setting
   - Default: false (no)
   - Stored as woonoow_auto_register_members option
   - Included in get_settings()
   - Handled in update_settings()

2. OrdersController.php
   - Removed register_as_member parameter
   - Now reads from CustomerSettingsProvider
   - Site-level setting applies to all orders
   - Consistent behavior across all order creation

Benefits:
 Site-level control (not per-order)
 Consistent customer experience
 Easier to manage (one setting)
 No UI clutter in order form
 Setting persists across all orders

Migration:
- Old orders with checkbox: No impact
- New orders: Use site setting
- Default: Disabled (safe default)

Result:
Admins can now control customer registration site-wide from Customer Settings instead of per-order checkbox
This commit is contained in:
dwindown
2025-11-20 20:40:43 +07:00
parent e8ca3ceeb2
commit c8bba9a91b
4 changed files with 28 additions and 26 deletions

View File

@@ -181,7 +181,6 @@ export default function OrderForm({
const [paymentMethod, setPaymentMethod] = React.useState(initial?.payment_method_id || initial?.payment_method || ''); const [paymentMethod, setPaymentMethod] = React.useState(initial?.payment_method_id || initial?.payment_method || '');
const [shippingMethod, setShippingMethod] = React.useState(initial?.shipping_method_id || initial?.shipping_method || ''); const [shippingMethod, setShippingMethod] = React.useState(initial?.shipping_method_id || initial?.shipping_method || '');
const [note, setNote] = React.useState(initial?.customer_note || ''); const [note, setNote] = React.useState(initial?.customer_note || '');
const [registerAsMember, setRegisterAsMember] = React.useState(false);
const [selectedCustomerId, setSelectedCustomerId] = React.useState<number | null>(null); const [selectedCustomerId, setSelectedCustomerId] = React.useState<number | null>(null);
const [submitting, setSubmitting] = React.useState(false); const [submitting, setSubmitting] = React.useState(false);
@@ -452,7 +451,6 @@ export default function OrderForm({
payment_method: paymentMethod || undefined, payment_method: paymentMethod || undefined,
shipping_method: shippingMethod || undefined, shipping_method: shippingMethod || undefined,
customer_note: note || undefined, customer_note: note || undefined,
register_as_member: registerAsMember,
items: itemsEditable ? items : undefined, items: itemsEditable ? items : undefined,
coupons: showCoupons ? validatedCoupons.map(c => c.code) : undefined, coupons: showCoupons ? validatedCoupons.map(c => c.code) : undefined,
}; };
@@ -1047,9 +1045,8 @@ export default function OrderForm({
} }
} }
// Mark customer as selected (hide register checkbox) // Mark customer as selected
setSelectedCustomerId(data.user_id); setSelectedCustomerId(data.user_id);
setRegisterAsMember(false);
} }
} catch (e) { } catch (e) {
console.error('Customer autofill error:', e); console.error('Customer autofill error:', e);
@@ -1287,27 +1284,6 @@ export default function OrderForm({
<Textarea value={note} onChange={e=>setNote(e.target.value)} placeholder={__('Write a note for this order…')} /> <Textarea value={note} onChange={e=>setNote(e.target.value)} placeholder={__('Write a note for this order…')} />
</div> </div>
{/* Register as member checkbox (only for new orders and when no existing customer selected) */}
{mode === 'create' && !selectedCustomerId && (
<div className="rounded border p-4">
<div className="flex items-start gap-2">
<Checkbox
id="register_member"
checked={registerAsMember}
onCheckedChange={(v) => setRegisterAsMember(Boolean(v))}
/>
<div className="flex-1">
<Label htmlFor="register_member" className="cursor-pointer">
{__('Register customer as site member')}
</Label>
<p className="text-xs text-muted-foreground mt-1">
{__('Customer will receive login credentials via email and can track their orders.')}
</p>
</div>
</div>
</div>
)}
{!hideSubmitButton && ( {!hideSubmitButton && (
<Button type="submit" disabled={submitting} className="w-full"> <Button type="submit" disabled={submitting} className="w-full">
{submitting ? (mode === 'edit' ? __('Saving…') : __('Creating…')) : (mode === 'edit' ? __('Save changes') : __('Create order'))} {submitting ? (mode === 'edit' ? __('Saving…') : __('Creating…')) : (mode === 'edit' ? __('Save changes') : __('Create order'))}

View File

@@ -11,6 +11,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@
import { formatMoney, getStoreCurrency } from '@/lib/currency'; import { formatMoney, getStoreCurrency } from '@/lib/currency';
interface CustomerSettings { interface CustomerSettings {
auto_register_members: boolean;
vip_min_spent: number; vip_min_spent: number;
vip_min_orders: number; vip_min_orders: number;
vip_timeframe: 'all' | '30' | '90' | '365'; vip_timeframe: 'all' | '30' | '90' | '365';
@@ -20,6 +21,7 @@ interface CustomerSettings {
export default function CustomersSettings() { export default function CustomersSettings() {
const [settings, setSettings] = useState<CustomerSettings>({ const [settings, setSettings] = useState<CustomerSettings>({
auto_register_members: false,
vip_min_spent: 1000, vip_min_spent: 1000,
vip_min_orders: 10, vip_min_orders: 10,
vip_timeframe: 'all', vip_timeframe: 'all',
@@ -113,6 +115,19 @@ export default function CustomersSettings() {
</div> </div>
)} )}
<SettingsCard
title={__('General')}
description={__('General customer settings')}
>
<ToggleField
id="auto_register_members"
label={__('Auto-register customers as site members')}
description={__('Automatically create WordPress user accounts for new customers when orders are created. Customers will receive login credentials via email and can track their orders.')}
checked={settings.auto_register_members}
onCheckedChange={(checked) => setSettings({ ...settings, auto_register_members: checked })}
/>
</SettingsCard>
<SettingsCard <SettingsCard
title={__('VIP Customer Qualification')} title={__('VIP Customer Qualification')}
description={__('Define criteria for identifying VIP customers')} description={__('Define criteria for identifying VIP customers')}

View File

@@ -780,7 +780,10 @@ class OrdersController {
$shipping_method = sanitize_text_field( $p['shipping_method'] ?? '' ); // e.g. flat_rate:1 $shipping_method = sanitize_text_field( $p['shipping_method'] ?? '' ); // e.g. flat_rate:1
$coupons = array_filter( array_map( 'sanitize_text_field', (array) ( $p['coupons'] ?? [] ) ) ); $coupons = array_filter( array_map( 'sanitize_text_field', (array) ( $p['coupons'] ?? [] ) ) );
$note = isset( $p['customer_note'] ) ? wp_kses_post( (string) $p['customer_note'] ) : ''; $note = isset( $p['customer_note'] ) ? wp_kses_post( (string) $p['customer_note'] ) : '';
$register_member = (bool) ( $p['register_as_member'] ?? false );
// Get auto-register setting from customer settings (site-level)
$customer_settings = \WooNooW\Compat\CustomerSettingsProvider::get_settings();
$register_member = $customer_settings['auto_register_members'] ?? false;
// Validation: Collect all missing required fields // Validation: Collect all missing required fields
$validation_errors = []; $validation_errors = [];

View File

@@ -18,6 +18,9 @@ class CustomerSettingsProvider {
*/ */
public static function get_settings() { public static function get_settings() {
return [ return [
// General
'auto_register_members' => get_option('woonoow_auto_register_members', 'no') === 'yes',
// VIP Customer Qualification // VIP Customer Qualification
'vip_min_spent' => floatval(get_option('woonoow_vip_min_spent', 1000)), 'vip_min_spent' => floatval(get_option('woonoow_vip_min_spent', 1000)),
'vip_min_orders' => intval(get_option('woonoow_vip_min_orders', 10)), 'vip_min_orders' => intval(get_option('woonoow_vip_min_orders', 10)),
@@ -36,6 +39,11 @@ class CustomerSettingsProvider {
public static function update_settings($settings) { public static function update_settings($settings) {
$updated = true; $updated = true;
// General settings
if (isset($settings['auto_register_members'])) {
$updated = $updated && update_option('woonoow_auto_register_members', $settings['auto_register_members'] ? 'yes' : 'no');
}
// VIP settings // VIP settings
if (isset($settings['vip_min_spent'])) { if (isset($settings['vip_min_spent'])) {
$updated = $updated && update_option('woonoow_vip_min_spent', floatval($settings['vip_min_spent'])); $updated = $updated && update_option('woonoow_vip_min_spent', floatval($settings['vip_min_spent']));