-- ===================================================== -- WooCommerce GUEST Checkout to Saleor Migration -- ===================================================== -- For stores without customer accounts - all data is in orders -- Since there are no customer accounts, we create users from order data -- Strategy: Create a Saleor user for each unique email in orders -- Step 1: Create mapping table for email-based customers CREATE TABLE IF NOT EXISTS wc_guest_customer_mapping ( email VARCHAR(255) PRIMARY KEY, saleor_user_id UUID, first_name VARCHAR(255), last_name VARCHAR(255), phone VARCHAR(255), order_count INTEGER DEFAULT 0, total_spent DECIMAL(12,2) DEFAULT 0, created_at TIMESTAMP DEFAULT NOW() ); -- Step 2: Export unique customers from orders (no wp_users needed!) -- Run this on WordPress/MariaDB: /* SELECT DISTINCT meta_email.meta_value as email, MAX(meta_first.meta_value) as first_name, MAX(meta_last.meta_value) as last_name, MAX(meta_phone.meta_value) as phone, COUNT(DISTINCT p.ID) as order_count, SUM(CAST(meta_total.meta_value AS DECIMAL(12,2))) as total_spent FROM wp_posts p JOIN wp_postmeta meta_email ON p.ID = meta_email.post_id AND meta_email.meta_key = '_billing_email' LEFT JOIN wp_postmeta meta_first ON p.ID = meta_first.post_id AND meta_first.meta_key = '_billing_first_name' LEFT JOIN wp_postmeta meta_last ON p.ID = meta_last.post_id AND meta_last.meta_key = '_billing_last_name' LEFT JOIN wp_postmeta meta_phone ON p.ID = meta_phone.post_id AND meta_phone.meta_key = '_billing_phone' LEFT JOIN wp_postmeta meta_total ON p.ID = meta_total.post_id AND meta_total.meta_key = '_order_total' WHERE p.post_type = 'shop_order' AND meta_email.meta_value IS NOT NULL AND meta_email.meta_value != '' GROUP BY meta_email.meta_value ORDER BY order_count DESC; */ -- Step 3: Insert guest customers into Saleor -- For each unique email, create a user account /* WITH new_guest_user AS ( INSERT INTO account_user ( id, email, first_name, last_name, is_staff, is_active, date_joined, last_login, password ) VALUES ( gen_random_uuid(), 'customer@example.com', -- from order billing_email 'John', -- from order billing_first_name 'Doe', -- from order billing_last_name false, true, NOW(), -- use first order date if available NULL, '!' -- unusable password - customer must set via password reset ) RETURNING id, email ) INSERT INTO wc_guest_customer_mapping (email, saleor_user_id, first_name, last_name) SELECT email, id, 'John', 'Doe' FROM new_guest_user; */ -- Step 4: Create addresses from most recent order per customer -- Get the most recent order for each email to extract address /* WITH latest_orders AS ( SELECT DISTINCT ON (meta_email.meta_value) meta_email.meta_value as email, p.ID as order_id, p.post_date as order_date FROM wp_posts p JOIN wp_postmeta meta_email ON p.ID = meta_email.post_id AND meta_email.meta_key = '_billing_email' WHERE p.post_type = 'shop_order' ORDER BY meta_email.meta_value, p.post_date DESC ), address_data AS ( SELECT lo.email, MAX(CASE WHEN pm.meta_key = '_billing_first_name' THEN pm.meta_value END) as bill_first, MAX(CASE WHEN pm.meta_key = '_billing_last_name' THEN pm.meta_value END) as bill_last, MAX(CASE WHEN pm.meta_key = '_billing_company' THEN pm.meta_value END) as bill_company, MAX(CASE WHEN pm.meta_key = '_billing_address_1' THEN pm.meta_value END) as bill_addr1, MAX(CASE WHEN pm.meta_key = '_billing_address_2' THEN pm.meta_value END) as bill_addr2, MAX(CASE WHEN pm.meta_key = '_billing_city' THEN pm.meta_value END) as bill_city, MAX(CASE WHEN pm.meta_key = '_billing_postcode' THEN pm.meta_value END) as bill_postcode, MAX(CASE WHEN pm.meta_key = '_billing_country' THEN pm.meta_value END) as bill_country, MAX(CASE WHEN pm.meta_key = '_billing_phone' THEN pm.meta_value END) as bill_phone, MAX(CASE WHEN pm.meta_key = '_shipping_first_name' THEN pm.meta_value END) as ship_first, MAX(CASE WHEN pm.meta_key = '_shipping_last_name' THEN pm.meta_value END) as ship_last, MAX(CASE WHEN pm.meta_key = '_shipping_company' THEN pm.meta_value END) as ship_company, MAX(CASE WHEN pm.meta_key = '_shipping_address_1' THEN pm.meta_value END) as ship_addr1, MAX(CASE WHEN pm.meta_key = '_shipping_address_2' THEN pm.meta_value END) as ship_addr2, MAX(CASE WHEN pm.meta_key = '_shipping_city' THEN pm.meta_value END) as ship_city, MAX(CASE WHEN pm.meta_key = '_shipping_postcode' THEN pm.meta_value END) as ship_postcode, MAX(CASE WHEN pm.meta_key = '_shipping_country' THEN pm.meta_value END) as ship_country FROM latest_orders lo JOIN wp_postmeta pm ON lo.order_id = pm.post_id GROUP BY lo.email ) -- Insert billing address and link to user INSERT INTO account_address (id, first_name, last_name, company_name, street_address_1, street_address_2, city, postal_code, country, phone) SELECT gen_random_uuid(), bill_first, bill_last, COALESCE(bill_company, ''), bill_addr1, COALESCE(bill_addr2, ''), bill_city, bill_postcode, COALESCE(bill_country, 'RS'), COALESCE(bill_phone, '') FROM address_data ad JOIN wc_guest_customer_mapping cm ON ad.email = cm.email WHERE cm.saleor_user_id IS NOT NULL RETURNING id, (SELECT email FROM wc_guest_customer_mapping WHERE saleor_user_id = (SELECT id FROM account_user WHERE id = account_address.id)); -- This needs adjustment -- Then link addresses to users via account_user_addresses */ -- Alternative simpler approach: Insert order with addresses inline (no separate customer record) -- Saleor supports orders without user accounts (guest orders) -- ===================================================== -- SIMPLIFIED: Orders Only (No Customer Accounts) -- ===================================================== -- If you don't want to create customer accounts at all, -- just migrate orders as guest orders with email addresses /* INSERT INTO order_order ( id, created_at, updated_at, status, user_email, -- Store email here (no user_id) user_id, -- NULL for guest orders currency, total_gross_amount, total_net_amount, shipping_price_gross_amount, shipping_price_net_amount, shipping_method_name, channel_id, billing_address, -- JSON with full address shipping_address, -- JSON with full address metadata, origin, should_refresh_prices, tax_exemption, discount_amount, display_gross_prices, customer_note ) VALUES ( gen_random_uuid(), '2024-01-15 10:30:00'::timestamp, '2024-01-15 10:30:00'::timestamp, 'FULFILLED', 'guest@example.com', -- Customer email from order NULL, -- No user account (guest order) 'RSD', 11500.00, 10000.00, 500.00, 500.00, 'Flat Rate', (SELECT id FROM channel_channel WHERE slug = 'default-channel'), '{ "first_name": "John", "last_name": "Doe", "street_address_1": "Kneza Milosa 10", "city": "Belgrade", "postal_code": "11000", "country": "RS", "phone": "+38164123456" }'::jsonb, '{ "first_name": "John", "last_name": "Doe", "street_address_1": "Kneza Milosa 10", "city": "Belgrade", "postal_code": "11000", "country": "RS", "phone": "+38164123456" }'::jsonb, '{"woo_order_id": "12345", "guest_checkout": true}'::jsonb, 'BULK_CREATE', false, false, 0.00, true, '' ); */ -- ===================================================== -- RECOMMENDED APPROACH: Hybrid -- ===================================================== -- 1. Create lightweight user accounts from unique emails -- 2. Link all orders to these accounts -- 3. Customers can claim accounts via password reset -- Benefits: -- - Order history tied to email -- - Customers can "activate" their account later -- - Better analytics (LTV per customer) -- - Future marketing (targeted emails)