goalsmanagement.goalitem.upsert
Scope:
goalsmanagementКто может вызывать: Права проверяются так же, как на странице карточки целей: участник карточки (сотрудник, руководитель, функциональный руководитель, директор, делегат) или администратор; процесс подразделения запущен; этап разрешает правку этой роли — «Черновик»: сотрудник, руководитель, делегат; «Согласование руководителем»: руководитель; «Функциональный руководитель»: функциональный руководитель; «Согласование директором»: директор; администратор — на любом этапе, кроме утверждённой карточки. Утверждённая карточка (
status_approval) только для просмотра, в том числе для администратора. С версии 16.0.1. Подробнее: Права доступа
Сохранить/обновить набор целей карточки (WAF-безопасное имя вместо *.save)
HTTP: POST
Побочные эффекты: перезаписывает цели карточки
Параметры метода
| Параметр | Тип | Обяз. | Описание |
|---|---|---|---|
cardId |
int |
да | ID карточки целей |
goals |
array |
да | Полный набор целей карточки. Свои строки с id, которых нет в массиве, удаляются (кроме ещё невидимых pending-каскадов) |
Поля элемента goals[]
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
id |
int |
нет | HL-id строки. Нет — создать, есть — обновить. Чужой id — VALIDATION_ERROR |
type_goal |
int |
да | Числовой id из goal.type.list, не xmlId. Без id и без типа строка пропускается. У подцелей/внешних каскадных строк валидация не проверяет |
goal |
int |
условно | ID цели каталога того же типа. Обязателен для strategy (1-й уровень). Одних task/weight недостаточно |
task |
string |
условно | Текст задачи. Обязателен для любого не-strategy типа (обычно operational/informational) |
weight |
number |
да | Число 0–100 в payload (валидация без подстановки из HL). Плюс min/step из каталога/настроек. Сумма 1-го уровня ≈ 100. У подцелей не проверяется. Если у цели каталога заданы текстовые описания градаций веса, значение должно быть одним из описанных, иначе INVALID_GOAL_WEIGHT_LABEL; неизменённый вес уже сохранённой строки принимается |
criterion |
string |
условно | Критерий. Обязателен и должен быть числом, если цель количественная. Для строки 1-го уровня цели каталога, у которой в справочнике критериев есть критерий с запретом менять формулировку, сохраняется формулировка этого критерия: отличающееся значение заменяется (метод возвращает saved: true, фактическое значение смотрите в goalitem.list) |
catalogCriterionId |
string |
нет | ID критерия из справочника критериев цели каталога, выбранного для строки. Если критерий доступен владельцу карточки и для него стоит запрет менять формулировку, его формулировка сохраняется как criterion. Неизвестные и недоступные ID игнорируются |
commentGeneral |
string |
нет | Комментарий |
file |
object |
нет | { "id": <fileId> } |
depend |
array |
нет | ID отделов |
related |
array |
нет | Связи { "id", "entityType": "task"|"project" } |
cascadeOnEmployees |
array |
нет | ID сотрудников для каскада |
cascadeOnBosses |
array |
нет | ID руководителей для каскада |
quantitative |
bool |
нет | Количественная цель |
allowToConvert |
bool |
нет | Разрешить перевод в количественную |
quantChildrenCalcMode |
string |
нет | Режим расчёта покрытия подцелей родителя: SUM (суммировать) или AVG (усреднить). Хранится в HL строки цели; при качественной цели сохраняется как SUM. Если не передан при создании — SUM. Используется для процента покрытия родителя по детям (количественный критерий или доля качественной подцели как эквивалент критерия), в том числе при смешанных подцелях |
isSubgoal |
bool |
нет | Подцель (не входит в сумму весов) |
part |
number |
нет | Доля подцели |
relatedCardId |
int |
нет | Карточка, на которой живёт строка |
cascadeParentGoal |
int |
нет | Родительская цель каскада |
userFields |
object |
нет | Значения каталожных пользовательских полей: ключ — fieldId (int), значение — по типу поля (строка, число, id элемента списка или массив id, дата YYYY-MM-DD, id файла). Метод всегда проверяет обязательные поля (см. «Пользовательские поля» ниже) |
Пользовательские поля
Принимаются только поля, включённые в карточку целей (SHOW_IN_GOAL_CARD=Y, поле активно). Остальные ключи userFields игнорируются.
- Запись. Значение сохраняется, если поле можно заполнять в карточке целей (
fillInGoalCard) иallowEmployeeEdit=true. ПриallowEmployeeEdit=falseполе недоступно для записи всем ролям (сотрудник карточки, руководитель, администратор) — значение из запроса молча игнорируется; если у строки ещё нет сохранённого значения, записывается значение по умолчанию. - Блокировка каскадной строки. Если строка каскадирована (
cascadeFrom/ чужаяrelatedCardId) и для поляallowEditInCascaded=false— значение из запроса игнорируется. ПриallowEditInCascaded=trueруководитель может менять UF на внешней (чужой) каскадной строке, пока связанная карточка подчинённого не утверждена; после утверждения запись UF на такой строке снова блокируется (сохраняется уже записанное или default). - Обязательность. В отличие от интерфейса (где черновик сохраняется с пустыми полями),
goalitem.upsertвсегда проверяет обязательные поля (isRequired, с учётом переопределения для цели каталога): пустое обязательное поле даётVALIDATION_ERRORи сохранение отменяется целиком. Поле, которое в карточке никто не может заполнить (fillInGoalCard=false), обязательным не считается. Необязательное поле можно очистить, передавnull, пустую строку или пустой массив. - Метаданные полей (
isRequired,allowEmployeeEdit,allowCascade,allowEditInCascaded) приходят вuserFieldMetaиз goalitem.list.
Справочник критериев цели каталога
У цели каталога может быть справочник критериев выполнения (формулировка, комментарий, доступность по правам, признак «Запретить сотрудникам менять формулировку»). Справочник настраивается в карточке цели каталога в интерфейсе, через REST он не читается и не меняется.
При сохранении строки цели каталога (не подцель и не каскадная строка) метод проверяет запрет на сервере, независимо от роли вызывающего:
- если передан
catalogCriterionIdзаблокированного критерия, доступного владельцу карточки, вcriterionсохраняется его формулировка; - иначе, если сохранённая формулировка строки совпадает с заблокированным критерием, она не изменяется;
- в остальных случаях
criterionсохраняется как передан.
Изменение формулировки критерия в справочнике не меняет формулировку в уже созданных карточках: в них остаётся прежнее значение, а запрет для такой строки перестаёт действовать, так как её формулировка больше не совпадает с критерием.
Возвращаемые данные
Ответ в конверте модуля: result.result — результат сохранения / карточка; result.error. Ключи total/next для не-list методов могут отсутствовать в сериализации, если не переданы.
Обработка ошибок
Справочник кодов: error-codes.md.
| Код | Описание |
|---|---|
UNAUTHORIZED |
Пользователь не авторизован |
VALIDATION_ERROR |
Некорректные или неполные параметры: тип/вес/критерий, чужой goals[].id, пустое обязательное каталожное поле, невалидное значение поля (формат, длина, диапазон, список, расширение/размер файла) |
ACCESS_DENIED |
Нет права править карточку на текущем этапе: не участник, процесс не запущен или завершён, карточка утверждена, этап правит другая роль |
INVALID_GOAL_WEIGHT_LABEL |
goals[].weight не входит в описанные градации веса цели каталога |
INTERNAL_ERROR |
Внутренняя ошибка сервера |
Пример запроса (POST)
curl -X POST "https://{портал}/rest/{user_id}/{webhook_code}/goalsmanagement.goalitem.upsert.json" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
--data '{
"cardId": 501,
"goals": [
{
"id": 1001,
"goal": 1049,
"type_goal": 62,
"criterion": "Рост выручки на 15%",
"commentGeneral": "Согласовано с руководителем",
"weight": 100,
"userFields": {
"12": "Q3 focus"
}
}
]
}'
Пример ответа
{
"result": {
"result": {
"cardId": 501,
"saved": true
},
"error": null
}
}