Merge feat/keycloak into add_filters with manual conflict resolution.

Preserve Keycloak auth/RBAC contracts while retaining filter behavior and generator consistency for future regenerations.

Made-with: Cursor
This commit is contained in:
MaKarin
2026-03-24 13:52:20 +03:00
78 changed files with 2949 additions and 3880 deletions

236
domain/TOiR.domain.dsl Normal file
View File

@@ -0,0 +1,236 @@
/*
КИС ТОиР — демонстрационная схема доменной модели
Сущности: Equipment (Оборудование), EquipmentType (Вид оборудования), RepairOrder (Заявка на ремонт)
*/
enum EquipmentStatus {
value Active {
label "В эксплуатации";
}
value Repair {
label "В ремонте";
}
value Reserve {
label "В резерве";
}
value WriteOff {
label "Списано";
}
}
enum RepairKind {
value TO {
label "Техническое обслуживание";
}
value TR {
label "Текущий ремонт";
}
value TRE {
label "Текущий расширенный ремонт";
}
value KR {
label "Капитальный ремонт";
}
value AR {
label "Аварийный ремонт";
}
value MP {
label "Метрологическая поверка";
}
}
enum RepairOrderStatus {
value Draft {
label "Черновик";
}
value Approved {
label "Утверждена";
}
value InWork {
label "В работе";
}
value Done {
label "Выполнена";
}
value Cancelled {
label "Отменена";
}
}
entity EquipmentType {
description "Вид (марка) оборудования — нормативный справочник НСИ";
attribute code {
key primary;
description "Код вида оборудования";
type string;
is required;
is unique;
}
attribute name {
description "Наименование вида";
type string;
is required;
}
attribute manufacturer {
description "Производитель";
type string;
}
attribute maintenanceIntervalHours {
description "Периодичность ТО, моточасов";
type integer;
}
attribute overhaulIntervalHours {
description "Периодичность КР, моточасов";
type integer;
}
}
entity Equipment {
description "Единица оборудования — объект ремонта и технического обслуживания";
attribute id {
type uuid;
key primary;
}
attribute inventoryNumber {
description "Инвентарный номер";
type string;
is required;
is unique;
}
attribute serialNumber {
description "Заводской (серийный) номер";
type string;
}
attribute name {
description "Наименование единицы оборудования";
type string;
is required;
}
attribute equipmentTypeCode {
type string;
key foreign {
relates EquipmentType.code;
}
is required;
}
attribute status {
description "Текущий статус";
type EquipmentStatus;
default Active;
is required;
}
attribute location {
description "Место эксплуатации / скважина / куст";
type string;
}
attribute commissionedAt {
description "Дата ввода в эксплуатацию";
type date;
}
attribute totalEngineHours {
description "Общая наработка, моточасов";
type decimal;
}
attribute engineHoursSinceLastRepair {
description "Наработка с последнего ремонта, моточасов";
type decimal;
}
attribute lastRepairAt {
description "Дата последнего ремонта";
type date;
}
attribute notes {
description "Примечания";
type text;
}
}
entity RepairOrder {
description "Заявка на ремонт — формируется по ППР или по факту обнаруженного дефекта";
attribute id {
type uuid;
key primary;
}
attribute number {
description "Номер заявки";
type string;
is required;
is unique;
}
attribute equipmentId {
type uuid;
key foreign {
relates Equipment.id;
}
is required;
}
attribute repairKind {
description "Вид ремонта";
type RepairKind;
is required;
}
attribute status {
type RepairOrderStatus;
default Draft;
is required;
}
attribute plannedAt {
description "Плановая дата начала";
type date;
is required;
}
attribute startedAt {
description "Фактическая дата начала";
type date;
}
attribute completedAt {
description "Фактическая дата завершения";
type date;
}
attribute contractor {
description "Подрядная организация (если внешний ремонт)";
type string;
}
attribute engineHoursAtRepair {
description "Наработка на момент ремонта, моточасов";
type decimal;
}
attribute description {
description "Описание работ / дефекта";
type text;
}
attribute notes {
description "Примечания";
type text;
}
}

View File

