Mutaciones GraphQL (escritura)

Crea, actualiza y elimina mediante GraphQL

6 min de lectura
Imprimir esta sección

A partir del plan Business, el endpoint GraphQL ofrece 12 mutaciones de escritura: crear, actualizar y eliminar en Órdenes de trabajo, Activos y Repuestos, más adjustStock para los movimientos de inventario. Las mutaciones pasan por los mismos servicios que usa la propia aplicación, así que el registro de auditoría, las notificaciones y la generación automática de referencias (WO-XX, ASS-XX, PART-XX) se comportan igual. La undécima, addMeterReading, registra lecturas de contador (horas de funcionamiento, totalizadores): ver más abajo. La duodécima, setPurchaseOrderErpReference, escribe en una orden de compra el número de documento de su ERP (solo con una clave de acceso FULL) y no dispara ningún webhook, así que su ERP nunca recibe de vuelta su propia escritura.

Mutaciones disponibles

  • createWorkOrder(input) → WorkOrder
  • updateWorkOrder(id, input) → WorkOrder
  • deleteWorkOrder(id) → DeleteResult
  • createAsset(input) → Asset
  • updateAsset(id, input) → Asset
  • deleteAsset(id, force?) → DeleteResult
  • createPart(input) → Part
  • updatePart(id, input) → Part
  • deletePart(id, force?) → DeleteResult
  • adjustStock(id, quantity, reason?, vendorId?, documentNumber?) → Part
  • addMeterReading(meterId, value?, incrementValue?, date?, notes?, confirmRegression?) → MeterReading
  • setPurchaseOrderErpReference(id, erpReference?) → PurchaseOrder

Forma de entrada

Cada mutación tiene un InputType con campos seguros únicamente: companyId, sequenceNumber, reference y createdById se completan en el servidor. Solo hay que pasar title, description, status, priority, assetId, locationId, etc. Los inputs de pieza también aceptan barcode, maxStockLevel, locationId y vendorId, y quantity/minQuantity/maxStockLevel admiten decimales (p. ej. 0.5). Los campos enumerados se validan: priority debe ser LOW, MEDIUM, HIGH, CRITICAL; el status de una orden de trabajo OPEN, SCHEDULED, IN_PROGRESS, ON_HOLD, COMPLETED, VALIDATED, CANCELLED, CLOSED; el status de un activo OPERATIONAL, DEGRADED, DOWN, MAINTENANCE, STANDBY, RETIRED. Cualquier otro valor se rechaza con BAD_REQUEST. Las entradas de repuesto también aceptan customReference — su propio código para la pieza (el de su ERP, por ejemplo), con el que luego coincide part(barcode:). No se impone su unicidad: eso corre por su cuenta.

Ejemplo: crear una orden de trabajo

Crear una orden de trabajo: mutation($i: WorkOrderCreateInput!) { createWorkOrder(input: $i) { id title reference status createdAt } } con las variables {"i": {"title": "Pump #3 leak", "priority": "HIGH"}}

Ajustar el stock

Para cambiar la cantidad de una pieza, usa adjustStock con un delta con signo — negativo para consumir, positivo para recibir. Actualiza la cantidad y escribe una fila de auditoría StockMovement en una sola transacción atómica, y nunca deja que el stock baje de cero. Para una pieza cuyo stock se controla por ubicación, pase locationId: el movimiento se aplica a esa ubicación y, sin él, la llamada se rechaza: errors[0].extensions.code es BAD_REQUEST y extensions.reason es LOCATION_STOCK_REQUIRES_LOCATION. updatePart(quantity), en cambio, fija un valor absoluto: se rechaza en una pieza controlada por ubicación por el mismo motivo y, en los demás casos, registra la diferencia como un movimiento ADJUSTMENT. También puede registrar el origen de la mercancía: vendorId y documentNumber (n.º de factura o albarán del proveedor, máx. 64 caracteres) se guardan en el propio movimiento, de modo que el historial muestra quién suministró y con qué documento. Ambos son opcionales: un consumo normal no envía ninguno. El proveedor debe pertenecer a su empresa.

Registrar lecturas de contador

addMeterReading registra una lectura en un contador —horas de funcionamiento, totalizador, odómetro, indicador— para que un sistema externo (SCADA, pasarela de PLC, ERP) alimente el mantenimiento preventivo por contador sin que nadie vuelva a teclear la cifra. Primero obtenga el id del contador: query { meters(assetId: 7) { id reference name unit type lastReadingValue lastReadingDate } } Después envíe O BIEN value (el total absoluto que marca el contador) O BIEN incrementValue (por ejemplo las horas de funcionamiento desde la última lectura, que el servidor suma a la lectura anterior), exactamente uno de los dos: mutation { addMeterReading(meterId: 12, value: 1250.5, date: "2026-09-25T06:00:00Z") { id value date isAnomaly } } date es opcional (ISO 8601, por defecto ahora) y puede estar en el pasado, nunca en el futuro. En los contadores RUNTIME y COUNTER, un valor inferior a la lectura anterior se rechaza con BAD_REQUEST; tras una puesta a cero o una sustitución del contador, reenvíelo con confirmRegression: true. La lectura pasa por el mismo servicio que la pantalla de contadores de la aplicación: si es la más reciente, los disparadores y el mantenimiento preventivo por contador se activan exactamente igual que con una lectura introducida por un técnico. Esta mutación requiere una clave con acceso FULL.

Atribución

Cada mutación se ejecuta como el propietario de la clave —la persona en cuyo nombre actúa la clave—, con sus permisos, su visibilidad de datos y su nombre en el registro de auditoría. Una clave nunca aprueba un paso del flujo de trabajo, aunque su propietario sí pudiera hacerlo.

Reintentar sin riesgo (Idempotency-Key)

Un tiempo de espera de red agotado no indica si una mutación se ejecutó. Envíe un encabezado Idempotency-Key (de 8 a 64 letras, dígitos o guiones; un UUID sirve) con cada solicitud que escribe, y envíe la MISMA clave cuando la reintente. Durante 7 días, un reintento con la misma clave devuelve el resultado guardado de la primera llamada (la respuesta lleva "Idempotent-Replayed: true") en lugar de ejecutar la mutación otra vez: ni una segunda orden de trabajo, ni un movimiento de stock duplicado.

  • Una clave por escritura. En una solicitud con varias mutaciones con alias, cada mutación se registra por separado bajo esa clave. Los valores enviados no se comparan: la misma clave con otros valores devuelve el resultado de la primera llamada.
  • Una llamada que falló no guarda nada: reintentarla con la misma clave la ejecuta de nuevo.
  • IDEMPOTENCY_KEY_REUSED — con esta clave, el mismo nombre (campo o alias) ya ejecutó otra mutación, u otro llamante usó la clave: use una clave nueva para cada nueva escritura.
  • IDEMPOTENCY_IN_PROGRESS — la primera llamada sigue en curso: espere unos segundos y vuelva a intentarlo.

Errores comunes

  • GRAPHQL_VALIDATION_FAILED — la forma de la entrada no coincide (por ejemplo, falta un título obligatorio)
  • BAD_REQUEST — falló la validación de un valor (por ejemplo, un título de más de 500 caracteres)
  • FORBIDDEN — tu plan es inferior a Business
  • NOT_FOUND — el id no existe o pertenece a otra empresa
  • FORBIDDEN — el nivel de acceso de la clave es insuficiente (por ejemplo, una clave READ llamando a una mutación)

Consejo

Si recibe un error de serialización de DateTime, verifique el escalar DateTime de su cliente: FreeMaint emite cadenas ISO 8601.

¿Te resultó útil esta página?