GraphQL-мутации (запись)

Создавайте, обновляйте и удаляйте через GraphQL

Чтение 6 мин
Распечатать этот раздел

Начиная с тарифа Business, эндпоинт GraphQL поддерживает 12 мутаций записи: создание, изменение и удаление для заявок, оборудования и запчастей, плюс adjustStock для складских движений. Мутации проходят через те же сервисы, что и само приложение, поэтому журнал аудита, уведомления и автогенерация номеров (WO-XX, ASS-XX, PART-XX) работают одинаково. Одиннадцатая, addMeterReading, записывает показания счётчиков (моточасы, счётчики изделий) — см. ниже. Двенадцатая, setPurchaseOrderErpReference, записывает в заказ на закупку номер документа вашей ERP (только ключом с доступом FULL) и не вызывает ни одного вебхука, поэтому ваша ERP никогда не получает собственную запись обратно.

Доступные мутации

  • 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

Введите форму

Каждая мутация имеет InputType только с безопасными полями — companyId, sequenceNumber, reference и createdById заполняются на стороне сервера. Вы передаёте только title, description, status, priority, assetId, locationId и т. д. Входные данные запчасти также принимают barcode, maxStockLevel, locationId и vendorId, а quantity/minQuantity/maxStockLevel допускают дробные значения (например, 0.5). Перечисляемые поля проверяются: priority должен быть одним из LOW, MEDIUM, HIGH, CRITICAL; status наряд-заказа — одним из OPEN, SCHEDULED, IN_PROGRESS, ON_HOLD, COMPLETED, VALIDATED, CANCELLED, CLOSED; status актива — одним из OPERATIONAL, DEGRADED, DOWN, MAINTENANCE, STANDBY, RETIRED. Любое другое значение отклоняется с BAD_REQUEST. Входные данные запчасти принимают также customReference — ваш собственный код детали (например, из ERP), с которым затем сопоставляется part(barcode:). Уникальность не навязывается: обеспечить её — ваша задача.

Пример: создать заказ на работу

Создать заявку: mutation($i: WorkOrderCreateInput!) { createWorkOrder(input: $i) { id title reference status createdAt } } с переменными {"i": {"title": "Pump #3 leak", "priority": "HIGH"}}

Корректировка запаса

Чтобы изменить количество детали, используйте adjustStock со знаковой дельтой — отрицательной для расхода, положительной для прихода. Он обновляет количество и записывает строку аудита StockMovement в одной атомарной транзакции и никогда не позволяет запасу опуститься ниже нуля. Для детали, запас которой учитывается по местам хранения, передайте locationId: движение применяется к этому месту, а без него вызов отклоняется — errors[0].extensions.code равен BAD_REQUEST, а extensions.reason — LOCATION_STOCK_REQUIRES_LOCATION. updatePart(quantity), напротив, задаёт абсолютное значение: на детали с учётом по местам хранения он отклоняется по той же причине, а в остальных случаях записывает разницу как движение ADJUSTMENT. Можно также зафиксировать происхождение товара: vendorId и documentNumber (номер счёта или накладной поставщика, не более 64 символов) сохраняются на самом движении, поэтому история показывает, кто поставил и по какому документу. Оба поля необязательны — обычное списание не передаёт ни одного. Поставщик должен принадлежать вашей компании.

Запись показаний счётчиков

addMeterReading записывает показание счётчика — моточасы, счётчик изделий, одометр, датчик, — чтобы внешняя система (SCADA, шлюз ПЛК, ERP) питала обслуживание по наработке без ручного ввода цифр. Сначала найдите id счётчика: query { meters(assetId: 7) { id reference name unit type lastReadingValue lastReadingDate } } Затем отправьте ЛИБО value (абсолютное значение, которое показывает счётчик), ЛИБО incrementValue (например, моточасы с момента последнего показания — сервер прибавит их к предыдущему показанию), ровно одно из двух: mutation { addMeterReading(meterId: 12, value: 1250.5, date: "2026-09-25T06:00:00Z") { id value date isAnomaly } } date необязателен (ISO 8601, по умолчанию — текущий момент) и может быть в прошлом, но не в будущем. Для счётчиков RUNTIME и COUNTER значение меньше предыдущего показания отклоняется с BAD_REQUEST — после сброса или замены счётчика отправьте его повторно с confirmRegression: true. Показание проходит через тот же сервис, что и экран счётчиков в приложении: если оно самое последнее, триггеры и обслуживание по наработке срабатывают точно так же, как для показания, введённого техником. Для этой мутации нужен ключ с доступом FULL.

Атрибуция

Каждая мутация выполняется от имени владельца ключа — того, от чьего имени действует ключ, — с его разрешениями, его видимостью данных и его именем в журнале аудита. Ключ никогда не утверждает шаг рабочего процесса, даже если его владелец мог бы это сделать.

Безопасный повтор (Idempotency-Key)

Истёкший сетевой тайм-аут не говорит, выполнилась ли мутация. Передавайте заголовок Idempotency-Key (от 8 до 64 букв, цифр или дефисов — подойдёт UUID) в каждом запросе, который что-то записывает, и при повторе отправляйте ТОТ ЖЕ ключ. В течение 7 дней повтор с тем же ключом возвращает сохранённый результат первого вызова (в ответе есть "Idempotent-Replayed: true") вместо повторного выполнения мутации: ни второго наряда, ни двойного движения запасов.

  • Один ключ на одну запись. В запросе с несколькими мутациями под псевдонимами каждая мутация сохраняется под этим ключом отдельно. Отправленные значения не сравниваются: тот же ключ с другими значениями возвращает результат первого вызова.
  • Неудачный вызов ничего не сохраняет: повтор с тем же ключом выполнит его снова.
  • IDEMPOTENCY_KEY_REUSED — с этим ключом то же имя (поле или псевдоним) уже выполнило другую мутацию, либо ключ использовал другой вызывающий: для новой записи используйте новый ключ.
  • IDEMPOTENCY_IN_PROGRESS — первый вызов ещё выполняется: подождите несколько секунд и повторите.

Распространенные ошибки

  • GRAPHQL_VALIDATION_FAILED — форма входных данных не совпадает (например, отсутствует обязательный title)
  • BAD_REQUEST — проверка значения не пройдена (например, title длиннее 500 символов)
  • FORBIDDEN — ваш тариф ниже Business
  • NOT_FOUND — id не существует или принадлежит другой компании
  • FORBIDDEN — уровень доступа ключа недостаточен (например, ключ READ вызывает mutation)

Совет

Если вы получаете ошибку сериализации DateTime, проверьте скаляр DateTime вашего клиента — FreeMaint генерирует строки ISO 8601.

Эта страница была полезна?