Skip to content

feat(mvp): backend master data and frontend architecture for AgroFlow - #47

Draft
facu030 wants to merge 15 commits into
mainfrom
feat/agroflow-mvp-end-to-end
Draft

facu030 wants to merge 15 commits into
mainfrom
feat/agroflow-mvp-end-to-end

Conversation

@facu030

@facu030 facu030 commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Objetivo

Dejar revisable el baseline de comportamiento aprobado para el MVP AgroFlow, la fundación backend y API de datos maestros, y la definición arquitectónica del frontend. Esta PR funciona como tracker en Draft para la Feature Branch Chain; no está lista para merge.

Trazabilidad

Resumen de lo implementado

Baseline y comportamiento

  • Se formalizaron OD-001..OD-013 como baseline de implementación en las capacidades OpenSpec existentes, sin crear una especificación normativa propiedad del frontend.
  • El baseline está aprobado por el usuario, pero el cambio OpenSpec sigue abierto: todavía no se consolidó en openspec/specs/.

Backend y API

  • Se agregaron modelos de ingenio, transportista, camión, finca, asociación, auditoría e idempotencia, con normalización, vigencia y aislamiento por ingenio en el modelo EF.
  • Se incorporó AgroFlowUser, claim/contexto efectivo de ingenio fail-closed, rechazo genérico de credenciales y políticas para los cuatro roles aprobados.
  • Se agregaron respuestas de error compatibles con ProblemDetails y políticas de idempotencia/auditoría en las mutaciones de datos maestros.
  • Se implementaron operaciones tenant-scoped de listado, detalle, alta, edición, inhabilitación/reactivación y asociaciones para transportistas, camiones y fincas.
  • Se documentaron en OpenAPI las rutas de datos maestros y sus DTOs/respuestas.

Frontend

  • Se documentó Next.js + TypeScript + App Router, feature-first, TanStack Query para estado remoto y Zustand solo para estado visual.
  • Se formalizaron el límite backend/frontend, el BFF con cookie opaca HttpOnly como dirección aceptada, permisos, aislamiento por ingenio, errores, pruebas y alcance del MVP.
  • No se incluye aplicación Next.js ejecutable ni pantallas funcionales todavía. OpenAPI tiene datos maestros; autenticación/sesión/contexto y consultas de turnos aún no tienen rutas.

Archivos y áreas incluidas

  • openspec/changes/mvp-baseline/, frontend-foundation/ y frontend-auth-readonly-slice/.
  • backend/Dsw2025Tpi.Domain/, Application/MasterData/, Data/ (modelos/contexto/repositorio), Api/ y Tests/.
  • docs/contracts/openapi.yaml y documentación de frontend, planificación y ADRs.
  • frontend/README.md únicamente; no hay código frontend ejecutable.

Exclusiones y limitaciones

  • Se excluyen los artefactos de migración y snapshots EF por instrucción del usuario; no se aplicó ninguna migración a SQL Server. El esquema de la base debe generarse/aplicarse y verificarse en un seguimiento antes de usar la API contra una base real.
  • Se excluyen .gitignore (cambio previo), .codegraph/, docs/contexto/ y odd/ (artefactos locales).
  • No se incluyen endpoints de turnos, dashboard, interrupciones ni n8n; tampoco la aplicación frontend ejecutable.
  • La autenticación web BFF y su ciclo operativo todavía requieren contrato e implementación.

Verificación ejecutada

  • dotnet test backend/Dsw2025Tpi.Tests/Dsw2025Tpi.Tests.csproj --configuration Release: 41 aprobadas, 0 fallidas, 0 omitidas.
  • dotnet build backend/Dsw2025Tpi.sln --configuration Release: 0 warnings, 0 errores.
  • Redocly: docs/contracts/openapi.yaml válido.
  • OpenSpec estricto: 13/13; enlaces Markdown locales: 76 archivos.
  • SQL Server y aplicación de migraciones: no verificados/diferidos.

Tamaño y cadena de revisión

El diff actual es de 75 archivos, 5.794 inserciones y 138 eliminaciones. Se solicita size:exception al mantenedor; la excepción no está aprobada. Esta PR permanece en Draft y no debe mergearse hasta que el tamaño sea aceptado y la cadena de implementación/aceptación esté completa.

Campo Valor
Cadena AgroFlow MVP Feature Branch Chain
Tracker PR Esta PR #47, Draft, destino main
Base main
Issue aprobado #46
Commits incluidos 683dfa6, a74d3ba, 4866ed5, 98e9622
Próximos slices UI Next.js ejecutable; autenticación/contexto y consultas de turnos; operación/n8n; SQL Server y aceptación integrada

Revisión

  • Revisar primero openspec/changes/mvp-baseline/, luego los modelos/servicios/endpoints de datos maestros y finalmente los ADR/alcance frontend.
  • Los tests actuales no sustituyen pruebas contra SQL Server, migraciones aplicadas, endpoints autenticados en hosting ni recorridos E2E frontend.

