tenantId; $role = $request->user->role ?? 'viewer'; $assignedCompanyId = $request->user->assigned_company_id ?? null; if ($role === 'super_admin') { $invoices = $this->invoiceModel->findByTenant($tenantId); } else { // Filter by assigned company for admin, accountant, etc. $db = \App\Core\Database::getInstance(); $stmt = $db->prepare("SELECT * FROM invoices WHERE tenant_id = ? AND company_id = ? AND deleted_at IS NULL ORDER BY created_at DESC"); $stmt->execute([$tenantId, $assignedCompanyId]); $invoices = $stmt->fetchAll(); } Response::json([ 'success' => true, 'data' => $invoices ]); } public function upload(Request $request): void { $files = $request->getFiles(); if (empty($files['invoice'])) { Response::error('يرجى اختيار ملف الفاتورة', 'MISSING_FILE', 422); return; } $companyId = $request->input('company_id'); if (!$companyId) { Response::error('يرجى تحديد الشركة', 'MISSING_COMPANY', 422); return; } try { $tenantId = $request->tenantId; $filePath = $this->storage->store($files['invoice'], $tenantId, $companyId); $fileHash = $this->storage->getHash($filePath); // Create invoice record $invoiceId = \Ramsey\Uuid\Uuid::uuid4()->toString(); $this->invoiceModel->create([ 'id' => $invoiceId, 'tenant_id' => $tenantId, 'company_id' => $companyId, 'uploaded_by' => $request->user->user_id, 'status' => 'uploaded', // Match schema ENUM 'original_file_path' => $filePath, 'original_file_hash' => $fileHash, 'idempotency_key' => bin2hex(random_bytes(16)) ]); // Attempt AI Extraction try { $mimeType = mime_content_type($filePath); $extractedData = $this->aiExtraction->extractInvoiceData($filePath, $mimeType); // Update Invoice with extracted data $this->invoiceModel->update($invoiceId, [ 'status' => 'extracted', // Match schema ENUM 'ai_raw_response' => json_encode($extractedData, JSON_UNESCAPED_UNICODE) ]); Response::json([ 'success' => true, 'data' => [ 'invoice_id' => $invoiceId, 'extracted_data' => $extractedData ], 'message' => 'تم رفع الفاتورة واستخراج البيانات بنجاح بالذكاء الاصطناعي' ]); } catch (Throwable $aiError) { // Keep it uploaded, maybe manual retry later $this->invoiceModel->update($invoiceId, [ 'status' => 'validation_failed' // Match schema fallback ]); Response::json([ 'success' => true, 'data' => ['invoice_id' => $invoiceId], 'message' => 'تم الرفع ولكن فشل استخراج البيانات. ' . $aiError->getMessage() ]); } } catch (Throwable $e) { Response::error($e->getMessage(), 'UPLOAD_FAILED', 500); } } }