fix(ucp): correction journal personnel Mes Appels CDR (v2.5.4)
This commit is contained in:
1 parent
d618d426e7
commit
c10c980024
3 files changed
+54
-13
No files matched your search
+33
-5
@@ -607,10 +607,16 @@ class UcpManager
|
|||||||
return ['calls' => [], 'stats' => ['total' => 0, 'answered' => 0, 'missed' => 0]];
|
return ['calls' => [], 'stats' => ['total' => 0, 'answered' => 0, 'missed' => 0]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$rawDisp = strtoupper(trim((string)($filters['disposition'] ?? 'all')));
|
||||||
|
$cdrDisp = match ($rawDisp) {
|
||||||
|
'ANSWERED' => 'answered',
|
||||||
|
default => 'all',
|
||||||
|
};
|
||||||
|
|
||||||
$res = CdrManager::getCalls($db, [
|
$res = CdrManager::getCalls($db, [
|
||||||
'limit' => 500,
|
'limit' => 500,
|
||||||
'direction' => (string)($filters['direction'] ?? 'all'),
|
'direction' => (string)($filters['direction'] ?? 'all'),
|
||||||
'disposition' => (string)($filters['disposition'] ?? 'all'),
|
'disposition' => $cdrDisp,
|
||||||
'period' => (string)($filters['period'] ?? 'all'),
|
'period' => (string)($filters['period'] ?? 'all'),
|
||||||
'search' => (string)($filters['search'] ?? ''),
|
'search' => (string)($filters['search'] ?? ''),
|
||||||
]);
|
]);
|
||||||
@@ -619,17 +625,39 @@ class UcpManager
|
|||||||
$answered = 0;
|
$answered = 0;
|
||||||
$missed = 0;
|
$missed = 0;
|
||||||
|
|
||||||
|
$extractExt = static function (string $chan): string {
|
||||||
|
if (preg_match('/^(?:PJSIP|SIP)\/([^-\/@]+)/i', trim($chan), $m)) {
|
||||||
|
return (string)$m[1];
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
foreach ($res['calls'] as $call) {
|
foreach ($res['calls'] as $call) {
|
||||||
$srcMatch = in_array((string)($call['src'] ?? ''), $extSet, true);
|
$callerNum = (string)($call['caller_number'] ?? $call['src'] ?? '');
|
||||||
$dstMatch = in_array((string)($call['dst'] ?? ''), $extSet, true);
|
$calleeNum = (string)($call['callee_number'] ?? $call['dst'] ?? '');
|
||||||
if (!$srcMatch && !$dstMatch) {
|
$srcChanEp = $extractExt((string)($call['channel'] ?? ''));
|
||||||
|
$dstChanEp = $extractExt((string)($call['dstchannel'] ?? ''));
|
||||||
|
|
||||||
|
$isMine = in_array($callerNum, $extSet, true)
|
||||||
|
|| in_array($calleeNum, $extSet, true)
|
||||||
|
|| ($srcChanEp !== '' && in_array($srcChanEp, $extSet, true))
|
||||||
|
|| ($dstChanEp !== '' && in_array($dstChanEp, $extSet, true));
|
||||||
|
|
||||||
|
if (!$isMine) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (($call['disposition'] ?? '') === 'ANSWERED') {
|
|
||||||
|
$disp = strtoupper((string)($call['disposition'] ?? 'NO ANSWER'));
|
||||||
|
if ($rawDisp === 'MISSED' && $disp === 'ANSWERED') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($disp === 'ANSWERED') {
|
||||||
$answered++;
|
$answered++;
|
||||||
} else {
|
} else {
|
||||||
$missed++;
|
$missed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filtered[] = $call;
|
$filtered[] = $call;
|
||||||
if (count($filtered) >= 120) {
|
if (count($filtered) >= 120) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
+19
-7
@@ -633,16 +633,28 @@ async function loadPersonalCdr() {
|
|||||||
};
|
};
|
||||||
const ok = c.disposition === 'ANSWERED';
|
const ok = c.disposition === 'ANSWERED';
|
||||||
const stBadge = ok
|
const stBadge = ok
|
||||||
? '<span class="px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 border border-emerald-200 text-[10px] font-bold">Répondu</span>'
|
? `<span class="px-2 py-0.5 rounded-full bg-emerald-50 text-emerald-700 border border-emerald-200 text-[10px] font-bold">${escapeHtml(c.status_label || 'Répondu')}</span>`
|
||||||
: '<span class="px-2 py-0.5 rounded-full bg-rose-50 text-rose-700 border border-rose-200 text-[10px] font-bold">Manqué</span>';
|
: `<span class="px-2 py-0.5 rounded-full bg-rose-50 text-rose-700 border border-rose-200 text-[10px] font-bold">${escapeHtml(c.status_label || 'Manqué')}</span>`;
|
||||||
|
|
||||||
|
const srcNum = String(c.caller_number ?? c.src ?? '');
|
||||||
|
const srcName = String(c.caller_name ?? '');
|
||||||
|
const dstNum = String(c.callee_number ?? c.dst ?? '');
|
||||||
|
const dstName = String(c.callee_name ?? '');
|
||||||
|
|
||||||
|
const formatParty = (name, num) => {
|
||||||
|
if (name && num && name !== num) {
|
||||||
|
return `<div class="font-semibold text-slate-900">${escapeHtml(name)}</div><div class="text-[11px] font-mono text-slate-500">${escapeHtml(num)}</div>`;
|
||||||
|
}
|
||||||
|
return `<span class="font-semibold font-mono text-slate-900">${escapeHtml(num || name || '—')}</span>`;
|
||||||
|
};
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<tr class="hover:bg-slate-50/80 transition">
|
<tr class="hover:bg-slate-50/80 transition">
|
||||||
<td class="py-3 px-4 text-slate-600 font-mono whitespace-nowrap">${escapeHtml(c.date_human || c.calldate || '')}</td>
|
<td class="py-3 px-4 text-slate-600 font-mono whitespace-nowrap">${escapeHtml(c.datetime_formatted || c.datetime || '')}</td>
|
||||||
<td class="py-3 px-4">${dirMap[c.direction] || escapeHtml(c.direction)}</td>
|
<td class="py-3 px-4">${dirMap[c.direction] || escapeHtml(c.direction_label || c.direction)}</td>
|
||||||
<td class="py-3 px-4 font-semibold text-slate-900">${escapeHtml(c.src_label || c.src || '')}</td>
|
<td class="py-3 px-4">${formatParty(srcName, srcNum)}</td>
|
||||||
<td class="py-3 px-4 font-semibold text-slate-900">${escapeHtml(c.dst_label || c.dst || '')}</td>
|
<td class="py-3 px-4">${formatParty(dstName, dstNum)}</td>
|
||||||
<td class="py-3 px-4 font-mono text-slate-600">${formatDuration(c.billsec || c.duration || 0)}</td>
|
<td class="py-3 px-4 font-mono text-slate-600">${escapeHtml(c.billsec_formatted || formatDuration(c.billsec || c.duration || 0))}</td>
|
||||||
<td class="py-3 px-4">${stBadge}</td>
|
<td class="py-3 px-4">${stBadge}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
|
|||||||
+2
-1
@@ -1,9 +1,10 @@
|
|||||||
{
|
{
|
||||||
"version": "2.5.3",
|
"version": "2.5.4",
|
||||||
"codename": "Pulsar UCP",
|
"codename": "Pulsar UCP",
|
||||||
"release_date": "2026-11-11",
|
"release_date": "2026-11-11",
|
||||||
"min_php_version": "8.2",
|
"min_php_version": "8.2",
|
||||||
"changelog": [
|
"changelog": [
|
||||||
|
"Correctif v2.5.4 : correction du journal personnel UCP « Mes Appels » (correspondance caller_number/callee_number/canaux PJSIP et filtres Répondus/Manqués)",
|
||||||
"Nouveauté v2.5.3 : onglet UCP « Notice & Codes » avec mémo pas-à-pas, codes de fonction dynamiques et export PDF / impression A4 corporate (logo, encarts, poste utilisateur)",
|
"Nouveauté v2.5.3 : onglet UCP « Notice & Codes » avec mémo pas-à-pas, codes de fonction dynamiques et export PDF / impression A4 corporate (logo, encarts, poste utilisateur)",
|
||||||
"Correctif v2.5.2 : purge systématique try/finally + auto-nettoyage des dossiers temporaires HA /tmp (élimine la saturation tmpfs 100% qui bloquait la réplication)",
|
"Correctif v2.5.2 : purge systématique try/finally + auto-nettoyage des dossiers temporaires HA /tmp (élimine la saturation tmpfs 100% qui bloquait la réplication)",
|
||||||
"Correctif v2.5.1 : auto-déploiement automatique Nginx/Fail2ban UCP même après un git pull manuel",
|
"Correctif v2.5.1 : auto-déploiement automatique Nginx/Fail2ban UCP même après un git pull manuel",
|
||||||
|
|||||||
Reference in new issue
Block a user