docs: runda 6 - cercetari, propuneri si conventia mediului Oracle

Cercetarile si propunerile rundelor 4-6 pe editarea facturii emise. Starea
rundei 6 si ce s-a stabilit intra in progres.md.

Nou: docs/conventii_mediu_oracle.md - pe dev/test se lucreaza numai cu
ROA_CENTRAL si schemele CONTAFIN_ORACLE si MARIUSM_AUTO; schema ACN nu se
foloseste. Scripturile de pachet sunt necalificate, deci schema tinta o
decide sirul de conectare, nu fisierul.

roafacturare.pj2 regenerat de git_sync.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gYCNE26G1G7UoGu2ju7aS
This commit is contained in:
2026-08-20 16:35:03 +03:00
parent b5a7108f34
commit ca3c5d7eea
26 changed files with 5316 additions and 103 deletions

View File

@@ -0,0 +1,143 @@
# Cercetare: rulaje (RUL) pe factura emisă din aviz (tip = 4) — `test_s8_matrice_surse.prg:308`
## Verdict
**Asserția e greșită pentru tip = 4.** Tabela `RUL` reține exclusiv mișcări pe conturi de stoc
(`371` în datele verificate); o factură emisă din aviz nu atinge niciodată contul de stoc — ea doar
transformă creanța provizorie (`418`) în creanță fermă (`4111`) și TVA neexigibilă în TVA colectată
(`4428`→`4428`) — pentru că marfa a ieșit deja din gestiune la avizul-sursă (tip 22), care e cel ce
scrie rândurile de `RUL`. `Reccount(trul) = 0` pe un document de tip 4 e starea corectă, nu un semn
că editarea a distrus rulaje.
---
## Ce am verificat la sursă (cod + date Oracle)
### 1. De unde se umple `trul`
`IncarcaCursoareModificareNota` (`COMUN\programe\ofacturare_editare.prg:35-148`) încarcă `trul`
direct din view-ul `vrul_tot`, filtrat pe `an`/`luna`/`cod`, fără nicio sinteză sau completare:
```
COMUN\programe\ofacturare_editare.prg:76
lcSql = [select * from vrul_tot where ] + lcConditieSters + [ an = ] + Transform(m.tnAn) + [ and luna = ] + Transform(m.tnLuna) + [ and cod = ] + Alltrim(Str(m.tnCod)) + [ order by id_rul]
```
`Reccount(trul)` e deci exact numărul de rânduri deja existente în `RUL` (server) pentru acel `cod`
— nu ceva calculat sau garantat nenul de vreo regulă de business în client.
### 2. Cine scrie rulajele — și diferența pe tip de document
Scrierea efectivă e server-side, în Oracle, `PACK_CONTAFIN.SCRIE_IN_RUL` (`COMUN\docs\PACK_CONTAFIN.pck:1896-2019`):
face `INSERT INTO RUL (...) SELECT ... FROM RUL_TEMP` — deci **scrie exact ce a fost pus în
`RUL_TEMP` de partea VFP**, fără vreo ramură condiționată de tipul documentului. Tot ce contează e
dacă `RUL_TEMP` (populat din `trul`, deci din `vrul_tot` deja existent) are rânduri.
Pe partea VFP, calea de editare a facturii (cea exercitată de test, prin `frm_facturi.do_editare_factura`,
`COMUN\clase\ofacturare_comun.vc2:3799-3821`) copiază necondiționat `trul` înapoi în `RUL_TEMP` și
apelează `OSCRIE_IN_FISIERE(0,.T.,.T.)` — al treilea parametru (echivalentul lui `llRul` din editorul
generic) e **hardcodat `.T.`**, nu depinde de starea inițială:
```
COMUN\clase\ofacturare_comun.vc2:3811-3821
If Used('rul_temp')
Use In rul_temp
Endif
Select * From trul Into Cursor RUL_TEMP Readwrite
Replace All id_util With gnIdUtil, sters With 0
...
lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.)
```
Deci: dacă `trul` a fost gol la încărcare (pasul 1), rămâne gol și la scriere — codul **conservă**
starea, nu o corectează și nu o strică. (Contrast: editorul generic de jurnal contabil,
`afisjurcom.do_modifica`, `COMUN\clase\comun.vc2:2370-2482`, are un flag explicit `llRul` setat doar
dacă `Reccount(lcCursor)>0` la încărcarea inițială din `vrul_tot` — dar calea de factură nu folosește
acest flag deloc, e mereu `.T.`, ceea ce confirmă din nou că absența rândurilor din `RUL` nu e
tratată ca eroare de nicio ramură a codului.)
Originea rândurilor din `RUL` e deci strict la **crearea/finalizarea notei**, nu la editare —
`PACK_CONTAFIN.finalizeaza_modificare_nota` (apelat și la creare, și la editare) doar re-scrie ce
primește; nu am găsit nicio ramură condiționată de `tip`/`ntip` care să decidă "acest tip de
document trebuie să aibă rulaje" — decizia e implicită, dată de **ce conturi apar în notă**, nu de
tipul documentului.
### 3. Rolul lui `IN_STOC` în `ActualizeazaVerdictActRul`
`COMUN\clase\omodificari.vc2:13045-13146`. Verdictul ACT/RUL are trei stări, toate **informative,
niciodată eroare**:
```
COMUN\clase\omodificari.vc2:13129-13139
DO CASE
CASE !m.llVerdictSigur
lcVerdict = 'Verdict ACT/RUL: nu se aplica (informativ, date de import)'
CASE Abs(This.nTotalActRon - This.nTotalRulRon) <= 0.02
lcVerdict = 'Verdict ACT/RUL: sincronizat (informativ)'
OTHERWISE
lcVerdict = 'Verdict ACT/RUL: divergent (informativ, nu e eroare)'
ENDCASE
```
`in_stoc` corectează doar **suma** comparată (exclude valoarea liniilor nestocate din articolele
facturii, convertită în RON, din totalul RUL — `tvd` unde `Nvl(in_stoc,1) = 0`, linia 13111), nu
decide dacă documentul "trebuie" să aibă rulaje. Nu există în această metodă (verificat integral,
liniile 13045-13146, nu doar grep) nicio ramură specifică pentru `RUL = 0` pe tip 4 — cazul cade pur
și simplu în "divergent (informativ, nu e eroare)" dacă `nTotalActRon <> 0` și `nTotalRulRon = 0`, ceea
ce confirmă că design-ul acceptă explicit acest caz ca non-eroare.
### 4. Verificare pe date, read-only, Oracle `MARIUSM_AUTO`/`ROA_CENTRAL`
Conectat cu succes (`sqlplus.exe`, `SET TRANSACTION READ ONLY` ... `ROLLBACK`, fișier `.sql` ASCII,
fără pipe). Cod-urile curente (verificate din `VANZARI`, nu presupuse):
| id_vanzare | tip | cod (curent) | sters | RUL (cnt activ) | ACT (cnt activ) |
|---|---|---|---|---|---|
| 1048 | 1 | 1140918 | 0 | 1 | 5 |
| 1052 | 22 (aviz) | 1140921 | 0 | 4 | 12 |
| 1054 | 4 (factură din aviz) | **1140923** | 0 | **0** | 2 |
| 1055 | 2 | 1140920 | 0 | 1 | 7 |
`id_vanzare = 1054` are `cod` curent `1140923` (confirmă realocarea din test:
`1140910 -> 1140922 -> 1140923`, citită direct din `VANZARI`, nu presupusă).
Detaliu decisiv — conturile efective din `ACT`/`RUL` pentru perechea aviz→factură (avizul 1052 e cel
mai probabil sursă a facturii 1054, pe baza secvenței de cod-uri și a fluxului tip 22→tip 4):
```
ACT pe avizul 1052 (tip 22): scd/scc includ 607/371, 371/378, 378/371, 4428/371, 371/4428, 418/704, 418/4428
RUL pe avizul 1052 (tip 22): 4 rânduri, toate CONT = 371 (cont de stoc)
ACT pe factura 1054 (tip 4): scd/scc = 4111/418 (305 lei) și 4428/4428 (52.93 lei) -- NICIUN cont 371
RUL pe factura 1054 (tip 4): 0 rânduri
```
Avizul e cel care mișcă efectiv contul de stoc (`371`) și de aceea are rânduri în `RUL` (care
urmărește exclusiv cantități pe conturi de stoc — vezi și `cant`/`cante` din `trul`, folosite ca
atare în `ActualizeazaVerdictActRul:13102`). Factura emisă din acel aviz nu mai atinge `371` deloc —
transformă doar creanța provizorie (`418`) în creanță fermă (`4111`) și TVA neexigibilă (`4428`) în
TVA colectată (`4428`). N-are, structural, ce rând de stoc să scrie.
Zero tranzacții deschise la final (`ROLLBACK` executat, `SET TRANSACTION READ ONLY` respectat pe tot
scriptul).
## Ce am dedus (nu verificat direct, dar consistent cu toate dovezile de mai sus)
- Regula generală: `RUL` se scrie doar pentru documentele/notele care conțin mișcare pe cont de
stoc (aviz, NIR, bonuri de consum etc.); facturile "de închidere" (emise din aviz, sau orice
document care doar transformă o creanță provizorie într-una fermă) nu vor avea niciodată rânduri
în `RUL`, indiferent câte documente de acest fel verifici — nu e o particularitate a lui
`id_vanzare = 1054`, ci a tipului de operațiune contabilă.
- Aserția de la `test_s8_matrice_surse.prg:308` (`Reccount(trul) > 0` obligatoriu după editare) e
probabil corectă ca test general "rulajele nu trebuie distruse de editare" pentru documentele care
AU avut rulaje înainte de editare, dar e o presupunere greșită aplicată universal — pentru tip 4
(și, prin extensie, orice tip de document care nu atinge cont de stoc) condiția trebuie relaxată
la "dacă documentul avea rulaje înainte, tot le are și după" sau pur și simplu exclusă pentru
tip = 4.
## Fișiere atinse
Niciunul (misiune read-only). Fișiere citite: `COMUN\programe\ofacturare_editare.prg`,
`COMUN\clase\omodificari.vc2`, `COMUN\clase\comun.vc2`, `COMUN\clase\ofacturare_comun.vc2`,
`COMUN\docs\PACK_CONTAFIN.pck`. Interogări Oracle read-only pe `MARIUSM_AUTO`@`ROA_CENTRAL`, cu
`ROLLBACK` la final.