Implement document reconciliation v2
This commit is contained in:
@@ -624,26 +624,10 @@ def get_task_detail(task_id: str) -> Optional[Dict[str, Any]]:
|
||||
LEFT JOIN opportunities o ON o.id = t.opportunity_id
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT
|
||||
cd.customer_id,
|
||||
COALESCE(cdoc.name, NULLIF(cd.company, ''), NULLIF(cd.payload->>'customer_name', '')) AS customer_name,
|
||||
COALESCE(cdoc.email, NULLIF(cd.payload->>'customer_email', ''), NULLIF(cd.payload->>'email', '')) AS customer_email,
|
||||
COALESCE(cdoc.tax_id, NULLIF(cd.payload->>'customer_tax_id', ''), NULLIF(cd.payload->>'tax_id', ''), NULLIF(cd.payload->>'nif', '')) AS customer_tax_id,
|
||||
cdoc.street_name AS customer_street_name,
|
||||
cdoc.postal_zone AS customer_postal_zone,
|
||||
cdoc.city_name AS customer_city_name,
|
||||
cdoc.phone AS customer_phone
|
||||
FROM commercial_documents cd
|
||||
LEFT JOIN customers cdoc ON cdoc.id = cd.customer_id
|
||||
WHERE cd.opportunity_id = o.id
|
||||
AND COALESCE(cd.is_active, TRUE) = TRUE
|
||||
AND cd.document_kind IN ('invoice', 'quotation', 'proforma')
|
||||
ORDER BY
|
||||
CASE cd.document_kind WHEN 'invoice' THEN 1 WHEN 'quotation' THEN 2 WHEN 'proforma' THEN 3 ELSE 4 END,
|
||||
CASE COALESCE(cd.role, 'current') WHEN 'current' THEN 1 WHEN 'accepted' THEN 2 WHEN 'historical' THEN 3 WHEN 'history' THEN 3 ELSE 4 END,
|
||||
COALESCE(cd.is_primary, FALSE) DESC,
|
||||
COALESCE(cd.document_date, cd.created_at::date) DESC,
|
||||
cd.created_at DESC
|
||||
LIMIT 1
|
||||
NULL::uuid AS customer_id, NULL::text AS customer_name,
|
||||
NULL::text AS customer_email, NULL::text AS customer_tax_id,
|
||||
NULL::text AS customer_street_name, NULL::text AS customer_postal_zone,
|
||||
NULL::text AS customer_city_name, NULL::text AS customer_phone
|
||||
) dcu ON TRUE
|
||||
-- Legacy guard anchor: LEFT JOIN customers cu ON cu.id = o.local_customer_id
|
||||
-- v4928.1.5.64: choose schema-supported opportunity customer, then document customer fallback.
|
||||
@@ -654,7 +638,29 @@ def get_task_detail(task_id: str) -> Optional[Dict[str, Any]]:
|
||||
with engine.begin() as conn:
|
||||
row = conn.execute(sql, {"task_id": task_id}).mappings().first()
|
||||
|
||||
return dict(row) if row else None
|
||||
result = dict(row) if row else None
|
||||
if result and result.get("opportunity_id") and not result.get("linked_customer_id"):
|
||||
from app.document_reconciliation_service import resolve_document_links, select_valid_primary
|
||||
links = resolve_document_links(str(result["opportunity_id"]))
|
||||
document = next((select_valid_primary(links, kind)
|
||||
for kind in ("invoice", "quotation", "proforma")
|
||||
if select_valid_primary(links, kind)), None)
|
||||
if document and document.get("customer_id"):
|
||||
with engine.begin() as conn:
|
||||
customer = conn.execute(text("""SELECT id::text, name, email, tax_id, street_name,
|
||||
postal_zone, city_name, phone FROM customers WHERE id=CAST(:id AS UUID)"""),
|
||||
{"id": document["customer_id"]}).mappings().first()
|
||||
if customer:
|
||||
customer = dict(customer)
|
||||
result["linked_customer_id"] = customer["id"]
|
||||
result["opportunity_fiscal_customer_id"] = customer["id"]
|
||||
for source_key, target_key in (("name", "linked_customer_name"),
|
||||
("email", "linked_customer_email"), ("tax_id", "linked_customer_tax_id"),
|
||||
("street_name", "linked_customer_street_name"),
|
||||
("postal_zone", "linked_customer_postal_zone"),
|
||||
("city_name", "linked_customer_city_name"), ("phone", "linked_customer_phone")):
|
||||
result[target_key] = result.get(target_key) or customer.get(source_key)
|
||||
return result
|
||||
|
||||
|
||||
def list_customer_task_history(
|
||||
|
||||
Reference in New Issue
Block a user