feat(oracle): kit de instalare la client + corectarea lipsurilor din instalare

Blocul de instalare/migrare Oracle 21c XE, terminat si validat pe VM 302.

Kit de instalare (nou)

  scripts/build-client-kit.ps1 exporta CONTAFIN_ORACLE si FIRMANOUA de pe
  LXC 108 (PDB ROA2, nu ROA - ROA e productia ROA_CENTRAL), le aduce local
  prin cele trei hopuri container -> LXC -> host -> statie, le redenumeste la
  numele pe care le asteapta scripturile si le impacheteaza cu o copie a
  directorului roa-windows-setup. Citeste logul expdp si raporteaza cate
  firme are NOM_FIRME, ca sa nu plece din greseala datele unui client.

  roa-windows-setup/INSTALEAZA.cmd ruleaza pasii 01..08 fara "set /p", deci
  merge si prin SSH - RunAll.cmd nu poate fi rulat neinteractiv. Trateaza
  corect codul 5 de la pasul 03 si se opreste la prima eroare reala.

Corectii

  01-setup-database.ps1 nu mai scrie SQLNET.RECV_TIMEOUT / SEND_TIMEOUT in
  sqlnet.ora. Le hardcoda la 30 s, iar fisierul e citit si de impdp: in timpul
  unui import serverul poate lucra minute fara sa trimita un pachet, clientul
  murea cu ORA-12609 iar scriptul raporta esec pentru un import care se
  terminase cu bine pe server. Reprodus si reparat pe VM 302.

  01-setup-database.ps1: Step 4c optional (-ResetSystemPassword) care curata
  EXPIRED(GRACE) pe SYSTEM in CDB root; ALTER PROFILE opreste expirarile
  viitoare dar nu reseteaza un cont deja intrat in gratie.

  uninstall-roa.sql: retry la DROP USER dupa KILL SESSION, plus un bloc final
  de verdict care numara ce a ramas si iese cu ORA-20900 daca baza nu e
  curata. Pana acum toate sectiunile prindeau exceptiile in WHEN OTHERS si
  scriptul tiparea "UNINSTALL COMPLETE" chiar si cand un user supravietuise,
  iar instalarea urmatoare dadea ORA-31684 in lant. 99-uninstall-roa.ps1
  propaga codul de iesire.

  08-post-install-config.ps1: Step 7b seteaza SMTP_OUT_SERVER si ACL-ul de
  retea pentru CONTAFIN_ORACLE. UTL_MAIL se instala si primea EXECUTE, adica
  destul cat sa compileze, dar nu si cat sa trimita. Privilegiul resolve nu
  accepta interval de porturi (ORA-24244), deci se acorda separat de connect.

  07-verify-installation.ps1: sectiune noua care verifica prezenta lui
  FIRMANOUA.dmp in DMPDIR si o raporteaza ca eroare daca lipseste. Fara el,
  adaugarea unei firme noi pica in DBMS_DATAPUMP.ADD_FILE peste luni de la
  instalare, cand nimeni nu mai leaga eroarea de instalare.

  configure-profile.sql: antetul spune ca e unealta de remediere manuala, nu
  parte din flux; pas nou la final pentru CDB root.

Documentatie

  README-ul roa-windows-setup descrie acum explicit cele doua scenarii -
  instalare pe curat si migrare - de unde se iau DMP-urile sablon, si capcana
  ORA-12609. Handoff-urile de sesiune au fost sterse; ce era durabil in ele a
  intrat in README-uri si in docs/diagnostic-spatiu-clienti.md.

Validare pe VM 302: ciclu complet din kit, instalare pe curat, verificarea
finala "[OK] All checks passed!".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
This commit is contained in:
Marius
2026-08-25 18:05:56 +03:00
parent 3a7e751fc1
commit 7fce925349
17 changed files with 3329 additions and 1753 deletions

View File

@@ -0,0 +1,205 @@
@echo off
REM =============================================================================
REM ROA Oracle - instalare la client, neinteractiva
REM =============================================================================
REM Ruleaza pasii 01..08 in ordine, din radacina kitului.
REM
REM Spre deosebire de RunAll.cmd, scriptul asta NU foloseste "set /p", deci
REM poate fi rulat si prin SSH / dintr-o sesiune fara tastatura.
REM
REM Utilizare:
REM INSTALEAZA.cmd curat [IdClient] [ServerSMTP]
REM INSTALEAZA.cmd migrare [IdClient] [ServerSMTP]
REM
REM Exemple:
REM INSTALEAZA.cmd curat 138 mail.romfast.ro
REM INSTALEAZA.cmd migrare 214
REM =============================================================================
setlocal enabledelayedexpansion
set "KIT=%~dp0"
set "SCEN=%~1"
set "IDCLIENT=%~2"
set "SMTP=%~3"
set "DMPDEST=C:\DMPDIR"
if /i "%SCEN%"=="curat" goto :scenar_ok
if /i "%SCEN%"=="migrare" goto :scenar_ok
goto :utilizare
:scenar_ok
if "%SMTP%"=="" set "SMTP=mail.romfast.ro"
echo.
echo ============================================================
echo ROA Oracle - instalare (%SCEN%)
echo ============================================================
echo.
echo Kit: %KIT%
echo DMPDIR tinta: %DMPDEST%
echo Id client: %IDCLIENT%
echo Server SMTP: %SMTP%
echo.
REM ---------------------------------------------------------------------------
REM Pregatirea DMPDIR
REM ---------------------------------------------------------------------------
if not exist "%KIT%DMPDIR\FIRMANOUA.dmp" (
echo [EROARE] Lipseste "%KIT%DMPDIR\FIRMANOUA.dmp".
echo Fara sablonul de firma noua, clientul nu va putea adauga firme.
echo Reconstruieste kitul cu build-client-kit.ps1.
exit /b 1
)
dir /b "%KIT%DMPDIR\*contafin*.dmp" >nul 2>&1
if errorlevel 1 (
echo [EROARE] Lipseste un fisier *contafin*.dmp din "%KIT%DMPDIR".
exit /b 1
)
if /i "%SCEN%"=="migrare" (
REM Kitul contine mereu 2 sabloane: *contafin*.dmp si FIRMANOUA.dmp.
REM Orice peste 2 sunt DMP-urile de firma ale clientului.
set /a TOTALDMP=0
for %%F in ("%KIT%DMPDIR\*.dmp") do set /a TOTALDMP+=1
if !TOTALDMP! LEQ 2 (
echo [ATENTIE] In "%KIT%DMPDIR" sunt doar !TOTALDMP! fisiere DMP,
echo adica doar sabloanele. La o migrare ar trebui sa existe
echo si cate un DMP per firma a clientului.
echo Continui - pasul 05 va raporta firmele lipsa.
echo.
)
)
if not exist "%DMPDEST%" mkdir "%DMPDEST%"
echo [1/9] Copiez fisierele DMP in %DMPDEST% ...
copy /Y "%KIT%DMPDIR\*.dmp" "%DMPDEST%\" >nul
if errorlevel 1 (
echo [EROARE] Copierea DMP-urilor a esuat.
exit /b 1
)
REM Serviciul Oracle citeste fisierele cu contul lui, nu cu al tau. Fara
REM drepturi explicite, Data Pump da ORA-39002 / LFI la deschiderea fisierului.
icacls "%DMPDEST%" /grant "NT SERVICE\OracleServiceXE:(OI)(CI)F" /T >nul 2>&1
echo Gata.
REM ---------------------------------------------------------------------------
REM Pasii de instalare
REM ---------------------------------------------------------------------------
echo.
echo [2/9] 01-setup-database.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\01-setup-database.ps1"
if errorlevel 1 goto :esec_01
echo.
echo [3/9] 02-create-sys-objects.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\02-create-sys-objects.ps1"
if errorlevel 1 goto :esec_02
echo.
echo [4/9] 03-import-contafin.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\03-import-contafin.ps1"
set RC=!ERRORLEVEL!
REM Codul 5 e normal aici: Data Pump raporteaza "completed with errors" pentru
REM ORA-31684 (userul e creat deja de pasul 01) si ORA-39082 (warning-uri de
REM compilare, rezolvate la pasul 04). Orice alt cod nenul e esec real.
if "!RC!"=="0" goto :pas_04
if "!RC!"=="5" (
echo [INFO] Cod de iesire 5 - normal pentru Data Pump, se continua.
goto :pas_04
)
echo [EROARE] 03-import-contafin.ps1 a iesit cu codul !RC!.
exit /b !RC!
:pas_04
echo.
echo [5/9] 04-create-synonyms-grants.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\04-create-synonyms-grants.ps1"
if errorlevel 1 goto :esec_04
echo.
echo [6/9] 05-import-companies.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\05-import-companies.ps1"
if errorlevel 1 goto :esec_05
echo.
echo [7/9] 08-post-install-config.ps1
if "%IDCLIENT%"=="" (
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\08-post-install-config.ps1" -EmailSmtp "%SMTP%"
) else (
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\08-post-install-config.ps1" -CustomerId "%IDCLIENT%" -EmailSmtp "%SMTP%"
)
if errorlevel 1 goto :esec_08
echo.
echo [8/9] 07-verify-installation.ps1
powershell.exe -ExecutionPolicy Bypass -NoProfile -File "%KIT%scripts\07-verify-installation.ps1"
set RCVERIF=!ERRORLEVEL!
echo.
echo [9/9] Rezultat
echo ============================================================
if "!RCVERIF!"=="0" (
echo INSTALARE COMPLETA - verificarea a trecut integral.
) else (
echo INSTALARE TERMINATA, DAR VERIFICAREA A SEMNALAT PROBLEME.
echo Citeste lista din raportul de mai sus si logurile din logs\.
if /i "%SCEN%"=="migrare" (
echo.
echo La migrare, "N company schemas are missing" inseamna ca lipsesc
echo DMP-urile firmelor respective. Copiaza-le in %DMPDEST% si reia
echo doar pasul 05.
)
)
echo ============================================================
echo.
if /i "%SCEN%"=="curat" (
echo PASUL URMATOR - prima firma:
echo.
echo Se creeaza DIN APLICATIA ROA, nu din scripturi. Aplicatia scrie firma
echo in CONTAFIN_ORACLE.NOM_FIRME si apeleaza SYS.NEWSCHEMA, care importa
echo structura din %DMPDEST%\FIRMANOUA.dmp.
echo.
echo NU sterge FIRMANOUA.dmp din %DMPDEST% - e folosit la fiecare firma
echo noua, oricand pe viitor.
echo.
)
endlocal & exit /b %RCVERIF%
REM ---------------------------------------------------------------------------
:esec_01
echo [EROARE] 01-setup-database.ps1 a esuat. Instalarea se opreste.
exit /b 1
:esec_02
echo [EROARE] 02-create-sys-objects.ps1 a esuat. Instalarea se opreste.
exit /b 1
:esec_04
echo [EROARE] 04-create-synonyms-grants.ps1 a esuat. Instalarea se opreste.
exit /b 1
:esec_05
echo [EROARE] 05-import-companies.ps1 a esuat. Instalarea se opreste.
exit /b 1
:esec_08
echo [EROARE] 08-post-install-config.ps1 a esuat. Instalarea se opreste.
exit /b 1
:utilizare
echo.
echo Utilizare:
echo INSTALEAZA.cmd curat [IdClient] [ServerSMTP]
echo INSTALEAZA.cmd migrare [IdClient] [ServerSMTP]
echo.
echo curat Client nou, fara firme anterioare. In DMPDIR trebuie sa fie
echo doar sabloanele: contafin_oracle.dmp si FIRMANOUA.dmp.
echo.
echo migrare Client cu date existente. In DMPDIR trebuie sa fie
echo contafin_oracle.dmp AL CLIENTULUI, cate un DMP per firma,
echo plus sablonul FIRMANOUA.dmp.
echo.
echo ServerSMTP e optional (implicit mail.romfast.ro).
echo.
exit /b 2

View File

