v2: подробные комментарии во всех модулях — что, зачем, контракты
This commit is contained in:
+39
-8
@@ -1,23 +1,42 @@
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
// V2 — CRUD API-слой (чистые функции, без Express)
|
||||
// V2 — CRUD API-слой
|
||||
//
|
||||
// Принимает clientId (W-номер), сам резолвит companyId через getOrCreateCompany.
|
||||
// Фронтенд (user/) и тесты (test/) дергают эти функции.
|
||||
// ЭТО: чистые функции — API между фронтендами и БД.
|
||||
// НЕ: Express, HTTP, req/res, сессии.
|
||||
//
|
||||
// Сигнатуры:
|
||||
// list(clientId) → { entries, used, limit }
|
||||
// add(clientId, cidr, comment, email, impBy) → { entry, wasNormalized }
|
||||
// edit(entryId, clientId, cidr, comment, email, impBy) → { entry, wasNormalized }
|
||||
// remove(entryId, clientId, email, impBy) → void
|
||||
// ЗАЧЕМ:
|
||||
// 1. Фронтенды (user/, admin/, test/) не знают про SQL, транзакции, companyId.
|
||||
// 2. Валидация вызывается ОДИН раз здесь, не дублируется в каждом фронтенде.
|
||||
// 3. clientId (W-номер) → companyId (внутренний ID БД) резолвится здесь.
|
||||
// 4. Каждую функцию можно тестировать изолированно, без Express.
|
||||
//
|
||||
// КОНТРАКТ:
|
||||
// list(clientId) → { entries, used, limit }
|
||||
// add(clientId, cidr, ...) → { entry, wasNormalized }
|
||||
// edit(entryId, clientId, ...) → { entry, wasNormalized }
|
||||
// remove(entryId, clientId, ...) → void
|
||||
//
|
||||
// Вход: clientId — W-номер компании (строка вида "WZ10001").
|
||||
// email — почта юзера (для аудита).
|
||||
// impBy — почта админа при имперсонации (null если нет).
|
||||
//
|
||||
// Ошибки: throw — валидация, лимит, дубликат, пересечение.
|
||||
// ═══════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
const q = require('../db/queries');
|
||||
const { validate } = require('../validators');
|
||||
|
||||
// ── resolve(clientId) → company (внутренний хелпер) ──────────────────────────
|
||||
// Атомарный upsert: если компании с таким W-номером нет — создаст.
|
||||
// Возвращает { id, client_id, name, custom_limit }.
|
||||
// Вызывается из list/add/edit/remove перед каждой операцией.
|
||||
async function resolve(clientId) {
|
||||
return q.getOrCreateCompany(clientId, clientId);
|
||||
}
|
||||
|
||||
// ── list(clientId, includeDeleted?) → { entries, used, limit } ──────────────
|
||||
// Всегда возвращает лимит и счётчик активных записей.
|
||||
// used — только неудалённые (deleted_at IS NULL).
|
||||
async function list(clientId, includeDeleted = false) {
|
||||
const co = await resolve(clientId);
|
||||
const entries = await q.listEntries(co.id, includeDeleted);
|
||||
@@ -26,18 +45,30 @@ async function list(clientId, includeDeleted = false) {
|
||||
return { entries, used, limit };
|
||||
}
|
||||
|
||||
// ── add(clientId, cidr, comment, email, impBy) → { entry, wasNormalized } ───
|
||||
// ПОРЯДОК:
|
||||
// 1. validate(rawCidr) — проверка ТЗ (маска, диапазоны, нормализация).
|
||||
// 2. resolve(clientId) — получить/создать компанию.
|
||||
// 3. db.createEntry() — транзакция: лимит, дубликаты, INSERT + аудит.
|
||||
// Если validate() бросает — до БД не доходим.
|
||||
async function add(clientId, cidr, comment, email, impBy) {
|
||||
const { cidr: validated, wasNormalized } = validate(cidr);
|
||||
const co = await resolve(clientId);
|
||||
return q.createEntry(co.id, validated, comment, email, impBy, wasNormalized);
|
||||
}
|
||||
|
||||
// ── edit(entryId, clientId, cidr, comment, email, impBy) → { entry, wasNormalized }
|
||||
// Аналогично add, но для существующей записи.
|
||||
// entryId — id из v2_entries (число).
|
||||
async function edit(entryId, clientId, cidr, comment, email, impBy) {
|
||||
const { cidr: validated, wasNormalized } = validate(cidr);
|
||||
const co = await resolve(clientId);
|
||||
return q.updateEntry(entryId, co.id, validated, comment, email, impBy, wasNormalized);
|
||||
}
|
||||
|
||||
// ── remove(entryId, clientId, email, impBy) → void ──────────────────────────
|
||||
// Soft delete: ставит deleted_at, записывает аудит.
|
||||
// Запись остаётся в БД, но не показывается в list().
|
||||
async function remove(entryId, clientId, email, impBy) {
|
||||
const co = await resolve(clientId);
|
||||
return q.deleteEntry(entryId, co.id, email, impBy);
|
||||
|
||||
Reference in New Issue
Block a user