first commit
This commit is contained in:
commit
efa5080897
127 changed files with 18610 additions and 0 deletions
65
backend/app/voice/call_resolver.py
Normal file
65
backend/app/voice/call_resolver.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from ..models import PhoneNumber, VoiceCall
|
||||
from .validators import format_bonvoice_destination, normalize_phone_digits
|
||||
|
||||
|
||||
def find_inbound_by_did(db: Session, did_value: str) -> PhoneNumber | None:
|
||||
did = normalize_phone_digits(did_value)
|
||||
if len(did) != 10:
|
||||
return None
|
||||
return db.scalar(
|
||||
select(PhoneNumber).where(
|
||||
PhoneNumber.phone_number == did,
|
||||
PhoneNumber.status == "assigned",
|
||||
PhoneNumber.user_id.is_not(None),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _phone_variants(value: str) -> set[str]:
|
||||
raw = value.strip()
|
||||
normalized = normalize_phone_digits(raw)
|
||||
variants = {raw, normalized, format_bonvoice_destination(raw)}
|
||||
if len(normalized) == 10:
|
||||
variants.add(f"91{normalized}")
|
||||
return {item for item in variants if item}
|
||||
|
||||
|
||||
def find_pending_outbound_call(db: Session, *, from_value: str, to_value: str) -> VoiceCall | None:
|
||||
"""
|
||||
Match a pending outbound call to Bonvoice media `start`.
|
||||
|
||||
Outbound Bonvoice streams report:
|
||||
- `to` = leg-A caller ID (purchased DID, e.g. 7946350706)
|
||||
- `from` = destination/callee (e.g. 919149154337)
|
||||
"""
|
||||
did_candidates = _phone_variants(to_value)
|
||||
owned_dids = {
|
||||
normalize_phone_digits(value)
|
||||
for value in did_candidates
|
||||
if len(normalize_phone_digits(value)) == 10
|
||||
}
|
||||
if not owned_dids:
|
||||
return None
|
||||
|
||||
candidates = db.scalars(
|
||||
select(VoiceCall)
|
||||
.where(
|
||||
VoiceCall.direction == "outbound",
|
||||
VoiceCall.status == "initiated",
|
||||
VoiceCall.from_did.in_(owned_dids),
|
||||
)
|
||||
.order_by(VoiceCall.created_at.desc())
|
||||
.limit(5)
|
||||
).all()
|
||||
if not candidates:
|
||||
return None
|
||||
|
||||
callee_variants = _phone_variants(from_value)
|
||||
for call in candidates:
|
||||
if _phone_variants(call.to_number) & callee_variants:
|
||||
return call
|
||||
|
||||
return None
|
||||
Loading…
Add table
Add a link
Reference in a new issue