diff --git a/RELEASE_NOTES_v2.3.7.md b/RELEASE_NOTES_v2.3.7.md new file mode 100644 index 0000000..02a7544 --- /dev/null +++ b/RELEASE_NOTES_v2.3.7.md @@ -0,0 +1,10 @@ +# Release Notes: v2.3.7 +**Date:** 16. maj 2026 + +## Changes +- fallback to mission_call_state when telefoni_opkald is empty +- legacy rows shown read-only in telefoni UI + +## Files changed +- app/modules/telefoni/backend/router.py +- app/modules/telefoni/templates/log.html diff --git a/app/modules/telefoni/backend/router.py b/app/modules/telefoni/backend/router.py index f151078..e602ffa 100644 --- a/app/modules/telefoni/backend/router.py +++ b/app/modules/telefoni/backend/router.py @@ -735,8 +735,69 @@ async def list_calls( """ params.extend([limit, offset]) - rows = execute_query(query, tuple(params)) - return rows or [] + rows = execute_query(query, tuple(params)) or [] + if rows: + return rows + + # Fallback: legacy mission call history (read-only rows) for environments + # where historical calls were stored before telefoni_opkald was populated. + if user_id is not None: + return [] + + legacy_where = [] + legacy_params = [] + if date_from: + legacy_where.append("m.started_at >= %s") + legacy_params.append(date_from) + if date_to: + legacy_where.append("m.started_at <= %s") + legacy_params.append(date_to) + + legacy_where_sql = ("WHERE " + " AND ".join(legacy_where)) if legacy_where else "" + + legacy_query = f""" + SELECT + -ROW_NUMBER() OVER (ORDER BY m.started_at DESC, m.call_id) AS id, + m.call_id AS callid, + NULL::INTEGER AS bruger_id, + CASE + WHEN LOWER(COALESCE(m.state, '')) IN ('outbound', 'udgaaende') THEN 'outbound' + ELSE 'inbound' + END AS direction, + m.caller_number AS ekstern_nummer, + m.caller_number AS display_number, + NULL::VARCHAR AS intern_extension, + NULL::INTEGER AS kontakt_id, + NULL::INTEGER AS sag_id, + m.started_at, + m.ended_at, + CASE + WHEN m.started_at IS NOT NULL AND m.ended_at IS NOT NULL + THEN GREATEST(EXTRACT(EPOCH FROM (m.ended_at - m.started_at))::int, 0) + ELSE NULL + END AS duration_sec, + m.updated_at AS created_at, + NULL::VARCHAR AS username, + NULL::VARCHAR AS full_name, + COALESCE(NULLIF(TRIM(m.contact_name), ''), NULL) AS contact_name, + COALESCE(NULLIF(TRIM(m.company_name), ''), NULL) AS contact_company, + NULL::VARCHAR AS sag_titel, + 'legacy_mission'::VARCHAR AS source + FROM mission_call_state m + {legacy_where_sql} + ORDER BY m.started_at DESC, m.call_id + LIMIT %s OFFSET %s + """ + legacy_params.extend([limit, offset]) + + try: + legacy_rows = execute_query(legacy_query, tuple(legacy_params)) or [] + except Exception: + legacy_rows = [] + + if without_case: + return [r for r in legacy_rows if not r.get("sag_id")] + return legacy_rows @router.patch("/telefoni/calls/{call_id}") diff --git a/app/modules/telefoni/templates/log.html b/app/modules/telefoni/templates/log.html index 7e077a2..c40ab5a 100644 --- a/app/modules/telefoni/templates/log.html +++ b/app/modules/telefoni/templates/log.html @@ -851,6 +851,8 @@ async function loadCalls() { } tbody.innerHTML = rows.map(r => { + const callId = Number(r.id); + const canMutateCall = Number.isInteger(callId) && callId > 0; const started = r.started_at ? new Date(r.started_at) : null; const dateTxt = started ? started.toLocaleString('da-DK') : '-'; const userTxt = escapeHtml(r.full_name || r.username || '-'); @@ -866,30 +868,38 @@ async function loadCalls() { const contactHtml = r.kontakt_id ? `