Cambios
This commit is contained in:
+46
-9
@@ -231,27 +231,64 @@
|
||||
|
||||
<!-- KPIs del período -->
|
||||
<h3 style="font-size:14px; margin-bottom:12px; color:#172b4d;">Métricas del período seleccionado</h3>
|
||||
<div class="kpi-row">
|
||||
<div class="kpi-row-3" style="margin-bottom:16px;">
|
||||
<div class="kpi qa" title="Total de tickets que han pasado por QA">
|
||||
<div class="kpi-value" id="kpi-qa-tickets">—</div>
|
||||
<div class="kpi-label">Tickets QA</div>
|
||||
<div class="kpi-sub">Procesados en el período</div>
|
||||
</div>
|
||||
<div class="kpi qa-time" title="Horas dedicadas a revisar un ticket (Tiempo neto en la columna QA)">
|
||||
<div class="kpi-value" id="kpi-qa-avg">—</div>
|
||||
<div class="kpi-label">Tiempo Prom. QA</div>
|
||||
<div class="kpi-sub">Horas promedio por ticket</div>
|
||||
<div class="kpi qa-time">
|
||||
<div class="kpi-value" id="kpi-qa-p50">—</div>
|
||||
<div class="kpi-label">
|
||||
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempo P50 QA
|
||||
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
|
||||
<div class="pop-item" style="font-size:12px;"><strong>Percentil 50 (Mediana)</strong><br>El 50% de las pruebas se completan en esta cantidad de horas netas o menos.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kpi-sub">Horas en prueba</div>
|
||||
</div>
|
||||
<div class="kpi qa-queue" title="Tiempo pasivo promedio esperando ser tomado (Cola 'Ready to QA')">
|
||||
<div class="kpi-value" id="kpi-qa-rtqa">—</div>
|
||||
<div class="kpi-label">Tiempo Prom. en Cola</div>
|
||||
<div class="kpi-sub">Horas esperando READY TO QA</div>
|
||||
<div class="kpi qa-time" style="border-color:#ff8b00;">
|
||||
<div class="kpi-value" id="kpi-qa-p90">—</div>
|
||||
<div class="kpi-label">
|
||||
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempos P90 y P99 QA
|
||||
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
|
||||
<div class="pop-item" style="font-size:12px;"><strong>Cuellos de Botella QA</strong><br><strong>P90:</strong> El 90% logran probarse en este tiempo.<br><strong>P99:</strong> El 99% logra terminar en este tiempo.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kpi-sub" id="kpi-qa-p99-sub">P99: — hs</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="kpi-row-3">
|
||||
<div class="kpi returned" title="Tickets que rebotaron en QA y el desarrollador tuvo que retomar ('Reaperturas' o regresos al ciclo En Curso)">
|
||||
<div class="kpi-value" id="kpi-qa-returned">—</div>
|
||||
<div class="kpi-label">Tickets Devueltos</div>
|
||||
<div class="kpi-sub" id="kpi-qa-returned-pct">Volvieron a En Curso</div>
|
||||
</div>
|
||||
<div class="kpi qa-queue">
|
||||
<div class="kpi-value" id="kpi-qa-rtqa-p50">—</div>
|
||||
<div class="kpi-label">
|
||||
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempo P50 RTQA
|
||||
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
|
||||
<div class="pop-item" style="font-size:12px;"><strong>Percentil 50 (Mediana)</strong><br>El 50% de los tickets espera esta cantidad de horas (o menos) en la cola antes de ser tomado por QA.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kpi-sub">Horas en cola</div>
|
||||
</div>
|
||||
<div class="kpi qa-queue" style="border-color:#ff8b00;">
|
||||
<div class="kpi-value" id="kpi-qa-rtqa-p90">—</div>
|
||||
<div class="kpi-label">
|
||||
<div class="pop-trigger" style="border-bottom: 1px dotted #5e6c84;">Tiempos P90 y P99 Cola
|
||||
<div class="pop-content" style="text-transform:none; font-weight:normal; letter-spacing:normal; text-align:left;">
|
||||
<div class="pop-item" style="font-size:12px;"><strong>Cuellos de Botella RTQA</strong><br>Casos atascados sin tester asignado.<br><br><strong>P90:</strong> El 90% de los tickets sale de la cola en este tiempo.<br><strong>P99:</strong> Bloqueos máximos en la cola.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="kpi-sub" id="kpi-qa-rtqa-p99-sub">P99: — hs</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Gráficos fila 1 -->
|
||||
|
||||
@@ -357,10 +357,16 @@ function renderQASection() {
|
||||
|
||||
// ── KPIs DEL PERÍODO ──────────────────────────────────────────────────────
|
||||
document.getElementById('kpi-qa-tickets').textContent = qa.tickets ?? '—';
|
||||
document.getElementById('kpi-qa-avg').textContent = qa.avgTimeQa != null ? qa.avgTimeQa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-rtqa').textContent = qa.avgTimeRtqa != null ? qa.avgTimeRtqa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-returned').textContent = qa.ticketsReturned ?? '—';
|
||||
|
||||
document.getElementById('kpi-qa-p50').textContent = qa.p50Qa != null ? qa.p50Qa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-p90').textContent = qa.p90Qa != null ? qa.p90Qa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-p99-sub').textContent = qa.p99Qa != null ? 'P99: ' + qa.p99Qa + ' hs' : 'P99: — hs';
|
||||
|
||||
document.getElementById('kpi-qa-rtqa-p50').textContent = qa.p50Rtqa != null ? qa.p50Rtqa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-rtqa-p90').textContent = qa.p90Rtqa != null ? qa.p90Rtqa + 'hs' : '—';
|
||||
document.getElementById('kpi-qa-rtqa-p99-sub').textContent = qa.p99Rtqa != null ? 'P99: ' + qa.p99Rtqa + ' hs' : 'P99: — hs';
|
||||
|
||||
const pctRet = qa.tickets > 0 ? ((qa.ticketsReturned / qa.tickets) * 100).toFixed(1) : 0;
|
||||
document.getElementById('kpi-qa-returned-pct').textContent =
|
||||
`${pctRet}% del total pasó por QA más de una vez`;
|
||||
|
||||
@@ -138,6 +138,7 @@ function processIssues(issues, period = '90d') {
|
||||
const qaData = {
|
||||
tickets: 0, ticketsReturned: 0, totalTimeQa: 0, totalTimeRtqa: 0,
|
||||
monthlyTotalQa: {}, monthlyCountQa: {}, monthlyTotalRtqa: {}, monthlyCountRtqa: {}, issues: [],
|
||||
timesQa: [], timesRtqa: []
|
||||
};
|
||||
|
||||
const deliveryData = {
|
||||
@@ -253,6 +254,7 @@ function processIssues(issues, period = '90d') {
|
||||
if (timeQaMin > 0) {
|
||||
qaData.tickets++;
|
||||
qaData.totalTimeQa += timeQaMin;
|
||||
qaData.timesQa.push(timeQaMin);
|
||||
if (timesRet > 1) qaData.ticketsReturned++;
|
||||
if (qaMonth) {
|
||||
qaData.monthlyTotalQa[qaMonth] = (qaData.monthlyTotalQa[qaMonth] || 0) + timeQaMin;
|
||||
@@ -264,10 +266,13 @@ function processIssues(issues, period = '90d') {
|
||||
});
|
||||
}
|
||||
|
||||
if (timeRtqaMin > 0 && qaMonth) {
|
||||
qaData.totalTimeRtqa += timeRtqaMin;
|
||||
qaData.monthlyTotalRtqa[qaMonth] = (qaData.monthlyTotalRtqa[qaMonth] || 0) + timeRtqaMin;
|
||||
qaData.monthlyCountRtqa[qaMonth] = (qaData.monthlyCountRtqa[qaMonth] || 0) + 1;
|
||||
if (timeRtqaMin > 0) {
|
||||
qaData.timesRtqa.push(timeRtqaMin);
|
||||
if (qaMonth) {
|
||||
qaData.totalTimeRtqa += timeRtqaMin;
|
||||
qaData.monthlyTotalRtqa[qaMonth] = (qaData.monthlyTotalRtqa[qaMonth] || 0) + timeRtqaMin;
|
||||
qaData.monthlyCountRtqa[qaMonth] = (qaData.monthlyCountRtqa[qaMonth] || 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const timeCrMin = f[config.fields.crTotalTime] ?? 0;
|
||||
@@ -341,6 +346,16 @@ function processIssues(issues, period = '90d') {
|
||||
const p90Cr = minsToHrs(getPercentile(crTimesSorted, 0.9));
|
||||
const p99Cr = minsToHrs(getPercentile(crTimesSorted, 0.99));
|
||||
|
||||
const qaTimesSorted = qaData.timesQa.sort((a, b) => a - b);
|
||||
const p50Qa = minsToHrs(getPercentile(qaTimesSorted, 0.5));
|
||||
const p90Qa = minsToHrs(getPercentile(qaTimesSorted, 0.9));
|
||||
const p99Qa = minsToHrs(getPercentile(qaTimesSorted, 0.99));
|
||||
|
||||
const rtqaTimesSorted = qaData.timesRtqa.sort((a, b) => a - b);
|
||||
const p50Rtqa = minsToHrs(getPercentile(rtqaTimesSorted, 0.5));
|
||||
const p90Rtqa = minsToHrs(getPercentile(rtqaTimesSorted, 0.9));
|
||||
const p99Rtqa = minsToHrs(getPercentile(rtqaTimesSorted, 0.99));
|
||||
|
||||
return {
|
||||
lastUpdated: new Date().toISOString(),
|
||||
assigneeData, monthlyDone, issuesList, warnings, currentStates,
|
||||
@@ -357,6 +372,7 @@ function processIssues(issues, period = '90d') {
|
||||
},
|
||||
qaData: {
|
||||
...qaData, monthlyAvgQa, monthlyAvgRtqa,
|
||||
p50Qa, p90Qa, p99Qa, p50Rtqa, p90Rtqa, p99Rtqa,
|
||||
avgTimeQa: qaData.tickets > 0 ? minsToHrs(qaData.totalTimeQa / qaData.tickets) : 0,
|
||||
avgTimeRtqa: qaData.tickets > 0 ? minsToHrs(qaData.totalTimeRtqa / qaData.tickets) : 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user