first(); $queriesRun++; // Per-category breakdown $categoryBreakdown = Product::select('category') ->selectRaw('COUNT(*) as product_count') ->selectRaw('SUM(stock_quantity) as category_stock') ->selectRaw('AVG(price) as avg_price') ->selectRaw('SUM(price * stock_quantity) as category_value') ->groupBy('category') ->orderByDesc('category_value') ->get() ->toArray(); $queriesRun++; // Stock level distribution using CASE WHEN $stockDistribution = Product::selectRaw(" CASE WHEN stock_quantity = 0 THEN 'out_of_stock' WHEN stock_quantity BETWEEN 1 AND 10 THEN 'low_stock' WHEN stock_quantity BETWEEN 11 AND 50 THEN 'medium_stock' ELSE 'high_stock' END as stock_level ") ->selectRaw('COUNT(*) as count') ->groupBy('stock_level') ->get() ->toArray(); $queriesRun++; return [ 'queriesRun' => $queriesRun, 'rowsAffected' => 0, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'globalStats' => $globalStats ? $globalStats->toArray() : [], 'categoryBreakdown' => $categoryBreakdown, 'stockDistribution' => $stockDistribution, ], 'attempt' => Activity::getInfo()->attempt, ]; } public function runOrderDeepLoad(array $simulationConfig = []): array { FaultSimulator::maybeApply($simulationConfig, 'runOrderDeepLoad'); $startTime = microtime(true); $queriesRun = 0; // Eager load orders with items and products, count items $orders = Order::with(['items.product']) ->withCount('items') ->get(); $queriesRun += 3; // orders + items + products (eager loading) // Collection mapping — build summary per order $orderSummaries = $orders->map(function ($order) { $items = $order->items; $heaviest = $items->sortByDesc('quantity')->first(); return [ 'id' => $order->id, 'order_number' => $order->order_number, 'customer_name' => $order->customer_name, 'items_count' => $order->items_count, 'total_amount' => $order->total_amount, 'heaviest_line_item' => $heaviest ? [ 'product' => $heaviest->product?->name, 'quantity' => $heaviest->quantity, ] : null, ]; })->toArray(); // Products that have been ordered vs never ordered $orderedProductCount = Product::whereHas('orderItems')->count(); $queriesRun++; $neverOrderedCount = Product::whereDoesntHave('orderItems')->count(); $queriesRun++; return [ 'queriesRun' => $queriesRun, 'rowsAffected' => 0, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'orderCount' => $orders->count(), 'orderSummaries' => array_slice($orderSummaries, 0, 10), 'orderedProductCount' => $orderedProductCount, 'neverOrderedCount' => $neverOrderedCount, ], 'attempt' => Activity::getInfo()->attempt, ]; } public function runProductScoring(array $simulationConfig = []): array { FaultSimulator::maybeApply($simulationConfig, 'runProductScoring'); $startTime = microtime(true); $queriesRun = 0; // Premium products: high price, in stock, ordered by price desc $premiumProducts = Product::where('price', '>', 50) ->where('stock_quantity', '>', 0) ->where('status', 'active') ->orderByDesc('price') ->limit(10) ->get(['id', 'name', 'price', 'stock_quantity', 'category']) ->toArray(); $queriesRun++; // At-risk inventory: nested where with orWhere closures $atRiskProducts = Product::where(function ($q) { $q->where('stock_quantity', 0) ->where('status', 'active'); })->orWhere(function ($q) { $q->where('stock_quantity', '<', 5) ->where('stock_quantity', '>', 0) ->whereHas('orderItems'); })->get(['id', 'name', 'stock_quantity', 'category', 'status']) ->toArray(); $queriesRun++; // Category tiers: groupBy with having $categoryTiers = Product::select('category') ->selectRaw('COUNT(*) as product_count') ->selectRaw('AVG(price) as avg_price') ->selectRaw('SUM(stock_quantity) as total_stock') ->groupBy('category') ->having('avg_price', '>', 50) ->get() ->toArray(); $queriesRun++; // Demand score: leftJoin with computed ratio $demandScores = DB::table('products') ->leftJoin('order_items', 'products.id', '=', 'order_items.product_id') ->select( 'products.id', 'products.name', 'products.stock_quantity', 'products.category' ) ->selectRaw('COALESCE(SUM(order_items.quantity), 0) as total_ordered') ->selectRaw('CASE WHEN products.stock_quantity > 0 THEN ROUND(COALESCE(SUM(order_items.quantity), 0)::numeric / products.stock_quantity, 2) ELSE 0 END as demand_ratio') ->groupBy('products.id', 'products.name', 'products.stock_quantity', 'products.category') ->orderByDesc('demand_ratio') ->limit(15) ->get() ->map(fn ($r) => (array) $r) ->toArray(); $queriesRun++; return [ 'queriesRun' => $queriesRun, 'rowsAffected' => 0, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'premiumProducts' => $premiumProducts, 'atRiskProducts' => array_slice($atRiskProducts, 0, 10), 'categoryTiers' => $categoryTiers, 'demandScores' => $demandScores, ], 'attempt' => Activity::getInfo()->attempt, ]; } public function runStockAudit(array $simulationConfig = []): array { FaultSimulator::maybeApply($simulationConfig, 'runStockAudit'); $startTime = microtime(true); $queriesRun = 0; $rowsAffected = 0; $negativeFixed = 0; $timestamped = 0; Product::orderBy('id')->chunk(100, function ($products) use (&$queriesRun, &$rowsAffected, &$negativeFixed, &$timestamped) { $queriesRun++; // each chunk is a query Activity::heartbeat([ 'processed' => $queriesRun * 100, 'negativeFixed' => $negativeFixed, 'timestamped' => $timestamped, ]); foreach ($products as $product) { $changed = false; $updates = []; // Fix negative stock if ($product->stock_quantity < 0) { $updates['stock_quantity'] = 0; $negativeFixed++; $changed = true; } // Stamp missing imported_at if ($product->imported_at === null) { $updates['imported_at'] = now(); $timestamped++; $changed = true; } if ($changed) { $product->update($updates); $rowsAffected++; $queriesRun++; } } }); return [ 'queriesRun' => $queriesRun, 'rowsAffected' => $rowsAffected, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'negativeStockFixed' => $negativeFixed, 'missingTimestampFixed' => $timestamped, 'note' => 'Idempotent — subsequent runs make 0 changes if data is clean', ], 'attempt' => Activity::getInfo()->attempt, ]; } public function runPriceRecalculation(array $simulationConfig = []): array { FaultSimulator::maybeApply($simulationConfig, 'runPriceRecalculation'); $startTime = microtime(true); $queriesRun = 0; $rowsAffected = 0; $discrepancies = []; // Recalculate each order total from its items within a transaction $orderIds = Order::pluck('id')->toArray(); $queriesRun++; foreach ($orderIds as $orderId) { DB::transaction(function () use ($orderId, &$queriesRun, &$rowsAffected, &$discrepancies) { $order = Order::lockForUpdate()->find($orderId); $queriesRun++; if (!$order) { return; } $recalculated = OrderItem::where('order_id', $orderId) ->selectRaw('SUM(quantity * unit_price) as computed_total') ->value('computed_total') ?? 0; $queriesRun++; $oldTotal = (float) $order->total_amount; $newTotal = round((float) $recalculated, 2); if (abs($oldTotal - $newTotal) > 0.01) { $discrepancies[] = [ 'order_id' => $orderId, 'old_total' => $oldTotal, 'new_total' => $newTotal, 'diff' => round($newTotal - $oldTotal, 2), ]; $order->update(['total_amount' => $newTotal]); $rowsAffected++; $queriesRun++; } }); } // Demonstrate updateOrCreate (upsert) pattern Product::updateOrCreate( ['sku' => '_RECONCILIATION_MARKER'], [ 'name' => 'Reconciliation Marker', 'price' => 0, 'stock_quantity' => count($orderIds), 'category' => 'system', 'status' => 'inactive', 'description' => 'Last reconciliation: ' . now()->toISOString(), 'imported_at' => now(), ] ); $queriesRun++; $rowsAffected++; return [ 'queriesRun' => $queriesRun, 'rowsAffected' => $rowsAffected, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'ordersChecked' => count($orderIds), 'discrepancies' => $discrepancies, 'discrepancyCount' => count($discrepancies), 'reconciliationMarkerSet' => true, ], 'attempt' => Activity::getInfo()->attempt, ]; } public function runSummaryReport(array $simulationConfig = []): array { FaultSimulator::maybeApply($simulationConfig, 'runSummaryReport'); $startTime = microtime(true); $queriesRun = 0; // Top-selling products via DB::table join $topSelling = DB::table('order_items') ->select('products.id', 'products.name', 'products.category') ->selectRaw('SUM(order_items.quantity) as total_sold') ->selectRaw('SUM(order_items.quantity * order_items.unit_price) as total_revenue') ->join('products', 'order_items.product_id', '=', 'products.id') ->groupBy('products.id', 'products.name', 'products.category') ->orderByDesc('total_revenue') ->limit(10) ->get() ->map(fn ($r) => (array) $r) ->toArray(); $queriesRun++; // Revenue per category $revenueByCategory = DB::table('order_items') ->join('products', 'order_items.product_id', '=', 'products.id') ->select('products.category') ->selectRaw('SUM(order_items.quantity * order_items.unit_price) as category_revenue') ->selectRaw('COUNT(DISTINCT order_items.order_id) as order_count') ->groupBy('products.category') ->orderByDesc('category_revenue') ->get() ->map(fn ($r) => (array) $r) ->toArray(); $queriesRun++; // Customer spend ranking $customerRanking = Order::select('customer_name') ->selectRaw('COUNT(*) as order_count') ->selectRaw('SUM(total_amount) as total_spent') ->selectRaw('AVG(total_amount) as avg_order_value') ->groupBy('customer_name') ->orderByDesc('total_spent') ->limit(10) ->get() ->toArray(); $queriesRun++; // Cross-model health summary $healthSummary = [ 'products' => Product::count(), 'active_products' => Product::where('status', 'active')->count(), 'orders' => Order::count(), 'order_items' => OrderItem::count(), 'users' => User::count(), ]; $queriesRun += 5; return [ 'queriesRun' => $queriesRun, 'rowsAffected' => 0, 'executionTimeMs' => round((microtime(true) - $startTime) * 1000, 2), 'data' => [ 'topSelling' => $topSelling, 'revenueByCategory' => $revenueByCategory, 'customerRanking' => $customerRanking, 'healthSummary' => $healthSummary, ], 'attempt' => Activity::getInfo()->attempt, ]; } }