@facu030 facu030 added the type:feature New product capability or user-facing functionality label Sep 25, 2026
@github-actions github-actions Bot added area:docs-devops area:shared Trabajo transversal o de integración labels Sep 25, 2026
@github-actions github-actions Bot added area:backend area:frontend Trabajo de la aplicación frontend labels Sep 25, 2026
@facu030 facu030 changed the title feat(mvp): establish AgroFlow MVP baseline feat(mvp): backend master data and frontend architecture for AgroFlow Sep 25, 2026
@agustinvallante

agustinvallante commented Sep 26, 2026 •

Copy link
Copy Markdown
Owner

Revisión de la PR #47 (commit 98e9622). Gracias por avanzar el modelo, la API de datos maestros y el contrato. Es funcionalidad nueva con refactorización parcial, no sólo un cambio de nombres: incorpora rutas y lógica de catálogos/asociaciones, pero todavía no completa el refactor B01 ni el MVP. No hice cambios en tu rama.

Qué está verificado y qué falta

Comprobé en una copia aislada dotnet test backend/Dsw2025Tpi.sln --configuration Release: la solución compila y pasan 41/41 pruebas. Es un avance real. Sin embargo, MasterDataServiceTests usa un FakeMasterDataUnitOfWork y las pruebas de EF inspeccionan el modelo sin abrir SQL Server. Las migraciones incluidas no crean las nuevas tablas/columnas, y no hay pruebas HTTP integradas con una base real. Por tanto, no está demostrado que los endpoints sean operativos de punta a punta con el esquema versionado. En GitHub, este HEAD sólo muestra el check de etiquetado, no CI de build/test; la PR sigue Draft y con conflictos contra main.

Correcciones de comportamiento y procedimiento

  1. Conciliar el baseline con main. docs/planning/mvp-defaults.md y openspec/changes/mvp-baseline/ contradicen decisiones ya registradas en ADR-004/B00: un solo transportista activo por camión (OD-002), asignación de la próxima ventana sin preferencia del solicitante (OD-003), duración/cupo configurables por ingenio —30 min/2 camiones sólo como seed demo— (OD-004), fecha/hora de corte y carga estimada obligatorias (OD-005), y gestión de catálogos por operador y supervisor (OD-007). Rebasar sobre main, resolver los conflictos y alinear delta OpenSpec, planificación, OpenAPI y pruebas. Mantener explícitamente abiertas las decisiones que main aún no aprobó.
  2. Corregir asociación camión–transportista. MasterDataService.CreateAssociation/reactivación y el índice de Dsw2025TpiContext impiden duplicar el mismo par, pero permiten dos transportistas activos para un mismo camión. Aplicar validación en servicio y restricción única filtrada por asociación activa sobre (IngenioId, CamionId); probar creación/reactivación concurrente, historial inactivo y aislamiento entre ingenios.
  3. Corregir permisos e identidad. AgroFlowPolicies.MasterDataAndCapacityManagement debe incluir OPERADOR para mutaciones de catálogos, conforme a OD-007. Completar B03/B10: retirar el POST /api/auth/register público y el flujo Customer/customerId/USER heredado; no emitir sesión interna a un usuario sin rol admitido e ingenio. El seed actual conserva Admin sin IngenioId y no deja un usuario listo para operar estas rutas. Probar por HTTP 401, 403 y recurso ajeno con usuarios de dos ingenios, y preparar seed ficticio/reproducible.
  4. Completar persistencia y aceptación. Se entiende que las migraciones SQL se difirieron por indicación del usuario: resolverlas en un PR/issue dependiente de B02 y aplicarlas en una base limpia antes de considerar operativos los endpoints. Tras resolver conflictos, ejecutar checks del commit actual: OpenSpec, enlaces, OpenAPI, build/test .NET, pruebas HTTP y arranque/migración SQL con dos ingenios. Completar también paginación/filtrado de listados en la consulta a BD y la proyección B38 (camiones de un transportista con patente/tipo de flota).

Relación con las issues

Sí corresponde referenciar esta PR como avance parcial, por ejemplo con Refs #9, Refs #15, etc., para dejar trazabilidad. Lo que no corresponde todavía es usar Closes/Fixes, vincularla como cierre automático desde Development, ni mover issues a Done. Avanza parcialmente B00 (#7), B02–B05 (#9–#12), B10 (#14), B11–B24 (#15–#28) y B38 (#43), pero no cumple todos los criterios de aceptación de ninguna. B01 (#8) sigue pendiente porque permanecen Dsw2025Tpi y componentes e-commerce. No se implementan turnos, ventanas, dashboard, interrupciones, n8n ni frontend ejecutable; en frontend sólo se agregan ADRs/documentación.

La descripción actual dice Closes #46, pero #46 exige el MVP end-to-end y no está resuelta. Sugiero cambiarlo por Refs #46 o Part of #46 antes de fusionar para que GitHub no la cierre automáticamente. Las rutas de las issues eran propuestas hasta cerrar B00: si se mantienen /api/v1/drivers|trucks|farms, acordar esa decisión en contrato/backlog; la diferencia de nombre no es un defecto por sí sola.

@agustinvallante

Copy link
Copy Markdown
Owner

Revisión actualizada de #47: guía para adaptarla al MVP