@@ -21,9 +21,12 @@ Scripts and documentation for setting up ROA Oracle Database on Windows servers:
| Scenario | Description |
|----------|-------------|
| **New Server** | Oracle 21c SE (non-CDB) or XE (CDB/PDB) + CONTAFIN_ORACLE.dmp |
| **Migration** | Import existing DMP files (CONTAFIN_ORACLE + 30-50 companies), inclusiv de pe Oracle XE 11 / 10g |
| **Add Company** | Add new company schema to existing server |
| **A. Instalare pe curat** | Client nou, fără firme anterioare. Pornești din șabloanele `contafin_oracle.dmp` + `FIRMANOUA.dmp` |
| **B. Migrare** | Client cu Oracle XE 11 / 10g. Aduci `contafin_oracle.dmp` al clientului + câte un `.dmp` per firmă |
| **Add Company** | Firmă nouă pe un server deja instalat (normal din aplicație, prin `SYS.NEWSCHEMA`) |
Ambele instalări rulează **aceleași** scripturi în **aceeași** ordine — diferă doar ce pui în
`C:\DMPDIR`. Pașii detaliați: [Cele două scenarii de instalare](#cele-două-scenarii-de-instalare).
---
@@ -40,6 +43,10 @@ Scripts and documentation for setting up ROA Oracle Database on Windows servers:
## Quick Start
> Care fișiere `.dmp` îți trebuie depinde de scenariu (A pe curat / B migrare) — vezi
> [DMP Files Required](#dmp-files-required). `FIRMANOUA.dmp` trebuie copiat în **ambele**
> cazuri, altfel clientul nu va putea adăuga firme noi.
### Oracle 21c Express Edition (XE) - Gratuit
1. Download și instalează Oracle 21c XE (see `docs/00-INSTALL-ORACLE-XE.md`)
2. Copiază fișierele DMP în `C:\DMPDIR\`
@@ -47,6 +54,8 @@ Scripts and documentation for setting up ROA Oracle Database on Windows servers:
```cmd
RunAll.cmd
```
`RunAll.cmd` e **interactiv** — cere confirmare la tastatură. Pentru rulare automată,
apelează scripturile în ordine (vezi scenariile A / B).
### Oracle 21c Standard Edition (SE) - Licență
1. Download și instalează Oracle 21c SE (see `docs/00-INSTALL-ORACLE-SE.md`)
@@ -223,12 +232,63 @@ Modern multitenant architecture with Container Database.
## DMP Files Required
### For New Installation
Care fișiere îți trebuie depinde de scenariu. **Alege întâi scenariul:**
| Scenariu | Când | DMP-uri necesare |
|---|---|---|
| **A. Instalare pe curat** | Client nou, fără firme anterioare | `contafin_oracle.dmp` (șablon) + `FIRMANOUA.dmp` (șablon) |
| **B. Migrare** | Client cu Oracle XE mai vechi, are deja date | `contafin_oracle.dmp` **al clientului** + câte un `.dmp` per firmă + `FIRMANOUA.dmp` (șablon) |
| File | Description | Size |
|------|-------------|------|
| `contafin_oracle.dmp` | Common schema (rights, updates, etc.) | ~50MB |
| `[company].dmp` | Company schema (one per company) | ~100-500MB each |
| `contafin_oracle.dmp` | Schema comună (drepturi, actualizări, `NOM_FIRME`) | ~50-280 MB |
| `FIRMANOUA.dmp` | **Șablon de firmă goală.** Sursa din care `SYS.NEWSCHEMA` și `06-add-company.ps1` creează orice firmă nouă | ~24 MB |
| `[company].dmp` | Schema unei firme existente (doar la migrare, una per firmă) | ~100-500 MB fiecare |
> **`FIRMANOUA.dmp` trebuie să ajungă în `C:\DMPDIR` la ORICE instalare, și la A și la B.**
> Nu e folosit de scripturile 01-08, ci mult mai târziu: când clientul adaugă o firmă nouă din
> aplicație, `SYS.NEWSCHEMA` îl caută în directorul Oracle `DMPDIR`
> ([`sql/sys-objects.sql`](sql/sys-objects.sql), `lcSchemaSursa := 'FIRMANOUA'`). Dacă lipsește,
> adăugarea firmei pică în `DBMS_DATAPUMP.ADD_FILE` — peste luni de la instalare, când nimeni
> nu mai leagă eroarea de instalare.
> `07-verify-installation.ps1` verifică prezența lui și raportează lipsa ca eroare.
### De unde iei DMP-urile șablon
Ambele stau pe **LXC 108** (`central-oracle`, 10.0.20.121), în containerul `oracle-xe`:
Sunt **trei** niveluri de scos, nu unul: container Docker → LXC 108 → host pvemini → stația ta.
`docker cp` te scoate doar din container, iar `scp root@10.0.20.201:/tmp/...` citește de pe
**host**, unde fișierul încă nu a ajuns — de aceea e nevoie și de `pct pull`.
```bash
# 1. container oracle-xe -> LXC 108 (fisierul ajunge in /tmp AL CONTAINERULUI 108)
ssh root@10.0.20.201 "pct exec 108 -- docker cp oracle-xe:/tmp/oracle-import-roa2/firmanoua.dmp /tmp/firmanoua.dmp"
# 2. LXC 108 -> host pvemini
ssh root@10.0.20.201 "pct pull 108 /tmp/firmanoua.dmp /tmp/firmanoua.dmp"
# 3. host -> statia ta
scp root@10.0.20.201:/tmp/firmanoua.dmp ./FIRMANOUA.dmp
```
Identic pentru `contafin_oracle.dmp` (înlocuiește numele în toți cei trei pași).
Apoi copiezi fișierele pe serverul clientului, în `C:\DMPDIR`:
```bash
scp ./FIRMANOUA.dmp <user>@<server-client>:C:/DMPDIR/FIRMANOUA.dmp
```
> Numele fișierului pe destinație trebuie să fie **`FIRMANOUA.dmp`** — `SYS.NEWSCHEMA` îl
> construiește ca `lcSchemaSursa || '.dmp'`, cu `lcSchemaSursa := 'FIRMANOUA'`. În container
> fișierul e cu litere mici (`firmanoua.dmp`); pe Windows nu contează, dar redenumește-l oricum
> ca să fie clar.
Copie identică există și în `/opt/oracle/admin/XE/dpdump/<GUID-PDB>/` din același container.
`contafin_oracle.dmp` de acolo este varianta **curată**: `NOM_FIRME` are doar rândul-sămânță
(`FIRMA = 0`, fără schemă) plus o firmă marcată ștearsă — deci
`07-verify-installation.ps1` nu va raporta firme lipsă după instalare.
### Obtaining DMP Files
@@ -251,37 +311,170 @@ scp root@10.0.20.201:/opt/oracle18/oradata/dmpdir/contafin_oracle.dmp C:\DMPDIR\
## Workflow Examples
### New Server Installation
### Cele două scenarii de instalare
Ambele rulează **aceleași** scripturi, în **aceeași** ordine. Diferența e doar în ce pui în
`C:\DMPDIR` înainte de a porni și ce faci după pasul 07.
#### Scenariul A — instalare pe curat (client nou, fără firme anterioare)
Pornești de la șabloanele de pe LXC 108. `NOM_FIRME` vine practic goală, deci pasul 05 nu are
ce importa — îl lași să ruleze, iese cu `0` și „No companies found in NOM_FIRME". Prima firmă o
creezi la final, din șablonul `FIRMANOUA.dmp`.
```powershell
# 1. Install Oracle 21c XE (see docs/00-INSTALL-ORACLE-XE.md)
# 1. Instalezi Oracle 21c XE (vezi docs/00-INSTALL-ORACLE-XE.md)
# Parola SYS/SYSTEM la instalare: romfastsoft
# 2. Configure
# 2. Configurare
Copy-Item config.example.ps1 config.ps1
notepad config.ps1 # Edit values
notepad config.ps1 # SERVICE_NAME=XEPDB1 pentru XE, ROA pentru SE
# 3. Copy DMP files
# 3. DMP-urile SABLON (vezi "De unde iei DMP-urile sablon")
mkdir C:\DMPDIR
Copy-Item \\server\dmp\*.dmp C:\DMPDIR\
Copy-Item \\server\sabloane\contafin_oracle.dmp C:\DMPDIR\
Copy-Item \\server\sabloane\FIRMANOUA.dmp C:\DMPDIR\
# 4. Run setup scripts
.\01-setup-database.ps1
.\02-create-sys-objects.ps1
.\03-import-contafin.ps1
.\04-create-synonyms-grants.ps1
.\05-import-companies.ps1
.\08-post-install-config.ps1
.\07-verify-installation.ps1
# 4. Instalarea propriu-zisa
Run.cmd 01-setup-database.ps1
Run.cmd 02-create-sys-objects.ps1
Run.cmd 03-import-contafin.ps1 # cod de iesire 5 = NORMAL, vezi mai jos
Run.cmd 04-create-synonyms-grants.ps1
Run.cmd 05-import-companies.ps1 # no-op: NOM_FIRME e goala
Run.cmd 08-post-install-config.ps1 -CustomerId "<id-client>" -EmailSmtp "mail.romfast.ro"
Run.cmd 07-verify-installation.ps1
```
**Pasul 5 — prima firmă — se face din aplicația ROA, nu din scripturi.** Aplicația inserează
firma în `CONTAFIN_ORACLE.NOM_FIRME` și apoi apelează `SYS.NEWSCHEMA(schema, luna, an)`, care
creează userul și îi importă structura din `FIRMANOUA.dmp` (`DMPDIR`). De asta fișierul
**rămâne** în `C:\DMPDIR` după instalare — e folosit la fiecare firmă nouă, oricând.
`06-add-company.ps1` este calea manuală, de depanare: creează schema și îi importă șablonul,
dar **nu** scrie în `NOM_FIRME`. Dacă îl folosești, firma nu apare în aplicație până nu o
înregistrezi tu, iar `07-verify-installation.ps1` o raportează ca „Orphan schema (not in
NOM_FIRME)".
```powershell
# doar daca ai nevoie de calea manuala:
Run.cmd 06-add-company.ps1 -CompanyName "FIRMACLIENT" -TemplateDump "C:\DMPDIR\FIRMANOUA.dmp" -TemplateSchema "FIRMANOUA"
# ...urmat de inregistrarea firmei in CONTAFIN_ORACLE.NOM_FIRME
```
#### Scenariul B — migrare de pe un Oracle XE mai vechi
Ai `contafin_oracle.dmp` **al clientului** (cu `NOM_FIRME` populată) plus câte un `.dmp` per
firmă. Pasul 05 citește `NOM_FIRME` din schema deja importată la pasul 03 și potrivește
fiecare firmă cu fișierul ei din `C:\DMPDIR`.
```powershell
# 0. Export de pe serverul VECHI - vezi "Migrare de la un server client existent" mai jos.
# Lista schemelor: SELECT schema FROM CONTAFIN_ORACLE.NOM_FIRME WHERE sters = 0;
# 1-2. Ca la scenariul A (instalare Oracle + config.ps1)
# 3. DMP-urile CLIENTULUI + sablonul de firma noua
mkdir C:\DMPDIR
Copy-Item D:\export-client\contafin_oracle.dmp C:\DMPDIR\
Copy-Item D:\export-client\*.dmp C:\DMPDIR\ # cate unul per firma
Copy-Item \\server\sabloane\FIRMANOUA.dmp C:\DMPDIR\ # NU vine de la client!
# 4. Aceeasi ordine, aceleasi scripturi
Run.cmd 01-setup-database.ps1
Run.cmd 02-create-sys-objects.ps1
Run.cmd 03-import-contafin.ps1 # aduce NOM_FIRME cu firmele clientului
Run.cmd 04-create-synonyms-grants.ps1
Run.cmd 05-import-companies.ps1 # importa toate firmele gasite in NOM_FIRME
Run.cmd 08-post-install-config.ps1 -CustomerId "<id-client>" -EmailSmtp "mail.romfast.ro"
Run.cmd 07-verify-installation.ps1
```
Verificare intermediară utilă înainte de import (nu modifică nimic):
```powershell
Run.cmd 05-import-companies.ps1 -DryRun # arata ce firma se leaga de ce fisier
```
Numele fișierului nu trebuie să fie identic cu schema — pasul 05 potrivește `NOM_FIRME.SCHEMA`
cu fișierele din director, deci `capidavatour_72001.dmp` se leagă de schema `CAPIDAVATOUR`.
#### Ce e comun ambelor scenarii
- **`03-import-contafin.ps1` iese cu codul 5 și asta e normal** — e codul Data Pump pentru
„completed with errors": `ORA-31684 ... already exists` (userul e creat deja de pasul 01) și
`ORA-39082` (warning-uri de compilare, rezolvate la pasul 04). Nu e eșec; citește logul.
- **`RunAll.cmd` nu poate fi rulat neinteractiv** (folosește `set /p`). Pe stdin redirecționat
fie anulează instalarea *ieșind cu codul 0*, fie dă „The syntax of the command is incorrect".
Pentru automatizare apelează scripturile în ordine, ca mai sus.
- **Conectarea se face la `XEPDB1`**, niciodată la `XE` (CDB root).
- La final `07-verify-installation.ps1` trebuie să iasă cu **0**. Cod `1` → citește lista de
probleme din raport; `FIRMANOUA.dmp missing from DMPDIR` e eroare reală în ambele scenarii.
- Dacă reiei instalarea de la zero, `99-uninstall-roa.ps1` trebuie să iasă cu **0**. Cod diferit
de 0 înseamnă că au rămas obiecte (uzual o sesiune activă ținea userul ocupat) — nu porni
instalarea, altfel pasul 05 dă `ORA-31684` în lanț.
### Kit de instalare pentru client (recomandat)
În loc să aduni manual DMP-urile și scripturile, construiește un kit gata de dus la client:
```powershell
cd proxmox\lxc108-oracle\scripts
.\build-client-kit.ps1 -Zip
```
Scriptul exportă `CONTAFIN_ORACLE` și `FIRMANOUA` de pe LXC 108 (PDB **ROA2**, nu ROA — ROA e
producția `ROA_CENTRAL`), le aduce local prin cele trei hopuri, le redenumește la
`contafin_oracle.dmp` / `FIRMANOUA.dmp` și le pune lângă o copie a scripturilor de instalare.
Verifică și **câte firme are `NOM_FIRME`** în dump, citind logul expdp. Un șablon curat are 2
rânduri; dacă vezi zeci, ai prins din greșeală datele unei baze reale și nu ai voie s-o trimiți
mai departe.
Kitul are structura lui `roa-windows-setup/` plus `DMPDIR/`, deci se dezarhivează pe serverul
clientului și se rulează direct:
```cmd
INSTALEAZA.cmd curat 138 mail.romfast.ro
INSTALEAZA.cmd migrare 214
```
`INSTALEAZA.cmd` face ce face `RunAll.cmd`, dar **fără `set /p`** — deci merge și prin SSH, fără
tastatură. Copiază DMP-urile în `C:\DMPDIR`, dă drepturi contului `NT SERVICE\OracleServiceXE`,
rulează pașii în ordine, tratează corect codul 5 de la pasul 03 și se oprește la prima eroare
reală.
Opțiuni utile:
| Parametru | Ce face |
|---|---|
| `-SkipExport` | Refolosește ultimele arhive de pe LXC 108, fără export nou |
| `-Zip` | Produce și o arhivă `.zip` de trimis |
| `-PushTo "user@host:C:/kit"` | Trimite kitul direct pe serverul țintă, prin scp |
| `-OracleVersion 18` | Exportă din `oracle18-xe` (`VERSION=11.2`), pentru baze mai vechi |
> `scp` copiază **conținutul** kitului direct în destinație dacă aceasta nu există, sau kitul ca
> subdirector dacă există deja. Verifică unde a ajuns înainte să rulezi `INSTALEAZA.cmd`.
Fluxul complet, kit → instalare pe curat → `[OK] All checks passed!`, e validat pe VM 302
(2026-08-25).
---
### Post-Installation Configuration (08-post-install-config.ps1)
This script completes the ROA setup by configuring:
1. **ROAUPDATE Directories**: Creates 54 physical folders and Oracle DIRECTORY objects
2. **SERVER_INFO**: Encoded passwords, paths, email settings for PACK_UPDATE
3. **Customer ID**: Sets AUTH_DETALII for license verification
4. **Scheduler Jobs**: UPDATEROA_ZILNIC and UPDATERTVAI_ZILNIC (disabled by default)
3. **SMTP**: setează `SMTP_OUT_SERVER` și ACL-ul de rețea pentru `CONTAFIN_ORACLE`
4. **Customer ID**: Sets AUTH_DETALII for license verification
5. **Scheduler Jobs**: UPDATEROA_ZILNIC and UPDATERTVAI_ZILNIC (disabled by default)
> **De ce e nevoie de pasul 3:** `sys-objects.sql` instalează `UTL_MAIL` și `sys-grants.sql` dă
> `EXECUTE` pe el — atât cât să *compileze* codul care trimite mailuri. Ca să și *funcționeze*
> mai trebuie parametrul `SMTP_OUT_SERVER` (altfel `ORA-29278/29279`) și un ACL de rețea către
> serverul SMTP (din 12c încoace orice acces de rețea din PL/SQL trece prin ACL, altfel
> `ORA-24247`). Ambele se pun aici; sari peste cu `-SkipSmtpConfig`.
```powershell
# Basic usage (defaults: D:\ROAUPDATE, no Customer ID)
@@ -290,11 +483,11 @@ This script completes the ROA setup by configuring:
# With custom ROAUPDATE path and Customer ID
.\08-post-install-config.ps1 -RoaUpdatePath "E:\ROAUPDATE" -CustomerId "138"
# With email configuration
.\08-post-install-config.ps1 -EmailTo "admin@company.ro" -EmailSmtp "mail.company.ro"
# With email configuration (seteaza si SMTP_OUT_SERVER + ACL)
.\08-post-install-config.ps1 -EmailTo "admin@company.ro" -EmailSmtp "mail.company.ro" -EmailPort 25
# Skip specific parts
.\08-post-install-config.ps1 -SkipSchedulerJobs -SkipServerInfo
.\08-post-install-config.ps1 -SkipSchedulerJobs -SkipServerInfo -SkipSmtpConfig
```
**Enable automatic updates after verification:**
@@ -424,6 +617,22 @@ sqlplus sys/romfastsoft@localhost:1521/XEPDB1 as sysdba @sql/uninstall-roa.sql
> **Warning:** This permanently deletes all ROA data! Use only for testing or before reinstallation.
**Verifică întotdeauna codul de ieșire.** Fiecare secțiune a scriptului prinde excepțiile în
`WHEN OTHERS` ca să nu se oprească la primul obstacol, deci mesajele intermediare nu spun dacă
a reușit. Verdictul e dat de blocul final, care numără ce a rămas:
| Cod | Înseamnă |
|---|---|
| `0` | Baza e curată. Poți relua instalarea. |
| ≠ `0` | `ORA-20900` — au rămas obiecte ROA. **Nu porni instalarea.** |
Cauza uzuală a unei dezinstalări incomplete e o sesiune activă care ține userul ocupat
(`ORA-01940`); scriptul mai încearcă o dată după `KILL SESSION`, dar dacă aplicația ROA e
pornită nu are ce face. Închide aplicația și sesiunile `sqlplus`, apoi rulează din nou.
Dacă ignori codul de ieșire și pornești instalarea peste o dezinstalare parțială, pasul 05 dă
`ORA-31684 ... already exists` în lanț.
---
## Troubleshooting
@@ -468,6 +677,35 @@ ALTER PLUGGABLE DATABASE XEPDB1 OPEN;
ALTER PLUGGABLE DATABASE XEPDB1 SAVE STATE;
```
### ORA-12609: TNS Receive timeout — importul „eșuează" deși a reușit
**Simptom:** `03-import-contafin.ps1` (sau `05`) se termină cu
`UDI-12609 / ORA-12609: TNS: Receive timeout occurred`, raportează `Objects imported: 0` și iese
cu cod nenul. Dar în logul Data Pump din `C:\DMPDIR` scrie
`Job "SYSTEM"."SYS_IMPORT_SCHEMA_01" completed`.
**Cauză:** `SQLNET.RECV_TIMEOUT` în `sqlnet.ora`. Fișierul e citit și de clienții de pe aceeași
mașină (`impdp`, `expdp`, `sqlplus`), iar în timpul unui import serverul poate lucra minute
întregi fără să trimită vreun pachet — creare de indecși, constrângeri. Clientul `impdp` moare,
jobul de pe server continuă și se termină cu bine, iar scriptul numără obiectele imediat după
moartea clientului și găsește 0.
Pe Oracle 21c fișierul care contează e cel din **read-only home**:
`C:\app\<user>\product\21c\homes\OraDB21Home1\network\admin\sqlnet.ora`, nu cel din `dbhomeXE`.
**Rezolvare:** scoate `SQLNET.RECV_TIMEOUT` și `SQLNET.SEND_TIMEOUT`. `01-setup-database.ps1` nu
le mai scrie (le hardcoda pe amândouă la 30 s), dar o instalare mai veche le poate avea încă:
```powershell
$f = "C:\app\romfast\product\21c\homes\OraDB21Home1\network\admin\sqlnet.ora"
(Get-Content $f) | Where-Object { $_ -notmatch 'SQLNET\.(RECV|SEND)_TIMEOUT' } | Set-Content $f
```
`SQLNET.INBOUND_CONNECT_TIMEOUT` poate rămâne — limitează doar handshake-ul de conectare.
Importul care „a eșuat" nu trebuie refăcut dacă logul spune `completed`; rulează doar
`07-verify-installation.ps1` ca să confirmi.
### Import Errors
**ORA-00959: tablespace 'ROA' does not exist:**

View File

@@ -322,7 +322,7 @@ EXIT;
$synData = @{}
foreach ($line in $synResult -split "`n") {
if ($line -match "^([A-Z_]+):(\d+)$") {
if ($line -match "^([A-Z_]+):(\d+)\s*$") {
$synData[$Matches[1]] = [int]$Matches[2]
}
}
@@ -454,6 +454,70 @@ EXIT;
}
}
# Company Template + SMTP
# ------------------------------------------------------------------------
# SYS.NEWSCHEMA (si 06-add-company.ps1) creeaza o firma noua importand
# sablonul FIRMANOUA.dmp din directorul Oracle DMPDIR. Daca fisierul nu e
# acolo, adaugarea de firme noi pica in DBMS_DATAPUMP.ADD_FILE - dar abia
# peste luni, cand clientul chiar adauga o firma. Il verificam la instalare.
Add-ReportSection "Company Template + SMTP"
# Lipsa sablonului e un defect real (blocheaza adaugarea de firme), deci
# intra in $issues si in codul de iesire. SMTP nesetat ramane doar o nota:
# nu toti clientii folosesc notificarile pe email.
$extraIssues = @()
$tmplSql = @"
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 200
SELECT 'DMPDIR_PATH:' || directory_path FROM dba_directories WHERE directory_name = 'DMPDIR';
SELECT 'SMTP_OUT:' || NVL(value, '<nesetat>') FROM v`$parameter WHERE name = 'smtp_out_server';
EXIT;
"@
$tmplResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
-Username "SYS" -Password $SystemPassword -SqlCommand $tmplSql -AsSysdba -Silent
$dmpDirPath = $null
$smtpOut = $null
foreach ($line in $tmplResult -split "`n") {
$line = $line.Trim()
if ($line -match "^DMPDIR_PATH:(.+)$") { $dmpDirPath = $Matches[1].Trim() }
if ($line -match "^SMTP_OUT:(.+)$") { $smtpOut = $Matches[1].Trim() }
}
if (-not $dmpDirPath) {
Add-ReportLine "[WARNING] Directorul Oracle DMPDIR nu exista."
$extraIssues += "Oracle directory DMPDIR missing"
}
else {
Add-ReportLine "DMPDIR: $dmpDirPath"
$tmplPath = Join-Path $dmpDirPath "FIRMANOUA.dmp"
if (Test-Path $tmplPath) {
$sizeMb = [math]::Round((Get-Item $tmplPath).Length / 1MB, 1)
Add-ReportLine "FIRMANOUA.dmp: OK ($sizeMb MB)"
}
else {
Add-ReportLine "FIRMANOUA.dmp: LIPSA"
Add-ReportLine ""
Add-ReportLine "[WARNING] Fara sablonul FIRMANOUA.dmp in DMPDIR, adaugarea unei firme"
Add-ReportLine " noi (SYS.NEWSCHEMA / 06-add-company.ps1) va esua la"
Add-ReportLine " DBMS_DATAPUMP.ADD_FILE. Copiaza-l in $dmpDirPath."
Add-ReportLine " Sursa: LXC 108, container oracle-xe,"
Add-ReportLine " /tmp/oracle-import-roa2/firmanoua.dmp"
$extraIssues += "FIRMANOUA.dmp missing from DMPDIR (adding new companies will fail)"
}
}
Add-ReportLine ""
if ($smtpOut -and $smtpOut -ne '<nesetat>') {
Add-ReportLine "SMTP_OUT_SERVER: $smtpOut"
}
else {
Add-ReportLine "SMTP_OUT_SERVER: NESETAT"
Add-ReportLine "[NOTA] UTL_MAIL.SEND va da ORA-29278/29279 pana cand e setat."
Add-ReportLine " Ruleaza 08-post-install-config.ps1 -EmailSmtp <server>."
}
# Network ACL Status
Add-ReportSection "Network ACL Status"
@@ -531,6 +595,10 @@ EXIT;
$issues += "$($missingCompanies.Count) company schemas are missing"
}
if ($extraIssues.Count -gt 0) {
$issues += $extraIssues
}
if ($issues.Count -eq 0) {
Add-ReportLine "[OK] All checks passed!"
Add-ReportLine ""

View File

@@ -1,159 +1,168 @@
# ============================================================================
# ROA UNINSTALL SCRIPT
# ============================================================================
# Removes all ROA application objects from Oracle database
#
# Usage:
# .\99-uninstall-roa.ps1 -SystemPassword "yourpassword"
# .\99-uninstall-roa.ps1 -SystemPassword "yourpassword" -Force
# .\99-uninstall-roa.ps1 -ServiceName "XEPDB1" -SystemPassword "yourpassword" -Force
#
# Parameters:
# -SystemPassword : SYS password for database connection (default: romfastsoft)
# -ServiceName : Oracle service name (auto-detected if not specified)
# -Force : Skip confirmation prompt
#
# ============================================================================
param(
[Parameter(Mandatory=$false)]
[string]$OracleHome,
[Parameter(Mandatory=$false)]
[string]$ServiceName,
[Parameter(Mandatory=$false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory=$false)]
[switch]$Force
)
$ErrorActionPreference = "Stop"
# ============================================================================
# LOAD CONFIGURATION AND LIBRARIES
# ============================================================================
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$RootDir = Split-Path -Parent $ScriptDir
# Load config (optional - script can work with auto-detection)
$ConfigFile = Join-Path $RootDir "config.ps1"
if (Test-Path $ConfigFile) {
. $ConfigFile
# Use config values if parameters not provided
if (-not $OracleHome -and $ORACLE_HOME) { $OracleHome = $ORACLE_HOME }
if (-not $ServiceName -and $SERVICE_NAME) { $ServiceName = $SERVICE_NAME }
if ($SystemPassword -eq "romfastsoft" -and $SYSTEM_PASSWORD) { $SystemPassword = $SYSTEM_PASSWORD }
}
# Load libraries
. (Join-Path $ScriptDir "lib\logging-functions.ps1")
. (Join-Path $ScriptDir "lib\oracle-functions.ps1")
# ============================================================================
# MAIN
# ============================================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " ROA UNINSTALL - REMOVING ALL ROA OBJECTS" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
# Get Oracle Home
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-Host "[INFO] Oracle Home: $oraHome" -ForegroundColor Green
# Get listener host
$OracleHost = Get-ListenerHost -OracleHome $oraHome
Write-Host "[INFO] Database Host: $OracleHost" -ForegroundColor Green
# Auto-detect service name if not specified
if (-not $ServiceName) {
$ServiceName = "XEPDB1" # Default for Oracle XE
}
Write-Host "[INFO] Service Name: $ServiceName" -ForegroundColor Green
# Build connection string
$OraclePort = 1521
$ConnString = "${OracleHost}:${OraclePort}/${ServiceName}"
Write-Host ""
Write-Host "Target database: $ConnString" -ForegroundColor Yellow
Write-Host ""
# Confirmation
if (-not $Force) {
Write-Host "WARNING: This will PERMANENTLY DELETE all ROA data!" -ForegroundColor Red
Write-Host ""
Write-Host "Objects to be removed:" -ForegroundColor Yellow
Write-Host " - All company user schemas (using ROA tablespace)"
Write-Host " - CONTAFIN_ORACLE user and all objects"
Write-Host " - Public synonyms pointing to CONTAFIN_ORACLE"
Write-Host " - SYS custom objects (AUTH_PACK, AUTH_SERII, etc.)"
Write-Host " - Application context SESIUNE"
Write-Host " - Tablespace ROA (including datafile)"
Write-Host ""
$confirm = Read-Host "Type 'YES' to confirm uninstall"
if ($confirm -ne "YES") {
Write-Host "Uninstall cancelled." -ForegroundColor Yellow
exit 0
}
}
Write-Host ""
Write-Host "Starting uninstall..." -ForegroundColor Cyan
Write-Host ""
# Find sqlplus
$SqlPlus = Join-Path $oraHome "bin\sqlplus.exe"
if (-not (Test-Path $SqlPlus)) {
Write-Host "ERROR: sqlplus.exe not found at $SqlPlus" -ForegroundColor Red
exit 1
}
# Run uninstall script
$SqlScript = Join-Path $RootDir "sql\uninstall-roa.sql"
if (-not (Test-Path $SqlScript)) {
Write-Host "ERROR: uninstall-roa.sql not found at $SqlScript" -ForegroundColor Red
exit 1
}
Write-Host "Running uninstall script..." -ForegroundColor Cyan
Write-Host ""
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
# Execute uninstall SQL script
try {
& $SqlPlus "sys/${SystemPassword}@${ConnString} as sysdba" "@$SqlScript"
$exitCode = $LASTEXITCODE
}
catch {
Write-Host "ERROR: Failed to execute uninstall script: $_" -ForegroundColor Red
exit 1
}
Write-Host ""
if ($exitCode -eq 0) {
Write-Host "============================================================" -ForegroundColor Green
Write-Host " ROA UNINSTALL COMPLETE" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Write-Host "Database is now clean. You can re-run the setup scripts." -ForegroundColor Cyan
}
else {
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host " ROA UNINSTALL COMPLETED WITH WARNINGS" -ForegroundColor Yellow
Write-Host "============================================================" -ForegroundColor Yellow
Write-Host ""
Write-Host "Some objects may not have been removed. Review output above." -ForegroundColor Yellow
}
Write-Host ""
# ============================================================================
# ROA UNINSTALL SCRIPT
# ============================================================================
# Removes all ROA application objects from Oracle database
#
# Usage:
# .\99-uninstall-roa.ps1 -SystemPassword "yourpassword"
# .\99-uninstall-roa.ps1 -SystemPassword "yourpassword" -Force
# .\99-uninstall-roa.ps1 -ServiceName "XEPDB1" -SystemPassword "yourpassword" -Force
#
# Parameters:
# -SystemPassword : SYS password for database connection (default: romfastsoft)
# -ServiceName : Oracle service name (auto-detected if not specified)
# -Force : Skip confirmation prompt
#
# ============================================================================
param(
[Parameter(Mandatory=$false)]
[string]$OracleHome,
[Parameter(Mandatory=$false)]
[string]$ServiceName,
[Parameter(Mandatory=$false)]
[string]$SystemPassword = "romfastsoft",
[Parameter(Mandatory=$false)]
[switch]$Force
)
$ErrorActionPreference = "Stop"
# ============================================================================
# LOAD CONFIGURATION AND LIBRARIES
# ============================================================================
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$RootDir = Split-Path -Parent $ScriptDir
# Load config (optional - script can work with auto-detection)
$ConfigFile = Join-Path $RootDir "config.ps1"
if (Test-Path $ConfigFile) {
. $ConfigFile
# Use config values if parameters not provided
if (-not $OracleHome -and $ORACLE_HOME) { $OracleHome = $ORACLE_HOME }
if (-not $ServiceName -and $SERVICE_NAME) { $ServiceName = $SERVICE_NAME }
if ($SystemPassword -eq "romfastsoft" -and $SYSTEM_PASSWORD) { $SystemPassword = $SYSTEM_PASSWORD }
}
# Load libraries
. (Join-Path $ScriptDir "lib\logging-functions.ps1")
. (Join-Path $ScriptDir "lib\oracle-functions.ps1")
# ============================================================================
# MAIN
# ============================================================================
Write-Host ""
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host " ROA UNINSTALL - REMOVING ALL ROA OBJECTS" -ForegroundColor Cyan
Write-Host "============================================================" -ForegroundColor Cyan
Write-Host ""
# Get Oracle Home
$oraHome = Get-OracleHome -OracleHome $OracleHome
Write-Host "[INFO] Oracle Home: $oraHome" -ForegroundColor Green
# Get listener host
$OracleHost = Get-ListenerHost -OracleHome $oraHome
Write-Host "[INFO] Database Host: $OracleHost" -ForegroundColor Green
# Auto-detect service name if not specified
if (-not $ServiceName) {
$ServiceName = "XEPDB1" # Default for Oracle XE
}
Write-Host "[INFO] Service Name: $ServiceName" -ForegroundColor Green
# Build connection string
$OraclePort = 1521
$ConnString = "${OracleHost}:${OraclePort}/${ServiceName}"
Write-Host ""
Write-Host "Target database: $ConnString" -ForegroundColor Yellow
Write-Host ""
# Confirmation
if (-not $Force) {
Write-Host "WARNING: This will PERMANENTLY DELETE all ROA data!" -ForegroundColor Red
Write-Host ""
Write-Host "Objects to be removed:" -ForegroundColor Yellow
Write-Host " - All company user schemas (using ROA tablespace)"
Write-Host " - CONTAFIN_ORACLE user and all objects"
Write-Host " - Public synonyms pointing to CONTAFIN_ORACLE"
Write-Host " - SYS custom objects (AUTH_PACK, AUTH_SERII, etc.)"
Write-Host " - Application context SESIUNE"
Write-Host " - Tablespace ROA (including datafile)"
Write-Host ""
$confirm = Read-Host "Type 'YES' to confirm uninstall"
if ($confirm -ne "YES") {
Write-Host "Uninstall cancelled." -ForegroundColor Yellow
exit 0
}
}
Write-Host ""
Write-Host "Starting uninstall..." -ForegroundColor Cyan
Write-Host ""
# Find sqlplus
$SqlPlus = Join-Path $oraHome "bin\sqlplus.exe"
if (-not (Test-Path $SqlPlus)) {
Write-Host "ERROR: sqlplus.exe not found at $SqlPlus" -ForegroundColor Red
exit 1
}
# Run uninstall script
$SqlScript = Join-Path $RootDir "sql\uninstall-roa.sql"
if (-not (Test-Path $SqlScript)) {
Write-Host "ERROR: uninstall-roa.sql not found at $SqlScript" -ForegroundColor Red
exit 1
}
Write-Host "Running uninstall script..." -ForegroundColor Cyan
Write-Host ""
# Set Oracle environment
$env:ORACLE_HOME = $oraHome
$env:PATH = "$oraHome\bin;$env:PATH"
$env:NLS_LANG = "AMERICAN_AMERICA.AL32UTF8"
# Execute uninstall SQL script
try {
& $SqlPlus "sys/${SystemPassword}@${ConnString} as sysdba" "@$SqlScript"
$exitCode = $LASTEXITCODE
}
catch {
Write-Host "ERROR: Failed to execute uninstall script: $_" -ForegroundColor Red
exit 1
}
# uninstall-roa.sql se termina cu un bloc de verdict:
# - EXIT SUCCESS daca nu a ramas niciun obiect ROA
# - EXIT FAILURE (ORA-20900) daca a supravietuit ceva
# Codul de iesire e deci autoritar; nu-l suprascrie si nu raporta succes fara el.
Write-Host ""
if ($exitCode -eq 0) {
Write-Host "============================================================" -ForegroundColor Green
Write-Host " ROA UNINSTALL COMPLETE" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Write-Host "Database is now clean. You can re-run the setup scripts." -ForegroundColor Cyan
exit 0
}
else {
Write-Host "============================================================" -ForegroundColor Red
Write-Host " ROA UNINSTALL INCOMPLET" -ForegroundColor Red
Write-Host "============================================================" -ForegroundColor Red
Write-Host ""
Write-Host "Au ramas obiecte ROA in baza (vezi ORA-20900 mai sus)." -ForegroundColor Red
Write-Host "Cauza uzuala: o sesiune activa tinea userul ocupat." -ForegroundColor Yellow
Write-Host ""
Write-Host "NU porni instalarea acum - pasul 05 va da ORA-31684 in lant." -ForegroundColor Yellow
Write-Host "Inchide aplicatia ROA / sesiunile sqlplus si ruleaza scriptul din nou." -ForegroundColor Yellow
exit $exitCode
}

View File

@@ -12,10 +12,18 @@
-- WARNING: This reduces security. For production environments, consider
-- creating a custom profile with appropriate settings.
--
-- Usage:
-- @configure-profile.sql
-- ATENTIE - UNELTA DE REMEDIERE MANUALA, NU FACE PARTE DIN FLUXUL DE INSTALARE
-- ----------------------------------------------------------------------------
-- La o instalare normala NU rulezi scriptul asta: `01-setup-database.ps1` face
-- deja acelasi lucru automat, la Step 4 (in PDB) si Step 4b (in CDB root).
-- Foloseste-l doar cand `07-verify-installation.ps1` / `verify-objects.sql`
-- semnaleaza ca profilul DEFAULT are din nou limite de parola - de exemplu pe o
-- baza configurata inainte ca Step 4b sa existe, sau dupa un patch Oracle.
--
-- Connect as: SYSDBA
-- Usage:
-- sqlplus sys/<parola>@<host>:1521/XEPDB1 as sysdba @configure-profile.sql
--
-- Connect as: SYSDBA, pe PDB (XEPDB1), NU pe CDB root.
-- ============================================================================
SET ECHO OFF
@@ -97,3 +105,46 @@ WHERE username IN ('CONTAFIN_ORACLE', 'SYSTEM', 'SYS')
OR username LIKE 'TEST%';
PROMPT
-- ============================================================================
-- ULTIMUL PAS: ACELASI PROFIL SI IN CDB ROOT
-- ============================================================================
-- ALTER PROFILE dintr-un PDB nu acopera CDB root: acolo DEFAULT ramane cu
-- PASSWORD_LIFE_TIME 180, deci SYSTEM din root expira la ~6 luni de la
-- instalare (ORA-28002, apoi ORA-28001) chiar daca in PDB totul e UNLIMITED.
--
-- DEFAULT din root e un profil LOCAL, deci clauza CONTAINER=ALL NU e valida
-- aici (ORA-65142). Se comuta containerul si se altereaza profilul de acolo.
--
-- Blocul e ULTIMUL din fisier intentionat: dupa ALTER SESSION SET CONTAINER
-- restul scriptului ar rula in root, nu in PDB.
-- Pe o baza non-CDB, ALTER SESSION esueaza inofensiv (WHENEVER SQLERROR
-- CONTINUE) si ALTER PROFILE se aplica pe singurul container existent.
PROMPT
PROMPT ========================================
PROMPT Applying the same profile in CDB root
PROMPT ========================================
PROMPT
ALTER SESSION SET CONTAINER = CDB$ROOT;
ALTER PROFILE DEFAULT LIMIT
PASSWORD_LIFE_TIME UNLIMITED
PASSWORD_GRACE_TIME UNLIMITED
PASSWORD_REUSE_TIME UNLIMITED
PASSWORD_REUSE_MAX UNLIMITED
FAILED_LOGIN_ATTEMPTS UNLIMITED
PASSWORD_LOCK_TIME UNLIMITED;
PROMPT
PROMPT Account status in CDB root:
SELECT username, account_status, expiry_date
FROM dba_users
WHERE username IN ('SYS', 'SYSTEM');
PROMPT
PROMPT NOTA: daca SYSTEM apare EXPIRED(GRACE), statusul NU se curata singur
PROMPT cand profilul devine UNLIMITED - cere o singura data:
PROMPT ALTER USER SYSTEM IDENTIFIED BY <parola>;
PROMPT (sau ruleaza 01-setup-database.ps1 -ResetSystemPassword)
PROMPT

View File

@@ -24,7 +24,7 @@ PROMPT
-- SECTION 1: GRANTS TO CONTAFIN_ORACLE
-- ============================================================================
PROMPT
PROMPT [1/5] Granting privileges to CONTAFIN_ORACLE...
PROMPT [1/6] Granting privileges to CONTAFIN_ORACLE...
-- Execute on SYS packages
GRANT EXECUTE ON SYS.AUTH_PACK TO CONTAFIN_ORACLE;
@@ -32,9 +32,16 @@ GRANT EXECUTE ON SYS.DBMS_SCHEDULER TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.DBMS_LOCK TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UTL_INADDR TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UTL_FILE TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UTL_MAIL TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UTL_SMTP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UTL_TCP TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.DBMS_CRYPTO TO CONTAFIN_ORACLE;
-- Proceduri SYS proprii ROA. Grant DIRECT, nu prin rol si nu prin sinonim public:
-- CONTAFIN_ORACLE.PACK_UPDATE are drepturi de definitor si apeleaza calificat
-- SYS.Updatesqlplus(...), deci rolurile si sinonimele nu se aplica. Fara ele
-- PACK_UPDATE ramane INVALID (PLS-00201). Confirmat pe ROA_CENTRAL 2026-08-25.
GRANT EXECUTE ON SYS.EXECUTESCRIPTOS TO CONTAFIN_ORACLE;
GRANT EXECUTE ON SYS.UPDATESQLPLUS TO CONTAFIN_ORACLE;
-- Directory privileges
GRANT CREATE ANY DIRECTORY TO CONTAFIN_ORACLE;
@@ -51,7 +58,7 @@ PROMPT Grants to CONTAFIN_ORACLE complete.
-- SECTION 2: PUBLIC GRANTS
-- ============================================================================
PROMPT
PROMPT [2/5] Granting public privileges...
PROMPT [2/6] Granting public privileges...
-- UTL packages for public use
GRANT EXECUTE ON SYS.UTL_FILE TO PUBLIC;
@@ -62,7 +69,7 @@ PROMPT Public grants complete.
-- SECTION 3: SYS PUBLIC SYNONYMS
-- ============================================================================
PROMPT
PROMPT [3/5] Creating SYS public synonyms...
PROMPT [3/6] Creating SYS public synonyms...
-- Synonyms for SYS procedures
BEGIN EXECUTE IMMEDIATE 'DROP PUBLIC SYNONYM SYN_NEWSCHEMA'; EXCEPTION WHEN OTHERS THEN NULL; END;
@@ -91,7 +98,7 @@ PROMPT SYS public synonyms complete.
-- SECTION 4: DIRECTORY DMPDIR
-- ============================================================================
PROMPT
PROMPT [4/5] Creating DMPDIR directory...
PROMPT [4/6] Creating DMPDIR directory...
BEGIN
EXECUTE IMMEDIATE 'CREATE OR REPLACE DIRECTORY DMPDIR AS ''C:\DMPDIR''';
@@ -126,7 +133,7 @@ GRANT READ, WRITE ON DIRECTORY DMPDIR TO PUBLIC;
-- Vederile absente pe versiunea/editia curenta sunt ignorate (ORA-00942).
-- ============================================================================
PROMPT
PROMPT [5/5] Granting data dictionary reads to CONTAFIN_ORACLE (PACK_DIAG_SPATIU)...
PROMPT [5/6] Granting data dictionary reads to CONTAFIN_ORACLE (PACK_DIAG_SPATIU)...
DECLARE
TYPE t_lista IS TABLE OF VARCHAR2(30);
@@ -170,6 +177,40 @@ END;
PROMPT Dictionary grants complete.
-- ============================================================================
-- SECTION 6: RECOMPILARE CONTAFIN_ORACLE
-- ============================================================================
-- Obiectele venite cu Data Pump raman INVALID: la momentul importului granturile
-- de mai sus inca nu erau puse, de unde ORA-39082 "created with compilation
-- warnings" pe SENDEMAIL, EMAIL*, PACK_UPDATE, PACK_UTILS. Oracle le-ar recompila
-- abia la primul apel, asa ca fara pasul asta 07-verify-installation raporteaza
-- obiecte invalide la fiecare instalare curata.
-- Verificat pe VM 302 (2026-08-25): 2 invalide inainte, 0 dupa.
-- ============================================================================
PROMPT
PROMPT [6/6] Recompiling CONTAFIN_ORACLE...
BEGIN
SYS.UTL_RECOMP.RECOMP_SERIAL('CONTAFIN_ORACLE');
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(' Recompilare: ' || SQLERRM);
END;
/
DECLARE
lnInvalid PLS_INTEGER;
BEGIN
SELECT COUNT(*) INTO lnInvalid
FROM dba_objects
WHERE owner = 'CONTAFIN_ORACLE' AND status = 'INVALID';
DBMS_OUTPUT.PUT_LINE(' Obiecte INVALID ramase in CONTAFIN_ORACLE: ' || lnInvalid);
END;
/
PROMPT Recompile complete.
PROMPT
PROMPT ============================================================
PROMPT SYS Grants and Synonyms Installation Complete

View File

@@ -32,7 +32,7 @@ PROMPT
-- SECTION 1: TABLES
-- ============================================================================
PROMPT [1/11] Creating SYS.AUTH_DETALII table...
PROMPT [1/10] Creating SYS.AUTH_DETALII table...
DECLARE
v_count NUMBER;
BEGIN
@@ -50,7 +50,7 @@ BEGIN
END;
/
PROMPT [2/11] Creating SYS.AUTH_SERII table...
PROMPT [2/10] Creating SYS.AUTH_SERII table...
DECLARE
v_count NUMBER;
BEGIN
@@ -76,7 +76,7 @@ BEGIN
END;
/
PROMPT [3/11] Creating SYS.INFO table (logging)...
PROMPT [3/10] Creating SYS.INFO table (logging)...
-- IMPORTANT: SYS.INFO e log de aplicatie, nu obiect de dictionar - SYS.pINFO scrie ~7 randuri la
-- fiecare conectare (~13.500 randuri / ~2 MB pe luna) si nimic nu o citeste. Tinuta in SYSTEM,
-- umple tablespace-ul dictionarului si **orice** script de actualizare pica apoi cu
@@ -116,7 +116,7 @@ END;
-- SECTION 2: SEQUENCE
-- ============================================================================
PROMPT [4/11] Creating SYS.SEQ_AUTH_SERII sequence...
PROMPT [4/10] Creating SYS.SEQ_AUTH_SERII sequence...
DECLARE
v_count NUMBER;
BEGIN
@@ -143,7 +143,7 @@ END;
-- SECTION 3: LOGGING PROCEDURE (pINFO)
-- ============================================================================
PROMPT [5/11] Creating SYS.pINFO procedure (logging)...
PROMPT [5/10] Creating SYS.pINFO procedure (logging)...
CREATE OR REPLACE PROCEDURE SYS.pINFO(
p_info IN CLOB,
p_locatia IN VARCHAR2 DEFAULT NULL
@@ -164,7 +164,7 @@ END pINFO;
-- SECTION 4: AUTH_PACK PACKAGE (Oracle 21c compatible with DBMS_CRYPTO)
-- ============================================================================
PROMPT [6/11] Creating SYS.AUTH_PACK package specification...
PROMPT [6/10] Creating SYS.AUTH_PACK package specification...
CREATE OR REPLACE PACKAGE SYS.AUTH_PACK IS
-- ========================================================================
-- AUTH_PACK - License and Authentication Management
@@ -229,7 +229,7 @@ CREATE OR REPLACE PACKAGE SYS.AUTH_PACK IS
END AUTH_PACK;
/
PROMPT [7/11] Creating SYS.AUTH_PACK package body...
PROMPT [7/10] Creating SYS.AUTH_PACK package body...
CREATE OR REPLACE PACKAGE BODY SYS.AUTH_PACK IS
-- ========================================================================
-- MODIFICATION HISTORY:
@@ -769,7 +769,7 @@ END AUTH_PACK;
-- SECTION 5: VIEW
-- ============================================================================
PROMPT [8/11] Creating SYS.VAUTH_SERII view...
PROMPT [8/10] Creating SYS.VAUTH_SERII view...
CREATE OR REPLACE VIEW SYS.VAUTH_SERII (
ID_PROGRAM,
NUME,
@@ -791,142 +791,355 @@ WHERE b.sters = 0
-- SECTION 6: ADDITIONAL PROCEDURES
-- ============================================================================
PROMPT [9/11] Creating SYS.EXECUTESCRIPTOS procedure...
CREATE OR REPLACE PROCEDURE SYS.EXECUTESCRIPTOS(
p_nume_script IN VARCHAR2,
p_param IN VARCHAR2,
p_wait IN VARCHAR2,
p_result OUT NUMBER
) IS
v_job_name VARCHAR2(100);
v_state VARCHAR2(30);
BEGIN
v_job_name := 'EXECUTESCRIPTOS_' || TO_CHAR(SYSDATE, 'YYYYMMDD_HH24MISS');
PROMPT [9/10] Creating SYS.EXECUTESCRIPTOS, NEWSCHEMA, NEWSCHEMAJOB, UPDATESQLPLUS...
-- ============================================================================
-- Sursa: procedurile SYS de pe ROA_CENTRAL (10.0.20.121:1521/ROA), extrase din
-- dba_source la 2026-08-25. Versiunile anterioare din acest fisier aveau
-- semnaturi inventate, incompatibile cu CONTAFIN_ORACLE.PACK_UPDATE, care apeleaza
-- SYS.Updatesqlplus(tcSqlPlusPath, tcScriptPath). Nu modifica semnaturile fara sa
-- verifici intai apelurile din PACK_UPDATE / PACK_UTILS.
-- ============================================================================
CREATE OR REPLACE PROCEDURE SYS.ExecuteScriptOS(tcPowerShellPath in varchar2,
tcScriptPath in varchar2) as
lcJobName varchar2(500);
begin
lcJobName := 'exec_ps_' || SUBSTR(SYS_GUID(), 1, 8);
DBMS_SCHEDULER.CREATE_JOB(
job_name => v_job_name,
job_type => 'EXECUTABLE',
job_action => p_nume_script,
number_of_arguments => 1,
start_date => SYSTIMESTAMP,
enabled => FALSE,
auto_drop => TRUE
job_name => lcJobName,
job_action => tcPowerShellPath,
number_of_arguments => 4,
job_type => 'executable',
enabled => FALSE
);
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
job_name => v_job_name,
argument_position => 1,
argument_value => p_param
);
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(lcJobName, 1, '-ExecutionPolicy');
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(lcJobName, 2, 'Bypass');
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(lcJobName, 3, '-File');
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(lcJobName, 4, tcScriptPath);
DBMS_SCHEDULER.ENABLE(v_job_name);
DBMS_SCHEDULER.ENABLE(lcJobName);
end ExecuteScriptOS;
/
IF p_wait = 'Y' THEN
LOOP
BEGIN
SELECT state INTO v_state
FROM dba_scheduler_jobs
WHERE job_name = v_job_name;
CREATE OR REPLACE PROCEDURE SYS.NewSchema(tcSchema varchar2,
tnLuna number,
tnAn number) is
lcCommand varchar2(1000);
EXIT WHEN v_state NOT IN ('SCHEDULED', 'RUNNING');
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT; -- Job completed and was auto-dropped
END;
DBMS_LOCK.SLEEP(1);
END LOOP;
END IF;
lcSchemaSursa VARCHAR2(100) := 'FIRMANOUA';
lcSchemaDestinatie VARCHAR2(100) := tcSchema;
lcDumpFile VARCHAR2(100);
lcDumpDir VARCHAR2(100) := 'DMPDIR';
-- lnCount number(10);
p_result := 0;
EXCEPTION
lcSql varchar2(1000);
lnAn number := tnAn;
lnLuna number := tnLuna;
ldDataI date;
ldDataF date;
lnZileLucratoare number(10) := 0;
lnOreLucratoare number(10) := 0;
lnMaxAn number(10);
lcLocatie varchar2(100) := 'CREARE FIRMA ' || tcSchema;
h1 NUMBER; -- Data Pump job handle
ind NUMBER; -- Loop index
percent_done NUMBER; -- Percentage of job complete
job_state VARCHAR2(30); -- To keep track of job state
le ku$_LogEntry; -- For WIP and error messages
js ku$_JobStatus; -- The job status from get_status
-- jd ku$_JobDesc; -- The job description from get_status
sts ku$_Status; -- The status object returned by get_status
begin
------------------------------------------------------------------------
-- CREATE THE USER
------------------------------------------------------------------------
/* SELECT COUNT(1)
INTO lnCount
FROM dba_users
WHERE username = UPPER(tcSchema);
IF lnCount <> 0 THEN
EXECUTE IMMEDIATE ('DROP USER ' || tcSchema || ' CASCADE');
END IF;*/
lcCommand := 'create user ' || tcSchema || ' identified by ' || CASE
WHEN upper(tcSchema) like 'TEST%' THEN
'"123"'
ELSE
'ROMFASTSOFT'
END || ' default tablespace ROA
temporary tablespace TEMP
profile DEFAULT';
pinfo(lcCommand, lcLocatie);
execute immediate lcCommand;
------------------------------------------------------------------------
-- GRANT PRIVILEGIES
------------------------------------------------------------------------
lcCommand := 'grant connect to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant resource to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create materialized view to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create procedure to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create sequence to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create table to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create trigger to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create type to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant create view to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant debug connect session to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant select any table to ' || tcSchema;
execute immediate lcCommand;
lcCommand := 'grant unlimited tablespace to ' || tcSchema;
execute immediate lcCommand;
------------------------------------------------------------------------
-- IMPORT DUMP
------------------------------------------------------------------------
-- Create a (user-named) Data Pump job to do a "full" import (everything
-- in the dump file without filtering).
lcDumpFile := lcSchemaSursa || '.dmp';
-- h1 := DBMS_DATAPUMP.OPEN('IMPORT', 'SCHEMA', NULL, lcSchemaDestinatie);
h1 := DBMS_DATAPUMP.OPEN('IMPORT', 'SCHEMA', NULL, lcSchemaDestinatie);
-- Specify the single dump file for the job (using the handle just returned)
-- and directory object, which must already be defined and accessible
-- to the user running this procedure. This is the dump file created by
-- the export operation in the first example.
-- DBMS_DATAPUMP.ADD_FILE(h1, lcDumpFile, lcDumpDir);
BEGIN
PINFO('DBMS_DATAPUMP.ADD_FILE LOG', lcLocatie);
DBMS_DATAPUMP.ADD_FILE(handle => h1,
filename => lcSchemaDestinatie || '.log',
directory => 'DMPDIR',
filetype => 3);
PINFO('DBMS_DATAPUMP.ADD_FILE DMP', lcLocatie);
DBMS_DATAPUMP.ADD_FILE(handle => h1,
filename => lcDumpFile,
directory => lcDumpDir,
filetype => 1);
-- A metadata remap will map all schema objects from HR to BLAKE.
PINFO('DBMS_DATAPUMP.METADATA_REMAP', lcLocatie);
DBMS_DATAPUMP.METADATA_REMAP(h1,
'REMAP_SCHEMA',
lcSchemaSursa,
lcSchemaDestinatie);
-- If a table already exists in the destination schema, skip it (leave
-- the preexisting table alone). This is the default, but it does not hurt
-- to specify it explicitly.
DBMS_DATAPUMP.SET_PARAMETER(h1, 'TABLE_EXISTS_ACTION', 'SKIP');
-- Start the job. An exception is returned if something is not set up properly.
PINFO('DBMS_DATAPUMP.START_JOB', lcLocatie);
DBMS_DATAPUMP.START_JOB(h1);
------------------------------------------------------------------------
-- The import job should now be running. In the following loop, the job is
-- monitored until it completes. In the meantime, progress information is
-- displayed. Note: this is identical to the export example.
percent_done := 0;
job_state := 'UNDEFINED';
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
dbms_datapump.get_status(h1,
dbms_datapump.ku$_status_job_error +
dbms_datapump.ku$_status_job_status +
dbms_datapump.ku$_status_wip,
-1,
job_state,
sts);
js := sts.job_status;
-- If the percentage done changed, display the new value.
if js.percent_done != percent_done then
pinfo('*** Job percent done = ' || to_char(js.percent_done),
lcLocatie);
percent_done := js.percent_done;
end if;
-- If any work-in-progress (WIP) or Error messages were received for the job,
-- display them.
if (bitand(sts.mask, dbms_datapump.ku$_status_wip) != 0) then
le := sts.wip;
else
if (bitand(sts.mask, dbms_datapump.ku$_status_job_error) != 0) then
le := sts.error;
else
le := null;
end if;
end if;
if le is not null then
ind := le.FIRST;
while ind is not null loop
-- dbms_output.put_line(le(ind).LogText);
pinfo(le(ind).LogText, lcLocatie);
ind := le.NEXT(ind);
end loop;
end if;
end loop;
-- Indicate that the job finished and gracefully detach from it.
-- dbms_output.put_line('Job has completed');
pinfo('Job has completed', lcLocatie);
-- dbms_output.put_line('Final job state = ' || job_state);
pinfo('Final job state = ' || job_state,
'CREARE FIRMA ' || lcSchemaDestinatie);
------------------------------------------------------------------------
-- POST IMPORT
-- 1. actualizare calendar, sal_calendar, cote_tva
-- CALENDAR
lcSql := 'UPDATE ' || lcSchemaDestinatie ||
'.CALENDAR SET ANUL = :1, LUNA = :2, AN = TO_CHAR(:3), NL = LPAD(:4, 2, ''0'')';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
USING lnAn, lnLuna, lnAn, lnLuna;
-- SAL_CALENDAR
ldDataI := TO_DATE(lpad(lnAn, 4, '0') || lpad(lnLuna, 2, '0'), 'YYYYMM');
ldDataF := ADD_MONTHS(ldDataI, 1) - 1;
lcSql := 'select ' || lcSchemaDestinatie ||
'.pack_personal.calculeaza_nr_zile(:1, :2) FROM DUAL';
EXECUTE IMMEDIATE lcSql
INTO lnZileLucratoare
USING ldDataI, ldDataF;
lnOreLucratoare := lnZileLucratoare * 8;
lcSql := 'UPDATE ' || lcSchemaDestinatie ||
'.SAL_CALENDAR SET AN = :1 , LUNA = :2, ZILELUC = :3, ORESTAS = :4, ORELUC = :5';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
USING lnAn, lnLuna, lnZileLucratoare, lnOreLucratoare, lnOreLucratoare;
-- SAL_IMPOZITAR
lcSql := 'UPDATE ' || lcSchemaDestinatie ||
'.SAL_IMPOZITAR SET AN = :1 , LUNA = :2';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
USING lnAn, lnLuna;
-- PLCONT
lcSql := 'SELECT max(an) as plan from ' || lcSchemaDestinatie ||
'.PLCONT';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
into lnMaxAn;
if lnMaxAn <> lnAn then
lcSql := 'UPDATE ' || lcSchemaDestinatie ||
'.PLCONT SET AN = :1 WHERE AN = :2';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
USING lnAn, lnMaxAn;
end if;
-- COTE_TVA
lcSql := 'SELECT max(an*12+luna) from ' || lcSchemaDestinatie ||
'.cote_tva';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
into lnMaxAn;
lcSql := 'UPDATE ' || lcSchemaDestinatie ||
'.COTE_TVA SET AN = :1, LUNA = :2 WHERE AN*12+LUNA = :3';
PINFO(lcSql, lcLocatie);
EXECUTE IMMEDIATE lcSql
USING lnAn, lnLuna, lnMaxAn;
------------------------------------------------------------------------
-- 2. ACTUALIZARE SCHEMA LA ZI
PINFO('Actualizare schema la zi...', lcLocatie);
CONTAFIN_ORACLE.PACK_UPDATE.UpdateROA(tnUpdateApp => 0,
tnUpdateScripturi => 0,
tnUpdateDatabase => 1,
tcSchemaList => tcSchema);
EXCEPTION
WHEN OTHERS THEN
p_result := -1;
END EXECUTESCRIPTOS;
PINFO(SQLERRM, lcLocatie);
raise_application_error(-20000, SQLERRM);
END;
DBMS_DATAPUMP.DETACH(h1);
end NewSchema;
/
PROMPT [10/11] Creating SYS.NEWSCHEMA procedure...
CREATE OR REPLACE PROCEDURE SYS.NEWSCHEMA(
p_schema_name IN VARCHAR2,
p_password IN VARCHAR2,
p_result OUT NUMBER
) IS
BEGIN
EXECUTE IMMEDIATE 'CREATE USER ' || p_schema_name ||
' IDENTIFIED BY ' || p_password ||
' DEFAULT TABLESPACE ROA' ||
' TEMPORARY TABLESPACE TEMP' ||
' QUOTA UNLIMITED ON ROA';
EXECUTE IMMEDIATE 'GRANT CONNECT, RESOURCE TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE SESSION TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE TABLE TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE VIEW TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE SEQUENCE TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE PROCEDURE TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE TRIGGER TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE TYPE TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE SYNONYM TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE DATABASE LINK TO ' || p_schema_name;
EXECUTE IMMEDIATE 'GRANT CREATE JOB TO ' || p_schema_name;
DBMS_OUTPUT.PUT_LINE('Schema ' || p_schema_name || ' created successfully!');
p_result := 0;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error creating schema: ' || SQLERRM);
p_result := -1;
END NEWSCHEMA;
CREATE OR REPLACE PROCEDURE SYS.NEWSCHEMAJOB(tcSchema varchar2,
tnLuna number,
tnAn number) as
lcJobName varchar2(500);
begin
lcJobName := 'NEWSCHEMA_' || UPPER(tcSchema);
dbms_scheduler.create_job(job_name => lcJobName,
job_type => 'STORED_PROCEDURE',
job_action => 'NEWSCHEMA',
number_of_arguments => 3,
enabled => false);
dbms_scheduler.set_job_argument_value(lcJobName, 1, tcSchema);
dbms_scheduler.set_job_argument_value(lcJobName, 2, to_char(tnLuna));
dbms_scheduler.set_job_argument_value(lcJobName, 3, to_char(tnAn));
dbms_scheduler.enable(lcJobName);
end NEWSCHEMAJOB;
/
PROMPT [11/11] Creating SYS.NEWSCHEMAJOB and SYS.UPDATESQLPLUS procedures...
CREATE OR REPLACE PROCEDURE SYS.NEWSCHEMAJOB(
p_schema_name IN VARCHAR2,
p_password IN VARCHAR2
) IS
v_job_name VARCHAR2(100);
BEGIN
v_job_name := 'NEWSCHEMA_' || p_schema_name;
DBMS_SCHEDULER.CREATE_JOB(
job_name => v_job_name,
job_type => 'STORED_PROCEDURE',
job_action => 'SYS.NEWSCHEMA',
number_of_arguments => 3,
start_date => SYSTIMESTAMP,
enabled => FALSE,
auto_drop => TRUE
);
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
job_name => v_job_name,
argument_position => 1,
argument_value => p_schema_name
);
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
job_name => v_job_name,
argument_position => 2,
argument_value => p_password
);
DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(
job_name => v_job_name,
argument_position => 3,
argument_value => '0'
);
DBMS_SCHEDULER.ENABLE(v_job_name);
END NEWSCHEMAJOB;
CREATE OR REPLACE PROCEDURE SYS.UpdateSQLPLUS(tcSqlPlusPath in varchar2,
tcScriptPath in varchar2) as
lcJobName varchar2(500);
begin
lcJobName := 'updateschema_' || to_char(sysdate, 'YYYYMMDDHH24MISS');
dbms_scheduler.create_job(lcJobName,
job_action => tcSqlPlusPath,
number_of_arguments => 2,
job_type => 'executable',
enabled => false);
dbms_scheduler.set_job_argument_value(lcJobName, 1, '/nolog');
dbms_scheduler.set_job_argument_value(lcJobName, 2, '@' || tcScriptPath);
dbms_scheduler.enable(lcJobName);
end;
/
CREATE OR REPLACE PROCEDURE SYS.UPDATESQLPLUS IS
v_result NUMBER;
BEGIN
-- Path may need to be adjusted for your Windows installation
EXECUTESCRIPTOS('D:\ROMFAST\UPDATE\UPDATE_SQLPLUS.BAT', '', 'N', v_result);
END UPDATESQLPLUS;
/
-- ============================================================================
-- SECTION 7: UTL_MAIL
-- ============================================================================
-- UTL_MAIL nu se instaleaza implicit in Oracle 21c. Fara el raman INVALID:
-- CONTAFIN_ORACLE.SENDEMAIL, EMAILINCASARI, EMAILNOTIFICAREFACTURI,
-- EMAILSTOCCRITIC, PACK_UPDATE si PACK_UTILS (PLS-00201: UTL_MAIL.SEND).
-- Un GRANT nu ajuta - pachetul trebuie creat. Pe ROA_CENTRAL (productie)
-- UTL_MAIL este VALID; verificat 2026-08-25.
--
-- Grantul catre CONTAFIN_ORACLE se face in sql\sys-grants.sql, dupa import.
-- Pentru trimiterea efectiva de mailuri mai trebuie setat SMTP_OUT_SERVER.
-- ============================================================================
PROMPT
PROMPT [10/10] Installing UTL_MAIL...
@?/rdbms/admin/utlmail.sql
@?/rdbms/admin/prvtmail.plb
PROMPT UTL_MAIL installed.
-- ============================================================================
-- VERIFICATION

