<# Genereaza fisierul .sql de deschidere firma (sablon PACK_DREPTURI.FIRMEMODINSPROC pe ConPress) pornind de la interogarea publica ANAF (sursa de adevar pentru denumire/adresa/CAEN/data inregistrare -- NU certificatul ONRC, care poate avea erori de OCR/transcriere). Nu scrie nimic in Oracle. Genereaza doar un fisier .sql (cu Pasii 1/2/4 tot comentati, ca in sablon) plecand de la schita existenta. Pasul 0 (SELECT) poate fi rulat optional daca se dau parametrii de conexiune -- tunelul si credentialele raman responsabilitatea lui Marius. Exemplu minimal: .\deschide_firma_conpress.ps1 -Cui 54602536 Exemplu cu parametri suplimentari (banca, drepturi): .\deschide_firma_conpress.ps1 -Cui 54602536 -Banca1 'BANCA X' -Contb1 'RO00XXXX...' ` -IdUtil 5 -IdGrupUseri 3 -IdUtilOp 5 -NumeUser1 Iliescu -PrenumeUser1 Vali ` -NumeUser2 Ion -PrenumeUser2 Raluca #> [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Cui, [datetime]$DataVerificare = (Get-Date), [int]$LunaStart = 5, [int]$AnStart = 2026, [string]$TemplateSql = '', [string]$OutSql = '', # --- date pe care ANAF nu le are: parametri optionali, implicit goale ("DE COMPLETAT") --- [string]$Antet = '', [string]$Banca1 = '', [string]$Contb1 = '', [string]$Codang = '', [string]$Nume = '', [string]$Prenume = '', [string]$Telefon2 = '', [string]$Telefon3 = '', [string]$Fax = '', [string]$Email = '', [string]$Oasp = '', [string]$CapitalSocVar = '', [string]$CapitalSocSub = '', [string]$PunctLuc = '', [string]$Schema = '', [string]$IdMama = '0', [string]$EMama = '', [string]$IdLoc = '', [string]$IdUtil = '', [string]$IdFormaJuridica = '', [string]$IdFormaOrganizare = '', [string]$IdFormaProp = '', [string]$IdTipSoc = '', [string]$Indicativ = '', [string]$Declarant = '', [string]$Functie = '', [string]$IndiceItm = '', [string]$TipModificare = '', [string]$CodFirma = '', [string]$NumeUser1 = '', [string]$PrenumeUser1 = '', [string]$NumeUser2 = '', [string]$PrenumeUser2 = '', [string]$IdGrupUseri = '', [string]$IdUtilOp = '', # --- Pasul 0 (SELECT) optional -- doar daca se dau explicit parametrii de conexiune --- [string]$TnsAlias = 'ROA_CONPRESS', [string]$DbUser = '', [securestring]$DbPassword, [switch]$RunPas0, [string]$SqlplusPath = 'D:\ROA\instantclient_19_18\sqlplus.exe', [string]$TnsAdmin = 'D:\ROA\instantclient_19_18' ) $ErrorActionPreference = 'Stop' function Write-Utf8NoBom { # sqlplus se poticneste pe BOM (SP2-0734) chiar rulat cu @fisier - scrie fara BOM explicit param([string]$Path, [string[]]$Lines) [System.IO.File]::WriteAllText($Path, ($Lines -join "`r`n") + "`r`n", (New-Object Text.UTF8Encoding($false))) } $ScriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Split-Path -Parent $MyInvocation.MyCommand.Path } if (-not $TemplateSql) { $TemplateSql = Join-Path $ScriptDir 'schita_deschidere_firma_conpress.sql' } function ConvertTo-DataRo { param([string]$s) if ([string]::IsNullOrWhiteSpace($s)) { return '' } foreach ($fmt in @('dd.MM.yyyy', 'dd-MM-yyyy', 'yyyy-MM-dd')) { $d = [datetime]::MinValue if ([datetime]::TryParseExact($s, $fmt, [Globalization.CultureInfo]::InvariantCulture, [Globalization.DateTimeStyles]::None, [ref]$d)) { return $d.ToString('dd.MM.yyyy') } } return $s } function Get-DateAnaf { param([string]$Cui, [datetime]$Data) $cuiNum = ($Cui -replace '[^0-9]', '') if ([string]::IsNullOrEmpty($cuiNum)) { throw "CUI invalid: '$Cui'" } $dataStr = $Data.ToString('yyyy-MM-dd') # JSON construit manual (payload trivial) - evita capcana ConvertTo-Json care despacheteaza # array-uri de un singur element cand trece prin pipeline. $body = '[{"cui":' + $cuiNum + ',"data":"' + $dataStr + '"}]' $url = 'https://webservicesp.anaf.ro/api/PlatitorTvaRest/v9/tva' # acelasi URL folosit de ANAF_CreeazaCerereANAF, COMUN\programe\validare.prg:1845 # decodare explicita UTF-8 din raspuns (nu Invoke-RestMethod): serverul ANAF nu trimite # charset in Content-Type, PowerShell 5.1 ghiceste ISO-8859-1 si strica diacriticele - # acelasi motiv notat in validare.prg:1744 pentru clientul VFP. $req = [System.Net.WebRequest]::Create($url) $req.Method = 'POST' $req.ContentType = 'application/json; charset=utf-8' $bytesOut = [Text.Encoding]::UTF8.GetBytes($body) $req.ContentLength = $bytesOut.Length $reqStream = $req.GetRequestStream() $reqStream.Write($bytesOut, 0, $bytesOut.Length) $reqStream.Close() $webResp = $req.GetResponse() $reader = New-Object IO.StreamReader($webResp.GetResponseStream(), [Text.Encoding]::UTF8) $json = $reader.ReadToEnd() $reader.Close() $webResp.Close() return $json | ConvertFrom-Json } function Get-DetaliiAdresa { param([string]$Text) $r = [ordered]@{ Bloc = ''; Scara = ''; Apart = '' } if ([string]::IsNullOrWhiteSpace($Text)) { return $r } if ($Text -match '(?i)BL\.?\s*([A-Z0-9\-]+)') { $r.Bloc = $Matches[1] } if ($Text -match '(?i)SC\.?\s*([A-Z0-9\-]+)') { $r.Scara = $Matches[1] } if ($Text -match '(?i)AP\.?\s*([A-Z0-9\-]+)') { $r.Apart = $Matches[1] } return $r # ponytail: heuristica regex pe text liber ANAF (bl./sc./ap.), nu un parser de adrese complet; # de verificat manual daca formatul sediului difera (ex. "et." lipsa, abrevieri neuzuale). } # --------------------------------------------------------------------------- # 1. Interogare ANAF # --------------------------------------------------------------------------- Write-Host "Interogare ANAF pentru CUI $Cui (data verificare $($DataVerificare.ToString('yyyy-MM-dd')))..." $resp = Get-DateAnaf -Cui $Cui -Data $DataVerificare if (-not $resp.found -or $resp.found.Count -eq 0) { Write-Warning "ANAF nu a gasit CUI $Cui (cod=$($resp.cod), message=$($resp.message)). Nu se genereaza fisierul .sql." if ($resp.notFound) { Write-Warning "notFound: $($resp.notFound -join ', ')" } return } $item = $resp.found[0] $dg = $item.date_generale $adr = $item.adresa_sediu_social $tva = $item.inregistrare_scop_Tva # data_inregistrare (yyyy-MM-dd) e campul structurat; stare_inregistrare (text liber cu # data in dd.mm.yyyy) e fallback daca lipseste. $dataInregRaw = if ($dg.data_inregistrare) { [string]$dg.data_inregistrare } elseif ($dg.stare_inregistrare -match '(\d{2}\.\d{2}\.\d{4})') { $Matches[1] } else { '' } # bl./sc./et./ap. NU sunt in adresa_sediu_social.sdetalii_Adresa (acolo apare doar # "CAMERA n") - sunt in date_generale.adresa, campul text liber complet. $detalii = Get-DetaliiAdresa -Text $dg.adresa $anaf = [ordered]@{ p_firma = $dg.denumire p_reg_comert = $dg.nrRegCom p_caen = if ($dg.cod_CAEN) { [string]$dg.cod_CAEN } else { '' } p_data_inreg = ConvertTo-DataRo $dataInregRaw p_telefon = $dg.telefon p_judet = $adr.sdenumire_Judet p_localitate = $adr.sdenumire_Localitate p_strada = $adr.sdenumire_Strada p_numar = $adr.snumar_Strada p_cod_postal = $adr.scod_Postal p_bloc = $detalii.Bloc p_scara = $detalii.Scara p_apart = $detalii.Apart } $persoanaJuridica = if ($dg.forma_organizare -match '(?i)persoana\s*juridica') { 'D' } else { '' } # --------------------------------------------------------------------------- # 2. Restul parametrilor - din argumentele scriptului (ANAF nu le are) # --------------------------------------------------------------------------- $params = [ordered]@{ p_firma = @{ v = $anaf.p_firma; src = 'ANAF' } p_antet = @{ v = if ($Antet) { $Antet } else { $anaf.p_firma }; src = if ($Antet) { 'PARAM' } else { 'ANAF (= denumire)' } } p_cod_fiscal = @{ v = ($Cui -replace '[^0-9]', ''); src = 'PARAM (-Cui)' } p_reg_comert = @{ v = $anaf.p_reg_comert; src = 'ANAF' } p_caen = @{ v = $anaf.p_caen; src = 'ANAF' } p_data_inreg = @{ v = $anaf.p_data_inreg; src = 'ANAF (date_generale.data_inregistrare)' } p_judet = @{ v = $anaf.p_judet; src = 'ANAF' } p_localitate = @{ v = $anaf.p_localitate; src = 'ANAF' } p_strada = @{ v = $anaf.p_strada; src = 'ANAF' } p_numar = @{ v = $anaf.p_numar; src = 'ANAF' } p_bloc = @{ v = $anaf.p_bloc; src = 'ANAF (heuristica text liber, DE VERIFICAT)' } p_scara = @{ v = $anaf.p_scara; src = 'ANAF (heuristica text liber, DE VERIFICAT)' } p_apart = @{ v = $anaf.p_apart; src = 'ANAF (heuristica text liber, DE VERIFICAT)' } p_cod_postal = @{ v = $anaf.p_cod_postal; src = 'ANAF' } p_banca1 = @{ v = $Banca1; src = if ($Banca1) { 'PARAM' } else { 'DE COMPLETAT (ANAF nu da IBAN)' } } p_contb1 = @{ v = $Contb1; src = if ($Contb1) { 'PARAM' } else { 'DE COMPLETAT (ANAF nu da IBAN)' } } p_persoana_juridica = @{ v = $persoanaJuridica; src = 'ANAF (forma_organizare)' } p_codang = @{ v = $Codang; src = if ($Codang) { 'PARAM' } else { 'DE COMPLETAT' } } p_nume = @{ v = $Nume; src = if ($Nume) { 'PARAM' } else { 'DE COMPLETAT (reprezentant legal)' } } p_prenume = @{ v = $Prenume; src = if ($Prenume) { 'PARAM' } else { 'DE COMPLETAT' } } p_telefon = @{ v = $anaf.p_telefon; src = 'ANAF' } p_telefon2 = @{ v = $Telefon2; src = if ($Telefon2) { 'PARAM' } else { 'DE COMPLETAT' } } p_telefon3 = @{ v = $Telefon3; src = if ($Telefon3) { 'PARAM' } else { 'DE COMPLETAT' } } p_fax = @{ v = $Fax; src = if ($Fax) { 'PARAM' } else { 'DE COMPLETAT' } } p_email = @{ v = $Email; src = if ($Email) { 'PARAM' } else { 'DE COMPLETAT' } } p_oasp = @{ v = $Oasp; src = if ($Oasp) { 'PARAM' } else { 'DE COMPLETAT' } } p_capital_soc_var = @{ v = $CapitalSocVar; src = if ($CapitalSocVar) { 'PARAM' } else { 'DE COMPLETAT' } } p_capital_soc_sub = @{ v = $CapitalSocSub; src = if ($CapitalSocSub) { 'PARAM' } else { 'DE COMPLETAT' } } p_punct_luc = @{ v = $PunctLuc; src = if ($PunctLuc) { 'PARAM' } else { 'gol (fara punct de lucru declarat)' } } p_schema = @{ v = if ($Schema) { $Schema } else { $Cui }; src = if ($Schema) { 'PARAM' } else { 'DE CONFIRMAT (implicit = CUI, corecteaza cu -Schema)' } } p_id_mama = @{ v = $IdMama; src = 'PARAM (implicit 0 = firma simpla)' } p_e_mama = @{ v = $EMama; src = if ($EMama) { 'PARAM' } else { 'gol (relevant doar daca p_id_mama <> 0)' } } p_id_loc = @{ v = $IdLoc; src = if ($IdLoc) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_util = @{ v = $IdUtil; src = if ($IdUtil) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_forma_juridica = @{ v = $IdFormaJuridica; src = if ($IdFormaJuridica) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_forma_organizare = @{ v = $IdFormaOrganizare; src = if ($IdFormaOrganizare) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_forma_prop = @{ v = $IdFormaProp; src = if ($IdFormaProp) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_tip_soc = @{ v = $IdTipSoc; src = if ($IdTipSoc) { 'PARAM' } else { 'DE COMPLETAT' } } p_indicativ = @{ v = $Indicativ; src = if ($Indicativ) { 'PARAM' } else { 'DE COMPLETAT' } } p_declarant = @{ v = $Declarant; src = if ($Declarant) { 'PARAM' } else { 'DE COMPLETAT' } } p_functie = @{ v = $Functie; src = if ($Functie) { 'PARAM' } else { 'DE COMPLETAT' } } p_indice_itm = @{ v = $IndiceItm; src = if ($IndiceItm) { 'PARAM' } else { 'DE COMPLETAT' } } p_tip_modificare = @{ v = $TipModificare; src = if ($TipModificare) { 'PARAM' } else { 'DE COMPLETAT' } } p_cod_firma = @{ v = $CodFirma; src = if ($CodFirma) { 'PARAM' } else { 'DE COMPLETAT' } } p_luna_start = @{ v = [string]$LunaStart; src = 'PARAM (implicit 5)' } p_an_start = @{ v = [string]$AnStart; src = 'PARAM (implicit 2026)' } p_nume_user1 = @{ v = $NumeUser1; src = if ($NumeUser1) { 'PARAM' } else { 'DE COMPLETAT' } } p_prenume_user1 = @{ v = $PrenumeUser1; src = if ($PrenumeUser1) { 'PARAM' } else { 'DE COMPLETAT' } } p_nume_user2 = @{ v = $NumeUser2; src = if ($NumeUser2) { 'PARAM' } else { 'DE COMPLETAT' } } p_prenume_user2 = @{ v = $PrenumeUser2; src = if ($PrenumeUser2) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_grup_useri = @{ v = $IdGrupUseri; src = if ($IdGrupUseri) { 'PARAM' } else { 'DE COMPLETAT' } } p_id_utilop = @{ v = $IdUtilOp; src = if ($IdUtilOp) { 'PARAM' } else { 'DE COMPLETAT' } } } # adresa compusa, ca in sablon $params['p_adresa'] = @{ v = '&p_strada. nr. &p_numar., bl. &p_bloc., sc. &p_scara., et. Parter, ap. &p_apart.' src = 'derivat (sablon sqlplus, substituit din campurile de mai sus)' } # --------------------------------------------------------------------------- # 3. Genereaza blocul DEFINE si scrie fisierul .sql (Pas 0-4 din sablon, neschimbate) # --------------------------------------------------------------------------- if (-not (Test-Path -LiteralPath $TemplateSql)) { throw "Sablon lipsa: $TemplateSql" } $templateLines = Get-Content -LiteralPath $TemplateSql -Encoding UTF8 $startIdx = ($templateLines | Select-String -Pattern '^DEFINE p_firma\s*=').LineNumber $endIdx = ($templateLines | Select-String -Pattern '^DEFINE p_id_utilop\s*=').LineNumber if (-not $startIdx -or -not $endIdx) { throw "Sablonul '$TemplateSql' nu are markerii asteptati (DEFINE p_firma / DEFINE p_id_utilop) - format schimbat?" } $startIdx = $startIdx[0] - 1 $endIdx = $endIdx[0] - 1 $before = $templateLines[0..($startIdx - 1)] $after = $templateLines[($endIdx + 1)..($templateLines.Count - 1)] $newBlock = New-Object System.Collections.Generic.List[string] $newBlock.Add('-- ============================================================================') $newBlock.Add("-- PARAMETRI GENERATI AUTOMAT de deschide_firma_conpress.ps1") $newBlock.Add("-- Rulat: $(Get-Date -Format 'dd.MM.yyyy HH:mm') -- CUI interogat: $Cui -- data verificare ANAF: $($DataVerificare.ToString('dd.MM.yyyy'))") $newBlock.Add("-- Sursa adresa/denumire/CAEN/data inregistrare: ANAF (webservicesp.anaf.ro/api/PlatitorTvaRest/v9/tva),") $newBlock.Add("-- NU certificatul ONRC -- ANAF e sursa de adevar (posibil OCR gresit pe certificat).") $newBlock.Add("-- Fiecare linie e adnotata cu sursa valorii: ANAF / PARAM (dat la rulare) / DE COMPLETAT.") $newBlock.Add('-- ============================================================================') $newBlock.Add('') foreach ($key in $params.Keys) { $entry = $params[$key] $val = [string]$entry.v $line = "DEFINE $key".PadRight(30) + "= '$val' -- $($entry.src)" $newBlock.Add($line) } $newBlock.Add('') if (-not $OutSql) { $OutSql = Join-Path (Split-Path -Path $TemplateSql -Parent) "deschidere_firma_$($Cui)_$(Get-Date -Format 'yyyyMMdd_HHmmss').sql" } $outLines = $before + $newBlock + $after Write-Utf8NoBom -Path $OutSql -Lines $outLines Write-Host "Fisier generat: $OutSql" # --------------------------------------------------------------------------- # 4. Rezumat consola: ce a venit din ANAF vs ce a ramas gol # --------------------------------------------------------------------------- Write-Host '' Write-Host '=== Rezumat campuri ===' foreach ($key in $params.Keys) { $entry = $params[$key] $shown = if ([string]::IsNullOrWhiteSpace([string]$entry.v)) { '(gol)' } else { $entry.v } Write-Host ("{0,-24} {1,-45} [{2}]" -f $key, $shown, $entry.src) } # --------------------------------------------------------------------------- # 5. Pasul 0 (SELECT) optional -- doar daca s-au dat explicit parametrii de conexiune # --------------------------------------------------------------------------- if ($RunPas0) { if (-not $DbUser -or -not $DbPassword) { Write-Warning "RunPas0 cerut dar lipsesc -DbUser/-DbPassword. Tunelul/conexiunea raman responsabilitatea lui Marius -- se sare peste Pasul 0." } elseif (-not (Test-Path -LiteralPath $SqlplusPath)) { Write-Warning "sqlplus nu a fost gasit la '$SqlplusPath'. Se sare peste Pasul 0." } else { $pas0Start = ($after | Select-String -Pattern '^-- PAS 0 ').LineNumber $pas0End = ($after | Select-String -Pattern '^-- PAS 1 ').LineNumber if (-not $pas0Start -or -not $pas0End) { Write-Warning "Nu s-a gasit sectiunea PAS 0 in sablon. Se sare peste." } else { $pas0Lines = $after[($pas0Start[0] - 1)..($pas0End[0] - 2)] $tmpSql = [System.IO.Path]::GetTempFileName() -replace '\.tmp$', '.sql' Write-Utf8NoBom -Path $tmpSql -Lines ($newBlock + $pas0Lines) $bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($DbPassword) try { $plainPwd = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) $env:TNS_ADMIN = $TnsAdmin & $SqlplusPath -S -L "$DbUser/$plainPwd@$TnsAlias" "@$tmpSql" } finally { [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) $plainPwd = $null Remove-Item -LiteralPath $tmpSql -ErrorAction SilentlyContinue } } } }