diff --git a/doc/PROYECTO.md b/doc/PROYECTO.md index aaa64da..0ee65a4 100644 --- a/doc/PROYECTO.md +++ b/doc/PROYECTO.md @@ -27,17 +27,16 @@ Existen 6 departamentos: *Marketing y Ventas, Finanzas, Investigación y Desarro ### 2. Ciclo de Vida de Proyectos * **En proceso:** Proyectos activos en los que se está trabajando. * **Completado:** Proyectos finalizados con éxito. Sus requerimientos y recursos recuperados se contabilizan. -* **Descartado:** Proyectos cancelados manualmente por el usuario pagando penalizaciones. ### 3. Mantenimiento Trimestral y Penalizaciones -En los cierres de trimestre (quincenas 6, 12, 18 y 24), los proyectos activos en proceso requieren el pago de un coste de mantenimiento (`Tiempo`, `Personal`, `Capital`). -* Si se paga, el proyecto se oculta temporalmente durante esa quincena y reaparece en la quincena siguiente (inicio de nuevo trimestre). -* Si no se puede o no se quiere pagar, el proyecto debe ser **desechado**, lo que resta un costo de **Penalización** del acumulado financiero acumulado del trimestre actual. +En los cierres de trimestre (quincenas 6, 12, 18 y 24), los proyectos activos en proceso requieren el pago de un coste de mantenimiento (`Tiempo`, `Personal`, `Capital`) o el pago de una **Penalización** financiera del acumulado de ingresos. +* En cualquiera de los dos casos, el proyecto se mantiene activo (`En proceso`) y visible en el tablero y en el resumen. +* En la pantalla de resumen, el proyecto se muestra en gris (deshabilitado) y sus botones de acción se bloquean una vez resuelto en el trimestre actual. ### 4. Habilidades Especiales (Acción Quincenal) Los departamentos pueden comprar habilidades especiales con cooldown (periodicidad). Ejemplos clave: * **Logística y Sistemas:** Permite omitir el costo de mantenimiento de un proyecto activo (pagarlo sin gastar recursos). -* **Operaciones:** Permite desechar un proyecto en proceso sin costo de penalización. +* **Operaciones:** Permite penalizar un proyecto en proceso sin costo de penalización. * **Ordenar proyectos:** Permite reordenar la cola de los próximos 5 proyectos en el tablero. ### 5. Contabilización de Activos @@ -57,6 +56,11 @@ Los activos producidos por proyectos completados se dividen en 6 tipos: *Persona ## 📈 Bitácora Histórica de Cambios (Changelog) +* **16/Jul/2026:** + * **Cambio de Desechar a Penalizar:** En la pantalla de resumen, se cambió el botón "Desechar" por "Penalizar". + * **Persistencia de Actividad:** Los proyectos penalizados ahora se mantienen activos (`En proceso`) en lugar de descartarse. + * **Actualización de Visualización:** Tanto al pagar mantenimiento como al penalizar, el proyecto permanece en la quincena actual; en el resumen, su tarjeta cambia a color gris y sus botones se bloquean. Se excluyeron de este bloqueo los proyectos con mantenimiento "N/A" (como "Capacitación Brigadas") y las Incidencias. + * **Descuentos de Habilidades en Mantenimiento:** Al pagar mantenimiento de forma normal, se aplican correctamente los beneficios/descuentos de recursos ganados por el departamento mediante sus habilidades compradas (`habilidadTiempo`, `habilidadPersonal`, `habilidadCapital`), reduciendo el costo cobrado en base a los beneficios definidos. * **03/Jul/2026:** * Implementación de la ventana de mantenimiento trimestral (Q6, 12, 18, 24) en resumen y tablero. * Integración de habilidades especiales para omitir costo de mantenimiento (Logística) y omitir penalizaciones por desecho (Operaciones). diff --git a/doc/walkthrough.md b/doc/walkthrough.md index eb53c3f..26f6535 100644 --- a/doc/walkthrough.md +++ b/doc/walkthrough.md @@ -1,44 +1,29 @@ -# Resumen de Cambios: Pago de Mantenimiento y Desecho de Proyectos Activos +# Resumen de Cambios: Mantenimiento y Penalización de Proyectos Activos (Actualizado) -Se ha implementado completamente la funcionalidad solicitada para gestionar proyectos activos al final del trimestre (quincenas 6, 12, 18, 24). +Se ha implementado la funcionalidad solicitada para gestionar proyectos activos al final del trimestre (quincenas 6, 12, 18, 24). ## Cambios Realizados ### 1. Pantalla de Resumen ([resumen.php](file:///c:/CHV/ludotecaLocal/Colaborando/resumen.php)) -- **Botones Dinámicos en Tarjetas:** Las tarjetas de proyectos activos (`En proceso`) muestran los botones **Pagar Manto** y **Desechar** si y solo si la quincena actual es un fin de trimestre (quincena % 6 === 0) y el mantenimiento no ha sido pagado en ese trimestre. -- **Información Adicional en Tarjetas Activas:** Ahora se visualiza en cada tarjeta de proyecto activo su **Potencial** de ingresos y su valor de **Penalización** (formateado como moneda). -- **Función Pagar Manto:** - - Solicita confirmación al usuario utilizando el diálogo `confirm()` asíncrono con el costo y departamento origen antes de proceder. - - Resta los recursos necesarios (Tiempo, Personal, Capital) del departamento seleccionado (`deptoActual`). - - Si el departamento no tiene recursos suficientes, muestra un mensaje de alerta. - - Guarda `mantenimientoPagadoEnTrimestre = trimestreActual` en el proyecto para indicar que se pagó la mantención para la transición al siguiente trimestre. - - **Habilidad Especial de Logística y Sistemas ("Omitir un mantenimiento"):** Si el departamento seleccionado es "LogisticaYSistemas", tiene comprada dicha habilidad especial (campo de acción especial distinto de `""`) y está disponible (cooldown), se le ofrece un diálogo modal preguntando si desea usar su habilidad para omitir el mantenimiento del proyecto **sin gastar ningún recurso**, o pagar de manera normal. Usar la habilidad actualiza su cooldown (`accionEspecialLastUsed`). -- **Función Desechar:** - - Valida que el acumulado general hasta el trimestre actual sea suficiente para pagar la penalización. Si es insuficiente, se impide el desecho y se muestra un mensaje explicativo. - - Utiliza la función `confirm()` personalizada asíncrona mediante callback (para evitar que aborte instantáneamente como lo hacía al usar un valor de retorno síncrono). Al confirmar, resta la penalización del acumulado del trimestre actual e internally cambia el estado del proyecto a `'descartado'`. - - **Habilidad Especial de Operaciones:** Si el departamento seleccionado es "Operaciones", tiene comprada dicha habilidad especial (es decir, el campo de la acción especial es distinto de vacío `""`) y no está en *cooldown* (periodicidad), se le presenta un diálogo de decisión ofreciendo descartar el proyecto **sin costo** utilizando la habilidad especial, o realizar un desecho normal pagando la penalización. Usar la habilidad especial actualiza su último turno de uso (`accionEspecialLastUsed`). +- **Botones Dinámicos en Tarjetas:** Las tarjetas de proyectos activos (`En proceso`) muestran los botones **Pagar Manto** y **Penalizar** (antes *Desechar*) si y solo si la quincena actual es un fin de trimestre (quincena % 6 === 0), excluyendo los proyectos con mantenimiento `'N/A'` y las Incidencias. +- **Persistencia de Proyectos:** El botón "Penalizar" ya no descarta el proyecto (no cambia su estatus a `descartado`). El proyecto permanece activo (`En proceso`). +- **Estado Deshabilitado:** Una vez que se paga el mantenimiento o se paga la penalización, la tarjeta del proyecto se tiñe de color gris en la pantalla de resumen, y los botones **Pagar Manto** y **Penalizar** quedan deshabilitados (`disabled`), indicando visualmente que ya se resolvió la situación del proyecto para el trimestre actual (los proyectos exentos o Incidencias permanecen activos y con su color blanco normal). +- **Descuentos por Habilidades:** Al realizar el pago de mantenimiento de forma normal, se aplican los descuentos de recursos (Tiempo, Personal, Capital) ganados mediante las habilidades compradas del departamento (`habilidadTiempo`, `habilidadPersonal`, `habilidadCapital`), restando del total del depto el costo neto descontado (mínimo de 0). +- **Textos e Interfaz:** Se ajustó la confirmación de penalización a: *"¿Estás seguro de que quieres pagar la penalización del proyecto..."*. Se detalla el costo original y costo neto final con descuento en el confirm del pago de mantenimiento. +- **Habilidad Especial de Operaciones:** Permite aplicar la penalización del proyecto sin costo utilizando la habilidad especial (actualizando su cooldown). ### 2. Tablero de Juego ([jsCode.js](file:///c:/CHV/ludotecaLocal/Colaborando/jsCode.js)) -- **Ocultamiento por Mantenimiento:** Se modificó la carga del tablero en la función `continuamos()` para que los proyectos activos cuyo mantenimiento ya se pagó en el trimestre actual no aparezcan en el tablero (de esta forma no se puede seguir trabajando en ellos en el fin de trimestre actual). -- **Reaparición en el Siguiente Trimestre:** Al cambiar el trimestre (por ejemplo, avanzar de la quincena 6 a la 7), la comparación detecta que el trimestre actual es mayor al del pago de mantenimiento, por lo que el proyecto vuelve a cargarse automáticamente en el tablero. -- **Función `limpiaProyectoGrande`**: Se implementó una nueva función helper para despejar la vista del proyecto grande cuando está en estado pendiente de pago o pago realizado en resumen. -- **Ancho de Diálogos de Alerta (`window.alert`)**: Se aumentó un 50% (de 300px a 450px) el ancho predeterminado de los cuadros de diálogo de alerta para evitar que los mensajes largos de advertencia o confirmación se vean estrechos. -- **Corrección de Actualización de Recursos (IDs Dinámicos)**: Se corrigió un problema donde los recursos del departamento seleccionado no se reflejaban visualmente al pagar el mantenimiento. Esto ocurría porque los IDs de los contenedores cambian de `#tiempoCh` a `#recursoDispTiempoGde` cuando un departamento está seleccionado. Se implementó una selección flexible que detecta ambos formatos. -- **Bypass de Cache del Navegador (Cache-Busting)**: Se implementó un parámetro único de marca de tiempo (`_t`) y la cabecera `cache: 'no-store'` en la carga AJAX de la sesión para evitar que el navegador devuelva respuestas cacheadas obsoletas del estado del juego al navegar entre el tablero y el resumen. +- **Visibilidad Permanente:** Se eliminaron los filtros que ocultaban el proyecto del tablero chico o grande cuando el mantenimiento ya había sido resuelto. El proyecto permanece visible tanto en el tablero como en el resumen durante la quincena actual, permitiendo seguir trabajando en él. ## Cómo Realizar las Pruebas (Verificación) -1. **Escenario de Pago de Mantenimiento:** +1. **Escenario de Pago de Mantenimiento / Penalización:** - Asegúrate de estar en una quincena fin de trimestre (ej. **Q6** del Trimestre 1). - - Ve a la pantalla de resumen. Verás los botones correspondientes en los proyectos en proceso. - - Selecciona un departamento con recursos suficientes y pulsa **Pagar Manto**. - - El proyecto desaparecerá inmediatamente de la lista del resumen. - - Ve al Tablero (`colaborando2.php`) en la misma quincena (Q6) y verifica que el proyecto no se muestra. - - Avanza la quincena a **Q7** (Trimestre 2). Vuelve al Tablero y comprueba que el proyecto reaparece en el tablero. - -2. **Escenario de Desecho con Penalización:** - - En la quincena fin de trimestre, ve a resumen. - - Intenta desechar un proyecto cuya penalización sea mayor que tu acumulado actual disponible. Verifica que la aplicación bloquee la acción e informe. - - Intenta desechar un proyecto teniendo fondos suficientes. - - Confirma la alerta; comprueba que el proyecto desaparece y que la penalización se resta en la tabla de progresión general. - - Ve al tablero y verifica que el proyecto desechado ya no vuelve a aparecer en ningún trimestre. + - Ve a la pantalla de resumen. Verás los botones **Pagar Manto** y **Penalizar** en los proyectos en proceso. + - Realiza cualquiera de las dos acciones: + - **Pagar Manto:** Selecciona un departamento con recursos suficientes y pulsa el botón. + - **Penalizar:** Pulsa el botón; confirmará que tengas acumulado financiero suficiente y aplicará la deducción. + - En ambos casos: + - La tarjeta del proyecto en el resumen cambiará inmediatamente a un fondo gris y los botones de acción se deshabilitarán de forma definitiva en la quincena actual. + - Ve al Tablero (`colaborando2.php`) en la misma quincena (Q6) y verifica que el proyecto **sigue estando visible** en el tablero chico y en el slot de proyecto grande. + - Avanza la quincena a **Q7** (Trimestre 2). Vuelve a la pantalla de resumen y verifica que el proyecto recupera su color blanco y los botones ya no aparecen (pues no es fin de trimestre), y que en el tablero continúa disponible con total normalidad. diff --git a/jsCode.js b/jsCode.js index 5d6d3a8..b9dde75 100644 --- a/jsCode.js +++ b/jsCode.js @@ -2021,10 +2021,7 @@ $('#accionHabilidadEspecial').click(function () { if (typeof guardaSesion === 'function') { guardaSesion() } - } else if ( - accionQuincenal === - 'Descartar un proyecto (se va al limbo con todo y activos)' - ) { + } else if (accionQuincenal === 'Descartar un proyecto') { // Actualizamos lastUsed const proyectosEnProceso = proyectos.filter( (p) => p.estatus === 'En proceso' @@ -3189,8 +3186,7 @@ function tieneTresHabilidades(depto) { textoAccion = 'Omitir un mantenimiento' break case 'Operaciones': - textoAccion = - 'Descartar un proyecto (se va al limbo con todo y activos)' + textoAccion = 'Descartar un proyecto' break } setArrayValue(elArreglo, 'accionEspecialQuincenal', textoAccion) @@ -3426,8 +3422,8 @@ function continuamos() { }) // --- FIN DEL PARCHE --- - const quincenaCargada = parseInt(arregloGeneral.quincena) || 1; - const trimestreActual = Math.floor((quincenaCargada - 1) / 6) + 1; + const quincenaCargada = parseInt(arregloGeneral.quincena) || 1 + const trimestreActual = Math.floor((quincenaCargada - 1) / 6) + 1 // 1. Usar el ID del proyecto grande que se guardó en la sesión, si no está completado. let proyectoGde = null @@ -3455,9 +3451,7 @@ function continuamos() { // 3. Llenar los proyectos chicos con los que están 'En proceso' (excluyendo el grande). const proyectosEnTablero = proyectos.filter( (p) => - p.estatus === 'En proceso' && - (!proyectoGde || p.id !== proyectoGde.id) && - (p.mantenimiento === 'N/A' || p.mantenimientoPagadoEnTrimestre !== trimestreActual) + p.estatus === 'En proceso' && (!proyectoGde || p.id !== proyectoGde.id) ) console.log('Proyectos para mostrar en tablero chico:', proyectosEnTablero) @@ -3505,11 +3499,7 @@ function continuamos() { // 5. Llenar el proyecto grande. if (proyectoGde) { - if (proyectoGde.mantenimiento !== 'N/A' && proyectoGde.mantenimientoPagadoEnTrimestre === trimestreActual) { - limpiaProyectoGrande() - } else { - llenaProyectoGde(proyectoGde.id) - } + llenaProyectoGde(proyectoGde.id) } 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) diff --git a/manejoDeSesiones.js b/manejoDeSesiones.js index 2eac1ae..0b7e911 100644 --- a/manejoDeSesiones.js +++ b/manejoDeSesiones.js @@ -30,7 +30,11 @@ function cargarDatosDesdeServidor() { console.log('nombreArchivo:', nombreArchivo) let url = 'manejoDeSesiones.php' if (nombreArchivo != '') { - url += '?nombre=' + encodeURIComponent(nombreArchivo) + '&_t=' + new Date().getTime() + url += + '?nombre=' + + encodeURIComponent(nombreArchivo) + + '&_t=' + + new Date().getTime() } else { url += '?_t=' + new Date().getTime() } @@ -166,7 +170,7 @@ function guardarDatosEnServidor() { .catch((error) => console.error('Error:', error)) } -const guardaSesion = guardarDatosEnServidor; +const guardaSesion = guardarDatosEnServidor // Cargar datos al iniciar la página document.addEventListener('DOMContentLoaded', cargarDatosDesdeServidor) @@ -180,21 +184,23 @@ window.addEventListener('beforeunload', function () { function toggleFullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen().catch((err) => { - console.error(`Error al intentar activar pantalla completa: ${err.message}`); - }); + console.error( + `Error al intentar activar pantalla completa: ${err.message}` + ) + }) } else { - document.exitFullscreen(); + document.exitFullscreen() } } // Escuchar el cambio de estado de pantalla completa para actualizar el texto del botón document.addEventListener('fullscreenchange', () => { - const btn = document.getElementById('btnFullscreen'); + const btn = document.getElementById('btnFullscreen') if (btn) { if (document.fullscreenElement) { - btn.textContent = 'Salir Pantalla Completa'; + btn.textContent = 'Salir Pantalla Completa' } else { - btn.textContent = 'Pantalla Completa'; + btn.textContent = 'Pantalla Completa' } } -}); +}) diff --git a/resumen.php b/resumen.php index b2d08d7..45ae080 100644 --- a/resumen.php +++ b/resumen.php @@ -1021,11 +1021,7 @@ if (p.estatus === 'Completado' && p.trimestreCompletado === trimestreActual) { completedContainer.append(crearTarjetaProyecto(p, true)); } else if (p.estatus === 'En proceso') { - // Solo se muestra en el resumen si no ha pagado mantenimiento en este trimestre - console.log("[ResumenUI] Proyecto:", p.nombreProyecto, "estatus:", p.estatus, "mantoPagadoEnTrimestre:", p.mantenimientoPagadoEnTrimestre, "trimestreActual:", trimestreActual); - if (p.mantenimientoPagadoEnTrimestre !== trimestreActual) { - activeContainer.append(crearTarjetaProyecto(p, false)); - } + activeContainer.append(crearTarjetaProyecto(p, false)); } }); @@ -1073,21 +1069,32 @@ const completadoClass = esCompletado ? 'completado' : ''; const quincena = parseInt($('#etQuincena').val()) || 1; + const trimestreActual = Math.floor((quincena - 1) / 6) + 1; const esFinTrimestre = (quincena % 6 === 0); + const yaResolvioManto = (proyecto.mantenimiento !== 'N/A' && proyecto.mantenimientoPagadoEnTrimestre === trimestreActual); let actionButtonsHtml = ''; - if (!esCompletado && esFinTrimestre) { + if (!esCompletado && esFinTrimestre && proyecto.dificultad !== 'Incidencia' && proyecto.mantenimiento !== 'N/A') { const showPay = proyecto.mantenimiento !== 'N/A'; - const buttonManto = showPay ? - `` : ''; - const penalizacionFormateada = formatCurrency(proyecto.penalizacion || 0); - const buttonDesechar = ``; + + let buttonManto = ''; + let buttonPenalizar = ''; + + if (yaResolvioManto) { + buttonManto = showPay ? + `` : ''; + buttonPenalizar = ``; + } else { + buttonManto = showPay ? + `` : ''; + buttonPenalizar = ``; + } actionButtonsHtml = `
${buttonManto} - ${buttonDesechar} + ${buttonPenalizar}
`; } @@ -1105,7 +1112,7 @@ } return ` -
+
${proyecto.nombreProyecto.toUpperCase()}
@@ -1423,7 +1430,7 @@ guardaSesion(); } } - } else if (accionQuincenal === 'Descartar un proyecto (se va al limbo con todo y activos)') { + } else if (accionQuincenal === 'Descartar un proyecto') { const proyectosEnProceso = proyectos.filter(p => p.estatus === 'En proceso'); if (proyectosEnProceso.length === 0) { alert('No hay proyectos en proceso para descartar.'); @@ -1433,11 +1440,16 @@ let dialogContent = $('

Selecciona el proyecto a descartar:

'); let projectList = $('
'); proyectosEnProceso.forEach((p) => { + let labelText = p.nombreProyecto; + if (p.dificultad === 'Incidencia') { + const shortDesc = p.descripcion.length > 35 ? p.descripcion.substring(0, 35) + '...' : p.descripcion; + labelText = `${p.nombreProyecto} (${shortDesc})`; + } projectList.append( `
` ); @@ -1477,6 +1489,74 @@ $(this).dialog('destroy').remove(); }, }); + } else if (accionQuincenal === 'Omitir un mantenimiento') { + const esFinTrimestre = (quincenaActual % 6 === 0); + const trimestreActual = Math.floor((quincenaActual - 1) / 6) + 1; + if (!esFinTrimestre) { + alert('Esta Habilidad Especial solo se puede utilizar en el cierre de un trimestre (quincenas 6, 12, 18 y 24).'); + return; + } + const proyectosPendientes = proyectos.filter(p => + p.estatus === 'En proceso' && + p.mantenimiento !== 'N/A' && + p.mantenimientoPagadoEnTrimestre !== trimestreActual + ); + + if (proyectosPendientes.length === 0) { + alert('No hay proyectos activos con mantenimiento pendiente en este trimestre.'); + return; + } + + let dialogContent = $('

Selecciona el proyecto al que deseas omitir el costo de mantenimiento:

'); + let projectList = $(''); + proyectosPendientes.forEach((p) => { + projectList.append( + `
+ + +
` + ); + }); + dialogContent.append(projectList); + + dialogContent.dialog({ + modal: true, + title: 'Omitir Mantenimiento - Logística y Sistemas', + width: 450, + buttons: { + "Omitir Costo": function() { + const selectedProjectId = $('input[name="proyectoAOmitir"]:checked').val(); + if (!selectedProjectId) { + alert('Por favor, selecciona un proyecto.'); + return; + } + const proyectoAOmitir = proyectos.find(p => p.id == selectedProjectId); + if (proyectoAOmitir) { + proyectoAOmitir.mantenimientoPagadoEnTrimestre = trimestreActual; + setArrayValue(elArreglo, 'accionEspecialLastUsed', quincenaActual); + actualizarResumenUI(); + actualizarTarjetaDepto('LogisticaYSistemas'); + var audio = new Audio('./Microwave_bell.wav'); + audio.play(); + alert(`¡El mantenimiento del proyecto "${proyectoAOmitir.nombreProyecto}" ha sido omitido con éxito sin costo!`); + if (typeof guardaSesion === 'function') { + guardaSesion(); + } else if (typeof guardarDatosEnServidor === 'function') { + guardarDatosEnServidor(); + } + } + $(this).dialog('close'); + }, + "Cancelar": function() { + $(this).dialog('close'); + } + }, + close: function() { + $(this).dialog('destroy').remove(); + } + }); } else if (accionQuincenal === 'Ordenar los próximos 5 proyectos') { alert('Esta habilidad especial solo se puede utilizar desde el tablero de juego.'); return; @@ -1539,11 +1619,35 @@ const recT = parseInt(findArrayValue(deptoArr, 'recursoTiempo')) || 0; const recP = parseInt(findArrayValue(deptoArr, 'recursoPersonal')) || 0; const recC = parseInt(findArrayValue(deptoArr, 'recursoCapital')) || 0; + + // Get department skills discounts + const habTiempo = findArrayValue(deptoArr, 'habilidadTiempo'); + const habPersonal = findArrayValue(deptoArr, 'habilidadPersonal'); + const habCapital = findArrayValue(deptoArr, 'habilidadCapital'); + + const discountT = (habTiempo && habTiempo !== 0) ? parseInt(findArrayValue(arreglosCapacitaciones[habTiempo], 'beneficio')) || 0 : 0; + const discountP = (habPersonal && habPersonal !== 0) ? parseInt(findArrayValue(arreglosCapacitaciones[habPersonal], 'beneficio')) || 0 : 0; + const discountC = (habCapital && habCapital !== 0) ? parseInt(findArrayValue(arreglosCapacitaciones[habCapital], 'beneficio')) || 0 : 0; + + const finalCostT = Math.max(0, cost.t + discountT); + const finalCostP = Math.max(0, cost.p + discountP); + const finalCostC = Math.max(0, cost.c + discountC); + console.log("[PagarManto] Recursos depto actual:", { recT, recP, recC }); + console.log("[PagarManto] Descuentos:", { + discountT, + discountP, + discountC + }); + console.log("[PagarManto] Costo final con descuento:", { + finalCostT, + finalCostP, + finalCostC + }); // Verificar si LogisticaYSistemas tiene comprada y disponible su habilidad especial let logisticaHabilidadEspecialDisponible = false; @@ -1602,7 +1706,7 @@ }, "Pagar Normal (Con costo)": function() { $(this).dialog('close'); - ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena); + ejecutarPagoNormal(proyecto, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, finalCostT, finalCostP, finalCostC); }, "Cancelar": function() { $(this).dialog('close'); @@ -1610,26 +1714,28 @@ } }); } else { - ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena); + ejecutarPagoNormal(proyecto, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, finalCostT, finalCostP, finalCostC); } } - function ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena) { - if (recT < cost.t || recP < cost.p || recC < cost.c) { + function ejecutarPagoNormal(proyecto, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, finalCostT, finalCostP, finalCostC) { + if (recT < finalCostT || recP < finalCostP || recC < finalCostC) { alert(`El departamento seleccionado (${deptoNombre}) NO tiene suficientes recursos para pagar el mantenimiento del proyecto "${proyecto.nombreProyecto}".\n` + - `Costo requerido: Tiempo: ${cost.t}, Personal: ${cost.p}, Capital: ${cost.c}\n` + + `Costo requerido (con descuento): ${finalCostT}T ${finalCostP}P ${finalCostC}C\n` + `Recursos actuales: Tiempo: ${recT}, Personal: ${recP}, Capital: ${recC}`); return; } - const confirmMessage = `¿Estás seguro de que deseas pagar el mantenimiento de ${proyecto.mantenimiento} para el proyecto "${proyecto.nombreProyecto}" desde el departamento ${deptoNombre}?`; + const confirmMessage = `¿Estás seguro de que deseas pagar el mantenimiento para el proyecto "${proyecto.nombreProyecto}" desde el departamento ${deptoNombre}?
` + + `Costo original: ${proyecto.mantenimiento}
` + + `Costo final con descuento aplicado: ${finalCostT}T ${finalCostP}P ${finalCostC}C`; confirm(confirmMessage, function(confirmed) { if (confirmed) { // Deduct resources - setArrayValue(deptoArr, 'recursoTiempo', recT - cost.t); - setArrayValue(deptoArr, 'recursoPersonal', recP - cost.p); - setArrayValue(deptoArr, 'recursoCapital', recC - cost.c); + setArrayValue(deptoArr, 'recursoTiempo', recT - finalCostT); + setArrayValue(deptoArr, 'recursoPersonal', recP - finalCostP); + setArrayValue(deptoArr, 'recursoCapital', recC - finalCostC); // Mark project maintenance as paid in the current trimester proyecto.mantenimientoPagadoEnTrimestre = trimestreActual; @@ -1655,7 +1761,7 @@ }, 450); } - function desecharProyecto(projectId) { + function penalizarProyecto(projectId) { const proyecto = proyectos.find(p => p.id == projectId); if (!proyecto) { alert('No se encontró el proyecto.'); @@ -1686,41 +1792,40 @@ } if (operacionesHabilidadEspecialDisponible) { - const dialogMsg = `El departamento de Operaciones tiene disponible la Habilidad Especial para descartar un proyecto sin costo.

` + - `¿Deseas usar la Habilidad Especial para desechar el proyecto "${proyecto.nombreProyecto}" sin pagar la penalización,
` + - `o prefieres realizar un desecho normal pagando la penalización de ${penalizacionFormateada}?`; + const dialogMsg = `El departamento de Operaciones tiene disponible la Habilidad Especial para exentar de penalización a un proyecto.

` + + `¿Deseas usar la Habilidad Especial para el proyecto "${proyecto.nombreProyecto}" sin pagar la penalización,
` + + `o prefieres pagar la penalización de ${penalizacionFormateada} de manera normal?`; $('
') .html(dialogMsg) .dialog({ modal: true, - title: 'Desechar Proyecto - Operaciones', + title: 'Penalizar Proyecto - Operaciones', width: 480, buttons: { "Usar Habilidad (Sin costo)": function() { $(this).dialog('close'); - // Mark project as discarded - proyecto.estatus = 'descartado'; + // Mantiene el estatus 'En proceso' pero marca el mantenimiento resuelto en este trimestre + proyecto.mantenimientoPagadoEnTrimestre = trimestreActual; - // Update skill cooldown + // Cooldown de la habilidad setArrayValue(elArregloOperaciones, 'accionEspecialLastUsed', quincena); - // Save and update UI actualizarResumenUI(); - actualizarTarjetaDepto('Operaciones'); // Refresca la tarjeta del depto en la UI + actualizarTarjetaDepto('Operaciones'); var audio = new Audio('./Microwave_bell.wav'); audio.play(); - alert(`El proyecto "${proyecto.nombreProyecto}" ha sido desechado sin costo utilizando la Habilidad Especial de Operaciones.`); + alert(`El proyecto "${proyecto.nombreProyecto}" ha sido exentado de la penalización utilizando la Habilidad Especial de Operaciones.`); if (typeof guardarDatosEnServidor === 'function') { guardarDatosEnServidor(); } }, - "Desechar Normal (Con costo)": function() { + "Pagar Penalización (Con costo)": function() { $(this).dialog('close'); - ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual); + ejecutarPenalizacionNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual); }, "Cancelar": function() { $(this).dialog('close'); @@ -1728,46 +1833,43 @@ } }); } else { - ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual); + ejecutarPenalizacionNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual); } } - function ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual) { - // Validar que el acumulado general acumulado hasta el trimestre actual sea suficiente + function ejecutarPenalizacionNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual) { let acumuladoDisponible = 0; for (let t = 1; t <= trimestreActual; t++) { acumuladoDisponible += (arregloGeneral['trimestre' + t] || 0); } if (acumuladoDisponible < penalizacionVal) { - alert(`No puedes desechar el proyecto "${proyecto.nombreProyecto}" porque no hay acumulado general suficiente.\n` + + alert(`No puedes penalizar el proyecto "${proyecto.nombreProyecto}" porque no hay acumulado general suficiente.\n` + `Penalización requerida: ${penalizacionFormateada}\n` + `Acumulado general disponible: ${formatCurrency(acumuladoDisponible)}`); return; } - const confirmMessage = `¿Estás seguro de que deseas desechar el proyecto "${proyecto.nombreProyecto}"?
` + + const confirmMessage = `¿Estás seguro de que quieres pagar la penalización del proyecto "${proyecto.nombreProyecto}"?
` + `Se aplicará una penalización de ${penalizacionFormateada} del acumulado general.`; confirm(confirmMessage, function(confirmed) { if (confirmed) { - // Subtract from current trimester's earnings const trimestreKey = 'trimestre' + trimestreActual; if (typeof arregloGeneral[trimestreKey] === 'undefined') { arregloGeneral[trimestreKey] = 0; } arregloGeneral[trimestreKey] -= penalizacionVal; - // Mark project as discarded - proyecto.estatus = 'descartado'; + // Mantiene el estatus 'En proceso' pero marca el mantenimiento resuelto en este trimestre + proyecto.mantenimientoPagadoEnTrimestre = trimestreActual; - // Save and update UI actualizarResumenUI(); var audio = new Audio('./Microwave_bell.wav'); audio.play(); - alert(`El proyecto "${proyecto.nombreProyecto}" ha sido desechado. Se aplicó una penalización de ${penalizacionFormateada}.`); + alert(`El proyecto "${proyecto.nombreProyecto}" ha sido penalizado. Se aplicó una penalización de ${penalizacionFormateada}.`); if (typeof guardarDatosEnServidor === 'function') { guardarDatosEnServidor(); @@ -1776,15 +1878,15 @@ }, 450); } - // Delegación de eventos para los botones de pagar y desechar + // Delegación de eventos para los botones de pagar y penalizar $(document).on('click', '.btn-pagar-mantenimiento', function() { const id = $(this).data('id'); pagarMantenimientoProyecto(id); }); - $(document).on('click', '.btn-desechar-proyecto', function() { + $(document).on('click', '.btn-penalizar-proyecto', function() { const id = $(this).data('id'); - desecharProyecto(id); + penalizarProyecto(id); }); // El listener para el click en .departamentos ya está en jsCode.js y funcionará ahora