Feature: add Paging & Intercom groups (Téléavertissement) with auto-answer headers, Asterisk Page application, and interactive member selection

This commit is contained in:
sorcier committed 2026-11-02 17:01:02 +01:00
1 parent 33ad75d571
commit 2bd1ae0777
5 files changed
+610

No files matched your search

+107
View File
@@ -90,6 +90,7 @@ try {
$settings = $db->query('SELECT * FROM settings WHERE id = 1')->fetch();
$extensions = $db->query('SELECT * FROM extensions ORDER BY CAST(extension AS INTEGER) ASC, extension ASC')->fetchAll();
$groups = $db->query('SELECT * FROM groups ORDER BY CAST(extension AS INTEGER) ASC, extension ASC')->fetchAll();
$pagingGroups = $db->query('SELECT * FROM paging_groups ORDER BY CAST(extension AS INTEGER) ASC, extension ASC')->fetchAll();
$extensionGroups = $db->query('SELECT * FROM extension_groups ORDER BY id ASC')->fetchAll();
$trunks = $db->query('SELECT * FROM trunks ORDER BY id ASC')->fetchAll();
$ivrs = $db->query('SELECT * FROM ivrs ORDER BY id ASC')->fetchAll();
@@ -102,6 +103,11 @@ try {
}
unset($g);
foreach ($pagingGroups as &$pg) {
$pg['members'] = json_decode((string)$pg['members'], true) ?: [];
}
unset($pg);
foreach ($extensionGroups as &$eg) {
$eg['members'] = json_decode((string)$eg['members'], true) ?: [];
}
@@ -136,6 +142,7 @@ try {
'settings' => $settings,
'extensions' => $extensions,
'groups' => $groups,
'paging_groups' => $pagingGroups,
'extension_groups' => $extensionGroups,
'trunks' => $trunks,
'ivrs' => $ivrs,
@@ -441,6 +448,106 @@ try {
]);
break;
case 'save_paging_group':
$id = isset($payload['id']) && $payload['id'] !== '' ? (int)$payload['id'] : null;
$extension = trim((string)($payload['extension'] ?? ''));
$name = trim((string)($payload['name'] ?? ''));
$desc = trim((string)($payload['description'] ?? ''));
$members = is_array($payload['members'] ?? null) ? array_values(array_filter(array_map('trim', $payload['members']))) : [];
$duplex = !empty($payload['duplex']) ? 1 : 0;
$busyMode = in_array($payload['busy_mode'] ?? '', ['skip', 'force'], true) ? $payload['busy_mode'] : 'skip';
$playBeep = isset($payload['play_beep']) ? (!empty($payload['play_beep']) ? 1 : 0) : 1;
$timeout = max(10, min(600, (int)($payload['timeout'] ?? 120)));
$enabled = isset($payload['enabled']) ? (!empty($payload['enabled']) ? 1 : 0) : 1;
if (!preg_match('/^\d{2,6}$/', $extension)) {
throw new InvalidArgumentException("Le numéro du groupe de téléavertissement doit comporter entre 2 et 6 chiffres.");
}
if ($name === '') {
throw new InvalidArgumentException("Le nom du groupe de téléavertissement est obligatoire.");
}
if (empty($members)) {
throw new InvalidArgumentException("Veuillez sélectionner au moins un poste membre pour ce groupe de téléavertissement.");
}
// Vérification de conflit avec un poste SIP existant
$chkExt = $db->prepare('SELECT COUNT(*) FROM extensions WHERE extension = :ext');
$chkExt->execute([':ext' => $extension]);
if ((int)$chkExt->fetchColumn() > 0) {
throw new InvalidArgumentException("Le numéro {$extension} est déjà assigné à un poste SIP individuel.");
}
// Vérification de conflit avec un groupe de sonnerie
$chkGrp = $db->prepare('SELECT COUNT(*) FROM groups WHERE extension = :ext');
$chkGrp->execute([':ext' => $extension]);
if ((int)$chkGrp->fetchColumn() > 0) {
throw new InvalidArgumentException("Le numéro {$extension} est déjà assigné à un groupe de sonnerie.");
}
if ($id) {
$stmt = $db->prepare('
UPDATE paging_groups
SET extension = :ext, name = :name, description = :desc,
members = :members, duplex = :duplex, busy_mode = :busy_mode,
play_beep = :play_beep, timeout = :timeout, enabled = :enabled,
updated_at = CURRENT_TIMESTAMP
WHERE id = :id
');
$stmt->execute([
':id' => $id,
':ext' => $extension,
':name' => $name,
':desc' => $desc,
':members' => json_encode($members),
':duplex' => $duplex,
':busy_mode' => $busyMode,
':play_beep' => $playBeep,
':timeout' => $timeout,
':enabled' => $enabled,
]);
} else {
$stmt = $db->prepare('
INSERT INTO paging_groups (extension, name, description, members, duplex, busy_mode, play_beep, timeout, enabled)
VALUES (:ext, :name, :desc, :members, :duplex, :busy_mode, :play_beep, :timeout, :enabled)
ON CONFLICT(extension) DO UPDATE SET
name = excluded.name,
description = excluded.description,
members = excluded.members,
duplex = excluded.duplex,
busy_mode = excluded.busy_mode,
play_beep = excluded.play_beep,
timeout = excluded.timeout,
enabled = excluded.enabled,
updated_at = CURRENT_TIMESTAMP
');
$stmt->execute([
':ext' => $extension,
':name' => $name,
':desc' => $desc,
':members' => json_encode($members),
':duplex' => $duplex,
':busy_mode' => $busyMode,
':play_beep' => $playBeep,
':timeout' => $timeout,
':enabled' => $enabled,
]);
}
echo json_encode([
'success' => true,
'message' => "Groupe de téléavertissement {$extension} ({$name}) sauvegardé.",
]);
break;
case 'delete_paging_group':
$id = (int)($payload['id'] ?? 0);
$db->prepare('DELETE FROM paging_groups WHERE id = :id')->execute([':id' => $id]);
echo json_encode([
'success' => true,
'message' => "Groupe de téléavertissement supprimé.",
]);
break;
case 'save_extension_group':
$id = isset($payload['id']) && $payload['id'] !== '' ? (int)$payload['id'] : null;
$name = trim((string)($payload['name'] ?? ''));