@facu030 revisé esta PR contra main 3631d595, que ya integra #76 y #77, las specs canónicas, ADR-004/005/006 y las issues relacionadas. Cabeza revisada de #47: 98e9622.

Conclusión: hay trabajo backend aprovechable, pero todavía no está apta para mergear. No hay que desecharla ni implementar el MVP entero aquí: hay que convertirla en un incremento compatible, acotado y verificable. Esta guía actualiza la revisión anterior según los avances posteriores.

Lo aprovechable

  • Separación MasterDataController → MasterDataService → IMasterDataUnitOfWork/EF, sin reglas en frontend.
  • Contexto de ingenio desde identidad, rechazo de claims inválidos/ambiguos, búsquedas por ID e ingenio, validación de asociaciones entre recursos del mismo ingenio y conflictos genéricos sin revelar datos ajenos.
  • Gestión sin borrado físico, recibos de mutación y diseño transaccional para datos/auditoría/idempotencia. Son bases útiles, no cumplimiento completo demostrado.
  • Pruebas de dominio, contexto, aislamiento y replay; documentación de contrato compartido y límites de responsabilidad. Las ideas pueden reutilizarse sin adoptar Next.js ni agregar librerías automáticamente.
  • La descripción actual ya usa correctamente Refs/avances parciales, no cierre automático de [MVP][Épica] Entrega integral de AgroFlow (React/Vite + .NET + n8n) #46 y todos los endpoints.

1. Actualizar sobre main sin recuperar lo retirado — bloqueante

GitHub informa CONFLICTING; la combinación local también detecta conflictos de contenido, entidades agregadas por ambas ramas y archivos modificados que main retiró.

Dónde: solución/proyectos, Program.cs, autenticación/JWT, middleware, entidades/contexto, OpenAPI y README afectados.

Corrección: incorporar main y portar sólo el delta útil a backend/AgroFlow.Api, AgroFlow.Application, AgroFlow.Data, AgroFlow.Domain, AgroFlow.Tests y backend/AgroFlow.sln. Actualizar namespaces, referencias, DI, comandos y pruebas. Resolver entidad por entidad, no aceptar en bloque la versión de #47.

Conservar API de appointments, SQLite/migraciones/seed, cupos/transiciones, frontend React/Vite y CI. No recrear Dsw2025TpiContext, productos/pedidos/clientes, Customer, registro público heredado, seeds customers.json/admins.json ni claims customerId: #77 ya los retiró. Los nombres activos son AgroFlow; las menciones históricas a Dsw2025Tpi en el detector de la base anterior, sus tests y el runbook son intencionales y no deben borrarse con reemplazos globales.

2. Corregir las contradicciones documentales — bloqueante

Dónde: docs/planning/mvp-defaults.md, mvp-frontend-scope.md, cambios OpenSpec mvp-baseline, frontend-foundation, frontend-auth-readonly-slice, ADR-FE-*, docs/architecture/frontend/ y README.

Tema Propuesta de #47 a corregir Acuerdo vigente
OD-002 Varios transportistas activos por camión Sólo uno activo por camión; conservar historial.
OD-003 Ventana preferida opcional Próxima ventana compatible automática, sin preferencia.
OD-004 Duración fija de 30 minutos/configuración editable Duración/cupo por ingenio mediante datos de arranque. 30 minutos/2 camiones son seed demo, no constantes de negocio. Sin edición desde Configuración en MVP.
OD-005 Sin carga estimada Corte y carga estimada obligatorios; detalles de validación pendientes se acuerdan en B00.
OD-007 Mutaciones de maestros sólo supervisor/administrador Operador y supervisor pueden listar/crear/editar/inhabilitar los tres catálogos de su ingenio. Otros permisos siguen pendientes.
Frontend Next.js/App Router/BFF de Next.js aceptados React/TypeScript/Vite, ADR-005; evolucionar el dashboard existente.
Persistencia SQL Server canónico/SQLite sólo para tests SQLite académico; WAL condicionado a evidencia. PostgreSQL antes del primer cliente real, ADR-006.

Corregir también escenarios, diseño, tareas y referencias que repitan estas reglas, no sólo el resumen. La prioridad por corte/flota/orden de solicitud sirve; no introducir el redondeo a minuto del desempate sin decisión explícita.

Los defaults antiguos de esta draft no prevalecen sobre las decisiones consolidadas. Coordinar con B00 #7, respetar docs/planning/open-decisions.md y consolidar el comportamiento aprobado mediante OpenSpec. Idempotencia, permisos restantes, gestión de asociaciones, auditoría, métricas y canal tienen detalles pendientes: no resolverlos implícitamente.

ADR-FE-006 depende de un BFF de Next.js: replantear sesión/custodia de credenciales para la arquitectura elegida, sin imponer una alternativa de seguridad no acordada.

3. Integrar maestros con la persistencia real de turnos — bloqueante funcional

Dónde: antiguo Dsw2025Tpi.Data/Dsw2025TpiContext.cs, EfMasterDataUnitOfWork, entidades y DI. Base actual: backend/AgroFlow.Data/Appointments/AgroFlowDbContext.cs, backend/AgroFlow.Domain/Entities/ y backend/AgroFlow.Api/Program.cs; coordinar B02 #9/B03 #10.

