e057fb9127
- Plan-Etapa1.md: plan detallado por fases/bloques (B0-B9) con horas, decisiones de arquitectura y lo bloqueado hasta el 22-jul - Avance-Etapa1-2026-07-16.md + Excel de avance ordenado por fechas (con script generador y de ordenamiento) - WhatsApp 16-jul: invitación al Git recibida, procedimientos de clientes enviados por correo, Erika pide avance de Etapa 1 - Actualiza PENDIENTES y REGISTRO
99 lines
3.1 KiB
Python
99 lines
3.1 KiB
Python
"""Genera el Excel de avance que se compartirá con Erika el 16-jul-2026."""
|
|
|
|
from copy import copy
|
|
from pathlib import Path
|
|
from shutil import copy2
|
|
|
|
import openpyxl
|
|
|
|
|
|
DIRECTORY = Path(__file__).parent
|
|
SOURCE = DIRECTORY / "Plan-actividades-avance-2026-07-10-ajustado.xlsx"
|
|
TARGET = DIRECTORY / "Plan-actividades-avance-2026-07-16.xlsx"
|
|
|
|
|
|
def find_row(sheet, task):
|
|
for row in range(2, sheet.max_row + 1):
|
|
if sheet.cell(row, 1).value == task:
|
|
return row
|
|
raise ValueError(f"No se encontró la actividad: {task}")
|
|
|
|
|
|
copy2(SOURCE, TARGET)
|
|
workbook = openpyxl.load_workbook(TARGET)
|
|
sheet = workbook["Plan"]
|
|
|
|
sheet.cell(1, 8, "Horas al 16/07")
|
|
|
|
updates = {
|
|
"Integracion de plataformas Balam": (
|
|
0.20,
|
|
"Corte de avance al 16-jul; Etapa 0 en validación y Etapa 1 en curso",
|
|
),
|
|
"Etapa 0": (
|
|
0.91,
|
|
"22 h registradas; prototipo entregado y validación agendada para el 23-jul",
|
|
),
|
|
"Etapa 1": (
|
|
0.20,
|
|
"8 h registradas; 1 de 8 entregables terminado y plataforma base parcial",
|
|
),
|
|
"Backend base: autenticación, roles y bitácora de auditoría": (
|
|
0.30,
|
|
"API, health check y DbContext base listos; autenticación, roles y auditoría pendientes",
|
|
),
|
|
"Repositorio privado GitHub": (
|
|
0.90,
|
|
"Invitación recibida y acceso confirmado el 16-jul; falta validar permiso de escritura",
|
|
),
|
|
"Arquitectura multi-tenant (tenant_id + RLS)": (
|
|
0.25,
|
|
"Diseño técnico inicial; entidades tenant y políticas RLS pendientes",
|
|
),
|
|
"Cliente de la API de BIND (reintentos, OData, errores)": (
|
|
1.00,
|
|
"Terminado: cliente C# solo lectura, paginación, reintentos y cuota; 13/13 pruebas aprobadas",
|
|
),
|
|
"Modelo de facturas + migraciones + datos de prueba": (
|
|
0.10,
|
|
"Base operativa con SyncCheckpoint y AuditLog; modelo de facturas y migración pendientes",
|
|
),
|
|
"Demostración semanal (viernes) + reporte de horas": (
|
|
0.50,
|
|
"Corte del 16-jul preparado; control local mientras se habilita Jira",
|
|
),
|
|
}
|
|
|
|
for task, (progress, note) in updates.items():
|
|
row = find_row(sheet, task)
|
|
sheet.cell(row, 7, progress)
|
|
sheet.cell(row, 10, note)
|
|
|
|
stage1_row = find_row(sheet, "Etapa 1")
|
|
sheet.cell(stage1_row, 8, "=SUM(H12:H24)")
|
|
|
|
for row in range(2, sheet.max_row + 1):
|
|
sheet.cell(row, 7).number_format = "0%"
|
|
|
|
sheet.oddFooter.center.text = (
|
|
"Avance al 16-jul-2026 · Horas reconstruidas pendientes de conciliación con Jira"
|
|
)
|
|
|
|
# Conserva los estilos y usa el nombre de archivo como título impreso.
|
|
sheet.oddHeader.center.text = "Plan de actividades y avance · Proyecto Balam"
|
|
for cell in sheet[1]:
|
|
cell._style = copy(cell._style)
|
|
|
|
temporary = TARGET.with_suffix(".tmp.xlsx")
|
|
workbook.save(temporary)
|
|
|
|
check = openpyxl.load_workbook(temporary, data_only=False)["Plan"]
|
|
assert check.cell(find_row(check, "Etapa 1"), 7).value == 0.20
|
|
assert check.cell(
|
|
find_row(check, "Cliente de la API de BIND (reintentos, OData, errores)"), 7
|
|
).value == 1.00
|
|
assert check.cell(find_row(check, "Etapa 1"), 8).value == "=SUM(H12:H24)"
|
|
|
|
temporary.replace(TARGET)
|
|
print(f"Generado: {TARGET}")
|