H-3821: задокументировал /admin/employment в v2 swagger

Новый admin read-only API трудоустройств. Основной кейс —
маппинг (origin_id, origin_organization_id) → user_id для
интеграторов (web-zaim, sokolove и др.).

- Тег admin-employment (Methods for admin read-only access...).
- GET /admin/employment: index с полным набором фильтров
  EmploymentSearch (origin_id[], origin_organization_id, user_id[],
  department_id, chief_id, is_main, status_id, reg_status_id,
  employment_date/fired_date/created_at range, name/position ilike,
  user_list_key, chief_only*, multipleEmployment).
- GET /admin/employment/view?id=<uuid>: одна запись.
- Доступ: user-edit (тот же perm что в legacy /api/employment v1).
- Схемы AdminEmployment, AdminEmploymentList, AdminEmploymentUserShort,
  AdminEmploymentChiefUserShort, AdminEmploymentDepartmentShort.
- В описании метода — главный кейс маппинга origin → user_id,
  совместительства, поведение uvol'нённых, батч origin_id[].

Источники: контроллер app\controllers\api\v2\admin\EmploymentController,
testrix tests/v2/admin/test_admin_employment.py +
hrbox/models/v2/AdminEmploymentModel.py (pydantic).
Проверено живьём на denis.hrbox.io: totalCount=9393, все поля
схемы совпадают с реальным ответом.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Denis
2026-05-28 16:01:35 +03:00
co-authored by Claude Opus 4.7
parent f86becd7ff
commit 6ad75bdd1e
+314
View File
@@ -73,6 +73,8 @@ tags:
description: Methods for managing personal API tokens (PATs) for server-to-server access. Requires "api-tokens-manage" permission. description: Methods for managing personal API tokens (PATs) for server-to-server access. Requires "api-tokens-manage" permission.
- name: admin-user-api-token - name: admin-user-api-token
description: Methods for admin oversight of personal API tokens. Requires "api-tokens-admin" permission. description: Methods for admin oversight of personal API tokens. Requires "api-tokens-admin" permission.
- name: admin-employment
description: Methods for admin read-only access to employee employments — primary source of origin_id ↔ user_id mapping for integrations. Requires "user-edit" permission.
paths: paths:
/mobile/bind/{id}/{token}: /mobile/bind/{id}/{token}:
@@ -7529,6 +7531,177 @@ paths:
404: 404:
description: Токен не найден. description: Токен не найден.
/admin/employment:
get:
tags: [admin-employment]
summary: Список трудоустройств — admin read-only
description: |
Постраничный список трудоустройств всего тенанта с фильтрами
`EmploymentSearch`. Поведением и набором полей идентичен
legacy-эндпоинту `/api/employment` (v1) — перенесён в v2 как
основа для интеграций (web-zaim, sokolove и др.) и будущей
Vue3-админки.
### Главный кейс — маппинг (origin_id, origin_organization_id) → user_id
```
GET /api/v2/admin/employment
?origin_id=12345
&origin_organization_id=default
```
В ответе `data[].user_id` — это родной HRBox UUIDv4 пользователя,
который дальше можно передавать в любые v2-эндпоинты, ожидающие
`user_id`. Поддерживается батч: `?origin_id[]=...&origin_id[]=...`.
### Совместительства
Один пользователь может иметь несколько трудоустройств с разными
`origin_id`. Поле `is_main` отличает основное от дополнительных.
### Уволенные
Записи с `fired_date != null` включены по умолчанию — нужны для
синхронизации увольнений. Если нужны только активные —
фильтруйте `status_id=1`.
operationId: adminEmploymentIndex
parameters:
- name: page
in: query
schema: { type: integer, minimum: 1, default: 1 }
- name: per-page
in: query
schema: { type: integer, minimum: 1, default: 20 }
- name: sort
in: query
schema: { type: string }
description: 'Префикс `-` для DESC. Атрибуты — `created_at`, `employment_date`, `fired_date`, и др. (по `EmploymentSearch::sort`).'
- name: id
in: query
schema: { type: string, format: uuid }
- name: user_id
in: query
schema:
oneOf:
- type: string
format: uuid
- type: array
items: { type: string, format: uuid }
description: 'UUID юзера. Массив через `?user_id[]=...&user_id[]=...` или comma-separated.'
- name: chief_id
in: query
schema: { type: string, format: uuid }
description: UUID employment'а руководителя.
- name: department_id
in: query
schema: { type: string, format: uuid }
description: UUID подразделения (с автоматическим учётом поддерева).
- name: origin_id
in: query
schema:
oneOf:
- type: string
- type: array
items: { type: string }
description: Внешний ID (например из 1С). Comma-separated или массив.
- name: origin_organization_id
in: query
schema: { type: string }
description: Идентификатор организации во внешней системе (для мульти-org тенантов).
- name: org_num
in: query
schema: { type: string }
description: Comma-separated табельные номера.
- name: first_name
in: query
schema: { type: string }
description: ilike-поиск.
- name: last_name
in: query
schema: { type: string }
description: ilike-поиск.
- name: name
in: query
schema: { type: string }
description: ilike по `first_name` + `last_name` через JOIN User.
- name: position
in: query
schema: { type: string }
description: ilike-поиск по должности.
- name: is_main
in: query
schema: { type: boolean }
description: Только основные трудоустройства.
- name: status_id
in: query
schema: { type: integer }
description: 'Стандартный enum `Status` (1=Active, 2=Disabled).'
- name: reg_status_id
in: query
schema: { type: string }
description: Comma-separated `RegStatus` (1=NO_ACCOUNT, 2=INVITED, 3=ACTIVE, 4=BLOCKED) — фильтр по статусу владельца.
- name: created_at
in: query
schema: { type: string }
description: 'Диапазон `from|to` (ISO).'
- name: employment_date
in: query
schema: { type: string }
description: 'Диапазон даты приёма `from|to`.'
- name: fired_date
in: query
schema: { type: string }
description: 'Диапазон даты увольнения `from|to`.'
- name: user_list_key
in: query
schema: { type: string, format: uuid }
description: 'Ключ закэшированной выборки сотрудников (см. `/user-list-cache/set-user-list`).'
- name: chief_only
in: query
schema: { type: boolean }
description: Только прямые подчинённые текущего юзера.
- name: chief_only_all
in: query
schema: { type: boolean }
description: Все подчинённые рекурсивно.
- name: multipleEmployment
in: query
schema: { type: boolean }
description: Только записи юзеров с несколькими трудоустройствами.
responses:
200:
description: Список трудоустройств
content:
application/json:
schema:
$ref: '#/components/schemas/AdminEmploymentList'
403:
description: Нет права `user-edit`.
/admin/employment/view:
get:
tags: [admin-employment]
summary: Одно трудоустройство — admin read-only
operationId: adminEmploymentView
parameters:
- name: id
in: query
required: true
schema: { type: string, format: uuid }
responses:
200:
description: Трудоустройство
content:
application/json:
schema:
$ref: '#/components/schemas/AdminEmployment'
400:
description: Невалидный UUID.
403:
description: Нет права `user-edit`.
404:
description: Запись не найдена (включая cross-tenant).
components: components:
securitySchemes: securitySchemes:
SessionAuth: SessionAuth:
@@ -12647,6 +12820,147 @@ components:
_meta: _meta:
$ref: '#/components/schemas/_meta' $ref: '#/components/schemas/_meta'
AdminEmploymentUserShort:
type: object
properties:
id: { type: string, format: uuid }
name: { type: string, nullable: true }
faceUrl: { type: string, format: uri, nullable: true }
AdminEmploymentChiefUserShort:
type: object
properties:
id: { type: string, format: uuid }
name: { type: string, nullable: true }
AdminEmploymentDepartmentShort:
type: object
properties:
id: { type: string, format: uuid }
name: { type: string, nullable: true }
departmentPath:
type: string
nullable: true
description: 'Полный путь от корня структуры через `/`.'
AdminEmployment:
type: object
description: |
Запись трудоустройства в admin-выдаче. Содержит как сырые поля
Employment, так и связанные `user` / `chiefUser` / `department`.
properties:
id:
type: string
format: uuid
description: UUID трудоустройства (родной HRBox).
is_main:
type: boolean
description: Основное трудоустройство (одно на юзера). Несколько `false` — совместительства.
user_id:
type: string
format: uuid
description: UUID владельца (`hr_user.id`) — **то самое значение для маппинга origin → user**.
chief_id:
type: string
format: uuid
nullable: true
description: UUID employment'а руководителя (не User'а).
department_id:
type: string
format: uuid
nullable: true
position:
type: string
nullable: true
employment_date:
type: string
nullable: true
description: Дата приёма (ISO).
fired_date:
type: string
nullable: true
description: Дата увольнения (ISO). `null` для действующих.
status_id:
type: integer
nullable: true
description: 'Стандартный `Status` (1=Active, 2=Disabled).'
origin_id:
type: string
nullable: true
description: Внешний идентификатор должности из системы-источника (1С и т.п.).
origin_organization_id:
type: string
nullable: true
description: Идентификатор внешней организации. Маппинг — это **пара** `(origin_id, origin_organization_id)`.
org_num:
type: string
nullable: true
description: Табельный номер.
first_name: { type: string, nullable: true }
last_name: { type: string, nullable: true }
photo:
type: string
nullable: true
description: Имя файла фото из источника (если приходит из интеграции).
created_at: { type: string, nullable: true }
updated_at: { type: string, nullable: true }
experience:
type: string
nullable: true
description: 'Стаж в человекочитаемом виде (например `15 years 3 months 19 days`).'
name:
type: string
nullable: true
description: Готовая строка ФИО юзера-владельца.
nameDetails:
type: string
nullable: true
iconUrl:
type: string
format: uri
nullable: true
profilePosition:
type: string
nullable: true
user:
$ref: '#/components/schemas/AdminEmploymentUserShort'
chiefUser:
allOf:
- $ref: '#/components/schemas/AdminEmploymentChiefUserShort'
nullable: true
department:
allOf:
- $ref: '#/components/schemas/AdminEmploymentDepartmentShort'
nullable: true
createdAt:
type: string
nullable: true
description: 'Локализованная `created_at`.'
employmentDate:
type: string
nullable: true
description: 'Локализованная `employment_date`.'
firedDate:
type: string
nullable: true
description: 'Локализованная `fired_date`.'
statusName:
type: string
nullable: true
description: 'Локализованное имя статуса.'
AdminEmploymentList:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AdminEmployment'
_links:
$ref: '#/components/schemas/_links'
_meta:
$ref: '#/components/schemas/_meta'
parameters: parameters:
boardDateTypeParam: boardDateTypeParam:
in: query in: query