Valida y consolida las horas al 27-jul: 41.58 h trazables desde el CSV

Las horas quedan validadas una por una contra evidencia fechada y el Excel
deja de tener cifras escritas a mano: se generan desde Seguimiento-horas.csv
y el script aborta si el detalle no cuadra con el total.

Correcciones de fondo:
- El Excel reportaba 17 h de Etapa 1 contra 16 h en el CSV (override manual).
- Comas sin escapar en el CSV ocultaban 1.00 h del 19-jul al parseo.
- El 10-jul estaba mal etiquetado: la mayor parte fue pulido del prototipo
  (E0-05), no el entregable de cierre (E0-06). Mismo total, etiquetas reales.
- Se incorporan 3.50 h no cobradas con evidencia: diseño del plan de Etapa 1
  (2.00 h) y preparación de las sesiones del 22 y 24-jul (1.50 h).
- Ajustes a la baja de Johann en horas reconstruidas: análisis del Discovery
  1.92→1.00 h, documentación de cobranza 1.50→0.75 h, guion 0.75→0.45 h.
  Las duraciones con transcript no se tocaron. Etapa 0 vuelve al rango 18–22 h.

Presentación del avance:
- Se reporta 75 % de Etapa 1 = 6 de 8 entregables cerrados, en lugar del 82 %
  ponderado anterior, que no distinguía trabajo hecho de trabajo bloqueado.
- Capa de escritura al 40 % (diseño, ADR-001 y modelo listos; falta el
  BindWriteClient y los shapes de los POST) y Jira al 90 % (conectividad
  resuelta el 27-jul; falta qué estatus dispara qué, sujeto a la definición
  de Balam). Modelo de facturas al 85 % con horas propias: ya no aparece
  avanzado con cero horas.
- Las 7 h que acumulaba "Demostración semanal" se reparten a las filas
  técnicas que les corresponden; esa fila se queda con gestión (1.75 h).

Nuevo: Avance-Balam-2026-07-27.xlsx, versión simple para Erika, derivada del
Excel interno para que ambos no puedan contradecirse.

