achizitie import: TVA DVI cu valuta proprie, discount financiar, cote multiple

- TVA-ul de pe DVI poate avea valuta si curs proprii, diferite de ale facturii
  (rand "protejat": rand_dvi/valuta_proprie pe introdc, sparge_tva_protejat).
- Discount financiar pe factura: rand tip_rand='G' (401 = 767), TVA calculat pe
  baza diminuata, marfa si preturile articolelor pe valoarea integrala.
- Factura multi-cota: randurile S, G si T se sparg pe cotele articolelor, cu
  explicatia TVA din familia coloanei si alinierea T -> S.
- Teste noi in utile/Teste/achizitie_import (discount, DVI, cote, e2e).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U9uDgDfUQXbh2Neib36CN8
This commit is contained in:
2026-08-01 09:32:35 +03:00
parent 704e25e190
commit 832fea4913
62 changed files with 12071 additions and 575 deletions

View File

@@ -46,13 +46,17 @@ c. **Asteptarea `ready_0`**: cu `.fxp` cald START apare in ~2s, la rece mult mai
classlib-uri). `-ReadyTimeoutSec` generos (implicit 180s); retry NUMAI la "start ratat",
nu la "start lent". Detectia "a pornit" se face pe mtime-ul log-ului > momentul lansarii
(un log stale tinut de un vfp9 zombi pacaleste verificarea "log ne-gol") - omoara zombii
inainte de fiecare lansare.
PROPRII (filtrati pe linia de comanda, vezi punctul e) inainte de fiecare lansare.
d. **`vfp9 -A test.prg` deschide INTERMITENT editorul** in loc sa ruleze (log gol). Lanseaza
`.fxp`-ul PRECOMPILAT. Precompilarea (`COMPILE`+`QUIT`) atarna dupa COMPILE si, rulata in
ACEEASI sesiune powershell, otraveste lansarile ulterioare - ruleaza-o intr-un proces copil
izolat (`Start-Process -Wait _precompile.ps1`).
e. **Suitele NU se ruleaza in paralel**: `_precompile.ps1` face `Get-Process vfp9 | Stop-Process
-Force` (omoara toate instantele), deci un test lansat in paralel il ucide pe cel in curs.
e. **Suitele NU se ruleaza in paralel** intre ele: harness-ul isi omoara instantele `vfp9`
ramase inainte de fiecare lansare, deci un al doilea test pornit peste primul il ucide.
Omorarea e INSA filtrata pe linia de comanda (`Win32_Process.CommandLine` care contine
folderul de teste): instantele `vfp9` straine — sesiunea IDE a utilizatorului sau teste
dintr-un ALT proiect VFP — nu sunt atinse si nu blocheaza rularea. Nu reintroduce
`Get-Process vfp9 | Stop-Process -Force` fara filtru.
f. **FARA FURT DE FOCUS (17/07/2026)**: `Graphics.CopyFromScreen` fura focus si se corupe daca
utilizatorul lucreaza in paralel - nu se mai foloseste. Capturile se fac cu `PrintWindow`
(user32, P/Invoke) pe `Process.MainWindowHandle`, flag `2` = `PW_RENDERFULLCONTENT`
@@ -83,13 +87,35 @@ j. **Mock-urile de date trebuie sa reproduca structura si semantica REALA a surs
valori "compuse" manual in test). Un mock incomplet lasa campuri mereu NULL sau ascunde
pasul care se testeaza. Cand un flag global activeaza cod suplimentar (ex. `gl406`), acel
cod cere mock-uri in plus - verifica ce apeleaza si adauga metodele lipsa din dummy.
Cu `gl406=.T.` (SAFT), `GetTaxCodeIdPart`/`GetTaxCode` cer: `goApp.ReadIni`/`WriteIni`
(proprietate simpla nu ajunge, clasa `dummyapp` are nevoie de METODE), `goExecutor.oReset`
(no-op e suficient), si un cursor `saft_taxtable` real (nu doar mock pe `goExecutor` -
`update_jtva_coloane` face `USE saft_taxtable` direct pe alias). Fara ele, simptomul e un
dialog nativ Windows "Open" (cauta `saft_taxtable.dbf`) care blocheaza headless la nesfarsit,
fara nicio linie noua in log si CPU 0% - vezi `depanare_testare_vfp.md` pentru diagnosticul
cu `EnumWindows`/`PrintWindow` pe fereastra ascunsa cand simptomul e "ecran gol, fara eroare".
k. **`LOCATE FOR camp == 'literal'` pe camp `C(n)` padded nu gaseste nimic** (`==` e exact) -
foloseste `ALLTRIM(camp) == 'literal'`.
l. **`CREATEOBJECT`/`ADDPROPERTY` se comporta gresit apelate DINTR-O PROCEDURA in acest runtime
headless** (obiect returnat ca string de 30 spatii; `ADDPROPERTY` da eroare 11). Din
programul PRINCIPAL merg. Construieste obiectele-parametru INLINE in main, nu intr-un helper.
(Cauza neclara; reproductibil.)
Cauza confirmata intr-un caz concret: linie de cod prea lunga in ACEEASI metoda de clasa -
vezi `depanare_testare_vfp.md` sectiunea 6. Remediul (constructie inline) ramane valabil
oricum, indiferent de cauza exacta dintr-un caz punctual.
m. **Fara `SELECT-SQL` pe cursorul legat de grid**: `SELECT ... FROM <cursor> INTO CURSOR` cat
timp cursorul e RecordSource-ul unui grid viu poate omori procesul vfp9 silentios (fara
eroare catchabila, fara semafor). Foloseste xBase nativ (`COUNT FOR ... TO`, `CALCULATE`,
`LOCATE`), care nu comuta zona de lucru a grid-ului.
n. **Wrapper-ul `.ps1` trebuie sa paseze `-SyncDir` daca `.prg`-ul isi seteaza propriul
`gcSyncDir`** - altfel testul scrie semafoarele intr-un folder si `vfp_ui_harness.ps1` le
asteapta in cel implicit (`uisync\`), deadlock pana la timeout. Simptom identic cu "test
agatat", dar FARA `.ERR` si cu CPU ~0 la procesul vfp9 (nu un dialog modal - procesul chiar
asteapta un fisier care nu vine). Timeout minim: ~30s x numarul de pasi din `-Steps`
(auto-continue per checkpoint din `HarnessWaitContinue`), plus marja de pornire.
o. **Formularul resincronizeaza singur dupa o alegere din grid** (`lSyncPending` + `tmrSync`,
ex. `do_modifica_explicatie_tva` din `ointroduceri.vcx`): starea de imediat dupa actiune NU e
observabila - `DOEVENTS FORCE` lasa timer-ul sa porneasca, iar resincronizarea rescrie ce
tocmai s-a aplicat (la explicatia TVA: randul S revine la familia documentului si randurile T
se realiniaza dupa el). Scrie assert-urile pe starea de DUPA resincronizare si alege un efect
pe care resincronizarea NU il repara (acolo: `scc`-ul randului T, atins doar cand se schimba
explicatia). Altfel testul pica fara sa fie ceva gresit in cod.