SURCO · 05-data-model.md · 7 de 22

En esta página 1. Visión general 0%

05 — Modelo de datos — SURCO

1. Visión general

Dominio mínimo de cuaderno de campo L2:

EntidadPropósito
UserIdentidad + rol FARMER | TECHNICIAN
ParcelBancal / parcela de la explotación del farmer
FieldTaskTarea de campo con estado, vencimiento y asignación opcional

Base: PostgreSQL (Neon) · ORM: Prisma · IDs: cuid().

2. Enums

Role

ValorDescripción
FARMERTitular / planificador; crea tareas y parcelas
TECHNICIANEjecutor de campo; ve asignaciones

TaskStatus

ValorDescripción
PENDINGPlanificada; sin arrancar o sin técnico
ACTIVEEn curso (p. ej. al asignar técnico)
DONECompletada
CANCELLEDAnulada

3. Diagrama ER (texto)

User ─────────────┬────────── Parcel
  id              │            id
  email           │            name
  passwordHash    │            crop
  name            │            hectares
  role            │            farmerId ──► User.id

                  ├────────── FieldTask (as farmer)
                  │            id, code, title, notes
                  │            status, dueAt
                  │            farmerId ──► User.id
                  │            technicianId? ──► User.id
                  │            parcelId ──► Parcel.id

                  └────────── FieldTask (as technician)

4. Tablas / modelos Prisma

User

CampoTipoConstraints
idStringPK, cuid
emailStringunique
passwordHashStringbcrypt
nameString
roleRole
createdAtDateTimedefault now
updatedAtDateTimeupdatedAt
parcelsParcel[]
tasksFarmerFieldTask[]rel “FarmerTasks”
tasksTechFieldTask[]rel “TechTasks”

Parcel

CampoTipoConstraints
idStringPK
nameStringnombre de bancal (no unique global; lookup por farmer+name)
cropStringcultivo
hectaresFloat
farmerIdStringFK User
tasksFieldTask[]
createdAtDateTime

FieldTask

CampoTipoConstraints
idStringPK
codeStringunique, formato SU-MMDD-XXX
titleString
notesStringdefault ""
statusTaskStatusdefault PENDING
dueAtDateTime
farmerIdStringFK
technicianIdString?FK opcional
parcelIdStringFK
createdAt / updatedAtDateTime

5. Reglas de integridad y negocio

ReglaImplementación
Solo FARMER crea tareasController: role check → 403
Lista filtrada por rolwhere farmerId o technicianId
Acceso a detalleMismas condiciones o 403
Parcela al vuelofindFirst name+farmer; else create
Técnico por emailUser.role debe ser TECHNICIAN
Código únicounique en DB; generación en service
PasswordNunca en claro; solo passwordHash

6. Seed de referencia (2026-08-07)

EntidadDatos
FARMERInés Roura · campo@surco.agro · password123
TECHNICIANPol Vidal · tecnico@surco.agro · password123
Parcel 1Bancal Nord · Olivo arbequina · 2.4 ha
Parcel 2Surco Baix · Almendro · 1.1 ha
Tasks5 filas: riego ACTIVE, plagas PENDING, poda DONE, suelo PENDING, abonado ACTIVE

Códigos ejemplo: SU-0807-01SU-0807-05 (el prefijo de fecha depende del día de seed).

7. Contratos API ↔ modelo

POST /api/auth/login

In: { email, password }
Out: { accessToken, user: { id, email, name, role } }

GET /api/tasks

Out: FieldTask[] con parcel, farmer, technician.

GET /api/tasks/stats/summary

Out:

{
  "total": 5,
  "open": 4,
  "byStatus": { "PENDING": 2, "ACTIVE": 2, "DONE": 1, "CANCELLED": 0 }
}

POST /api/tasks

In:

{
  "title": "Riego gota a gota",
  "parcelName": "Bancal Nord",
  "crop": "Olivo arbequina",
  "dueAt": "2026-08-08T08:00:00.000Z",
  "notes": "2 h sector A",
  "technicianEmail": "tecnico@surco.agro"
}

Out: FieldTask creado (status ACTIVE si técnico OK).

PATCH /api/tasks/:id/status

In: { "status": "DONE" }
Out: FieldTask actualizado.

GET /api/tasks/:id

Out: un FieldTask con relaciones; 403/404 según acceso.

8. Índices y escalado (notas)

Necesidad futuraÍndice sugerido
Listas por farmer + due(farmerId, dueAt)
Listas por tech + status(technicianId, status)
Búsqueda por codeya unique en code

v1 no define índices extra más allá de PK/unique Prisma.

9. Privacidad de datos (enlace a doc 11)

  • Email y nombre son datos de cuenta demo.
  • Notas de tarea pueden contener info operativa de finca: no loguear bodies en claro en producción.
  • No se almacenan coordenadas GPS ni datos de salud vegetal sensibles más allá de texto libre.

10. Criterios de aceptación de datos

  1. Migración init aplica User, Parcel, FieldTask + enums.
  2. Seed es idempotente en la práctica (deleteMany + create).
  3. No se puede insertar FieldTask sin parcelId y farmerId válidos (FK).
  4. code único impide colisiones exactas (retry no implementado; probabilidad baja con random 100–999).