Saltar al contenido principal

trial

Ver en Git


Trial PDF Linking

Resumen​

Se extendieron los endpoints POST /activities/trial y PATCH /activities/trial para aceptar un campo opcional reports con un array de UUIDs de archivos. Esto permite vincular PDFs a un ensayo en la misma request de creación o actualización.


Cambios realizados​

Schema (features/trials/schema/trial_schema.py)​

  • TrialPostSchema: se agregó reports = fields.List(fields.UUID(), load_default=None, validate=validate.Length(max=50))
  • TrialPatchSchema: idem, más class Meta: unknown = EXCLUDE para ignorar campos extra del frontend (ej: isRowDisabled)

API (features/trials/api/trial.py)​

  • POST: extrae reports del body, si viene no-null llama a repo.bulk_link_reports(trial_uuid, reports, trial_name)
  • PATCH: extrae reports del body, si viene no-null busca el nombre del trial y llama a repo.replace_reports(trial_uuid, reports, trial_name)
  • Se eliminó el import de TrialReportRepo — todo opera dentro de TrialRepo (misma transacción)

Service (features/trials/service/trial_service.py)​

Se agregaron dos métodos a TrialRepo:

  • De-duplica UUIDs
  • Inserta en trial_reports con un WHERE NOT EXISTS para no crear duplicados contra links activos
  • Genera el nombre como {trial_name}_{1}, {trial_name}_{2}, etc.
  • Una sola query al DB

replace_reports(trial_uuid, file_uuids, trial_name)​

  • Hace soft-delete de todos los reports activos del trial (SET deleted_at = NOW())
  • Si hay UUIDs nuevos, llama a bulk_link_reports
  • Dos queries al DB (mínimo necesario)

Service (features/trials/service/trial_report_service.py)​

  • Se eliminaron bulk_link_reports, replace_reports y _validate_files_exist (duplicados, ahora viven en TrialRepo)
  • Se mantienen: get_by_trial, create_report, _soft_delete_all, delete_report (usados por el endpoint standalone POST/DELETE /activities/trial/reports)
  • get_by_trial ahora hace LEFT JOIN attachments para resolver el nombre real del archivo: COALESCE(a.filename, tr.name)

Contrato del frontend​

POST /activities/trial​

{
"name": "ensayo1",
"yeargroup": 2025,
"field_uuid": "8df6c91c-...",
"reports": ["010a1277-69e3-4d3f-91ca-eb0a5ff4356e", "otro-uuid"]
}
  • reports es opcional. Si no viene, el trial se crea sin reportes.
  • Máximo 50 UUIDs.
  • El nombre de cada report se genera como ensayo1_1, ensayo1_2, etc.

PATCH /activities/trial​

{
"uuid": "30a112c9-...",
"reports": ["ff42c99d-...", "3489b087-..."]
}
  • reports es opcional. Si no viene, los reportes existentes no se tocan.
  • Si viene como array vacío [], se eliminan (soft-delete) todos los reportes.
  • Si viene con UUIDs, se reemplazan todos los reportes anteriores por los nuevos.
  • Campos desconocidos del frontend (ej: isRowDisabled) se ignoran.

GET /activities/trial/reports?trial_uuid=...​

Respuesta:

{
"reports": [
{
"report_uuid": "aaa-...",
"file_uuid": "010a1277-...",
"name": "archivo_original.pdf",
"created_at": "2025-07-13T17:48:38.384555"
}
]
}
  • El name se resuelve con prioridad: nombre real del archivo en attachments.filename, o fallback al nombre secuencial generado (ensayo1_1).

Notas​

  • Todo opera dentro de la misma transacción de TrialRepo. Si falla la vinculación, se hace rollback del trial completo.
  • No se valida existencia de archivos contra la tabla attachments (los ensayos se crean offline).
  • La de-duplicación se resuelve en la misma query SQL (WHERE NOT EXISTS), sin queries extra.