Files
claude-skills/1c-analyst/references/devprom-alm-api.md
T
creator dee7d51c19 fix(1c-analyst): DELETE через /issue/items работает для любых записей Request
На пути /request/items/{id} DELETE действительно заблокирован
(возвращает Unable access entity), но тот же Id можно убрать
через DELETE /issue/items/{id} — он универсален и работает как
для U-записей (созданных через /issue/items), так и для I-записей
(созданных через /request/items). Эмпирически подтверждено чисткой
33 зомби-записей I-6122..I-6176 в test-api-claude за один проход.

Поправлены разделы:
- devprom-alm-api.md §4 «Удаление» — таблица расширена комментарием
  про универсальность /issue/items DELETE
- devprom-alm-api.md §6 «Что НЕ работает» — DELETE request/items
  отмечен как «не препятствие»
- SKILL.md §«Критически важно» — корректное правило про DELETE
- meeting-wishes-extraction.md антипаттерн №7 — UI больше не нужен
2026-04-22 00:25:35 +00:00

280 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Devprom ALM REST API — рабочая шпаргалка
Справочник для загрузки Пожеланий, Заявок, Требований и вложений в Devprom ALM
через REST API. Имена сущностей сверены с официальной таблицей справочника
разработчика: `/pm/all/apidocs/list` (например,
[artsaterra.myalm.ru/pm/all/apidocs/list](https://artsaterra.myalm.ru/pm/all/apidocs/list)),
где каждая строка — одна сущность с её `ReferenceName` (используется в REST API)
и русским именем. Ключевые строки, участвующие в режиме Пожеланий из совещания:
| № | ReferenceName | Сущность |
|----|------------------|--------------------|
| 45 | `issue` | **Пожелание** |
| 18 | `request` | Доработка (заявка с типом) |
| 81 | `requesttype` | Тип пожелания |
| 92 | `requirement` | Требование |
| 57 | `attachment` | Приложение (файл) |
| 33 | `company` | Компания |
| 46 | `user` | Пользователь |
Дополнительные эмпирические детали (поведение, которое в публичной
документации не раскрыто явно) проверены на инстансе `artsaterra.myalm.ru`
и отмечаются в тексте курсивом _(проверено эмпирически)_.
Связанные ресурсы:
- Публичная документация Devprom: [docs.myalm.ru](https://docs.myalm.ru/)
- Раздел про управление пожеланиями: [artsaterra.myalm.ru/docs/8835.html](https://artsaterra.myalm.ru/docs/8835.html)
---
## 0. Базовое
- **Хост:** `https://<host>/pm/<project-slug>/api/latest`
- **Аутентификация:** заголовок `Devprom-Auth-Key: <hex>` (личный API-ключ пользователя)
- **Content-Type:** `application/json`
- **Ответ:** HTTP 200 всегда, ошибки валидации приходят в теле как `{"error":"…"}`
- **PATCH не поддерживается** — HTTP 405. Обновление только через PUT.
- **Успешный ответ на создание:** иногда возвращается как объект, иногда — как массив с одним элементом. Учитывать оба случая.
## 1. Пожелания vs Заявки — КРИТИЧНО
В официальной схеме Devprom это **две разные сущности** с разными
`ReferenceName` (см. таблицу выше):
- **`issue` (Пожелание)** — сущность из строки 45. Создаётся без типа,
UID с префиксом `U-`. В UI живёт в разделе «Пожелания»
(`/module/requirements/issues`).
- **`request` (Доработка)** — сущность из строки 18. Создаётся с обязательным
типом (Доработка / Ошибка), UID с префиксом `I-`. В UI живёт на доске
заявок (`/issues/board`).
| Логический класс | Эндпоинт | Префикс UID | Поле Type | UI-раздел |
|------------------------------|-------------------|-------------|-----------------|------------------------------------|
| **Пожелание** (`issue`) | `/issue/items` | `U-` | пусто | `/module/requirements/issues` |
| **Доработка** (`request`) | `/request/items` | `I-` | 397 (Доработка) / 398 (Ошибка) | `/issues/board` |
_Проверено эмпирически:_ GET на `/issue/items/{id}` и `/request/items/{id}`
возвращает **одну и ту же запись** (разные виды на один ресурс — внутренне
это один класс `pm_ChangeRequest`). Разница проявляется при POST — сервер
применяет разную логику автозаполнения в зависимости от эндпоинта.
### Почему попасть в «Доску пожеланий» можно только через `/issue/items`
_Проверено эмпирически:_ `/request/items` при POST **всегда принудительно
проставляет `Type=397`** (Доработка), даже если передать `Type: null`,
`Type: {}` или `Type: {"Id":""}`. Все варианты PUT тоже бессильны — сервер
восстанавливает 397. Подтверждено на 8 вариантах тела.
Поэтому для создания «чистого» Пожелания (с пустым Type и префиксом `U-`)
используется эндпоинт именно сущности `issue`**POST на `/issue/items`**.
## 2. Алгоритм создания Пожелания (рабочий рецепт)
Один POST на одно Пожелание. Без PUT, без привязки к требованиям.
```python
post_body = {
"Caption": "<заголовок>",
"Content": "<html-описание>", # по документации; Description тоже принимается
"Priority": {"Id": "2"}, # 1=Критично, 2=Высокий, 3=Обычный
"Author": {"Id": "<issueauthor.id>"},
"Function": {"Id": "<feature.id>"}, # подсистема (группировка)
"Company": {"Id": "<company.id>"}, # опционально: клиент-источник
}
# POST {BASE}/issue/items → {UID: "U-xxxx", Id: "xxxx", ...}
```
Поля `Requirement` и `RequirementDocument` в теле **не передаются**:
привязка к документу требований — задача пользователя в UI, не API.
На этапе создания Пожелания она и не нужна — заказчик подтверждает
пожелания, формализует требования и уже потом вручную связывает одно
с другим.
> **Примечание для других сценариев.** Если всё-таки нужно привязать
> Пожелание к существующему требованию из API (например, массовая
> миграция из внешней системы), это делается вторым шагом через
> `PUT /issue/items/{id}` с тем же телом + `Requirement.Id`
> — в одном POST эти поля молча игнорируются. Для режима «Пожелания
> из совещания» этот путь не нужен.
### Retry-политика
Egress-прокси периодически роняет запросы с HTTP 502/503/504 («DNS cache overflow»). Всегда оборачивать вызов в цикл `retries=3` с `sleep(2..3)`. Это не связано с Devprom — лечится только ретраями.
## 3. Поля Пожелания — полный справочник
| Поле | Тип / формат | Обязательность | Комментарий |
|-----------------------|------------------------------|----------------|-------------|
| `Caption` | string | обязательно | Заголовок пожелания |
| `Content` | HTML-string | обязательно | Описание. Разрешены: `<p> <b> <ul> <ol> <li> <a> <blockquote> <code>`. Поле `Description` на входе тоже принимается как алиас. |
| `Priority.Id` | "1" / "2" / "3" | по смыслу | 1=Критично, 2=Высокий, 3=Обычный |
| `Author.Id` | issueauthor.id | обязательно | Автор пожелания. Справочник инстанс-уровня. |
| `Function.Id` | feature.id | рекомендовано | Группировка по подсистемам (создаются через `/feature/items`) |
| `Company.Id` | company.id | опционально | Клиент-источник пожелания. Принимается в POST напрямую. |
| `Requirement.Id` | requirement.id | **не передавать в режиме Пожелания из совещания** | Привязка к документу требований — задача пользователя в UI. Для других сценариев (миграция) — только через отдельный PUT после POST. |
| `RequirementDocument` | — | — | **Не передавать**, заполняется сервером автоматически по родителю `Requirement` |
| `Type.Id` | requesttype.id / пусто | **НЕ передавать для пожелания** | Любая попытка обнулить через API бесполезна; если передать — получится «Заявка» с префиксом I- |
## 4. Удаление
| Эндпоинт | DELETE работает? | Поведение |
|------------------------------|------------------|-----------|
| `DELETE /issue/items/{id}` | **ДА — универсальный** | HTTP 200, запись пропадает. Работает для ЛЮБОЙ записи — и для U- (созданных через `/issue/items`), и для I- (созданных через `/request/items`). Сущности `issue` и `request` указывают на один класс `pm_ChangeRequest` в БД, но DELETE разрешён только на пути `issue/items`. |
| `DELETE /request/items/{id}` | **НЕТ** | HTTP 200 с `{"error":"Unable access entity"}`, запись не удаляется. Сервер возвращает эту ошибку даже для записей, созданных через `/request/items`. |
| `DELETE /requirement/items/{id}` | _Не гарантировано_ | Возвращает HTTP 200 с `{"error":"Unable access entity"}`, но GET после этого иногда показывает запись пустой (UID='', Caption=''). Эффект — неявное удаление / повреждение записи. Использовать с осторожностью. |
**Практический вывод:** для удаления любой записи Request/Issue —
всегда `DELETE /issue/items/{id}`, независимо от того, как она была создана.
## 5. Справочные эндпоинты (read-only для нашего ключа)
| Эндпоинт | Назначение |
|-------------------------------|------------------------------------|
| `/requesttype/items` | Типы заявок: Доработка, Ошибка |
| `/priority/items` | Приоритеты |
| `/feature/items` | Подсистемы/функции (**имя "feature", не "function"!**) |
| `/issueauthor/items` | Авторы пожеланий (инстанс-справочник) |
| `/user/items` | Пользователи проекта |
| `/company/items` | Компании-клиенты |
| `/requirement/items` | Требования и документы требований |
| `/state/items` | Состояния |
## 6. Что НЕ работает через API (заблокировано политикой прав)
| Операция | Ответ API | Обход |
|---------------------------------------|------------------------------------|-------|
| POST `/issueauthor/items` | HTTP 200 + `{"error":"Lack of permissions to create object of IssueAuthor"}` | Только UI: `/pm/<project>/issueauthor` или inline-форма в карточке пожелания |
| POST `/user/items` | То же | Только UI |
| DELETE `/request/items/{id}` | `{"error":"Unable access entity"}` | **Не препятствие:** удалять через `DELETE /issue/items/{id}` — он работает для любой записи Request (см. раздел 4). |
Пытаться обойти через write-only ключ проекта, `api/v1`, `api/v2`, инстанс-путь без `/pm/<project>/`**бесполезно**, все варианты дают тот же отказ.
## 7. Создание документа требований
> ⚠️ **В режиме «Пожелания из совещания» этот путь НЕ используется.**
> Структуру документов требований (`requirement`, строка 92 таблицы сущностей)
> выстраивает владелец проекта/аналитик вручную через UI Devprom —
> постепенно, по мере формализации требований, согласованных с заказчиком.
> Привязку Пожеланий (`issue`) к требованиям пользователь тоже делает
> вручную в UI. Режим извлечения пожеланий в эту структуру не вмешивается.
> Раздел оставлен для справки — на случай других задач (миграция требований,
> импорт из внешней системы и т.п.).
```python
POST /requirement/items
body = {
"Caption": "Корневой документ",
"Content": "<p>описание</p>",
# "ParentPage": {"Id": "..."} # если создаём подстраницу
}
```
Корневой документ — без `ParentPage`. Подстраница — с `ParentPage.Id = <id_корня>`. UID корневых документов присваивается по правилам шаблона проекта (например, `О-1`, `R-35`).
## 8. Attachment (приложить файл)
По [официальной документации](https://artsaterra.myalm.ru/docs/8835.html):
```python
POST /attachment/items
body = {
"FileExt": "transcript.txt",
"ObjectId": "<request.id>",
"ObjectClass": "Request", # именно Request — общий класс для issue и request
"File": "<base64 содержимого>",
}
```
## 9. Альтернативные и несуществующие эндпоинты
Тестировались, но возвращают `{"error":"Unknown entity: ..."}`:
- `/userwish/items`, `/wish/items`, `/userrequest/items`, `/suggestion/items`
- `/admin/request/items`, `/api/latest/admin/request/items`
- `/pmcustomclass/items`, `/customclass/items`, `/class/items`
Существующие служебные варианты:
- `/api/v1/request/items`, `/api/v2/request/items` — принимают POST,
но принудительная логика `Type=397` та же, что на `/api/latest/request/items`;
использовать не нужно.
> Примечание: эндпоинт `/issue/items` — не алиас `/request/items`,
> а отдельная сущность `issue` (Пожелание) из таблицы сущностей Devprom,
> строка 45. Под капотом они указывают на один и тот же класс
> `pm_ChangeRequest`, но серверная логика автозаполнения при POST
> у них разная (см. раздел 1).
## 10. Порядок подготовки проекта для загрузки пожеланий
Граница ответственности: **структуру проекта готовит человек через UI,
пожелания загружает скрипт через API**. Скрипт не создаёт Company,
Feature, документы требований, IssueAuthor — только читает их.
### Делается вручную через UI (один раз на проект, силами аналитика)
1. **Company** для каждого клиента, который генерирует пожелания.
- Пример: «АРД» с доменом `alreadycom.ru`.
2. **Feature** (подсистемы) — 3–5 на проект по подсистемам целевой
конфигурации. Можно создать и скриптом (`POST /feature/items`) —
на `feature` ограничений API нет, но обычно удобнее через UI.
- Пример для КА 2.5: «НСИ и администрирование», «Продажи», «Склад»,
«Казначейство», «Производство».
3. **IssueAuthor** для представителей заказчика — если нужно, чтобы
автором пожелания был сам клиент, а не аналитик. Только через UI.
4. **Документы требований** — структуру требований клиент/аналитик
выстраивает постепенно, по мере работы над проектом. Режим
извлечения Пожеланий в неё не вмешивается.
### Делается скриптом через API (каждое новое совещание)
5. **Цикл по Пожеланиям** — для каждого: один POST `/issue/items`
с полями Caption, Content, Priority, Author, Function и опционально
Company. `Requirement` не передаётся.
6. **GET** `/issue/items/{id}` — верификация, что UID начинается
на `U-`.
7. **Привязка Пожеланий к требованиям****вне скрипта**,
это ручная работа пользователя в UI, когда требования появятся
и согласованы с заказчиком.
---
## Appendix — примеры curl
### Создание пожелания (как в документации, с Type=Доработка)
```bash
curl -X POST \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/request/items \
-d '{"Caption":"Новая доработка","Content":"<p>Описание</p>","Type":{"Id":"397"}}'
# → UID=I-xxxx, Type=Доработка
```
### Создание пожелания без типа (рекомендуемый путь)
```bash
curl -X POST \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/issue/items \
-d '{"Caption":"Пожелание","Content":"<p>Описание</p>","Priority":{"Id":"2"},"Author":{"Id":"1"},"Function":{"Id":"190"},"Company":{"Id":"146"}}'
# → UID=U-xxxx, Type=пусто
```
### Привязка к документу требований (не нужна в режиме «Пожелания из совещания»)
Используется только для миграционных сценариев:
```bash
curl -X PUT \
-H "Devprom-Auth-Key: <KEY>" -H "Content-Type: application/json" \
https://<host>/pm/<proj>/api/latest/issue/items/6179 \
-d '{"Caption":"Пожелание","Content":"<p>Описание</p>","Priority":{"Id":"2"},"Author":{"Id":"1"},"Function":{"Id":"190"},"Requirement":{"Id":"4378"}}'
```
### Удаление
```bash
curl -X DELETE \
-H "Devprom-Auth-Key: <KEY>" \
https://<host>/pm/<proj>/api/latest/issue/items/6179
# → HTTP 200, []
```