Business Actions

No todo lo que el ERP hace es CRUD. Hay operaciones que cambian el estado de una entidad de manera no-trivial: autorizar una compra, cancelar una venta, timbrar un CFDI, recalcular saldos. Para eso existe el mecanismo de Business Actions.

Forma del endpoint

POST /api/v1/{modelo}/actions/{accion}            # batch (n registros)
POST /api/v1/{modelo}/{id}/actions/{accion}       # single (1 registro)

Ambos retornan el envelope estándar { data, meta, errors }.

Modos de ejecución

Cada acción declara cómo se ejecuta. Hay tres modos:

grid_action

La acción opera sobre una lista de IDs (típico de la grid del ERP: seleccionas varias filas y aplicas la acción). El body lleva un array.

curl -X POST http://localhost/api/v1/Compra/actions/autorizar_compra \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ids": [12345, 12346, 12347]}'

La respuesta es por registro:

{
  "data": {
    "results": [
      { "id": 12345, "ok": true },
      { "id": 12346, "ok": true },
      { "id": 12347, "ok": false, "errors": [{ "code": "INVALID_STATE", "message": "Compra ya autorizada" }] }
    ]
  },
  "meta": { "model": "Compra", "action": "autorizar_compra", "total": 3, "succeeded": 2, "failed": 1 },
  "errors": null
}

url_action

La acción opera sobre un registro identificado por path param. Útil cuando el flujo de la UI es "estoy en el detalle de X y oprimo el botón".

curl -X POST http://localhost/api/v1/Compra/12345/actions/cancelar_compra \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"motivo": "Duplicado"}'

native

La acción es autocontenida: no opera sobre un registro existente sino que el body define todos sus inputs (ej. un wizard de generación de un asiento contable). Más raro pero existe.

Acciones habilitadas hoy

ModeloAcciónModo
Compraautorizar_compragrid_action
Compracancelar_compragrid_action
Compracambiar_iniciadagrid_action

La hoja de ruta incluye acciones para Venta (timbrar_venta, cancelar_venta), Asociado (alta_de_empleado) y muchas más.

Manejo de errores en batch

En grid_action, una acción puede tener éxitos parciales: parte de los IDs procesados ok y parte con error. El status HTTP siempre es 200 si al menos uno se procesó. Esto facilita el flujo de la UI: mostrar la grid con un check verde por fila exitosa y una x roja por fila fallida.

Para detectar fallos totales, revisa meta.succeeded === 0.

const r = await fetch(`/api/v1/Compra/actions/autorizar_compra`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
  body: JSON.stringify({ ids: selectedIds }),
});
const json = await r.json();
const failures = json.data.results.filter((x) => !x.ok);
if (failures.length) {
  console.warn('Fallaron:', failures);
}

¿Cuándo es Business Action y cuándo CRUD?

OperaciónMecanismo
Cambiar el nombre de una MonedaPUT /Moneda/{id}
Cambiar el estado de una Compra a "autorizada"POST /Compra/{id}/actions/autorizar_compra

Como regla general: si solo cambia un campo plano, es CRUD. Si dispara efectos secundarios (genera pólizas, manda email, registra auditoría, valida flujo de aprobación), es una Business Action.