View File

@@ -94,7 +94,8 @@ DECLARE
)
)
ORDER BY username;
v_count NUMBER := 0;
v_count NUMBER := 0;
v_failed NUMBER := 0;
BEGIN
FOR r IN c_users LOOP
BEGIN
@@ -107,10 +108,30 @@ BEGIN
v_count := v_count + 1;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(' ERROR: ' || SQLERRM);
-- O sesiune agatata tine userul ocupat (ORA-01940 "cannot drop a
-- user that is currently connected"). Prima incercare poate pica
-- inainte ca ALTER SYSTEM KILL SESSION sa fi terminat efectiv.
-- Mai incercam o data; ce ramane e raportat si prins de
-- verificarea finala, care iese cu cod de eroare.
DBMS_OUTPUT.PUT_LINE(' WARN (incercarea 1): ' || SQLERRM);
BEGIN
roa_kill_user_sessions(r.username);
DBMS_SESSION.SLEEP(3);
EXECUTE IMMEDIATE 'DROP USER ' || r.username || ' CASCADE';
DBMS_OUTPUT.PUT_LINE(' Dropped user (retry): ' || r.username);
v_count := v_count + 1;
EXCEPTION
WHEN OTHERS THEN
v_failed := v_failed + 1;
DBMS_OUTPUT.PUT_LINE(' ERROR: ' || r.username ||
' NU a fost sters: ' || SQLERRM);
END;
END;
END LOOP;
DBMS_OUTPUT.PUT_LINE('Total company users dropped: ' || v_count);
IF v_failed > 0 THEN
DBMS_OUTPUT.PUT_LINE('ATENTIE: ' || v_failed || ' user(i) de firma NU au fost stersi.');
END IF;
END;
/
@@ -137,8 +158,18 @@ BEGIN
END;
-- Now drop the user
EXECUTE IMMEDIATE 'DROP USER CONTAFIN_ORACLE CASCADE';
DBMS_OUTPUT.PUT_LINE(' User CONTAFIN_ORACLE dropped successfully.');
BEGIN
EXECUTE IMMEDIATE 'DROP USER CONTAFIN_ORACLE CASCADE';
DBMS_OUTPUT.PUT_LINE(' User CONTAFIN_ORACLE dropped successfully.');
EXCEPTION
WHEN OTHERS THEN
-- Acelasi motiv ca la sectiunea 1: sesiune inca vie.
DBMS_OUTPUT.PUT_LINE(' WARN (incercarea 1): ' || SQLERRM);
roa_kill_user_sessions('CONTAFIN_ORACLE');
DBMS_SESSION.SLEEP(3);
EXECUTE IMMEDIATE 'DROP USER CONTAFIN_ORACLE CASCADE';
DBMS_OUTPUT.PUT_LINE(' User CONTAFIN_ORACLE dropped successfully (retry).');
END;
ELSE
DBMS_OUTPUT.PUT_LINE(' User CONTAFIN_ORACLE does not exist.');
END IF;
@@ -170,7 +201,7 @@ DECLARE
'PACK_UTILS_FILE', 'PACK_ROARTVAI', 'RTVAI_AGENTI', 'RTVAI_ISTORIC',
'FF_SUME', 'FF_PERSINTRET', 'VANZARI_DETALII_TAB', 'PIVOT_TABLE',
'PIVOT_ROW', 'TABINCHIDERETVA', 'TABELAVALORITAGURI',
'RANDINCHIDERETVA', 'SERVER_INFO'
'RANDINCHIDERETVA', 'SERVER_INFO', 'EXECUTESCRIPTOS'
)
OR synonym_name LIKE 'SYN_%');
v_count NUMBER := 0;
@@ -344,10 +375,100 @@ PROMPT
PROMPT Tablespace ROA:
SELECT tablespace_name, status FROM dba_tablespaces WHERE tablespace_name = 'ROA';
PROMPT
PROMPT ============================================================
PROMPT ROA UNINSTALL COMPLETE
PROMPT ============================================================
PROMPT
PROMPT Database is now clean. You can re-run the setup scripts.
PROMPT
-- ============================================================================
-- VERDICT: verificare autoritara, cu cod de iesire
-- ============================================================================
-- Toate sectiunile de mai sus prind exceptiile in WHEN OTHERS si doar scriu in
-- DBMS_OUTPUT, ca sa nu opreasca dezinstalarea la primul obstacol. Consecinta:
-- scriptul se termina "cu succes" chiar daca un user a supravietuit, iar
-- instalarea urmatoare pica in lant cu ORA-31684 ... already exists.
-- Blocul asta numara ce a ramas si iese cu cod de eroare daca nu e curat.
-- Pas 1: raportarea (nu poate pica scriptul, deci output-ul ajunge pe ecran).
DECLARE
v_users NUMBER := 0;
v_contafin NUMBER := 0;
v_sysobj NUMBER := 0;
v_syn NUMBER := 0;
v_tbs NUMBER := 0;
v_total NUMBER := 0;
v_msg VARCHAR2(4000) := '';
BEGIN
SELECT COUNT(*) INTO v_users
FROM dba_users
WHERE default_tablespace = 'ROA'
AND username <> 'CONTAFIN_ORACLE';
SELECT COUNT(*) INTO v_contafin
FROM dba_users WHERE username = 'CONTAFIN_ORACLE';
SELECT COUNT(*) INTO v_sysobj
FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN (
'AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'EXECUTESCRIPTOS', 'NEWSCHEMA', 'NEWSCHEMAJOB', 'UPDATESQLPLUS',
'PINFO', 'INFO', 'SEQ_AUTH_SERII');
SELECT COUNT(*) INTO v_syn
FROM dba_synonyms
WHERE owner = 'PUBLIC' AND table_owner = 'CONTAFIN_ORACLE';
SELECT COUNT(*) INTO v_tbs
FROM dba_tablespaces WHERE tablespace_name = 'ROA';
IF v_users > 0 THEN v_msg := v_msg || v_users || ' user(i) de firma; '; END IF;
IF v_contafin > 0 THEN v_msg := v_msg || 'CONTAFIN_ORACLE; '; END IF;
IF v_sysobj > 0 THEN v_msg := v_msg || v_sysobj || ' obiecte SYS; '; END IF;
IF v_syn > 0 THEN v_msg := v_msg || v_syn || ' sinonime publice; '; END IF;
IF v_tbs > 0 THEN v_msg := v_msg || 'tablespace ROA; '; END IF;
v_total := v_users + v_contafin + v_sysobj + v_syn + v_tbs;
IF v_total = 0 THEN
DBMS_OUTPUT.PUT_LINE('============================================================');
DBMS_OUTPUT.PUT_LINE(' ROA UNINSTALL COMPLETE');
DBMS_OUTPUT.PUT_LINE('============================================================');
DBMS_OUTPUT.PUT_LINE('Baza este curata. Poti relua scripturile de instalare.');
ELSE
DBMS_OUTPUT.PUT_LINE('============================================================');
DBMS_OUTPUT.PUT_LINE(' ROA UNINSTALL INCOMPLET');
DBMS_OUTPUT.PUT_LINE('============================================================');
DBMS_OUTPUT.PUT_LINE('Au ramas: ' || RTRIM(v_msg, '; '));
DBMS_OUTPUT.PUT_LINE('Cauza uzuala: o sesiune activa tinea userul ocupat.');
DBMS_OUTPUT.PUT_LINE('Inchide aplicatia ROA / sesiunile sqlplus si ruleaza din nou.');
DBMS_OUTPUT.PUT_LINE('NU porni instalarea acum - pasul 05 va da ORA-31684 in lant.');
END IF;
END;
/
-- Pas 2: verdictul propriu-zis. Recalculeaza acelasi total si iese cu cod de
-- eroare daca nu e zero. Diagnosticul detaliat e deja tiparit mai sus.
WHENEVER SQLERROR EXIT FAILURE
DECLARE
v_total NUMBER;
BEGIN
SELECT (SELECT COUNT(*) FROM dba_users
WHERE default_tablespace = 'ROA' AND username <> 'CONTAFIN_ORACLE')
+ (SELECT COUNT(*) FROM dba_users WHERE username = 'CONTAFIN_ORACLE')
+ (SELECT COUNT(*) FROM dba_objects
WHERE owner = 'SYS'
AND object_name IN (
'AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
'EXECUTESCRIPTOS', 'NEWSCHEMA', 'NEWSCHEMAJOB', 'UPDATESQLPLUS',
'PINFO', 'INFO', 'SEQ_AUTH_SERII'))
+ (SELECT COUNT(*) FROM dba_synonyms
WHERE owner = 'PUBLIC' AND table_owner = 'CONTAFIN_ORACLE')
+ (SELECT COUNT(*) FROM dba_tablespaces WHERE tablespace_name = 'ROA')
INTO v_total
FROM dual;
IF v_total > 0 THEN
RAISE_APPLICATION_ERROR(-20900,
'ROA UNINSTALL INCOMPLET - au ramas ' || v_total ||
' obiect(e). Vezi raportul de mai sus.');
END IF;
END;
/
EXIT SUCCESS

