mirror of
https://github.com/cheveguerra/Colaborando.git
synced 2026-08-18 16:36:39 +00:00
* **Nuevo botón de Pantalla Completa:** Integrado en los encabezados de la pantalla de Resumen y el Tablero mediante la API de Fullscreen de HTML5, actualizando su texto de forma reactiva a eventos del navegador.
* **Alineación de Departamentos:** Se fijó la altura (38px) de la celda de habilidad especial en el tablero y se restauró el tamaño de letra original (14px) con un line-height controlado (1.2) para evitar desfases de altura cuando el texto ocupa dos líneas sin perder legibilidad.
This commit is contained in:
@@ -4,3 +4,7 @@
|
||||
- El asistente de IA tiene permitido leer cualquier archivo y ejecutar comandos de lectura/diagnóstico sin necesidad de confirmación previa en el chat.
|
||||
- El asistente **NUNCA** debe crear, modificar o eliminar ningún archivo (tanto dentro como fuera del espacio de trabajo) ni ejecutar comandos que modifiquen el sistema sin la autorización previa y explícita del usuario en el chat.
|
||||
- Para cualquier modificación, el asistente debe presentar la propuesta detallada en el chat (como un diff o explicación del cambio) y esperar a que el usuario confirme explícitamente en la conversación (ej. "procede", "aplica", "ejecuta") antes de proceder.
|
||||
|
||||
2. **Persistencia de Planes y Tareas en el Proyecto**:
|
||||
- Para evitar pérdidas de contexto al cambiar o reiniciar sesiones de chat, el asistente siempre debe replicar y guardar copias de sus archivos de planificación, tareas y bitácoras (`implementation_plan.md`, `task.md`, `walkthrough.md`) en la carpeta `doc/` ubicada en la raíz del proyecto.
|
||||
- Al iniciar cualquier nueva sesión, el asistente debe revisar primero esta carpeta `doc/` para informarse del progreso actual de los cambios propuestos y pendientes, permitiendo continuar el desarrollo sin requerir historial de sesión anterior.
|
||||
|
||||
Vendored
+1
-1
@@ -13,7 +13,7 @@
|
||||
"passphrase": null,
|
||||
"agent": null,
|
||||
"allow": [],
|
||||
"ignore": ["\\.vscode", "\\.git", "\\.DS_Store"],
|
||||
"ignore": ["\\.vscode", "\\.git", "\\.DS_Store", "doc"],
|
||||
"generatedFiles": {
|
||||
"extensionsToInclude": [""],
|
||||
"path": ""
|
||||
|
||||
Vendored
+2
-1
@@ -10,7 +10,8 @@
|
||||
"concurrency": 5,
|
||||
"ignore": [
|
||||
".git/**/*",
|
||||
".vscode/**/*"
|
||||
".vscode/**/*",
|
||||
"doc/**/*"
|
||||
],
|
||||
"include": [],
|
||||
"targets": [
|
||||
|
||||
Vendored
+7
-1
@@ -9,5 +9,11 @@
|
||||
"uploadOnSave": true,
|
||||
"passive": true,
|
||||
"useTempFile": false,
|
||||
"openSsh": false
|
||||
"openSsh": false,
|
||||
"ignore": [
|
||||
".vscode",
|
||||
".git",
|
||||
".DS_Store",
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
|
||||
+11
-8
@@ -280,7 +280,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;">.</td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;">.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -294,7 +294,10 @@
|
||||
<img id="logo" src="img/logoColaborando-tablero.png">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: 0 15px;">
|
||||
<div id="nombreSesion" style="font-weight: bold; font-size: 16px; color: #555;"></div>
|
||||
<a href="resumen.php?n=<?php echo htmlspecialchars($_GET['n'] ?? $_GET['nombre'] ?? ''); ?>" class="nav-button">Ir al Resumen</a>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<button id="btnFullscreen" onclick="toggleFullscreen()" class="nav-button" style="border: none; cursor: pointer;">Pantalla Completa</button>
|
||||
<a href="resumen.php?n=<?php echo htmlspecialchars($_GET['n'] ?? $_GET['nombre'] ?? ''); ?>" class="nav-button">Ir al Resumen</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -520,7 +523,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -597,7 +600,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -706,7 +709,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -815,7 +818,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -924,7 +927,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1033,7 +1036,7 @@
|
||||
<td colspan="10" style="text-align:center;background-color:gray;color:white;height:20px;">Habilidad Especial / Quincenal</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:19px;"> </td>
|
||||
<td colspan="10" id="accionEspecialGde" style="text-align:center;background-color:silver;color:black;height:38px;line-height:1.2;vertical-align:middle;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Documentación General y Bitácora de Cambios - Co.Laborando
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Regla de Mantenimiento:** Para evitar el consumo excesivo de tokens, este archivo debe mantenerse conciso, con un tamaño objetivo de **entre 150 y 250 líneas** en total. Al realizar nuevos cambios, se debe resumir o actualizar la información en lugar de añadir bloques redundantes de texto.
|
||||
|
||||
---
|
||||
|
||||
## 🎮 Concepto General del Proyecto
|
||||
**Co.Laborando** es una aplicación interactiva de simulación y ludoteca empresarial. Los jugadores administran múltiples departamentos con recursos limitados (Tiempo, Personal, Capital) para completar proyectos en un tablero a lo largo de un ciclo temporal de **24 quincenas (4 trimestres)**.
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Arquitectura de Archivos Principal
|
||||
* **[colaborando2.php](file:///c:/CHV/ludotecaLocal/Colaborando/colaborando2.php) / [colaborando.php](file:///c:/CHV/ludotecaLocal/Colaborando/colaborando.php):** Vistas del tablero principal del juego, donde se colocan y arrastran los proyectos y recursos.
|
||||
* **[resumen.php](file:///c:/CHV/ludotecaLocal/Colaborando/resumen.php):** Pantalla del panel de control central (dashboard) que muestra métricas acumuladas, estado de departamentos, listado de activos y control de habilidades.
|
||||
* **[jsCode.js](file:///c:/CHV/ludotecaLocal/Colaborando/jsCode.js):** Lógica del lado del cliente que maneja las interacciones del tablero, transiciones de turnos y renders dinámicos.
|
||||
* **[manejoDeSesiones.js](file:///c:/CHV/ludotecaLocal/Colaborando/manejoDeSesiones.js) / [manejoDeSesiones.php](file:///c:/CHV/ludotecaLocal/Colaborando/manejoDeSesiones.php):** Sistema de persistencia que guarda y carga el estado del juego (en archivos `.json` en la raíz del proyecto).
|
||||
* **[sesiones.php](file:///c:/CHV/ludotecaLocal/Colaborando/sesiones.php):** Panel de administración para crear, inicializar o eliminar las sesiones guardadas.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Mecánicas de Juego Clave
|
||||
|
||||
### 1. Departamentos y Recursos
|
||||
Existen 6 departamentos: *Marketing y Ventas, Finanzas, Investigación y Desarrollo, Logística y Sistemas, Operaciones*, y *Recursos Humanos*. Cada uno posee recursos de **Tiempo, Personal** y **Capital**, representados dinámicamente en el tablero y resumen.
|
||||
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
* **Ordenar proyectos:** Permite reordenar la cola de los próximos 5 proyectos en el tablero.
|
||||
|
||||
### 5. Contabilización de Activos
|
||||
Los activos producidos por proyectos completados se dividen en 6 tipos: *Personal Calificado, Analistas, Flujo de Efectivo, Crédito e Inversión, Tecnología* y *Transporte y Maquinaria*. Se calculan dinámicamente y se clasifican en:
|
||||
* **Producidos:** Total de activos creados por proyectos completados.
|
||||
* **Recuperados:** Activos que fueron arrastrados con éxito de vuelta a los departamentos.
|
||||
* **Perdidos:** Activos que no se recuperaron a tiempo antes de cambiar de trimestre.
|
||||
|
||||
---
|
||||
|
||||
## 💾 Sistema de Sesiones
|
||||
* Las sesiones de juego se guardan localmente en archivos JSON en la raíz del proyecto.
|
||||
* Para evitar que estos archivos ensucien el repositorio Git, el archivo [.gitignore](file:///c:/CHV/ludotecaLocal/Colaborando/.gitignore) ignora todos los archivos `/*.json` de la raíz.
|
||||
* Se utiliza una técnica de *cache-busting* con el parámetro `_t` y la cabecera `cache: 'no-store'` para evitar cargas AJAX obsoletas entre pantallas.
|
||||
|
||||
---
|
||||
|
||||
## 📈 Bitácora Histórica de Cambios (Changelog)
|
||||
|
||||
* **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).
|
||||
* Bypass de caché del navegador (`cache: 'no-store'`) para la carga de datos del juego.
|
||||
* Añadida regla `/*.json` en `.gitignore` para limpiar el repositorio de archivos de juego locales.
|
||||
* **Nuevo botón de Pantalla Completa:** Integrado en los encabezados de la pantalla de Resumen y el Tablero mediante la API de Fullscreen de HTML5, actualizando su texto de forma reactiva a eventos del navegador.
|
||||
* **Alineación de Departamentos:** Se fijó la altura (38px) de la celda de habilidad especial en el tablero y se restauró el tamaño de letra original (14px) con un line-height controlado (1.2) para evitar desfases de altura cuando el texto ocupa dos líneas sin perder legibilidad.
|
||||
* **11/Jun/2026:**
|
||||
* Creación del módulo de contabilización de activos (Producidos, Recuperados, Perdidos) calculado dinámicamente e integrado en la esquina inferior izquierda de resumen.
|
||||
* Ajustes y correcciones en la habilidad especial de reordenamiento de proyectos.
|
||||
* **10/Jun/2026:**
|
||||
* Implementación de la habilidad para previsualizar y ordenar los siguientes 5 proyectos del tablero.
|
||||
* Añadido botón de habilidades especiales y opción de descarte de proyectos básicos.
|
||||
@@ -0,0 +1,85 @@
|
||||
# Gestión de Mantenimiento y Penalización de Proyectos Activos (Fin de Trimestre)
|
||||
|
||||
Este plan revisado describe las modificaciones necesarias en el código para permitir que los usuarios paguen el mantenimiento de proyectos activos o los desechen (pagando la penalización correspondiente) **únicamente en las quincenas de fin de trimestre (6, 12, 18 y 24)**.
|
||||
|
||||
## Revisión del Usuario Requerida
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Lógica de Visibilidad del Proyecto:**
|
||||
> - Cuando un proyecto activo paga su mantenimiento en el fin de un trimestre (por ejemplo, en la quincena 6, que es el fin del Trimestre 1), el proyecto se marca con `mantenimientoPagadoEnTrimestre = 1`.
|
||||
> - Durante el resto del trimestre actual (mientras sigan en la quincena 6), el proyecto **se ocultará tanto del resumen como del tablero**.
|
||||
> - En cuanto la quincena avance al siguiente trimestre (quincena 7, Trimestre 2), el proyecto **reaparecerá automáticamente en el tablero** para continuar trabajando en él.
|
||||
>
|
||||
> **Lógica de Desecho:**
|
||||
> - Si se decide no pagar el mantenimiento, el usuario puede desechar el proyecto pagando la penalización (que se resta del acumulado general del trimestre actual). El estatus del proyecto cambiará a `'descartado'` y desaparecerá permanentemente.
|
||||
|
||||
## Cambios Propuestos
|
||||
|
||||
### Componente Frontend y Lógica del Juego
|
||||
|
||||
---
|
||||
|
||||
#### [MODIFY] [resumen.php](file:///c:/CHV/ludotecaLocal/Colaborando/resumen.php)
|
||||
|
||||
1. **Modificar `crearTarjetaProyecto`**:
|
||||
- Agregar botones de acción **solo si** el proyecto está activo (`!esCompletado`), tiene costo de mantenimiento (`proyecto.mantenimiento !== 'N/A'`) y la quincena actual es un fin de trimestre (`quincena % 6 === 0`).
|
||||
- Botón **Pagar Manto**: Llama a `pagarMantenimientoProyecto(proyecto.id)`.
|
||||
- Botón **Desechar**: Llama a `desecharProyecto(proyecto.id)`.
|
||||
|
||||
2. **Actualizar `actualizarResumenUI`**:
|
||||
- Filtrar los proyectos activos para mostrar solo aquellos cuyo mantenimiento **no ha sido pagado** en el trimestre actual:
|
||||
`proyecto.mantenimientoPagadoEnTrimestre !== trimestreActual`
|
||||
- Ocultar los proyectos que tengan mantenimiento `'N/A'` de la lista de pagos pendientes, o mostrarlos sin botones de acción (ya que no requieren pago).
|
||||
|
||||
3. **Funciones de Control**:
|
||||
- `parseMantenimiento(mantenimientoStr)`: Parsea el formato `'1T 1P 1C'` en un objeto `{ t, p, c }`.
|
||||
- `pagarMantenimientoProyecto(projectId)`:
|
||||
- Valida la selección de departamento y que este cuente con los recursos necesarios.
|
||||
- Deduce los recursos y actualiza la tarjeta del departamento.
|
||||
- Guarda el trimestre actual en el proyecto: `proyecto.mantenimientoPagadoEnTrimestre = trimestreActual`.
|
||||
- Guarda la sesión y refresca la UI del resumen.
|
||||
- `desecharProyecto(projectId)`:
|
||||
- Solicita confirmación al usuario.
|
||||
- Deduce la penalización de `arregloGeneral['trimestre' + trimestreActual]`.
|
||||
- Cambia el estatus del proyecto a `'descartado'`.
|
||||
- Guarda la sesión y refresca la UI del resumen.
|
||||
|
||||
4. **Event Listeners**:
|
||||
- Registrar delegación de clics con jQuery para `.btn-pagar-mantenimiento` y `.btn-desechar-proyecto`.
|
||||
|
||||
---
|
||||
|
||||
#### [MODIFY] [jsCode.js](file:///c:/CHV/ludotecaLocal/Colaborando/jsCode.js)
|
||||
|
||||
1. **Definir `limpiaProyectoGrande()`**:
|
||||
- Función helper para limpiar visualmente el contenedor del proyecto grande en el tablero cuando este está en espera del pago de mantenimiento.
|
||||
|
||||
2. **Modificar `continuamos()`**:
|
||||
- Calcular el trimestre actual de la quincena cargada:
|
||||
`const trimestreActual = Math.floor((parseInt(arregloGeneral.quincena) - 1) / 6) + 1;`
|
||||
- Modificar el filtro de proyectos para el tablero (tablero chico):
|
||||
Un proyecto se muestra solo si está en proceso y no se ha pagado su mantenimiento en el trimestre actual (o no requiere mantenimiento):
|
||||
```javascript
|
||||
const proyectosEnTablero = proyectos.filter(
|
||||
(p) =>
|
||||
p.estatus === 'En proceso' &&
|
||||
(!proyectoGde || p.id !== proyectoGde.id) &&
|
||||
(p.mantenimiento === 'N/A' || p.mantenimientoPagadoEnTrimestre !== trimestreActual)
|
||||
)
|
||||
```
|
||||
- Modificar la asignación de `proyectoGde`:
|
||||
Si el proyecto grande actual está en proceso pero ya pagó su mantenimiento para el siguiente trimestre, no se muestra en el tablero actual. Se llama a `limpiaProyectoGrande()`.
|
||||
|
||||
## Plan de Verificación
|
||||
|
||||
### Verificación Manual
|
||||
1. Iniciar o cargar una sesión en la quincena 6 (fin del Trimestre 1).
|
||||
2. Ir a **Resumen** y verificar que los proyectos activos que requieren mantenimiento muestren los botones "Pagar Manto" y "Desechar".
|
||||
3. Seleccionar un departamento y hacer clic en **Pagar Manto**:
|
||||
- Verificar que se deduzcan los recursos del departamento.
|
||||
- Verificar que el proyecto desaparezca de la lista en el resumen.
|
||||
- Ir al tablero y comprobar que **no aparece** en la quincena 6.
|
||||
- Avanzar a la quincena 7 (Trimestre 2) y comprobar que el proyecto **reaparece en el tablero**.
|
||||
4. Volver a la quincena 6, seleccionar otro proyecto activo y hacer clic en **Desechar**:
|
||||
- Confirmar y verificar que la penalización se reste del acumulado general de T1.
|
||||
- Verificar que el proyecto cambie su estatus a `'descartado'` en el JSON de sesión y no vuelva a aparecer en ningún lado.
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
- [x] Implement resource subtraction, maintenance payment, and project discarding in `resumen.php`
|
||||
- [x] Add `parseMantenimiento` helper function
|
||||
- [x] Add `pagarMantenimientoProyecto` function
|
||||
- [x] Add `desecharProyecto` function with accumulated general check
|
||||
- [x] Modify `crearTarjetaProyecto` to show action buttons on active projects at end of trimester
|
||||
- [x] Filter paid projects in `actualizarResumenUI`
|
||||
- [x] Bind event delegation for the buttons
|
||||
- [x] Implement board rendering updates in `jsCode.js`
|
||||
- [x] Define `limpiaProyectoGrande` function
|
||||
- [x] Filter `proyectosEnTablero` in `continuamos` based on `mantenimientoPagadoEnTrimestre`
|
||||
- [x] Adjust project grande loading in `continuamos` to respect maintenance payment
|
||||
- [x] Verify functionality
|
||||
- [x] Test paying maintenance
|
||||
- [x] Test discarding project with check for sufficient accumulated funds
|
||||
- [x] Test quincena transitions
|
||||
@@ -0,0 +1,44 @@
|
||||
# Resumen de Cambios: Pago de Mantenimiento y Desecho de Proyectos Activos
|
||||
|
||||
Se ha implementado completamente 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`).
|
||||
|
||||
### 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.
|
||||
|
||||
## Cómo Realizar las Pruebas (Verificación)
|
||||
|
||||
1. **Escenario de Pago de Mantenimiento:**
|
||||
- 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.
|
||||
@@ -504,7 +504,9 @@ function llenaDepartamentoChico(depto) {
|
||||
$('#' + deptoActual + ' #capitalHA').text(
|
||||
findArrayValue(elArreglo, 'habilidadCapital')
|
||||
)
|
||||
// $("#accionEspecialGde").text(findArrayValue(elArreglo, "accionEspecialQuincenal"));
|
||||
$('#' + deptoActual + ' #accionEspecialGde').text(
|
||||
findArrayValue(elArreglo, 'accionEspecialQuincenal') || ''
|
||||
)
|
||||
console.log(`[llenaDepartamentoChico] <- FIN para depto: '${depto}'`)
|
||||
}
|
||||
|
||||
@@ -543,6 +545,27 @@ function limpiaProyectoChico(elProyecto) {
|
||||
}
|
||||
}
|
||||
|
||||
function limpiaProyectoGrande() {
|
||||
console.log('Limpia proyecto grande')
|
||||
$('#TablaProyectoGde').removeAttr('num')
|
||||
$('#TablaProyectoGde').removeAttr('estatus')
|
||||
$('#TablaProyectoGde').css('background-color', '')
|
||||
$('#nombreProyectoGde').text('')
|
||||
$('#descripcionProyectoGde').text('')
|
||||
$('#TablaProyectoGde #puntosGanados').text('')
|
||||
$('#puntosPerdidos').text('')
|
||||
$('#activoReqProyectoNom1').attr('class', '').text('')
|
||||
$('#activoReqProyectoNom2').attr('class', '').text('')
|
||||
$('#activoReqProyectoNom3').attr('class', '').text('')
|
||||
$('#activoReqProyectoCantX1').text('0')
|
||||
$('#activoReqProyectoCantX2').text('0')
|
||||
$('#activoReqProyectoCantX3').text('0')
|
||||
$('#activoReqProyectoCant1').attr('class', '').text('')
|
||||
$('#activoReqProyectoCant2').attr('class', '').text('')
|
||||
$('#activoReqProyectoCant3').attr('class', '').text('')
|
||||
$('#mantoGde').text('MANTENIMIENTO')
|
||||
}
|
||||
|
||||
function llenaProyectoChico(proyectoNum) {
|
||||
console.log('Llenando proyectos! ', proyectoNum)
|
||||
const colores = [
|
||||
@@ -3403,6 +3426,9 @@ function continuamos() {
|
||||
})
|
||||
// --- FIN DEL PARCHE ---
|
||||
|
||||
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
|
||||
console.log('ID de proyecto grande guardado:', proyectoGdeActual)
|
||||
@@ -3429,7 +3455,9 @@ 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.estatus === 'En proceso' &&
|
||||
(!proyectoGde || p.id !== proyectoGde.id) &&
|
||||
(p.mantenimiento === 'N/A' || p.mantenimientoPagadoEnTrimestre !== trimestreActual)
|
||||
)
|
||||
|
||||
console.log('Proyectos para mostrar en tablero chico:', proyectosEnTablero)
|
||||
@@ -3477,7 +3505,11 @@ function continuamos() {
|
||||
|
||||
// 5. Llenar el proyecto grande.
|
||||
if (proyectoGde) {
|
||||
llenaProyectoGde(proyectoGde.id)
|
||||
if (proyectoGde.mantenimiento !== 'N/A' && proyectoGde.mantenimientoPagadoEnTrimestre === trimestreActual) {
|
||||
limpiaProyectoGrande()
|
||||
} else {
|
||||
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)
|
||||
@@ -3674,12 +3706,13 @@ function toggleColor(button) {
|
||||
|
||||
$(function () {
|
||||
// Sobrescribir la función alert
|
||||
window.alert = function (message) {
|
||||
window.alert = function (message, customWidth) {
|
||||
$('<div></div>')
|
||||
.html(message)
|
||||
.dialog({
|
||||
modal: true,
|
||||
title: 'Atención',
|
||||
width: customWidth || 450,
|
||||
buttons: {
|
||||
Ok: function () {
|
||||
$(this).dialog('close')
|
||||
|
||||
+27
-2
@@ -30,9 +30,11 @@ function cargarDatosDesdeServidor() {
|
||||
console.log('nombreArchivo:', nombreArchivo)
|
||||
let url = 'manejoDeSesiones.php'
|
||||
if (nombreArchivo != '') {
|
||||
url += '?nombre=' + encodeURIComponent(nombreArchivo)
|
||||
url += '?nombre=' + encodeURIComponent(nombreArchivo) + '&_t=' + new Date().getTime()
|
||||
} else {
|
||||
url += '?_t=' + new Date().getTime()
|
||||
}
|
||||
fetch(url)
|
||||
fetch(url, { cache: 'no-store' })
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
datosCarga = data
|
||||
@@ -173,3 +175,26 @@ document.addEventListener('DOMContentLoaded', cargarDatosDesdeServidor)
|
||||
window.addEventListener('beforeunload', function () {
|
||||
guardarDatosEnServidor()
|
||||
})
|
||||
|
||||
// Función global para alternar pantalla completa
|
||||
function toggleFullscreen() {
|
||||
if (!document.fullscreenElement) {
|
||||
document.documentElement.requestFullscreen().catch((err) => {
|
||||
console.error(`Error al intentar activar pantalla completa: ${err.message}`);
|
||||
});
|
||||
} else {
|
||||
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');
|
||||
if (btn) {
|
||||
if (document.fullscreenElement) {
|
||||
btn.textContent = 'Salir Pantalla Completa';
|
||||
} else {
|
||||
btn.textContent = 'Pantalla Completa';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
+354
-14
@@ -256,7 +256,10 @@
|
||||
<img id="logo" src="img/logoColaborando-tablero.png">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; padding: 5px 10px;">
|
||||
<div id="nombreSesion" style="font-weight: bold; font-size: 16px; color: #555;"></div>
|
||||
<a href="colaborando2.php?n=<?php echo htmlspecialchars($_GET['n'] ?? $_GET['nombre'] ?? ''); ?>" class="nav-button">Ir al Tablero</a>
|
||||
<div style="display: flex; gap: 5px;">
|
||||
<button id="btnFullscreen" onclick="toggleFullscreen()" class="nav-button" style="border: none; cursor: pointer;">Pantalla Completa</button>
|
||||
<a href="colaborando2.php?n=<?php echo htmlspecialchars($_GET['n'] ?? $_GET['nombre'] ?? ''); ?>" class="nav-button">Ir al Tablero</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
@@ -778,10 +781,14 @@
|
||||
|
||||
if (!deptoArr || !deptoCard.length) return;
|
||||
|
||||
// Actualizar recursos
|
||||
deptoCard.find('#tiempoCh').text(findArrayValue(deptoArr, 'recursoTiempo'));
|
||||
deptoCard.find('#personalCh').text(findArrayValue(deptoArr, 'recursoPersonal'));
|
||||
deptoCard.find('#capitalCh').text(findArrayValue(deptoArr, 'recursoCapital'));
|
||||
// Actualizar recursos (con selector flexible para soportar el deptoActual con IDs renombrados)
|
||||
const tiempoElem = deptoCard.find('#tiempoCh').length ? deptoCard.find('#tiempoCh') : deptoCard.find('#recursoDispTiempoGde');
|
||||
const personalElem = deptoCard.find('#personalCh').length ? deptoCard.find('#personalCh') : deptoCard.find('#recursoDispPersonalGde');
|
||||
const capitalElem = deptoCard.find('#capitalCh').length ? deptoCard.find('#capitalCh') : deptoCard.find('#recursoDispCapitalGde');
|
||||
|
||||
tiempoElem.text(findArrayValue(deptoArr, 'recursoTiempo'));
|
||||
personalElem.text(findArrayValue(deptoArr, 'recursoPersonal'));
|
||||
capitalElem.text(findArrayValue(deptoArr, 'recursoCapital'));
|
||||
|
||||
// Actualizar activos
|
||||
deptoCard.find('#activoCh1').text(findArrayValue(deptoArr, 'activo1'));
|
||||
@@ -1014,7 +1021,11 @@
|
||||
if (p.estatus === 'Completado' && p.trimestreCompletado === trimestreActual) {
|
||||
completedContainer.append(crearTarjetaProyecto(p, true));
|
||||
} else if (p.estatus === 'En proceso') {
|
||||
activeContainer.append(crearTarjetaProyecto(p, false));
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1061,15 +1072,53 @@
|
||||
|
||||
const completadoClass = esCompletado ? 'completado' : '';
|
||||
|
||||
return `
|
||||
<div class="project-card ${completadoClass}" style="flex-basis: 48%;">
|
||||
<div class="project-header">${proyecto.nombreProyecto.toUpperCase()}</div>
|
||||
<div class="project-body">
|
||||
<i>${proyecto.descripcion}</i>
|
||||
<div class="project-assets-req">${activosReqHtml}</div>
|
||||
<div class="project-assets-asig">${activosAsigHtml}</div>
|
||||
const quincena = parseInt($('#etQuincena').val()) || 1;
|
||||
const esFinTrimestre = (quincena % 6 === 0);
|
||||
|
||||
let actionButtonsHtml = '';
|
||||
if (!esCompletado && esFinTrimestre) {
|
||||
const showPay = proyecto.mantenimiento !== 'N/A';
|
||||
const buttonManto = showPay ?
|
||||
`<button class="nav-button btn-pagar-mantenimiento" data-id="${proyecto.id}" style="background-color: #28a745; border: none; font-size: 11px; padding: 5px 8px; cursor: pointer; flex: 1;">Pagar Manto</button>` : '';
|
||||
|
||||
const penalizacionFormateada = formatCurrency(proyecto.penalizacion || 0);
|
||||
const buttonDesechar = `<button class="nav-button btn-desechar-proyecto" data-id="${proyecto.id}" style="background-color: #dc3545; border: none; font-size: 11px; padding: 5px 8px; cursor: pointer; flex: 1;">Desechar (${penalizacionFormateada})</button>`;
|
||||
|
||||
actionButtonsHtml = `
|
||||
<div class="project-actions" style="display: flex; gap: 8px; margin-top: 10px; width: 100%;">
|
||||
${buttonManto}
|
||||
${buttonDesechar}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
let infoAdicionalHtml = '';
|
||||
if (!esCompletado) {
|
||||
const penalizacionFormateada = formatCurrency(proyecto.penalizacion || 0);
|
||||
const potencialVal = proyecto.potencial || 'N/A';
|
||||
infoAdicionalHtml = `
|
||||
<div class="project-info-adicional" style="font-size: 1.2em; color: #444; margin-top: 8px; border-top: 1px dashed #ccc; padding-top: 5px; text-align: left; display: flex; justify-content: space-between;">
|
||||
<span><b>Potencial:</b> ${potencialVal}</span>
|
||||
<span><b>Penalización:</b> ${penalizacionFormateada}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="project-card ${completadoClass}" style="flex-basis: 48%; display: flex; flex-direction: column; justify-content: space-between; min-height: 180px; box-sizing: border-box; padding: 10px;">
|
||||
<div>
|
||||
<div class="project-header" style="font-weight: bold; margin-bottom: 5px; text-align: center; border-bottom: 1px solid gray; padding-bottom: 4px;">${proyecto.nombreProyecto.toUpperCase()}</div>
|
||||
<div class="project-body" style="padding: 5px; text-align: center;">
|
||||
<i style="font-size: 0.9em; color: #555;">${proyecto.descripcion}</i>
|
||||
<div class="project-assets-req" style="margin-top: 5px; display: flex; justify-content: center; gap: 2px;">${activosReqHtml}</div>
|
||||
<div class="project-assets-asig" style="margin-top: 5px; display: flex; justify-content: center; gap: 2px;">${activosAsigHtml}</div>
|
||||
${infoAdicionalHtml}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="project-footer" style="font-size: 0.9em; margin-top: 8px; font-weight: bold; border-top: 1px solid #ddd; padding-top: 5px; text-align: center;">MANTENIMIENTO: ${proyecto.mantenimiento}</div>
|
||||
${actionButtonsHtml}
|
||||
</div>
|
||||
<div class="project-footer">MANTENIMIENTO: ${proyecto.mantenimiento}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -1447,6 +1496,297 @@
|
||||
}
|
||||
});
|
||||
|
||||
function parseMantenimiento(mantenimientoStr) {
|
||||
let t = 0,
|
||||
p = 0,
|
||||
c = 0;
|
||||
if (mantenimientoStr && mantenimientoStr !== 'N/A') {
|
||||
const matchesT = mantenimientoStr.match(/(\d+)T/i);
|
||||
const matchesP = mantenimientoStr.match(/(\d+)P/i);
|
||||
const matchesC = mantenimientoStr.match(/(\d+)C/i);
|
||||
if (matchesT) t = parseInt(matchesT[1]);
|
||||
if (matchesP) p = parseInt(matchesP[1]);
|
||||
if (matchesC) c = parseInt(matchesC[1]);
|
||||
}
|
||||
return {
|
||||
t,
|
||||
p,
|
||||
c
|
||||
};
|
||||
}
|
||||
|
||||
function pagarMantenimientoProyecto(projectId) {
|
||||
console.log("[PagarManto] Iniciando pago para proyecto ID:", projectId);
|
||||
if (typeof deptoActual === 'undefined' || !deptoActual) {
|
||||
alert('Por favor, selecciona primero un departamento haciendo clic en él.');
|
||||
return;
|
||||
}
|
||||
|
||||
const proyecto = proyectos.find(p => p.id == projectId);
|
||||
if (!proyecto) {
|
||||
alert('No se encontró el proyecto.');
|
||||
console.error("[PagarManto] Proyecto no encontrado con ID:", projectId);
|
||||
return;
|
||||
}
|
||||
console.log("[PagarManto] Proyecto encontrado:", proyecto.nombreProyecto);
|
||||
|
||||
// Parse maintenance cost
|
||||
const cost = parseMantenimiento(proyecto.mantenimiento);
|
||||
console.log("[PagarManto] Costo parsed:", cost);
|
||||
|
||||
// Get department resources
|
||||
const deptoArr = arreglosDeptos['arr' + deptoActual];
|
||||
const recT = parseInt(findArrayValue(deptoArr, 'recursoTiempo')) || 0;
|
||||
const recP = parseInt(findArrayValue(deptoArr, 'recursoPersonal')) || 0;
|
||||
const recC = parseInt(findArrayValue(deptoArr, 'recursoCapital')) || 0;
|
||||
console.log("[PagarManto] Recursos depto actual:", {
|
||||
recT,
|
||||
recP,
|
||||
recC
|
||||
});
|
||||
|
||||
// Verificar si LogisticaYSistemas tiene comprada y disponible su habilidad especial
|
||||
let logisticaHabilidadEspecialDisponible = false;
|
||||
let elArregloLogistica = null;
|
||||
const quincena = parseInt($('#etQuincena').val()) || 1;
|
||||
const trimestreActual = Math.floor((quincena - 1) / 6) + 1;
|
||||
|
||||
if (typeof deptoActual !== 'undefined' && deptoActual === 'LogisticaYSistemas') {
|
||||
elArregloLogistica = arreglosDeptos['arrLogisticaYSistemas'];
|
||||
if (elArregloLogistica) {
|
||||
const accionQuincenal = findArrayValue(elArregloLogistica, 'accionEspecialQuincenal');
|
||||
if (accionQuincenal && accionQuincenal !== '') {
|
||||
const lastUsed = parseInt(findArrayValue(elArregloLogistica, 'accionEspecialLastUsed')) || 0;
|
||||
const periodicidad = parseInt(findArrayValue(elArregloLogistica, 'accionEspecialPeriodicidad')) || 2;
|
||||
if (lastUsed === 0 || quincena >= lastUsed + periodicidad) {
|
||||
logisticaHabilidadEspecialDisponible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const deptoNombre = findArrayValue(deptoArr, 'nombre');
|
||||
|
||||
if (logisticaHabilidadEspecialDisponible) {
|
||||
const dialogMsg = `El departamento de Logística y Sistemas tiene disponible la Habilidad Especial para omitir un mantenimiento sin costo.<br><br>` +
|
||||
`¿Deseas usar la Habilidad Especial para omitir el mantenimiento del proyecto "${proyecto.nombreProyecto}" <b>sin gastar recursos</b>,<br>` +
|
||||
`o prefieres realizar un pago normal gastando recursos (${proyecto.mantenimiento})?`;
|
||||
|
||||
$('<div></div>')
|
||||
.html(dialogMsg)
|
||||
.dialog({
|
||||
modal: true,
|
||||
title: 'Pagar Mantenimiento - Logística y Sistemas',
|
||||
width: 480,
|
||||
buttons: {
|
||||
"Usar Habilidad (Sin costo)": function() {
|
||||
$(this).dialog('close');
|
||||
// Mark project maintenance as paid in the current trimester
|
||||
proyecto.mantenimientoPagadoEnTrimestre = trimestreActual;
|
||||
|
||||
// Update skill cooldown
|
||||
setArrayValue(elArregloLogistica, 'accionEspecialLastUsed', quincena);
|
||||
|
||||
// Save and update UI
|
||||
actualizarResumenUI();
|
||||
actualizarTarjetaDepto('LogisticaYSistemas'); // Refresca la tarjeta en la UI
|
||||
|
||||
var audio = new Audio('./Microwave_bell.wav');
|
||||
audio.play();
|
||||
|
||||
alert(`Se ha omitido el mantenimiento del proyecto "${proyecto.nombreProyecto}" sin costo utilizando la Habilidad Especial de Logística y Sistemas.`);
|
||||
|
||||
if (typeof guardarDatosEnServidor === 'function') {
|
||||
guardarDatosEnServidor();
|
||||
}
|
||||
},
|
||||
"Pagar Normal (Con costo)": function() {
|
||||
$(this).dialog('close');
|
||||
ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena);
|
||||
},
|
||||
"Cancelar": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena);
|
||||
}
|
||||
}
|
||||
|
||||
function ejecutarPagoNormal(proyecto, cost, deptoArr, recT, recP, recC, deptoNombre, trimestreActual, quincena) {
|
||||
if (recT < cost.t || recP < cost.p || recC < cost.c) {
|
||||
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` +
|
||||
`Recursos actuales: Tiempo: ${recT}, Personal: ${recP}, Capital: ${recC}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmMessage = `¿Estás seguro de que deseas pagar el mantenimiento de <b>${proyecto.mantenimiento}</b> para el proyecto "${proyecto.nombreProyecto}" desde el departamento <b>${deptoNombre}</b>?`;
|
||||
|
||||
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);
|
||||
|
||||
// Mark project maintenance as paid in the current trimester
|
||||
proyecto.mantenimientoPagadoEnTrimestre = trimestreActual;
|
||||
console.log("[PagarManto] Asignado mantenimientoPagadoEnTrimestre a:", trimestreActual);
|
||||
|
||||
// Save and update UI
|
||||
actualizarTarjetaDepto(deptoActual);
|
||||
console.log("[PagarManto] Tarjeta departamento actualizada.");
|
||||
|
||||
actualizarResumenUI();
|
||||
console.log("[PagarManto] UI de resumen actualizada.");
|
||||
|
||||
var audio = new Audio('./Microwave_bell.wav');
|
||||
audio.play();
|
||||
|
||||
alert(`Mantenimiento pagado con éxito para el proyecto "${proyecto.nombreProyecto}" desde el departamento ${deptoNombre}. El proyecto continuará en proceso en el siguiente trimestre.`);
|
||||
|
||||
if (typeof guardarDatosEnServidor === 'function') {
|
||||
console.log("[PagarManto] Guardando sesión en el servidor...");
|
||||
guardarDatosEnServidor();
|
||||
}
|
||||
}
|
||||
}, 450);
|
||||
}
|
||||
|
||||
function desecharProyecto(projectId) {
|
||||
const proyecto = proyectos.find(p => p.id == projectId);
|
||||
if (!proyecto) {
|
||||
alert('No se encontró el proyecto.');
|
||||
return;
|
||||
}
|
||||
|
||||
const penalizacionVal = parseInt(proyecto.penalizacion) || 0;
|
||||
const penalizacionFormateada = formatCurrency(penalizacionVal);
|
||||
|
||||
const quincena = parseInt($('#etQuincena').val()) || 1;
|
||||
const trimestreActual = Math.floor((quincena - 1) / 6) + 1;
|
||||
|
||||
// Verificar si Operaciones tiene comprada y disponible su habilidad especial
|
||||
let operacionesHabilidadEspecialDisponible = false;
|
||||
let elArregloOperaciones = null;
|
||||
if (typeof deptoActual !== 'undefined' && deptoActual === 'Operaciones') {
|
||||
elArregloOperaciones = arreglosDeptos['arrOperaciones'];
|
||||
if (elArregloOperaciones) {
|
||||
const accionQuincenal = findArrayValue(elArregloOperaciones, 'accionEspecialQuincenal');
|
||||
if (accionQuincenal && accionQuincenal !== '') {
|
||||
const lastUsed = parseInt(findArrayValue(elArregloOperaciones, 'accionEspecialLastUsed')) || 0;
|
||||
const periodicidad = parseInt(findArrayValue(elArregloOperaciones, 'accionEspecialPeriodicidad')) || 2;
|
||||
if (lastUsed === 0 || quincena >= lastUsed + periodicidad) {
|
||||
operacionesHabilidadEspecialDisponible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operacionesHabilidadEspecialDisponible) {
|
||||
const dialogMsg = `El departamento de Operaciones tiene disponible la Habilidad Especial para descartar un proyecto sin costo.<br><br>` +
|
||||
`¿Deseas usar la Habilidad Especial para desechar el proyecto "${proyecto.nombreProyecto}" <b>sin pagar la penalización</b>,<br>` +
|
||||
`o prefieres realizar un desecho normal pagando la penalización de <b>${penalizacionFormateada}</b>?`;
|
||||
|
||||
$('<div></div>')
|
||||
.html(dialogMsg)
|
||||
.dialog({
|
||||
modal: true,
|
||||
title: 'Desechar Proyecto - Operaciones',
|
||||
width: 480,
|
||||
buttons: {
|
||||
"Usar Habilidad (Sin costo)": function() {
|
||||
$(this).dialog('close');
|
||||
// Mark project as discarded
|
||||
proyecto.estatus = 'descartado';
|
||||
|
||||
// Update skill cooldown
|
||||
setArrayValue(elArregloOperaciones, 'accionEspecialLastUsed', quincena);
|
||||
|
||||
// Save and update UI
|
||||
actualizarResumenUI();
|
||||
actualizarTarjetaDepto('Operaciones'); // Refresca la tarjeta del depto en la UI
|
||||
|
||||
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.`);
|
||||
|
||||
if (typeof guardarDatosEnServidor === 'function') {
|
||||
guardarDatosEnServidor();
|
||||
}
|
||||
},
|
||||
"Desechar Normal (Con costo)": function() {
|
||||
$(this).dialog('close');
|
||||
ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual);
|
||||
},
|
||||
"Cancelar": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual);
|
||||
}
|
||||
}
|
||||
|
||||
function ejecutarDesechoNormal(proyecto, penalizacionVal, penalizacionFormateada, trimestreActual) {
|
||||
// Validar que el acumulado general acumulado hasta el trimestre actual sea suficiente
|
||||
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` +
|
||||
`Penalización requerida: ${penalizacionFormateada}\n` +
|
||||
`Acumulado general disponible: ${formatCurrency(acumuladoDisponible)}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const confirmMessage = `¿Estás seguro de que deseas desechar el proyecto "${proyecto.nombreProyecto}"?<br>` +
|
||||
`Se aplicará una penalización de <b>${penalizacionFormateada}</b> 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';
|
||||
|
||||
// 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}.`);
|
||||
|
||||
if (typeof guardarDatosEnServidor === 'function') {
|
||||
guardarDatosEnServidor();
|
||||
}
|
||||
}
|
||||
}, 450);
|
||||
}
|
||||
|
||||
// Delegación de eventos para los botones de pagar y desechar
|
||||
$(document).on('click', '.btn-pagar-mantenimiento', function() {
|
||||
const id = $(this).data('id');
|
||||
pagarMantenimientoProyecto(id);
|
||||
});
|
||||
|
||||
$(document).on('click', '.btn-desechar-proyecto', function() {
|
||||
const id = $(this).data('id');
|
||||
desecharProyecto(id);
|
||||
});
|
||||
|
||||
// El listener para el click en .departamentos ya está en jsCode.js y funcionará ahora
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
const fs = require('fs');
|
||||
let content = fs.readFileSync('colaborando.php', 'utf8');
|
||||
|
||||
[3, 4, 5, 6].forEach(num => {
|
||||
let oldStr = ` {
|
||||
name: 'accionEspecialQuincenal',
|
||||
value: "Generar ${num} activo sin costo"
|
||||
}
|
||||
];`;
|
||||
let newStr = ` {
|
||||
name: 'accionEspecialQuincenal',
|
||||
value: "Generar ${num} activo sin costo"
|
||||
},
|
||||
{
|
||||
name: 'accionEspecialLastUsed',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: 'accionEspecialPeriodicidad',
|
||||
value: 2
|
||||
}
|
||||
];`;
|
||||
content = content.replace(oldStr, newStr);
|
||||
});
|
||||
|
||||
fs.writeFileSync('colaborando.php', content);
|
||||
Reference in New Issue
Block a user