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:
Christian 2026-03-02 00:35:44 +01:00
parent 09de3c7373
commit ea4905ef8a
3 changed files with 64 additions and 3 deletions

View File

@ -1 +1 @@
2.2.19
2.2.20

View File

@ -652,6 +652,7 @@ async def extract_vendor_suggestion(email_id: int):
"domain": None,
"source": "pdf_extraction",
"vendor_id": vendor_row.get('id') if vendor_row else None,
"match_score": 100 if vendor_row else 0,
"confidence": 0.95,
}
logger.info(
@ -890,6 +891,65 @@ JSON:"""
if em_domain in PLATFORM_DOMAINS:
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
except HTTPException:

View File

@ -2349,7 +2349,7 @@ async function quickCreateVendor(emailId, senderName, senderEmail) {
const s = await resp.json();
// ── 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();
// Auto-link direkte
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 })
});
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));
} else {
showError('Auto-link fejlede — åbner formularen');