diff --git a/v2/swagger.yaml b/v2/swagger.yaml index c29476c..9676bbf 100644 --- a/v2/swagger.yaml +++ b/v2/swagger.yaml @@ -69,6 +69,8 @@ tags: description: Methods for admin wallet transactions — manual and excel-based credit/debit. - name: file-processing description: Methods for polling async file processing (excel import/export, archives). Scoped to current user's files. + - name: user-list-cache + description: Methods for caching ad-hoc employee selections to pass to mass operations (e.g. wallet credit/debit). - name: user-api-token description: Methods for managing personal API tokens (PATs) for server-to-server access. Requires "api-tokens-manage" permission. - name: admin-user-api-token @@ -7114,12 +7116,27 @@ paths: tags: [admin-wallet-transaction] summary: Провести начисление/списание по форме description: | - Массовая операция через `usersListKey` (ключ закэшированной выборки сотрудников). - Запускается асинхронно через launcher. + Массовая операция по выборке сотрудников. Запускается асинхронно + через launcher — баланс и история транзакций обновятся в течение + нескольких секунд. - Soft-error состояния возвращаются в `message.type=warning`: - - "Укажите сотрудников" — выборка пустая - - "Невозможно провести транзакцию, у некоторых сотрудников недостаточно средств..." — debit, не хватает баланса (имена в тексте) + ### Как получить `usersListKey` + + 1. `POST /api/v2/user-list-cache/set-user-list` с телом + `{key, userList:{usersId:[...]}}` — кэширует выборку под вашим + ключом (TTL 24 часа). + 2. Этот же `key` отдаёте здесь как `usersListKey`. + + Подробности и пример — в описании метода `set-user-list`. + + ### Soft-error состояния (`200 OK` + `message.type=warning`) + + - `"Укажите сотрудников"` — выборка по `usersListKey` пустая + (ключ протух, не существует или userList отдали через form-urlencoded — + см. `set-user-list`). + - `"Невозможно провести транзакцию, у некоторых сотрудников + недостаточно средств на балансе: <имена>"` — debit, не хватает + баланса хотя бы у одного юзера; вся операция отменяется. operationId: adminWalletTransactionCreate requestBody: required: true @@ -7271,6 +7288,93 @@ paths: schema: $ref: '#/components/schemas/FileProcessing' + /user-list-cache/set-user-list: + post: + tags: [user-list-cache] + summary: Закэшировать выборку сотрудников и получить ключ + description: | + Кэширует произвольную выборку сотрудников (по `usersId`, + `departmentsId`, `userGroupsId`, динамическим условиям и т.д.) + и связывает её с переданным `key`. Дальше этот `key` можно + отдавать в массовые операции — например в + `POST /api/v2/admin/wallet-transaction/create` как `usersListKey`. + + Ключ хранится в кеше **сутки** (60 × 1440 секунд). Повторный + вызов с тем же `key` перетирает выборку. + + ### ⚠️ Content-Type обязательно `application/json` + + Поле `userList` — это вложенный JSON-объект (см. схему + `UserListForm`). Через `application/x-www-form-urlencoded` + кастомный `Model::setAttributes` не парсит вложенные JSON-модели, + и сервер сохранит **пустую** выборку. Внешне ответ будет + `{success:true}`, но при попытке провести транзакцию вы получите + `{type:"warning", text:"Укажите сотрудников"}`. Только JSON. + + ### Пример + + ```json + POST /api/v2/user-list-cache/set-user-list + Content-Type: application/json + Authorization: Bearer hrb_... + + { + "key": "my-integration-key-2026-05-22", + "userList": { + "usersId": ["25840ad3-a07f-4893-aa70-3a696b79a6f1"] + } + } + ``` + + `key` придумываете сами (до 50 символов). + operationId: userListCacheSet + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UserListCacheSetBody' + responses: + 200: + description: | + Успех (`data: true`) или ошибки валидации в стандартном формате + `httpJsonResponse`. + content: + application/json: + schema: + $ref: '#/components/schemas/httpJsonResponse' + + /user-list-cache/user-list-data: + get: + tags: [user-list-cache] + summary: Получить состав закэшированной выборки сотрудников + description: | + Возвращает развёрнутый состав выборки по ключу: список пользователей + (`users`), список подразделений (`departments`), список групп + (`userGroups`), исходную форму (`userList`), нормализованные + условия групп и т.д. Полезно для preview перед массовой операцией. + + Если ключ протух (24 ч) или не существует — `userList` будет + пустым, остальные коллекции — пустыми массивами. + operationId: userListCacheData + parameters: + - name: key + in: query + required: true + schema: { type: string, maxLength: 50 } + responses: + 200: + description: Данные выборки + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/httpJsonResponse' + - type: object + properties: + data: + $ref: '#/components/schemas/UserListData' + /user-api-token: get: tags: [user-api-token] @@ -12521,6 +12625,107 @@ components: _meta: $ref: '#/components/schemas/_meta' + UserListForm: + type: object + description: | + Описание выборки сотрудников. Все поля опциональны — указывайте те, + которыми хотите задать состав. Условия объединяются через OR + (любой из критериев включает юзера). + properties: + usersId: + type: array + description: Явный список UUID сотрудников. + items: + type: string + format: uuid + departmentsId: + type: array + description: UUID подразделений. Включает всех сотрудников этих подразделений. + items: + type: string + format: uuid + isDepartmentRecursive: + type: boolean + default: false + description: Если `true` — захватывает сотрудников вложенных подразделений тоже. + userGroupsId: + type: array + description: UUID статических групп сотрудников. + items: + type: string + format: uuid + userGroupConditions: + type: array + description: | + Динамические условия выборки (как в админке UserGroup). Каждый + элемент — объект `{condition, operator, values}`. + items: + type: object + employmentStatuses: + type: array + description: Фильтр по статусам трудоустройства. + items: + type: integer + fileProcessingId: + type: string + format: uuid + nullable: true + description: UUID `FileProcessing` с распарсенным xlsx — выборка возьмётся оттуда. + + UserListCacheSetBody: + type: object + required: [key, userList] + properties: + key: + type: string + maxLength: 50 + description: | + Произвольный идентификатор выборки. Этот же ключ потом передаётся + как `usersListKey` в массовые операции. + example: "my-integration-2026-05-22" + userList: + $ref: '#/components/schemas/UserListForm' + + UserListData: + type: object + description: | + Развёрнутый состав выборки. Возвращается `GET /user-list-cache/user-list-data`. + properties: + userList: + $ref: '#/components/schemas/UserListForm' + users: + type: array + description: Развёрнутые юзеры из выборки (с `faceUrl`). + items: + type: object + departments: + type: array + description: Развёрнутые подразделения. + items: + type: object + userGroups: + type: array + description: Развёрнутые группы. + items: + type: object + userGroupConditions: + type: array + items: + type: object + userGroupConditionsReadable: + type: array + items: + type: object + userGroupConditionValues: + type: array + nullable: true + items: + type: object + fileProcessing: + allOf: + - $ref: '#/components/schemas/FileProcessing' + nullable: true + UserApiTokenStatus: type: integer description: |