fix: vendor info + rerun button on supplier invoices v2.2.21
- Fix get_files_by_status query: LATERAL join to get latest extraction
per file, returning vendor_name, vendor_match_confidence, total_amount
- Fix renderUnhandledFiles: use best_vendor_name, convert confidence
0-1 to %, use total_amount field
- Add rerun button for all files (not just failed) via rerunSingleFile()
- rerunSingleFile() calls /reprocess/{file_id} and reloads unhandled tab
- Fix retry_extraction endpoint to actually run extraction immediately
This commit is contained in:
parent
ea4905ef8a
commit
744b405142
@ -339,10 +339,22 @@ async def get_files_by_status(status: Optional[str] = None, limit: int = 100):
|
||||
SELECT f.file_id, f.filename, f.file_path, f.file_size, f.mime_type,
|
||||
f.status, f.uploaded_at, f.processed_at, f.detected_cvr,
|
||||
f.detected_vendor_id, v.name as detected_vendor_name,
|
||||
e.total_amount as detected_amount
|
||||
ext.vendor_name,
|
||||
ext.vendor_cvr,
|
||||
ext.vendor_matched_id,
|
||||
COALESCE(v_ext.name, ext.vendor_name, v.name) as best_vendor_name,
|
||||
ext.total_amount,
|
||||
ext.confidence as vendor_match_confidence
|
||||
FROM incoming_files f
|
||||
LEFT JOIN vendors v ON f.detected_vendor_id = v.id
|
||||
LEFT JOIN extractions e ON f.file_id = e.file_id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT vendor_name, vendor_cvr, vendor_matched_id, total_amount, confidence
|
||||
FROM extractions
|
||||
WHERE file_id = f.file_id
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
) ext ON true
|
||||
LEFT JOIN vendors v_ext ON v_ext.id = ext.vendor_matched_id
|
||||
WHERE f.status IN ({placeholders})
|
||||
ORDER BY f.uploaded_at DESC
|
||||
LIMIT %s
|
||||
@ -353,10 +365,22 @@ async def get_files_by_status(status: Optional[str] = None, limit: int = 100):
|
||||
SELECT f.file_id, f.filename, f.file_path, f.file_size, f.mime_type,
|
||||
f.status, f.uploaded_at, f.processed_at, f.detected_cvr,
|
||||
f.detected_vendor_id, v.name as detected_vendor_name,
|
||||
e.total_amount as detected_amount
|
||||
ext.vendor_name,
|
||||
ext.vendor_cvr,
|
||||
ext.vendor_matched_id,
|
||||
COALESCE(v_ext.name, ext.vendor_name, v.name) as best_vendor_name,
|
||||
ext.total_amount,
|
||||
ext.confidence as vendor_match_confidence
|
||||
FROM incoming_files f
|
||||
LEFT JOIN vendors v ON f.detected_vendor_id = v.id
|
||||
LEFT JOIN extractions e ON f.file_id = e.file_id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT vendor_name, vendor_cvr, vendor_matched_id, total_amount, confidence
|
||||
FROM extractions
|
||||
WHERE file_id = f.file_id
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1
|
||||
) ext ON true
|
||||
LEFT JOIN vendors v_ext ON v_ext.id = ext.vendor_matched_id
|
||||
ORDER BY f.uploaded_at DESC
|
||||
LIMIT %s
|
||||
"""
|
||||
@ -3255,16 +3279,9 @@ async def retry_extraction(file_id: int):
|
||||
|
||||
logger.info(f"🔄 Retrying extraction for file {file_id}: {file_data['filename']}")
|
||||
|
||||
# Trigger re-analysis by calling the existing upload processing logic
|
||||
# For now, just mark as pending - the user can then run batch-analyze
|
||||
|
||||
return {
|
||||
"file_id": file_id,
|
||||
"filename": file_data['filename'],
|
||||
"message": "File marked for re-analysis. Run batch-analyze to process.",
|
||||
"previous_status": file_data['status'],
|
||||
"new_status": "pending"
|
||||
}
|
||||
# Run full extraction cascade immediately
|
||||
result = await reprocess_uploaded_file(file_id)
|
||||
return result
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
|
||||
@ -1812,9 +1812,10 @@ function renderUnhandledFiles(files) {
|
||||
|
||||
for (const file of files) {
|
||||
const statusBadge = getFileStatusBadge(file.status);
|
||||
const vendorName = file.detected_vendor_name || '-';
|
||||
const confidence = file.vendor_match_confidence ? `${file.vendor_match_confidence}%` : '-';
|
||||
const amount = file.detected_amount ? formatCurrency(file.detected_amount) : '-';
|
||||
const vendorName = file.best_vendor_name || file.vendor_name || file.detected_vendor_name || '-';
|
||||
const confRaw = file.vendor_match_confidence;
|
||||
const confidence = confRaw !== null && confRaw !== undefined ? `${Math.round(confRaw * 100)}%` : '-';
|
||||
const amount = file.total_amount ? formatCurrency(file.total_amount) : '-';
|
||||
const uploadDate = file.uploaded_at ? new Date(file.uploaded_at).toLocaleDateString('da-DK') : '-';
|
||||
|
||||
html += `
|
||||
@ -1842,14 +1843,9 @@ function renderUnhandledFiles(files) {
|
||||
<td>${statusBadge}</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-sm">
|
||||
${file.status === 'extraction_failed' ?
|
||||
`<button class="btn btn-outline-warning" onclick="retryExtraction(${file.file_id})" title="Prøv igen">
|
||||
<i class="bi bi-arrow-clockwise"></i>
|
||||
</button>` :
|
||||
`<button class="btn btn-outline-primary" onclick="analyzeFile(${file.file_id})" title="Analyser">
|
||||
<i class="bi bi-search"></i>
|
||||
</button>`
|
||||
}
|
||||
<button class="btn btn-outline-warning" onclick="rerunSingleFile(${file.file_id})" title="Kør analyse igen">
|
||||
<i class="bi bi-arrow-repeat"></i>
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary" onclick="viewFilePDF(${file.file_id})" title="Vis PDF">
|
||||
<i class="bi bi-file-pdf"></i>
|
||||
</button>
|
||||
@ -1965,6 +1961,36 @@ async function retryExtraction(fileId) {
|
||||
}
|
||||
}
|
||||
|
||||
// Rerun full extraction for a file in the unhandled tab
|
||||
async function rerunSingleFile(fileId) {
|
||||
try {
|
||||
showLoadingOverlay('Kører analyse...');
|
||||
|
||||
const response = await fetch(`/api/v1/supplier-invoices/reprocess/${fileId}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const err = await response.json().catch(() => ({}));
|
||||
throw new Error(err.detail || 'Analyse fejlede');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
hideLoadingOverlay();
|
||||
|
||||
const confPct = result.confidence ? Math.round(result.confidence * 100) + '%' : '?%';
|
||||
const vendorInfo = result.vendor_id ? `Leverandør matchet (ID ${result.vendor_id})` : 'Ingen leverandør matchet';
|
||||
alert(`✅ Analyse færdig\n${vendorInfo}\nConfidence: ${confPct}`);
|
||||
|
||||
loadUnhandledFiles();
|
||||
|
||||
} catch (error) {
|
||||
hideLoadingOverlay();
|
||||
console.error('Rerun error:', error);
|
||||
alert('❌ Fejl ved analyse: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// NEW: Analyze single file
|
||||
async function analyzeFile(fileId) {
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user