Mutation GraphQL (scrittura)

Crea, aggiorna ed elimina tramite GraphQL

6 min di lettura
Stampa questa sezione

Dal piano Business, l'endpoint GraphQL offre 12 mutation di scrittura: creare, aggiornare ed eliminare su Ordini di lavoro, Asset e Ricambi, più adjustStock per i movimenti di magazzino. Le mutation passano dagli stessi servizi usati dall'applicazione, quindi log di audit, notifiche e generazione automatica dei riferimenti (WO-XX, ASS-XX, PART-XX) si comportano allo stesso modo. L'undicesima, addMeterReading, registra le letture dei contatori (ore di funzionamento, contapezzi): vedi sotto. La dodicesima, setPurchaseOrderErpReference, scrive su un ordine di acquisto il numero di documento del tuo ERP (solo con una chiave ad accesso FULL) e non genera alcun webhook, così il tuo ERP non riceve mai indietro la propria scrittura.

Mutazioni disponibili

  • 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 di input

Ogni mutazione ha un InputType solo con campi sicuri: companyId, sequenceNumber, reference e createdById vengono riempiti lato server. Si passano solo title, description, status, priority, assetId, locationId, ecc. Gli input dei ricambi accettano anche barcode, maxStockLevel, locationId e vendorId, e quantity/minQuantity/maxStockLevel ammettono decimali (es. 0.5). I campi enumerati sono verificati: priority deve essere LOW, MEDIUM, HIGH, CRITICAL; lo status di un ordine di lavoro OPEN, SCHEDULED, IN_PROGRESS, ON_HOLD, COMPLETED, VALIDATED, CANCELLED, CLOSED; lo status di un asset OPERATIONAL, DEGRADED, DOWN, MAINTENANCE, STANDBY, RETIRED. Qualsiasi altro valore viene rifiutato con BAD_REQUEST. Gli input dei ricambi accettano anche customReference — il vostro codice per il pezzo (per esempio quello dell'ERP), a cui part(barcode:) corrisponde poi. L'unicità non è imposta: garantirla spetta a voi.

Esempio: creare un ordine di lavoro

Creare un ordine di lavoro: mutation($i: WorkOrderCreateInput!) { createWorkOrder(input: $i) { id title reference status createdAt } } con le variabili {"i": {"title": "Pump #3 leak", "priority": "HIGH"}}

Regolare lo stock

Per modificare la quantità di un articolo, usa adjustStock con un delta con segno — negativo per consumare, positivo per ricevere. Aggiorna la quantità e scrive una riga di audit StockMovement in un'unica transazione atomica, e non lascia mai scendere lo stock sotto zero. Per un articolo gestito per ubicazione, passa locationId: il movimento viene applicato a quell'ubicazione e, senza, la chiamata viene rifiutata: errors[0].extensions.code è BAD_REQUEST ed extensions.reason è LOCATION_STOCK_REQUIRES_LOCATION. updatePart(quantity), invece, imposta un valore assoluto: per lo stesso motivo viene rifiutato su un articolo gestito per ubicazione e, negli altri casi, registra la differenza come movimento ADJUSTMENT. Puoi anche registrare la provenienza della merce: vendorId e documentNumber (numero di fattura o bolla del fornitore, max 64 caratteri) sono salvati sul movimento stesso, così lo storico mostra chi ha fornito e con quale documento. Entrambi sono facoltativi: un consumo ordinario non ne invia nessuno. Il fornitore deve appartenere alla tua azienda.

Registrare le letture dei contatori

addMeterReading registra una lettura su un contatore — ore di funzionamento, contapezzi, contachilometri, indicatore — così un sistema esterno (SCADA, gateway PLC, ERP) alimenta la manutenzione preventiva a contatore senza che nessuno ridigiti il numero. Trova prima l'id del contatore: query { meters(assetId: 7) { id reference name unit type lastReadingValue lastReadingDate } } Poi invia O value (il totale assoluto indicato dal contatore) O incrementValue (per esempio le ore di funzionamento dall'ultima lettura, che il server somma alla lettura precedente), esattamente uno dei due: mutation { addMeterReading(meterId: 12, value: 1250.5, date: "2026-09-25T06:00:00Z") { id value date isAnomaly } } date è facoltativa (ISO 8601, predefinita adesso) e può essere nel passato, mai nel futuro. Sui contatori RUNTIME e COUNTER, un valore inferiore alla lettura precedente viene rifiutato con BAD_REQUEST: dopo un azzeramento o una sostituzione del contatore, reinvialo con confirmRegression: true. La lettura passa dallo stesso servizio della schermata contatori dell'app: se è la più recente, trigger e manutenzione preventiva a contatore scattano esattamente come per una lettura inserita da un tecnico. Questa mutation richiede una chiave con accesso FULL.

Attribuzione

Ogni mutation viene eseguita come il proprietario della chiave — la persona per conto della quale agisce la chiave — con i suoi permessi, la sua visibilità sui dati e il suo nome nel registro di audit. Una chiave non approva mai un passaggio del flusso di lavoro, anche quando il suo proprietario potrebbe farlo.

Riprovare in sicurezza (Idempotency-Key)

Un timeout di rete non dice se una mutazione è stata eseguita. Invia un'intestazione Idempotency-Key (da 8 a 64 lettere, cifre o trattini: va bene un UUID) con ogni richiesta che scrive, e invia la STESSA chiave quando la riprovi. Per 7 giorni, un nuovo tentativo con la stessa chiave restituisce il risultato salvato della prima chiamata (la risposta contiene "Idempotent-Replayed: true") invece di eseguire di nuovo la mutazione: nessun secondo ordine di lavoro, nessun movimento di magazzino doppio.

  • Una chiave per scrittura. In una richiesta con più mutazioni con alias, ogni mutazione viene registrata separatamente con quella chiave. I valori inviati non vengono confrontati: la stessa chiave con valori diversi restituisce il risultato della prima chiamata.
  • Una chiamata fallita non lascia nulla: riprovarla con la stessa chiave la esegue di nuovo.
  • IDEMPOTENCY_KEY_REUSED — con questa chiave, lo stesso nome (campo o alias) ha già eseguito un'altra mutazione, oppure un altro chiamante ha usato la chiave: usa una nuova chiave per una nuova scrittura.
  • IDEMPOTENCY_IN_PROGRESS — la prima chiamata è ancora in corso: attendi qualche secondo e riprova.

Errori comuni

  • GRAPHQL_VALIDATION_FAILED — la forma dell'input non corrisponde (per esempio manca un titolo obbligatorio)
  • BAD_REQUEST — la convalida di un valore è fallita (per esempio un titolo oltre 500 caratteri)
  • FORBIDDEN — il tuo piano è inferiore a Business
  • NOT_FOUND — l'id non esiste o appartiene a un'altra azienda
  • FORBIDDEN — il livello di accesso della chiave è insufficiente (per esempio una chiave READ che chiama una mutation)

Suggerimento

Se ricevi un errore di serializzazione DateTime, controlla lo scalare DateTime del tuo client: FreeMaint emette stringhe ISO 8601.

Questa pagina è stata utile?