#47 guarda maestros en SQL Server heredado; los turnos leen SQLite/AgroFlowDbContext. Sin integrar ambos, un alta de catálogo no habilita solicitar turnos con ese registro.

  • Evolucionar las entidades actuales, no crear una segunda definición. Conservar IDs/referencias, Ingenio.TimeZoneId e historial.
  • Mantener Finca.NormalizedCode: appointments compara códigos sin distinguir mayúsculas, pero feat(mvp): backend master data and frontend architecture for AgroFlow #47 sólo usa Code.Trim() y omite ese campo. Unificar alta/edición/unicidad/búsqueda para evitar códigos distintos que luego resulten indistinguibles.
  • Unificar normalización de DNI/teléfono/patente con el modelo/contrato actuales. Ejemplo: el normalizador WhatsApp de feat(mvp): backend master data and frontend architecture for AgroFlow #47 conserva +, el modelo actual usa dígitos normalizados; no mezclar representaciones en índices/consultas.
  • Revisar longitudes, tablas, relaciones e índices. Implementar las unicidades globales del MVP donde corresponda; la demo no las demuestra todas. Antes de endurecer restricciones, detectar colisiones existentes y acordar transición segura, sin borrar/recrear datos para que pase.
  • Incluir migraciones/snapshot SQLite del incremento ejecutable y probar base limpia, actualización desde demo, seed repetible y reinicio. La exclusión anterior de migraciones está declarada: si se mantiene, entregar sólo una fundación no habilitada, dependiente de B02; no declarar CRUD listo ni exponerlo sin esquema.

No activar WAL sin las pruebas/procedimientos de ADR-006 ni retirar LocalDemoDatabase.ResolveConnectionString y su protección contra iniciar otra base accidentalmente.

4. Impedir dos transportistas activos por camión — bloqueante

Dónde: MasterDataService.CreateAssociation, SetAssociationActive, interfaz/UoW y mapeo EF.

La consulta y el índice de #47 sólo evitan duplicar el mismo par (IngenioId, TransportistaId, CamionId). Dos transportistas distintos para el mismo camión pasan esa validación.

Consultar cualquier asociación activa del camión en alta y reactivación, excluyendo la propia cuando corresponda. Preservar el índice real de main: CamionId único filtrado por actividad; no reemplazarlo por unicidad del par. Conservar historial/reutilización del par según contrato y pertenencia de ambos extremos al ingenio.

Probar: segundo transportista, reactivación con otro vínculo activo, carreras de alta/reactivación, recursos inactivos/ajenos y turnos históricos intactos. Corregir también el comentario XML antiguo de TransportistaCamion en main, que aún dice que admite varias asociaciones activas pese a la restricción/spec.

5. Corregir roles e integrar Identity — bloqueante de seguridad/uso

Dónde: AgroFlowPolicies, MasterDataController, AuthenticateController, JwtTokenService, AgroFlowUser, AuthenticateContext, HttpTenantContext y arranque.

  • MasterDataAndCapacityManagement excluye OPERADOR y se usa para todas las mutaciones de maestros: separar permisos y permitir operador/supervisor para lo acordado. No extender automáticamente esa concesión a capacidad/asociaciones pendientes.
  • Conservar Identity y adaptar usuario activo/ingenio a B03 y al proveedor objetivo. SQLite no sustituye Identity. Seed ficticio reproducible de usuarios/roles por ingenio, sin recuperar secretos heredados.
  • El login aún consulta/devuelve datos de Customer, usa fallback USER y puede emitir token sin ingenio efectivo: retirar restos comerciales y exigir rol/contexto válidos según contrato. Usar sujeto estable de Identity para auditoría/idempotencia.
  • Preservar controles seguros de JWT incorporados en refactor(backend): B01 renombrar solución y retirar e-commerce heredado #77 y rechazo fail-closed; no recuperar claves inseguras.
  • Mantener LocalDemo explícito y limitado. No omitir autorización de maestros para hacerlos funcionar en demo ni confundir el perfil sin login con seguridad MVP. El recorrido autenticado debe integrarse y probarse o quedar como dependencia no habilitada.

Probar por HTTP: operador/supervisor permitidos, roles no autorizados, token ausente/expirado, usuario inactivo, claim ausente/ambiguo y accesos cruzados por ID con dos ingenios. Los tests del contexto no sustituyen estas pruebas.

6. Adaptar conflictos, idempotencia y auditoría a SQLite

Dónde: EfMasterDataUnitOfWork.Commit/IsUniqueConstraintViolation, MasterDataService.Mutate, filtro/middleware de errores y tests.

El detector sólo reconoce errores SQL Server 2601/2627 y nombres de sus índices. Adaptarlo al proveedor real, distinguiendo unicidad, FK, concurrencia y bloqueo, sin convertir carreras esperables en 500; revisar mapeos de fechas específicos.

