Files
comun/docs/wip_firma-ludipedia-conpress/deschide_firma_conpress.ps1
2026-09-16 21:11:41 +03:00

310 lines
17 KiB
PowerShell

<#
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
}
}
}
}