mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-22 11:51:04 +02:00
* ViciDial Working * feat(telephony): add FreeSWITCH provider to upstream-PBX seam Generalize the upstream-PBX capture and control paths to dispatch by provider. FreeSWITCH bridges in with X-PBX-* headers and is driven over the Event Socket Library (uuid_kill / uuid_transfer) by the channel UUID, alongside the existing VICIdial ra_call_control path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * add vici specific configs * feat(telephony): env-based VICIdial config + address3 post-call routing Move VICIdial agent/non-agent API and FreeSWITCH ESL connection settings out of hardcoded POC values into environment variables so the same image works against a PBX on another server. Add VICIdial update_lead forwarding: X-VICI-UPDATE-LEAD_* extracted variables are mapped to lead columns and pushed via the non-agent API before a transfer, with reserved API-control params dropped. Add hardcoded address3 disposition routing (Y/N -> in-group transfer, else hang up) and a synchronous final variable extraction so the transfer path sees the freshest conversation state. Skip upstream_pbx capture on non-PJSIP channels to avoid Asterisk 500s. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: run formatter * feat: make vici configurable from UI * chore: clean up PR * fix: incorporate review comments * chore: incorporate review comments * chore: generate client * chore: incporporate review comments * chore: incorporate review comments --------- Co-authored-by: Dograh POC <payment@dograh.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
"""Workflow-configuration policies shared by workflow update surfaces."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from copy import deepcopy
|
|
from typing import Any
|
|
|
|
from api.db import db_client
|
|
from api.services.organization_preferences import external_pbx_integrations_enabled
|
|
|
|
|
|
class WorkflowConfigurationNotFoundError(LookupError):
|
|
"""Raised when configuration policy cannot resolve the target workflow."""
|
|
|
|
|
|
class ExternalPBXConfigurationDisabledError(PermissionError):
|
|
"""Raised when a disabled organization changes external-PBX mappings."""
|
|
|
|
|
|
async def apply_external_pbx_mapping_policy(
|
|
workflow_configurations: dict[str, Any] | None,
|
|
*,
|
|
workflow_id: int,
|
|
organization_id: int,
|
|
) -> dict[str, Any] | None:
|
|
"""Preserve hidden mappings and reject edits while external PBX is disabled.
|
|
|
|
Workflow configuration updates replace the stored configuration document. When
|
|
the External PBX UI is hidden, its field mappings are absent from the request,
|
|
so they must be copied from the active draft or published definition before the
|
|
update is persisted.
|
|
"""
|
|
if workflow_configurations is None or await external_pbx_integrations_enabled(
|
|
organization_id
|
|
):
|
|
return workflow_configurations
|
|
|
|
workflow = await db_client.get_workflow(
|
|
workflow_id, organization_id=organization_id
|
|
)
|
|
if workflow is None:
|
|
raise WorkflowConfigurationNotFoundError(
|
|
f"Workflow with id {workflow_id} not found"
|
|
)
|
|
|
|
draft = await db_client.get_draft_version(workflow_id)
|
|
stored_configurations = (
|
|
draft.workflow_configurations
|
|
if draft
|
|
else workflow.released_definition.workflow_configurations
|
|
)
|
|
stored_mappings = (stored_configurations or {}).get(
|
|
"external_pbx_field_mappings", []
|
|
)
|
|
incoming_mappings = workflow_configurations.get(
|
|
"external_pbx_field_mappings", stored_mappings
|
|
)
|
|
|
|
if incoming_mappings != stored_mappings:
|
|
raise ExternalPBXConfigurationDisabledError(
|
|
"External PBX integrations are disabled for this organization. "
|
|
"Enable them in Platform Settings before changing field mappings."
|
|
)
|
|
|
|
if not stored_mappings:
|
|
return workflow_configurations
|
|
|
|
prepared_configurations = dict(workflow_configurations)
|
|
prepared_configurations["external_pbx_field_mappings"] = deepcopy(stored_mappings)
|
|
return prepared_configurations
|