La transacción es aprovechable, pero aprobar con B00/B05 la política de clave, alcance, hash, replay, vigencia y conflictos antes de imponer Idempotency-Key obligatorio a todos los consumidores. Probar con SQLite real, conexiones concurrentes y reinicio:

  • misma clave/entrada: mismo recibo, sin recurso/evento duplicados;
  • misma clave/otra entrada: conflicto sin cambios;
  • fallo de persistencia: sin dato/auditoría/clave de éxito parciales;
  • carreras de clave/identificador/asociación: respuesta contractual, sin éxito ficticio ni exposición ajena.

Conservar que el registro idempotente no guarda cuerpos personales completos. Coordinar eventos/correlación con OD-009/B05: insertar un evento no demuestra auditoría completa.

7. Ampliar el OpenAPI actual, sin degradar turnos — bloqueante

Dónde: docs/contracts/openapi.yaml, DTOs, controladores, middleware y tests de contrato; B00/B04/B10.

#47 propone 0.1.0 de maestros; main contiene 0.3.0 de demo. Reconciliar conservando /health, POST/GET /api/v1/appointments, detalle y /transitions, filtros, estados, corte/carga y errores. No retroceder versión ni aplicar seguridad global a la demo accidentalmente. Cambios MVP de seguridad/DTO deben declararse y coordinarse con frontend/n8n.

Los paths /api/v1/drivers, /trucks, /farms y /driver-truck-associations son propuestas evaluables, no aprobados por existir aquí; las rutas de títulos antiguos tampoco obligan a cambiar por inercia. Acordar una superficie en B00, incluyendo autenticación/contexto/permisos.

Preservar AppointmentProblemDetails; alinear application/problem+json, códigos y trazabilidad. El DTO genérico name/code/identifier/secondaryIdentifier está documentado, pero sobrecarga significados: evaluar DTOs explícitos con el responsable del contrato, no inventarlos en el cliente.

Los listados filtran/ordenan en DB, pero no paginan: agregar paginación antes de materializar, según B11 #15 y equivalentes, con parámetros/orden acordados. Para B38 #43, el listado genérico de UUIDs no cubre camiones de un transportista con patente/flota/estado: agregar la proyección acordada sin N+1 o mantener B38 fuera del incremento, sin declararla cumplida.

8. Documentar continuidad frontend, no una reconstrucción

Dónde: README frontend, ADRs/documentos frontend y planificación añadidos.

Usar como base real frontend/src/composition/container.ts, infrastructure/http/ApiClient.ts, HttpTurnoRepository, DTO/mappers, repositorios de dominio, hooks/vistas/tests y F01–F09. Distinguir turnos HTTP integrados de panel/catálogos aún mock.

Esta PR no agrega frontend ejecutable: no se le exige construir todas las pantallas para aceptar un incremento backend acotado. Sí reformular documentación incompatible. TanStack Query/Zustand y otra topología de sesión requieren evaluación, no son obligaciones heredadas de esta rama.

9. Evidencia y alcance antes de pasar a Ready

En #47 sólo figura el check de etiquetas, no la CI actual. Las 41 pruebas declaradas son de la base antigua: MasterDataServiceTests usa UoW falso y EfModelAndMigrationVerificationTests inspecciona metadatos SQL Server, sin aplicar migraciones ni arrancar HTTP. No demuestran integración con main. Esta auditoría contrastó código/documentación/conflictos y evidencia de CI; no afirma que se haya ejecutado una versión corregida de #47.

La CI de main pasó con 112 tests backend y 37 frontend. Conservar esas suites y sumar las del incremento, sin reducirlas a los 41 antiguos. Ejecutar:

dotnet restore backend/AgroFlow.sln
dotnet build backend/AgroFlow.sln --configuration Release --no-restore
dotnet test backend/AgroFlow.sln --configuration Release --no-build --no-restore
cd frontend
npm ci
npm run typecheck
npm run lint
npm test
npm run build

Además, validaciones OpenSpec/OpenAPI/enlaces de .github/workflows/ci.yml, migraciones/seed/reinicio y HTTP autenticado real. Recorrido mínimo: crear maestros/asociación por API, pedir turno con esas referencias, consultar/avanzar/cancelar y verificar historial/cupo; repetir con inhabilitados y otro ingenio. No exige implementar todo dashboard/interrupciones/n8n aquí.

Actualizar título/cuerpo/tareas con resultado entregado, evidencia y dependencias. Mantener Refs para lo parcial; no declarar #46 ni G01–G12 completas. Reevaluar tamaño/excepción después del recorte; no condicionar esta PR a completar una cadena Next.js/SQL Server obsoleta.

Orden de corrección recomendado

  1. Alinear alcance con ADR-004/005/006; cerrar en B00 sólo decisiones que bloquean el incremento.
  2. Incorporar main y preservar B01/demo/frontend/CI; portar servicios al modelo AgroFlow/SQLite.
  3. Integrar esquema e Identity con B02/B03, o separar fundación no habilitada con dependencia explícita. No publicar endpoints a medias.
  4. Corregir asociaciones/roles/normalización/conflictos; alinear OpenAPI y consumidores afectados.
  5. Ejecutar CI y pruebas SQLite/HTTP/integración, actualizar trazabilidad y pedir nueva review.

