mirror of
https://github.com/cheveguerra/Colaborando.git
synced 2026-08-18 16:36:39 +00:00
- Resumen de activos en la esquina inferior izq del resumen
- Correccion en la habilidad de reordenamiento - Se agregaron los activos, penalizacin y potencial al reordenamiento
This commit is contained in:
@@ -443,9 +443,6 @@ function llenaProyectoGde(proyectoNum) {
|
||||
$('#activoReqProyectoCant2').text(proyectos[proyectoNum].activoAsignado2)
|
||||
$('#activoReqProyectoCant3').text(proyectos[proyectoNum].activoAsignado3)
|
||||
$('#mantoGde').text('MANTENIMIENTO ' + proyectos[proyectoNum].mantenimiento)
|
||||
|
||||
// Quitamos el proyecto actual del arreglo siguientesProyectos.
|
||||
siguientesProyectos.splice(0, 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -972,6 +969,15 @@ function redibujarTablero() {
|
||||
// Prioridad 3: Si no hay ninguno 'En proceso', tomar el primero de la cola 'En siguientes'.
|
||||
if (!nuevoProyectoGde) {
|
||||
nuevoProyectoGde = proyectos.find((p) => p.estatus === 'En siguientes')
|
||||
if (nuevoProyectoGde) {
|
||||
let index = siguientesProyectos.findIndex(
|
||||
(p) => p.id === nuevoProyectoGde.id
|
||||
)
|
||||
if (index !== -1) {
|
||||
siguientesProyectos.splice(index, 1)
|
||||
sincronizarColaSiguientes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Limpiar todos los slots de proyectos chicos.
|
||||
@@ -1980,7 +1986,7 @@ $('#accionHabilidadEspecial').click(function () {
|
||||
guardaSesion()
|
||||
}
|
||||
} else if (accionQuincenal === 'Ordenar los próximos 5 proyectos') {
|
||||
abrirDialogoOrdenarProyectos(elArreglo, quincenaActual);
|
||||
abrirDialogoOrdenarProyectos(elArreglo, quincenaActual)
|
||||
} else if (accionQuincenal === 'Omitir un mantenimiento') {
|
||||
// Actualizamos lastUsed
|
||||
setArrayValue(elArreglo, 'accionEspecialLastUsed', quincenaActual)
|
||||
@@ -3373,6 +3379,8 @@ function continuamos() {
|
||||
obtenerProyectosPendientes()
|
||||
if (siguientesProyectos.length > 0) {
|
||||
llenaProyectoGde(siguientesProyectos[0].id)
|
||||
siguientesProyectos.splice(0, 1)
|
||||
sincronizarColaSiguientes()
|
||||
}
|
||||
} else {
|
||||
// JUEGO CARGADO
|
||||
@@ -3431,7 +3439,17 @@ function continuamos() {
|
||||
|
||||
// 4. Reconstruir la cola de 'siguientesProyectos'.
|
||||
// Primero, tomar los que ya estaban 'En siguientes' del estado guardado.
|
||||
siguientesProyectos = proyectos.filter((p) => p.estatus === 'En siguientes')
|
||||
let tempSiguientes = proyectos.filter((p) => p.estatus === 'En siguientes')
|
||||
if (arregloGeneral.siguientesProyectosIds) {
|
||||
tempSiguientes.sort((a, b) => {
|
||||
let idxA = arregloGeneral.siguientesProyectosIds.indexOf(a.id)
|
||||
let idxB = arregloGeneral.siguientesProyectosIds.indexOf(b.id)
|
||||
if (idxA === -1) idxA = 999
|
||||
if (idxB === -1) idxB = 999
|
||||
return idxA - idxB
|
||||
})
|
||||
}
|
||||
siguientesProyectos = tempSiguientes
|
||||
|
||||
// Luego, completar la cola con proyectos 'Pendiente' si es necesario.
|
||||
const proyectosPendientes = proyectos.filter(
|
||||
@@ -3455,6 +3473,7 @@ function continuamos() {
|
||||
siguientesProyectos.push(proyectoElegido)
|
||||
proyectosDisponibles.splice(randomIndex, 1)
|
||||
}
|
||||
sincronizarColaSiguientes()
|
||||
|
||||
// 5. Llenar el proyecto grande.
|
||||
if (proyectoGde) {
|
||||
@@ -3462,6 +3481,8 @@ function continuamos() {
|
||||
} else if (siguientesProyectos.length > 0) {
|
||||
// Si no había ningún proyecto en el tablero, tomar el primero de la cola.
|
||||
llenaProyectoGde(siguientesProyectos[0].id)
|
||||
siguientesProyectos.splice(0, 1)
|
||||
sincronizarColaSiguientes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3696,82 +3717,145 @@ window.confirm = function (message, callback, customWidth) {
|
||||
})
|
||||
}
|
||||
|
||||
function sincronizarColaSiguientes() {
|
||||
if (typeof arregloGeneral !== 'undefined' && siguientesProyectos) {
|
||||
arregloGeneral.siguientesProyectosIds = siguientesProyectos.map((p) => p.id)
|
||||
}
|
||||
}
|
||||
|
||||
function abrirDialogoOrdenarProyectos(elArreglo, quincenaActual) {
|
||||
let proyectosAOrdenar = siguientesProyectos.slice(0, 5);
|
||||
let proyectosRestantes = siguientesProyectos.slice(5);
|
||||
let proyectosAOrdenar = siguientesProyectos.slice(0, 5)
|
||||
let proyectosRestantes = siguientesProyectos.slice(5)
|
||||
|
||||
let container = $('<div></div>');
|
||||
container.append('<p style="margin-bottom: 15px; font-size: 14px;">Arrastra los proyectos para ordenar la prioridad en la que aparecerán:</p>');
|
||||
let container = $('<div></div>')
|
||||
container.append(
|
||||
'<p style="margin-bottom: 15px; font-size: 14px;">Arrastra los proyectos para ordenar la prioridad en la que aparecerán:</p>'
|
||||
)
|
||||
|
||||
let list = $(
|
||||
'<ul id="sortable-proyectos" style="list-style-type: none; padding: 0; margin: 0;"></ul>'
|
||||
)
|
||||
const claseMapa = {
|
||||
amarillo: 'actPersonalCalificado',
|
||||
naranjas: 'actAnalistas',
|
||||
verdes: 'actFlujoDeEfectivo',
|
||||
azules: 'actTransporteYMaquinaria',
|
||||
rojos: 'actTecnologia',
|
||||
morados: 'actCreditoEInversion',
|
||||
}
|
||||
const colores = [
|
||||
'amarillo',
|
||||
'naranjas',
|
||||
'verdes',
|
||||
'azules',
|
||||
'rojos',
|
||||
'morados',
|
||||
]
|
||||
|
||||
let list = $('<ul id="sortable-proyectos" style="list-style-type: none; padding: 0; margin: 0;"></ul>');
|
||||
proyectosAOrdenar.forEach((p, idx) => {
|
||||
let activosReqHtml = ''
|
||||
colores.forEach((color) => {
|
||||
const valor = p[color]
|
||||
if (valor !== null && valor > 0) {
|
||||
const claseActivo = claseMapa[color]
|
||||
const textColor =
|
||||
color === 'amarillo' || color === 'naranjas' || color === 'verdes'
|
||||
? 'black'
|
||||
: 'white'
|
||||
activosReqHtml += `<span class="${claseActivo}" style="padding: 2px 6px; border-radius: 3px; color: ${textColor}; font-weight: bold; font-size: 11px; margin-right: 4px;">${valor}</span>`
|
||||
}
|
||||
})
|
||||
|
||||
const penVal = parseInt(p.penalizacion) || 0
|
||||
const penalizacionFormateada =
|
||||
penVal > 0 ? '$' + new Intl.NumberFormat('es-MX').format(penVal) : 'N/A'
|
||||
|
||||
let item = $(`
|
||||
<li class="ui-state-default" data-id="${p.id}" style="margin: 8px 0; padding: 10px; border: 2px solid gray; border-radius: 4px; background-color: #f9f9f9; cursor: grab; display: flex; justify-content: space-between; align-items: center; font-size: 14px;">
|
||||
<span style="font-weight: bold;">${idx + 1}. ${p.nombreProyecto}</span>
|
||||
<span style="font-size: 11px; background-color: #eee; padding: 2px 6px; border-radius: 3px; color: #555;">${p.departamento}</span>
|
||||
<li class="ui-state-default" data-id="${p.id}" style="margin: 8px 0; padding: 10px; border: 2px solid gray; border-radius: 4px; background-color: #f9f9f9; cursor: grab; display: flex; flex-direction: column; gap: 6px; font-size: 14px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; width: 100%;">
|
||||
<span style="font-weight: bold;">${idx + 1}. ${p.nombreProyecto}</span>
|
||||
<span style="font-size: 11px; background-color: #eee; padding: 2px 6px; border-radius: 3px; color: #555;">${p.departamento}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; width: 100%; font-size: 12px; color: #666;">
|
||||
<div style="display: flex; gap: 4px;">
|
||||
${activosReqHtml}
|
||||
</div>
|
||||
<div style="text-align: left; line-height: 1.4;">
|
||||
Potencial: <b>${p.potencial || 'N/A'}</b><br>
|
||||
Penalización: <b>${penalizacionFormateada}</b>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
`);
|
||||
list.append(item);
|
||||
});
|
||||
container.append(list);
|
||||
`)
|
||||
list.append(item)
|
||||
})
|
||||
container.append(list)
|
||||
|
||||
container.dialog({
|
||||
modal: true,
|
||||
title: 'Ordenar Próximos 5 Proyectos',
|
||||
width: 500,
|
||||
open: function() {
|
||||
open: function () {
|
||||
list.sortable({
|
||||
placeholder: "ui-state-highlight",
|
||||
placeholder: 'ui-state-highlight',
|
||||
forcePlaceholderSize: true,
|
||||
update: function(event, ui) {
|
||||
list.find('li').each(function(index) {
|
||||
let nombre = $(this).find('span').first().text();
|
||||
nombre = nombre.replace(/^\d+\.\s*/, '');
|
||||
$(this).find('span').first().text((index + 1) + '. ' + nombre);
|
||||
});
|
||||
}
|
||||
});
|
||||
list.disableSelection();
|
||||
$('<style id="sortable-style">.ui-state-highlight { height: 40px; background-color: #ffffcc; border: 2px dashed #999; margin: 8px 0; border-radius: 4px; }</style>').appendTo('head');
|
||||
update: function (event, ui) {
|
||||
list.find('li').each(function (index) {
|
||||
let nombre = $(this).find('span').first().text()
|
||||
nombre = nombre.replace(/^\d+\.\s*/, '')
|
||||
$(this)
|
||||
.find('span')
|
||||
.first()
|
||||
.text(index + 1 + '. ' + nombre)
|
||||
})
|
||||
},
|
||||
})
|
||||
list.disableSelection()
|
||||
$(
|
||||
'<style id="sortable-style">.ui-state-highlight { height: 40px; background-color: #ffffcc; border: 2px dashed #999; margin: 8px 0; border-radius: 4px; }</style>'
|
||||
).appendTo('head')
|
||||
},
|
||||
close: function() {
|
||||
$('#sortable-style').remove();
|
||||
$(this).dialog('destroy').remove();
|
||||
close: function () {
|
||||
$('#sortable-style').remove()
|
||||
$(this).dialog('destroy').remove()
|
||||
},
|
||||
buttons: {
|
||||
"Guardar Orden": function() {
|
||||
let nuevoOrdenIds = [];
|
||||
list.find('li').each(function() {
|
||||
nuevoOrdenIds.push(parseInt($(this).data('id')));
|
||||
});
|
||||
'Guardar Orden': function () {
|
||||
let nuevoOrdenIds = []
|
||||
list.find('li').each(function () {
|
||||
nuevoOrdenIds.push(parseInt($(this).data('id')))
|
||||
})
|
||||
|
||||
let nuevosSiguientes = [];
|
||||
nuevoOrdenIds.forEach(id => {
|
||||
let proj = proyectos.find(p => p.id === id);
|
||||
if (proj) nuevosSiguientes.push(proj);
|
||||
});
|
||||
|
||||
nuevosSiguientes = nuevosSiguientes.concat(proyectosRestantes);
|
||||
siguientesProyectos = nuevosSiguientes;
|
||||
let nuevosSiguientes = []
|
||||
nuevoOrdenIds.forEach((id) => {
|
||||
let proj = proyectos.find((p) => p.id === id)
|
||||
if (proj) nuevosSiguientes.push(proj)
|
||||
})
|
||||
|
||||
proyectos.forEach(p => {
|
||||
if (p.estatus === 'En siguientes') p.estatus = 'Pendiente';
|
||||
});
|
||||
siguientesProyectos.forEach(p => {
|
||||
let proj = proyectos.find(pr => pr.id === p.id);
|
||||
if (proj) proj.estatus = 'En siguientes';
|
||||
});
|
||||
nuevosSiguientes = nuevosSiguientes.concat(proyectosRestantes)
|
||||
siguientesProyectos = nuevosSiguientes
|
||||
sincronizarColaSiguientes()
|
||||
|
||||
setArrayValue(elArreglo, 'accionEspecialLastUsed', quincenaActual);
|
||||
var audio = new Audio('./Microwave_bell.wav');
|
||||
audio.play();
|
||||
window.alert('¡Orden de proyectos actualizado con éxito!');
|
||||
proyectos.forEach((p) => {
|
||||
if (p.estatus === 'En siguientes') p.estatus = 'Pendiente'
|
||||
})
|
||||
siguientesProyectos.forEach((p) => {
|
||||
let proj = proyectos.find((pr) => pr.id === p.id)
|
||||
if (proj) proj.estatus = 'En siguientes'
|
||||
})
|
||||
|
||||
if (typeof guardaSesion === 'function') guardaSesion();
|
||||
$(this).dialog('close');
|
||||
setArrayValue(elArreglo, 'accionEspecialLastUsed', quincenaActual)
|
||||
var audio = new Audio('./Microwave_bell.wav')
|
||||
audio.play()
|
||||
window.alert('¡Orden de proyectos actualizado con éxito!')
|
||||
|
||||
if (typeof guardaSesion === 'function') guardaSesion()
|
||||
$(this).dialog('close')
|
||||
},
|
||||
"Cancelar": function() { $(this).dialog('close'); }
|
||||
}
|
||||
});
|
||||
Cancelar: function () {
|
||||
$(this).dialog('close')
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
// </script>
|
||||
|
||||
@@ -164,6 +164,8 @@ function guardarDatosEnServidor() {
|
||||
.catch((error) => console.error('Error:', error))
|
||||
}
|
||||
|
||||
const guardaSesion = guardarDatosEnServidor;
|
||||
|
||||
// Cargar datos al iniciar la página
|
||||
document.addEventListener('DOMContentLoaded', cargarDatosDesdeServidor)
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# Plan de Implementación: Contabilización de Activos (Producidos, Recuperados y Perdidos)
|
||||
|
||||
Este documento detalla la lógica matemática y los pasos técnicos necesarios para implementar la visualización y el cálculo de estadísticas de activos en la pantalla de resumen de la aplicación **Colaborando**.
|
||||
|
||||
---
|
||||
|
||||
## 📋 Resumen del Enfoque
|
||||
|
||||
Para evitar desincronizaciones de datos y la necesidad de alterar la base de datos o los esquemas JSON de persistencia de sesión, utilizaremos un **cálculo dinámico en el cliente** (JavaScript). Toda la información necesaria ya existe dentro del arreglo global `proyectos` y el objeto `arregloGeneral`, que se guardan y cargan automáticamente con la sesión.
|
||||
|
||||
---
|
||||
|
||||
## 🧮 Lógica de Cálculo de Métricas
|
||||
|
||||
Para cada tipo de activo (p. ej., *Personal Calificado*, *Analistas*, *Flujo de Efectivo*, etc.), los valores se calculan recorriendo el arreglo global `proyectos` buscando proyectos con `estatus === 'Completado'`:
|
||||
|
||||
### 1. Activos Producidos (Total)
|
||||
* **Definición:** Activos que fueron creados/asignados para completar los proyectos finalizados.
|
||||
* **Lógica:** Suma de los requerimientos originales de todos los proyectos completados.
|
||||
* **Fórmula:**
|
||||
$$\text{Producidos}(c) = \sum_{p \in \text{Completados}} p[c]$$
|
||||
*(Donde $c$ es el campo de requerimiento del activo, como `amarillo`, `naranjas`, etc.)*
|
||||
|
||||
### 2. Activos Recuperados
|
||||
* **Definición:** Activos que se arrastraron exitosamente desde los proyectos terminados hacia los departamentos (lo cual resta del proyecto y suma al departamento).
|
||||
* **Lógica:** La diferencia entre el requerimiento original del proyecto completado y su valor de asignación actual (que disminuye al ser arrastrado).
|
||||
* **Fórmula:**
|
||||
$$\text{Recuperados}(c) = \sum_{p \in \text{Completados}} (p[c] - p['activoAsignado' + (i+1)])$$
|
||||
*(Donde $i$ es el índice del slot correspondiente al tipo de activo en el proyecto)*
|
||||
|
||||
### 3. Activos Perdidos
|
||||
* **Definición:** Activos que no se pudieron recuperar de proyectos finalizados por falta de recursos o de espacio antes de cambiar de periodo.
|
||||
* **Lógica:** Suma de los activos remanentes (`activoAsignadoX`) en proyectos completados que pertenecen a trimestres anteriores (ya que en el trimestre actual todavía es posible recuperarlos).
|
||||
* **Fórmula:**
|
||||
$$\text{Perdidos}(c) = \sum_{p \in \text{Completados}, p.\text{trimestreCompletado} < \text{trimestreActual}} p['activoAsignado' + (i+1)]$$
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Archivos y Cambios Requeridos
|
||||
|
||||
Todo el cambio se centraliza en el archivo **[resumen.php](file:///C:/CHV/ludotecaLocal/Colaborando/resumen.php)**.
|
||||
|
||||
### Paso 1: Interfaz de Usuario (HTML)
|
||||
Modificar la estructura de la tabla `#tablaActivos` (líneas ~308-348) para cambiar sus encabezados a:
|
||||
1. **Activo**
|
||||
2. **Producidos**
|
||||
3. **Recuperados**
|
||||
4. **Perdidos**
|
||||
|
||||
Asignar identificadores de celda descriptivos para inyectar los datos, por ejemplo:
|
||||
* Para Personal Calificado: `producidosPersonalCalificado`, `recuperadosPersonalCalificado`, `perdidosPersonalCalificado`.
|
||||
* Para Analistas: `producidosAnalistas`, `recuperadosAnalistas`, `perdidosAnalistas`.
|
||||
* *(Repetir para los 6 tipos de activos)*.
|
||||
|
||||
### Paso 2: Motor de Cálculo (JavaScript)
|
||||
Dentro de la función `actualizarResumenUI()` (línea ~720):
|
||||
1. **Inicializar:** Crear un objeto local para llevar las cuentas por tipo de activo e indicador (ej. `const stats = { PersonalCalificado: { producidos: 0, recuperados: 0, perdidos: 0 }, ... }`).
|
||||
2. **Procesar:** Iterar sobre el arreglo `proyectos` y clasificar según las fórmulas explicadas.
|
||||
3. **Renderizar:** Actualizar el contenido de las celdas del HTML utilizando jQuery (ej. `$('#producidosPersonalCalificado').text(stats.PersonalCalificado.producidos)`).
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Beneficios de esta Solución
|
||||
* **Integridad de datos:** No requiere modificar la estructura JSON del archivo de datos (`datos.json` / `cheve.json`).
|
||||
* **Sincronización total:** Si el usuario recarga la página o arrastra activos, la tabla se vuelve a calcular en tiempo real reflejando el estado real del juego.
|
||||
* **Mantenibilidad:** El código queda autocontenido en la vista de resumen.
|
||||
+188
@@ -391,6 +391,57 @@
|
||||
<!-- Contenido se llenará con JS -->
|
||||
</table>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>CONTABILIZACIÓN DE ACTIVOS</h2>
|
||||
<table id="tablaConteoActivos" class="summary-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Activo</th>
|
||||
<th>Producidos</th>
|
||||
<th>Recuperados</th>
|
||||
<th>Perdidos</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="actPersonalCalificado" style="color:black!important; font-weight: bold; text-align: left;">Personal calificado</td>
|
||||
<td id="conteoProducidosPersonalCalificado">0</td>
|
||||
<td id="conteoRecuperadosPersonalCalificado">0</td>
|
||||
<td id="conteoPerdidosPersonalCalificado">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="actAnalistas" style="color:black!important; font-weight: bold; text-align: left;">Analistas</td>
|
||||
<td id="conteoProducidosAnalistas">0</td>
|
||||
<td id="conteoRecuperadosAnalistas">0</td>
|
||||
<td id="conteoPerdidosAnalistas">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="actFlujoDeEfectivo" style="color:black!important; font-weight: bold; text-align: left;">Flujo de efectivo</td>
|
||||
<td id="conteoProducidosFlujoDeEfectivo">0</td>
|
||||
<td id="conteoRecuperadosFlujoDeEfectivo">0</td>
|
||||
<td id="conteoPerdidosFlujoDeEfectivo">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="actCreditoEInversion" style="font-weight: bold; text-align: left;">Crédito e Inversión</td>
|
||||
<td id="conteoProducidosCreditoEInversion">0</td>
|
||||
<td id="conteoRecuperadosCreditoEInversion">0</td>
|
||||
<td id="conteoPerdidosCreditoEInversion">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="actTecnologia" style="font-weight: bold; text-align: left;">Tecnología</td>
|
||||
<td id="conteoProducidosTecnologia">0</td>
|
||||
<td id="conteoRecuperadosTecnologia">0</td>
|
||||
<td id="conteoPerdidosTecnologia">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="actTransporteYMaquinaria" style="font-weight: bold; text-align: left;">Transporte y Maquinaria</td>
|
||||
<td id="conteoProducidosTransporteYMaquinaria">0</td>
|
||||
<td id="conteoRecuperadosTransporteYMaquinaria">0</td>
|
||||
<td id="conteoPerdidosTransporteYMaquinaria">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- =================================================================
|
||||
@@ -426,6 +477,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -465,6 +521,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -504,6 +565,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -543,6 +609,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -582,6 +653,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -621,6 +697,11 @@
|
||||
<div style="vertical-align:middle; display:inline-block; font-weight:bold; font-size:16px;" id="capitalCh" class="draggable recurso-item">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioTiempoCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioPersonalCh"></td>
|
||||
<td style="text-align:center; font-size:11px; color:#c9302c; font-weight:bold; height:15px; padding: 0;" class="beneficioCapitalCh"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -706,6 +787,32 @@
|
||||
deptoCard.find('#activoCh1').text(findArrayValue(deptoArr, 'activo1'));
|
||||
deptoCard.find('#activoCh2').text(findArrayValue(deptoArr, 'activo2'));
|
||||
|
||||
// Actualizar beneficios de habilidades acreditadas (-1 T, -1 P, -1 C)
|
||||
const habTiempo = findArrayValue(deptoArr, 'habilidadTiempo');
|
||||
const habPersonal = findArrayValue(deptoArr, 'habilidadPersonal');
|
||||
const habCapital = findArrayValue(deptoArr, 'habilidadCapital');
|
||||
|
||||
let txtTiempo = '';
|
||||
let txtPersonal = '';
|
||||
let txtCapital = '';
|
||||
|
||||
if (habTiempo && habTiempo !== 0) {
|
||||
const ben = findArrayValue(arreglosCapacitaciones[habTiempo], 'beneficio');
|
||||
txtTiempo = `${ben} T`;
|
||||
}
|
||||
if (habPersonal && habPersonal !== 0) {
|
||||
const ben = findArrayValue(arreglosCapacitaciones[habPersonal], 'beneficio');
|
||||
txtPersonal = `${ben} P`;
|
||||
}
|
||||
if (habCapital && habCapital !== 0) {
|
||||
const ben = findArrayValue(arreglosCapacitaciones[habCapital], 'beneficio');
|
||||
txtCapital = `${ben} C`;
|
||||
}
|
||||
|
||||
deptoCard.find('.beneficioTiempoCh').text(txtTiempo);
|
||||
deptoCard.find('.beneficioPersonalCh').text(txtPersonal);
|
||||
deptoCard.find('.beneficioCapitalCh').text(txtCapital);
|
||||
|
||||
// Mostrar/Ocultar Habilidad Especial si ya se acreditó
|
||||
const accionEspecial = findArrayValue(deptoArr, 'accionEspecialQuincenal');
|
||||
const rowHE = deptoCard.find('.fila-habilidad-especial');
|
||||
@@ -799,6 +906,87 @@
|
||||
}
|
||||
});
|
||||
|
||||
// --- 2.5 Contabilización de Activos (Producidos, Recuperados y Perdidos) ---
|
||||
const statsActivos = {
|
||||
PersonalCalificado: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
},
|
||||
Analistas: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
},
|
||||
FlujoDeEfectivo: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
},
|
||||
CreditoEInversion: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
},
|
||||
Tecnologia: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
},
|
||||
TransporteYMaquinaria: {
|
||||
producidos: 0,
|
||||
recuperados: 0,
|
||||
perdidos: 0
|
||||
}
|
||||
};
|
||||
|
||||
const mapaColoresActivos = {
|
||||
amarillo: 'PersonalCalificado',
|
||||
naranjas: 'Analistas',
|
||||
verdes: 'FlujoDeEfectivo',
|
||||
azules: 'TransporteYMaquinaria',
|
||||
rojos: 'Tecnologia',
|
||||
morados: 'CreditoEInversion'
|
||||
};
|
||||
const listaColores = ['amarillo', 'naranjas', 'verdes', 'azules', 'rojos', 'morados'];
|
||||
|
||||
proyectos.forEach(p => {
|
||||
if (p.estatus === 'Completado') {
|
||||
const coloresConValores = listaColores
|
||||
.filter(color => p[color] !== null && p[color] > 0)
|
||||
.map(color => ({
|
||||
color,
|
||||
valor: p[color]
|
||||
}));
|
||||
|
||||
coloresConValores.forEach((item, idx) => {
|
||||
const tipoActivo = mapaColoresActivos[item.color];
|
||||
const reqOriginal = item.valor;
|
||||
const asignadoActual = parseInt(p['activoAsignado' + (idx + 1)]) || 0;
|
||||
|
||||
// Producidos
|
||||
statsActivos[tipoActivo].producidos += reqOriginal;
|
||||
|
||||
// Recuperados
|
||||
const recuperados = reqOriginal - asignadoActual;
|
||||
statsActivos[tipoActivo].recuperados += (recuperados > 0 ? recuperados : 0);
|
||||
|
||||
// Perdidos (sólo si pertenece a un trimestre anterior)
|
||||
if (p.trimestreCompletado < trimestreActual) {
|
||||
statsActivos[tipoActivo].perdidos += asignadoActual;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Inyectar datos en la tabla HTML (con prefijo conteo)
|
||||
const tiposActivos = ['PersonalCalificado', 'Analistas', 'FlujoDeEfectivo', 'CreditoEInversion', 'Tecnologia', 'TransporteYMaquinaria'];
|
||||
tiposActivos.forEach(tipo => {
|
||||
$(`#conteoProducidos${tipo}`).text(statsActivos[tipo].producidos);
|
||||
$(`#conteoRecuperados${tipo}`).text(statsActivos[tipo].recuperados);
|
||||
$(`#conteoPerdidos${tipo}`).text(statsActivos[tipo].perdidos);
|
||||
});
|
||||
|
||||
$('#resumen-proyectos').html(`
|
||||
<thead><tr><th></th><th>T1</th><th>T2</th><th>T3</th><th>T4</th></tr></thead>
|
||||
<tbody>
|
||||
|
||||
Reference in New Issue
Block a user