View File

@@ -0,0 +1,459 @@
#Requires -Version 5.1
<#
.SYNOPSIS
Construieste kitul de instalare ROA pentru un client: DMP-urile sablon
exportate din LXC 108 + scripturile de instalare/migrare, intr-un singur
director gata de copiat pe serverul clientului.
.DESCRIPTION
Ce face, in ordine:
1. Ruleaza exportul pe LXC 108 (`export-roa2.sh`, acelasi script folosit
de `export-roa2.ps1`). Sursa e PDB-ul ROA2, nu ROA - ROA e instanta
de productie ROA_CENTRAL si nu se scrie in ea.
2. Aduce arhivele .tar.gz pe statia locala. Sunt trei niveluri:
container Docker -> LXC 108 -> host pvemini -> statia ta. `docker cp`
te scoate doar din container, de aceea e nevoie si de `pct pull`.
3. Despacheteaza si redenumeste DMP-urile la numele pe care le asteapta
scripturile: `contafin_oracle.dmp` si `FIRMANOUA.dmp`.
4. Citeste logul expdp si raporteaza cate firme are NOM_FIRME in dump.
Asa vezi daca ai construit un sablon curat sau ai prins din greseala
datele unui client.
5. Copiaza peste ele continutul din `roa-windows-setup/`.
Rezultatul e un director care se dezarhiveaza la client si se ruleaza cu
`INSTALEAZA.cmd curat` sau `INSTALEAZA.cmd migrare`.
.PARAMETER OracleVersion
Sursa exportului: '21' (PDB ROA2, VERSION=19) sau '18' (container
oracle18-xe, VERSION=11.2, pentru baze mai vechi). Implicit '21'.
.PARAMETER OutputDir
Directorul parinte in care se creeaza kitul. Implicit E:\backups\roa-kit.
.PARAMETER KitName
Numele directorului de kit. Implicit roa-kit-<data>.
.PARAMETER SkipExport
Nu ruleaza export nou; foloseste cele mai recente arhive deja prezente pe
LXC 108. Util cand ai exportat deja si vrei doar sa reconstruiesti kitul.
.PARAMETER Zip
Creeaza si o arhiva .zip a kitului, langa director.
.PARAMETER PushTo
Optional, destinatie scp pentru kit dupa constructie, in forma
`utilizator@gazda:/cale`. Se trimite directorul intreg, recursiv.
.EXAMPLE
.\build-client-kit.ps1
Export nou din ROA2 si kit in E:\backups\roa-kit\roa-kit-<data>.
.EXAMPLE
.\build-client-kit.ps1 -Zip -KitName "roa-kit-clientX"
Kit cu nume fix, plus arhiva .zip de trimis clientului.
.EXAMPLE
.\build-client-kit.ps1 -SkipExport -PushTo "romfast@10.0.20.130:C:/roa-kit"
Refoloseste ultimele arhive si trimite kitul direct pe serverul tinta.
.NOTES
Necesita ssh/scp (OpenSSH din Windows 10+) si tar (bsdtar, tot din Windows).
Acces cu cheie la host-ul Proxmox - vezi docs/acces-ssh-chei-angajati.md.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $false)]
[ValidateSet('21', '18')]
[string]$OracleVersion = '21',
[Parameter(Mandatory = $false)]
[string]$OutputDir = 'E:\backups\roa-kit',
[Parameter(Mandatory = $false)]
[string]$KitName,
[Parameter(Mandatory = $false)]
[switch]$SkipExport,
[Parameter(Mandatory = $false)]
[switch]$Zip,
[Parameter(Mandatory = $false)]
[string]$PushTo,
[Parameter(Mandatory = $false)]
[string]$ProxmoxHost = 'root@10.0.20.201',
[Parameter(Mandatory = $false)]
[int]$Ctid = 108
)
$ErrorActionPreference = 'Stop'
# Schemele exportate si numele sub care ajung in kit. FIRMANOUA.dmp trebuie sa
# aiba exact numele asta: SYS.NEWSCHEMA il compune ca <schema-sursa> || '.dmp'.
$SchemaMap = [ordered]@{
'CONTAFIN_ORACLE' = 'contafin_oracle.dmp'
'FIRMANOUA' = 'FIRMANOUA.dmp'
}
if ($OracleVersion -eq '18') {
$Container = 'oracle18-xe'
$RemoteDmpDir = '/opt/oracle18/oradata/dmpdir'
$SourceLabel = 'Oracle 18c (XEPDB1), VERSION=11.2'
}
else {
$Container = 'oracle-xe'
$RemoteDmpDir = '/opt/oracle/oradata/dmpdir'
$SourceLabel = 'Oracle 21c (PDB ROA2), VERSION=19'
}
function Write-Step { param([string]$m) Write-Host "`n=== $m ===" -ForegroundColor Cyan }
function Write-Ok { param([string]$m) Write-Host " [OK] $m" -ForegroundColor Green }
function Write-Info { param([string]$m) Write-Host " $m" }
function Write-Warn { param([string]$m) Write-Host " [ATENTIE] $m" -ForegroundColor Yellow }
function Invoke-Remote {
<# Ruleaza o comanda pe host-ul Proxmox si intoarce iesirea.
Opreste scriptul daca ssh iese cu cod nenul. #>
param(
[Parameter(Mandatory = $true)][string]$Command,
[switch]$AllowFailure
)
# Fara "2>&1": in Windows PowerShell 5.1 redirectarea stderr-ului unei
# comenzi native impacheteaza fiecare linie intr-un ErrorRecord, iar
# mesajul de eroare devine "System.Management.Automation.RemoteException".
# Lasam stderr sa curga direct in consola si ne bazam pe codul de iesire.
$out = & ssh -o BatchMode=yes $ProxmoxHost $Command
if ($LASTEXITCODE -ne 0 -and -not $AllowFailure) {
throw "Comanda pe $ProxmoxHost a esuat (cod $LASTEXITCODE): $Command"
}
return $out
}
# =============================================================================
# 0. Validari locale
# =============================================================================
Write-Step "Verificari initiale"
$SetupDir = Join-Path (Split-Path $PSScriptRoot -Parent) 'roa-windows-setup'
if (-not (Test-Path $SetupDir -PathType Container)) {
throw "Nu gasesc directorul cu scripturile de instalare: $SetupDir"
}
$InstallCmd = Join-Path $SetupDir 'INSTALEAZA.cmd'
if (-not (Test-Path $InstallCmd)) {
throw "Nu gasesc $InstallCmd - kitul ar fi inutilizabil fara el."
}
Write-Ok "Scripturi de instalare: $SetupDir"
foreach ($tool in @('ssh', 'scp', 'tar')) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) {
throw "Lipseste '$tool' din PATH. Pe Windows 10+ vine cu OpenSSH / bsdtar."
}
}
Write-Ok "ssh, scp, tar disponibile"
if (-not $KitName) {
$KitName = "roa-kit-$(Get-Date -Format 'yyyyMMdd_HHmmss')"
}
$KitDir = Join-Path $OutputDir $KitName
if (Test-Path $KitDir) {
throw "Directorul $KitDir exista deja. Sterge-l sau foloseste alt -KitName."
}
$Staging = Join-Path ([System.IO.Path]::GetTempPath()) "roa-kit-staging-$([System.Guid]::NewGuid().ToString('N').Substring(0,8))"
New-Item -ItemType Directory -Path $Staging -Force | Out-Null
try {
# =========================================================================
# 1. Starea LXC 108 si a containerului Oracle
# =========================================================================
Write-Step "Starea LXC $Ctid si a containerului $Container"
$lxcStatus = Invoke-Remote "pct status $Ctid"
if ($lxcStatus -notmatch 'running') {
throw "LXC $Ctid nu ruleaza ($lxcStatus). Porneste-l cu: ssh $ProxmoxHost `"pct start $Ctid`""
}
Write-Ok "LXC $Ctid ruleaza"
$running = Invoke-Remote "pct exec $Ctid -- docker ps --format '{{.Names}}'"
if ($running -notcontains $Container) {
throw "Containerul $Container nu ruleaza in LXC $Ctid. Porneste-l cu: ssh $ProxmoxHost `"pct exec $Ctid -- docker start $Container`" si asteapta ~60s."
}
Write-Ok "Containerul $Container ruleaza"
Write-Info "Sursa exportului: $SourceLabel"
# =========================================================================
# 2. Exportul
# =========================================================================
if ($SkipExport) {
Write-Step "Export sarit (-SkipExport) - folosesc arhivele existente"
}
else {
Write-Step "Export din $SourceLabel"
Write-Info "Dureaza cateva minute. Ruleaza export-roa2.sh pe LXC $Ctid..."
$exportOut = Invoke-Remote "pct exec $Ctid -- bash /opt/oracle/oradata/export-roa2.sh $OracleVersion"
$exportOut | Where-Object { $_ -match 'EROARE|ORA-|successfully completed|elapsed' } |
ForEach-Object { Write-Info $_ }
Write-Ok "Export terminat"
}
# =========================================================================
# 3. Aducerea arhivelor: container -> LXC -> host -> statie
# =========================================================================
Write-Step "Aduc arhivele pe statia locala"
$archives = @{}
foreach ($schema in $SchemaMap.Keys) {
$newest = (Invoke-Remote "pct exec $Ctid -- bash -c 'ls -t $RemoteDmpDir/${schema}*.tar.gz 2>/dev/null | head -1'" | Select-Object -First 1)
if ([string]::IsNullOrWhiteSpace($newest)) {
throw "Nu am gasit nicio arhiva ${schema}*.tar.gz in $RemoteDmpDir. Ruleaza fara -SkipExport."
}
$newest = $newest.Trim()
$leaf = Split-Path $newest -Leaf
# pct pull scoate fisierul din LXC pe host-ul Proxmox; scp il aduce mai
# departe. Fara pct pull, scp ar citi de pe host, unde nu exista nimic.
Invoke-Remote "pct pull $Ctid $newest /tmp/$leaf" | Out-Null
& scp -o BatchMode=yes "${ProxmoxHost}:/tmp/$leaf" (Join-Path $Staging $leaf) | Out-Null
if ($LASTEXITCODE -ne 0) { throw "scp a esuat pentru $leaf" }
Invoke-Remote "rm -f /tmp/$leaf" -AllowFailure | Out-Null
$localArchive = Join-Path $Staging $leaf
$sizeMb = [math]::Round((Get-Item $localArchive).Length / 1MB, 1)
Write-Ok "$leaf ($sizeMb MB)"
$archives[$schema] = $localArchive
}
# =========================================================================
# 4. Despachetare, redenumire, verificarea continutului
# =========================================================================
Write-Step "Despachetez si verific"
$KitDmpDir = Join-Path $KitDir 'DMPDIR'
New-Item -ItemType Directory -Path $KitDmpDir -Force | Out-Null
$nomFirmeRows = $null
foreach ($schema in $SchemaMap.Keys) {
$extractDir = Join-Path $Staging "x_$schema"
New-Item -ItemType Directory -Path $extractDir -Force | Out-Null
& tar -xzf $archives[$schema] -C $extractDir | Out-Null
if ($LASTEXITCODE -ne 0) { throw "tar a esuat la despachetarea $($archives[$schema])" }
$dmp = Get-ChildItem -Path $extractDir -Filter '*.dmp' -File | Select-Object -First 1
if (-not $dmp) { throw "Arhiva pentru $schema nu contine niciun fisier .dmp" }
$target = Join-Path $KitDmpDir $SchemaMap[$schema]
Copy-Item -Path $dmp.FullName -Destination $target -Force
$sizeMb = [math]::Round((Get-Item $target).Length / 1MB, 1)
Write-Ok "$($SchemaMap[$schema]) ($sizeMb MB)"
# Logul expdp spune exact cate randuri are fiecare tabela. Pentru
# CONTAFIN_ORACLE, NOM_FIRME e indicatorul care separa un sablon curat
# de datele unui client.
$log = Get-ChildItem -Path $extractDir -Filter '*.log' -File | Select-Object -First 1
if ($log -and $schema -eq 'CONTAFIN_ORACLE') {
$m = Select-String -Path $log.FullName -Pattern '"NOM_FIRME"\s+\S+\s+\S+\s+(\d+)\s+rows' |
Select-Object -First 1
if ($m) { $nomFirmeRows = [int]$m.Matches[0].Groups[1].Value }
}
}
if ($null -eq $nomFirmeRows) {
Write-Warn "Nu am putut citi numarul de firme din logul expdp. Verifica manual continutul lui NOM_FIRME."
}
elseif ($nomFirmeRows -le 5) {
Write-Ok "NOM_FIRME: $nomFirmeRows randuri - sablon curat, potrivit pentru instalare pe curat"
}
else {
Write-Warn "NOM_FIRME are $nomFirmeRows randuri - NU e un sablon curat!"
Write-Warn "Dump-ul contine firmele unei baze reale. Nu-l trimite altui client."
}
# =========================================================================
# 5. Scripturile de instalare
# =========================================================================
Write-Step "Copiez scripturile de instalare"
# Kitul are structura lui roa-windows-setup direct in radacina, plus DMPDIR:
# Run.cmd si INSTALEAZA.cmd se bazeaza pe %~dp0scripts, deci trebuie sa fie
# la acelasi nivel cu scripts\.
$excludeNames = @('logs', 'test')
# Gunoiul din working tree nu are ce cauta la client. *.dmp e exclus ca
# masura de siguranta: daca cineva a lasat dump-ul unui client in
# roa-windows-setup, nu vrem sa plece mai departe.
$excludePatterns = @('*.stackdump', '*.zip', '*.dmp', '*.log', 'config.ps1')
Get-ChildItem -Path $SetupDir -Force | Where-Object {
$item = $_
($excludeNames -notcontains $item.Name) -and
(-not ($excludePatterns | Where-Object { $item.Name -like $_ }))
} | ForEach-Object {
Copy-Item -Path $_.FullName -Destination $KitDir -Recurse -Force
}
# Acelasi filtru, aplicat si in subdirectoare (config.ps1 poate contine
# parolele altui client, logurile pot contine nume de firme).
# DMPDIR e scutit: acolo tocmai am pus sabloanele, iar '*.dmp' e in lista de
# excluderi. Fara filtrul asta, pasul de curatare isi sterge propriul rezultat.
foreach ($pat in $excludePatterns) {
Get-ChildItem -Path $KitDir -Filter $pat -Recurse -File -Force -ErrorAction SilentlyContinue |
Where-Object { $_.DirectoryName -ne $KitDmpDir } |
Remove-Item -Force -ErrorAction SilentlyContinue
}
New-Item -ItemType Directory -Path (Join-Path $KitDir 'logs') -Force | Out-Null
# Plasa de siguranta: in kit au voie exact cele doua sabloane, nimic altceva.
$strayDmp = Get-ChildItem -Path $KitDir -Filter '*.dmp' -Recurse -File |
Where-Object { $_.DirectoryName -ne $KitDmpDir }
if ($strayDmp) {
throw "Fisiere .dmp neasteptate in kit, in afara DMPDIR: $($strayDmp.FullName -join ', ')"
}
# ...si invers: sabloanele TREBUIE sa fie acolo. Verificarea asta prinde
# orice pas ulterior care le-ar sterge din greseala.
foreach ($expected in $SchemaMap.Values) {
$p = Join-Path $KitDmpDir $expected
if (-not (Test-Path $p)) {
throw "Lipseste $expected din kit - constructia e incompleta."
}
if ((Get-Item $p).Length -lt 1MB) {
throw "$expected are sub 1 MB - fisier trunchiat sau gresit."
}
}
$copied = (Get-ChildItem -Path $KitDir -Recurse -File).Count
Write-Ok "$copied fisiere in kit"
# =========================================================================
# 6. Instructiunile
# =========================================================================
$sursa = if ($SkipExport) { "$SourceLabel (arhive existente, neexportate acum)" } else { $SourceLabel }
$firme = if ($null -ne $nomFirmeRows) { "$nomFirmeRows" } else { "necunoscut" }
$citeste = @"
KIT DE INSTALARE ROA ORACLE
===========================
Construit: $(Get-Date -Format 'yyyy-MM-dd HH:mm')
Sursa DMP-urilor: $sursa
Firme in NOM_FIRME din contafin_oracle.dmp: $firme
CE E IN KIT
-----------
DMPDIR\contafin_oracle.dmp schema comuna (drepturi, actualizari, NOM_FIRME)
DMPDIR\FIRMANOUA.dmp sablon de firma goala
scripts\, sql\, config\ scripturile de instalare
INSTALEAZA.cmd ruleaza toti pasii, in ordine
README.md documentatia completa
CUM SE INSTALEAZA
-----------------
Inainte de orice: instaleaza Oracle 21c XE pe server (docs\00-INSTALL-ORACLE-XE.md),
cu parola SYS/SYSTEM 'romfastsoft'. Apoi, din radacina kitului:
A. CLIENT NOU, fara firme anterioare:
INSTALEAZA.cmd curat <IdClient> [ServerSMTP]
Prima firma se creeaza DUPA aceea, DIN APLICATIA ROA - nu din scripturi.
Aplicatia scrie firma in CONTAFIN_ORACLE.NOM_FIRME si apeleaza
SYS.NEWSCHEMA, care ii importa structura din FIRMANOUA.dmp.
B. MIGRARE de pe un Oracle mai vechi:
1. Inlocuieste DMPDIR\contafin_oracle.dmp cu cel exportat de la client
(cel din kit are NOM_FIRME goala).
2. Pune in DMPDIR si cate un .dmp per firma a clientului.
3. LASA FIRMANOUA.dmp pe loc - nu vine de la client, dar e obligatoriu.
4. INSTALEAZA.cmd migrare <IdClient> [ServerSMTP]
Instalarea e gata cand ultimul pas (07-verify-installation) iese cu codul 0.
DE STIUT
--------
- FIRMANOUA.dmp ramane in C:\DMPDIR si dupa instalare. E folosit la fiecare
firma noua, oricand pe viitor. Daca il stergi, adaugarea de firme va esua
cu o eroare in DBMS_DATAPUMP.ADD_FILE.
- Pasul 03 (import contafin) iese cu codul 5 si asta e NORMAL: e codul Data
Pump pentru "completed with errors", din ORA-31684 (userul exista deja,
creat de pasul 01) si ORA-39082 (warning-uri de compilare, rezolvate la
pasul 04). INSTALEAZA.cmd il trateaza corect.
- Conectarea se face la serviciul XEPDB1, niciodata la XE (CDB root).
- Daca reiei instalarea de la zero: scripts\99-uninstall-roa.ps1 trebuie sa
iasa cu codul 0. Orice alt cod inseamna ca au ramas obiecte in baza (uzual
o sesiune activa tinea userul ocupat) - nu porni instalarea peste ele.
- Logurile fiecarui pas sunt in logs\.
"@
Set-Content -Path (Join-Path $KitDir 'CITESTE-MA.txt') -Value $citeste -Encoding UTF8
# =========================================================================
# 7. Arhivare si livrare
# =========================================================================
$zipPath = $null
if ($Zip) {
Write-Step "Creez arhiva .zip"
$zipPath = Join-Path $OutputDir "$KitName.zip"
if (Test-Path $zipPath) { Remove-Item $zipPath -Force }
Compress-Archive -Path (Join-Path $KitDir '*') -DestinationPath $zipPath -CompressionLevel Optimal
$zipMb = [math]::Round((Get-Item $zipPath).Length / 1MB, 1)
Write-Ok "$zipPath ($zipMb MB)"
}
if ($PushTo) {
Write-Step "Trimit kitul catre $PushTo"
& scp -o BatchMode=yes -r $KitDir $PushTo | Out-Null
if ($LASTEXITCODE -ne 0) { throw "scp catre $PushTo a esuat (cod $LASTEXITCODE)" }
Write-Ok "Kit trimis"
}
# =========================================================================
# 8. Sumar
# =========================================================================
$totalMb = [math]::Round(((Get-ChildItem -Path $KitDir -Recurse -File | Measure-Object Length -Sum).Sum) / 1MB, 1)
Write-Host ""
Write-Host "============================================================" -ForegroundColor Green
Write-Host " KIT GATA" -ForegroundColor Green
Write-Host "============================================================" -ForegroundColor Green
Write-Host ""
Write-Host " Director: $KitDir"
if ($zipPath) { Write-Host " Arhiva: $zipPath" }
Write-Host " Marime: $totalMb MB"
Write-Host " NOM_FIRME: $firme randuri in contafin_oracle.dmp"
Write-Host ""
Write-Host " La client, din radacina kitului:"
Write-Host " INSTALEAZA.cmd curat <IdClient> (client nou)" -ForegroundColor Cyan
Write-Host " INSTALEAZA.cmd migrare <IdClient> (are date existente)" -ForegroundColor Cyan
Write-Host ""
Write-Host " Detalii complete: $KitDir\CITESTE-MA.txt"
Write-Host ""
}
catch {
Write-Host ""
Write-Host "[EROARE] $_" -ForegroundColor Red
if (Test-Path $KitDir) {
Write-Host "[INFO] Kit incomplet la $KitDir - sterge-l inainte de a relua." -ForegroundColor Yellow
}
exit 1
}
finally {
if (Test-Path $Staging) {
Remove-Item -Path $Staging -Recurse -Force -ErrorAction SilentlyContinue
}
}

