Implement document reconciliation v2
This commit is contained in:
@@ -110,6 +110,17 @@ def _missing_fields(customer: Dict[str, Any]) -> List[str]:
|
||||
|
||||
|
||||
def _select_candidate_doc(conn: Any, opportunity_id: str) -> Optional[Dict[str, Any]]:
|
||||
from app.document_reconciliation_service import resolve_document_links
|
||||
effective = [row for row in resolve_document_links(opportunity_id, conn=conn)
|
||||
if row.get("relationship") == "PRIMARY"
|
||||
and row.get("system") == "jasmin"
|
||||
and row.get("document_kind") in {"quotation", "invoice", "proforma"}]
|
||||
effective.sort(key=lambda row: (
|
||||
{"invoice": 3, "quotation": 2, "proforma": 1}.get(str(row.get("document_kind")), 0),
|
||||
str(row.get("document_date") or ""), str(row.get("created_at") or "")), reverse=True)
|
||||
if not effective:
|
||||
return None
|
||||
document_ids = [str(row["document_id"]) for row in effective[:5]]
|
||||
rows = conn.execute(text("""
|
||||
SELECT
|
||||
d.id::text,
|
||||
@@ -134,16 +145,14 @@ def _select_candidate_doc(conn: Any, opportunity_id: str) -> Optional[Dict[str,
|
||||
c.jasmin_customer_id AS doc_customer_jasmin_id
|
||||
FROM commercial_documents d
|
||||
LEFT JOIN customers c ON c.id = d.customer_id
|
||||
WHERE d.opportunity_id = CAST(:opportunity_id AS UUID)
|
||||
AND d.system = 'jasmin'
|
||||
AND d.document_kind IN ('quotation', 'invoice', 'proforma')
|
||||
WHERE d.id = ANY(CAST(:document_ids AS UUID[]))
|
||||
AND COALESCE(d.is_active, TRUE) = TRUE
|
||||
ORDER BY
|
||||
CASE d.document_kind WHEN 'invoice' THEN 1 WHEN 'quotation' THEN 2 WHEN 'proforma' THEN 3 ELSE 4 END,
|
||||
COALESCE(d.document_date, d.created_at::date) DESC,
|
||||
d.created_at DESC
|
||||
LIMIT 5
|
||||
"""), {"opportunity_id": opportunity_id}).mappings().all()
|
||||
"""), {"document_ids": document_ids}).mappings().all()
|
||||
best = None
|
||||
best_score = -1
|
||||
for row in rows:
|
||||
@@ -324,12 +333,15 @@ def apply_jasmin_fiscal_sync(opportunity_id: str, *, actor: str = "operator") ->
|
||||
WHERE id = CAST(:opportunity_id AS UUID)
|
||||
AND (local_customer_id IS NULL OR local_customer_id = CAST(:customer_id AS UUID))
|
||||
"""), {"customer_id": target_customer_id, "opportunity_id": opportunity_id})
|
||||
conn.execute(text("""
|
||||
UPDATE commercial_documents
|
||||
SET customer_id = COALESCE(customer_id, CAST(:customer_id AS UUID)), updated_at = now()
|
||||
WHERE opportunity_id = CAST(:opportunity_id AS UUID)
|
||||
AND system = 'jasmin'
|
||||
"""), {"customer_id": target_customer_id, "opportunity_id": opportunity_id})
|
||||
from app.document_reconciliation_service import resolve_document_links
|
||||
document_ids = [str(row["document_id"]) for row in resolve_document_links(opportunity_id, conn=conn)
|
||||
if row.get("relationship") in {"PRIMARY", "SECONDARY", "HISTORICAL"}
|
||||
and row.get("system") == "jasmin"]
|
||||
if document_ids:
|
||||
conn.execute(text("""UPDATE commercial_documents
|
||||
SET customer_id=COALESCE(customer_id,CAST(:customer_id AS UUID)), updated_at=now()
|
||||
WHERE id=ANY(CAST(:document_ids AS UUID[]))"""),
|
||||
{"customer_id": target_customer_id, "document_ids": document_ids})
|
||||
after_dict = dict(row or {})
|
||||
filled = [key for key in ("tax_id", "email", "phone", "street_name", "postal_zone", "city_name", "country") if not _clean(before_dict.get(key)) and _clean(after_dict.get(key))]
|
||||
conn.execute(text("""
|
||||
@@ -349,10 +361,11 @@ def audit_jasmin_fiscal_gaps(limit: int = 200) -> List[Dict[str, Any]]:
|
||||
ensure_commercial_schema()
|
||||
findings: List[Dict[str, Any]] = []
|
||||
with engine.begin() as conn:
|
||||
# Candidate eligibility is resolved per opportunity below; this query
|
||||
# deliberately contains no authoritative legacy/v2 relationship read.
|
||||
rows = conn.execute(text("""
|
||||
SELECT DISTINCT o.id::text, o.title, o.customer_name
|
||||
SELECT o.id::text, o.title, o.customer_name
|
||||
FROM opportunities o
|
||||
JOIN commercial_documents d ON d.opportunity_id = o.id AND d.system = 'jasmin'
|
||||
LEFT JOIN customers c ON c.id = o.local_customer_id
|
||||
WHERE COALESCE(o.status, 'open') <> 'closed'
|
||||
AND (
|
||||
|
||||
Reference in New Issue
Block a user