Recomendación: rescatar #47 como incremento backend de maestros compatible o dividir el delta en porciones revisables sobre main. No fusionar el baseline obsoleto ni reemplazar lo que ya funciona. Con estas correcciones y evidencia podrá reevaluarse; la cabeza revisada todavía no se aprueba.

Preserve the AgroFlow appointments demo, SQLite migrations, React/Vite frontend and CI while porting the useful master-data foundation. Keep catalog HTTP routes disabled pending B00/B02/B03/B05 and align planning with ADR-004/005/006.

Verified: 206 backend tests, 37 frontend tests, strict OpenSpec 17/17, OpenAPI lint and local Markdown links. Unrelated local runtime ignores and tracking artifacts are excluded.
Record the original PR47 history alongside the verified AgroFlow/SQLite foundation after a per-file audit and normal merge resolution. Legitimate backend and documentation work is already ported; superseded platform choices and duplicate legacy sources remain retired.

The complete tree is identical to 15fb3a0. Verified again: 206 backend tests, 37 frontend tests, OpenSpec 17/17, OpenAPI lint and local links. Catalog endpoints remain disabled pending the documented MVP dependencies.
@facu030

facu030 commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator Author

Actualización de PR #47 según la guía MVP

@agustinvallante, gracias por la guía actualizada. Conservamos el trabajo aprovechable y lo adaptamos a main (3631d595, con #76 y #77), sin reconstruir el MVP ni recuperar lo retirado.

Se eligió la alternativa de fundación compatible, todavía no habilitada. Esta actualización no presenta CRUD de maestros operativo ni aceptación del MVP completo. La rama está publicada en efe8c7c, con CI y Required checks en verde. El commit 15fb3a0 integra main y las correcciones; efe8c7c reconcilia la historia original mediante merge normal y auditoría por archivo, sin reescritura remota ni cambios al contenido verificado.

Respuesta a los puntos 1–9

  1. Estructura actual y retiro del legado. La fundación está en backend/AgroFlow.Api, AgroFlow.Application, AgroFlow.Data, AgroFlow.Domain, AgroFlow.Tests y AgroFlow.sln, con namespaces y referencias adaptados. Se conservaron servicios, DTO, interfaces, controlador preparatorio y pruebas útiles. Se preservaron appointments, migraciones/seed SQLite, cupos/transiciones, protección de selección de base, frontend React/Vite y CI de main. No se recuperaron Dsw2025TpiContext, ecommerce, Customer, registro público, seeds comerciales ni customerId. Las menciones históricas intencionales de DSW siguen en detector, pruebas y runbook.

  2. Documentación y acuerdos vigentes. README, planificación, ADR-FE y propuestas frontend distinguen decisiones vigentes de antecedentes supersedidos. Se respeta una asociación activa por camión, ventana compatible automática sin preferencia, corte/carga obligatorios, duración/cupo por ingenio desde datos de arranque y catálogos para operador/supervisor. Los 30 minutos/2 camiones siguen siendo seed demo, no constantes de negocio. React/Vite y SQLite académico prevalecen sobre Next/SQL Server; PostgreSQL es futuro y no se activó WAL. No se agregó redondeo al minuto ni se decidió una sesión/BFF o nuevas librerías. OD-006, permisos restantes, campos, auditoría y métricas siguen abiertos.

  3. Modelo y persistencia compatibles, no un segundo catálogo operativo. EfMasterDataUnitOfWork se portó sobre AgroFlowDbContext, conservando entidades, identificadores, Ingenio.TimeZoneId y Finca.NormalizedCode. Se corrigieron la construcción y consulta normalizada de fincas, conservando Code visible; la actualización de transportistas valida todos los valores antes de modificar propiedades. DNI sigue la regla canónica de solo dígitos; WhatsApp conserva la representación de comparación de main, sin convertir el delta pendiente de OD-013 en aprobación. Los ocho CreatedAtUtc/InactivatedAtUtc de cuatro entidades se ignoran explícitamente porque faltan sus columnas. No se suprimen advertencias EF: la prueba HasPendingModelChanges() comprueba compatibilidad con el snapshot. No se añadieron migraciones de maestros ni se afirma auditoría durable; esquema completo, unicidades globales/transición segura e Identity MVP quedan en B02/B03. Las migraciones existentes y el reinicio de la demo siguen probados.

  4. Asociación activa única. CreateAssociation y SetAssociationActive comprueban cualquier asociación activa del camión, excluyendo la propia al reactivar. Se preservó el índice SQLite único filtrado de CamionId, pertenencia de recursos, inactividad e historial, y se corrigió el comentario de dominio incompatible. No se sustituyó por unicidad del mismo par ni se habilitaron permisos externos de asociaciones pendientes. Estas comprobaciones no equivalen a un CRUD HTTP concurrente completo.

  5. Roles e Identity, con límites explícitos. La política preparatoria de catálogos admite operador/supervisor; operaciones no aprobadas fallan cerradas. El login rechaza cero/múltiples roles y roles no admitidos antes de emitir JWT. Se mantienen Identity/JWT y sus validaciones seguras; IdentityUser sigue operativo y AgroFlowUser permanece preparatorio, sin registrarlo como si B03 estuviera resuelto. HttpTenantContext rechaza claims ausentes/ambiguos. MasterDataController tiene [NonController] y la fundación no está registrada en DI: no se añadió bypass de maestros en LocalDemo. Seed de usuarios/roles, usuario activo, contexto efectivo y recorrido autenticado con dos ingenios siguen pendientes de integración B03.

  6. Errores SQLite, auditoría e idempotencia. El adaptador reconoce UNIQUE/PK por códigos extendidos del proveedor y no confunde FK, CHECK o BUSY/LOCKED con duplicados. Se añadieron pruebas SQLite reales de esas clases de error, incluido bloqueo acotado en una base temporal aislada. Se conservaron recibos y lógica transaccional preparatoria, sin guardar cuerpos personales completos. Acceder a auditoría/idempotencia sin las entidades del esquema falla cerrado. No se declara replay durable, atomicidad dato/evento/clave probada con SQLite ni un Idempotency-Key público obligatorio: esa política y el esquema requieren B00/B02/B05 y OD-006/OD-009.

  7. Contrato activo sin degradar turnos. OpenAPI conserva 0.3.0, /health, POST/GET appointments, detalle/transiciones, filtros/estados/corte/carga y security: [] por operación demo. Se preservan AppointmentProblemDetails del backend y el esquema ProblemDetails existente. Rutas/DTO/headers de maestros se separaron en docs/contracts/master-data-foundation-proposal.md, no como API habilitada. Se conserva la proyección interna de camiones con patente/flota/estado, pero no se declara B38 terminado. Rutas públicas, DTO explícitos, paginación y permisos quedan pendientes de B00 y del incremento ejecutable.

  8. Continuidad frontend. Se conserva el código React/TypeScript/Vite de main, composición, ApiClient, HttpTurnoRepository, DTO/mappers, hooks/vistas y pruebas. Turnos HTTP se distingue de panel/catálogos y otros recorridos todavía mock. No se añadieron pantallas ni se impuso Next, TanStack Query, Zustand o una nueva custodia de credenciales.

  9. Evidencia actual y aceptación acotada. Las 41 pruebas antiguas ya no describen el candidato. La verificación local y técnica independiente del contenido publicado pasó con 206/206 backend, sin omitidas; 37/37 frontend; OpenSpec estricto 17/17; Redocly válido y enlaces válidos en 106 archivos. Restore/build Release pasaron sin errores ni warnings; también typecheck/lint/build frontend. CI del SHA publicado, dependency review y Required checks terminaron correctamente. Persisten 5 warnings de lint, el aviso heredado de /health sin 4XX y un advisory npm alto heredado, no remediado. No se acredita el recorrido maestros/asociación por API → turno con Identity real ni G01–G12 completos.

Siguiente revisión

La PR continúa Draft, con trazabilidad parcial mediante Refs, sin cerrar #46 ni declarar B02/B03/B05/B38 completos. El tamaño y la eventual división/excepción siguen siendo una decisión de revisión, no una aprobación implícita por tener CI verde.

La descripción inicial aún contiene Next/SQL y cifras anteriores; este comentario registra el estado actual, no modifica ese texto. La matriz documental inicial también contiene un snapshot intermedio de pruebas, no el resultado final anterior.

¿Puedes reevaluar este incremento como fundación compatible no habilitada y señalar las dependencias que deben quedar en los siguientes slices? No estoy solicitando aprobación del MVP completo ni merge.

@agustinvallante

Copy link
Copy Markdown
Owner

Revisión del candidato actualizado — aún requiere correcciones puntuales

@facu030 revisé efe8c7c8c00d8faad5c4c912c6adf5e57b3d1ea1 contra main 3631d595, tu comentario de actualización y la guía anterior. La alternativa de fundación compatible, no habilitada, es un alcance razonable: no te pido completar el CRUD/MVP entero para integrar esta PR.

Avances que sí quedaron bien

  • Estructura AgroFlow, sin recuperar e-commerce; conservación del frontend React/Vite y la demo SQLite.
  • MasterDataController con [NonController] y servicios preparatorios sin registro en DI: no hay nuevas rutas públicas a medio implementar.
  • Operador/supervisor para los catálogos acordados, asociación activa única por camión, normalización de fincas y distinción de restricciones SQLite.
  • OpenAPI 0.3.0 y las cinco operaciones demo preservadas; propuestas de maestros separadas del contrato activo.
  • Identity permanece como andamiaje y el esquema/segregación MVP sigue explícitamente pendiente de B02/B03. No se exige retirar los Ignore ni agregar ahora migraciones incompletas.

Evidencia de esta revisión

Ejecuté nuevamente dotnet test backend/AgroFlow.sln --configuration Release sobre una copia aislada: 206 aprobadas, 0 fallidas, 0 omitidas. Comprobé además la CI del candidato: backend 206/206, frontend 37/37 y checks de contrato/especificaciones en verde. El verificador local de enlaces también pasa. No modifiqué tu rama.

La suite verde no cubre los dos casos siguientes, que reproduje adicionalmente con el adaptador compilado:

1. [P2] Listado de asociaciones ordena por una propiedad ignorada por EF

Dónde: backend/AgroFlow.Data/Repositories/EfMasterDataUnitOfWork.cs, ListAssociations, línea 32; y backend/AgroFlow.Data/Appointments/AgroFlowDbContext.cs, mapeo de TransportistaCamion.

AgroFlowDbContext ignora expresamente CreatedAtUtc, pero la consulta hace .OrderBy(x => x.CreatedAtUtc). Al ejecutarla con el proveedor SQLite, EF lanza InvalidOperationException indicando que no puede traducir ese miembro no mapeado. Falla incluso antes de leer filas; no es un problema de una base sin seed.

Corrección: mientras B02 no migre esos metadatos, ordenar por columnas realmente persistidas con desempate estable —por ejemplo Id para esta lectura preparatoria, sin prometer orden cronológico— o dejar explícitamente deshabilitada esa operación con una excepción de dependencia clara. No usar AsEnumerable() para ocultar el fallo, ni quitar Ignore sin esquema/migración.

Prueba a agregar: ejecutar ListAssociations contra SQLite con las migraciones vigentes, no contra el UoW falso: lista vacía, filas activas/inactivas, filtro de ingenio y orden estable. Puede incluirse en EfMasterDataUnitOfWorkTests.cs/MasterDataProjectionTests.cs. Mantener el test HasPendingModelChanges().

2. [P2] La proyección permite datos de un camión de otro ingenio

Dónde: backend/AgroFlow.Data/Repositories/EfMasterDataUnitOfWork.cs, ListActiveTrucksForTransportista, líneas 35–44, y backend/AgroFlow.Tests/MasterDataProjectionTests.cs.

La consulta comprueba al transportista y filtra el ingenio de la asociación, pero el join sólo usa CamionId; no exige truck.IngenioId == ingenioId. El esquema de demo no impide todos los vínculos cruzados: pude insertar en una SQLite migrada dos ingenios ficticios, un transportista del A, un camión del B y una asociación que declara A. La proyección de A devolvió la patente del camión B.

Hoy no constituye una filtración HTTP porque el controlador no está habilitado, pero sí es un defecto del fundamento de lectura que luego reutilizaremos.

Corrección: filtrar también el ingenio del camión en el join/where; si la consulta puede reutilizarse sin la comprobación previa, conservar igualmente el alcance del transportista. Dejar las FK compuestas/integridad completa como parte de B02, sin alterar a ciegas las migraciones demo para resolver este filtro.

Prueba a agregar: asociación inconsistente A→camión B debe devolver cero filas; las asociaciones válidas de A siguen devolviendo patente/flota/actividad y el transportista ajeno sigue sin revelar datos. El test existente sólo usa asociaciones consistentes y no detecta este caso.

3. Reconciliar descripción y evidencia documental del candidato

Dónde: título/cuerpo de esta PR; docs/planning/pr47-mvp-guide-alignment.md (fila 9), openspec/changes/reconciliar-pr47-con-mvp/design.md (Evidencia), proposal.md y tasks.md.

El comentario nuevo aclara correctamente la entrega, pero el cuerpo principal todavía describe Next.js, SQL Server, rutas maestras operativas, nombres DSW y 41 pruebas. Los documentos también presentan el snapshot intermedio de 177/205, 28 fallas y lock excluido sin distinguirlo claramente del candidato final.

  • Reemplazar el cuerpo por el alcance real: fundación preparatoria no habilitada, versiones AgroFlow/SQLite/React-Vite y dependencias B00/B02/B03/B05; mantener Refs, no cierres parciales.
  • Registrar evidencia final con SHA/comandos/enlace CI; si se conserva el resultado intermedio, marcarlo como histórico, con fecha/revisión, no como estado actual. Retirar referencias internas a “padre/unidad T3/T5” de la documentación para compañeros.
  • Tras agregar las regresiones anteriores, actualizar el total observado y las tareas de verificación realmente completadas. No marcar B03, CRUD, B38 ni G01–G12 completos, ni archivar propuestas pendientes de OD-013.
  • Cuando esté listo, pasar de Draft a Ready y resolver la justificación de tamaño/recorte con el mantenedor. El comentario de actualización no solicita merge y la descripción actual tampoco lo declara listo.

Qué puede quedar para los próximos incrementos

Schema/migraciones de auditoría e idempotencia y metadatos, unicidades globales y migración segura (B02); usuarios activos, sujeto estable de Identity, ingenio efectivo y recorrido autenticado real (B03/B10); política durable de reintentos/auditoría (B00/B05); rutas/DTO/paginación/CRUD público y B38. Estos pendientes no bloquean por sí solos una fundación explícitamente deshabilitada; no registrar servicios ni quitar [NonController] para esta entrega.

Resultado: no apruebo ni integro esta cabeza todavía. Corregidos los dos casos reproducidos y la coherencia documental, puede reevaluarse como incremento técnico acotado; no hace falta reconstruir el trabajo ya corregido.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:backend area:docs-devops area:frontend Trabajo de la aplicación frontend area:shared Trabajo transversal o de integración type:feature New product capability or user-facing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants