Compare commits
5 Commits
da0fb555d7
...
8857e8fedf
| Author | SHA1 | Date | |
|---|---|---|---|
| 8857e8fedf | |||
| ce9ec394df | |||
| 5249670062 | |||
| da19090ed9 | |||
| 349130c369 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -92,6 +92,7 @@ Teste/uisync/
|
|||||||
Teste/screenshots/
|
Teste/screenshots/
|
||||||
Teste/_erori_test.txt
|
Teste/_erori_test.txt
|
||||||
Teste/*_log.txt
|
Teste/*_log.txt
|
||||||
|
Teste/raport_*.csv
|
||||||
|
|
||||||
# --- Cache text extern (inlocuit de fluxul in-arbore .??2) ---
|
# --- Cache text extern (inlocuit de fluxul in-arbore .??2) ---
|
||||||
_textcache/
|
_textcache/
|
||||||
|
|||||||
12
ALTE/check_cf_litere.ps1
Normal file
12
ALTE/check_cf_litere.ps1
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Ce coduri fiscale NENUMERICE apar in XML-urile Fidelio (posibili parteneri straini)
|
||||||
|
param([string]$Dir = "D:\PROIECTE\FLORA\FLORA2ROA\EXEMPLE\hotel")
|
||||||
|
$map = @{}
|
||||||
|
Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | ForEach-Object {
|
||||||
|
$t = Get-Content $_.FullName -Raw
|
||||||
|
foreach ($m in [regex]::Matches($t, '(?i)<CODFISCAL_CNP>([^<]*)</CODFISCAL_CNP>')) {
|
||||||
|
$v = $m.Groups[1].Value.Trim()
|
||||||
|
if ($v -ne '' -and $v -match '[A-Za-z]') { $map[$v] = 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"coduri cu litere = $($map.Count)"
|
||||||
|
$map.Keys | Sort-Object
|
||||||
50
ALTE/check_cnp.ps1
Normal file
50
ALTE/check_cnp.ps1
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Simulare a regulii GetCodFiscalValid pe TOATE codurile din XML-urile Fidelio.
|
||||||
|
# Raporteaza cate coduri se pastreaza, cate se sterg si cate sunt straine (nevalidate).
|
||||||
|
param([string]$Dir = "D:\PROIECTE\FLORA\FLORA2ROA\EXEMPLE\hotel")
|
||||||
|
|
||||||
|
function Test-CNP([string]$c) {
|
||||||
|
if ($c -notmatch '^\d{13}$') { return $false }
|
||||||
|
$w = @(2,7,9,1,4,6,3,5,8,2,7,9); $s = 0
|
||||||
|
for ($i = 0; $i -lt 12; $i++) { $s += [int]::Parse($c[$i]) * $w[$i] }
|
||||||
|
$r = $s % 11; if ($r -eq 10) { $r = 1 }
|
||||||
|
return ($r -eq [int]::Parse($c[12]))
|
||||||
|
}
|
||||||
|
function Test-CUI([string]$c) {
|
||||||
|
if ($c -notmatch '^\d{2,10}$') { return $false }
|
||||||
|
$c = $c.PadLeft(10, '0'); $k = '7532175321'; $s = 0
|
||||||
|
for ($i = 0; $i -lt 9; $i++) { $s += [int]::Parse($c[$i]) * [int]::Parse($k[$i]) }
|
||||||
|
$r = ($s * 10) % 11; if ($r -eq 10) { $r = 0 }
|
||||||
|
return ($r -eq [int]::Parse($c[9]))
|
||||||
|
}
|
||||||
|
|
||||||
|
$map = @{}
|
||||||
|
Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | ForEach-Object {
|
||||||
|
$t = Get-Content $_.FullName -Raw
|
||||||
|
foreach ($m in [regex]::Matches($t, '(?i)<CODFISCAL_CNP>([^<]*)</CODFISCAL_CNP>')) {
|
||||||
|
$v = $m.Groups[1].Value.Trim().ToUpper()
|
||||||
|
if ($v -ne '') { $map[$v] = 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$pastratCNP = 0; $pastratCUI = 0; $strain = 0; $sters = 0
|
||||||
|
$listaStersi = @()
|
||||||
|
foreach ($cod in $map.Keys) {
|
||||||
|
$prefix = ($cod -replace '[^A-Z]', '')
|
||||||
|
$roPrefix = @('RO', 'CUI', 'CF', 'CIF') -contains $prefix
|
||||||
|
$romanesc = ($prefix -eq '' -or $roPrefix)
|
||||||
|
if (-not $romanesc) { $strain++; continue }
|
||||||
|
$cifre = ($cod -replace '[^\d]', '')
|
||||||
|
if ($cifre.Length -eq 13 -and -not $roPrefix) {
|
||||||
|
if (Test-CNP $cifre) { $pastratCNP++ } else { $sters++; $listaStersi += $cod }
|
||||||
|
} elseif ($cifre.Length -ge 2 -and $cifre.Length -le 10) {
|
||||||
|
if (Test-CUI $cifre) { $pastratCUI++ } else { $sters++; $listaStersi += $cod }
|
||||||
|
} else { $sters++; $listaStersi += $cod }
|
||||||
|
}
|
||||||
|
|
||||||
|
"total coduri distincte : $($map.Count)"
|
||||||
|
"CNP valide pastrate : $pastratCNP"
|
||||||
|
"CUI valide pastrate : $pastratCUI"
|
||||||
|
"straine (nevalidate) : $strain"
|
||||||
|
"STERSE (invalide) : $sters"
|
||||||
|
'--- primele 30 sterse ---'
|
||||||
|
$listaStersi | Select-Object -First 30
|
||||||
91
ALTE/check_semnale_pj.ps1
Normal file
91
ALTE/check_semnale_pj.ps1
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# Cat de bine putem distinge persoana fizica (PF) de persoana juridica (PJ) in Fidelio,
|
||||||
|
# FARA sa ne bazam pe validitatea codului fiscal.
|
||||||
|
param([string]$Dir = "D:\PROIECTE\FLORA\FLORA2ROA\EXEMPLE\hotel")
|
||||||
|
|
||||||
|
function Test-CNP([string]$c) {
|
||||||
|
if ($c -notmatch '^\d{13}$') { return $false }
|
||||||
|
$w = @(2,7,9,1,4,6,3,5,8,2,7,9); $s = 0
|
||||||
|
for ($i = 0; $i -lt 12; $i++) { $s += [int]::Parse($c[$i]) * $w[$i] }
|
||||||
|
$r = $s % 11; if ($r -eq 10) { $r = 1 }
|
||||||
|
return ($r -eq [int]::Parse($c[12]))
|
||||||
|
}
|
||||||
|
function Test-CUI([string]$c) {
|
||||||
|
if ($c -notmatch '^\d{2,10}$') { return $false }
|
||||||
|
$c = $c.PadLeft(10, '0'); $k = '7532175321'; $s = 0
|
||||||
|
for ($i = 0; $i -lt 9; $i++) { $s += [int]::Parse($c[$i]) * [int]::Parse($k[$i]) }
|
||||||
|
$r = ($s * 10) % 11; if ($r -eq 10) { $r = 0 }
|
||||||
|
return ($r -eq [int]::Parse($c[9]))
|
||||||
|
}
|
||||||
|
|
||||||
|
# indicii de denumire pentru persoana juridica
|
||||||
|
$cuvintePJ = @('SRL','S.R.L','SA','S.A','SC','S.C','PFA','P.F.A','SNC','SCS','SRL-D','II','I.I',
|
||||||
|
'ASOCIATIA','ASOCIATIE','FUNDATIA','SOCIETATE','COMPANY','LTD','LIMITED','GMBH','GMBH.',
|
||||||
|
'BV','NV','INC','CORP','GROUP','HOLDING','UNIVERSITE','UNIVERSITATEA','UNIVERSITY',
|
||||||
|
'SPITAL','PRIMARIA','MINISTERUL','AGENTIA','INSTITUTUL','SCOALA','LICEUL','COLEGIUL',
|
||||||
|
'CLUB','ACS','A.C.S','CAR','CFR','TRANS','TOURS','TRAVEL','IMOB','CONSTRUCT','CONSULT',
|
||||||
|
'SOLUTIONS','TECHTRONIC','WORKSHOP','STUDIO','CONCEPT','SERV','COMERCIAL','PROFESSIONAL')
|
||||||
|
|
||||||
|
function Get-TipDupaNume([string]$nume) {
|
||||||
|
$cuv = $nume -split '[^A-Z0-9\.]+' | Where-Object { $_ -ne '' }
|
||||||
|
foreach ($c in $cuv) { if ($cuvintePJ -contains $c) { return 'PJ' } }
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
function Get-TipDupaReg([string]$reg) {
|
||||||
|
if ($reg -eq '') { return '' }
|
||||||
|
if ($reg -match '^[JFC]\s?\d{1,2}\s?/\s?\d+\s?/\s?\d{4}') { return 'PJ' } # J40/1234/2018
|
||||||
|
if ($reg -match '^[JL]\d{6,}') { return 'PJ' } # L2019000159348
|
||||||
|
if ($reg -match '^\d{1,2}/\d{4}$') { return 'PJ' } # 54/1997
|
||||||
|
if ($reg -match '^[A-Z]{2}\s?\d{6}$') { return 'PF' } # serie CI: ZV 093375
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = @{}
|
||||||
|
Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | ForEach-Object {
|
||||||
|
$t = Get-Content $_.FullName -Raw
|
||||||
|
foreach ($m in [regex]::Matches($t, '(?is)<CUMPARATOR>([^<]*)</CUMPARATOR>.*?<CODFISCAL_CNP>([^<]*)</CODFISCAL_CNP>\s*<REGCOMERT_CI_PASS>([^<]*)</REGCOMERT_CI_PASS>')) {
|
||||||
|
$nume = $m.Groups[1].Value.Trim().ToUpper()
|
||||||
|
$cod = $m.Groups[2].Value.Trim().ToUpper()
|
||||||
|
$reg = $m.Groups[3].Value.Trim().ToUpper()
|
||||||
|
if ($cod -ne '') { $rows["$nume|$cod|$reg"] = [pscustomobject]@{ Nume=$nume; Cod=$cod; Reg=$reg } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rez = foreach ($r in $rows.Values) {
|
||||||
|
$d = $r.Cod -replace '[^\d]', ''
|
||||||
|
$roPrefix = ($r.Cod -replace '[^A-Z]', '') -in @('RO','CUI','CF','CIF')
|
||||||
|
$tipNume = Get-TipDupaNume $r.Nume
|
||||||
|
$tipReg = Get-TipDupaReg $r.Reg
|
||||||
|
$cnpOk = Test-CNP $d
|
||||||
|
$cuiOk = (Test-CUI $d) -and -not $cnpOk
|
||||||
|
|
||||||
|
# decizie: semnale tari intai (nume/reg comert/prefix RO), apoi forma codului
|
||||||
|
$tip = ''
|
||||||
|
if ($roPrefix) { $tip = 'PJ' }
|
||||||
|
elseif ($tipNume -eq 'PJ') { $tip = 'PJ' }
|
||||||
|
elseif ($tipReg -eq 'PJ') { $tip = 'PJ' }
|
||||||
|
elseif ($cnpOk) { $tip = 'PF' }
|
||||||
|
elseif ($tipReg -eq 'PF') { $tip = 'PF' }
|
||||||
|
elseif ($cuiOk) { $tip = 'PJ' }
|
||||||
|
else { $tip = 'PF?' } # necunoscut, presupunem PF
|
||||||
|
|
||||||
|
[pscustomobject]@{ Nume=$r.Nume; Cod=$r.Cod; Reg=$r.Reg; Tip=$tip; CnpOk=$cnpOk; CuiOk=$cuiOk }
|
||||||
|
}
|
||||||
|
|
||||||
|
"total = $($rez.Count)"
|
||||||
|
$rez | Group-Object Tip | Sort-Object Count -Descending | Format-Table Name, Count | Out-String -Width 100
|
||||||
|
|
||||||
|
''
|
||||||
|
'=== PJ cu cod care NU trece validarea de CUI (raman cu cod, ca sa atentioneze declaratia) ==='
|
||||||
|
$pjInvalid = $rez | Where-Object { $_.Tip -eq 'PJ' -and -not $_.CuiOk }
|
||||||
|
"numar = $($pjInvalid.Count)"
|
||||||
|
$pjInvalid | Select-Object -First 25 | Format-Table -AutoSize Nume, Cod, Reg | Out-String -Width 200
|
||||||
|
|
||||||
|
''
|
||||||
|
'=== PF cu CNP invalid (se vor salva CU CNP GOL) ==='
|
||||||
|
$pfInvalid = $rez | Where-Object { $_.Tip -like 'PF*' -and -not $_.CnpOk }
|
||||||
|
"numar = $($pfInvalid.Count)"
|
||||||
|
$pfInvalid | Select-Object -First 25 | Format-Table -AutoSize Nume, Cod, Reg | Out-String -Width 200
|
||||||
|
|
||||||
|
''
|
||||||
|
'=== risc: clasificate PJ dar codul e CNP valid (nu trebuie sa existe) ==='
|
||||||
|
($rez | Where-Object { $_.Tip -eq 'PJ' -and $_.CnpOk }) | Format-Table -AutoSize Nume, Cod, Reg | Out-String -Width 200
|
||||||
49
ALTE/check_swap_tara.ps1
Normal file
49
ALTE/check_swap_tara.ps1
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Cazuri in care CODFISCAL_CNP e invalid dar REGCOMERT_CI_PASS contine un CNP valid (campuri inversate).
|
||||||
|
param([string]$Dir = "D:\PROIECTE\FLORA\FLORA2ROA\EXEMPLE\hotel")
|
||||||
|
|
||||||
|
function Test-CNP([string]$c) {
|
||||||
|
if ($c -notmatch '^\d{13}$') { return $false }
|
||||||
|
$w = @(2,7,9,1,4,6,3,5,8,2,7,9); $s = 0
|
||||||
|
for ($i = 0; $i -lt 12; $i++) { $s += [int]::Parse($c[$i]) * $w[$i] }
|
||||||
|
$r = $s % 11; if ($r -eq 10) { $r = 1 }
|
||||||
|
return ($r -eq [int]::Parse($c[12]))
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = @{}
|
||||||
|
Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | ForEach-Object {
|
||||||
|
$t = Get-Content $_.FullName -Raw
|
||||||
|
foreach ($m in [regex]::Matches($t, '(?is)<CUMPARATOR>([^<]*)</CUMPARATOR>.*?<CODFISCAL_CNP>([^<]*)</CODFISCAL_CNP>\s*<REGCOMERT_CI_PASS>([^<]*)</REGCOMERT_CI_PASS>')) {
|
||||||
|
$nume = $m.Groups[1].Value.Trim().ToUpper()
|
||||||
|
$cod = $m.Groups[2].Value.Trim().ToUpper()
|
||||||
|
$reg = $m.Groups[3].Value.Trim().ToUpper()
|
||||||
|
if ($cod -ne '') { $rows["$nume|$cod|$reg"] = [pscustomobject]@{ Nume=$nume; Cod=$cod; Reg=$reg } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$swap = $rows.Values | Where-Object {
|
||||||
|
$d = $_.Cod -replace '[^\d]', ''
|
||||||
|
$r = $_.Reg -replace '[^\d]', ''
|
||||||
|
-not (Test-CNP $d) -and (Test-CNP $r)
|
||||||
|
}
|
||||||
|
"cazuri cu campuri inversate (CNP valid in REGCOMERT) = $($swap.Count)"
|
||||||
|
$swap | Format-Table -AutoSize Nume, Cod, Reg | Out-String -Width 200
|
||||||
|
|
||||||
|
# exista informatie de tara la cumparator?
|
||||||
|
$f = Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | Select-Object -First 1
|
||||||
|
$t = Get-Content $f.FullName -Raw
|
||||||
|
$m = [regex]::Match($t, '(?is)<ROW>.*?</ROW>')
|
||||||
|
''
|
||||||
|
'=== campurile de tara existente in XML (primul rand) ==='
|
||||||
|
[regex]::Matches($m.Value, '(?i)<(\w*TARA\w*)>([^<]*)</\1>') | ForEach-Object { " $($_.Groups[1].Value) = [$($_.Groups[2].Value)]" }
|
||||||
|
|
||||||
|
''
|
||||||
|
'=== cate randuri au COMPANIE_TARA completat ==='
|
||||||
|
$cuTara = 0; $total = 0
|
||||||
|
Get-ChildItem -Path $Dir -Filter 'bts_detalii_facturi_rep_*.xml' | ForEach-Object {
|
||||||
|
$txt = Get-Content $_.FullName -Raw
|
||||||
|
foreach ($mm in [regex]::Matches($txt, '(?i)<COMPANIE_TARA>([^<]*)</COMPANIE_TARA>')) {
|
||||||
|
$total++
|
||||||
|
if ($mm.Groups[1].Value.Trim() -ne '') { $cuTara++ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"COMPANIE_TARA completat pe $cuTara din $total randuri"
|
||||||
113
CLAUDE.md
Normal file
113
CLAUDE.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
Ghid pentru agenti (Claude Code / Jcode) care lucreaza in acest repo.
|
||||||
|
|
||||||
|
## Ce este
|
||||||
|
|
||||||
|
FLORA2ROA e o aplicatie Visual FoxPro 9 care importa facturile si vanzarile din **Fidelio**
|
||||||
|
(hotel, XML) si **BIZ** (restaurant, XML) si genereaza note contabile in **ROA** (Oracle).
|
||||||
|
Un singur formular, `frm_import.scx`, face tot fluxul: citeste XML-urile din interval,
|
||||||
|
completeaza nomenclatorul de parteneri, construieste notele si le scrie in ROA.
|
||||||
|
|
||||||
|
Radacina: `D:\PROIECTE\FLORA\FLORA2ROA`. Nu are folder `COMUN\` (doar `comun.h` local), deci
|
||||||
|
scripturile partajate ROA au echivalente locale in `Teste\`.
|
||||||
|
|
||||||
|
## Reguli de lucru: OBLIGATORIU inainte de orice modificare
|
||||||
|
|
||||||
|
**Citeste `D:\ROA\ROACONT\COMUN\docs\reguli_lucru.md`.** Nu e context optional, e contractul de
|
||||||
|
livrare. Ce se incalca cel mai usor daca nu-l citesti:
|
||||||
|
|
||||||
|
- **Nu se comite fara aprobare.** Livrezi diff ca FISIER (`docs\diff_runda<N>_<subiect>.patch`),
|
||||||
|
iar write-back-ul in binar si commit-ul se fac dupa ce utilizatorul aproba. Patch-urile de
|
||||||
|
review nu se comit niciodata (sunt in `.gitignore`).
|
||||||
|
- **Comentarii minime, fara jurnal.** O linie, descriind comportamentul CURENT. Interzis inline:
|
||||||
|
istoricul modificarii ("inlocuieste...", "nu mai depinde de..."), nume de agent, referinte la
|
||||||
|
runde/decizii. Istoricul sta doar in antetul fisierului, cumulativ, semnat de om.
|
||||||
|
- **Modificari minime**: doar ce s-a cerut, fara refactorizari din oficiu.
|
||||||
|
- Punctul 7 din acel fisier e un index de conventii per zona atinsa (encoding cp1252, UX
|
||||||
|
formulare, `GO` pe `Recno()`, `goExecutor` + `ALTER TABLE`, testare UI, export Oracle).
|
||||||
|
|
||||||
|
## Documentatia proprie a proiectului
|
||||||
|
|
||||||
|
- `docs\depanare_testare_flora2roa.md` - harnessul de testare headless, ce contine `Teste\`,
|
||||||
|
comenzile uzuale si capcanele confirmate aici. **De citit inainte de a rula sau scrie teste.**
|
||||||
|
- `docs\flux_git_flora2roa.md` - fluxul git + SVN, ce urmareste fiecare, `roa_sync.bat`.
|
||||||
|
|
||||||
|
## Versionare
|
||||||
|
|
||||||
|
**SVN** e sursa de adevar, inclusiv pentru binarele VFP. **git** urmareste versiunile TEXT
|
||||||
|
(`.sc2`, `.pj2`) generate de FoxBin2Prg in arbore, plus `.prg`, `Teste\`, `docs\`. Binarele sunt
|
||||||
|
git-ignored, ca diff-urile sa fie lizibile. La inceput de sesiune: `roa_sync.bat`.
|
||||||
|
|
||||||
|
`svn commit` (care atinge binarele) se face **doar cu acordul explicit al utilizatorului**.
|
||||||
|
|
||||||
|
## Editarea formularului
|
||||||
|
|
||||||
|
`frm_import.scx` se editeaza pe text, byte-safe in Windows-1252:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\text_din_bin.ps1 # binar -> frm_import.sc2
|
||||||
|
# editezi frm_import.sc2 cu [IO.File]::ReadAllText/WriteAllText + GetEncoding(1252)
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile frm_import.sc2
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\recompileaza_binare.ps1
|
||||||
|
```
|
||||||
|
|
||||||
|
Ultimul pas nu e optional: write-back-ul reface `.scx/.sct` fara cod obiect, deci formularul
|
||||||
|
ruleaza fara `#INCLUDE "comun.h"` si constantele (`CT_SUCCES`) crapa in RUNTIME, desi
|
||||||
|
verificarea de sintaxa trece.
|
||||||
|
|
||||||
|
## Testare
|
||||||
|
|
||||||
|
Nu exista IDE in flux. Totul headless, din PowerShell:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\ruleaza_teste.ps1 # suita + sinteza
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\verifica_sintaxa.ps1 # dupa orice editare .prg
|
||||||
|
```
|
||||||
|
|
||||||
|
Un `.fxp` vechi ascunde modificarile din `.prg`: daca un test da acelasi rezultat dupa o
|
||||||
|
corectie evidenta, sterge `.fxp`-ul si reia.
|
||||||
|
|
||||||
|
## Cod
|
||||||
|
|
||||||
|
- Punct de intrare `main.prg`; `myutils.prg` = biblioteca de functii utilitare; `capp/app/myapp.prg`
|
||||||
|
= obiectele globale (`goApp`, `goConn`, `goExecutor`, `goLog`).
|
||||||
|
- Constantele din `comun.h` (`CT_SUCCES = 1`, `CT_INSUCCES`) sunt conventia de retur.
|
||||||
|
- Cod si mesaje in **romana, fara diacritice** (fisierele sunt cp1252).
|
||||||
|
- Functiile utilitare partajate se copiaza din `D:\ROA\ROACONT\COMUN\programe\oproceduri_comune.prg`,
|
||||||
|
nu se rescriu.
|
||||||
|
|
||||||
|
## Reguli de domeniu (contabil) de stiut
|
||||||
|
|
||||||
|
- In ROA, `RO12345678` (platitor de TVA) si `12345678` sunt **doi parteneri diferiti**: prefixul
|
||||||
|
`RO` se pastreaza exact cum vine din import si nu se adauga niciodata automat.
|
||||||
|
- La D394/D406 o **persoana fizica** poate fi raportata fara CNP, deci un CNP invalid se goleste.
|
||||||
|
O **persoana juridica** trebuie sa aiba cod fiscal: codul ei nu se sterge niciodata, ca eroarea
|
||||||
|
sa fie semnalata la validarea declaratiei si corectata la sursa, in Fidelio.
|
||||||
|
- Algoritmul romanesc de validare (CNP/CUI) nu se aplica partenerilor straini; codurile lor pot fi
|
||||||
|
si numai din cifre, de orice lungime.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
`changelog_flora2roa.txt`, blocuri de comentariu HTML, cel mai nou primul:
|
||||||
|
|
||||||
|
```
|
||||||
|
<!--
|
||||||
|
DD/MM/YYYY
|
||||||
|
FLORA2ROA - X.Y.Z
|
||||||
|
|
||||||
|
:modificare:
|
||||||
|
Ce vede utilizatorul.
|
||||||
|
-->
|
||||||
|
```
|
||||||
|
|
||||||
|
Taguri: `:nou:`, `:modificare:`, `:eroare:`. Text **pentru utilizator**, scurt, netehnic, o fraza
|
||||||
|
per idee. Erorile introduse si reparate in aceeasi versiune nelivrata nu se trec: `:eroare:` e
|
||||||
|
doar pentru ce a fost in productie. La bump de versiune se actualizeaza si `flora2roa.txt`
|
||||||
|
(fisierul pe care `update.bat` il compara cu cel de pe server).
|
||||||
|
|
||||||
|
## Stil de raspuns
|
||||||
|
|
||||||
|
Scurt si concret. Ce e gata (fisier:linie), ce urmeaza, ce trebuie decis. Fara naratiunea
|
||||||
|
drumului pana la rezultat, fara reluari, fara justificari necerute. Detaliile lungi (dovezi,
|
||||||
|
iesiri de test) se scriu in fisier si se trimite link.
|
||||||
59
Teste/recompileaza_binare.ps1
Normal file
59
Teste/recompileaza_binare.ps1
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Recompileaza formularele/clasele VFP dupa un write-back din text (bin_din_text.ps1).
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
FoxBin2Prg regenereaza .scx/.sct DIN TEXT, dar fara codul obiect compilat. Un formular
|
||||||
|
regenerat si NErecompilat ruleaza fara `#INCLUDE`-uri: constantele din comun.h (CT_SUCCES,
|
||||||
|
CT_INSUCCES...) devin "Variable not found" abia in RUNTIME, nu la verificarea de sintaxa.
|
||||||
|
|
||||||
|
De aceea, dupa FIECARE bin_din_text.ps1 se ruleaza si scriptul asta.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile frm_import.sc2
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\recompileaza_binare.ps1
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string[]]$Formular = @('frm_import.scx'),
|
||||||
|
[string]$ProjectRoot
|
||||||
|
)
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
if (-not $ProjectRoot) { $ProjectRoot = Split-Path $PSScriptRoot -Parent }
|
||||||
|
|
||||||
|
$vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe'
|
||||||
|
if (-not (Test-Path $vfp)) { throw "Nu gasesc $vfp" }
|
||||||
|
|
||||||
|
$prg = Join-Path $env:TEMP ("recompile_" + [guid]::NewGuid().ToString('N') + '.prg')
|
||||||
|
$linii = @(
|
||||||
|
"SET DEFAULT TO `"$ProjectRoot`"",
|
||||||
|
"SET PATH TO `"$ProjectRoot`""
|
||||||
|
)
|
||||||
|
foreach ($f in $Formular) {
|
||||||
|
$cale = Join-Path $ProjectRoot $f
|
||||||
|
if (-not (Test-Path $cale)) { throw "Nu exista $cale" }
|
||||||
|
$linii += "COMPILE FORM `"$f`""
|
||||||
|
}
|
||||||
|
$linii += 'QUIT'
|
||||||
|
[IO.File]::WriteAllLines($prg, $linii, [Text.Encoding]::GetEncoding(1252))
|
||||||
|
|
||||||
|
try {
|
||||||
|
& $vfp -A -T $prg | Out-Null
|
||||||
|
} finally {
|
||||||
|
Remove-Item $prg -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
# verificare: .sct trebuie sa contina cod obiect, nu doar textul metodelor
|
||||||
|
$rezultate = foreach ($f in $Formular) {
|
||||||
|
$sct = Join-Path $ProjectRoot ([IO.Path]::ChangeExtension($f, '.sct'))
|
||||||
|
[pscustomobject]@{
|
||||||
|
Formular = $f
|
||||||
|
SCT_KB = if (Test-Path $sct) { [math]::Round((Get-Item $sct).Length / 1KB) } else { 0 }
|
||||||
|
Stare = if ((Test-Path $sct) -and (Get-Item $sct).Length -gt 0) { 'OK' } else { 'LIPSA' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rezultate | Format-Table -AutoSize
|
||||||
|
|
||||||
|
if ($rezultate | Where-Object { $_.Stare -ne 'OK' }) { exit 1 }
|
||||||
|
Write-Host 'Recompilare terminata.' -ForegroundColor Green
|
||||||
@@ -34,6 +34,8 @@ $Root = Split-Path $Teste -Parent
|
|||||||
$suita = @(
|
$suita = @(
|
||||||
@{ Prg = 'test_frm_import_ui.prg'; Steps = @('afisat', 'trace', 'date') }
|
@{ Prg = 'test_frm_import_ui.prg'; Steps = @('afisat', 'trace', 'date') }
|
||||||
@{ Prg = 'test_export_date.prg'; Steps = @('afisat', 'importat') }
|
@{ Prg = 'test_export_date.prg'; Steps = @('afisat', 'importat') }
|
||||||
|
@{ Prg = 'test_cod_fiscal.prg'; Steps = @('validari') }
|
||||||
|
@{ Prg = 'test_cod_fiscal_real.prg'; Steps = @('analiza') }
|
||||||
)
|
)
|
||||||
if ($Doar) { $suita = $suita | Where-Object { $_.Prg -like "*$Doar*" } }
|
if ($Doar) { $suita = $suita | Where-Object { $_.Prg -like "*$Doar*" } }
|
||||||
|
|
||||||
|
|||||||
211
Teste/test_cod_fiscal.prg
Normal file
211
Teste/test_cod_fiscal.prg
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
* test_cod_fiscal.prg - teste pentru clasificarea partenerilor importati si curatarea CNP-urilor.
|
||||||
|
*
|
||||||
|
* Regula verificata:
|
||||||
|
* - PERSOANA FIZICA cu CNP invalid => cod fiscal GOL (permis la D394/D406)
|
||||||
|
* - PERSOANA FIZICA cu CNP valid => CNP pastrat, curatat de spatii/puncte
|
||||||
|
* - PERSOANA JURIDICA => codul NU se sterge NICIODATA, chiar daca nu trece
|
||||||
|
* validarea romaneasca (poate fi partener strain),
|
||||||
|
* ca sa fim atentionati la validarea declaratiei
|
||||||
|
*
|
||||||
|
* Rulare directa:
|
||||||
|
* vfp9.exe -A -T "D:\PROIECTE\FLORA\FLORA2ROA\Teste\test_cod_fiscal.prg"
|
||||||
|
|
||||||
|
SET SAFETY OFF
|
||||||
|
SET TALK OFF
|
||||||
|
|
||||||
|
PUBLIC gcUILog, gcSyncDir, gnTestFail, gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
|
||||||
|
gnTestFail = 0
|
||||||
|
gnMockRaspuns = 6
|
||||||
|
gcMockUltimMesaj = ''
|
||||||
|
gnMockUltimTip = 0
|
||||||
|
|
||||||
|
LOCAL lcTestDir
|
||||||
|
lcTestDir = ADDBS(JUSTPATH(SYS(16, 0)))
|
||||||
|
gcUILog = lcTestDir + 'test_cod_fiscal_log.txt'
|
||||||
|
gcSyncDir = lcTestDir + 'uisync\'
|
||||||
|
IF !DIRECTORY(gcSyncDir)
|
||||||
|
MD (gcSyncDir)
|
||||||
|
ENDIF
|
||||||
|
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
|
||||||
|
|
||||||
|
DO (lcTestDir + 'test_init_env_auto.prg') WITH .F.
|
||||||
|
SET PROCEDURE TO (lcTestDir + 'ui_harness.prg') ADDITIVE
|
||||||
|
SET PROCEDURE TO (lcTestDir + 'mock_amessagebox.prg') ADDITIVE
|
||||||
|
|
||||||
|
DO HarnessInit
|
||||||
|
|
||||||
|
LOCAL lnTip, lcRez
|
||||||
|
|
||||||
|
*==============================================================
|
||||||
|
* 1. PERSOANE FIZICE - singurele la care se sterge codul
|
||||||
|
*==============================================================
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('1800101410013', @lnTip, 'POPESCU ION', 'ZV 093375')
|
||||||
|
TestAssertEqual('1800101410013', m.lcRez, 'PF: CNP valid pastrat')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'PF: CNP valid => persoana fizica')
|
||||||
|
|
||||||
|
TestAssertEqual('1800101410013', GetCodFiscalValid(' 1800101410013. ', @lnTip, 'POPESCU ION', ''), ;
|
||||||
|
'PF: CNP valid curatat de spatii si punct')
|
||||||
|
|
||||||
|
* CNP-uri invalide reale din Fidelio: codul se goleste
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('2650407170374', @lnTip, 'TRUTA CLAUDIA MIHAELA', 'RK 800386')
|
||||||
|
TestAssertEqual('', m.lcRez, 'PF: CNP cu cifra de control gresita se sterge')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'PF: ramane persoana fizica')
|
||||||
|
|
||||||
|
TestAssertEqual('', GetCodFiscalValid('171030126201', @lnTip, 'TARTA GAVRIL SILVIU', ''), ;
|
||||||
|
'PF: CNP de 12 cifre se sterge')
|
||||||
|
TestAssertEqual('', GetCodFiscalValid('29050709211182', @lnTip, 'HOGESCU CRISTINA', ''), ;
|
||||||
|
'PF: CNP de 14 cifre se sterge')
|
||||||
|
TestAssertEqual('', GetCodFiscalValid('60109121600600', @lnTip, 'IOANCA DAMARIS', ''), ;
|
||||||
|
'PF: CNP de 14 cifre se sterge (2)')
|
||||||
|
|
||||||
|
* CNP valid scris cu punct la final
|
||||||
|
TestAssertEqual('2920121295914', GetCodFiscalValid('2920121295914.', @lnTip, 'ANDREI MARIA', ''), ;
|
||||||
|
'PF: CNP valid cu punct la final se curata')
|
||||||
|
|
||||||
|
* persoana fizica fara niciun semnal, cod invalid => tot persoana fizica, cod gol
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('287101935573', @lnTip, 'OPREA ANDREEA', '')
|
||||||
|
TestAssertEqual('', m.lcRez, 'PF: fara semnale, cod invalid => gol')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'PF: fara semnale => persoana fizica')
|
||||||
|
|
||||||
|
*==============================================================
|
||||||
|
* 2. PERSOANE JURIDICE - codul NU se sterge niciodata
|
||||||
|
*==============================================================
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('RO21675175', @lnTip, 'JUST MULTISERV SRL', 'J03/245/2007')
|
||||||
|
TestAssertEqual('RO21675175', m.lcRez, 'PJ: CUI cu prefix RO pastrat')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: prefix RO => persoana juridica')
|
||||||
|
|
||||||
|
TestAssertEqual('RO23565004', GetCodFiscalValid('RO 23565004', @lnTip, 'FIRMA SRL', ''), ;
|
||||||
|
'PJ: spatiul din cod se elimina')
|
||||||
|
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('24536740', @lnTip, 'KALVA SOLUTIONS SRL', 'J29/2677/2008')
|
||||||
|
TestAssertEqual('24536740', m.lcRez, 'PJ: CUI fara RO pastrat')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: denumire cu SRL => persoana juridica')
|
||||||
|
|
||||||
|
* CUI romanesc GRESIT la o persoana juridica: NU se sterge, ca sa dea eroare la declaratie
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('24536741', @lnTip, 'KALVA SOLUTIONS SRL', 'J29/2677/2008')
|
||||||
|
TestAssertEqual('24536741', m.lcRez, 'PJ: CUI invalid NU se sterge')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: CUI invalid ramane persoana juridica')
|
||||||
|
|
||||||
|
* partener strain cu cod alfanumeric
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('BE0325777171', @lnTip, 'UNIVERSITE DE LIEGE', '')
|
||||||
|
TestAssertEqual('BE0325777171', m.lcRez, 'PJ straina: TVA belgian pastrat')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ straina: cod TVA intracomunitar => persoana juridica')
|
||||||
|
|
||||||
|
TestAssertEqual('DICA9712015/99KS', GetCodFiscalValid('DICA9712015/99KS', @lnTip, 'FIRMA STRAINA SRL', ''), ;
|
||||||
|
'PJ straina: cod cu slash pastrat cand denumirea are forma juridica')
|
||||||
|
|
||||||
|
* cod cu litere care NU e cod de TVA si fara alt semnal => pasaport de persoana fizica
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('NN9J17714', @lnTip, 'TORRES MELISSA', '')
|
||||||
|
TestAssertEqual('', m.lcRez, 'PF straina: pasaportul nu se salveaza pe cod fiscal')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'PF straina: pasaport fara alt semnal => persoana fizica')
|
||||||
|
|
||||||
|
* prefixul romanesc se normalizeaza la RO
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('CUI 14770212', @lnTip, 'ASOCIATIA JUDETEANA DE HANDBAL', '')
|
||||||
|
TestAssertEqual('14770212', m.lcRez, 'PJ: eticheta CUI se scoate, fara sa se adauge RO')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: eticheta CUI => persoana juridica')
|
||||||
|
|
||||||
|
* 'RO' inseamna platitor de TVA: in ROA e ALT partener decat neplatitorul cu acelasi numar,
|
||||||
|
* deci prefixul se pastreaza exact cum vine si NU se adauga niciodata de noi
|
||||||
|
TestAssertEqual('RO24536740', GetCodFiscalValid('RO24536740', @lnTip, 'KALVA SOLUTIONS SRL', ''), ;
|
||||||
|
'PJ platitoare de TVA: prefixul RO se pastreaza')
|
||||||
|
TestAssertEqual('24536740', GetCodFiscalValid('24536740', @lnTip, 'KALVA SOLUTIONS SRL', ''), ;
|
||||||
|
'PJ neplatitoare: NU se adauga RO')
|
||||||
|
|
||||||
|
* partener strain cu cod NUMAI DIN CIFRE, recunoscut dupa tara
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('123456789012345', @lnTip, 'HOTEL PARTNER', '', 'BE')
|
||||||
|
TestAssertEqual('123456789012345', m.lcRez, 'PJ straina: cod numeric cu tara straina se pastreaza')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ straina: tara straina => persoana juridica')
|
||||||
|
|
||||||
|
* persoana juridica recunoscuta dupa numarul de registrul comertului
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('99999999', @lnTip, 'DENUMIRE FARA FORMA JURIDICA', 'J40/5790/2018')
|
||||||
|
TestAssertEqual('99999999', m.lcRez, 'PJ: cod invalid pastrat cand exista nr. reg. comertului')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: nr. registrul comertului => persoana juridica')
|
||||||
|
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('88888888', @lnTip, 'TICMAR EMMA CONCEPT', 'J2018000211289')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: nr. reg. comertului fara slash => persoana juridica')
|
||||||
|
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('9924188', @lnTip, 'CAR CFR SECTIA L2 SI CT1 BRAILA', '54/1997')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ: numar/an => persoana juridica')
|
||||||
|
|
||||||
|
* tipul venit direct din import bate toate celelalte semnale
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('1800101410013', @lnTip, 'POPESCU ION', '', '', '1')
|
||||||
|
TestAssertEqual('1800101410013', m.lcRez, 'tip impus PJ: codul se pastreaza')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'tip impus din import => persoana juridica')
|
||||||
|
|
||||||
|
*==============================================================
|
||||||
|
* 3. Recuperare din campuri inversate in Fidelio
|
||||||
|
*==============================================================
|
||||||
|
* operatorul a scris pasaportul pe cod fiscal si CNP-ul pe serie CI
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('XD 061964', @lnTip, 'POPITIU IOANA', '2640626364228')
|
||||||
|
TestAssertEqual('2640626364228', m.lcRez, 'recuperare: CNP valid luat din campul de serie CI')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'recuperare: ramane persoana fizica')
|
||||||
|
|
||||||
|
* daca in campul de serie CI nu exista CNP valid, nu inventam nimic
|
||||||
|
TestAssertEqual('', GetCodFiscalValid('XD 061964', @lnTip, 'POPITIU IOANA', 'ZV 093375'), ;
|
||||||
|
'recuperare: fara CNP valid in serie CI ramane gol')
|
||||||
|
|
||||||
|
*==============================================================
|
||||||
|
* 4. Cazuri limita
|
||||||
|
*==============================================================
|
||||||
|
lnTip = 0
|
||||||
|
TestAssertEqual('', GetCodFiscalValid('', @lnTip, 'POPESCU ION', ''), 'cod gol ramane gol')
|
||||||
|
TestAssertEqual(2, m.lnTip, 'cod gol + nume de persoana => persoana fizica')
|
||||||
|
|
||||||
|
lnTip = 0
|
||||||
|
TestAssertEqual('', GetCodFiscalValid(' ', @lnTip, 'POPESCU ION', ''), 'spatii => gol')
|
||||||
|
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid('', @lnTip, 'ALFA CONSTRUCT SRL', '')
|
||||||
|
TestAssertEqual('', m.lcRez, 'PJ fara cod ramane fara cod')
|
||||||
|
TestAssertEqual(1, m.lnTip, 'PJ fara cod este tot persoana juridica')
|
||||||
|
|
||||||
|
*--- functiile ajutatoare ---
|
||||||
|
TestAssert(EstePersoanaJuridica('KALVA SOLUTIONS SRL'), 'EstePersoanaJuridica: SRL')
|
||||||
|
TestAssert(EstePersoanaJuridica('ASOCIATIA SPORTIVA X'), 'EstePersoanaJuridica: ASOCIATIA')
|
||||||
|
TestAssert(EstePersoanaJuridica('UNIVERSITE DE LIEGE'), 'EstePersoanaJuridica: UNIVERSITE')
|
||||||
|
TestAssert(!EstePersoanaJuridica('SAVU MARIA'), 'EstePersoanaJuridica: SAVU nu e SA')
|
||||||
|
TestAssert(!EstePersoanaJuridica('MIHAII ION'), 'EstePersoanaJuridica: MIHAII nu e II')
|
||||||
|
TestAssert(!EstePersoanaJuridica('POPESCU ION'), 'EstePersoanaJuridica: nume simplu')
|
||||||
|
|
||||||
|
TestAssert(EsteNrRegComert('J40/5790/2018'), 'EsteNrRegComert: J40/5790/2018')
|
||||||
|
TestAssert(EsteNrRegComert('J2018000211289'), 'EsteNrRegComert: J2018000211289')
|
||||||
|
TestAssert(EsteNrRegComert('54/1997'), 'EsteNrRegComert: 54/1997')
|
||||||
|
TestAssert(!EsteNrRegComert('ZV 093375'), 'EsteNrRegComert: serie CI nu e reg. comert')
|
||||||
|
TestAssert(!EsteNrRegComert(''), 'EsteNrRegComert: gol')
|
||||||
|
|
||||||
|
TestAssert(EsteSerieCI('ZV 093375'), 'EsteSerieCI: cu spatiu')
|
||||||
|
TestAssert(EsteSerieCI('IF834409'), 'EsteSerieCI: fara spatiu')
|
||||||
|
TestAssert(!EsteSerieCI('J40/5790/2018'), 'EsteSerieCI: nr. reg. comert nu e serie CI')
|
||||||
|
TestAssert(!EsteSerieCI('2990118070015'), 'EsteSerieCI: CNP nu e serie CI')
|
||||||
|
|
||||||
|
TestAssert(EsteCodTVAStrain('BE0325777171'), 'EsteCodTVAStrain: BE')
|
||||||
|
TestAssert(EsteCodTVAStrain('DE811234567'), 'EsteCodTVAStrain: DE')
|
||||||
|
TestAssert(!EsteCodTVAStrain('NN9J17714'), 'EsteCodTVAStrain: pasaport nu e cod TVA')
|
||||||
|
TestAssert(!EsteCodTVAStrain('XD061964'), 'EsteCodTVAStrain: serie pasaport nu e cod TVA')
|
||||||
|
|
||||||
|
TestAssertEqual('RO23565004', GetCodFiscalCurat('RO 23565004'), 'GetCodFiscalCurat: spatii, RO pastrat')
|
||||||
|
TestAssertEqual('14770212', GetCodFiscalCurat('CUI 14770212'), 'GetCodFiscalCurat: eticheta CUI se scoate')
|
||||||
|
TestAssertEqual('14770212', GetCodFiscalCurat('CF 14770212'), 'GetCodFiscalCurat: eticheta CF se scoate')
|
||||||
|
TestAssertEqual('2920121295914', GetCodFiscalCurat('2920121295914.'), 'GetCodFiscalCurat: punct')
|
||||||
|
|
||||||
|
DO HarnessStep WITH 0, 'validari cod fiscal'
|
||||||
|
|
||||||
|
HarnessLog('REZULTAT: ' + TestRezultat())
|
||||||
|
DO HarnessDone WITH TestRezultat()
|
||||||
|
|
||||||
|
QUIT
|
||||||
133
Teste/test_cod_fiscal_real.prg
Normal file
133
Teste/test_cod_fiscal_real.prg
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
* test_cod_fiscal_real.prg - ruleaza GetCodFiscalValid pe TOATE codurile din XML-urile Fidelio
|
||||||
|
* si scrie un raport, ca sa vedem efectul real inainte de import.
|
||||||
|
*
|
||||||
|
* Verifica invariantii care conteaza pentru declaratii:
|
||||||
|
* - nicio persoana JURIDICA nu ramane fara cod din cauza noastra (codul nu se sterge)
|
||||||
|
* - se sterge cod DOAR la persoane fizice si DOAR cand CNP-ul chiar este invalid
|
||||||
|
* - niciun CNP valid nu se pierde
|
||||||
|
*
|
||||||
|
* Rulare: vfp9.exe -A -T "D:\PROIECTE\FLORA\FLORA2ROA\Teste\test_cod_fiscal_real.prg"
|
||||||
|
|
||||||
|
SET SAFETY OFF
|
||||||
|
SET TALK OFF
|
||||||
|
|
||||||
|
PUBLIC gcUILog, gcSyncDir, gnTestFail, gnMockRaspuns, gcMockUltimMesaj, gnMockUltimTip
|
||||||
|
gnTestFail = 0
|
||||||
|
gnMockRaspuns = 6
|
||||||
|
gcMockUltimMesaj = ''
|
||||||
|
gnMockUltimTip = 0
|
||||||
|
|
||||||
|
LOCAL lcTestDir
|
||||||
|
lcTestDir = ADDBS(JUSTPATH(SYS(16, 0)))
|
||||||
|
gcUILog = lcTestDir + 'test_cod_fiscal_real_log.txt'
|
||||||
|
gcSyncDir = lcTestDir + 'uisync\'
|
||||||
|
IF !DIRECTORY(gcSyncDir)
|
||||||
|
MD (gcSyncDir)
|
||||||
|
ENDIF
|
||||||
|
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
|
||||||
|
|
||||||
|
DO (lcTestDir + 'test_init_env_auto.prg') WITH .F.
|
||||||
|
SET PROCEDURE TO (lcTestDir + 'ui_harness.prg') ADDITIVE
|
||||||
|
SET PROCEDURE TO (lcTestDir + 'mock_amessagebox.prg') ADDITIVE
|
||||||
|
|
||||||
|
DO HarnessInit
|
||||||
|
|
||||||
|
LOCAL lcCale, lcFisier, lnFisiere, lcRaport
|
||||||
|
lcCale = ADDBS(ALLTRIM(goApp.oSettings.cale_import_fidelio))
|
||||||
|
HarnessLog('Citesc XML-urile din: ' + m.lcCale)
|
||||||
|
|
||||||
|
CREATE CURSOR cTot (denumire C(200), cod C(50), reg_com C(50))
|
||||||
|
|
||||||
|
lnFisiere = 0
|
||||||
|
lnSarite = 0
|
||||||
|
lcFisier = SYS(2000, m.lcCale + 'bts_detalii_facturi_rep_*.xml')
|
||||||
|
DO WHILE !EMPTY(m.lcFisier)
|
||||||
|
lnRanduri = 0
|
||||||
|
* fisierele goale sau fara coloanele asteptate se sar controlat
|
||||||
|
TRY
|
||||||
|
lnRanduri = XMLTOCURSOR(m.lcCale + m.lcFisier, 'cUnul', 512)
|
||||||
|
CATCH
|
||||||
|
lnRanduri = 0
|
||||||
|
ENDTRY
|
||||||
|
|
||||||
|
IF m.lnRanduri > 0 AND USED('cUnul') AND ;
|
||||||
|
TYPE('cUnul.codfiscal_cnp') = 'C' AND TYPE('cUnul.cumparator') = 'C'
|
||||||
|
SELECT DISTINCT CAST(ALLTRIM(cumparator) AS C(200)) AS denumire, ;
|
||||||
|
CAST(ALLTRIM(codfiscal_cnp) AS C(50)) AS cod, ;
|
||||||
|
CAST(ALLTRIM(regcomert_ci_pass) AS C(50)) AS reg_com ;
|
||||||
|
FROM cUnul WHERE !EMPTY(NVL(codfiscal_cnp, '')) INTO CURSOR cTemp
|
||||||
|
SELECT cTot
|
||||||
|
APPEND FROM DBF('cTemp')
|
||||||
|
USE IN (SELECT('cTemp'))
|
||||||
|
lnFisiere = m.lnFisiere + 1
|
||||||
|
ELSE
|
||||||
|
lnSarite = m.lnSarite + 1
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
USE IN (SELECT('cUnul'))
|
||||||
|
lcFisier = SYS(2000, m.lcCale + 'bts_detalii_facturi_rep_*.xml', 1)
|
||||||
|
ENDDO
|
||||||
|
|
||||||
|
HarnessLog('Fisiere citite: ' + TRANSFORM(m.lnFisiere) + ', sarite (goale/fara coloane): ' + TRANSFORM(m.lnSarite))
|
||||||
|
TestAssert(m.lnFisiere > 0, 'exista fisiere XML de analizat')
|
||||||
|
|
||||||
|
SELECT DISTINCT denumire, cod, reg_com FROM cTot INTO CURSOR cUnic
|
||||||
|
HarnessLog('Combinatii distincte nume+cod+regcom: ' + TRANSFORM(RECCOUNT('cUnic')))
|
||||||
|
|
||||||
|
LOCAL lnPF, lnPJ, lnSters, lnPJNevalidat, lnCnpPierdut, lnPJFaraCod
|
||||||
|
LOCAL lnTip, lcRez, lcCifre, lcCod
|
||||||
|
STORE 0 TO lnPF, lnPJ, lnSters, lnPJNevalidat, lnCnpPierdut, lnPJFaraCod
|
||||||
|
lcRaport = 'denumire;cod_import;reg_com;tip;cod_salvat' + CHR(13) + CHR(10)
|
||||||
|
|
||||||
|
SELECT cUnic
|
||||||
|
SCAN
|
||||||
|
lcCod = ALLTRIM(cUnic.cod)
|
||||||
|
lnTip = 0
|
||||||
|
lcRez = GetCodFiscalValid(m.lcCod, @lnTip, cUnic.denumire, cUnic.reg_com)
|
||||||
|
|
||||||
|
IF m.lnTip = 1
|
||||||
|
lnPJ = m.lnPJ + 1
|
||||||
|
* invariant 1: la persoana juridica NU stergem niciodata codul
|
||||||
|
IF EMPTY(m.lcRez) AND !EMPTY(m.lcCod)
|
||||||
|
lnPJFaraCod = m.lnPJFaraCod + 1
|
||||||
|
HarnessLog('EROARE invariant: PJ ramasa fara cod: ' + ALLTRIM(cUnic.denumire) + ' [' + m.lcCod + ']')
|
||||||
|
ENDIF
|
||||||
|
IF !VerifCF(m.lcRez)
|
||||||
|
lnPJNevalidat = m.lnPJNevalidat + 1
|
||||||
|
ENDIF
|
||||||
|
ELSE
|
||||||
|
lnPF = m.lnPF + 1
|
||||||
|
IF EMPTY(m.lcRez)
|
||||||
|
lnSters = m.lnSters + 1
|
||||||
|
* invariant 2: nu stergem CNP-uri VALIDE
|
||||||
|
lcCifre = CHRTRAN(m.lcCod, CHRTRAN(m.lcCod, '0123456789', ''), '')
|
||||||
|
IF LEN(m.lcCifre) = 13 AND cValidCNP(m.lcCifre)
|
||||||
|
lnCnpPierdut = m.lnCnpPierdut + 1
|
||||||
|
HarnessLog('EROARE invariant: CNP valid pierdut: ' + ALLTRIM(cUnic.denumire) + ' [' + m.lcCod + ']')
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
lcRaport = m.lcRaport + ALLTRIM(cUnic.denumire) + ';' + m.lcCod + ';' + ALLTRIM(cUnic.reg_com) + ';' + ;
|
||||||
|
IIF(m.lnTip = 1, 'PJ', 'PF') + ';' + m.lcRez + CHR(13) + CHR(10)
|
||||||
|
ENDSCAN
|
||||||
|
|
||||||
|
STRTOFILE(m.lcRaport, m.lcTestDir + 'raport_cod_fiscal_real.csv', .F.)
|
||||||
|
|
||||||
|
HarnessLog('persoane fizice : ' + TRANSFORM(m.lnPF))
|
||||||
|
HarnessLog('persoane juridice : ' + TRANSFORM(m.lnPJ))
|
||||||
|
HarnessLog('PF cu CNP sters : ' + TRANSFORM(m.lnSters))
|
||||||
|
HarnessLog('PJ cu cod nevalidat RO : ' + TRANSFORM(m.lnPJNevalidat) + ' (raman cu cod, atentioneaza declaratia)')
|
||||||
|
|
||||||
|
TestAssertEqual(0, m.lnPJFaraCod, 'nicio persoana juridica nu ramane fara cod')
|
||||||
|
TestAssertEqual(0, m.lnCnpPierdut, 'niciun CNP valid nu se pierde')
|
||||||
|
TestAssert(m.lnPF + m.lnPJ > 1000, 's-au analizat toti partenerii din exemple')
|
||||||
|
TestAssert(m.lnSters > 0, 'exista CNP-uri invalide care se curata')
|
||||||
|
TestAssert(m.lnPJ > 0, 'exista si persoane juridice detectate')
|
||||||
|
|
||||||
|
DO HarnessStep WITH 0, 'analiza pe date reale'
|
||||||
|
|
||||||
|
HarnessLog('REZULTAT: ' + TestRezultat())
|
||||||
|
DO HarnessDone WITH TestRezultat()
|
||||||
|
|
||||||
|
QUIT
|
||||||
@@ -1,3 +1,14 @@
|
|||||||
|
<!--
|
||||||
|
02/08/2026
|
||||||
|
FLORA2ROA - 2.0.6
|
||||||
|
|
||||||
|
:modificare:
|
||||||
|
Import parteneri. Persoanele fizice cu CNP invalid se salveaza fara CNP, ca sa nu dea eroare la D394/D406.
|
||||||
|
Codul persoanelor juridice nu se mai sterge, ca sa fie semnalat la validarea declaratiei si corectat in Fidelio.
|
||||||
|
Daca CNP-ul a fost scris din greseala in campul de serie CI, este preluat de acolo.
|
||||||
|
In jurnalul de import se scriu CNP-urile curatate si codurile de firma care nu trec validarea.
|
||||||
|
-->
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
02/07/2026
|
02/07/2026
|
||||||
FLORA2ROA - 2.0.5
|
FLORA2ROA - 2.0.5
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ Specific FLORA2ROA:
|
|||||||
`settings.ini`, `Trace` scrie in `edtInfo`.
|
`settings.ini`, `Trace` scrie in `edtInfo`.
|
||||||
- `test_export_date.prg` - functional: `ExportDate()` citeste XML-urile din interval si
|
- `test_export_date.prg` - functional: `ExportDate()` citeste XML-urile din interval si
|
||||||
populeaza cursoarele (fara Oracle).
|
populeaza cursoarele (fara Oracle).
|
||||||
|
- `test_cod_fiscal.prg` - unitar: clasificarea partenerilor (persoana fizica / juridica) si
|
||||||
|
curatarea CNP-urilor invalide (`GetCodFiscalValid` si functiile ajutatoare din `myutils.prg`).
|
||||||
|
- `test_cod_fiscal_real.prg` - ruleaza aceeasi logica pe TOATE codurile din `EXEMPLE\hotel`
|
||||||
|
si verifica invariantii: nicio persoana juridica nu ramane fara cod, niciun CNP valid nu se
|
||||||
|
pierde. Scrie `Teste\raport_cod_fiscal_real.csv` cu decizia luata pentru fiecare partener.
|
||||||
- `test_conectare_roa.prg` - verifica drumul CU conectare la Oracle: fie se conecteaza si
|
- `test_conectare_roa.prg` - verifica drumul CU conectare la Oracle: fie se conecteaza si
|
||||||
executa o interogare de proba, fie raporteaza esecul si iese controlat. NU e in suita
|
executa o interogare de proba, fie raporteaza esecul si iese controlat. NU e in suita
|
||||||
implicita (depinde de reteaua/serverul Oracle).
|
implicita (depinde de reteaua/serverul Oracle).
|
||||||
@@ -66,8 +71,14 @@ powershell -ExecutionPolicy Bypass -File Teste\text_din_bin.ps1 # binar
|
|||||||
# [IO.File]::WriteAllText($p, $t, [Text.Encoding]::GetEncoding(1252))
|
# [IO.File]::WriteAllText($p, $t, [Text.Encoding]::GetEncoding(1252))
|
||||||
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile _textcache\frm_import.sc2 -DryRun
|
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile _textcache\frm_import.sc2 -DryRun
|
||||||
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile _textcache\frm_import.sc2
|
powershell -ExecutionPolicy Bypass -File Teste\bin_din_text.ps1 -TextFile _textcache\frm_import.sc2
|
||||||
|
powershell -ExecutionPolicy Bypass -File Teste\recompileaza_binare.ps1 # OBLIGATORIU dupa write-back
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **Write-back-ul NU compileaza.** FoxBin2Prg reface `.scx`/`.sct` din text, dar fara codul
|
||||||
|
> obiect, deci formularul ruleaza fara `#INCLUDE "comun.h"`: constantele (`CT_SUCCES`,
|
||||||
|
> `CT_INSUCCES`) devin *"Variable not found"* abia in RUNTIME. Verificarea de sintaxa trece,
|
||||||
|
> testul pica. `Teste\recompileaza_binare.ps1` face `COMPILE FORM` si repara asta.
|
||||||
|
|
||||||
Write-back-ul face fidelity check (bin -> text, comparat pe octeti) inainte de a atinge
|
Write-back-ul face fidelity check (bin -> text, comparat pe octeti) inainte de a atinge
|
||||||
binarul si refuza daca `frm_import.scx` e blocat de IDE sau de `flora2roa.exe`.
|
binarul si refuza daca `frm_import.scx` e blocat de IDE sau de `flora2roa.exe`.
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.0.3
|
2.0.6
|
||||||
@@ -272,7 +272,7 @@ DEFINE CLASS form1 AS form
|
|||||||
* Completez id_part
|
* Completez id_part
|
||||||
Local lcBanca, lcCod_fiscal, lcCont_Banca, lcCorespDel, lcDenumire, lcIdString, lcId_categ_ent
|
Local lcBanca, lcCod_fiscal, lcCont_Banca, lcCorespDel, lcDenumire, lcIdString, lcId_categ_ent
|
||||||
Local lcId_loc_inreg, lcId_util, lcMesaj, lcMotiv_inactiv, lcNume, lcPrefix, lcPrenume, lcReg_comert
|
Local lcId_loc_inreg, lcId_util, lcMesaj, lcMotiv_inactiv, lcNume, lcPrefix, lcPrenume, lcReg_comert
|
||||||
Local lcSql, lcSqlInsert, lcSufix, lcTip_persoana, lcinactiv, lnSucces
|
Local lcSql, lcSqlInsert, lcSufix, lcTip_persoana, lcinactiv, lnSucces, lnTip_persoana, lcCodTara
|
||||||
Local lcAdresa, lcAdreseParteneri, lcApart, lcBloc, lcCaleImport, lcCod, lcCodpostal, lcDA_apare
|
Local lcAdresa, lcAdreseParteneri, lcApart, lcBloc, lcCaleImport, lcCod, lcCodpostal, lcDA_apare
|
||||||
Local lcDenumire_adresa, lcEmail, lcEtaj, lcFax, lcFile, lcIdPart, lcId_Judet, lcId_loc, lcId_tara
|
Local lcDenumire_adresa, lcEmail, lcEtaj, lcFax, lcFile, lcIdPart, lcId_Judet, lcId_loc, lcId_tara
|
||||||
Local lcItem1, lcItem2, lcItem3, lcItem4, lcJudet, lcJudetBucuresti, lcLocalitate, lcNumar
|
Local lcItem1, lcItem2, lcItem3, lcItem4, lcJudet, lcJudetBucuresti, lcLocalitate, lcNumar
|
||||||
@@ -400,30 +400,27 @@ DEFINE CLASS form1 AS form
|
|||||||
lcReg_comert = Nvl(Alltrim(Upper(reg_com)), "")
|
lcReg_comert = Nvl(Alltrim(Upper(reg_com)), "")
|
||||||
***************************
|
***************************
|
||||||
lcCod=Alltrim(Upper(Nvl(m.lcCod_fiscal,"")))
|
lcCod=Alltrim(Upper(Nvl(m.lcCod_fiscal,"")))
|
||||||
lcTip_persoana="2" && 1 = juridica, 2 = fizica
|
lcTip_persoana = "2" && 1 = juridica, 2 = fizica
|
||||||
* Prefer persoanele fizice pentru ca sunt mai multe fata de persoanele juridice
|
* GetCodFiscalValid decide tipul de persoana din denumire, nr. registrul comertului si
|
||||||
* Sunt multe persoane fizice cu CNP-uri gresite
|
* forma codului, apoi curata DOAR CNP-urile invalide ale persoanelor fizice.
|
||||||
|
* Codul unei persoane juridice nu se sterge niciodata: daca e gresit, vrem sa fim
|
||||||
|
* atentionati la validarea declaratiei si sa il corectam in Fidelio, nu sa il ascundem.
|
||||||
If !Empty(m.lcCod)
|
If !Empty(m.lcCod)
|
||||||
If Left(lcCod,2)="RO"
|
lnTip_persoana = 0
|
||||||
lcCod=Substr(m.lcCod,3)
|
lcCodTara = Alltrim(Upper(Nvl(cod_tara, "")))
|
||||||
lcTip_persoana="1"
|
lcCod_fiscal = GetCodFiscalValid(m.lcCod, @lnTip_persoana, m.lcDenumire, m.lcReg_comert, m.lcCodTara)
|
||||||
ENDIF
|
lcTip_persoana = Iif(m.lnTip_persoana = 1, "1", "2")
|
||||||
IF ISALPHA(m.lcCod)
|
|
||||||
lcTip_persoana="1"
|
|
||||||
ENDIF
|
|
||||||
|
|
||||||
If Len(m.lcCod)=13 And Isdigit(m.lcCod)
|
Do Case
|
||||||
If !cValidCNP(m.lcCod)
|
Case m.lcTip_persoana = "2" And Empty(m.lcCod_fiscal)
|
||||||
* daca CNP invalid, sterg CNP, sa nu dea eroare la D406
|
* persoana fizica cu CNP invalid: se salveaza fara CNP (permis la D394/D406)
|
||||||
lcCod_fiscal = ''
|
Thisform.trace('CNP invalid, partenerul se salveaza fara CNP: [' + m.lcCod + '] ' + Alltrim(m.lcDenumire))
|
||||||
Endif
|
Case m.lcTip_persoana = "1" And !VerifCF(m.lcCod_fiscal)
|
||||||
ELSE
|
* persoana juridica cu cod fiscal care nu trece validarea romaneasca: poate fi
|
||||||
* PJ din ROMANIA au coduri fiscale intre 2-10 cifre
|
* partener strain (cod valid la el in tara) sau o eroare de operare. Codul ramane,
|
||||||
* Exista si PJ din alte tari care pot avea coduri fiscale cu alt numar de cifre, dar sunt exceptii
|
* dar il semnalam in log ca sa poata fi verificat.
|
||||||
If Len(m.lcCod)>=2 And Len(m.lcCod)<=10 And Isdigit(m.lcCod)
|
Thisform.trace('ATENTIE: persoana juridica cu cod fiscal nevalidat: [' + m.lcCod_fiscal + '] ' + Alltrim(m.lcDenumire))
|
||||||
lcTip_persoana="1"
|
Endcase
|
||||||
Endif
|
|
||||||
Endif
|
|
||||||
ENDIF
|
ENDIF
|
||||||
IF m.lcTip_Persoana = "2"
|
IF m.lcTip_Persoana = "2"
|
||||||
lnPos = At(' ', m.lcNume)
|
lnPos = At(' ', m.lcNume)
|
||||||
|
|||||||
265
myutils.prg
265
myutils.prg
@@ -1664,6 +1664,25 @@ FUNCTION GetDataCNP
|
|||||||
RETURN CTOD(SUBSTR(plcnp, 6, 2) + "." + SUBSTR(plcnp, 4, 2) + "." + mlan)
|
RETURN CTOD(SUBSTR(plcnp, 6, 2) + "." + SUBSTR(plcnp, 4, 2) + "." + mlan)
|
||||||
ENDFUNC
|
ENDFUNC
|
||||||
*
|
*
|
||||||
|
*
|
||||||
|
* Copiata din D:\ROA\ROACONT\COMUN\programe\oproceduri_comune.prg (GetNrFromString),
|
||||||
|
* ca sa nu duplic logica: taie de la inceputul sirului literele si separatorii,
|
||||||
|
* pana la prima cifra. Ex. 'RO 15613488' -> '15613488', 'CUI 14770212' -> '14770212'.
|
||||||
|
FUNCTION GetNrFromString
|
||||||
|
LPARAMETERS plstr
|
||||||
|
LOCAL mlenstr
|
||||||
|
mlenstr = LEN(ALLTRIM(plstr))
|
||||||
|
|
||||||
|
DO WHILE ISALPHA(plstr) .OR. LEFT(plstr, 1) == " ";
|
||||||
|
.OR. LEFT(plstr, 1) == "&" .OR. LEFT(plstr, 1) == "/";
|
||||||
|
.OR. LEFT(plstr, 1) == "-" .OR. LEFT(plstr, 1) == "_";
|
||||||
|
.OR. LEFT(plstr, 1) == "." .OR. LEFT(plstr, 1) == ":"
|
||||||
|
plstr = RTRIM(SUBSTR(plstr, 2, mlenstr))
|
||||||
|
ENDDO
|
||||||
|
|
||||||
|
RETURN plstr
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
FUNCTION VerifCF
|
FUNCTION VerifCF
|
||||||
LPARAMETERS plcfisc
|
LPARAMETERS plcfisc
|
||||||
LOCAL mlsuma, mlrest
|
LOCAL mlsuma, mlrest
|
||||||
@@ -1705,3 +1724,249 @@ FUNCTION GetCodFiscalFRO
|
|||||||
RETURN m.lcCodFiscalFRO
|
RETURN m.lcCodFiscalFRO
|
||||||
ENDFUNC
|
ENDFUNC
|
||||||
*
|
*
|
||||||
|
* Clasifica partenerul importat (Fidelio hotel, BIZ restaurant) in persoana fizica / juridica
|
||||||
|
* si curata DOAR CNP-urile invalide.
|
||||||
|
*
|
||||||
|
* De ce asa:
|
||||||
|
* - la declaratii (D394/D406) o PERSOANA FIZICA poate fi raportata FARA CNP, deci un CNP
|
||||||
|
* invalid se poate goli fara sa pierdem nimic si fara sa dea eroare de validare;
|
||||||
|
* - o PERSOANA JURIDICA trebuie sa aiba cod fiscal, deci codul ei NU se sterge niciodata:
|
||||||
|
* daca e gresit, ramane asa ca sa fie semnalat la validarea declaratiei si sa fie corectat
|
||||||
|
* la sursa (in Fidelio), nu ascuns aici.
|
||||||
|
*
|
||||||
|
* De ce NU ne putem baza pe validarea romaneasca ca sa decidem tipul:
|
||||||
|
* codurile straine pot fi si numai cifre (fara prefix de tara), deci un cod numeric care nu
|
||||||
|
* trece algoritmul romanesc NU inseamna automat "gresit". Tipul se decide din alte semnale,
|
||||||
|
* in ordinea increderii:
|
||||||
|
* 1. tcTipCunoscut - tip venit din import, daca sistemul sursa il stie (cel mai sigur)
|
||||||
|
* 2. prefix de tara pe cod (RO/BE/DE...) sau litere in cod => persoana juridica
|
||||||
|
* 3. denumire cu forma juridica (SRL, SA, PFA, ASOCIATIA...) => persoana juridica
|
||||||
|
* 4. numar de registrul comertului in tcRegCom (J40/1234/2018, L2019...) => juridica
|
||||||
|
* serie+numar de CI (2 litere + 6 cifre) => fizica
|
||||||
|
* 5. CNP valid pe 13 cifre => fizica; CUI romanesc valid => juridica
|
||||||
|
* 6. altfel => fizica (majoritatea covarsitoare a clientilor de hotel)
|
||||||
|
*
|
||||||
|
* Parametri:
|
||||||
|
* tcCod - codul brut din import (CODFISCAL_CNP)
|
||||||
|
* tnTipPersoana - IESIRE prin referinta: 1 = juridica, 2 = fizica
|
||||||
|
* tcDenumire - optional, denumirea partenerului (pentru forma juridica)
|
||||||
|
* tcRegCom - optional, REGCOMERT_CI_PASS (nr. registrul comertului sau serie CI)
|
||||||
|
* tcCodTara - optional, codul/denumirea tarii daca importul o stie
|
||||||
|
* tcTipCunoscut - optional, tipul deja stiut din import: '1'/'PJ' sau '2'/'PF'
|
||||||
|
*
|
||||||
|
* Intoarce: codul de pastrat in ROA. Sir GOL doar cand este persoana fizica cu CNP invalid.
|
||||||
|
FUNCTION GetCodFiscalValid
|
||||||
|
LPARAMETERS tcCod, tnTipPersoana, tcDenumire, tcRegCom, tcCodTara, tcTipCunoscut
|
||||||
|
|
||||||
|
LOCAL lcCod, lcBrut, lcCifre, lcCifreReg, lcPrefix, lcPrefixBrut, lcTara, lcTip
|
||||||
|
LOCAL llLitere, llPrefixFiscal, lnParam
|
||||||
|
lnParam = PCOUNT()
|
||||||
|
|
||||||
|
lcCod = GetCodFiscalCurat(m.tcCod)
|
||||||
|
lcCifre = CHRTRAN(m.lcCod, CHRTRAN(m.lcCod, '0123456789', ''), '')
|
||||||
|
lcPrefix = ALLTRIM(CHRTRAN(m.lcCod, CHRTRAN(m.lcCod, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), ''))
|
||||||
|
llLitere = !EMPTY(m.lcPrefix)
|
||||||
|
|
||||||
|
* Eticheta din codul BRUT ('CUI 14770212') e semnal de persoana juridica, chiar daca
|
||||||
|
* GetCodFiscalCurat o scoate din codul salvat. 'RO' se pastreaza in cod pentru ca inseamna
|
||||||
|
* platitor de TVA, iar in ROA acela e alt partener decat neplatitorul cu acelasi numar.
|
||||||
|
lcBrut = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcCod, ''))))
|
||||||
|
lcPrefixBrut = ALLTRIM(CHRTRAN(m.lcBrut, CHRTRAN(m.lcBrut, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), ''))
|
||||||
|
llPrefixFiscal = INLIST(m.lcPrefixBrut, 'RO', 'CUI', 'CF', 'CIF')
|
||||||
|
|
||||||
|
lcTara = IIF(m.lnParam > 4 AND VARTYPE(m.tcCodTara) = 'C', ALLTRIM(UPPER(m.tcCodTara)), '')
|
||||||
|
lcTip = IIF(m.lnParam > 5 AND VARTYPE(m.tcTipCunoscut) = 'C', ALLTRIM(UPPER(m.tcTipCunoscut)), '')
|
||||||
|
|
||||||
|
DO CASE
|
||||||
|
CASE INLIST(m.lcTip, '1', 'PJ', 'J')
|
||||||
|
tnTipPersoana = 1
|
||||||
|
CASE INLIST(m.lcTip, '2', 'PF', 'F')
|
||||||
|
tnTipPersoana = 2
|
||||||
|
CASE m.llPrefixFiscal
|
||||||
|
* eticheta romaneasca de cod fiscal (RO/CUI/CF/CIF) => persoana juridica
|
||||||
|
tnTipPersoana = 1
|
||||||
|
CASE !EMPTY(m.lcTara) AND !INLIST(m.lcTara, 'RO', 'ROU', 'ROMANIA')
|
||||||
|
* tara straina declarata: nu putem valida romaneste, tratam ca juridica
|
||||||
|
tnTipPersoana = 1
|
||||||
|
CASE EstePersoanaJuridica(m.tcDenumire)
|
||||||
|
tnTipPersoana = 1
|
||||||
|
CASE EsteNrRegComert(m.tcRegCom)
|
||||||
|
tnTipPersoana = 1
|
||||||
|
CASE LEN(m.lcCifre) = 13 AND cValidCNP(m.lcCifre)
|
||||||
|
tnTipPersoana = 2
|
||||||
|
CASE EsteSerieCI(m.tcRegCom)
|
||||||
|
tnTipPersoana = 2
|
||||||
|
CASE m.llLitere
|
||||||
|
* cod cu litere fara alt semnal: TVA intracomunitar (BE0325777171) daca incepe cu
|
||||||
|
* un cod de tara UE, altfel e cel mai probabil pasaport de persoana fizica
|
||||||
|
tnTipPersoana = IIF(EsteCodTVAStrain(m.lcCod), 1, 2)
|
||||||
|
CASE BETWEEN(LEN(m.lcCifre), 2, 10) AND VerifCF(m.lcCifre)
|
||||||
|
tnTipPersoana = 1
|
||||||
|
OTHERWISE
|
||||||
|
* clientii de hotel sunt in marea lor majoritate persoane fizice
|
||||||
|
tnTipPersoana = 2
|
||||||
|
ENDCASE
|
||||||
|
|
||||||
|
IF m.tnTipPersoana = 1
|
||||||
|
* persoana juridica: codul NU se sterge niciodata, chiar daca nu trece validarea.
|
||||||
|
* Vrem sa fim atentionati la declaratie, nu sa ascundem problema.
|
||||||
|
RETURN m.lcCod
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* persoana fizica: pastram CNP-ul doar daca este valid, altfel gol (permis la declaratii).
|
||||||
|
* Pasapoartele si seriile de CI nu sunt CNP-uri, deci nu se salveaza pe cod fiscal.
|
||||||
|
IF LEN(m.lcCifre) = 13 AND cValidCNP(m.lcCifre)
|
||||||
|
RETURN m.lcCifre
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* recuperare: in Fidelio se intampla ca operatorul sa inverseze campurile si sa scrie CNP-ul
|
||||||
|
* in 'serie CI / pasaport'. Daca acolo gasim un CNP valid, il folosim pe acela.
|
||||||
|
lcCifreReg = GetCodFiscalCurat(m.tcRegCom)
|
||||||
|
lcCifreReg = CHRTRAN(m.lcCifreReg, CHRTRAN(m.lcCifreReg, '0123456789', ''), '')
|
||||||
|
IF LEN(m.lcCifreReg) = 13 AND cValidCNP(m.lcCifreReg)
|
||||||
|
RETURN m.lcCifreReg
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
RETURN ''
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
* .T. daca sirul arata a cod de TVA intracomunitar: 2 litere = cod de tara UE, urmate de cifre.
|
||||||
|
* Ex: 'BE0325777171', 'DE811234567', 'HU12345678'. NU include 'RO' (tratat separat).
|
||||||
|
FUNCTION EsteCodTVAStrain
|
||||||
|
LPARAMETERS tcCod
|
||||||
|
|
||||||
|
LOCAL lcCod, lcTari, lcTara, lcRest
|
||||||
|
lcCod = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcCod, ''))))
|
||||||
|
lcCod = CHRTRAN(m.lcCod, ' .-', '')
|
||||||
|
IF LEN(m.lcCod) < 6
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* coduri de tara UE + cateva uzuale in turism
|
||||||
|
lcTari = ' AT BE BG CY CZ DE DK EE EL ES FI FR GR HR HU IE IT LT LU LV MT NL PL PT SE SI SK ' + ;
|
||||||
|
' GB CH NO MD UA RS TR US '
|
||||||
|
|
||||||
|
lcTara = LEFT(m.lcCod, 2)
|
||||||
|
IF !(' ' + m.lcTara + ' ' $ m.lcTari)
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* dupa codul de tara trebuie sa urmeze numai cifre
|
||||||
|
lcRest = SUBSTR(m.lcCod, 3)
|
||||||
|
RETURN LEN(CHRTRAN(m.lcRest, CHRTRAN(m.lcRest, '0123456789', ''), '')) = LEN(m.lcRest)
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
* Curata un cod fiscal / CNP de spatii, puncte si separatori redundanti, pastrand literele
|
||||||
|
* semnificative.
|
||||||
|
* 'RO 23565004' -> 'RO23565004'
|
||||||
|
* 'CUI 14770212' -> '14770212'
|
||||||
|
* '2920121295914.' -> '2920121295914'
|
||||||
|
*
|
||||||
|
* ATENTIE: prefixul 'RO' NU se adauga niciodata de la noi. In ROA, 'RO12345678' (platitor de
|
||||||
|
* TVA) si '12345678' (neplatitor) sunt DOI parteneri diferiti, deci prefixul se pastreaza
|
||||||
|
* exact cum a venit din import. Etichetele 'CUI'/'CF'/'CIF' sunt doar text descriptiv, nu
|
||||||
|
* atribut fiscal, deci se sterg fara sa fie inlocuite cu 'RO'.
|
||||||
|
FUNCTION GetCodFiscalCurat
|
||||||
|
LPARAMETERS tcCod
|
||||||
|
|
||||||
|
LOCAL lcCod, lcCifre, lcPrefix
|
||||||
|
lcCod = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcCod, ''))))
|
||||||
|
lcCod = CHRTRAN(m.lcCod, CHR(9) + CHR(13) + CHR(10), ' ')
|
||||||
|
* scot spatiile si punctele; liniuta si slash-ul pot face parte din coduri straine
|
||||||
|
lcCod = ALLTRIM(CHRTRAN(m.lcCod, ' .', ''))
|
||||||
|
|
||||||
|
* 'CUI 14770212' -> '14770212': eticheta nu spune nimic despre calitatea de platitor de TVA
|
||||||
|
lcPrefix = ALLTRIM(CHRTRAN(m.lcCod, CHRTRAN(m.lcCod, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', ''), ''))
|
||||||
|
IF INLIST(m.lcPrefix, 'CUI', 'CF', 'CIF')
|
||||||
|
lcCifre = CHRTRAN(m.lcCod, CHRTRAN(m.lcCod, '0123456789', ''), '')
|
||||||
|
IF !EMPTY(m.lcCifre)
|
||||||
|
lcCod = m.lcCifre
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
RETURN m.lcCod
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
* .T. daca denumirea contine o forma juridica (SRL, SA, PFA, ASOCIATIA, LTD, GMBH...).
|
||||||
|
* Compara pe cuvinte intregi, ca sa nu ia 'SA' din 'SAVU' sau 'II' din 'MIHAII'.
|
||||||
|
FUNCTION EstePersoanaJuridica
|
||||||
|
LPARAMETERS tcDenumire
|
||||||
|
|
||||||
|
LOCAL lcDen, lcForme, lcCuv, lnI, lnCuvinte
|
||||||
|
lcDen = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcDenumire, ''))))
|
||||||
|
IF EMPTY(m.lcDen)
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* separatorii devin spatii, ca sa pot compara cuvant cu cuvant
|
||||||
|
lcDen = CHRTRAN(m.lcDen, '.,-/()"' + CHR(9), ' ')
|
||||||
|
|
||||||
|
lcForme = ' SRL SA SC SNC SCS SCA PFA II IF SRLD RA RL ' + ;
|
||||||
|
' ASOCIATIA ASOCIATIE FUNDATIA FUNDATIE SOCIETATEA COOPERATIVA CABINET ' + ;
|
||||||
|
' PRIMARIA MINISTERUL AGENTIA INSTITUTUL SPITALUL SCOALA LICEUL COLEGIUL ' + ;
|
||||||
|
' UNIVERSITATEA UNIVERSITE UNIVERSITY UNIVERSITAT INSPECTORATUL DIRECTIA ' + ;
|
||||||
|
' LTD LIMITED GMBH AG BV NV INC LLC PLC CORP CORPORATION COMPANY HOLDING KFT SPZOO OOD '
|
||||||
|
|
||||||
|
lnCuvinte = GETWORDCOUNT(m.lcDen, ' ')
|
||||||
|
FOR lnI = 1 TO m.lnCuvinte
|
||||||
|
lcCuv = ALLTRIM(GETWORDNUM(m.lcDen, m.lnI, ' '))
|
||||||
|
IF !EMPTY(m.lcCuv) AND (' ' + m.lcCuv + ' ') $ m.lcForme
|
||||||
|
RETURN .T.
|
||||||
|
ENDIF
|
||||||
|
ENDFOR
|
||||||
|
|
||||||
|
RETURN .F.
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
* .T. daca sirul arata a numar de inregistrare la Registrul Comertului.
|
||||||
|
* Forme acceptate: 'J40/1234/2018', 'F13/45/2005', 'C23/9/2019', 'L2019000159348', '54/1997'
|
||||||
|
FUNCTION EsteNrRegComert
|
||||||
|
LPARAMETERS tcRegCom
|
||||||
|
|
||||||
|
LOCAL lcReg, lcRest
|
||||||
|
lcReg = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcRegCom, ''))))
|
||||||
|
lcReg = CHRTRAN(m.lcReg, ' ', '')
|
||||||
|
IF EMPTY(m.lcReg)
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* J40/1234/2018 - litera + cifre + doua slash-uri
|
||||||
|
IF INLIST(LEFT(m.lcReg, 1), 'J', 'F', 'C') AND OCCURS('/', m.lcReg) = 2 AND ;
|
||||||
|
ISDIGIT(SUBSTR(m.lcReg, 2, 1))
|
||||||
|
RETURN .T.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* L2019000159348 / J2018000211289 - litera urmata de minim 10 cifre
|
||||||
|
IF INLIST(LEFT(m.lcReg, 1), 'J', 'L') AND LEN(m.lcReg) >= 11
|
||||||
|
lcRest = SUBSTR(m.lcReg, 2)
|
||||||
|
IF ISDIGIT(m.lcRest) AND LEN(CHRTRAN(m.lcRest, CHRTRAN(m.lcRest, '0123456789', ''), '')) = LEN(m.lcRest)
|
||||||
|
RETURN .T.
|
||||||
|
ENDIF
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
* 54/1997 - numar/an, tipic institutiilor publice
|
||||||
|
IF OCCURS('/', m.lcReg) = 1 AND LEN(m.lcReg) <= 8 AND ;
|
||||||
|
ISDIGIT(m.lcReg) AND LEN(GETWORDNUM(m.lcReg, 2, '/')) = 4
|
||||||
|
RETURN .T.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
RETURN .F.
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
* .T. daca sirul arata a serie + numar de carte de identitate: 2 litere urmate de 6 cifre.
|
||||||
|
* Ex: 'ZV 093375', 'IF834409', 'RK 340434'
|
||||||
|
FUNCTION EsteSerieCI
|
||||||
|
LPARAMETERS tcRegCom
|
||||||
|
|
||||||
|
LOCAL lcReg
|
||||||
|
lcReg = ALLTRIM(UPPER(TRANSFORM(NVL(m.tcRegCom, ''))))
|
||||||
|
lcReg = CHRTRAN(m.lcReg, ' -.', '')
|
||||||
|
IF LEN(m.lcReg) <> 8
|
||||||
|
RETURN .F.
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
RETURN ISALPHA(LEFT(m.lcReg, 1)) AND ISALPHA(SUBSTR(m.lcReg, 2, 1)) AND ;
|
||||||
|
ISDIGIT(SUBSTR(m.lcReg, 3, 1)) AND ;
|
||||||
|
LEN(CHRTRAN(SUBSTR(m.lcReg, 3), CHRTRAN(SUBSTR(m.lcReg, 3), '0123456789', ''), '')) = 6
|
||||||
|
ENDFUNC
|
||||||
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user