@@ -1,6 +1,46 @@
# DSL Language Specification
This document describes the DSL (Domain Specific Language) used to specify fullstack CRUD applications. The DSL has four layers: Domain, DTO, API, and UI.
This document describes the single DSL (Domain Specific Language) used to specify fullstack CRUD applications. The only required DSL input is `domain/*.dsl`.
`domain-summary.json` is a derived artifact generated from this DSL to stabilize LLM-first generation and feed the lightweight validation gate. It must never replace the DSL as the source of truth. The active prompt corpus that consumes this contract lives in `prompts/`.
---
# DSL Responsibility
The domain DSL defines only:
- domain model
- relations
- enums
The domain DSL is the single source of truth for:
- entities
- attributes
- primary keys
- foreign keys
- enums
The following layers are always derived from the domain DSL and must not be authored as standalone authoritative DSL inputs:
- DTO
- API
- UI
Optional extension mechanism:
```text
overrides/
api-overrides.dsl
ui-overrides.dsl
```
Override rules:
- Overrides are optional.
- The generator must work without them.
- Overrides may refine derived API or UI behavior, but they must not duplicate or redefine entities, attributes, primary keys, foreign keys, relations, or enums.
---
@@ -108,7 +148,7 @@ attribute equipmentTypeCode {
## required
- **is required** — attribute is non-nullable in domain and (unless overridden) in DTOs.
- **is required** — attribute is non-nullable in the domain model and drives requiredness in derived DTO/API/UI artifacts.
- Absence of `is required` means the attribute is optional (nullable).
---
@@ -120,33 +160,6 @@ attribute equipmentTypeCode {
---
## map
Used in **DTO** and **UI** layers to bind a DTO/UI field to a domain entity attribute.
**In DTO:**
```
attribute name {
type string;
map Equipment.name;
}
```
- Ensures DTO attribute corresponds to an existing `Entity.attribute` and that types align.
**In UI:**
```
attribute Наименование {
map Equipment.name;
}
```
- UI label (e.g. "Наименование") maps to domain field `Equipment.name` for correct data binding and generation.
---
# DSL → System Component Mapping
## DSL → Prisma
@@ -174,9 +187,9 @@ attribute Наименование {
| entity | One module (e.g. equipment.module.ts) |
| entity | Controller with CRUD endpoints |
| entity | Service with Prisma CRUD |
| DTO (Create) | create-{entity}.dto.ts |
| DTO (Update) | update-{entity}.dto.ts |
| DTO (Response) | Used for GET response shape |
| entity + attribute metadata | create-{entity}.dto.ts |
| entity + attribute metadata | update-{entity}.dto.ts |
| entity + attribute metadata | Response DTO / API shape |
API paths are derived from entity name: PascalCase → kebab-case, pluralized (e.g. `Equipment``/equipment`, `RepairOrder``/repair-orders`).
@@ -193,21 +206,12 @@ API paths are derived from entity name: PascalCase → kebab-case, pluralized (e
| type date | DateInput, DateField |
| enum | SelectInput with choices |
| foreign key | ReferenceInput, ReferenceField |
| UI attribute with map | Field with correct source |
---
# DTO Mapping
# Derived Layer Mapping
- **map Entity.attribute** — DTO attribute corresponds to domain attribute; types must match.
- **Create DTO** — must not include generated primary keys (e.g. no `id` for uuid PK).
- **Update DTO** — all fields optional (nullable) for partial updates.
- **List response DTO** — must expose `data` (array) and `total` (integer) for React Admin compatibility.
---
# UI Mapping
- Each UI attribute should have **map Entity.attribute** so it binds to a real domain field.
- UI attribute name is the label (e.g. "Наименование"); **source** in generated components is the domain attribute name (e.g. `name`).
- Enums → SelectInput; foreign keys → ReferenceInput/ReferenceField.
- **Create DTO** — derived from domain attributes and must not include generated primary keys (for example no `id` for uuid PKs).
- **Update DTO** — derived from the same domain attributes with all fields optional for partial updates.
- **API response shape** — derived from domain attributes and must expose React Admin-compatible identifiers when needed.
- **UI field mapping** — derived from attribute types, descriptions, enums, and foreign keys without a separate UI DSL.