prepare(" UPDATE cad_area_jobs SET status = 'processing', message = 'Elaborazione in corso...', updated_at = NOW() WHERE id = ? "); $stmt->execute([$id]); } function updateJobError(PDO $pdo, int $id, string $message, ?array $pythonResponse = null): void { $stmt = $pdo->prepare(" UPDATE cad_area_jobs SET status = 'error', message = ?, python_response = ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([ $message, $pythonResponse ? json_encode($pythonResponse) : null, $id ]); } function updateJobCompleted(PDO $pdo, int $id, array $response): void { $stmt = $pdo->prepare(" UPDATE cad_area_jobs SET status = 'completed', message = ?, area_mm2 = ?, area_cm2 = ?, area_m2 = ?, width_mm = ?, height_mm = ?, scale_detected = ?, scale_used = ?, confidence = ?, python_response = ?, updated_at = NOW() WHERE id = ? "); $stmt->execute([ $response['message'] ?? 'Area calcolata correttamente.', $response['area_mm2'] ?? null, $response['area_cm2'] ?? null, $response['area_m2'] ?? null, $response['width_mm'] ?? null, $response['height_mm'] ?? null, $response['scale_detected'] ?? null, $response['scale_used'] ?? null, $response['confidence'] ?? null, json_encode($response), $id ]); } function normalizeCalculationMode(?string $mode): string { $allowed = [ 'auto_roi', 'stitch_contour', 'filled_union', 'closed_path' ]; if (!$mode || !in_array($mode, $allowed, true)) { return 'auto_roi'; } return $mode; } function hasValidRoi(array $job): bool { return ( array_key_exists('roi_x', $job) && array_key_exists('roi_y', $job) && array_key_exists('roi_width', $job) && array_key_exists('roi_height', $job) && $job['roi_x'] !== null && $job['roi_y'] !== null && $job['roi_width'] !== null && $job['roi_height'] !== null && (float)$job['roi_width'] > 0 && (float)$job['roi_height'] > 0 ); } function callPythonAreaService(string $url, array $job): array { $filePath = $job['file_path'] ?? ''; $originalFilename = $job['original_filename'] ?? basename($filePath); if (!$filePath || !file_exists($filePath)) { return [ 'success' => false, 'message' => 'File PDF non trovato sul server: ' . $filePath ]; } $mode = normalizeCalculationMode($job['calculation_mode'] ?? 'auto_roi'); $scaleRatio = $job['scale_used'] ?? null; if ($scaleRatio === null || $scaleRatio === '' || (float)$scaleRatio <= 0) { $scaleRatio = '1'; } $curlFile = new CURLFile( $filePath, 'application/pdf', $originalFilename ); $postFields = [ 'file' => $curlFile, 'mode' => $mode, 'scale_ratio' => (string)$scaleRatio, 'roi_x' => (string)$job['roi_x'], 'roi_y' => (string)$job['roi_y'], 'roi_width' => (string)$job['roi_width'], 'roi_height' => (string)$job['roi_height'], 'roi_page' => (string)($job['roi_page'] ?? 1) ]; $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postFields, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 180, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_HTTPHEADER => [ 'Accept: application/json' ] ]); $rawResponse = curl_exec($ch); $curlError = curl_error($ch); $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($rawResponse === false) { return [ 'success' => false, 'message' => 'Errore cURL verso Python: ' . $curlError ]; } $decoded = json_decode($rawResponse, true); if (!is_array($decoded)) { return [ 'success' => false, 'message' => 'Risposta Python non JSON valida.', 'http_code' => $httpCode, 'raw_response' => $rawResponse ]; } if ($httpCode < 200 || $httpCode >= 300) { return [ 'success' => false, 'message' => $decoded['message'] ?? ('Servizio Python HTTP ' . $httpCode), 'http_code' => $httpCode, 'python_response' => $decoded, 'raw_response' => $rawResponse ]; } return $decoded; } try { $db = DBHandlerSelect::getInstance(); $pdo = $db->getConnection(); $iduser = $iduserlogin ?? null; $input = json_decode(file_get_contents('php://input'), true); if (!is_array($input)) { jsonResponse([ 'success' => false, 'message' => 'Payload JSON non valido.' ]); } $ids = $input['ids'] ?? []; if (!is_array($ids) || count($ids) === 0) { jsonResponse([ 'success' => false, 'message' => 'Nessun ID ricevuto.' ]); } $ids = array_values(array_unique(array_map('intval', $ids))); $ids = array_filter($ids, fn($id) => $id > 0); if (count($ids) === 0) { jsonResponse([ 'success' => false, 'message' => 'Nessun ID valido ricevuto.' ]); } $pythonServiceUrl = 'http://127.0.0.1:5055/calculate'; $results = []; foreach ($ids as $id) { if ($iduser === null || $iduser === '') { $stmt = $pdo->prepare(" SELECT * FROM cad_area_jobs WHERE id = ? LIMIT 1 "); $stmt->execute([$id]); } else { $stmt = $pdo->prepare(" SELECT * FROM cad_area_jobs WHERE id = ? AND iduser = ? LIMIT 1 "); $stmt->execute([$id, $iduser]); } $job = $stmt->fetch(PDO::FETCH_ASSOC); if (!$job) { $results[] = [ 'id' => $id, 'success' => false, 'message' => 'Record non trovato.' ]; continue; } if (!hasValidRoi($job)) { $message = 'Prima devi definire la sezione da misurare tramite il pulsante Sezione.'; updateJobError($pdo, $id, $message, [ 'success' => false, 'message' => $message, 'job_roi_debug' => [ 'roi_x' => $job['roi_x'] ?? null, 'roi_y' => $job['roi_y'] ?? null, 'roi_width' => $job['roi_width'] ?? null, 'roi_height' => $job['roi_height'] ?? null, 'roi_page' => $job['roi_page'] ?? null, 'calculation_mode' => $job['calculation_mode'] ?? null ] ]); $results[] = [ 'id' => $id, 'success' => false, 'message' => $message ]; continue; } updateJobProcessing($pdo, $id); $pythonResponse = callPythonAreaService($pythonServiceUrl, $job); if (!($pythonResponse['success'] ?? false)) { $message = $pythonResponse['message'] ?? 'Errore durante il calcolo Python.'; updateJobError($pdo, $id, $message, $pythonResponse); $results[] = [ 'id' => $id, 'success' => false, 'message' => $message, 'python_response' => $pythonResponse ]; continue; } updateJobCompleted($pdo, $id, $pythonResponse); $results[] = [ 'id' => $id, 'success' => true, 'message' => $pythonResponse['message'] ?? 'Area calcolata.', 'area_mm2' => $pythonResponse['area_mm2'] ?? null, 'area_cm2' => $pythonResponse['area_cm2'] ?? null ]; } jsonResponse([ 'success' => true, 'results' => $results ]); } catch (Throwable $e) { error_log('CAD area process error: ' . $e->getMessage()); jsonResponse([ 'success' => false, 'message' => $e->getMessage() ]); }