diff --git a/backend/migrations/092_fix_trulieve_urls.sql b/backend/migrations/092_fix_trulieve_urls.sql new file mode 100644 index 00000000..f46afd44 --- /dev/null +++ b/backend/migrations/092_fix_trulieve_urls.sql @@ -0,0 +1,30 @@ +-- Fix 3 Trulieve/Harvest stores with incorrect menu URLs +-- These records have NULL or mismatched platform_dispensary_id so store_discovery +-- ON CONFLICT can't update them automatically + +UPDATE dispensaries +SET + menu_url = 'https://dutchie.com/dispensary/svaccha-llc-nirvana-center-apache-junction', + updated_at = NOW() +WHERE id = 224; + +UPDATE dispensaries +SET + menu_url = 'https://dutchie.com/dispensary/trulieve-of-phoenix-tatum', + updated_at = NOW() +WHERE id = 76; + +UPDATE dispensaries +SET + menu_url = 'https://dutchie.com/dispensary/harvest-of-havasu', + updated_at = NOW() +WHERE id = 403; + +-- Queue entry_point_discovery tasks to resolve their platform_dispensary_id +-- method='http' ensures only workers that passed http preflight can claim these +INSERT INTO worker_tasks (role, dispensary_id, priority, scheduled_for, method) +VALUES + ('entry_point_discovery', 224, 5, NOW(), 'http'), + ('entry_point_discovery', 76, 5, NOW(), 'http'), + ('entry_point_discovery', 403, 5, NOW(), 'http') +ON CONFLICT DO NOTHING; diff --git a/backend/src/routes/intelligence.ts b/backend/src/routes/intelligence.ts index 8b13715d..a01a541b 100644 --- a/backend/src/routes/intelligence.ts +++ b/backend/src/routes/intelligence.ts @@ -325,11 +325,12 @@ router.get('/stores', async (req: Request, res: Response) => { (SELECT COUNT(*) FROM store_product_snapshots sps WHERE sps.store_product_id IN (SELECT id FROM store_products WHERE dispensary_id = d.id)) as snapshot_count FROM dispensaries d - LEFT JOIN store_products sp ON sp.dispensary_id = d.id + INNER JOIN store_products sp ON sp.dispensary_id = d.id LEFT JOIN chains c ON d.chain_id = c.id WHERE d.state IS NOT NULL AND d.crawl_enabled = true ${stateFilter} GROUP BY d.id, d.name, d.dba_name, d.city, d.state, d.menu_type, d.crawl_enabled, c.name + HAVING COUNT(sp.id) > 0 ORDER BY sku_count DESC LIMIT $1 `, params); diff --git a/cannaiq/src/pages/IntelligenceStores.tsx b/cannaiq/src/pages/IntelligenceStores.tsx index 7832358f..6c9acd49 100644 --- a/cannaiq/src/pages/IntelligenceStores.tsx +++ b/cannaiq/src/pages/IntelligenceStores.tsx @@ -82,10 +82,16 @@ export function IntelligenceStores() { }; const getCrawlFrequencyBadge = (hours: number | null) => { - if (hours === null) return Unknown; - if (hours <= 4) return High ({hours}h); - if (hours <= 12) return Medium ({hours}h); - return Low ({hours}h); + if (hours === null) { + return Unknown; + } + if (hours <= 4) { + return High ({hours}h); + } + if (hours <= 12) { + return Medium ({hours}h); + } + return Low ({hours}h); }; if (loading) { @@ -263,7 +269,7 @@ export function IntelligenceStores() { {store.chainName ? ( - {store.chainName} + {store.chainName} ) : ( - )} @@ -275,7 +281,7 @@ export function IntelligenceStores() { {(store.snapshotCount || 0).toLocaleString()} - + {formatTimeAgo(store.lastCrawl)}