Auto Preferences Feature¶
Overview¶
The Auto Preferences feature automatically sets customer preferences to "NO" for items they have repeatedly substituted out from their orders. This helps streamline the customer experience by proactively managing their preferences based on their actual behavior.
How It Works¶
Detection Logic¶
- Trigger: The system runs before starting a new week
- Analysis: For each customer with orders in the current week who made substitutions:
- Identifies items that were substituted (where
cust_menu_id != menu_id) - Checks if those same items were substituted in any previous orders
-
If an item was subbed before, it automatically sets that product classification to "NO"
-
Preference Update: Creates or updates a record in
custy_likestable withpref = 0 -
Customer Notification:
- Sends an email notification listing all items set to "NO"
- Creates a popup notification for their next login
Database Schema¶
New Table: custy_preference_notifications¶
CREATE TABLE `custy_preference_notifications` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`customer_id` INT(11) NOT NULL,
`notification_type` VARCHAR(64) NOT NULL,
`notification_data` TEXT NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`shown_at` TIMESTAMP NULL DEFAULT NULL,
`dismissed_at` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_customer_shown` (`customer_id`, `shown_at`),
KEY `idx_customer_type` (`customer_id`, `notification_type`)
)
New Email Template: Auto Preferences Updated¶
- Subject: "We updated your preferences based on your substitution history"
- Contains placeholder:
**auto_preference_list**for items list - Uses standard template variables:
**first_name**
Files Created/Modified¶
New Files¶
/kiv/helpers/helper.autoPreferences.php- Core automation logic
-
Functions:
processAutoPreferences($dryRun, $specificCustomerId)- Main processorprocessCustomerAutoPreferences($customerId, $currentWeekId, $dryRun, &$stats)- Per-customer logicsendAutoPreferenceEmail($customerId, $preferencesUpdated)- Email notificationcreateAutoPreferenceNotification($customerId, $preferencesUpdated)- Popup notificationgetCustomerPreferenceNotifications($customerId)- Get unshown notificationsmarkNotificationShown($notificationId)- Mark as shownmarkNotificationDismissed($notificationId)- Mark as dismissed
-
/home/auto-preference-notification.php - Modal/popup display for customer portal
- Shows list of items set to "NO"
- Provides links to update preferences
-
Auto-dismisses when clicked outside or on escape key
-
/home/dismiss-auto-pref-notification.php - AJAX endpoint for dismissing notifications
- Validates customer ownership
- Marks notification as dismissed
Modified Files¶
/kiv/migrate.php- Added case 821: Create
custy_preference_notificationstable -
Added case 822: Insert email template
-
/kiv/tools.php -
Added
processAutoPreferencesRunto the$actionsarray at the top -
/inc/helper.tools.php - Added
processAutoPreferencesRun()function - Provides browser-based wrapper for processAutoPreferences
-
Supports query parameters:
dry_runandcustomer -
/home/welcome.php - Added include for
auto-preference-notification.php - Displays popup on customer login if notifications exist
Usage¶
Running the Automation¶
Before starting a new week in the system, access the tool from your browser:
- Go to
/kiv/tools.php?processAutoPreferencesRun=1 - Use the quick links to run in different modes:
- Dry Run mode:
?processAutoPreferencesRun=1&dry_run=1(test without making changes) - Live mode:
?processAutoPreferencesRun=1(actually process and send emails) - Single customer:
?processAutoPreferencesRun=1&dry_run=1&customer=12345
The tool will display a formatted HTML page with: - Status banner (DRY RUN vs LIVE) - Full output in a formatted code block - Quick navigation links
Output Example¶
=== Auto Preferences Processor ===
*** DRY RUN MODE - No changes will be made ***
Processing for week ID: 456
Found 15 customers with substitutions this week
Processing customer ID: 12345
Item 'Organic Bananas' (classify_id: 78) subbed 2 time(s) before
[DRY RUN] Would set to NO
Item 'Kale' (classify_id: 45) subbed 1 time(s) before
[DRY RUN] Would set to NO
Processing customer ID: 67890
Item 'Broccoli' (classify_id: 89) subbed 3 time(s) before
[DRY RUN] Would set to NO
=== SUMMARY ===
Customers processed: 15
Customers with changes: 2
Total preferences set to NO: 3
Emails sent: 0
Customer Experience¶
- Email Notification: Customer receives email with list of items set to "NO"
- Login Popup: Next time they log in, they see a modal popup with:
- Explanation of why preferences were updated
- List of items set to "NO"
- Link to preferences page
-
"Got It" button to dismiss
-
Preferences Page: Customer can visit their preferences page (
/home/love-hate.php) to review and change any preferences
Implementation Details¶
How Substitutions Are Detected¶
A substitution occurs when:
cust_order_contents.cust_menu_id != cust_order_contents.menu_id
AND cust_order_contents.cust_menu_id > 0
menu_id= What the customer has chosen (their substitution choice ifcust_menu_idis set)cust_menu_id= What was originally assigned to the customer (menu_id gets moved here when customer makes a sub)
When a customer makes a substitution:
1. The original menu_id value is moved to cust_menu_id
2. The new choice is stored in menu_id
3. If no substitution was made, menu_id contains the item and cust_menu_id is 0
How Preferences Are Set¶
Uses the custy_likes table:
- customer = Customer ID
- product_class = The classify_id from the menu item
- pref = 0 (NO) or 1 (YES)
The system:
1. Gets the classify_id from the menu table for the substituted item
2. Checks if a custy_likes record exists for this customer + classify_id
3. If exists: Updates pref to 0 (if not already)
4. If not exists: Creates new record with pref = 0
Notification System¶
Notifications are stored in custy_preference_notifications:
- notification_data = JSON with preferences array and count
- shown_at = Timestamp when modal was displayed (NULL = not shown yet)
- dismissed_at = Timestamp when customer dismissed it (NULL = not dismissed)
The system only shows unshown notifications (where shown_at IS NULL).
Testing¶
Test Scenarios¶
- Dry Run Test:
php command-line-tools.php process-auto-preferences --dry-run - Should show what would happen without making changes
- No emails sent
-
No database changes
-
Single Customer Test:
php command-line-tools.php process-auto-preferences --dry-run --customer 12345 -
Test with a specific customer who has made substitutions
-
Full Run Test:
php command-line-tools.php process-auto-preferences - Actually updates preferences
- Sends emails
-
Creates popup notifications
-
Popup Test:
- After running automation, log in as affected customer
- Should see modal popup on welcome page
- Click "Got It" - modal should close
- Refresh page - modal should NOT appear again (marked as shown)
Verification Queries¶
Check if preferences were set:
SELECT cl.*, pc.name
FROM custy_likes cl
JOIN product_classification pc ON cl.product_class = pc.id
WHERE cl.customer = 12345
AND cl.pref = 0
ORDER BY cl.id DESC
Check notifications created:
SELECT *
FROM custy_preference_notifications
WHERE customer_id = 12345
ORDER BY created_at DESC
Check substitution history:
SELECT co.id, co.week_id, coc.menu_id, coc.cust_menu_id, m.name as original_item
FROM cust_order co
JOIN cust_order_contents coc ON co.id = coc.cust_order_id
JOIN menu m ON coc.menu_id = m.id
WHERE co.customer = 12345
AND coc.cust_menu_id != coc.menu_id
AND coc.cust_menu_id > 0
ORDER BY co.week_id DESC
Integration with Weekly Workflow¶
Recommended workflow before starting a new week:
- Run dry run to see impact:
-
Navigate to
/kiv/tools.php?processAutoPreferencesRun=1&dry_run=1 -
Review the output - check customer count and items being set
-
Run actual processing:
-
Navigate to
/kiv/tools.php?processAutoPreferencesRun=1 -
Verify emails were sent (check email logs or mailhog in dev)
-
Proceed with starting new week in system
Troubleshooting¶
No customers found¶
- Check that current week has orders with substitutions
- Verify that
cust_order_contentshas records wherecust_menu_id != menu_id
Emails not sending¶
- Check email template exists:
SELECT * FROM email_templates WHERE name = 'Auto Preferences Updated' - Verify customer has valid email address
- Check email sending configuration and logs
Popup not showing¶
- Verify notification was created in database
- Check that
shown_atis NULL - Ensure
auto-preference-notification.phpis included in welcome page - Check browser console for JavaScript errors
Preferences not updating¶
- Verify
menutable has validclassify_idfor items - Check that
custy_likestable is accessible - Review error messages in automation output
Future Enhancements¶
Possible improvements: 1. Add threshold setting (e.g., only set to NO after 3+ subs, not 2) 2. Add admin interface to review auto-set preferences before applying 3. Add customer setting to opt-out of auto-preferences 4. Track and report on accuracy (did customer change preference back?) 5. Email summary to admin showing all customers affected 6. Add preference history tracking (when/why preference was changed)
Security Notes¶
- Notification dismissal endpoint validates customer ownership
- Only shows notifications for logged-in customers
- AJAX endpoint returns proper HTTP status codes
- SQL injection protection via
mysql_real_escape_stringandintval
Performance Considerations¶
- Indexes added to
custy_preference_notificationsfor efficient queries - Query optimization using JOINs instead of nested loops where possible
- Notifications marked as "shown" to avoid repeated displays
- Email sending happens inline (not queued) - consider adding queue for large customer base