@hubex/mcp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +54 -0
- package/CONNECTING.md +260 -0
- package/README.md +266 -0
- package/dist/auth.js +226 -0
- package/dist/config.js +120 -0
- package/dist/generated/manifest.js +3643 -0
- package/dist/guides/field-notes.json +27 -0
- package/dist/guides/loader.js +32 -0
- package/dist/guides/service-map.js +6 -0
- package/dist/http.js +93 -0
- package/dist/index/store.js +134 -0
- package/dist/index/types.js +1 -0
- package/dist/index.js +20 -0
- package/dist/paths.js +20 -0
- package/dist/pii/fields.js +100 -0
- package/dist/pii/mask.js +50 -0
- package/dist/pii/strategies.js +88 -0
- package/dist/schema/build-index.js +67 -0
- package/dist/schema/deref.js +87 -0
- package/dist/schema/describe.js +65 -0
- package/dist/server.js +62 -0
- package/dist/token-prompt.js +41 -0
- package/dist/tools/curated.js +151 -0
- package/dist/tools/discovery.js +187 -0
- package/dist/tools/guides.js +126 -0
- package/dist/tools/registry.js +37 -0
- package/dist/tools/request.js +170 -0
- package/dist/tools/types.js +1 -0
- package/docs/guides/assets.md +334 -0
- package/docs/guides/attributes.md +125 -0
- package/docs/guides/checklisttemplates.md +154 -0
- package/docs/guides/companies.md +57 -0
- package/docs/guides/dictionaries.md +64 -0
- package/docs/guides/lifecycle.md +263 -0
- package/docs/guides/materials.md +135 -0
- package/docs/guides/notifications.md +184 -0
- package/docs/guides/roles.md +125 -0
- package/docs/guides/sla.md +130 -0
- package/docs/guides/start.md +67 -0
- package/docs/guides/taskchecklists.md +149 -0
- package/docs/guides/taskcreate.md +260 -0
- package/docs/guides/taskedit.md +277 -0
- package/docs/guides/tasktypes.md +156 -0
- package/docs/guides/users.md +71 -0
- package/generated/index.dev.json +18776 -0
- package/generated/index.prod.json +18858 -0
- package/package.json +48 -0
- package/swagger/dev/ADM.json +27777 -0
- package/swagger/dev/AUTH.json +1739 -0
- package/swagger/dev/AUTHN.json +1250 -0
- package/swagger/dev/AUTHZ.json +1404 -0
- package/swagger/dev/CM.json +309 -0
- package/swagger/dev/COMMON.json +6543 -0
- package/swagger/dev/ES.json +28029 -0
- package/swagger/dev/EXPORT.json +4575 -0
- package/swagger/dev/IMPORT.json +1479 -0
- package/swagger/dev/LIC.json +224 -0
- package/swagger/dev/MSG.json +7883 -0
- package/swagger/dev/NEWS.json +348 -0
- package/swagger/dev/PA.json +5981 -0
- package/swagger/dev/PMP.json +3196 -0
- package/swagger/dev/PROXY.json +416 -0
- package/swagger/dev/REPORT.json +3921 -0
- package/swagger/dev/SC.json +3771 -0
- package/swagger/dev/SLA.json +2837 -0
- package/swagger/dev/TSTG.json +4981 -0
- package/swagger/dev/UI.json +4720 -0
- package/swagger/dev/WH.json +16796 -0
- package/swagger/dev/WORK.json +36024 -0
- package/swagger/dev/WSP.json +1612 -0
- package/swagger/prod/ADM.json +27777 -0
- package/swagger/prod/AUTH.json +1308 -0
- package/swagger/prod/AUTHN.json +2710 -0
- package/swagger/prod/AUTHZ.json +896 -0
- package/swagger/prod/CM.json +162 -0
- package/swagger/prod/COMMON.json +4910 -0
- package/swagger/prod/ES.json +28029 -0
- package/swagger/prod/EXPORT.json +3091 -0
- package/swagger/prod/LIC.json +123 -0
- package/swagger/prod/MSG.json +6239 -0
- package/swagger/prod/NEWS.json +295 -0
- package/swagger/prod/PA.json +5123 -0
- package/swagger/prod/PMP.json +2978 -0
- package/swagger/prod/PROXY.json +250 -0
- package/swagger/prod/REPORT.json +3729 -0
- package/swagger/prod/SC.json +3771 -0
- package/swagger/prod/SLA.json +2201 -0
- package/swagger/prod/TSTG.json +4220 -0
- package/swagger/prod/UI.json +3879 -0
- package/swagger/prod/WH.json +16730 -0
- package/swagger/prod/WORK.json +35994 -0
- package/swagger/prod/WSP.json +1468 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: assets
|
|
3
|
+
sources:
|
|
4
|
+
- page: admin/ExampleRequestsAPI.md
|
|
5
|
+
content_hash: ad3e2bf92fe6a736
|
|
6
|
+
- page: admin/ObjectClass.md
|
|
7
|
+
content_hash: 77c473001aff5b7e
|
|
8
|
+
- page: admin/ObjectsType.md
|
|
9
|
+
content_hash: 631a7aec138691e5
|
|
10
|
+
- page: admin/PlacesVSObjectsClass.md
|
|
11
|
+
content_hash: f3a3726398998a1e
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Объекты обслуживания
|
|
15
|
+
|
|
16
|
+
Объект (Asset) — оборудование или площадка, по которым создают заявки. Он
|
|
17
|
+
принадлежит сервису `ES`, может иметь локацию, участки, виды работ и родителя
|
|
18
|
+
в иерархии.
|
|
19
|
+
|
|
20
|
+
Гайд состоит из трёх частей: справочники, создание объекта (раздел
|
|
21
|
+
«Создание»), изменение существующего (раздел «Редактирование»). Создание и
|
|
22
|
+
редактирование устроены по-разному: при создании связи добавляются цепочкой,
|
|
23
|
+
при редактировании — вычисляются как дельта.
|
|
24
|
+
|
|
25
|
+
## Справочники
|
|
26
|
+
|
|
27
|
+
| Значение | Запрос |
|
|
28
|
+
| --- | --- |
|
|
29
|
+
| объект | `ES:GET:/Assets` или `ES:GET:/Assets/{assetID}` |
|
|
30
|
+
| тип объекта | `ES:GET:/AssetTypes` |
|
|
31
|
+
| класс объекта | `ES:GET:/AssetClasses` |
|
|
32
|
+
| компания-владелец | `ES:GET:/Companies` |
|
|
33
|
+
| локация | `ES:GET:/Locations` |
|
|
34
|
+
| участок | `ES:GET:/Districts` |
|
|
35
|
+
| виды работ | `WORK:GET:/WorkTypes` |
|
|
36
|
+
|
|
37
|
+
Тип объекта и класс объекта — разные сущности. Тип определяет назначение и
|
|
38
|
+
может требовать собственную локацию; класс служит для классификации и
|
|
39
|
+
фильтрации. Участок (`district`) ограничивает доступ пользователей к объекту
|
|
40
|
+
и заявкам.
|
|
41
|
+
|
|
42
|
+
# Создание объекта
|
|
43
|
+
|
|
44
|
+
Этот порядок повторяет короткую форму создания объекта в веб-клиенте HubEx:
|
|
45
|
+
локация → объект → связи с локацией, участками и видами работ → публикация.
|
|
46
|
+
Сам `ES:POST:/Assets` создаёт только основную запись; для объекта, готового к
|
|
47
|
+
работе в заявках, выполни всю цепочку.
|
|
48
|
+
|
|
49
|
+
Перед записью убедись, что на сервере разрешены `POST` и `PUT`. Не создавай
|
|
50
|
+
тестовый или «примерный» объект без явной просьбы пользователя.
|
|
51
|
+
|
|
52
|
+
## 1. Собери обязательные значения
|
|
53
|
+
|
|
54
|
+
Форма веб-клиента требует имя, компанию, адрес и хотя бы один участок. В
|
|
55
|
+
Swagger поля `ES:POST:/Assets` nullable, но для результата, соответствующего
|
|
56
|
+
интерфейсу, собери:
|
|
57
|
+
|
|
58
|
+
| Значение | Справочник |
|
|
59
|
+
| --- | --- |
|
|
60
|
+
| `name` | запрос пользователя |
|
|
61
|
+
| `companyID` | `ES:GET:/Companies` |
|
|
62
|
+
| `assetTypeID` | `ES:GET:/AssetTypes` |
|
|
63
|
+
| `assetClassID` | `ES:GET:/AssetClasses` |
|
|
64
|
+
| адрес или `locationID` | `ES:GET:/Locations` / запрос пользователя |
|
|
65
|
+
| `districtIDs` | `ES:GET:/Districts` |
|
|
66
|
+
| `workTypeIDs` | `WORK:GET:/WorkTypes` |
|
|
67
|
+
|
|
68
|
+
`parentID` необязателен. Для дочернего объекта найди родителя через
|
|
69
|
+
`ES:GET:/Assets` с `includePath=true`. Если значение не задано пользователем,
|
|
70
|
+
веб-клиент берёт тип, класс и участок с `isDefault: true`, а также все
|
|
71
|
+
опубликованные виды работ. Используй дефолт только при единственном подходящем
|
|
72
|
+
варианте; иначе уточни выбор.
|
|
73
|
+
|
|
74
|
+
## 2. Создай или выбери локацию
|
|
75
|
+
|
|
76
|
+
Если подходящая локация уже существует, используй её `id`. Для нового адреса
|
|
77
|
+
вызови `ES:POST:/Locations`; тело — **массив**:
|
|
78
|
+
|
|
79
|
+
```json
|
|
80
|
+
[
|
|
81
|
+
{
|
|
82
|
+
"address": "Москва, ул. Примерная, 1",
|
|
83
|
+
"coordinate": "55.7558:37.6173",
|
|
84
|
+
"isIgnorePossibleDuplication": true
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Обязателен только `address`. Ответ — массив идентификаторов; первый элемент —
|
|
90
|
+
`locationID`. Схему полей страны, временной зоны и описания получай через
|
|
91
|
+
`hubex_describe_endpoint` для `ES:POST:/Locations`.
|
|
92
|
+
|
|
93
|
+
## 3. Создай основную запись объекта
|
|
94
|
+
|
|
95
|
+
Вызови `ES:POST:/Assets` с **одним объектом**, не массивом:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"name": "Кофемашина 3 этаж",
|
|
100
|
+
"companyID": 120,
|
|
101
|
+
"assetTypeID": 4,
|
|
102
|
+
"assetClassID": 7,
|
|
103
|
+
"parentID": 501,
|
|
104
|
+
"isAutoPublish": true
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`parentID` опционален. Допустимые дополнительные поля (`serialNumber`, `erpID`,
|
|
109
|
+
`notes`, `responsiblePerson`, `warrantyTill`, `assetTemplateID`) описывает
|
|
110
|
+
`hubex_describe_endpoint` для `ES:POST:/Assets`. Не передавай произвольные
|
|
111
|
+
поля: схема запрещает дополнительные свойства.
|
|
112
|
+
|
|
113
|
+
Ответ `201` содержит `{ "id", "name" }`; `id` — это `assetID`. Веб-клиент не
|
|
114
|
+
передаёт `locationID` в теле этого запроса: он создаёт отдельную связь на
|
|
115
|
+
следующем шаге.
|
|
116
|
+
|
|
117
|
+
## 4. Добавь связи
|
|
118
|
+
|
|
119
|
+
Сначала привяжи локацию через `ES:POST:/AssetLocations`:
|
|
120
|
+
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"assetID": 840,
|
|
124
|
+
"locationID": 991
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Затем добавь виды работ и участки:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
// ES:POST:/AssetWorkTypes
|
|
132
|
+
{
|
|
133
|
+
"assetID": 840,
|
|
134
|
+
"data": [12, 18]
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
// ES:POST:/AssetDistricts
|
|
140
|
+
{
|
|
141
|
+
"assetID": 840,
|
|
142
|
+
"data": [{ "id": 3 }, { "id": 9 }]
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Для `AssetWorkTypes.data` нужны числовые id, для `AssetDistricts.data` —
|
|
147
|
+
объекты `{ id }`. Веб-клиент при привязке локации ещё отправляет `dateFrom` и
|
|
148
|
+
`dateTill`, но в Swagger `hubexMCP` для `ES:POST:/AssetLocations` описаны лишь
|
|
149
|
+
`assetID` и `locationID`. Ориентируйся на актуальный результат
|
|
150
|
+
`hubex_describe_endpoint`.
|
|
151
|
+
|
|
152
|
+
## 5. Опубликуй и проверь
|
|
153
|
+
|
|
154
|
+
Вызови `ES:PUT:/Assets/{assetID}/publish`, передав id в `pathParams`; тело не
|
|
155
|
+
нужно. Веб-клиент выполняет публикацию явно и безусловно, даже если в создании
|
|
156
|
+
был указан `isAutoPublish: true`.
|
|
157
|
+
|
|
158
|
+
Затем прочитай `ES:GET:/Assets/{assetID}` и проверь имя, компанию, тип, класс,
|
|
159
|
+
родителя, локацию и публикацию. Связи проверяются через
|
|
160
|
+
`ES:GET:/Assets/{assetID}/districts` и `ES:GET:/Assets/{assetID}/workTypes`.
|
|
161
|
+
|
|
162
|
+
## Последовательность MCP-вызовов при создании
|
|
163
|
+
|
|
164
|
+
Перед каждым write-запросом запрашивай его схему через
|
|
165
|
+
`hubex_describe_endpoint`.
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
hubex_request_write(endpointId: `ES:POST:/Locations`, body: [{ address, coordinate }])
|
|
169
|
+
→ locationID
|
|
170
|
+
hubex_request_write(endpointId: `ES:POST:/Assets`, body: { name, companyID, assetTypeID, assetClassID, parentID? })
|
|
171
|
+
→ assetID
|
|
172
|
+
hubex_request_write(endpointId: `ES:POST:/AssetLocations`, body: { assetID, locationID })
|
|
173
|
+
hubex_request_write(endpointId: `ES:POST:/AssetWorkTypes`, body: { assetID, data: workTypeIDs })
|
|
174
|
+
hubex_request_write(endpointId: `ES:POST:/AssetDistricts`, body: { assetID, data: districtIDs.map(id => ({ id })) })
|
|
175
|
+
hubex_request_write(endpointId: `ES:PUT:/Assets/{assetID}/publish`, pathParams: { assetID })
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Не запускай шаги со связями параллельно: веб-клиент подавляет ошибки дочерних
|
|
179
|
+
вызовов. MCP должен остановиться на первой ошибке и сообщить `assetID` уже
|
|
180
|
+
созданной частичной записи, а не повторять `POST /Assets` и создавать дубликат.
|
|
181
|
+
|
|
182
|
+
Локация останется в системе, если объект создать не удалось. Не удаляй её
|
|
183
|
+
автоматически: сначала сообщи пользователю её id и запроси разрешение на
|
|
184
|
+
очистку.
|
|
185
|
+
|
|
186
|
+
# Редактирование объекта
|
|
187
|
+
|
|
188
|
+
Раздел повторяет форму редактирования объекта в веб-клиенте HubEx. Основные
|
|
189
|
+
поля, участки и локация меняются разными запросами; не пытайся отправить всё в
|
|
190
|
+
`ES:PUT:/Assets/{assetID}`.
|
|
191
|
+
|
|
192
|
+
Фронтенд выполняет основной `PUT`, затем запускает изменения участков и после
|
|
193
|
+
этого обрабатывает локацию. Для MCP безопаснее дождаться результата каждого
|
|
194
|
+
шага: интерфейс запускает изменения участков в фоне и может показать успех при
|
|
195
|
+
неуспешной привязке участка.
|
|
196
|
+
|
|
197
|
+
## 1. Прочитай текущее состояние
|
|
198
|
+
|
|
199
|
+
Перед любым изменением получи:
|
|
200
|
+
|
|
201
|
+
- `ES:GET:/Assets/{assetID}` — основные поля, компания, тип, класс, родитель,
|
|
202
|
+
локация и публикация;
|
|
203
|
+
- `ES:GET:/Assets/{assetID}/districts` — текущие участки;
|
|
204
|
+
- `ES:GET:/Assets/{assetID}/workTypes` — текущие виды работ.
|
|
205
|
+
|
|
206
|
+
Сравни текущее состояние с запросом пользователя. Не передавай `null` или
|
|
207
|
+
пустой массив как замену неизвестного значения: это может снять родителя,
|
|
208
|
+
стереть ссылку или отвязать все элементы. Для справочных значений используй
|
|
209
|
+
`ES:GET:/Companies`, `ES:GET:/AssetTypes`, `ES:GET:/AssetClasses`,
|
|
210
|
+
`ES:GET:/Districts` и `WORK:GET:/WorkTypes`.
|
|
211
|
+
|
|
212
|
+
## 2. Обнови основную карточку
|
|
213
|
+
|
|
214
|
+
Вызови `ES:PUT:/Assets/{assetID}` с `assetID` в `pathParams`. Веб-клиент
|
|
215
|
+
передаёт все доступные для формы значения, а не только изменённое поле:
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"name": "Кофемашина 3 этаж",
|
|
220
|
+
"companyID": 120,
|
|
221
|
+
"assetTypeID": 4,
|
|
222
|
+
"assetClassID": 7,
|
|
223
|
+
"parentID": 501,
|
|
224
|
+
"isMobileAsset": false,
|
|
225
|
+
"isInheritParentDistricts": false,
|
|
226
|
+
"isSkipForEscalation": false,
|
|
227
|
+
"isStopEscalation": false,
|
|
228
|
+
"notes": "Установлена у ресепшена",
|
|
229
|
+
"serialNumber": "SN-0001"
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Перед вызовом получи точную схему через `hubex_describe_endpoint` для
|
|
234
|
+
`ES:PUT:/Assets/{assetID}` и собери тело из прочитанных данных плюс изменения
|
|
235
|
+
пользователя. Дополнительные поддерживаемые поля: `responsiblePerson`, `erpID`,
|
|
236
|
+
`scheduleRuleID`, `warrantyTill`, `positionOnSchema`, `locationID`,
|
|
237
|
+
`useAllWorkTypes` и `isAutoPublish`.
|
|
238
|
+
|
|
239
|
+
Не используй `ES:PUT:/Assets` для одного объекта: это массовое изменение с
|
|
240
|
+
другим телом (`assets: [id, ...]`) и другой семантикой.
|
|
241
|
+
|
|
242
|
+
Веб-клиент всегда отправляет `isSkipForEscalation: false` и
|
|
243
|
+
`isStopEscalation: false`, даже если пользователь их не менял. MCP не должен
|
|
244
|
+
копировать это поведение: возьми текущие значения из объекта и меняй их только
|
|
245
|
+
по явной просьбе пользователя.
|
|
246
|
+
|
|
247
|
+
## 3. Измени участки и виды работ как дельту
|
|
248
|
+
|
|
249
|
+
Для добавления участков используй `ES:POST:/AssetDistricts`:
|
|
250
|
+
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"assetID": 840,
|
|
254
|
+
"data": [{ "id": 3 }]
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Для удаления — `ES:DELETE:/AssetDistricts`:
|
|
259
|
+
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"assetID": 840,
|
|
263
|
+
"data": [9]
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Виды работ меняются аналогично через `ES:POST:/AssetWorkTypes` и
|
|
268
|
+
`ES:DELETE:/AssetWorkTypes`; в обоих телах `data` — массив числовых id:
|
|
269
|
+
|
|
270
|
+
```json
|
|
271
|
+
{
|
|
272
|
+
"assetID": 840,
|
|
273
|
+
"data": [18]
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Сначала вычисли `added` и `removed` относительно прочитанного состояния.
|
|
278
|
+
Отправляй только дельту, не удаляй и не добавляй весь список заново.
|
|
279
|
+
|
|
280
|
+
Короткая форма редактирования веб-клиента меняет только участки; виды работ в
|
|
281
|
+
ней не редактируются. В MCP вызывай методы `AssetWorkTypes` лишь когда
|
|
282
|
+
пользователь отдельно запросил изменение видов работ.
|
|
283
|
+
|
|
284
|
+
## 4. Измени локацию осознанно
|
|
285
|
+
|
|
286
|
+
Есть три разных операции:
|
|
287
|
+
|
|
288
|
+
1. Привязать к объекту существующую локацию —
|
|
289
|
+
`ES:POST:/AssetLocations` с телом `{ assetID, locationID }`.
|
|
290
|
+
2. Создать новую локацию — `ES:POST:/Locations` с телом-массивом
|
|
291
|
+
`[{ address, coordinate, ... }]`, получить `locationID`, затем создать
|
|
292
|
+
связь через `ES:POST:/AssetLocations`.
|
|
293
|
+
3. Исправить данные уже существующей локации — `ES:PUT:/Locations` с
|
|
294
|
+
телом-массивом `[{ id, address, coordinate, ... }]`.
|
|
295
|
+
|
|
296
|
+
Третий вариант меняет саму локацию, а не только объект. Перед ним проверь,
|
|
297
|
+
используется ли она другими объектами; если да, для нового адреса безопаснее
|
|
298
|
+
создать отдельную локацию и привязать её на шагах 1–2.
|
|
299
|
+
|
|
300
|
+
Веб-клиент при выборе нового адреса добавляет новую связь и не удаляет старую.
|
|
301
|
+
Не предполагай, что предыдущая связь будет снята автоматически: после операции
|
|
302
|
+
перечитай объект и только затем решай, требуется ли дополнительное действие.
|
|
303
|
+
|
|
304
|
+
Если в выбранном адресе изменилось только `description`, веб-клиент правит
|
|
305
|
+
существующую локацию через `ES:PUT:/Locations`; изменение `address` или
|
|
306
|
+
`coordinate` тоже требует передавать полный объект локации по актуальной схеме.
|
|
307
|
+
Не изменяй общую локацию, пока не проверишь, не используют ли её другие
|
|
308
|
+
объекты.
|
|
309
|
+
|
|
310
|
+
## 5. Управляй публикацией отдельно
|
|
311
|
+
|
|
312
|
+
Для публикации используй `ES:PUT:/Assets/{assetID}/publish`, для снятия с
|
|
313
|
+
публикации — `ES:PUT:/Assets/{assetID}/unpublish`. Оба вызова принимают
|
|
314
|
+
`assetID` в `pathParams` и не требуют тело.
|
|
315
|
+
|
|
316
|
+
## 6. Проверь результат
|
|
317
|
+
|
|
318
|
+
После каждого успешного шага прочитай `ES:GET:/Assets/{assetID}`; после правки
|
|
319
|
+
участков или видов работ также перечитай соответствующую связь. Если один из
|
|
320
|
+
последующих шагов не выполнился, не откатывай уже выполненные автоматически:
|
|
321
|
+
сообщи пользователю, какие изменения сохранились, и предложи дозапустить только
|
|
322
|
+
неуспешное действие.
|
|
323
|
+
|
|
324
|
+
## Подводные камни
|
|
325
|
+
|
|
326
|
+
- Тела `ES:PUT:/Locations` — массивы, а тела связей с объектом — объекты.
|
|
327
|
+
- `parentID: null` снимает родителя. Передавай это значение только по явной
|
|
328
|
+
просьбе пользователя.
|
|
329
|
+
- Участки и виды работ не обновляются телом `ES:PUT:/Assets/{assetID}`.
|
|
330
|
+
- Изменения участков в интерфейсе выполняются в фоне. В MCP проверяй ответ
|
|
331
|
+
каждого вызова, иначе объект может сохраниться без нужного участка.
|
|
332
|
+
- При создании связи добавляются цепочкой, при редактировании — только
|
|
333
|
+
дельтой: не переноси порядок из раздела «Создание» на правку существующего
|
|
334
|
+
объекта.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: attributes
|
|
3
|
+
sources:
|
|
4
|
+
- page: adminapp/src/modules/Attributes/saga.js
|
|
5
|
+
content_hash: 06fc2d7e52a7cf7a
|
|
6
|
+
- page: adminapp/src/helpers/attributes.js
|
|
7
|
+
content_hash: b02bb20d39fbd6c5
|
|
8
|
+
- page: adminapp/src/config/defaultProperties.js
|
|
9
|
+
content_hash: 280a0b7c004e5820
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Дополнительные поля (атрибуты)
|
|
13
|
+
|
|
14
|
+
Атрибут — дополнительное поле, которое расширяет карточку заявки, объекта,
|
|
15
|
+
чек-листа, выполненной работы, компании, договора, сотрудника или заказчика.
|
|
16
|
+
Живёт в сервисе COMMON и общий для всего тенанта; к какой сущности он
|
|
17
|
+
относится, задаётся набором флагов `IsRelevantFor*`.
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
GET COMMON:GET:/Attributes список
|
|
21
|
+
GET COMMON:GET:/Attributes/{attributeID} одно поле
|
|
22
|
+
POST COMMON:POST:/Attributes создать
|
|
23
|
+
PUT COMMON:PUT:/Attributes изменить
|
|
24
|
+
DELETE COMMON:DELETE:/Attributes/{id} удалить
|
|
25
|
+
POST COMMON:POST:/AttributeListOfValues значения списка
|
|
26
|
+
GET COMMON:GET:/Attributes/{attributeID}/listOfValues
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 1. Создание поля
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
[
|
|
33
|
+
{
|
|
34
|
+
"name": "Субподрядчик",
|
|
35
|
+
"attributeTypeID": 5,
|
|
36
|
+
"measurementUnitID": null,
|
|
37
|
+
"isPublic": true,
|
|
38
|
+
"IsRelevantForTask": true,
|
|
39
|
+
"IsRelevantForAsset": false,
|
|
40
|
+
"IsRelevantForCheckList": false,
|
|
41
|
+
"IsRelevantForCompletedWork": false,
|
|
42
|
+
"IsRelevantForCompany": false,
|
|
43
|
+
"IsRelevantForContract": false,
|
|
44
|
+
"IsRelevantForCustomer": false,
|
|
45
|
+
"IsRelevantForTechnician": false
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- `attributeTypeID` — тип поля: `COMMON:GET:/AttributeTypes` (или
|
|
51
|
+
`COMMON:GET:/AttributeTypes/v2`). У типа есть `code` — по нему определяется
|
|
52
|
+
поведение: `Select` и `MultiSelect` требуют списка значений (см. ниже),
|
|
53
|
+
тип «значение из справочника» связывает поле с одним из справочников
|
|
54
|
+
(объекты, компании, сотрудники, заказчики, материалы).
|
|
55
|
+
- `measurementUnitID` — единица измерения для числовых полей:
|
|
56
|
+
`COMMON:GET:/MeasurementUnits`.
|
|
57
|
+
- Флаги `IsRelevantFor*` — для каких сущностей поле доступно. AdminApp всегда
|
|
58
|
+
отправляет **все восемь** флагов, невыбранные — `false`; частичное тело
|
|
59
|
+
может обнулить остальные признаки.
|
|
60
|
+
- `isPublic` — поле видно в паспорте объекта (данные, доступные по QR-коду).
|
|
61
|
+
|
|
62
|
+
Ответ `201` — массив идентификаторов.
|
|
63
|
+
|
|
64
|
+
## 2. Значения списка
|
|
65
|
+
|
|
66
|
+
Для типов `Select` и `MultiSelect` сразу после создания или изменения атрибута
|
|
67
|
+
веб-клиент отправляет значения:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
[
|
|
71
|
+
{
|
|
72
|
+
"attributeID": 128,
|
|
73
|
+
"data": [
|
|
74
|
+
{ "key": "1", "value": "Подрядчик А" },
|
|
75
|
+
{ "key": "2", "value": "Подрядчик Б" }
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`key` — уникальный идентификатор значения (в интерфейсе заполняется по
|
|
82
|
+
порядку), `value` — то, что видит пользователь. Запрос заменяет список
|
|
83
|
+
значений целиком: чтобы удалить значение, отправь набор без него.
|
|
84
|
+
|
|
85
|
+
## 3. Где ещё используются атрибуты
|
|
86
|
+
|
|
87
|
+
- **Чек-листы**: атрибут задаёт способ ответа на пункт (число, дата, список,
|
|
88
|
+
вложение) — `hubex_get_guide topic="checklisttemplates"`, фильтр
|
|
89
|
+
`isRelevantForCheckList=true`.
|
|
90
|
+
- **Форма заявки**: дополнительные поля попадают в раскладку
|
|
91
|
+
(`UI:GET:/LayoutTemplates/{id}/Attributes`) и в настройку доступности по
|
|
92
|
+
ролям и стадиям (`TSTG:POST:/TaskStageComponents`, секция `attributes`).
|
|
93
|
+
- **Объекты и компании**: значения проставляются своими эндпоинтами —
|
|
94
|
+
`ES:POST:/AssetAttributes/v2`, `ES:POST:/Companies/{companyID}/attributes`,
|
|
95
|
+
`ADM:POST:/Users/{userID}/attributes`.
|
|
96
|
+
- **SLA**: атрибуты правил SLA — это другая сущность (`SLA:GET:/Attributes`),
|
|
97
|
+
не путать с дополнительными полями.
|
|
98
|
+
|
|
99
|
+
## Последовательность MCP-вызовов
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
hubex_request_read(endpointId: `COMMON:GET:/AttributeTypes`) → attributeTypeID и code
|
|
103
|
+
hubex_request_read(endpointId: `COMMON:GET:/MeasurementUnits`) → measurementUnitID
|
|
104
|
+
hubex_request_write(endpointId: `COMMON:POST:/Attributes`, body: [{ name, attributeTypeID, IsRelevantForTask: true, ... }])
|
|
105
|
+
→ response[0] = attributeID
|
|
106
|
+
hubex_request_write(endpointId: `COMMON:POST:/AttributeListOfValues`, body: [{ attributeID, data: [{ key, value }] }])
|
|
107
|
+
hubex_request_read(endpointId: `COMMON:GET:/Attributes/{attributeID}/listOfValues`, pathParams: { attributeID })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Подводные камни
|
|
111
|
+
|
|
112
|
+
- Флаги `IsRelevantFor*` пишутся с заглавной буквы в теле запроса, а в ответе
|
|
113
|
+
приходят вложенным объектом `relevantFor` (`task`, `asset`, `checkList`,
|
|
114
|
+
`completedWork`, `company`, `contract`, `customer`, `technician`) — при
|
|
115
|
+
копировании поля перекладывай значения между этими формами.
|
|
116
|
+
- Список значений имеет смысл только для типов `Select` и `MultiSelect`; для
|
|
117
|
+
остальных типов вызов `COMMON:POST:/AttributeListOfValues` бессмысленен.
|
|
118
|
+
- Создание атрибута не размещает его на форме заявки: новое поле появляется
|
|
119
|
+
внизу основного блока раскладки, а видимость по ролям и стадиям настраивается
|
|
120
|
+
отдельно.
|
|
121
|
+
- Удаление атрибута (`COMMON:DELETE:/Attributes/{id}`) затрагивает все
|
|
122
|
+
заполненные значения в заявках и объектах — делай только по явному
|
|
123
|
+
подтверждению пользователя.
|
|
124
|
+
- В списках атрибутов почти всегда нужен фильтр `isDeleted=false`: удалённые
|
|
125
|
+
поля продолжают возвращаться.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: checklisttemplates
|
|
3
|
+
sources:
|
|
4
|
+
- page: admin/ExampleRequestsAPI.md
|
|
5
|
+
content_hash: ad3e2bf92fe6a736
|
|
6
|
+
- page: admin/TicketLifeCycle.md
|
|
7
|
+
content_hash: 60be5a94c8573779
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Создание шаблона чек-листа
|
|
11
|
+
|
|
12
|
+
Этот гайд создаёт **шаблон** чек-листа: название, пункты и необязательные
|
|
13
|
+
привязки к объектам обслуживания и видам работ. Это не заполнение чек-листа
|
|
14
|
+
в уже созданной заявке — для него используй
|
|
15
|
+
`hubex_get_guide topic="taskchecklists"`.
|
|
16
|
+
|
|
17
|
+
MainApp создаёт шаблон тремя последовательными запросами:
|
|
18
|
+
|
|
19
|
+
```text
|
|
20
|
+
POST /CheckLists → checkListID
|
|
21
|
+
POST /CheckListItems → пункты
|
|
22
|
+
POST /CheckLists/{checkListID}/assign → привязки (при наличии)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Не запускай шаги параллельно: каждый следующий требует `checkListID` из
|
|
26
|
+
предыдущего. Перед каждым write-запросом получай актуальную схему через
|
|
27
|
+
`hubex_describe_endpoint`.
|
|
28
|
+
|
|
29
|
+
## 1. Собери данные
|
|
30
|
+
|
|
31
|
+
В форме MainApp обязательны название шаблона и хотя бы один пункт. Описание,
|
|
32
|
+
атрибут пункта, объекты и виды работ необязательны.
|
|
33
|
+
|
|
34
|
+
| Данные | Ограничение интерфейса | Где взять id |
|
|
35
|
+
| --- | --- | --- |
|
|
36
|
+
| `name` шаблона | 1–60 символов | пользователь |
|
|
37
|
+
| `description` шаблона | до 500 символов | пользователь |
|
|
38
|
+
| `name` пункта | 1–100 символов | пользователь |
|
|
39
|
+
| `description` пункта | до 500 символов | пользователь |
|
|
40
|
+
| `attributeID` | необязателен, один на пункт | `COMMON:GET:/Attributes` с `isDeleted=false`, `isRelevantForCheckList=true` |
|
|
41
|
+
| `assets` | необязательный список объектов | `ES:GET:/Assets` |
|
|
42
|
+
| `workTypes` | необязательный список видов работ | `WORK:GET:/WorkTypes` с `isPublished=true` |
|
|
43
|
+
|
|
44
|
+
Атрибут задаёт способ ответа на пункт: например, число, дата, текст, список
|
|
45
|
+
значений или вложение. Если для пункта достаточно отметки о выполнении, не
|
|
46
|
+
задавай `attributeID`.
|
|
47
|
+
|
|
48
|
+
Привязка к объекту и (или) виду работ нужна, чтобы шаблон автоматически
|
|
49
|
+
появлялся в заявке при выборе соответствующих значений. Шаблон без привязок
|
|
50
|
+
создаётся успешно, но в заявки автоматически не добавляется.
|
|
51
|
+
|
|
52
|
+
## 2. Создай шаблон
|
|
53
|
+
|
|
54
|
+
`WORK:POST:/CheckLists` принимает **массив**, даже если создаётся один
|
|
55
|
+
шаблон:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
[
|
|
59
|
+
{
|
|
60
|
+
"name": "Ежедневный осмотр кофемашины",
|
|
61
|
+
"description": "Проверки перед началом работы"
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Ответ `201` — массив идентификаторов. Для одного шаблона возьми первый элемент
|
|
67
|
+
как `checkListID`. Право: `CheckListAdd`.
|
|
68
|
+
|
|
69
|
+
## 3. Добавь пункты
|
|
70
|
+
|
|
71
|
+
`WORK:POST:/CheckListItems` тоже принимает массив, но его элемент — контейнер
|
|
72
|
+
с `checkListID` и массивом `data`. `sortOrder` начинается с нуля и определяет
|
|
73
|
+
порядок отображения. MainApp отправляет все пункты одним запросом.
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
[
|
|
77
|
+
{
|
|
78
|
+
"checkListID": 251,
|
|
79
|
+
"data": [
|
|
80
|
+
{
|
|
81
|
+
"name": "Проверить уровень воды",
|
|
82
|
+
"description": "Не ниже отметки MIN",
|
|
83
|
+
"attributeID": 42,
|
|
84
|
+
"sortOrder": 0
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "Очистить поддон",
|
|
88
|
+
"description": null,
|
|
89
|
+
"attributeID": null,
|
|
90
|
+
"sortOrder": 1
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Право: `CheckListItemMerge`. Не передавай `id` для новых пунктов. Если
|
|
98
|
+
создание шаблона прошло, а этот запрос завершился ошибкой, не повторяй
|
|
99
|
+
создание: сохрани пользователю `checkListID` частично созданного шаблона и
|
|
100
|
+
исправь пункты отдельным вызовом.
|
|
101
|
+
|
|
102
|
+
## 4. Привяжи шаблон — при необходимости
|
|
103
|
+
|
|
104
|
+
После создания пунктов вызови
|
|
105
|
+
`WORK:POST:/CheckLists/{checkListID}/assign`, передав идентификатор в
|
|
106
|
+
`pathParams`. Тело — **один объект**, не массив:
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"assets": [840, 841],
|
|
111
|
+
"workTypes": [12, 18]
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Оба массива независимы: можно указать только `assets`, только `workTypes` или
|
|
116
|
+
оба. В MainApp при выборе объекта с дочерними объектами список разворачивается
|
|
117
|
+
до конкретных `assets`; для MCP передавай явные id всех объектов, к которым
|
|
118
|
+
нужна привязка. Право: `CheckListAssign`.
|
|
119
|
+
|
|
120
|
+
Не вызывай `/assign` с пустыми обоими массивами: веб-клиент в таком случае
|
|
121
|
+
пропускает запрос. При ошибке привязки сам шаблон и его пункты уже существуют;
|
|
122
|
+
не создавай их заново.
|
|
123
|
+
|
|
124
|
+
## 5. Проверь результат
|
|
125
|
+
|
|
126
|
+
1. `WORK:GET:/CheckLists/{checkListID}/items` — пункты, их порядок и атрибуты.
|
|
127
|
+
2. `WORK:GET:/CheckLists` с `searchText`, `assetID` или `workTypeID` — шаблон
|
|
128
|
+
в общем списке и результаты привязки.
|
|
129
|
+
3. При необходимости перечитай `WORK:GET:/CheckLists/{id}` — основное
|
|
130
|
+
название и описание.
|
|
131
|
+
|
|
132
|
+
## Последовательность MCP-вызовов
|
|
133
|
+
|
|
134
|
+
```text
|
|
135
|
+
hubex_request_write(endpointId: `WORK:POST:/CheckLists`, body: [{ name, description? }])
|
|
136
|
+
→ response[0] = checkListID
|
|
137
|
+
hubex_request_write(endpointId: `WORK:POST:/CheckListItems`, body: [{ checkListID, data: items }])
|
|
138
|
+
hubex_request_write(endpointId: `WORK:POST:/CheckLists/{checkListID}/assign`, pathParams: { checkListID }, body: { assets?, workTypes? })
|
|
139
|
+
hubex_request_read(endpointId: `WORK:GET:/CheckLists/{checkListID}/items`, pathParams: { checkListID })
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Подводные камни
|
|
143
|
+
|
|
144
|
+
- `checkListID` — id шаблона. Не путай его с `taskCheckListID`, который
|
|
145
|
+
появляется только после добавления шаблона в конкретную заявку.
|
|
146
|
+
- Создание шаблона и создание пунктов — разные операции. Тело первого запроса
|
|
147
|
+
— массив шаблонов, второго — массив контейнеров `{ checkListID, data }`.
|
|
148
|
+
- Привязки не создают заявку и не добавляют шаблон в уже существующие заявки;
|
|
149
|
+
они влияют на дальнейший выбор объекта и вида работ.
|
|
150
|
+
- `attributeID` не создаёт атрибут. Если подходящего атрибута нет, нужна его
|
|
151
|
+
предварительная настройка в консоли администратора, а не произвольный id.
|
|
152
|
+
- Не удаляй частично созданный шаблон автоматически. Удаление — отдельная
|
|
153
|
+
операция с правом `CheckListDelete` и должно быть явно подтверждено
|
|
154
|
+
пользователем.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
topic: companies
|
|
3
|
+
sources:
|
|
4
|
+
- page: admin/ExampleRequestsAPI.md
|
|
5
|
+
content_hash: ad3e2bf92fe6a736
|
|
6
|
+
- page: admin/CustomerAgreement.md
|
|
7
|
+
content_hash: a04f9f0fa7b158a4
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Компании
|
|
11
|
+
|
|
12
|
+
Компания (Company) — заказчик или внутренняя (наша) организация в HubEx.
|
|
13
|
+
Живёт в сервисе ES. К компании привязываются объекты обслуживания и заявки;
|
|
14
|
+
для компаний-заказчиков можно настроить процесс согласования выполненных
|
|
15
|
+
заявок (жизненный цикл с веткой согласования, см. гайд `taskedit`).
|
|
16
|
+
|
|
17
|
+
## Создание компании: порядок вызовов
|
|
18
|
+
|
|
19
|
+
1. `ES:GET:/Companies` — посмотреть существующие компании, чтобы не плодить
|
|
20
|
+
дубликаты (поиск по названию делается на своей стороне, фильтрацией
|
|
21
|
+
ответа).
|
|
22
|
+
2. `ES:POST:/Companies` — создание. Тело — **массив** объектов компании
|
|
23
|
+
(можно создавать несколько компаний одним запросом). Тело каждого
|
|
24
|
+
элемента — по схеме из `hubex_describe_endpoint`.
|
|
25
|
+
|
|
26
|
+
## Обязательные и ключевые поля тела
|
|
27
|
+
|
|
28
|
+
- `name` — наименование компании.
|
|
29
|
+
- `isEmployer` — признак типа компании: `true` для собственной/внутренней
|
|
30
|
+
организации, `false` для заказчика.
|
|
31
|
+
- `registrationTypeID` — тип регистрации компании (см. `ES:GET:/CompanyRegistrationTypes`
|
|
32
|
+
в swagger сервиса ES).
|
|
33
|
+
|
|
34
|
+
## Чтение и изменение
|
|
35
|
+
|
|
36
|
+
- Список: `ES:GET:/Companies`; одна запись — фильтруй ответ по `id`, так как
|
|
37
|
+
коллекция приходит словарём.
|
|
38
|
+
- Изменение: `ES:PUT:/Companies` — метод обновляет компанию **целиком**,
|
|
39
|
+
требуется массив с полным набором текущих полей плюс изменяемое значение,
|
|
40
|
+
иначе остальные поля будут очищены.
|
|
41
|
+
- Удаление: `ES:DELETE:/Companies` — помечает компанию удалённой, физически
|
|
42
|
+
не стирает.
|
|
43
|
+
|
|
44
|
+
## Подводные камни
|
|
45
|
+
|
|
46
|
+
- `ES:POST:/Companies` и `ES:PUT:/Companies` принимают **массив**, а не
|
|
47
|
+
одиночный объект, даже при создании/изменении одной компании — забытые
|
|
48
|
+
квадратные скобки дадут ошибку валидации.
|
|
49
|
+
- Ответ на успешное создание — тоже массив, но не эхо тела, а список ID
|
|
50
|
+
созданных записей (например `[21]`), а не JSON с полями компании.
|
|
51
|
+
- Для компании-заказчика согласование выполненных заявок настраивается не в
|
|
52
|
+
самой компании, а в жизненном цикле типа заявки (ветка «действий
|
|
53
|
+
заказчика», см. гайд `taskedit`): к компании это отношения не имеет, но
|
|
54
|
+
часто путают эти два уровня настройки.
|
|
55
|
+
- Банковские реквизиты (`bankAccounts`), локация (`location`) и контакты
|
|
56
|
+
(`contacts`) — вложенные структуры внутри тела компании, а не отдельные
|
|
57
|
+
сущности верхнего уровня для базового сценария создания.
|