View File

@@ -163,6 +163,62 @@ C:\roa-setup\
---
### Capcane de mediu (verificate 2026-08-25)
**1. VM-ul își poate pierde IP-ul static la boot.** La pornirea din 2026-08-25 adaptorul
s-a re-enumerat ca `Ethernet 2` și a venit pe DHCP (`10.0.20.118`). `listener.ora` are
`HOST=10.0.20.130` scris în clar, deci serviciul listener pornește („Running") dar nu
leagă portul, iar orice conectare dă `ORA-12541: TNS:no listener`. Verifică IP-ul
**înainte** de a începe testul:
```bash
ssh root@10.0.20.201 "qm agent 302 network-get-interfaces" | grep ip-address
```
Dacă nu e `10.0.20.130`, restaurează-l (comanda rupe sesiunea SSH curentă, de aceea
rulează printr-un task programat):
```powershell
Set-NetIPInterface -InterfaceAlias 'Ethernet 2' -Dhcp Disabled
Get-NetIPAddress -InterfaceAlias 'Ethernet 2' -AddressFamily IPv4 | Remove-NetIPAddress -Confirm:$false
New-NetIPAddress -InterfaceAlias 'Ethernet 2' -IPAddress 10.0.20.130 -PrefixLength 24 -DefaultGateway 10.0.20.1
Set-DnsClientServerAddress -InterfaceAlias 'Ethernet 2' -ServerAddresses 10.0.20.1
```
Apoi `Restart-Service OracleOraDB21Home1TNSListener`. Listener-ul mai are nevoie de
~60 s ca instanța să se înregistreze (PMON), altfel primești `ORA-12514`.
**2. `C:\roa-setup\` este o copie, nu un clone al repo-ului.** La 2026-08-25 era în urmă
cu două commit-uri (`sys-objects.sql`, `scheduler-jobs.sql`, `uninstall-roa.sql` erau
dinainte de `015cd79`). Sincronizează **tot** directorul, nu doar fișierele pe care
crezi că le-ai atins, și confirmă cu hash-uri:
```bash
cd proxmox/lxc108-oracle/roa-windows-setup
scp sql/*.sql romfast@10.0.20.130:C:/roa-setup/sql/
scp scripts/*.ps1 romfast@10.0.20.130:C:/roa-setup/scripts/
scp scripts/lib/*.ps1 romfast@10.0.20.130:C:/roa-setup/scripts/lib/
scp Run.cmd RunAll.cmd romfast@10.0.20.130:C:/roa-setup/
```
**3. `RunAll.cmd` nu poate fi condus neinteractiv.** Folosește `set /p` pentru
confirmări; pe stdin redirecționat (`< NUL` sau prin `ssh`) fie se anulează cu
„Installation cancelled" **și iese cu codul 0**, fie crapă cu „The syntax of the command
is incorrect". Nu te lua după codul de ieșire — verifică logul. Pentru rulare automată,
apelează scripturile în ordine direct:
```
01-setup-database.ps1 → 02-create-sys-objects.ps1 → 03-import-contafin.ps1
→ 04-create-synonyms-grants.ps1 → 05-import-companies.ps1
→ 08-post-install-config.ps1 → 07-verify-installation.ps1
```
**4. `03-import-contafin.ps1` iese normal cu codul 5.** E codul Data Pump pentru
„completat cu erori"; erorile sunt `ORA-31684 already exists` (userul e creat de scriptul
01) și `ORA-39082` (warning-uri de compilare). Nu e un eșec.
---
## Testing Workflow
### Full Installation Test