|
@@ -987,6 +987,523 @@ serve(wrapHandler('api', async (req) => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // GET /api/store-data/products|orders|customers - Get store data by type
|
|
|
|
|
+ if (path.match(/^store-data\/(products|orders|customers)$/) && req.method === 'GET') {
|
|
|
|
|
+ const dataType = path.split('/')[1] // products, orders, or customers
|
|
|
|
|
+ const storeId = url.searchParams.get('store_id')
|
|
|
|
|
+ const page = parseInt(url.searchParams.get('page') || '1')
|
|
|
|
|
+ const limit = parseInt(url.searchParams.get('limit') || '25')
|
|
|
|
|
+ const search = url.searchParams.get('search')
|
|
|
|
|
+ const enabledFilter = url.searchParams.get('enabled')
|
|
|
|
|
+
|
|
|
|
|
+ if (!storeId) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'store_id is required' }),
|
|
|
|
|
+ { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify store ownership
|
|
|
|
|
+ const { data: store, error: storeError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('id, platform_name')
|
|
|
|
|
+ .eq('id', storeId)
|
|
|
|
|
+ .eq('user_id', user.id)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (storeError || !store) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Store not found or access denied' }),
|
|
|
|
|
+ { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // Map dataType to singular form for table lookup
|
|
|
|
|
+ const singularType = dataType === 'products' ? 'product' : dataType === 'orders' ? 'order' : 'customer'
|
|
|
|
|
+ const platform = store.platform_name
|
|
|
|
|
+
|
|
|
|
|
+ // Get table info based on platform
|
|
|
|
|
+ const tableName = platform === 'woocommerce'
|
|
|
|
|
+ ? `woocommerce_${dataType}_cache`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${dataType}_cache`
|
|
|
|
|
+ : `shoprenter_${dataType}_cache`
|
|
|
|
|
+
|
|
|
|
|
+ const idColumn = platform === 'woocommerce'
|
|
|
|
|
+ ? `wc_${singularType}_id`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${singularType}_id`
|
|
|
|
|
+ : `shoprenter_${singularType}_id`
|
|
|
|
|
+
|
|
|
|
|
+ // Build cache query
|
|
|
|
|
+ let cacheQuery = supabase
|
|
|
|
|
+ .from(tableName)
|
|
|
|
|
+ .select('*')
|
|
|
|
|
+ .eq('store_id', storeId)
|
|
|
|
|
+ .order('created_at', { ascending: false })
|
|
|
|
|
+
|
|
|
|
|
+ // Apply search filter
|
|
|
|
|
+ if (search) {
|
|
|
|
|
+ if (dataType === 'products') {
|
|
|
|
|
+ if (platform === 'shoprenter') {
|
|
|
|
|
+ cacheQuery = cacheQuery.or(`product_data->>name.ilike.%${search}%,product_data->>sku.ilike.%${search}%`)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ cacheQuery = cacheQuery.or(`name.ilike.%${search}%,sku.ilike.%${search}%`)
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (dataType === 'orders') {
|
|
|
|
|
+ cacheQuery = cacheQuery.or(`order_number.ilike.%${search}%,customer_name.ilike.%${search}%,customer_email.ilike.%${search}%`)
|
|
|
|
|
+ } else if (dataType === 'customers') {
|
|
|
|
|
+ cacheQuery = cacheQuery.or(`email.ilike.%${search}%,first_name.ilike.%${search}%,last_name.ilike.%${search}%,phone.ilike.%${search}%`)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const { data: cacheItems, error: cacheError } = await cacheQuery
|
|
|
|
|
+
|
|
|
|
|
+ if (cacheError) {
|
|
|
|
|
+ console.error(`Error fetching ${dataType} from cache:`, cacheError)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: `Failed to fetch ${dataType}` }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!cacheItems || cacheItems.length === 0) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ data: [],
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ enabled_count: 0,
|
|
|
|
|
+ disabled_count: 0
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Get all exclusions for this store and type
|
|
|
|
|
+ const { data: exclusions } = await supabase
|
|
|
|
|
+ .from('store_data_exclusions')
|
|
|
|
|
+ .select('data_id, is_enabled')
|
|
|
|
|
+ .eq('store_id', storeId)
|
|
|
|
|
+ .eq('data_type', singularType)
|
|
|
|
|
+
|
|
|
|
|
+ // Create exclusion map
|
|
|
|
|
+ const exclusionMap = new Map()
|
|
|
|
|
+ if (exclusions) {
|
|
|
|
|
+ exclusions.forEach(e => {
|
|
|
|
|
+ exclusionMap.set(e.data_id, e.is_enabled)
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Transform cache items to result format
|
|
|
|
|
+ let results: any[] = []
|
|
|
|
|
+ for (const item of cacheItems) {
|
|
|
|
|
+ const itemId = item[idColumn]
|
|
|
|
|
+ const isEnabled = exclusionMap.has(itemId) ? exclusionMap.get(itemId) : true
|
|
|
|
|
+
|
|
|
|
|
+ let resultItem: any = {
|
|
|
|
|
+ id: itemId,
|
|
|
|
|
+ enabled_in_context: isEnabled
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Add type-specific fields
|
|
|
|
|
+ if (dataType === 'products') {
|
|
|
|
|
+ if (platform === 'shoprenter') {
|
|
|
|
|
+ resultItem.name = item.product_data?.name || ''
|
|
|
|
|
+ resultItem.sku = item.product_data?.sku || ''
|
|
|
|
|
+ resultItem.price = item.product_data?.price || '0'
|
|
|
|
|
+ resultItem.currency = item.product_data?.currency || 'HUF'
|
|
|
|
|
+ } else {
|
|
|
|
|
+ resultItem.name = item.name || item.title || ''
|
|
|
|
|
+ resultItem.sku = item.sku || ''
|
|
|
|
|
+ resultItem.price = item.price || '0'
|
|
|
|
|
+ resultItem.currency = item.currency || 'USD'
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (dataType === 'orders') {
|
|
|
|
|
+ resultItem.order_number = item.order_number || item.name || ''
|
|
|
|
|
+ resultItem.customer_name = item.customer_name || ''
|
|
|
|
|
+ resultItem.customer_email = item.customer_email || item.email || ''
|
|
|
|
|
+ resultItem.total = item.total || item.total_price || '0'
|
|
|
|
|
+ resultItem.currency = item.currency || 'USD'
|
|
|
|
|
+ } else if (dataType === 'customers') {
|
|
|
|
|
+ resultItem.name = `${item.first_name || ''} ${item.last_name || ''}`.trim()
|
|
|
|
|
+ resultItem.email = item.email || ''
|
|
|
|
|
+ resultItem.orders_count = item.orders_count || 0
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ results.push(resultItem)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Apply enabled filter if specified
|
|
|
|
|
+ if (enabledFilter !== null) {
|
|
|
|
|
+ const filterEnabled = enabledFilter === 'true'
|
|
|
|
|
+ results = results.filter(r => r.enabled_in_context === filterEnabled)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Calculate counts
|
|
|
|
|
+ const enabledCount = results.filter(r => r.enabled_in_context).length
|
|
|
|
|
+ const disabledCount = results.filter(r => !r.enabled_in_context).length
|
|
|
|
|
+ const totalCount = results.length
|
|
|
|
|
+
|
|
|
|
|
+ // Apply pagination
|
|
|
|
|
+ const offset = (page - 1) * limit
|
|
|
|
|
+ const paginatedResults = results.slice(offset, offset + limit)
|
|
|
|
|
+
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ data: paginatedResults,
|
|
|
|
|
+ total: totalCount,
|
|
|
|
|
+ enabled_count: enabledCount,
|
|
|
|
|
+ disabled_count: disabledCount
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error(`Error fetching ${dataType}:`, error)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: `Failed to fetch ${dataType}` }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // PUT /api/store-data/:type/:id/toggle - Toggle individual item
|
|
|
|
|
+ if (path.match(/^store-data\/(products|orders|customers)\/[^\/]+\/toggle$/) && req.method === 'PUT') {
|
|
|
|
|
+ const pathParts = path.split('/')
|
|
|
|
|
+ const dataType = pathParts[1] // products, orders, or customers
|
|
|
|
|
+ const itemId = pathParts[2]
|
|
|
|
|
+ const { store_id, enabled } = await req.json()
|
|
|
|
|
+
|
|
|
|
|
+ if (!store_id) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'store_id is required' }),
|
|
|
|
|
+ { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify store ownership
|
|
|
|
|
+ const { data: store, error: storeError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('id, platform_name')
|
|
|
|
|
+ .eq('id', store_id)
|
|
|
|
|
+ .eq('user_id', user.id)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (storeError || !store) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Store not found or access denied' }),
|
|
|
|
|
+ { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const singularType = dataType === 'products' ? 'product' : dataType === 'orders' ? 'order' : 'customer'
|
|
|
|
|
+ const platform = store.platform_name
|
|
|
|
|
+
|
|
|
|
|
+ // Get metadata from cache
|
|
|
|
|
+ const tableName = platform === 'woocommerce'
|
|
|
|
|
+ ? `woocommerce_${dataType}_cache`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${dataType}_cache`
|
|
|
|
|
+ : `shoprenter_${dataType}_cache`
|
|
|
|
|
+
|
|
|
|
|
+ const idColumn = platform === 'woocommerce'
|
|
|
|
|
+ ? `wc_${singularType}_id`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${singularType}_id`
|
|
|
|
|
+ : `shoprenter_${singularType}_id`
|
|
|
|
|
+
|
|
|
|
|
+ const { data: cacheItem } = await supabase
|
|
|
|
|
+ .from(tableName)
|
|
|
|
|
+ .select('*')
|
|
|
|
|
+ .eq('store_id', store_id)
|
|
|
|
|
+ .eq(idColumn, itemId)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ let metadata = {}
|
|
|
|
|
+ if (cacheItem) {
|
|
|
|
|
+ if (singularType === 'product') {
|
|
|
|
|
+ if (platform === 'shoprenter') {
|
|
|
|
|
+ metadata = {
|
|
|
|
|
+ name: cacheItem.product_data?.name,
|
|
|
|
|
+ sku: cacheItem.product_data?.sku,
|
|
|
|
|
+ price: cacheItem.product_data?.price
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ metadata = {
|
|
|
|
|
+ name: cacheItem.name || cacheItem.title,
|
|
|
|
|
+ sku: cacheItem.sku,
|
|
|
|
|
+ price: cacheItem.price
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (singularType === 'order') {
|
|
|
|
|
+ metadata = {
|
|
|
|
|
+ order_number: cacheItem.order_number || cacheItem.name,
|
|
|
|
|
+ customer_name: cacheItem.customer_name,
|
|
|
|
|
+ total: cacheItem.total || cacheItem.total_price
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (singularType === 'customer') {
|
|
|
|
|
+ metadata = {
|
|
|
|
|
+ email: cacheItem.email,
|
|
|
|
|
+ first_name: cacheItem.first_name,
|
|
|
|
|
+ last_name: cacheItem.last_name
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Upsert exclusion
|
|
|
|
|
+ const { error: upsertError } = await supabase
|
|
|
|
|
+ .from('store_data_exclusions')
|
|
|
|
|
+ .upsert({
|
|
|
|
|
+ store_id: store_id,
|
|
|
|
|
+ data_type: singularType,
|
|
|
|
|
+ data_id: itemId,
|
|
|
|
|
+ is_enabled: enabled,
|
|
|
|
|
+ metadata,
|
|
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
|
|
+ }, {
|
|
|
|
|
+ onConflict: 'store_id,data_type,data_id'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (upsertError) {
|
|
|
|
|
+ console.error('Error upserting exclusion:', upsertError)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to update item' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: `Item ${enabled ? 'enabled' : 'disabled'} successfully`
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('Error toggling item:', error)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to update item' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // PUT /api/store-data/:type/bulk-toggle - Bulk toggle items
|
|
|
|
|
+ if (path.match(/^store-data\/(products|orders|customers)\/bulk-toggle$/) && req.method === 'PUT') {
|
|
|
|
|
+ const dataType = path.split('/')[1]
|
|
|
|
|
+ const { store_id, item_ids, enabled } = await req.json()
|
|
|
|
|
+
|
|
|
|
|
+ if (!store_id || !item_ids || !Array.isArray(item_ids)) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'store_id and item_ids array are required' }),
|
|
|
|
|
+ { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify store ownership
|
|
|
|
|
+ const { data: store, error: storeError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('id, platform_name')
|
|
|
|
|
+ .eq('id', store_id)
|
|
|
|
|
+ .eq('user_id', user.id)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (storeError || !store) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Store not found or access denied' }),
|
|
|
|
|
+ { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const singularType = dataType === 'products' ? 'product' : dataType === 'orders' ? 'order' : 'customer'
|
|
|
|
|
+
|
|
|
|
|
+ for (const itemId of item_ids) {
|
|
|
|
|
+ await supabase
|
|
|
|
|
+ .from('store_data_exclusions')
|
|
|
|
|
+ .upsert({
|
|
|
|
|
+ store_id: store_id,
|
|
|
|
|
+ data_type: singularType,
|
|
|
|
|
+ data_id: itemId,
|
|
|
|
|
+ is_enabled: enabled,
|
|
|
|
|
+ metadata: {},
|
|
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
|
|
+ }, {
|
|
|
|
|
+ onConflict: 'store_id,data_type,data_id'
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: `${item_ids.length} items ${enabled ? 'enabled' : 'disabled'} successfully`
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('Error bulk toggling items:', error)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to update items' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // PUT /api/store-data/:type/enable-all - Enable all items
|
|
|
|
|
+ if (path.match(/^store-data\/(products|orders|customers)\/enable-all$/) && req.method === 'PUT') {
|
|
|
|
|
+ const dataType = path.split('/')[1]
|
|
|
|
|
+ const { store_id } = await req.json()
|
|
|
|
|
+
|
|
|
|
|
+ if (!store_id) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'store_id is required' }),
|
|
|
|
|
+ { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify store ownership
|
|
|
|
|
+ const { data: store, error: storeError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('id')
|
|
|
|
|
+ .eq('id', store_id)
|
|
|
|
|
+ .eq('user_id', user.id)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (storeError || !store) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Store not found or access denied' }),
|
|
|
|
|
+ { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const singularType = dataType === 'products' ? 'product' : dataType === 'orders' ? 'order' : 'customer'
|
|
|
|
|
+
|
|
|
|
|
+ // Update all exclusions for this store and type to enabled
|
|
|
|
|
+ const { error: updateError } = await supabase
|
|
|
|
|
+ .from('store_data_exclusions')
|
|
|
|
|
+ .update({ is_enabled: true, updated_at: new Date().toISOString() })
|
|
|
|
|
+ .eq('store_id', store_id)
|
|
|
|
|
+ .eq('data_type', singularType)
|
|
|
|
|
+
|
|
|
|
|
+ if (updateError) {
|
|
|
|
|
+ console.error('Error enabling all items:', updateError)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to enable all items' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: `All ${dataType} enabled successfully`
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('Error enabling all items:', error)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to enable all items' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // PUT /api/store-data/:type/disable-all - Disable all items
|
|
|
|
|
+ if (path.match(/^store-data\/(products|orders|customers)\/disable-all$/) && req.method === 'PUT') {
|
|
|
|
|
+ const dataType = path.split('/')[1]
|
|
|
|
|
+ const { store_id } = await req.json()
|
|
|
|
|
+
|
|
|
|
|
+ if (!store_id) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'store_id is required' }),
|
|
|
|
|
+ { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Verify store ownership
|
|
|
|
|
+ const { data: store, error: storeError } = await supabase
|
|
|
|
|
+ .from('stores')
|
|
|
|
|
+ .select('id, platform_name')
|
|
|
|
|
+ .eq('id', store_id)
|
|
|
|
|
+ .eq('user_id', user.id)
|
|
|
|
|
+ .single()
|
|
|
|
|
+
|
|
|
|
|
+ if (storeError || !store) {
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Store not found or access denied' }),
|
|
|
|
|
+ { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ const singularType = dataType === 'products' ? 'product' : dataType === 'orders' ? 'order' : 'customer'
|
|
|
|
|
+ const platform = store.platform_name
|
|
|
|
|
+
|
|
|
|
|
+ // Get all items from cache to create exclusions
|
|
|
|
|
+ const tableName = platform === 'woocommerce'
|
|
|
|
|
+ ? `woocommerce_${dataType}_cache`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${dataType}_cache`
|
|
|
|
|
+ : `shoprenter_${dataType}_cache`
|
|
|
|
|
+
|
|
|
|
|
+ const idColumn = platform === 'woocommerce'
|
|
|
|
|
+ ? `wc_${singularType}_id`
|
|
|
|
|
+ : platform === 'shopify'
|
|
|
|
|
+ ? `shopify_${singularType}_id`
|
|
|
|
|
+ : `shoprenter_${singularType}_id`
|
|
|
|
|
+
|
|
|
|
|
+ const { data: cacheItems } = await supabase
|
|
|
|
|
+ .from(tableName)
|
|
|
|
|
+ .select(idColumn)
|
|
|
|
|
+ .eq('store_id', store_id)
|
|
|
|
|
+
|
|
|
|
|
+ if (cacheItems && cacheItems.length > 0) {
|
|
|
|
|
+ // Create or update exclusions for all items
|
|
|
|
|
+ const exclusions = cacheItems.map(item => ({
|
|
|
|
|
+ store_id: store_id,
|
|
|
|
|
+ data_type: singularType,
|
|
|
|
|
+ data_id: item[idColumn],
|
|
|
|
|
+ is_enabled: false,
|
|
|
|
|
+ metadata: {},
|
|
|
|
|
+ updated_at: new Date().toISOString()
|
|
|
|
|
+ }))
|
|
|
|
|
+
|
|
|
|
|
+ const { error: upsertError } = await supabase
|
|
|
|
|
+ .from('store_data_exclusions')
|
|
|
|
|
+ .upsert(exclusions, {
|
|
|
|
|
+ onConflict: 'store_id,data_type,data_id'
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (upsertError) {
|
|
|
|
|
+ console.error('Error disabling all items:', upsertError)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to disable all items' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({
|
|
|
|
|
+ success: true,
|
|
|
|
|
+ message: `All ${dataType} disabled successfully`
|
|
|
|
|
+ }),
|
|
|
|
|
+ { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('Error disabling all items:', error)
|
|
|
|
|
+ return new Response(
|
|
|
|
|
+ JSON.stringify({ error: 'Failed to disable all items' }),
|
|
|
|
|
+ { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// GET /api/dashboard/stats - Get dashboard statistics
|
|
// GET /api/dashboard/stats - Get dashboard statistics
|
|
|
if (path === 'dashboard/stats' && req.method === 'GET') {
|
|
if (path === 'dashboard/stats' && req.method === 'GET') {
|
|
|
// TODO: Implement real dashboard stats calculation
|
|
// TODO: Implement real dashboard stats calculation
|