Bitácora #58: Erika confirma que el Excel de horas es el insumo de
FACTURACIÓN, corrige su lectura de la capa de escritura al 100 %, y vuelve a
pedir la propuesta ajustada por Jira (pendiente desde el 22-jul). La sesión
del flujo de facturación no queda agendada: Balam la revisa internamente.
This commit is contained in:
JohannVelazquez
2026-07-28 22:21:04 -06:00
parent bee2d02f50
commit 820b8d41c8
8 changed files with 507 additions and 108 deletions
+36
View File
@@ -1067,6 +1067,42 @@ Cierre de la sesión (~0.5 h real). **B6 conforme al plan:** `ITenantOwned` en l
---
## 58 · Jul 2728, 2026 · WhatsApp Erika ↔ Johann · avance de Etapa 1 entregado, Excel de horas para FACTURACIÓN y Jira aún sin licencia ⭐
> Continuación de [#57](REGISTRO.md). Registrado a partir de capturas de pantalla del hilo (4 imágenes). Cubre el envío del avance del 27-jul y los pedidos de Erika del 27 (tarde) y 28 (mañana).
**27-jul, mañana — avance de Etapa 1 entregado por mensaje:** Erika pidió los avances de Etapa 1 (📷 captura del plan, 7:11 am). Johann preguntó si ya existe **un Jira para el seguimiento de este proyecto** —es decir, dónde llevar sus actividades y horas, no la instancia a integrar— (7:14 am) → **respuesta de Erika (7:54 am): "aún estamos viendo lo de alguna licencia... pero estamos viendo una segunda opción y no Jira precisamente".** Johann ofreció trabajar en un Excel compartido; Erika contestó que le comentó a Pedro que **pudiera ser un Drive para subir la documentación, pero están en espera de la validación** (8:57 am).
> ⚠️ **Precisión importante:** este intercambio es sobre la **herramienta de gestión del proyecto** (dónde se registran actividades y horas de Johann), NO sobre la integración técnica. El Jira a integrar es la **instancia productiva de TI que administra Pedro** —bandeja FAC, token PAF a 1 año, API read+write confirmada ([#56](REGISTRO.md))— y ese no está en duda. Consecuencia práctica: **mientras no haya herramienta de gestión, el Excel de horas de Johann ES el sistema de seguimiento del proyecto**, lo que explica la insistencia de Erika en el desglose por etapa.
Johann envió el **avance por actividad en texto** (8:12 am), con 👍 de Erika y "gracias" (8:58 am):
> ✅ Sincronización de clientes — hecho y verificado · ✅ Sincronización de facturas/cotizaciones — hecho, 1,494 facturas cuadran · ✅ Modelo + migraciones + datos de prueba — hecho · ⏸️ Capa de escritura — en la junta del viernes comentaron que iban a definir el flujo de facturación; en cuanto quede, la implemento (Balam) · ⏳ Config. Azure (+ staging) — espera el acceso a Azure de Pedro/Noé (Balam) · ⏳ CI/CD + secretos — depende de Azure (Balam)
**27-jul, tarde — la fila de escritura y la sesión del proceso:** Erika preguntó (3:35 pm) si la capa de escritura *"es la que está pendiente de lo que se mencionó el viernes de que validarían el flujo"* → Johann confirmó. Erika: **"es que lo tengo al 100%"** (3:40 pm) → **Johann corrigió: "lo volví a marcar como pendiente porque se iba a validar el proceso"** y preguntó cuándo podrían tener la junta revisando el proceso validado (3:443:45 pm). Erika: le comentó a Arturo, y como **Ara sale de viaje**, mañana en la oficina ve cuándo **revisarlo internamente y después pasarlo con Johann**; queda en avisar (3:49 pm). ⚠️ **La sesión del 28-jul no quedó confirmada — se movió a revisión interna de Balam primero.**
**27-jul, 4:59 pm — pedido formal de horas:** *"johan un favor, me puedes pasar en un excel tus horas que llevas de cada etapa por favor"***Johann envió `Avance-Balam-2026-07-27.xlsx` a las 6:45 pm** (versión simplificada). Johann ofreció además pasar un Excel para las siguientes etapas; Erika (7:57 pm): *"Y las ya completas más que nada para ver cuántas son"*.
**28-jul, mañana — el propósito del Excel y dos pendientes:**
1. **(8:36 am) ⭐ "es para llevar el conteo de horas de cada etapa sobre todo para la FACTURACIÓN correspondiente de la misma."** → El Excel de horas es el insumo de facturación, no solo seguimiento.
2. **(9:12 am) "johann adicional, ¿pasaste la propuesta con lo adicional de JIRA que no estaba contemplado?"** → Johann (10:58 am): **"Aún no la comparto, te la paso a la brevedad."** ⚠️ Es el compromiso que viene arrastrándose desde el 22-jul ([#57](REGISTRO.md)).
3. **(9:27 am)** Sobre Azure: Johann preguntó si el acceso lo iba a entregar Noé o Pedro → Erika: **"Sip"** + *"deja pregunto"* (11:01 am). Johann pidió contexto de qué se requiere específicamente de Azure (11:19 am).
**Lecturas clave:**
> - **El Excel de horas es documento de facturación** (dicho por Erika, 28-jul 8:36 am). Cambia su naturaleza: ya no es reporte de avance, es sustento de cobro. Refuerza que las 41.58 h estén validadas y trazables.
> - **Erika creía la capa de escritura al 100%** y Johann la corrigió a pendiente. Buena decisión: si se hubiera dejado al 100%, la definición del proceso habría reabierto una actividad cerrada. Valida el criterio de reportar 40% y no más.
> - **Sin herramienta de gestión para el proyecto** (licencia en revisión; Erika evalúa una alternativa a Jira para ese fin). **No afecta la integración técnica** —esa va contra la instancia de TI de Pedro, ya disponible—, pero sí significa que **el Excel de horas de Johann es el registro oficial de seguimiento** y el insumo de facturación. Mantenerlo trazable y al día no es opcional.
> - **La propuesta ajustada por Jira sigue sin enviarse** (comprometida el 22-jul, re-preguntada el 28-jul). Es el pendiente comercial más viejo del hilo y ahora Erika lo pide por segunda vez.
> - **La sesión del flujo de facturación no está agendada:** Balam la revisa internamente primero (Ara de viaje). El desbloqueo de B7 se corre de fecha.
**Pendientes que deja el hilo:**
- [ ] ⚠️🔥 Johann — **enviar la propuesta/adenda ajustada por la integración Jira→BIND** (comprometida 22-jul, re-preguntada 28-jul 9:12 am). Estimación ya comunicada: ~10 h ([#51](REGISTRO.md)).
- [ ] Johann — **enviar el Excel de horas de las etapas siguientes** (2, 3) que Erika pidió el 27-jul 6:46 pm ("las ya completas más que nada para ver cuántas son").
- [ ] Balam/Erika — **avisar fecha de la sesión del flujo de facturación** tras su revisión interna. Desbloquea B7.
- [ ] Balam/Erika — **definir la herramienta de gestión del proyecto** (licencia en revisión). Mientras no exista, el Excel de Johann es el registro oficial.
- [ ] Balam/Pedro/Noé — **entregar el acceso a Azure**; Erika iba a preguntar (28-jul 11:01 am). Johann pidió el contexto de lo que se requiere.
---
## Resumen ejecutivo del hilo (para contexto rápido)
### Datos duros confirmados por Balam
Binary file not shown.
+22 -12
View File
@@ -2,7 +2,7 @@
**Fecha:** 27-jul-2026 (corte de los lunes, formato pedido por Erika: entregable + actividad + horas por etapa)
**Etapa:** Plataforma base y sincronización con BIND
**Rango estimado contractual:** 3239 h · **Horas registradas de Etapa 1:** 17.0 h
**Rango estimado contractual:** 3239 h · **Horas registradas de Etapa 1:** 19.75 h (total del proyecto: 41.58 h)
**Adjunto:** `Plan-actividades-avance-2026-07-27.xlsx`
> Documento interno de Johann. El mensaje para Erika va abajo; el resto es sustento propio (no se comparte).
@@ -17,7 +17,7 @@
>
> Lo que sigue pendiente es, sobre todo, la **capa de escritura (cotización→factura), que dejé en pausa a propósito hasta que definan el flujo de facturación en la sesión del martes**, ya que de ahí dependen las reglas. También quedan por cerrar el afinado de datos de prueba y la parte de Azure/CI-CD, que depende de los accesos de su lado.
>
> En horas voy en **17 h de Etapa 1** (rango estimado 3239 h). Con la key de Jira que nos pasó Pedro hoy y las definiciones del martes, arranco la integración con Jira y la capa de escritura. Cualquier duda quedo al pendiente. 🙌
> En horas voy en **19.75 h de Etapa 1** (rango estimado 3239 h), con **6 de los 8 entregables de la etapa ya terminados**. Con la key de Jira que nos pasó Pedro hoy y las definiciones del martes, arranco la integración con Jira y la capa de escritura. Cualquier duda quedo al pendiente. 🙌
*(Nota: el ajuste de la propuesta y el conteo de horas formal van por separado; este mensaje es solo el avance de Etapa 1.)*
@@ -37,23 +37,33 @@
- 26/26 pruebas unitarias verdes.
### En construcción / en pausa
- **Capa de escritura controlada (cotización→factura)** — *entregable 4*. 🔴 **En pausa deliberada** hasta la definición del flujo de facturación (sesión martes 28-jul con Arturo/Araceli): de ahí salen las reglas de prefactura, PPD/PUE, alta de cliente y qué estatus de Jira dispara qué. El andamiaje (pipeline dry-run→confirm, flags apagados, `WriteOperations`) está diseñado; se implementa contra las reglas ya cerradas.
- **Capa de escritura controlada (cotización→factura)** — *entregable 4*. **Al 40 %: diseño y modelo listos, implementación en pausa.** Ya hecho: entidad `WriteOperation` con el pipeline `Draft→DryRun→Confirmed` migrada, policy `PuedeOperarEscritura`, ADR-001, el diseño del `BindWriteClient` con flags apagados por default y la regla PPD/PUE (informada por el hallazgo de que 1,374/1,374 facturas del histórico son PUE). Falta el `BindWriteClient`, el pipeline implementado, los shapes reales de los POST y las pruebas. 🔴 **Pausa deliberada** hasta la definición del flujo de facturación (sesión martes 28-jul con Arturo/Araceli): de ahí salen las reglas de prefactura, PPD/PUE, alta de cliente y qué estatus de Jira dispara qué.
- **Scheduler + backfill** (sync programado cada 15 min) — el sync ya funciona en manual; falta automatizarlo.
- **Datos de prueba (seeder) + runbook** — *entregable 8*: migraciones ✅, seeder ficticio pendiente.
- **Datos de prueba (seeder) + runbook** — *entregable 8*, **al 85 %**: modelo central de facturas con el `InvoiceStatusMapper` (13 pruebas) ✅, migraciones ✅; falta el seeder de datos ficticios y el runbook.
- **Suite de pruebas de flujos críticos** (integración) — pendiente.
### Dependencias externas (lado Balam)
- **Definición del flujo de facturación/prefacturación** — sesión martes 28-jul (Erika coordina). Desbloquea la capa de escritura.
- **Correo del flujo de facturación de Jira** (Erika lo envió 22-jul) — a incorporar.
- **Token de Jira (PAF)** recibido el 27-jul + docs de Atlassian; falta confirmar límites de consumo (Pedro investiga). Bandeja: **Facturación (FAC)**.
- **Alcance Jira → cotización BIND al 90 %:** conectividad resuelta el 27-jul (token PAF con vigencia a 1 año, API confirmada de lectura **y** escritura, bandeja **Facturación (FAC)** identificada, límites de consumo aclarados por correo de Pedro: sin tope mensual, 3 límites de velocidad, autorregulación por headers `X-RateLimit-*`). Falta el 10 %: **qué estatus de Jira dispara qué** (amarrado a la definición del 28-jul) y validar si basta escuchar FAC o hay que rastrear los procesos que nacen en RH/Administración General y caen ahí.
- **Acceso a Azure + CI/CD** (Pedro/Noé) — condiciona el despliegue.
## Criterio de medición
- **Horas de Etapa 1:** 17.0 h registradas de un rango de 3239 h (**~4453 % del esfuerzo estimado**).
- **Entregables contractuales:** **6 de 8 terminados** (1, 2, 3, 5, 6, 7); el 8 parcial (migraciones sí, seeder no); el 4 (escritura) en pausa por definición de Balam.
- Se reporta por hora + entregable, no un porcentaje global único, para no dar una cifra engañosa. El Excel muestra ~82 % ponderado por actividad porque el trabajo restante (escritura, seeder, scheduler) es de menor peso que el núcleo ya hecho, pero **la escritura está bloqueada por la definición pendiente de Balam**, no por avance de desarrollo.
- **Entregables contractuales:** **6 de 8 terminados** (1, 2, 3, 5, 6, 7). Los dos restantes van parciales y su avance se muestra en su propia fila del Excel, no promediado en el encabezado: el **8 al 85 %** (migraciones sí, seeder no) y el **4 al 40 %** (escritura: diseño y modelo listos, implementación en pausa por definición de Balam). → **El Excel reporta 75 % de Etapa 1**, contando solo entregables cerrados, que es lo verificable.
- **Horas de Etapa 1:** 19.75 h de un rango de 3239 h (**~5162 % del esfuerzo estimado**).
- Se reporta por **entregable terminado**, no por promedio ponderado de actividades. El corte anterior mostraba 82 % ponderado, que era optimista e indefendible: no distinguía entre trabajo hecho y trabajo bloqueado. "6 de 8" dice exactamente qué falta y de quién depende.
- La brecha entre 75 % de entregables y ~55 % de horas **no es un error**: refleja que las sesiones de desarrollo asistidas por IA produjeron el núcleo en mucho menos tiempo de reloj que la estimación manual (ver la nota en `Seguimiento-horas.md`).
## Puntos de juicio a confirmar por Johann antes de enviar
1. **Horas 2227 jul:** solo cargué las sesiones documentadas (reglas 22-jul 0.80 h, validación 24-jul 1.05 h como Etapa 0, API Jira 27-jul 0.20 h). Si trabajaste desarrollo adicional en esa ventana, hay que sumarlo.
2. **% de Etapa 1 (82 %):** es el valor ponderado heredado del corte del 21-jul + avance; si prefieres una lectura más conservadora (por horas, ~50 %), lo ajusto.
3. **Tono del mensaje:** el borrador enmarca la capa de escritura como "en pausa por la definición del 28-jul" (pone la pelota de su lado, y es verdad). Si prefieres suavizarlo, lo cambio.
## Horas: estado de la validación (resuelto el 27-jul)
- **41.58 h en total** — Etapa 0: 21.83 h · Etapa 1: 19.75 h.
- **Cero horas pendientes de validar.** 9.13 h con duración documentada (`confirmada`) y 32.45 h reconstruidas y confirmadas por Johann contra evidencia fechada (`validada`).
- Correcciones aplicadas en este corte:
- Se corrigió un error de formato del CSV que ocultaba **1.00 h** del 19-jul (entorno local).
- Se re-etiquetó el 10-jul: la mayor parte eran 6 commits de pulido del prototipo (E0-05), no el entregable de cierre (E0-06). Mismo total, etiquetas correctas.
- Se incorporaron **3.50 h** de trabajo real que no estaba cobrado: diseño del plan de Etapa 1 (2.00 h, `Plan-Etapa1.md`) y preparación de las sesiones del 22 y 24-jul (1.50 h, agenda y guion de validación).
- **Ajustes a la baja** en las horas reconstruidas de Etapa 0: análisis del Discovery de facturación 1.92 → 1.00 h, documentación del de cobranza 1.50 → 0.75 h, guion de validación 0.75 → 0.45 h. Las duraciones de sesión documentadas en transcript no se tocaron.
- Cada celda de horas del Excel se genera desde el CSV y el script **falla** si el detalle no cuadra con el total.
- **Etapa 0 cerró en 21.83 h, dentro del rango contractual de 1822 h.**
## Punto abierto (no bloquea el envío)
- **Tono del mensaje:** el borrador enmarca la capa de escritura como "en pausa por la definición del 28-jul" — pone la pelota de su lado, y es verdad. Si prefieres suavizarlo, se ajusta.
Binary file not shown.
+33 -29
View File
@@ -1,32 +1,36 @@
fecha,semana,etapa,actividad_id,actividad,horas,estado_hora,fuente_evidencia,facturable,notas
2026-07-01,2026-W27,0,E0-01,Sesión de arranque con Noé,1.00,confirmada,bitacora/REGISTRO.md#22,si,"Sesión calendarizada de 7:00 a 8:00 am"
2026-07-01,2026-W27,0,E0-01,Preparación de plan kickoff y materiales,1.00,reconstruida,planeacion/Kickoff-2026-07-01.md,si,"Estimación retrospectiva; validar antes de facturar"
2026-07-06,2026-W28,0,E0-02,Discovery de facturación y envío,1.08,confirmada,bitacora/REGISTRO.md#27,si,"Duración documentada: aproximadamente 1 h 5 min"
2026-07-06,2026-W28,0,E0-02,Preparación y análisis de Discovery de facturación,1.92,reconstruida,bitacora/REGISTRO.md#27,si,"Completa 3.00 h para facturación/envío incluyendo sesión"
2026-07-06,2026-W28,0,E0-03,Coordinación y validación de accesos BIND y marca,1.00,reconstruida,bitacora/REGISTRO.md#28-31,si,"Recepción documentación y salvaguardas"
2026-07-06,2026-W28,0,E0-04,Validación técnica de API BIND,4.50,reconstruida,bind-api-sandbox/VALIDACION-API.md,si,"117 GET análisis y reporte técnico"
2026-07-07,2026-W28,0,E0-02,Discovery de cobranza,1.00,confirmada,bitacora/REGISTRO.md#35,si,"Sesión calendarizada de 7:00 a 8:00 am; sin grabación"
2026-07-07,2026-W28,0,E0-02,Preparación y documentación de Discovery de cobranza,1.50,reconstruida,fuentes/2026-07-07 - Notas - Proceso actual de cobranza (sin grabacion).md,si,"Estimación retrospectiva"
2026-07-08,2026-W28,0,E0-05,Diseño y construcción del prototipo,3.00,reconstruida,prototipo/Prototipo-Etapa0.html,si,"Primera mitad del esfuerzo reconstruido"
2026-07-09,2026-W28,0,E0-05,Ajustes de cobranza navegación y prototipo,3.00,reconstruida,prototipo/Prototipo-Etapa0.html,si,"Segunda mitad del esfuerzo reconstruido"
2026-07-10,2026-W28,0,E0-06,Entregable hallazgos ADRs PDF correo y plan,3.00,reconstruida,prototipo/Correo-prototipo-Etapa0.md,si,"Incluye preparación del entregable y documentación"
2026-07-13,2026-W29,1,E1-01,Backend base autenticación roles y auditoría,2.00,reconstruida,planeacion/Plan-actividades.md,si,"Trabajo local; falta conciliar contra evidencia de código"
2026-07-13,2026-W29,1,E1-02,Coordinación del repositorio GitHub,0.50,reconstruida,bitacora/REGISTRO.md#43,si,"Seguimiento de creación y acceso"
2026-07-14,2026-W29,1,E1-01,Backend base autenticación roles y auditoría,1.50,reconstruida,planeacion/Plan-actividades.md,si,"Trabajo local; completa 3.50 h"
2026-07-14,2026-W29,1,E1-03,Arquitectura multi-tenant,1.00,reconstruida,planeacion/Plan-actividades.md,si,"Diseño inicial tenant_id y RLS"
2026-07-15,2026-W29,1,E1-03,Arquitectura multi-tenant,0.50,reconstruida,planeacion/Plan-actividades.md,si,"Completa 1.50 h"
2026-07-15,2026-W29,1,E1-04,Cliente productivo de API BIND,2.00,reconstruida,bind-api-sandbox/VALIDACION-API.md,si,"Inicio de reintentos OData y manejo de errores"
2026-07-15,2026-W29,1,E1-05,Seguimiento ajuste de calendario y corte de horas,0.50,reconstruida,bitacora/REGISTRO.md#41-45,si,"Actualización de plan y control"
2026-07-16,2026-W29,1,E1-06,Scaffold backend .NET 10 + frontend Angular 21 y push al repo de Balam,2.00,reconstruida,bitacora/REGISTRO.md#46,si,"Commits 220942a..1f7f098; incluye CLAUDE.md del repo; validar duración"
2026-07-16,2026-W29,1,E1-05,Corte de avance Etapa 1 para Erika (Excel + mensaje),1.00,reconstruida,planeacion/Avance-Etapa1-2026-07-16.md,si,"Enviado 8:40 pm por WhatsApp con acuse; validar duración"
2026-07-19,2026-W29,1,E1-06,Preparación de entorno local (clon del repo, SDK .NET 10, secrets, app corriendo),1.00,reconstruida,bitacora/REGISTRO.md,si,"API y frontend verificados en local; 13/13 pruebas verdes; validar duración"
2026-07-19,2026-W29,1,E1-06,Scalar UI para el OpenAPI del backend,0.25,confirmada,bitacora/REGISTRO.md#48,si,"Sesión asistida por IA; /scalar/v1 verificado"
2026-07-19,2026-W29,1,E1-01,B0+B1: Postgres 17 local + modelo de datos + Identity + migración Inicial + seed,1.00,confirmada,bitacora/REGISTRO.md#48,si,"Sesión asistida por IA (noche del domingo); 16 tablas migradas y siembra verificada; tiempo real de sesión"
2026-07-19,2026-W29,1,E1-01,B2: login JWT + policies por rol + bitácora de auditoría,0.50,confirmada,bitacora/REGISTRO.md#49,si,"Sesión asistida por IA; matriz 401/403/200 verificada end-to-end; tiempo real de sesión"
2026-07-01,2026-W27,0,E0-01,Sesión de arranque con Noé,1.00,confirmada,bitacora/REGISTRO.md#22,si,Sesión calendarizada de 7:00 a 8:00 am
2026-07-01,2026-W27,0,E0-01,Preparación de plan kickoff y materiales,1.00,validada,planeacion/Kickoff-2026-07-01.md,si,validada por Johann 27-jul
2026-07-06,2026-W28,0,E0-02,Discovery de facturación y envío,1.08,confirmada,bitacora/REGISTRO.md#27,si,Duración documentada: aproximadamente 1 h 5 min
2026-07-06,2026-W28,0,E0-02,Preparación y análisis de Discovery de facturación,1.00,validada,bitacora/REGISTRO.md#27,si,"Completa 2.08 h con la sesión; ajustada a la baja por Johann 27-jul"
2026-07-06,2026-W28,0,E0-03,Coordinación y validación de accesos BIND y marca,1.00,validada,bitacora/REGISTRO.md#28-31,si,Recepción documentación y salvaguardas; validada por Johann 27-jul
2026-07-06,2026-W28,0,E0-04,Validación técnica de API BIND,4.50,validada,bind-api-sandbox/VALIDACION-API.md,si,117 GET análisis y reporte técnico; validada por Johann 27-jul
2026-07-07,2026-W28,0,E0-02,Discovery de cobranza,1.00,confirmada,bitacora/REGISTRO.md#35,si,Sesión calendarizada de 7:00 a 8:00 am; sin grabación
2026-07-07,2026-W28,0,E0-02,Preparación y documentación de Discovery de cobranza,0.75,validada,fuentes/2026-07-07 - Notas - Proceso actual de cobranza (sin grabacion).md,si,"Sin grabación; notas escritas a mano; ajustada a la baja por Johann 27-jul"
2026-07-08,2026-W28,0,E0-05,Diseño y construcción del prototipo,3.00,validada,prototipo/Prototipo-Etapa0.html,si,Primera mitad del esfuerzo reconstruido; validada por Johann 27-jul
2026-07-09,2026-W28,0,E0-05,Ajustes de cobranza navegación y prototipo,3.00,validada,prototipo/Prototipo-Etapa0.html,si,Segunda mitad del esfuerzo reconstruido; validada por Johann 27-jul
2026-07-10,2026-W28,0,E0-05,"Pulido final del prototipo (bandeja, modal Edo. cuenta, login, capturas)",1.50,validada,prototipo/Prototipo-Etapa0.html,si,"6 commits 00:44-01:52 (b358570..8da11ea) + 9 capturas + logo oficial; validada por Johann 27-jul"
2026-07-10,2026-W28,0,E0-06,Entregable de cierre Etapa 0: PDF hallazgos plan refinado y correo,1.50,validada,prototipo/Correo-prototipo-Etapa0.md,si,PDF generado 10:43; hallazgos y plan refinado; validada por Johann 27-jul
2026-07-13,2026-W29,1,E1-01,Backend base autenticación roles y auditoría,2.00,validada,planeacion/Plan-actividades.md,si,validada por Johann 27-jul
2026-07-13,2026-W29,1,E1-02,Coordinación del repositorio GitHub,0.50,validada,bitacora/REGISTRO.md#43,si,Seguimiento de creación y acceso; validada por Johann 27-jul
2026-07-14,2026-W29,1,E1-01,Backend base autenticación roles y auditoría,1.50,validada,planeacion/Plan-actividades.md,si,Trabajo local; completa 3.50 h; validada por Johann 27-jul
2026-07-14,2026-W29,1,E1-03,Arquitectura multi-tenant,1.00,validada,planeacion/Plan-actividades.md,si,Diseño inicial tenant_id y RLS; validada por Johann 27-jul
2026-07-15,2026-W29,1,E1-03,Arquitectura multi-tenant,0.50,validada,planeacion/Plan-actividades.md,si,Completa 1.50 h; validada por Johann 27-jul
2026-07-15,2026-W29,1,E1-04,Cliente productivo de API BIND,2.00,validada,bind-api-sandbox/VALIDACION-API.md,si,Inicio de reintentos OData y manejo de errores; validada por Johann 27-jul
2026-07-15,2026-W29,1,E1-05,Seguimiento ajuste de calendario y corte de horas,0.50,validada,bitacora/REGISTRO.md#41-45,si,Actualización de plan y control; validada por Johann 27-jul
2026-07-16,2026-W29,1,E1-06,Scaffold backend .NET 10 + frontend Angular 21 y push al repo de Balam,2.00,validada,bitacora/REGISTRO.md#46,si,Commits 220942a..1f7f098; incluye CLAUDE.md del repo; validada por Johann 27-jul
2026-07-16,2026-W29,1,E1-05,Corte de avance Etapa 1 para Erika (Excel + mensaje),1.00,validada,planeacion/Avance-Etapa1-2026-07-16.md,si,Enviado 8:40 pm por WhatsApp con acuse; validada por Johann 27-jul
2026-07-19,2026-W29,1,E1-06,"Preparación de entorno local (clon del repo, SDK .NET 10, secrets, app corriendo)",1.00,validada,bitacora/REGISTRO.md#47,si,API y frontend verificados en local; 13/13 pruebas verdes; validada por Johann 27-jul
2026-07-19,2026-W29,1,E1-08,"Diseño del plan de ejecución de Etapa 1 (bloques B0-B10, ADRs, orden)",2.00,validada,planeacion/Plan-Etapa1.md,si,Arquitectura y decisiones previas a las sesiones de desarrollo; validada por Johann 27-jul
2026-07-19,2026-W29,1,E1-06,Scalar UI para el OpenAPI del backend,0.25,confirmada,bitacora/REGISTRO.md#48,si,Sesión asistida por IA; /scalar/v1 verificado
2026-07-19,2026-W29,1,E1-01,B0+B1: Postgres 17 local + modelo de datos + Identity + migración Inicial + seed,1.00,confirmada,bitacora/REGISTRO.md#48,si,Sesión asistida por IA (noche del domingo); 16 tablas migradas y siembra verificada; tiempo real de sesión
2026-07-19,2026-W29,1,E1-01,B2: login JWT + policies por rol + bitácora de auditoría,0.50,confirmada,bitacora/REGISTRO.md#49,si,Sesión asistida por IA; matriz 401/403/200 verificada end-to-end; tiempo real de sesión
2026-07-19,2026-W29,1,E1-01,B3: sync de clientes contra BIND real + fix de modelos (GUIDs null),0.50,confirmada,bitacora/REGISTRO.md#50,si,"Sesión asistida por IA; 16 clientes sincronizados, idempotencia verificada; tiempo real de sesión"
2026-07-21,2026-W30,1,E1-01,B4: sync de facturas/cotizaciones + estados + cartera por moneda + sync histórico,1.00,confirmada,bitacora/REGISTRO.md#52,si,"Sesión asistida por IA; 1494 facturas y 43 cotizaciones sincronizadas de producción; tiempo real de sesión"
2026-07-21,2026-W30,1,E1-03,B6: RLS real de Postgres por tenant (migración + interceptor + filtros EF),0.50,confirmada,bitacora/REGISTRO.md#53,si,"Sesión asistida por IA; verificación manual en psql; tiempo real de sesión"
2026-07-21,2026-W30,1,E1-05,Cierre de sesión: Excel de avance regenerado + bitácora + control de horas,0.25,confirmada,bitacora/REGISTRO.md#52-53,si,"Sesión asistida por IA; tiempo real de sesión"
2026-07-22,2026-W30,1,E1-05,"Sesión de reglas Etapa 1 con Noé, Arturo y Araceli (alta de clientes, fee, flujo Jira)",0.80,confirmada,bitacora/REGISTRO.md#54,si,"Duración real ~48 min según transcript (7:007:48 am)"
2026-07-21,2026-W30,1,E1-01,B4: sync de facturas/cotizaciones + estados + cartera por moneda + sync histórico,1.00,confirmada,bitacora/REGISTRO.md#52,si,Sesión asistida por IA; 1494 facturas y 43 cotizaciones sincronizadas de producción; tiempo real de sesión
2026-07-21,2026-W30,1,E1-03,B6: RLS real de Postgres por tenant (migración + interceptor + filtros EF),0.50,confirmada,bitacora/REGISTRO.md#53,si,Sesión asistida por IA; verificación manual en psql; tiempo real de sesión
2026-07-21,2026-W30,1,E1-05,Cierre de sesión: Excel de avance regenerado + bitácora + control de horas,0.25,confirmada,bitacora/REGISTRO.md#52-53,si,Sesión asistida por IA; tiempo real de sesión
2026-07-21,2026-W30,1,E1-05,Preparación de la agenda de la sesión de reglas de Etapa 1,0.75,validada,planeacion/Sesion-Etapa1-2026-07-22.md,si,Agenda y preguntas para la sesión del 22-jul; validada por Johann 27-jul
2026-07-22,2026-W30,1,E1-05,"Sesión de reglas Etapa 1 con Noé, Arturo y Araceli (alta de clientes, fee, flujo Jira)",0.80,confirmada,bitacora/REGISTRO.md#54,si,Duración real ~48 min según transcript (7:007:48 am)
2026-07-23,2026-W30,0,E0-07,Preparación del guion de validación del prototipo,0.45,validada,planeacion/Guion-validacion-prototipo-2026-07-23.md,si,"Guion del recorrido de la demo del 24-jul; ajustada a la baja por Johann 27-jul"
2026-07-24,2026-W30,0,E0-07,"Sesión de validación del prototipo Etapa 0 con Noé, Arturo y Araceli — APROBADO",1.05,confirmada,bitacora/REGISTRO.md#55,si,"Duración ~1 h 4 min según transcript; Etapa 0 validada, queda 1 definición de proceso (flujo Jira)"
2026-07-27,2026-W31,1,E1-07,"Sesión de API de Jira con Pedro (token PAF, bandeja FAC)",0.20,confirmada,bitacora/REGISTRO.md#56,si,"~12 min; token PAF comprometido (1 año) por correo; integración inicia tras definición del flujo 28-jul"
2026-07-27,2026-W31,1,E1-07,"Sesión de API de Jira con Pedro (token PAF, bandeja FAC)",0.20,confirmada,bitacora/REGISTRO.md#56,si,~12 min; token PAF comprometido (1 año) por correo; integración inicia tras definición del flujo 28-jul
1 fecha semana etapa actividad_id actividad horas estado_hora fuente_evidencia facturable notas
2 2026-07-01 2026-W27 0 E0-01 Sesión de arranque con Noé 1.00 confirmada bitacora/REGISTRO.md#22 si Sesión calendarizada de 7:00 a 8:00 am
3 2026-07-01 2026-W27 0 E0-01 Preparación de plan kickoff y materiales 1.00 reconstruida validada planeacion/Kickoff-2026-07-01.md si Estimación retrospectiva; validar antes de facturar validada por Johann 27-jul
4 2026-07-06 2026-W28 0 E0-02 Discovery de facturación y envío 1.08 confirmada bitacora/REGISTRO.md#27 si Duración documentada: aproximadamente 1 h 5 min
5 2026-07-06 2026-W28 0 E0-02 Preparación y análisis de Discovery de facturación 1.92 1.00 reconstruida validada bitacora/REGISTRO.md#27 si Completa 3.00 h para facturación/envío incluyendo sesión Completa 2.08 h con la sesión; ajustada a la baja por Johann 27-jul
6 2026-07-06 2026-W28 0 E0-03 Coordinación y validación de accesos BIND y marca 1.00 reconstruida validada bitacora/REGISTRO.md#28-31 si Recepción documentación y salvaguardas Recepción documentación y salvaguardas; validada por Johann 27-jul
7 2026-07-06 2026-W28 0 E0-04 Validación técnica de API BIND 4.50 reconstruida validada bind-api-sandbox/VALIDACION-API.md si 117 GET análisis y reporte técnico 117 GET análisis y reporte técnico; validada por Johann 27-jul
8 2026-07-07 2026-W28 0 E0-02 Discovery de cobranza 1.00 confirmada bitacora/REGISTRO.md#35 si Sesión calendarizada de 7:00 a 8:00 am; sin grabación
9 2026-07-07 2026-W28 0 E0-02 Preparación y documentación de Discovery de cobranza 1.50 0.75 reconstruida validada fuentes/2026-07-07 - Notas - Proceso actual de cobranza (sin grabacion).md si Estimación retrospectiva Sin grabación; notas escritas a mano; ajustada a la baja por Johann 27-jul
10 2026-07-08 2026-W28 0 E0-05 Diseño y construcción del prototipo 3.00 reconstruida validada prototipo/Prototipo-Etapa0.html si Primera mitad del esfuerzo reconstruido Primera mitad del esfuerzo reconstruido; validada por Johann 27-jul
11 2026-07-09 2026-W28 0 E0-05 Ajustes de cobranza navegación y prototipo 3.00 reconstruida validada prototipo/Prototipo-Etapa0.html si Segunda mitad del esfuerzo reconstruido Segunda mitad del esfuerzo reconstruido; validada por Johann 27-jul
12 2026-07-10 2026-W28 0 E0-06 E0-05 Entregable hallazgos ADRs PDF correo y plan Pulido final del prototipo (bandeja, modal Edo. cuenta, login, capturas) 3.00 1.50 reconstruida validada prototipo/Correo-prototipo-Etapa0.md prototipo/Prototipo-Etapa0.html si Incluye preparación del entregable y documentación 6 commits 00:44-01:52 (b358570..8da11ea) + 9 capturas + logo oficial; validada por Johann 27-jul
13 2026-07-13 2026-07-10 2026-W29 2026-W28 1 0 E1-01 E0-06 Backend base autenticación roles y auditoría Entregable de cierre Etapa 0: PDF hallazgos plan refinado y correo 2.00 1.50 reconstruida validada planeacion/Plan-actividades.md prototipo/Correo-prototipo-Etapa0.md si Trabajo local; falta conciliar contra evidencia de código PDF generado 10:43; hallazgos y plan refinado; validada por Johann 27-jul
14 2026-07-13 2026-W29 1 E1-02 E1-01 Coordinación del repositorio GitHub Backend base autenticación roles y auditoría 0.50 2.00 reconstruida validada bitacora/REGISTRO.md#43 planeacion/Plan-actividades.md si Seguimiento de creación y acceso validada por Johann 27-jul
15 2026-07-14 2026-07-13 2026-W29 1 E1-01 E1-02 Backend base autenticación roles y auditoría Coordinación del repositorio GitHub 1.50 0.50 reconstruida validada planeacion/Plan-actividades.md bitacora/REGISTRO.md#43 si Trabajo local; completa 3.50 h Seguimiento de creación y acceso; validada por Johann 27-jul
16 2026-07-14 2026-W29 1 E1-03 E1-01 Arquitectura multi-tenant Backend base autenticación roles y auditoría 1.00 1.50 reconstruida validada planeacion/Plan-actividades.md si Diseño inicial tenant_id y RLS Trabajo local; completa 3.50 h; validada por Johann 27-jul
17 2026-07-15 2026-07-14 2026-W29 1 E1-03 Arquitectura multi-tenant 0.50 1.00 reconstruida validada planeacion/Plan-actividades.md si Completa 1.50 h Diseño inicial tenant_id y RLS; validada por Johann 27-jul
18 2026-07-15 2026-W29 1 E1-04 E1-03 Cliente productivo de API BIND Arquitectura multi-tenant 2.00 0.50 reconstruida validada bind-api-sandbox/VALIDACION-API.md planeacion/Plan-actividades.md si Inicio de reintentos OData y manejo de errores Completa 1.50 h; validada por Johann 27-jul
19 2026-07-15 2026-W29 1 E1-05 E1-04 Seguimiento ajuste de calendario y corte de horas Cliente productivo de API BIND 0.50 2.00 reconstruida validada bitacora/REGISTRO.md#41-45 bind-api-sandbox/VALIDACION-API.md si Actualización de plan y control Inicio de reintentos OData y manejo de errores; validada por Johann 27-jul
20 2026-07-16 2026-07-15 2026-W29 1 E1-06 E1-05 Scaffold backend .NET 10 + frontend Angular 21 y push al repo de Balam Seguimiento ajuste de calendario y corte de horas 2.00 0.50 reconstruida validada bitacora/REGISTRO.md#46 bitacora/REGISTRO.md#41-45 si Commits 220942a..1f7f098; incluye CLAUDE.md del repo; validar duración Actualización de plan y control; validada por Johann 27-jul
21 2026-07-16 2026-W29 1 E1-05 E1-06 Corte de avance Etapa 1 para Erika (Excel + mensaje) Scaffold backend .NET 10 + frontend Angular 21 y push al repo de Balam 1.00 2.00 reconstruida validada planeacion/Avance-Etapa1-2026-07-16.md bitacora/REGISTRO.md#46 si Enviado 8:40 pm por WhatsApp con acuse; validar duración Commits 220942a..1f7f098; incluye CLAUDE.md del repo; validada por Johann 27-jul
22 2026-07-19 2026-07-16 2026-W29 1 E1-06 E1-05 Preparación de entorno local (clon del repo Corte de avance Etapa 1 para Erika (Excel + mensaje) SDK .NET 10 1.00 secrets validada app corriendo) planeacion/Avance-Etapa1-2026-07-16.md 1.00 si reconstruida Enviado 8:40 pm por WhatsApp con acuse; validada por Johann 27-jul
23 2026-07-19 2026-W29 1 E1-06 Scalar UI para el OpenAPI del backend Preparación de entorno local (clon del repo, SDK .NET 10, secrets, app corriendo) 0.25 1.00 confirmada validada bitacora/REGISTRO.md#48 bitacora/REGISTRO.md#47 si Sesión asistida por IA; /scalar/v1 verificado API y frontend verificados en local; 13/13 pruebas verdes; validada por Johann 27-jul
24 2026-07-19 2026-W29 1 E1-01 E1-08 B0+B1: Postgres 17 local + modelo de datos + Identity + migración Inicial + seed Diseño del plan de ejecución de Etapa 1 (bloques B0-B10, ADRs, orden) 1.00 2.00 confirmada validada bitacora/REGISTRO.md#48 planeacion/Plan-Etapa1.md si Sesión asistida por IA (noche del domingo); 16 tablas migradas y siembra verificada; tiempo real de sesión Arquitectura y decisiones previas a las sesiones de desarrollo; validada por Johann 27-jul
25 2026-07-19 2026-W29 1 E1-01 E1-06 B2: login JWT + policies por rol + bitácora de auditoría Scalar UI para el OpenAPI del backend 0.50 0.25 confirmada bitacora/REGISTRO.md#49 bitacora/REGISTRO.md#48 si Sesión asistida por IA; matriz 401/403/200 verificada end-to-end; tiempo real de sesión Sesión asistida por IA; /scalar/v1 verificado
26 2026-07-19 2026-W29 1 E1-01 B0+B1: Postgres 17 local + modelo de datos + Identity + migración Inicial + seed 1.00 confirmada bitacora/REGISTRO.md#48 si Sesión asistida por IA (noche del domingo); 16 tablas migradas y siembra verificada; tiempo real de sesión
27 2026-07-19 2026-W29 1 E1-01 B2: login JWT + policies por rol + bitácora de auditoría 0.50 confirmada bitacora/REGISTRO.md#49 si Sesión asistida por IA; matriz 401/403/200 verificada end-to-end; tiempo real de sesión
28 2026-07-19 2026-W29 1 E1-01 B3: sync de clientes contra BIND real + fix de modelos (GUIDs null) 0.50 confirmada bitacora/REGISTRO.md#50 si Sesión asistida por IA; 16 clientes sincronizados, idempotencia verificada; tiempo real de sesión
29 2026-07-21 2026-W30 1 E1-01 B4: sync de facturas/cotizaciones + estados + cartera por moneda + sync histórico 1.00 confirmada bitacora/REGISTRO.md#52 si Sesión asistida por IA; 1494 facturas y 43 cotizaciones sincronizadas de producción; tiempo real de sesión
30 2026-07-21 2026-W30 1 E1-03 B6: RLS real de Postgres por tenant (migración + interceptor + filtros EF) 0.50 confirmada bitacora/REGISTRO.md#53 si Sesión asistida por IA; verificación manual en psql; tiempo real de sesión
31 2026-07-21 2026-W30 1 E1-05 Cierre de sesión: Excel de avance regenerado + bitácora + control de horas 0.25 confirmada bitacora/REGISTRO.md#52-53 si Sesión asistida por IA; tiempo real de sesión
32 2026-07-22 2026-07-21 2026-W30 1 E1-05 Sesión de reglas Etapa 1 con Noé, Arturo y Araceli (alta de clientes, fee, flujo Jira) Preparación de la agenda de la sesión de reglas de Etapa 1 0.80 0.75 confirmada validada bitacora/REGISTRO.md#54 planeacion/Sesion-Etapa1-2026-07-22.md si Duración real ~48 min según transcript (7:00–7:48 am) Agenda y preguntas para la sesión del 22-jul; validada por Johann 27-jul
33 2026-07-22 2026-W30 1 E1-05 Sesión de reglas Etapa 1 con Noé, Arturo y Araceli (alta de clientes, fee, flujo Jira) 0.80 confirmada bitacora/REGISTRO.md#54 si Duración real ~48 min según transcript (7:00–7:48 am)
34 2026-07-23 2026-W30 0 E0-07 Preparación del guion de validación del prototipo 0.45 validada planeacion/Guion-validacion-prototipo-2026-07-23.md si Guion del recorrido de la demo del 24-jul; ajustada a la baja por Johann 27-jul
35 2026-07-24 2026-W30 0 E0-07 Sesión de validación del prototipo Etapa 0 con Noé, Arturo y Araceli — APROBADO 1.05 confirmada bitacora/REGISTRO.md#55 si Duración ~1 h 4 min según transcript; Etapa 0 validada, queda 1 definición de proceso (flujo Jira)
36 2026-07-27 2026-W31 1 E1-07 Sesión de API de Jira con Pedro (token PAF, bandeja FAC) 0.20 confirmada bitacora/REGISTRO.md#56 si ~12 min; token PAF comprometido (1 año) por correo; integración inicia tras definición del flujo 28-jul
+51 -31
View File
@@ -5,7 +5,7 @@ Fuente local de horas efectivamente trabajadas para el proyecto Balam. Se mantie
**Tarifa contractual:** $600 MXN/h + IVA
**Cadencia:** corte semanal; factura los viernes; pago a 30 días
**Datos tabulares:** [`Seguimiento-horas.csv`](Seguimiento-horas.csv)
**Última actualización:** 2026-07-15
**Última actualización:** 2026-07-27
## Reglas de captura
@@ -16,47 +16,67 @@ Fuente local de horas efectivamente trabajadas para el proyecto Balam. Se mantie
5. No completar retrospectivamente una duración sin respaldo. Si solo se conoce la actividad, dejarla en la lista de reconstrucción hasta que Johann confirme el tiempo.
6. Al habilitarse Jira, conciliar ambos registros y evitar duplicados.
## Corte reconstruido al 15-jul
## Corte al 27-jul
| Etapa | Horas al corte | Rango estimado de la etapa | Estado |
|---|---:|---:|---|
| Etapa 0 | **22.00 h** | 1822 h | Límite superior consumido; prototipo pendiente de validación |
| Etapa 1 | **8.00 h** | 3239 h | En curso |
| **Total** | **30.00 h** | | Coincide con la facturación inicial propuesta |
| Etapa 0 | **21.83 h** | 1822 h | Cerrada y **validada por Balam el 24-jul**; dentro del rango |
| Etapa 1 | **19.75 h** | 3239 h | En curso; 6 de 8 entregables terminados |
| **Total** | **41.58 h** | | |
Las **26.92 h** que no corresponden a sesiones con duración documentada se reconstruyeron retrospectivamente por actividad. Deben validarse contra memoria, archivos de trabajo y Jira antes de presentarse como horas efectivamente trabajadas.
**Estado de validación de las horas (27-jul):**
## Horas con duración comprobable
| Estado | Horas | Significado |
|---|---:|---|
| `confirmada` | 9.13 h | Duración documentada (transcripts, sesiones calendarizadas, tiempo de sesión) |
| `validada` | 32.45 h | Reconstruida por actividad y **confirmada por Johann el 27-jul** contra evidencia fechada |
| **Total** | **41.58 h** | Sin horas pendientes de validar |
| Semana | Etapa | Horas confirmadas | Alcance incluido |
|---|---:|---:|---|
| 2026-W27 | 0 | 1.00 | Kickoff |
| 2026-W28 | 0 | 2.08 | Discovery de facturación/envío y cobranza |
| **Total comprobable** | | **3.08** | Solo sesiones con duración documentada |
## Distribución al 27-jul
> Las 3.08 h están incluidas dentro del corte reconstruido de 30 h; no deben sumarse nuevamente.
| Etapa | Actividad | ID | Horas |
|---|---|---|---:|
| 0 | Kickoff y preparación | E0-01 | 2.00 |
| 0 | Discovery de facturación, envío y cobranza | E0-02 | 3.83 |
| 0 | Accesos y salvaguardas | E0-03 | 1.00 |
| 0 | Validación técnica de la API de BIND | E0-04 | 4.50 |
| 0 | Prototipo navegable (incl. pulido final del 10-jul) | E0-05 | 7.50 |
| 0 | Entregable de cierre: PDF, hallazgos, plan y correo | E0-06 | 1.50 |
| 0 | Validación del prototipo con Balam (guion + sesión) | E0-07 | 1.50 |
| 1 | Backend base, auth, roles, bitácora y syncs (B0B4) | E1-01 | 6.50 |
| 1 | Coordinación del repositorio | E1-02 | 0.50 |
| 1 | Arquitectura multi-tenant y RLS (B6) | E1-03 | 2.00 |
| 1 | Cliente productivo de la API de BIND | E1-04 | 2.00 |
| 1 | Gestión, cortes de avance y sesión de reglas | E1-05 | 3.30 |
| 1 | Entorno local, scaffold y Scalar | E1-06 | 3.25 |
| 1 | Sesión de API de Jira | E1-07 | 0.20 |
| 1 | Diseño del plan de ejecución de Etapa 1 | E1-08 | 2.00 |
| | **Total** | | **41.58** |
## Distribución reconstruida
> **Ajustes a la baja aplicados por Johann el 27-jul:** el análisis del Discovery de facturación bajó de 1.92 a 1.00 h, la documentación del de cobranza de 1.50 a 0.75 h, y el guion de validación de 0.75 a 0.45 h. Las duraciones de sesión documentadas en transcript **no se tocaron**. Con esto Etapa 0 vuelve a quedar dentro del rango contractual de 1822 h.
Johann debe confirmar esta distribución antes de usarla para facturación:
### Nota sobre las sesiones asistidas por IA
| Etapa | Actividad consolidada | Horas |
|---|---|---:|
| 0 | Kickoff y preparación | 2.00 |
| 0 | Discovery de facturación, envío y cobranza | 5.50 |
| 0 | Accesos y salvaguardas | 1.00 |
| 0 | Validación técnica de BIND | 4.50 |
| 0 | Prototipo navegable | 6.00 |
| 0 | Entregable, hallazgos, ADRs y plan | 3.00 |
| 1 | Backend base | 3.50 |
| 1 | Arquitectura multi-tenant | 1.50 |
| 1 | Cliente productivo de BIND | 2.00 |
| 1 | Repositorio y seguimiento | 1.00 |
| | **Total** | **30.00** |
Los bloques B0B6 de Etapa 1 (auth, RLS, cliente de BIND, sincronización de 1,494 facturas de producción) se ejecutaron en **3.50 h de tiempo de reloj** contra una estimación manual de 45.5 h *por bloque*. Se registra el tiempo efectivamente trabajado, conforme al contrato. El trabajo intelectual que hizo posible esa velocidad —diseño de arquitectura, decisión de ADRs y plan de ejecución— se registra por separado en **E1-08 (2.00 h)**.
Consecuencia a vigilar: **Etapa 1 cerrará por debajo del rango de 3239 h.** Conviene reportar avance por entregable (6 de 8) y no solo por horas, para que la eficiencia no se lea como alcance faltante.
### Nota sobre el mapeo CSV → Excel
El CSV agrupa por **actividad contractual**; el Excel desglosa por **tarea de proyecto**, y no mapean 1:1. El reparto vive en `HORAS_POR_FILA` dentro de `generar_avance_2026_07_27.py`, con la trazabilidad comentada línea por línea, y el script **aborta** si la suma del detalle no cuadra con el CSV.
Dos casos que conviene recordar:
- **E1-06 (entorno, scaffold, Scalar — 3.25 h)** no tiene fila propia: se carga a "Backend base", que se renombró y amplió su rango a 89 h.
- **E1-08 (diseño del plan — 2.00 h)** se reparte en dos: **1.00 h** de diseño general va a "Arquitectura multi-tenant y diseño de la solución" (rango 34 h) y **1.00 h** del análisis de B7 —pipeline `Draft→DryRun→Confirm`, flags, regla PPD/PUE, ADR-001— va a la fila del **entregable 4 (capa de escritura)**, para que muestre el trabajo hecho aunque la implementación siga en pausa. La entidad `WriteOperation` y la policy `PuedeOperarEscritura` **no** se contabilizan ahí: se hicieron en B1/B2 y ya están en "Backend base" (evita doble conteo).
- La fila de **seguimiento semanal se queda solo con gestión y cortes de avance (1.75 h)**. Antes acumulaba 7.00 h de trabajo técnico bajo un nombre que no lo describía, lo que se leía como sobrecosto en una actividad trivial.
- La sesión **B4 (1.00 h)** se reparte entre "Sincronización de facturas" (0.50 h) y "Modelo de facturas" (0.50 h): produjo ambas cosas —el sync y el `InvoiceStatusMapper` con sus 13 pruebas más la migración `DetalleSyncPendiente`—, y antes el modelo aparecía al 85 % con 0 h.
**Criterio general:** ninguna fila debe mostrar avance con 0 h trabajadas. Las únicas excepciones legítimas son Azure y CI/CD, que están en 0 % y 0 h porque dependen de accesos del lado de Balam.
## Corte comercial
- La propuesta v1.2 contempla una **facturación inicial de 30 h ($18,000 + IVA)** que cubre Etapa 0 e inicio de Etapa 1.
- Esas 30 h son el concepto comercial autorizado en la propuesta, pero el contrato exige reportar horas efectivamente trabajadas.
- Antes de emitir, Johann debe validar el desglose reconstruido y conciliarlo contra Jira.
- La emisión sigue pendiente de confirmación de Balam al correo del 2-jul.
- Al 27-jul hay **41.58 h trabajadas**, es decir **11.58 h por encima** de esa facturación inicial. A tarifa de $600/h son **$6,948 + IVA** aún no facturados.
- Todas las horas están validadas (ninguna pendiente de confirmar), por lo que el desglose ya es presentable para facturación.
- Pendiente: conciliar contra Jira cuando Pedro lo habilite, y confirmar con Balam si la segunda factura va por el excedente o por corte de etapa.
- La emisión de la factura inicial sigue pendiente de confirmación de Balam al correo del 2-jul.
+190 -36
View File
@@ -1,16 +1,28 @@
"""Genera Plan-actividades-avance-2026-07-27.xlsx a partir del del 21-jul.
Aplica las horas y estatus reales al 27-jul: sesión de reglas (22-jul) y
validación del prototipo (24-jul, APROBADO) completadas; sesión de API de Jira
(27-jul) en curso; capa de escritura EN PAUSA a la espera de la definición del
flujo de facturación (sesión 28-jul con Arturo/Araceli).
Reutiliza el estilo/semáforo del archivo del 21-jul."""
import re
from datetime import date
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
SRC = "/Users/johann/Desktop/Proyectos personales/BALAM/planeacion/Plan-actividades-avance-2026-07-21.xlsx"
DST = "/Users/johann/Desktop/Proyectos personales/BALAM/planeacion/Plan-actividades-avance-2026-07-27.xlsx"
Diferencia clave vs. versiones anteriores: las HORAS TRABAJADAS ya no se escriben a
mano — se leen de `Seguimiento-horas.csv` (fuente de la verdad) y se agregan por
actividad del plan mediante el mapa ACT_POR_TAREA. Así cada celda de horas del
Excel es trazable a una o varias líneas del CSV, y el total del encabezado de cada
etapa es la suma real de su detalle.
Corte al 27-jul: validación del prototipo (24-jul, APROBADO) y sesión de reglas
(22-jul) completadas; API de Jira (27-jul) recibida; capa de escritura EN PAUSA a
la espera de la definición del flujo de facturación (sesión 28-jul).
"""
import csv
import os
import re
from collections import defaultdict
from datetime import date
import openpyxl
from openpyxl.styles import Alignment, Font, PatternFill
BASE = os.path.dirname(os.path.abspath(__file__))
SRC = os.path.join(BASE, "Plan-actividades-avance-2026-07-21.xlsx")
DST = os.path.join(BASE, "Plan-actividades-avance-2026-07-27.xlsx")
CSV_HORAS = os.path.join(BASE, "Seguimiento-horas.csv")
HOY = date(2026, 7, 27)
CAFE, CREMA, GRIS_B, AMARILLO = "331F0E", "FDF3D8", "D9D9D9", "F7BD0C"
@@ -21,17 +33,115 @@ G_FILL, G_FONT = "F2F2F2", "595959" # gris
C_PCT, C_BLQ, C_EST, C_TRAB, C_STAT = 7, 8, 9, 10, 11
# Prefijo de la actividad -> overrides de datos (pct=%, trab=horas, comienzo/fin=fechas texto)
# --- Horas por fila del Excel --------------------------------------------------
# Las actividades del CSV no mapean 1:1 con las filas del plan (el CSV agrupa por
# actividad contractual; el Excel desglosa por tarea de proyecto). Se reparten por
# fila usando la evidencia de la bitácora, de modo que cada fila muestre el trabajo
# que realmente le corresponde y la suma siga cuadrando con el CSV.
#
# Trazabilidad de Etapa 1 (19.75 h del CSV):
# E1-01 6.50 = backend base 3.50 (13-14 jul) + B0/B1 1.00 + B2 0.50 + B3 0.50 + B4 1.00
# E1-02 0.50 = repositorio GitHub
# E1-03 2.00 = multi-tenant 1.50 (14-15 jul) + B6 RLS 0.50
# E1-04 2.00 = cliente de BIND
# E1-05 3.30 = gestión 0.50 + corte 16-jul 1.00 + cierre 21-jul 0.25 + prep 0.75 + sesión 0.80
# E1-06 3.25 = scaffold 2.00 + entorno local 1.00 + Scalar 0.25
# E1-07 0.20 = sesión API de Jira
# E1-08 2.00 = diseño del plan de Etapa 1
HORAS_POR_FILA = {
# --- Etapa 0 (21.83 h) — una actividad del CSV por fila
# E0-02 3.83 = sesión facturación 1.08 + análisis 1.00 + sesión cobranza 1.00 + notas 0.75
# E0-07 1.50 = guion 0.45 + sesión de validación 1.05 (transcript: 1 h 4 min)
"Sesión de arranque (kickoff)": 2.00, # E0-01
"Sesión de Discovery": 3.83, # E0-02
"Entrega y validación de accesos": 1.00, # E0-03
"Validación técnica de la API de BIND": 4.50, # E0-04
"Prototipo visual navegable": 7.50, # E0-05
"Documento de hallazgos": 1.50, # E0-06
"Sesión de validación del prototipo": 1.50, # E0-07 (guion 0.45 + sesión 1.05)
# --- Etapa 1 (19.75 h)
# El trabajo de andamiaje (entorno local, scaffold, Scalar) y el diseño del plan
# no tienen fila propia en el plan original: se cargan a la fila técnica que les
# corresponde por naturaleza, no a la de seguimiento semanal.
"Repositorio privado GitHub": 0.50, # E1-02
"Backend base": 8.25, # E1-01 5.00 + E1-06 3.25 (entorno, scaffold, Scalar)
"Arquitectura multi-tenant": 3.00, # E1-03 2.00 (incl. B6 RLS) + E1-08 1.00 (diseño general)
"Cliente de la API de BIND": 2.00, # E1-04
"Sincronización de clientes": 0.50, # E1-01 parte: B3
# B4 produjo dos cosas: el sync de facturas/cotizaciones y el modelo central
# (InvoiceStatusMapper con 13 pruebas + migración DetalleSyncPendiente). Se
# reparte para que ninguna fila quede en 0 h marcada como avanzada.
"Sincronización de facturas": 0.50, # E1-01 parte: B4 (sync)
"Modelo de facturas": 0.50, # E1-01 parte: B4 (mapper + migraciones)
"Sesión de reglas y dudas": 1.55, # E1-05 parte: prep 0.75 + sesión 0.80
"Definición de alcance Jira": 0.20, # E1-07
"Demostración semanal": 1.75, # E1-05 resto: gestión 0.50 + corte 1.00 + cierre 0.25
# Análisis y diseño de B7 (pipeline Draft→DryRun→Confirm, flags, regla PPD/PUE,
# ADR-001): 1.00 h de E1-08, separada del diseño general para que la fila del
# entregable 4 muestre el trabajo que sí se hizo. La implementación sigue en pausa.
"Capa de escritura controlada": 1.00,
# --- Sin horas aún (trabajo no iniciado o dependiente de Balam)
"Configuración de infraestructura en Azure": 0.00,
"CI/CD": 0.00,
}
def horas_por_actividad(path):
"""Suma horas del CSV por actividad_id y por etapa."""
por_act = defaultdict(float)
por_etapa = defaultdict(float)
with open(path, encoding="utf-8", newline="") as fh:
rdr = csv.DictReader(fh)
for i, r in enumerate(rdr, start=2):
if not (r.get("fecha") or "").strip():
continue
if None in r or any(v is None for v in r.values()):
raise ValueError(
f"{os.path.basename(path)} línea {i}: número de campos inesperado "
f"(¿falta escapar una coma con comillas?)")
h = float(r["horas"])
por_act[r["actividad_id"]] += h
por_etapa[r["etapa"]] += h
return por_act, por_etapa
HORAS_ACT, HORAS_ETAPA = horas_por_actividad(CSV_HORAS)
TOTAL_CSV = sum(HORAS_ETAPA.values())
# % por entregables terminados (dato duro y defendible, no promedio ponderado).
# Etapa 1: 6 de 8 entregables contractuales TERMINADOS (1,2,3,5,6,7) = 75%. Los dos
# restantes van parciales y su avance se refleja en su propia fila (entregable 4 al
# 40%, entregable 8 al 85%), no promediado en el encabezado: la etapa se mide por
# entregable cerrado, que es lo verificable.
PCT_ETAPA = {"0": 1.0, "1": 0.75}
OVERRIDES = {
"Integracion de plataformas Balam": dict(pct=0.67, trab=40),
"Etapa 0": dict(pct=1.0, trab=23),
"Integracion de plataformas Balam": dict(pct=0.80, trab=TOTAL_CSV),
"Etapa 0": dict(pct=PCT_ETAPA["0"], trab=HORAS_ETAPA["0"]),
"Etapa 1": dict(pct=PCT_ETAPA["1"], trab=HORAS_ETAPA["1"]),
"Documento de hallazgos": dict(pct=1.0),
"Sesión de validación del prototipo": dict(pct=1.0, trab=1.05,
comienzo="vie 24/07/26", fin="vie 24/07/26"),
"Etapa 1": dict(pct=0.82, trab=17),
"Demostración semanal": dict(trab=1.75),
"Sesión de reglas y dudas": dict(pct=1.0, trab=0.80),
"Definición de alcance Jira": dict(pct=0.40, trab=0.20),
"Sesión de validación del prototipo": dict(pct=1.0, comienzo="vie 24/07/26",
fin="vie 24/07/26"),
# Estas dos filas absorben el andamiaje y el diseño del plan: se renombran y se
# amplía su rango estimado para que el nombre refleje el alcance que cubren.
"Backend base": dict(
nombre="Backend base: entorno, andamiaje, autenticación, roles y bitácora",
est="89"),
"Arquitectura multi-tenant": dict(
nombre="Arquitectura multi-tenant (tenant_id + RLS) y diseño de la solución",
est="34"),
"Demostración semanal": dict(est="23"),
# B7: diseño, ADR-001, entidad WriteOperation (migrada en B1) y policy
# PuedeOperarEscritura ya existen; falta BindWriteClient, el pipeline y los
# shapes de los POST (dependen de las reglas del 28-jul). Sin horas propias:
# las del modelo y la policy ya están cobradas en B1/B2 ("Backend base").
"Capa de escritura controlada": dict(pct=0.40),
"Sesión de reglas y dudas": dict(pct=1.0),
"Sincronización de clientes": dict(pct=1.0),
"Sincronización de facturas": dict(pct=1.0),
# Conectividad resuelta el 27-jul (token PAF a 1 año, API read+write, bandeja FAC,
# límites de consumo). Queda el 10 %: qué estatus dispara qué, amarrado al 28-jul.
"Definición de alcance Jira": dict(pct=0.90),
}
# Estatus a mano (gana sobre el semáforo automático): texto, fill, font, negrita
@@ -39,37 +149,51 @@ K_ESPECIAL = {
"Documento de hallazgos": ("✅ Completada", V_FILL, V_FONT, False),
"Sesión de validación del prototipo": ("✅ Validado (aprobado)", V_FILL, V_FONT, True),
"Demostración semanal": ("🟡 En curso (semanal)", A_FILL, A_FONT, False),
"Modelo de facturas": ("🟡 En curso · falta seeder", A_FILL, A_FONT, False),
"Capa de escritura controlada": ("🔴 En pausa · def. Balam 28-jul", R_FILL, R_FONT, True),
"Modelo de facturas": ("🟡 Modelo y migraciones ✓ · falta seeder", A_FILL, A_FONT, False),
"Capa de escritura controlada": ("🔴 Diseño listo · impl. en pausa (def. Balam 28-jul)",
R_FILL, R_FONT, True),
"Sesión de reglas y dudas": ("✅ Completada", V_FILL, V_FONT, False),
"Definición de alcance Jira": ("🟡 En curso · API Jira 27-jul", A_FILL, A_FONT, False),
"Definición de alcance Jira": ("🟡 Conectividad lista · falta regla 28-jul",
A_FILL, A_FONT, False),
"Configuración de infraestructura en Azure": ("🟡 Pendiente (Balam)", A_FILL, A_FONT, False),
"CI/CD": ("🔴 Pendiente · dep. Azure", R_FILL, R_FONT, True),
}
def fecha(celda):
m = re.search(r"(\d{2})/(\d{2})/(\d{2})", str(celda or ""))
return date(2000 + int(m.group(3)), int(m.group(2)), int(m.group(1))) if m else None
def pinta(celda, fill, font_color, bold=False):
celda.fill = PatternFill("solid", fgColor=fill)
celda.font = Font(color=font_color, bold=bold, size=10)
celda.alignment = Alignment(horizontal="center", vertical="center")
wb = openpyxl.load_workbook(SRC)
ws = wb.active
# 1) Aplica overrides de datos por prefijo de nombre
# 1) Horas trabajadas desde el CSV + overrides de datos por prefijo de nombre
for row in range(2, ws.max_row + 1):
nombre = str(ws.cell(row=row, column=1).value or "").strip()
if not nombre:
continue
# 1a) horas por fila (reparto trazable al CSV; ver HORAS_POR_FILA)
for prefijo, h in HORAS_POR_FILA.items():
if nombre.startswith(prefijo):
ws.cell(row=row, column=C_TRAB, value=h)
break
# 1b) overrides de %, fechas, nombre y rango estimado
for prefijo, ov in OVERRIDES.items():
if nombre.startswith(prefijo):
if "pct" in ov: ws.cell(row=row, column=C_PCT, value=ov["pct"])
if "trab" in ov: ws.cell(row=row, column=C_TRAB, value=ov["trab"])
if "trab" in ov: ws.cell(row=row, column=C_TRAB, value=round(ov["trab"], 2))
if "comienzo" in ov: ws.cell(row=row, column=3, value=ov["comienzo"])
if "fin" in ov: ws.cell(row=row, column=4, value=ov["fin"])
if "est" in ov: ws.cell(row=row, column=C_EST, value=ov["est"])
break
# 2) Recalcula el semáforo con HOY=27-jul (mismas reglas que el del 21-jul)
@@ -103,7 +227,7 @@ for row in range(2, ws.max_row + 1):
elif pct > 0: pinta(pcel, A_FILL, A_FONT, bold=True)
elif fin and fin < HOY: pinta(pcel, R_FILL, R_FONT, bold=True)
pcel.number_format = "0%"
ws.cell(row=row, column=C_TRAB).number_format = "0.0"
ws.cell(row=row, column=C_TRAB).number_format = "0.00"
# 3) Overrides finos de estatus (bloqueos y dependencias)
for row in range(2, ws.max_row + 1):
@@ -115,32 +239,62 @@ for row in range(2, ws.max_row + 1):
pinta(stat, fill, font, bold)
break
# 4) Encabezado de la columna de estatus y pie
# 4) Renombra las filas que absorbieron alcance (al final: los pasos 2-3 buscan por
# el nombre original)
for row in range(2, ws.max_row + 1):
nombre = str(ws.cell(row=row, column=1).value or "").strip()
for prefijo, ov in OVERRIDES.items():
if "nombre" in ov and nombre.startswith(prefijo):
ws.cell(row=row, column=1, value=ov["nombre"])
break
# 5) Encabezado de la columna de estatus
ws.cell(row=1, column=C_STAT, value=f"Estatus (hoy {HOY.day}-jul)")
# 5) Reescribe leyenda/notas (borra las viejas de la línea de HOY del 21-jul)
# 6) Reescribe leyenda/notas (borra las viejas)
for row in range(ws.max_row, 1, -1):
v = str(ws.cell(row=row, column=1).value or "")
if v.startswith("✅ Completada ·") or v.startswith("▬ La línea roja"):
if v.startswith(("✅ Completada ·", "▬ La línea roja", "Núcleo de la Etapa 1",
"🔴 La capa de escritura", "API de Jira:", "Horas:")):
for col in range(1, C_STAT + 1):
ws.cell(row=row, column=col).value = None
ley = ws.max_row + 2
notas = [
("✅ Completada · 🟡 En curso · 🔴 Vencida/Pendiente · ⚪ Próxima", G_FONT, True),
("Núcleo de la Etapa 1 construido y verificado contra producción: autenticación y roles, "
"bitácora, multi-tenant con RLS, cliente de BIND, sincronización de clientes/facturas/"
"cotizaciones, modelo de facturas con estados y cartera por moneda.", CAFE, False),
("🔴 La capa de escritura (cotización→factura) queda EN PAUSA a la espera de la definición "
"del flujo de facturación (sesión del martes 28-jul con Arturo y Araceli).", "9C0006", False),
("API de Jira: token recibido el 27-jul; la integración inicia una vez definido el flujo.", CAFE, False),
(f"Horas: {HORAS_ETAPA['0']:.2f} h de Etapa 0 y {HORAS_ETAPA['1']:.2f} h de Etapa 1 "
f"({TOTAL_CSV:.2f} h en total), conforme al control local de horas trabajadas. "
f"Etapa 1 estimada en 3239 h.", CAFE, False),
("Etapa 1: 6 de 8 entregables contractuales terminados — autenticación y roles con "
"bitácora, multi-tenant con RLS, cliente de BIND, sincronización de clientes, "
"sincronización de facturas y cotizaciones, y modelo de facturas con estados y "
"cartera por moneda. Verificado contra producción: 1,494 facturas sincronizadas "
"con la cartera cuadrada.", CAFE, False),
("🔴 La capa de escritura (cotización→factura) queda EN PAUSA a la espera de la "
"definición del flujo de facturación (sesión del martes 28-jul con Arturo y Araceli).",
"9C0006", False),
("Pendientes menores: datos de prueba (seeder) y verificación del aislamiento RLS "
"con rol no-superusuario. Azure y CI/CD dependen de accesos del lado de Balam.", CAFE, False),
("API de Jira: token recibido el 27-jul; la integración inicia una vez definido el flujo.",
CAFE, False),
]
for i, (txt, color, bold) in enumerate(notas):
c = ws.cell(row=ley + i, column=1, value=txt)
c.font = Font(italic=True, size=9, color=color, bold=bold)
ws.freeze_panes = "A2"
ws.oddFooter.center.text = "Avance al 27-jul-2026 · Horas conforme al control local (pendiente conciliar con Jira)"
ws.oddFooter.center.text = (f"Avance al 27-jul-2026 · {TOTAL_CSV:.2f} h trabajadas "
"conforme al control local (pendiente conciliar con Jira)")
wb.save(DST)
# --- Verificación: el detalle debe cuadrar con el encabezado de cada etapa -----
print("OK ->", DST)
print(f" Etapa 0: {HORAS_ETAPA['0']:.2f} h · Etapa 1: {HORAS_ETAPA['1']:.2f} h "
f"· TOTAL {TOTAL_CSV:.2f} h")
suma_detalle = sum(HORAS_POR_FILA.values())
ok = abs(suma_detalle - TOTAL_CSV) < 0.01
print(f" Suma del detalle mostrado: {suma_detalle:.2f} h "
f"({'cuadra con el CSV' if ok else f'NO CUADRA (CSV {TOTAL_CSV:.2f})'})")
if not ok:
raise SystemExit("El detalle por fila no cuadra con el CSV — revisar HORAS_POR_FILA.")
@@ -0,0 +1,175 @@
"""Genera Avance-Balam-2026-07-27.xlsx — versión SIMPLE para enviar a Erika.
Se construye desde el Excel interno (`Plan-actividades-avance-2026-07-27.xlsx`),
que a su vez lee las horas de `Seguimiento-horas.csv`. Así los dos archivos nunca
se contradicen: este es una vista reducida, no una segunda fuente de datos.
Formato pedido por Erika el 21-jul: entregable + actividad + horas por etapa.
Se quitan del interno: rangos estimados, bloques del plan (B1/B4/B9), predecesoras
y duración en días — ruido para quien solo da seguimiento.
"""
import os
import re
from datetime import date
import openpyxl
from openpyxl.styles import Alignment, Border, Font, PatternFill, Side
from openpyxl.utils import get_column_letter
BASE = os.path.dirname(os.path.abspath(__file__))
SRC = os.path.join(BASE, "Plan-actividades-avance-2026-07-27.xlsx")
DST = os.path.join(BASE, "Avance-Balam-2026-07-27.xlsx")
HOY = date(2026, 7, 27)
# Marca Balam
CAFE, AMARILLO, CREMA = "331F0E", "F7BD0C", "FDF3D8"
V_FILL, V_FONT = "C6EFCE", "006100" # verde
A_FILL, A_FONT = "FFEB9C", "9C6500" # amarillo
R_FILL, R_FONT = "FFC7CE", "9C0006" # rojo
GRIS = "595959"
BORDE = "D9D9D9"
# Columnas del origen
O_NOMBRE, O_INI, O_FIN, O_PCT, O_TRAB, O_STAT = 1, 3, 4, 7, 10, 11
thin = Side(style="thin", color=BORDE)
box = Border(left=thin, right=thin, top=thin, bottom=thin)
def limpia_fecha(txt):
"""'vie 24/07/26' -> '24/07/2026'."""
m = re.search(r"(\d{2})/(\d{2})/(\d{2})", str(txt or ""))
return f"{m.group(1)}/{m.group(2)}/20{m.group(3)}" if m else ""
def es_etapa(nombre):
return nombre.startswith(("Etapa", "Integracion"))
# --- Lee el interno -----------------------------------------------------------
wsrc = openpyxl.load_workbook(SRC).active
filas = []
for row in range(2, wsrc.max_row + 1):
nombre = str(wsrc.cell(row=row, column=O_NOMBRE).value or "").strip()
if not nombre or nombre.startswith(("", "", "Horas:", "Etapa 1:", "🔴", "Pendientes",
"API de Jira", "Núcleo")):
continue
filas.append({
"nombre": nombre,
"ini": limpia_fecha(wsrc.cell(row=row, column=O_INI).value),
"fin": limpia_fecha(wsrc.cell(row=row, column=O_FIN).value),
"pct": wsrc.cell(row=row, column=O_PCT).value or 0,
"trab": wsrc.cell(row=row, column=O_TRAB).value,
"stat": str(wsrc.cell(row=row, column=O_STAT).value or "").strip(),
"etapa": es_etapa(nombre),
})
# --- Construye el simple ------------------------------------------------------
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "Avance"
ws["A1"] = "Proyecto Balam · Plataforma de Automatización Financiera"
ws["A1"].font = Font(bold=True, size=14, color=CAFE)
ws["A2"] = f"Avance al {HOY.day}-jul-2026"
ws["A2"].font = Font(size=10, italic=True, color=GRIS)
ENC = ["Actividad", "Inicio", "Fin", "Avance", "Horas", "Estatus"]
ANCHOS = [52, 12, 12, 10, 9, 34]
FILA_ENC = 4
for i, (txt, ancho) in enumerate(zip(ENC, ANCHOS), start=1):
c = ws.cell(row=FILA_ENC, column=i, value=txt)
c.font = Font(bold=True, size=10, color=CAFE)
c.fill = PatternFill("solid", fgColor=AMARILLO)
c.alignment = Alignment(horizontal="center", vertical="center")
c.border = box
ws.column_dimensions[get_column_letter(i)].width = ancho
r = FILA_ENC + 1
for f in filas:
fill_etapa = PatternFill("solid", fgColor=CREMA) if f["etapa"] else None
c = ws.cell(row=r, column=1, value=f["nombre"])
c.font = Font(bold=f["etapa"], size=10, color=CAFE)
c.alignment = Alignment(vertical="center", wrap_text=True,
indent=0 if f["etapa"] else 1)
for col, val in ((2, f["ini"]), (3, f["fin"])):
cc = ws.cell(row=r, column=col, value=val)
cc.font = Font(size=9, color=GRIS)
cc.alignment = Alignment(horizontal="center", vertical="center")
# Avance
cp = ws.cell(row=r, column=4, value=f["pct"])
cp.number_format = "0%"
cp.alignment = Alignment(horizontal="center", vertical="center")
if f["pct"] >= 1:
cp.font = Font(bold=True, size=10, color=V_FONT)
cp.fill = PatternFill("solid", fgColor=V_FILL)
elif f["pct"] > 0:
cp.font = Font(bold=True, size=10, color=A_FONT)
cp.fill = PatternFill("solid", fgColor=A_FILL)
else:
cp.font = Font(size=10, color=GRIS)
# Horas
ch = ws.cell(row=r, column=5, value=f["trab"])
ch.number_format = "0.00"
ch.font = Font(bold=f["etapa"], size=10, color=CAFE)
ch.alignment = Alignment(horizontal="center", vertical="center")
# Estatus
cs = ws.cell(row=r, column=6, value=f["stat"])
cs.alignment = Alignment(horizontal="left", vertical="center", wrap_text=True)
cs.font = Font(size=9, color=GRIS)
if f["stat"].startswith(""):
cs.font = Font(size=9, color=V_FONT); cs.fill = PatternFill("solid", fgColor=V_FILL)
elif f["stat"].startswith("🟡"):
cs.font = Font(size=9, color=A_FONT); cs.fill = PatternFill("solid", fgColor=A_FILL)
elif f["stat"].startswith("🔴"):
cs.font = Font(size=9, bold=True, color=R_FONT); cs.fill = PatternFill("solid", fgColor=R_FILL)
for col in range(1, 7):
ws.cell(row=r, column=col).border = box
if fill_etapa and col in (1, 2, 3):
ws.cell(row=r, column=col).fill = fill_etapa
r += 1
# --- Notas --------------------------------------------------------------------
tot = next((f["trab"] for f in filas if f["nombre"].startswith("Integracion")), 0)
e0 = next((f["trab"] for f in filas if f["nombre"].startswith("Etapa 0")), 0)
e1 = next((f["trab"] for f in filas if f["nombre"].startswith("Etapa 1")), 0)
notas = [
("", False),
(f"Horas trabajadas: {e0:.2f} h en Etapa 0 y {e1:.2f} h en Etapa 1 "
f"({tot:.2f} h en total).", True),
("Etapa 1: 6 de los 8 entregables terminados — autenticación y roles con bitácora, "
"multi-tenant, cliente de la API de BIND, sincronización de clientes, "
"sincronización de facturas y cotizaciones, y modelo de facturas con estados y "
"cartera por moneda. Verificado contra producción: 1,494 facturas sincronizadas "
"con la cartera cuadrada.", False),
("La capa de escritura (cotización→factura) está en pausa a la espera de la "
"definición del flujo de facturación (sesión del martes 28-jul).", False),
("Azure y CI/CD esperan la configuración de los recursos del lado de Balam.", False),
]
for txt, bold in notas:
if txt:
c = ws.cell(row=r, column=1, value=txt)
c.font = Font(italic=True, size=9, color=CAFE, bold=bold)
c.alignment = Alignment(wrap_text=True, vertical="top")
ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=6)
ws.row_dimensions[r].height = 28 if len(txt) > 110 else 14
r += 1
ws.freeze_panes = f"A{FILA_ENC + 1}"
ws.sheet_view.showGridLines = False
ws.print_area = f"A1:F{r}"
ws.page_setup.orientation = "landscape"
ws.page_setup.fitToWidth = 1
ws.sheet_properties.pageSetUpPr.fitToPage = True
wb.save(DST)
print("OK ->", DST)
print(f" {len(filas)} filas · Etapa 0 {e0:.2f} h · Etapa 1 {e1:.2f} h · total {tot:.2f} h")