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
This commit is contained in:
201
scripts/migrate_guest_orders.sql
Normal file
201
scripts/migrate_guest_orders.sql
Normal file
@@ -0,0 +1,201 @@
|
||||
-- =====================================================
|
||||
-- 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)
|
||||
Reference in New Issue
Block a user