Fix extraction for companies and religious entities

This commit is contained in:
Georges Haddad
2026-04-15 10:07:57 +03:00
parent 85b5b21106
commit 88f047a654
4 changed files with 506 additions and 98 deletions
+104 -9
View File
@@ -24,6 +24,28 @@
</div>
</div>
{% if doc.status in ['extracted', 'confirmed', 'error'] %}
<div class="info-banner rescan-banner">
<div>
<strong>إعادة المسح</strong>
<span class="rescan-copy">إذا خلط الذكاء الاصطناعي بين أحرف مثل س و ن، يمكنك إعادة القراءة بنفس المحرك أو بمحرك آخر.</span>
</div>
<div class="rescan-controls">
<label for="providerSelect" class="sr-only">محرك الاستخراج</label>
<select id="providerSelect" title="محرك الاستخراج">
{% for provider in providers %}
<option value="{{ provider.id }}" {{ 'selected' if provider.id == current_provider else '' }}>
{{ provider.name }}
</option>
{% endfor %}
</select>
<button type="button" class="btn btn-warning btn-sm" id="rescanBtn" onclick="retriggerExtraction({{ doc.id }})">
إعادة المسح
</button>
</div>
</div>
{% endif %}
{% if doc.status == 'error' %}
<div class="error-banner">
⚠ خطأ في الاستخراج: {{ doc.extraction_error }}
@@ -57,13 +79,25 @@
{% if doc.get('is_subsequent_page') %}
<div class="info-banner page-group-banner">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>
هذه صفحة تكميلية ({{ doc.get('page_info') or doc.get('page_number') or '' }}) من مستند متعدد الصفحات.
{% if doc.get('inherited_from_page1') %}
بيانات الشخص مستوردة تلقائياً من الصفحة الأولى.
{% else %}
يرجى التأكد من بيانات الشخص يدوياً — لم يتم العثور على صفحة أولى مؤكدة بعد.
{% endif %}
<div class="page-group-copy">
<div>
هذه صفحة تكميلية ({{ doc.get('page_info') or doc.get('page_number') or '' }}) من مستند متعدد الصفحات.
{% if doc.get('inherited_from_page1') %}
بيانات الشخص مستوردة تلقائياً من الصفحة الأولى.
{% else %}
يرجى التأكد من بيانات الشخص يدوياً — لم يتم العثور على صفحة أولى مؤكدة بعد.
{% endif %}
</div>
{% if doc.get('page1_doc_id') and ai_verification_available %}
<div class="page-group-actions">
<button type="button" class="btn btn-secondary btn-sm" id="verifyCorrelationBtn" onclick="verifyCorrelation({{ doc.id }})">
تحقق بالذكاء الاصطناعي
</button>
</div>
{% endif %}
</div>
</div>
<div id="correlationResult" class="hidden"></div>
{% endif %}
<!-- Person Info -->
@@ -418,9 +452,70 @@ async function confirmDocument() {
}
async function retriggerExtraction(docId) {
if (!confirm('إعادة استخراج البيانات بالذكاء الاصطناعي؟')) return;
await fetch(`/extract/${docId}`, { method: 'POST' });
location.reload();
const provider = document.getElementById('providerSelect')?.value || '';
const btn = document.getElementById('rescanBtn');
const providerLabel = document.getElementById('providerSelect')?.selectedOptions?.[0]?.text || 'المحرك الحالي';
if (!confirm(`إعادة استخراج البيانات باستخدام ${providerLabel}؟ سيتم استبدال النتائج الحالية.`)) return;
if (btn) {
btn.disabled = true;
btn.textContent = 'جارٍ إعادة المسح...';
}
try {
const params = new URLSearchParams();
if (provider) params.set('provider', provider);
const res = await fetch(`/extract/${docId}?${params.toString()}`, { method: 'POST' });
const data = await res.json();
if (!res.ok || !data.ok) {
throw new Error(data.error || data.detail || 'تعذر بدء إعادة المسح.');
}
window.location.href = `/review/${docId}?wait=1`;
} catch (e) {
alert('حدث خطأ أثناء إعادة المسح: ' + e.message);
if (btn) {
btn.disabled = false;
btn.textContent = 'إعادة المسح';
}
}
}
async function verifyCorrelation(docId) {
const btn = document.getElementById('verifyCorrelationBtn');
const resultEl = document.getElementById('correlationResult');
if (!btn || !resultEl) return;
btn.disabled = true;
btn.textContent = 'جارٍ التحقق...';
resultEl.className = 'info-banner correlation-result';
resultEl.innerHTML = 'جارٍ فحص الترابط بين الصفحة الحالية والصفحة الأولى...';
try {
const res = await fetch(`/review/${docId}/verify-correlation`, { method: 'POST' });
const data = await res.json();
if (!res.ok || !data.ok) {
throw new Error(data.error || 'تعذر التحقق من الترابط.');
}
const statusClass = data.same_document ? 'success-banner' : 'error-banner';
const reasons = (data.reasons_ar || []).map(item => `<li>${item}</li>`).join('');
const mismatches = (data.mismatch_flags || []).map(item => `<li>${item}</li>`).join('');
resultEl.className = `${statusClass} correlation-result`;
resultEl.innerHTML = `
<div class="correlation-heading">
<strong>${data.verdict_ar}</strong>
<span class="correlation-meta">الثقة: ${data.confidence} | المحرك: ${data.provider}</span>
</div>
${reasons ? `<ul class="correlation-list">${reasons}</ul>` : ''}
${mismatches ? `<ul class="correlation-list correlation-warnings">${mismatches}</ul>` : ''}
`;
} catch (e) {
resultEl.className = 'error-banner correlation-result';
resultEl.textContent = 'فشل التحقق: ' + e.message;
} finally {
btn.disabled = false;
btn.textContent = 'تحقق بالذكاء الاصطناعي';
}
}
async function deleteDoc(docId) {