DB Schema — Registrul Interdicțiilor (v2)
Acest conținut nu este încă disponibil în limba selectată.
Schema derivată din interdictii.jdl (v2) pentru verificare manuală înainte
de jhipster jdl ../interdictii.jdl --force.
Tipuri de date: PostgreSQL (profil prod). H2 (dev) folosește mapări
echivalente generate de Liquibase. Toate tabelele moștenesc 4 câmpuri de audit
de la AbstractAuditingEntity (omise din DDL-urile de mai jos pentru
lizibilitate — vezi §6).
1. ER diagram
Section titled “1. ER diagram”erDiagram ENTITATE ||--o{ INTERDICTIE : "vizat de" AUTORITATE_EMITENTA ||--o{ INTERDICTIE : "emite" TEMEI_LEGAL ||--o{ INTERDICTIE : "fundamentează" INTERDICTIE ||--o| CONDITIE : "(OneToOne, opțional)" CONDITIE }o--o| ACT : "îndeplinită prin" INTERDICTIE ||--o{ ACTIUNE_INTERZISA : "blochează" INTERDICTIE ||--o{ INTERDICTIE_ACT : "" ACT ||--o{ INTERDICTIE_ACT : "" INTERDICTIE ||--o{ EVENIMENT_INTERDICTIE : "audit append-only" INTERDICTIE ||--o{ NOTIFICARE : ""
ENTITATE { bigint id PK varchar categorie "enum CategorieEntitate (9)" varchar identificator "64 - IDNP/IDNO/VIN/IBAN/..." varchar nume_afisat "255" text atribute "jsonb după §6" } INTERDICTIE { bigint id PK varchar statut "enum 11 valori" varchar categorie_jurisdictie varchar categorie_domeniu varchar durata varchar intensitate date start_date date end_date text description bigint entitate_id FK bigint autoritate_id FK bigint temei_legal_id FK bigint conditie_id FK "UNIQUE - OneToOne" } ACTIUNE_INTERZISA { bigint id PK varchar actiune "enum 32 valori" text scope "jsonb" varchar intensitate bigint interdictie_id FK } CONDITIE { bigint id PK varchar tip text descriere boolean indeplinita timestamptz data_indeplinire bigint act_indeplinire_id FK } TEMEI_LEGAL { bigint id PK varchar act_normativ "255" varchar articol "64" varchar alineat "64" text descriere } AUTORITATE_EMITENTA { bigint id PK varchar name "255" varchar familie "enum 4" varchar nivel "enum 2" varchar cod_idno "13" } ACT { bigint id PK varchar tip varchar numar "64" date data varchar storage_uri "512" varchar hash_sha256 "64" varchar signature "2048" text descriere } INTERDICTIE_ACT { bigint id PK varchar rol "enum 9" date data_atasare bigint interdictie_id FK bigint act_id FK } EVENIMENT_INTERDICTIE { bigint id PK varchar tip "enum 13" varchar actor "64" timestamptz data text payload "jsonb" bigint interdictie_id FK } NOTIFICARE { bigint id PK varchar canal varchar destinatar "255" varchar status timestamptz sent_at text payload "jsonb" bigint interdictie_id FK } APP_USER { bigint id PK varchar username "64 UK" varchar password "255" varchar statut varchar rol }2. Tabele de domeniu (DDL)
Section titled “2. Tabele de domeniu (DDL)”2.1 entitate — entitatea polimorfică al interdicției
Section titled “2.1 entitate — entitatea polimorfică al interdicției”CREATE TABLE entitate ( id BIGINT NOT NULL PRIMARY KEY, categorie VARCHAR(32) NOT NULL, identificator VARCHAR(64) NOT NULL, nume_afisat VARCHAR(255) NOT NULL, atribute TEXT, -- → jsonb (§6) -- audit (§6) created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT chk_entitate_categorie CHECK (categorie IN ( 'PF','PJ','ADMIN','FUNCTIONAR_PUBLIC','STRAIN', 'MARFA','ARMA','VEHICUL','ACTIV_FINANCIAR' )));
-- Unicitate per categorie: același IDNP poate exista ca PF și ADMINCREATE UNIQUE INDEX ux_entitate_categorie_identificator ON entitate (categorie, identificator);
CREATE INDEX ix_entitate_nume_afisat ON entitate (nume_afisat);2.2 interdictie — nucleul registrului
Section titled “2.2 interdictie — nucleul registrului”CREATE TABLE interdictie ( id BIGINT NOT NULL PRIMARY KEY, statut VARCHAR(32) NOT NULL, categorie_jurisdictie VARCHAR(32) NOT NULL, categorie_domeniu VARCHAR(32) NOT NULL, durata VARCHAR(32) NOT NULL, intensitate VARCHAR(32) NOT NULL, start_date DATE NOT NULL, end_date DATE, description TEXT,
entitate_id BIGINT NOT NULL, autoritate_id BIGINT NOT NULL, temei_legal_id BIGINT, conditie_id BIGINT, -- OneToOne
-- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ,
CONSTRAINT fk_interdictie_entitate FOREIGN KEY (entitate_id) REFERENCES entitate(id), CONSTRAINT fk_interdictie_autoritate FOREIGN KEY (autoritate_id) REFERENCES autoritate_emitenta(id), CONSTRAINT fk_interdictie_temei_legal FOREIGN KEY (temei_legal_id) REFERENCES temei_legal(id), CONSTRAINT fk_interdictie_conditie FOREIGN KEY (conditie_id) REFERENCES conditie(id), CONSTRAINT ux_interdictie_conditie UNIQUE (conditie_id), -- OneToOne enforced CONSTRAINT chk_interdictie_statut CHECK (statut IN ( 'DRAFT','CONDITIONATA','ACTIV','SUSPENDAT','CONTESTATA','PRELUNGITA', 'RIDICATA','REVOCATA','EXECUTATA','EXPIRAT','ANULAT' )), CONSTRAINT chk_interdictie_durata CHECK (durata IN ( 'TEMPORARA','PERMANENTA','CONDITIONATA','PANA_LA_EXECUTARE' )), -- regulă de integritate: durata=CONDITIONATA ⇒ conditie_id NOT NULL CONSTRAINT chk_interdictie_conditie_req CHECK ( durata <> 'CONDITIONATA' OR conditie_id IS NOT NULL ));
CREATE INDEX ix_interdictie_statut ON interdictie (statut);CREATE INDEX ix_interdictie_entitate ON interdictie (entitate_id);CREATE INDEX ix_interdictie_autoritate ON interdictie (autoritate_id);CREATE INDEX ix_interdictie_validitate ON interdictie (start_date, end_date);CREATE INDEX ix_interdictie_statut_active ON interdictie (statut) WHERE statut IN ('ACTIV','SUSPENDAT','CONTESTATA','PRELUNGITA','CONDITIONATA');2.3 actiune_interzisa — acțiunea concretă blocată + scope
Section titled “2.3 actiune_interzisa — acțiunea concretă blocată + scope”CREATE TABLE actiune_interzisa ( id BIGINT NOT NULL PRIMARY KEY, actiune VARCHAR(48) NOT NULL, scope TEXT, -- → jsonb (§6) intensitate VARCHAR(32), interdictie_id BIGINT NOT NULL, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT fk_actiune_interdictie FOREIGN KEY (interdictie_id) REFERENCES interdictie(id) ON DELETE CASCADE);
CREATE INDEX ix_actiune_interdictie ON actiune_interzisa (interdictie_id);CREATE INDEX ix_actiune_actiune ON actiune_interzisa (actiune);2.4 conditie — pentru durata=CONDITIONATA
Section titled “2.4 conditie — pentru durata=CONDITIONATA”CREATE TABLE conditie ( id BIGINT NOT NULL PRIMARY KEY, tip VARCHAR(32) NOT NULL, descriere TEXT NOT NULL, indeplinita BOOLEAN NOT NULL DEFAULT FALSE, data_indeplinire TIMESTAMPTZ, act_indeplinire_id BIGINT, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT fk_conditie_act FOREIGN KEY (act_indeplinire_id) REFERENCES act(id), CONSTRAINT chk_conditie_tip CHECK (tip IN ( 'EVENIMENT','INDEPLINIRE_OBLIGATIE','DECIZIE_AUTORITATE','PRAG_TEMPORAL' )), -- consistență: indeplinita=true ⇒ data_indeplinire NOT NULL CONSTRAINT chk_conditie_data CHECK ( indeplinita = FALSE OR data_indeplinire IS NOT NULL ));
CREATE INDEX ix_conditie_pending ON conditie (indeplinita) WHERE indeplinita = FALSE;2.5 temei_legal
Section titled “2.5 temei_legal”CREATE TABLE temei_legal ( id BIGINT NOT NULL PRIMARY KEY, act_normativ VARCHAR(255) NOT NULL, articol VARCHAR(64) NOT NULL, alineat VARCHAR(64), descriere TEXT, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ);
CREATE UNIQUE INDEX ux_temei_legal ON temei_legal (act_normativ, articol, COALESCE(alineat, ''));2.6 autoritate_emitenta
Section titled “2.6 autoritate_emitenta”CREATE TABLE autoritate_emitenta ( id BIGINT NOT NULL PRIMARY KEY, name VARCHAR(255) NOT NULL, familie VARCHAR(32) NOT NULL, nivel VARCHAR(32) NOT NULL, cod_idno VARCHAR(13), -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT chk_autoritate_familie CHECK (familie IN ( 'JUDICIARA','ADMINISTRATIVA','CONTROL','SPECIALA' )), CONSTRAINT chk_autoritate_nivel CHECK (nivel IN ('CENTRALA','TERITORIALA')));
CREATE INDEX ix_autoritate_familie ON autoritate_emitenta (familie);CREATE INDEX ix_autoritate_cod_idno ON autoritate_emitenta (cod_idno) WHERE cod_idno IS NOT NULL;2.7 act — document atașat
Section titled “2.7 act — document atașat”CREATE TABLE act ( id BIGINT NOT NULL PRIMARY KEY, tip VARCHAR(32) NOT NULL, numar VARCHAR(64) NOT NULL, data DATE NOT NULL, storage_uri VARCHAR(512), hash_sha256 VARCHAR(64), signature VARCHAR(2048), descriere TEXT, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT chk_act_tip CHECK (tip IN ( 'HOTARARE','SENTINTA','DECIZIE','PROCES_VERBAL','ORDIN','DISPOZITIE','ALTUL' )));
-- hash unic (deduplica fișiere identice)CREATE UNIQUE INDEX ux_act_hash ON act (hash_sha256) WHERE hash_sha256 IS NOT NULL;CREATE INDEX ix_act_numar_data ON act (numar, data);2.8 interdictie_act — join cu rol (M2M atributat)
Section titled “2.8 interdictie_act — join cu rol (M2M atributat)”CREATE TABLE interdictie_act ( id BIGINT NOT NULL PRIMARY KEY, rol VARCHAR(32) NOT NULL, data_atasare DATE NOT NULL, interdictie_id BIGINT NOT NULL, act_id BIGINT NOT NULL, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT fk_ia_interdictie FOREIGN KEY (interdictie_id) REFERENCES interdictie(id) ON DELETE CASCADE, CONSTRAINT fk_ia_act FOREIGN KEY (act_id) REFERENCES act(id), CONSTRAINT chk_ia_rol CHECK (rol IN ( 'EMITERE','MODIFICARE','PRELUNGIRE','SUSPENDARE','REACTIVARE', 'CONTESTARE','RIDICARE','REVOCARE','EXECUTARE' )));
-- un act poate avea același rol pentru o interdicție o singură datăCREATE UNIQUE INDEX ux_ia_interdictie_act_rol ON interdictie_act (interdictie_id, act_id, rol);CREATE INDEX ix_ia_interdictie ON interdictie_act (interdictie_id);CREATE INDEX ix_ia_act ON interdictie_act (act_id);2.9 eveniment_interdictie — event log append-only
Section titled “2.9 eveniment_interdictie — event log append-only”CREATE TABLE eveniment_interdictie ( id BIGINT NOT NULL PRIMARY KEY, tip VARCHAR(48) NOT NULL, actor VARCHAR(64) NOT NULL, data TIMESTAMPTZ NOT NULL, payload TEXT, -- → jsonb (§6) interdictie_id BIGINT NOT NULL, -- audit (redundant cu actor/data dar păstrat pentru uniformitate) created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT fk_ev_interdictie FOREIGN KEY (interdictie_id) REFERENCES interdictie(id), CONSTRAINT chk_ev_tip CHECK (tip IN ( 'CREATA','APROBATA','SUSPENDATA','REACTIVATA','CONTESTATA', 'PRELUNGIRE_CERUTA','PRELUNGITA','REVOCATA','RIDICATA','EXECUTATA', 'EXPIRATA','ANULATA','CONDITIE_INDEPLINITA' )));
CREATE INDEX ix_ev_interdictie_data ON eveniment_interdictie (interdictie_id, data DESC);CREATE INDEX ix_ev_tip ON eveniment_interdictie (tip);2.10 notificare
Section titled “2.10 notificare”CREATE TABLE notificare ( id BIGINT NOT NULL PRIMARY KEY, canal VARCHAR(32) NOT NULL, destinatar VARCHAR(255) NOT NULL, status VARCHAR(32) NOT NULL, sent_at TIMESTAMPTZ, payload TEXT, interdictie_id BIGINT NOT NULL, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT fk_notif_interdictie FOREIGN KEY (interdictie_id) REFERENCES interdictie(id), CONSTRAINT chk_notif_canal CHECK (canal IN ('EMAIL','SMS','MCONNECT','WEBHOOK')), CONSTRAINT chk_notif_status CHECK (status IN ('PENDING','SENT','DELIVERED','FAILED')));
CREATE INDEX ix_notif_pending ON notificare (status, sent_at) WHERE status = 'PENDING';CREATE INDEX ix_notif_interdictie ON notificare (interdictie_id);2.11 app_user — operator aplicație (≠ jhi_user)
Section titled “2.11 app_user — operator aplicație (≠ jhi_user)”CREATE TABLE app_user ( id BIGINT NOT NULL PRIMARY KEY, username VARCHAR(64) NOT NULL, password VARCHAR(255) NOT NULL, statut VARCHAR(32) NOT NULL, rol VARCHAR(32) NOT NULL, -- audit created_by VARCHAR(50) NOT NULL, created_date TIMESTAMPTZ, last_modified_by VARCHAR(50), last_modified_date TIMESTAMPTZ, CONSTRAINT ux_app_user_username UNIQUE (username), CONSTRAINT chk_app_user_statut CHECK (statut IN ('ACTIV','INACTIV','BLOCAT')), CONSTRAINT chk_app_user_rol CHECK (rol IN ('ADMIN','EMITENT')));3. Tabele built-in JHipster (auth)
Section titled “3. Tabele built-in JHipster (auth)”Generate automat — listate aici doar pentru referință, nu se editează manual.
jhi_user— autentificare (login, password_hash, email, activated, lang_key).jhi_authority—name PK∈ {ROLE_ADMIN, ROLE_USER}.jhi_user_authority— M2M user ↔ authority.jhi_persistent_audit_event,jhi_persistent_audit_evt_data— audit Spring Boot.databasechangelog,databasechangeloglock— Liquibase.
Diferența vs. app_user: jhi_user e pentru autentificare (cine se loghează);
app_user e entitate de domeniu (operator de registru) cu rol funcțional și
statut administrativ.
4. Indici suplimentari recomandați
Section titled “4. Indici suplimentari recomandați”-- Căutare frecventă în registru public după IDNP/IDNO (filtrat doar la-- interdicții care produc efecte juridice).CREATE INDEX ix_entitate_pf_idnp_active ON entitate (identificator) WHERE categorie IN ('PF','ADMIN','FUNCTIONAR_PUBLIC');
CREATE INDEX ix_entitate_pj_idno ON entitate (identificator) WHERE categorie = 'PJ';
-- Pentru raport „interdicții care expiră în următoarele N zile"CREATE INDEX ix_interdictie_expirare ON interdictie (end_date) WHERE statut = 'ACTIV' AND end_date IS NOT NULL;
-- Pentru consultare cronologică a evenimentelor unei interdicții-- (deja acoperit de ix_ev_interdictie_data — verificare).
-- Full-text local (înainte de Elasticsearch sau ca fallback)CREATE INDEX ix_entitate_nume_fts ON entitate USING gin (to_tsvector('simple', nume_afisat));5. Trigger append-only pentru eveniment_interdictie
Section titled “5. Trigger append-only pentru eveniment_interdictie”Cerință din interdictii.jdl (audit/forensic/Legea 133) — la nivel de DB,
nu doar repository:
CREATE OR REPLACE FUNCTION eveniment_interdictie_no_modify()RETURNS TRIGGER AS $$BEGIN RAISE EXCEPTION 'eveniment_interdictie este append-only (% blocat)', TG_OP;END;$$ LANGUAGE plpgsql;
CREATE TRIGGER tr_ev_no_update BEFORE UPDATE ON eveniment_interdictie FOR EACH ROW EXECUTE FUNCTION eveniment_interdictie_no_modify();
CREATE TRIGGER tr_ev_no_delete BEFORE DELETE ON eveniment_interdictie FOR EACH ROW EXECUTE FUNCTION eveniment_interdictie_no_modify();Notă: Liquibase rulează cu utilizator privilegiat; pentru migrări care chiar trebuie să modifice istoricul (caz extrem), trigger-ul se dezactivează temporar într-un changelog cu
runOnChange=falseși apoi se reactivează.
6. Câmpuri standard de audit
Section titled “6. Câmpuri standard de audit”Toate entitățile au (de la AbstractAuditingEntity + SpringSecurityAuditorAware):
| Coloană | Tip | Populare |
|---|---|---|
created_by | VARCHAR(50) NOT NULL | login al utilizatorului la INSERT |
created_date | TIMESTAMPTZ | Instant.now() la INSERT |
last_modified_by | VARCHAR(50) | login al utilizatorului la UPDATE |
last_modified_date | TIMESTAMPTZ | Instant.now() la UPDATE |
7. Conversie JSONB (post-jhipster jdl)
Section titled “7. Conversie JSONB (post-jhipster jdl)”JDL nu are tip jsonb; câmpurile TextBlob sunt generate ca TEXT + @Lob.
După regenerare, adaugă un changelog Liquibase manual:
<!-- src/main/resources/config/liquibase/changelog/<timestamp>_jsonb_conversion.xml --><changeSet id="jsonb-conversion-001" author="manual"> <sql> ALTER TABLE entitate ALTER COLUMN atribute TYPE jsonb USING atribute::jsonb; ALTER TABLE actiune_interzisa ALTER COLUMN scope TYPE jsonb USING scope::jsonb; ALTER TABLE eveniment_interdictie ALTER COLUMN payload TYPE jsonb USING payload::jsonb; ALTER TABLE notificare ALTER COLUMN payload TYPE jsonb USING payload::jsonb; </sql> <rollback> ALTER TABLE notificare ALTER COLUMN payload TYPE text USING payload::text; ALTER TABLE eveniment_interdictie ALTER COLUMN payload TYPE text USING payload::text; ALTER TABLE actiune_interzisa ALTER COLUMN scope TYPE text USING scope::text; ALTER TABLE entitate ALTER COLUMN atribute TYPE text USING atribute::text; </rollback></changeSet>Apoi, în cod Java, adaugă pe câmpurile corespunzătoare:
@JdbcTypeCode(SqlTypes.JSON)@Column(name = "atribute", columnDefinition = "jsonb")private String atribute;(Sau folosește io.hypersistence:hypersistence-utils-hibernate-63 cu
@Type(JsonType.class) și un tip Map<String, Object> în loc de String.)
Indici GIN pe câmpurile jsonb pentru căutare (ex. „interdicții pe vehicule din anul X”):
CREATE INDEX ix_entitate_atribute_gin ON entitate USING gin (atribute jsonb_path_ops);CREATE INDEX ix_actiune_scope_gin ON actiune_interzisa USING gin (scope jsonb_path_ops);8. Checklist de revizuit
Section titled “8. Checklist de revizuit”- Unicitate
entitate (categorie, identificator)— corect, sau ai nevoie de unicitate globală peidentificator? (IDNP repetat în PF + ADMIN e legitim sau nu?) -
interdictie.conditie_idUNIQUE — păstrăm OneToOne sau lăsăm mai multe condiții per interdicție? (atunci → mută FK peconditieși permite ManyToMany cu logică AND/OR). -
ON DELETE CASCADEpeactiune_interzisașiinterdictie_act— cascadă e OK pentru acțiuni (parte integrantă) dar pentrueveniment_interdictieam evitat-o (audit nu se șterge niciodată). Confirmă. - Soft delete vs. hard delete pentru
interdictie— pentru registru juridic, hard delete e probabil interzis (păstrăm istoricul prin ANULAT/REVOCATA). Dacă da, adaugă coloanădeleted_at TIMESTAMPTZși o vizualizareinterdictie_active. - Retenție evenimente —
eveniment_interdictiecrește nelimitat. Politica de arhivare (partitioning pedata)? - Index pe
actorîneveniment_interdictie— pentru raport „ce a făcut user X în perioada Y”? - Constraint cross-table durata↔conditie —
chk_interdictie_conditie_reqasigură căCONDITIONATA ⇒ conditie_id. Verifică dacă reciproca e dorită:conditie_id NOT NULL ⇒ durata = CONDITIONATA? -
statut = EXPIRATautomat — job@Scheduledzilnic care seteazăstatut = EXPIRATla interdicțiile cuend_date < CURRENT_DATEși genereazăEvenimentInterdictie(tip=EXPIRATA, actor='SYSTEM'). Asta este logică aplicație, dar verifică indexulix_interdictie_expirare. -
autoritate_emitenta.cod_idno— autoritățile guvernamentale au IDNO? Dacă nu, transformă încod_externmai generic. - Lungimi
VARCHARpentru enum-uri — am ales 32/48; verifică dacă cea mai lungă valoare încape (OCUPARE_FUNCTIE_CONDUCERE= 24,CONDITIE_INDEPLINITA= 21 — OK pentru 32;INDEPLINIRE_OBLIGATIE= 21).