fix: vendor DB lookup after regex/AI extraction v2.2.20
extract_vendor_suggestion now matches found CVR/domain/name against vendors table for ALL code paths (not just fast path): - CVR match → score 100 - Domain match → score 80 - Email-domain match → score 75 - Name substring → score 60 Frontend auto-links when match_score >= 80 (was only pdf_extraction source). Shows score reason: CVR-match/domæne-match/navne-match in success toast. Also: saves newly found CVR to extracted_vendor_cvr so fast path works on subsequent calls for old emails too.
This commit is contained in:
parent
09de3c7373
commit
ea4905ef8a
@ -652,6 +652,7 @@ async def extract_vendor_suggestion(email_id: int):
|
|||||||
"domain": None,
|
"domain": None,
|
||||||
"source": "pdf_extraction",
|
"source": "pdf_extraction",
|
||||||
"vendor_id": vendor_row.get('id') if vendor_row else None,
|
"vendor_id": vendor_row.get('id') if vendor_row else None,
|
||||||
|
"match_score": 100 if vendor_row else 0,
|
||||||
"confidence": 0.95,
|
"confidence": 0.95,
|
||||||
}
|
}
|
||||||
logger.info(
|
logger.info(
|
||||||
@ -890,6 +891,65 @@ JSON:"""
|
|||||||
if em_domain in PLATFORM_DOMAINS:
|
if em_domain in PLATFORM_DOMAINS:
|
||||||
suggestion['email'] = None
|
suggestion['email'] = None
|
||||||
|
|
||||||
|
# ── Vendor DB-opslag (gælder alle stier undtagen fast path ovenfor) ───
|
||||||
|
# Prøv at matche det udtrukkede CVR/navn/domæne mod vendors-tabellen.
|
||||||
|
vendor_id = None
|
||||||
|
match_score = 0
|
||||||
|
|
||||||
|
all_vendors = execute_query(
|
||||||
|
"SELECT id, name, cvr_number, email, domain FROM vendors WHERE is_active = true",
|
||||||
|
None
|
||||||
|
) or []
|
||||||
|
|
||||||
|
cvr_found = suggestion.get('cvr_number')
|
||||||
|
name_found = (suggestion.get('name') or '').lower().strip()
|
||||||
|
domain_found = (suggestion.get('domain') or '').lower().strip()
|
||||||
|
|
||||||
|
for v in all_vendors:
|
||||||
|
score = 0
|
||||||
|
# CVR-match er stærkest (100 point)
|
||||||
|
if cvr_found and v.get('cvr_number') and str(cvr_found).strip() == str(v['cvr_number']).strip():
|
||||||
|
score = 100
|
||||||
|
# Domæne-match (80 point)
|
||||||
|
elif domain_found and v.get('domain') and domain_found == v['domain'].lower().strip():
|
||||||
|
score = 80
|
||||||
|
# Email-domæne-match (75 point)
|
||||||
|
elif domain_found and v.get('email') and '@' in (v['email'] or ''):
|
||||||
|
vdom = v['email'].split('@')[1].lower()
|
||||||
|
if domain_found == vdom:
|
||||||
|
score = 75
|
||||||
|
# Navne-match: vendor-navn er substring af fundne navn eller omvendt (60 point)
|
||||||
|
elif name_found and v.get('name'):
|
||||||
|
vname = v['name'].lower().strip()
|
||||||
|
if vname and (vname in name_found or name_found in vname):
|
||||||
|
score = 60
|
||||||
|
|
||||||
|
if score > match_score:
|
||||||
|
match_score = score
|
||||||
|
vendor_id = v['id']
|
||||||
|
suggestion['name'] = suggestion.get('name') or v['name']
|
||||||
|
if not cvr_found and v.get('cvr_number'):
|
||||||
|
suggestion['cvr_number'] = v['cvr_number']
|
||||||
|
|
||||||
|
if vendor_id:
|
||||||
|
suggestion['vendor_id'] = vendor_id
|
||||||
|
suggestion['match_score'] = match_score
|
||||||
|
logger.info(f"✅ Vendor match for email {email_id}: vendor_id={vendor_id}, score={match_score}")
|
||||||
|
|
||||||
|
# Gem CVR på emailen så fast path virker næste gang
|
||||||
|
if cvr_found and not email.get('extracted_vendor_cvr'):
|
||||||
|
try:
|
||||||
|
execute_update(
|
||||||
|
"UPDATE email_messages SET extracted_vendor_cvr = %s, extracted_vendor_name = %s WHERE id = %s",
|
||||||
|
(cvr_found, suggestion.get('name'), email_id)
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
suggestion['vendor_id'] = None
|
||||||
|
suggestion['match_score'] = 0
|
||||||
|
logger.info(f"⚠️ Ingen vendor match for email {email_id}: CVR={cvr_found}, navn={name_found}")
|
||||||
|
|
||||||
return suggestion
|
return suggestion
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
|
|||||||
@ -2349,7 +2349,7 @@ async function quickCreateVendor(emailId, senderName, senderEmail) {
|
|||||||
const s = await resp.json();
|
const s = await resp.json();
|
||||||
|
|
||||||
// ── Hurtig genvej: leverandøren kendes allerede (vendor_id fra PDF) ──
|
// ── Hurtig genvej: leverandøren kendes allerede (vendor_id fra PDF) ──
|
||||||
if (s.vendor_id && s.source === 'pdf_extraction') {
|
if (s.vendor_id && (s.source === 'pdf_extraction' || s.match_score >= 80)) {
|
||||||
bootstrap.Modal.getInstance(document.getElementById('quickCreateVendorModal')).hide();
|
bootstrap.Modal.getInstance(document.getElementById('quickCreateVendorModal')).hide();
|
||||||
// Auto-link direkte
|
// Auto-link direkte
|
||||||
const linkResp = await fetch(`/api/v1/emails/${emailId}/link`, {
|
const linkResp = await fetch(`/api/v1/emails/${emailId}/link`, {
|
||||||
@ -2358,7 +2358,8 @@ async function quickCreateVendor(emailId, senderName, senderEmail) {
|
|||||||
body: JSON.stringify({ supplier_id: s.vendor_id })
|
body: JSON.stringify({ supplier_id: s.vendor_id })
|
||||||
});
|
});
|
||||||
if (linkResp.ok) {
|
if (linkResp.ok) {
|
||||||
showSuccess(`Leverandør "${s.name || s.cvr_number}" auto-linket fra faktura-PDF`);
|
const scoreLabel = s.match_score >= 100 ? 'CVR-match' : s.match_score >= 80 ? 'domæne-match' : 'navne-match';
|
||||||
|
showSuccess(`Leverandør "${s.name || s.cvr_number}" auto-linket (${scoreLabel})`);
|
||||||
loadEmailDetail(parseInt(emailId));
|
loadEmailDetail(parseInt(emailId));
|
||||||
} else {
|
} else {
|
||||||
showError('Auto-link fejlede — åbner formularen');
|
showError('Auto-link fejlede — åbner formularen');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user