|
|
@@ -10,6 +10,20 @@ import {
|
|
|
ShopifyCustomer
|
|
|
} from '../_shared/shopify-client.ts'
|
|
|
import { formatFirstValidPhone, detectCountryCode } from '../_shared/phone-formatter.ts'
|
|
|
+import {
|
|
|
+ collectionExists,
|
|
|
+ createCollection,
|
|
|
+ upsertPoints,
|
|
|
+ deletePointsByFilter,
|
|
|
+ scrollPoints,
|
|
|
+ getCollectionName,
|
|
|
+ initializeStoreCollections,
|
|
|
+ generateSimpleEmbedding,
|
|
|
+ createProductText,
|
|
|
+ createOrderText,
|
|
|
+ createCustomerText,
|
|
|
+ QdrantPoint
|
|
|
+} from '../_shared/qdrant-client.ts'
|
|
|
|
|
|
const corsHeaders = {
|
|
|
'Access-Control-Allow-Origin': '*',
|
|
|
@@ -51,15 +65,373 @@ async function fetchWithRetry<T>(
|
|
|
throw new Error('Max retries exceeded')
|
|
|
}
|
|
|
|
|
|
-// Sync products from Shopify
|
|
|
-async function syncProducts(
|
|
|
+// Log Qdrant sync operation
|
|
|
+async function logQdrantSync(
|
|
|
+ supabaseAdmin: any,
|
|
|
+ storeId: string,
|
|
|
+ syncType: string,
|
|
|
+ collectionName: string,
|
|
|
+ operation: string,
|
|
|
+ itemsProcessed: number,
|
|
|
+ itemsSucceeded: number,
|
|
|
+ itemsFailed: number,
|
|
|
+ startedAt: Date,
|
|
|
+ errorMessage?: string
|
|
|
+): Promise<void> {
|
|
|
+ try {
|
|
|
+ await supabaseAdmin
|
|
|
+ .from('qdrant_sync_logs')
|
|
|
+ .insert({
|
|
|
+ store_id: storeId,
|
|
|
+ sync_type: syncType,
|
|
|
+ collection_name: collectionName,
|
|
|
+ operation,
|
|
|
+ items_processed: itemsProcessed,
|
|
|
+ items_succeeded: itemsSucceeded,
|
|
|
+ items_failed: itemsFailed,
|
|
|
+ error_message: errorMessage,
|
|
|
+ started_at: startedAt.toISOString(),
|
|
|
+ completed_at: new Date().toISOString(),
|
|
|
+ })
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[Qdrant] Failed to log sync operation:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Sync products to Qdrant
|
|
|
+async function syncProductsToQdrant(
|
|
|
+ storeId: string,
|
|
|
+ storeName: string,
|
|
|
+ products: ShopifyProduct[],
|
|
|
+ supabaseAdmin: any
|
|
|
+): Promise<{ synced: number; errors: number }> {
|
|
|
+ const startTime = new Date()
|
|
|
+ const collectionName = getCollectionName(storeName, 'products')
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Syncing ${products.length} products to ${collectionName}`)
|
|
|
+
|
|
|
+ let synced = 0
|
|
|
+ let errors = 0
|
|
|
+
|
|
|
+ try {
|
|
|
+ // Ensure collection exists
|
|
|
+ if (!(await collectionExists(collectionName))) {
|
|
|
+ await createCollection(collectionName, [
|
|
|
+ { field: 'store_id', type: 'keyword' },
|
|
|
+ { field: 'product_id', type: 'keyword' },
|
|
|
+ { field: 'platform', type: 'keyword' },
|
|
|
+ { field: 'status', type: 'keyword' },
|
|
|
+ { field: 'price', type: 'float' },
|
|
|
+ { field: 'sku', type: 'keyword' },
|
|
|
+ ])
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get existing product IDs from Qdrant to detect deletions
|
|
|
+ const existingPoints = await scrollPoints(collectionName, {
|
|
|
+ must: [{ key: 'store_id', match: { value: storeId } }]
|
|
|
+ }, 1000)
|
|
|
+
|
|
|
+ const existingProductIds = new Set(
|
|
|
+ existingPoints.points.map((p: any) => p.payload?.product_id).filter(Boolean)
|
|
|
+ )
|
|
|
+
|
|
|
+ // Current product IDs from Shopify
|
|
|
+ const currentProductIds = new Set(products.map(p => p.id.toString()))
|
|
|
+
|
|
|
+ // Find deleted products (in Qdrant but not in Shopify)
|
|
|
+ const deletedProductIds = Array.from(existingProductIds).filter(
|
|
|
+ id => !currentProductIds.has(id)
|
|
|
+ )
|
|
|
+
|
|
|
+ // Delete removed products from Qdrant
|
|
|
+ if (deletedProductIds.length > 0) {
|
|
|
+ console.log(`[Qdrant] Deleting ${deletedProductIds.length} removed products`)
|
|
|
+ await deletePointsByFilter(collectionName, {
|
|
|
+ must: [
|
|
|
+ { key: 'store_id', match: { value: storeId } },
|
|
|
+ { key: 'product_id', match: { any: deletedProductIds } }
|
|
|
+ ]
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // Convert products to Qdrant points
|
|
|
+ const points: QdrantPoint[] = products.map((product) => {
|
|
|
+ const primaryVariant = product.variants?.[0]
|
|
|
+ const productText = createProductText({
|
|
|
+ title: product.title,
|
|
|
+ description: product.body_html,
|
|
|
+ sku: primaryVariant?.sku,
|
|
|
+ vendor: product.vendor,
|
|
|
+ product_type: product.product_type,
|
|
|
+ tags: product.tags ? product.tags.split(',').map(t => t.trim()) : [],
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `shopify-${storeId}-${product.id}`,
|
|
|
+ vector: generateSimpleEmbedding(productText),
|
|
|
+ payload: {
|
|
|
+ store_id: storeId,
|
|
|
+ product_id: product.id.toString(),
|
|
|
+ platform: 'shopify',
|
|
|
+ title: product.title,
|
|
|
+ handle: product.handle,
|
|
|
+ vendor: product.vendor || null,
|
|
|
+ product_type: product.product_type || null,
|
|
|
+ status: product.status,
|
|
|
+ price: primaryVariant ? parseFloat(primaryVariant.price) : 0,
|
|
|
+ sku: primaryVariant?.sku || null,
|
|
|
+ inventory_quantity: primaryVariant?.inventory_quantity || 0,
|
|
|
+ description: product.body_html || null,
|
|
|
+ tags: product.tags ? product.tags.split(',').map(t => t.trim()) : [],
|
|
|
+ synced_at: new Date().toISOString(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // Upsert to Qdrant
|
|
|
+ await upsertPoints(collectionName, points)
|
|
|
+ synced = points.length
|
|
|
+
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'products',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ products.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime
|
|
|
+ )
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Products sync complete: ${synced} synced, ${deletedProductIds.length} deleted`)
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('[Qdrant] Product sync error:', error)
|
|
|
+ errors = products.length
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'products',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ products.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime,
|
|
|
+ error.message
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors }
|
|
|
+}
|
|
|
+
|
|
|
+// Sync orders to Qdrant
|
|
|
+async function syncOrdersToQdrant(
|
|
|
storeId: string,
|
|
|
+ storeName: string,
|
|
|
+ orders: ShopifyOrder[],
|
|
|
supabaseAdmin: any
|
|
|
): Promise<{ synced: number; errors: number }> {
|
|
|
+ const startTime = new Date()
|
|
|
+ const collectionName = getCollectionName(storeName, 'orders')
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Syncing ${orders.length} orders to ${collectionName}`)
|
|
|
+
|
|
|
+ let synced = 0
|
|
|
+ let errors = 0
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!(await collectionExists(collectionName))) {
|
|
|
+ await createCollection(collectionName, [
|
|
|
+ { field: 'store_id', type: 'keyword' },
|
|
|
+ { field: 'order_id', type: 'keyword' },
|
|
|
+ { field: 'platform', type: 'keyword' },
|
|
|
+ { field: 'financial_status', type: 'keyword' },
|
|
|
+ { field: 'total_price', type: 'float' },
|
|
|
+ { field: 'customer_email', type: 'keyword' },
|
|
|
+ ])
|
|
|
+ }
|
|
|
+
|
|
|
+ const points: QdrantPoint[] = orders.map((order) => {
|
|
|
+ const orderText = createOrderText({
|
|
|
+ order_number: order.order_number,
|
|
|
+ name: order.name,
|
|
|
+ customer_name: order.customer ? `${order.customer.first_name || ''} ${order.customer.last_name || ''}`.trim() : null,
|
|
|
+ total_price: order.current_total_price,
|
|
|
+ currency: order.currency,
|
|
|
+ financial_status: order.financial_status,
|
|
|
+ fulfillment_status: order.fulfillment_status,
|
|
|
+ line_items: order.line_items,
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `shopify-${storeId}-${order.id}`,
|
|
|
+ vector: generateSimpleEmbedding(orderText),
|
|
|
+ payload: {
|
|
|
+ store_id: storeId,
|
|
|
+ order_id: order.id.toString(),
|
|
|
+ platform: 'shopify',
|
|
|
+ order_number: order.order_number.toString(),
|
|
|
+ name: order.name,
|
|
|
+ email: order.email || null,
|
|
|
+ phone: order.customer?.phone || order.billing_address?.phone || null,
|
|
|
+ financial_status: order.financial_status,
|
|
|
+ fulfillment_status: order.fulfillment_status || null,
|
|
|
+ total_price: parseFloat(order.current_total_price) || 0,
|
|
|
+ currency: order.currency,
|
|
|
+ customer_name: order.customer ? `${order.customer.first_name || ''} ${order.customer.last_name || ''}`.trim() : null,
|
|
|
+ customer_email: order.customer?.email || order.email || null,
|
|
|
+ synced_at: new Date().toISOString(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ await upsertPoints(collectionName, points)
|
|
|
+ synced = points.length
|
|
|
+
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'orders',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ orders.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime
|
|
|
+ )
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Orders sync complete: ${synced} synced`)
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('[Qdrant] Order sync error:', error)
|
|
|
+ errors = orders.length
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'orders',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ orders.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime,
|
|
|
+ error.message
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors }
|
|
|
+}
|
|
|
+
|
|
|
+// Sync customers to Qdrant
|
|
|
+async function syncCustomersToQdrant(
|
|
|
+ storeId: string,
|
|
|
+ storeName: string,
|
|
|
+ customers: ShopifyCustomer[],
|
|
|
+ supabaseAdmin: any
|
|
|
+): Promise<{ synced: number; errors: number }> {
|
|
|
+ const startTime = new Date()
|
|
|
+ const collectionName = getCollectionName(storeName, 'customers')
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Syncing ${customers.length} customers to ${collectionName}`)
|
|
|
+
|
|
|
+ let synced = 0
|
|
|
+ let errors = 0
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (!(await collectionExists(collectionName))) {
|
|
|
+ await createCollection(collectionName, [
|
|
|
+ { field: 'store_id', type: 'keyword' },
|
|
|
+ { field: 'customer_id', type: 'keyword' },
|
|
|
+ { field: 'platform', type: 'keyword' },
|
|
|
+ { field: 'email', type: 'keyword' },
|
|
|
+ ])
|
|
|
+ }
|
|
|
+
|
|
|
+ const points: QdrantPoint[] = customers.map((customer) => {
|
|
|
+ const customerText = createCustomerText({
|
|
|
+ first_name: customer.first_name,
|
|
|
+ last_name: customer.last_name,
|
|
|
+ email: customer.email,
|
|
|
+ phone: customer.phone,
|
|
|
+ orders_count: customer.orders_count,
|
|
|
+ total_spent: customer.total_spent,
|
|
|
+ currency: customer.currency,
|
|
|
+ tags: customer.tags ? customer.tags.split(',').map(t => t.trim()) : [],
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ id: `shopify-${storeId}-${customer.id}`,
|
|
|
+ vector: generateSimpleEmbedding(customerText),
|
|
|
+ payload: {
|
|
|
+ store_id: storeId,
|
|
|
+ customer_id: customer.id.toString(),
|
|
|
+ platform: 'shopify',
|
|
|
+ email: customer.email,
|
|
|
+ first_name: customer.first_name || null,
|
|
|
+ last_name: customer.last_name || null,
|
|
|
+ phone: customer.phone || customer.default_address?.phone || null,
|
|
|
+ orders_count: customer.orders_count || 0,
|
|
|
+ total_spent: parseFloat(customer.total_spent) || 0,
|
|
|
+ currency: customer.currency || 'USD',
|
|
|
+ state: customer.state,
|
|
|
+ synced_at: new Date().toISOString(),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ await upsertPoints(collectionName, points)
|
|
|
+ synced = points.length
|
|
|
+
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'customers',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ customers.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime
|
|
|
+ )
|
|
|
+
|
|
|
+ console.log(`[Qdrant] Customers sync complete: ${synced} synced`)
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('[Qdrant] Customer sync error:', error)
|
|
|
+ errors = customers.length
|
|
|
+ await logQdrantSync(
|
|
|
+ supabaseAdmin,
|
|
|
+ storeId,
|
|
|
+ 'customers',
|
|
|
+ collectionName,
|
|
|
+ 'upsert',
|
|
|
+ customers.length,
|
|
|
+ synced,
|
|
|
+ errors,
|
|
|
+ startTime,
|
|
|
+ error.message
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors }
|
|
|
+}
|
|
|
+
|
|
|
+// Sync products from Shopify
|
|
|
+async function syncProducts(
|
|
|
+ storeId: string,
|
|
|
+ storeName: string,
|
|
|
+ supabaseAdmin: any,
|
|
|
+ qdrantEnabled: boolean,
|
|
|
+ canSyncProducts: boolean
|
|
|
+): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
|
|
|
console.log('[Shopify] Syncing products...')
|
|
|
let synced = 0
|
|
|
let errors = 0
|
|
|
|
|
|
+ if (!canSyncProducts) {
|
|
|
+ console.log('[Shopify] Product sync disabled by store permissions')
|
|
|
+ return { synced: 0, errors: 0 }
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
const products = await fetchWithRetry(() => fetchAllProducts(storeId))
|
|
|
|
|
|
@@ -77,9 +449,8 @@ async function syncProducts(
|
|
|
|
|
|
const currency = store?.alt_data?.currency || 'USD'
|
|
|
|
|
|
- // Map and upsert products
|
|
|
+ // Map and upsert products to SQL cache
|
|
|
const productsToCache = products.map((product: ShopifyProduct) => {
|
|
|
- // Get primary variant for main product data
|
|
|
const primaryVariant = product.variants?.[0]
|
|
|
|
|
|
return {
|
|
|
@@ -126,24 +497,39 @@ async function syncProducts(
|
|
|
}
|
|
|
|
|
|
console.log(`[Shopify] Products sync complete: ${synced} synced, ${errors} errors`)
|
|
|
+
|
|
|
+ // Sync to Qdrant if enabled
|
|
|
+ let qdrantResult
|
|
|
+ if (qdrantEnabled) {
|
|
|
+ qdrantResult = await syncProductsToQdrant(storeId, storeName, products, supabaseAdmin)
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors, qdrant: qdrantResult }
|
|
|
} catch (error) {
|
|
|
console.error('[Shopify] Product sync error:', error)
|
|
|
errors++
|
|
|
+ return { synced, errors }
|
|
|
}
|
|
|
-
|
|
|
- return { synced, errors }
|
|
|
}
|
|
|
|
|
|
// Sync orders from Shopify
|
|
|
async function syncOrders(
|
|
|
storeId: string,
|
|
|
+ storeName: string,
|
|
|
supabaseAdmin: any,
|
|
|
- countryCode: string
|
|
|
-): Promise<{ synced: number; errors: number }> {
|
|
|
+ countryCode: string,
|
|
|
+ qdrantEnabled: boolean,
|
|
|
+ canSyncOrders: boolean
|
|
|
+): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
|
|
|
console.log('[Shopify] Syncing orders...')
|
|
|
let synced = 0
|
|
|
let errors = 0
|
|
|
|
|
|
+ if (!canSyncOrders) {
|
|
|
+ console.log('[Shopify] Order sync disabled by store permissions')
|
|
|
+ return { synced: 0, errors: 0 }
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
const orders = await fetchWithRetry(() => fetchAllOrders(storeId))
|
|
|
|
|
|
@@ -204,24 +590,39 @@ async function syncOrders(
|
|
|
}
|
|
|
|
|
|
console.log(`[Shopify] Orders sync complete: ${synced} synced, ${errors} errors`)
|
|
|
+
|
|
|
+ // Sync to Qdrant if enabled
|
|
|
+ let qdrantResult
|
|
|
+ if (qdrantEnabled) {
|
|
|
+ qdrantResult = await syncOrdersToQdrant(storeId, storeName, orders, supabaseAdmin)
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors, qdrant: qdrantResult }
|
|
|
} catch (error) {
|
|
|
console.error('[Shopify] Order sync error:', error)
|
|
|
errors++
|
|
|
+ return { synced, errors }
|
|
|
}
|
|
|
-
|
|
|
- return { synced, errors }
|
|
|
}
|
|
|
|
|
|
// Sync customers from Shopify
|
|
|
async function syncCustomers(
|
|
|
storeId: string,
|
|
|
+ storeName: string,
|
|
|
supabaseAdmin: any,
|
|
|
- countryCode: string
|
|
|
-): Promise<{ synced: number; errors: number }> {
|
|
|
+ countryCode: string,
|
|
|
+ qdrantEnabled: boolean,
|
|
|
+ canSyncCustomers: boolean
|
|
|
+): Promise<{ synced: number; errors: number; qdrant?: { synced: number; errors: number } }> {
|
|
|
console.log('[Shopify] Syncing customers...')
|
|
|
let synced = 0
|
|
|
let errors = 0
|
|
|
|
|
|
+ if (!canSyncCustomers) {
|
|
|
+ console.log('[Shopify] Customer sync disabled by store permissions')
|
|
|
+ return { synced: 0, errors: 0 }
|
|
|
+ }
|
|
|
+
|
|
|
try {
|
|
|
const customers = await fetchWithRetry(() => fetchAllCustomers(storeId))
|
|
|
|
|
|
@@ -277,12 +678,19 @@ async function syncCustomers(
|
|
|
}
|
|
|
|
|
|
console.log(`[Shopify] Customers sync complete: ${synced} synced, ${errors} errors`)
|
|
|
+
|
|
|
+ // Sync to Qdrant if enabled
|
|
|
+ let qdrantResult
|
|
|
+ if (qdrantEnabled) {
|
|
|
+ qdrantResult = await syncCustomersToQdrant(storeId, storeName, customers, supabaseAdmin)
|
|
|
+ }
|
|
|
+
|
|
|
+ return { synced, errors, qdrant: qdrantResult }
|
|
|
} catch (error) {
|
|
|
console.error('[Shopify] Customer sync error:', error)
|
|
|
errors++
|
|
|
+ return { synced, errors }
|
|
|
}
|
|
|
-
|
|
|
- return { synced, errors }
|
|
|
}
|
|
|
|
|
|
serve(wrapHandler('shopify-sync', async (req) => {
|
|
|
@@ -325,13 +733,13 @@ serve(wrapHandler('shopify-sync', async (req) => {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
- // Verify store ownership
|
|
|
+ // Verify store ownership and get permissions
|
|
|
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
|
|
|
const supabaseAdmin = createClient(supabaseUrl, supabaseServiceKey)
|
|
|
|
|
|
const { data: store, error: storeError } = await supabaseAdmin
|
|
|
.from('stores')
|
|
|
- .select('id, platform_name, store_name, store_url')
|
|
|
+ .select('id, platform_name, store_name, store_url, qdrant_sync_enabled, data_access_permissions')
|
|
|
.eq('id', storeId)
|
|
|
.eq('user_id', user.id)
|
|
|
.eq('platform_name', 'shopify')
|
|
|
@@ -344,6 +752,33 @@ serve(wrapHandler('shopify-sync', async (req) => {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+ // Check data access permissions
|
|
|
+ const permissions = store.data_access_permissions || {}
|
|
|
+ const canSyncProducts = permissions.allow_product_access !== false
|
|
|
+ const canSyncOrders = permissions.allow_order_access !== false
|
|
|
+ const canSyncCustomers = permissions.allow_customer_access !== false
|
|
|
+ const qdrantEnabled = store.qdrant_sync_enabled !== false
|
|
|
+
|
|
|
+ console.log('[Shopify] Sync permissions:', {
|
|
|
+ products: canSyncProducts,
|
|
|
+ orders: canSyncOrders,
|
|
|
+ customers: canSyncCustomers,
|
|
|
+ qdrant: qdrantEnabled
|
|
|
+ })
|
|
|
+
|
|
|
+ // Initialize Qdrant collections if enabled
|
|
|
+ if (qdrantEnabled) {
|
|
|
+ try {
|
|
|
+ await initializeStoreCollections(
|
|
|
+ store.store_name,
|
|
|
+ canSyncOrders,
|
|
|
+ canSyncCustomers
|
|
|
+ )
|
|
|
+ } catch (error) {
|
|
|
+ console.error('[Qdrant] Failed to initialize collections:', error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// Detect country code from store URL for phone formatting
|
|
|
const countryCode = detectCountryCode(store.store_url)
|
|
|
console.log(`[Shopify] Detected country code: ${countryCode} for store: ${store.store_name}`)
|
|
|
@@ -359,15 +794,15 @@ serve(wrapHandler('shopify-sync', async (req) => {
|
|
|
|
|
|
// Perform sync based on type
|
|
|
if (syncType === 'all' || syncType === 'products') {
|
|
|
- results.products = await syncProducts(storeId, supabaseAdmin)
|
|
|
+ results.products = await syncProducts(storeId, store.store_name, supabaseAdmin, qdrantEnabled, canSyncProducts)
|
|
|
}
|
|
|
|
|
|
if (syncType === 'all' || syncType === 'orders') {
|
|
|
- results.orders = await syncOrders(storeId, supabaseAdmin, countryCode)
|
|
|
+ results.orders = await syncOrders(storeId, store.store_name, supabaseAdmin, countryCode, qdrantEnabled, canSyncOrders)
|
|
|
}
|
|
|
|
|
|
if (syncType === 'all' || syncType === 'customers') {
|
|
|
- results.customers = await syncCustomers(storeId, supabaseAdmin, countryCode)
|
|
|
+ results.customers = await syncCustomers(storeId, store.store_name, supabaseAdmin, countryCode, qdrantEnabled, canSyncCustomers)
|
|
|
}
|
|
|
|
|
|
results.completed_at = new Date().toISOString()
|
|
|
@@ -384,4 +819,14 @@ serve(wrapHandler('shopify-sync', async (req) => {
|
|
|
{ status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
)
|
|
|
|
|
|
+ } catch (error: any) {
|
|
|
+ console.error('[Shopify] Sync error:', error)
|
|
|
+ return new Response(
|
|
|
+ JSON.stringify({
|
|
|
+ success: false,
|
|
|
+ error: error.message || 'Sync failed'
|
|
|
+ }),
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
+ )
|
|
|
+ }
|
|
|
}))
|