- Introduced tests for drift operations UI and backend to ensure proper handling of ignore rules and UI elements. - Added tests for email identity API to validate email linking and identity retrieval without updates. - Implemented tests for email purchase link service to verify correct handling of purchase mail links and conflict scenarios. - Created tests for email reply automation to ensure proper routing and processing of replies based on classification. - Developed tests for email sender creation to validate suggestions and handling of existing contacts and companies. - Added tests for email sender identity to ensure correct matching of contacts and domains. - Implemented tests for work desk functionalities to validate task management, meeting registrations, and timer functionalities.
53 lines
3.4 KiB
Python
53 lines
3.4 KiB
Python
"""Explicit purchase-mail linking, without changing purchase fulfilment or running workflows."""
|
|
import json
|
|
from fastapi import HTTPException
|
|
from app.core.database import atomic_transaction, execute_query_single, execute_update
|
|
|
|
|
|
def link_purchase_mail(email_id, purchase_id, kind, tracking_number=None, user_id=None):
|
|
if kind not in {'order_confirmation', 'freight_note'}:
|
|
raise HTTPException(400, 'Ukendt indkøbsmailtype')
|
|
tracking = str(tracking_number or '').strip() or None
|
|
if tracking and (kind != 'freight_note' or len(tracking) > 100):
|
|
raise HTTPException(400, 'Trackingnummer må højst være 100 tegn og bruges kun ved levering')
|
|
with atomic_transaction():
|
|
mail = execute_query_single(
|
|
'SELECT id, linked_case_id FROM email_messages WHERE id = %s AND deleted_at IS NULL FOR UPDATE',
|
|
(email_id,))
|
|
if not mail:
|
|
raise HTTPException(404, 'Mailen blev ikke fundet')
|
|
purchase = execute_query_single("""
|
|
SELECT p.id, p.sag_id, p.description, s.titel AS case_title
|
|
FROM sag_salgsvarer p JOIN sag_sager s ON s.id = p.sag_id
|
|
WHERE p.id = %s AND p.type = 'purchase' AND p.status <> 'cancelled'
|
|
AND s.deleted_at IS NULL FOR UPDATE OF p, s
|
|
""", (purchase_id,))
|
|
if not purchase:
|
|
raise HTTPException(404, 'Bestillingen findes ikke eller er annulleret')
|
|
if mail.get('linked_case_id') and mail['linked_case_id'] != purchase['sag_id']:
|
|
raise HTTPException(409, 'Mailen er allerede knyttet til en anden sag. Ret sagstilknytningen først.')
|
|
metadata = {'purchase_id': purchase_id, 'sag_id': purchase['sag_id'], 'kind': kind,
|
|
'tracking_number': tracking}
|
|
previous = execute_query_single("""SELECT metadata FROM email_activity_log
|
|
WHERE email_id = %s AND event_type = 'purchase_mail_link'
|
|
ORDER BY id DESC LIMIT 1""", (email_id,))
|
|
if previous:
|
|
if previous['metadata'] != metadata:
|
|
raise HTTPException(409, 'Mailen er allerede behandlet som indkøbsmail med andre oplysninger.')
|
|
return {'success': True, 'sag_id': purchase['sag_id'], 'idempotent': True,
|
|
'message': 'Mailen er allerede knyttet til bestillingen'}
|
|
execute_update('''INSERT INTO sag_emails (sag_id, email_id) VALUES (%s, %s)
|
|
ON CONFLICT (sag_id, email_id) DO NOTHING''', (purchase['sag_id'], email_id))
|
|
execute_update("""UPDATE email_messages SET linked_case_id = %s,
|
|
classification = %s, confidence_score = 1.0,
|
|
extracted_tracking_number = COALESCE(%s, extracted_tracking_number),
|
|
status = 'processed', folder = 'Processed', processed_at = CURRENT_TIMESTAMP,
|
|
updated_at = CURRENT_TIMESTAMP WHERE id = %s""",
|
|
(purchase['sag_id'], kind, tracking, email_id))
|
|
execute_update("""INSERT INTO email_activity_log
|
|
(email_id, event_type, event_category, description, metadata, user_id, created_by)
|
|
VALUES (%s, 'purchase_mail_link', 'user', %s, %s::jsonb, %s, 'mailindbakke')""",
|
|
(email_id, ('Ordrebekræftelse' if kind == 'order_confirmation' else 'Levering / tracking')
|
|
+ ': ' + purchase['description'], json.dumps(metadata), user_id))
|
|
return {'success': True, 'sag_id': purchase['sag_id'], 'message': 'Mailen er knyttet til bestillingen og sagen'}
|