Files
manoon-headless/scripts/migrate_guest_orders.sql
Unchained 7b94537670 feat(saleor): Phase 1 - GraphQL Client Setup
- Add Apollo Client for Saleor GraphQL API
- Create GraphQL fragments (Product, Variant, Checkout)
- Create GraphQL queries (Products, Checkout)
- Create GraphQL mutations (Checkout operations)
- Add TypeScript types for Saleor entities
- Add product helper functions
- Install @apollo/client and graphql dependencies

Part of WordPress/WooCommerce → Saleor migration
2026-03-21 12:36:21 +02:00

202 lines
8.2 KiB
SQL

-- =====================================================
-- 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)