Implement document reconciliation v2
This commit is contained in:
@@ -321,16 +321,17 @@ def _historical_stage_rates(conn: Any) -> dict[str, dict[str, Any]]:
|
||||
|
||||
|
||||
def _realised_for_period(conn: Any, *, metric: str, period_start: date, period_end: date) -> dict[str, Any]:
|
||||
from app.document_reconciliation_service import prepare_effective_document_links
|
||||
prepare_effective_document_links(conn)
|
||||
if metric == "cash_received":
|
||||
rows = conn.execute(text("""
|
||||
WITH latest_doc AS (
|
||||
SELECT DISTINCT ON (opportunity_id) opportunity_id, COALESCE(total_amount, amount, 0) AS amount
|
||||
FROM commercial_documents
|
||||
WHERE opportunity_id IS NOT NULL AND COALESCE(is_active, TRUE) = TRUE
|
||||
ORDER BY opportunity_id,
|
||||
CASE WHEN document_kind = 'invoice' THEN 0 ELSE 1 END,
|
||||
COALESCE(document_date, created_at::date) DESC,
|
||||
created_at DESC
|
||||
SELECT DISTINCT ON (l.opportunity_id) l.opportunity_id, COALESCE(d.total_amount, d.amount, 0) AS amount
|
||||
FROM _effective_document_links l JOIN commercial_documents d ON d.id=l.document_id
|
||||
WHERE l.ended_at IS NULL AND l.relationship='PRIMARY'
|
||||
AND upper(COALESCE(d.status,'')) NOT IN ('CANCELLED','CANCELED')
|
||||
ORDER BY l.opportunity_id, CASE WHEN d.document_kind = 'invoice' THEN 0 ELSE 1 END,
|
||||
COALESCE(d.document_date, d.created_at::date) DESC, d.created_at DESC
|
||||
)
|
||||
SELECT ol.opportunity_id::text,
|
||||
COALESCE(CASE WHEN COALESCE(ol.payload->>'amount','') ~ '^[0-9]+([.,][0-9]+)?$' THEN replace(ol.payload->>'amount', ',', '.')::numeric END, ld.amount, o.value_amount, 0) AS amount,
|
||||
@@ -352,9 +353,10 @@ def _realised_for_period(conn: Any, *, metric: str, period_start: date, period_e
|
||||
COALESCE(o.customer_name, o.title, 'Venda ganha') AS reference
|
||||
FROM opportunities o
|
||||
LEFT JOIN LATERAL (
|
||||
SELECT COALESCE(total_amount, amount, 0) AS amount
|
||||
FROM commercial_documents d
|
||||
WHERE d.opportunity_id = o.id AND COALESCE(d.is_active, TRUE) = TRUE
|
||||
SELECT COALESCE(d.total_amount, d.amount, 0) AS amount
|
||||
FROM _effective_document_links l JOIN commercial_documents d ON d.id=l.document_id
|
||||
WHERE l.opportunity_id = o.id AND l.ended_at IS NULL AND l.relationship='PRIMARY'
|
||||
AND upper(COALESCE(d.status,'')) NOT IN ('CANCELLED','CANCELED')
|
||||
ORDER BY CASE WHEN d.document_kind = 'invoice' THEN 0 ELSE 1 END,
|
||||
COALESCE(d.document_date, d.created_at::date) DESC
|
||||
LIMIT 1
|
||||
@@ -364,14 +366,14 @@ def _realised_for_period(conn: Any, *, metric: str, period_start: date, period_e
|
||||
"""), {"period_start": period_start, "period_end": period_end}).mappings().all()
|
||||
else:
|
||||
rows = conn.execute(text("""
|
||||
SELECT d.opportunity_id::text,
|
||||
SELECT l.opportunity_id::text,
|
||||
COALESCE(d.total_amount, d.amount, 0) AS amount,
|
||||
COALESCE(d.document_date::timestamp, d.created_at) AS realised_at,
|
||||
COALESCE(d.document_number, d.external_id, 'Fatura') AS reference
|
||||
FROM commercial_documents d
|
||||
FROM _effective_document_links l JOIN commercial_documents d ON d.id=l.document_id
|
||||
WHERE lower(d.document_kind) = 'invoice'
|
||||
AND COALESCE(d.is_active, TRUE) = TRUE
|
||||
AND COALESCE(d.role, 'current') IN ('current','accepted')
|
||||
AND l.ended_at IS NULL AND l.relationship='PRIMARY'
|
||||
AND upper(COALESCE(d.status,'')) NOT IN ('CANCELLED','CANCELED')
|
||||
AND COALESCE(d.document_date, d.created_at::date) BETWEEN :period_start AND :period_end
|
||||
"""), {"period_start": period_start, "period_end": period_end}).mappings().all()
|
||||
items = [dict(r) for r in rows]
|
||||
@@ -384,6 +386,8 @@ def _realised_for_period(conn: Any, *, metric: str, period_start: date, period_e
|
||||
|
||||
|
||||
def _already_realised_ids(conn: Any, *, metric: str) -> set[str]:
|
||||
from app.document_reconciliation_service import prepare_effective_document_links
|
||||
prepare_effective_document_links(conn)
|
||||
if metric == "cash_received":
|
||||
sql = """
|
||||
SELECT DISTINCT opportunity_id::text
|
||||
@@ -398,12 +402,11 @@ def _already_realised_ids(conn: Any, *, metric: str) -> set[str]:
|
||||
"""
|
||||
else:
|
||||
sql = """
|
||||
SELECT DISTINCT opportunity_id::text
|
||||
FROM commercial_documents
|
||||
WHERE opportunity_id IS NOT NULL
|
||||
AND lower(document_kind) = 'invoice'
|
||||
AND COALESCE(is_active, TRUE) = TRUE
|
||||
AND COALESCE(role, 'current') IN ('current','accepted')
|
||||
SELECT DISTINCT l.opportunity_id::text
|
||||
FROM _effective_document_links l JOIN commercial_documents d ON d.id=l.document_id
|
||||
WHERE l.ended_at IS NULL AND l.relationship='PRIMARY'
|
||||
AND lower(d.document_kind) = 'invoice'
|
||||
AND upper(COALESCE(d.status,'')) NOT IN ('CANCELLED','CANCELED')
|
||||
"""
|
||||
return {str(r[0]) for r in conn.execute(text(sql)).all() if r[0]}
|
||||
|
||||
@@ -435,25 +438,21 @@ def get_revenue_forecast(*, limit: int = 1000, month: str | None = None, metric:
|
||||
target = get_sales_target(month=period_start, metric=metric)
|
||||
|
||||
with engine.begin() as conn:
|
||||
from app.document_reconciliation_service import prepare_effective_document_links
|
||||
prepare_effective_document_links(conn)
|
||||
historical = _historical_stage_rates(conn)
|
||||
realised = _realised_for_period(conn, metric=metric, period_start=period_start, period_end=period_end)
|
||||
already_realised_ids = _already_realised_ids(conn, metric=metric)
|
||||
rows = conn.execute(text("""
|
||||
WITH latest_doc AS (
|
||||
SELECT DISTINCT ON (opportunity_id)
|
||||
opportunity_id,
|
||||
total_amount,
|
||||
document_number,
|
||||
document_kind,
|
||||
document_date
|
||||
FROM commercial_documents
|
||||
WHERE COALESCE(is_active, TRUE) = TRUE
|
||||
AND COALESCE(role, 'current') IN ('current','accepted','historical','history')
|
||||
ORDER BY opportunity_id,
|
||||
CASE WHEN COALESCE(is_primary, FALSE) THEN 0 ELSE 1 END,
|
||||
CASE document_kind WHEN 'invoice' THEN 1 WHEN 'quotation' THEN 2 WHEN 'proforma' THEN 3 ELSE 4 END,
|
||||
COALESCE(document_date, created_at::date) DESC,
|
||||
created_at DESC
|
||||
SELECT DISTINCT ON (l.opportunity_id)
|
||||
l.opportunity_id, d.total_amount, d.document_number, d.document_kind, d.document_date
|
||||
FROM _effective_document_links l JOIN commercial_documents d ON d.id=l.document_id
|
||||
WHERE l.ended_at IS NULL AND l.relationship='PRIMARY'
|
||||
AND upper(COALESCE(d.status,'')) NOT IN ('CANCELLED','CANCELED')
|
||||
ORDER BY l.opportunity_id,
|
||||
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
|
||||
), item_totals AS (
|
||||
SELECT opportunity_id, SUM(COALESCE(total_price, 0)) AS total
|
||||
FROM opportunity_items
|
||||
|
||||
Reference in New Issue
Block a user