feat: полный бэк и фронт (попытки, разбор, импорт, ИИ, назначения)
- Сервисы: testAttemptService, testAccess, document import/gen/extract, LLM, assignment, aiEditor - Конфиг: devAuthor, featureFlags; messages/ru; интеграция V.9 (skip без БД) - API/роуты: app, auth, server; Dockerfile и env example - Фронт: TestAttempt, TestAttemptReview, AttemptReviewBlock, стили, правки App/api/login/vite - compose и README; смоук-тесты расширены Закрывает отсутствие модулей в origin после клона. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Создать/найти запись `clinic_tests.users` по staff_id (HR), чтобы назначить target_id = uuid.
|
||||
*/
|
||||
import { queryHr, getHrPool } from '../db/hrPool.js';
|
||||
import { HR_MANAGED_PASSWORD_PLACEHOLDER } from '../config/authConstants.js';
|
||||
import { RU } from '../messages/ru.js';
|
||||
|
||||
/**
|
||||
* @param {import('pg').Pool} pool
|
||||
* @param {number} staffId
|
||||
* @returns {Promise<string>} uuid в clinic_tests.users
|
||||
*/
|
||||
export async function ensureClinicUserIdForStaff(pool, staffId) {
|
||||
const n = Math.floor(Number(staffId));
|
||||
if (!Number.isFinite(n) || n < 1) {
|
||||
const e = new Error(RU.assignmentUserRequired);
|
||||
e.status = 400;
|
||||
throw e;
|
||||
}
|
||||
const { rows: ex } = await pool.query(
|
||||
`SELECT id FROM users WHERE staff_id = $1 AND is_active = true LIMIT 1`,
|
||||
[n]
|
||||
);
|
||||
if (ex.length) {
|
||||
return ex[0].id;
|
||||
}
|
||||
if (!getHrPool()) {
|
||||
const e = new Error('Нет HR БД: нельзя завести учётку по staff_id.');
|
||||
e.status = 400;
|
||||
throw e;
|
||||
}
|
||||
const { rows: st } = await queryHr(
|
||||
`SELECT id, fio, web_login FROM staff_members WHERE id = $1`,
|
||||
[n]
|
||||
);
|
||||
if (!st.length) {
|
||||
const e = new Error('Сотрудник не найден в HR.');
|
||||
e.status = 400;
|
||||
throw e;
|
||||
}
|
||||
const fio = st[0].fio || `staff #${n}`;
|
||||
const rawLogin = (st[0].web_login && String(st[0].web_login).trim()) || null;
|
||||
let login = rawLogin;
|
||||
if (!login) {
|
||||
login = `staff_${n}@clinic.local`;
|
||||
}
|
||||
const { rows: taken } = await pool.query(
|
||||
`SELECT 1 FROM users WHERE LOWER(TRIM(login)) = LOWER(TRIM($1)) AND (staff_id IS NULL OR staff_id <> $2) LIMIT 1`,
|
||||
[login, n]
|
||||
);
|
||||
if (taken.length) {
|
||||
login = `staff_${n}@clinic.local`;
|
||||
}
|
||||
const ins = await pool.query(
|
||||
`INSERT INTO users (login, password_hash, full_name, role, department_id, is_active, staff_id)
|
||||
VALUES ($1, $2, $3, 'employee', null, true, $4)
|
||||
ON CONFLICT (staff_id) DO UPDATE SET
|
||||
full_name = EXCLUDED.full_name,
|
||||
is_active = true
|
||||
RETURNING id`,
|
||||
[login, HR_MANAGED_PASSWORD_PLACEHOLDER, fio, n]
|
||||
);
|
||||
return ins.rows[0].id;
|
||||
}
|
||||
Reference in New Issue
Block a user