|
|
@@ -61,8 +61,6 @@ serve(wrapHandler('shoprenter-scheduled-sync', async (req) => {
|
|
|
enabled,
|
|
|
sync_frequency,
|
|
|
sync_products,
|
|
|
- sync_orders,
|
|
|
- sync_customers,
|
|
|
last_sync_at,
|
|
|
next_sync_at
|
|
|
)
|
|
|
@@ -125,8 +123,8 @@ serve(wrapHandler('shoprenter-scheduled-sync', async (req) => {
|
|
|
store_id: storeId,
|
|
|
store_name: store.store_name,
|
|
|
products: { synced: 0, errors: 0 },
|
|
|
- orders: { synced: 0, errors: 0 },
|
|
|
- customers: { synced: 0, errors: 0 },
|
|
|
+ customer_access: { available: false, tested: false },
|
|
|
+ order_access: { available: false, tested: false },
|
|
|
started_at: new Date().toISOString(),
|
|
|
completed_at: null as string | null,
|
|
|
status: 'success' as 'success' | 'partial' | 'failed',
|
|
|
@@ -134,195 +132,102 @@ serve(wrapHandler('shoprenter-scheduled-sync', async (req) => {
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- // Sync Products
|
|
|
- try {
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Syncing products for store ${storeId}`)
|
|
|
- let page = 1
|
|
|
- let hasMore = true
|
|
|
- const limit = 50
|
|
|
-
|
|
|
- while (hasMore) {
|
|
|
- const productsData = await fetchProducts(storeId, page, limit)
|
|
|
-
|
|
|
- if (productsData.items && productsData.items.length > 0) {
|
|
|
- const productsToCache = productsData.items.map((product: any) => ({
|
|
|
- store_id: storeId,
|
|
|
- shoprenter_product_id: product.id,
|
|
|
- name: product.name,
|
|
|
- sku: product.sku,
|
|
|
- price: parseFloat(product.price) || 0,
|
|
|
- currency: product.currency || 'HUF',
|
|
|
- description: product.description,
|
|
|
- stock: product.stock,
|
|
|
- active: product.active !== false,
|
|
|
- raw_data: product,
|
|
|
- last_synced_at: new Date().toISOString()
|
|
|
- }))
|
|
|
-
|
|
|
- const { error: upsertError } = await supabaseAdmin
|
|
|
- .from('shoprenter_products_cache')
|
|
|
- .upsert(productsToCache, {
|
|
|
- onConflict: 'store_id,shoprenter_product_id'
|
|
|
- })
|
|
|
-
|
|
|
- if (upsertError) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Error caching products for store ${storeId}:`, upsertError)
|
|
|
- syncStats.products.errors += productsToCache.length
|
|
|
+ // Sync Products (only data type we cache now for GDPR compliance)
|
|
|
+ if (config?.sync_products !== false) {
|
|
|
+ try {
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Syncing products for store ${storeId}`)
|
|
|
+ let page = 1
|
|
|
+ let hasMore = true
|
|
|
+ const limit = 50
|
|
|
+
|
|
|
+ while (hasMore) {
|
|
|
+ const productsData = await fetchProducts(storeId, page, limit)
|
|
|
+
|
|
|
+ if (productsData.items && productsData.items.length > 0) {
|
|
|
+ const productsToCache = productsData.items.map((product: any) => ({
|
|
|
+ store_id: storeId,
|
|
|
+ shoprenter_product_id: product.id,
|
|
|
+ name: product.name,
|
|
|
+ sku: product.sku,
|
|
|
+ price: parseFloat(product.price) || 0,
|
|
|
+ currency: product.currency || 'HUF',
|
|
|
+ description: product.description,
|
|
|
+ stock: product.stock,
|
|
|
+ active: product.active !== false,
|
|
|
+ raw_data: product,
|
|
|
+ last_synced_at: new Date().toISOString()
|
|
|
+ }))
|
|
|
+
|
|
|
+ const { error: upsertError } = await supabaseAdmin
|
|
|
+ .from('shoprenter_products_cache')
|
|
|
+ .upsert(productsToCache, {
|
|
|
+ onConflict: 'store_id,shoprenter_product_id'
|
|
|
+ })
|
|
|
+
|
|
|
+ if (upsertError) {
|
|
|
+ console.error(`[ShopRenter Scheduled Sync] Error caching products for store ${storeId}:`, upsertError)
|
|
|
+ syncStats.products.errors += productsToCache.length
|
|
|
+ } else {
|
|
|
+ syncStats.products.synced += productsToCache.length
|
|
|
+ }
|
|
|
+
|
|
|
+ // Check if there are more pages
|
|
|
+ if (productsData.pagination && productsData.pagination.total) {
|
|
|
+ const totalPages = Math.ceil(productsData.pagination.total / limit)
|
|
|
+ hasMore = page < totalPages
|
|
|
+ } else {
|
|
|
+ hasMore = productsData.items.length === limit
|
|
|
+ }
|
|
|
+
|
|
|
+ page++
|
|
|
} else {
|
|
|
- syncStats.products.synced += productsToCache.length
|
|
|
+ hasMore = false
|
|
|
}
|
|
|
-
|
|
|
- // Check if there are more pages
|
|
|
- if (productsData.pagination && productsData.pagination.total) {
|
|
|
- const totalPages = Math.ceil(productsData.pagination.total / limit)
|
|
|
- hasMore = page < totalPages
|
|
|
- } else {
|
|
|
- hasMore = productsData.items.length === limit
|
|
|
- }
|
|
|
-
|
|
|
- page++
|
|
|
- } else {
|
|
|
- hasMore = false
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Products synced: ${syncStats.products.synced}, errors: ${syncStats.products.errors}`)
|
|
|
- } catch (error) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Product sync error for store ${storeId}:`, error)
|
|
|
- syncStats.products.errors++
|
|
|
- syncStats.status = 'partial'
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Products synced: ${syncStats.products.synced}, errors: ${syncStats.products.errors}`)
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`[ShopRenter Scheduled Sync] Product sync error for store ${storeId}:`, error)
|
|
|
+ syncStats.products.errors++
|
|
|
+ syncStats.status = 'partial'
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // Sync Orders
|
|
|
- try {
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Syncing orders for store ${storeId}`)
|
|
|
- let page = 1
|
|
|
- let hasMore = true
|
|
|
- const limit = 50
|
|
|
-
|
|
|
- while (hasMore) {
|
|
|
- const ordersData = await fetchOrders(storeId, page, limit)
|
|
|
-
|
|
|
- if (ordersData.items && ordersData.items.length > 0) {
|
|
|
- const ordersToCache = ordersData.items.map((order: any) => ({
|
|
|
- store_id: storeId,
|
|
|
- shoprenter_order_id: order.id,
|
|
|
- order_number: order.order_number || order.number || order.id,
|
|
|
- status: order.status,
|
|
|
- total: parseFloat(order.total) || 0,
|
|
|
- currency: order.currency || 'HUF',
|
|
|
- customer_name: order.customer_name || `${order.customer?.firstname || ''} ${order.customer?.lastname || ''}`.trim() || null,
|
|
|
- customer_email: order.customer_email || order.customer?.email || null,
|
|
|
- customer_phone: formatFirstValidPhone([
|
|
|
- order.customer_phone,
|
|
|
- order.customer?.phone,
|
|
|
- order.billing_address?.phone,
|
|
|
- order.shipping_address?.phone
|
|
|
- ], countryCode),
|
|
|
- line_items: order.items || order.line_items || [],
|
|
|
- billing_address: order.billing_address || null,
|
|
|
- shipping_address: order.shipping_address || null,
|
|
|
- order_created_at: order.created_at || order.date_created || new Date().toISOString(),
|
|
|
- raw_data: order,
|
|
|
- last_synced_at: new Date().toISOString()
|
|
|
- }))
|
|
|
-
|
|
|
- const { error: upsertError } = await supabaseAdmin
|
|
|
- .from('shoprenter_orders_cache')
|
|
|
- .upsert(ordersToCache, {
|
|
|
- onConflict: 'store_id,shoprenter_order_id'
|
|
|
- })
|
|
|
-
|
|
|
- if (upsertError) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Error caching orders for store ${storeId}:`, upsertError)
|
|
|
- syncStats.orders.errors += ordersToCache.length
|
|
|
- } else {
|
|
|
- syncStats.orders.synced += ordersToCache.length
|
|
|
- }
|
|
|
-
|
|
|
- // Check if there are more pages
|
|
|
- if (ordersData.pagination && ordersData.pagination.total) {
|
|
|
- const totalPages = Math.ceil(ordersData.pagination.total / limit)
|
|
|
- hasMore = page < totalPages
|
|
|
- } else {
|
|
|
- hasMore = ordersData.items.length === limit
|
|
|
- }
|
|
|
-
|
|
|
- page++
|
|
|
- } else {
|
|
|
- hasMore = false
|
|
|
- }
|
|
|
+ // Test customer data access (don't sync, just validate)
|
|
|
+ // Check if store has data_access_permissions.allow_customer_access enabled
|
|
|
+ const { data: storeData } = await supabaseAdmin
|
|
|
+ .from('stores')
|
|
|
+ .select('data_access_permissions')
|
|
|
+ .eq('id', storeId)
|
|
|
+ .single()
|
|
|
+
|
|
|
+ if (storeData?.data_access_permissions?.allow_customer_access) {
|
|
|
+ try {
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Testing customer data access for store ${storeId}`)
|
|
|
+ const customersTest = await fetchCustomers(storeId, 1, 1)
|
|
|
+ syncStats.customer_access.tested = true
|
|
|
+ syncStats.customer_access.available = !!(customersTest && customersTest.items)
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Customer access available: ${syncStats.customer_access.available}`)
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`[ShopRenter Scheduled Sync] Customer access test error for store ${storeId}:`, error)
|
|
|
+ syncStats.customer_access.tested = true
|
|
|
+ syncStats.customer_access.available = false
|
|
|
}
|
|
|
-
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Orders synced: ${syncStats.orders.synced}, errors: ${syncStats.orders.errors}`)
|
|
|
- } catch (error) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Order sync error for store ${storeId}:`, error)
|
|
|
- syncStats.orders.errors++
|
|
|
- syncStats.status = 'partial'
|
|
|
}
|
|
|
|
|
|
- // Sync Customers
|
|
|
- try {
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Syncing customers for store ${storeId}`)
|
|
|
- let page = 1
|
|
|
- let hasMore = true
|
|
|
- const limit = 50
|
|
|
-
|
|
|
- while (hasMore) {
|
|
|
- const customersData = await fetchCustomers(storeId, page, limit)
|
|
|
-
|
|
|
- if (customersData.items && customersData.items.length > 0) {
|
|
|
- const customersToCache = customersData.items.map((customer: any) => ({
|
|
|
- store_id: storeId,
|
|
|
- shoprenter_customer_id: customer.id,
|
|
|
- email: customer.email,
|
|
|
- first_name: customer.firstname,
|
|
|
- last_name: customer.lastname,
|
|
|
- phone: formatFirstValidPhone([
|
|
|
- customer.phone,
|
|
|
- customer.billing_address?.phone,
|
|
|
- customer.shipping_address?.phone
|
|
|
- ], countryCode),
|
|
|
- billing_address: customer.billing_address || null,
|
|
|
- shipping_address: customer.shipping_address || null,
|
|
|
- orders_count: customer.orders_count || 0,
|
|
|
- total_spent: parseFloat(customer.total_spent) || 0,
|
|
|
- raw_data: customer,
|
|
|
- last_synced_at: new Date().toISOString()
|
|
|
- }))
|
|
|
-
|
|
|
- const { error: upsertError } = await supabaseAdmin
|
|
|
- .from('shoprenter_customers_cache')
|
|
|
- .upsert(customersToCache, {
|
|
|
- onConflict: 'store_id,shoprenter_customer_id'
|
|
|
- })
|
|
|
-
|
|
|
- if (upsertError) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Error caching customers for store ${storeId}:`, upsertError)
|
|
|
- syncStats.customers.errors += customersToCache.length
|
|
|
- } else {
|
|
|
- syncStats.customers.synced += customersToCache.length
|
|
|
- }
|
|
|
-
|
|
|
- // Check if there are more pages
|
|
|
- if (customersData.pagination && customersData.pagination.total) {
|
|
|
- const totalPages = Math.ceil(customersData.pagination.total / limit)
|
|
|
- hasMore = page < totalPages
|
|
|
- } else {
|
|
|
- hasMore = customersData.items.length === limit
|
|
|
- }
|
|
|
-
|
|
|
- page++
|
|
|
- } else {
|
|
|
- hasMore = false
|
|
|
- }
|
|
|
+ // Test order data access (don't sync, just validate)
|
|
|
+ if (storeData?.data_access_permissions?.allow_order_access) {
|
|
|
+ try {
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Testing order data access for store ${storeId}`)
|
|
|
+ const ordersTest = await fetchOrders(storeId, 1, 1)
|
|
|
+ syncStats.order_access.tested = true
|
|
|
+ syncStats.order_access.available = !!(ordersTest && ordersTest.items)
|
|
|
+ console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Order access available: ${syncStats.order_access.available}`)
|
|
|
+ } catch (error) {
|
|
|
+ console.error(`[ShopRenter Scheduled Sync] Order access test error for store ${storeId}:`, error)
|
|
|
+ syncStats.order_access.tested = true
|
|
|
+ syncStats.order_access.available = false
|
|
|
}
|
|
|
-
|
|
|
- console.log(`[ShopRenter Scheduled Sync] Store ${storeId}: Customers synced: ${syncStats.customers.synced}, errors: ${syncStats.customers.errors}`)
|
|
|
- } catch (error) {
|
|
|
- console.error(`[ShopRenter Scheduled Sync] Customer sync error for store ${storeId}:`, error)
|
|
|
- syncStats.customers.errors++
|
|
|
- syncStats.status = 'partial'
|
|
|
}
|
|
|
|
|
|
// Update store last_sync timestamp
|
|
|
@@ -331,8 +236,8 @@ serve(wrapHandler('shoprenter-scheduled-sync', async (req) => {
|
|
|
last_sync_at: new Date().toISOString(),
|
|
|
last_sync_stats: {
|
|
|
products: syncStats.products,
|
|
|
- orders: syncStats.orders,
|
|
|
- customers: syncStats.customers
|
|
|
+ customer_access: syncStats.customer_access,
|
|
|
+ order_access: syncStats.order_access
|
|
|
},
|
|
|
last_sync_type: 'scheduled'
|
|
|
}
|
|
|
@@ -415,4 +320,11 @@ serve(wrapHandler('shoprenter-scheduled-sync', async (req) => {
|
|
|
{ status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
)
|
|
|
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[ShopRenter Scheduled Sync] Unexpected error:', error)
|
|
|
+ return new Response(
|
|
|
+ JSON.stringify({ error: 'Internal server error', details: error.message }),
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
+ )
|
|
|
+ }
|
|
|
}))
|