feat(outbound): add voice announcement on trunk congestion & clarify MoH options

This commit is contained in:
sorcier committed 2026-11-04 00:55:53 +01:00
1 parent a308f5d0ed
commit e98410202f
4 files changed
+47 -9

No files matched your search

+22 -6
View File
@@ -2561,14 +2561,30 @@ function openOutboundRouteModal(route = null) {
const recMode = route ? route.record_mode : 'dontcare';
form.querySelectorAll('input[name="record_mode"]').forEach(r => r.checked = (r.value === recMode));
// Destination sur congestion
// Destination sur congestion / Trunks indisponibles
const congSel = document.getElementById('ob-congestion-dest-select');
if (congSel) {
congSel.innerHTML = `
<option value="terminate-congestion" ${(!route || route.congestion_dest === 'terminate-congestion') ? 'selected' : ''}>Congestion (Tonalité réseau saturé)</option>
<option value="terminate-busy" ${route?.congestion_dest === 'terminate-busy' ? 'selected' : ''}>Busy (Occupation définitive)</option>
<option value="terminate-hangup" ${route?.congestion_dest === 'terminate-hangup' ? 'selected' : ''}>Hangup (Raccrocher)</option>
const curCong = route ? route.congestion_dest : 'all-circuits-busy';
let congOpts = `
<optgroup label="📢 Messages Vocaux (Recommandé)">
<option value="all-circuits-busy" ${(curCong === 'all-circuits-busy' || (!route && curCong !== 'terminate-congestion')) ? 'selected' : ''}>📢 Message vocal standard (« Toutes les lignes sont occupées »)</option>
`;
const annSounds = (appState.sounds || []).filter(s => s.usage_type !== 'moh');
if (annSounds.length > 0) {
annSounds.forEach(s => {
const val = `sound-${s.id}`;
congOpts += `<option value="${val}" ${curCong === val ? 'selected' : ''}>🎙️ Annonce : ${escapeHtml(s.name)}</option>`;
});
}
congOpts += `
</optgroup>
<optgroup label="📴 Tonalités & Raccrochage">
<option value="terminate-congestion" ${curCong === 'terminate-congestion' ? 'selected' : ''}>Tonalité de Congestion (Bip rapide réseau saturé)</option>
<option value="terminate-busy" ${curCong === 'terminate-busy' ? 'selected' : ''}>Tonalité d'Occupation (Bip occupé)</option>
<option value="terminate-hangup" ${curCong === 'terminate-hangup' ? 'selected' : ''}>Raccrocher immédiatement</option>
</optgroup>
`;
congSel.innerHTML = congOpts;
}
// Musique d'attente (MOH)
@@ -2576,7 +2592,7 @@ function openOutboundRouteModal(route = null) {
if (mohSel) {
const curMoh = route ? (route.moh_class || 'default') : 'default';
const mohSounds = (appState.sounds || []).filter(s => s.usage_type === 'moh');
let mohOpts = `<option value="default" ${curMoh === 'default' ? 'selected' : ''}>Défaut (Standard)</option>`;
let mohOpts = `<option value="default" ${curMoh === 'default' ? 'selected' : ''}>🌐 Hériter du Trunk / Global (Recommandé)</option>`;
mohSounds.forEach(s => {
const sSlug = slugifyTrunkName(s.site_category || 'global');
const cName = (sSlug === 'global' || sSlug === 'default') ? 'default' : `moh-${sSlug}`;
+1 -1
View File
@@ -3102,7 +3102,7 @@ $currentUser = Auth::getUsername();
<select id="ob-musicclass-select" name="moh_class" class="w-full px-3 py-2 rounded-lg bg-anthracite-900 border border-anthracite-700 text-xs text-white"></select>
</div>
<div>
<label class="block text-xs font-medium text-slate-200 mb-1">Destination sur Congestion <span class="text-slate-400">(Échec total)</span></label>
<label class="block text-xs font-medium text-slate-200 mb-1">📢 Si Trunks indisponibles <span class="text-slate-400">(Échec / Congestion)</span></label>
<select id="ob-congestion-dest-select" name="congestion_dest" class="w-full px-3 py-2 rounded-lg bg-anthracite-900 border border-anthracite-700 text-xs text-white"></select>
</div>
</div>
+23 -1
View File
@@ -1240,6 +1240,24 @@ class ConfigGenerator
$lines[] = " same => n,Congestion(20)";
$lines[] = " same => n,Hangup()";
$lines[] = "";
$lines[] = "exten => all-circuits-busy,1,NoOp(Terminate Call: Message vocal toutes les lignes sont occupees)";
$lines[] = " same => n,Answer()";
$lines[] = " same => n,Playback(all-circuits-busy-now)";
$lines[] = " same => n,Congestion(10)";
$lines[] = " same => n,Hangup()";
$lines[] = "";
$lines[] = "exten => _play-custom-.,1,NoOp(Terminate Call: Lecture annonce personnalisee \${EXTEN:12})";
$lines[] = " same => n,Answer()";
$lines[] = " same => n,Playback(custom/\${EXTEN:12})";
$lines[] = " same => n,Congestion(10)";
$lines[] = " same => n,Hangup()";
$lines[] = "";
$lines[] = "exten => _play-.,1,NoOp(Terminate Call: Lecture annonce systeme \${EXTEN:5})";
$lines[] = " same => n,Answer()";
$lines[] = " same => n,Playback(\${EXTEN:5})";
$lines[] = " same => n,Congestion(10)";
$lines[] = " same => n,Hangup()";
$lines[] = "";
$lines[] = "exten => zapateller,1,NoOp(Terminate Call: Tonalite SIT Anti-Robot)";
$lines[] = " same => n,Answer()";
$lines[] = " same => n,Zapateller()";
@@ -2130,6 +2148,9 @@ class ConfigGenerator
if ($dest === 'congestion' || $dest === 'terminate-congestion') {
return 'Goto(app-terminate,congestion,1)';
}
if ($dest === 'all-circuits-busy' || $dest === 'voice-all-circuits-busy') {
return 'Goto(app-terminate,all-circuits-busy,1)';
}
if ($dest === 'zapateller' || $dest === 'terminate-zapateller') {
return 'Goto(app-terminate,zapateller,1)';
}
@@ -2160,7 +2181,8 @@ class ConfigGenerator
if (str_starts_with($dest, 'sound-')) {
$snd = $this->resolveSoundFile(substr($dest, 6));
if ($snd !== '') {
return "Playback({$snd})";
$safeTarget = str_replace('/', '-', $snd);
return "Goto(app-terminate,play-{$safeTarget},1)";
}
return 'Goto(app-terminate,hangup,1)';
}
+1 -1
View File
@@ -639,7 +639,7 @@ class Database
':agroups' => json_encode($grps),
':aexts' => json_encode($exts),
':cont' => 1,
':cdest' => 'terminate-busy',
':cdest' => 'all-circuits-busy',
':rec' => 'dontcare',
]);