prepare( "SELECT l.id, l.product_sku, l.lot_number, l.expiry_date, l.description, p.product_name, p.uom, 'md_lot' AS source FROM md_lot l INNER JOIN md_product p ON p.company_id = l.company_id AND p.sku = l.product_sku WHERE l.company_id = :company_id AND p.status > 0 ORDER BY l.product_sku ASC, l.lot_number ASC" ); $sth->execute([':company_id' => $company_id]); $rows = $sth->fetchAll(PDO::FETCH_ASSOC); $seen = []; foreach ($rows as $row) { $seen[$row['product_sku'] . '|' . $row['lot_number']] = true; } $warehouses = $pdo2->prepare( "SELECT id FROM md_warehouse WHERE company_id = :company_id AND status = 1" ); $warehouses->execute([':company_id' => $company_id]); foreach ($warehouses->fetchAll(PDO::FETCH_COLUMN) as $warehouse_id) { $table = stockTableNameFromWarehouseId((int)$warehouse_id); $stock = $pdo2->query( "SELECT s.product_sku, s.lot_number, p.product_name, p.uom, ROUND(SUM(COALESCE(s.`in`, 0)) - SUM(COALESCE(s.`out`, 0)), 2) AS balance FROM `{$table}` s INNER JOIN md_product p ON p.company_id = s.company_id AND p.sku = s.product_sku WHERE s.company_id = " . (int)$company_id . " AND s.status = 1 AND s.lot_number IS NOT NULL AND s.lot_number <> '' AND p.status > 0 GROUP BY s.product_sku, s.lot_number, p.product_name, p.uom HAVING balance > 0" ); foreach ($stock->fetchAll(PDO::FETCH_ASSOC) as $row) { $key = $row['product_sku'] . '|' . $row['lot_number']; if (isset($seen[$key])) continue; $seen[$key] = true; $rows[] = [ 'id' => null, 'product_sku' => $row['product_sku'], 'lot_number' => $row['lot_number'], 'expiry_date' => null, 'description' => 'Found in active stock; missing md_lot row.', 'product_name'=> $row['product_name'], 'uom' => $row['uom'], 'source' => 'active_stock', ]; } } $barcodes = $pdo2->prepare( "SELECT b.product_sku, b.lot_number, b.serial_number, b.barcode, b.status, b.created_dt, p.product_name, p.uom FROM md_barcode b INNER JOIN md_product p ON p.company_id = b.company_id AND p.sku = b.product_sku WHERE b.company_id = :company_id AND b.barcode_type = 'sku' AND b.product_sku IS NOT NULL AND b.product_sku <> '' AND b.lot_number IS NOT NULL AND b.lot_number <> '' AND p.status > 0 ORDER BY b.created_dt DESC, b.id DESC" ); $barcodes->execute([':company_id' => $company_id]); foreach ($barcodes->fetchAll(PDO::FETCH_ASSOC) as $row) { $key = $row['product_sku'] . '|' . $row['lot_number']; if (isset($seen[$key])) continue; $seen[$key] = true; $rows[] = [ 'id' => null, 'product_sku' => $row['product_sku'], 'lot_number' => $row['lot_number'], 'expiry_date' => null, 'description' => 'Prepared barcode exists; missing md_lot row.', 'product_name' => $row['product_name'], 'uom' => $row['uom'], 'source' => 'md_barcode', 'serial_number' => $row['serial_number'], 'barcode' => $row['barcode'], ]; } $status_rows = $pdo2->prepare( "SELECT product_sku, lot_number, SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS active_count, SUM(CASE WHEN status <> 1 THEN 1 ELSE 0 END) AS disabled_count FROM md_barcode WHERE company_id = :company_id AND barcode_type = 'sku' AND product_sku IS NOT NULL AND product_sku <> '' AND lot_number IS NOT NULL AND lot_number <> '' GROUP BY product_sku, lot_number" ); $status_rows->execute([':company_id' => $company_id]); $label_status = []; foreach ($status_rows->fetchAll(PDO::FETCH_ASSOC) as $row) { $label_status[$row['product_sku'] . '|' . $row['lot_number']] = [ 'active_count' => (int)$row['active_count'], 'disabled_count' => (int)$row['disabled_count'], ]; } foreach ($rows as &$row) { $status = $label_status[$row['product_sku'] . '|' . $row['lot_number']] ?? null; $row['barcode_active_count'] = $status['active_count'] ?? 0; $row['barcode_disabled_count'] = $status['disabled_count'] ?? 0; } unset($row); usort($rows, fn($a, $b) => [$a['product_sku'], $a['lot_number']] <=> [$b['product_sku'], $b['lot_number']]); $answer['success'] = 1; $answer['output'] = $rows; exit(json_encode($answer)); ?>