docs: cercetarile comune trec in COMUN, reziduul #6 dispare, progres.md la zi
Curatenie ceruta dupa inchiderea lui #6. Folderul cercetare\ NU se putea sterge in bloc: plan_13 se sprijina pe el cu 85 de trimiteri, deci e baza de dovezi a planului aflat in lucru. Impartirea: - 14 cercetari trans-proiect trec in COMUN\docs\cercetare\ - valuta si curs, TVA/VANZARI, consumatorii VANZARI din toata suita, integrarile #10/#11/#12, watchdog VFP, proiectarea Oracle a lui S5, view-ul VVANZARI_ARTICOLE. Nu sunt ale ROAFACTURARE, iar #10/#11/#12 se reiau chiar din ele. - 20 de rapoarte de executie ale lui #6, nereferite de nimic viu, sterse. - 91 raman, neatinse. Trimiterile catre handoff-urile si diff-urile intermediare deja desfiintate au fost curatate peste tot (39 de fisiere): 50 catre handoff-uri, 37 catre diff-uri aplicate, plus caile celor mutate in COMUN. Zero trimiteri rupte ramase. progres.md preia rolul de predare: ce ramane din #6 (cele sase documente parazite, cele doua esecuri reale din S8 pe factura din aviz), cifrele de test citite din log, si cele doua capcane de mediu platite - .FXP vechi executat in locul .prg-ului, si GETFONT() care atarna un formular instantiat fara goApp. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Briefing — S5, testul cu scriere reala in Oracle
|
||||
|
||||
Misiune pentru un agent proaspat. Se citeste **impreuna cu** `docs\handoff_s5.md` (starea blocului) si
|
||||
Misiune pentru un agent proaspat. Se citeste **impreuna cu** handoff intermediar (sters) (starea blocului) si
|
||||
`COMUN\docs\reguli_lucru.md` (regulile de livrare si testare). Nu relua cercetarea — e facuta.
|
||||
|
||||
## De ce exista acest test
|
||||
@@ -66,7 +66,7 @@ linia finala a suitei (`REZULTAT` sau `done`, dupa tipar).
|
||||
|
||||
## Aprobare si costuri
|
||||
|
||||
**Scrierea reala e aprobata de Marius** (09.08.2026), aprobarea e consemnata in `handoff_s5.md`.
|
||||
**Scrierea reala e aprobata de Marius** (09.08.2026), aprobarea e consemnata in handoff intermediar (sters).
|
||||
**Consuma date de test ireversibil**: `cod`-ul documentului se realoca la fiecare salvare (la testul
|
||||
precedent, `1140886 -> 1140893 -> 1140894`). Alege un document de test, **nu** unul folosit ca baza de
|
||||
regresie de alte suite daca poti evita, si **consemneaza in raport `cod`-urile consumate**.
|
||||
@@ -88,7 +88,7 @@ regresie de alte suite daca poti evita, si **consemneaza in raport `cod`-urile c
|
||||
1. `COMUN\utile\Teste\editare_factura\test_s5_scriere_reala.prg` — suita.
|
||||
2. `D:\ROA\ROAFACTURARE\docs\cercetare\rec_s5_scriere_reala.md` — raportul: ce s-a dovedit, ce nu,
|
||||
`SELECT`-urile de verificare cu rezultatele lor, `cod`-urile consumate, cifrele din loguri.
|
||||
3. `D:\ROA\ROAFACTURARE\docs\diff_s5_test_scriere_reala.patch` — diff-ul.
|
||||
3. diff aplicat (sters) — diff-ul.
|
||||
|
||||
Raspunsul catre orchestrator e **scurt**: „GATA" + cifrele + ce nu s-a dovedit. **Nu trimite raportul
|
||||
in text** — el sta pe disc.
|
||||
@@ -96,6 +96,6 @@ in text** — el sta pe disc.
|
||||
## Predarea contextului (REGULA ZERO)
|
||||
|
||||
Daca ajungi la **~200-250k** context: **opreste-te**, adu tot la o stare consistenta pe disc, scrie
|
||||
`D:\ROA\ROAFACTURARE\docs\handoff_s5_scriere_reala.md` cu **starea** (ce e facut, ce nu, ce e
|
||||
handoff intermediar (sters) cu **starea** (ce e facut, ce nu, ce e
|
||||
periculos: tranzactie deschisa, proces viu, date consumate), si anunta. Nu continua „ca mai e putin" —
|
||||
si **nu lasa niciodata o tranzactie deschisa** in Oracle.
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
# Contul inregistrat pe o linie de vanzare, cu/fara politica de pret
|
||||
|
||||
**Raspuns scurt**: nu exista, nicaieri in codul cercetat (VFP `ofacturare*` + Oracle
|
||||
`pack_facturare`), un "cont de venit" (707/704/706/708) legat de linia de factura. Singurul cont
|
||||
propagat pe linie e coloana `CONT` din `VANZARI_DETALII`/`VANZARI_DETALII_TEMP` (varchar 4
|
||||
caractere) — si aceasta e contul de **gestiune/stoc** (371 marfuri, 301-303 materii prime, 357
|
||||
custodie etc.), folosit pentru descarcarea de gestiune, nu un cont de venit. El **nu vine din
|
||||
politica de pret** (`CRM_POLITICI_PRET_ART` nu are coloana `CONT` — verificat, nicio
|
||||
`CREATE`/`ALTER TABLE CRM_POLITICI_PRET_ART ADD CONT` in `D:\ROA\DATABASE\SCRIPTURI_CLAR`), ci din
|
||||
nomenclatorul de articole si din lotul de stoc ales. Asta inseamna ca "adaugarea directa din
|
||||
nomenclator, fara politica de pret" **nu schimba mecanismul de completare a acestui camp** — el
|
||||
oricum nu depinde de politica azi. Ramane neverificat unde/daca se decide efectiv un cont de venit
|
||||
707/704/706/708 pentru nota contabila (nu e in `pack_facturare`).
|
||||
|
||||
## 1. Unde e stocat / de unde se ia campul `CONT`
|
||||
|
||||
- **Tabel/coloana tinta**: `VANZARI_DETALII_TEMP.CONT` si `VANZARI_DETALII.CONT`, populate prin
|
||||
`pack_facturare.adauga_articol_factura` / `_deviz` / `_stoc`
|
||||
(`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql:4690,4711,4735` / `:4761,4792,4814` /
|
||||
`:5013,5247,5277`).
|
||||
- **Sursa 1 — `NOM_ARTICOLE.CONT`** (prin view `vnom_articole`/`vnom_articole_crm`): coloana `a.cont`
|
||||
e adusa in grila de cautare a articolelor, `COMUN\programe\ocautare.prg:1671,1683,1687` (`caut_articol`,
|
||||
folosit de formularul unificat de facturare la alegerea articolului). Confirmata ca fiind pe
|
||||
`NOM_ARTICOLE` prin `alter table NOM_ARTICOLE add ... A.CONT ...` (`D:\ROA\DATABASE\SCRIPTURI_CLAR\2019\12\ff_2019_12_20_02_COMUN.sql:12`, coloana veche, prezenta din 2009-2010).
|
||||
- **Sursa 2 — `STOC.CONT`** (contul de pe lotul de stoc): `pack_facturare.cursor_gestiuni_articol`
|
||||
(`ff_...:4358-4452`) — `SELECT ... A.CONT ... FROM STOC A2 ...` — folosit cand articolul e
|
||||
**gestionabil** si se alege un lot din stoc (`frm_facturare_articole.do_alege_stoc`,
|
||||
`COMUN\clase\ofacturare.vc2:13239-13345`, care seteaza `poArticol.Cont = Alltrim(Cont)` la
|
||||
`:13345` din cursorul intors de Oracle).
|
||||
- **Sursa 3 — `NOM_GESTIUNI.CONT`**: fallback cand nu exista lot de stoc, vezi punctul 2
|
||||
(`cursor_gestiuni_articol_stoc0`).
|
||||
- **Politica de pret** (`CRM_POLITICI_PRET_ART`): are `PRET`, `PROC_TVAV`, `ID_VALUTA`,
|
||||
`PRETFTVA` (vazute in `adauga_articol_factura`, declaratiile `V_PRET`, `V_PROC_TVAV` etc. la
|
||||
`ff_...:5033-5036`) — **nicio coloana de cont**. Cautarea in `SCRIPTURI_CLAR` pentru
|
||||
`ALTER TABLE CRM_POLITICI_PRET_ART ADD ... CONT` nu a gasit nimic.
|
||||
- Nu exista `CONT_VENIT`/`ID_CONT_VENIT`/`COD_CONT` nicaieri in
|
||||
`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql` (grep pe fisierul intreg, 17020 linii — zero
|
||||
potriviri) si nici in `NOM_ARTICOLE`/`CRM_POLITICI_PRET_ART` (cautat in `SCRIPTURI_CLAR`).
|
||||
|
||||
## 2. Cum se decide efectiv la scriere — `cursor_gestiuni_articol` / `_stoc0`
|
||||
|
||||
Cand articolul e gestionabil si exista stoc, `cursor_gestiuni_articol` (`ff_...:4358-4452`) ia
|
||||
contul direct de pe lotul de stoc:
|
||||
```
|
||||
SELECT 0 AS ALES, A.ID_GESTIUNE, A.CANTITATE, A.CONT, ...
|
||||
FROM (SELECT ... A2.CONT, ... FROM STOC A2 ...) A
|
||||
LEFT JOIN NOM_GESTIUNI B ON A.ID_GESTIUNE = B.ID_GESTIUNE
|
||||
```
|
||||
— `A.CONT` = `STOC.CONT`, fara nicio alta sursa, fara fallback (daca lotul de stoc are `CONT`
|
||||
`NULL`, ramane `NULL`).
|
||||
|
||||
Cand articolul e gestionabil dar **nu exista stoc** (optiunea `RF_FACTURARE_FARA_STOC = 1`),
|
||||
`cursor_gestiuni_articol_stoc0` (`ff_...:4459-4558`) foloseste un lant `NVL2` explicit
|
||||
(`ff_...:4472-4473`):
|
||||
```sql
|
||||
CAST(NVL2(B.CONT, B.CONT, NVL2(A.CONT, A.CONT, '371')) AS VARCHAR2(4)) AS CONT,
|
||||
```
|
||||
unde `B` = `NOM_GESTIUNI` (contul implicit al gestiunii) si `A.CONT` = ultimul cont vazut in
|
||||
`STOC` pentru articol (an curent/precedent). Ordinea reala: **cont gestiune -> ultimul cont din
|
||||
stoc -> `'371'` hardcodat**. Acesta e singurul loc din pachet cu un `COALESCE`/`NVL2` in cascada
|
||||
pe `CONT`, si singurul cu un default hardcodat.
|
||||
|
||||
`adauga_articol_factura` (varianta apelata din `frm_facturare_articole.do_scrie_articole`, params
|
||||
la `ff_...:4998-5024`) **nu recalculeaza** contul — il primeste ca parametru `V_CONT` si il scrie
|
||||
ca atare (`V_CONT2 := V_CONT` daca `V_CONT <> 'XXXX'`, altfel ramane `NULL` — `ff_...:5044-5046`,
|
||||
`V_CONT2` la INSERT `ff_...:5277`). `'XXXX'` e sentinela VFP pentru "fara valoare" — vezi
|
||||
`COMUN\clase\ofacturare.vc2:6963,7123,7992` (`poDateGestiuneDest.Cont = Nvl(loCauta.Cont,[XXXX])`).
|
||||
Aceeasi logica de trecere directa, fara recalcul, e in `adauga_articol_factura_deviz`
|
||||
(`ff_...:4675-4745`, `V_CONT` scris direct in `CONT`, fara sentinela `'XXXX'`, fara `NVL`).
|
||||
|
||||
## 3. Precedent ROAAUTO — "Alte servicii" (articol din nomenclator brut, fara politica de pret)
|
||||
|
||||
Cursorul `lcCursorDeviz` (`ROAAUTO\Programe\oproceduri_devize.prg:880-887`) **nu are coloana
|
||||
`Cont`**. `crsvanztemp` are `Cont c(4)` (`:1190-1192`) dar `INSERT INTO crsvanztemp(...)` de la
|
||||
`:1201-1206` **nu o include** in lista de coloane si nici in `SELECT`-ul sursa — ramane la
|
||||
valoarea implicita de camp caracter needatat, adica blank. La apel:
|
||||
```
|
||||
['] + Alltrim(Nvl(poArticol.Cont,'')) + [',] + ... -- oproceduri_devize.prg:1256
|
||||
```
|
||||
trimite un literal `''` (gol) catre `adauga_articol_factura_deviz(..., V_CONT IN NUMBER, ...)`
|
||||
(`ff_...:4690`). Un literal `''` convertit implicit la `NUMBER` devine `NULL` in Oracle; `V_CONT`
|
||||
ajunge `NULL` si e scris direct in `VANZARI_DETALII_TEMP.CONT` (`ff_...:4735`), fara `NVL`, fara
|
||||
fallback. **Concluzie**: liniile "Alte servicii" din ROAAUTO (articol real, fara politica de pret,
|
||||
pret tastat manual — vezi `roaauto_articole_lista_preturi.md`) ajung cu `CONT = NULL` in Oracle.
|
||||
Nu exista in cod niciun raspuns explicit "cont pentru articol fara politica" — rezultatul e pur si
|
||||
simplu absenta valorii, nu o valoare calculata.
|
||||
|
||||
## 4. Gestionabile vs. negestionabile
|
||||
|
||||
Difera **calea**, nu neaparat sursa initiala:
|
||||
- **Gestionabil** (`poArticol.gestionabil <> 0`): `frm_facturare_articole.do_adauga_articol`
|
||||
(`COMUN\clase\ofacturare.vc2:12871-12896`) cere alegerea unui lot/gestiune prin `do_alege_stoc`,
|
||||
care suprascrie `poArticol.Cont` cu valoarea din `cursor_gestiuni_articol[_stoc0]` (punctul 2) —
|
||||
deci `STOC.CONT`/`NOM_GESTIUNI.CONT`, nu `NOM_ARTICOLE.CONT`.
|
||||
- **Negestionabil** (`poArticol.gestionabil = 0`) sau `gnScadereStoc = 0`: se instantiaza
|
||||
`frm_articol_factura` direct (`:12871-12880`), fara trecere prin `do_alege_stoc` — `poArticol.Cont`
|
||||
ramane cel citit initial la cautarea articolului, adica `NOM_ARTICOLE.CONT` (punctul 1, sursa 1),
|
||||
neschimbat.
|
||||
|
||||
## 5. Ce se intampla daca nu se gaseste niciun cont
|
||||
|
||||
- Nicio exceptie/`RAISE_APPLICATION_ERROR` legata de `CONT` in tot pachetul (spre deosebire de
|
||||
cota de TVA, unde lipsa produce explicit `FACT-012`/`FACT-013`/`FACT-018`,
|
||||
`ff_...:5151-5153,5184-5187,5203-5206`).
|
||||
- **Gestionabil, cu stoc**: `CONT` = `STOC.CONT`; daca acesta e `NULL` in stoc, ramane `NULL` —
|
||||
fara fallback (punctul 2, `cursor_gestiuni_articol`).
|
||||
- **Gestionabil, fara stoc** (`RF_FACTURARE_FARA_STOC=1`): fallback pana la `'371'` hardcodat
|
||||
(punctul 2, `cursor_gestiuni_articol_stoc0`).
|
||||
- **Negestionabil / articol adaugat fara trecere prin gestiune** (inclusiv "Alte servicii" ROAAUTO):
|
||||
`CONT` ramane ce a venit din `NOM_ARTICOLE.CONT`; daca e gol, `Nvl(poArt.Cont,'')` -> `''` ->
|
||||
`NULL` in Oracle (`adauga_articol_factura`, sentinela `'XXXX'` la `ff_...:5044-5046`) — linie
|
||||
scrisa **fara cont**, fara eroare.
|
||||
|
||||
## Neverificat
|
||||
|
||||
- Unde (daca undeva) se determina un **cont de venit propriu-zis** (707/704/706/708) pentru nota
|
||||
contabila a vanzarii — nu e in `pack_facturare`; grep pentru `707`/`704`/`706`/`708` in
|
||||
`ff_2026_08_06_10_COMUN_PACK_FACTURARE.sql` si in `ROAFACTURARE\Programe`/`COMUN\programe\ofacturare_comun.prg`
|
||||
nu a gasit nimic. Probabil intr-un pachet de contabilitate/note contabile separat, neinclus in
|
||||
scriptul analizat — ar necesita identificarea acelui pachet (posibil in ROACONT sau un
|
||||
`pack_contabilitate`/`pack_note_ct`) si urmarirea generarii notei contabile din `VANZARI`/`VANZARI_DETALII`.
|
||||
- Continutul exact al coloanei `NOM_ARTICOLE.CONT` pentru articole de tip "serviciu" (daca e
|
||||
populata cu conturi de cheltuiala/productie 6xx/3xx sau lasata goala) — ar necesita o interogare
|
||||
pe schema Oracle live, in afara bugetului acestei cercetari (doar cod static disponibil).
|
||||
- Rolul exact al `ID_VENCHELT`/`NOM_VENIT_CHELTUIELI` (parametru la nivel de `ACT`/factura, vazut
|
||||
la `ff_...:191,1885` si in `initializeaza_date_factura`) — pare o clasificare
|
||||
venituri/cheltuieli la nivel de document, nu un cont de venit per linie; nu am urmarit
|
||||
consumatorul lui pana la capat (posibil in raportare, nu in inregistrarea contabila).
|
||||
@@ -59,7 +59,7 @@ directa `contabilizeaza_articol` in `proceduri_acnpro.prg`: zero rezultate). Not
|
||||
documentului ACN o scrie **`pack_acn.salveaza_regdoc`**, o procedura complet separata, specifica ACN,
|
||||
apelata cu parametri proprii (`?.id_articol, ?.id_locatia, ?.id_valuta, ?.id_client, ?.id_contract,
|
||||
?.pret, ?.curs, ?.cantitate, ?.valval, ?.tvaval, ?.totval, ...`) — **fara `id_pol`** in lista de
|
||||
parametri. Confirmat si de raportul deja existent `docs\cercetare\import_roris_roaacnpro.md`
|
||||
parametri. Confirmat si de raportul deja existent `COMUN\docs\cercetare\import_roris_roaacnpro.md`
|
||||
(sectiunea 3): "**nicio procedura Oracle stocata (`pack_*`) nu e apelata in etapa de import** ...
|
||||
acestea sunt apelate abia la salvarea finala", si articolele/preturile vin din dialoage de calcul tarife
|
||||
proprii ACN (`frm_calcul_tranzit`, `vctr_articole2`), nu din `CRM_POLITICI_PRET_ART`.
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
# Investigatie: discount pe articol (linie de factura) — ROAFACTURARE
|
||||
|
||||
Intrebare: discountul pe articol e azi doar procentual, sau exista si discount in valoare
|
||||
absoluta pe unitate / pe linie?
|
||||
|
||||
## 1. Model de date — DISCOUNT / DISCOUNT_UNITAR
|
||||
|
||||
**Concluzie**: Exista deja o coloana de discount **in valoare absoluta pe unitate**
|
||||
(`DISCOUNT_UNITAR`) pe `VANZARI_DETALII` (si pe `VANZARI_DETALII_TEMP`, tabela de lucru din care
|
||||
se compune factura), pe langa discountul de document `VANZARI.DISCOUNT` (valoare absoluta
|
||||
rezultata dintr-un procent aplicat la baza, nu procent stocat). Exista si un flag boolean
|
||||
`VANZARI.DISCOUNT_EVIDENTIAT`.
|
||||
|
||||
**Dovezi**:
|
||||
- Tip coloana: `alter table VANZARI_DETALII modify discount_unitar NUMBER(22,6);` /
|
||||
`alter table VANZARI_DETALII_TEMP modify discount_unitar NUMBER(22,6);` /
|
||||
`alter table CRM_POLITICI_PRET_ART modify discount_unitar NUMBER(22,6);` —
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2024\06\ff_2024_06_13_02_COMUN_FACTURARE.sql:3,9,16`. Precizia
|
||||
`(22,6)` e cea folosita la coloane de pret/valoare, nu la procente.
|
||||
- Exista si la nivel de politica de pret (`CRM_POLITICI_PRET_ART.DISCOUNT_UNITAR`), deci
|
||||
discountul unitar poate proveni din politica de pret a clientului, nu doar tastat pe linie.
|
||||
- Coloana e folosita direct ca scadere din pret: `A.PRET - NVL(A.DISCOUNT_UNITAR, 0) AS PRET` —
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:3315,3500`.
|
||||
- Document-level: `v.discount as disc_fara_tva` / `v.discount_evidentiat` —
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2011\08\ff_2011_08_30_02_FACTURARE.sql:36-42,251-252,267,291`.
|
||||
Discountul document e o valoare (lei/valuta), calculata din procent tastat de operator x baza
|
||||
(vezi punctul 3), nu un procent stocat pe `VANZARI`.
|
||||
|
||||
## 2. VFP — grid-uri de linii factura (`frm_facturare_articole` si `frm_facturare_articole2`)
|
||||
|
||||
**Concluzie**: Ambele forme au coloane de grid pentru discountul unitar **in valoare absoluta**,
|
||||
cu etichete explicite "Discount unitar cu TVA" / "Discount unitar in valuta fara TVA". In
|
||||
`frm_facturare_articole` (forma standard) aceste coloane sunt read-only in grid (afisare, nu
|
||||
editare directa pe linie); in `frm_facturare_articole2` (forma "noua", optionala) sunt editabile
|
||||
si exista in plus o coloana de **procent pe linie** ("Procent discount", legata de campul
|
||||
`procdisc`).
|
||||
|
||||
**Dovezi**:
|
||||
- `frm_facturare_articole`: `Column5.ControlSource = "discountctva"`, `Column5.Name =
|
||||
"cDiscountCTva"`, `Column5.ReadOnly = .T.` si `Column9.ControlSource = "vdiscountftva"`,
|
||||
`Column9.Name = "cVdiscountftva"` (fara `ReadOnly`, deci editabil implicit) —
|
||||
`D:\ROA\ROAFACTURARE\COMUN\clase\ofacturare.vc2:12311-12317, 12340-12345`. Header-e:
|
||||
`Caption = "Discount unitar cu TVA"` (`:12409`), `Caption = "Discount unitar in valuta fara
|
||||
TVA"` (`:12546`).
|
||||
- `frm_facturare_articole2`: `Column5.Name = "cDiscountCTva", Column5.ReadOnly = .F.`
|
||||
(`:16656-16657`), `Column9.Name = "cVdiscountftva", Column9.ReadOnly = .F.` (`:16687-16688`),
|
||||
plus `Column14.ControlSource = "procdisc"`, `Column14.Name = "cProcentDiscount"`,
|
||||
`Column14.Format = "RK"`, `Column14.InputMask = "99 999.99"`, `Column14.ReadOnly = .F.`
|
||||
(`:16720-16727`), header `Caption = "Procent discount"` (`:16934-16940`).
|
||||
- Vizibilitate conditionata: nu de `poDate.tip` direct, ci de `poDate.in_valuta` —
|
||||
`If poDate.in_valuta = 0 ... RemoveObject([cVdiscountftva]) ... Else ...
|
||||
RemoveObject([cDiscountctva])` — `ofacturare.vc2:15269-15278` (pattern analog si la `:19065`
|
||||
pentru `frm_facturare_articole2`).
|
||||
- `frm_facturare_articole2` e optionala, activata prin `gnFacturareNou = 1` cu un dialog Da/Nu
|
||||
("Facturare noua (DA) sau standard (NU)?") — `COMUN\programe\ofacturare.prg:87-93`, instantiata
|
||||
la `:929` (`lcObject = [frm_facturare_articole2]`).
|
||||
|
||||
## 3. Calculul + `discount_evidentiat`
|
||||
|
||||
**Concluzie**: `DISCOUNT_UNITAR` se scade direct din pretul unitar **fara TVA**, in valuta
|
||||
documentului, inainte de a se aplica TVA-ul, apoi se inmulteste cu cantitatea. Flagul
|
||||
`DISCOUNT_EVIDENTIAT` schimba doar mecanismul aritmetic (scade discountul din valoarea deja
|
||||
calculata vs. din pretul unitar rotunjit), nu semantica — discountul ramane o valoare absoluta pe
|
||||
unitate in ambele ramuri. In VFP, checkbox-ul corespunzator e etichetat "Se pune in evidenta
|
||||
discount-ul pe articole in notele contabile si pe factura" — adica discountul e afisat separat pe
|
||||
document/nota contabila vs. absorbit tacit in pret.
|
||||
|
||||
**Dovezi** (`FUNCTION calculeaza_total_fara_tva_fact`,
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:15794-15847`):
|
||||
|
||||
```
|
||||
IF V_DISCOUNT_EVIDENTIAT = 1 THEN
|
||||
V_SUMA_FARA_TVA := ROUND((ROUND(curs*PRET,...) - DIFERENTA)*CANTITATE,...)
|
||||
- ROUND(ROUND(curs*NVL(DISCOUNT_UNITAR,0),...)*CANTITATE,...)
|
||||
ELSE
|
||||
V_SUMA_FARA_TVA := ROUND((ROUND(curs*ROUND(PRET,...),...)
|
||||
- ROUND(curs*ROUND(NVL(DISCOUNT_UNITAR,0),...),...) - DIFERENTA)*CANTITATE,...)
|
||||
```
|
||||
|
||||
Aceeasi structura simetrica in `calculeaza_total_tva_fact` (`:15899-15944`). In VFP, sinteza
|
||||
corespunzatoare: `valdiminuatftva WITH poArticol.pretftva - NVL(poArticol.discount_unitar,0)` —
|
||||
`ofacturare.vc2:13126`, conversia cu-TVA: `discount_unitar_ctva =
|
||||
discount_unitar*(proc_tvav-1) + discount_unitar` — `:13635-13636`. Checkbox:
|
||||
`ADD OBJECT 'ck_discountevidentiat' AS _checkbox WITH ... Caption = "Se pune in evidenta
|
||||
discount-ul pe articole in notele contabile si pe factura", ControlSource =
|
||||
"poDate.discount_evidentiat"` — `:11300-11305`.
|
||||
|
||||
## 4. Oracle — parametrii `adauga_articol_factura`
|
||||
|
||||
**Concluzie**: procedura primeste discountul ca parametru numeric absolut
|
||||
`V_DISCOUNT_UNITAR IN NUMBER` si il scrie direct in `VANZARI_DETALII_TEMP.DISCOUNT_UNITAR`, fara
|
||||
nicio transformare procent->valoare. Discountul de document (`VANZARI.discount`) e separat,
|
||||
aplicat/gestionat la alt nivel (agregare pe factura, cf. `do_calculeaza_discount` in VFP).
|
||||
|
||||
**Dovezi**: semnatura completa
|
||||
`PROCEDURE adauga_articol_factura(V_ID_TEMP IN NUMBER, ... V_CANTITATE IN NUMBER,
|
||||
V_DISCOUNT_UNITAR IN NUMBER, V_CONT IN VARCHAR2, ...)` —
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:4972-4998`,
|
||||
parametrul `V_DISCOUNT_UNITAR` la linia `4986`;
|
||||
`INSERT INTO VANZARI_DETALII_TEMP (... DISCOUNT_UNITAR ...) VALUES (... V_DISCOUNT_UNITAR ...)` —
|
||||
`:5219, 5249`.
|
||||
|
||||
## 5. Discount unitar in valoare absoluta — exista deja in suita
|
||||
|
||||
**Concluzie**: Da, exista deja in toata suita ROA — nu doar "conceptual", ci implementat si
|
||||
cablat de la Oracle pana la grid. `COMUN\clase\ofacturare.vc2` (fisierul verificat pentru
|
||||
ROAFACTURARE) e literalmente acelasi fisier partajat cu
|
||||
`D:\ROA\ROAGEST\COMUN\clase\ofacturare.vc2` si `D:\ROA\ROAACNPRO\COMUN\clase\ofacturare.vc2`
|
||||
(confirmat prin grep pe ambele arbore), la fel `pack_facturare`. Nu a fost nevoie de o cautare
|
||||
separata in alt produs — e literalmente acelasi cod, aceeasi coloana.
|
||||
|
||||
**Dovezi**: `discount_unitar`/`discountunitar` apare identic in
|
||||
`D:\ROA\ROAGEST\COMUN\clase\ofacturare.vc2`, `D:\ROA\ROAGEST\COMUN\clase\ofacturare_comun.vc2`,
|
||||
`D:\ROA\ROAGEST\COMUN\programe\ofacturare*.prg`, `D:\ROA\ROAACNPRO\COMUN\clase\ofacturare.vc2` si
|
||||
`D:\ROA\ROAACNPRO\COMUN\clase\ofacturare_comun.vc2`; SQL-uri de discount identice (ex.
|
||||
`v.discount as disc_fara_tva`) gasite si in
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2021\02\ff_2021_02_03_01_VANZARI.sql:19-20,259-260,409-410,
|
||||
481-482,612`.
|
||||
|
||||
## 6. Ce ar presupune un discount unitar in valoare absoluta — inventar (nu solutie, doar puncte de atins)
|
||||
|
||||
- **Coloana tabela**: deja exista (`VANZARI_DETALII.DISCOUNT_UNITAR`, `NUMBER(22,6)`, plus pe
|
||||
`VANZARI_DETALII_TEMP` si `CRM_POLITICI_PRET_ART`) — nimic de adaugat.
|
||||
- **Parametru Oracle**: deja exista (`adauga_articol_factura(... V_DISCOUNT_UNITAR ...)`,
|
||||
`ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:4986`) — nimic de adaugat.
|
||||
- **Coloana grid**: deja exista in ambele forme (`cDiscountCTva`/`cVdiscountftva`); in
|
||||
`frm_facturare_articole` (forma standard, majoritara) e read-only — de decis daca se face
|
||||
editabila pe linie sau ramane doar afisaj derivat din politica de pret / discountul procentual
|
||||
de pe factura.
|
||||
- **Intrare pentru operator**: in forma standard nu s-a gasit un punct unde operatorul tasteaza
|
||||
manual `discount_unitar` per linie la adaugarea articolului — pare alimentat din
|
||||
`CRM_POLITICI_PRET_ART.DISCOUNT_UNITAR` (politica de pret a clientului) sau din redistribuirea
|
||||
discountului procentual de pe factura (`do_calculeaza_discount`, `ofacturare.vc2:13405-13424`).
|
||||
De clarificat fluxul exact inainte de a proiecta un input nou.
|
||||
- **Recalcul**: formulele Oracle (`calculeaza_total_fara_tva_fact`/`calculeaza_total_tva_fact`)
|
||||
deja trateaza `DISCOUNT_UNITAR` ca valoare absoluta — nimic de schimbat aritmetic daca se
|
||||
reutilizeaza calea existenta.
|
||||
- **Rapoarte `.frx`**: nu s-a verificat daca discountul unitar apare pe rapoartele tiparite de
|
||||
factura — necunoscut, de verificat separat.
|
||||
- **eFactura / SAF-T**: nu s-a verificat daca `discount_unitar` e mapat in XML-ul UBL/eFactura sau
|
||||
in declaratia SAF-T — necunoscut, de verificat separat (fisierele `COMUN_EFACTURA*.sql` /
|
||||
`COMUN_SAFT*.sql` contin "discount" dar nu au fost citite).
|
||||
|
||||
## Raspuns scurt la intrebare
|
||||
|
||||
Nu doar procentual: **discountul pe articol exista deja si ca valoare absoluta pe unitate**
|
||||
(`DISCOUNT_UNITAR`, `NUMBER(22,6)`), implementat capat la capat — coloana Oracle pe
|
||||
`VANZARI_DETALII`/`VANZARI_DETALII_TEMP`, parametru in `pack_facturare.adauga_articol_factura`,
|
||||
formule de calcul care scad direct din pret, si coloane de grid in VFP cu eticheta explicita
|
||||
"Discount unitar cu TVA"/"...in valuta fara TVA". Discountul de document (`VANZARI.discount`)
|
||||
ramane procentual-la-origine (tastat ca procent, stocat ca valoare calculata). Ce nu e clar e daca
|
||||
operatorul poate tasta liber discountul unitar pe linie in forma standard
|
||||
(`frm_facturare_articole`, unde coloana e read-only) — in forma "noua" optionala
|
||||
(`frm_facturare_articole2`, `gnFacturareNou=1`) e editabila si are si un procent-pe-linie separat.
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Sursa exacta a valorii `discount_unitar` la adaugarea unui articol in forma standard (politica
|
||||
de pret vs. redistribuire din discountul procentual de pe factura) — nu s-a urmarit tot lantul
|
||||
`do_adauga`/`crsgestarticol`.
|
||||
- Daca `discount_unitar` apare pe rapoartele `.frx` tiparite.
|
||||
- Daca `discount_unitar` e transmis in eFactura (UBL) sau SAF-T.
|
||||
- Cat de folosita e efectiv `frm_facturare_articole2` in productie (e optionala, per sesiune, cu
|
||||
prompt).
|
||||
@@ -1,182 +0,0 @@
|
||||
# Verificare discount pe linie de factura — frm_facturare_articole / VANZARI_DETALII
|
||||
|
||||
Investigatie read-only. Toate liniile citate au fost verificate pe fisierul text real din working
|
||||
copy (`ofacturare.vc2`, 23087 linii, ultima scriere 07.08 22:18) si pe scripturile DDL din
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR`. Nu s-a executat nimic pe baza de date.
|
||||
|
||||
## 1. Confirmare/infirmare afirmatii initiale
|
||||
|
||||
**Concluzie**: toate afirmatiile despre `frm_facturare_articole` sunt corecte, cu linii care se
|
||||
potrivesc exact sau aproape exact. Confirmat via `vfp_symbols.ps1 -Where` ca formularul
|
||||
`frm_facturare_articole` ocupa exact `ofacturare.vc2:10968-15739`.
|
||||
|
||||
**Dovezi**:
|
||||
- `Column5.ControlSource = "discountctva"`, `Column5.Name = "cDiscountCTva"`, `Column5.ReadOnly = .T.`
|
||||
— confirmat la `ofacturare.vc2:12311-12317` (identic cu afirmatia).
|
||||
- `Column9.ControlSource = "vdiscountftva"`, `Column9.Name = "cVdiscountftva"`, **fara** `ReadOnly`
|
||||
— confirmat la `ofacturare.vc2:12340-12345` (identic).
|
||||
- Capete de coloana: `Caption = "Discount unitar cu TVA"` la `:12409`, `Caption = "Discount unitar in
|
||||
valuta fara TVA"` la `:12546` — ambele confirmate exact.
|
||||
- Excludere reciproca pe valuta la `ofacturare.vc2:15269-15278`:
|
||||
```
|
||||
15269 If poDate.in_valuta = 0
|
||||
15270 Thisform.grd_factura.RemoveObject([cVpretFtva])
|
||||
15271 Thisform.grd_factura.RemoveObject([cVdiscountftva])
|
||||
15272 Thisform.grd_factura.RemoveObject([cVvaldiminuatftva])
|
||||
15273 Else
|
||||
15274 Thisform.grd_factura.RemoveObject([cPretFtva])
|
||||
15275 Thisform.grd_factura.RemoveObject([cDiscountctva])
|
||||
```
|
||||
confirmat identic (linii exacte, nu doar apropiate).
|
||||
- `VANZARI_DETALII.DISCOUNT_UNITAR NUMBER(22,6)` — confirmat, dar cu precizare: linia corecta in
|
||||
`ff_2024_06_13_02_COMUN_FACTURARE.sql` e `:3` (nu si `:9`/`:16` cum lasa sa se inteleaga
|
||||
formularea initiala — acelea sunt `VANZARI_DETALII_TEMP` si, respectiv, `CRM_POLITICI_PRET_ART`,
|
||||
vezi punctul 4).
|
||||
|
||||
## 2. Consecinta practica pe ecran
|
||||
|
||||
**Concluzie**: pe factura in lei, coloana vizibila e **"Discount unitar cu TVA"** (`discountctva`)
|
||||
si e **needitabila** in grid (`ReadOnly = .T.`). Pe factura in valuta, coloana vizibila e
|
||||
**"Discount unitar in valuta fara TVA"** (`vdiscountftva`) si **este editabila direct in grid**
|
||||
(nicio proprietate `ReadOnly` setata pe coloana sau pe `Text1`-ul ei → mosteneste default-ul VFP,
|
||||
`.F.`).
|
||||
|
||||
**Dovezi**:
|
||||
- Ramane pe ecran: cand `in_valuta = 0` se elimina cele 3 coloane "V..." (inclusiv
|
||||
`cVdiscountftva`) → ramane `cDiscountCTva`. Cand `in_valuta <> 0` se elimina `cDiscountctva` (si
|
||||
celelalte 3 coloane fara "V") → ramane `cVdiscountftva`. (`:15269-15278`, citat mai sus).
|
||||
- Ca sa nu presupun ca lipsa lui `Column9.ReadOnly` inseamna implicit editabil, am verificat lantul
|
||||
de clase: grid-ul `grd_factura` e `ADD OBJECT 'grd_factura' AS _grdrow` (`:12263`), fara
|
||||
`ReadOnly` la nivel de grid intre `:12263-12364`; clasa `_grdrow` (`_grd_base.vc2:445`) nu
|
||||
seteaza `ReadOnly` nicaieri in propriul body, iar parintele ei `_grdbase`/`_grid` de asemenea nu
|
||||
(singurele 3 aparitii de `ReadOnly` in `_grd_base.vc2` sunt in clasa separata `_grdfooter`,
|
||||
neinrudita). Deci Column9 chiar e editabila.
|
||||
- Confirmare suplimentara: in formularul **`frm_facturare_articole2`** (prototip separat, clasa la
|
||||
`ofacturare.vc2:15741-19355`, NU formularul in productie), aceleasi doua coloane apar cu
|
||||
`ReadOnly` explicit: `Column5.ReadOnly = .F.` (`:16657`) si `Column9.ReadOnly = .F.` (`:16688`) —
|
||||
adica in prototip discountul e editabil in ambele monede direct din grid; in formularul real
|
||||
doar varianta in valuta e editabila din grid.
|
||||
|
||||
## 3. Poate operatorul introduce azi un discount pe linie, si pe ce cale
|
||||
|
||||
**Concluzie**: da, poate — dar nu prin `do_calculeaza_discount` de la
|
||||
`frm_facturare_articole:13405-13424` (asta calculeaza discountul **global pe toata factura**,
|
||||
`Thisform.ndiscfactron`/`ndiscfactval`, nicio legatura cu `discountctva`/`vdiscountftva` pe
|
||||
linie — vezi corectia de la final). Calea reala e formularul **`frm_articol_factura`**
|
||||
(`ofacturare.vc2:1108-2659`), deschis din `do_adauga_articol` la adaugarea unui articol
|
||||
(`:12873`, `ofrmadarticol.Show(1)` doar daca `!tlImplicit`). Acolo exista metoda
|
||||
`frm_articol_factura.do_calculeaza_discount` (`:1874-1976`) legata de 3 controale editabile:
|
||||
`Clb_procent_discount.Text_simplu1` (procent), `Clb_discount_unitar.tx_suma_nat`/`tx_suma_val`
|
||||
(suma in lei / valuta), `Clb_discountctva.tx_suma_nat`/`tx_suma_val` (varianta cu TVA) — toate cu
|
||||
handler `Valid`/`InteractiveChange` care apeleaza `do_calculeaza_discount(valoare, tip)` cu
|
||||
`tip=1` procent, `tip=2` lei, `tip=3` valuta (`:2602-2624`, `:2646-2649`).
|
||||
|
||||
**Lantul, cu linii**:
|
||||
1. Operator tasteaza in unul din campurile de mai sus → `Valid`/`InteractiveChange` →
|
||||
`Thisform.do_calculeaza_discount(valoare, tip)` (`ofacturare.vc2:2602-2649`).
|
||||
2. `do_calculeaza_discount` (`:1874-1976`) scrie in obiectul `poArticol`:
|
||||
`poArticol.discount_unitar`, `discount_unitar_val`, `discount_unitar_ctva`,
|
||||
`discount_unitar_ctva_val` (ex. `:1898-1906`, `:1943-1951`).
|
||||
3. La revenirea in `do_adauga_articol` (`:12813-13086`), `poArticol` e scris in `crsfactura` prin
|
||||
`Gather`/`Replace`:
|
||||
```
|
||||
12956 Replace id_temp With Recno(), codmat With Nvl(poArticol.codmat, Space(50)), ;
|
||||
...
|
||||
12957 discountftva With poArticol.discount_unitar, discountctva With poArticol.discount_unitar_ctva, ;
|
||||
vdiscountftva With Nvl(poArticol.discount_unitar_val, 0), vdiscountctva With Nvl(poArticol.discount_unitar_ctva_val, 0)
|
||||
```
|
||||
(linii `12956-12957`; varianta pentru selectie multipla de articole la `13003-13005`).
|
||||
4. `discount_unitar` initial (inainte de tastare) e preluat din `crsarticole` (cursorul de stoc,
|
||||
populat inainte de deschiderea dialogului) prin `do_initializeaza_articol` (`:13618` si urm.):
|
||||
`toArticol.discount_unitar = Nvl(toArticol.discount_unitar, 0)` (`:13630`) — deci daca stocul /
|
||||
politica de pret vine deja cu un discount populat, acela e valoarea implicita afisata in dialog,
|
||||
pe care operatorul o poate suprascrie.
|
||||
5. Cale suplimentara, directa: pe factura in valuta, cum `cVdiscountftva` e editabil in grid
|
||||
(punctul 2), operatorul poate scrie si direct in celula `vdiscountftva` din `grd_factura` — dar
|
||||
fara niciun `Valid`/`InteractiveChange` propriu definit pentru acea coloana in
|
||||
`frm_facturare_articole` (cautat explicit `cVdiscountftva`/`cDiscountCTva` in intervalul
|
||||
`10968-15739`: singurele hit-uri sunt definitiile de coloana si `RemoveObject`, niciun handler
|
||||
de eveniment) — editarea directa in grid NU declanseaza recalcularea automata a
|
||||
`vvaldiminuatftva`/totaluri, doar modifica valoarea bruta in `crsfactura`.
|
||||
|
||||
## 4. Structura reala a coloanelor de discount pe VANZARI_DETALII
|
||||
|
||||
**Concluzie**: nu exista un `CREATE TABLE VANZARI_DETALII` in `SCRIPTURI_CLAR` (arhiva incepe din
|
||||
2009, iar tabela exista deja atunci — coloana `DISCOUNT_UNITAR` era deja in uz in pachete PL/SQL
|
||||
din 2009, deci a fost creata inainte de arhiva). Singura coloana de discount pe
|
||||
`VANZARI_DETALII`/`VANZARI_DETALII_TEMP` gasita in `SCRIPTURI_CLAR` e **`DISCOUNT_UNITAR`**, si
|
||||
singura modificare de tip/precizie inregistrata e cea din 2024.
|
||||
|
||||
**Dovezi (cronologic, tot ce am gasit cu `DISCOUNT` in contextul acestei tabele)**:
|
||||
- Nu exista niciun `CREATE TABLE VANZARI_DETALII` sau `ALTER TABLE VANZARI_DETALII ADD DISCOUNT...`
|
||||
in toata arhiva `SCRIPTURI_CLAR` (2009-2026). Cel mai vechi hit pe `DISCOUNT_UNITAR` legat de
|
||||
aceasta tabela e o declaratie de variabila `V_DISCOUNT_UNITAR VANZARI_DETALII.DISCOUNT_UNITAR%TYPE`
|
||||
in pachetul `PACK_FACTURARE`, prezenta deja in scripturile din 2009 (ex.
|
||||
`2009\9\ff_2009_09_03_01_FACTURARE_PACK_FACTURARE.sql`) — coloana exista deja atunci.
|
||||
- Singura modificare de precizie gasita: `ff_2024_06_13_02_COMUN_FACTURARE.sql:3` —
|
||||
`alter table VANZARI_DETALII modify discount_unitar NUMBER(22,6);` — si simetric pentru
|
||||
`VANZARI_DETALII_TEMP` la linia `:9`, si pentru `CRM_POLITICI_PRET_ART` (tabela de **politici de
|
||||
pret**) la linia `:16`. Deci forma finala confirmata: **`DISCOUNT_UNITAR NUMBER(22,6)`**, o
|
||||
singura coloana de discount (valoare, nu procent), identica pe toate cele 3 tabele.
|
||||
- Nu exista alte coloane `DISCOUNT%`/`VDISCOUNT%` la nivel Oracle pe `VANZARI_DETALII` — cele patru
|
||||
campuri VFP `discountftva`/`discountctva`/`vdiscountftva`/`vdiscountctva` din `crsfactura` NU au
|
||||
corespondent 1:1 in schema Oracle; la scriere (`Gather`/`Replace` in `do_adauga_articol`, punctul
|
||||
3) doar `discount_unitar` (si varianta cu TVA calculata din el) ajunge, prin campurile
|
||||
intermediare, la coloana unica Oracle.
|
||||
- Convenția de interogare a bazei de dezvoltare, gasita in `COMUN\docs\scripturi-migrare-db.md:36-40`:
|
||||
sursa de referinta pentru DDL e schema de dezvoltare **`MARIUSM_AUTO`** (bazata pe
|
||||
`ROA_CENTRAL`), interogata prin `goExecutor`, niciodata o schema de client. Nu am rulat nimic pe
|
||||
baza — doar raportez conventia, asa cum a cerut sarcina.
|
||||
|
||||
## 5. Coloana de procent de discount pe VANZARI_DETALII / campul procdisc
|
||||
|
||||
**Concluzie**: **nu** exista o coloana de procent de discount pe `VANZARI_DETALII` (doar
|
||||
`DISCOUNT_UNITAR`, o valoare absoluta). Campul `procdisc` din `frm_facturare_articole2` e doar un
|
||||
camp de lucru in grid, **fara nicio scriere in cursorul local si fara corespondent Oracle** —
|
||||
practic un camp scaffolded si neconectat.
|
||||
|
||||
**Dovezi**:
|
||||
- Cautare `DISCOUNT`+`PROCENT`/`PROC` in `ff_2024_06_13_02_COMUN_FACTURARE.sql` (scriptul care
|
||||
fixeaza forma finala a coloanelor de discount): nicio potrivire — confirma ca nu exista un
|
||||
"procent discount" ca si coloana pe `VANZARI_DETALII`.
|
||||
- `procdisc` apare **o singura data** in tot `ofacturare.vc2`: `Column14.ControlSource = "procdisc"`
|
||||
la `:16721`, in interiorul clasei `frm_facturare_articole2` (`15741-19355` — prototip, nu
|
||||
formularul in productie).
|
||||
- Nicio instructiune `Gather`/`Replace ... procdisc With ...` in tot fisierul (cautat pe tot
|
||||
`ofacturare.vc2`) — camp fara sursa de populare in cod.
|
||||
- Toate celelalte aparitii de "procdisc" din fisier sunt de fapt variabila de memorie
|
||||
`gnMemProcDisc` ("memorare procent discount" — o optiune de aplicatie care controleaza daca
|
||||
procentul de discount tastat se retine intre articole, `:2299`, `:2441`, `:12835` etc.), fara
|
||||
legatura cu campul de cursor `procdisc`.
|
||||
- Cautare `PROCDISC` in `SCRIPTURI_CLAR`: doar 2 hit-uri, ambele in scripturi din 2015 pentru
|
||||
tabela de **optiuni firma** (`co_2015_12_09_01_OPTIUNI.sql`, `ff_2015_12_09_01_OPTIUNI.sql`) —
|
||||
legate de aceeasi optiune `gnMemProcDisc`, nu de `VANZARI_DETALII`.
|
||||
|
||||
## Ce era gresit in afirmatiile de mai sus
|
||||
|
||||
- Formularea "linia 3, 9, 16" pentru coloana Oracle `DISCOUNT_UNITAR` grupa laolalta 3 tabele
|
||||
diferite (`VANZARI_DETALII` la `:3`, `VANZARI_DETALII_TEMP` la `:9`, `CRM_POLITICI_PRET_ART` la
|
||||
`:16`) ca si cum ar fi acelasi lucru repetat de 3 ori — corect ca valoare (toate devin
|
||||
`NUMBER(22,6)`), dar sunt 3 tabele distincte, nu 3 confirmari ale aceleiasi coloane.
|
||||
- Cea mai importanta corectie: linia indicata pentru "de unde se scrie discountctva/vdiscountftva
|
||||
— din `do_calculeaza_discount` (`ofacturare.vc2:13405-13424`)" trimite la metoda gresita.
|
||||
`frm_facturare_articole.do_calculeaza_discount` de la acea linie calculeaza discountul **global
|
||||
pe factura** (`Thisform.ndiscfactron`/`ndiscfactval`), nu discountul pe linie. Metoda care chiar
|
||||
calculeaza `discount_unitar`/`discount_unitar_ctva` (sursa reala pentru `discountctva` si
|
||||
`vdiscountftva`) e **`frm_articol_factura.do_calculeaza_discount`**, o metoda cu acelasi nume dar
|
||||
in alta clasa, la `ofacturare.vc2:1874-1976`. Cele doua metode au nume identic dar apartin la
|
||||
doua clase diferite din acelasi fisier — o capcana reala de grep fara indexul de simboluri.
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Nu am verificat daca `crsarticole` (cursorul de stoc din care pleaca `poArticol.discount_unitar`
|
||||
la `do_initializeaza_articol:13630`) e populat vreodata cu un discount nenul direct dintr-o
|
||||
interogare de politica de pret (`CRM_POLITICI_PRET_ART`) inainte de a ajunge in dialogul
|
||||
`frm_articol_factura` — am gasit doar ca acea tabela are aceeasi coloana `discount_unitar`
|
||||
(`NUMBER(22,6)`), nu am urmarit interogarea SQL efectiva care umple `crsarticole`/`crsartselectate`
|
||||
(cod probabil in `Programe/`, in afara `ofacturare.vc2`, netrasat din lipsa de timp alocat).
|
||||
- Nu am confirmat pe date reale (Oracle) daca exista astazi randuri cu `DISCOUNT_UNITAR` populat pe
|
||||
`VANZARI_DETALII` provenind din editarea directa in grid pe factura in valuta (punctul 2/3,
|
||||
ultimul paragraf) — doar am aratat ca acea cale exista in cod, fara handler de recalcul.
|
||||
- Nu am cautat daca `frm_facturare_articole2` (prototipul) e instantiat undeva in productie sau e
|
||||
cu adevarat mort/nefolosit — task-ul l-a framat deja ca "prototip" si am pastrat presupunerea.
|
||||
@@ -1,35 +0,0 @@
|
||||
-- 08.08.2026 Marius Mutu
|
||||
-- VVANZARI_ARTICOLE: liniile unei vanzari (VANZARI_DETALII) cu denumirea articolului, a gestiunii
|
||||
-- si a valutei, pentru gridul de articole din formularul de modificare a notei. Valori brute, fara
|
||||
-- conversie valutara si fara calcule - editarea scrie inapoi exact ce a citit. Filtrul STERS ramane
|
||||
-- pe seama apelantului, ca la VACT_TOT / VRUL_TOT / VRUL_OBINV_TOT.
|
||||
|
||||
CREATE OR REPLACE VIEW VVANZARI_ARTICOLE AS
|
||||
select vd.id_vanzare,
|
||||
vd.id_vanzare_det,
|
||||
vd.id_articol,
|
||||
vd.cantitate,
|
||||
vd.pret,
|
||||
vd.pret_cu_tva,
|
||||
vd.proc_tvav,
|
||||
vd.discount_unitar,
|
||||
vd.id_gestiune,
|
||||
vd.cont,
|
||||
vd.id_valuta,
|
||||
vd.id_jtva_coloana,
|
||||
vd.serie,
|
||||
vd.explicatie,
|
||||
vd.taxcode,
|
||||
vd.lot,
|
||||
vd.sters,
|
||||
na.denumire,
|
||||
na.codmat,
|
||||
ng.nume_gestiune,
|
||||
nv.nume_val
|
||||
from vanzari_detalii vd
|
||||
left join nom_articole na on na.id_articol = vd.id_articol
|
||||
left join nom_gestiuni ng on ng.id_gestiune = vd.id_gestiune
|
||||
left join nom_valute nv on nv.id_valuta = vd.id_valuta;
|
||||
|
||||
exec pack_migrare.UpdateVersiune('ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE');
|
||||
commit;
|
||||
@@ -1,103 +0,0 @@
|
||||
# Predare — deblocarea proprietatilor custom pe frm_modific2024
|
||||
|
||||
Bloc de lucru TERMINAT CU SUCCES (nu la prag de context — predare la incheierea blocului,
|
||||
conform Regula zero).
|
||||
|
||||
## Concluzie
|
||||
|
||||
**Ipoteza principala ("FoxBin2Prg Prg2Bin nu poate crea proprietati noi intr-un .vcx") e
|
||||
INFIRMATA**, cu dovada directa (test izolat, mai jos). Cauza reala era alta, si s-a reparat.
|
||||
|
||||
## Cauza reala, cu dovada
|
||||
|
||||
Proprietatile noi (`larearticolevanzari`, `nidvanzare`, `ntipvanzare`) fusesera adaugate de
|
||||
agentul anterior **doar** in blocul `*<PropValue>` (valorile), dar **lipseau din
|
||||
`*<DefinedPropArrayMethod>`** (lista `*p:` care inregistreaza o proprietate custom ca membru real
|
||||
al clasei). Fara intrarea `*p:`, `Prg2Bin` scrie linia de valoare, dar VFP n-o materializeaza ca
|
||||
proprietate pe obiect — de-asta `PEMSTATUS` intorcea `.F.` desi valoarea aparea in text si
|
||||
supravietuia fidelity-check-ului (fidelity-ul verifica doar ca textul regenerat == textul editat,
|
||||
nu ca proprietatea exista pe obiect).
|
||||
|
||||
Regula era deja documentata **pentru metode** in `COMUN\docs\flux-editare-vfp-text.md:76-78`
|
||||
("Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, ... o arunca
|
||||
tacut") — se aplica identic si proprietatilor (`*p:`), doar ca nu era scrisa explicit acolo. De
|
||||
adaugat separat in acel fisier (nu am facut-o eu, e in afara sarcinii primite).
|
||||
|
||||
## Testul izolat care a transat ipoteza
|
||||
|
||||
Nu am atins `omodificari` pentru test. Am copiat `COMUN\clase\_pf_base.vcx/.vct/.vc2` (clasa
|
||||
`_pfbase`, fara nicio importanta) intr-un folder complet izolat in scratchpad, am adaugat text-only
|
||||
o proprietate noua (`ltestpropnoua`) cu intrare `*p:` corecta, write-back cu `txt2vcx.ps1` (proiect
|
||||
izolat, nu ProjectRoot real), apoi `CREATEOBJECT` + `PEMSTATUS`:
|
||||
|
||||
```
|
||||
PEMSTATUS(ltestpropnoua)=DA valoare=.T.
|
||||
```
|
||||
|
||||
Confirma ca fluxul text->bin **poate** crea proprietati noi, cand sunt inregistrate corect.
|
||||
|
||||
**Bonus gasit tot in acest test**: FoxBin2Prg foloseste o colatie unde `_` sorteaza **dupa**
|
||||
literele obisnuite (nu ordine ASCII simpla pe litere mici) — `nidvanzare` < `nid_set` alfabetic
|
||||
pentru tool, desi `'_' (0x5F) < 'v' (0x76)` in ASCII brut pe litere mici. Confirmat printr-un al
|
||||
doilea test izolat: am scris `*p: nid_set` inaintea lui `*p: nidvanzare` (ordine ASCII) — fidelity
|
||||
check a **picat** cu exact acest motiv; textul canonic din `<staging>\verify\` a aratat ordinea
|
||||
corecta, `nidvanzare` inaintea lui `nid_set`. Coincide cu ordinea deja existenta, corecta, din
|
||||
`*<PropValue>`-ul real al lui `frm_modific2024`. De adaugat in `flux-editare-vfp-text.md` /
|
||||
`foxbin2prg\CLAUDE.md` ca nota separata (nu am facut-o, in afara sarcinii primite).
|
||||
|
||||
## Ce am schimbat in `omodificari.vc2`/`.vcx`/`.vct`
|
||||
|
||||
`COMUN\clase\omodificari.vc2`, clasa `frm_modific2024` (`:6375-15856`), blocul
|
||||
`*<DefinedPropArrayMethod>` — 3 linii `*p:` noi, in ordine alfabetica (colatia tool-ului):
|
||||
- `*p: larearticolevanzari` — linia 6804 (inainte de `lavertizatexigibilizare`)
|
||||
- `*p: nidvanzare` — linia 6811 (inainte de `nid_set`)
|
||||
- `*p: ntipvanzare` — linia 6818 (dupa `ntaxcode`)
|
||||
|
||||
Blocul `*<PropValue>` **nu a fost atins** — valorile erau deja acolo, deja in ordinea corecta,
|
||||
de la agentul anterior.
|
||||
|
||||
Write-back real cu `txt2vcx.ps1 -AllowComun` — **fidelity check OK**. Backup pastrat:
|
||||
`COMUN\clase\omodificari.vc2.pre_proprietati_custom.bak` (starea dinainte de aceasta reparatie,
|
||||
distinct de `.pre_s4runda1.bak` mai vechi).
|
||||
|
||||
**Capcana pe care am picat-o si am reparat-o singura**: prima incercare a folosit
|
||||
`$lines.IndexOf(text_exact)` ca sa gasesc pozitia liniilor `*p:` tinta — a gasit o potrivire
|
||||
falsa mult mai devreme in fisier (alta clasa cu proprietati cu nume asemanator), inserand 3 linii
|
||||
in locul gresit. Am restaurat din backup **inainte** de a rula orice write-back cu starea gresita,
|
||||
am refacut editarea cu index-uri de linie verificate explicit (assert pe continutul exact al
|
||||
liniei), si abia apoi am scris pe disc. Fisierul de pe disc e curat, o singura editare corecta.
|
||||
|
||||
## Verificare finala — PASS complet
|
||||
|
||||
`test_page3_articole.prg` sub `watchdog_vfp.ps1 -AutoDismiss`: exit 0, 0 dialoguri.
|
||||
|
||||
```
|
||||
cod=1140888: PageCount = 3 (asteptat 3), lAreArticoleVanzari = .T. (asteptat .T.), nIdVanzare = 1050 -> PASS
|
||||
cod=1125486: PageCount = 2 (asteptat 2), lAreArticoleVanzari = .F. (asteptat .F.) -> PASS
|
||||
```
|
||||
|
||||
Toate celelalte asertii din suita (verifica_vanzare_nota x3, verifica_coliziune_cod) tot PASS,
|
||||
neschimbate. `PEMSTATUS(loForm,'lAreArticoleVanzari',5)` si `PEMSTATUS(loForm,'nIdVanzare',5)`
|
||||
acum `.T.` (erau `.F.` la predarea anterioara).
|
||||
|
||||
## Starea la predare
|
||||
|
||||
- **Fara commit git/SVN.** `svn status` pe COMUN arata `M` pe `omodificari.vcx`/`.VCT` (write-back
|
||||
real); `.vc2` e `I` (ignorat de SVN, urmarit doar de `comun.git`).
|
||||
- `comun.git status` arata `omodificari.vc2` modificat — diff-ul cumuleaza **toata munca
|
||||
necomisa de azi pe S4 runda 1** (PAGE3, grid, cele 3 proprietati), nu doar reparatia mea; nimic
|
||||
neasteptat.
|
||||
- **Fara tranzactii Oracle deschise** — testul de verificare face doar `SELECT`-uri prin
|
||||
`goExecutor`, zero scriere.
|
||||
- **Niciun proces `vfp9.exe` ramas viu** (verificat, `Get-Process vfp9` gol).
|
||||
- Scratch-ul de test izolat (`_pf_base.vcx` copiat) a ramas doar in
|
||||
`C:\Users\...\scratchpad\testproj\` — in afara working copy, nu necesita curatare.
|
||||
|
||||
## Ce ramane (in afara sarcinii primite azi)
|
||||
|
||||
Pasii 3-5 din `docs\progres.md` sectiunea „#6, S4 runda 1": scoaterea liniilor `[BISECT]`/`[DIAG]`
|
||||
din test, stergerea `test_baseline_isolation.prg` (concluzia lui e nula, vezi handoff anterior),
|
||||
scrierea `docs\diff_s4_runda1_page3.patch` + `docs\cercetare\rec_s4_runda1.md`, actualizarea
|
||||
`COMUN\docs\testare-ui-vfp.md` cu cele trei capcane noi (`DO...WITH` prin referinta, `SET PATH`
|
||||
ROACONT, watchdog fara input real) **plus** cele doua descoperite acum (`*p:` obligatoriu si
|
||||
pentru proprietati, colatia cu `_` dupa litere) — raman pentru runda urmatoare.
|
||||
@@ -185,7 +185,7 @@ sesiune doar pentru asta).
|
||||
alta depanare GUI.
|
||||
3. Daca se rezolva: reruleaza `test_page3_articole.prg` complet, confirma PASS pe toate cazurile
|
||||
(inclusiv `verifica_pagecount_form`), sterge `test_baseline_isolation.prg` + `.fxp` + log-ul lui,
|
||||
scrie diff-ul (`docs\diff_s4_runda1_page3.patch`, `git diff --no-index <bak> <editat>`) si
|
||||
scrie diff-ul (diff aplicat (sters), `git diff --no-index <bak> <editat>`) si
|
||||
raportul (`docs\cercetare\rec_s4_runda1.md`) cerute initial de team-lead.
|
||||
4. Daca team-lead sau alt agent scrie capcana "View Parameter / LOCAL vs PRIVATE" in
|
||||
`testare-ui-vfp.md`, nu o duplica — team-lead a intrebat explicit cine o scrie.
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
# Handoff — test real write-back buton=1 (do_editare_factura)
|
||||
|
||||
Predare la prag de context, conform Regula zero din `CLAUDE.md`. Fara analiza noua aici, doar
|
||||
starea.
|
||||
|
||||
## CORECTIE IMPORTANTA fata de ce stie team-lead acum
|
||||
|
||||
Team-lead a verificat baza INAINTE de ultima rulare si a raportat "`id_vanzare=1048` e neatins,
|
||||
nimic de curatat". **Nu mai e adevarat** - intre timp corectia `LOCAL` -> `PRIVATE` a fost aplicata
|
||||
SI rulata, iar testul **a reusit complet, cu COMMIT real, de doua ori**. Documentul `id_vanzare=1048`
|
||||
**a fost modificat legitim**, exact cum era scopul aprobat de Marius:
|
||||
|
||||
- `cod` a trecut `1140886` -> `1140893` (TEST 1, salvare fara modificari) -> `1140894` (TEST 2,
|
||||
cu explicatia unui rand `ACT` modificata: "NOTA 1" -> "NOTA 1 (test writeback)").
|
||||
- **Cod-ul curent activ in baza pentru acest document este `1140894`**, nu `1140886`.
|
||||
- Randurile vechi (`cod=1140886` si `cod=1140893`) raman in `ACT`/`RUL` cu `STERS=1` - asta e
|
||||
comportamentul normal, prin design (vezi "Fapte stabilite" din `docs\progres.md`).
|
||||
- `VANZARI.total_cu_tva`/`total_fara_tva`/`total_tva`/`id_fact`/`sters` au ramas neschimbate,
|
||||
verificat si din log VFP si independent prin `sqlplus` dupa rulare.
|
||||
- `VANZARI_DETALII` a ramas neatins (verificat, cum era de asteptat pe aceasta cale).
|
||||
|
||||
**Raport complet deja scris**: `docs\cercetare\rec_test_writeback.md` (tabel cu cele 5 verificari
|
||||
pe ambele teste, PASS pe toate, plus istoricul celor 2 incidente si cum s-au rezolvat). Rezultatul
|
||||
a fost deja trimis catre team-lead prin mesaj ("PASS complet pe ambele teste, commit real
|
||||
confirmat independent") - posibil incrucisat cu mesajul lui de STOP.
|
||||
|
||||
## 1. Starea fisierului de test
|
||||
|
||||
`COMUN\utile\Teste\editare_factura\test_writeback_buton1.prg` (ultima modificare azi, 08.08.2026).
|
||||
|
||||
- **Corectia `LOCAL` -> `PRIVATE` (linia ~133, acum ~149-153): DA, APLICATA.** Declararea curenta:
|
||||
```foxpro
|
||||
PRIVATE pnAn, pnLuna, lnCod, lnIdFact
|
||||
LOCAL lnSters, llEProforma
|
||||
LOCAL lnIdSet, lnIdFactD, lnSucces, llGasitRand
|
||||
```
|
||||
(restul variabilelor de test raman `LOCAL`, corect - nu sunt folosite ca bind `?` in SQL).
|
||||
- `frm_modific2024` e ocolit COMPLET (nu se mai instantiaza deloc) - s-a blocat de doua ori
|
||||
headless (a se vedea sectiunea 3) si s-a decis cu team-lead sa fie scos din harness. `buton=1`
|
||||
e fortat direct in cod, `inainte_de_do_termin` NU se executa.
|
||||
`Thisform.do_deschide_tranzactie`/`do_inchide_tranzactie` sunt reproduse inline in fisier
|
||||
(`MyDeschideTranzactie`/`MyInchideTranzactie`, copiate dupa `_frm_base.vc2:252-302`).
|
||||
- `PUBLIC gcMockUltimMesaj, gnMockUltimTip` + logare `goExecutor.cEroare` dupa fiecare pas: DA,
|
||||
adaugate (procedura `LogMockSiEroare`, apelata dupa fiecare `OSCRIE_IN_FISIERE` si dupa
|
||||
`finalizeaza_modificare_nota`).
|
||||
- Logare granulara `[chk]` inainte/dupa fiecare sub-pas din ramura `buton=1`: DA, adaugata.
|
||||
- **Fisierul e in stare FINALA, functionala - nu mai necesita nicio corectie pentru scopul cerut.**
|
||||
Orice rulare viitoare pe acest script trebuie sa citeasca `cod`-ul curent din `VANZARI` (nu
|
||||
presupune `1140886`), pentru ca scriptul insusi face asta (interogheaza `VANZARI` la inceputul
|
||||
fiecarui apel al procedurii `test_editare_writeback`).
|
||||
|
||||
## 2. Comanda exacta de rulare
|
||||
|
||||
```powershell
|
||||
$testPrg = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_writeback_buton1.prg'
|
||||
Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -ArgumentList '-A','-T',"`"$testPrg`"" -PassThru
|
||||
```
|
||||
|
||||
Log: `D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_writeback_buton1_log.txt`
|
||||
(suprascris de la zero la fiecare rulare - `STRTOFILE(..., lcLog)` fara `,1` pe prima linie).
|
||||
|
||||
Inainte de orice rulare: verifica sa nu existe deja un `vfp9.exe` activ
|
||||
(`Get-CimInstance Win32_Process -Filter "Name='vfp9.exe'"`) si sterge `.FXP`/`.ERR`/log vechi din
|
||||
acelasi folder.
|
||||
|
||||
## 3. Ce s-a stabilit deja (nu se reia)
|
||||
|
||||
- Prima varianta a testului instantia `frm_modific2024` (modeless, `WindowType=0`, ca in
|
||||
`test_page3_articole.prg`) - s-a blocat de doua ori, headless, fara nicio linie de eroare in
|
||||
log: prima data pe un dialog nativ Windows **"Open"** (`#32770`, confirmat prin
|
||||
`EnumWindows`/`GetWindowText` pe procesul viu), a doua oara (dupa ce s-a scos `frm_modific2024`
|
||||
si inainte de corectia `PRIVATE`) pe un dialog **nativ VFP "View Parameter"** ("Enter the value
|
||||
for pnLuna"), confirmat de captura de ecran trimisa de Marius si de `EnumWindows` local.
|
||||
- **Ipoteza "backupset" (clasa `BackupXML`, `oproceduri_comune.prg:3685-3987`) respinsa**: foloseste
|
||||
doar `CREATE CURSOR`/`Cursortoxml`/`Delete File`, niciun `USE` pe tabela lipsa; si oricum prima
|
||||
rulare (cea cu `-1`) trecuse deja prin acelasi cod fara sa se blocheze.
|
||||
- **Cauza reala a dialogului "View Parameter"**: `pnAn`/`pnLuna` erau declarate `LOCAL` in harness,
|
||||
in loc de `PRIVATE` ca in codul real (`ofacturare_comun.vc2:3742`). `PRIVATE` le face vizibile
|
||||
in josul stivei de apel, unde `goExecutor.oExecuta` rezolva bind-urile `?pnLuna`/`?pnAn` din
|
||||
apelul catre `pack_contafin.finalizeaza_modificare_nota`. Cu `LOCAL`, VFP nu le gasea si deschidea
|
||||
dialogul nativ de introducere manuala - niciodata catchabil prin `ON ERROR`/`TRY`/mock de
|
||||
`amessagebox` (nu e un `AMESSAGEBOX`, e un mecanism VFP intern).
|
||||
- **Dupa corectie (`PRIVATE`), ambele teste au trecut curat, cu COMMIT real** - vezi "CORECTIE
|
||||
IMPORTANTA" de mai sus si `docs\cercetare\rec_test_writeback.md` pentru tabelul complet.
|
||||
- Inainte de corectie, o rulare intermediara aratase `OSCRIE_IN_FISIERE(2,.T.,.T.) => -1` (esec
|
||||
curat, cu ROLLBACK, fara nicio scriere) - **acel `-1` nu s-a mai reprodus dupa corectia
|
||||
`PRIVATE`** (ambele `OSCRIE_IN_FISIERE` au intors `1` in rularea finala). Motivul exact al lui
|
||||
`-1` din acea rulare intermediara **ramane neexplicat definitiv** (posibil efect secundar al
|
||||
aceleiasi probleme de scope, posibil altceva) - nu mai e relevant, testul final a trecut, dar
|
||||
daca reapare vreodata pe alt document, `gcMockUltimMesaj`/`goExecutor.cEroare` sunt deja logate
|
||||
dupa fiecare pas.
|
||||
|
||||
## 4. Ce e interzis (neschimbat)
|
||||
|
||||
- Nu mock-ui `OSCRIE_IN_FISIERE`.
|
||||
- Nu modifica codul aplicatiei (`ofacturare_comun.vc2`, `oscrie_in_fisiere.prg`,
|
||||
`omodificari.vc2` etc.) - niciun bug de aplicatie n-a fost gasit, toate problemele au fost in
|
||||
harness.
|
||||
- Nu folosi `cod=1140888` / `cod=1140885` (baze de regresie ale `test_incarca_cursoare.prg`).
|
||||
- Nu rula `git_sync.ps1` si nu atinge `omodificari.vc2`/`.vcx` (alt agent lucreaza in paralel pe
|
||||
PAGE3, task separat).
|
||||
|
||||
## 5. Starea datelor - vezi CORECTIA de la inceputul fisierului
|
||||
|
||||
Pe scurt: `id_vanzare=1048` a fost editat legitim de doua ori prin testul aprobat. `cod` curent =
|
||||
`1140894`. Nimic de reparat sau de facut rollback - e rezultatul dorit al testului. Daca se doreste
|
||||
un test suplimentar pe alt document, se alege un `cod`/`id_vanzare` nou (nu `1140886`/`1140888`/
|
||||
`1140885`).
|
||||
|
||||
## 6. Fisiere temporare
|
||||
|
||||
Nimic de sters in working copy. `test_writeback_buton1.FXP` si `test_writeback_buton1_log.txt`
|
||||
din `COMUN\utile\Teste\editare_factura\` sunt artefacte normale, in acelasi tipar cu
|
||||
`test_incarca_cursoare.FXP`/`test_page3_articole.FXP` deja existente in acel folder (folder de
|
||||
teste, neurmarit ca binare in git). Fisierele de diagnostic SQL folosite pentru verificarea
|
||||
independenta au fost in scratchpad-ul de sesiune (`C:\Users\...\Temp\claude\...\scratchpad\`), in
|
||||
afara working copy - nu necesita curatare de catre urmatorul agent.
|
||||
|
||||
Un fisier `test_baseline_isolation.prg`/`.FXP`/`_log.txt` exista in acelasi folder, creat inainte
|
||||
de aceasta sesiune si NU de agentul curent - probabil al agentului paralel de pe alta sarcina; nu
|
||||
l-am atins.
|
||||
@@ -1,127 +0,0 @@
|
||||
# Handoff — watchdog VFP + bisectie blocaj "View Parameter" gnAn
|
||||
|
||||
Predare la peste 310k context (Regula zero). **Doar stare, fara analize noi.** Raport analitic
|
||||
complet (dovezi, log-uri, discutie): `docs\cercetare\rec_watchdog_vfp.md`.
|
||||
|
||||
## 1. Inventar livrabile, cu fisier:linie
|
||||
|
||||
**Utilitar**: `D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_vfp.ps1`. Linia de comanda completa:
|
||||
|
||||
```
|
||||
powershell -ExecutionPolicy Bypass -File "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_vfp.ps1" -Script "<cale.prg>" -TimeoutSec 90 -AutoDismiss -MaxDialogs 10
|
||||
```
|
||||
|
||||
Lanseaza `vfp9.exe -A -T "<script>"`, detecteaza orice fereastra noua diferita de
|
||||
`Process.MainWindowHandle`, o captureaza (PNG + `WM_GETTEXT` pe titlu si controale copil) in
|
||||
`<folderul scriptului>\watchdog_out\`, si cu `-AutoDismiss` incearca s-o inchida STRICT prin mesaje
|
||||
Windows tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare -> `WM_COMMAND IDCANCEL` ->
|
||||
`WM_KEYDOWN`/`WM_KEYUP` ca mesaj -> `WM_CLOSE`) - **FARA input real** (vezi sectiunea 3). Omoara
|
||||
procesul mereu la iesire (`finally`).
|
||||
|
||||
**Fisiere de test noi**:
|
||||
- `COMUN\utile\Teste\watchdog_selftest.prg` - caz banal de validare (MESSAGEBOX), folosit doar ca
|
||||
sa confirme ca watchdog-ul detecteaza/captureaza/dismite corect, inainte de cazul real.
|
||||
- `COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg` - experimentul B (izolat): DOAR
|
||||
`test_init_env_auto` + `update_jtva_coloane("", "crsJtvaTemp", 6)`, fara nimic din S4. NU
|
||||
reproduce blocajul - dovada ca `update_jtva_coloane`/`updateserver.prg` sunt nevinovate.
|
||||
|
||||
**Fisier de test modificat**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg`:
|
||||
- linia 176: `update_jtva_coloane("", "crsJtvaTemp", 6)` (parametrul schimbat din `0` in `6` -
|
||||
necesar pentru indexul `id_jtva` cerut de `Column63.ControlSource` din `omodificari.vc2:9199`;
|
||||
independent de defectul principal, fix cunoscut deja din `date_test_nnir.md`);
|
||||
- `PROCEDURE bisect_log_gnan` (noua, la coada fisierului, ~linia 236) + apeluri `DO bisect_log_gnan
|
||||
WITH <tag>, lcLog` inserate: in programul principal intre fiecare apel de nivel superior, si ca
|
||||
PRIMA linie in interiorul fiecarei proceduri (`verifica_vanzare_nota`, `verifica_coliziune_cod`,
|
||||
`verifica_pagecount_form`) - infrastructura de bisectie, ramasa in cod ca dovada;
|
||||
- **liniile 37, 39, 50 - remediul APLICAT DE TEAM-LEAD** (nu de mine, sub pragul lui de editare
|
||||
directa): `gnAn`/`gnLuna` parantezate - `(gnAn)`, `(gnLuna)` - in apelurile `DO verifica_vanzare_nota
|
||||
WITH ...` (x2) si `DO verifica_pagecount_form WITH ...` (primul), cu comentariu explicativ deasupra
|
||||
primei aparitii (liniile 34-36).
|
||||
|
||||
**Log-uri si capturi**: `test_page3_articole_log.txt` (log-ul aplicatiei, contine liniile `[BISECT]`),
|
||||
`watchdog_out\*.png` + `watchdog_out\*_watchdog.log` (capturi + jurnal watchdog, per fisier de test),
|
||||
toate in `COMUN\utile\Teste\editare_factura\`.
|
||||
|
||||
## 2. Ce e terminat, ce nu
|
||||
|
||||
**Terminat**:
|
||||
- Watchdog-ul: scris, testat pe caz banal, testat pe cazul real, corectat (heuristica de fereastra
|
||||
principala, bug de indexare PowerShell pe array cu 1 element, input real scos complet).
|
||||
- Bisectia: COMPLETA, cauza CONFIRMATA cu date brute (nu deductie) - vezi sectiunea 4.
|
||||
- Remediul: APLICAT de team-lead (liniile 37/39/50).
|
||||
|
||||
**Neterminat**: remediul NU a fost re-testat dupa aplicare. Ultima rulare a suitei (a mea) a fost
|
||||
INAINTE de remediul team-lead-ului. Team-lead ruleaza el insusi suita, separat - **eu nu mai rulez
|
||||
nimic** (interdictie explicita primita).
|
||||
|
||||
## 3. Stare fisiere - write-back
|
||||
|
||||
**Toate fisierele atinse in aceasta sesiune sunt `.prg`/`.ps1` (text simplu)** - NU exista
|
||||
`.vc2`/`.sc2`/`.vcx`/`.vct` atinse, deci **NU exista niciun write-back nefacut**.
|
||||
|
||||
Confirmare explicita: `COMUN\clase\omodificari.vc2/.vcx/.vct` si `COMUN\programe\updateserver.prg`
|
||||
sunt **NEATINSE** in aceasta sesiune (nici de mine, nici - din cate stiu - de altcineva). Fara
|
||||
commit git/svn facut sau initiat.
|
||||
|
||||
## 4. Ce s-a stabilit deja - NU relua
|
||||
|
||||
- **Cauza CONFIRMATA, nu ipoteza**: `test_page3_articole.prg` (inainte de remediu) trecea
|
||||
`gnAn`/`gnLuna` NEPARANTEZAT in `DO...WITH` (liniile 34, 36, 47 - numerotare dinainte de remediu).
|
||||
`DO proc WITH var` paseaza variabile de memorie BY REFERENCE implicit in VFP; `LPARAMETERS`
|
||||
primitor devine alias direct pe storage-ul original, iar numele original (`gnAn`) devine
|
||||
inaccesibil (`TYPE()='U'`) STRICT pe durata acelui apel, revenind valid imediat dupa `RETURN`.
|
||||
Confirmat simetric pe 3 apeluri afectate vs 2 neafectate (vezi tabelul din `rec_watchdog_vfp.md`
|
||||
sectiunea 5).
|
||||
- **`updateserver.prg`/`update_jtva_coloane` sunt nevinovate** - experimentul B (izolat, fara nimic
|
||||
din S4) NU reproduce; functia merge perfect cand `gnAn` e vizibil normal.
|
||||
- **`gnAn` NU e eliberata niciodata** - ramane valida (`TYPE()='N'`, 2026) la FIECARE checkpoint din
|
||||
scope-ul PRINCIPAL, fara exceptie. Nu exista `CLEAR ALL`/`CLEAR MEMORY`/`RELEASE ALL EXTENDED` pe
|
||||
lantul executat.
|
||||
- **Nu e coliziune de nume in corpul procedurii**: `verifica_pagecount_form` NU are `gnAn` in
|
||||
`LOCAL` (linia ei 148/159), si NU exista `PRIVATE gnAn`/`LOCAL gnAn` nicaieri in `COMUN\programe`.
|
||||
Umbrirea vine din SINTAXA APELULUI (`DO...WITH` neparantezat), nu din declaratiile callee-ului.
|
||||
- **Handler-ul de eroare** (`test_error_handler`/`ON ERROR`) doar logheaza (`STRTOFILE`) si continua
|
||||
- nu ascunde nimic, util pentru diagnostic.
|
||||
- **Incidentul de focus**: ESC-ul trimis de o versiune veche a watchdog-ului (cu `SetForegroundWindow`
|
||||
+ `keybd_event`, SCOASA complet acum) a aterizat de fapt in PROPRIUL nostru proces de test, NU in
|
||||
sesiunea utilizatorului - dar mecanismul tot nu are tinta si regula "fara input real" ramane
|
||||
obligatorie indiferent (documentat in `rec_watchdog_vfp.md` sectiunea 1, corectat acolo dupa o
|
||||
formulare initiala gresita).
|
||||
|
||||
## 5. Ce e interzis
|
||||
|
||||
- Input real de tastatura/mouse in watchdog (`keybd_event`, `SetForegroundWindow`, `SendInput`,
|
||||
`mouse_event`) - masina e PARTAJATA. Deja scos din cod, verificat cu grep (zero hit-uri de cod,
|
||||
doar comentarii care explica interdictia).
|
||||
- Atingerea `COMUN\clase\omodificari.vc2/.vcx/.vct` si `COMUN\programe\updateserver.prg`.
|
||||
- Commit git/svn.
|
||||
- **Eu nu mai rulez suita** - team-lead o ruleaza separat dupa remediul lui.
|
||||
|
||||
## 6. Capcane de mediu platite in aceasta sesiune
|
||||
|
||||
- **Heuristica "prima fereastra vazuta = principala" e o cursa pierduta**: un dialog poate aparea in
|
||||
aceeasi fractiune de secunda cu fereastra principala. Solutia corecta: `Process.MainWindowHandle`
|
||||
(.NET), NU ordinea de aparitie si NU numele clasei (VFP foloseste clase `vfp9...` si pentru shell,
|
||||
si pentru dialogurile proprii - `vfp99400000` vs `vfp994000002`).
|
||||
- **Dialogurile proprii VFP (ex. "View Parameter") sunt owner-drawn** - `EnumChildWindows` intoarce
|
||||
ZERO controale copil (butoanele sunt desenate, nu HWND-uri reale). `BM_CLICK` e imposibil pentru
|
||||
ele; chiar si `WM_CLOSE` poate "reusi" aparent (`IsWindow` -> fals) FARA sa deblocheze de fapt
|
||||
motorul VFP din spate (SQLEXEC ramas agatat, fara linie noua in log, pana la timeout) - un fals
|
||||
"succes" de retinut daca cineva reia mecanismul de dismiss.
|
||||
- **Bug PowerShell subtil**: un `List[string]` cu UN SINGUR element e "descompus" de PowerShell la
|
||||
scalar string simplu la `return` din functie (fara `,` unar) - indexarea ulterioara `$x[0]` citeste
|
||||
atunci primul CARACTER, nu primul element. Prins la dump-ul de text al dialogului "View Parameter"
|
||||
(fara controale copil = un singur element in listă). Fix: `return , $lista.ToArray()`.
|
||||
- **`.fxp` vechi blocat**: sterge intotdeauna `.fxp`-ul inainte de fiecare rulare (watchdog-ul o face
|
||||
singur) - altfel VFP ruleaza tacut codul vechi compilat.
|
||||
- **Bisectia**: `TRANSFORM(gnAn)` pe o variabila `TYPE()='U'` ARUNCA eroare catchabila ("Variable
|
||||
'GNAN' is not found") - helper-ul `bisect_log_gnan` verifica `TYPE()<>'U'` INAINTE de a apela
|
||||
`TRANSFORM()`, ca sa nu produca o eroare noua care ar fi intrerupt bisectia la primul checkpoint
|
||||
"gol".
|
||||
|
||||
## Confirmare finala
|
||||
|
||||
**PID 16548 nu mai exista** (verificat cu `Get-Process -Id 16548` - inexistent la momentul acestui
|
||||
handoff) si **niciun `vfp9.exe` nu ruleaza** (verificat cu `Get-Process vfp9` - lista goala). Nimic
|
||||
in stare periculoasa: fara editare pe jumatate, fara cursor/tranzactie Oracle deschisa (doar
|
||||
citiri), fara fisier binar atins. Sesiunea se opreste aici.
|
||||
@@ -1,210 +0,0 @@
|
||||
# Anatomia butonului "Import Roris & Contracte" (ROAACNPRO)
|
||||
|
||||
Cercetare read-only in `D:\ROA\ROAACNPRO`, ca model pentru un buton generic
|
||||
"importa articole din sursa" intr-un formular de facturare unificat in ROAFACTURARE.
|
||||
Nicio editare de fisiere, niciun `git_sync.ps1`/`txt2vcx.ps1`, niciun commit — doar investigatie.
|
||||
|
||||
## 1. Localizare
|
||||
|
||||
**Concluzie**: Butonul e `cmdImport` (clasa `cmd_executa`) pe formularul `frm_factura`, definit in
|
||||
`Clase\oacnpro.vc2`. Nu are `Click` propriu — mosteneste `Click` din clasa de baza a butoanelor,
|
||||
care ruleaza metoda numita in proprietatea `caction`; `cmdImport` nu suprascrie `caction`, deci
|
||||
ramane valoarea implicita `do_executa` mostenita de la clasa `cmd_executa`
|
||||
(`COMUN\clase\cmd_butoane.vc2:474`). Codul efectiv e in `PROCEDURE do_executa` a formularului
|
||||
`frm_factura`.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:6894-6905` — definirea controlului:
|
||||
```
|
||||
ADD OBJECT 'cmdImport' AS cmd_executa WITH ... Caption = "\<Import Roris & Contracte", ... Left = 597, Top = 65, Width = 169
|
||||
```
|
||||
- `COMUN\clase\cmd_butoane.vc2:474` — `caction = do_executa` (mostenit de `cmd_executa`).
|
||||
- `COMUN\clase\_cmd_base.vc2:120-159` — `PROCEDURE Click` a clasei de baza: construieste
|
||||
`lcCommand = [this.Parent.] + lcAction + ...` si il executa cu macro (`&lcCommand`).
|
||||
- `Clase\oacnpro.vc2:7814-7836` — `PROCEDURE do_executa` a lui `frm_factura` (clasa incepe la
|
||||
`oacnpro.vc2:6398 DEFINE CLASS frm_factura`, se termina la `8383`).
|
||||
|
||||
## 2. Preconditii
|
||||
|
||||
**Concluzie**: Butonul e activ doar daca (a) factura nu e inca salvata (`llFacturaEditabila`) si
|
||||
(b) tipul facturii (`poDate.cTip`, ales din `cboTip`) e unul din
|
||||
`TRANZIT, CHEIAJ, CHIRII, APA, PENALITATI`. In plus, la Click, `do_executa` verifica separat ca a
|
||||
fost ales clientul.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:8117-8145`:
|
||||
```
|
||||
llFacturaEditabila = !This.lFacturaSalvata
|
||||
llRorisSauContracte = INLIST(poDate.cTip, 'TRANZIT', 'CHEIAJ', 'CHIRII', 'APA', 'PENALITATI') && butonul import RORIS&Contracte este activ doar pentru RORIS sau contracte
|
||||
...
|
||||
.cmdImport.Enabled = m.llFacturaEditabila and m.llRorisSauContracte
|
||||
```
|
||||
- `Clase\oacnpro.vc2:7820-7823`:
|
||||
```
|
||||
IF EMPTY(NVL(this.nIdClient,0))
|
||||
AMESSAGEBOX('Alegeti clientul!',0+48,_screen.Caption)
|
||||
RETURN
|
||||
ENDIF
|
||||
```
|
||||
- Fara client ales, butonul e vizibil/activ dar Click-ul se opreste cu acest mesaj.
|
||||
|
||||
## 3. Ce face efectiv
|
||||
|
||||
**Concluzie**: `do_executa` -> `factura_import()` (`Programe\proceduri_acnpro.prg:3151`) ramifica
|
||||
dupa `poDate.cTip`:
|
||||
- TRANZIT/CHEIAJ: `vizualizare_tranzit()` -> deschide dialogul `frm_tranzit` (selectie convoaie din
|
||||
vederea Oracle `ips_vvoyages`) -> la confirmare, `calcul_tranzit()`/`calcul_cheiaj()` interogheaza
|
||||
direct (SELECT-uri simple, nu pachete PL/SQL) tabelele/vederile `ips_vvoyage_members_calcul`,
|
||||
`ips_vvoyage_locks`, apoi deschide un al doilea dialog de editare tarife (`frm_calcul_tranzit`).
|
||||
- CHIRII/APA: `vizualizare_contract()` -> `calcul_contract()` -> SELECT din vederea
|
||||
`vctr_articole2` (articole de contract) -> dialog `frm_calcul_contract`.
|
||||
- PENALITATI: `vizualizare_penalitati()` -> `frm_penalitati` cu cursorul `crsCalculPenalitati`
|
||||
calculat in VFP din vederile `vanzari`/`ireg_parteneri`/`penalitati`.
|
||||
|
||||
Dupa confirmarea dialogului (validat prin variabila globala `gnButon = 1`, standard framework
|
||||
pentru formulare modale), se apeleaza `make_factura_tranzit` / `make_factura_cheiaj` /
|
||||
`make_factura_contracte` / `make_factura_penalitati`, care insereaza direct in `crsFactura`.
|
||||
|
||||
**Important**: nicio procedura Oracle stocata (`pack_*`) nu e apelata in etapa de import — acestea
|
||||
(`pack_facturare.*`, `pack_acn.salveaza_regdoc`, `pack_contafin.*`) sunt apelate abia la
|
||||
**salvarea** finala a facturii (`factura_salvare_db`, `Programe\proceduri_acnpro.prg:3290+`), nu
|
||||
la import.
|
||||
|
||||
**Dovezi**:
|
||||
- `Programe\proceduri_acnpro.prg:3151-3212` (`Procedure factura_import`), `740-771`
|
||||
(`calcul_tranzit`, sursa `ips_vvoyage_members_calcul`), `1127-1161` (`calcul_contract`, sursa
|
||||
`vctr_articole2`).
|
||||
- `Programe\proceduri_acnpro.prg:939-943`:
|
||||
`loFrmTranzit = Crea("frm_calcul_tranzit", ...); loFrmTranzit.Show(1); llSucces = (m.gnButon = 1)`.
|
||||
- `Programe\proceduri_acnpro.prg:3331-3467` — apelurile `pack_facturare.*`/`pack_acn.salveaza_regdoc`
|
||||
sunt in `factura_salvare_db`, nu in `factura_import`.
|
||||
|
||||
## 4. Cum populeaza factura
|
||||
|
||||
**Concluzie**: Scrie **direct** in cursorul de articole al facturii, `crsFactura`, prin
|
||||
`INSERT INTO crsFactura(...)` in fiecare `make_factura_*` — nu trece prin vreo metoda generica
|
||||
"adauga articol" a formularului (exista o metoda separata `do_adauga_articol` pentru adaugare
|
||||
manuala de linie, dar importul n-o foloseste). Liniile se **adauga** peste cele existente (nu
|
||||
sterge/inlocuieste `crsFactura` inainte). Protectia la dublu-import e partiala:
|
||||
- dupa un import reusit, `This.cmdImport.Enabled = .F.` dezactiveaza butonul (nu se mai poate
|
||||
importa a doua oara in aceeasi sesiune de editare a facturii);
|
||||
- pentru TRANZIT/CHEIAJ exista un avertisment (nu blocaj) daca pe convoaiele alese exista deja
|
||||
facturi (`ips_vvoyages_vanzari.numar_act IS NOT NULL`) — utilizatorul poate continua oricum.
|
||||
|
||||
**Dovezi**:
|
||||
- `Clase\oacnpro.vc2:7827-7834`:
|
||||
```
|
||||
llSucces = factura_import(m.tlImportCalculat)
|
||||
IF m.llSucces
|
||||
This.cmdImport.Enabled = .F. && nu mai import altceva
|
||||
This.chkIntern.Enabled = .F.
|
||||
This.ActiveazaSalvare()
|
||||
...
|
||||
```
|
||||
- `Programe\proceduri_acnpro.prg:3601` (TRANZIT) / `3677-3678` (CHEIAJ) / `3764-3765`
|
||||
(CHIRII/APA): `Insert Into crsFactura(nrcrt, id_articol, denumire, ...)`.
|
||||
- `Clase\oacnpro.vc2:14915-14930` — avertisment dublu-import in `frm_tranzit.do_executa`:
|
||||
```
|
||||
SELECT numar_act, data_act, client FROM ips_vvoyages_vanzari WHERE vye_id in (...) AND numar_act is NOT null ...
|
||||
IF RECCOUNT('cFacturiTranzitTemp') > 0
|
||||
lcMesaj = 'Atentie! Exista facturi pe tranzitele alese!' + CHR(13)+CHR(10) + ...
|
||||
AMESSAGEBOX(m.lcMesaj,0+48,_screen.Caption)
|
||||
ENDIF
|
||||
```
|
||||
(mesaj informativ, apoi continua oricum cu `calcul_tranzit`/`calcul_cheiaj`).
|
||||
|
||||
## 5. Feedback catre utilizator
|
||||
|
||||
**Concluzie**: Mesaje punctuale prin `AMESSAGEBOX`, nu un sistem unitar de raportare:
|
||||
- Client lipsa: `'Alegeti clientul!'` (`oacnpro.vc2:7821`).
|
||||
- Convoi/liniile de import lipsa dupa dialog: `'Alegeti un convoi!'` in `make_factura_tranzit`
|
||||
daca `poDate.uuid` (id-urile alese) e gol (`proceduri_acnpro.prg:3530`); analog pentru
|
||||
CHIRII/APA prin `factura_salvare` (`'Alegeti convoiul'`/`'Adaugati prestatii'`,
|
||||
`proceduri_acnpro.prg:3221`, dar aceasta e verificare la *salvare*, nu la import).
|
||||
- Facturi deja existente pe convoaiele alese: avertisment neblocant (vezi punctul 4).
|
||||
- Zero rezultate in dialogul de selectie (`frm_tranzit`/`frm_calcul_contract`): niciun mesaj
|
||||
explicit gasit — grila ramane goala, iar la `Calculare`/`Terminat` fara nimic bifat `lcVyeIds`
|
||||
ramane vid si `IF !EMPTY(m.lcVyeIds)` (`oacnpro.vc2:14912`) sare peste tot calculul, fara mesaj
|
||||
catre utilizator (comportament implicit: butonul pare sa nu faca nimic).
|
||||
- Eroare Oracle: nu exista tratare `TRY/CATCH` explicita in `factura_import`/`calcul_tranzit`/
|
||||
`make_factura_*`; erorile SQL se propaga prin returul `.F.` al lui
|
||||
`goExecutor.oExecuta`/`oSelecteaza2Value`, iar afisarea erorii tine de comportamentul standard
|
||||
al `goExecutor` (framework comun, neexaminat in detaliu aici).
|
||||
|
||||
**Dovezi**: citatele de mai sus; pentru "zero rezultate fara mesaj" — `Clase\oacnpro.vc2:14898-14943`.
|
||||
|
||||
## 6. Selectivitate
|
||||
|
||||
**Concluzie**: Da, exista dialoage intermediare cu selectie, diferite pe tip:
|
||||
- **TRANZIT/CHEIAJ**: `frm_tranzit` (`oacnpro.vc2:14492-15003`) — grid `grdTranzit` cu coloane
|
||||
`Declaratia`, `Data decl.`, `Convoi`, `Origin`, `Destinatie` si o coloana checkbox `cAles`
|
||||
(`ControlSource='crsConvoaie.ales'`), plus criterii de cautare (`Cb_tx_cautare1`,
|
||||
`But_start_criterii1`/`But_reset_criterii1`) si buton `cmdCalculeaza` ("Calculare Tarife").
|
||||
Utilizatorul bifeaza unul sau mai multe convoaie; daca nu bifeaza niciunul, se ia randul curent
|
||||
(`lcVyeId` din `crsConvoaie` la pozitia curenta). Dupa `Calculare Tarife`, se deschide **al
|
||||
doilea nivel** — `frm_calcul_tranzit`/`frm_calcul_cheiaj` — pentru editarea/confirmarea
|
||||
tarifelor calculate, inainte de a reveni in factura.
|
||||
- **CHIRII/APA**: `calcul_contract()` deschide `frm_calcul_contract` cu cursorul
|
||||
`crsArticoleContract` (articol, perioada, um, pret, cantitate, valoare, valuta, locatie) din
|
||||
vederea `vctr_articole2` filtrata pe `id_ctr` — practic toate articolele contractului curent,
|
||||
editabile in acel dialog.
|
||||
- **PENALITATI**: `frm_penalitati` cu grid `grdPenalitati` (`crsCalculPenalitati`), coloane
|
||||
vizibile precum `cNrDoc`, `cSuma` ("Sold restant" in modul evaluare), `cDataDoc`.
|
||||
|
||||
Deci nu e un "importa tot" fara interventie — e mereu mediat de un dialog de vizualizare/calcul/
|
||||
confirmare (`gnButon = 1` = utilizatorul a confirmat).
|
||||
|
||||
**Dovezi**: `Clase\oacnpro.vc2:14500-14515` (obiecte grid + `cAles`), `14801`
|
||||
(`ControlSource='crsConvoaie.ales'`), `14594-14601` (`cmdCalculeaza`);
|
||||
`Programe\proceduri_acnpro.prg:1137-1153` (`crsArticoleContract` din `vctr_articole2`);
|
||||
`Programe\proceduri_acnpro.prg:545-555` (`frm_penalitati`, `grdPenalitati.cSuma`, `.cNrDoc`,
|
||||
`.cDataDoc`).
|
||||
|
||||
## 7. Butoanele vecine
|
||||
|
||||
**Concluzie**: Pe `frm_factura`, `cmdImport` e plasat in zona antetului facturii
|
||||
(`Left=597, Top=65`), langa `cboTip` (`Left=507, Top=67` — combo cu tipul facturii) si
|
||||
`chkIntern` (`Left=412, Top=70`) — nu langa bara principala de butoane. Bara principala de sus
|
||||
(`Top=0`) contine, in ordinea `Left`: `but_factura_noua` ("Nou", `Left=688`), `But_salveaza1`
|
||||
("Salveaza", `Left=719`), `But_renunt1` ("Renunta", `Left=749`). Separat, langa grila
|
||||
`grdFactura`, exista butoane de linie (`Top=120`): `But_nou1` ("Adauga linie", `Left=707`) si
|
||||
`But_sterge1` ("Sterge linie", `Left=737`). Mai sunt `but_cautare_client`/`but_cautare_beneficiar`
|
||||
(lupa cautare partener, langa campurile de client/beneficiar).
|
||||
|
||||
**Dovezi**: `Clase\oacnpro.vc2:6779-6818` (definitiile `but_factura_noua`, `But_nou1`,
|
||||
`But_renunt1`, `But_salveaza1`, `But_sterge1` cu `Left`/`Top`), `6836-6851` (`cboTip`),
|
||||
`6853-6863` (`chkIntern`), `6894-6905` (`cmdImport`).
|
||||
|
||||
## Ce e transferabil in ROAFACTURARE
|
||||
|
||||
Tiparul general merita copiat ca **model de arhitectura pentru un buton generic "importa
|
||||
articole din sursa"**:
|
||||
1. Buton activ conditionat de (a) factura editabila (nesalvata) si (b) tip de document care are o
|
||||
sursa de import — exact ca `llFacturaEditabila and llRorisSauContracte`.
|
||||
2. O metoda de intrare unica (`do_executa`/`factura_import`) care ramifica dupa tipul documentului
|
||||
catre functii specializate de "vizualizare/selectie" — fiecare deschide un dialog modal de
|
||||
selectie (grid cu coloana checkbox `ales`, criterii de cautare), returneaza succes/esec prin
|
||||
variabila globala tip `gnButon = 1`.
|
||||
3. Populare prin `INSERT INTO <cursor_articole>` direct, aditiv (nu sterge liniile existente), cu
|
||||
dezactivarea butonului dupa import reusit ca protectie minimala la dublu-import — plus
|
||||
(optional) un avertisment neblocant daca sursa a mai fost deja folosita in alta factura.
|
||||
4. Separarea neta intre etapa de **calcul/import** (SELECT-uri simple pe vederi Oracle, fara
|
||||
proceduri stocate) si etapa de **salvare** (unde intra pachetele PL/SQL) — util ca principiu:
|
||||
importul nu trebuie sa scrie definitiv in baza, doar sa populeze cursorul local.
|
||||
|
||||
Ce e strict specific ACN/RORIS si **nu** se transfera: sursele de date (`ips_vvoyages`,
|
||||
`ips_voyage_members_vanzari`, `ips_vberthing_details_vanzari`, `vctr_articole2`), logica de calcul
|
||||
tarife/ecluzari/porturi, formularele `frm_tranzit`/`frm_calcul_tranzit`/`frm_calcul_contract`/
|
||||
`frm_penalitati` ca atare, si valorile `poDate.cTip` (`TRANZIT/CHEIAJ/CHIRII/APA/PENALITATI`).
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Comportamentul exact al `goExecutor.oExecuta`/`oSelecteaza2Value` la eroare Oracle (mesaj
|
||||
afisat, retry, log) — n-a fost verificat in profunzime (functie framework comun).
|
||||
- Continutul complet al dialogului `frm_calcul_tranzit`/`frm_calcul_cheiaj` (al doilea nivel,
|
||||
editare tarife) — am confirmat doar ca exista si ca `gnButon=1` marcheaza confirmarea, dar nu am
|
||||
detaliat coloanele/campurile lui.
|
||||
- Detaliile `frm_calcul_contract` (butoane, posibilitate de deselectare articole individuale) nu
|
||||
au fost citite integral — doar sursa cursorului.
|
||||
- Nu am verificat daca exista vreo validare suplimentara de "acelasi convoi importat de doua ori
|
||||
in aceeasi factura" dincolo de avertismentul cross-factura mentionat la punctul 4.
|
||||
@@ -74,7 +74,7 @@ tabel — e folosit exclusiv ca filtru intr-un calcul de disponibil.
|
||||
|
||||
Nu exista. DDL-ul complet nu e disponibil in acest repo (nu exista `CREATE TABLE VANZARI_DETALII` in
|
||||
`docs/`; confirmat deja de cercetari anterioare — `docs/cercetare/discount_verificare2.md:104-111`,
|
||||
`docs/cercetare/rec_tva_vanzari.md:19`), dar structura efectiva a fost verificata pe schema live in
|
||||
`COMUN\docs\cercetare\rec_tva_vanzari.md:19`), dar structura efectiva a fost verificata pe schema live in
|
||||
`docs/cercetare/rec_cale_vanzari_detalii.md:157-169` (interogare `all_tab_columns`, 08.08.2026):
|
||||
35 de coloane, PK `ID_VANZARE_DET` (generat prin trigger `TRG_VANZARI_DET_BEFOINS` din
|
||||
`SEQ_VANZARI_DETALII`), FK logic `ID_VANZARE`. Lista coloanelor relevante citata acolo: `ID_ARTICOL`,
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# Mockup #13 — v6 -> v7 (runda 8), ce s-a schimbat
|
||||
|
||||
Fisier atins: `D:\ROA\ROAFACTURARE\docs\mockup_13_formular_unificat.html`. Niciun alt fisier.
|
||||
|
||||
## Sectiuni atinse
|
||||
|
||||
- **Eyebrow / marcaj versiune** (linia ~199): `versiunea 6` -> `versiunea 7 (runda 8)`.
|
||||
- **Sectiunea 8** ("Ce trebuie verificat inainte"): item-ul "cont de venit fara politica" a fost
|
||||
rescris — decizia 24 (politica implicita) marcata retrasa, inlocuita cu decizia 27/27-bis, cu
|
||||
trimitere la sectiunea 10 noua. S-au adaugat trei intrari noi, toate `raspuns`: nepotrivirea de
|
||||
afisare ROAAUTO (decizia 28), stergerea liniei din comanda (decizia 29), coordonarea cu #6
|
||||
(decizia 30). Cele 7 intrari `de verificat` originale nu s-au atins.
|
||||
- **Sectiunea 9** (ROAAUTO): ultimul paragraf ("Ce ramane e o nepotrivire de afisare", pill
|
||||
`de acceptat`) a fost rescris ca decizie inchisa (pill `decis`), cu conditia explicita — MANOPERA
|
||||
si MATERIALE conform devizului — si precizarea "nu se cere cod nou in ROAAUTO".
|
||||
- **Sectiune noua 10** ("Contul de venit pentru articole adaugate din nomenclator"), adaugata la
|
||||
finalul documentului: nu exista o sectiune dedicata in v6, doar bulletul cramponat din sectiunea 8
|
||||
cu raspunsul vechi (politica implicita) — s-a creat sectiune noua, nu s-a renumerotat nimic
|
||||
existent. Contine: decizia 24 barata (`<s>`) cu motivul retragerii; tabel cu decizia 27 (cele doua
|
||||
ramuri — gestionabil prin `CORESP_CONT_VENCHELT.CONT_VENIT`, negestionabil prin `NOM_ARTICOLE.CONT`
|
||||
sau `704`); decizia 27-bis ca listă ordonata de 4 pasi (calculeaza contul -> cauta politica cu
|
||||
acel cont -> `pack_preturi.adauga_politica_pret_art` -> trimite `id_pol`); intrebarea lui Marius
|
||||
("de ce nu si in ROAACNPRO / pe contract") cu raspunsul exact din plan (ROAACNPRO nu cheama
|
||||
`contabilizeaza_articol`; pe contract articolele au `id_pol` din cursor; `FACT-024` ramane
|
||||
blocantul); lista "Ce nu e gratuit" cu cele 4 costuri din J-quater.
|
||||
|
||||
## CSS
|
||||
|
||||
S-a extins selectorul `ul.tight` la `ul.tight, ol.tight` (si `li`-urile lor), ca sa poata fi folosita
|
||||
o lista numerotata (reteta VFP in 4 pasi) cu exact aceeasi tipografie ca listele `<ul class="tight">`
|
||||
deja existente. Nicio alta regula CSS schimbata, nicio paleta/biblioteca noua.
|
||||
|
||||
## Ce NU s-a atins
|
||||
|
||||
- Relatia cu #6 nu avea nicio mentiune in v6; s-a adaugat doar in bulletul nou de la decizia 30 din
|
||||
sectiunea 8 (unde e cel mai la locul lui) — nu s-a creat sectiune separata pentru asta, planul nu
|
||||
o cerea explicit.
|
||||
- "Riscuri" (primele doua puncte din plan) nu au sectiune proprie in mockup si nu li s-a creat una —
|
||||
continutul lor (perimetrul cu #6 inchis, riscul mutat pe vizibilitatea politicii tehnice) e deja
|
||||
reflectat implicit in sectiunea 10 ("Ce nu e gratuit") si in bulletul decizia 30.
|
||||
- Sectiunile 1-7 (formular, buton antet, meniu de adaugare, valuta, discount, puncte de intrare,
|
||||
ce se scrie la Termina) nu au fost modificate — deciziile rundei 8 nu le afecteaza continutul.
|
||||
|
||||
## Contradictii / alegeri facute
|
||||
|
||||
- Sarcina mentioneaza "sectiunea despre contul de venit ... (daca exista; altfel o adaugi ca
|
||||
sectiune noua)". In v6 exista doar un bullet in sectiunea 8, nu o sectiune propriu-zisa — am
|
||||
tratat asta ca "nu exista" si am creat sectiunea 10, pastrand si bulletul din sectiunea 8 (actualizat,
|
||||
mai scurt, cu trimitere catre sectiunea 10 pentru detalii).
|
||||
- Pentru pill-ul de pe decizia inchisa am folosit eticheta `decis` (sectiunea 9) si am reutilizat
|
||||
`raspuns` (sectiunea 8, clasa CSS `pill have`) — nu exista in CSS o eticheta dedicata "decis", dar
|
||||
clasa `pill have` (verde, „raspuns/rezolvat") e deja folosita cu text variabil in restul
|
||||
documentului (`exista deja`, `rezolvat`, `da`), asa ca am urmat conventia in loc sa inventez o clasa.
|
||||
@@ -1,99 +0,0 @@
|
||||
# Mockup #13 — v7 -> v8 (rundele 9-11, deciziile 31-42), ce s-a schimbat
|
||||
|
||||
Fisier atins: `D:\ROA\ROAFACTURARE\docs\mockup_13_formular_unificat.html`. Niciun alt fisier.
|
||||
Citire unica a HTML-ului (decizia 33); editarile de mai jos s-au aplicat intr-o singura serie, fara
|
||||
recitire intermediara.
|
||||
|
||||
## Sectiuni atinse
|
||||
|
||||
- **Eyebrow / marcaj versiune** (linia ~199): `versiunea 7 (runda 8)` -> `versiunea 8 (runda 11)`.
|
||||
- **Sectiunea 1** (disclosure-ul din panoul Document): decizia 41 — comutatorul unic „Alte date —
|
||||
analitice, delegat si transport, incasare, adresa de facturare, text aditional” s-a despartit in
|
||||
**doua** `.disclosure`: unul nou, doar „Incasare” (fara callout numerotat, ca sa nu se renumeroteze
|
||||
legenda), cu hint „alocare/dezalocare — comutator propriu”; al doilea pastreaza callout-ul 2 si restul
|
||||
campurilor (fara incasare). Legenda callout-ului 2 a fost rescrisa: titlu „Restul, pliat — doua
|
||||
comutatoare”, text care explica motivul izolarii (efecte laterale reale doar pe incasare, blocata pe
|
||||
document emis prin decizia 25, garda de non-alocare scrisa/testata intr-un singur loc).
|
||||
- **Sectiunea 3** (meniul de adaugare): paragraf nou dupa observatia despre „adauga tot” — decizia 39:
|
||||
`crsarticole` ramane registrul cantitatii ramase de facturat (folosit la inchiderea automata a
|
||||
comenzii/avizului), decuplat de gridul incarcat; cautarea pe server ramane cum era in v7, doar
|
||||
bookkeeping-ul se muta intr-un registru propriu.
|
||||
- **Sectiunea 4** (Valuta si data cursului): paragraf nou la final — decizia 42: validarea cursurilor
|
||||
(`verifica_cursuri_valute`) se restrange la valuta articolului cautat, nu mai ruleaza global la
|
||||
deschidere; diferenta de comportament asumata explicit.
|
||||
- **Sectiunea 7** (Ce se scrie la Termina): paragraf nou dupa tabel — decizia 35: un singur cod de
|
||||
scriere contabila, `scrie_factura2` → `contabilizeaza_articol`, si la emitere si la editare (etapa
|
||||
II); canalul `oscrie_in_fisiere` (folosit azi de #6) nu intra in #13.
|
||||
- **Sectiunea 8** (Ce trebuie verificat inainte): bulletul „Coordonarea cu #6” (decizia 30) extins cu
|
||||
decizia 38 — fluxul de editare al lui #6 nu se retrage, coexista cu regenerarea din #13, decizia
|
||||
despre unificare se ia mai tarziu. Bullet nou, mic, pentru decizia 40 — bug-ul de dezalocare POS se
|
||||
repara in trecere in S3b, testarea trebuie sa acopere si dezalocarea pe calea veche.
|
||||
- **Sectiunea 10** (Contul de venit) — **rescrisa integral**, cum a fost cerut:
|
||||
- decizia 24 ramane barata (`<s>`), neschimbata din v7;
|
||||
- decizia 27 (tabelul cu cele doua ramuri, gestionabil/negestionabil) neschimbata;
|
||||
- **decizia 27-bis (reteta VFP in 4 pasi) e acum barata** (`<s>`), cu explicatia abandonarii
|
||||
(decizia 32 → decizia 34) — tiparul vizual e identic cu cel folosit pentru decizia 24 respinsa,
|
||||
cerut explicit de mandat;
|
||||
- **sectiune noua „Decizia 34”**: coloana noua `VANZARI_DETALII_TEMP.CONT_VENIT`, parametrul nou
|
||||
`V_CONT_VENIT` la coada lui `adauga_articol_factura`, cei trei apelanti interni neatinsi
|
||||
(BULK COLLECT pe `%ROWTYPE`), ramura noua infasoara `FACT-024`, `descarca_gestiune` o data prin
|
||||
constructie, plus bulletul „de retinut la implementare” cu cele doua clase VFP separate
|
||||
(`frm_facturare_articole` / `frm_facturare_articole2`), lista de coloane a `scrie_in_vanzari`, si
|
||||
excluderea structurala a articolului compus;
|
||||
- **sectiune noua „Decizia 36”**: tabel cu sursa lui `SCD` (optiune de firma, implicit `4111`, tiparul
|
||||
din `scrie_incasare2`) si `CU_TVA` (derivat din `proc_tvav > 0`, cu riscul gasit la verificarea
|
||||
adversariala explicat);
|
||||
- **sectiune noua „Decizia 37”**: cheia `RF_CONT_ART_FARA_POL`, fara validare de cont, garda de
|
||||
lungime (`ORA-12899`);
|
||||
- paragraful „Intrebarea lui Marius, verificata” pastrat (raspunsul nu s-a schimbat fata de v7);
|
||||
- **„Ce nu e gratuit” rescris** — cele 4 costuri vechi (specifice retetei in 4 pasi, azi abandonate)
|
||||
inlocuite cu 4 costuri noi: regresia pe toata suita, cele doua clase VFP cablate separat, lista de
|
||||
coloane a `scrie_in_vanzari`, si absenta validarii pe un cont fara precedent.
|
||||
- **Sectiune noua 12** *(vezi corectie mai jos — de fapt 11)*: „Puncte marunte ramase”, tabelul a-k din
|
||||
plan, cu nota „se merge pe recomandare daca Marius nu spune altfel”.
|
||||
|
||||
*Corectie fata de un draft intermediar al acestui raport: sectiunea noua e numerotata corect
|
||||
**11** (urmatorul numar liber dupa 10, cum cere regula „nu renumerota sectiunile existente”), nu 12.*
|
||||
|
||||
## CSS
|
||||
|
||||
Nicio regula noua, nicio paleta noua. S-au refolosit `pill have` / `pill check`, `<s>`, `table.doc`,
|
||||
`.tbl`, `ul.tight` — exact ca in v7. Ordonata list (`ol.tight`) a disparut din document odata cu
|
||||
eliminarea retetei in 4 pasi (nu mai exista niciun `<ol>` in fisier), dar selectorul CSS extins la
|
||||
`ul.tight, ol.tight` din v7 a fost pastrat neschimbat, pentru refolosire viitoare.
|
||||
|
||||
## Ce NU s-a atins
|
||||
|
||||
- Deciziile 31 si 33 nu apar in mockup (reguli de lucru interne, nu decizii de produs), cum a cerut
|
||||
mandatul.
|
||||
- Decizia 32 nu are sectiune proprie — e reflectata implicit prin explicatia abandonarii retetei in 4
|
||||
pasi (barata) din sectiunea 10.
|
||||
- Ramura `ntip = 4` / avize / `SCD` pe aviz — **exclusa deliberat**, nu apare nicaieri in mockup (in
|
||||
verificare adversariala, conform mandatului).
|
||||
- Sectiunile 2, 5, 6, 9 nu au fost modificate — deciziile 31-42 nu le ating continutul.
|
||||
|
||||
## Verificare
|
||||
|
||||
- Ambele fisiere exista pe cale absoluta (`docs\mockup_13_formular_unificat.html`,
|
||||
`docs\cercetare\mockup_v8_modificari.md`).
|
||||
- Tag-uri numarate cu regex pe fisierul final: `div` 148/148, `section` 6/6, `table` 11/11,
|
||||
`tbody`/`thead` 11/11, `tr` 56/56, `ul` 2/2, `ol` 0/0 (eliminat odata cu reteta), `p` 58/58,
|
||||
`h2` 11/11, `h3` 5/5 — toate echilibrate.
|
||||
|
||||
## Contradictii / alegeri facute
|
||||
|
||||
- **Numarul callout-ului pe noul disclosure „Incasare” (decizia 41):** am ales sa NU-i dau un numar de
|
||||
callout propriu, ca sa nu renumerotez legenda existenta (1-4) sau sa creez un al 5-lea item de legenda
|
||||
pentru un detaliu minor. In schimb am pus un `.hint` inline, dupa tiparul deja folosit in alte locuri
|
||||
ale mockup-ului (ex. nota „3 linii · comanda CMD 3312 acoperita 100%”) pentru text explicativ fara
|
||||
callout numerotat.
|
||||
- **Plasarea deciziei 35:** am ales sectiunea 7 (Ce se scrie la Termina) in loc de o sectiune noua,
|
||||
pentru ca tabelul de acolo descrie deja exact ce cod scrie fiecare tip de modificare — decizia 35 e o
|
||||
precizare directa pe acel tabel, nu un subiect separat.
|
||||
- **Plasarea deciziilor 39/42:** ambele au fost puse ca paragrafe `.meta` la finalul sectiunilor deja
|
||||
existente (3, respectiv 4) despre subiectul lor, nu ca sectiuni noi — mandatul preciza ca „se vad in
|
||||
formular”, dar niciuna nu schimba un desen existent (spre deosebire de 41), deci text a fost suficient.
|
||||
- **Sectiunea 10, „Intrebarea lui Marius, verificata”:** am pastrat-o neschimbata din v7 pentru ca
|
||||
raspunsul (ROAACNPRO nu cheama `contabilizeaza_articol`, contractul are `id_pol` din cursor) nu s-a
|
||||
schimbat prin nicio decizie a rundelor 9-11 — doar mecanismul prin care se evita `FACT-024` s-a
|
||||
schimbat, nu raspunsul la intrebarea de ce nu se aplica si acolo.
|
||||
@@ -1,193 +0,0 @@
|
||||
# Cercetare: bifa de deblocare campuri in formularul actual de modificare antet
|
||||
|
||||
Sursa: cache text `.vc2` (deja la zi in acest working copy) din `COMUN\clase\`. Investigatie
|
||||
read-only, fara editare de cod.
|
||||
|
||||
## 1. Localizarea clasei `frm_modifica_factura`
|
||||
|
||||
**Concluzie**: Clasa e definita in `COMUN\clase\ofacturare_comun.vc2:5262-5774`
|
||||
(`DEFINE CLASS frm_modifica_factura AS frm_termin_renunt OF "_frm_child.vcx"`), formular modal
|
||||
mic (Width=613, Height=412), deschis din `frm_facturi.do_modifica`
|
||||
(`ofacturare_comun.vc2:4538-4637`, `Createobject("frm_modifica_factura", ...)` la linia 4588).
|
||||
Ancestor chain: `frm_modifica_factura -> frm_termin_renunt -> _frm_child.vcx`.
|
||||
|
||||
**Dovezi** — lista completa a controalelor proprii (nume / clasa-baza / caption sau control source):
|
||||
|
||||
| Control | Clasa | Caption / rol | Linie |
|
||||
|---|---|---|---|
|
||||
| `Ct_clb_ruta` | `ct_clb_cautare` (caut_ora.vcx) | "Ruta" | 5510 |
|
||||
| `Ct_clb_agent` | `ct_clb_cautare` | "Agent" | 5455 |
|
||||
| `Ct_clb_delegat` | `ct_clb_cautare` | "Delegat" | 5473 |
|
||||
| `Ct_clb_masina` | `ct_clb_cautare` | "Masina" | 5491 |
|
||||
| `clb_adresa_facturare` | `ct_clb_cautare` | "Adresa facturare" | 5418 |
|
||||
| `Clb_dataora_exp` | `clb_tx_simplu` (lb_tx.vcx) | "Data si ora expedierii", `poRec.dataora_exp` | 5437 |
|
||||
| `shpTipFactura` / `lblTipFactura` / `cboTipFactura` | shape / label / `_combobox` | "Tip factura", `poRec.tip_saft` (vizibil doar daca `gl406`) | 5335, 5553, 5562 |
|
||||
| `chkDetaliat` | `_checkbox` | "Listare detaliata", `poRec.listare_detaliata` | 5379 |
|
||||
| `Ed_tx_simplu1` | `ed_tx_simplu` (lb_tx.vcx) | "Text aditional...", `poRec.text_aditional` | 5528 |
|
||||
| `chkSerieAct` | `_checkbox` | "Serie factura", `Enabled=.F.` implicit | 5405 |
|
||||
| `chkNrAct` | `_checkbox` | "Numar factura", `Enabled=.F.` implicit | 5392 |
|
||||
| `chkDataAct` | `_checkbox` | "Data factura", `Enabled=.F.` implicit | 5353 |
|
||||
| `chkDataScad` | `_checkbox` | "Data scadenta", `Enabled=.F.` implicit | 5366 |
|
||||
| `txtSerieAct` | `_textbox` | `poRec.serie_act`, `Enabled=.F.` implicit | 5605 |
|
||||
| `txtNrAct` | `_textbox` | `poRec.numar_act`, `Enabled=.F.` implicit | 5594 |
|
||||
| `txtDataAct` | `_textbox` | `poRec.data_act`, `Enabled=.F.` implicit | 5572 |
|
||||
| `txtDataScad` | `_textbox` | `poRec.data_scad`, `Enabled=.F.` implicit | 5583 |
|
||||
| `BUT_TERMIN1` / `But_renunt1` | din `frm_termin_renunt` | Terminat / Renunta | 5322, 5328 |
|
||||
| `Lb_titlu_alb_b121` | label titlu | "Modifica date factura" | 5318 |
|
||||
|
||||
## 2. Bifa de deblocare a campurilor
|
||||
|
||||
**Concluzie: NU exista o singura bifa care sa activeze/dezactiveze tot antetul.** Ceea ce exista
|
||||
e altceva: **4 checkbox-uri separate**, cate unul pentru fiecare camp "act" (serie/numar/data
|
||||
factura + data scadenta), fiecare deblocand DOAR campul lui propriu, si toate 4 pornesc ele
|
||||
insele dezactivate (`Enabled=.F.`) daca factura nu are deja un "act" atasat. Toate celelalte
|
||||
campuri (ruta, delegat, agent, masina, adresa, data/ora expeditie, tip factura, listare
|
||||
detaliata, text aditional) **nu sunt blocate deloc** — sunt mereu editabile, fara nicio bifa.
|
||||
|
||||
**Dovezi**:
|
||||
|
||||
`Init` (`ofacturare_comun.vc2:5736-5750`):
|
||||
```
|
||||
this.chkSerieAct.Enabled = !EMPTY(NVL(poRec.numar_act,0))
|
||||
this.chkNrAct.Enabled = !EMPTY(NVL(poRec.numar_act,0))
|
||||
this.chkDataAct.Enabled = !EMPTY(NVL(poRec.numar_act,0))
|
||||
this.chkDataScad.Enabled = !EMPTY(NVL(poRec.numar_act,0))
|
||||
```
|
||||
adica cele 4 checkbox-uri sunt ele insele clickabile doar daca factura are deja `numar_act`
|
||||
completat (act existent); altfel raman gri, nefolosibile.
|
||||
|
||||
Handlerele lor (`:5758-5772`), fiecare cuplat 1-la-1 cu textbox-ul corespunzator:
|
||||
```
|
||||
PROCEDURE chkDataAct.Valid
|
||||
thisform.txtDataAct.Enabled = this.Value
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE chkDataScad.Click
|
||||
thisform.txtDataScad.Enabled = this.Value
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE chkNrAct.Valid
|
||||
thisform.txtNrAct.Enabled = this.Value
|
||||
ENDPROC
|
||||
|
||||
PROCEDURE chkSerieAct.Valid
|
||||
thisform.txtSerieAct.Enabled = this.Value
|
||||
ENDPROC
|
||||
```
|
||||
Nu apeleaza `.activeaza()`/`.dezactiveaza()` pe niciun container — seteaza direct
|
||||
`Enabled = this.Value` pe textbox-ul propriu. Nu exista alt mecanism de blocare (nu se apeleaza
|
||||
`dezactiveaza()` in `Init` pe vreun container din formular — vezi punctul 5).
|
||||
|
||||
## 3. Campuri sub bifa vs. campuri libere
|
||||
|
||||
**Concluzie**: singurele campuri gatate sunt cele 4 legate de documentul "act" (justificativ):
|
||||
serie act, numar act, data act, data scadenta. Serie/numar **ale facturii insesi** nu sunt pe
|
||||
acest formular deloc (se aloca ireversibil la emitere, prin `poGeneratorNumere`, in afara acestui
|
||||
flux). Delegat/agent/masina/ruta/adresa sunt tratate identic intre ele — toate prin containere
|
||||
`ct_clb_cautare` fara nicio gata de `Enabled`/`ReadOnly` proprie in acest formular.
|
||||
|
||||
**Dovezi**: vezi tabelul de la punctul 1 — coloana "Caption / rol" arata `Enabled=.F.` explicit
|
||||
doar pe cele 4 perechi checkbox+textbox de "act"; niciun `Enabled=.F.` sau apel de dezactivare pe
|
||||
`Ct_clb_ruta`/`Ct_clb_agent`/`Ct_clb_delegat`/`Ct_clb_masina`/`clb_adresa_facturare`/
|
||||
`Clb_dataora_exp`/`chkDetaliat`/`Ed_tx_simplu1`/`cboTipFactura`.
|
||||
|
||||
## 4. Calea de salvare
|
||||
|
||||
**Concluzie**: la `Terminat` (`gnButon=1`), se apeleaza **`pack_facturare.modifica_date_factura`**
|
||||
o data pentru fiecare factura selectata, cu 14 parametri — toti metadate de antet/logistica, deci
|
||||
salvarea antetului e **complet independenta de articole/note contabile**: nu exista in
|
||||
`do_modifica` niciun apel spre `oscrie_in_fisiere`, `pack_contafin`, sau vreun cursor de articole.
|
||||
|
||||
**Dovezi** (`ofacturare_comun.vc2:4587-4630`, `do_modifica` pe `frm_facturi`):
|
||||
```
|
||||
If poRec.sters = 0 AND NVL(m.pnEFactura,0) = 0
|
||||
ofrmmodificare = Createobject("frm_modifica_factura", ...)
|
||||
ofrmmodificare.Show(1)
|
||||
...
|
||||
If gnButon = 1
|
||||
...
|
||||
Scan For &lcFiltru
|
||||
TEXT TO lcSql NOSHOW TEXTMERGE
|
||||
begin pack_facturare.modifica_date_factura(<<...id_vanzare...>>,
|
||||
<<...id_ruta...>>, <<...id_delegat...>>, <<...id_agent...>>, <<...id_masina...>>,
|
||||
to_date('<<TTOC(poRec.dataora_exp,1)>>','YYYYMMDDHH24:MI:SS'),
|
||||
<<...id_facturare...>>, <<...listare_detaliata...>>,
|
||||
?poRec.text_aditional, ?poRec.tip_saft, ?poRec.efactura,
|
||||
?poRec.data_act, ?poRec.data_scad, ?poRec.numar_act, ?poRec.serie_act);
|
||||
end;
|
||||
ENDTEXT
|
||||
lnSucces = goExecutor.oExecute(lcSql)
|
||||
ENDSCAN
|
||||
Endif
|
||||
Else
|
||||
amessagebox("Nu puteti face modificari pe inregistrarile sterse sau facturile trimise in eFactura!", 48, "Atentie")
|
||||
Endif
|
||||
```
|
||||
Garda de intrare (poate edita doar daca nu e stearsa si nu e in eFactura) e la linia 4587,
|
||||
verificarea `anaf_efactura` la 4583-4585. Se poate confirma direct din semnatura RPC-ului
|
||||
(`id_vanzare, id_ruta, id_delegat, id_agent, id_masina, dataora_exp, id_facturare,
|
||||
listare_detaliata, text_aditional, tip_saft, efactura, data_act, data_scad, numar_act,
|
||||
serie_act`) ca nu exista niciun parametru de articol/nota — deci da, **antetul se salveaza singur,
|
||||
fara sa atinga restul documentului**.
|
||||
|
||||
## 5. Conventia de containere blocabile in suita (`clb_*`/`ct_clb_*`)
|
||||
|
||||
**Concluzie**: conventia exista, dar **e inconsistenta intre clase si niciuna din variantele cu
|
||||
adevarat blocante nu e folosita in `frm_modifica_factura`**. Trei situatii diferite gasite:
|
||||
|
||||
1. **`ct_clb_cautare`** (`caut_ora.vc2:710`, folosit de `Ct_clb_ruta/agent/delegat/masina/
|
||||
clb_adresa_facturare`) — are `do_activeaza()`/`do_dezactiveaza()` (property `lactiv`,
|
||||
`caut_ora.vc2:780-806`), dar acestea **nu blocheaza textbox-ul** (care e oricum
|
||||
`ReadOnly=.T.` prin design — editarea se face doar prin popup de cautare, nu prin tastare
|
||||
directa), ci doar ascund iconita de cautare si tooltip-ul:
|
||||
```
|
||||
PROCEDURE do_dezactiveaza
|
||||
This.lactiv = .F.
|
||||
This.img_cautare.Visible = .F.
|
||||
...
|
||||
ENDPROC
|
||||
```
|
||||
Popup-ul se declanseaza doar daca `This.Parent.lactiv` e adevarat (`DblClick`/`KeyPress`/
|
||||
`img_cautare.Click`, :819-844). **Confirmat prin grep: `do_activeaza`/`do_dezactiveaza` NU sunt
|
||||
apelate nicaieri in `ofacturare_comun.vc2`** — deci in `frm_modifica_factura` raman mereu
|
||||
`lactiv=.T.` (valoarea implicita), adica mereu deblocate.
|
||||
2. **`clb_tx_data`** (`lb_tx.vc2:461-548`, container de camp-data cu buton calendar — NU e folosit
|
||||
in `frm_modifica_factura`, dar e "sora" a `clb_tx_simplu` in aceeasi biblioteca) — are metodele
|
||||
care fac chiar ce cere Marius: `dezactiveaza()`/`reactiveaza()` (`lb_tx.vc2:521-538`):
|
||||
```
|
||||
PROCEDURE dezactiveaza
|
||||
This.text_simplu1.ReadOnly = .T.
|
||||
This.text_simplu1.TabStop =.F.
|
||||
This.cmd_buton1.Enabled = .F.
|
||||
ENDPROC
|
||||
PROCEDURE reactiveaza
|
||||
This.text_simplu1.ReadOnly = .F.
|
||||
This.text_simplu1.TabStop =.T.
|
||||
This.cmd_buton1.Enabled = .T.
|
||||
ENDPROC
|
||||
```
|
||||
3. **`clb_tx_simplu`** (`lb_tx.vc2:551-585`, chiar clasa folosita pentru `Clb_dataora_exp` in
|
||||
`frm_modifica_factura`) — **nu are nicio metoda `activeaza`/`dezactiveaza`/`reactiveaza`**
|
||||
(verificat prin grep pe intreg intervalul clasei).
|
||||
4. **`clb_serie_act`** (`serii_numere.vc2:7`, containerul dedicat seriei-numarului de document) —
|
||||
**nu are nicio metoda `activeaza`/`dezactiveaza`** (grep negativ pe tot fisierul).
|
||||
|
||||
Deci: mecanismul "blocheaza antetul, deblocheaza-l la bifa" **NU exista gata-facut la nivel de
|
||||
container** pentru containerele efectiv folosite in `frm_modifica_factura`. Ce exista deja, gata
|
||||
de reutilizat ca tipar (nu ca apel direct), e reteta din `clb_tx_data.dezactiveaza()/reactiveaza()`
|
||||
(punctul 2 de mai sus, ReadOnly+TabStop+buton) — si tiparul checkbox-pe-camp deja folosit chiar in
|
||||
`frm_modifica_factura` pentru cele 4 campuri "act" (`Enabled = this.Value` pe `Valid`/`Click`,
|
||||
punctul 2 de mai sus).
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Nu am gasit in `ROAFACTURARE` niciun formular existent care sa foloseasca o **singura** bifa
|
||||
pentru a debloca simultan tot un grup de campuri de antet (nu doar `frm_modifica_factura`) —
|
||||
posibil exista un asemenea tipar in alt produs ROA (ROAGEST/ROACONT) sau in alta clasa
|
||||
ne-cautata aici; nu am extins cautarea in afara `ROAFACTURARE\COMUN`.
|
||||
- Comportamentul exact al `ReadOnly=.T.` pe `ct_clb_cautare.clb_tx_cautare.text_simplu1`
|
||||
(adica daca userul poate edita manual textul cand `lactiv=.F.`, sau doar iconita dispare) nu a
|
||||
fost testat vizual/headless, doar dedus din cod.
|
||||
- Nu am verificat daca exista vreo diferenta de comportament la nivel de `_frm_child.vcx` /
|
||||
`frm_termin_renunt` (clasele parinte) care ar putea injecta alt mecanism de blocare — am citit
|
||||
doar metodele proprii ale `frm_modifica_factura`, nu ascendenta completa.
|
||||
@@ -1,199 +0,0 @@
|
||||
# Cercetare — proforma, copiere document, puncte de intrare comanda/contract
|
||||
|
||||
Investigatie read-only, 09.08.2026. Nicio modificare de cod. Vezi si `docs\plan_13_unificare_formular_facturare.md`
|
||||
si `docs\handoff_13_formular_unificat.md` (sesiune paralela, activa la data cercetarii — nu s-a atins
|
||||
`COMUN\clase\ofacturare_comun.vc2` si nici `COMUN\programe\ofacturare_editare.prg`, marcate acolo ca "in lucru").
|
||||
|
||||
## 1. Proforma
|
||||
|
||||
**Concluzie.** Proforma nu e un tip de document separat (`poDate.tip` ramane 1-52, ca la orice
|
||||
factura), ci un **atribut de numerotare/serie** (`poDate.nIdTipDoc = 23`, fata de `5` = FACTURA).
|
||||
Se seteaza dintr-un combo "Tip document" (FACTURA/PROFORMA/BON FISCAL) aflat direct pe formularul
|
||||
de antet unificat `frm_date_factura` — **acelasi formular** folosit si pentru facturi normale, fara
|
||||
formular separat. Combo-ul e vizibil doar cand `frm_date_factura` e instantiat, adica doar pentru
|
||||
tipuri de "factura" (nu si pentru avize, care merg pe `frm_date_aviz`, fara acest combo).
|
||||
Nu exista un buton/meniu dedicat "Proforma noua": utilizatorul apeleaza fluxul normal de facturare
|
||||
(`factureaza(tnTip)`) si comuta manual pe PROFORMA in antet.
|
||||
|
||||
**Dovezi:**
|
||||
- `COMUN\programe\ofacturare_comun.prg:593-599` — setter-ul care leaga `nIdTipDoc` de `eProforma`:
|
||||
`This.eProforma = IIF(m.tnIdTipDoc = This.nIdTipDocProforma, 1, 0)` (`nIdTipDocProforma = 23`,
|
||||
`COMUN\programe\ofacturare_comun.prg:104`).
|
||||
- `COMUN\clase\ofacturare.vc2:9396-9403` — `frm_date_factura.do_schimba_tipdoc`:
|
||||
`lcTipDoc = UPPER(this.ct_clb_fdoc._combobox1.Value)` → mapare FACTURA/PROFORMA/BON FISCAL/AVIZ
|
||||
la `nIdTipDoc`.
|
||||
- `COMUN\clase\ofacturare.vc2:8745-8754` — combo-ul: `RowSource = "FACTURA,PROFORMA,BON FISCAL"`,
|
||||
`Value = FACTURA` (implicit). Owner confirmat cu `vfp_symbols.ps1 -Where`:
|
||||
`frm_date_factura [class] ofacturare.vc2:8482-9869`.
|
||||
- `COMUN\clase\ofacturare.vc2:9415,9427-9428` — la schimbarea tipului: `initializeaza_setari_document(-102)`
|
||||
pentru proforma, `poGeneratorNumere.dezaloca_numar(...)` + `creeaza_cursor_serii(poDate.nIdTipDoc)` —
|
||||
**serie/numar propriu**, realocat la comutare.
|
||||
- `COMUN\programe\ofacturare.prg:81-196` — `factureaza(tnTip, toFactura)`: la creare, `poDate.nIdTipDoc`
|
||||
se seteaza explicit la `5` (FACTURA) sau `6` (AVIZ) dupa `tnTip` (`:187-196`); PROFORMA (23) nu
|
||||
apare niciodata aici — se ajunge la ea **doar** din interactiunea cu combo-ul din antet.
|
||||
- **Fara note contabile pe proforma**: `COMUN\programe\ofacturare.prg:1960,1996,2052,2063,2103` —
|
||||
blocurile de scriere/actualizare nota contabila si atasamente sunt garzduite cu
|
||||
`poDate.eProforma = 0`.
|
||||
- **Continut specific de raport**: `COMUN\programe\ofacturare.prg:1119` (`Case poDate.eProforma = 1`)
|
||||
ramifica pe un SQL de antet propriu (parteneri/adresa facturare) pentru listare; `:1638-1643`
|
||||
(`Case ... And poDate.eProforma = 1` → `lcRaport = [PROFORMA]`) alege formularul `.fr2` dedicat
|
||||
(`COMUN\Rapoarte\proforma.fr2`, `proforma_orig.fr2`, `proforma_val.fr2`).
|
||||
- **Transformare in factura = copiere**: tooltip explicit,
|
||||
`COMUN\clase\ofacturare_comun.vc2:1409`: *"Copiere (CTRL+K) * Se foloseste si pentru generarea
|
||||
unei facturi din proforma prin copiere"*. Mecanismul: la copiere (`completeaza_setari_document`,
|
||||
vezi §2) linia care ar propaga `nIdTipDoc` de la documentul sursa e **comentata**
|
||||
(`COMUN\programe\ofacturare_comun.prg:370`: `*.nIdTipDoc = toDateAnterior.nIdTipDoc`), deci noul
|
||||
document porneste implicit la `nIdTipDoc=5` (FACTURA) indiferent ca sursa era proforma — functioneaza,
|
||||
dar prin omisiune, nu printr-o ramura dedicata "proforma → factura".
|
||||
- **Relistare proforma**: cale separata de `factureaza`, in gridul de facturi:
|
||||
`COMUN\clase\ofacturare_comun.vc2:7230-7264` (`PROCEDURE do_listare`, alt context decat
|
||||
`frm_facturi.do_listare`) — filtreaza `crsFacturi` dupa `id_proforma=`, forteaza
|
||||
`poDate.eProforma = 1` si `poDate.nRelistare = 1` (`:7258-7260`).
|
||||
- Referinta tipuri: `COMUN\docs\tipuri_documente_facturare.md` — confirma ca `TIP` (1-52) e ortogonal
|
||||
fata de proforma; niciun rand din tabel nu e "proforma" ca atare.
|
||||
|
||||
**Ce e specific proformei, confirmat cu dovada:**
|
||||
1. Serie/numar propriu (`nIdTipDoc=23`, realocare la comutare din combo).
|
||||
2. Fara scriere de nota contabila / atasamente (gate `eProforma=0` in `ofacturare.prg`).
|
||||
3. Raport de listare propriu (`.fr2` dedicate).
|
||||
4. "Transformare in factura" = copiere obisnuita, care scapa tipul de document proforma pentru ca
|
||||
linia de propagare e comentata (efect secundar, nu design explicit).
|
||||
|
||||
**Nu am putut confirma cu dovada** (vezi "Necunoscute ramase"): daca descarcarea de gestiune e
|
||||
efectiv sarita pentru proforma la nivel de Oracle (`PACK_FACTURARE`, sursa nu e in cache text local).
|
||||
|
||||
## 2. Copierea documentului
|
||||
|
||||
**Concluzie.** Traseul e `frm_facturi.But_copiaza1.Click` → `do_copiaza` (degradeaza tipul) →
|
||||
`copiere_factura` → `factureaza(tip_degradat, toFactura)` → `frm_date_factura` cu antetul
|
||||
pre-completat din `completeaza_setari_document(toFactura, .T.)`. Se aloca **intotdeauna** numar nou
|
||||
(alocarea de serie ruleaza neconditionat in `factureaza`, indiferent de `llCopiere`). Campurile de
|
||||
antet raman editabile (nimic din traseu seteaza `Enabled=.F.` pe controale de antet la copiere);
|
||||
singurul efect vizibil e relabelarea campului "Altele" in "Nr. factura" cand tipul degradat e
|
||||
1/5/10/48/49 sau 48/49 sub `gnScadereStoc=0`.
|
||||
|
||||
**Dovezi:**
|
||||
- `COMUN\clase\ofacturare_comun.vc2:3628-3713` — `do_copiaza`: degradeaza tipul (tabelul deja
|
||||
cunoscut, ex. `T2/T3/T4/T8/... → T1`, `:3696-3710`), apoi `DO copiere_factura WITH loFactura IN
|
||||
oproceduri_facturare.prg` (`:3710`).
|
||||
**Bug observat, nu cerut de investigat**: ramura `CASE INLIST(loFactura.tip,T21,T24,T26,T30,...)`
|
||||
(`:3702-3703`) scrie `lnTip = T22` in loc de `loFactura.tip = T22` — variabila gresita, degradarea
|
||||
nu se aplica efectiv pe aceasta ramura (avize catre clienti din comanda/contract/retur etc.).
|
||||
- `COMUN\programe\oproceduri_facturare.prg:150-153` — `copiere_factura`: `factureaza(toFactura.Tip,
|
||||
toFactura)`.
|
||||
- `COMUN\programe\ofacturare.prg:111` — `llCopiere = (Type('toFactura') = 'O')`;
|
||||
`:203-206` — `If m.llCopiere: poDate.completeaza_setari_document(m.toFactura, .T.)`.
|
||||
- `COMUN\programe\ofacturare_comun.prg:362-412` — `completeaza_setari_document(toDateAnterior,
|
||||
tlFactura)`: ramura `tlFactura=.T.` (copiere) seteaza `.lCopiere=.T.` si precompleteaza
|
||||
lucrare/sectie/agent/delegat/masina/`listaid = toDateAnterior.id_vanzare`/`descriere`
|
||||
(serie+numar sursa)/client (`:368-390`); **nu** propaga `nIdTipDoc`, `id_responsabil`,
|
||||
`id_venchelt` (comentate, `:370,373,377`).
|
||||
- **Numar nou, mereu**: `COMUN\programe\ofacturare.prg:208,211` — `poGeneratorNumere.ResetNumere()`
|
||||
+ `poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc)` ruleaza in
|
||||
bucla principala a lui `factureaza`, inainte de a deschide formularul, **neconditionat de
|
||||
`llCopiere`**. Functia: `COMUN\programe\oserii_numere.prg:128-177` (`Function
|
||||
creeaza_cursor_serii`).
|
||||
- **Relabel antet la copiere**: `COMUN\clase\ofacturare.vc2:9622-9628,9652-9658` —
|
||||
`IF m.llCopiere: .ct_clb_altele.do_schimba_explicatia([Nr. factura])` (altfel campul e eliminat
|
||||
din formular pentru acele tipuri).
|
||||
- **Reutilizabil vs specific degradarii**: reutilizabil = `copiere_factura`/`factureaza(tip,
|
||||
toFactura)`/`completeaza_setari_document` (mecanismul general de copiere, indiferent de tip);
|
||||
strict legat de degradare = tabelul `#DEFINE T.../DO CASE` din `do_copiaza` (`:3629-3708`) — acolo
|
||||
se decide explicit "ce tip devine ce tip la copiere", nimic din asta nu se refoloseste in afara
|
||||
acestei metode.
|
||||
|
||||
## 3. Punctele de intrare "factura din comanda" / "factura din contract"
|
||||
|
||||
**Concluzie.** Ambele exista deja, **cu precompletare reala**, dar pe cai diferite:
|
||||
- **Contract**: azi precompletarea vine **din ROACONTRACTE** (produs separat), nu din ROAFACTURARE.
|
||||
Butonul "Factura" de pe gridul de contracte populeaza globalul `goContract` din randul selectat si
|
||||
cheama acelasi `factureaza(2/6/52)` din COMUN.
|
||||
- **Comanda**: exista deja un buton de facturare **direct in ROAFACTURARE**, pe tab-ul Comenzi
|
||||
(`Page5.Ct_comenzi1`), care populeaza `goComanda` din randul de grid selectat inainte de a chema
|
||||
`factureaza(3)` — deci raspunsul la "exista deja un buton?" e **da**, nu ipotetic.
|
||||
- Exista si o cale **generica, nepre-completata**, in meniul principal al ROAFACTURARE
|
||||
(`Clase\ofundal_facturare.vc2`, tab Page2): pentru contract nu atinge `goContract`; pentru comanda
|
||||
**reseteaza explicit** `goComanda = ''` inainte de apel — utilizatorul alege manual din formular.
|
||||
|
||||
**Semnatura `factureaza`:**
|
||||
```
|
||||
COMUN\programe\ofacturare.prg:81-82
|
||||
Procedure factureaza
|
||||
Lparameters tnTip, toFactura
|
||||
```
|
||||
`tnTip` = tipul de business (1-52, tabelul din `tipuri_documente_facturare.md`); `toFactura` = obiect
|
||||
opational, folosit azi **doar** pentru copiere factura/aviz (nu pentru contract/comanda). Nu exista
|
||||
parametru dedicat pentru "contract precompletat" sau "comanda precompletata" — canalul e globalul
|
||||
`goContract`/`goComanda`, citit in `oDateFactura.Init`.
|
||||
|
||||
**Dovezi — mecanismul comun (globale citite la creare `poDate`):**
|
||||
- `COMUN\programe\ofacturare_comun.prg:261-297` — `Init`, ramura
|
||||
`If INLIST(m.tnTip, 2, 6, 52) And Type('goContract') <> 'U'` → `.id_client = goContract.id_part`,
|
||||
`.listaid = goContract.id_ctr`, `.descriere = goContract.contract`, plus interogare
|
||||
`fact_vcontracte` pentru scadenta (`:274-296`).
|
||||
- `COMUN\programe\ofacturare_comun.prg:301-328` — ramura
|
||||
`If tnTip = 3 And Type('goComanda') = 'O'` → `.id_client = goComanda.id_part`,
|
||||
`.listaid = goComanda.id_comanda`, `.descriere = goComanda.nr_comanda`, plus interogare sectie
|
||||
(`:312-323`).
|
||||
|
||||
**Dovezi — contract, din ROACONTRACTE:**
|
||||
- `D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2:1605` — `grid_contracte.AfterRowColChange`:
|
||||
`SCATTER NAME goContract MEMO` la fiecare schimbare de rand selectat.
|
||||
- `D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2:1538-1549` — `but_factura.Click`: meniu
|
||||
"Factura lei;Invoice;Factura fiscala in valuta" → `DO facturare_contracte WITH 'FACTURA LEI'/...
|
||||
IN oproceduri_facturare.prg` (copia locala din `ROACONTRACTE\COMUN`, acelasi cod ca in
|
||||
ROAFACTURARE).
|
||||
- `COMUN\programe\oproceduri_facturare.prg:118-136` — `facturare_contracte(tcTip)` →
|
||||
`factureaza(2)` / `factureaza(6)` / `factureaza(52)`.
|
||||
- **Cale generica, fara precompletare**, in ROAFACTURARE insusi:
|
||||
`Clase\ofundal_facturare.vc2:886-897` (`Page2.Cw2.do_actiune`) — acelasi meniu, aceeasi
|
||||
`facturare_contracte`, dar **nu** atinge `goContract` inainte — daca globalul nu a fost populat
|
||||
in sesiune (`Type('goContract') = 'U'`), ramura de precompletare din `Init` nu se activeaza si
|
||||
userul alege contractul manual din `frm_date_factura.do_cauta_contract`
|
||||
(`COMUN\clase\ofacturare.vc2:9067-9115`, deja cunoscut din context).
|
||||
|
||||
**Dovezi — comanda, buton deja existent in ROAFACTURARE:**
|
||||
- `COMUN\clase\ocomenzi.vc2:1580-1596` — `ct_comenzi.do_factura`:
|
||||
`SELECT crsComenzi` → `SCATTER NAME goComanda MEMO` → `DO facturare_comenzi IN
|
||||
oproceduri_facturare.prg` → `this.do_cauta()`.
|
||||
- `COMUN\clase\ocomenzi.vc2:932-937` — butonul: `ADD OBJECT 'But_factura1' AS but_factura`, clasa
|
||||
de baza `COMUN\clase\cmd_butoane.vc2:96-107` (`DEFINE CLASS but_factura ... caction = do_factura`,
|
||||
`ToolTipText = "Factura"`, `Picture = factura1.bmp`).
|
||||
Vizibilitate conditionata de starea comenzii: `COMUN\clase\ocomenzi.vc2:2199-2203`
|
||||
(`grid_comenzi...`) — `this.Parent.but_factura1.Visible = (goComanda.facturat = 0)` (ascuns daca
|
||||
deja facturata).
|
||||
- **Montare in ROAFACTURARE**: `Clase\ofundal_facturare.vc2:604` — `ADD OBJECT 'Page5.Ct_comenzi1'
|
||||
AS ct_comenzi`; `Ferestre\fundal.sc2:206` — `Page5.Ct_comenzi1.But_factura1.Name = "But_factura1"`
|
||||
confirma montarea concreta pe formular (nu doar in clasa sursa).
|
||||
- `COMUN\programe\oproceduri_facturare.prg:138-141` — `facturare_comenzi` → `factureaza(3)`.
|
||||
- **Cale generica, fara precompletare**: `Clase\ofundal_facturare.vc2:899-902`
|
||||
(`Page2.Cw3.do_actiune`): `goComanda = ''` apoi `DO facturare_comenzi ...` — reseteaza explicit
|
||||
globalul inainte de apel, deci userul alege comanda manual in formular.
|
||||
|
||||
**Concluzie combinata pentru "gazda naturala"**: pentru comanda, gazda exista deja
|
||||
(`COMUN\clase\ocomenzi.vc2`, buton `But_factura1`, montat in `Clase\ofundal_facturare.vc2` Page5).
|
||||
Pentru contract, gazda echivalenta **nu exista in ROAFACTURARE** — traieste azi doar in
|
||||
`ROACONTRACTE\Clase\ferestre_contracte.vc2`; daca s-ar dori acelasi tipar in ROAFACTURARE, ar trebui
|
||||
fie o pagina de contracte proprie (subiectul planului `docs\plan_10_integrare_contracte.md`, azi
|
||||
"propunere, neinceput", cu decizie go/no-go in asteptare), fie un buton similar montat direct pe o
|
||||
lista de contracte inexistenta azi in acest produs.
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
1. **Descarcare de gestiune pe proforma**: n-am putut confirma/infirma daca `PACK_FACTURARE`
|
||||
(server-side Oracle) sare efectiv descarcarea de stoc pentru documente cu `nIdTipDoc=23`. Sursa
|
||||
pachetului nu e in cache text local (`COMUN\docs\PACK_FACTURARE.pck` nu exista; doar
|
||||
`PACK_CONTAFIN.pck`, `PACK_UPDATE.pck` etc.). Comentariul din `ofacturare.prg:52` ("daca este
|
||||
proforma, pun toate articolele negestionabile, ca sa nu mai arate stocul") sugereaza ca partea
|
||||
VFP trateaza stocul doar vizual, nu ca dovada asupra scrierii server-side.
|
||||
2. **Campuri de antet blocate la copiere**: am confirmat ca traseul de copiere nu seteaza explicit
|
||||
`Enabled=.F.` pe controale de antet (nimic gasit in `frm_date_factura` pentru `llCopiere`), dar
|
||||
nu am verificat exhaustiv fiecare control individual — doar relabelarea campului "Altele".
|
||||
Tratati ca "probabil toate editabile", nu ca fapt verificat camp-cu-camp.
|
||||
3. **Bug-ul din `do_copiaza` (`:3702-3703`, `lnTip` in loc de `loFactura.tip`)** e raportat ca
|
||||
dovada gasita in timpul cercetarii, nu ca urmare a unei cereri explicite de audit — nu a fost
|
||||
verificat efectul lui in productie (date de test).
|
||||
4. **ROACONTRACTE nu are cod la fel de detaliat verificat ca ROAFACTURARE**: desi are cache text
|
||||
(203 fisiere `.vc2/.sc2`, contrar notei mai vechi din `plan_10_integrare_contracte.md` care spunea
|
||||
ca nu exista), nu am facut o trecere completa a formularului de contracte — doar traseul minim
|
||||
pentru `but_factura.Click`.
|
||||
@@ -1,19 +0,0 @@
|
||||
set linesize 32767
|
||||
set pagesize 200
|
||||
set trimspool on
|
||||
set feedback on
|
||||
set heading on
|
||||
|
||||
prompt ==MEMBRI_POLITICA_7==
|
||||
select count(*) from crm_politici_pret_art where id_pol=7;
|
||||
select id_pol_art, id_articol from crm_politici_pret_art where id_pol=7;
|
||||
|
||||
prompt ==CATE_LINII_COMENZI_ELEMENTE_ID_POL_7_TOTAL==
|
||||
select count(*), sum(case when cantitate<0 then 1 else 0 end) as negative, sum(case when cantitate>0 then 1 else 0 end) as pozitive
|
||||
from comenzi_elemente where id_pol=7 and sters=0;
|
||||
|
||||
prompt ==DISTINCT_ARTICOLE_PE_POLITICA_7_IN_COMENZI==
|
||||
select id_articol, count(*), sum(cantitate) from comenzi_elemente where id_pol=7 and sters=0 group by id_articol;
|
||||
|
||||
prompt ==DONE==
|
||||
exit
|
||||
@@ -1,6 +1,6 @@
|
||||
# Cine sunt "cele 41 de facturi" de la decizia 9, si daca `cod=1138989` e printre ele
|
||||
|
||||
Intrebare deschisa 4 din `docs\handoff_sesiune_08082026.md`. **Se raspunde din date, nu are nevoie
|
||||
Intrebare deschisa 4 din handoff intermediar (sters). **Se raspunde din date, nu are nevoie
|
||||
de Marius.** Sursa: `MARIUSM_AUTO@ROA_CENTRAL`, 08.08.2026.
|
||||
|
||||
## Definitia care da exact 41
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
# Inventar consumatori `VANZARI.AVIZE`/`CURS`/`ID_VALUTA`/`MULTIPLICATOR` in suita ROA
|
||||
|
||||
Cercetare STRICT de citire (fara modificari de cod, fara DDL, fara conexiuni DB, fara rulare de
|
||||
conversii noi `vcx2txt.ps1`/`git_sync.ps1`) — masoara riscul de comportament schimbat dupa
|
||||
corectiile S4 (AVIZE, WHERE lipsa) si S8/curs (garda `nin_valuta`) aplicate in `PACK_FACTURARE`
|
||||
(vezi `rec_s4_aplicare.md`). Executata cu 3 subagenti in paralel: (a) ROAFACTURARE+COMUN, (b) cele
|
||||
8 produse cu cache text deja generat, (c) restul suitei (~56 directoare).
|
||||
|
||||
## RISC REAL
|
||||
|
||||
**1. Referinta la aviz dispare de pe factura retiparita (tip=4).**
|
||||
`COMUN\programe\oproceduri_facturare.prg` (`listeaza_formular`, ~:1125/:1189/:1265) si dublura ei
|
||||
`COMUN\clase\ofacturare_comun.vc2` (`frm_facturi.do_listeaza_formular`, ~:4103/:4204) — cod
|
||||
partajat, prezent in tot ecosistemul ROA*. Construiesc `crsFacturaListare` din `FACT_VFACTURI2`
|
||||
(coloana `altele` = alias pentru `vanzari.avize` cand `tip in (4,24,8,9)`), apoi
|
||||
`poDate.descriere = Alltrim(altele)` specific pentru `tip=4` ("factura din aviz"). `poDate.descriere`
|
||||
ajunge pe formularul tiparit ca referinta "nr. aviz" (layout exact in `.frx`, neconvertit — vezi
|
||||
gap mai jos). **Ce se schimba**: la retiparirea/relistarea unei facturi `tip=4` mai vechi, unde
|
||||
`vanzari.avize` era populat gresit inainte (smearat de UPDATE-ul fara WHERE) si acum e gol pentru
|
||||
majoritatea facturilor, referinta la aviz dispare vizibil de pe document. E in calea de reprint,
|
||||
nu de emitere — deci afecteaza utilizatorul la orice reeditare/retiparire ulterioara corectiei.
|
||||
|
||||
**2. Nota "Curs: X RON/valuta" pe factura electronica/PDF, generata fara verificare `in_valuta`.**
|
||||
`xmlefactura.prg` (COMUN partajat, cod identic — verificat prin hash — in ROAEFACTURA, ROASITFIN,
|
||||
ROACONIMPORT, ROAPRINT, ROAPRODUCTIE, ROACONT/OUTPUT, si prezent si in ROAFACTURARE/COMUN):
|
||||
```
|
||||
IF !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
lcTextAditional = ... + "Curs: " + ALLTRIM(STR(loDate.curs,10,4)) + " RON/" + ... loDate.cValuta ...
|
||||
ENDIF
|
||||
```
|
||||
Conditia verifica doar `curs` nenul, nu si `loDate.in_valuta` (spre deosebire de blocul de cateva
|
||||
linii mai jos, `DocumentCurrencyCode`, care testeaza corect `in_valuta=1`). Inainte, facturile in
|
||||
LEI aveau deja `curs` populat gresit (bug), deci nota aparea eronat, dar cu o valoare "plauzibila".
|
||||
**Ce se schimba**: dupa corectie, `curs=1` pe facturile in lei — `!EMPTY(1)` tot trece, deci nota
|
||||
tot apare, dar acum arata constant `"Curs: 1.0000 RON/"` cu sufix de valuta gol (`id_valuta=0`).
|
||||
Vizibil pe fiecare factura/aviz in lei exportata ca e-factura sau tiparita, in toate produsele de
|
||||
mai sus.
|
||||
|
||||
## RISC POSIBIL
|
||||
|
||||
3. **`ofacturare_comun.vc2:4156-4157`** (si dublura `oproceduri_facturare.prg:1225-1226`): dupa
|
||||
blocul `If poDate.in_valuta = 1 ... Else ... Endif`, `poDate.Curs`/`poDate.multiplicator` sunt
|
||||
suprascrise necondiționat din valorile citite din view. Calculul de discount e corect protejat
|
||||
de `in_valuta=1`, dar nu s-a putut confirma daca FRX-ul (neconvertit) afiseaza aceste campuri
|
||||
necondiționat de `in_valuta`. De verificat in layout-ul tiparit.
|
||||
4. **`vizualizare_facturi2` (`oproceduri_facturare.prg:431-479`)**: grid-ul de cautare/listare
|
||||
facturi expune coloanele `altele`, `curs`, `multiplicator`, `valuta`, `id_valuta`, `nume_val`
|
||||
direct din `FACT_VFACTURI2`. Nu s-a putut confirma legarea la `ControlSource` in `.scx`
|
||||
(neconvertit) — daca vreuna e legata vizibil intr-un grid, utilizatorii ar vedea coloane
|
||||
goale/"1" unde inainte vedeau valori (gresite).
|
||||
5. **ROAACNPRO** `Programe\proceduri_acnpro.prg:1180-1229`, `calcul_penalitati` (calea activa):
|
||||
`Select v.Curs, v.id_Valuta ... left join vnom_valute vl on v.id_valuta = vl.id_valuta From
|
||||
vanzari v`, afisat probabil intr-un grid de review inainte de generarea facturilor de
|
||||
penalizare. Calculul numeric al penalitatii NU foloseste `curs` (confirmat), deci fara risc de
|
||||
calcul; ramane risc de **afisare**: `id_valuta=0` ar putea sa nu se potriveasca in
|
||||
`left join vnom_valute` (tabela de valute proprie ACNPRO, distincta de `NOM_VALUTE`), lasand
|
||||
coloana `valuta` goala. Nu s-a putut confirma daca `vnom_valute` are un rand pentru
|
||||
`id_valuta=0` (spre deosebire de `NOM_VALUTE`, unde existenta randului `id_valuta=0` a fost deja
|
||||
confirmata in `rec_s4_aplicare.md`, punctul 3 din sectiunea S8/curs — deci pentru view-urile
|
||||
`FACT_VFACTURI*` din COMUN acest risc e deja exclus, ramane specific tabelei proprii ACNPRO).
|
||||
6. **ROAAUTO** `Programe\oproceduri_devize.prg:1486-1532`, `relisteaza_factura_deviz`: citeste
|
||||
`curs`/`multiplicator`/`altele` din `fact_vfacturi` la reafisarea unei facturi, dar cursorul se
|
||||
inchide imediat fara ca valorile sa fie propagate mai departe — risc redus, de reverificat doar
|
||||
daca un apelant viitor se bazeaza pe acelasi cursor.
|
||||
7. **`CONTAFIN2ORA\VFP2ORA\Programe\acn.prg:~1247-1319`** (unealta de migrare, nu produs curent de
|
||||
vanzare): scrie direct `curs`/`id_valuta`/`multiplicator` in `INSERT INTO VANZARI` +
|
||||
`MERGE INTO VANZARI_CURSURI`, cu propria regula de zero-ing independenta de `PACK_FACTURARE` —
|
||||
probabil neafectata functional, dar merita o verificare separata daca unealta mai e folosita
|
||||
activ.
|
||||
|
||||
## FARA RISC (rezumat, nu enumerate)
|
||||
|
||||
- **ROAFACTURARE+COMUN**: restul celor ~930 potriviri brute pentru `AVIZE`/`CURS`/`ID_VALUTA`/
|
||||
`MULTIPLICATOR`/`ALTELE` — module NIR/import, balante/parteneri/compensari, salarii, curs
|
||||
valutar BNR, sau citiri deja corect protejate de `in_valuta`/`tip_valuta`
|
||||
(`ofacturare.prg::listeaza_ofacturare` la emitere, `ofacturare_stoc.prg`, `anaf_efactura.prg` cu
|
||||
`decode(in_valuta,1,curs,1)`, `makexmlfacturaelectronica.prg` cu garda `mmoneda<>"RON"`). Niciun
|
||||
hit `.avize` (acces direct de camp) in afara celor doua raportate mai sus.
|
||||
- **ROACONT**: `Programe\saft_d406.prg` (declaratia fiscala D406, `oSalesInvoices`) — foloseste
|
||||
`DECODE(v.in_valuta, 0, 0, ...)` explicit, output SAF-T neschimbat de corectie. Restul hit-urilor
|
||||
pe tabele proprii (`ireg_parteneri`, `act`, `rul`) sau text necorelat.
|
||||
- **ROAACNPRO** (restul), **ROACONTRACTE**, **ROAGEST**, **ROAIMOB**, **ROAREGISTRATURA**,
|
||||
**ROASTART**: zero hit relevant legat de `VANZARI` in afara COMUN (verificat, nu doar negasit).
|
||||
- **~40 de produse din restul suitei** (ROAEFACTURA si variante, ROASITFIN, ROAPRINT,
|
||||
ROACONIMPORT, ROAPRODUCTIE, ROAHOTEL si variante, ROASAL, ROAMANAGER, ROADECL, ROAPRETURI,
|
||||
ROABAZA, ROAAPROV, ROADEVIZE, etc.): hit-uri pe "AVIZE" = conceptul de business "aviz de
|
||||
expeditie" (tip document), nu coloana; hit-uri "CURS"/"ID_VALUTA" pe alte tabele proprii sau in
|
||||
`oDateFactura` (populate de apelant, protejate de `in_valuta`). `COMUNROA` (depozitul central)
|
||||
contine doar scripturi de deployment, fara logica de facturare.
|
||||
|
||||
## Rezumat acoperire
|
||||
|
||||
- **ROAFACTURARE + COMUN local**: acoperire completa `.prg` + `.vc2`/`.sc2` via `vfp_symbols.ps1
|
||||
-CodeOnly` (index deja construit). **Gap**: 207 `.frx` si 30 `.mnx` fara `.fr2`/`.mn2` in cache —
|
||||
layout-ul efectiv tiparit (unde `poDate.descriere`/`Curs`/`cValuta` chiar apar pe hartie) nu e
|
||||
verificabil fara conversie (interzisa in acest task). Riscurile REAL #1/#2 si POSIBIL #3/#4
|
||||
depind partial de acest layout.
|
||||
- **8 produse cu cache text existent** (ROAACNPRO, ROAAUTO, ROACONT, ROACONTRACTE, ROAGEST,
|
||||
ROAIMOB, ROAREGISTRATURA, ROASTART): acoperire completa `.prg` + `.vc2`/`.sc2` via
|
||||
`vfp_symbols.ps1 -CodeOnly`. **Gap**: proprietati/metadata (`ControlSource` de grid legat direct
|
||||
de o coloana, fara linie de cod explicita) nu apar in `-CodeOnly` — dar un asemenea caz s-ar
|
||||
clasifica oricum FARA RISC (simpla afisare).
|
||||
- **Restul suitei** (~56 directoare, inclusiv `COMUNROA`): acoperire **doar** pe fisierele `.prg`
|
||||
(text simplu, nu necesita conversie); zero cache text pentru `.vcx`/`.scx` — **niciun cod din
|
||||
clase/formulare compilate al acestor produse nu a fost verificat**, conform interdictiei de a
|
||||
genera cache nou. ~35 produse identificate ca in afara domeniului (unelte/infrastructura: SSH,
|
||||
server, telefonie, criptare, declaratii D1xx/D3xx/D406 etc.) fara nicio potrivire pe termenii
|
||||
cautati.
|
||||
- Nicio conexiune la baza de date folosita; cifrele despre distributia datelor (ex. randul
|
||||
`id_valuta=0` din `NOM_VALUTE`) sunt preluate din `rec_s4_aplicare.md`, deja documentate.
|
||||
|
||||
## Concluzie
|
||||
|
||||
Doua locuri cu **risc real** confirmat, ambele in codul COMUN partajat (deci efect cross-project):
|
||||
disparitia referintei la aviz de pe facturile `tip=4` retiparite, si textul "Curs: 1.0000 RON/"
|
||||
afisat gresit pe nota facturii electronice/PDF pentru facturile in lei. Restul e risc posibil,
|
||||
dependent de layout-uri `.frx`/`.scx` neconvertite (gap de acoperire cunoscut, nu absenta de risc).
|
||||
Nu s-a gasit niciun consumator cu risc real de **calcul** (sume/discounturi) — toate caile de
|
||||
calcul verificate sunt deja protejate corect de `in_valuta`.
|
||||
|
||||
---
|
||||
|
||||
## Corectie aplicata — riscul REAL #2 (nota "Curs:" din `xmlefactura.prg`)
|
||||
|
||||
Modificare de cod, ceruta explicit de team-lead dupa livrarea inventarului de mai sus. Domeniu:
|
||||
**doar** `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg`. Nicio alta copie din suita nu a
|
||||
fost atinsa.
|
||||
|
||||
### Ce s-a schimbat
|
||||
|
||||
Linia 374 (acum singura diferenta fata de fisierul dinainte de editare):
|
||||
```diff
|
||||
- IF !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
+ IF loDate.in_valuta = 1 AND !EMPTY(NVL(loDate.curs,0)) AND ATC('curs', m.lcTextAditional) = 0
|
||||
lcTextAditional = m.lcTextAditional + Iif(!Empty(m.lcTextAditional), ' # ', '') + "Curs: " + ...
|
||||
ENDIF
|
||||
```
|
||||
Garda adaugata (`loDate.in_valuta = 1 AND`) e preluata **identic** din modelul deja corect din
|
||||
acelasi fisier, la 9 linii mai jos (acum `:385`, era `:384`): `If loDate.in_valuta = 1` /
|
||||
`oinvoice.lastchild.Text = m.mmoneda`, folosit pentru `DocumentCurrencyCode`. Nicio forma noua
|
||||
inventata. Fara comentarii adaugate (regula 2, rezolvari de erori). Diff complet:
|
||||
`D:\ROA\ROAFACTURARE\docs\diff_xmlefactura_garda_valuta.patch`.
|
||||
|
||||
### Verificare pe cazuri (dupa modificare)
|
||||
|
||||
1. **Factura in lei (`in_valuta=0`), `curs=1`** (comportamentul nou, generalizat, al facturilor in
|
||||
lei dupa corectia `PACK_FACTURARE`): inainte, `!EMPTY(NVL(1,0))=.T.` -> nota aparea cu
|
||||
`"Curs: 1.0000 RON/"` (valuta goala). Acum, `loDate.in_valuta = 1` e `.F.` -> intreg `AND`-ul e
|
||||
fals -> nota NU se mai adauga. **Singurul caz care isi schimba comportamentul** (cel vizat).
|
||||
2. **Factura in valuta reala (`in_valuta=1`)**, curs populat normal: `loDate.in_valuta = 1` e
|
||||
`.T.`, restul conditiei neschimbat -> nota apare identic ca inainte. Neschimbat.
|
||||
3. **Factura veche cu `curs` NULL** (orice `in_valuta`): `NVL(NULL,0)=0` -> `!EMPTY(0)=.F.` ->
|
||||
conditia era deja falsa inainte de garda si ramane falsa (garda adaugata doar restrange in plus
|
||||
cazul `in_valuta=0`, nu schimba nimic pe ramura `curs` NULL). Neschimbat.
|
||||
|
||||
Confirmat: doar cazul 1 (facturi in lei cu `curs` efectiv nenul) isi schimba comportamentul, exact
|
||||
riscul identificat.
|
||||
|
||||
### Verificare encoding (byte-level)
|
||||
|
||||
Fisierul contine octeti cp1252 `>=0x80` (`0xEE` = "î", la liniile 1203 si 1330 — "puteti încarca
|
||||
prin SPV"), deci risc de corupere la scriere cu tool care nu pastreaza octetii nativ. Editare
|
||||
facuta cu `perl` in mod raw (`s/.../.../ `), nu cu Edit/Write:
|
||||
- Backup pre-editare: `xmlefactura.prg.pre_runda.bak` (md5 `e800c71bd08e6c472b6fe912437f37f8`,
|
||||
62093 octeti).
|
||||
- Dupa editare: md5 `c9c9f4774346b2e62bfe9c12ea02dfb3`, 62118 octeti (+25 = exact lungimea
|
||||
textului `loDate.in_valuta = 1 AND ` inserat).
|
||||
- Comparatie linie-cu-linie (raw bytes) intre backup si fisierul editat: **1364 linii in ambele,
|
||||
o singura linie diferita (374)** — restul fisierului byte-identic.
|
||||
- Octetii `0xEE` de la liniile 1203/1330 confirmati neschimbati dupa editare.
|
||||
- Scanare pentru markeri de corupere (`EF BF BD` = U+FFFD reincodat): zero potriviri.
|
||||
|
||||
Encoding intact, nicio corupere.
|
||||
|
||||
### Copii identice/asemanatoare in suita — corectie fata de raportul initial
|
||||
|
||||
Raportul initial (sectiunea RISC REAL #2) afirma ca fisierul e "identic prin hash" in ROAEFACTURA,
|
||||
ROASITFIN, ROACONIMPORT, ROAPRINT, ROAPRODUCTIE si ROACONT/OUTPUT — verificare hash directa acum
|
||||
(md5 pe tot arborele `D:\ROA`, exclus `DATABASE`) arata ca afirmatia era **partial gresita**: doar
|
||||
`ROACONIMPORT` si `ROAPRINT` sunt byte-identice intre ele; restul au fiecare continut propriu,
|
||||
divergent de `ROAFACTURARE`. Ce e adevarat si ramane valabil: **toate contin acelasi tipar de cod
|
||||
vulnerabil** (linia cu conditia fara garda pe `in_valuta`), verificat cu grep, o singura aparitie
|
||||
in fiecare fisier.
|
||||
|
||||
**Grup A — fisier byte-identic cu `ROAFACTURARE/COMUN` INAINTE de editarea de azi**
|
||||
(md5 `e800c71bd08e6c472b6fe912437f37f8`, deci acelasi patch de o linie de la `:374` se aplica
|
||||
identic, byte cu byte, in toate):
|
||||
`ROAACNPRO`, `ROAAUTO`, `ROACONT`, `ROACONTRACTE`, `ROADEF`, `ROAGEST`, `ROAIMOB`,
|
||||
`ROAREGISTRATURA`, `ROARES`, `ROASTART` — cale `D:\ROA\<PRODUS>\COMUN\programe\xmlefactura.prg`.
|
||||
(In plus, acelasi hash apare si in foldere de backup istoric fara relevanta:
|
||||
`_backup_comun_conflicts\*`, `_backup_roaimob_comun_conflict\*` — nu sunt copii vii.)
|
||||
|
||||
**Grup B — fisier divergent (alt continut/alte linii in rest), dar cu ACELASI tipar vulnerabil**
|
||||
(conditie identica textual, gasita o singura data per fisier, doar la alt numar de linie):
|
||||
| Produs | Cale | md5 | Linia conditiei |
|
||||
|---|---|---|---|
|
||||
| OUTPUT/ROACONT | `D:\ROA\OUTPUT\ROACONT\COMUN\programe\xmlefactura.prg` | `504dc24e771f6d66e4f028d1347671a8` | 350 |
|
||||
| ROACONIMPORT | `D:\ROA\ROACONIMPORT\COMUN\programe\xmlefactura.prg` | `fa1e389839109ae46da1ef815e102259` | 356 |
|
||||
| ROAEFACTURA | `D:\ROA\ROAEFACTURA\COMUN\programe\xmlefactura.prg` | `200442ad86e180c2484c96367ac9514a` | 356 |
|
||||
| ROAPRINT | `D:\ROA\ROAPRINT\COMUN\programe\xmlefactura.prg` | `fa1e389839109ae46da1ef815e102259` | 356 |
|
||||
| ROAPRODUCTIE | `D:\ROA\ROAPRODUCTIE\COMUN\programe\xmlefactura.prg` | `b71c1d9284d8ee78d02429b04c968a35` | 326 |
|
||||
| ROASITFIN | `D:\ROA\ROASITFIN\COMUN\programe\xmlefactura.prg` | `47bb2e49770713b396e855e8af0ae2ea` | 356 |
|
||||
|
||||
**Grup C — NU are acest bloc de cod deloc** (verificat, nu doar negasit — nu construiesc nota de
|
||||
curs valutar in e-factura): `ROADECL`, `ROAMANAGER`, `ROAPRETURI`, `ROASAL`. Fara risc, fara
|
||||
propagare necesara.
|
||||
|
||||
**Fisierul modificat azi**: doar `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg` (md5 nou
|
||||
`c9c9f4774346b2e62bfe9c12ea02dfb3`). Toate celelalte 16 cai listate mai sus (Grup A + Grup B)
|
||||
raman NEATINSE, cu bug-ul inca prezent — propagarea e decizie de proces a lui Marius, nu s-a facut
|
||||
aici.
|
||||
|
||||
### Livrabile
|
||||
|
||||
- Modificare: `D:\ROA\ROAFACTURARE\COMUN\programe\xmlefactura.prg` (linia 374, +garda `in_valuta`).
|
||||
- Patch de review: `D:\ROA\ROAFACTURARE\docs\diff_xmlefactura_garda_valuta.patch`.
|
||||
- Backup pre-editare (ramas pe disc, netracked): `xmlefactura.prg.pre_runda.bak` in acelasi folder.
|
||||
- Aceasta sectiune.
|
||||
|
||||
Fara commit git/svn — asteapta aprobarea patch-ului.
|
||||
@@ -39,7 +39,7 @@ conform interdictiei primite.
|
||||
> dupa adaugarea discountului — ea verifica `.When`-urile de celula, neatinse de aceasta completare,
|
||||
> deci riscul e mic, dar golul e declarat, nu ascuns.
|
||||
>
|
||||
> Diff-ul consolidat (COMUN + ROAGEST) e regenerat in `docs\diff_d42_efactura_readonly.patch`.
|
||||
> Diff-ul consolidat (COMUN + ROAGEST) e regenerat in diff aplicat (sters).
|
||||
|
||||
## Ce s-a schimbat, si unde
|
||||
|
||||
@@ -233,7 +233,7 @@ e demonstrat pe flag, nu pe o coincidenta a documentului ales. Captura:
|
||||
- Zero scrieri in Oracle in toata sesiunea — toate interogarile (`EsteInEFactura`,
|
||||
`IncarcaCursoareModificareNota`, `IncarcaVanzareNota`, `IncarcaArticoleFactura`) sunt `SELECT`.
|
||||
- Zero commit (git/svn).
|
||||
- Diff consolidat: `docs\diff_d42_efactura_readonly.patch` (ambele fisiere).
|
||||
- Diff consolidat: diff aplicat (sters) (ambele fisiere).
|
||||
- Fisiere noi, necomise: `COMUN\utile\Teste\editare_factura\test_efactura_readonly.prg` (+ log),
|
||||
`COMUN\utile\Teste\editare_factura\test_ui_efactura_readonly.prg` (+ log + screenshot in
|
||||
`screenshots_efactura\`).
|
||||
|
||||
@@ -175,7 +175,7 @@ Altele:
|
||||
| `COMUN\utile\Teste\editare_factura\descopera_caz_test.prg` | **nou** |
|
||||
| `COMUN\utile\Teste\editare_factura\test_page3_articole.prg` | modificat |
|
||||
| `COMUN\utile\Teste\editare_factura\test_incarca_vanzare_din_nota.prg` | modificat |
|
||||
| `docs\diff_datoria6_suite_regresie.patch` | diff-ul celor trei |
|
||||
| diff aplicat (sters) | diff-ul celor trei |
|
||||
|
||||
Comenzile de rulare:
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ dupa modelul `test_ui_sterge_linie.prg`:
|
||||
**`test_d42_efactura_readonly.prg`** — cazul pozitiv, cu date mock (nu exista document real din
|
||||
luna curenta trimis in eFactura, cf. §1):
|
||||
1. Incarca `tact`/`tvd` pentru un document real din luna curenta cu `lAreArticoleVanzari = .T.`
|
||||
(ex. acelasi `id_vanzare = 1049` mentionat in `handoff_punct6_dupa_s5.md`, daca inca in luna
|
||||
(ex. acelasi `id_vanzare = 1049` mentionat in handoff intermediar (sters), daca inca in luna
|
||||
curenta la momentul rularii).
|
||||
2. Dupa `IncarcaVanzareDinNota`, forteaza `tvanz.id_fact` (sau `tact.id_fact`, dupa care varianta se
|
||||
alege in §8) la o valoare stiuta ca exista in `ANAF_EFACTURA` (mock: `INSERT` intr-un cursor
|
||||
@@ -230,7 +230,7 @@ ca nu s-a facut nicio interogare Oracle suplimentara, sau direct daca se mock-ui
|
||||
contor de apeluri).
|
||||
|
||||
Toate cele trei suite: fara scriere in Oracle, `QUIT` la final, log langa `.prg` cu acelasi nume +
|
||||
`_log.txt`, conform conventiei din `handoff_punct6_dupa_s5.md`.
|
||||
`_log.txt`, conform conventiei din handoff intermediar (sters).
|
||||
|
||||
## 8. Schita de diff — corectia necesara peste diff-ul in lucru
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ fara coloane*" - identica, doar declansata din `Show()` in loc de `Init()`. `Rec
|
||||
text) ramane `"tvd"`, dar `Columns` colapseaza la 0 - de aici simptomul "pagina apare, grid gol".
|
||||
|
||||
## Arhitectura FINALA (dupa o coliziune de editare intre agenti concurenti pe `Show()`,
|
||||
## descrisa in `docs\handoff_fix_grid_tvd_blank.md` - rezolvata, verificata mai jos)
|
||||
## descrisa in handoff intermediar (sters) - rezolvata, verificata mai jos)
|
||||
|
||||
Varianta livrata difera de iteratia descrisa initial mai sus (`ZAP`+`APPEND FROM` in
|
||||
`IncarcaArticoleFactura` + `Refresh()` in `Show()`). Arhitectura finala muta incarcarea
|
||||
@@ -116,7 +116,7 @@ impactul in ROACONT pe `comun.vc2:2436` (registrul jurnal) ramane de verificat s
|
||||
## Stare livrare
|
||||
|
||||
Fara commit. Diff regenerat din starea curenta (git diff vs HEAD, in `COMUN`):
|
||||
`docs\diff_fix_grid_tvd_blank.patch`. Write-back facut in `COMUN\clase\omodificari.vcx`/`.vct` si
|
||||
diff aplicat (sters). Write-back facut in `COMUN\clase\omodificari.vcx`/`.vct` si
|
||||
`COMUN\clase\ofacturare_comun.vcx`/`.vct` (mtime text/binar sincrone, verificat 08.08.2026 23:49).
|
||||
`ofacturare_editare.prg` e ASCII pur, editat direct, fara risc de encoding.
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ principal.
|
||||
sintetice (1 id_set / 2 id_set +5 / 2 id_set fara relatia +5 / 3 id_set) - toate 4 + cele 2
|
||||
cazuri de regresie (`cod=1140888`, `cod=1140885`) au dat rezultatul asteptat la rulare headless
|
||||
(`vfp9.exe -A -T`).
|
||||
- Patch: `docs\diff_runda3_garda_idset.patch` (netrimis la commit, asteapta review).
|
||||
- Patch: diff aplicat (sters) (netrimis la commit, asteapta review).
|
||||
- Baseline: `COMUN\clase\ofacturare_comun.vc2.pre_runda3.bak`.
|
||||
|
||||
## Netestat
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
# Cercetare: integrare CONTRACTE, politici de preturi, nomenclator ca lista de preturi
|
||||
|
||||
Metoda: `vfp_symbols.ps1` (cache text ROAFACTURARE deja la zi) + Grep pe `.prg`/`.vc2`/`.mn2`.
|
||||
Fapte cu `fisier:linie`; ipoteze marcate `IPOTEZA:`.
|
||||
|
||||
## SUBIECT A - Integrare pagina CONTRACTE (todo #10)
|
||||
|
||||
### 1. Unde exista azi contractele
|
||||
|
||||
Produs separat, working copy completa: `D:\ROA\ROACONTRACTE` (`.git` + `.svn`, `roaContracte.pjx`,
|
||||
`roacontracte.exe`). Structura: `Clase\` (`ofundal.vcx`, `onom_clienti.vcx`, `oOptiuni.vcx`,
|
||||
`roaclienti.vcx`, `ferestre_contracte.vcx` - probabil formularele CRUD de contracte),
|
||||
`Ferestre\`, `Programe\`, `Rapoarte\`, `Meniuri\`, `COMUN\` (propria copie a librariei partajate),
|
||||
`Teste\`, `docs\`.
|
||||
|
||||
**Important**: ROAFACTURARE NU e izolat de contracte azi - are deja o integrare de facturare
|
||||
partiala "pe baza de contract" (vezi punctul 4), care citeste direct din schema Oracle a
|
||||
ROACONTRACTE prin view-uri (`vcontracte`, `fact_vcontracte`, `tipuri_contracte`), fara pagina de
|
||||
editare. `ferestre_contracte.vcx` din ROACONTRACTE contine probabil formularele CRUD care ar
|
||||
trebui aduse in ROAFACTURARE (nu au fost deschise/citite - binar, necesita conversie separata daca
|
||||
se trece la implementare).
|
||||
|
||||
Exista deja urme ale unei integrari partiale de UI in ROAFACTURARE:
|
||||
- `Meniuri\contracte.mnx`/`.mn2` (`D:\ROA\ROAFACTURARE\Meniuri\contracte.mn2:1`) - NU e un meniu de
|
||||
administrare contracte, ci un shortcut-popup cu 3 optiuni de facturare ("Factura fiscala lei /
|
||||
Invoice / Factura fiscala valuta") - cf. continut citit integral.
|
||||
- `Grafice\icon_contracte1.png`, `icon_contracte2.png`, `Grafice\Originale\contracte.png` -
|
||||
iconite deja pregatite in ROAFACTURARE.
|
||||
|
||||
### 2. Cum e integrata azi COMENZI in ROAFACTURARE (sablonul de urmat)
|
||||
|
||||
COMENZI **nu** e produs separat legat prin exe, ci cod montat direct in ROAFACTURARE din
|
||||
`COMUN\` (librarie partajata `gitea.romfast.ro:romfast/comun.git`, cf. CLAUDE.md). Exista si un
|
||||
produs stand-alone `D:\ROA\ROACOMENZI` (cu `.pjx` propriu), dar in ROAFACTURARE comenzile sunt
|
||||
o **pagina/panou montat direct in formularul principal (fundal)**, nu un exe separat lansat.
|
||||
|
||||
Reteta pas cu pas (comenzi ca model pentru contracte):
|
||||
|
||||
1. **Clasa container** `ct_comenzi` din `COMUN\clase\ocomenzi.vcx` (`.vc2` cache:
|
||||
`COMUN\clase\ocomenzi.vc2`) - contine formulare/containere CRUD comenzi
|
||||
(`frm_optiuni_comenzi`, cursoare `vcomenzi_elemente` etc.).
|
||||
2. **Montare in formularul principal**: containerul e plasat ca obiect copil in
|
||||
`Clase\ofundal_facturare.vc2` (form fundal), cu comentariul `< END OBJECT:
|
||||
ClassLib="..\comun\clase\ocomenzi.vcx" BaseClass="container" />` in jurul liniei
|
||||
`Clase\ofundal_facturare.vc2:831`; obiectul se numeste `lb_comenzi`
|
||||
(`Clase\ofundal_facturare.vc2:824`).
|
||||
3. **Butoane de actiune** ("Cw" = clase de tip buton-cu-drept, vezi punctul 3) legate la proceduri
|
||||
business, ex. `Page2.Cw3.do_actiune` -> `DO facturare_comenzi IN oproceduri_facturare.prg`
|
||||
(`Clase\ofundal_facturare.vc2:899-902`).
|
||||
4. **Inregistrare in `Programe\roafacturare.prg`** (entry point):
|
||||
- `SET CLASSLIB TO ocomenzi ADDITIVE` sub comentariul `*** COMENZI`
|
||||
(`Programe\roafacturare.prg:180-181`);
|
||||
- `SET PROCEDURE TO orap_comenzi.prg / onom_comenzi.prg / update_comenzi.prg ADDITIVE`
|
||||
(`Programe\roafacturare.prg:239-242`), tot sub `*** COMENZI`;
|
||||
- variabile module: `PRIVATE pocomenzi,pocomenzielemente,polucrari,pocomenzi2,polucrarielemente`
|
||||
(`Programe\roafacturare.prg:246-247`).
|
||||
- Toate cele 3 `.prg` (`orap_comenzi.prg`, `onom_comenzi.prg`, `update_comenzi.prg`) si clasa
|
||||
`ocomenzi.vcx`/`.vct` locuiesc fizic in `COMUN\programe\` / `COMUN\clase\`, dar sunt
|
||||
inregistrate ca membri ai proiectului `roafacturare.pjx` (confirmat prin Grep pe `.pjx`:
|
||||
`COMUN\clase\ocomenzi.vcx`, `COMUN\programe\orap_comenzi.prg` etc. apar in el).
|
||||
5. **Business logic de facturare din comenzi**: `Procedure facturare_comenzi` in
|
||||
`COMUN\programe\oproceduri_facturare.prg:139-141` - un simplu `factureaza(3)` (tip document 3
|
||||
= "din comanda", motorul central `factureaza()` face restul).
|
||||
6. **Meniu**: nu exista `Meniuri\comenzi.mnx` separat in ROAFACTURARE - comenzile nu au intrare de
|
||||
meniu proprie, ci doar butonul `Cw3` de pe pagina fundal (Page2 = "Facturare"). Contractele au
|
||||
deja `Meniuri\contracte.mnx` dar cu alt continut (shortcut factura), deci pentru pagina noua de
|
||||
contracte ar trebui fie extins acest fisier, fie creat altul.
|
||||
|
||||
Concluzie sablon: pentru CONTRACTE ar insemna (a) o clasa container tip `ct_contracte` (posibil
|
||||
adaptata din `ferestre_contracte.vcx` al ROACONTRACTE, mutata/duplicata in `COMUN\clase\`), (b)
|
||||
montarea ei ca obiect in `ofundal_facturare.vc2` langa `lb_comenzi`, (c) inregistrare `SET
|
||||
CLASSLIB`/`SET PROCEDURE` in `roafacturare.prg` sub un bloc nou `*** CONTRACTE`, (d) adaugare in
|
||||
`roafacturare.pjx`.
|
||||
|
||||
### 3. Mecanismul de DREPTURI pe obiecte
|
||||
|
||||
Sursa: `COMUN\programe\acces_meniu.prg` (fisier citit integral).
|
||||
|
||||
- **Sursa de date**: view Oracle `contafin_oracle.vdef_util_obiecte`, interogat cu
|
||||
`select cheie,id_firma from contafin_oracle.vdef_util_obiecte where id_util=?gnIdUtil and
|
||||
id_program=?gnIdProgram and id_firma=?gnIdFirma` (`acces_meniu.prg:29-31`), rezultat in cursorul
|
||||
`crsdrepturi` (o singura coloana cheie relevanta: `cheie`, string).
|
||||
- **Codificarea cheii**: concatenare de "caractere de nivel" - `Chr(lnKey)` pentru fiecare nivel de
|
||||
pageframe/pagina (`dezactiveaza_obiecte_pageframe`, `acces_meniu.prg:103-165`, recursiv pe
|
||||
subpageframe-uri), plus un cod de 2 cifre pentru fiecare buton `Cw*`:
|
||||
`lcCheie = lcKey + Padl(Alltrim(Str(.Objects(l).nid_cw)), 2, '0')` (`acces_meniu.prg:138`).
|
||||
Fiecare obiect `Cw*` are proprietatea `nid_cw` (numarul lui in cadrul paginii) si la runtime i se
|
||||
seteaza `ccheie` (`acces_meniu.prg:140`) si `coptiuni_active` (lista de operatii CRUD permise,
|
||||
citita din caracterele urmatoare cheii - `acces_meniu.prg:141-149`). Butonul apeleaza
|
||||
`.Objects(l).activeaza()` / `.dezactiveaza()` in functie de gasire (`acces_meniu.prg:150-152`).
|
||||
- **Pentru imagini/iconite** (nivel diferit, folosit pe alte forme): proprietate `ccod` pe obiect
|
||||
(`acces_meniu.prg:48`), aceeasi logica de cautare in `crsdrepturi`.
|
||||
- **Cod de meniu (pad-uri)**: `GetAccesByCod(tcCod, tcAccesDefault)` (`acces_meniu.prg:236-276`)
|
||||
cauta o cheie explicita (cod optiune meniu, ex. "ZA01") in `crsdrepturi` si intoarce lista de
|
||||
operatii permise (ex. "1;2;3;4").
|
||||
- **Punct de intrare**: `verifica_drepturi(tcObiectFundal, tcPageFrame)`
|
||||
(`acces_meniu.prg:9-15`) apelat din formularul fundal (`Ferestre\fundal.sc2:699`:
|
||||
`verifica_drepturi('gofundal','_pgfrmbase1')`), care incarca `crsdrepturi` o singura data per
|
||||
firma (cache in memorie, `citeste_drepturi`, `acces_meniu.prg:17-37`) si dezactiveaza in cascada
|
||||
paginile/butoanele/meniurile fara drept.
|
||||
- **Administrare drepturi** (unde se declara catalogul de obiecte si se atribuie pe grupuri):
|
||||
`COMUN\clase\drept_grupuri.vc2` - `frm_grupuri`, apel catre pachetul Oracle
|
||||
`PACK_DREPTURI.grupdreptmodproc` (`COMUN\clase\drept_grupuri.vc2:39`) si `citeste_drepturi
|
||||
(loRec.id_grup)` (`COMUN\clase\drept_grupuri.vc2:205`).
|
||||
|
||||
IPOTEZA: catalogul efectiv de "obiecte disponibile pentru ROAFACTURARE" (denumirile/codurile
|
||||
`nid_cw`/`ccod`/coduri de meniu, ex. cele pentru COMENZI) e definit **partial in designerul VFP**
|
||||
(proprietatea `nid_cw` seteaza pe fiecare buton la design-time in `.scx`/`.vcx`) si **partial
|
||||
server-side** in schema Oracle `contafin_oracle` (tabelul din spatele view-ului
|
||||
`vdef_util_obiecte`, populat probabil printr-un script de instalare/migrare, nu vazut in sursa
|
||||
VFP). Pentru "comasarea" drepturilor ROACONTRACTE + ROAFACTURARE mentionata in cerere, ar trebui
|
||||
inspectat acest tabel server-side (in afara sursei VFP disponibile aici) plus alocarea de noi
|
||||
`nid_cw` pentru butoanele noi de contracte, fara sa coincida cu cele deja folosite de COMENZI/
|
||||
lista de preturi/avize pe aceeasi pagina.
|
||||
|
||||
Exemplu concret COMENZI: butonul `Page2.Cw3` (facturare din comenzi) foloseste automat cheia
|
||||
`<cheie_pagina>+'03'` (Cw3 => `nid_cw=3`); pentru un buton nou de contracte pe aceeasi pagina ar
|
||||
trebui un `nid_cw` neutilizat (ex. 11+, dat fiind ca Page2 are deja Cw1..Cw9 conform
|
||||
`Clase\ofundal_facturare.vc2:882-926`).
|
||||
|
||||
### 4. Facturarea pe baza de comanda / pe baza de contract
|
||||
|
||||
**Comanda -> factura**: `Procedure facturare_comenzi` (`COMUN\programe\oproceduri_facturare.prg:
|
||||
139-141`) => `factureaza(3)`. Cautarea comenzii disponibile pentru facturare:
|
||||
`Function caut_comanda_gestiune` (`COMUN\programe\oproceduri_facturare.prg:1961-1983`), citeste
|
||||
din view-ul `vcomenzi` (`... FROM ] + gcS + [.vcomenzi`), filtru
|
||||
`facturat = 0 and interna = 3 ... ` (linia 1977).
|
||||
|
||||
**"Pe baza de contract" EXISTA DEJA**, mai complet decat comenzile pe alocuri:
|
||||
- `Procedure facturare_contracte(tcTip)` (`COMUN\programe\oproceduri_facturare.prg:119-136`) -
|
||||
primeste tipul de document ("FACTURA LEI"/"INVOICE"/"FACTURA VALUTA") si apeleaza
|
||||
`factureaza(2)`/`factureaza(6)`/`factureaza(52)`.
|
||||
- Buton pe pagina fundal: `Page2.Cw2.do_actiune` (`Clase\ofundal_facturare.vc2:886-897`) - meniu
|
||||
`xmenu` cu cele 3 optiuni, cheama `facturare_contracte`.
|
||||
- **Cautare contract**: `Function caut_contract_facturare(tnIdPart, tcSirTipFacturare)`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:1986-2021`) - citeste din view-ul `fact_vcontracte`
|
||||
(`select id_ctr, contract, numar, data, denumire, scadenta_incasare, opt_facturare,
|
||||
text_standard, afisare_scadenta FROM fact_vcontracte`, linia 2001), filtrat pe
|
||||
`opt_facturare in (...)` si `id_part`.
|
||||
- **Alegerea contractului la factura**: `frm_date_factura.do_cauta_contract`
|
||||
(`COMUN\clase\ofacturare.vc2:9067-9115`) si `frm_date_aviz.do_cauta_contract`
|
||||
(`COMUN\clase\ofacturare.vc2:7049-7051`) apeleaza `caut_contract_facturare`.
|
||||
- **Editorul de articole pe factura** are un tab/grid dedicat contractelor:
|
||||
`frm_facturare_articole` cu controale `grd_contracte`, `cb_contracte` (combobox cu ratele /
|
||||
contractele), populate din cursorul `crscontracte` (`COMUN\clase\ofacturare.vc2:15069-15107` si
|
||||
in jur). Optiunea `opt_facturare` din `fact_vcontracte`/`crsfactura` marcheaza randurile "din
|
||||
contract" (`COMUN\programe\oproceduri_facturare.prg:176-177`, `Inlist(opt_facturare,1,2)` in alt
|
||||
context legat de seturi).
|
||||
- **Aviz pe baza de contract**: exista si un tip de aviz "26 - catre clienti din contract"
|
||||
(`COMUN\programe\oproceduri_facturare.prg:207`, enumerat si in `caut_avize`,
|
||||
`COMUN\programe\oproceduri_facturare.prg:2045`), apelat din `emitere_aviz_clienti(tnTip=3)`.
|
||||
|
||||
Concluzie: **motorul de facturare din contract e deja complet functional** in ROAFACTURARE (citire
|
||||
din schema ROACONTRACTE prin view-uri Oracle `vcontracte`/`fact_vcontracte`/`tipuri_contracte`).
|
||||
Ce lipseste conform cererii e (a) o **pagina de editare CRUD a contractelor** in ROAFACTURARE
|
||||
(azi doar in exe-ul separat ROACONTRACTE) si (b) **rapoarte de contracte** in ROAFACTURARE, plus
|
||||
(c) unificarea drepturilor. Nu a fost gasit niciun raport de contracte in
|
||||
`ROAFACTURARE\Rapoarte\` (glob `*contract*` nu a dat `.frx` in Rapoarte, doar meniu/iconite).
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT B - Politici de preturi (todo #11)
|
||||
|
||||
### 5. Unde sunt azi definite/editate
|
||||
|
||||
Produs separat, mic, dedicat: `D:\ROA\ROAPRETURI` (`.pjx` propriu, `roapreturi.exe`). Structura:
|
||||
`Programe\onom_preturi.prg`, `Programe\update_preturi.prg`, `Programe\update_nomenclator.prg`,
|
||||
`Clase\opreturi.vcx`, `Clase\onom_preturi.vcx`, `Clase\ofundal_preturi.vcx`,
|
||||
`Clase\ofundal_roapreturi.vcx`, `Ferestre\fundal.scx`. (Continutul acestor clase nu a fost convertit
|
||||
in text - ROAPRETURI nu are un cache text propriu generat in aceasta sesiune; doar structura de
|
||||
fisiere a fost inspectata.)
|
||||
|
||||
Interfata de editare pare sa fie un produs desktop de sine statator, distinct de ROAFACTURARE si de
|
||||
ROACONT, focalizat strict pe politici/liste de preturi si pe actualizarea nomenclatorului
|
||||
(`update_nomenclator.prg` sugereaza ca ROAPRETURI scrie si in nomenclatorul comun de articole).
|
||||
|
||||
### 6. Tabele/view-uri implicate (identificate din ROAFACTURARE)
|
||||
|
||||
Din codul ROAFACTURARE care CITESTE politici de preturi (nu editeaza), gasite:
|
||||
- `vcrm_politici_preturi` - view folosit in cautare dupa drepturi utilizator
|
||||
(`COMUN\clase\baza.vc2:10087`, `:10157`, `:10502-10512`). Interogare efectiva:
|
||||
`select nume_lista_preturi, id_pol from crm_vpolpretcurutil` (`COMUN\clase\baza.vc2:10504`) -
|
||||
deci exista si view-ul `crm_vpolpretcurutil` ("politica de pret curenta pentru utilizator"),
|
||||
cheie `id_pol`.
|
||||
- `vvanzari_detalii` - contine coloana `nume_lista_preturi` folosita in rapoarte de marfa
|
||||
(`COMUN\clase\configurare.vc2:3915-3972`, `frm_raport_marfa`).
|
||||
- Meniu dedicat facturarii pe lista de preturi: `Meniuri\politica.mnx`/`.mn2`/`.MPR` in
|
||||
ROAFACTURARE; procedura `facturare_lista_de_preturi` = `Do politica.mpr`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:113-116`), buton `Page2.Cw1.do_actiune`
|
||||
(`Clase\ofundal_facturare.vc2:882-884`).
|
||||
- Prefixul `crm_`/`CRM` in numele tabelelor/view-urilor (`vcrm_politici_preturi`,
|
||||
`crm_vpolpretcurutil`) sugereaza schema/modul Oracle numit "CRM", separat de schema principala
|
||||
de facturare (`gcS`). IPOTEZA: politicile de pret sunt un modul Oracle transversal (folosit si
|
||||
de ROAGEST, ROAPRETURI, ROACONTRACTE), nu proprietatea exclusiva a unui singur produs VFP.
|
||||
- Comenzile (ROACOMENZI/`ocomenzi.vcx`) au propriul mecanism de asociere pret-din-comanda:
|
||||
globale `gnIdPoliticaPret`, `gnId_lista_preturi_PV` (`Programe\roafacturare.prg:467,469`),
|
||||
folosite si in `frm_optiuni_comenzi` (`COMUN\clase\ocomenzi.vc2:6488-6686`, variabila
|
||||
`gnID_LISTA_PRETURI_PV` = politica de pret "de productie" folosita la generarea automata a
|
||||
comenzilor). Cursorul de articole al comenzii are coloanele `id_pol`, `nume_lista_preturi`,
|
||||
`pret`, `pret_cu_tva`, `ptva` direct in el (`COMUN\clase\ocomenzi.vc2:1227-1229`, cursor creat
|
||||
din view-ul `vcomenzi_elemente`).
|
||||
|
||||
Nu a fost gasita nicio schema DBF/DDL explicita pentru "politici de preturi" / "liste de preturi"
|
||||
in sursa VFP (tabelele reale sunt Oracle, definite server-side; VFP le vede doar prin view-uri
|
||||
enumerate mai sus). N-a fost identificat un tabel separat de "note contabile asociate politicii de
|
||||
pret" in codul cercetat - contul contabil de vanzare pare sa vina din nomenclatorul de articole
|
||||
(`nom_articole.cont`, vezi punctul 10), nu dintr-o tabela separata legata de politica.
|
||||
|
||||
### 7. Ce foloseste ROAFACTURARE azi din aceste date
|
||||
|
||||
- **Facturare pe lista de preturi** (`Do politica.mpr`) - flux complet de vanzare pe baza unei
|
||||
politici de pret selectate (analog cu vanzarea din stoc/comenzi/contract), tip document
|
||||
distinct in motorul central `factureaza()`.
|
||||
- **Cautare/afisare politica dupa drepturi utilizator** (`COMUN\clase\baza.vc2:10502-10512`) -
|
||||
ROAFACTURARE citeste `crm_vpolpretcurutil` pentru a limita politicile vizibile la cele pe care
|
||||
utilizatorul are drept (alt strat de drepturi, distinct de `acces_meniu.prg` - specific pe
|
||||
politici de pret, posibil gestionat tot server-side prin pachetul `PACK_DREPTURI`).
|
||||
- **Rapoarte de vanzari pe lista de preturi** (`frm_raport_marfa`,
|
||||
`COMUN\clase\configurare.vc2:3915-3972`) - grupare/însumare pe `nume_lista_preturi`.
|
||||
- Nu editeaza politici/liste - doar le CITESTE si le foloseste ca sursa de pret la facturare/
|
||||
raportare. Editarea (adaugare politica, adaugare articole in politica, preturi) ramane in
|
||||
ROAPRETURI.
|
||||
|
||||
Concluzie pentru migrare: ce ar trebui **mutat efectiv in ROAFACTURARE** (conform cererii - "se
|
||||
folosesc numai in programul ROAFACTURARE") e interfata de editare (`opreturi.vcx`/
|
||||
`onom_preturi.vcx` din ROAPRETURI), nu structura de date (Oracle, deja partajata/citita corect).
|
||||
Rapoartele si drepturile pe liste de preturi trebuie de asemenea aduse ca pagina/panou in
|
||||
ROAFACTURARE, dupa acelasi sablon COMENZI descris la punctul 2.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT C - Nomenclatorul de articole ca lista de preturi virtuala (todo #12)
|
||||
|
||||
### 8. Structura tabelei de nomenclator
|
||||
|
||||
Tabela Oracle **`catalog_articole`**, expusa prin view-ul **`vnom_articole`** (si `vnom_articole2`
|
||||
pentru un al doilea tip - vezi `nom_articole2_nou`, `COMUN\programe\onomenclatoare.prg:1376-1396`,
|
||||
tabela `catalog_articole2`).
|
||||
|
||||
Coloane identificate din interogari/scatter (nu e o lista exhaustiva - vin din SELECT-uri
|
||||
punctuale, nu din DDL):
|
||||
`id_articol, denumire, codmat, codmatf (cod furnizor), codbare, um, grupa, subgrupa, id_grupa,
|
||||
id_subgrupa, dnf, cont (cont contabil, 3-4 caractere), acont, inactiv, sters, in_stoc, in_crm,
|
||||
tip (ex. 1 = manopera pt. ROAACNPRO), id_part/partener (pt. articole legate de furnizor/client)`.
|
||||
Surse: `COMUN\clase\ocriterii.vc2:1531` (`select denumire, codmat, um, grupa, subgrupa, id_grupa,
|
||||
id_subgrupa, dnf, cont, acont, inactiv, id_articol from vnom_articole`),
|
||||
`COMUN\programe\onomenclatoare.prg:1345-1353` (`in_crm`, `in_stoc`, `tip`),
|
||||
`COMUN\clase\ointroduceri.vc2:9631` (`in_stoc, cont`).
|
||||
|
||||
**Nicio coloana de pret** nu a fost gasita direct pe `nom_articole`/`catalog_articole` (grep
|
||||
`pret_v|pretv|pret_lista` in `onomenclatoare.prg` = fara rezultate; scatter-ul din
|
||||
`nom_articole_nou` nu populeaza niciun camp de pret). Confirma punctul 11 mai jos.
|
||||
|
||||
**Formular de editare**: `frm_catalog_articole` (grid/cautare) si `frm_catalog_articole_nou`
|
||||
(fisa), ambele in `COMUN\clase\onom_articole.vc2` (`:531-599`, `:1655-1733`), salvare prin
|
||||
`cus_odata_catalog_articole.salvare` si `Adauga_Modifica_Inregistrare('catalog_articole', ...)`
|
||||
(`COMUN\programe\onomenclatoare.prg:1367,1443`). Deschidere din meniu:
|
||||
`Procedure viz_catalog_articole` (`COMUN\programe\oproceduri_articole.prg:62-122`).
|
||||
|
||||
**Important pentru subiectul B/C**: `nom_articole_nou` (`COMUN\programe\onomenclatoare.prg:
|
||||
1343-1353`) marcheaza acelasi articol cu `in_crm = 1` cand programul curent e ROAPRETURI sau
|
||||
ROACONTRACTE, respectiv `in_stoc = 1` in rest (inclusiv ROAFACTURARE) - **nomenclatorul de
|
||||
articole e deja UNIC/PARTAJAT** intre ROAFACTURARE, ROAPRETURI, ROACONTRACTE si ROAACNPRO (aceeasi
|
||||
tabela `catalog_articole`), flagurile `in_stoc`/`in_crm`/`tip` fiind doar clasificari de
|
||||
utilizare, nu tabele separate. Asta simplifica mult todo #12: nomenclatorul nu trebuie replicat,
|
||||
doar completat cu campuri de pret/tva/cont-vanzare si folosit direct ca sursa de pret la
|
||||
facturare.
|
||||
|
||||
### 9. Mecanismul actual de "lista de articole din stoc ca lista de preturi virtuala"
|
||||
|
||||
Confirmat: e mecanismul de **"vanzare din stoc/gestiune"**, un tip de facturare paralel cu
|
||||
"lista de preturi"/"contract"/"comanda", identificat prin variabila globala `gnTipGest`:
|
||||
- `Procedure vanzare_materii_prime` -> `gnTipGest = 2`, `Do vanzare1.mpr`
|
||||
- `Procedure vanzare_produse` -> `gnTipGest = 4`, `Do vanzare2.mpr`
|
||||
- `Procedure vanzare_marfa_pret_achi` -> `gnTipGest = 5`, `Do vanzare3.mpr` (marfa la pret de
|
||||
achizitie)
|
||||
- `Procedure vanzare_marfa_pret_vanz` -> `gnTipGest = 6`, `Do vanzare4.mpr` (marfa la pret de
|
||||
**vanzare**)
|
||||
- `Procedure vanzare_marfa_pret_achi_vanz` -> `gnTipGest = 7`, `Do vanzare5.mpr`
|
||||
(toate in `COMUN\programe\oproceduri_facturare.prg:1505-1534`; butoane `Page2.Cw5..Cw9` in
|
||||
`Clase\ofundal_facturare.vc2:908-926`).
|
||||
|
||||
Gestiunile disponibile per tip se filtreaza prin `Procedure selecteaza_gestiuni`
|
||||
(`COMUN\programe\oproceduri_facturare.prg:1536-1565`), pe view-ul `vnom_GESTIUNI` filtrat
|
||||
`nr_pag = ?gnTipGest`, plus un al doilea nivel de drept pe gestiuni (view-urile
|
||||
`vgest_coresp_grupe_gestiuni` / `vgest_coresp_util_grupe`, linia 1552-1555) - deci "lista de
|
||||
preturi virtuala" = stocul unei gestiuni, cu control de acces pe gestiune (nu pe politica de
|
||||
pret).
|
||||
|
||||
Motorul de scriere: `Function oscrie_vanzare_din_stoc` in `COMUN\programe\ofacturare_stoc.prg:
|
||||
104-...`, apelat din `initializeaza_vanzare_din_stoc` (`ofacturare_stoc.prg:31-99`). Comentariu
|
||||
explicit in cod: *"in vanzari_detalii scriu pretul cu tva daca am marfa la pret de vanzare, daca
|
||||
nu scriu pretul de vanzare fara tva"* (`ofacturare_stoc.prg:107`), cu
|
||||
`lnPretCuTva = Iif(INLIST(gnTipGest,6,7), 1, 0)` (linia 111) - deci flagul "pret cu TVA" e
|
||||
determinat de TIPUL de vanzare din stoc ales (6/7 = la pret de vanzare), nu citit dintr-o coloana
|
||||
a nomenclatorului.
|
||||
|
||||
Cursorul-cheie `crsvanztemp` (`ofacturare_stoc.prg:137-139`) are coloanele:
|
||||
`id_articol, Pret, proc_tvav, id_jtva_coloana, cantitate, discount_unitar, id_gestiune, Cont
|
||||
(c4), pret_cu_tva, serie, id_valuta, codmat, Curs, multiplicator, pret_achizitie, pretd,
|
||||
id_valuta_d, id_rul_aux, taxcode, lot`.
|
||||
|
||||
### 10. Lantul de cod: pret, valuta, %TVA, pret_cu_tva, cont vanzare - la facturare "din stoc"
|
||||
|
||||
Din structura `crsvanztemp` (punctul 9) rezulta explicit lantul folosit azi cand se factureaza
|
||||
"virtual" din stoc (echivalentul cerut pentru nomenclator-ca-lista-de-preturi):
|
||||
- **Pret**: coloana `Pret` in `crsvanztemp`, luata din inregistrarea de gestiune/stoc (miscarea de
|
||||
intrare), nu din nomenclator - `pret_achizitie` separat pentru pretul de achizitie.
|
||||
- **Valuta**: `id_valuta`, `Curs`, plus varianta in alta valuta `pretd`/`id_valuta_d` (pret dublu,
|
||||
pentru afisare in a doua valuta).
|
||||
- **%TVA**: `proc_tvav` + `id_jtva_coloana` (coloana de defalcare TVA in jurnal) + `taxcode` (cod
|
||||
fiscal pt. integrari, ex. eFactura).
|
||||
- **Flag pret_cu_tva**: `pret_cu_tva` in cursor, calculat din `gnTipGest` (`ofacturare_stoc.prg:
|
||||
111`), NU citit dintr-o coloana persistenta a articolului.
|
||||
- **Cont vanzare (echivalent 4111=7xx)**: coloana `Cont c(4)` in `crsvanztemp` - cont contabil pe
|
||||
4 caractere (ex. "707x"/"701x"), scris explicit in cursor la nivel de linie de vanzare. Sursa lui
|
||||
cea mai probabila (nu confirmata cu linie exacta de SELECT in aceasta cercetare, cursorul e
|
||||
populat mai jos in fisier, dincolo de zona citita) e coloana `nom_articole.cont` (confirmata ca
|
||||
existenta la punctul 8) sau contul gestiunii (`nom_gestiuni`) - **IPOTEZA**: trebuie verificat
|
||||
punctual restul lui `oscrie_vanzare_din_stoc` (fisierul continua dupa linia 140, necitit
|
||||
integral in aceasta trecere) pentru sursa exacta linie-cu-linie a lui `Cont`.
|
||||
|
||||
Pentru comparatie, la facturarea pe **lista de preturi/politica** (nu pe stoc), pretul/valuta/TVA
|
||||
vin din politica de pret (view `crm_vpolpretcurutil`/`vcrm_politici_preturi`, punctul 6), deci
|
||||
lantul e diferit dupa tipul de facturare ales (`gnTipGest` vs. `id_pol`).
|
||||
|
||||
### 11. Coloane de pret existente/partial folosite in nomenclator
|
||||
|
||||
**Nu exista azi nicio coloana de pret pe `nom_articole`/`catalog_articole`** (cautare explicita
|
||||
fara rezultate). Exista insa deja doua campuri reutilizabile direct pentru scenariul din cerere:
|
||||
- `cont` (cont contabil de vanzare/achizitie, deja pe articol - vezi punctul 8) - poate fi folosit
|
||||
ca "nota contabila" fara tabel separat.
|
||||
- Flagurile `in_stoc` / `in_crm` - clasifica deja fiecare articol dupa modul de utilizare (stoc
|
||||
vs. politica de pret / CRM), un precedent direct pentru un viitor flag suplimentar de tipul
|
||||
"articol cu pret propriu in nomenclator" daca se implementeaza todo #12.
|
||||
|
||||
Nu au fost gasite coloane de tipul `pret`, `pret_vanzare`, `valuta_pret`, `ptva` direct pe
|
||||
nomenclator - toate preturile de vanzare vin azi fie din politici de pret (Oracle, schema CRM),
|
||||
fie din miscarile de gestiune/stoc (nu din articolul insusi). Implementarea todo #12
|
||||
("nomenclatorul direct ca lista de preturi, fara politica + nota contabila asociate") ar necesita
|
||||
adaugarea a cel putin: pret (+valuta), procent TVA, flag pret_cu_tva pe `catalog_articole`/
|
||||
`nom_articole` - camp nou, nu o coloana ascunsa deja existenta.
|
||||
|
||||
---
|
||||
|
||||
## Rezumat surse cheie (fisier:linie)
|
||||
|
||||
- Sablon COMENZI: `Programe\roafacturare.prg:180-181,239-247`; `Clase\ofundal_facturare.vc2:
|
||||
760-926`; `COMUN\clase\ocomenzi.vc2`.
|
||||
- Drepturi: `COMUN\programe\acces_meniu.prg` (tot fisierul, 306 linii).
|
||||
- Facturare contract: `COMUN\programe\oproceduri_facturare.prg:119-136,1986-2021`;
|
||||
`COMUN\clase\ofacturare.vc2:9067-9115,15069-15107`.
|
||||
- Politici de pret: `COMUN\clase\baza.vc2:10087,10157,10453-10512`;
|
||||
`COMUN\programe\oproceduri_facturare.prg:113-116`.
|
||||
- Vanzare din stoc (lista virtuala): `COMUN\programe\oproceduri_facturare.prg:1505-1534`;
|
||||
`COMUN\programe\ofacturare_stoc.prg:31-140`.
|
||||
- Nomenclator articole: `COMUN\programe\onomenclatoare.prg:1302-1373`;
|
||||
`COMUN\clase\onom_articole.vc2:531-599,1655-1733`.
|
||||
@@ -1,177 +0,0 @@
|
||||
# Cercetare frm_modific2024 — editare directa act/rul in ROAFACTURARE
|
||||
|
||||
## 1. Localizare frm_modific2024
|
||||
|
||||
Clasa `frm_modific2024` e definita in `D:\ROA\ROAFACTURARE\COMUN\clase\omodificari.vc2`
|
||||
(clasa incepe la `omodificari.vc2:6375`; metodele proprii ale lui `frm_modific2024` sunt la
|
||||
liniile `12200`-`15319`). Text `.vc2` (492 942 octeti, 02.08.2026 12:28) e mai nou decat
|
||||
binarul `.vcx` (64 144 octeti, 02.08.2026 12:24) — cu ~4 minute, deci sincronizat, nimic
|
||||
neconvertit ramas in urma.
|
||||
|
||||
Important: `omodificari.vc2` NU e specific unui singur produs — exista un fisier aproape
|
||||
identic si in `D:\ROA\ROAGEST\COMUN\clase\omodificari.vc2` (aceleasi metode, linii aproape
|
||||
identice, cf. `_symbols.tsv` per-produs). `COMUN/` e propriul working copy git per produs
|
||||
(cf. CLAUDE.md), deci **frm_modific2024 exista deja, azi, in checkout-ul COMUN al
|
||||
ROAFACTURARE** — nu trebuie adus/portat de nicaieri, doar instantiat.
|
||||
|
||||
E o **clasa .vcx instantiabila** (`Createobject([frm_modific2024], lnIdSet, ...)`), nu un
|
||||
`.scx` monolitic. Ascendenta: `frm_modific2024 -> _frmbase (_frm_base.vc2:7) -> _form
|
||||
(_baza.vc2:157) -> form`.
|
||||
|
||||
## 2. Ce face efectiv
|
||||
|
||||
Editeaza **cursoare locale in memorie** `tact` / `trul` / `trul_obinv` (READWRITE), NU
|
||||
tabelele Oracle `ACT`/`RUL` direct:
|
||||
|
||||
- `Init` (`omodificari.vc2:13510-13616`) primeste `tnIdSet, tlNotaNoua, toBackupXML, toSet,
|
||||
tlVizualizare` — nu incarca date, doar configureaza UI (readonly pe coloane cand
|
||||
`id_set` e "specializat", vizibilitate butoane).
|
||||
- `do_modifica` (`12906-13027`), `do_sterge` (`13111-13185`), `do_adauga` (`12615-12663`)
|
||||
editeaza direct pe `SELECT tact` / `SELECT trul` — grid-uri legate de aceste cursoare.
|
||||
- `inainte_de_do_termin` (`13316-13508`) ruleaza validari (`verificare_note_contabile`,
|
||||
echilibru conturi 4426-4428, `VerificaAvertizareExigibilizareTVA`) inainte de a permite
|
||||
inchiderea formularului cu `gnButon=1`.
|
||||
- `do_termin` in sine e mostenit din `_frmbase` (`_frm_base.vc2:363-376`): doar seteaza
|
||||
`gnButon=pnButon=Buton=pnIesire=1` si inchide formularul — **nu scrie nimic in baza de
|
||||
date**. Scrierea e responsabilitatea apelantului, dupa `.Show()`.
|
||||
|
||||
**Salvarea reala** (in codul apelant, vezi pct. 5) trece prin `ACT_TEMP`/`RUL_TEMP` +
|
||||
`oscrie_in_fisiere.prg` + pachetul Oracle `PACK_CONTAFIN`, intr-o tranzactie manuala
|
||||
(`SQLSetProp(gnhandle,'Transactions',2)` ... `COMMIT`/`ROLLBACK`).
|
||||
|
||||
Protectii: `glLunaInchisa` (luna inchisa → return), verificare sucursala curenta pe stergere
|
||||
(`do_sterge:13129-13136`), verificare referinte incasari/plati inainte de stergere
|
||||
(`ReferinteDocument`, `do_sterge:13152`), validare structura nota (`verificare_note_contabile`
|
||||
in `inainte_de_do_termin`).
|
||||
|
||||
## 3. Reutilizabilitate din ROAFACTURARE
|
||||
|
||||
**Direct reutilizabila, fara portare** — clasa e deja in `ROAFACTURARE\COMUN\clase\omodificari.vc2`,
|
||||
iar `COMUN\clase` e deja inregistrat in `SET CLASSLIB`/`SET PROCEDURE` din
|
||||
`Programe\roafacturare.prg` (verificat ca `omodificari.vc2` foloseste variabile globale
|
||||
standard ROA: `gnAn`, `gnLuna`, `goExecutor`, `gcs`, `gnIdUtil`, `glLunaInchisa` — toate deja
|
||||
setate de bootstrap-ul ROAFACTURARE). Nu am gasit dependinte de clase/proceduri absente din
|
||||
ROAFACTURARE — `verificare_note_contabile`, `update_saft_taxtable`, `backupxml` etc sunt tot
|
||||
in `COMUN`, deci deja disponibile.
|
||||
|
||||
Ce lipseste NU e clasa in sine, ci **codul apelant** (echivalentul `afisjurcom.do_modifica`)
|
||||
care: (a) incarca `vact_tot`/`vrul_tot`/`vrul_obinv_tot` filtrate pe `cod` in `tact`/`trul`/
|
||||
`trul_obinv`, (b) deschide tranzactia, (c) apeleaza `oscrie_in_fisiere` de doua ori (sterge +
|
||||
scrie), (d) apeleaza `pack_contafin.finalizeaza_modificare_nota`, (e) inchide tranzactia. Acest
|
||||
cod nu exista inca in ROAFACTURARE si trebuie scris nou, dupa modelul de la pct. 5-6 (dar e
|
||||
~40 linii, nu o clasa noua).
|
||||
|
||||
## 4. Punctul de agatare in ROAFACTURARE: frm_facturi
|
||||
|
||||
`frm_facturi` e in `COMUN\clase\ofacturare_comun.vc2:1168`, ascendenta `frm_facturi ->
|
||||
_frmbase -> _form -> form` (aceeasi baza ca `frm_modific2024`).
|
||||
|
||||
- `do_modifica` (`ofacturare_comun.vc2:4382-4482`): deschide un formular **diferit**,
|
||||
`frm_modifica_factura` (editeaza doar metadate: ruta/delegat/agent/masina/text
|
||||
aditional/data act/serie act — NU sume), apoi cheama `pack_facturare.modifica_date_factura(...)`.
|
||||
La linia 4432 exista deja garda exacta ceruta de utilizator:
|
||||
`If poRec.sters = 0 AND NVL(m.pnEFactura,0) = 0` — verifica `anaf_efactura` (linia 4428) si
|
||||
blocheaza cu mesajul *"Nu puteti face modificari pe inregistrarile sterse sau facturile
|
||||
trimise in eFactura!"* daca factura a plecat deja. **Acesta e modelul de garda de reutilizat**
|
||||
pentru o actiune noua "editare directa".
|
||||
- `do_sterge` (`4503-4719`) e modelul arhitectural cel mai apropiat de ce se cere: incarca
|
||||
`vact_tot`/`vrul_tot`/`vrul_obinv_tot` filtrate pe `cod` in `actactan`/`rul_temp`/
|
||||
`rul_temp_obinv` (4573-4615), arata un formular de verificare (`Createobject('verificare')`,
|
||||
4620), deschide tranzactie manuala (4625), apeleaza `OSCRIE_IN_FISIERE(2,.F.,llRul)` (4632),
|
||||
apoi `pack_contafin.finalizeaza_stergere_nota(...)` (4652-4653), commit/rollback (4662-4673).
|
||||
Cazul special "eProforma" foloseste in schimb un singur apel PL/SQL,
|
||||
`pack_facturare.sterge_proforma` (4549-4560); cazul fara randuri in `act` foloseste
|
||||
`pack_facturare.sterge_factura` direct (4689).
|
||||
- **Corectie fata de ipoteza initiala**: nu exista `nid_cw` in `ofacturare_comun.vc2`.
|
||||
Vizibilitatea/activarea butoanelor `do_modifica`/`do_sterge` e controlata prin flag-urile
|
||||
`This.lactiv3`/`This.lactiv4` (definite in `_frm_base.vc2`, default `.F.`) si prin variabila
|
||||
globala `gcAcces` (sir de tokeni gen `"4;"` pentru dreptul de stergere — vezi
|
||||
`ofacturare_comun.vc2:4773-4776`, unde `glLunaInchisa` scoate tokenul `4;` din `gcAcces` si
|
||||
ascunde `Thisform.but_sterge1`). `nid_cw` exista doar in `ofundal.vc2` si
|
||||
`drept_grupuri.vc2` (proprietate pe clasa de fundal/toolbar, nefolosita in
|
||||
`ofacturare_comun.vc2`) — deci reteta de "adaugare actiune noua" e: (1) adauga metoda
|
||||
`do_<actiune>` pe `frm_facturi` dupa modelul `do_sterge`, (2) adauga un buton nou pe
|
||||
toolbar-ul formularului (langa `but_sterge1`) cu `Click` care cheama `Thisform.do_<actiune>()`,
|
||||
(3) controleaza vizibilitatea prin acelasi mecanism `gcAcces`/`lactivN` daca se doreste
|
||||
control pe drepturi, altfel doar prin garda `sters=0 AND eFactura=0` din pct. eFactura de mai
|
||||
sus.
|
||||
|
||||
## 5. Fezabilitate scriere (cel mai important)
|
||||
|
||||
**NU exista niciun `UPDATE`/`DELETE` direct pe `ACT`/`RUL` in cod VFP** (cautat
|
||||
`update act `, `update rul `, `delete from act`, `delete from rul` in tot
|
||||
`ROAFACTURARE` si `ROAGEST\COMUN` — zero rezultate). Singura cale de scriere e prin
|
||||
tabelele staging Oracle `ACT_TEMP`/`RUL_TEMP`:
|
||||
|
||||
1. VFP populeaza cursoare `actactan`/`rul_temp`/`rul_temp_obinv` (READWRITE, incarcate din
|
||||
view-urile `vact_tot`/`vrul_tot`/`vrul_obinv_tot`).
|
||||
2. `COMUN\programe\oscrie_in_fisiere.prg` (10 461 octeti, 25.03.2026): parametrul
|
||||
`tnScrie_Sterge` (0=scriere, 2=stergere) — apeleaza `pack_contafin.init_scriere_act_rul_local`
|
||||
(linia 121), apoi `sql_temp_insert('actactan','ACT_TEMP')` / `sql_temp_insert('rul_temp',
|
||||
'RUL_TEMP')` care fac `INSERT INTO ACT_TEMP`/`RUL_TEMP` rand cu rand (liniile 127-136, 272-274
|
||||
— singurele DML explicite din acest fisier, si sunt pe tabelele `_TEMP`, nu pe `ACT`/`RUL`),
|
||||
apoi `pack_contafin.final_scriere_act_rul_local` (linia 141-143) care, in Oracle, ruleaza
|
||||
`SCRIE_IN_ACT`/`STERGE_DIN_ACT` din `PACK_CONTAFIN.pck` — **acolo** se face efectiv
|
||||
`UPDATE ACT SET STERS=1 ...` (stergere) sau `INSERT`/`UPDATE ACT_TEMP -> ACT` (scriere) prin
|
||||
PL/SQL, in Oracle, nu in VFP.
|
||||
3. Editarea NU suprascrie randul vechi: la modificare, randurile vechi din `ACT`/`RUL`/`RUL_OBINV`
|
||||
raman cu `STERS=1`, iar un document nou (`cod` nou, acelasi `id_fact`/`id_factd`) e scris in
|
||||
locul lor — comportament confirmat explicit ca "nu e bug" in
|
||||
`D:\ROA\ROAGEST\COMUN\docs\flux-modificare-stergere-nota-jurnal.md`.
|
||||
4. `pack_contafin.finalizeaza_modificare_nota` (`PACK_CONTAFIN.pck:8601-8651`) — apelata dupa
|
||||
`oscrie_in_fisiere` — **deja contine sincronizarea cu `vanzari`**:
|
||||
```
|
||||
SELECT COUNT(*) INTO lnEInVanzari FROM vanzari WHERE cod = tnCod;
|
||||
IF lnEInVanzari > 0 THEN pack_facturare.actualizeaza_vanzari(tnCod, lnCodNou); END IF;
|
||||
UPDATE atasamente_vanzari SET cod = lnCodNou WHERE cod = tnCod;
|
||||
```
|
||||
si simetric, `finalizeaza_stergere_nota` (`8653-8709`) apeleaza
|
||||
`pack_facturare.sterge_din_vanzari(tnCod, tnAn, tnLuna, tnIdUtil)`.
|
||||
**Acesta e precedentul concret ca "editarea act/rul actualizeaza automat vanzari"** — dar
|
||||
sursa pachetului `PACK_FACTURARE` (unde traiesc `actualizeaza_vanzari`/`sterge_din_vanzari`/
|
||||
`modifica_date_factura`/`sterge_factura`/`sterge_proforma`) **nu e exportata** in
|
||||
`COMUN\docs\*.pck` din acest working copy (doar `PACK_CONTAFIN`, `PACK_DIAG_SPATIU`,
|
||||
`PACK_MIGRARE`, `PACK_UPDATE`) — deci **nu se poate stabili din working copy** daca
|
||||
`actualizeaza_vanzari` recalculeaza si sumele/liniile din `vanzari_detalii` sau doar
|
||||
realiniaza `vanzari.cod` la `cod`-ul nou generat de `pack_contafin.get_cod()`. Asta e
|
||||
intrebarea-cheie de lamurit inainte de a proiecta planul (posibil necesar acces la codul
|
||||
Oracle sau la un DBA/export suplimentar al `PACK_FACTURARE`).
|
||||
|
||||
Concluzie arhitecturala: planul de "editare directa" trebuie sa respecte acelasi flux
|
||||
(cursoare temp -> `ACT_TEMP`/`RUL_TEMP` -> `PACK_CONTAFIN`), nu un `UPDATE`/`DELETE` VFP
|
||||
direct pe `ACT`/`RUL` — asta nu exista nicaieri ca precedent si ar ocoli toata logica de
|
||||
alocare `cod` nou, marcare `sters`, si sincronizare `vanzari`/`atasamente_vanzari` care traieste
|
||||
in Oracle.
|
||||
|
||||
## 6. Precedent de editare de nota contabila (afara de frm_modific2024)
|
||||
|
||||
**Nu exista un formular separat** pentru "MODIFICARE REGISTRU JURNAL" — e acelasi
|
||||
`frm_modific2024`, folosit din `afisjurcom.do_modifica`
|
||||
(`D:\ROA\ROAFACTURARE\COMUN\clase\comun.vc2:2222-2563`, identic si in
|
||||
`ROAGEST\COMUN\clase\comun.vc2`). `afisjurcom` = clasa formularului "Registru jurnal" (afisare
|
||||
jurnal contabil). Acesta e **precedentul complet, deja documentat**:
|
||||
`D:\ROA\ROAGEST\COMUN\docs\flux-modificare-stergere-nota-jurnal.md` descrie exact acest flux
|
||||
(scris de un agent/dezvoltator anterior, cross-verificat de mine cu codul — coincide integral
|
||||
cu ce am gasit independent la pct. 2 si 5). N-am gasit un literal "MODIFICARE REGISTRU JURNAL"
|
||||
in `ROAGEST\todo.txt` (cautat, zero potriviri) — probabil e o formulare verbala a
|
||||
utilizatorului, nu un text din cod; funcțional se refera la exact acest `afisjurcom.do_modifica`.
|
||||
|
||||
`afisjurcom.do_modifica` (rezumat, pentru referinta directa la implementare):
|
||||
- 2253-2264: citeste `an`/`luna`/`cod`/`id_set`/`id_fact`/`id_factd` din randul curent din grid.
|
||||
- 2265-2268: blocheaza daca nu e luna curenta.
|
||||
- 2313-2331: elibereaza cursoarele vechi (`actactan`, `tact`, `rul_temp`, `trul`, ...).
|
||||
- 2352-2427: incarca `vact_tot`/`vrul_tot`/`vrul_obinv_tot` filtrate pe `cod` in
|
||||
`actactan`→`tact`, `rul_temp`→`trul`, `rul_temp_obinv`→`trul_obinv` (READWRITE).
|
||||
- 2436: `Omodif = Createobject([frm_modific2024],lnIdSet)` ; 2442: `Omodif.Show()` (modal).
|
||||
- 2444-2541: daca userul a apasat Terminat (`buton=1`), deschide tranzactie
|
||||
(`Thisform.do_deschide_tranzactie()`), `oscrie_in_fisiere(2,.T.,llRul)` (sterge vechi),
|
||||
reincarca `tact`→`actactan`/`trul`→`RUL_TEMP`/`trul_obinv`→`RUL_TEMP_OBINV` cu
|
||||
`id_util`/`sters=0`, `oscrie_in_fisiere(0,.T.,llRul)` (scrie nou),
|
||||
`pack_contafin.finalizeaza_modificare_nota(...)`, apoi
|
||||
`Thisform.do_inchide_tranzactie(...)` (commit/rollback) si `Thisform.do_cauta` (refresh grid).
|
||||
- Cod mort comentat la 2496-2503 arata ca la un moment dat exista aici EXPLICIT un apel
|
||||
`pack_facturare.actualizeaza_vanzari(lnCod, pack_contafin.get_cod())` **direct din VFP** pentru
|
||||
"nota din ROAFACTURARE" — mutat ulterior in Oracle, in
|
||||
`pack_contafin.finalizeaza_modificare_nota` (pct. 5). Confirma ca legatura
|
||||
notă-contabila-din-jurnal <-> `vanzari` a fost tratata explicit de dezvoltatori anterior,
|
||||
exact pentru cazul ROAFACTURARE.
|
||||
@@ -1,243 +0,0 @@
|
||||
# Cercetare: lant pret (#12) + editare politici pret (#11/#10) + lazy loading
|
||||
|
||||
## REZUMAT (max 30 linii, focus A2 + C2)
|
||||
|
||||
**A2 — NU exista niciun fallback la nomenclator azi.** Confirmat din chiar view-ul care alimenteaza
|
||||
majoritatea ramurilor lui `cursor_preturi` (`fact_vpreturi_utilizator`, definit in
|
||||
`D:\ROA\DATABASE\SCRIPTURI\2009\4\ff_2009_04_21_03_FACTURARE.sql:11-50`): clauza
|
||||
`and d.id_pol is not null` (linia 49) e o conditie **obligatorie** pe `crm_politici_pret_art d` —
|
||||
un articol nu apare deloc in lista de vanzare daca nu are un rand in `CRM_POLITICI_PRET_ART` pentru
|
||||
politica activa a utilizatorului. `NOM_ARTICOLE` e joinat doar pentru `um/denumire/codmat/codbare/
|
||||
in_stoc` (descriptive), niciodata pentru `pret/valuta/proc_tvav`. In `PACK_FACTURARE.cursor_preturi`
|
||||
insusi (`ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql:2121-2627`) acelasi tipar se repeta in toate
|
||||
ramurile (2, 45, 1/2, 5/6/10/52, 7, else/aviz): driver-ul e mereu `CRM_POLITICI_PRET_ART`/politica,
|
||||
niciun `NVL`/`COALESCE` catre `catalog_articole`/`nom_articole` pentru pret. Nu exista deloc referinte
|
||||
la `catalog_articole` in tot pachetul `PACK_FACTURARE` (grep pe fisierul de 16948 linii: 0 hit-uri).
|
||||
**Concluzie: fallback-ul de #12 chiar trebuie construit de la zero.** Locul ieftin de inserat: in
|
||||
`fact_vpreturi_utilizator` si/sau direct in `cursor_preturi`, un `UNION ALL`/`LEFT JOIN` suplimentar
|
||||
care aduce articolele din `catalog_articole` **fara** rand in `CRM_POLITICI_PRET_ART` pentru
|
||||
politica curenta, cu pret/valuta/tva **NULL sau valori implicite din optiuni firma** — deoarece
|
||||
`catalog_articole` nu are nicio coloana de pret/valuta/tva (confirmat de echipa, si verificat: n-am
|
||||
gasit `PRET`/`ID_VALUTA`/`PROC_TVAV` pe `NOM_ARTICOLE`/`CATALOG_ARTICOLE` in DDL). Fallback-ul e deci
|
||||
"articolul apare, dar utilizatorul trebuie sa completeze pretul manual" — nu un pret implicit real.
|
||||
|
||||
**C2 — Exista deja un sablon de lazy loading, complet si reutilizabil**, in
|
||||
`COMUN\clase\_ct_base.vc2:278-281` (`do_activeaza_container` → `This.actualizeaza_cursoare()`), legat
|
||||
la `PageX.Activate` (`Clase\ofundal_facturare.vc2:1006-1008` pentru comenzi). Implementarea reala e
|
||||
in `COMUN\clase\ocomenzi.vc2:1088-1104`: cursorul se creeaza o singura data (guard
|
||||
`!Used('crscomenzi') Or gcS!=This.cSchema Or ...schimbare sectie`), cu un `WHERE` imposibil
|
||||
(`id_comanda = -9999999`) — deci structura se creeaza dar nu se aduc date. Datele reale vin abia la
|
||||
`do_cauta()` (`ocomenzi.vc2:1484-1510`), care trimite un `WHERE` filtrat prin `gencursor`/
|
||||
`ca_baza1.afisare()` — deci cautarea e deja server-side (Oracle), nu filtrare locala. **Acesta e
|
||||
sablonul de refolosit pentru #11/#10, exact cum indica deja `plan_10_integrare_contracte.md` S3.**
|
||||
Atentie: baza `_ct_base.actualizeaza_cursoare` (linia 231-232) e un stub gol — clasa container noua
|
||||
(`ct_preturi`/`ct_contracte`) trebuie sa suprascrie explicit `actualizeaza_cursoare`, dupa modelul
|
||||
`ocomenzi`, nu doar sa mosteneasca `_ct_base`. `ct_contracte` din ROACONTRACTE **nu** face asta azi
|
||||
(vezi C4) — deci nu e lazy, desi mosteneste acelasi `_ct_base`.
|
||||
|
||||
---
|
||||
|
||||
## A. Lantul de determinare a pretului
|
||||
|
||||
### A1. `cursor_preturi` — surse pe ramura (spec `:335-343`, body `:2121-2627`,
|
||||
`ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`)
|
||||
|
||||
Toate ramurile pornesc din `pack_facturare.initializeaza_facturare` + `completare_politica_stoc` +
|
||||
`verifica_cursuri_valute` (:2132-2136), apoi `CASE V_TIP`:
|
||||
|
||||
- **V_TIP=45 (restaurant)**, `:2143-2247`: subselect A = politica activa a utilizatorului
|
||||
(`utilizatori_rol_intern` → `politici_grupuri` → `crm_politici_preturi` → `crm_note_vanzari` →
|
||||
`note_contabile`, filtrat pe `datai/datas` fata de luna curenta si `id_sucursala`), apoi
|
||||
`LEFT JOIN CRM_POLITICI_PRET_ART B ON A.ID_POL=B.ID_POL`, `LEFT JOIN NOM_ARTICOLE C`. **Pret**:
|
||||
`B.PRET`/`B.DISCOUNT_UNITAR` convertite prin curs (`F.CURS`) daca valuta politicii ≠ valuta
|
||||
nationala. **Valuta**: `B.ID_VALUTA` → `NOM_VALUTE G`. **TVA%**: `B.PROC_TVAV` (direct din
|
||||
`CRM_POLITICI_PRET_ART`, nicio referinta la `ID_JTVA_COLOANA` in acest cursor). **Flag
|
||||
pret_cu_tva**: `A.PRETURI_CU_TVA` (de pe `crm_politici_preturi`, nu per-articol). **Cont**:
|
||||
`'371' AS CONT` — **hardcodat**, nu vine din nicio tabela.
|
||||
- **V_TIP IN (1,2) (factura lei)**, `:2248-2372`: acelasi tipar (A/B/C), plus `LEFT JOIN` pe `STOC`
|
||||
pentru cantitate gestionabila (E) si pe `CURS`/`NOM_VALUTE` (F/G). Nicio coloana `CONT` in select.
|
||||
- **V_TIP IN (5,6,10,52) (valuta)** si **V_TIP=7 (credit note)**, `:2374-2524`: sursa e view-ul
|
||||
`FACT_VPRETURI_UTILIZATOR A` (nu mai construieste politica inline), plus `STOC` (C) si `CURS`/
|
||||
`NOM_VALUTE` (D/E). Filtru `A.ID_VALUTA=V_ID_VALUTA AND A.IN_VALUTA=1` (sau `A.ID_POL=
|
||||
pack_facturare.nid_politica_stoc` la tip 5/6/10/52). Nicio coloana `CONT`.
|
||||
- **ELSE (aviz)**, `:2526-2624`: tot din `FACT_VPRETURI_UTILIZATOR A`, fara filtru pe valuta. Nicio
|
||||
coloana `CONT`.
|
||||
|
||||
**Definitia `FACT_VPRETURI_UTILIZATOR`** (cea mai recenta gasita, `D:\ROA\DATABASE\SCRIPTURI\2009\4\
|
||||
ff_2009_04_21_03_FACTURARE.sql:11-50`; nu a mai fost modificata in `SCRIPTURI_CLAR`, deci pare
|
||||
stabila de atunci):
|
||||
```
|
||||
utilizatori_rol_intern a
|
||||
left join politici_grupuri b on a.id_grup=b.id_grup
|
||||
left join crm_politici_preturi c on b.id_politica=c.id_pol
|
||||
left join crm_politici_pret_art d on b.id_politica=d.id_pol
|
||||
left join nom_articole e on d.id_articol=e.id_articol -- doar um/denumire/codmat/codbare/in_stoc
|
||||
left join crm_note_vanzari f on c.id_nota=f.id_nota
|
||||
left join note_contabile g on f.id_set=g.id_set
|
||||
where ... and d.id_pol is not null -- <- gate-ul, vezi A2
|
||||
```
|
||||
Coloane expuse: `id_pol, preturi_cu_tva, nume_lista_preturi, id_articol, pret, discount_unitar,
|
||||
proc_tvav, um, denumire, codmat, codbare, gestionabil, id_valuta, in_valuta, nota_discount`. **Nicio
|
||||
coloana `cont`.**
|
||||
|
||||
**`ID_JTVA_COLOANA`**: nu apare deloc in `cursor_preturi`. Grep pe tot pachetul arata ca se
|
||||
foloseste doar mai tarziu, la scriere/postare (`scrie_in_vanzari`, `descarca_gestiune`,
|
||||
`contabilizeaza_tva`, in jur de liniile 3700-4130, 4660-5400, 12250-13700 din pachet) — deci cota de
|
||||
TVA "oficiala" (coloana `JTVA_COLOANE`) se rezolva separat de `PROC_TVAV`-ul afisat la selectarea
|
||||
pretului, probabil prin cautare dupa procent in `citeste_id_jtva_coloana`-tip logica (nu am urmarit
|
||||
in detaliu — in afara bugetului A, marcat ca zona neexplorata).
|
||||
|
||||
**Cont de vanzare, de fapt**: parametrul `V_CONT` din `PACK_FACTURARE.adauga_articol_factura`
|
||||
(`:4972-4998`) e trimis de VFP la adaugarea liniei (valoare `'XXXX'` = "fara override" -> `V_CONT2`
|
||||
ramane NULL). Nu am gasit el sa fie citit din `CRM_POLITICI_PRET_ART`/`NOM_ARTICOLE` in acest flux;
|
||||
in schimb exista deja `initializeaza_date_gestiune(V_ID_GESTIUNE, V_ID_TIPGEST, V_CONT, V_ACONT)`
|
||||
(spec `:311-314`) care leaga contul de **gestiune**, nu de articol/politica. Separat, pachetul
|
||||
`PACK_PRETURI` (editorul din ROAPRETURI) scrie `NOM_ARTICOLE.CONT` direct la
|
||||
`adauga_articol`/`modifica_articol` (`D:\ROA\DATABASE\SCRIPTURI\2008\7\ff_2008_07_31_01_PRETURI.sql
|
||||
:107-130, 300-330, 386-424`) — deci **contul de vanzare al articolului exista deja pe
|
||||
`NOM_ARTICOLE.CONT`** (= `catalog_articole.cont` din nomenclatura curenta), independent de orice
|
||||
lista de preturi. Asta inseamna ca, pentru #12, contul NU are nevoie de fallback nou — poate fi citit
|
||||
direct din nomenclator, exact ce cere planul (ramane de confirmat unde/cum VFP populeaza azi `V_CONT`
|
||||
la trimiterea catre `adauga_articol_factura`, cautare separata, in afara bugetului acestei runde).
|
||||
|
||||
### A2. Fallback existent — **NU exista**. Detaliat mai sus (rezumat) si in A1
|
||||
(`d.id_pol is not null`, zero hit-uri `catalog_articole` in `PACK_FACTURARE`). Singurul loc unde
|
||||
`NOM_ARTICOLE`/nomenclatorul intra in calculul de pret e ca sursa a campurilor descriptive
|
||||
(um/denumire/codmat/codbare/in_stoc), niciodata pentru pret/valuta/tva/cont.
|
||||
|
||||
### A3. `citeste_setari_pol_pret` (`:2025-2065`)
|
||||
Nu seteaza `pret_cu_tva`/TVA. Citeste doar **care politica e implicita** pentru un `V_ID_UTIL`, in
|
||||
functie de `V_TIP`: `OPTIUNI.VARNAME` = `'ID_POL_PRET_TR'` (tip 23/30/41), `'ID_POL_PRET_STOC'`
|
||||
(tip 1), `'IDPOLPRETFACTK'` (tip 48/49), fiecare cu `LEFT JOIN CRM_VPOLPRETCURUTIL B ON ... AND
|
||||
B.ID_UTIL=V_ID_UTIL`. Deci `pret_cu_tva`/TVA vin exclusiv din randurile `crm_politici_preturi`/
|
||||
`crm_politici_pret_art` selectate ulterior de `cursor_preturi`, nu din aceasta procedura.
|
||||
|
||||
### A4. Tabelele politicii de pret (coloane confirmate din uz + din
|
||||
`ff_2008_07_31_01_PRETURI.sql:10-95`, ADD/FK, si `create or replace view vcrm_politici_preturi`):
|
||||
|
||||
- **`CRM_POLITICI_PRETURI`**: `ID_POL, NUME_LISTA_PRETURI, DATAI, DATAS, ID_VALUTA, ID_UTIL,
|
||||
DATAORA, NOTA_ONLINE, ID_NOTA, PRETURI_CU_TVA, ID_SUCURSALA, STERS`. FK: `ID_VALUTA->NOM_VALUTE`,
|
||||
`ID_NOTA->CRM_NOTE_VANZARI`, `ID_SUCURSALA->CONTAFIN_ORACLE.NOM_FIRME`.
|
||||
- **`CRM_POLITICI_PRET_ART`**: `ID_POL, ID_ARTICOL, ID_VALUTA, PRET, PRETFTVA, PRETCTVA, PROC_TVAV,
|
||||
DISCOUNT_UNITAR, STERS` (din `modificare_politica_stoc`, `:2105-2119`, si din selectii). **Nicio
|
||||
coloana CONT.**
|
||||
- Nu am gasit `CREATE TABLE` originar pentru aceste doua tabele in `SCRIPTURI_CLAR` (probabil
|
||||
create inainte de 2006, in afara arhivei "clare"); coloanele de mai sus sunt derivate din uz activ
|
||||
in cod, nu dintr-un DDL complet — de tratat ca aproape sigure, nu 100% exhaustive (pot exista
|
||||
coloane suplimentare needitate de codul cercetat).
|
||||
- View-uri asociate: `VCRM_POLITICI_PRETURI` (`ff_2008_07_31_01_PRETURI.sql:42-65`),
|
||||
`VPOLITICI_GRUPURI` (`:67-95`), `CRM_VPOLPRETCURUTIL` (folosit pretutindeni, definitia lui nu a
|
||||
fost cautata — in afara bugetului).
|
||||
|
||||
---
|
||||
|
||||
## B. Cine mai foloseste listele de preturi
|
||||
|
||||
- **ROAFACTURARE**: doar citeste. `crm_vpolpretcurutil` la `COMUN\clase\baza.vc2:10087,10157,
|
||||
10502-10512` (filtrare politici dupa dreptul utilizatorului); `facturare_lista_de_preturi` =
|
||||
`Do politica.mpr` (`COMUN\programe\oproceduri_facturare.prg:113-116`); rapoarte grupate pe
|
||||
`nume_lista_preturi` din `vvanzari_detalii` (`COMUN\clase\configurare.vc2:3915-3972`).
|
||||
(Sursa: `docs\plan_11_integrare_politici_preturi.md:15-22`, deja in `D:\ROA\ROAFACTURARE\docs\`.)
|
||||
- **ROAPRETURI** (`D:\ROA\ROAPRETURI`, exe separat `roapreturi.exe`): **editeaza** politicile —
|
||||
`Clase\opreturi.vcx`, `Clase\onom_preturi.vcx`, `Clase\ofundal_preturi.vcx`,
|
||||
`Programe\update_preturi.prg`, `Programe\update_nomenclator.prg`. Pachet Oracle `PACK_PRETURI`
|
||||
(`adauga_articol`/`modifica_articol`/`verifica_articol` — scriu si pe `NOM_ARTICOLE`, nu doar pe
|
||||
politica). **Nu are cache text (.vc2/.sc2) generat** — nu s-a putut inspecta clasa in detaliu (vezi
|
||||
C4); confirmat prin `Glob D:\ROA\ROAPRETURI\**\*.vc2` = 0 fisiere, doar `.vcx` binare.
|
||||
- **ROACONTRACTE** (`D:\ROA\ROACONTRACTE\Clase\ferestre_contracte.vc2`): citeste direct
|
||||
`vcrm_politici_preturi` / `vcrm_politici_pret_art` prin SQL Pass Through (`goExecutor.oExecute`),
|
||||
la cautarea/atasarea unui articol pe linie de contract
|
||||
(`Programe\oproceduri_roacontracte.prg:213-239`: `select id_pol,... from vcrm_politici_preturi`,
|
||||
apoi `select id_articol, id_pol_art, ... from ]+gcS+[.vcrm_politici_pret_art where id_pol=...`).
|
||||
Nu editeaza politica insasi, doar o consuma pentru a atasa articole+pret pe contract.
|
||||
- **ROAGEST**: 0 hit-uri directe pe `CRM_POLITICI_PRET*`/`cursor_preturi`/`PACK_PRETURI` in cod VFP
|
||||
(`.vc2`/`.prg`) — foloseste probabil acelasi `PACK_FACTURARE` server-side prin
|
||||
`Programe\ofactureaza.prg` (fisier gasit la cautarea `id_pol`, dar doar in comentarii vechi de
|
||||
schema cursor, nu apel activ identificat in bugetul alocat).
|
||||
- **ROAACNPRO**: la fel, 0 hit-uri directe; `id_pol` apare doar intr-un `Text To lcSchema`/
|
||||
`lcSelect` ascuns (`Omitted long matching line` — continut necunoscut, de investigat separat daca
|
||||
devine relevant).
|
||||
- **ROAIMOB**: 0 hit-uri (`.vc2`).
|
||||
- **COMUNROA**: 0 hit-uri (`.vc2`) — surprinzator pentru un modul "CRM transversal"; posibil ca
|
||||
accesul se face exclusiv server-side (proceduri Oracle), nu prin VFP direct in produsele
|
||||
verificate, sau ROAGEST/ROAACNPRO folosesc cod VFP montat din `COMUN` (acelasi `ocomenzi.vcx` etc.)
|
||||
fara sa atinga politica de pret local.
|
||||
- **Nomenclatorul comun** (`update_nomenclator.prg` in ROAPRETURI) scrie in tabela de articole
|
||||
folosita de toate produsele — punct de atentie deja notat in `plan_11...md:82-84` (S2, perimetru).
|
||||
|
||||
**Concluzie B**: politica de pret (structura de date) e deja un modul transversal minim
|
||||
(ROAFACTURARE citeste, ROAPRETURI editeaza, ROACONTRACTE citeste), consistent cu ce spune deja
|
||||
`plan_11...md`. Nu s-a gasit inca un al patrulea consumator activ in cod VFP (ROAGEST/ROAACNPRO
|
||||
probabil trec prin acelasi `PACK_FACTURARE` server-side, fara sa atinga tabelele direct din VFP).
|
||||
|
||||
---
|
||||
|
||||
## C. Incarcare lazy si cautare
|
||||
|
||||
### C1. Cum incarca azi paginile mari
|
||||
|
||||
- **`ct_comenzi`** (`COMUN\clase\ocomenzi.vc2`): montat ca `Page5.Ct_comenzi1`
|
||||
(`Clase\ofundal_facturare.vc2:604-606`). `PROCEDURE Page5.Activate` (`:1006-1008`) apeleaza
|
||||
`this.ct_comenzi1.do_activeaza_container()`. Aceasta e mostenita din `_ct_base.vc2:278-281`
|
||||
(`do_activeaza_container` → `bind keypress` + `This.actualizeaza_cursoare()`).
|
||||
`ocomenzi.actualizeaza_cursoare` (`:1088-1104`) **nu incarca date** — creeaza doar structura
|
||||
cursorului prin `creeaza_cursoare()` (`:1191-1245`), cu `lcFiltru = [id_comanda = -9999999]`
|
||||
(`:1216`) — deci 0 randuri reale la deschidere/activare de pagina.
|
||||
- **`onom_articole.vc2`**: editorul de articol individual (`PROCEDURE Init`, `:1704-1772`) e per-
|
||||
inregistrare (`toRec`), nu o grila; incarca doar cursoarele mici de grupe/subgrupe pentru combo-uri
|
||||
(`crs_grupe_art`, `crs_subgrupe_art`, `:1717-1729`). Nu s-a gasit/verificat in bugetul alocat cum
|
||||
se incarca lista/grila principala de articole a nomenclatorului (formularul-parinte, nu editorul) —
|
||||
**neacoperit**, marcat ca zona pentru o runda ulterioara daca devine relevanta pentru #12/#11.
|
||||
|
||||
### C2. Sablon de lazy loading existent — **DA**, detaliat in rezumat.
|
||||
Cheia: `_ct_base.do_activeaza_container` (hook legat de `Page.Activate`) → `actualizeaza_cursoare()`
|
||||
**suprascrisa** in clasa concreta cu un guard `!Used(cursor) Or <context s-a schimbat>` →
|
||||
`creeaza_cursoare()` cu `WHERE` fals → date reale doar la `do_cauta()`. `_ct_base` insusi ofera doar
|
||||
stub-uri goale (`:231-232` pentru `actualizeaza_cursoare`, la fel `do_adauga/do_cauta/...` la
|
||||
`:283-322`) — **fiecare container concret trebuie sa implementeze explicit lazy-load-ul**, nu vine
|
||||
gratis din mostenire.
|
||||
|
||||
### C3. Cautare server-side vs. filtrare locala
|
||||
- **Server-side (tiparul de urmat)**: `ocomenzi.do_cauta` (`:1484-1510`) construieste `lcFiltru`
|
||||
(`id_sectie = ...` + `filtru_pretty`) si il trimite prin `actualizeaza_grid1(lcFiltru)` →
|
||||
`pocomenzi.ca_baza1.cfiltru=lcFiltru` → `pocomenzi.ca_baza1.afisare()` (`:1109-1123`) — clasa
|
||||
`ca_baza1` (generata de `gencursor`) trimite `WHERE`-ul catre Oracle prin `goExecutor`, nu
|
||||
filtreaza un cursor deja incarcat integral.
|
||||
- **Local (contra-exemplu)**: `actualizeaza_grid1` in continuare (`:1119-1124`) face si operatii pur
|
||||
locale pe cursor deja adus (`SELECT * FROM crscomenzi WITH (Buffering=.T.) WHERE selectat=1 INTO
|
||||
CURSOR crstempcomenzi`) — dar asta e pentru pastrarea selectiei intre reincarcari, nu pentru
|
||||
cautare/filtrare initiala.
|
||||
|
||||
### C4. ROAPRETURI / ROACONTRACTE — incarca tot la deschidere?
|
||||
|
||||
- **ROAPRETURI**: **nu se poate stabili** — lipseste cache-ul text (`.vc2`/`.sc2`), doar `.vcx`
|
||||
binare (`Clase\opreturi.vcx`, `Clase\ofundal_preturi.vcx`); conform regulilor primite, nu am
|
||||
convertit nimic. Precondiitia e deja documentata ca blocanta in `plan_11...md:66-70` (S1: inrolare
|
||||
in fluxul text, procedura `COMUN\docs\inrolare-proiect-git-text.md`).
|
||||
- **ROACONTRACTE**: `ferestre_contracte.vc2` are cache text si e vizibil. Descoperire importanta:
|
||||
clasa container `ct_contracte` (`:9`, `DEFINE CLASS ct_contracte AS _ctfrmbase OF
|
||||
"..\comun\clase\_ct_base.vcx"`) **mosteneste acelasi `_ct_base`** ca `ct_comenzi`, si are propriul
|
||||
`filtru_pretty`/`but_start_criterii1` (vazut in `But_reset_criterii1.Click`, `:1551-1567`) — deci
|
||||
infrastructura de cautare exista. **Dar nu suprascrie `actualizeaza_cursoare`/`creeaza_cursoare`**
|
||||
(0 hit-uri in fisier) — inseamna ca foloseste stub-ul gol din `_ct_base` pentru acel hook, iar
|
||||
cursorul principal (`cContracte`, vazut deja populat la `PROCEDURE Init` a ferestrei,
|
||||
`:1518-1527`, `Select cContracte / If Reccount()>0`) se incarca **altundeva, probabil eager, la
|
||||
deschiderea formularului** — nu s-a gasit punctul exact de populare in bugetul alocat (cautare
|
||||
separata necesara: `cContracte` INTO CURSOR / gencursor pentru contracte). **Concluzie: ROACONTRACTE
|
||||
NU e azi lazy**, desi are "schela" pentru a deveni (acelasi `_ct_base`). Pentru #10/#11, sablonul
|
||||
de copiat e strict cel din `ocomenzi.vc2`, nu cel din `ferestre_contracte.vc2`.
|
||||
|
||||
---
|
||||
|
||||
## Neacoperit / de reluat intr-o runda viitoare
|
||||
- `CRM_VPOLPRETCURUTIL` — definitia view-ului (coloane exacte, drepturi).
|
||||
- `ID_JTVA_COLOANA` — cum se leaga procentul afisat in `cursor_preturi` (`PROC_TVAV`) de coloana TVA
|
||||
oficiala folosita la postare.
|
||||
- Unde/cum populeaza azi VFP parametrul `V_CONT` la `adauga_articol_factura` (ipoteza: din gestiune,
|
||||
nu din articol) — relevant pentru a confirma daca planul #12 poate refolosi direct
|
||||
`NOM_ARTICOLE.CONT` fara alta lucrare.
|
||||
- Incarcarea listei/grilei principale de articole din `onom_articole.vc2` (formularul-parinte, nu
|
||||
editorul per-inregistrare).
|
||||
- Unde exact se populeaza `cContracte` in `ferestre_contracte.vc2` (cautare punctuala, nu facuta).
|
||||
- ROAGEST/ROAACNPRO: confirmarea ca folosesc `PACK_FACTURARE` exclusiv server-side pentru preturi
|
||||
(ipoteza, nu verificata prin citirea completa a `ofactureaza.prg`/`proceduri_acnpro.prg`).
|
||||
@@ -1,6 +1,6 @@
|
||||
# Review S4 runda 1 (PAGE3 "Articole factura") - ancorare coloane + calitate cod
|
||||
|
||||
Review de cod, fara nicio modificare aplicata. Obiect: `docs\diff_s4_runda1_page3.patch`
|
||||
Review de cod, fara nicio modificare aplicata. Obiect: diff aplicat (sters)
|
||||
(`COMUN\clase\omodificari.vc2` clasa `frm_modific2024`, `COMUN\programe\ofacturare_editare.prg`).
|
||||
Context citit: `docs\cercetare\rec_s4_runda1.md`, `docs\progres.md` (sectiunea "#6, S4 runda 1" si
|
||||
decizia/nota despre pozitionarea in `actactan`), `COMUN\docs\reguli_lucru.md`,
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
# S10 + S12 — versiune_db.txt, curatare VERSIUNE, propunere changelog 2.11.13
|
||||
|
||||
## S10 — `versiune_db.txt`
|
||||
|
||||
Regula exacta, confirmata in `COMUN\docs\scripturi-migrare-db.md` ("Numerotare si versiune_db.txt"):
|
||||
in `versiune_db.txt` se trece **doar versiunea ultimului script `ff_`** (nu `co_`/`sys_`/`rf_`/`ris_`),
|
||||
pentru ca programele se conecteaza pe schema firmei, nu pe `CONTAFIN_ORACLE`.
|
||||
|
||||
Verificat pe disc, `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\`: cinci scripturi `ff_2026_08_06_*`
|
||||
aplicate azi pe `MARIUSM_AUTO` — `_02` (`PACK_FACTURARE`, S4), `_03` (`PACK_FACTURARE`, S7), `_04`
|
||||
(`VANZARI_COMANDA_CONTRACT`, S6), `_05` (`FACT_VFACTURI`, S8), `_06` (`VANZARI_BACKFILL`, S5).
|
||||
Confirmat si prin interogare pe `VERSIUNE` (`order by data_script desc, seq_script desc`): ultimul
|
||||
`ff_` aplicat e `ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql`.
|
||||
|
||||
**Scris in `versiune_db.txt`: `2026_08_06_06`** (fara newline la final, pastrand conventia
|
||||
fisierului existent — verificat byte-level, 13 octeti, identic ca lungime cu vechea valoare
|
||||
`2026_08_02_01`).
|
||||
|
||||
## S10 — starea tabelei `VERSIUNE`
|
||||
|
||||
Interogata direct pe `MARIUSM_AUTO` (`docs\cercetare\s10_curata_versiune.sql`, pasul 1). Numar de
|
||||
inregistrari per script, azi:
|
||||
|
||||
| Script | Inregistrari |
|
||||
|---|---|
|
||||
| `ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql` (S4) | 2 |
|
||||
| `ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql` (S7) | 1 |
|
||||
| `ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql` (S6) | 2 |
|
||||
| `ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql` (S8) | 4 |
|
||||
| `ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql` (S5) | 5 |
|
||||
|
||||
14 randuri in total pentru cele 5 scripturi de azi, 9 in plus fata de cate 1 per script. Confirma
|
||||
tiparul semnalat: `_02`, `_05`, `_06` (si, in plus fata de ce era asteptat, `_04`) au fost aplicate
|
||||
de mai multe ori pe masura extinderii lor in cursul zilei; `_03` are deja un singur rand, nimic de
|
||||
curatat acolo.
|
||||
|
||||
**Propunere, nerulata**: `docs\cercetare\s10_curata_versiune.sql`. Pastreaza per script randul cu
|
||||
`ID_VERSIUNE` maxim (ultima aplicare = starea finala reala a scriptului), sterge restul — scoped
|
||||
strict pe cele 5 nume de script din lista de mai sus, cu `select` de verificare inainte si dupa,
|
||||
`delete` la mijloc, `commit` comentat (de dat manual). Fara impact functional indiferent daca se
|
||||
ruleaza sau nu: nici `versiune_db.txt`, nici aplicarea DDL nu depind de numarul de randuri din
|
||||
`VERSIUNE`. **Nu s-a rulat** — stergerea de istoric ramane decizie de om.
|
||||
|
||||
## S12 — propunere changelog
|
||||
|
||||
Livrat: `docs\propunere_changelog_2.11.13.txt` (neaplicat in `changelog_roafacturare.txt`).
|
||||
|
||||
```
|
||||
<!--
|
||||
06/08/2026
|
||||
ROAFACTURARE - 2.11.13
|
||||
|
||||
:eroare:
|
||||
Referinta catre aviz de pe facturi era gresita - toate facturile aratau acelasi aviz, indiferent de cel real. Acum se afiseaza avizul corect acolo unde exista, iar unde nu exista referinta, campul ramane necompletat.
|
||||
|
||||
Unele facturi mai vechi ramasesera fara total salvat la emitere si aparea fara valoare la listare sau retiparire. Totalurile lipsa au fost completate.
|
||||
|
||||
Cursul valutar afisat pe facturile emise in lei era uneori inregistrat gresit. Facturile in lei nu mai afiseaza curs valutar strain.
|
||||
|
||||
La facturile de retur-transfer numele clientului afisat in lista de facturi era uneori gresit. Acum se afiseaza clientul corect.
|
||||
|
||||
:modificare:
|
||||
S-a uniformizat textul explicativ (comanda/contract) afisat pe facturi.
|
||||
-->
|
||||
```
|
||||
|
||||
### Motivare inclusiune/excludere
|
||||
|
||||
- **Aviz, totaluri, curs valutar** (`:eroare:`) — toate trei sunt defecte confirmate ca fiind
|
||||
efectiv pe date de productie (`VENDING`), vizibile pe facturi reale (lista principala si
|
||||
retiparire), acum corectate. Se incadreaza clar la `:eroare:`.
|
||||
- **`CLIENT` pe retur-transfer** (`:eroare:`) — `fact_vfacturi`, folosit de gridul principal de
|
||||
listare, calcula gresit numele clientului pe cele 23 de facturi `tip=41`/`tip=-6`; view-ul
|
||||
corect (`fact_vfacturi2`) confirma sursa deliberata din cod. E o valoare gresita afisata in
|
||||
productie, nu doar o diferenta cosmetica intre doua liste — de aceea l-am pus la `:eroare:` si
|
||||
nu la `:modificare:`, desi in mesajul initial parea doar "etichete neuniforme".
|
||||
- **`EXPLICATIE`** (`:modificare:`) — diferenta e strict de formatare a textului
|
||||
("COMERCIAL - FACTURARE" vs "COMERCIAL-FACTURARE" etc.), nu o valoare gresita; l-am tinut separat
|
||||
si mai jos in prioritate, la `:modificare:`.
|
||||
- **Denormalizarea comanda/contract (S6) — EXCLUSA din changelog.** Harnessul de regresie da
|
||||
aceleasi cifre inainte si dupa aplicarea scriptului; nu exista nimic vizibil pentru utilizator.
|
||||
O intrare de changelog ar fi inselatoare (ar sugera o schimbare functionala inexistenta).
|
||||
- **Incasarea lipsa pe facturile din devize auto — EXCLUSA din `changelog_roafacturare.txt`.**
|
||||
Corectia e integral in cod VFP din **ROAAUTO** (`Programe\oproceduri_devize.prg`,
|
||||
`factureaza_deviz`) plus un parametru nou cu `DEFAULT` in `PACK_FACTURARE.scrie_incasari`
|
||||
(pachet Oracle comun, dar ramura noua e apelata **doar** din ROAAUTO). Recompilarea
|
||||
`roafacturare.exe` singura, fara recompilarea ROAAUTO, nu produce niciun efect vizibil pentru
|
||||
utilizatorul ROAFACTURARE — deci intrarea nu apartine acestui changelog, chiar daca facturile
|
||||
respective ar putea fi vazute si din listele ROAFACTURARE dupa ce ROAAUTO e recompilat si el.
|
||||
**Propunere de text pentru `changelog_roaauto.txt` (needitat, doar propus aici)**:
|
||||
|
||||
```
|
||||
<!--
|
||||
06/08/2026
|
||||
ROAAUTO - 2.5.5
|
||||
|
||||
:eroare:
|
||||
La facturile emise din deviz auto nu se inregistra incasarea (chitanta/bon), desi factura era platita. S-a corectat.
|
||||
-->
|
||||
```
|
||||
|
||||
## Fisiere livrate
|
||||
|
||||
- `versiune_db.txt` — actualizat la `2026_08_06_06` (editat direct, marcaj de proiect).
|
||||
- `docs\cercetare\s10_curata_versiune.sql` — propunere de curatare, **nerulata**.
|
||||
- `docs\propunere_changelog_2.11.13.txt` — propunere, **neaplicata** in `changelog_roafacturare.txt`.
|
||||
- Acest raport.
|
||||
|
||||
**Fara commit** (git/SVN). Nu s-au atins scripturile de migrare, nu s-a rulat DDL, nu s-a scris in
|
||||
`VERSIUNE`.
|
||||
@@ -1,446 +0,0 @@
|
||||
# Cercetare S1-S3 (plan_06_editare_factura.md) - stare cod la 08.08.2026
|
||||
|
||||
Refera ancorele planului dupa commit-urile #7/#8. Toate liniile de mai jos sunt din textul
|
||||
`.vc2` regenerat de `git_sync.ps1` in aceasta sesiune (deci la zi cu binarul).
|
||||
|
||||
## A. Ancore re-verificate
|
||||
|
||||
### A1. frm_facturi.do_sterge - COMUN\clase\ofacturare_comun.vc2:4501-4717
|
||||
|
||||
Clasa `frm_facturi` incepe la `ofacturare_comun.vc2:1168` (mosteneste `_frmbase`). Metoda
|
||||
`do_sterge` e imediat dupa `do_modifica_explicatie` (4482-4499) si inainte de `do_verifica`
|
||||
(4719-4766). Structura pe pasi:
|
||||
|
||||
1. `4502-4508`: citeste `gnLuna`/`gnAn` in variabile, iese daca `crsfacturi` e gol.
|
||||
2. `4516-4518`: garda **luna inchisa** (`glLunaInchisa`) - `Return` fara mesaj.
|
||||
3. `4520-4527`: pozitioneaza pe randul curent din `crsfacturi`, citeste `id_vanzare`, `cod`,
|
||||
an/luna din `data_act`, `sters`, `eproforma`.
|
||||
4. `4529-4536`: daca deja sters -> mesaj si `Return`; confirmare cu `amessagebox(...,4+32,...)`.
|
||||
5. `4541-4544`: garda **luna curenta** - `(pnAn*12)+pnLuna <> (gnAn*12)+gnLuna` -> mesaj si
|
||||
`Return`.
|
||||
6. `4546-4559`: ramura separata **STERGERE PROFORMA** (`eproforma=1`) - apeleaza direct
|
||||
`pack_facturare.sterge_proforma(pnIdVanzare,gnIdUtil)` si iese cu `RETURN`, **inainte** de
|
||||
garda de referinte de mai jos. Facturile/avizele nu intra pe aceasta ramura.
|
||||
7. `4562-4567`: garda **referinte incasari/plati** -
|
||||
`ReferinteDocumenteNota(pnAn, pnLuna, lnCod)` (definita in
|
||||
`COMUN\programe\odocumente.prg:8`) -> daca `.T.`, mesaj si `Return`.
|
||||
8. `4569-4614`: incarca cursoare pe `cod` din `vact_tot`/`vrul_tot`/`vrul_obinv_tot` (schema
|
||||
`gcs`), filtrate `sters=0 and an=gnAn and luna=gnLuna and cod=lnCod`, in `actactan`/
|
||||
`rul_temp`/`rul_temp_obinv`.
|
||||
9. `4617-4620`: daca sunt randuri in `actactan`, deschide formularul modal `verificare`
|
||||
(confirmare vizuala inainte de stergere efectiva).
|
||||
10. `4622-4685`: daca `buton=1` din `verificare`, trece manual pe tranzactie
|
||||
(`SQLSetprop(gnhandle,"Transactions",2)`), apeleaza `OSCRIE_IN_FISIERE(2,.F.,llRul)`, apoi
|
||||
`pack_contafin.finalizeaza_stergere_nota(pnLuna,pnAn,Null,lnIdSet,lnCod,lnIdFact,lnIdFactD,
|
||||
gnIdUtil)`, COMMIT/ROLLBACK dupa rezultat, revine pe tranzactie automata.
|
||||
11. `4686-4701`: ramura alternativa (fara randuri in `actactan`, adica document fara nota) -
|
||||
apel direct `pack_facturare.sterge_factura(pnIdVanzare,gnLuna,gnAn,gnIdUtil)`.
|
||||
12. `4707-4716`: inchide cursoarele temporare.
|
||||
|
||||
**Nu exista nicio verificare eFactura in do_sterge** - vezi A3, e o corectie fata de plan.
|
||||
|
||||
### A2. Cele 3 garzi lipsa din do_modifica - confirmate, linii curente
|
||||
|
||||
Toate trei sunt in `do_sterge` (A1) si lipsesc din `do_modifica` (`ofacturare_comun.vc2:4381-4480`,
|
||||
care nu verifica deloc luna sau referinte, doar `sters`+eFactura, vezi A3):
|
||||
|
||||
- **Luna inchisa**, `ofacturare_comun.vc2:4516-4518`:
|
||||
```
|
||||
If glLunaInchisa
|
||||
Return
|
||||
Endif
|
||||
```
|
||||
- **Luna curenta**, `ofacturare_comun.vc2:4541-4544`:
|
||||
```
|
||||
If (pnAn * 12) + pnLuna <> (gnAn * 12) + gnLuna
|
||||
amessagebox('Nu puteti sterge decat inregistrari din luna curenta!',0,'Atentie!')
|
||||
Return
|
||||
Endif
|
||||
```
|
||||
Text hardcodat pe "stergere" - la reutilizare pentru editare trebuie schimbat mesajul.
|
||||
- **Referinte incasari/plati**, `ofacturare_comun.vc2:4562-4567`:
|
||||
```
|
||||
*** verificare restrictie stergere documente cu referinte (incasari/plati)
|
||||
llReferinteDocumente = ReferinteDocumenteNota(pnAn, pnLuna, lnCod) && && odocumente.prg
|
||||
If llReferinteDocumente
|
||||
amessagebox("Documentul are referinte (incasari/plati). Nu poate fi sters.", 0+48,"Stergere")
|
||||
Return
|
||||
Endif
|
||||
```
|
||||
Idem, mesajul e specific stergerii.
|
||||
|
||||
### A3. Garda eFactura - CORECTIE fata de plan: e in do_modifica, NU in do_sterge
|
||||
|
||||
Cautare exhaustiva `anaf_efactura` in `ofacturare_comun.vc2`: **o singura aparitie**, la linia
|
||||
4426, in interiorul lui `do_modifica` (4381-4480). `do_sterge` nu contine deloc `anaf_efactura`.
|
||||
|
||||
Cod exact, `ofacturare_comun.vc2:4426-4430`:
|
||||
```
|
||||
lcSql = [select count(*) as lneFactura from anaf_efactura where id_fact = ] + ALLTRIM(STR(poRec.id_fact))
|
||||
pneFactura = 0
|
||||
llSucces = goExecutor.oSelecteaza2Value(m.lcSql, @pneFactura)
|
||||
|
||||
If poRec.sters = 0 AND NVL(m.pnEFactura,0) = 0
|
||||
```
|
||||
(`pneFactura`/`pnEFactura` e aceeasi variabila, VFP e case-insensitive.)
|
||||
|
||||
Garda e refolosibila ca atare (interogare + conditie), dar trebuie extrasa dintr-un `If` care
|
||||
astazi conditioneaza doar deschiderea dialogului `frm_modifica_factura` - pentru actiunea noua
|
||||
S1 trebuie sa devina un `Return` explicit cu mesaj, dupa modelul celorlalte garzi din
|
||||
`do_sterge`, nu o simpla conditie de `If`.
|
||||
|
||||
### A4. Mecanismul de drepturi pe frm_facturi
|
||||
|
||||
Nu exista o proprietate `lactiv3`/`lactiv4` setata explicit in `ofacturare_comun.vc2` - ele sunt
|
||||
proprietati generice mostenite din `_frmbase` (`_frm_base.vc2:7`), populate dinamic din
|
||||
`gcAcces` de metoda comuna `actualizeaza_drepturi`, `_frm_base.vc2:195-228`:
|
||||
|
||||
- Format `gcAcces = "opt1;opt2;...;optN;"` (string cu numere separate prin `;`).
|
||||
- Pentru fiecare token `N` prezent, seteaza `thisform.lactivN = .T.` (linia 203-205:
|
||||
`lcProp='thisform.lactiv'+Alltrim(lcAcces)` + `&lcProp=.T.`).
|
||||
- Daca exista si o proprietate `thisform.cbutonN` (lista de nume de butoane separate prin `;`),
|
||||
seteaza `.Visible = .T.` pe fiecare buton din lista (206-221).
|
||||
|
||||
Uzul din `inainte_de_do_modifica`/`inainte_de_do_sterge` (`_frm_base.vc2:476-481, 493-498`):
|
||||
`If This.lactiv3 Then This.do_modifica()` / `If This.lactiv4 Then This.do_sterge()`. Deci
|
||||
`lactivN` gateaza EXECUTIA actiunii, `cbutonN` gateaza VIZIBILITATEA butoanelor asociate.
|
||||
|
||||
**Tokenii folositi azi de frm_facturi** (proprietati proprii clasei, `ofacturare_comun.vc2:1352-1353`):
|
||||
- `cbuton2 = but_listare1;but_listare2;But_listare3` (token "2" = listare)
|
||||
- `cbuton3 = but_modifica1;but_modifica2` (token "3" = modificare - **ambele** butoane de
|
||||
modificare, cel de antet si cel de explicatie articol, vezi A5)
|
||||
- Tokenul "4" (stergere) nu are `cbuton4` definit pe `frm_facturi` - vizibilitatea lui
|
||||
`but_sterge1` e gestionata separat, direct in `Init` (`4770-4773`): daca `glLunaInchisa`,
|
||||
scoate manual `"4;"` din `gcAcces` si ascunde butonul. `lactiv4` insa tot se seteaza normal
|
||||
din `gcAcces` (prin mecanismul generic), si `but_sterge1.Click` foloseste implicit
|
||||
`caction = inainte_de_do_sterge` (default din clasa de baza `but_modifica`/`but_sterge`,
|
||||
`cmd_butoane.vc2:358`), care verifica `This.lactiv4`.
|
||||
- Tokenul "1" nu e folosit de `frm_facturi` (fara `cbuton1`) - liber pentru o semnificatie noua
|
||||
daca s-ar dori, dar mai curat e un token nou (ex. "5").
|
||||
|
||||
**Sursa lui `gcAcces`**: variabila globala PUBLIC (comentariul `*:Global gcAcces`,
|
||||
`ofacturare_comun.vc2:4770`), NU e setata in codul lui `frm_facturi` sau in procedura care il
|
||||
deschide (`COMUN\programe\oproceduri_facturare.prg:416, 505` - `Createobject("frm_facturi")`
|
||||
fara nicio atribuire de `gcAcces` inainte). E populata inainte, la click pe iconita de pe
|
||||
ecranul-fundal (`ofundal.vc2:69,186,311,391` - `gcAcces = This.coptiuni_active`), unde
|
||||
`coptiuni_active` per iconita vine din `dezactiveaza_imagini` (`COMUN\programe\acces_meniu.prg:39-80`),
|
||||
care citeste central din view-ul Oracle `contafin_oracle.vdef_util_obiecte` (interogat in
|
||||
`citeste_drepturi`, `acces_meniu.prg:17-37`, filtrat pe `id_util`/`id_program`/`id_firma`) si
|
||||
mapeaza pe cheia iconitei (`cheie`) ultima cifra la un token numeric. Editarea drepturilor per
|
||||
grup se face prin `PACK_DREPTURI.grupdreptmodproc` (`COMUN\clase\drept_grupuri.vc2:39`, apelat
|
||||
din `frm_grupuri`).
|
||||
|
||||
**Nu am gasit** un catalog central editabil in VFP care sa enumere sensul fiecarui token numeric
|
||||
per program (ex. un tabel `optiuni_program` cu eticheta "3 = modificare"). Sensul e o conventie
|
||||
fixata in cod (proprietatile `cbutonN` din fiecare clasa de formular) - vezi intrebarea D2.
|
||||
|
||||
### A5. frm_facturi.do_modifica - CORECTIE fata de descrierea din task/plan
|
||||
|
||||
**Contrar formularii din plan_06 ("butonul existent din frm_facturi deschide
|
||||
frm_modifica_articol_factura, care editeaza doar explicatie si taxcode")**, in codul de azi
|
||||
exista DOUA actiuni distincte de "modificare" pe `frm_facturi`, ambele gateate de acelasi token
|
||||
"3" (`cbuton3`), dar cu efecte diferite:
|
||||
|
||||
1. **`do_modifica`** (`ofacturare_comun.vc2:4381-4480`), legata de `but_modifica1` (butonul din
|
||||
bara de sus, `Left=609`, fara `caction` explicit -> foloseste default-ul din clasa de baza
|
||||
`but_modifica` = `caction = inainte_de_do_modifica` -> `This.lactiv3` -> `do_modifica()`).
|
||||
Deschide **`frm_modifica_factura`** (antet document) si, la `gnButon=1`, ruleaza
|
||||
`pack_facturare.modifica_date_factura(...)` pe UNA sau MAI MULTE facturi (dupa selectie
|
||||
multipla `ales=1`) cu campurile: `id_ruta`, `id_delegat`, `id_agent`, `id_masina`,
|
||||
`dataora_exp`, `id_facturare`, `listare_detaliata`, `text_aditional`, `tip_saft`,
|
||||
`efactura`(flag intentie trimitere), `data_act`, `data_scad`, `numar_act`, `serie_act`.
|
||||
**Niciun camp de suma/cantitate/pret.** Contine garda eFactura (A3).
|
||||
2. **`do_modifica_explicatie`** (`ofacturare_comun.vc2:4482-4499`), legata de `But_modifica2`
|
||||
(langa grid-ul de detalii, `caction = do_modifica_explicatie` explicit,
|
||||
`ofacturare_comun.vc2:1433-1441`, tooltip "Modificare explicatie articol"). Deschide
|
||||
**`frm_modifica_articol_factura`** (`ofacturare_comun.vc2:4959`, caption "Modifica explicatie
|
||||
articol"), care editeaza DOAR `explicatie` (memo) si `taxcode` (combo SAFT) pe linia curenta
|
||||
din `crsDetalii`. Garda: doar `poRec.sters = 0` - **fara verificare eFactura**.
|
||||
|
||||
Deci descrierea corecta pentru plan: actiunea care deschide `frm_modifica_articol_factura` e
|
||||
`do_modifica_explicatie` (nu `do_modifica`), iar niciuna din cele doua actiuni existente nu
|
||||
atinge sume/cantitati - confirma nevoia unei actiuni noi (S1), dar sablonul de clonat pentru
|
||||
garzi ramane `do_sterge`, nu vreuna din cele doua `do_modifica*`.
|
||||
|
||||
### A6. afisjurcom.do_modifica - COMUN\clase\comun.vc2:2222-2563
|
||||
|
||||
Clasa `afisjurcom` (extinde `_frmbase`). Pasi:
|
||||
|
||||
1. `2230-2232`: `If !Thisform.lactiv3 Then Return` (acelasi mecanism de drept ca A4).
|
||||
2. `2238-2240`: garda luna inchisa (`glLunaInchisa`).
|
||||
3. `2242-2258`: determina daca se arata si randurile sterse (`lleSters`, dupa filtrul curent),
|
||||
citeste `cod`/`an`/`luna`/`id_set`/`sters`/`id_fact`/`id_factd` din `actjur`.
|
||||
4. `2265-2268`: garda luna curenta - **acelasi tipar** ca in `do_sterge`:
|
||||
`(pnAn*12)+pnLuna <> (gnAn*12)+gnLuna` -> mesaj -> `Return`.
|
||||
5. `2278-2281`: garda suplimentara - `id_set` intre 30000-30009 (note din ROAPRODUCTIE) ->
|
||||
blocate necontional.
|
||||
6. `2313-2332`: inchide cursoarele reziduale `actactan`/`tact`/`rul_temp`/`trul`/
|
||||
`rul_temp_obinv`/`trul_obinv` daca sunt deschise.
|
||||
7. `2352-2368`: incarca `vact_tot` in `actactan` -> `tact` (READWRITE), filtrat
|
||||
`sters=0 and an=gnAn and luna=gnLuna and cod=lnCod` (daca nu se arata stersele) sau fara
|
||||
filtrul de sters, ORDER BY `id_act`.
|
||||
8. `2370-2427`: daca succes, incarca similar `vrul_tot` -> `rul_temp`/`trul` si
|
||||
`vrul_obinv_tot` -> `rul_temp_obinv`/`trul_obinv`, cu recalcul de `valoare`/`valtva`/
|
||||
`valoarev`/`valtvav` pe randurile goale (2383-2387, 2412-2416) inainte de a construi
|
||||
`trul`/`trul_obinv`.
|
||||
9. `2429-2442`: alege clasa de formular dupa an (`gnAn >= gnAnFormNou` implicit 2007) ->
|
||||
**`frm_modific2024`** (`Createobject([frm_modific2024], lnIdSet)`) sau varianta veche
|
||||
`frm_modific`; `Select tact` inainte de `Omodif.Show()`.
|
||||
10. `2444-2538`: daca `buton=1`, deschide tranzactie manuala (`do_deschide_tranzactie`),
|
||||
`oscrie_in_fisiere(2,.T.,llRul)`, reconstruieste `actactan`/`RUL_TEMP`/`RUL_TEMP_OBINV` din
|
||||
`tact`/`trul`/`trul_obinv` cu `id_util`/`sters=0`, apoi `oscrie_in_fisiere(0,.T.,llRul)`,
|
||||
apoi **`pack_contafin.finalizeaza_modificare_nota(pnLuna,pnAn,pdDataOra,lnIdSet,lnCod,
|
||||
lnIdFact,lnIdfactd,gnIdUtil)`** (2484-2487), `do_inchide_tranzactie` si `do_cauta` la final.
|
||||
11. Cod comentat (2496-2513, dezactivat) arata o incercare anterioara de a apela direct
|
||||
`pack_facturare.actualizeaza_vanzari` din client dupa `finalizeaza_modificare_nota` - azi
|
||||
e mort, apelul real se face DOAR server-side, in interiorul lui
|
||||
`finalizeaza_modificare_nota` (confirma faptul deja stabilit in `progres.md`).
|
||||
12. `llVanzari` e declarata (`Store .F.`, 2235) dar logica ei de activare e tot comentata
|
||||
(2292-2307) - variabila ramane mereu `.F.`, deci sincronizarea cu `VANZARI` e complet
|
||||
transparenta pentru `afisjurcom`, indiferent de tipul documentului.
|
||||
|
||||
### A7. frm_modific2024 - COMUN\clase\omodificari.vc2:6375-...
|
||||
|
||||
Clasa (`DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"`) incepe la linia 6375.
|
||||
Metodele proprii merg de la `Activate` (12238) pana la ultimul handler de grid
|
||||
(`pgfArticole.PAGE2.grdRulajeObinv.Init`, 15422-15424) - interval `12238-15424`, usor deplasat
|
||||
fata de planul vechi (`12200-15319`).
|
||||
|
||||
**Contract de intrare** (`Init`, `13551-13660`):
|
||||
```
|
||||
Lparameters tnIdSet, tlNotaNoua, toBackupXML, toSet, tlVizualizare
|
||||
```
|
||||
- `tnIdSet`: id-ul setului de nota (obligatoriu, stocat in `This.nid_set`).
|
||||
- `tlNotaNoua`: `.T.` daca vine din nota fara predefinire.
|
||||
- `toBackupXML`, `toSet`: obiecte optionale (backup XML, respectiv setul de editare
|
||||
restrictionata "doar Salveaza/Renunta" - `This.lEditare`).
|
||||
- `tlVizualizare`: parametru opus, numeric sau logic - `1`/`.T.`=vizualizare, `2`=modificare
|
||||
(default), `3`=verificare note (`13576-13591`).
|
||||
- **Nu primeste cursoare ca parametru.** Formularul se leaga la aliasul curent `tact` (setat de
|
||||
apelant cu `Select tact` inainte de `Createobject`) - grid-ul principal `Grid1` are
|
||||
`RecordSource` legat implicit pe `tact` (conventie mostenita, nu vazuta explicit in Init, dar
|
||||
confirmata de apelul din A6 pas 9). Grid-urile din pageframe au `RecordSource` FIX in
|
||||
definitia clasei: `pgfArticole.PAGE1.grdRulaje.RecordSource = "trul"`
|
||||
(`omodificari.vc2:8669`) si (dupa acelasi tipar, de verificat direct) `grdRulajeObinv` pe
|
||||
`trul_obinv`. **Deci apelantul trebuie sa aiba deschise, cu exact aceste nume de alias,
|
||||
cursoarele `tact`/`trul`/`trul_obinv` READWRITE inainte de instantiere** - exact ce face A6
|
||||
pas 7-8.
|
||||
- **Iesire**: `do_termin` nu e suprascrisa in `frm_modific2024` - foloseste default-ul din
|
||||
`_frmbase` (`_frm_base.vc2:363-376`, seteaza `gnButon=1`/`Buton=1` si inchide/ascunde), dar
|
||||
trece prin `inainte_de_do_termin` proprie, foarte lunga (`13357-13549`, ~192 linii) - acolo e
|
||||
validarea grea (verificari de total, TVA exigibil etc.) inainte sa lase `buton=1`. **Orice
|
||||
validare noua legata de sume factura trebuie sa intre in acest lant**, nu doar in `do_salvare`.
|
||||
- **La iesire cu `buton=1`, cursoarele `tact`/`trul`/`trul_obinv` raman deschise** (formularul nu
|
||||
le inchide) - apelantul (A6 pas 10) le reciteste in `actactan`/`RUL_TEMP`/`RUL_TEMP_OBINV`
|
||||
dupa `Show()`.
|
||||
|
||||
**Pageframe existent** (`pgfArticole`, `omodificari.vc2:8627-8642`, doar 2 pagini azi):
|
||||
```
|
||||
PAGE1.Caption = "Rulaje materii prime, materiale, marfuri, obiecte inventar (303)" (grid grdRulaje pe trul)
|
||||
PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)" (grid grdRulajeObinv pe trul_obinv)
|
||||
```
|
||||
Nu exista azi PAGE3 - de adaugat pentru S4.
|
||||
|
||||
### A8. Butonul/actiunea in bara formularului si modelul de adaugare
|
||||
|
||||
Modelul concret (`But_modifica2`, `ofacturare_comun.vc2:1433-1441`):
|
||||
```
|
||||
ADD OBJECT 'But_modifica2' AS but_modifica WITH ;
|
||||
Anchor = 12, ;
|
||||
caction = do_modifica_explicatie, ;
|
||||
Caption = "", ;
|
||||
Left = 710, ;
|
||||
Name = "But_modifica2", ;
|
||||
TabIndex = 27, ;
|
||||
ToolTipText = "Modificare explicatie articol", ;
|
||||
Top = 341
|
||||
```
|
||||
Dispatch generic: `Click` din clasa de baza a butoanelor (`_cmd_base.vc2:41-...` si a doua
|
||||
implementare la `120-...`) citeste `This.cAction` si il executa pe `Thisform` (cu
|
||||
`This.clistaparametri` optional ca argument). Deci un buton nou nu are nevoie de propriul
|
||||
`Click` - doar de `caction = <nume_metoda_pe_thisform>`.
|
||||
|
||||
Pentru o actiune noua gateata de drept (ca `but_modifica1`, nu ca `But_modifica2`):
|
||||
1. Adauga metoda `do_editare_sume` (sau numele ales) pe `frm_facturi`.
|
||||
2. Adauga `ADD OBJECT 'But_editare_sume1' AS but_modifica WITH ... caption/picture/tooltip/
|
||||
pozitie ...` (poate mosteni orice clasa vizuala din `cmd_butoane.vcx`, nu neaparat
|
||||
`but_modifica`).
|
||||
3. Daca actiunea trebuie gateata separat de token-ul "3" (modificare antet/explicatie) - decizie
|
||||
de arhitectura, vezi D1 - adauga `inainte_de_do_editare_sume` proprie care verifica
|
||||
`This.lactivN` (N = tokenul nou ales, ex. "5"), si seteaza `caction =
|
||||
inainte_de_do_editare_sume` pe buton (dupa modelul `but_modifica1`, care NU seteaza caption
|
||||
explicit pe buton ci mosteneste `inainte_de_do_modifica` din `cmd_butoane.vc2:188`).
|
||||
4. Adauga proprietatea `cbuton5 = But_editare_sume1` pe `frm_facturi` (langa `cbuton2`/`cbuton3`
|
||||
existente, `ofacturare_comun.vc2:1352-1353`) ca butonul sa fie ascuns automat cand tokenul
|
||||
"5" lipseste din `gcAcces` (mecanismul din A4).
|
||||
5. Vezi `COMUN\docs\conventie_ux_formulare.md` pentru pozitionare/anchor in bara existenta.
|
||||
|
||||
## B. Deosebiri de fond fata de plan
|
||||
|
||||
1. **Garda eFactura NU e in `do_sterge`, e in `do_modifica`** (A3). Planul o citeaza gresit ca
|
||||
parte a sablonului `do_sterge` ("Garda eFactura, de refolosit: `ofacturare_comun.vc2:4428-4432`"
|
||||
sub titlul despre `do_sterge`). Practic nu schimba directia (garda tot exista si e
|
||||
refolosibila), dar sursa corecta de citat si tiparul de extras (azi e un simplu `If`, nu un
|
||||
`Return` cu mesaj ca restul garzilor) trebuie corectate in implementare.
|
||||
2. **`frm_facturi.do_modifica` NU deschide `frm_modifica_articol_factura`** (A5). Planul (si
|
||||
textul din task) atribuie asta lui `do_modifica`; in realitate `do_modifica` deschide
|
||||
`frm_modifica_factura` (antet, alte campuri), iar `frm_modifica_articol_factura` (explicatie+
|
||||
taxcode) e deschis de `do_modifica_explicatie`, legata de `But_modifica2`. Nu schimba
|
||||
concluzia planului (niciuna din cele doua nu atinge sume), dar numele metodei/formularului de
|
||||
citat in orice implementare viitoare trebuie sa fie cel corect.
|
||||
3. **Drepturile pe `frm_facturi` nu sunt "lactiv3/lactiv4 + tokeni in gcAcces" ca fapt
|
||||
autonom al formularului** - sunt mecanismul GENERIC din `_frm_base.actualizeaza_drepturi`
|
||||
(A4), aplicat oricarui formular care extinde `_frmbase`. `frm_facturi` doar declara ce
|
||||
inseamna fiecare token pentru el (`cbuton2`, `cbuton3`) si manipuleaza direct `gcAcces`/
|
||||
vizibilitatea pentru cazul special "luna inchisa" (`Init`, 4770-4773). Nu exista o lista
|
||||
centrala DB-editabila a semnificatiei tokenilor (vezi D2) - planul nu gresea factual, dar
|
||||
ii lipsea acest nivel de detaliu, relevant pentru cum se inregistreaza un token nou.
|
||||
4. Restul ancorelor (A1, A2, A6, A7) confirma planul, doar cu liniile deplasate de commit-urile
|
||||
#7/#8 - nicio diferenta de fond.
|
||||
|
||||
## C. Propunerea de implementare S1-S3
|
||||
|
||||
### Arhitectura: unde se pune ce
|
||||
|
||||
Decizia lui Marius (progres.md, punctul 5) cere ca garzile sa se aplice pe AMBELE puncte de
|
||||
intrare (`frm_facturi` din ROAFACTURARE si `afisjurcom` din ROACONT/ROAGEST). Azi, garzile
|
||||
"luna inchisa" si "luna curenta" **exista deja si independent** in ambele clase
|
||||
(`do_sterge`/A1 respectiv `do_modifica`/A6) - fiecare punct de intrare are propria lor copie,
|
||||
pattern deja folosit in cod (nu e o incalcare noua sa le duplic). Garda "referinte
|
||||
incasari/plati" si garda "eFactura" insa **exista azi doar in `frm_facturi`** (ROAFACTURARE) -
|
||||
`afisjurcom.do_modifica` nu le are deloc.
|
||||
|
||||
Recomandare:
|
||||
- **`ReferinteDocumenteNota`** (`COMUN\programe\odocumente.prg:8`) e deja in `COMUN`, deci
|
||||
reutilizabila ca atare din `afisjurcom.do_modifica` fara nicio mutare de cod - se apeleaza cu
|
||||
aceiasi parametri (`an`, `luna`, `cod`), doar ca `afisjurcom` trebuie sa stie cand documentul
|
||||
curent e o factura (vezi mai jos).
|
||||
- **Garda eFactura** foloseste `poRec.id_fact` - `afisjurcom` are deja `lnIdFact`/`lnIdfactd`
|
||||
(A6 pas 3) din `actjur`, deci parametrul exista, doar interogarea (azi inline in
|
||||
`do_modifica` a lui `frm_facturi`) trebuie extrasa intr-o functie mica in `COMUN\programe\`
|
||||
(ex. `EsteInEFactura(tnIdFact)`) ca sa fie apelabila din ambele clase fara duplicare literala
|
||||
a SQL-ului.
|
||||
- Cazul "documentul curent e o factura de vanzare" trebuie detectat in ambele puncte de intrare
|
||||
(nu doar in `frm_facturi`, care STIE deja ca lucreaza cu facturi) - pentru `afisjurcom`
|
||||
inseamna un test suplimentar (ex. `id_set` intre valorile care corespund facturarii, sau
|
||||
existenta unui rand in `vanzari` cu acel `cod`) inainte de a aplica garda eFactura/referinte -
|
||||
pe alte tipuri de note aceste garzi nu au sens si nu trebuie sa apara.
|
||||
- **Cel mai simplu 80/20**: o singura functie noua in `COMUN\programe\` (langa
|
||||
`odocumente.prg` sau intr-un fisier nou `ofacturare_editare.prg`), ex.
|
||||
`VerificaEditareFactura(tnCod, tnAn, tnLuna, tnIdFact)`, care ruleaza toate garzile
|
||||
aplicabile facturii (eFactura + referinte; luna inchisa/curenta raman ca azi, duplicate local,
|
||||
pentru ca deja exista identic in ambele clase) si intoarce `.T./.F.` + mesajul de eroare deja
|
||||
afisat. Apelata din `frm_facturi` (actiune noua, S1) SI din `afisjurcom.do_modifica` (adaugare
|
||||
minima, cateva linii), cu un test prealabil "e factura?" facut de fiecare apelant dupa
|
||||
contextul lui.
|
||||
|
||||
### S1 - Actiunea noua in frm_facturi
|
||||
|
||||
- Metoda noua `do_editare_sume` (nume de discutat) pe `frm_facturi`
|
||||
(`COMUN\clase\ofacturare_comun.vc2`), clonata dupa scheletul de garzi din `do_sterge`
|
||||
(A1 pasii 1-7), dar FARA ramurile de stergere efectiva (pasii 8-12) - se opreste dupa garzi si
|
||||
preda la S2/S3.
|
||||
- Buton nou dupa modelul A8, cu `caption = do_editare_sume` (sau `inainte_de_do_editare_sume`
|
||||
daca se doreste gating explicit prin `lactivN`), token nou in `gcAcces` (propun "5", primul
|
||||
liber - A4) + `cbuton5` pe `frm_facturi`.
|
||||
- Semnatura: fara parametri (citeste contextul din `crsfacturi`/pozitia curenta, ca `do_sterge`).
|
||||
|
||||
### S2 - Incarcarea cursoarelor (COMUN, refolosibila)
|
||||
|
||||
Extrage pasii 7-8 din A6 (incarcarea `vact_tot`/`vrul_tot`/`vrul_obinv_tot` in
|
||||
`tact`/`trul`/`trul_obinv`, filtrate pe `cod`+`an`+`luna`) intr-o procedura comuna, ex.
|
||||
`IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, tlAratasterse)` in `COMUN\programe\`, apelata
|
||||
identic din `afisjurcom.do_modifica` (inlocuind codul inline de azi, refactorizare minima) si din
|
||||
noua actiune din `frm_facturi`. Asta e singura cale sa se garanteze ca cele doua puncte de
|
||||
intrare incarca EXACT acelasi lucru, cerinta explicita a lui Marius.
|
||||
|
||||
### S3 - Deschiderea frm_modific2024 (cod apelant ~40 linii)
|
||||
|
||||
Schita (in `frm_facturi.do_editare_sume`, dupa ce S1 a validat garzile si S2 a incarcat
|
||||
cursoarele):
|
||||
|
||||
```foxpro
|
||||
PROCEDURE do_editare_sume
|
||||
* garzi S1 (eFactura, referinte, luna inchisa/curenta) - vezi A1, A3
|
||||
...
|
||||
Local lnCod, pnAn, pnLuna, lnIdSet, lnIdFact, lnIdFactD
|
||||
* citeste cod/an/luna/id_set/id_fact/id_factd din crsfacturi, ca in A1 pas 3
|
||||
|
||||
If !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) && S2, COMUN
|
||||
Return
|
||||
Endif
|
||||
|
||||
If Reccount('actactan') = 0
|
||||
amessagebox("Nu exista nota contabila pentru aceasta factura.",0+48,"Atentie")
|
||||
Return
|
||||
Endif
|
||||
|
||||
Select tact
|
||||
Local Omodif
|
||||
Omodif = Createobject([frm_modific2024], lnIdSet)
|
||||
Omodif.Show()
|
||||
|
||||
If Omodif.gnButon = 1 && sau variabila globala Buton, ca in A6 pas 10
|
||||
If Thisform.do_deschide_tranzactie()
|
||||
lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.)
|
||||
If lnSucces > 0
|
||||
* reconstruieste actactan/RUL_TEMP/RUL_TEMP_OBINV din tact/trul/trul_obinv, ca in A6
|
||||
...
|
||||
lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.)
|
||||
Endif
|
||||
If lnSucces > 0
|
||||
lcSql = [begin pack_contafin.finalizeaza_modificare_nota(...); end;] && A6 pas 10
|
||||
lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
|
||||
Endif
|
||||
Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1))
|
||||
If lnSucces > 0
|
||||
Thisform.do_cauta()
|
||||
Endif
|
||||
Endif
|
||||
Endif
|
||||
|
||||
* inchide actactan/rul_temp/rul_temp_obinv/tact/trul/trul_obinv
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
Notă: `do_deschide_tranzactie`/`do_inchide_tranzactie` exista deja pe `_frmbase`
|
||||
(`_frm_base.vc2:252-265` si un omolog de inchidere, de verificat numele exact la implementare -
|
||||
`afisjurcom` il foloseste direct, A6 pas 10) - de reutilizat, nu de reprodus manual ca in
|
||||
`do_sterge` (care foloseste `SQLSetprop` direct, tipar mai vechi).
|
||||
|
||||
### Fisiere atinse (estimare S1-S3)
|
||||
|
||||
| Fisier | Proiect | Ce se schimba |
|
||||
|---|---|---|
|
||||
| `COMUN\clase\ofacturare_comun.vc2` | COMUN (cross-project) | metoda noua `do_editare_sume` + buton nou pe `frm_facturi`, token nou in `cbuton*` |
|
||||
| `COMUN\clase\comun.vc2` | COMUN (cross-project) | `afisjurcom.do_modifica` - apel la garda noua + la `IncarcaCursoareModificareNota` (inlocuind codul inline) |
|
||||
| `COMUN\programe\odocumente.prg` sau fisier nou `COMUN\programe\ofacturare_editare.prg` | COMUN (cross-project) | functiile comune noi: garda eFactura extrasa, `IncarcaCursoareModificareNota` |
|
||||
| `COMUN\clase\omodificari.vc2` | COMUN (cross-project) | NEATINS in S1-S3 (S4 adauga PAGE3) |
|
||||
|
||||
Orice modificare in `COMUN\clase\comun.vc2` (`afisjurcom`) afecteaza registrul jurnal din TOATE
|
||||
produsele ROA care il folosesc (ROACONT, ROAGEST, posibil altele) - de tratat cu maxima grija si
|
||||
testat separat de `frm_facturi`.
|
||||
|
||||
## D. Intrebari deschise
|
||||
|
||||
1. **Ce token numeric folosim pentru dreptul nou** si daca trebuie sa fie distinct de tokenul
|
||||
"3" (modificare) existent, sau daca e acceptabil ca cine are drept de "modificare" (token 3)
|
||||
sa capete automat si dreptul de editare sume. Propunere: token separat (ex. "5"), pentru ca
|
||||
editarea sumelor are impact contabil mult mai mare decat editarea campurilor de antet/
|
||||
explicatie - un utilizator ar trebui sa primeasca acest drept explicit, nu implicit prin
|
||||
dreptul existent.
|
||||
2. **Cum se inregistreaza practic un token nou in sistemul de drepturi** ca un administrator sa-l
|
||||
poata acorda per grup din `frm_grupuri` (`COMUN\clase\drept_grupuri.vc2`). Am gasit
|
||||
mecanismul tehnic (`gcAcces` -> `lactivN`/`cbutonN`, populat prin `vdef_util_obiecte` +
|
||||
`PACK_DREPTURI.grupdreptmodproc`), dar nu am gasit un catalog editabil al semnificatiei
|
||||
tokenilor per program - posibil sa fie o eticheta hardcodata undeva neindexat inca in cache-ul
|
||||
text, sau sa fie nevoie de un rand nou in Oracle. De clarificat inainte de S1, altfel tokenul
|
||||
nou risca sa fie "orfan" (functioneaza in cod dar nimeni nu-l poate acorda din UI).
|
||||
3. **Cum se determina in `afisjurcom` ca documentul curent e o factura de vanzare**, ca sa aplice
|
||||
garda eFactura/referinte doar atunci (S4 foloseste acelasi test pentru afisarea PAGE3). Optiuni:
|
||||
test pe `id_set` (interval cunoscut pentru facturare) sau pe existenta unui rand in `vanzari`
|
||||
cu `cod`-ul curent. A doua varianta e mai robusta (nu depinde de conventia de `id_set`) dar
|
||||
costa un SELECT suplimentar la fiecare deschidere - de decis cu Marius pragul de cost acceptat.
|
||||
4. ~~Numele exact al metodelor de tranzactie pe `_frmbase`~~ - rezolvat in cercetare:
|
||||
`do_deschide_tranzactie` (`_frm_base.vc2:252-265`) si `do_inchide_tranzactie`
|
||||
(`_frm_base.vc2:279`) exista amandoua pe `_frmbase`, deci reutilizabile ca atare in S3.
|
||||
@@ -147,7 +147,7 @@ fara pas de write-back binar.
|
||||
|
||||
Neatinse (interzise): `COMUN\clase\omodificari.vc2`, `COMUN\clase\ofacturare_comun.vc2`.
|
||||
|
||||
**Fara commit** — diff-ul: `docs\diff_s4_apelanti_frm_modific2024.patch` (2 sectiuni: `COMUN` din
|
||||
**Fara commit** — diff-ul: diff aplicat (sters) (2 sectiuni: `COMUN` din
|
||||
`comun.git`, `ROAGEST\Programe\roagest.prg` din `roagest.git`).
|
||||
|
||||
## Ce ramane pentru decizia lui Marius
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
# S4 — doua defecte pe pagina de articole: culoarea liniei sterse + valuta liniilor noi (09.08.2026)
|
||||
|
||||
Doua defecte raportate dupa livrarea sub-blocului B (stergere + adaugare de linii). Ambele in
|
||||
`COMUN\clase\omodificari.vc2` (`frm_modific2024`, `pgfArticole.PAGE3`); al doilea atinge si
|
||||
`COMUN\programe\ofacturare_editare.prg`. **Ambele REZOLVATE, dovedite, scrise in binar,
|
||||
necomise.**
|
||||
|
||||
## Defectul 1 — marcajul vizual `DynamicForeColor` nu se aplica pe linia stearsa
|
||||
|
||||
### Cauza reala (nu ipoteza de start, confirmata pe cod)
|
||||
|
||||
`grdArticoleFactura` e definit ca `ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura' AS _grdrow`
|
||||
(`omodificari.vc2:12306`), unde `_grdrow` (`COMUN\clase\_grd_base.vc2:445-489`) e o clasa a suitei
|
||||
comune (nu proprietatea acestei livrari — doar citita) care evidentiaza linia curenta a gridului:
|
||||
|
||||
```
|
||||
PROCEDURE Init
|
||||
DoDefault()
|
||||
If This.nRgbrow = 1
|
||||
...
|
||||
This.SetAll("DynamicForeColor","iif(RECNO() = This.nRecno,RGB(" + This.cRGB_Font + "),RGB(0,0,0))","Column")
|
||||
Endif
|
||||
ENDPROC
|
||||
```
|
||||
|
||||
`nrgbrow` implicit e `1`. La instantiere, dupa ce `PropValue`-urile clasei (inclusiv
|
||||
`Column1..14.DynamicForeColor = "IIF(tvd.sters=1,RGB(150,150,150),RGB(0,0,0))"`) sunt aplicate,
|
||||
`Init` ruleaza si **`SetAll` suprascrie necondiționat** `DynamicForeColor` pe toate cele 14
|
||||
coloane cu o expresie care ignora `tvd.sters` complet — de-asta linia stearsa avea pixeli negri
|
||||
puri (0,0,0), nu gri (150,150,150): codul din clasa era corect, dar era deja inlocuit inainte de
|
||||
primul `Refresh()`.
|
||||
|
||||
Ipoteza de start din briefing ("`_grdrow.Init` castiga in fata lui `DynamicForeColor`") s-a
|
||||
confirmat exact, cu mecanismul precis identificat (`SetAll` in `Init`, nu doar `AfterRowColChange`).
|
||||
|
||||
### De ce nu solutia gridurilor surori
|
||||
|
||||
`grdRulaje`/`grdRulajeObinv` (`pgfArticole.PAGE1`/`PAGE2`) rezolva coliziunea cu `Init` **gol**
|
||||
(`*Nu sterge`, `omodificari.vc2:~15659`/`~15926`) — asta taie tot lantul `DoDefault()`, deci si
|
||||
`_grid.Init()` (cel care seteaza `ReadOnly` pe coloanele text dupa `lcamptextneeditabil`).
|
||||
`grdArticoleFactura` are nevoie sa ramana editabil pe `cantitate`/`pret`/`pret_cu_tva`
|
||||
(`lcamptextneeditabil=.F.`, fix din sesiunea anterioara) — un `Init` gol ar fi rupt din nou
|
||||
editabilitatea.
|
||||
|
||||
### Fix
|
||||
|
||||
O singura proprietate pe `ADD OBJECT`-ul gridului (`omodificari.vc2:12317`):
|
||||
|
||||
```
|
||||
nrgbrow = 0, ;
|
||||
```
|
||||
|
||||
`nrgbrow=0` scurt-circuiteaza intreg blocul `If This.nRgbrow = 1` din `_grdrow.Init` (deci si
|
||||
`SetAll`) **fara sa taie** `DoDefault()` -> `_grid.Init()` — editabilitatea ramane intacta.
|
||||
Tiparul e deja folosit in **20+ griduri** din suita comuna (`COMUN\clase\configurare.vc2`,
|
||||
`COMUN\clase\onomenclatoare.vc2`), deci nu e o solutie inventata pentru acest caz — e conventia
|
||||
existenta pentru "grid cu culoare proprie pe randuri, fara evidentierea implicita a liniei
|
||||
curente".
|
||||
|
||||
### Dovada — esantionare de pixeli, nu vizual
|
||||
|
||||
Doua capturi noi, sub `vfp_ui_harness.ps1 -SyncDir` explicit (capcana de sincronizare deja
|
||||
rezolvata in sesiunea precedenta):
|
||||
|
||||
- `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\step_0_contrast_gri_vs_negru.png`
|
||||
— document cu 4 linii (`cod=1140895`/`id_vanzare=1050`), linia 2 marcata stearsa prin
|
||||
`cmdStergeArticol.Click()`, linia curenta a gridului mutata pe linia 3 (`GO 3` +
|
||||
`loGrid.SetFocus()`) ca selectia (fundal albastru) sa nu acopere nici linia stearsa, nici o
|
||||
linie de control. Esantionare cu `System.Drawing.Bitmap.GetPixel` pe banda de text a fiecarei
|
||||
linii (PowerShell, cautare pixel cu luminanta minima in regiune):
|
||||
|
||||
| Linie | Pixel cel mai inchis (RGB) |
|
||||
|---|---|
|
||||
| Linia 1 (normala, `sters=0`) | `(0,0,0)` |
|
||||
| **Linia 2 (STEARSA, `sters=1`)** | **`(150,150,150)`** — exact `RGB(150,150,150)` din `DynamicForeColor` |
|
||||
| Linia 4 (normala, `sters=0`) | `(0,0,0)` |
|
||||
|
||||
- `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\step_0_linia_grizata.png` —
|
||||
document cu 2 linii (`cod=1139934`/`id_vanzare=882`), aceeasi verificare, acelasi rezultat
|
||||
(`RGB(150,150,150)` pe linia stearsa).
|
||||
|
||||
Capturile "before" (linia stearsa cu pixeli negri puri, dovada defectului inainte de fix), mutate
|
||||
din sesiunea anterioara: `screenshots_before_fix_culoare\step_0_linia grizata dupa sters.png` +
|
||||
`step_0_crop_zoom.png`.
|
||||
|
||||
### Testat, regresie
|
||||
|
||||
`test_ui_sterge_linie.prg` (existent, nemodificat in logica — doar rerulat): **8 PASS / 0 FAIL**,
|
||||
log complet pana la `REZULTAT`. `test_page3_articole.prg`: **14 PASS / 2 FAIL** (identic cu
|
||||
baseline, cele 2 FAIL sunt artefactul headless cunoscut de la datoria 7 — `ColumnCount`/`ReadOnly`
|
||||
nu se materializeaza sub `-A -T`). `test_incarca_vanzare_din_nota.prg`: **5 PASS / 0 FAIL**.
|
||||
|
||||
Suita noua `test_ui_culoare_contrast.prg` (dedicata acestui fix, ramane in suita de regresie):
|
||||
descopera dinamic un document cu minim 3 linii (`DescoperaCazTest('FACTURA_ARTICOLE', ...)`,
|
||||
nu ancorat pe `cod`), marcheaza a doua linie stearsa, muta linia curenta pe a treia, face captura.
|
||||
**1 PASS / 0 FAIL** pe asertia functionala (`sters=1` dupa click); dovada vizuala e in captura +
|
||||
esantionarea de pixeli de mai sus, nu intr-o asertie automata (culoarea nu se poate verifica prin
|
||||
`EVALUATE` in interiorul testului — eroarea 1929, deja documentata in `rec_s4_runda3b2.md`).
|
||||
|
||||
## Defectul 2 — liniile adaugate intrau fortat in RON
|
||||
|
||||
### Cauza reala (diferita de formularea initiala din briefing)
|
||||
|
||||
Briefingul presupunea ca `AdaugaLinieTvdDinArticol` scrie `tip_valuta = 0` fix — **verificat pe
|
||||
cod, fals**: `tvd` (structura din `CreeazaCursorArticoleGol`, `ofacturare_editare.prg:268-271`) nu
|
||||
are deloc un camp `tip_valuta`, `curs` sau `multiplicator` — acele campuri nu exista in view-ul
|
||||
`VVANZARI_ARTICOLE` (linia stocheaza doar `id_valuta`, o referinta la `nom_valute`, fara factor de
|
||||
conversie propriu).
|
||||
|
||||
Cauza reala e in alta parte: `tip_valuta=0`/`Curs=1`/`multiplicator=1` sunt hardcodate pe
|
||||
**`poArticol`** in `CreeazaPoArticolNouTvd` (`ofacturare_editare.prg:429-431`), iar
|
||||
`poDate.in_valuta` e hardcodat `0` in `cmdAdaugaArticol.Click` (`omodificari.vc2:16190`) — asta
|
||||
tine dialogul `frm_articol_factura` in **modul RON** indiferent de valuta reala a documentului.
|
||||
Dialogul calculeaza `pretftva`/`pretctva` (campurile RON) pe baza a ce introduce utilizatorul, iar
|
||||
`AdaugaLinieTvdDinArticol` scria acele valori **neconvertite** in `tvd.pret`/`tvd.discount_unitar`.
|
||||
|
||||
Bara de totaluri (`ActualizeazaBaraTotaluri`, decizia 33, `omodificari.vc2:12856-12899`) insumeaza
|
||||
`tvd.valoare` **brut** (`SUM valoare FOR sters<>1`) si aplica **o singura data**
|
||||
`tvanz.curs`/`multiplicator` pe suma — asta presupune ca fiecare linie e deja stocata in valuta
|
||||
documentului, nu in RON. Verificat pe date (schema `MARIUSM_AUTO`):
|
||||
|
||||
| `id_vanzare` | `VANZARI.in_valuta` | `VANZARI.id_valuta` | `curs` | linia (`VANZARI_DETALII.pret`) |
|
||||
|---|---|---|---|---|
|
||||
| 1037 | 1 | 2 (EURO) | 5.2688 | `pret=200` — 200 EUR brut, nu 200 RON |
|
||||
|
||||
O linie noua scrisa in RON (ex. utilizatorul intentioneaza 1053.76 RON) ar fi ramas `pret=1053.76`
|
||||
in `tvd`, iar bara de totaluri ar fi calculat `1053.76 * 5.2688 = 5551.6` RON — de peste 5 ori
|
||||
valoarea reala.
|
||||
|
||||
### Fix — scopat strict pe stocare, fara sa ating dialogul
|
||||
|
||||
`frm_articol_factura`/`ofacturare.vc2` **nu sunt in proprietatea acestei livrari** (partajate cu
|
||||
tot restul suitei), si a face dialogul sa accepte pret direct in valuta ar cere
|
||||
`poDate.id_valuta`/`poDate.zi_curs` populate corect (altfel validarea interna a dialogului
|
||||
respinge la "Terminare" cu mesaj — verificat pe cod, `ofacturare.vc2:9484,9490`) — netestabil
|
||||
headless (`Show()` e modal) si risc pe o clasa mare, necunoscuta. Fix ales, minim si sigur:
|
||||
|
||||
1. **`tvanz` extins** cu `in_valuta`, `id_valuta`, `nume_val` (join nou pe `nom_valute` in
|
||||
`IncarcaVanzareNota`, `ofacturare_editare.prg:150-176`; `CreeazaCursorTvanzGol` la fel).
|
||||
2. **`AdaugaLinieTvdDinArticol` (`omodificari.vc2:12901-12934`) converteste** pretul/discountul
|
||||
calculate de dialog (RON) in valuta documentului, inainte de a le scrie in `tvd`:
|
||||
`pret = pretRON * tvanz.multiplicator / tvanz.curs` (si simetric pentru `discount_unitar`) —
|
||||
inversul exact al formulei din bara de totaluri, deci **no-op pe documente RON**
|
||||
(`curs=multiplicator=1`, verificat neregresat pe suita existenta).
|
||||
3. **`id_valuta`/`nume_val` ale liniei noi preiau valorile de pe `tvanz`** (`tvanz.id_valuta`,
|
||||
`tvanz.nume_val`) in loc de `.Null.`/gol — simetric cu liniile existente, care le au populate
|
||||
din `VVANZARI_ARTICOLE`.
|
||||
|
||||
**Limitare ramasa, de raportat explicit**: dialogul **tot lucreaza in RON** — utilizatorul introduce
|
||||
pretul in RON chiar si pe un document in valuta, iar conversia se face "in spate", la scriere.
|
||||
STOCAREA e acum corecta valutar (bara de totaluri calculeaza corect regardless de valuta
|
||||
documentului), dar UX-ul de introducere a pretului direct in valuta nu e implementat — ar cere
|
||||
atingerea `ofacturare.vc2`, in afara scope-ului primit ("nu era ceruta multi-valuta in briefing" —
|
||||
decizie mostenita din sub-blocul B partea 2, `rec_s4_runda3b2.md`).
|
||||
|
||||
### Testat
|
||||
|
||||
- `test_page3_articole.prg`: **14 PASS / 2 FAIL** (identic cu baseline).
|
||||
- `test_incarca_vanzare_din_nota.prg`: **5 PASS / 0 FAIL**.
|
||||
- `test_adauga_linie_articol.prg` (existent, caz RON): **20 PASS / 0 FAIL** — confirma ca
|
||||
conversia e no-op cand `curs=multiplicator=1`, nicio regresie pe calea deja acoperita.
|
||||
- **Suita noua** `test_adauga_linie_valuta.prg`: foloseste un document real cu articole
|
||||
(descoperit dinamic, nu ancorat pe `cod`), dar suprascrie manual `tvanz.curs=5.2688`,
|
||||
`multiplicator=1`, `in_valuta=1`, `id_valuta=2`, `nume_val='EURO'` dupa `Show()` — nu exista in
|
||||
schema un caz descoperibil simultan "cu articole" si "in valuta reala" (`id_vanzare=1037`, EURO,
|
||||
are o singura linie, nefolosibila pentru un test de "adaugare langa liniile existente" fara
|
||||
ambiguitate). Construieste `poArticol` cu `pretftva=1053.76` (echivalentul RON a 200 EUR la
|
||||
cursul testat) si verifica: **6 PASS / 0 FAIL** —
|
||||
`tvd.pret` convertit la `200.00`, `id_valuta=2`, `nume_val='EURO'`, `tvd.valoare=200.00`, iar
|
||||
bara de totaluri creste cu exact `1053.76` RON (echivalentul corect, nu suma bruta).
|
||||
|
||||
## Cens de octeti si write-back
|
||||
|
||||
Baseline la inceputul sesiunii: `2 aa / 2 e3 / 2 fe`, zero `EF BF BD`. Primul `Edit` pe
|
||||
`omodificari.vc2` (adaugarea `nrgbrow = 0`) a reencodat tot fisierul, stricand din nou cele doua
|
||||
linii `Caption = "CTRL+F = Terminare; ESC = Renunțare; CTRL+N = Adăugare; CTRL+D = Ștergere"`
|
||||
(capcana deja cunoscuta, lovita si in sesiunile precedente) — cens dupa: `6 ef / 6 bf / 6 bd`.
|
||||
Reparat byte-cu-byte cu Perl (pozitional: octetul 1 din fiecare tripleta `EF BF BD` -> `0xFE`
|
||||
(ț), octetul 2 -> `0xE3` (ă), octetul 3 -> `0xAA` (Ș), ciclic pe cele 2 linii x 3 caractere).
|
||||
Cens final, verificat inainte si dupa `txt2vcx.ps1`: **identic cu baseline, `2 aa/2 e3/2 fe`, zero
|
||||
`EF BF BD`**.
|
||||
|
||||
`ofacturare_editare.prg` e ASCII pur (verificat, zero octeti >0x7F) — fara risc de encoding, nu
|
||||
necesita reparare.
|
||||
|
||||
**Fidelity-check trecut din prima incercare** (`txt2vcx.ps1 -AllowComun`, un singur fisier
|
||||
regenerat) — spre deosebire de sesiunile precedente, nu a fost nevoie sa adopt textul regenerat
|
||||
din `<staging>\verify\`.
|
||||
|
||||
## Fisiere atinse, stare write-back
|
||||
|
||||
| Fisier | Stare |
|
||||
|---|---|
|
||||
| `COMUN\clase\omodificari.vc2` | Editat (`nrgbrow=0` pe grid + `AdaugaLinieTvdDinArticol` rescrisa), write-back FACUT, fidelity check OK din prima, cens OK |
|
||||
| `COMUN\clase\omodificari.vcx` / `.VCT` | Scrise, mtime sincron cu `.vc2` (16:59) |
|
||||
| `COMUN\clase\omodificari.vc2.pre_fix_culoare.bak` | Backup, luat la inceputul sesiunii |
|
||||
| `COMUN\programe\ofacturare_editare.prg` | Editat (`CreeazaCursorTvanzGol` + `IncarcaVanzareNota` extinse cu valuta documentului, antet rescris), ASCII pur |
|
||||
| `COMUN\programe\ofacturare_editare.prg.pre_fix_culoare.bak` | Backup, luat la inceputul sesiunii |
|
||||
| `COMUN\utile\Teste\editare_factura\test_adauga_linie_valuta.prg` | Nou, testat, 6/6 PASS |
|
||||
| `COMUN\utile\Teste\editare_factura\test_ui_culoare_contrast.prg` | Nou, testat, captura + esantionare pixeli |
|
||||
| `COMUN\utile\Teste\editare_factura\screenshots_after_fix_culoare\` | Nou — 2 capturi, dovada pe pixeli |
|
||||
| `COMUN\utile\Teste\editare_factura\screenshots_before_fix_culoare\` | Capturile "before" din sesiunea anterioara, mutate din `screenshots\` ca sa nu se piarda |
|
||||
| `docs\diff_s4_fix_culoare_valuta.patch` | Nou — `omodificari.vc2` |
|
||||
| `docs\diff_s4_fix_culoare_valuta_ofacturare_editare.patch` | Nou — `ofacturare_editare.prg` |
|
||||
| `docs\progres.md` | Actualizat |
|
||||
|
||||
**Fara commit** — asteapta review, conform regulii.
|
||||
|
||||
## Ce NU e acoperit
|
||||
|
||||
1. **Dialogul `frm_articol_factura` tot lucreaza in RON** — utilizatorul introduce pretul in RON
|
||||
chiar si pe un document in valuta; conversia se aplica la scriere, nu la intrare. A schimba
|
||||
asta ar cere atingerea `ofacturare.vc2` (`poDate.in_valuta=1` + `id_valuta`/`zi_curs`
|
||||
populate), in afara proprietatii/scope-ului acestei livrari.
|
||||
2. **`Show(1)` (dialogul modal chiar deschis)** — netestat automat (netestabil headless), ca in
|
||||
sesiunile precedente; acoperit doar prin analiza de cod si testare manuala recomandata.
|
||||
3. **Editarea unei linii existente prin acelasi dialog** (dublu-clic) — ramane nefacuta, in afara
|
||||
scope-ului primit in aceasta sesiune.
|
||||
4. **Decizia de arhitectura despre `_grd_base.vc2`**: fixul defectului 1 s-a facut fara sa ating
|
||||
`_grd_base.vc2` (clasa comuna) — `nrgbrow` era deja o proprietate expusa pentru exact acest caz,
|
||||
nu a fost nevoie de nicio modificare acolo.
|
||||
@@ -1,9 +1,9 @@
|
||||
# S4 runda 1 (PAGE3, doar afisare) — raport de inchidere, 08.08.2026
|
||||
|
||||
Runda 1 din S4 (`plan_06_s4_proiectare.md`) e **inchisa**. Diff-ul de review:
|
||||
`docs\diff_s4_runda1_page3.patch`. Istoricul complet al sesiunii de implementare/depanare:
|
||||
`docs\cercetare\handoff_s4_runda1.md`, `docs\cercetare\handoff_propr_custom.md`,
|
||||
`docs\handoff_sesiune_08082026_c.md`.
|
||||
diff aplicat (sters). Istoricul complet al sesiunii de implementare/depanare:
|
||||
`docs\cercetare\handoff_s4_runda1.md`, handoff intermediar (sters),
|
||||
handoff intermediar (sters).
|
||||
|
||||
## Ce s-a implementat
|
||||
|
||||
@@ -61,7 +61,7 @@ Testul nu atinge Oracle in scriere — doar `SELECT`-uri prin `goExecutor`.
|
||||
## Blocaje rezolvate in aceasta sesiune (istoric, nu de reluat)
|
||||
|
||||
Trei blocaje separate au impiedicat verificarea live inainte de aceasta runda de inchidere, toate
|
||||
documentate pe larg in `handoff_sesiune_08082026_c.md` si `COMUN\docs\testare-ui-vfp.md`:
|
||||
documentate pe larg in handoff intermediar (sters) si `COMUN\docs\testare-ui-vfp.md`:
|
||||
|
||||
1. `DO ... WITH gnAn, gnLuna` pasa prin referinta si umbrea variabilele in procedurile apelate,
|
||||
provocand dialogul nativ "View Parameter" pe un `?gnAn` din SQL passthrough — remediat cu
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# S4 runda 2 (PAGE3 "Articole factura") - view VVANZARI_ARTICOLE, pozitionare in tact, garda ROACONT/ROAGEST
|
||||
|
||||
Runda 2 pe fisierele deja livrate in runda 1 (`docs\diff_s4_runda1_page3.patch`, netrimis inca la
|
||||
commit). Diff: `docs\diff_s4_runda2_view_pozitionare.patch` (`COMUN\programe\ofacturare_editare.prg`
|
||||
Runda 2 pe fisierele deja livrate in runda 1 (diff aplicat (sters), netrimis inca la
|
||||
commit). Diff: diff aplicat (sters) (`COMUN\programe\ofacturare_editare.prg`
|
||||
+ `COMUN\clase\omodificari.vc2`, clasa `frm_modific2024`). Fara commit.
|
||||
|
||||
## Ce s-a schimbat
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Stare: **stergerea logica e implementata si scrisa in binar**; **adaugarea (dialog
|
||||
`frm_articol_factura`) NU e implementata** — sub-blocul s-a dovedit prea mare pentru un
|
||||
singur context si a fost impartit, conform aprobarii din briefing. Cercetarea de contract
|
||||
pentru adaugare e completa si predata mai jos / in `docs\handoff_s4_runda3b_adaugare.md`,
|
||||
pentru adaugare e completa si predata mai jos / in handoff intermediar (sters),
|
||||
ca urmatorul agent sa nu o reia.
|
||||
|
||||
## Ce s-a implementat: stergerea logica de linie
|
||||
@@ -61,7 +61,7 @@ in manifestul clasei (`omodificari.vc2:6660`), cerinta FoxBin2Prg pentru orice c
|
||||
|
||||
## Diff
|
||||
|
||||
`docs\diff_s4_runda3b_linii.patch` — **scopat strict pe modificarile mele**, nu pe tot ce e
|
||||
diff aplicat (sters) — **scopat strict pe modificarile mele**, nu pe tot ce e
|
||||
necomis in `omodificari.vc2` (fisierul are si munca altor agenti din aceeasi zi, inca
|
||||
necomisa). Reconstruit dintr-un baseline `.pre_runda3b.bak` obtinut prin reversul exact al
|
||||
celor 4 editari facute (nu am luat backup INAINTE de prima editare — lectie pentru viitor,
|
||||
@@ -144,7 +144,7 @@ nu blocheaza livrarea sub-blocului, dar merita bifat.
|
||||
## Ce NU e acoperit (predat mai departe)
|
||||
|
||||
- **Adaugarea de linii** (dialog `frm_articol_factura`) — **neinceputa in cod**. Cercetarea
|
||||
de contract e completa si predata in `docs\handoff_s4_runda3b_adaugare.md`.
|
||||
de contract e completa si predata in handoff intermediar (sters).
|
||||
- **Editarea per-linie prin acelasi dialog** (dublu-clic pe o linie existenta) — la fel,
|
||||
parte din adaugare, nu inceputa.
|
||||
- **Discountul de antet** (`tvanz`, decizia 17) si **bara de totaluri** — sub-blocul C,
|
||||
@@ -158,7 +158,7 @@ nu blocheaza livrarea sub-blocului, dar merita bifat.
|
||||
| `COMUN\clase\omodificari.vcx` / `.VCT` | Scrise, mtime sincron cu `.vc2` |
|
||||
| `COMUN\clase\omodificari.vc2.pre_runda3b.bak` | Backup reconstruit (baseline pentru diff) |
|
||||
| `COMUN\utile\Teste\editare_factura\test_ui_sterge_linie.prg` | Nou, testat |
|
||||
| `docs\diff_s4_runda3b_linii.patch` | Nou, scopat pe sub-blocul B |
|
||||
| `docs\handoff_s4_runda3b_adaugare.md` | Nou, cercetarea de contract pentru adaugare |
|
||||
| diff aplicat (sters) | Nou, scopat pe sub-blocul B |
|
||||
| handoff intermediar (sters) | Nou, cercetarea de contract pentru adaugare |
|
||||
|
||||
**Fara commit** — asteapta review, conform regulii.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# S4 runda 3, sub-blocul B partea 2 — adaugarea de linii + doua goluri, 09.08.2026
|
||||
|
||||
Continuarea lui `rec_s4_runda3b.md` (stergerea logica, GATA) si `handoff_s4_runda3b_adaugare.md`
|
||||
Continuarea lui `rec_s4_runda3b.md` (stergerea logica, GATA) si handoff intermediar (sters)
|
||||
(cercetarea de contract, predata). Aici: **adaugarea de linii prin dialogul `frm_articol_factura`**,
|
||||
plus inchiderea celor doua goluri lasate de partea 1.
|
||||
|
||||
@@ -165,10 +165,10 @@ interventie, doar asteptare.
|
||||
| `COMUN\programe\ofacturare_editare.prg` | Editat (functie noua `CreeazaPoArticolNouTvd` + antet), ASCII pur, zero risc de encoding |
|
||||
| `COMUN\utile\Teste\editare_factura\test_adauga_linie_articol.prg` | Nou, testat, 20/20 PASS |
|
||||
| `COMUN\utile\Teste\editare_factura\test_ui_sterge_linie.prg` | Modificat (golul #2 + pozitionare pentru captura), testat, 8/8 PASS |
|
||||
| `docs\diff_s4_runda3b2_adaugare.patch` | Nou — scopat strict pe modificarile mele in `omodificari.vc2` |
|
||||
| `docs\diff_s4_runda3b2_ofacturare_editare.patch` | Nou — **atentie**: `COMUN` are git propriu, diff-ul e fata de ultimul commit, deci contine si munca altor agenti din aceeasi zi, inca necomisa (linia `CreeazaCursorTvdGol()` -> `CreeazaCursorArticoleGol` in `IncarcaArticoleFactura`, `PregatesteArticoleFacturaEditare` intreaga functie). **Partea mea**: antetul fisierului (rescris) + functia `CreeazaPoArticolNouTvd` intreaga, adaugata la coada fisierului. |
|
||||
| diff aplicat (sters) | Nou — scopat strict pe modificarile mele in `omodificari.vc2` |
|
||||
| diff aplicat (sters) | Nou — **atentie**: `COMUN` are git propriu, diff-ul e fata de ultimul commit, deci contine si munca altor agenti din aceeasi zi, inca necomisa (linia `CreeazaCursorTvdGol()` -> `CreeazaCursorArticoleGol` in `IncarcaArticoleFactura`, `PregatesteArticoleFacturaEditare` intreaga functie). **Partea mea**: antetul fisierului (rescris) + functia `CreeazaPoArticolNouTvd` intreaga, adaugata la coada fisierului. |
|
||||
| `COMUN\utile\Teste\editare_factura\screenshots\step_0_linia grizata dupa sters.png` | Nou — dovada vizuala (revela defectul DynamicForeColor) |
|
||||
| `docs\handoff_s4_runda3b2.md` | Handoff intermediar scris in timpul asteptarii write-back-ului — poate fi sters, sesiunea s-a incheiat normal |
|
||||
| handoff intermediar (sters) | Handoff intermediar scris in timpul asteptarii write-back-ului — poate fi sters, sesiunea s-a incheiat normal |
|
||||
|
||||
**Fara commit** — asteapta review, conform regulii.
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ predat separat, vezi sectiunea "Ce NU e acoperit".
|
||||
- `tvanz` capata doua coloane noi, `curs N(10,4)` si `multiplicator N(10,4)`, atat in
|
||||
`CreeazaCursorTvanzGol` (`:145-150`) cat si in `SELECT`-ul din `IncarcaVanzareNota` (`:172-174`) —
|
||||
necesare pentru conversia RON (decizia 33). Diff izolat (2 linii):
|
||||
`docs\diff_s4_runda3c_ofacturare_editare.patch`.
|
||||
diff aplicat (sters).
|
||||
|
||||
## Defect gasit si reparat in aceeasi sesiune (nu era in cod inainte)
|
||||
|
||||
@@ -126,8 +126,8 @@ PASS in log, pe formular real instantiat, nu simulat) sta in picioare.
|
||||
|
||||
## Diff-uri
|
||||
|
||||
- `docs\diff_s4_runda3c_totaluri.patch` — `omodificari.vc2` (fata de `.pre_runda3c.bak`).
|
||||
- `docs\diff_s4_runda3c_ofacturare_editare.patch` — `ofacturare_editare.prg`, izolat (2 linii).
|
||||
- diff aplicat (sters) — `omodificari.vc2` (fata de `.pre_runda3c.bak`).
|
||||
- diff aplicat (sters) — `ofacturare_editare.prg`, izolat (2 linii).
|
||||
|
||||
**Fara commit.**
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ corectie). Nu a fost atins `AdaugaLinieTvdDinArticol` — in afara scopului aces
|
||||
## Testat
|
||||
|
||||
**Regresie, headless, `vfp9.exe -A -T`, watchdog, exit 0, zero dialoguri**, identic cu baseline-ul
|
||||
de plecare (`docs\handoff_s4_runda3c2.md`):
|
||||
de plecare (handoff intermediar (sters)):
|
||||
- `test_page3_articole.prg`: **14 PASS / 2 FAIL** (cele 2 = artefactul headless cunoscut de la
|
||||
datoria 7, neschimbat).
|
||||
- `test_incarca_vanzare_din_nota.prg`: **5 PASS / 0 FAIL**.
|
||||
@@ -146,8 +146,8 @@ documentat mai sus, nu o dovada ca formula e gresita pe restul datelor.
|
||||
|
||||
## Diff-uri
|
||||
|
||||
- `docs\diff_s4_runda3c2_verdict.patch` — `omodificari.vc2` (fata de `.pre_verdict.bak`).
|
||||
- `docs\diff_s4_runda3c2_ofacturare_editare.patch` — `ofacturare_editare.prg`, izolat.
|
||||
- diff aplicat (sters) — `omodificari.vc2` (fata de `.pre_verdict.bak`).
|
||||
- diff aplicat (sters) — `ofacturare_editare.prg`, izolat.
|
||||
|
||||
**Fara commit** (nici git, nici SVN).
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ SUM (Nvl(cant,0) + Nvl(cante,0)) * Nvl(pretvtva,0) ;
|
||||
TO lnTotalRul FOR Nvl(sters,0) = 0 AND Nvl(id_tip_rulaj,0) = 0
|
||||
```
|
||||
|
||||
Diff complet: `docs\diff_s4_runda3c3_decizii_36_37.patch`.
|
||||
Diff complet: diff aplicat (sters).
|
||||
|
||||
## Test actualizat
|
||||
|
||||
@@ -67,7 +67,7 @@ Diff complet: `docs\diff_s4_runda3c3_decizii_36_37.patch`.
|
||||
- pe tip=1 (fara rata), acelasi rand mutat pe `461` NU mai intra — contul ramane strict `4111`,
|
||||
verificand ca extinderea nu s-a scapat pe tipurile obisnuite de factura.
|
||||
|
||||
Diff complet: `docs\diff_s4_runda3c3_test.patch`.
|
||||
Diff complet: diff aplicat (sters).
|
||||
|
||||
## Testat
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Livrare - decizia 35: intrare directa in valuta la adaugarea de linii
|
||||
|
||||
Implementare pe baza cercetarii de contract deja facute (`docs\handoff_decizia35_valuta_dialog.md`):
|
||||
Implementare pe baza cercetarii de contract deja facute (handoff intermediar (sters)):
|
||||
premisa initiala (atingerea `ofacturare.vc2`) a fost infirmata acolo - dialogul `frm_articol_factura`
|
||||
nu citeste `poDate.in_valuta`, ramura de valuta e condusa de `poArticol.tip_valuta`/`Curs`/
|
||||
`multiplicator`/`nume_val`. Toata lucrarea de mai jos e in apelant, **`ofacturare.vc2` nu a fost atins**.
|
||||
@@ -70,8 +70,8 @@ write-back necesar.
|
||||
- `COMUN\programe\ofacturare_editare.prg` (+ `.pre_s4_valuta.bak`)
|
||||
- `COMUN\clase\omodificari.vc2` (+ `.pre_s4_valuta.bak`), scris in `omodificari.vcx`/`.vct`
|
||||
- `COMUN\utile\Teste\editare_factura\test_adauga_linie_valuta.prg` (+ `.pre_s4_valuta.bak`)
|
||||
- Patch-uri: `docs\diff_s4_valuta_dialog.patch`, `docs\diff_s4_valuta_dialog_prg.patch`,
|
||||
`docs\diff_s4_valuta_dialog_test.patch`
|
||||
- Patch-uri: diff aplicat (sters), diff aplicat (sters),
|
||||
diff aplicat (sters)
|
||||
|
||||
**Fara commit** (git/SVN). **Zero scrieri in Oracle** - toate testele lucreaza pe cursoare in
|
||||
memorie.
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
# S4b etapa 2 — smoke test headless al dialogului `frm_sincronizare_articole`
|
||||
|
||||
Suita nouă: `COMUN\utile\Teste\editare_factura\test_s4b_dialog.prg`, model
|
||||
`test_s4b_sincronizare.prg` (același folder) — `tvd`/`trul` construite în test cu helperele
|
||||
`AdaugaTvd`/`AdaugaTrul` (copiate identic), `dummyform` (copiat identic) refolosit ca
|
||||
`oFormArticole`. Complet headless (`vfp9.exe -A -T`), **fără Oracle**.
|
||||
|
||||
**Nu s-a atins `COMUN\clase\omodificari.vc2` sau `COMUN\programe\ofacturare_editare.prg`** — doar
|
||||
citite, niciun write-back.
|
||||
|
||||
## Rezultat
|
||||
|
||||
```
|
||||
REZULTAT: 35 PASS / 0 FAIL
|
||||
```
|
||||
|
||||
Log: `D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s4b_dialog_log.txt`
|
||||
|
||||
Comandă de reproducere:
|
||||
```
|
||||
cd "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura"
|
||||
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T test_s4b_dialog.prg
|
||||
```
|
||||
|
||||
Niciun proces `vfp9.exe` rămas viu, verificat cu `tasklist` înainte și după rulare (0 ambele dăți).
|
||||
|
||||
## Mediu (fără Oracle, fără `test_init_env_auto`)
|
||||
|
||||
Clasa e `OF "_frm_child.vcx"` (`WindowType=1`, modală), dar modalitatea se declanșează la
|
||||
`.Show()`, nu la `Createobject()` — verificat pe cod (`_frm_child.vc2`/`_frm_base.vc2`, niciun
|
||||
`.Show(` în lanțul de moștenire) înainte de a scrie testul, ca niciun caz să nu rămână blocat.
|
||||
Mediul de clase a fost replicat din `Programe\roafacturare.prg` (SET PATH + tot lanțul SET
|
||||
CLASSLIB, minus procedurile Oracle/`init_program`), plus `SET PROCEDURE TO proceduri_comune.prg`
|
||||
și `ofacturare_editare.prg` — suficient ca `CreateObject('frm_sincronizare_articole')` să rezolve
|
||||
lanțul `_frm_child.vcx -> _frm_base.vcx -> _baza.vcx` și controalele `_grdrow`/`_optiongrup`/`_label`.
|
||||
|
||||
## Ce s-a testat (cele 7 puncte din brief, toate acoperite)
|
||||
|
||||
1. **Instanțiere fără eroare** — 6 instanțe create (T1, T2, T2b, T3, T4, T5, T6), pe seturi diferite
|
||||
de `tvd`/`trul` (Modificare+Adaugare+Semnalare+N-A, document identic, doar N-A/Semnalare), toate
|
||||
verificate `Vartype(loForm)=='O'` — PASS pe toate.
|
||||
2. **`propunere_afisata` identică camp-cu-camp cu `propunere_sincronizare`** (T1) — comparație
|
||||
completă (`id_articol`, `denumire`, `codmat`, `cantitate_veche/noua`, `pret_vechi/nou`,
|
||||
`actiune`, `motiv`) prin helper dedicat `VerificaCursoareIdentice`, 0 nepotriviri pe 4 rânduri.
|
||||
3. **`But_termin1.Enabled`** — `.T.` cu Modificare+Adaugare prezente (T1), `.F.` pe propunere goală
|
||||
(document identic, T2) și `.F.` pe propunere cu doar N-A/Semnalare (T2b) — ambele variante cerute.
|
||||
4. **Comutarea direcției** (T3) — `optDirectie.Value=2` + `.Click()` (apel direct de metodă, fără
|
||||
input real): `propunere_afisata` s-a reumplut la tot 3 rânduri (nu dublat), rolurile s-au
|
||||
inversat corect (900 Adaugare→Semnalare, 1000 Semnalare→Adaugare, 800 rămas Modificare) —
|
||||
exact regresia pe care corecția (`rec_s4b_etapa2.md`, punctul 2) o vizează.
|
||||
5. **`inainte_de_do_termin()`** (T4) — întoarce `.T.`, aplică efectiv în `tvd` (800 modificat
|
||||
4/16, 900 adăugat ca linie nouă 1/50), `dummyform.nAdaugaCalls==1`, `nBaraCalls>=1`.
|
||||
6. **`oFormArticole` rămas `.F.`** (T5) — nicio eroare, garda `Vartype(...)=='O'` funcționează,
|
||||
REPLACE-ul de bază tot se aplică pe `tvd` (4/16) fără `toForm`.
|
||||
7. **Unload/Release** (T6) — `propunere_afisata` deschisă înainte, închisă după `.Release()`.
|
||||
|
||||
Nicio asercțiune pe coloane de grid, lățimi sau `DynamicForeColor` — confirmat inutilizabil sub
|
||||
`-A -T` (nu a fost nevoie: dialogul se instanțiază fără eroare fatală chiar și fără materializarea
|
||||
gridului, deci n-a trebuit mutat nimic în harness-ul UI vizibil).
|
||||
|
||||
## Zgomot de mediu — NU e defect în clasa nouă
|
||||
|
||||
La fiecare `CreateObject`, `ON ERROR` a prins ~20 erori în cascadă în `ACTUALIZEAZA_DREPTURI`
|
||||
(variabile `gcAcces`, `lcProp`, `lcButoane`, `lcButon`, `lnPf` negăsite) urmate de
|
||||
`Object GOAPP is not found` în `_frmbase.Init`. Astea vin din codul de bază moștenit
|
||||
(`_frmbase`/`_baza.vcx`, folosit de **toate** formularele aplicației, nu doar de
|
||||
`frm_sincronizare_articole`) — gestionarea drepturilor pe butoane, care citește global `gcAcces` și
|
||||
`goApp`, ambele setate normal la login-ul real în aplicație. Harness-ul acestui test nu face login
|
||||
(fără Oracle, cum a cerut sarcina), deci aceste globale lipsesc. `frm_sincronizare_articole` **nu
|
||||
suprascrie** `ACTUALIZEAZA_DREPTURI` — nu are nicio metodă cu acest nume în `omodificari.vc2`.
|
||||
`ON ERROR` înghite fiecare eroare și continuă linie cu linie (comportament VFP normal la eroare
|
||||
needivizată), iar `ConstruiesteEnumerare()` din `Init` rulează *după* `DoDefault()` și suprascrie
|
||||
explicit `But_termin1.Enabled` — de-aia toate cele 35 de asercțiuni ies corect în ciuda zgomotului.
|
||||
Nu e raportat ca defect (nu ține de clasa nouă), doar semnalat ca limitare de mediu a harness-ului
|
||||
fără Oracle.
|
||||
|
||||
## Ce nu s-a putut testa
|
||||
|
||||
Nimic din cele 7 puncte cerute nu a fost blocat. Netestat (în afara scopului acestei sarcini):
|
||||
comportamentul vizual real al gridului (coloane/culori — cere harness UI vizibil, nu a fost necesar
|
||||
aici) și `.Show()` modal (deliberat neatins, ca să nu rămână vreun `vfp9.exe` blocat pe un dialog
|
||||
modal fără input real).
|
||||
@@ -1,214 +0,0 @@
|
||||
# S4b - documente reale cu divergenta (pentru testarea pe ecran a dialogului nou)
|
||||
|
||||
Cercetare read-only pe `MARIUSM_AUTO`. Niciun `INSERT`/`UPDATE`/`DELETE`, niciun `COMMIT`. Doar
|
||||
`SELECT` prin `goExecutor.oExecute` si apeluri directe la `ConstruiestePropunereSincronizare('RUL_SURSA')`
|
||||
(`COMUN\programe\ofacturare_editare.prg:572`), fara UI, fara scriere in `tvd`/`trul` reale (cursoare
|
||||
in memorie, aruncate dupa fiecare document). Niciun proces `vfp9.exe` ramas viu la finalul cercetarii
|
||||
(verificat cu `tasklist`, inainte si dupa fiecare rulare).
|
||||
|
||||
## Metoda
|
||||
|
||||
1. **Prefiltru SQL aproximativ** (nu verdictul final - doar ca sa nu testez document cu document
|
||||
toata baza), doua interogari peste `vanzari`/`vrul_tot`/`vvanzari_articole` (sters=0, neproforma):
|
||||
- **candidati A**: `id_articol` prezent doar in rulaj sau doar in articolele facturii (seturi
|
||||
diferite, `MINUS` in ambele sensuri) - candidati pentru Adaugare/Semnalare.
|
||||
- **candidati B**: articole comune la care cantitatea agregata difera (`SUM(cant + IIF(id_tip_rulaj<>3,cante,0))`
|
||||
din `vrul_tot`, sters exclus, vs `SUM(cantitate)` din `vvanzari_articole`, sters exclus) -
|
||||
candidati pentru Modificare.
|
||||
- Reunite fara duplicate: **286 documente candidat** din toata istoria bazei.
|
||||
2. **Verdictul real**: pentru fiecare din cei 286 candidati, incarcare completa a documentului exact
|
||||
ca in fluxul de editare (`IncarcaCursoareModificareNota` -> `IncarcaVanzareDinNota` ->
|
||||
`IncarcaArticoleFactura`), apoi apel direct `ConstruiestePropunereSincronizare('RUL_SURSA')` si
|
||||
citirea cursorului rezultat. **Toti cei 286 candidati au fost testati** (nu doar un esantion).
|
||||
3. **Sweep suplimentar, exhaustiv, fara prefiltru**, pe toate documentele din luna/anul curent
|
||||
(`gnAn/gnLuna = 2026/8`) care au rulaje - 5 documente in total - ca sa acopar si un eventual caz
|
||||
"doar diferenta de pret, cantitate si set de articole identice", pe care prefiltrul de mai sus
|
||||
nu-l prinde daca articolul respectiv e singurul din document. Confirmare: aceleasi 2 documente
|
||||
gasite si de acest sweep exhaustiv (fara documente noi ratate de prefiltru in luna curenta).
|
||||
|
||||
Comanda de reprodus (scripturile raman in scratchpad, nu in proiect):
|
||||
```
|
||||
"C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe" -A -T "<script>.prg"
|
||||
```
|
||||
Scripturi si loguri (in scratchpad-ul acestei sesiuni, nu in `docs/`):
|
||||
`rec_s4b_finder.prg` / `rec_s4b_finder_log.txt` (cei 286 candidati, toata istoria),
|
||||
`rec_s4b_finder_luna_curenta.prg` / `_log.txt` (sweep exhaustiv luna curenta),
|
||||
`rec_s4b_finder_idfix.prg` / `_log.txt` (diagnostic id_articol, mai jos).
|
||||
|
||||
## Rezultat
|
||||
|
||||
**Din 286 candidati testati cu functia reala, 21 de documente produc cel putin o linie
|
||||
Modificare/Adaugare.** Niciunul din cele 21 nu combina Modificare **si** Adaugare **si** Semnalare
|
||||
in acelasi document - cel mai bogat caz gasit are Modificare + doua/trei linii N-A (context, nu
|
||||
aplicabile). Zero documente cu Semnalare-efectiv-in-cursor au aparut printre cele 21 (Semnalare cere
|
||||
articol prezent doar in `tvd`, stocat - in datele astea, articolele "doar in tvd" gasite erau toate
|
||||
nestocate, deci cad pe N-A inaintea verificarii de Semnalare).
|
||||
|
||||
**Foarte important pentru testarea pe ecran**: fluxul real de editare (`do_editare_factura` /
|
||||
`afisjurcom.do_modifica`) accepta la editare **doar documente din luna/anul curent al sesiunii**
|
||||
(garda `(an*12+luna) = (gnAn*12+gnLuna)`, verificata in `test_s8_matrice_surse.prg`). Azi
|
||||
(11.08.2026), `gnAn/gnLuna = 2026/8`. Din cele 21 documente cu Modificare/Adaugare, **doar 2 sunt in
|
||||
luna curenta** - restul de 19 nu se pot deschide acum prin formularul real (ar trebui alt `gnAn/gnLuna`
|
||||
de sesiune sau alta data de sistem ca sa fie editabile).
|
||||
|
||||
### Cele 2 documente editabile ACUM (luna curenta, 2026/8)
|
||||
|
||||
**#1 - id_vanzare=1050, cod=1140895, tip=1, id_fact=8009660, an/luna=2026/8** (cel mai bogat dintre
|
||||
cele doua - 2 linii in propunere)
|
||||
|
||||
| id_articol | denumire | codmat | cant_veche | cant_noua | pret_vechi | pret_nou | actiune | motiv |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| 3598545102 | ACOPERIRE STILP B IVECO | IV93900901 | 2 | 0 | 121.0100 | 0 | Modificare | |
|
||||
| 315554536 | ACOPERIRE FAR VOLVO FH12 | 11.00003 | 1 | 2 | 302.5000 | 302.5000 | N-A | Mai multe randuri RUL active pe acelasi articol, verificati manual |
|
||||
|
||||
**#2 - id_vanzare=1052, cod=1140921, tip=22 (aviz), id_fact=8009677, an/luna=2026/8**
|
||||
|
||||
| id_articol | denumire | codmat | cant_veche | cant_noua | pret_vechi | pret_nou | actiune | motiv |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| 3598545102 | ACOPERIRE STILP B IVECO | IV93900901 | 1 | 0 | 23.1100 | 0 | Modificare | |
|
||||
|
||||
### Constatare suplimentara, verificata pe date - overflow `id_articol` pe articolul IV93900901
|
||||
|
||||
`id_articol` real (din `nom_articole`, verificat cu `select id_articol from nom_articole where
|
||||
codmat = 'IV93900901'`) = **3598545102** - depaseste limita reprezentabila de campul `id_articol I`
|
||||
(Integer VFP, 4 octeti, max 2147483647) din cursorul `propunere_sincronizare`
|
||||
(`CREATE CURSOR propunere_sincronizare (id_articol I, ...)`, `ofacturare_editare.prg:587`). Verificat
|
||||
direct: `STR(id_articol,15)` pe randul citit din `propunere_sincronizare` dupa
|
||||
`ConstruiestePropunereSincronizare` tot arata markerul de depasire VFP (`***************`), nu
|
||||
valoarea - deci valoarea stocata in cursor e trunchiata/deja corupta, nu doar o problema de afisare
|
||||
in scriptul meu de logare (am verificat cu doua latimi diferite, 15 si 20, acelasi rezultat).
|
||||
|
||||
Consecinta verificata in cod (nu doar presupusa): `AplicaSincronizareArticole` citeste
|
||||
`lnIdArticol = id_articol` direct din `propunere_sincronizare` (linia 790) si il foloseste in
|
||||
`AplicaModificareTvd`/`AplicaAdaugareTvd`/`AplicaModificareTrul` pentru `LOCATE FOR id_articol =
|
||||
m.tnIdArticol` pe `tvd`/`trul` (liniile 836, 874, 910) - cursoare unde `id_articol` vine direct din
|
||||
Oracle, deci pastreaza valoarea reala (3598545102). Cu valoarea din campul `I` deja trunchiata,
|
||||
`LOCATE` nu are cum sa gaseasca randul corect pe acest articol. Ambele documente editabile acum
|
||||
(#1 si #2 de mai sus) au randul lor de Modificare exact pe acest articol - deci propunerea s-ar
|
||||
afisa corect in dialogul nou, dar `AplicaSincronizareArticole` ar putea sa nu scrie efectiv
|
||||
modificarea pe acest rand quand se apasa "Aplica". Nu am testat efectiv `AplicaSincronizareArticole`
|
||||
pe date reale (ar fi scriere, chiar daca doar in cursor in memorie, si nu era ceruta cercetarea de
|
||||
aplicare) - constatarea e din citirea codului + valoarea reala confirmata din Oracle, nu din rulare.
|
||||
|
||||
## Alte documente cu Modificare/Adaugare, NU editabile acum (alta luna/an) - pentru context
|
||||
|
||||
Cele mai "curate" (fara efectul de trunchiere de mai sus, sau cu cantitate neschimbata si doar pretul
|
||||
diferit intre doua valori nenule - nu artefact de zero):
|
||||
|
||||
**id_vanzare=943, cod=1140122, tip=-3, id_fact=8007141, an/luna=2022/4** - singurul document din cele
|
||||
21 cu Adaugare (nu Modificare):
|
||||
|
||||
| id_articol | denumire | codmat | cant_veche | cant_noua | pret_vechi | pret_nou | actiune | motiv |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| (overflow, vezi mai sus) | ADAPTOR | SATACADU1 | 0 | 1 | 0 | 0 | Adaugare | |
|
||||
|
||||
**id_vanzare=631, cod=1138622, tip=3, id_fact=8001320, an/luna=2014/1** - singurul caz din toata
|
||||
cautarea cu Modificare "curata": cantitate **neschimbata** (1->1), doar pretul difera intre doua
|
||||
valori nenule:
|
||||
|
||||
| id_articol | denumire | codmat | cant_veche | cant_noua | pret_vechi | pret_nou | actiune | motiv |
|
||||
|---|---|---|---|---|---|---|---|---|
|
||||
| (overflow, vezi mai sus) | ACOPERIRE STILP B IVECO | IV93900901 | 1 | 1 | 24.9200 | 112.1600 | Modificare | |
|
||||
| 315554536 | ACOPERIRE FAR VOLVO FH12 | 11.00003 | 10 | 20 | 124 | 558 | N-A | Mai multe randuri RUL active pe acelasi articol, verificati manual |
|
||||
|
||||
**id_vanzare=953, cod=1140144, tip=23, id_fact=8007201, an/luna=2022/5** si **id_vanzare=887,
|
||||
cod=1139941, tip=23, id_fact=8006845, an/luna=2021/12** - alt tipar de Modificare curata pe cantitate
|
||||
(neschimbata), doar pretul difera (articol "COCA COLA 0.33L", fara overflow de id_articol):
|
||||
|
||||
| document | id_articol | cant_veche | cant_noua | pret_vechi | pret_nou | actiune |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 953 | (overflow diferit, neverificat individual) | 1 | 1 | 11.9000 | 0 | Modificare |
|
||||
| 887 | (overflow diferit, neverificat individual) | 1 | 1 | 3.5100 | 0 | Modificare |
|
||||
|
||||
Restul de 14 documente (id_vanzare 976, 937, 793, 682, 681, 1006, 985, 905, 881, 695, 686, 685, 1013,
|
||||
1014) urmeaza acelasi tipar predominant: un singur articol RUL cu un rand `id_tip_rulaj=3` (diferenta
|
||||
de pret) al carui `cant` propriu e 0 - agregarea E.3 exclude `cante` pentru randurile tip 3, deci
|
||||
`cant_articol`/`val_articol` ies 0, iar propunerea arata "Modificare, cantitate/pret -> 0". E un
|
||||
rezultat corect al formulei documentate (nu o eroare de interogare), dar nu e un exemplu "tipic" de
|
||||
sincronizare cantitate/pret - lista completa, cu toate liniile, e in
|
||||
`rec_s4b_finder_log.txt` (liniile cu `GASIT`).
|
||||
|
||||
## Ce nu am gasit / limite ale cautarii
|
||||
|
||||
- **Zero documente cu Modificare + Adaugare in acelasi document**, din cei 286 candidati testati
|
||||
(acoperire 100% pe cele doua euristici de prefiltru).
|
||||
- **Zero documente cu actiune efectiv Semnalare** in cursorul rezultat, din aceiasi 286.
|
||||
- Prefiltrul SQL (candidati A/B) **nu garanteaza acoperire completa**: un document la care UN SINGUR
|
||||
articol difera **doar** prin pret (cantitate identica) si care e si singurul articol divergent din
|
||||
acel document (fara alt articol cu set/cantitate diferita in acelasi document care sa-l fi adus in
|
||||
lista de candidati) ar fi ratat de ambele euristici. Nu am facut un scan exhaustiv pe pret peste
|
||||
toata istoria (ar fi insemnat sute de mii de documente testate cu functia reala, cost prea mare
|
||||
pentru scopul cercetarii) - doar pe luna curenta (5 documente, exhaustiv, fara ratari).
|
||||
- Nu am testat `AplicaSincronizareArticole` (scrierea efectiva in `tvd`/`trul` in memorie) pe niciun
|
||||
document real - cercetarea ceruta a fost doar pentru `ConstruiestePropunereSincronizare`.
|
||||
|
||||
## Verificari de siguranta
|
||||
|
||||
- Toate interogarile au fost `SELECT` prin `goExecutor.oExecute`; niciun `INSERT`/`UPDATE`/`DELETE`,
|
||||
niciun `goExecutor.oExecuta` (DML) apelat in aceasta cercetare.
|
||||
- Niciun `COMMIT`/`ROLLBACK` - nicio tranzactie deschisa (nu s-a apelat `MyDeschideTranzactie`).
|
||||
- Niciun formular deschis, nicio tasta/click injectat.
|
||||
- `tasklist` verificat inainte si dupa fiecare rulare `vfp9.exe -A -T`: zero procese `vfp9.exe` ramase
|
||||
vii la finalul cercetarii.
|
||||
|
||||
## Precizia coloanelor identificator
|
||||
|
||||
Interogare `ALL_TAB_COLUMNS`, read-only, pe coloanele identificator din cursoarele de editare a
|
||||
facturii. Script: `rec_s4b_precizie_coloane.prg`, log: `rec_s4b_precizie_coloane_log.txt`.
|
||||
|
||||
| tabela/view | coloana | tip Oracle | precizie/scala |
|
||||
|---|---|---|---|
|
||||
| VVANZARI_ARTICOLE | ID_VANZARE / ID_VANZARE_DET / ID_ARTICOL / ID_JTVA_COLOANA / ID_VALUTA / ID_VANZARE_SET | NUMBER | 10/0 |
|
||||
| VVANZARI_ARTICOLE | ID_GESTIUNE | NUMBER | 20/0 |
|
||||
| VVANZARI_ARTICOLE | TAXCODE | NUMBER | 6/0 |
|
||||
| VVANZARI_ARTICOLE | STERS | NUMBER | 1/0 |
|
||||
| NOM_ARTICOLE | ID_ARTICOL | NUMBER | 20/0 |
|
||||
| VRUL_TOT | ID_ARTICOL / ID_TIP_RULAJ / ID_VALUTA | NUMBER | 10/0 |
|
||||
| VANZARI_DETALII | ID_VANZARE (MARIUSM_AUTO) / ID_VANZARE_DET / ID_ARTICOL / ID_JTVA_COLOANA / ID_VALUTA / ID_VANZARE_SET | NUMBER | 10/0 |
|
||||
| VANZARI_DETALII | ID_VANZARE (schema ACN) | NUMBER | 20/0 (alta schema, acelasi nume de tabela) |
|
||||
| VANZARI_DETALII | ID_GESTIUNE | NUMBER | 20/0 |
|
||||
|
||||
**Valoare maxima efectiva in date + randuri care depasesc 2147483647 (max VFP `I`, Integer 4 octeti):**
|
||||
|
||||
| coloana | max efectiv | randuri > 2147483647 | total randuri |
|
||||
|---|---|---|---|
|
||||
| NOM_ARTICOLE.ID_ARTICOL | 4294511702 | **5795** | 6457 (89.8%) |
|
||||
| VRUL_TOT.ID_ARTICOL | 4294511700 | **6432** | 10293 (62.5%) |
|
||||
| VANZARI_DETALII.ID_VANZARE_DET | 1609 | 0 | 1362 |
|
||||
| VANZARI_DETALII.ID_VANZARE | 1060 | 0 | 1362 |
|
||||
|
||||
**Concluzie factuala**: `id_articol` e afectat masiv (nu e un caz izolat) - aproape 9 din 10 articole
|
||||
din `NOM_ARTICOLE` si peste 6 din 10 randuri din `VRUL_TOT` au `id_articol` peste limita unui camp
|
||||
VFP `I`. Valorile maxime (4294511700-4294511702) sunt foarte aproape de 2^32 (4294967296), consistent
|
||||
cu un id generat in intervalul unsigned pe 32 de biti, nu cu o secventa Oracle standard. Precizia
|
||||
declarata in Oracle (`NUMBER(10)` sau `NUMBER(20)`) e suficienta pentru aceste valori - problema e
|
||||
strict de partea VFP (campul `I`), nu de precizia coloanei Oracle. `id_vanzare`/`id_vanzare_det`,
|
||||
in schimb, sunt mici (sub 2000) in datele curente si nu au niciun rand peste limita - nu inseamna
|
||||
insa ca schema le limiteaza (ambele sunt tot `NUMBER(10)`/`NUMBER(20)` dupa schema, fara CHECK
|
||||
constraint vizibil aici care sa impuna un plafon sub 2^31).
|
||||
|
||||
## Restul campurilor I din tvd
|
||||
|
||||
Cursorul `tvd` (`CreeazaCursorArticoleGol`, `ofacturare_editare.prg:276`) mai declara `I` (Integer
|
||||
VFP, 4 octeti, max 2147483647) pe: `id_gestiune`, `id_valuta`, `id_jtva_coloana`, `taxcode`, `sters`,
|
||||
`id_vanzare_set` (plus `id_vanzare`/`id_vanzare_det`, deja verificate mai sus - fara depasiri).
|
||||
Toate cele 6 coloane cerute exista in `VVANZARI_ARTICOLE` sub numele exact. Script:
|
||||
`rec_s4b_restul_campuri_i.prg`, log: `rec_s4b_restul_campuri_i_log.txt`.
|
||||
|
||||
| coloana | sursa | max efectiv | randuri > 2147483647 |
|
||||
|---|---|---|---|
|
||||
| ID_GESTIUNE | VVANZARI_ARTICOLE (facturi existente) | 23 | 0 din 1362 |
|
||||
| ID_GESTIUNE | NOM_GESTIUNI (nomenclator complet, `NUMBER(5,0)`) | 29 | 0 din 28 |
|
||||
| ID_VALUTA | VVANZARI_ARTICOLE | 3 | 0 din 1362 |
|
||||
| ID_JTVA_COLOANA | VVANZARI_ARTICOLE | 188 | 0 din 1362 |
|
||||
| ID_VANZARE_SET | VVANZARI_ARTICOLE | 4 | 0 din 1362 |
|
||||
| TAXCODE | VVANZARI_ARTICOLE | 310354 | 0 din 1362 |
|
||||
| STERS | VVANZARI_ARTICOLE | 1 | 0 din 1362 |
|
||||
|
||||
**Raspuns la intrebare**: nu, niciunul din aceste 6 campuri nu are, azi, vreo valoare peste
|
||||
2147483647, si niciunul nu e nici macar apropiat de limita (cel mai mare, `TAXCODE`, e la 310354 -
|
||||
de ~6900 de ori sub prag). Spre deosebire de `id_articol` (`NUMBER(10)`/`NUMBER(20)` cu valori reale
|
||||
pana la ~4.29 miliarde), `id_gestiune` are un plafon de schema explicit jos: `NOM_GESTIUNI.ID_GESTIUNE`
|
||||
e declarata `NUMBER(5,0)` - max teoretic posibil 99999, cu 4-5 ordine de marime sub limita `I`. Nu
|
||||
exista un risc plauzibil pe termen scurt pentru niciunul din aceste 6 campuri; `id_articol` ramane
|
||||
singurul camp `I` din `tvd` cu depasire reala confirmata in date.
|
||||
@@ -1,175 +0,0 @@
|
||||
# S4b etapa 1 - contractul ConstruiestePropunereSincronizare/AplicaSincronizareArticole
|
||||
|
||||
Implementare, nu doar proiectare. Cod nou exclusiv in `COMUN\programe\ofacturare_editare.prg` (dupa
|
||||
`ScrieArticoleFacturaEditate`). Niciun `.vc2` atins - formularul si dialogul raman etapa 2, a altui
|
||||
agent. Baza: `docs\propunere_s4b_sincronizare.md` (proiectarea aprobata, punctele 2 si 4) si
|
||||
`docs\cercetare\rec_suma_act.md` E.3 (formula de agregare RUL, reutilizata neschimbata).
|
||||
|
||||
## Functii noi (publice, apelabile din etapa 2)
|
||||
|
||||
### `ConstruiestePropunereSincronizare(tcDirectie)`
|
||||
|
||||
Parametru: `tcDirectie` - accepta exact doua valori, `'RUL_SURSA'` (rulajul e sursa, actualizeaza
|
||||
articolele facturii) sau `'ARTICOLE_SURSA'` (articolele sunt sursa, actualizeaza rulajul). Orice alta
|
||||
valoare (inclusiv goala) cade pe `'RUL_SURSA'` - e implicit-ul recomandat de Marius (`docs\handoff_
|
||||
punct6_10082026_seara.md`, decizia 4).
|
||||
|
||||
Lasa deschis, READWRITE, cursorul `propunere_sincronizare`:
|
||||
|
||||
| camp | tip | continut |
|
||||
|---|---|---|
|
||||
| `id_articol` | I | cheia de matching (singura comuna intre `trul`/`tvd`) |
|
||||
| `denumire` | C(100) | preferata din `tvd` daca articolul exista acolo, altfel din `trul` |
|
||||
| `codmat` | C(30) | idem |
|
||||
| `cantitate_veche` | N(12,3) | valoarea curenta din cursorul-**tinta** |
|
||||
| `cantitate_noua` | N(12,3) | valoarea calculata din cursorul-**sursa** |
|
||||
| `pret_vechi` | N(14,4) | idem, pret unitar **cu TVA** |
|
||||
| `pret_nou` | N(14,4) | idem |
|
||||
| `actiune` | C(12) | `Modificare` / `Adaugare` / `Semnalare` / `N-A` |
|
||||
| `motiv` | C(80) | populat pe `N-A`/`Semnalare`, si pe `Adaugare` in `ARTICOLE_SURSA` |
|
||||
|
||||
Articolele **identice** intre sursa si tinta nu apar in cursor (fara zgomot, ca in propunere.md).
|
||||
|
||||
Retur logic: `.F.` doar cand `tvd`/`trul` nu sunt ambele deschise la apel (cursorul iese oricum creat,
|
||||
gol) - restul cazurilor (0 articole, document fara diferente) intorc `.T.` cu cursorul gol sau partial.
|
||||
|
||||
**Agregarea**, per `id_articol`, separat pe `trul` si pe `tvd`, doar randuri `Nvl(sters,0)<>1`:
|
||||
- RUL: `cant_articol = SUM(cant) + SUM(IIF(id_tip_rulaj<>3, cante, 0))`,
|
||||
`val_articol = SUM(cant*pretvtva) + SUM(IIF(id_tip_rulaj<>3, cante*pretvtva, 0))` (formula E.3
|
||||
neschimbata), `pret_articol = val_articol/cant_articol`.
|
||||
- tvd: `cant_articol = SUM(cantitate)`, `val_articol = SUM(valoare)` (coloana `tvd.valoare`, deja
|
||||
calculata cu TVA la incarcare/editare - **citita, nu recalculata** - `IncarcaArticoleFactura`,
|
||||
`ofacturare_editare.prg:318-320`, e chiar in acest fisier), `pret_articol = val_articol/cant_articol`.
|
||||
|
||||
**Actiune**, in ordinea exacta de verificare (prima conditie adevarata castiga):
|
||||
1. **Documentul e in valuta** (`tvanz.in_valuta<>0`, cand `tvanz` e deschis cu un rand) -> `N-A` pe
|
||||
**toate** articolele, indiferent de restul. *Decizie luata in aceasta implementare, nu era in
|
||||
propunere.md*: conversia RON<->valuta intre `trul.pretvtva` (presupus RON) si `tvd.pret` (in
|
||||
valuta documentului cand documentul e in valuta) nu a fost verificata pe date reale in bugetul
|
||||
alocat - mai sigur sa semnalez decat sa scriu o suma gresita. Fara aceasta garda, restul logicii
|
||||
(agregare, matching, Modificare/Adaugare/Semnalare) e neschimbata pe documente RON.
|
||||
2. **Mai multe randuri RUL active pe acelasi articol** (`nrand_rul>1`) -> `N-A`, chiar daca agregatul
|
||||
ar fi identic cu tinta (verificat explicit in test, caz A6: o pereche `id_tip_rulaj=3` a carei sume
|
||||
egaleaza exact `tvd`, tot N-A) - decizia lui Marius/propunere.md punctul 6, generalizata la ambele
|
||||
directii (nu doar la aplicare, ca in propunere.md sectiunea 4 - vezi "Diferente fata de propunere"
|
||||
mai jos).
|
||||
3. **Articol nestocat** (`tvd.in_stoc=0`, doar cand articolul exista in `tvd`) -> `N-A`.
|
||||
4. **Doar in sursa** -> `Adaugare`.
|
||||
5. **Doar in tinta** -> `Semnalare` (niciodata stergere automata).
|
||||
6. **In ambele, diferit** -> `Modificare`; identic -> nu apare in cursor.
|
||||
|
||||
## `AplicaSincronizareArticole(tcDirectie, toForm)`
|
||||
|
||||
Parametru nou fata de brief: **`toForm`, opus** (contractul descris mai jos, punctul "Ce ramane pe
|
||||
seama etapei 2"). Reconstruieste propunerea (apeleaza `ConstruiestePropunereSincronizare` intern -
|
||||
etapa 2 nu trebuie sa o apeleze separat inainte) si aplica **tot ce nu e `N-A`/`Semnalare`** - deci
|
||||
`Modificare` + `Adaugare`, decizia lui Marius ("fara selectie pe linie"). **Niciun `INSERT`/`UPDATE`
|
||||
Oracle** - doar `tvd`/`trul` in memorie.
|
||||
|
||||
Retur numeric: cate linii au fost efectiv aplicate (nu cate erau in propunere) - formularul il
|
||||
foloseste ca sa stie daca sa reactualizeze bara de totaluri/gridul.
|
||||
|
||||
- **`RUL_SURSA`**: `Modificare` -> `REPLACE tvd.cantitate/pret/discount_unitar` pe primul rand activ
|
||||
gasit pe articol, **pastrand `pret_cu_tva` existent pe rand** (pretul propus, mereu cu TVA per E.3,
|
||||
se converteste la fara-TVA prin `/proc_tvav` daca randul era asa) - decizie luata acum, nu era in
|
||||
propunere.md (care zicea doar "REPLACE ... pret_cu_tva WITH ..." fara sa spuna cu ce): am ales sa
|
||||
NU schimb convenția per-rand, ca sa nu inversez brusc semnificatia unei coloane pe care utilizatorul
|
||||
a vazut-o intr-un fel; `Adaugare` -> `toForm.AdaugaLinieTvdDinArticol()`, cu obiectul construit din
|
||||
`CreeazaPoArticolNouTvd` (tiparul cerut de brief), suprascris cu cantitate/pret din RUL,
|
||||
`preturi_cu_tva=1` (linie noua, fara conventie de pastrat), `cont`/`id_gestiune`/`proc_tvav` din
|
||||
randul RUL al articolului.
|
||||
- **`ARTICOLE_SURSA`**: `Modificare` -> `REPLACE` doar `cant` sau `cante` (dupa care era deja populat
|
||||
pe rand - verificat in test, caz C1) si `pretvtva`, pe singurul rand RUL activ (garantat unic, altfel
|
||||
propunerea a marcat N-A la pasul 2). Nu atinge `id_tip_rulaj`/conturi/campuri derivate
|
||||
(`valoare`/`tva`/etc.) - raman de recalculat de apelant daca e nevoie, in afara scopului acestei
|
||||
livrari. `Adaugare` -> **nu se aplica niciodata** (niciun rand RUL nou, decizia din propunere.md
|
||||
punctul 5.B).
|
||||
|
||||
## Ce ramane pe seama etapei 2 - contractul lui `toForm`
|
||||
|
||||
Am ales varianta **"primesc obiectul formular ca parametru"**, nu "duplic tiparul separat". Fara
|
||||
`toForm` (sau un obiect care nu implementeaza metodele), `AplicaSincronizareArticole` tot face
|
||||
`REPLACE`-ul de baza pe `tvd` pentru `Modificare` (verificat in test, caz B2), dar:
|
||||
- **nu recalculeaza `tvd.valoare`** (ramane cea veche pana la un recalcul extern);
|
||||
- **nu cheama `ActualizeazaBaraTotaluri`**;
|
||||
- **sare complet liniile `Adaugare`** (fara `toForm.AdaugaLinieTvdDinArticol`, nu exista alta cale sa
|
||||
adauge linia fara sa duplice acel helper).
|
||||
|
||||
Deci etapa 2 (butonul/dialogul din PAGE3) **trebuie sa apeleze `AplicaSincronizareArticole(tcDirectie,
|
||||
Thisform)`**, cu `Thisform` fiind instanta `frm_modific2024` deja incarcata (are ambele metode:
|
||||
`calculeaza_valori_articol`, `AdaugaLinieTvdDinArticol`). Contractul verificat prin `Pemstatus()`, nu
|
||||
presupus - un obiect fara aceste metode e tratat exact ca "fara toForm".
|
||||
|
||||
## Diferente fata de `propunere_s4b_sincronizare.md` - de confirmat cu Marius/etapa 2
|
||||
|
||||
1. **Documentele in valuta sunt N-A pe tot** (mai sus, punctul 1 al ordinii de actiune) - propunere.md
|
||||
nu mentiona deloc valuta pentru S4b. Scop deliberat restrans: fara o verificare pe un document real
|
||||
in valuta CU randuri RUL, nu am vrut sa livrez o conversie neverificata. Daca Marius vrea si
|
||||
documentele in valuta acoperite, e nevoie de o cercetare separata (confirmarea daca `trul.pretvtva`
|
||||
e RON sau in valuta proprie a randului RUL - `VRUL_TOT` are propriile `CURS`/`ID_VALUTA` per rand,
|
||||
verificat prin `DESCRIBE`, dar nu s-a confirmat ce inseamna practic pentru `PRETVTVA`).
|
||||
2. **"Mai multe randuri RUL active" e N-A in ambele directii, la nivelul propunerii** (nu doar la
|
||||
aplicarea `ARTICOLE_SURSA`, cum sugera propunere.md sectiunea 4) - generalizare ceruta explicit de
|
||||
briefing-ul acestei sarcini ("niciodata alegere automata a randului", listat ca regula a
|
||||
`ConstruiestePropunereSincronizare`, nu doar a aplicarii). Efect: pe un document cu perechi
|
||||
`id_tip_rulaj=3` (diferenta de pret la marfa/produse la pret de vanzare, `rec_suma_act.md` E.1),
|
||||
articolul respectiv ram**a** mereu N-A, chiar daca suma agregata (E.3) ar fi corecta si identica -
|
||||
propunerea nu ofera Modificare/Adaugare automata pe acele articole, doar afisare informativa.
|
||||
3. **`tvd` cu mai multe randuri active pe acelasi articol nu are o garda separata** - `AplicaModificare
|
||||
Tvd` scrie pe **primul** rand activ gasit. Cazul e rar (articol adaugat de doua ori manual pe
|
||||
aceeasi factura) si n-a fost cerut explicit in briefing; il semnalez ca limitare cunoscuta, nu l-am
|
||||
tratat ca sa nu extind scopul peste ce s-a cerut.
|
||||
|
||||
## Teste
|
||||
|
||||
`COMUN\utile\Teste\editare_factura\test_s4b_sincronizare.prg`, model `test_s5_validari_articole.prg`.
|
||||
Complet headless, **fara Oracle** - nici `ConstruiestePropunereSincronizare`, nici
|
||||
`AplicaSincronizareArticole` nu ating `goExecutor`, deci testul nu are nevoie de `test_init_env_auto`/
|
||||
conexiune - doar `SET PROCEDURE TO ofacturare_editare.prg` si `gnPC` setat manual. `tvd`/`trul` sunt
|
||||
construite direct in test (helpere `AdaugaTvd`/`AdaugaTrul`); `trul` e o structura minimala (doar
|
||||
campurile citite de cod), nu cele 218 coloane reale ale `VRUL_TOT`.
|
||||
|
||||
Cazuri acoperite (sectiunea A - `ConstruiestePropunereSincronizare`, cate un caz pe ambele directii
|
||||
unde se aplica): identic (A1), modificare cu valori inversate corect intre directii (A2), doar-in-
|
||||
sursa/doar-in-tinta -> Adaugare/Semnalare cu roluri schimbate intre directii (A3/A4), articol nestocat
|
||||
(A5), mai multe randuri RUL active - N-A chiar cand agregatul ar fi identic (A6), randuri `sters`
|
||||
excluse din agregare pe ambele cursoare (A7), document in valuta -> N-A pe tot (A8), tvd/trul lipsa la
|
||||
apel (A9). Sectiunea B (`AplicaSincronizareArticole`, `RUL_SURSA`): aplicare completa cu `toForm`
|
||||
(Modificare + Adaugare, verificate valorile scrise in `tvd` si apelurile pe test-double, semnalare/N-A
|
||||
neatinse - B1), **fara** `toForm` (Adaugare sarita fara eroare, Modificare tot se aplica - B2),
|
||||
pastrarea conventiei `pret_cu_tva=0` cu conversia pretului propus (B3). Sectiunea C
|
||||
(`AplicaSincronizareArticole`, `ARTICOLE_SURSA`): `cant` vs `cante` pastrat dupa care era populat pe
|
||||
rand, Adaugare niciodata scrisa in `trul` (C1).
|
||||
|
||||
`test-double`-ul `dummyform` (definit la finalul fisierului, tipar identic cu `dummyexecutor` din
|
||||
`test_s5_validari_articole.prg`) oglindeste EXACT formula din `calculeaza_valori_articol`/
|
||||
`AdaugaLinieTvdDinArticol` - verifica ca `AplicaSincronizareArticole` cheama metodele corecte cu
|
||||
argumentele corecte, fara sa deschida formularul real sau sa atinga vreun `.vc2`.
|
||||
|
||||
**Capcana gasita si reparata in acest bloc**: comparatii `==` intre un camp `Character` de latime
|
||||
fixa (`actiune`, C(12)) si un literal mai scurt (`'Modificare'`) esueaza mereu din cauza spatiilor de
|
||||
umplere din dreapta - VFP `==` e comparatie stricta, nu trece prin `SET EXACT`. Aparea atat in codul
|
||||
de productie (`AplicaSincronizareArticole`, filtrul `SCAN FOR Inlist(actiune,...)` si `DO CASE`), cat
|
||||
si in asertiunile testului. Reparat cu `Alltrim()` pe partea citita din camp, in ambele fisiere.
|
||||
|
||||
**Cifra din log** (`test_s4b_sincronizare_log.txt`, rulare `vfp9.exe -A -T`):
|
||||
|
||||
```
|
||||
REZULTAT: 35 PASS / 0 FAIL
|
||||
```
|
||||
|
||||
Toate testate (headless, cursoare construite in test) - niciun caz "doar analizat static". Nu s-a
|
||||
verificat pe un document real din Oracle (nu era ceruta si nici necesara pentru logica pura), si nici
|
||||
comportamentul pe un document real in valuta (vezi punctul 1 din "Diferente fata de propunere" -
|
||||
scop restrans deliberat).
|
||||
|
||||
## Ce lipseste pentru punctul #6 complet (etapa 2, alt agent)
|
||||
|
||||
1. Butonul `cmdSincronizeazaArticole` in PAGE3 si toggle-ul de `Enabled` in `Show()`
|
||||
(`omodificari.vc2`, punctul 1 din propunere.md).
|
||||
2. Dialogul modal `frm_sincronizare_articole` (radio pe directie, grid needitabil pe
|
||||
`propunere_sincronizare`, Aplica/Renunta) - punctele 2-3 din propunere.md.
|
||||
3. Verificarea la salvare (`inainte_de_do_termin`) care ofera enumerarea si permite salvarea mai
|
||||
departe fara sincronizare - decizia 2 a lui Marius (`docs\handoff_punct6_10082026_seara.md`).
|
||||
4. Apelul `AplicaSincronizareArticole(tcDirectie, Thisform)` din dialog, la "Aplica", si reactualizarea
|
||||
gridului/barei de totaluri folosind numarul de linii aplicate intors.
|
||||
@@ -1,93 +0,0 @@
|
||||
# S5 — agatarea scrierii de articole in cele doua puncte de intrare
|
||||
|
||||
Implementare, 09.08.2026 seara. Atinse: `COMUN\clase\ofacturare_comun.vc2`,
|
||||
`COMUN\clase\comun.vc2` (+ write-back in binare). Niciun alt fisier atins, niciun commit.
|
||||
|
||||
## Ce s-a facut
|
||||
|
||||
In ambele metode, imediat dupa `Endif`-ul care inchide apelul
|
||||
`pack_contafin.finalizeaza_modificare_nota` si inainte de `do_inchide_tranzactie` (tranzactia
|
||||
manuala e inca deschisa acolo):
|
||||
|
||||
- `frm_facturi.do_editare_factura` — `ofacturare_comun.vc2:3828-3830` (intre vechile `:3827`/`:3828`,
|
||||
deplasate cu +3 linii de insertie).
|
||||
- `afisjurcom.do_modifica` — `comun.vc2:2491-2493` (intre vechile `:2490`/`:2538`; inserat imediat
|
||||
dupa `Endif`, inaintea blocului de cod comentat existent, nedeplasat).
|
||||
|
||||
Bloc identic in ambele (o singura conditie, fara `Else`, ca sa nu strice `lnSucces` cand garda nu
|
||||
trece):
|
||||
|
||||
```foxpro
|
||||
If lnSucces > 0 And "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) And Used('tvanz') And Reccount('tvanz') = 1
|
||||
lnSucces = Iif(ScrieArticoleFacturaEditate(tvanz.id_vanzare), 1, -1)
|
||||
Endif
|
||||
```
|
||||
|
||||
`ScrieArticoleFacturaEditate` (definita de alt agent in `COMUN\programe\ofacturare_editare.prg:468`,
|
||||
verificata la momentul scrierii apelului) intoarce logic si include deja pasul de recalcul
|
||||
(`pack_facturare.recalculeaza_totaluri_vanzari`) — nu mai e nevoie de un apel separat din VFP, cum
|
||||
sugera o formulare anterioara a planului.
|
||||
|
||||
## De ce asa
|
||||
|
||||
- `-1`, nu `0`, la esec — garda de commit e `Iif(lnSucces<0,2,1)`.
|
||||
- Garda pe `"OFACTURARE_EDITARE" $ Upper(Set("Procedure"))` pusa si in `ofacturare_comun.vc2`
|
||||
(desi acolo `ofacturare_editare.prg` e mereu inregistrat, ROAFACTURARE fiind singurul consumator),
|
||||
pentru simetrie cu `comun.vc2`, unde e obligatorie (fisierul nu exista in `SET PROCEDURE` pe
|
||||
ROACONT/ROAGEST).
|
||||
- `Used('tvanz') And Reccount('tvanz') = 1` inainte de a citi `tvanz.id_vanzare` — formularul e deja
|
||||
`Release`-uit la acest punct, dar cursorul supravietuieste; fara garda, `tvanz.id_vanzare` ar arunca
|
||||
eroare de alias daca pagina de articole n-a fost activa.
|
||||
- Un singur `If` fara `Else`: cand oricare conditie e falsa, blocul se sare complet si `lnSucces`
|
||||
ramane neschimbat (comportamentul de dinainte de modificare).
|
||||
|
||||
## Cens de octeti (inainte / dupa, identic pe caracterele >=0x80)
|
||||
|
||||
| Fisier | octeti >0x7F inainte | octeti >0x7F dupa | `EF BF BD` | LF izolat |
|
||||
|---|---|---|---|---|
|
||||
| `ofacturare_comun.vc2` | 12 | 12 | 0 | 0 |
|
||||
| `comun.vc2` | 1 | 1 | 0 | 0 |
|
||||
|
||||
Editare facuta byte-safe (PowerShell, round-trip `GetEncoding(1252)`, text nou strict ASCII) —
|
||||
niciun octet existent atins.
|
||||
|
||||
## Write-back
|
||||
|
||||
Ambele `txt2vcx.ps1 -AllowComun` — fidelity-check trecut, binare cu mtime nou:
|
||||
- `ofacturare_comun.vcx`/`.vct` — OK.
|
||||
- `comun.vcx`/`.vct` — OK (fisier mare, ~330 KB text; write-back a durat >120s, rulat in fundal,
|
||||
finalizat cu succes).
|
||||
|
||||
## Testare
|
||||
|
||||
**Testul de garda** (`test_page3_articole.prg`, ultimul caz din suita: scoate
|
||||
`ofacturare_editare.prg` din `SET PROCEDURE`, verifica `PageCount=2`): **PASS**. Confirma ca in
|
||||
ROACONT/ROAGEST, unde fisierul nu e inregistrat, blocul nou e complet inert — nu doar prin gardele
|
||||
proprii, ci si prin faptul ca `ScrieArticoleFacturaEditate` nici nu ar fi rezolvabila acolo.
|
||||
|
||||
**Regresie**, rulata 09.08.2026 ~22:46-22:48, sub watchdog (`-AutoDismiss`, exit 0, zero dialoguri
|
||||
pe toate):
|
||||
|
||||
| Suita | Rezultat | Baseline |
|
||||
|---|---|---|
|
||||
| `test_page3_articole` | 14 PASS / 2 FAIL | 14/2 (identic — cele 2 sunt artefactul headless cunoscut pe coloanele de grid) |
|
||||
| `test_incarca_vanzare_din_nota` | 5/0 | 5/0 |
|
||||
| `test_adauga_linie_articol` | 20/0 | 20/0 |
|
||||
| `test_adauga_linie_valuta` | 16/0 | 16/0 |
|
||||
| `test_ui_sterge_linie` | 8/0 | 8/0 |
|
||||
| `test_verdict_act_rul` | 26/0 | 26/0 |
|
||||
|
||||
Toate cifrele identice cu baseline-ul dat — nicio regresie introdusa, nici de modificarea proprie,
|
||||
nici de lucrarile paralele pe `omodificari.vc2` la ora rularii.
|
||||
|
||||
Cifrele s-au numarat din liniile `REZULTAT: N PASS / M FAIL` din fiecare log (`grep -c "PASS"/"FAIL"`
|
||||
brut supra-numara cu 1, pentru ca linia `REZULTAT` insasi contine ambele cuvinte).
|
||||
|
||||
## Ce nu s-a testat
|
||||
|
||||
- Scrierea reala in Oracle prin noul apel (tranzactie -> `ScrieArticoleFacturaEditate` ->
|
||||
`SELECT` de verificare -> rollback/commit) — nu face parte din aceasta livrare, ramane la pasul
|
||||
de aplicare in `MARIUSM_AUTO` (nepornit inca, per `docs\handoff_s5.md`).
|
||||
- Fluxul UI complet (click real pe butonul de editare, `frm_modific2024` deschis modal) — testele de
|
||||
regresie folosesc harnessul headless existent, care nu exercita interactiunea reala de grid
|
||||
(limitare documentata, nu introdusa aici).
|
||||
@@ -125,7 +125,7 @@ Se umple din `VVANZARI_ARTICOLE` prin `IncarcaArticoleFactura`
|
||||
| **`lmodificat` (L)** | calculat, `.F.` la incarcare (`:316`) | — |
|
||||
| **`valoare` (N 14,2)** | calculat la incarcare (`:316-319`) si recalculat la fiecare editare | nu (`Column14.ReadOnly = .T.`) |
|
||||
|
||||
Definitia view-ului: `docs\cercetare\ff_view_articole_vanzare.sql` (21 de coloane, valori brute,
|
||||
Definitia view-ului: `COMUN\docs\cercetare\ff_view_articole_vanzare.sql` (21 de coloane, valori brute,
|
||||
fara conversie valutara; filtrul `STERS` lasat pe seama apelantului).
|
||||
|
||||
**Doar 3 coloane sunt editabile: `cantitate`, `pret`, `pret_cu_tva`.** Tot restul e read-only in
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Inchide cele doua goluri declarate de `docs\cercetare\rec_s5_scriere_reala.md`, sectiunea
|
||||
„Ce NU acopera testul". Suita: `COMUN\utile\Teste\editare_factura\test_s5_discount_valuta.prg`.
|
||||
Log: `COMUN\utile\Teste\editare_factura\test_s5_discount_valuta_log.txt` (rulare 10.08.2026,
|
||||
00:05:16-00:05:21). Diff: `docs\diff_s5_discount_valuta.patch`.
|
||||
00:05:16-00:05:21). Diff: diff aplicat (sters).
|
||||
|
||||
## Rezultat
|
||||
|
||||
|
||||
@@ -201,4 +201,4 @@ Pe `id_vanzare=1049` (acelasi document folosit de toate suitele S5 anterioare):
|
||||
`ofacturare_comun.vc2`, `comun.vc2`, `ofacturare_editare.prg`, `COMUN\clase\ofacturare.vc2` —
|
||||
neatinse, conform interdictiei din briefing.
|
||||
|
||||
Diff (fisiere noi): `docs\diff_s5_goluri_test.patch`.
|
||||
Diff (fisiere noi): diff aplicat (sters).
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
# S5 — helper VFP `ScrieArticoleFacturaEditate` (`COMUN\programe\ofacturare_editare.prg`)
|
||||
|
||||
Implementare, nu doar cercetare. Singurul fisier atins: `COMUN\programe\ofacturare_editare.prg`
|
||||
(`.prg` sursa directa, fara binar, fara write-back). Diff: `docs\diff_s5_helper_scriere.patch`.
|
||||
|
||||
## 1. Ce s-a facut
|
||||
|
||||
- `CreeazaCursorArticoleGol` (deci si `CreeazaCursorTvdGol`): adaugate `id_vanzare_set I NULL` si
|
||||
`pret_achizitie N(14,4) NULL`, imediat dupa `sters`, inainte de `denumire` — aceeasi pozitie ca in
|
||||
view-ul `VVANZARI_ARTICOLE` extins de `ff_2026_08_09_02_COMUN_VVANZARI_ARTICOLE.sql` (verificat pe
|
||||
disc, coloanele intra la coada listei proprii tabelei, inainte de join-uri).
|
||||
- `IncarcaArticoleFactura`: **nicio modificare de cod** — foloseste deja `select v.*, na.in_stoc from
|
||||
vvanzari_articole v ...` (`:299`), deci cele doua coloane noi ale view-ului ajung automat in `tvd`
|
||||
prin `v.*` in momentul in care view-ul e aplicat in Oracle. Extinderea cursorului gol (mai sus) e
|
||||
suficienta pentru ca `tvd` sa poarte ambele coloane si pe ramura de eroare/fallback.
|
||||
- **A doua definitie a cursorului, `omodificari.vc2:14571` (ramura ROACONT/ROAGEST, `CREATE CURSOR`
|
||||
duplicat literal) NU a fost atinsa** — confirmarea ceruta explicit. Trebuie tinuta sincron manual de
|
||||
agentul care lucreaza pe `.vc2`, altfel `tvd` are structuri diferite dupa aplicatie.
|
||||
- Functie noua `ScrieArticoleFacturaEditate(tnIdVanzare, tcAliasArticole, tcAliasVanzare)` —
|
||||
implicit `'tvd'`/`'tvanz'`. Patru pasi, in ordinea impusa de decizia 38 (marcheaza tot, invie ce
|
||||
ramane, insereaza, recalculeaza), fara `COMMIT`/`ROLLBACK`, fara inchidere de cursoare,
|
||||
salveaza/restaureaza workarea si `Recno()` pe alias.
|
||||
|
||||
## 2. Recalculul de totaluri (pasul 4) — LAMURIT de team-lead, acum in helper
|
||||
|
||||
Livrarea initiala nu includea apelul la `recalculeaza_totaluri_vanzari` in helper, motivat de
|
||||
`rec_s5_cale_scriere_vfp.md` 3.3 ("apelul trebuie facut din VFP, ca pas separat, dupa helper") si de
|
||||
secventa din decizia 38 care arata doua apeluri distincte la nivelul apelantului. **Team-lead a
|
||||
corectat**: acea schita era la nivel de apelant, nu contractul final; apelul intra in helper tocmai ca
|
||||
sa ramana un singur punct de scriere (altfel cele doua puncte de intrare, `ofacturare_comun.vc2` si
|
||||
`comun.vc2`, trebuie amandoua sa-si aminteasca sa-l cheme, cu riscul de a uita unul).
|
||||
|
||||
**Implementat acum**: pasul 4, ultimul, dupa `INSERT`-uri, gardat de `IF m.llSucces`:
|
||||
```
|
||||
begin pack_facturare.recalculeaza_totaluri_vanzari(<tnIdVanzare>, <discount sau NULL>); end;
|
||||
```
|
||||
- discountul se citeste din `<tcAliasVanzare>.discount` (primul rand, garantat unic de garda de
|
||||
no-op) imediat la inceputul functiei, inainte de pasii 1-3 (pozitia in cursorul de articole nu
|
||||
intra in conflict, sunt cursoare separate).
|
||||
- daca `discount` e `.NULL.` in cursor, se trimite literal `NULL` in apelul PL/SQL (pastreaza
|
||||
discountul curent din baza) — **nu** `0`, care l-ar sterge. Daca are valoare, se trimite prin
|
||||
`Alltrim(Str(...,18,4))`.
|
||||
- niciun `UPDATE VANZARI SET DISCOUNT` separat — scrierea discountului ramane exclusiv in
|
||||
responsabilitatea procedurii Oracle, primit ca parametru, exact cum cere decizia 41.
|
||||
- acelasi tratament de eroare ca la ceilalti pasi: `goExecutor.oExecuta`, `.F.` la esec, fara mesaj
|
||||
propriu, fara `COMMIT`/`ROLLBACK`.
|
||||
|
||||
## 3. `PRET_ACHIZITIE` pe linia noua — INCHIS: se citeste din cursor, nu se calculeaza in helper
|
||||
|
||||
Premisa initiala a deciziei 40 ("se preia din nomenclator / stoc") s-a dovedit gresita si a fost
|
||||
revizuita de Marius, dupa constatarea de mai jos. Decizia finala: valoarea **o introduce
|
||||
utilizatorul**, intr-o coloana noua editabila in gridul de pe PAGE3 (`omodificari.vc2`, doar pe
|
||||
liniile noi — alt agent, nu se atinge aici). Helperul doar **citeste** `pret_achizitie` din cursorul
|
||||
de articole (`Nvl(pret_achizitie,0)`), fara niciun lookup Oracle propriu.
|
||||
|
||||
**Constatarea care a schimbat decizia** (`SELECT` read-only in `MARIUSM_AUTO`, pastrata aici ca sa nu
|
||||
se redescopere):
|
||||
- `NOM_ARTICOLE` **nu are nicio coloana de pret de achizitie curent** — singura coloana cu "PRET" sau
|
||||
"ACHIZ" in nume e `PRETACHCTVA` (`NUMBER`, `DEFAULT 0`), care e un **flag** ("pretul de achizitie
|
||||
contine TVA?"), nu o valoare — confirmat prin utilizarea ei in
|
||||
`pack_facturare.scrie_fact_aviz_custodie` (`docs\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql:10116,
|
||||
10168-10169, 10209`), unde e citita alaturi de `V_PRET_ACHIZITIE` (parametru separat), niciodata ca
|
||||
sursa a lui.
|
||||
- La emitere, `pret_achizitie` **nu vine dintr-o coloana statica** — vine fie din cursorul de stoc VFP
|
||||
(`ofacturare_stoc.prg:221`, `a.Pret As pret_achizitie` din `rul_temp`, adica pretul lotului de stoc
|
||||
ales), fie din cursorul de articole selectate la alegerea din gestiune
|
||||
(`ofacturare.vc2:13822/13849`, `poArticol.pret_achizitie = Pret` din `crsartselectate`), fie e
|
||||
re-derivat in Oracle in `adauga_articol_factura` (`docs\ff_...PACK_FACTURARE.sql:5020,
|
||||
5093-5134`) — numai pe ramura restaurant (`ntip=45`) din `CRM_POLITICI_PRET_ART.PRETFTVA` +
|
||||
procent de adaos; pe toate celelalte ramuri ramane valoarea primita ca parametru din VFP. Niciuna
|
||||
din aceste cai exista in fluxul de editare: liniile noi la editare se adauga prin
|
||||
`CreeazaPoArticolNouTvd` (`ofacturare_editare.prg:356-457`), care fixeaza
|
||||
**`id_gestiune = -1000` si `gestionabil = 0`** necondtionat — adica editarea NU deschide dialogul
|
||||
de alegere din stoc, deci n-are un lot/gestiune reala de unde sa citeasca pretul.
|
||||
- `STOC` (verificat structura, `all_tab_columns`): tabela periodica `AN, LUNA, ID_ARTICOL,
|
||||
ID_GESTIUNE, PRET, PRETV, CANTS, ...` — un rand pe lot/perioada/gestiune, aceeasi granularitate ca
|
||||
`RUL`. **Nu exista un "pret curent" unic** fara o formula de agregare (ce perioada, ce gestiuni).
|
||||
|
||||
**Ce e implementat acum, in `ScrieArticoleFacturaEditate`**: la pasul `INSERT` al liniei noi,
|
||||
`PRET_ACHIZITIE = Nvl(<tcAliasArticole>.pret_achizitie, 0)`, citit direct din cursor (coloana
|
||||
adaugata la punctul 1) — fara `STOC`, fara `NOM_ARTICOLE`, fara functie ajutatoare. La `UPDATE`-ul
|
||||
liniilor pastrate, coloana ramane **omisa din `SET`**, exact ca in specificatia initiala (pe liniile
|
||||
existente nu e editabila, valoarea persistata nu se atinge).
|
||||
|
||||
## 4. Coloanele `NOT NULL` din `VANZARI_DETALII` — verificat, punctul NEVERIFICAT din cercetare e inchis
|
||||
|
||||
`SELECT column_name, nullable, data_default FROM all_tab_columns WHERE owner='MARIUSM_AUTO' AND
|
||||
table_name='VANZARI_DETALII' AND nullable='N'` (read-only, `MARIUSM_AUTO`/`ROA_CENTRAL`):
|
||||
|
||||
| Coloana | `DATA_DEFAULT` | Tratament in `INSERT` |
|
||||
|---|---|---|
|
||||
| `ID_VANZARE_DET` | — | nu se scrie, vine din trigger `TRG_VANZARI_DET_BEFOINS` |
|
||||
| `ID_VANZARE` | — | scris explicit (`tnIdVanzare`) |
|
||||
| `PRET` | — | scris explicit (din `tvd.pret`) |
|
||||
| `VALIDAT` | `0` | nescris, ramane `DEFAULT 0` |
|
||||
| `STERS` | `0` | nescris, ramane `DEFAULT 0` (linie noua = activa) |
|
||||
| `DIFERENTA` | `0` | nescris, ramane `DEFAULT 0` |
|
||||
| `CUSTODIE` | `0` | nescris, ramane `DEFAULT 0` |
|
||||
| `DESCARCAT` | `0` | nescris, ramane `DEFAULT 0` |
|
||||
|
||||
Toate cele cinci `NOT NULL` fara valoare din trigger **au `DEFAULT 0` la nivel de coloana** — nu e
|
||||
nevoie sa fie enumerate in `INSERT`. Singurele `NOT NULL` care trebuie scrise explicit sunt
|
||||
`ID_VANZARE` si `PRET`, deja acoperite de contract.
|
||||
|
||||
## 5. SQL generat, cate un exemplu per categorie
|
||||
|
||||
**Pasul 1 — marcheaza tot sters** (`tnIdVanzare = 12345`, `gnIdUtil = 7`):
|
||||
```sql
|
||||
update vanzari_detalii set sters = 1, id_utils = 7, dataoras = sysdate where id_vanzare = 12345 and sters = 0
|
||||
```
|
||||
|
||||
**Pasul 2 — linie pastrata** (`id_vanzare_det = 98765`, `cantitate = 2.5`, `pret = 10.5`,
|
||||
`pret_cu_tva = 0`):
|
||||
```sql
|
||||
update vanzari_detalii set sters = 0, cantitate = 2.500, pret = 10.5000, pret_cu_tva = 0, id_utils = 7, dataoras = sysdate where id_vanzare_det = 98765
|
||||
```
|
||||
|
||||
**Pasul 3 — linie noua** (`id_articol = 111`, `cantitate = 1`, `pret = 20`, `pret_cu_tva = 0`,
|
||||
`proc_tvav = 1.19`, `discount_unitar = 0`, `id_gestiune = -1000`, `cont` gol -> `NULL`, `id_valuta`
|
||||
`.NULL.` -> `NULL`, `id_jtva_coloana = 3`, `serie`/`lot` goale -> `NULL`, `explicatie = "test 'x'"`,
|
||||
`taxcode` `.NULL.` -> `NULL`, `pret_achizitie` tastat de utilizator in grid = `15.2300`):
|
||||
```sql
|
||||
insert into vanzari_detalii (id_vanzare, id_articol, cantitate, pret, pret_cu_tva, proc_tvav, discount_unitar, id_gestiune, cont, id_valuta, id_jtva_coloana, serie, explicatie, taxcode, lot, pret_achizitie, id_utils, dataoras) values (12345,111,1.000,20.0000,0,1.1900,0.0000,-1000,NULL,NULL,3,NULL,'test ''x''',NULL,NULL,15.2300,7,sysdate)
|
||||
```
|
||||
(`OracleSpecialCharacters` a dublat apostroful din `explicatie`.)
|
||||
|
||||
**Pasul 4 — recalculul totalurilor** (`tnIdVanzare = 12345`, `tvanz.discount = 5` — cazul cu valoare):
|
||||
```sql
|
||||
begin pack_facturare.recalculeaza_totaluri_vanzari(12345,5.0000); end;
|
||||
```
|
||||
Cazul `tvanz.discount` `.NULL.` (pastreaza discountul curent din baza):
|
||||
```sql
|
||||
begin pack_facturare.recalculeaza_totaluri_vanzari(12345,NULL); end;
|
||||
```
|
||||
|
||||
## 6. Ce a ramas netestat, si de ce
|
||||
|
||||
- **Nimic rulat** — nu era in scope ("NU rulezi teste care scriu in baza"). Verificarea de mai sus
|
||||
(coloane `NOT NULL`, tipuri, existenta view-ului) a fost facuta prin `SELECT`-uri read-only in
|
||||
`MARIUSM_AUTO`, nu prin executarea functiei.
|
||||
- Textul SQL generat pentru cei 4 pasi (sectiunea 5) e verificat manual, pe exemple, nu prin rularea
|
||||
functiei cu un `goExecutor` mock.
|
||||
- Restul e netestabil headless din motivele deja consemnate in `rec_s5_cale_scriere_vfp.md` sectiunea
|
||||
7 (ordonarea fata de `actualizeaza_vanzari` cere Oracle real; grid-ul de pe PAGE3 care va scrie
|
||||
`pret_achizitie` in cursor nu exista inca — depinde de agentul pe `omodificari.vc2`).
|
||||
|
||||
## 7. Rezumat pentru revizuire
|
||||
|
||||
Ambele puncte semnalate initial ca neconfirmate au fost lamurite de team-lead/Marius:
|
||||
1. **Recalculul de totaluri** — intra in helper, ca pasul 4 (sectiunea 2).
|
||||
2. **`PRET_ACHIZITIE`** — nu se mai calculeaza in helper; se citeste din cursor, unde va fi scrisa de
|
||||
utilizator prin coloana noua din grid (sectiunea 3).
|
||||
|
||||
Toata functionalitatea (structura cursorului, cei 4 pasi de scriere, coloanele `NOT NULL`) e
|
||||
implementata conform contractului final, fara ambiguitate ramasa in acest fisier.
|
||||
|
||||
## 8. Corectii din revizuirea team-lead
|
||||
|
||||
**1. Garda de no-op extinsa cu `Reccount(tcAliasArticole) = 0` — schimbare de fond fata de cercetare.**
|
||||
`rec_s5_cale_scriere_vfp.md` sectiunea 6 spunea explicit ca un cursor de articole gol cu
|
||||
`tnIdVanzare > 0` **nu** e no-op ("s-au sters toate liniile"), plecand de la premisa ca un cursor gol
|
||||
apare doar prin stergerea tuturor liniilor de catre utilizator. Team-lead a aratat, cu dovada din cod,
|
||||
ca premisa e incompleta: `IncarcaArticoleFactura` (`ofacturare_editare.prg:305-309`) intoarce **`.T.`
|
||||
cu cursor gol** si la esec Oracle:
|
||||
```
|
||||
IF lnSucces < 0
|
||||
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
|
||||
CreeazaCursorArticoleGol(m.lcAlias)
|
||||
RETURN .T.
|
||||
ENDIF
|
||||
```
|
||||
Helperul nu poate distinge "utilizatorul a sters tot" de "incarcarea a picat" — ambele ajung cu
|
||||
`tvd` gol si `.T.` de la apelul de incarcare. Fara garda, al doilea caz ar duce, prin pasul 1
|
||||
(marcheaza tot sters, fara nimic de inviat la pasul 2), la golirea tacuta a facturii la un simplu esec
|
||||
de retea/Oracle la deschiderea formularului. Corectat: `Reccount(m.lcAliasArt) = 0` s-a adaugat la
|
||||
garda initiala de no-op — cursorul gol nu mai scrie nimic. Cazul legitim (utilizatorul chiar sterge
|
||||
toate liniile) e oricum oprit mai devreme de validarea din `inainte_de_do_termin` (alt agent,
|
||||
`omodificari.vc2`), inainte ca helperul sa fie apelat.
|
||||
|
||||
**2. `UPDATE`-ul liniilor pastrate (pasul 2) ancorat si pe `id_vanzare`.** `WHERE id_vanzare_det = ...`
|
||||
nu avea garda pe document. Adaugat `and id_vanzare = <tnIdVanzare>` — cost zero, inchide posibilitatea
|
||||
teoretica de scriere intr-un alt document daca aliasul ar ajunge vreodata sa contina o linie straina
|
||||
de `tnIdVanzare`.
|
||||
|
||||
Nimic altceva schimbat: ordinea pasilor, `NULL` pe discount, omiterea `PRET_ACHIZITIE` din `SET`-ul
|
||||
de `UPDATE`, `OracleSpecialCharacters`, restaurarea `Recno()`/workarea raman ca in runda anterioara.
|
||||
@@ -1,780 +0,0 @@
|
||||
# Cercetare S5 — proiectarea partii Oracle (plan #6, editare factura emisa)
|
||||
|
||||
Data: 09.08.2026. Sursa: export PROASPAT din `MARIUSM_AUTO@ROA_CENTRAL` (`all_source`), facut in
|
||||
aceasta sesiune, in scratchpad (nu in proiect):
|
||||
|
||||
- `PACK_FACTURARE.pck` — 16160 linii
|
||||
- `PACK_CONTAFIN.pck` — 8550 linii
|
||||
|
||||
**Toate numerele de linie de mai jos sunt din ACEST export.** Raportul precedent
|
||||
(`rec_s5_oracle_vanzari.md`, 08.08.2026) declara `PACK_FACTURARE.pck = 17010` linii; offset-urile
|
||||
procedurilor coincid totusi exact (`scrie_in_vanzari` la `:13491`, `actualizeaza_vanzari` la
|
||||
`:16015`), deci diferenta e de formatare a spool-ului, nu de continut. Concluziile lui A.1-A.2, C si
|
||||
D raman valabile pe sursa de azi si nu se repeta aici.
|
||||
|
||||
**Doua corectii de fond fata de raportul precedent** (detaliate la 3 si 4):
|
||||
|
||||
1. agregarea NU citeste `VANZARI_SETURI_TEMP`, ci tabela **persistenta `VANZARI_SETURI`**
|
||||
(`:13916`) — deci liniile de set se pot reconstitui integral la editare;
|
||||
2. recomandarea „procedura noua apelata din interiorul `finalizeaza_modificare_nota`" e
|
||||
**incompatibila cu ordinea corecta de scriere** si trebuie abandonata.
|
||||
|
||||
---
|
||||
|
||||
## 1. Baza de plecare e la zi? DA (pentru `ff_`)
|
||||
|
||||
Comparatie `VERSIUNE` (4151 randuri) vs. `D:\ROA\DATABASE\SCRIPTURI_CLAR` (3030 fisiere `.sql`):
|
||||
|
||||
- **`ff_` pe disc dar neaplicate in `MARIUSM_AUTO`: 0.** Schema e la zi pe tot ce o priveste.
|
||||
- Ultimul `ff_` inregistrat: `ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql`, identic cu
|
||||
`versiune_db.txt` din radacina proiectului (`2026_08_08_01`).
|
||||
- Cele 26 de scripturi din 2026 care lipsesc din `VERSIUNE` sunt **exclusiv `co_` si `sys_`** — se
|
||||
aplica pe `CONTAFIN_ORACLE`, respectiv `SYS`, nu pe schema firmei; `VERSIUNE` din `MARIUSM_AUTO`
|
||||
contine doar 3 randuri `co_`, deci absenta lor e normala, nu o restanta.
|
||||
|
||||
**Verdict: se poate construi propunerea peste sursa exportata azi.**
|
||||
|
||||
### Doua anomalii de semnalat (nu blocheaza S5)
|
||||
|
||||
- **`ff_2026_08_08_01_COMUN_VVD_TOT.sql` e inregistrat in `VERSIUNE` dar NU exista nicaieri pe
|
||||
disc** (cautat recursiv in tot `SCRIPTURI_CLAR`). Un obiect aplicat in dev fara script salvat nu
|
||||
ajunge niciodata la clienti. De verificat cu Marius daca e un script de lucru abandonat sau daca
|
||||
lipseste din SVN.
|
||||
- Acelasi `NN` (`2026_08_08_01`) e folosit de doua scripturi `ff_` (`VVANZARI_ARTICOLE` si
|
||||
`VVD_TOT`), contra regulii „NN e secventa unica pe zi".
|
||||
|
||||
---
|
||||
|
||||
## 2. Blocul de agregare din `scrie_in_vanzari` — integral
|
||||
|
||||
Procedura: `PACK_FACTURARE.pck:13491-13956`. Blocul de agregare + `UPDATE VANZARI` e
|
||||
`:13762-13954`, citat integral:
|
||||
|
||||
```
|
||||
13762 -- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
13763 begin
|
||||
13764 select DISC_TVA_VAL AS DISCOUNT_TVA,
|
||||
13765 VALOARE_ACHIZITIE,
|
||||
13766 a.suma_fara_tva_ron - a.disc_fara_tva_ron as TOTAL_FARA_TVA,
|
||||
13767 a.suma_tva_ron - a.disc_tva_ron as TOTAL_TVA,
|
||||
13768 a.suma_fara_tva_ron - a.disc_fara_tva_ron + a.suma_tva_ron -
|
||||
13769 a.disc_tva_ron as TOTAL_CU_TVA,
|
||||
13770 a.suma_fara_tva_val - a.disc_fara_tva_val as VALVAL,
|
||||
13771 a.suma_tva_val - a.disc_tva_val as TVAVAL,
|
||||
13772 a.suma_fara_tva_val - a.disc_fara_tva_val + a.suma_tva_val -
|
||||
13773 a.disc_tva_val as TOTVAL,
|
||||
13774 id_valuta,
|
||||
13775 curs,
|
||||
13776 multiplicator,
|
||||
13777 pack_facturare.cserie_act_incasare as SERIE_INCASAT,
|
||||
13778 pack_facturare.nnumar_act_incasare as NR_INCASAT,
|
||||
13779 pack_facturare.nsuma_incasare AS SUMA_INCASAT,
|
||||
13780 pack_facturare.ntip_doc_incasare as TIP_INCASAT
|
||||
13781 INTO lnDiscountTVA,
|
||||
13782 lnValoareAchizitie,
|
||||
13783 lnTotalFaraTVA,
|
||||
13784 lnTotalTVA,
|
||||
13785 lnTotalCuTVA,
|
||||
13786 lnValVal,
|
||||
13787 lnTVAVal,
|
||||
13788 lnTotVal,
|
||||
13789 lnIdValuta,
|
||||
13790 lnCurs,
|
||||
13791 lnMultiplicator,
|
||||
13792 lnSerieIncasat,
|
||||
13793 lnNrIncasat,
|
||||
13794 lnSumaIncasat,
|
||||
13795 lnTipIncasat
|
||||
13796 FROM (select MAX(decode(pack_facturare.nin_valuta,
|
||||
13797 1,
|
||||
13798 ROUND(a1.curs * NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
13799 a1.multiplicator,
|
||||
13800 lnPreciziePretV),
|
||||
13801 NVL(V_DISCOUNT_FACTURA, 0))) as DISC_FARA_TVA_RON,
|
||||
13802 NVL(V_DISCOUNT_FACTURA, 0) as DISC_FARA_TVA_VAL,
|
||||
13803 pack_facturare.nin_valuta AS IN_VALUTA,
|
||||
13804 MAX(ROUND(decode(pack_facturare.nin_valuta,
|
||||
13805 1,
|
||||
13806 ROUND(a1.curs *
|
||||
13807 NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
13808 a1.multiplicator,
|
||||
13809 lnPreciziePretV),
|
||||
13810 NVL(V_DISCOUNT_FACTURA, 0)) *
|
||||
13811 (a1.proc_tvav - 1),
|
||||
13812 lnPreciziePretV)) as DISC_TVA_RON,
|
||||
13813 MAX(ROUND(NVL(V_DISCOUNT_FACTURA, 0) *
|
||||
13814 (a1.proc_tvav - 1),
|
||||
13815 lnPreciziePretV)) as DISC_TVA_VAL,
|
||||
13816 sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_ron,
|
||||
13817 0,
|
||||
13818 1,
|
||||
13819 NVL(a1.discount_unitar_ron,
|
||||
13820 0),
|
||||
13821 pack_facturare.ndiscount_evidentiat,
|
||||
13822 a1.cantitate,
|
||||
13823 a1.pret_cu_tva,
|
||||
13824 a1.proc_tvav)) AS SUMA_FARA_TVA_RON,
|
||||
13825 sum(pack_facturare.calculeaza_total_tva_fact(a1.pret_ron,
|
||||
13826 0,
|
||||
13827 1,
|
||||
13828 NVL(a1.discount_unitar_ron,
|
||||
13829 0),
|
||||
13830 pack_facturare.ndiscount_evidentiat,
|
||||
13831 a1.cantitate,
|
||||
13832 a1.pret_cu_tva,
|
||||
13833 a1.proc_tvav)) as SUMA_TVA_RON,
|
||||
13834 sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_val,
|
||||
13835 0,
|
||||
13836 1,
|
||||
13837 NVL(a1.discount_unitar_val,
|
||||
13838 0),
|
||||
13839 pack_facturare.ndiscount_evidentiat,
|
||||
13840 a1.cantitate,
|
||||
13841 a1.pret_cu_tva,
|
||||
13842 a1.proc_tvav)) AS SUMA_FARA_TVA_VAL,
|
||||
13843 sum(pack_facturare.calculeaza_total_tva_fact(a1.pret_val,
|
||||
13844 0,
|
||||
13845 1,
|
||||
13846 NVL(a1.discount_unitar_val,
|
||||
13847 0),
|
||||
13848 pack_facturare.ndiscount_evidentiat,
|
||||
13849 a1.cantitate,
|
||||
13850 a1.pret_cu_tva,
|
||||
13851 a1.proc_tvav)) as SUMA_TVA_VAL,
|
||||
13852 sum(round(a1.cantitate * a1.pret_achizitie,
|
||||
13853 lnPrecizieCalcul)) AS VALOARE_ACHIZITIE,
|
||||
13854 max(decode(pack_facturare.nin_valuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
13855 max(decode(pack_facturare.nin_valuta, 1, a1.curs, 1)) as curs,
|
||||
13856 max(decode(pack_facturare.nin_valuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
13857 from (select vd.id_vanzare_set,
|
||||
13858 (case
|
||||
13859 when (pack_facturare.nin_valuta = 1 or
|
||||
13860 vd.id_valuta <>
|
||||
13861 pack_def.GetIdMonedaNationala()) then
|
||||
13862 ROUND(vc.curs * vd.pret / vc.multiplicator,
|
||||
13863 lnPreciziePretV)
|
||||
13864 else
|
||||
13865 vd.pret
|
||||
13866 end) as pret_ron,
|
||||
13867 vd.pret as pret_val,
|
||||
13868 vd.proc_tvav,
|
||||
13869 vd.cantitate,
|
||||
13870 vd.diferenta,
|
||||
13871 (case
|
||||
13872 when (pack_facturare.nin_valuta = 1 or
|
||||
13873 vd.id_valuta <>
|
||||
13874 pack_def.GetIdMonedaNationala()) then
|
||||
13875 ROUND(vc.curs * vd.discount_unitar /
|
||||
13876 vc.multiplicator,
|
||||
13877 lnPreciziePretV)
|
||||
13878 else
|
||||
13879 vd.discount_unitar
|
||||
13880 end) as discount_unitar_ron,
|
||||
13881 vd.discount_unitar as discount_unitar_val,
|
||||
13882 vd.id_valuta,
|
||||
13883 vd.pret_cu_tva,
|
||||
13884 vd.pret_achizitie,
|
||||
13885 vc.curs,
|
||||
13886 vc.multiplicator
|
||||
13887 from (select a.id_vanzare_set,
|
||||
13888 a.pret,
|
||||
13889 a.proc_tvav,
|
||||
13890 a.cantitate,
|
||||
13891 a.diferenta,
|
||||
13892 a.discount_unitar,
|
||||
13893 a.id_valuta,
|
||||
13894 a.pret_cu_tva,
|
||||
13895 a.pret_achizitie
|
||||
13896 from VANZARI_DETALII_TEMP a
|
||||
13897 where nvl(a.id_vanzare_set, 0) = 0
|
||||
13898 union all
|
||||
13899 select b.id_vanzare_set,
|
||||
13900 b.pret,
|
||||
13901 max(c.proc_tvav) as proc_tvav,
|
||||
13902 b.cantitate,
|
||||
13903 0 as diferenta,
|
||||
13904 b.discount_unitar,
|
||||
13905 decode(pack_facturare.nin_valuta,
|
||||
13906 0,
|
||||
13907 pack_def.GetIdMonedaNationala(),
|
||||
13908 c.id_valuta) as id_valuta,
|
||||
13909 b.pret_cu_tva,
|
||||
13910 sum(decode(b.cantitate,
|
||||
13911 0,
|
||||
13912 0,
|
||||
13913 c.pret_achizitie * c.cantitate /
|
||||
13914 b.cantitate)) as pret_achizitie
|
||||
13915 from vanzari_detalii_temp c
|
||||
13916 left join vanzari_seturi b
|
||||
13917 on b.id_vanzare_set = c.id_vanzare_set
|
||||
13918 where nvl(c.id_vanzare_set, 0) <> 0
|
||||
13919 and nvl(pack_facturare.nin_valuta, -1) > -1
|
||||
13920 group by b.id_vanzare_set,
|
||||
13921 b.pret,
|
||||
13922 b.cantitate,
|
||||
13923 b.discount_unitar,
|
||||
13924 b.pret_cu_tva,
|
||||
13925 decode(pack_facturare.nin_valuta,
|
||||
13926 0,
|
||||
13927 pack_def.GetIdMonedaNationala(),
|
||||
13928 c.id_valuta)) vd
|
||||
13929 left join vanzari_cursuri vc
|
||||
13930 on vc.id_vanzare = V_ID_VANZARE
|
||||
13931 and vd.id_valuta = vc.id_valuta) a1) a;
|
||||
13932
|
||||
13933 update vanzari
|
||||
13934 set discount_tva = lnDiscountTVA,
|
||||
13935 valoare_achizitie = lnValoareAchizitie,
|
||||
13936 total_fara_tva = lnTotalFaraTVA,
|
||||
13937 total_tva = lnTotalTVA,
|
||||
13938 total_cu_tva = lnTotalCuTVA,
|
||||
13939 valval = lnValVal,
|
||||
13940 tvaval = lnTVAVal,
|
||||
13941 totval = lnTotVal,
|
||||
13942 id_valuta = lnIdValuta,
|
||||
13943 curs = lnCurs,
|
||||
13944 multiplicator = lnMultiplicator,
|
||||
13945 serie_incasat = lnSerieIncasat,
|
||||
13946 nr_incasat = lnNrIncasat,
|
||||
13947 suma_incasat = lnSumaIncasat,
|
||||
13948 tip_incasat = lnTipIncasat
|
||||
13949 where id_vanzare = V_ID_VANZARE;
|
||||
13950
|
||||
13951 exception
|
||||
13952 when NO_DATA_FOUND then
|
||||
13953 null;
|
||||
13954 end;
|
||||
```
|
||||
|
||||
Variabilele locale relevante, declarate la `:13501-13523`:
|
||||
|
||||
```
|
||||
13522 lnPrecizieCalcul NUMBER(2) := pack_sesiune.getOptiuneFirma('PC');
|
||||
13523 lnPreciziePretV NUMBER(2) := pack_sesiune.getOptiuneFirma('PPRETV');
|
||||
```
|
||||
|
||||
### Inventarul dependentelor blocului
|
||||
|
||||
| Dependenta | Linii | Sursa la emitere | Echivalent PERSISTENT la editare | Verdict |
|
||||
|---|---|---|---|---|
|
||||
| `V_DISCOUNT_FACTURA` | 13798, 13801, 13802, 13807, 13810, 13813 | parametru al procedurii | **`VANZARI.DISCOUNT`** — scrisa la INSERT din exact acelasi parametru (`:13621` / `:13682`) | reconstituibil |
|
||||
| `pack_facturare.nin_valuta` | 13796, 13803, 13804, 13854-13856, 13859, 13872, 13905, 13919, 13925 | stare de sesiune pe pachet | **`VANZARI.IN_VALUTA`** (`NUMBER(1)`, NOT NULL) — scrisa la INSERT din aceeasi variabila (`:13625` / `:13686`) | reconstituibil |
|
||||
| `pack_facturare.ndiscount_evidentiat` | 13821, 13830, 13839, 13848 | stare de sesiune pe pachet | **`VANZARI.DISCOUNT_EVIDENTIAT`** — scrisa la INSERT din aceeasi variabila (`:13622` / `:13683`) | reconstituibil |
|
||||
| `cserie_act_incasare`, `nnumar_act_incasare`, `nsuma_incasare`, `ntip_doc_incasare` | 13777-13780 | stare de sesiune, setata numai in fluxul de emitere (`:13102-13144`; resetate la `:1882-1886`) | **NICIUNUL** | vezi 6 |
|
||||
| `pack_def.GetIdMonedaNationala()` | 13861, 13874, 13907, 13927 | functie pura: `SELECT MIN(ID_VALUTA) FROM NOM_VALUTE WHERE STERS=0 AND MONEDA_NATIONALA=1` (PACK_DEF body `:214-230`) | idem — fara stare | fara probleme |
|
||||
| `pack_sesiune.getOptiuneFirma('PC'/'PPRETV')` | 13522-13523, 13853 | `SELECT varvalue FROM optiuni WHERE ...` (PACK_SESIUNE body `:119-141`) — **lookup pe tabela, fara stare de pachet** | idem | fara probleme |
|
||||
| `VANZARI_DETALII_TEMP` (liniile directe) | 13896-13897 | GTT `ON COMMIT DELETE ROWS` | **`VANZARI_DETALII WHERE ID_VANZARE = :id AND STERS = 0 AND NVL(ID_VANZARE_SET,0) = 0`** | vezi 3 |
|
||||
| `VANZARI_DETALII_TEMP` (liniile de set, alias `c`) | 13915, 13918 | GTT | **`VANZARI_DETALII ... AND NVL(ID_VANZARE_SET,0) <> 0`** | vezi 3 |
|
||||
| `vanzari_seturi` (alias `b`) | 13916 | **tabela PERSISTENTA, deja** | ea insasi | vezi 3 |
|
||||
| `vanzari_cursuri vc` | 13929-13930 | tabela persistenta, populata cu `id_vanzare`-ul curent la `:13704` (`scrie_cursuri`) | ea insasi, deja legata pe `ID_VANZARE` | fara probleme |
|
||||
|
||||
Verificat pe `all_tab_columns`: **toate cele 9 coloane citite din `VANZARI_DETALII_TEMP` de
|
||||
agregare** (`id_vanzare_set, pret, proc_tvav, cantitate, diferenta, discount_unitar, id_valuta,
|
||||
pret_cu_tva, pret_achizitie`) exista, cu acelasi nume, in `VANZARI_DETALII`. Singurele coloane pe
|
||||
care TEMP le are in plus si care nu exista in tabela reala sunt `CURS, MULTIPLICATOR, EXPLICATIA,
|
||||
ID_COMANDA, NUMAR_ACT, ID_TEMP, ID_UTIL, IN_STOC, PRETV_ORIG, ID_GESTIUNE_DEST, ID_LUCRARE_REZ,
|
||||
ID_PART_REZ` — **niciuna nu e folosita de blocul de agregare** (`curs`/`multiplicator` vin din
|
||||
`vanzari_cursuri vc`, nu din linie).
|
||||
|
||||
**Concluzie: blocul se reproduce 1:1 pe surse persistente, schimband doar clauzele `FROM` si
|
||||
inlocuind cele 3 valori de stare cu cele 3 coloane din `VANZARI`.** Nu e nevoie de nicio
|
||||
reformulare a formulei — inclusiv `calculeaza_total_fara_tva_fact` / `calculeaza_total_tva_fact`
|
||||
(`PACK_FACTURARE.pck:15858-16013`, semnaturi in spec la `:1167-1185`) raman apelate identic.
|
||||
|
||||
Doua observatii de detaliu:
|
||||
- `a1.diferenta` e selectata (`:13870`, `:13891`) dar **nu e folosita nicaieri** in agregarea din
|
||||
`scrie_in_vanzari` (parametrul `V_DIFERENTA` e `0` hard-codat la `:13817`, `:13826`, `:13835`,
|
||||
`:13844`). Se poate pastra pentru fidelitate sau elimina; recomand pastrarea, ca diff-ul fata de
|
||||
original sa ramana citibil.
|
||||
- Handler-ul `WHEN NO_DATA_FOUND THEN NULL` (`:13951-13953`) e defensiv si practic inaccesibil:
|
||||
subinterogarea are agregate fara `GROUP BY`, deci intoarce mereu exact un rand. **Dar** pe zero
|
||||
linii agregatele intorc `NULL`, nu `0` — la emitere cazul nu poate aparea, la editare da (vezi
|
||||
riscul R4).
|
||||
|
||||
---
|
||||
|
||||
## 3. Liniile din seturi — EXISTA echivalent persistent
|
||||
|
||||
**Corectia raportului precedent.** Agregarea nu citeste `VANZARI_SETURI_TEMP`, ci
|
||||
**`VANZARI_SETURI`** (`PACK_FACTURARE.pck:13916`), care e o tabela **normala, persistenta**
|
||||
(verificat pe `all_tables`: `VANZARI_SETURI temporary=N`; doar `VANZARI_SETURI_TEMP` si
|
||||
`VANZARI_DETALII_TEMP` sunt `temporary=Y duration=SYS$TRANSACTION`).
|
||||
|
||||
Trecerea TEMP -> persistent o face `pack_facturare.scrie_seturi` (`:13993-14028`), apelata la
|
||||
`:13706`, **inainte** de agregare: insereaza fiecare rand din `VANZARI_SETURI_TEMP` in
|
||||
`VANZARI_SETURI` (`ID_VANZARE_SET` din `SEQ_VANZARI_SETURI`, prin trigger
|
||||
`TRG_VANZARI_SET_BEFOINS`) si reface pointerul in `VANZARI_DETALII_TEMP.ID_VANZARE_SET`. De aceea
|
||||
agregarea de la `:13915-13928` face join intre TEMP (componentele) si tabela persistenta (capul de
|
||||
set).
|
||||
|
||||
Structura `VANZARI_SETURI` (`all_tab_columns`), identica cu a TEMP-ului:
|
||||
|
||||
```
|
||||
ID_VANZARE_SET NUMBER(10) NOT NULL -- PK, din SEQ_VANZARI_SETURI
|
||||
DENUMIRE VARCHAR2(100)
|
||||
EXPLICATIE VARCHAR2(100)
|
||||
CANTITATE NUMBER(10,4)
|
||||
UM VARCHAR2(10)
|
||||
SERIE VARCHAR2(100)
|
||||
PRET NUMBER(20,4)
|
||||
DISCOUNT_UNITAR NUMBER(20,4)
|
||||
PRET_CU_TVA NUMBER(1) NOT NULL
|
||||
```
|
||||
|
||||
Nu are `ID_VANZARE` si nu are `STERS`: legatura cu documentul e **exclusiv** prin
|
||||
`VANZARI_DETALII.ID_VANZARE_SET`. Deci filtrarea pe document se face tot din `VANZARI_DETALII`.
|
||||
|
||||
**Precedent care confirma reconstituirea**: `pack_facturare.citeste_vanzari_seturi`
|
||||
(`:16619-16698`) reface deja exact acest lucru pe surse persistente — `VANZARI` (`cod`, `sters=0`)
|
||||
+ `VANZARI_DETALII` (`sters=0`, `id_vanzare_set is not null`) + `VANZARI_CURSURI` +
|
||||
`VANZARI_SETURI`, cu acelasi `GROUP BY b.id_vanzare_set`. Nu inventam un tipar nou.
|
||||
|
||||
**Raspuns la intrebarea din brief: DA, recalculul poate acoperi si liniile de set, fara pierdere de
|
||||
informatie.** Transformarea necesara in ramura de set:
|
||||
|
||||
```
|
||||
from vanzari_detalii c -- in loc de vanzari_detalii_temp c
|
||||
left join vanzari_seturi b on b.id_vanzare_set = c.id_vanzare_set
|
||||
where nvl(c.id_vanzare_set, 0) <> 0
|
||||
and c.id_vanzare = V_ID_VANZARE
|
||||
and c.sters = 0
|
||||
```
|
||||
|
||||
Date (test, `MARIUSM_AUTO`): 4 randuri in `VANZARI_SETURI`, 4 documente cu linii de set. **Nu e o
|
||||
dovada** — validarea ramane pe cod, nu pe volum.
|
||||
|
||||
### Ce NU se poate face din interfata (limitare de semnalat pentru S4)
|
||||
|
||||
View-ul `VVANZARI_ARTICOLE` (sursa lui `IncarcaArticoleFactura`,
|
||||
`COMUN\programe\ofacturare_editare.prg:288-330`) **nu expune `ID_VANZARE_SET` si nici
|
||||
`PRET_ACHIZITIE`**:
|
||||
|
||||
```
|
||||
select vd.id_vanzare, vd.id_vanzare_det, vd.id_articol, vd.cantitate, vd.pret, vd.pret_cu_tva,
|
||||
vd.proc_tvav, vd.discount_unitar, vd.id_gestiune, vd.cont, vd.id_valuta,
|
||||
vd.id_jtva_coloana, vd.serie, vd.explicatie, vd.taxcode, vd.lot, vd.sters,
|
||||
na.denumire, na.codmat, ng.nume_gestiune, nv.nume_val
|
||||
from vanzari_detalii vd
|
||||
left join nom_articole na on na.id_articol = vd.id_articol
|
||||
left join nom_gestiuni ng on ng.id_gestiune = vd.id_gestiune
|
||||
left join nom_valute nv on nv.id_valuta = vd.id_valuta
|
||||
```
|
||||
|
||||
Consecinte concrete:
|
||||
|
||||
1. componentele de set apar in grid ca linii obisnuite, dar formularul **nu poate sti** ca sunt
|
||||
componente si nu poate edita capul de set (`VANZARI_SETURI.PRET`/`CANTITATE`), care e ceea ce
|
||||
intra efectiv in totaluri. Un utilizator care schimba pretul unei componente **nu schimba
|
||||
totalul documentului** — recalculul ia pretul din `VANZARI_SETURI`. Divergenta tacuta.
|
||||
2. `PRET_ACHIZITIE` lipseste din cursor, deci VFP nu-l poate rescrie la un `UPDATE` de linie: la
|
||||
scriere trebuie **omis din `SET`**, ca sa ramana valoarea existenta (altfel `VALOARE_ACHIZITIE`
|
||||
se pierde). Pentru liniile **noi** insa nu exista sursa — vor intra cu `PRET_ACHIZITIE` NULL si
|
||||
vor contribui cu NULL la `SUM(round(cantitate * pret_achizitie))`, deci **`VALOARE_ACHIZITIE`
|
||||
devine NULL pe tot documentul** daca fie si o singura linie noua are NULL. Vezi riscul R3.
|
||||
|
||||
---
|
||||
|
||||
## 4. Capcana de ordonare — punctul central
|
||||
|
||||
### Ce ruleaza azi, in ce ordine
|
||||
|
||||
Punctul de intrare nou (deja scris in ramura curenta):
|
||||
`COMUN\clase\ofacturare_comun.vc2`, `do_editare_factura`, blocul de salvare:
|
||||
|
||||
```
|
||||
3798 If Thisform.do_deschide_tranzactie() && SQLSetprop(gnHandle,"Transactions",2)
|
||||
3800 lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.) && marcheaza STERS=1 nota veche
|
||||
...
|
||||
3820 lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.) && scrie nota noua (COD nou din SCRIE_IN_ACT)
|
||||
3823 If lnSucces > 0
|
||||
3824 lcSql = [begin pack_contafin.finalizeaza_modificare_nota(...); end]
|
||||
3826 lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
|
||||
3827 Endif
|
||||
3828 If Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1)) && SQLCOMMIT / SQLROLLBACK
|
||||
```
|
||||
|
||||
`do_deschide_tranzactie` / `do_inchide_tranzactie`: `COMUN\clase\_frm_base.vc2:251-269` si
|
||||
`:278-302` — `SQLSetprop(gnHandle,"Transactions",2)` / `Sqlcommit(gnHandle)`.
|
||||
|
||||
`finalizeaza_modificare_nota` (`PACK_CONTAFIN.pck:8601-8651`) apeleaza `actualizeaza_vanzari` la
|
||||
`:8616`, gardat de `SELECT COUNT(*) FROM vanzari WHERE cod = tnCod > 0` (`:8613-8615`).
|
||||
|
||||
`actualizeaza_vanzari` (`PACK_FACTURARE.pck:16015-16025`):
|
||||
|
||||
```
|
||||
16018 -- de modificat in caz ca il las sa stearga manual inregistrari din VANZARI_DETALII
|
||||
16019 -- acum se marcheaza cu STERS = 1 doar cand se sterge toata factura
|
||||
16020 UPDATE VANZARI_DETALII
|
||||
16021 SET STERS = 0
|
||||
16022 WHERE ID_VANZARE IN
|
||||
16023 (SELECT ID_VANZARE FROM VANZARI WHERE COD = V_COD_VECHI);
|
||||
16024 UPDATE VANZARI SET COD = V_COD_NOU, STERS = 0 WHERE COD = V_COD_VECHI;
|
||||
```
|
||||
|
||||
### De ce exista `STERS = 0` acolo (nu e cod mort)
|
||||
|
||||
E perechea lui `sterge_din_vanzari` -> `sterge_factura`, care marcheaza documentul sters:
|
||||
|
||||
```
|
||||
5549 UPDATE VANZARI_DETALII
|
||||
5550 SET STERS = V_STERS, ID_UTILS = V_ID_UTIL, DATAORAS = V_DATAORA
|
||||
5551 WHERE ID_VANZARE = V_ID_VANZARE
|
||||
5552 AND STERS = V_NESTERS
|
||||
```
|
||||
|
||||
Reeditarea unei note sterse trebuie sa readuca la viata si randul din `VANZARI`, si liniile lui.
|
||||
**Scoaterea reset-ului ar rupe fluxul „stergi nota, apoi o reeditezi" pe toata suita ROA.**
|
||||
|
||||
### Consecinta pentru S5 — mai grava decat „stergerile se pierd"
|
||||
|
||||
Reset-ul e **in bloc, fara nicio garda**: nici `AND STERS = 1` (irelevant), nici o discriminare
|
||||
intre „stersa ca linie" si „stersa odata cu documentul". `sterge_factura` marcheaza doar liniile
|
||||
active (`AND STERS = V_NESTERS`, `:5552`), deci o linie stearsa la o editare anterioara ramane
|
||||
`STERS=1` — si e **inviata** de `actualizeaza_vanzari` la urmatoarea salvare a notei.
|
||||
|
||||
Deci daca liniile se scriu inainte de `finalizeaza_modificare_nota`:
|
||||
|
||||
- stergerile din editarea CURENTA se pierd tacut;
|
||||
- **si**, independent de ce face utilizatorul acum, orice stergere facuta la o editare
|
||||
ANTERIOARA e anulata la fiecare salvare ulterioara — inclusiv la o salvare care nu atinge deloc
|
||||
articolele. Stergerea de linie **nu s-ar fixa niciodata**.
|
||||
|
||||
`UPDATE`-urile de pret/cantitate si `INSERT`-urile de linii noi ar supravietui — deci esecul e
|
||||
partial si asimetric, exact tipul care trece de un test superficial.
|
||||
|
||||
### Variantele de ordonare
|
||||
|
||||
**(a) VFP scrie detaliile inainte, `actualizeaza_vanzari` neatinsa.**
|
||||
Respinsa. Motivul complet e cel de mai sus: nu doar ca stergerile din sesiunea curenta se pierd,
|
||||
dar mecanismul de stergere de linie devine structural imposibil, fiindca fiecare salvare a notei
|
||||
reseteaza tot documentul la `STERS = 0`. In plus, dupa `actualizeaza_vanzari` `VANZARI.COD` s-a
|
||||
schimbat, deci orice scriere ulterioara ancorata pe `cod` ar rata randul (`ID_VANZARE` ramane —
|
||||
vezi A.1 din raportul precedent, reconfirmat la `:16024`).
|
||||
|
||||
**(a') VFP scrie inainte + `actualizeaza_vanzari` primeste o garda.**
|
||||
Respinsa. Ar cere un discriminator „stearsa ca linie" vs „stearsa cu documentul", care nu exista in
|
||||
schema (`VANZARI_DETALII` nu are alt marcaj decat `STERS`/`ID_UTILS`/`DATAORAS`); orice euristica
|
||||
pe `DATAORAS` e fragila. Si e Varianta A din raportul precedent — modificare in-place a unei
|
||||
proceduri apelate de **orice** editare de nota cu `cod` in `vanzari`, din toata suita ROA.
|
||||
|
||||
**(b) VFP scrie detaliile DUPA ce `finalizeaza_modificare_nota` s-a intors, apoi apeleaza
|
||||
`pack_facturare.recalculeaza_totaluri_vanzari(id_vanzare, discount)`, in aceeasi tranzactie.**
|
||||
**RECOMANDATA.** Verificat, nu presupus:
|
||||
|
||||
- **tranzactia e inca deschisa** cand se intoarce `finalizeaza_modificare_nota`: aceasta ruleaza la
|
||||
`ofacturare_comun.vc2:3826`, iar `do_inchide_tranzactie` abia la `:3828`; tranzactia e manuala pe
|
||||
`gnHandle` (`_frm_base.vc2:255`), aceeasi conexiune ODBC pe care ruleaza `goExecutor`. Deci
|
||||
scrierile de dupa intra in acelasi `COMMIT`/`ROLLBACK`, fara fereastra de inconsistenta.
|
||||
- `actualizeaza_vanzari` ramane **neatinsa** — zero regresie pe ROAGEST/ROACONT.
|
||||
- `PACK_CONTAFIN` ramane **neatins** — nu se recompileaza pachetul central de scriere a
|
||||
documentelor.
|
||||
- reset-ul `STERS = 0` ruleaza primul, iar VFP re-aplica dupa el starea autoritativa a liniilor.
|
||||
- `VANZARI.COD` e deja rescris cand VFP scrie — de aceea toate scrierile se ancoreaza pe
|
||||
`ID_VANZARE` (`lnIdVanzare`, citit din `crsfacturi` la `ofacturare_comun.vc2:3735`, stabil).
|
||||
|
||||
**Atentie — (b) naiv are un defect.** `IncarcaArticoleFactura` incarca **doar `sters = 0`**
|
||||
(`ofacturare_editare.prg:302`), deci liniile sterse la o editare anterioara nu sunt in
|
||||
`crsArticoleFactura`: reset-ul le-a inviat, iar VFP nu le atinge, deci raman active. Corectia e in
|
||||
**forma scrierii**, nu in Oracle — VFP scrie o stare completa, nu un delta:
|
||||
|
||||
```
|
||||
1. UPDATE VANZARI_DETALII SET STERS = 1, ID_UTILS = ?, DATAORAS = SYSDATE
|
||||
WHERE ID_VANZARE = <id> AND STERS = 0 -- marcheaza tot
|
||||
2. pentru fiecare linie pastrata din cursor, cu id_vanzare_det > 0:
|
||||
UPDATE VANZARI_DETALII SET STERS = 0, CANTITATE = ?, PRET = ?, PRET_CU_TVA = ?, ...
|
||||
WHERE ID_VANZARE_DET = <det> -- invie doar ce ramane
|
||||
3. pentru fiecare linie noua: INSERT INTO VANZARI_DETALII (...) -- ID_VANZARE_DET din trigger
|
||||
4. pack_facturare.recalculeaza_totaluri_vanzari(<id>, <discount>)
|
||||
```
|
||||
|
||||
Idiomul „marcheaza tot, invie ce ramane" e idempotent, nu are limita de 1000 de elemente intr-un
|
||||
`IN`, nu cere lista separata de linii sterse, si pastreaza sterse liniile scoase la editari
|
||||
anterioare. La pasul 2, `PRET_ACHIZITIE` se **omite** din `SET` (nu e in cursor — vezi 3).
|
||||
|
||||
**(c) recalcul apelat din interiorul `finalizeaza_modificare_nota`** (recomandarea raportului
|
||||
precedent, sectiunea B). **De abandonat.** Este incompatibila cu (b): daca recalculul ruleaza
|
||||
inauntrul lui `finalizeaza_modificare_nota`, el vede liniile **vechi** (VFP nu le-a scris inca,
|
||||
pentru ca nu poate scrie inainte de reset), deci ar produce exact totalurile de dinainte de editare
|
||||
— tacut corecte ca formula, tacut gresite ca valoare. Nu e o varianta mai riscanta, e o varianta
|
||||
gresita.
|
||||
|
||||
**(c') procedura Oracle care primeste si liniile** (prin `VANZARI_DETALII_TEMP` sau o colectie) si
|
||||
face si scrierea, si recalculul. Respinsa: reintroduce calea TEMP pe care planul a exclus-o explicit
|
||||
(`plan_06_editare_factura.md:106-114`), cere o forma de parametru incomoda prin ODBC, si dubleaza
|
||||
scrierea per-linie pe care planul a decis-o deja in VFP, dupa modelul `modifica_explicatie_articol`
|
||||
(`PACK_FACTURARE.pck:14514-14522`).
|
||||
|
||||
### Recomandare
|
||||
|
||||
**Varianta (b), cu scrierea in forma „marcheaza tot, invie ce ramane".** Argumentul decisiv nu e
|
||||
comoditatea, ci ca e **singura ordine in care reset-ul `STERS = 0` din `actualizeaza_vanzari` ramane
|
||||
inofensiv fara sa modificam procedura** — iar procedura aceea e folosita azi de toata suita, pentru
|
||||
un scop legitim (reeditarea unei note sterse) pe care nu-l putem sacrifica.
|
||||
|
||||
---
|
||||
|
||||
## 5. Discountul de document (`VANZARI.DISCOUNT`)
|
||||
|
||||
**Cine il scrie azi: nimeni, dupa emitere.** Verificat pe toata schema, nu doar pe `PACK_FACTURARE`:
|
||||
|
||||
- `all_source` (`PACKAGE BODY`/`PROCEDURE`/`FUNCTION`/`TRIGGER`, `MARIUSM_AUTO`), cautand
|
||||
`discount\s*=` exclusiv coloanele `discount_unitar|discount_tva|discount_evidentiat`: **niciun
|
||||
`UPDATE ... SET DISCOUNT = ...` pe `VANZARI`.** Rezultatele sunt toate pe alte tabele
|
||||
(`PACK_COMENZI.PROC_DISCOUNT`, `PACK_CRM.val_discount`, `PACK_OFERTARE.valdiscount`, ...).
|
||||
- Toate cele 8 instructiuni `UPDATE VANZARI` din `PACK_FACTURARE` (`:5485, :5493, :5516, :5615,
|
||||
:14817, :15387, :15397, :15509`) plus `modifica_date_factura` (`:14463-14512`, singura procedura
|
||||
de „modifica antetul facturii" existenta) ating `STERS`/`FACTURAT`/`ID_FACT`/`AVIZE`/
|
||||
`SERIE_ACT`/`NUMAR_ACT`/`DATA_ACT`/`DATA_SCAD` — **niciuna `DISCOUNT`**.
|
||||
- In VFP: cautare pe `COMUN\` dupa `set discount =` / `vanzari set ... discount` — **niciun
|
||||
rezultat**.
|
||||
- Trigger-ele pe `VANZARI` nu-l ating: `TRG_VANZARI_BEFOUPD` face doar audit pe
|
||||
`NR_ACT`/`SERIE_ACT`/`DATA_ACT`/`DATA_SCAD` (`pack_audit.verifica_val`).
|
||||
|
||||
Deci `VANZARI.DISCOUNT` e scris **o singura data in viata documentului**, la `INSERT`-ul din
|
||||
`scrie_in_vanzari` (`:13621` in lista de coloane, `:13682` in `VALUES`, din `V_DISCOUNT_FACTURA`).
|
||||
Nu exista nici procedura de modificare, nici cale VFP.
|
||||
|
||||
Pe partea VFP valoarea e deja disponibila in memorie: cursorul `tvanz` are coloana `discount`
|
||||
(`ofacturare_editare.prg:152`, `CreeazaCursorTvanzGol`), populata din `VANZARI` de
|
||||
`IncarcaVanzareNota` (`:176`).
|
||||
|
||||
### Recomandare: **parametru al procedurii noi**, nu `UPDATE` separat din VFP
|
||||
|
||||
```
|
||||
recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER, V_DISCOUNT IN NUMBER DEFAULT NULL)
|
||||
```
|
||||
|
||||
cu semantica `V_DISCOUNT IS NULL` = „pastreaza valoarea curenta". Motive:
|
||||
|
||||
1. **discountul si totalurile nu pot diverge.** Cu doua instructiuni separate din VFP, un esec pe
|
||||
a doua (sau o omisiune la un viitor call-site) lasa `DISCOUNT` nou si totaluri calculate pe cel
|
||||
vechi. Cu un parametru, e imposibil sa recalculezi cu un discount invechit.
|
||||
2. procedura ramane utilizabila ca **recalcul pur** (fara al doilea argument) de oriunde altundeva
|
||||
— de exemplu dintr-un script de backfill.
|
||||
3. e o instructiune ODBC in minus pe drumul critic.
|
||||
|
||||
Implementare: `V_DISCOUNT` se aplica in acelasi `UPDATE vanzari` final,
|
||||
`discount = NVL(V_DISCOUNT, discount)`, iar valoarea folosita in agregare se citeste **inainte**,
|
||||
ca `NVL(V_DISCOUNT, (select discount from vanzari where id_vanzare = V_ID_VANZARE))` — altfel
|
||||
agregarea ar lucra pe discountul vechi.
|
||||
|
||||
---
|
||||
|
||||
## 6. Coloanele care NU se recalculeaza — reconfirmat pe sursa proaspata
|
||||
|
||||
`SERIE_INCASAT` / `NR_INCASAT` / `SUMA_INCASAT` / `TIP_INCASAT` (`:13777-13780`, scrise la
|
||||
`:13945-13948`) vin din `pack_facturare.cserie_act_incasare` / `nnumar_act_incasare` /
|
||||
`nsuma_incasare` / `ntip_doc_incasare`.
|
||||
|
||||
Cautare exhaustiva a atribuirilor catre aceste 4 variabile in `PACK_FACTURARE.pck` — **7 rezultate,
|
||||
toate in fluxul de emitere**:
|
||||
|
||||
```
|
||||
1882-1886 cserie_act_incasare := NULL; nnumar_act_incasare := NULL;
|
||||
ntip_doc_incasare := NULL; nsuma_incasare := NULL; (initializeaza_date_factura)
|
||||
13102-13105 cserie_act_incasare := V_SERIE_ACT_INCASARE; nnumar_act_incasare := V_NUMAR_ACT_INCASARE;
|
||||
ntip_doc_incasare := nTipIncasareChitanta; nsuma_incasare := 0;
|
||||
13136 nsuma_incasare := nsuma_incasare + ...
|
||||
13140,13144 ntip_doc_incasare := V_TIP / nTipIncasareBonFiscal;
|
||||
```
|
||||
|
||||
Sursele lor (`V_SERIE_ACT_INCASARE`, `V_NUMAR_ACT_INCASARE`) sunt parametri ai emiterii unei
|
||||
facturi-cu-incasare combinata. **Nu exista nicio tabela din care sa fie reconstituite la o editare
|
||||
ulterioara** — singura urma persistenta sunt chiar cele 4 coloane din `VANZARI`, care ar fi
|
||||
suprascrise cu `NULL` de o copiere naiva a `UPDATE`-ului.
|
||||
|
||||
**Concluzie reconfirmata: procedura noua scrie 11 coloane** (`discount_tva`, `valoare_achizitie`,
|
||||
`total_fara_tva`, `total_tva`, `total_cu_tva`, `valval`, `tvaval`, `totval`, `id_valuta`, `curs`,
|
||||
`multiplicator`), **plus optional `discount`** (vezi 5). Cele 4 de incasare raman la valoarea de la
|
||||
emitere.
|
||||
|
||||
---
|
||||
|
||||
## 7. Semnatura propusa si scripturile de migrare
|
||||
|
||||
### Declaratia din PACKAGE SPEC
|
||||
|
||||
Se adauga imediat dupa `actualizeaza_vanzari` (`PACK_FACTURARE.pck:1187-1188`), langa procedurile
|
||||
surori:
|
||||
|
||||
```sql
|
||||
PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER,
|
||||
V_DISCOUNT IN NUMBER DEFAULT NULL);
|
||||
```
|
||||
|
||||
`recalculeaza_totaluri_vanzari` = **29 de caractere**, sub limita de 30 a lui Oracle 10.2/11
|
||||
(peste 30 ar da `ORA-00972`). Nu mai lungi numele.
|
||||
|
||||
### Corpul (schita, compatibila 10.2)
|
||||
|
||||
Constructii folosite: `SELECT INTO`, `UPDATE`, `DECODE`, `CASE`, `NVL`, `ROUND`, `MAX`, `SUM`,
|
||||
`LEFT JOIN`, `UNION ALL`, `GROUP BY`, subinterogari inline. **Nimic din tabelul de incompatibilitati
|
||||
din `scripturi-migrare-db.md`** — fara `LISTAGG`, `CONTINUE`, `REGEXP_COUNT`, `FETCH FIRST`,
|
||||
`PIVOT`, `secventa.NEXTVAL` in atribuire.
|
||||
|
||||
```sql
|
||||
PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER,
|
||||
V_DISCOUNT IN NUMBER DEFAULT NULL) IS
|
||||
lnDiscountFactura VANZARI.DISCOUNT%TYPE;
|
||||
lnInValuta VANZARI.IN_VALUTA%TYPE;
|
||||
lnDiscountEvidentiat VANZARI.DISCOUNT_EVIDENTIAT%TYPE;
|
||||
lnDiscountTVA VANZARI.DISCOUNT_TVA%TYPE;
|
||||
lnValoareAchizitie VANZARI.VALOARE_ACHIZITIE%TYPE;
|
||||
lnTotalFaraTVA VANZARI.TOTAL_FARA_TVA%TYPE;
|
||||
lnTotalTVA VANZARI.TOTAL_TVA%TYPE;
|
||||
lnTotalCuTVA VANZARI.TOTAL_CU_TVA%TYPE;
|
||||
lnValVal VANZARI.VALVAL%TYPE;
|
||||
lnTVAVal VANZARI.TVAVAL%TYPE;
|
||||
lnTotVal VANZARI.TOTVAL%TYPE;
|
||||
lnIdValuta VANZARI.ID_VALUTA%TYPE;
|
||||
lnCurs VANZARI.CURS%TYPE;
|
||||
lnMultiplicator VANZARI.MULTIPLICATOR%TYPE;
|
||||
lnPrecizieCalcul NUMBER(2) := pack_sesiune.getOptiuneFirma('PC');
|
||||
lnPreciziePretV NUMBER(2) := pack_sesiune.getOptiuneFirma('PPRETV');
|
||||
BEGIN
|
||||
SELECT NVL(V_DISCOUNT, discount), in_valuta, NVL(discount_evidentiat, 0)
|
||||
INTO lnDiscountFactura, lnInValuta, lnDiscountEvidentiat
|
||||
FROM vanzari
|
||||
WHERE id_vanzare = V_ID_VANZARE;
|
||||
|
||||
-- acelasi bloc de agregare ca in scrie_in_vanzari (:13764-13931), cu trei substitutii:
|
||||
-- VANZARI_DETALII_TEMP a -> VANZARI_DETALII a WHERE a.id_vanzare = V_ID_VANZARE AND a.sters = 0
|
||||
-- vanzari_detalii_temp c -> vanzari_detalii c WHERE c.id_vanzare = V_ID_VANZARE AND c.sters = 0
|
||||
-- pack_facturare.nin_valuta -> lnInValuta
|
||||
-- pack_facturare.ndiscount_evidentiat -> lnDiscountEvidentiat
|
||||
-- V_DISCOUNT_FACTURA -> lnDiscountFactura
|
||||
-- fara coloanele de incasare (serie/nr/suma/tip)
|
||||
SELECT ... INTO lnDiscountTVA, lnValoareAchizitie, lnTotalFaraTVA, lnTotalTVA,
|
||||
lnTotalCuTVA, lnValVal, lnTVAVal, lnTotVal,
|
||||
lnIdValuta, lnCurs, lnMultiplicator
|
||||
FROM ( ... );
|
||||
|
||||
UPDATE vanzari
|
||||
SET discount = lnDiscountFactura,
|
||||
discount_tva = lnDiscountTVA,
|
||||
valoare_achizitie = lnValoareAchizitie,
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
total_tva = lnTotalTVA,
|
||||
total_cu_tva = lnTotalCuTVA,
|
||||
valval = lnValVal,
|
||||
tvaval = lnTVAVal,
|
||||
totval = lnTotVal,
|
||||
id_valuta = lnIdValuta,
|
||||
curs = lnCurs,
|
||||
multiplicator = lnMultiplicator
|
||||
WHERE id_vanzare = V_ID_VANZARE;
|
||||
END recalculeaza_totaluri_vanzari;
|
||||
```
|
||||
|
||||
Idempotenta: `SELECT` + `UPDATE ... WHERE id_vanzare = :id`, fara `INSERT` — rularea de doua ori pe
|
||||
acelasi id da acelasi rezultat.
|
||||
|
||||
**Fara handler `WHEN NO_DATA_FOUND THEN NULL`** pe modelul originalului: la editare, un `id_vanzare`
|
||||
inexistent e o eroare reala care trebuie sa opreasca tranzactia, nu sa fie inghitita. (Primul
|
||||
`SELECT INTO`, pe cheia primara, e singurul care poate ridica `NO_DATA_FOUND`.)
|
||||
|
||||
### Scripturile de migrare
|
||||
|
||||
Azi, 09.08.2026, in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08` nu exista niciun script cu data de azi
|
||||
(ultimele sunt `..._2026_08_08_01` si `..._2026_08_08_02`), deci **`NN` porneste de la `01`**.
|
||||
`NN` e secventa unica pe zi, comuna tuturor prefixelor.
|
||||
|
||||
**Un singur script**, fiindca S5 atinge un singur pachet si nimic altceva:
|
||||
|
||||
```
|
||||
ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql
|
||||
```
|
||||
|
||||
- prefix `ff_` — pachetul sta pe schema fiecarei firme;
|
||||
- **un pachet sta singur in scriptul lui**: fara DDL de tabele si fara DML alaturi (nu e nevoie de
|
||||
niciunul — nu se adauga coloane si nu se curata date);
|
||||
- contine SPEC + BODY (SPEC-ul se schimba: declaratia noua), CRLF obligatoriu, antet de 4-5 randuri,
|
||||
fara `select` de raportare, si se incheie cu
|
||||
`exec pack_migrare.UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql');` + `commit;`;
|
||||
- `versiune_db.txt` din radacina proiectului se muta pe `2026_08_09_01` (fara newline final).
|
||||
|
||||
**Nu e nevoie de un script separat pentru `VVANZARI_ARTICOLE`** pentru S5 asa cum e proiectat aici
|
||||
— dar vezi intrebarea 3 de mai jos, care ar cere unul (`NN = 02`, si atunci **inainte** de cel al
|
||||
pachetului daca pachetul l-ar folosi; aici nu-l foloseste, deci ordinea e libera).
|
||||
|
||||
---
|
||||
|
||||
## 8. Riscuri si intrebari deschise
|
||||
|
||||
**R1 — Componentele de set sunt editabile in grid dar nu influenteaza totalurile. (mediu)**
|
||||
`VVANZARI_ARTICOLE` nu expune `ID_VANZARE_SET`, deci S4 nu poate distinge componentele de liniile
|
||||
normale; recalculul ia insa pretul/cantitatea din `VANZARI_SETURI`, nu din componente. Utilizatorul
|
||||
modifica o componenta, apasa salvare, totalul nu se schimba. Tacut.
|
||||
*Recomandarea mea:* pentru #6, **adauga `ID_VANZARE_SET` in `VVANZARI_ARTICOLE`** (script separat,
|
||||
`ff_2026_08_09_02_COMUN_VVANZARI_ARTICOLE.sql`) si fa liniile cu `id_vanzare_set` nenul
|
||||
**needitabile in grid**, cu o eticheta („linie din set"). Editarea seturilor e o functionalitate
|
||||
proprie, nu o extindere gratuita a lui S4. Alternativa minimala, daca Marius nu vrea scriptul de
|
||||
view: blocheaza intreaga factura care contine seturi — dar asta contrazice decizia din
|
||||
`plan_06_editare_factura.md:183-186` („fara blocarea facturilor care le contin").
|
||||
|
||||
**R2 — Stergerea unei componente de set. (mic, dar urat)**
|
||||
Cu idiomul „marcheaza tot, invie ce ramane", stergerea in grid a unei componente lasa capul de set
|
||||
in `VANZARI_SETURI` si celelalte componente pe loc: totalul ramane neschimbat (vine din cap), dar
|
||||
`VALOARE_ACHIZITIE` scade (se pierde `pret_achizitie`-ul componentei). Divergenta partiala.
|
||||
*Recomandare:* acoperit de R1 — daca liniile de set sunt needitabile, cazul dispare.
|
||||
|
||||
**R3 — `PRET_ACHIZITIE` NULL pe liniile noi anuleaza `VALOARE_ACHIZITIE` pe tot documentul. (mediu)**
|
||||
`SUM(round(cantitate * pret_achizitie))` cu un singur operand NULL nu da NULL pe total (SUM ignora
|
||||
NULL-urile), dar **linia noua nu contribuie deloc** — deci `VALOARE_ACHIZITIE` (baza de calcul a
|
||||
marjei) subestimeaza sistematic dupa fiecare adaugare de linie. Coloana nu e in cursorul din grid si
|
||||
nu are sursa la editare (la emitere vine din stoc/politica de pret).
|
||||
*Recomandare:* la `INSERT`-ul liniei noi, VFP scrie `PRET_ACHIZITIE` cu pretul de achizitie curent
|
||||
al articolului (acelasi lookup pe care il face `adauga_articol_factura_stoc`), sau, daca nu se poate
|
||||
determina, cu `0` explicit si o avertizare in verificarile din S4b. **Nu lasa NULL tacut.**
|
||||
|
||||
**R4 — Factura fara nicio linie da totaluri NULL, nu 0. (mic)**
|
||||
Agregatele pe zero randuri intorc NULL; la emitere cazul nu poate aparea, la editare da.
|
||||
*Recomandare:* nu modifica formula (ar diverge de original). Interzice in S4b salvarea unei facturi
|
||||
cu zero linii active — e oricum un document invalid.
|
||||
|
||||
**R5 — Linie cu valuta fara rand in `VANZARI_CURSURI`. (mic)**
|
||||
`left join vanzari_cursuri vc on vc.id_vanzare = V_ID_VANZARE and vd.id_valuta = vc.id_valuta`
|
||||
(`:13929-13930`): daca o linie ajunge cu o valuta pentru care documentul nu are curs, `vc.curs` e
|
||||
NULL si `pret_ron` iese NULL. `CreeazaPoArticolNouTvd` primeste explicit valuta documentului
|
||||
(`tnIdValutaDoc`, `ofacturare_editare.prg:356`), deci in fluxul proiectat nu ar trebui sa apara.
|
||||
**NEVERIFICAT** ca S4 chiar transmite acel parametru pe toate caile de adaugare.
|
||||
*Recomandare:* verificare in S4b, nu garda in Oracle.
|
||||
|
||||
**R6 — `pack_sesiune.getOptiuneFirma` intoarce `''` la orice eroare. (mic)**
|
||||
`PACK_SESIUNE` body `:128-131`: `WHEN OTHERS THEN lcValue := ''`. Atribuit intr-un `NUMBER(2)`, `''`
|
||||
devine NULL, iar `ROUND(x, NULL)` da NULL. Comportament identic cu cel de la emitere — deci nu e o
|
||||
regresie introdusa de S5, dar merita stiut daca apar totaluri NULL inexplicabile.
|
||||
*Recomandare:* nimic de facut in S5; consemnat pentru depanare.
|
||||
|
||||
**R7 — `ff_2026_08_08_01_COMUN_VVD_TOT.sql` aplicat in dev fara script pe disc. (de clarificat)**
|
||||
Obiectul nu exista in `all_objects` sub niciun nume `VVD%`, deci probabil scriptul a creat altceva
|
||||
sau a fost anulat ulterior. Fisierul lipseste din `SCRIPTURI_CLAR` -> nu ajunge la clienti.
|
||||
*Recomandare:* intrebare pentru Marius, nu blocheaza S5.
|
||||
|
||||
### Intrebari pentru Marius
|
||||
|
||||
1. **Liniile de set (R1)** — le facem needitabile in grid, cu `ID_VANZARE_SET` adaugat in
|
||||
`VVANZARI_ARTICOLE` printr-un al doilea script? *Recomandarea mea: da.* Fara asta, editarea unei
|
||||
facturi cu seturi arata ca merge si nu merge.
|
||||
2. **Discountul de document** — parametru al procedurii (`V_DISCOUNT ... DEFAULT NULL`), sau
|
||||
`UPDATE VANZARI SET DISCOUNT` separat din VFP? *Recomandarea mea: parametru*, ca discountul si
|
||||
totalurile sa nu poata diverge (vezi 5).
|
||||
3. **`PRET_ACHIZITIE` pe linia noua (R3)** — se citeste din nomenclator/stoc la adaugare, sau se
|
||||
scrie `0` cu avertizare? *Recomandarea mea: citit din nomenclator*, cu `0` doar ca ultima
|
||||
rezerva, niciodata NULL.
|
||||
4. **`VALVAL`/`TVAVAL`/`TOTVAL`** — raman in recalcul? *Recomandarea mea: da* (cost zero, fac parte
|
||||
din acelasi `SELECT`; excluderea lor ar lasa facturile in valuta inconsistente). Confirmare
|
||||
ceruta si in raportul precedent, inca neconfirmata.
|
||||
5. **`ff_2026_08_08_01_COMUN_VVD_TOT.sql`** — script de lucru abandonat, sau lipseste din SVN?
|
||||
|
||||
---
|
||||
|
||||
## Ce a ramas neverificat
|
||||
|
||||
- **R5**: nu am verificat pe codul S4 in lucru ca `CreeazaPoArticolNouTvd` primeste efectiv valuta
|
||||
documentului pe toate caile de adaugare de linie.
|
||||
- Nu am rulat nimic in Oracle in afara de `SELECT`-uri de dictionar si de export — **niciun DDL,
|
||||
niciun DML, niciun test de executie a procedurii propuse.** Corpul propus la 7 e schita, nu cod
|
||||
compilat.
|
||||
- Numarul de documente cu seturi in `MARIUSM_AUTO` (4) e din date de test si **nu constituie
|
||||
dovada** pentru niciuna dintre afirmatiile de mai sus; toate concluziile sunt din cod.
|
||||
@@ -1,9 +1,9 @@
|
||||
# S5 — testul cu scriere reala in Oracle. Rezultat
|
||||
|
||||
Aprobat de Marius (09.08.2026, consemnat in `docs\handoff_s5.md`). Suita:
|
||||
Aprobat de Marius (09.08.2026, consemnat in handoff intermediar (sters)). Suita:
|
||||
`COMUN\utile\Teste\editare_factura\test_s5_scriere_reala.prg`. Log:
|
||||
`COMUN\utile\Teste\editare_factura\test_s5_scriere_reala_log.txt` (rulare 09.08.2026 23:41:32-23:41:35).
|
||||
Diff: `docs\diff_s5_test_scriere_reala.patch`.
|
||||
Diff: diff aplicat (sters).
|
||||
|
||||
## Rezultat
|
||||
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
# Verificare script Oracle S5 — PACK_FACTURARE.recalculeaza_totaluri_vanzari
|
||||
|
||||
Data: 09.08.2026. Livrabil: `docs/ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (823433 octeti,
|
||||
17231 randuri; 17010->17231 fata de `.pck`-ul sursa, +221 randuri de continut adaugat).
|
||||
|
||||
Construit programatic dintr-un script PowerShell (nu retastat): citeste `PACK_FACTURARE.pck`
|
||||
(export proaspat, scratchpad, 810960 octeti, 17011 randuri) ca octeti ASCII, insereaza declaratia
|
||||
noua in SPEC dupa `actualizeaza_vanzari` si corpul nou in BODY dupa `actualizeaza_vanzari`, adauga
|
||||
`CREATE OR REPLACE` pe cele doua linii de start (absente in exportul brut din `all_source`),
|
||||
antetul si coada, si scrie rezultatul CRLF. Fiecare punct de insertie e verificat printr-un
|
||||
assert pe textul exact al ancorei (throw daca nu se potriveste) — scriptul s-a oprit si a fost
|
||||
corectat de doua ori in timpul lucrului (vezi „Erori prinse" mai jos), rularea finala a trecut
|
||||
toate ancorele.
|
||||
|
||||
## Ce s-a facut
|
||||
|
||||
1. **PACKAGE SPEC** (`.pck:1187-1189`): dupa declaratia `actualizeaza_vanzari`, s-a inserat
|
||||
`PROCEDURE recalculeaza_totaluri_vanzari(V_ID_VANZARE IN NUMBER, V_DISCOUNT IN NUMBER DEFAULT
|
||||
NULL);` — text identic cu cel din brief.
|
||||
2. **PACKAGE BODY** (`.pck:16015-16025`, dupa `END actualizeaza_vanzari;`): s-a inserat procedura
|
||||
noua, corpul fiind blocul de agregare din `scrie_in_vanzari` (`.pck:13762-13954`) cu substitutiile
|
||||
cerute, plus SELECT-ul de discount/in_valuta/discount_evidentiat inainte, plus `discount` in
|
||||
UPDATE, fara handler de exceptie — toate exact ca in sectiunea 7 a specificatiei.
|
||||
3. Antet de 6 randuri (4 randuri text + 1 rand `--` gol + titlu), fara referinte la planuri/rapoarte.
|
||||
4. Coada: `exec pack_migrare.UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql'); commit;`
|
||||
|
||||
## Verificari cerute, cu cifre
|
||||
|
||||
**CRLF** — octeti LF fara CR inainte in fisierul final: **0**.
|
||||
|
||||
**Nume sub 30 caractere** — `'recalculeaza_totaluri_vanzari'.Length` = **29**. Confirmat.
|
||||
|
||||
**Diff-ul blocului de agregare** — original (`.pck:13762-13954`, 193 randuri, citat integral in
|
||||
`rec_s5_proiectare_oracle.md` sectiunea 2) vs. blocul nou din procedura (extras din fisierul
|
||||
livrat). Generat cu `diff -u -b` (ignora *doar* diferentele de cantitate de spatiu — necesar
|
||||
pentru ca tot blocul a fost mutat cu un nivel de indentare mai putin, vezi nota de mai jos; `-b`
|
||||
nu ascunde nicio diferenta de continut). Diff-ul integral:
|
||||
|
||||
```diff
|
||||
--- orig_block.txt (PACK_FACTURARE.pck:13762-13954)
|
||||
+++ new_block.txt (recalculeaza_totaluri_vanzari, corpul agregarii)
|
||||
@@ -1,5 +1,4 @@
|
||||
- -- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
- begin
|
||||
+-- Completare totaluri in vanzari din vanzari_detalii pentru a usura selectiile din fact_vfacturi
|
||||
select DISC_TVA_VAL AS DISCOUNT_TVA,
|
||||
VALOARE_ACHIZITIE,
|
||||
a.suma_fara_tva_ron - a.disc_fara_tva_ron as TOTAL_FARA_TVA,
|
||||
@@ -12,11 +11,7 @@
|
||||
a.disc_tva_val as TOTVAL,
|
||||
id_valuta,
|
||||
curs,
|
||||
- multiplicator,
|
||||
- pack_facturare.cserie_act_incasare as SERIE_INCASAT,
|
||||
- pack_facturare.nnumar_act_incasare as NR_INCASAT,
|
||||
- pack_facturare.nsuma_incasare AS SUMA_INCASAT,
|
||||
- pack_facturare.ntip_doc_incasare as TIP_INCASAT
|
||||
+ multiplicator
|
||||
INTO lnDiscountTVA,
|
||||
lnValoareAchizitie,
|
||||
lnTotalFaraTVA,
|
||||
@@ -27,29 +22,25 @@
|
||||
lnTotVal,
|
||||
lnIdValuta,
|
||||
lnCurs,
|
||||
- lnMultiplicator,
|
||||
- lnSerieIncasat,
|
||||
- lnNrIncasat,
|
||||
- lnSumaIncasat,
|
||||
- lnTipIncasat
|
||||
- FROM (select MAX(decode(pack_facturare.nin_valuta,
|
||||
+ lnMultiplicator
|
||||
+ FROM (select MAX(decode(lnInValuta,
|
||||
1,
|
||||
- ROUND(a1.curs * NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
+ ROUND(a1.curs * NVL(lnDiscountFactura, 0) /
|
||||
a1.multiplicator,
|
||||
lnPreciziePretV),
|
||||
- NVL(V_DISCOUNT_FACTURA, 0))) as DISC_FARA_TVA_RON,
|
||||
- NVL(V_DISCOUNT_FACTURA, 0) as DISC_FARA_TVA_VAL,
|
||||
- pack_facturare.nin_valuta AS IN_VALUTA,
|
||||
- MAX(ROUND(decode(pack_facturare.nin_valuta,
|
||||
+ NVL(lnDiscountFactura, 0))) as DISC_FARA_TVA_RON,
|
||||
+ NVL(lnDiscountFactura, 0) as DISC_FARA_TVA_VAL,
|
||||
+ lnInValuta AS IN_VALUTA,
|
||||
+ MAX(ROUND(decode(lnInValuta,
|
||||
1,
|
||||
ROUND(a1.curs *
|
||||
- NVL(V_DISCOUNT_FACTURA, 0) /
|
||||
+ NVL(lnDiscountFactura, 0) /
|
||||
a1.multiplicator,
|
||||
lnPreciziePretV),
|
||||
- NVL(V_DISCOUNT_FACTURA, 0)) *
|
||||
+ NVL(lnDiscountFactura, 0)) *
|
||||
(a1.proc_tvav - 1),
|
||||
lnPreciziePretV)) as DISC_TVA_RON,
|
||||
- MAX(ROUND(NVL(V_DISCOUNT_FACTURA, 0) *
|
||||
+ MAX(ROUND(NVL(lnDiscountFactura, 0) *
|
||||
(a1.proc_tvav - 1),
|
||||
lnPreciziePretV)) as DISC_TVA_VAL,
|
||||
sum(pack_facturare.calculeaza_total_fara_tva_fact(a1.pret_ron,
|
||||
@@ -57,7 +48,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_ron,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) AS SUMA_FARA_TVA_RON,
|
||||
@@ -66,7 +57,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_ron,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) as SUMA_TVA_RON,
|
||||
@@ -75,7 +66,7 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_val,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) AS SUMA_FARA_TVA_VAL,
|
||||
@@ -84,18 +75,18 @@
|
||||
1,
|
||||
NVL(a1.discount_unitar_val,
|
||||
0),
|
||||
- pack_facturare.ndiscount_evidentiat,
|
||||
+ lnDiscountEvidentiat,
|
||||
a1.cantitate,
|
||||
a1.pret_cu_tva,
|
||||
a1.proc_tvav)) as SUMA_TVA_VAL,
|
||||
sum(round(a1.cantitate * a1.pret_achizitie,
|
||||
lnPrecizieCalcul)) AS VALOARE_ACHIZITIE,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.curs, 1)) as curs,
|
||||
- max(decode(pack_facturare.nin_valuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
+ max(decode(lnInValuta, 1, a1.id_valuta, 0)) as id_valuta,
|
||||
+ max(decode(lnInValuta, 1, a1.curs, 1)) as curs,
|
||||
+ max(decode(lnInValuta, 1, a1.multiplicator, 1)) as multiplicator
|
||||
from (select vd.id_vanzare_set,
|
||||
(case
|
||||
- when (pack_facturare.nin_valuta = 1 or
|
||||
+ when (lnInValuta = 1 or
|
||||
vd.id_valuta <>
|
||||
pack_def.GetIdMonedaNationala()) then
|
||||
ROUND(vc.curs * vd.pret / vc.multiplicator,
|
||||
@@ -108,7 +99,7 @@
|
||||
vd.cantitate,
|
||||
vd.diferenta,
|
||||
(case
|
||||
- when (pack_facturare.nin_valuta = 1 or
|
||||
+ when (lnInValuta = 1 or
|
||||
vd.id_valuta <>
|
||||
pack_def.GetIdMonedaNationala()) then
|
||||
ROUND(vc.curs * vd.discount_unitar /
|
||||
@@ -132,8 +123,10 @@
|
||||
a.id_valuta,
|
||||
a.pret_cu_tva,
|
||||
a.pret_achizitie
|
||||
- from VANZARI_DETALII_TEMP a
|
||||
+ from VANZARI_DETALII a
|
||||
where nvl(a.id_vanzare_set, 0) = 0
|
||||
+ and a.id_vanzare = V_ID_VANZARE
|
||||
+ and a.sters = 0
|
||||
union all
|
||||
select b.id_vanzare_set,
|
||||
b.pret,
|
||||
@@ -141,7 +134,7 @@
|
||||
b.cantitate,
|
||||
0 as diferenta,
|
||||
b.discount_unitar,
|
||||
- decode(pack_facturare.nin_valuta,
|
||||
+ decode(lnInValuta,
|
||||
0,
|
||||
pack_def.GetIdMonedaNationala(),
|
||||
c.id_valuta) as id_valuta,
|
||||
@@ -151,17 +144,19 @@
|
||||
0,
|
||||
c.pret_achizitie * c.cantitate /
|
||||
b.cantitate)) as pret_achizitie
|
||||
- from vanzari_detalii_temp c
|
||||
+ from vanzari_detalii c
|
||||
left join vanzari_seturi b
|
||||
on b.id_vanzare_set = c.id_vanzare_set
|
||||
where nvl(c.id_vanzare_set, 0) <> 0
|
||||
- and nvl(pack_facturare.nin_valuta, -1) > -1
|
||||
+ and c.id_vanzare = V_ID_VANZARE
|
||||
+ and c.sters = 0
|
||||
+ and nvl(lnInValuta, -1) > -1
|
||||
group by b.id_vanzare_set,
|
||||
b.pret,
|
||||
b.cantitate,
|
||||
b.discount_unitar,
|
||||
b.pret_cu_tva,
|
||||
- decode(pack_facturare.nin_valuta,
|
||||
+ decode(lnInValuta,
|
||||
0,
|
||||
pack_def.GetIdMonedaNationala(),
|
||||
c.id_valuta)) vd
|
||||
@@ -170,7 +165,8 @@
|
||||
and vd.id_valuta = vc.id_valuta) a1) a;
|
||||
|
||||
update vanzari
|
||||
- set discount_tva = lnDiscountTVA,
|
||||
+ set discount = lnDiscountFactura,
|
||||
+ discount_tva = lnDiscountTVA,
|
||||
valoare_achizitie = lnValoareAchizitie,
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
total_tva = lnTotalTVA,
|
||||
@@ -180,14 +176,5 @@
|
||||
totval = lnTotVal,
|
||||
id_valuta = lnIdValuta,
|
||||
curs = lnCurs,
|
||||
- multiplicator = lnMultiplicator,
|
||||
- serie_incasat = lnSerieIncasat,
|
||||
- nr_incasat = lnNrIncasat,
|
||||
- suma_incasat = lnSumaIncasat,
|
||||
- tip_incasat = lnTipIncasat
|
||||
+ multiplicator = lnMultiplicator
|
||||
where id_vanzare = V_ID_VANZARE;
|
||||
-
|
||||
- exception
|
||||
- when NO_DATA_FOUND then
|
||||
- null;
|
||||
- end;
|
||||
```
|
||||
|
||||
Diff-ul contine **exact**: cele 6 substitutii din tabelul din brief (`nin_valuta`->`lnInValuta` x11,
|
||||
`ndiscount_evidentiat`->`lnDiscountEvidentiat` x4, `NVL(V_DISCOUNT_FACTURA, 0)`->
|
||||
`NVL(lnDiscountFactura, 0)` x6, cele doua perechi FROM/WHERE), eliminarea celor 4 coloane de
|
||||
incasare din SELECT/INTO/UPDATE (cu fixarea virgulei ramase), adaugarea `discount =
|
||||
lnDiscountFactura,` in UPDATE si eliminarea wrapper-ului `begin ... exception ... end;` (cerut
|
||||
explicit: „Fara handler WHEN NO_DATA_FOUND THEN NULL"). **Nicio alta diferenta de continut.**
|
||||
|
||||
Nota pe metoda: `-b` a fost necesar (nu `diff` simplu) pentru ca tot blocul, o data scos din
|
||||
`begin...end;`-ul intern, a coborat cu un nivel de indentare (2 spatii) — o consecinta mecanica,
|
||||
uniforma, a aplatizarii cerute de sectiunea 7, nu o modificare de continut. Fara `-b`, diff-ul ar
|
||||
fi aratat *toate* liniile ca schimbate, desi doar spatiul de inceput difera pe liniile
|
||||
neatinse de tabelul de substitutii (verificat separat: liniile fara nicio substitutie, ex.
|
||||
`select DISC_TVA_VAL AS DISCOUNT_TVA,`, `VALOARE_ACHIZITIE,`, nu apar deloc in diff-ul de mai sus).
|
||||
|
||||
**`;` in comentarii `--` in interiorul unei instructiuni** — 11 aparitii ale tiparului `--.*;` in
|
||||
tot fisierul, **toate preexistente** in codul neatins (`scrie_incasari`, `contabilizeaza_articol`
|
||||
etc., linii 5908-14852 din script), **niciuna** introdusa de mine (verificat separat: 0 in antetul
|
||||
nou, 0 in declaratia SPEC noua, 0 in corpul noii proceduri). Riscul descris in
|
||||
`scripturi-migrare-db.md` (SP2-0734) se aplica instructiunilor SQL terminate cu `;`
|
||||
(`CREATE VIEW` etc.); intregul script de fata e un singur bloc `CREATE OR REPLACE PACKAGE`/
|
||||
`PACKAGE BODY` terminat cu `/`, deci riscul nu se aplica structural — dar cifra e cea ceruta.
|
||||
|
||||
**Constructii peste Oracle 10.2** — scanat corpul noii proceduri pentru
|
||||
`LISTAGG|CONTINUE|REGEXP_COUNT|FETCH FIRST|PIVOT|NEXTVAL`: **0 aparitii** pentru fiecare.
|
||||
Identificatori: cel mai lung e `recalculeaza_totaluri_vanzari` (29) si `lnDiscountEvidentiat` (20)
|
||||
— niciunul peste 30.
|
||||
|
||||
**Numarul de linii** — fisier final: **17231** (17230 dupa convenția `wc -l`, care nu numara
|
||||
ultimul rand fiindca fisierul, la fel ca sursa, nu are newline final); `.pck` original:
|
||||
**17011** (17010 `wc -l`). Delta: +221 randuri adaugate (antet 7 + insert SPEC 3 + rand gol inainte
|
||||
de `CREATE OR REPLACE PACKAGE BODY` 1 + procedura noua in BODY 205 + coada 4 + `CREATE OR REPLACE`
|
||||
adaugat pe 2 linii existente, fara linii noi acolo).
|
||||
|
||||
**Coloanele de incasare** — `serie_incasat`, `nr_incasat`, `suma_incasat`, `tip_incasat`: **0**
|
||||
aparitii in SELECT/INTO/UPDATE-ul noii proceduri (verificat separat, izolat pe textul extras al
|
||||
procedurii). Apar in continuare de 5 ori fiecare **in restul fisierului** — in `scrie_in_vanzari`,
|
||||
neatinsa, unde e corect sa ramana (comportamentul de emitere nu se schimba).
|
||||
|
||||
## Erori prinse si corectate in timpul lucrului (nu au ajuns in fisierul livrat)
|
||||
|
||||
1. Prima rulare a omis complet linia `discount = lnDiscountFactura,` din `UPDATE` (am copiat doar
|
||||
eliminarea coloanelor de incasare, am uitat adaugarea cerincetei separat in brief). Prins de
|
||||
verificarea numerica (`lnDiscountFactura` aparea de 8 ori in loc de 9) inainte de a scrie
|
||||
raportul; corectat si re-rulat.
|
||||
2. Prima rulare a scris `PACKAGE "PACK_FACTURARE" is` si `PACKAGE BODY PACK_FACTURARE is` fara
|
||||
prefixul `CREATE OR REPLACE` pe **linia de SPEC** (l-am adaugat doar pe linia de BODY). Ar fi
|
||||
dat eroare de sintaxa la aplicare — `PACKAGE ... is` singur nu e o instructiune DDL valida.
|
||||
Prins prin citirea directa a antetului fisierului scris; corectat si re-rulat.
|
||||
|
||||
## Ce NU am facut / neverificat
|
||||
|
||||
- Nu am rulat nimic in Oracle — niciun `sqlplus`, niciun DDL, niciun test de compilare a
|
||||
pachetului. Corectitudinea sintactica dincolo de verificarile de mai sus (paranteze, virgule,
|
||||
cuvinte cheie) nu e garantata decat prin inspectie si prin construirea mecanica din blocul
|
||||
original deja compilat.
|
||||
- Coada scriptului foloseste `UpdateVersiune('ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql')` **cu**
|
||||
extensia `.sql`, asa cum cere explicit brief-ul si `scripturi-migrare-db.md` („script_final =
|
||||
numele fisierului, cu tot cu .sql"). Modelul citat (`ff_2026_08_06_10_...sql:17019`) foloseste
|
||||
de fapt numele **fara** `.sql` — o inconsistenta intre precedent si regula scrisa. Am urmat
|
||||
regula scrisa si instructiunea explicita, nu precedentul; semnalez discrepanta, nu am
|
||||
„reparat-o" in modelul vechi (nu era in scop).
|
||||
- Nu am atins `versiune_db.txt`, nu am scris in `D:\ROA\DATABASE\SCRIPTURI_CLAR`, nu am dat
|
||||
commit — conform interdictiilor din brief.
|
||||
@@ -1,8 +1,8 @@
|
||||
# S5 — acoperirea de teste pentru scrierea articolelor (decizii 38-41)
|
||||
|
||||
Raport de testare pentru functionalitatea S5 (`docs\handoff_s5.md`), care nu avea niciun test la
|
||||
Raport de testare pentru functionalitatea S5 (handoff intermediar (sters)), care nu avea niciun test la
|
||||
inceputul acestei lucrari. Trei fisiere de test atinse, toate in
|
||||
`COMUN\utile\Teste\editare_factura\`, plus diff-ul: `docs\diff_s5_teste.patch`.
|
||||
`COMUN\utile\Teste\editare_factura\`, plus diff-ul: diff aplicat (sters).
|
||||
|
||||
Niciun fisier de productie nu a fost atins (`omodificari.vc2`, `ofacturare_editare.prg`,
|
||||
`ofacturare_comun.vc2`, `comun.vc2`, `ofacturare.vc2` — toate neschimbate de acest agent). Nu s-a
|
||||
@@ -151,7 +151,7 @@ mtime):
|
||||
|
||||
\* cifra `raport_teste.ps1` (regex pe inceput de linie — subraporteaza pentru aceasta suita
|
||||
specifica, vezi mai jos). \*\* cifra reala, numarata ca ocurente literale `PASS`/`FAIL` in log —
|
||||
aceasta e conventia din `docs\handoff_s5.md` ("test_page3_articole 14/2"), verificata identica
|
||||
aceasta e conventia din handoff intermediar (sters) ("test_page3_articole 14/2"), verificata identica
|
||||
inainte si dupa editarea mea.
|
||||
|
||||
**Atentie separata pentru viitor**: `raport_teste.ps1` numara doar liniile care incep cu
|
||||
@@ -162,12 +162,12 @@ deja in cod dinainte), dar inseamna ca **pentru `test_page3_articole`, raportul
|
||||
incredere** — verificarea trebuie facuta manual (`grep -o PASS/FAIL`, cum s-a facut aici), nu doar
|
||||
cu `raport_teste.ps1`.
|
||||
|
||||
Toate celelalte suite: identice cu baseline-ul din `docs\handoff_s5.md`, nicio regresie.
|
||||
Toate celelalte suite: identice cu baseline-ul din handoff intermediar (sters), nicio regresie.
|
||||
|
||||
## F. Ce nu s-a acoperit si de ce
|
||||
|
||||
- **Test cu scriere reala in Oracle** (aprobat de Marius pentru S5, dar separat de mandatul acestui
|
||||
agent — interzis explicit sa scrie in baza) — ramane pentru o lucrare ulterioara, dupa modelul
|
||||
`test_writeback_buton1.prg`.
|
||||
- **R5** (linie cu valuta fara rand in `VANZARI_CURSURI`) — ramane deschis din `handoff_s5.md`, nu
|
||||
- **R5** (linie cu valuta fara rand in `VANZARI_CURSURI`) — ramane deschis din handoff intermediar (sters), nu
|
||||
s-a adaugat un test nou pentru el, in afara mandatului de "validari + helper + grid".
|
||||
|
||||
@@ -15,7 +15,7 @@ inainte. Nu e nevoie de reparatie — nu exista defect.
|
||||
|
||||
Sursa: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_09_01_COMUN_PACK_FACTURARE.sql` (fisierul
|
||||
real aplicat in baza, nu un export `all_source` — capcana deja platita in S5, vezi
|
||||
`docs\handoff_s5.md`).
|
||||
handoff intermediar (sters)).
|
||||
|
||||
**1. `ACT_TEMP` e tabela de lucru (scratch), golita automat la fiecare COMMIT/ROLLBACK.**
|
||||
Verificat direct din dictionar, nu presupus:
|
||||
@@ -27,7 +27,7 @@ select table_name, temporary, duration from all_tables where table_name in ('ACT
|
||||
```
|
||||
|
||||
Un GTT cu `DURATION = SYS$TRANSACTION` se goleste singur la finalul TRANZACTIEI curente. Decizia 38
|
||||
(`docs\handoff_s5.md`, deja testata cu scriere reala in S5) stabileste ca **fiecare editare ruleaza
|
||||
(handoff intermediar (sters), deja testata cu scriere reala in S5) stabileste ca **fiecare editare ruleaza
|
||||
intr-o singura tranzactie manuala, incheiata cu COMMIT** — deci `ACT_TEMP` porneste mereu **goala**
|
||||
la inceputul fiecarei editari; nu poate purta randuri dintr-o editare anterioara.
|
||||
|
||||
@@ -183,7 +183,7 @@ consistent cu punctul 4 din dovada pe cod (blocul vechi se retrage integral).
|
||||
|
||||
## Date de test consumate
|
||||
|
||||
Continuare pe **`id_vanzare = 1049`** (deja in lucru din S5, `docs\handoff_punct6_dupa_s5.md`):
|
||||
Continuare pe **`id_vanzare = 1049`** (deja in lucru din S5, handoff intermediar (sters)):
|
||||
`cod` realocat suplimentar **1140900 -> 1140901 -> 1140902 -> 1140903** (prima rulare, cu interogarea
|
||||
de numarare gresita — pastrata doar ca generatie reala, nu s-a revenit peste ea) **-> 1140904 ->
|
||||
1140905 -> 1140906** (rularea finala, cea raportata mai sus). **Cod curent: `1140906`.** Niciun
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
# S8 — Inventar pe tipuri de sursa. Rezultat
|
||||
|
||||
Cerinta din plan (`docs\plan_06_editare_factura.md:282-291`): test pe fluxul real, cate un caz din
|
||||
fiecare tip de sursa (lista de preturi, comanda, contract, aviz), fiecare rulat **de doua ori** (o
|
||||
data din ROAFACTURARE, o data din registrul jurnal ROACONT), plus un al treilea caz obligatoriu — un
|
||||
document care nu e factura, deschis din jurnal (**deja acoperit**, testul de garda
|
||||
`ofacturare_editare.prg` scos din `SET PROCEDURE` -> `PageCount = 2`).
|
||||
|
||||
Faza de fata e **inventar, READ-ONLY**: doar `SELECT` si un apel de functie PL/SQL
|
||||
(`pack_documente.ReferinteDocumenteNota`, functie de citire, fara `INSERT`/`UPDATE`/`COMMIT`).
|
||||
Zero scriere, zero editare de documente, zero modificare de cod.
|
||||
|
||||
## Verdict
|
||||
|
||||
**Matricea completa NU e realizabila azi.** Doar tipul **lista de preturi** are documente eligibile
|
||||
in luna curenta (august 2026) — 3 documente, din care **2 sunt deja indisponibile** (consumate/baza
|
||||
de regresie in lucrari anterioare). Ramane **un singur candidat neatins**: `id_vanzare=1048`.
|
||||
|
||||
Celelalte trei tipuri — **comanda, contract, aviz** — au **zero documente in luna curenta**. Nu e o
|
||||
limitare de cod sau de garda: nu exista niciun document de acel tip datat in august 2026, in toata
|
||||
`MARIUSM_AUTO`. Cea mai recenta factura pe comanda e din 26.03.2026, pe contract din 30.06.2026, iar
|
||||
pe aviz (`tip=4`, "FACT. DIN AVIZ") din **30.11.2023**. Nu se fabrica date.
|
||||
|
||||
## 1. Cum se determina „tipul de sursa" — dovada pe cod
|
||||
|
||||
`VANZARI.TIP` — mapat explicit in `COMUN\clase\ofacturare.vc2`, atat in configurarea UI a
|
||||
formularului de facturare (`frm_facturare_articole.Init`, `Do Case` pe `poDate.tip`, `:15122-15153`)
|
||||
cat si in constantele denumite din `do_copiaza` (`:3628-3681`):
|
||||
|
||||
| Tip sursa (cerut de S8) | `VANZARI.TIP` | Eticheta din cod | Sursa |
|
||||
|---|---|---|---|
|
||||
| lista de preturi | `1, 5, 7, 10` | POLITICA PRETURI (lei / invoice / credit note / factura valuta) | `ofacturare.vc2:15122-15123`, `:3629-3632` |
|
||||
| contract | `2, 6` | CONTRACT / CONTRACT - VALUTA | `ofacturare.vc2:15129-15130`, `:3638`, `:3658` |
|
||||
| comanda | `3` | COMANDA | `ofacturare.vc2:15144-15145`, `:3639` |
|
||||
| aviz | `4` | FACT. DIN AVIZ (factura emisa pe baza unui aviz anterior) | `ofacturare.vc2:15151-15152`, `:3640` |
|
||||
|
||||
Se mapeaza curat pe un singur camp (`VANZARI.TIP`), fara ambiguitate. Precizari:
|
||||
|
||||
- Tipurile `21/22/23/24/25/26/28/29/41` etc. sunt **avize propriu-zise sau transferuri** (documente
|
||||
separate, nu facturi cu sursa aviz) — nu intra in matrice, pentru ca S8 cere editarea unei
|
||||
**facturi**, nu a unui aviz.
|
||||
- `tip=-12` (facturi din ROAAUTO, devize auto) e alt caz, deja documentat separat in
|
||||
`docs\cercetare\roaauto_facturi.md` — nu face parte din cele patru tipuri cerute de plan.
|
||||
- Contractul (`2,6`) are azi acces liber la lista de preturi in dialogul de adaugare articole
|
||||
(`docs\cercetare\retur_si_lista_preturi.md`, sectiunea B), dar asta nu schimba clasificarea sursei
|
||||
— clasificarea e pe `VANZARI.TIP`, nu pe ce se poate adauga ulterior.
|
||||
|
||||
## 2. Cate documente exista, per filtru — cifre pe `MARIUSM_AUTO`
|
||||
|
||||
Garda de editare cumulata (varianta strictă, `frm_facturi.do_editare_factura`,
|
||||
`ofacturare_comun.vc2:3715-3872`): `sters=0`, `eproforma<>1`, luna curenta (`data_act` in august
|
||||
2026), fara linii din seturi (`id_vanzare_set` nenul pe nicio linie activa), fara referinte
|
||||
(`pack_documente.ReferinteDocumenteNota`), netrimisa in eFactura (`anaf_efactura.id_fact`).
|
||||
|
||||
| Pas / filtru | lista de preturi | contract | comanda | aviz |
|
||||
|---|---|---|---|---|
|
||||
| 1. `sters=0`, tip in grup, luna curenta (08.2026) | **3** | 0 | 0 | 0 |
|
||||
| 2. + `eproforma<>1` | 3 (neschimbat) | 0 | 0 | 0 |
|
||||
| 3. + fara linii din seturi | 3 (neschimbat) | 0 | 0 | 0 |
|
||||
| 4. + fara referinte incasari/plati | 3 (neschimbat) | 0 | 0 | 0 |
|
||||
| 5. + netrimis in eFactura (**eligibil final**) | **3** | 0 | 0 | 0 |
|
||||
|
||||
Niciun filtru nu a eliminat vreun document din grupul „lista de preturi" — cele 3 existente treceau
|
||||
deja toate gardele. Pentru celelalte trei tipuri, blocajul e la pasul 1: **nu exista document in
|
||||
luna curenta**, deci pasii 2-5 sunt irelevanti (cifra ramane 0, nu se pierde nimic pe drum).
|
||||
|
||||
**Istoric, ca sa se vada ca nu e o problema de cautare**: `comanda` are 38 de facturi nesterse in
|
||||
total (cea mai recenta 26.03.2026), `contract` 23 (cea mai recenta 30.06.2026), `aviz` doar 5 in tot
|
||||
istoricul (cea mai recenta **30.11.2023**) — tipul `aviz` (facturare directa dintr-un aviz emis, fara
|
||||
trecere prin lista de preturi/comanda/contract) e practic neutilizat de câţiva ani, nu doar in luna
|
||||
curenta.
|
||||
|
||||
**Al doilea punct de intrare (ROACONT/`afisjurcom.do_modifica`, `comun.vc2:2222-2572`)**: garda e
|
||||
mai laxa — verifica doar luna curenta si `id_set` in afara intervalului `[30000,30009]` (rezervat
|
||||
ROAPRODUCTIE); nu verifica `eproforma`, referinte sau eFactura (vezi `handoff_punct6_dupa_s5.md`,
|
||||
confirmat din nou pe cod la aceasta cercetare). Verificat pe cei 3 candidati lista de preturi:
|
||||
`id_set=25010` pentru toti trei (an=2026, luna=8) — in afara intervalului interzis, deci **toti trei
|
||||
trec si garda ROACONT**. Cum niciun filtru specific ROAFACTURARE (eproforma/referinte/eFactura) n-a
|
||||
eliminat vreun document din cele 3, garda mai laxa a jurnalului **nu aduce candidati suplimentari**
|
||||
pentru lista de preturi — si, evident, nu poate aduce candidati pentru comanda/contract/aviz, unde
|
||||
blocajul e lipsa documentului insusi (ambele puncte de intrare cer luna curenta).
|
||||
|
||||
## 3. Lista concreta de candidati propusi
|
||||
|
||||
| Tip sursa | `id_vanzare` | `cod` | `id_fact` | Stare | De ce |
|
||||
|---|---|---|---|---|---|
|
||||
| lista de preturi | **1048** | 1140894 | 8009658 | **neatins, eligibil** | 1 linie activa, fara valuta (`in_valuta=0`), `discount=0`, client RAJA (`id_part=463`) — document simplu, curat, tip=1 |
|
||||
| lista de preturi | 1049 | 1140906 (curent) | 8009659 | eligibil pe cod, dar **deja consumat** | documentul de test S5/S7 — `cod` realocat de 8 ori, folosit intentionat ca baza de continuitate; nu se reia pentru S8 fara sa se stie ca istoricul lui e deja incarcat |
|
||||
| lista de preturi | 1050 | 1140895 | 8009660 | eligibil pe cod, dar **interzis explicit** | „baza suitelor de regresie — nu se atinge" (`handoff_punct6_dupa_s5.md`) |
|
||||
| contract | — | — | — | **zero** | niciun document `tip in (2,6)` in august 2026 (cel mai recent 30.06.2026) |
|
||||
| comanda | — | — | — | **zero** | niciun document `tip=3` in august 2026 (cel mai recent 26.03.2026) |
|
||||
| aviz | — | — | — | **zero** | niciun document `tip=4` in august 2026 (cel mai recent **30.11.2023**) |
|
||||
|
||||
**Singurul candidat utilizabil pentru matrice, azi: `id_vanzare=1048` (lista de preturi).** Pentru
|
||||
comanda/contract/aviz nu exista alternativa in luna curenta — orice executie ar cere fie asteptarea
|
||||
pana quando apare un document nou de acel tip in perioada curenta, fie o decizie explicita de a
|
||||
relaxa criteriul „luna curenta" (schimbare de scop, nu de agent).
|
||||
|
||||
## 4. Ce ar consuma executia matricei (daca se aproba)
|
||||
|
||||
- **Un singur `cod` disponibil de consumat**: `id_vanzare=1048`, `cod=1140894`. Fiecare trecere prin
|
||||
fluxul de editare realoca `cod` ireversibil (pattern confirmat empiric in S5/S7: 8 realocari pe
|
||||
`id_vanzare=1049`). Testarea „de doua ori" (ROAFACTURARE + ROACONT) ar realoca `cod`-ul cel putin
|
||||
**de doua ori** pe acest document.
|
||||
- **Comanda/contract/aviz**: executie **imposibila** azi, indiferent de aprobare — nu exista document
|
||||
de consumat. Singura cale de a acoperi aceste trei tipuri e sa apara documente noi in productie in
|
||||
luna curenta, sau o decizie separata de relaxare a scopului (nu s-a luat).
|
||||
- Al treilea caz obligatoriu (document care nu e factura, din jurnal) — deja acoperit, zero consum
|
||||
suplimentar.
|
||||
- Nimic din inventarul de fata nu a consumat date: read-only, zero `INSERT`/`UPDATE`/`COMMIT`.
|
||||
|
||||
## Ce NU acopera cercetarea
|
||||
|
||||
- `glLunaInchisa` (garda VFP „luna contabila inchisa") nu e verificabila din Oracle — presupusa
|
||||
deschisa (mediul de test curent), neverificata direct.
|
||||
- Nu s-a cautat in alte luni/ani pentru un eventual document comanda/contract/aviz care sa fi ramas
|
||||
needitat din alt motiv — cerinta explicita a fost „luna curenta", conform gardei reale de editare.
|
||||
- Coloana `VANZARI.ID_VANZARE_SET` nu exista direct pe `VANZARI` — verificarea „fara linii din
|
||||
seturi" s-a facut pe `VANZARI_DETALII.ID_VANZARE_SET` (linii active), consistent cu decizia 39
|
||||
(`handoff_s5.md`).
|
||||
|
||||
## Date de test — NIMIC consumat
|
||||
|
||||
Interogari `SELECT` + un apel de functie PL/SQL de citire (`pack_documente.ReferinteDocumenteNota`).
|
||||
Zero `INSERT`/`UPDATE`/`DELETE`/`COMMIT`. `id_vanzare=1049` si `1050` — neatinse, doar citite.
|
||||
`id_vanzare=1048` — doar citit, nu editat; ramane candidatul propus pentru executia viitoare.
|
||||
|
||||
## Fisiere atinse
|
||||
|
||||
Niciunul de productie. Scripturi `.sql` de interogare, in scratchpad (nu in `docs\`, nu in
|
||||
`SCRIPTURI_CLAR`) — pur exploratorii, nu fac parte din livrare.
|
||||
@@ -1,164 +0,0 @@
|
||||
# S8 — matricea pe tipuri de sursa, cele 4 documente
|
||||
|
||||
Test: `COMUN\utile\Teste\editare_factura\test_s8_matrice_surse.prg`, log:
|
||||
`COMUN\utile\Teste\editare_factura\test_s8_matrice_surse_log.txt` (rescris la fiecare rulare -
|
||||
cifrele de mai jos sunt citite din log **imediat dupa fiecare rulare**, inainte de a activa
|
||||
urmatorul document, si verificate independent prin `sqlplus`).
|
||||
|
||||
Matricea completa (4 documente) a fost rulata, cate unul pe rand, activat prin `gaCazuriActive` in
|
||||
`test_s8_matrice_surse.prg`. Codul (`EditeazaDinRoafacturare`/`EditeazaDinRegistruJurnal`/
|
||||
`VerificaDupaEditare`/`CalculeazaTotaluriS4b`) e neschimbat intre rulari - parametrizarea prin
|
||||
`id_vanzare` a functionat neschimbata pe toate cele 4 tipuri.
|
||||
|
||||
## Sinteza cifrelor `REZULTAT` (autoritare, din log)
|
||||
|
||||
| Document | Tip sursa | REZULTAT | FAIL-uri | Cauza FAIL-urilor |
|
||||
|---|---|---|---|---|
|
||||
| 1048 | lista de preturi (tip 1) | **44 PASS / 0 FAIL** | - | - |
|
||||
| 1055 | factura din contract (tip 2) | **44 PASS / 0 FAIL** | - | - |
|
||||
| 1052 | aviz (tip 22) | **26 PASS / 1 FAIL** | 1 | garda `ReferinteDocumenteNota` blocheaza corect intrarea ROAFACTURARE (constatare, nu defect de test - vezi mai jos) |
|
||||
| 1054 | factura din aviz (tip 4) | **42 PASS / 2 FAIL** | 2 | `Reccount(trul)=0` pe ambele intrari - normal pentru tip 4 (vezi mai jos), nu defect |
|
||||
|
||||
Niciun `EROARE` in niciunul din cele 4 loguri.
|
||||
|
||||
## Document 1048 — lista de preturi (tip 1)
|
||||
|
||||
Deja raportat integral in versiunea anterioara a acestui document (ambele intrari au reusit complet,
|
||||
0 anomalii). Stare finala neschimbata de rularile ulterioare pe celelalte documente: `cod=1140918`,
|
||||
`id_fact=8009658` (neschimbat), totaluri `250.01/52.50/302.51` (neschimbate), 1 linie activa.
|
||||
|
||||
## Document 1055 — factura din contract (tip 2)
|
||||
|
||||
Ambele intrari au reusit complet (`COMMIT`), fara nicio anomalie in lantul de scriere.
|
||||
|
||||
| | inainte | dupa ROAFACTURARE | dupa registrul jurnal |
|
||||
|---|---|---|---|
|
||||
| `cod` | 1140911 | 1140919 | **1140920** |
|
||||
| `id_fact` | 8009680 | 8009680 | 8009680 (neschimbat) |
|
||||
| totaluri | 200.00 / 42.00 / 242.00 | neschimbate | neschimbate |
|
||||
| linii active | 2 | 2 | 2 |
|
||||
|
||||
`vact_tot`: cod 1140911 si 1140919 (notele vechi) - toate randurile `STERS=1`; cod 1140920 (nota
|
||||
curenta) - toate randurile `STERS=0`.
|
||||
|
||||
**Constatare (nu defect)**: verdictul S4b e **divergent** pe tot parcursul - `ACT=242`, `RUL=121`
|
||||
(exact jumatate), neschimbat de cele doua editari (`121 -> 121` pe ambele treceri). Verdictul e
|
||||
etichetat explicit "informativ, nu e eroare" de catre `frm_modific2024` insusi (decizia din S4b:
|
||||
formularul arata divergenta, nu o blocheaza). Asertiile testului nu presupun `ACT=RUL` - verifica
|
||||
doar ca fiecare total ramane **concordant fata de inainte de editare**, ceea ce s-a confirmat.
|
||||
|
||||
## Document 1052 — aviz (tip 22)
|
||||
|
||||
**Nu e factura** - constatare confirmata, exact cum a semnalat briefingul.
|
||||
|
||||
### Intrarea ROAFACTURARE (`do_editare_factura`): BLOCATA de garda, corect
|
||||
|
||||
```
|
||||
FAIL ... document fara referinte / netrimis in eFactura [.T.]
|
||||
```
|
||||
|
||||
`ReferinteDocumenteNota(2026, 8, 1140908)` a intors adevarat - verificat direct in Oracle:
|
||||
`ACT.id_factc = 8009677` (id_fact-ul avizului 1052) exista pe cod=1140910, care e nota lui **1054**
|
||||
("factura din aviz", emisa din acest aviz). Garda functioneaza exact cum trebuie: **blocheaza
|
||||
editarea unui document sursa care are deja o factura emisa din el** - nicio scriere nu s-a produs
|
||||
(verificat: `cod` a ramas `1140908` neschimbat pana la intrarea urmatoare). `EsteInEFactura` nu a
|
||||
contribuit (`anaf_efactura` nu are randuri pentru `id_fact=8009677`).
|
||||
|
||||
Aceasta e o `FAIL` de asertie **asteptata si corecta** - testul a presupus (mostenit din modelul
|
||||
S5, gandit pentru facturi) ca documentul e editabil; pentru un aviz cu factura deja emisa din el,
|
||||
nu e. Marcata ca atare, nu ca defect.
|
||||
|
||||
### Intrarea registru jurnal ROACONT (`do_modifica`): A REUSIT COMPLET, fara aceeasi garda
|
||||
|
||||
```
|
||||
PASS ... blocul ScrieArticoleFacturaEditate s-a executat pe aceasta cale (garda satisfacuta) [.T.]
|
||||
PASS ... lantul complet a reusit (COMMIT) [lnSucces=1]
|
||||
```
|
||||
|
||||
**Constatare reala, de raportat lui Marius**: `afisjurcom.do_modifica` (`comun.vc2:2222-2569`) **nu
|
||||
are garda `ReferinteDocumenteNota`/`EsteInEFactura`** in secventa reprodusa (confirmat deja indirect
|
||||
de `test_s5_al_doilea_intrare.prg`, dar niciodata exercitata pana acum pe un document care CHIAR are
|
||||
o referinta reala). Rezultat: editarea prin registrul jurnal a trecut pana la `COMMIT` pe un
|
||||
document (1052) pe care intrarea ROAFACTURARE l-a blocat explicit din acelasi motiv.
|
||||
|
||||
Pe aceasta rulare **fara** consecinta vizibila (editarea nu a modificat nicio linie - doar a
|
||||
realocat `cod`-ul si a refacut nota; documentul 1054, care il refera, a fost verificat neschimbat:
|
||||
`cod=1140910`, `id_fact=8009679`, totaluri `252.07/52.93/305.00`, toate identice cu inainte).
|
||||
Legatura structurala ramane valida pentru ca trece prin `id_fact`/`id_vanzare`, niciodata prin `cod`
|
||||
(S6, deja inchis). Dar daca editarea prin ROACONT ar fi inclus si o modificare de continut pe un
|
||||
document cu referinte reale, nimic nu ar fi oprit-o - asimetria intre cele doua puncte de intrare e
|
||||
reala, nu doar teoretica. **Nu s-a atins `comun.vc2`/`omodificari.vc2` pentru a o corecta** (livrare
|
||||
inchisa) - se raporteaza pentru decizia lui Marius.
|
||||
|
||||
| | inainte | dupa ROAFACTURARE | dupa registrul jurnal |
|
||||
|---|---|---|---|
|
||||
| `cod` | 1140908 | *(blocat, nescris)* | **1140921** |
|
||||
| `id_fact` | 8009677 | - | 8009677 (neschimbat) |
|
||||
| totaluri | 271.17 / 56.94 / 328.11 | - | neschimbate |
|
||||
| linii active | 2 | - | 2 |
|
||||
|
||||
`vact_tot`: cod 1140908 (nota veche) - toate randurile `STERS=1`; cod 1140921 (nota curenta) -
|
||||
toate randurile `STERS=0`. S4b: `ACT=RUL=328.11`, verdict sincronizat, neschimbat de editare.
|
||||
|
||||
## Document 1054 — factura din aviz (tip 4)
|
||||
|
||||
Ambele intrari au reusit complet (`COMMIT`), singurele 2 `FAIL` din aceasta rulare sunt pe
|
||||
`Reccount(trul)>0`.
|
||||
|
||||
**Stabilit inainte de editare, nu ghicit**: interogare pe toate cele 6 documente `tip=4` din baza
|
||||
(`145, 665, 668, 697, 974, 1054`) - **toate** au exact 2 randuri `ACT` si **0** randuri `RUL`,
|
||||
indiferent de `total_cu_tva`. Tiparul e 100% consistent pe populatia completa de documente tip 4,
|
||||
nu doar pe 1054 - **normal pentru tip 4**, nu o particularitate a acestui document. Explicatia
|
||||
structurala plauzibila: miscarea de stoc s-a inregistrat deja la emiterea avizului sursa; factura
|
||||
emisa din aviz nu mai genereaza randuri `RUL` proprii (ar dubla miscarea), doar nota contabila
|
||||
(`ACT`). Cele doua `FAIL` (`Reccount(trul)>0` cerut de asertia generica, `Reccount(trul)=0` gasit)
|
||||
sunt **asteptate si corecte pentru acest tip de document** - verificarea "rulaje refacute" nu e
|
||||
concludenta pentru tip 4 (nu exista rulaje de refacut), nu semnaleaza un defect.
|
||||
|
||||
Restul verificarilor (nota veche/noua, `id_fact`, totaluri denormalizate, S4b ACT concordant,
|
||||
stoc) au trecut integral pe ambele intrari.
|
||||
|
||||
| | inainte | dupa ROAFACTURARE | dupa registrul jurnal |
|
||||
|---|---|---|---|
|
||||
| `cod` | 1140910 | 1140922 | **1140923** |
|
||||
| `id_fact` | 8009679 | 8009679 | 8009679 (neschimbat) |
|
||||
| totaluri | 252.07 / 52.93 / 305.00 | neschimbate | neschimbate |
|
||||
| linii active | 1 | 1 | 1 |
|
||||
|
||||
`vact_tot`: cod 1140910 si 1140922 (notele vechi) - toate randurile `STERS=1`; cod 1140923 (nota
|
||||
curenta) - toate randurile `STERS=0`. S4b: `ACT=305`, `RUL=0`, verdict divergent (informativ),
|
||||
neschimbat de editare (`305->305`, `0->0`).
|
||||
|
||||
## Verdict explicit pe cele 8 verificari cerute de plan (`plan_06_editare_factura.md:286-288`)
|
||||
|
||||
| # | Verificare | Verdict pe matrice |
|
||||
|---|---|---|
|
||||
| 1 | nota veche `STERS=1` | **PASS** pe toate cele 7 scrieri reusite (1048x2, 1055x2, 1052x1 - ROACONT, 1054x2). N/A pe 1052/ROAFACTURARE (blocat inainte de scriere, nu s-a creat nicio nota noua). |
|
||||
| 2 | nota noua corecta (exista, activa, acelasi `id_fact`) | **PASS** pe toate cele 7 scrieri reusite. |
|
||||
| 3 | `id_fact` neschimbat | **PASS** pe toate cele 7 - 8009658, 8009680, 8009677, 8009679 identice inainte/dupa. |
|
||||
| 4 | `VANZARI`/`VANZARI_DETALII` sincronizate | **PASS** pe toate cele 7 - numar de linii active neschimbat, totaluri coerente (`ftva+tva=ctva`). |
|
||||
| 5 | totalurile denormalizate corecte | **PASS** pe toate cele 7 - identice cu inainte de editare (reeditare fara modificari de continut). |
|
||||
| 6 | rulajele refacute | **PASS** pe 1048 (x2), 1055 (x2), 1052 (x1, ROACONT). **FAIL asteptat** pe 1054 (x2) - `RUL=0` e normal pentru tip 4 (confirmat pe toate cele 6 documente tip 4 din baza), verificarea nu e concludenta pentru acest tip. |
|
||||
| 7 | totalurile de control S4b concordante | **PASS** pe toate cele 7 - `Total ACT` si `Total RUL` raman fiecare **neschimbate fata de inainte de editare**, indiferent daca verdictul absolut e sincronizat (1048, 1052) sau divergent (1055, 1054 - divergenta insasi e preexistenta editarii, nu cauzata de ea). |
|
||||
| 8 | verificarile de stoc de la emitere NU s-au declansat | **PASS** pe toate cele 7 - `gcMockUltimMesaj` ramas gol dupa fiecare lant de scriere; structural, `verifica_stoc` (`oscrie_in_fisiere.prg:92`) nu se poate declansa pentru ca ambele puncte de intrare trec `tlModificare=.T.`. |
|
||||
|
||||
**Al treilea caz obligatoriu** (document care nu e factura, deschis din registru jurnal, fara
|
||||
pagina de articole) - deja acoperit separat, per handoff (`docs\handoff_punct6_10082026_pm.md:113`).
|
||||
|
||||
## Constatare de raportat separat (nu de reparat aici)
|
||||
|
||||
**Asimetria de garda intre punctele de intrare** (sectiunea document 1052 de mai sus): intrarea
|
||||
ROAFACTURARE (`ofacturare_comun.vc2`, `do_editare_factura`) verifica `ReferinteDocumenteNota`/
|
||||
`EsteInEFactura` inainte de a permite editarea; intrarea registru jurnal ROACONT
|
||||
(`comun.vc2`, `afisjurcom.do_modifica`) nu are aceasta garda in secventa reprodusa si a scris pana
|
||||
la capat pe acelasi document pe care ROAFACTURARE l-a blocat. Nicio consecinta vizibila pe aceasta
|
||||
rulare (editare fara modificari de continut, documentul care refera - 1054 - verificat neschimbat),
|
||||
dar protectia lipseste structural pe calea ROACONT. `omodificari.vc2`/`comun.vc2` **nu au fost
|
||||
atinse** (livrari inchise) - decizia (adaugarea gardei si pe ROACONT, sau acceptarea asimetriei) ii
|
||||
revine lui Marius.
|
||||
|
||||
## Ramas de facut
|
||||
|
||||
Toate cele 4 documente din matrice au fost editate de doua ori si verificate. Nimic ramas pe
|
||||
felia S8 in sine. Documentele consumate (coduri realocate, note vechi sterse ireversibil):
|
||||
1048 (-> 1140918), 1052 (-> 1140921), 1054 (-> 1140923), 1055 (-> 1140920).
|
||||
@@ -1,7 +1,7 @@
|
||||
# S9 — documentatia fluxului de editare a facturii, adaugata in flux-modificare-stergere-nota-jurnal.md
|
||||
|
||||
Fisier editat: `D:\ROA\ROAGEST\COMUN\docs\flux-modificare-stergere-nota-jurnal.md`.
|
||||
Diff salvat: `D:\ROA\ROAFACTURARE\docs\diff_s9_flux_nota_jurnal.patch`.
|
||||
Diff salvat: diff aplicat (sters).
|
||||
**Nimic comis** (nici git, nici SVN) - `COMUN` e dublu-versionat SVN+git, `git stash` acolo e
|
||||
interzis; nu s-a folosit.
|
||||
|
||||
@@ -49,7 +49,7 @@ Doua sectiuni noi, dupa `## Atentie: nu e valabil la fel pentru stergerea simpla
|
||||
pe care il documenteaza fisierul tinta. L-am scos ca sa nu ingreunez sectiunea cu un subiect
|
||||
distinct (planul cere explicit doar "ramura de facturi" pe fluxul de modificare/stergere).
|
||||
- **Actiunea de sincronizare cu enumerarea liniilor vechi->noi** - nu exista inca in cod (S4b
|
||||
partial, per `docs\handoff_punct6_dupa_s5.md`), n-am documentat ceva nelivrat.
|
||||
partial, per handoff intermediar (sters)), n-am documentat ceva nelivrat.
|
||||
- **Eticheta text "linie din set"** - handoff-ul S5 o mentioneaza, dar in cod (grep pe
|
||||
`omodificari.vc2`) nu exista un literal cu acest text; marcajul e doar vizual, prin
|
||||
`DynamicForeColor` (culoare distincta). Am scris "culoare distincta", nu "eticheta", ca sa nu
|
||||
@@ -69,7 +69,7 @@ Doua sectiuni noi, dupa `## Atentie: nu e valabil la fel pentru stergerea simpla
|
||||
pot spune din documentatie daca e o omisiune ramasa din S1 sau o decizie asumata (planul spune
|
||||
doar ca "garzile trebuie sa fie in formular sau in codul comun", fara sa specifice care cale
|
||||
trebuia sa le primeasca). Am documentat faptul, nu l-am calificat drept bug.
|
||||
2. **Eticheta "linie din set"** mentionata in `handoff_s5.md` (decizia 39) nu exista ca text in cod
|
||||
2. **Eticheta "linie din set"** mentionata in handoff intermediar (sters) (decizia 39) nu exista ca text in cod
|
||||
la verificare - posibil ramasa doar la nivel de intentie sau inlocuita de marcajul de culoare in
|
||||
implementarea finala. N-am putut confirma din git log/istoric fara sa ies din scop; las-o ca
|
||||
discrepanta cunoscuta intre document de decizie si livrare.
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
# Cercetare: TVA calculat vs salvat (#7) + denormalizare VANZARI (#8)
|
||||
|
||||
Sursele principale sunt fisierele "curate" din arhiva de migrare Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\...` (nu in working copy VFP git — DDL/PL-SQL nu e versionat in
|
||||
`ROAFACTURARE`), plus `D:\ROA\ROAFACTURARE\COMUN\clase\ofacturare.vc2` (working copy VFP, text
|
||||
`.vc2` deja la zi).
|
||||
|
||||
Cea mai recenta definitie **completa** a pachetului `PACK_FACTURARE` (COMUN, folosit de toate
|
||||
produsele ROA care factureaza) e in
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql` (16948 linii).
|
||||
Toate liniile citate mai jos fara alta mentiune sunt din acest fisier.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT A — TVA calculat, nu salvat (#7)
|
||||
|
||||
### 1. Structura VANZARI / VANZARI_DETALII (coloane pret/TVA)
|
||||
|
||||
Nu exista `CREATE TABLE VANZARI_DETALII` in arhiva cautata (tabela e mai veche decat
|
||||
`SCRIPTURI_CLAR`, care incepe efectiv din 2009; originea e probabil in
|
||||
`D:\ROA\DATABASE\SCRIPTURI\2006-2008`, nu am parcurs exhaustiv acel arhiv de migrari vechi).
|
||||
Coloanele efective au fost confirmate prin utilizarea lor in cod (view-uri + SQL dinamic VFP):
|
||||
|
||||
**VANZARI_DETALII** (per linie articol):
|
||||
- `PRET` — pret unitar (fara/cu TVA, in functie de flag)
|
||||
- `DIFERENTA` — ajustare pret (folosita in `calculeaza_total_*_fact`)
|
||||
- `DISCOUNT_UNITAR`
|
||||
- `CANTITATE`
|
||||
- `PRET_CU_TVA` — flag NUMBER(1): 1 = pretul de mai sus e cu TVA inclus, 0 = fara TVA
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:25,43` — `b.pret_cu_tva`)
|
||||
- `PROC_TVAV` — procent TVA ca multiplicator (ex. 1.19), nu procent brut
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:26` — `b.proc_tvav`)
|
||||
- `PRET_ACHIZITIE` (`ff_2026_07_27_01_FACTURARE.sql:105,130`)
|
||||
- `ID_ARTICOL`, `ID_VALUTA`, `ID_POL` (politica de pret), `SERIE`, `STERS`, `ID_VANZARE`,
|
||||
`ID_VANZARE_DET` (`ff_2026_07_27_01_FACTURARE.sql:11-76`)
|
||||
- `TAXCODE` — adaugata `2022\03\ff_2022_03_24_01_COMUN_SAFT.sql:6` (cod taxa SAFT)
|
||||
- `ID_JTVA_COLOANA_EX` — adaugata `2019\08\ff_2019_08_20_04_COMUN.sql:7`
|
||||
- `LOT` — adaugata `2024\06\ff_2024_06_04_01_COMUN_FACTURARE.sql:3`
|
||||
|
||||
**NU exista** o coloana de TVA calculata/salvata per linie (nici `valoare_tva`, nici
|
||||
`pret_fara_tva` rezultat) — doar inputurile (`pret`, `pret_cu_tva` flag, `proc_tvav`), confirmand
|
||||
exact ce zice todo #7: TVA e derivat, nu stocat.
|
||||
|
||||
**VANZARI** (antet factura) — coloane denormalizate relevante TVA, toate adaugate prin
|
||||
`2017\03\ff_2017_03_28_01_FACTURARE.sql:9-38`:
|
||||
- `DISCOUNT_TVA` — "TVA DISCOUNT (DISCOUNT * MAX(PROC_TVA) ARTICOLE)"
|
||||
- `TOTAL_FARA_TVA`, `TOTAL_TVA`, `TOTAL_CU_TVA` — totaluri pe document (denormalizate)
|
||||
- `VALOARE_ACHIZITIE`
|
||||
- vezi si Subiect B pt. `SERIE_INCASAT`/`NR_INCASAT`/`SUMA_INCASAT`/`TIP_INCASAT`/`AVIZE`
|
||||
|
||||
### 2. Unde se calculeaza TVA-ul pe linie — toate locurile
|
||||
|
||||
Calculul e centralizat in doua straturi Oracle, apelate de fiecare punct de consum (VFP nu face
|
||||
calcul TVA local — doar construieste SQL dinamic care cheama functiile Oracle):
|
||||
|
||||
- **`PACK_SESIUNE.calculeaza_pret_fara_tva/tva/cu_tva`** — motorul de rotunjire per-unitate de
|
||||
pret (nu e in `PACK_FACTURARE`; pachetul `PACK_SESIUNE` nu a fost gasit definit separat in
|
||||
arhiva cautata — cautare punctuala pe cateva luni din 2025/2026, fara succes; probabil e intr-un
|
||||
script `COMUN_PACK_SESIUNE` mai vechi, netestat exhaustiv).
|
||||
- **`PACK_FACTURARE.calculeaza_pret`** (linia 14557) — wrapper subtire peste cele 3 functii
|
||||
`PACK_SESIUNE` de mai sus.
|
||||
- **`PACK_FACTURARE.calculeaza_sume`** (linia 14631, spec 980) — calculeaza suma_fara_tva /
|
||||
suma_tva / suma_cu_tva pe linie (cantitate * pret), delegand catre:
|
||||
- **`calculeaza_total_fara_tva`** (linia 15745/15769) — delega la `pack_sesiune.calculeaza_total_fara_tva`
|
||||
- **`calculeaza_total_tva`** (linia 15850/15874) — delega la `pack_sesiune.calculeaza_total_tva`
|
||||
- **`calculeaza_total_cu_tva`** (linia 15638/15662) — delega la `pack_sesiune.calculeaza_total_cu_tva`
|
||||
- variantele `_fact` (`calculeaza_total_fara_tva_fact` 15794, `calculeaza_total_tva_fact` 15899,
|
||||
`calculeaza_total_cu_tva_fact` 15687) au **formula proprie inline** (nu delega la
|
||||
`pack_sesiune`), documentata explicit in cod ca fiind "folosita in view-ul
|
||||
fact_vrap_centralizator_fact" (comentarii 15686, 15744, 15793, 15848, 15897).
|
||||
|
||||
Formula `_fact` (exemplu `calculeaza_total_tva_fact`, 15899-15949) e explicit ROUND-based, cu
|
||||
ramuri separate pentru `discount_evidentiat` — aici e punctul central de rotunjire per linie.
|
||||
|
||||
- **Puncte de CONSUM ale acestor functii** (unde efectiv se calculeaza TVA afisat/raportat):
|
||||
- Views `fact_vrap_fact_articole` si `fact_vrap_articole_vandute`
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:18-44, 131-196` — apeleaza
|
||||
`calculeaza_total_fara_tva`/`calculeaza_total_tva` direct in `SELECT`)
|
||||
- Raport VFP dinamic: `COMUN\programe\oproceduri_rapoarte_fact.prg:581-590` — SQL construit in
|
||||
VFP apeleaza direct `pack_sesiune.calculeaza_pret_cu_tva(...)` si
|
||||
`pack_sesiune.calculeaza_total_cu_tva(...)` pentru listare/relistare rapoarte articole vandute.
|
||||
- `PACK_FACTURARE.scrie_in_vanzari` (13468) si `finalizeaza_avize_lucrare` (14807) — calculeaza
|
||||
si scriu `VANZARI.TOTAL_FARA_TVA`/`TOTAL_CU_TVA` folosind `calculeaza_total_fara_tva_fact` in
|
||||
subquery-uri (13716-13786, 14965-15008).
|
||||
- `verifica_total_document` (16009) — vezi punctul 5, verifica totalul calculat vs. cel din
|
||||
notele contabile si genereaza o corectie.
|
||||
|
||||
Nu am gasit un apel VFP direct catre `calculeaza_pret(` sau `calculeaza_sume(` in working copy
|
||||
`ROAFACTURARE`/`COMUN` (grep pe nume exact, fara rezultate) — deci formularul de introducere
|
||||
factura in VFP nu recalculeaza local pretul/TVA-ul linie cu linie prin apel explicit de
|
||||
procedura; cel mai probabil articolele + preturile lor (deja cu `pret`, `pret_cu_tva`,
|
||||
`proc_tvav`) vin dintr-un cursor Oracle (`PACK_FACTURARE.cursor_preturi`, spec 335, body 2121)
|
||||
populat cand se adauga articolul, iar TVA vizibila in grid e calculata la afisare din acele
|
||||
coloane brute — nu am gasit expresia VFP exacta (`cursor_preturi` e ~500 linii, nu am parcurs
|
||||
linie cu linie in bugetul acestei cercetari).
|
||||
|
||||
### 3. Ce inseamna "preturi_cu_tva" / `pret_cu_tva`
|
||||
|
||||
- Pe linie: `VANZARI_DETALII.PRET_CU_TVA` — NUMBER(1), 0/1, transmis ca parametru `V_PRET_CU_TVA`
|
||||
/ `V_PRET_ARE_TVA` la toate functiile de calcul de mai sus (controleaza care ramura de formula
|
||||
se aplica — pornind de la pret cu TVA sau fara TVA).
|
||||
- In grid-ul VFP exista o coloana **checkbox** `cPret_cu_tva` in
|
||||
`D:\ROA\ROAFACTURARE\Clase\ofundal_facturare.vc2:696-699` (`_grdrow2.cPret_cu_tva...`) — probabil
|
||||
afiseaza/permite editarea flagului per linie in formular.
|
||||
- **Nu am gasit** coloana `PRET_CU_TVA` (sau similara) direct pe `CRM_POLITICI_PRETURI` in
|
||||
scripturile de migrare cautate (am cautat `ALTER TABLE CRM_POLITICI_PRETURI ADD`, fara hit
|
||||
pe acest nume) — deci originea exacta a valorii implicite per politica de pret ("politica are
|
||||
bifat 'preturi fara TVA'", cum descrie todo #7) nu e confirmata cu `fisier:linie`; e probabil
|
||||
citita/propagata in `PACK_FACTURARE.cursor_preturi` (2121) sau
|
||||
`citeste_setari_pol_pret` (spec 324, body 2025) cand se adauga articolul pe factura — nu am
|
||||
parcurs acele corpuri in detaliu (buget de cercetare).
|
||||
|
||||
### 4. Locuri de atins daca s-ar salva `pret_cu_tva`/`valoare_tva` per linie real (nu calculat)
|
||||
|
||||
Enumerare pe baza punctelor de consum gasite mai sus:
|
||||
|
||||
1. **DDL**: `ALTER TABLE VANZARI_DETALII ADD (valoare_tva, pret_fara_tva_calculat, ...)` — coloane
|
||||
noi + migrare date istorice.
|
||||
2. **`PACK_FACTURARE`** (Oracle, `ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`):
|
||||
- `adauga_articol_factura` (spec 529, body 4972) — punctul unde se insereaza linia in
|
||||
`VANZARI_DETALII_TEMP`; ar trebui sa scrie valoarea (eventual editata de user) in loc s-o
|
||||
lase doar pe `pret`/`pret_cu_tva`/`proc_tvav`.
|
||||
- `calculeaza_sume` (14631) — daca valoarea e editabila, aceasta procedura ar trebui sa
|
||||
citeasca valoarea salvata in loc s-o recalculeze, sau sa fie ocolita.
|
||||
- `scrie_in_vanzari` (13468) si `finalizeaza_avize_lucrare` (14807) — subquery-urile care insumeaza
|
||||
`calculeaza_total_fara_tva_fact`/`calculeaza_total_tva_fact` pe toate liniile
|
||||
(13716-13786, 14965-15008) ar trebui sa insumeze coloana noua in loc s-o recalculeze.
|
||||
- `verifica_total_document` (16009) — logica de reconciliere total-vs-note-contabile ar trebui
|
||||
ajustata (vezi punct 5) daca totalul nu se mai deriva strict din formula.
|
||||
3. **Views Oracle**: `fact_vrap_fact_articole`, `fact_vrap_articole_vandute`
|
||||
(`ff_2026_07_27_01_FACTURARE.sql:10-257`), `fact_vfacturi`/`fact_vfacturi2` (vezi Subiect B #11)
|
||||
— toate ar trebui sa citeasca noua coloana in loc de `calculeaza_total_*`.
|
||||
4. **VFP**: `COMUN\programe\oproceduri_rapoarte_fact.prg:581-590` — SQL-ul de raport care apeleaza
|
||||
direct `pack_sesiune.calculeaza_pret_cu_tva`/`calculeaza_total_cu_tva`.
|
||||
5. **VFP grid formular**: `D:\ROA\ROAFACTURARE\Clase\ofundal_facturare.vc2` (coloana
|
||||
`cPret_cu_tva` + coloanele de pret/valoare din grid — nu identificate exhaustiv, cautare
|
||||
punctuala doar pe flag).
|
||||
6. **Rapoarte `.frx`** care afiseaza TVA pe linie de factura (ex. `usr_factura*.fr2` — 25 de
|
||||
fisiere gasite cu referinta la `PACK_FACTURARE`, listate la cautarea initiala; nu au fost
|
||||
deschise individual).
|
||||
|
||||
Estimare: minim **6 zone distincte** (DDL, pachet Oracle ~4 proceduri, 3-4 views, 1 program raport
|
||||
VFP, grid formular, rapoarte `.frx`) — consistent cu observatia ca e o schimbare "de volum", nu
|
||||
locala.
|
||||
|
||||
### 5. Mecanism existent de ajustare/rotunjire
|
||||
|
||||
**Da, exista, dar la nivel contabil, nu la nivel de linie facturata / vizibil userului.**
|
||||
|
||||
`PACK_FACTURARE.verifica_total_document` (linia 16009-16188+) compara totalul FTVA/TVA asteptat
|
||||
(`pack_facturare.ntotftva`, populat din VFP la `pnTotalFtva`/`Thisform.nbazaron`) cu suma reala din
|
||||
notele contabile generate (`ACT_TEMP`, grupate pe conturi `4111`/`4427`/`418`/`4428`). Daca difera
|
||||
(16082-16083: `NVL(pack_facturare.ntotftva,0) <> V_TOTFTVA_VER`), calculeaza diferenta
|
||||
`pack_facturare.ndifftva := pack_facturare.ntotftva - V_TOTFTVA_VER` (16085) si **insereaza automat
|
||||
o linie de corectie in `ACT_TEMP`** (16086-16188, INSERT cu `suma => pack_facturare.ndifftva`) —
|
||||
adica ajustarea de rotunjire se absoarbe silentios in nota contabila, nu apare ca linie editabila
|
||||
pe factura si nu se reflecta in `VANZARI_DETALII`. Aceasta e probabil exact mecanismul care face ca
|
||||
utilizatorul sa nu poata corecta manual TVA-ul afisat: rotunjirea se "repara" doar in contabilitate,
|
||||
dupa fapt.
|
||||
|
||||
---
|
||||
|
||||
## SUBIECT B — Denormalizare VANZARI, bug facturi din avize + numerar (#8)
|
||||
|
||||
### 6. Locatia `PACK_FACTURARE`
|
||||
|
||||
Nu exista fisier `.pck`/`.sql` cu acest pachet in working copy `ROAFACTURARE` (nici in `COMUN/`
|
||||
local) — **e in afara working copy-ului VFP**, in arhiva DDL/PL-SQL Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\`. Cea mai recenta versiune completa (16948 linii):
|
||||
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql`
|
||||
|
||||
(exista si un diff mai nou, doar pe view-uri, `2026\07\ff_2026_07_27_01_FACTURARE.sql` — vezi #11).
|
||||
Istoricul complet de modificari e in `SCRIPTURI_CLAR\<an>\<luna>\ff_..._COMUN_PACK_FACTURARE.sql`
|
||||
respectiv `..._FACTURARE.sql` (zeci de fisiere, 2006-2026).
|
||||
|
||||
### 7. Procedura care scrie in VANZARI valorile denormalizate
|
||||
|
||||
**`PACK_FACTURARE.scrie_in_vanzari`** (spec linia 894, body **linia 13468-13908**) — apelata din
|
||||
`finalizeaza_factura` (linia **14740**). Face `UPDATE VANZARI SET ...` cu (13886-13898):
|
||||
|
||||
```
|
||||
total_fara_tva = lnTotalFaraTVA,
|
||||
...
|
||||
total_cu_tva = lnTotalCuTVA,
|
||||
...
|
||||
serie_incasat = lnSerieIncasat,
|
||||
nr_incasat = lnNrIncasat,
|
||||
suma_incasat = lnSumaIncasat,
|
||||
tip_incasat = lnTipIncasat
|
||||
```
|
||||
|
||||
unde `lnSerieIncasat`/`lnNrIncasat`/`lnSumaIncasat`/`lnTipIncasat` sunt populate (13727-13730) din
|
||||
variabilele **de pachet** `pack_facturare.cserie_act_incasare`, `.nnumar_act_incasare`,
|
||||
`.nsuma_incasare`, `.ntip_doc_incasare` (declarate 179-182).
|
||||
|
||||
O a doua ramura echivalenta exista in **`finalizeaza_avize_lucrare`** (spec 1011, body
|
||||
**14807-15176**), care face acelasi UPDATE (15124-15130) — pentru ramura "avize pe lucrare".
|
||||
|
||||
Variabilele de pachet `cserie_act_incasare`/`nnumar_act_incasare`/`ntip_doc_incasare`/
|
||||
`nsuma_incasare` sunt setate **doar** de **`PACK_FACTURARE.scrie_incasari`** (spec 864, body
|
||||
**13070-13139**), apelata condiționat (`IF V_LISTA_INCASARE IS NOT NULL`) din:
|
||||
- `scrie_factura2` — linia **6178** (ramura factura normala / comanda / contract)
|
||||
- `scrie_factura_avize` — linia **7008** (ramura **factura din aviz**)
|
||||
|
||||
Sunt resetate la `NULL` in `initializeaza_date_factura` (comentariu 1384-1386, cod la
|
||||
**1876-1880**) — fix explicit din 03.07.2020: *"ramaneau completate pe facturile urmatoare de la o
|
||||
factura anterioara"*.
|
||||
|
||||
`VANZARI.AVIZE` (seria/numarul avizelor facturate) e scris de
|
||||
**`scrie_corespondente_vanzari`** (spec 1057, body **15421-15457**, comentariu la linia **15445**:
|
||||
*"Completez VANZARI.AVIZE redundant, pentru a nu face mai rapid fact_vfacturi"*) — nu am confirmat
|
||||
in acest buget de cercetare din ce apeleaza `finalizeaza_factura` daca `scrie_corespondente_vanzari`
|
||||
ruleaza necondiționat pe toate tipurile sau doar pe unele (`V_TIP` e parametru) — merita verificat
|
||||
punctual daca se investigheaza bug-ul mai departe.
|
||||
|
||||
### 8. Coloanele denormalizate din VANZARI si ramura care le populeaza
|
||||
|
||||
Toate adaugate prin `2017\03\ff_2017_03_28_01_FACTURARE.sql:9-38` (comentariu fisier, linia 1-4:
|
||||
*"adaugare coloane in vanzari pentru denormalizarea join-urilor din fact_vfacturi"*):
|
||||
|
||||
| Coloana | Comentariu DB (linia 44-54 din script) | Populata de |
|
||||
|---|---|---|
|
||||
| `DISCOUNT_TVA` | TVA DISCOUNT (DISCOUNT * MAX(PROC_TVA) ARTICOLE) | `scrie_in_vanzari` |
|
||||
| `VALOARE_ACHIZITIE` | Valoare la pret achizitie articole | `scrie_in_vanzari` |
|
||||
| `TOTAL_FARA_TVA` | Total fara TVA lei | `scrie_in_vanzari` (13886), `finalizeaza_avize_lucrare` (15124) |
|
||||
| `TOTAL_TVA` | Total TVA lei | idem |
|
||||
| `TOTAL_CU_TVA` | Total cu TVA lei | `scrie_in_vanzari` (13888), `finalizeaza_avize_lucrare` (15126) |
|
||||
| `SERIE_INCASAT` | Seria chitanta/bon fiscal | `scrie_in_vanzari` (13895), din `pack_facturare.cserie_act_incasare` (setat de `scrie_incasari`) |
|
||||
| `NR_INCASAT` | Nr chitanta/bon fiscal | idem (13896) |
|
||||
| `SUMA_INCASAT` | Suma chitanta/bon fiscal | idem (13897) |
|
||||
| `TIP_INCASAT` | 11=CHITANTA, 2=BON FISCAL | idem (13898); vezi si `nTipIncasareCardBancar`=3, `nTipIncasareTichete`=5 |
|
||||
| `AVIZE` | Serie/numar avize facturate (max 1000 caractere, comentariu la linia 1490) | `scrie_corespondente_vanzari` (15421) |
|
||||
|
||||
### 9. Tipurile de factura/aviz si ramificarea codului
|
||||
|
||||
Din `VANZARI.TIP` (CASE explicit in view `fact_vfacturi2`,
|
||||
`ff_2017_03_28_01_FACTURARE.sql:89-171`) — cateva valori cheie:
|
||||
`1`=POLITICA PRETURI, `2`=CONTRACT, `3`=COMANDA, **`4`=FACT. DIN AVIZ**, `21`=AVIZ PE BAZA DE
|
||||
COMANDA, `24`=AVIZ DE RETUR, `43`=BON FISCAL MAGAZIN, etc. (lista completa la liniile citate).
|
||||
|
||||
Ramificare in VFP, `D:\ROA\ROAFACTURARE\COMUN\clase\ofacturare.vc2`, metoda
|
||||
**`do_scrie_factura`** — exista **doua copii aproape identice** ale acestei logici, in doua clase
|
||||
diferite (confirmat via `vfp_symbols.ps1 -Where`):
|
||||
- `frm_facturare_articole.do_scrie_factura` — **liniile 13981-14339**
|
||||
- `frm_facturare_articole2.do_scrie_factura` — **liniile 18004-18331**
|
||||
|
||||
Structura `DO CASE` (identica in ambele, ex. clasa 1 la liniile 14067-14174):
|
||||
- `poDate.eProforma = 1` → `{call pack_facturare.scrie_proforma(...)}` (14071)
|
||||
- `poDate.Tip = 4` → **`{call pack_facturare.scrie_factura_avize(...)}`** (14103) — "facturare din
|
||||
aviz" (comentariu 14086-14087)
|
||||
- `poDate.Tip IN (3,21,25,28,42,47)` → `{call pack_facturare.scrie_factura2(...)}` (14130) —
|
||||
"facturare pe baza de comanda / avize pe baza de comanda"
|
||||
- `Otherwise` → `{call pack_facturare.scrie_factura2(...)}` (14158) — politica de preturi/contract
|
||||
|
||||
Inainte de asta, lista de incasare `lcListaIncasare` se construieste (14012-14038) din
|
||||
`poDate.ntip_incasare` (11=chitanta, 2=bon fiscal, 3=POS/card), comun tuturor ramurilor.
|
||||
|
||||
### 10. Ramura "factura din aviz" + "achitata numerar" — ce ar trebui sa scrie si ipoteza de cauza
|
||||
|
||||
**Ce se intampla, pas cu pas** (`Tip = 4`, `ntip_incasare` in (11,2,3)):
|
||||
|
||||
1. VFP (`ofacturare.vc2:14012-14038`) construieste `lcListaIncasare` de forma
|
||||
`'11|<suma>|<id_casa>;'` (chitanta) sau `'2|...'`/`'3|...'` (bon fiscal/card) — **daca**
|
||||
`ntip_incasare` nu e in (11,2,3), `lcListaIncasare = [NULL]` (literal SQL NULL).
|
||||
2. VFP construieste `lcSql = {call pack_facturare.scrie_factura_avize(pnDiscount, serie_chit,
|
||||
nr_incasare, lcListaIncasare, id_delegat, id_masina, id_facturare, listare_detaliata,
|
||||
dataora_exp, id_agent, text_aditional, discount_evidentiat, param_aditional, ?@nid_vanzare)}`
|
||||
(14103-14115) — semnatura corespunde exact cu procedura Oracle activa
|
||||
`scrie_factura_avize` (linia **6675-7041**, care NU are `V_TOTFTVA`/`V_TOTTVA` ca prime
|
||||
argumente, spre deosebire de `scrie_factura2` — asta e corect, nu e discrepanta de parametri).
|
||||
3. In Oracle, `scrie_factura_avize` (7007-7012): `IF V_LISTA_INCASARE IS NOT NULL THEN
|
||||
pack_facturare.scrie_incasari(...)` — deci **doar daca** `lcListaIncasare` nu e literalul
|
||||
`NULL` se seteaza variabilele de pachet `cserie_act_incasare`/etc.
|
||||
4. `scrie_factura_avize` seteaza `pack_facturare.clistaid_avize := ...V_LISTAID` (7020) — lista de
|
||||
ID-uri de avize facturate, folosita ulterior de `scrie_corespondente_vanzari` pentru
|
||||
`VANZARI.AVIZE`.
|
||||
5. `scrie_factura_avize` cheama `finalizeaza_factura` (7026-7034), care cheama `scrie_in_vanzari`
|
||||
(14740) → scrie `serie_incasat`/`nr_incasat`/`suma_incasat`/`tip_incasat` din variabilele de
|
||||
pachet setate la pasul 3.
|
||||
|
||||
**La nivel de cod citit, lantul pare corect cablat** — parametrii trec prin, semnaturile se
|
||||
potrivesc, iar cele doua clase VFP (`frm_facturare_articole` si `frm_facturare_articole2`) au
|
||||
logica identica pentru aceasta ramura.
|
||||
|
||||
**IPOTEZA (cauza posibila a bug-ului, nedemonstrata prin citire de cod — necesita investigatie
|
||||
suplimentara/testare)**:
|
||||
- Daca ordinea reala de operatii difera de `ordine_operatii_facturare.txt` (ex. daca intre pasul 3
|
||||
si pasul 5 se mai apeleaza `initializeaza_date_factura` pentru alt document/lucru din aceeasi
|
||||
sesiune, inainte ca `finalizeaza_factura` sa apuce sa citeasca variabilele de pachet), fix-ul din
|
||||
03.07.2020 (linia 1876-1880, reset la NULL) ar putea sterge datele de incasare **inainte** ca
|
||||
`scrie_in_vanzari` sa le foloseasca — dar nu am gasit in codul citit un asemenea apel intercalat.
|
||||
- Alternativ: daca pe ramura aviz `scrie_corespondente_vanzari` (care scrie `VANZARI.AVIZE`) nu e
|
||||
apelata necondiționat din `finalizeaza_factura` pentru `TIP=4` (nu am verificat corpul complet al
|
||||
`finalizeaza_factura`, liniile 14723-14807, dincolo de apelul la `scrie_in_vanzari`) — merita
|
||||
verificat explicit daca acel apel exista si e neconditionat de tip.
|
||||
- Nu am verificat daca exista vreo diferenta intre `scrie_factura_avize` si
|
||||
`scrie_factura_avize_retur` (spec 667, alta ramura pentru tip retur din aviz) in privinta
|
||||
apelului `scrie_incasari`/`scrie_in_vanzari` — posibil ca bug-ul sa fie specific ramurii de retur,
|
||||
nu celei simple.
|
||||
|
||||
Recomandare pentru pasul urmator (daca se investigheaza mai departe): instrumentare/breakpoint pe
|
||||
`scrie_in_vanzari` (13468) intr-un mediu de test, pentru o factura Tip=4 platita numerar, verificand
|
||||
valorile efective ale `pack_facturare.cserie_act_incasare`/`nnumar_act_incasare`/`nsuma_incasare`/
|
||||
`ntip_doc_incasare` chiar inainte de UPDATE (13886-13898).
|
||||
|
||||
### 11. Cele doua view-uri de facturi
|
||||
|
||||
- **`fact_vfacturi`** — view-ul "original" (pe model relational, cu join-uri catre `VANZARI_DETALII`
|
||||
/ `ACT` / etc., fara denormalizare). Redefinit de multe ori de-a lungul timpului; cea mai recenta
|
||||
gasita: `D:\ROA\DATABASE\SCRIPTURI_CLAR\2023\11\ff_2023_11_17_01_COMUN.sql` (si
|
||||
`2023\02\ff_2023_02_08_01_COMUN.sql`) — nu am deschis continutul exact in acest buget.
|
||||
- **`fact_vfacturi2`** — view-ul cu totaluri **denormalizate din VANZARI** (`total_fara_tva`,
|
||||
`total_tva`, `total_cu_tva`, `serie_incasat`, `nr_incasat`, `suma_incasat`, `tip_incasat`,
|
||||
`avize` citite direct din coloanele `VANZARI`, nu recalculate din `VANZARI_DETALII`/`ACT`).
|
||||
Definit initial in **`D:\ROA\DATABASE\SCRIPTURI_CLAR\2017\03\ff_2017_03_28_01_FACTURARE.sql:59-236`**,
|
||||
cu comentariul explicit (linia 3): *"View fact_vfacturi2 - temporar, urmand a inlocui view-ul
|
||||
fact_vfacturi, dupa completarea coloanelor din vanzari pentru datele existente deja"*.
|
||||
|
||||
Separat, exista si o a doua pereche de view-uri, mai recenta si mai granulara (pe linie de
|
||||
articol, nu pe factura): **`fact_vrap_fact_articole`** / **`fact_vrap_articole_vandute`**, definite
|
||||
in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\07\ff_2026_07_27_01_FACTURARE.sql:10-257` — acestea NU
|
||||
citesc din coloane denormalizate, ci calculeaza TVA live prin `pack_facturare.calculeaza_total_*`
|
||||
(vezi Subiect A #2). Nu sunt aceleasi cu perechea mentionata in cerinta (care pare sa se refere la
|
||||
`fact_vfacturi`/`fact_vfacturi2`), dar sunt relevante daca se cauta "view-ul cu totaluri din
|
||||
vanzari" generic.
|
||||
|
||||
---
|
||||
|
||||
## Note metodologice
|
||||
|
||||
- `PACK_SESIUNE` (motorul de rotunjire per-pret, apelat de `PACK_FACTURARE`) nu a fost gasit
|
||||
definit ca fisier separat in cautarile punctuale facute (cateva luni din 2025-2026); daca se
|
||||
continua investigatia pe rotunjire, merita o cautare dedicata `create or replace package
|
||||
pack_sesiune` in `D:\ROA\DATABASE\SCRIPTURI_CLAR`.
|
||||
- Arhiva `D:\ROA\DATABASE\SCRIPTURI_CLAR` e foarte mare (mii de fisiere, 2009-2026); cautarile de
|
||||
mai sus au fost tintite (nume de coloane/proceduri cunoscute), nu exhaustive — un `grep` complet
|
||||
pe intreg arhivul repetat timeout la 20s in unele incercari initiale.
|
||||
- Nu am gasit apeluri catre `PACK_FACTURARE` din `D:\ROA\ROAFACTURARE` propriu-zis (in afara
|
||||
`COMUN\clase\ofacturare.vc2`) — pachetul e consumat exclusiv prin acea clasa si prin
|
||||
`COMUN\programe\oproceduri_rapoarte_fact.prg`.
|
||||
@@ -1,164 +0,0 @@
|
||||
# Proiectare view Oracle pentru liniile de articole ale unei vanzari (VVANZARI_ARTICOLE)
|
||||
|
||||
Cercetare + proiectare, read-only pe baza. Decizia lui Marius (08.08.2026): view dedicat, varianta B
|
||||
din `rec_review_ancorare_s4.md` (respinsa atunci doar pentru ca insemna migrare de schema - acum
|
||||
aprobata). Inlocuieste lista de 20 coloane + join pe 4 tabele din `IncarcaArticoleFactura`
|
||||
(`COMUN\programe\ofacturare_editare.prg:201-208`).
|
||||
|
||||
## A. Precoditia VERSIUNE
|
||||
|
||||
`MARIUSM_AUTO` e la zi **pentru schema firmei (`ff_`)** pe orice ar putea atinge `VANZARI_DETALII`/
|
||||
facturare: toate scripturile `ff_` din 2015 incoace apar in `VERSIUNE`, inclusiv cele mai recente
|
||||
patru (`ff_2026_08_06_09/10/11/12`, comanda/contract, `PACK_FACTURARE`, `FACT_VFACTURI`,
|
||||
`VANZARI_BACKFILL`). Diferenta gasita fata de `SCRIPTURI_CLAR` (452 de fisiere, din care 14 `ff_`)
|
||||
e integral din 2009-2014 (dinainte de generalizarea `UpdateVersiune`) plus scripturi de diagnostic
|
||||
fara prefix de tracking (`DIAG_SPATIU_*`, ad-hoc-uri fara nume standard) - niciunul din ele nu
|
||||
atinge `VANZARI`/`VANZARI_DETALII`/facturare. Verdict: **precoditia trece**, sursa `MARIUSM_AUTO` e
|
||||
de incredere pentru acest DDL.
|
||||
|
||||
## B. Ce exista deja - niciun candidat direct refolosibil, dar un precedent util
|
||||
|
||||
Cautat in `all_views` (MARIUSM_AUTO) orice view pe `VANZARI_DETALII`/liniile unei vanzari:
|
||||
`VVANZARI_DETALII`, `VVANZARI_DETALII_TOT`, `FACT_VFACTURI_DETALII` sunt cele relevante.
|
||||
|
||||
- **`FACT_VFACTURI_DETALII`** (exportat integral) e cel mai apropiat candidat structural - selecteaza
|
||||
direct din `vanzari_detalii`, cu join-uri catre `nom_articole`/`nom_gestiuni`/`nom_valute` ca in
|
||||
proiectarea de mai jos. **Nu e reutilizabil ca atare**: `pret` si `discount_unitar` sunt
|
||||
RECALCULATE la cursul valutar curent (`ROUND(NVL(g.curs,1)*NVL(a.pret,0)/NVL(g.multiplicator,1),
|
||||
pack_sesiune.getoptiunefirma('PPRETV'))`, apel de functie PL/SQL per coloana per rand), construit
|
||||
pentru **afisare/tiparire** facturi, nu pentru editare. Pagina de editare (#6) trebuie sa lucreze
|
||||
pe valorile RAW stocate, ca la salvare (S5) sa scrie inapoi exact ce a citit - un `pret` deja
|
||||
convertit ar strica exact acest contract. Confirma insa tiparul de join corect (articol/gestiune/
|
||||
valuta) si ca genul asta de view exista deja in familia `FACT_*` pentru alt scop.
|
||||
- **`VVANZARI_DETALII`/`VVANZARI_DETALII_TOT`**: alt scop (afisare generica vanzari + utilizatori +
|
||||
politici de pret), nu au `pret_cu_tva`, `cont`, `id_valuta`, `id_gestiune`, `taxcode`, `lot` -
|
||||
nepotrivite.
|
||||
|
||||
Niciunul nu inlocuieste nevoia unui view nou - se continua cu proiectarea.
|
||||
|
||||
## C. Numele: `VVANZARI_ARTICOLE`
|
||||
|
||||
Verificat liber in `all_objects` (MARIUSM_AUTO). 17 caractere, sub limita de 30 (Oracle 10.2).
|
||||
|
||||
**Criteriul lui Marius (08.08.2026)**: numele trebuie sa pastreze prefixul familiei de vanzari,
|
||||
`vvanzari_*`, pentru ca el se uita la view-uri **alfabetic** si vrea sa vada dintr-o privire ca tine
|
||||
de vanzari. La o listare alfabetica: `VVANZARI_ARTICOLE`, `VVANZARI_DETALII`,
|
||||
`VVANZARI_DETALII_TOT`, `VVANZARI_TOT`.
|
||||
|
||||
Numele analog conventiei surorilor de pe acelasi formular (`vact_tot`, `vrul_tot`,
|
||||
`vrul_obinv_tot`) ar fi fost `vvanzari_detalii_tot`, dar e **deja ocupat** (alt view, B mai sus).
|
||||
|
||||
Numele de lucru din prima varianta a fost `VVD_TOT` (`v` + abreviere + `_tot`, aliniat cu aliasul
|
||||
VFP `tvd`), respins de Marius pe criteriul de mai sus: nu se citea ca facand parte din familie si
|
||||
cadea in alta parte a listei alfabetice.
|
||||
|
||||
## D. Coloanele - RAW, fara filtru STERS in view
|
||||
|
||||
Cele 20 de coloane consumate azi + **`id_vanzare` adaugat**: lista din
|
||||
`ofacturare_editare.prg:201-203` filtreaza pe `vd.id_vanzare` dar nu-l intoarce niciodata ca si
|
||||
coloana - omisiune reala, semnalata in misiune, acum corectata in view.
|
||||
|
||||
- **Fara conversie valutara, fara valori calculate** (spre deosebire de `FACT_VFACTURI_DETALII`) -
|
||||
editarea scrie inapoi exact ce citeste.
|
||||
- **`STERS` ramane in view ca si coloana, dar FARA filtru `WHERE sters=0` in definitie** - acelasi
|
||||
tipar ca `VACT_TOT`/`VRUL_TOT`/`VRUL_OBINV_TOT` (niciunul nu filtreaza `sters` in view, apelantul
|
||||
o face explicit). Apelantul de azi (`IncarcaArticoleFactura`) deja are `WHERE ... vd.sters = 0` -
|
||||
ramane neschimbat, doar `FROM vanzari_detalii vd ... WHERE vd.id_vanzare=... AND vd.sters=0` devine
|
||||
`FROM vvanzari_articole vd WHERE vd.id_vanzare=... AND vd.sters=0`.
|
||||
|
||||
## E. Ce s-a respins: valorile calculate `CALCULEAZA_TOTAL_FARA_TVA_FACT`/`_TVA_FACT`
|
||||
|
||||
Ambele sunt functii **in `PACK_FACTURARE`**, semnatura `(V_PRET, V_DIFERENTA, V_CURS,
|
||||
V_DISCOUNT_UNITAR, V_DISCOUNT_EVIDENTIAT, V_CANTITATE, V_PRET_CU_TVA, V_PROC_TVAV) RETURN NUMBER` -
|
||||
strict `NUMBER`, deci **apelabile din SQL** (confirmat prin `all_arguments`, fara tip PL/SQL-only).
|
||||
Exista precedent local pentru functii de pachet apelate per-rand intr-un view din aceeasi familie
|
||||
(`VRUL_TOT` cheama `PACK_SESIUNE.SUMA_RON` pe aproape fiecare coloana numerica), deci performanta nu
|
||||
e un argument respingator prin ea insasi pe un view filtrat pe `id_vanzare` (cateva linii/factura).
|
||||
|
||||
**Respins totusi, pentru acum**:
|
||||
1. `V_DISCOUNT_EVIDENTIAT` **nu e coloana pe `VANZARI_DETALII`** - e pe antet (`VANZARI.
|
||||
DISCOUNT_EVIDENTIAT`, confirmat in `all_tab_columns`). A include totalul calculat per linie ar
|
||||
cere fie un join suplimentar la `VANZARI` (umfla view-ul cu o dependenta noua doar pentru un
|
||||
parametru), fie parametrul trimis din VFP - oricum, in afara scopului Rundei 1 (doar afisare).
|
||||
2. Runda 1 (deja implementata si testata, `docs\progres.md`) **nu consuma** aceste valori - grid-ul
|
||||
e readonly, fara subtotal calculat.
|
||||
3. Nevoia reala apare la S4b/Runda 4 (`plan_06_s4_proiectare.md`, C.1-C.3) - dar acolo e vorba de
|
||||
**totalul pe DOCUMENT** (suma peste toate liniile), comparat cu `ACT`/`RUL`, nu de o coloana pe
|
||||
fiecare rand din grid. O interogare de agregare separata (sau o functie Oracle dedicata) e o
|
||||
potrivire mai buna pentru "totalul de control" decat 2 coloane calculate in view-ul de grid.
|
||||
4. **Costul amanarii e mic**: extinderea unui VIEW (`CREATE OR REPLACE`) nu e o migrare de schema in
|
||||
sensul de risc/coordonare al unei modificari de tabela - se poate adauga oricand printr-un script
|
||||
nou, fara sa afecteze datele sau consumatorii existenti ai coloanelor deja definite. Deci nu e
|
||||
nevoie sa se "prevada" acum ca sa se evite un al doilea script peste o saptamana.
|
||||
|
||||
**Recomandare pentru Runda 4**: cand S4b ajunge la implementare, se adauga fie doua coloane noi in
|
||||
`VVANZARI_ARTICOLE` (dupa un join la `VANZARI` pentru `DISCOUNT_EVIDENTIAT`), fie - preferabil - o interogare
|
||||
de agregare separata in Oracle care calculeaza direct SUMA pe document, fara sa treaca prin grid.
|
||||
Decizia ramane a lui Marius/sesiunii care implementeaza S4b, pe baza planului deja scris in
|
||||
`plan_06_s4_proiectare.md` C.1.
|
||||
|
||||
## F. Validare pe cele doua cazuri de regresie
|
||||
|
||||
Rulat direct ca `SELECT` (fara `CREATE VIEW`), corpul propus vs. interogarea de azi din
|
||||
`IncarcaArticoleFactura`, pe `MARIUSM_AUTO`:
|
||||
|
||||
- **`id_vanzare = 1050`** (`cod=1140888`, `tip=1`): **4 randuri**, valori identice rand-cu-rand intre
|
||||
interogarea veche si corpul noului view (`id_vanzare_det` 1584-1587). Coincide cu baza de regresie
|
||||
din `docs\progres.md`.
|
||||
- **`id_vanzare = 1047`** (`cod=1140885`, `tip=-12`): **2 randuri** (1578, 1579), identice intre cele
|
||||
doua interogari.
|
||||
|
||||
Ambele cazuri: zero divergenta, inclusiv pe coloanele cu `NULL` (ex. `id_gestiune`/`nume_gestiune`
|
||||
pe liniile nestocate din `id_vanzare=1047`).
|
||||
|
||||
## G. Numele coloanelor la iesire
|
||||
|
||||
Fara alias-uri noi - toate coloanele pastreaza numele lor de baza din tabelele sursa (Oracle
|
||||
foloseste automat numele coloanei cand nu exista `AS`):
|
||||
|
||||
```
|
||||
ID_VANZARE, ID_VANZARE_DET, ID_ARTICOL, CANTITATE, PRET, PRET_CU_TVA, PROC_TVAV, DISCOUNT_UNITAR,
|
||||
ID_GESTIUNE, CONT, ID_VALUTA, ID_JTVA_COLOANA, SERIE, EXPLICATIE, TAXCODE, LOT, STERS,
|
||||
DENUMIRE, CODMAT, NUME_GESTIUNE, NUME_VAL
|
||||
```
|
||||
|
||||
**Zero schimbari fata de azi** pentru `ControlSource`-urile existente ale `grdArticoleFactura`
|
||||
(`tvd.denumire`, `tvd.codmat`, etc.) - toate numele coincid cu ce se foloseste azi. Singura
|
||||
schimbare vizibila e coloana noua `tvd.id_vanzare`, disponibila dar neconsumata inca de grid.
|
||||
|
||||
## H. Numerotare script
|
||||
|
||||
`SCRIPTURI_CLAR\2026\08\` exista deja, ultimul numar folosit azi (08.08.2026, la momentul
|
||||
verificarii) e **niciunul** - nu exista fisiere `_2026_08_08_` in director (ultimele sunt din
|
||||
06.08.2026, `NN` pana la 12). **`NN=01` e liber pentru 08.08.2026**, comun tuturor prefixelor -
|
||||
de reverificat la momentul aplicarii, pentru ca sesiunea are mai multi agenti activi in paralel azi
|
||||
care ar putea consuma acelasi numar inaintea acestui script.
|
||||
|
||||
Nume final propus: **`ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql`** - scriptul livrat foloseste deja acest
|
||||
nume in `exec pack_migrare.UpdateVersiune(...)`; daca sesiunea principala aloca alt `NN`, fisierul
|
||||
**si** acel apel trebuie schimbate impreuna (altfel `VERSIUNE` inregistreaza un nume care nu exista
|
||||
pe disc).
|
||||
|
||||
## I. Format script
|
||||
|
||||
`CREATE OR REPLACE VIEW` (fara `FORCE`) - verificat pe modelul cel mai recent din `SCRIPTURI_CLAR`
|
||||
(`ff_2026_08_06_11_COMUN_FACT_VFACTURI.sql`, care creeaza doua view-uri fara `FORCE`); `FORCE` nu e
|
||||
necesar oricum, toate tabelele sursa (`VANZARI_DETALII`, `NOM_ARTICOLE`, `NOM_GESTIUNI`,
|
||||
`NOM_VALUTE`) exista deja. CRLF verificat byte-safe dupa scriere (44 CRLF, 0 LF singur). Fara `;` in
|
||||
comentarii inaintea instructiunii. Se incheie cu `UpdateVersiune` + `commit`.
|
||||
|
||||
## Livrabil
|
||||
|
||||
`D:\ROA\ROAFACTURARE\docs\cercetare\ff_view_articole_vanzare.sql` - scriptul complet, **neaplicat**.
|
||||
|
||||
## Ce trebuie schimbat in VFP ca urmare (doar cand se aplica scriptul)
|
||||
|
||||
1. `COMUN\programe\ofacturare_editare.prg:201-208` (`IncarcaArticoleFactura`): inlocuieste
|
||||
`FROM vanzari_detalii vd LEFT JOIN nom_articole na ... LEFT JOIN nom_gestiuni ng ... LEFT JOIN
|
||||
nom_valute nv ...` cu `FROM vvanzari_articole vd`, pastrand neschimbat `WHERE vd.id_vanzare = ... AND
|
||||
vd.sters = 0` si toata lista de coloane din `SELECT` (numele raman identice).
|
||||
2. Fallback-ul `CREATE CURSOR tvd (...)` (`:214-216`) si duplicatul din `omodificari.vc2` (~14076,
|
||||
semnalate deja ca duplicare in `rec_review_ancorare_s4.md`) **nu se ating** de aceasta schimbare -
|
||||
raman neschimbate structural, doar sursa `SELECT`-ului se simplifica.
|
||||
3. **Opional**, daca se doreste sa se profite de coloana noua `id_vanzare`: nu e necesar niciun
|
||||
consum imediat in VFP - grid-ul nu are nevoie de ea (id-ul e deja cunoscut din parametrul functiei).
|
||||
@@ -1,207 +0,0 @@
|
||||
# Watchdog VFP + diagnostic blocaj "View Parameter" (test_page3_articole.prg)
|
||||
|
||||
## 1. Utilitarul: `COMUN\utile\Teste\watchdog_vfp.ps1`
|
||||
|
||||
Lanseaza `vfp9.exe -A -T "<script>"`, polleaza la ~700ms ferestrele TOP-LEVEL ale procesului
|
||||
(`EnumWindows`+`GetWindowThreadProcessId`, filtrate pe PID). Fereastra principala VFP se identifica
|
||||
prin `Process.MainWindowHandle` (.NET) - **nu** dupa numele clasei: VFP inregistreaza clase diferite
|
||||
prefixate `vfp9...` atat pentru shell-ul principal (`vfp99400000`) cat si pentru dialogurile lui
|
||||
proprii (`vfp994000002` pentru "View Parameter") - o clasificare pe clasa a lasat "View Parameter"
|
||||
nedetectat la prima incercare (corectat).
|
||||
|
||||
Pentru fiecare fereastra noua (diferita de `MainWindowHandle`): captura PNG (`PrintWindow`, fallback
|
||||
`CopyFromScreen` daca iese neagra) + dump text (titlu, clasa, si textul/clasa fiecarui control copil
|
||||
via `WM_GETTEXT`, cross-proces). Cu `-AutoDismiss`: cauta un buton copil "Cancel"/"Anulare" si
|
||||
trimite `BM_CLICK`; altfel incearca, in ordine, `WM_COMMAND IDCANCEL` -> ESCAPE ca MESAJ
|
||||
(`WM_KEYDOWN`/`WM_KEYUP`, tintit pe handle) -> `WM_CLOSE`.
|
||||
|
||||
**REGULA OBLIGATORIE, incalcata initial si corectata**: watchdog-ul NU are voie sa foloseasca INPUT
|
||||
REAL de tastatura/mouse (`keybd_event`, `SetForegroundWindow`, `SendInput`, `mouse_event`) - masina e
|
||||
PARTAJATA cu utilizatorul. Prima versiune folosea `SetForegroundWindow`+`keybd_event(ESCAPE)` ca
|
||||
fallback pentru dialogurile proprii VFP owner-drawn (fara controale copil reale) - **acest input NU
|
||||
are tinta, ajunge in orice fereastra are focus pe masina in acel moment, indiferent al cui proces
|
||||
e**. **Fapt clarificat de team-lead, dupa investigare**: in acest caz concret, ESC-ul a aterizat de
|
||||
fapt in PROPRIUL NOSTRU proces de test (eroarea "Variable 'GNAN' is not found" vazuta imediat inainte
|
||||
de "Execution was canceled by the user" e chiar semnatura testului nostru) - **nu in sesiunea lui
|
||||
Marius**, deci de fapt nu s-a intrerupt munca nimanui de data asta. Asta NU schimba regula: mecanismul
|
||||
tot nu are tinta si putea la fel de usor sa ajunga in aplicatia de productie (`roafacturare.exe`/
|
||||
`roacont.exe`) daca utilizatorul avea focus acolo in acea clipa - o formulare anterioara aici spunea
|
||||
gresit ca ar fi afectat sesiunea utilizatorului, corectata acum. **Scos complet** din cod (nu mai
|
||||
exista nicio linie `keybd_event`/`SetForegroundWindow` in `watchdog_vfp.ps1`). Consecinta: pentru
|
||||
dialogurile owner-drawn care nu raspund la mesaje tintite, `-AutoDismiss` **esueaza cinstit** (dialogul
|
||||
ramane deschis pana la `-TimeoutSec`, apoi procesul e omorat) - captura (PNG+dump text) ramane de incredere,
|
||||
dismiss-ul nu e garantat pentru acest tip de dialog. Procesul e omorat mereu la iesire (`finally`),
|
||||
nu ramane niciodata viu.
|
||||
|
||||
Validat intai pe caz banal: `COMUN\utile\Teste\watchdog_selftest.prg` (`MESSAGEBOX` cu OK/Cancel) -
|
||||
detectie, captura, dump text si auto-dismiss confirmate corecte inainte de a-l rula pe cazul real.
|
||||
|
||||
Utilizare: `powershell -ExecutionPolicy Bypass -File watchdog_vfp.ps1 -Script "<test.prg>" -AutoDismiss [-TimeoutSec 90] [-MaxDialogs 10] [-OutDir <cale>]`.
|
||||
|
||||
## 2. Dialogurile capturate pe `test_page3_articole.prg`
|
||||
|
||||
**Dialog 0** - nativ VFP, clasa `vfp994000002`, titlu **"View Parameter"**, text **"Enter the value
|
||||
for gnAn:"** (fara controale copil reale - owner-drawn). Screenshot:
|
||||
`COMUN\utile\Teste\editare_factura\watchdog_out\test_page3_articole_dialog0.png`.
|
||||
|
||||
**Dialog 1** (apare doar cand dialog 0 e inchis prin ESCAPE real, care functioneaza) - "Open" Win32
|
||||
standard, filtru "Table/DBF (*.dbf)", folder implicit `ROACONT` (working directory-ul mediului de
|
||||
test, mostenit din `test_init_env_auto.prg`). Screenshot:
|
||||
`COMUN\utile\Teste\editare_factura\watchdog_out\test_page3_articole_dialog1.png`.
|
||||
|
||||
## 3. PROGRAM()/LINENO() din log (dupa Cancel pe dialog 0)
|
||||
|
||||
Din `test_page3_articole_log.txt`, PROGRAM()=`VERIFICA_PAGECOUNT_FORM` (procedura de test) pe
|
||||
liniile din jurul apelului `loForm = Createobject([frm_modific2024], lnIdSet)`:
|
||||
|
||||
```
|
||||
EROARE 1 [VERIFICA_PAGECOUNT_FORM:165] File 'crsjtvatemp.dbf' does not exist.
|
||||
EROARE 1924 [VERIFICA_PAGECOUNT_FORM:166..173] LOFORM is not an object. (cascada, zgomot)
|
||||
```
|
||||
|
||||
## 4. Experimente de izolare (cerute de team-lead) - **INFIRMA ipoteza initiala**
|
||||
|
||||
Ipoteza initiala din aceasta sectiune ("`SQLEXEC` din `update_jtva_coloane` nu rezolva `?gnAn`") era
|
||||
o **deductie**, nu o masuratoare - team-lead a cerut-o verificata direct, corect. Trei experimente
|
||||
ieftine, in ordine:
|
||||
|
||||
**Experiment A - "chiar exista in acel moment?"** `TYPE('gnAn')`/`TRANSFORM(gnAn)` puse imediat
|
||||
**INAINTE** de apelul `update_jtva_coloane` (linia 161 curenta, nu inainte de `Createobject` cum
|
||||
fusese verificat prima data):
|
||||
|
||||
```
|
||||
EROARE 12 [VERIFICA_PAGECOUNT_FORM:161] Variable 'GNAN' is not found.
|
||||
```
|
||||
|
||||
- Eroare aparuta DOAR la primul apel al `verifica_pagecount_form` (`cod=1140888`), inainte sa se
|
||||
ajunga la `update_jtva_coloane`. **Rezultat: `gnAn` e deja invizibila INAINTE ca `update_jtva_coloane`
|
||||
sa fie apelata** - markerele `?gnAn`/`?gnLuna` din `updateserver.prg:597` nu pot fi (macar nu
|
||||
singure) cauza, contrazice ipoteza initiala.
|
||||
|
||||
**Experiment B - "se reproduce izolat, fara nimic din S4?"** Script nou,
|
||||
`COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg`: DOAR `test_init_env_auto` +
|
||||
`update_jtva_coloane("", "crsJtvaTemp", 6)`, fara `IncarcaCursoareModificareNota`, fara
|
||||
`frm_modific2024`, fara nimic din PAGE3. Rezultat:
|
||||
|
||||
```
|
||||
TYPE(gnAn)=N TRANSFORM(gnAn)=2026 TYPE(gnLuna)=N TRANSFORM(gnLuna)=8
|
||||
dupa update_jtva_coloane: Used(crsJtvaTemp)=.T. Reccount=120
|
||||
done
|
||||
```
|
||||
|
||||
**NU reproduce.** Zero dialog, exit curat, cursorul se creeaza corect cu 120 randuri.
|
||||
`update_jtva_coloane` singura, chemata imediat dupa initul mediului, functioneaza perfect -
|
||||
**nu e o capcana preexistenta a harness-ului si nici o vina proprie a functiei in izolare**.
|
||||
Rerulat identic dupa scoaterea input-ului real din watchdog (vezi sectiunea 1) - acelasi rezultat,
|
||||
deci reconfirmat, nu era un artefact al mecanismului de dismiss.
|
||||
|
||||
**Experiment C - oprit inainte de a-l rula.** Premisa lui ("copiaza corpul lui `update_jtva_coloane`
|
||||
cu concatenare in loc de `?param`, ca sa confirmi mecanismul") presupune ca vina e in legarea
|
||||
`SQLEXEC` a functiei - exact ce B tocmai a infirmat. Nu are sens sa continue in forma ceruta initial
|
||||
fara o noua directie.
|
||||
|
||||
## 5. Cauza CONFIRMATA prin bisectie (nu doar deductie)
|
||||
|
||||
Bisectie ceruta de team-lead: `TYPE('gnAn')`/`TRANSFORM(gnAn)` logat in **doua straturi** - (a) in
|
||||
programul principal, intre fiecare apel de nivel superior, si (b) ca **prima linie** in interiorul
|
||||
fiecarei proceduri (`verifica_vanzare_nota`, `verifica_coliziune_cod`, `verifica_pagecount_form`).
|
||||
Helper `bisect_log_gnan` (nou, la coada `test_page3_articole.prg`) - TYPE() e sigur necoditionat,
|
||||
TRANSFORM() doar daca TYPE()<>'U', ca sa nu produca o eroare noua care ar intrerupe bisectia.
|
||||
|
||||
Rezultat brut (`test_page3_articole_log.txt`):
|
||||
|
||||
```
|
||||
[BISECT] main: dupa test_init_env_auto :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1140888 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] main: dupa verifica_vanzare_nota #1 (cod=1140888) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1140885 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] main: dupa verifica_vanzare_nota #2 (cod=1140885) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_vanzare_nota ENTRY cod=1125486 :: TYPE(gnAn)=N gnAn=2026 <- diferit!
|
||||
[BISECT] main: dupa verifica_vanzare_nota #3 (cod=1125486) :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_coliziune_cod ENTRY :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] main: dupa verifica_coliziune_cod :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] main: inainte de verifica_pagecount_form :: TYPE(gnAn)=N gnAn=2026
|
||||
[BISECT] verifica_pagecount_form ENTRY cod=1140888 :: TYPE(gnAn)=U gnAn=(U)
|
||||
[BISECT] verifica_pagecount_form inainte de update_jtva_coloane :: TYPE(gnAn)=U gnAn=(U)
|
||||
```
|
||||
|
||||
**Tiparul e limpede si consecvent**: `gnAn` e INTOTDEAUNA valid (`N`, `2026`) in scope-ul PRINCIPAL,
|
||||
la fiecare checkpoint, fara exceptie - deci **NU e "eliberata"** (nu e `CLEAR ALL`/`CLEAR MEMORY`/
|
||||
`RELEASE ALL EXTENDED` pe undeva). E **`'U'` STRICT la intrarea in proceduri apelate cu `DO ... WITH`
|
||||
in care `gnAn`/`gnLuna` sunt trecute NEPARANTEZATE ca argumente**, si redevine valid imediat ce
|
||||
procedura respectiva se termina si controlul revine in principal. Corelatia e exacta cu sintaxa
|
||||
apelului, nu cu ce face procedura pe dinauntru:
|
||||
|
||||
- `verifica_vanzare_nota` apelul #1/#2 (`gnAn` -> `U`): call-site-urile trec `gnAn, gnLuna` DIRECT -
|
||||
`test_page3_articole.prg:34` (`DO verifica_vanzare_nota WITH 1140888, gnAn, gnLuna, ...`) si
|
||||
`test_page3_articole.prg:36` (`... WITH 1140885, gnAn, gnLuna, ...`).
|
||||
- `verifica_vanzare_nota` apelul #3 (`gnAn` ramane `N`): `test_page3_articole.prg:38` trece
|
||||
`2008, 2` LITERAL, nu `gnAn`/`gnLuna`.
|
||||
- `verifica_coliziune_cod` (`gnAn` ramane `N`): `test_page3_articole.prg:42` nu trece deloc
|
||||
`gnAn`/`gnLuna` (doar `lcLog`).
|
||||
- `verifica_pagecount_form` primul apel (`gnAn` -> `U`, **exact scenariul blocat**):
|
||||
**`test_page3_articole.prg:47`** - `DO verifica_pagecount_form WITH 1140888, gnAn, gnLuna, 'A (factura reala)', lcLog, 3, .T.`.
|
||||
|
||||
**Mecanismul**: `DO <procedura> WITH <arg1>, <arg2>, ...` (stilul vechi, folosit peste tot in acest
|
||||
script) trece variabilele de memorie **BY REFERENCE** implicit (`SET UDFPARMS` e `REFERENCE` in mod
|
||||
implicit VFP) - `LPARAMETERS tnAn, tnLuna` din procedura primitoare devin ALIAS-uri directe pe
|
||||
storage-ul lui `gnAn`/`gnLuna`, iar numele ORIGINAL devine inaccesibil (`TYPE()='U'`) **pe toata
|
||||
durata apelului**, exact cat tine executia procedurii - confirmat empiric de simetria perfecta
|
||||
"intra U, revine N" la fiecare din cele 3 perechi de apeluri afectate.
|
||||
|
||||
**Clasificare in termenii cerutii de team-lead**: e **"umbrire de scope"** (categoria 2), NU
|
||||
"eliberare" (categoria 1) - dar mecanismul exact nu e o coliziune de nume `PRIVATE`/`LOCAL` in corpul
|
||||
procedurii (team-lead avea deja dreptate: `verifica_pagecount_form` nu are `gnAn` in `LOCAL`, si nu
|
||||
exista `PRIVATE gnAn`/`LOCAL gnAn` nicaieri in `COMUN\programe`) - **umbrirea vine din SINTAXA
|
||||
APELULUI** (`DO...WITH` fara paranteze in jurul lui `gnAn`/`gnLuna`), nu din declaratiile procedurii
|
||||
apelate.
|
||||
|
||||
**Statement-ul vinovat exact, cu fisier:linie**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg:47`.
|
||||
|
||||
**IMPLICATIE IMPORTANTA**: acesta e un tipar din **SCRIPTUL DE TEST**, nu din fluxul real al
|
||||
aplicatiei - `do_editare_factura` (codul de productie) nu trece prin `verifica_pagecount_form`
|
||||
(helper propriu testului). Team-lead a confirmat verdictul: **e strict un defect de harness** -
|
||||
`updateserver.prg`, `omodificari.*` si codul S4 sunt toate nevinovate.
|
||||
|
||||
**Remediu APLICAT de team-lead** (3 linii, sub pragul lui de editare directa): argumentele
|
||||
`gnAn`/`gnLuna` sunt acum parantezate - `(gnAn)`, `(gnLuna)` - la liniile 37, 39 si 50 din
|
||||
`test_page3_articole.prg` (parantezele forteaza trecere PRIN VALOARE in loc de PRIN REFERINTA),
|
||||
cu un comentariu explicativ deasupra primei aparitii. Nerulat inca de mine (interzis explicit -
|
||||
suita o ruleaza team-lead-ul dupa eliberarea `.fxp`-ului).
|
||||
|
||||
**Remediul din rundele anterioare ale acestui raport (concatenare in loc de `?gnAn`/`?gnLuna` in
|
||||
`updateserver.prg:597`) ramane infirmat** - nu era cauza. `updateserver.prg` nu a fost si nu e atins.
|
||||
|
||||
## 6. Fisiere atinse
|
||||
|
||||
- **Nou**: `COMUN\utile\Teste\watchdog_vfp.ps1`, `COMUN\utile\Teste\watchdog_selftest.prg`,
|
||||
`COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan.prg` (experimentul B, izolat).
|
||||
- **Modificat**: `COMUN\utile\Teste\editare_factura\test_page3_articole.prg`
|
||||
- linia 176 (`update_jtva_coloane(..., 6)`, ramane - fix necesar pt. indexul `id_jtva`, independent
|
||||
de defectul de mai jos);
|
||||
- `PROCEDURE bisect_log_gnan` (noua, la coada fisierului) + apeluri `DO bisect_log_gnan WITH ...`
|
||||
inserate in principal (intre apelurile de nivel superior) si ca prima linie in fiecare procedura
|
||||
- ramase in cod, sunt dovada bisectiei;
|
||||
- **liniile 37, 39, 50 - remediul APLICAT de team-lead**: `gnAn`/`gnLuna` parantezate (`(gnAn)`,
|
||||
`(gnLuna)`), forteaza trecere prin valoare in loc de prin referinta in `DO...WITH`.
|
||||
- **Neatins**: `COMUN\clase\omodificari.vc2/.vcx/.vct`, `COMUN\programe\updateserver.prg` (ambele
|
||||
infirmate ca posibila cauza, vezi sectiunea 5).
|
||||
- Artefacte de rulare (`watchdog_out\*.png/.log`, `*_log.txt`) raman pe disc ca dovada; se pot sterge
|
||||
cu `curatenie.ps1` la finalul lucrarii.
|
||||
|
||||
## 7. Stare la data acestui raport
|
||||
|
||||
**Cauza confirmata prin bisectie (sectiunea 5) si remediul APLICAT de team-lead** (paranteze la
|
||||
liniile 37/39/50). **Nerulat inca** de nimeni dupa aplicarea remediului - team-lead ruleaza suita
|
||||
separat, dupa eliberarea `.fxp`-ului (nu s-a mai relansat testul in aceasta sesiune, per interdictia
|
||||
primita). Ramane deschis, pentru cine continua:
|
||||
|
||||
1. Confirma cu o rulare ca remediul chiar elimina dialogul si `verifica_pagecount_form` trece PASS
|
||||
pe `PageCount=3`/`lAreArticoleVanzari=.T.` pentru cod=1140888.
|
||||
2. Optional: verifica daca fluxul REAL de productie (`do_editare_factura` in `ofacturare_comun.vc2`)
|
||||
are undeva acelasi tipar `DO...WITH <variabila PUBLIC>` NEPARANTEZAT inainte de un `?param` in
|
||||
SQLEXEC - team-lead a verdictuit "defect de harness", dar asta ramane neverificat exhaustiv pe
|
||||
codul de productie.
|
||||
3. Watchdog-ul (`watchdog_vfp.ps1`) ramane instrumentul de verificat orice ipoteza noua fara sa se
|
||||
agate procesul si FARA input real (regula obligatorie, sectiunea 1) - reutilizabil pentru orice
|
||||
alt blocaj similar in suita.
|
||||
@@ -76,9 +76,9 @@ tipar `Createobject("oDateFactura", tip1, tip2)`).
|
||||
**`tip = -12` e deja cunoscut in ROAFACTURARE** — nu ca un cod nou, ci ca ceva deja intalnit si
|
||||
documentat in cercetarea recenta de regresie a editarii facturii (proiectul S4,
|
||||
`docs\progres.md:339`, `:1142`; `docs\cercetare\rec_datoria6_baza_regresie.md:93`;
|
||||
`docs\cercetare\rec_s4_runda1.md:38`; `docs\cercetare\rec_view_articole_vanzare.md:108`), pe un rand
|
||||
`docs\cercetare\rec_s4_runda1.md:38`; `COMUN\docs\cercetare\rec_view_articole_vanzare.md:108`), pe un rand
|
||||
real din baza de test `MARIUSM_AUTO`: `cod=1140885` -> `id_vanzare=1047`, `tip=-12`. Acolo e descris
|
||||
explicit: **"nu e factura, e alt tip de document"** (`handoff_s4_runda1.md:77`) si decizia produsului
|
||||
explicit: **"nu e factura, e alt tip de document"** (handoff intermediar (sters)) si decizia produsului
|
||||
(decizia 19) e ca detectia liniilor de articole "merge pe orice tip, nu doar facturi" — adica
|
||||
`IncarcaArticoleFactura`/`IncarcaVanzareNota` din `COMUN\programe\ofacturare_editare.prg` (mentionate
|
||||
in `rec_datoria6_baza_regresie.md:83-84`) nu filtreaza dupa `tip=1`, deci **vad si randurile
|
||||
@@ -100,7 +100,7 @@ in `rec_datoria6_baza_regresie.md:83-84`) nu filtreaza dupa `tip=1`, deci **vad
|
||||
(`:1026-1027`), `-100007`/`-100008` INSPECTIE TEHNICA / SPALARE AUTO (`:979-982`). Optional, daca
|
||||
`gnAUTOIdArticolReparatii` e setat, toate liniile de mai sus se **cumuleaza intr-o singura linie**
|
||||
cu un articol real din nomenclator ("REPARATII AUTO", `:989-1004`). Confirmat pe date reale in
|
||||
`docs\cercetare\rec_view_articole_vanzare.md:108-109`: `id_vanzare=1047` (`tip=-12`) are doar
|
||||
`COMUN\docs\cercetare\rec_view_articole_vanzare.md:108-109`: `id_vanzare=1047` (`tip=-12`) are doar
|
||||
**2 randuri** in `VANZARI_DETALII`, cu `id_gestiune`/`nume_gestiune` NULL (linii nestocate,
|
||||
netinute in gestiune). Deci pe factura nu apar piesele individual — apar totaluri
|
||||
MATERIALE/MANOPERA (cu exceptia cazului cumulat, unde apare un singur articol generic).
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
-- S10 - curatare istoric TABELA VERSIUNE, MARIUSM_AUTO/ROA_CENTRAL
|
||||
-- Scop: cele 5 scripturi ff_2026_08_06_* au fiecare mai multe inregistrari in VERSIUNE,
|
||||
-- din aplicari succesive pe masura ce au fost extinse in cursul zilei de 06.08.2026.
|
||||
-- Fara impact functional (versiune_db.txt si aplicarea DDL nu depind de numarul de randuri),
|
||||
-- doar istoric zgomotos. Pastreaza UN singur rand per script (cel cu ID_VERSIUNE maxim, adica
|
||||
-- ultima aplicare - starea finala reala a scriptului), sterge restul.
|
||||
--
|
||||
-- NU S-A RULAT. Propunere pentru aprobare - stergerea de istoric e decizie de om, iar
|
||||
-- MARIUSM_AUTO e schema de dezvoltare partajata.
|
||||
|
||||
-- 1) Verificare inainte de stergere: cate randuri per script, azi
|
||||
select script_final, count(*) as nr_inregistrari
|
||||
from versiune
|
||||
where script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
group by script_final
|
||||
order by script_final;
|
||||
|
||||
-- Stare masurata 06.08.2026: _02=2, _03=1 (nimic de sters), _04=2, _05=4, _06=5 (14 randuri total,
|
||||
-- 9 de sters, ramanand 5 - unul per script).
|
||||
|
||||
-- 2) Stergere: pastreaza doar randul cu ID_VERSIUNE maxim per script (ultima aplicare)
|
||||
delete from versiune v
|
||||
where v.script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
and v.id_versiune < (
|
||||
select max(v2.id_versiune)
|
||||
from versiune v2
|
||||
where v2.script_final = v.script_final
|
||||
);
|
||||
|
||||
-- 3) Verificare dupa stergere: fiecare script din lista trebuie sa aiba exact 1 rand
|
||||
select script_final, count(*) as nr_inregistrari
|
||||
from versiune
|
||||
where script_final in (
|
||||
'ff_2026_08_06_02_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_03_COMUN_PACK_FACTURARE.sql',
|
||||
'ff_2026_08_06_04_COMUN_VANZARI_COMANDA_CONTRACT.sql',
|
||||
'ff_2026_08_06_05_COMUN_FACT_VFACTURI.sql',
|
||||
'ff_2026_08_06_06_COMUN_VANZARI_BACKFILL.sql'
|
||||
)
|
||||
group by script_final
|
||||
order by script_final;
|
||||
|
||||
-- commit; -- de dat manual, dupa verificarea pasului 3
|
||||
@@ -16,7 +16,7 @@ schimbare, clasificate (A) trebuie remigrat / (B) trebuie sters-refacut / (C) nu
|
||||
- `docs\plan_13_unificare_formular_facturare.md` — sectiunea `#### S11` (linia ~3024)
|
||||
- `docs\cercetare\idfact_refolosire_si_documente.md`
|
||||
- `docs\cercetare\rec_cale_vanzari_detalii.md`
|
||||
- `docs\cercetare\rec_consumatori_vanzari.md`
|
||||
- `COMUN\docs\cercetare\rec_consumatori_vanzari.md`
|
||||
- `docs\cercetare\cont_venit_corespondente.md`
|
||||
- `docs\cercetare\legatura_linie_retur.md`
|
||||
- `docs\cercetare\rec_d42_efactura.md`
|
||||
|
||||
@@ -357,7 +357,7 @@ pe proza handoff-ului**: `docs\diff_s4_valuta_dialog*.patch` (trei fisiere) atin
|
||||
`COMUN\clase\omodificari.vc2`, `COMUN\programe\ofacturare_editare.prg` si un fisier de test —
|
||||
**niciunul nu atinge `ofacturare.vc2` (unde traiesc `frm_date_factura`, `do_schimba_tipdoc`,
|
||||
`clb_serie_act`) sau `ofacturare.prg` (unde traieste bucla `factureaza`)**. Confirmat si de continutul
|
||||
lui `docs\handoff_decizia35_valuta_dialog.md`: intreaga lui cercetare e despre `frm_articol_factura`
|
||||
lui handoff intermediar (sters): intreaga lui cercetare e despre `frm_articol_factura`
|
||||
(dialogul de adaugare articol pe linie, alt fisier/clasa) si `frm_modific2024.cmdAdaugaArticol.Click`
|
||||
— un mecanism de valuta **pe linie de articol**, fara nicio legatura cu antetul sau cu bucla de
|
||||
emitere. **#6 nu a atins deloc lantul lui #16. Bug-ul e in intregime valabil si neschimbat.**
|
||||
@@ -418,7 +418,7 @@ Specific pentru S3 (antet):
|
||||
interactiunea reala de selectare dintr-o lista si `Show(1)` modal nu se poate simula headless; se
|
||||
pot testa doar efectele **dupa** ce `poCauta`/rezultatul e construit manual (tiparul deja folosit in
|
||||
`test_pret_cu_tva_dialog.prg`/`test_adauga_linie_valuta.prg` mentionat in
|
||||
`docs\handoff_decizia35_valuta_dialog.md`, punctul 7) — apel direct al metodei cu un obiect
|
||||
handoff intermediar (sters), punctul 7) — apel direct al metodei cu un obiect
|
||||
simulat, fara `Show()`.
|
||||
- **`Init`-ul complet** (redimensionare, `RemoveObject` in cascada, repozitionare containere) e
|
||||
verificabil pe proprietati (`.Visible`, `.Height`, existenta obiectului dupa `Type(...)`) fara UI
|
||||
|
||||
@@ -283,7 +283,7 @@ formular — vezi mai jos).
|
||||
|
||||
### 4.1 Nu porni de la `frm_tranzit` (RORIS) — porneste de la `cauta_alfa`
|
||||
|
||||
Raportul de referinta (`docs\cercetare\import_roris_roaacnpro.md`) descrie corect **arhitectura
|
||||
Raportul de referinta (`COMUN\docs\cercetare\import_roris_roaacnpro.md`) descrie corect **arhitectura
|
||||
generala** (buton conditionat -> metoda unica -> dialog cu bifare si criterii -> populare aditiva prin
|
||||
`INSERT`, fara scriere Oracle pana la salvare) — dar `frm_tranzit` insusi e un formular **specific
|
||||
ROAACNPRO**, care nu exista in ROAFACTURARE si n-ar trebui portat ca formular.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Poveste: `docs\plan_13_unificare_formular_facturare.md`, `#### S4d` (decizia 15, proiectata in
|
||||
sectiunea M). Cercetare preliminara deja facuta si citata ca sursa de adevar:
|
||||
`docs\cercetare\zi_curs_validare.md`, `docs\cercetare\valuta_si_curs.md`,
|
||||
`docs\cercetare\zi_curs_validare.md`, `COMUN\docs\cercetare\valuta_si_curs.md`,
|
||||
`docs\cercetare\rec_dec42_proiectare.md`/`rec_d42_efactura.md` (decizia 42),
|
||||
`docs\cercetare\s3_portare_antet.md` (bug #16), `docs\cercetare\s4_cautare_articole_server.md`/
|
||||
`s4_puncte_deschise.md` (decizia 42, mecanismul ei exact). Read-only: nicio editare de cod, niciun
|
||||
|
||||
@@ -1,296 +0,0 @@
|
||||
# Cercetare: `poDate.in_valuta`, `Clb_zi_curs` si cele doua concepte de valuta
|
||||
|
||||
Investigatie read-only (fara editari, fara `git_sync.ps1`/`txt2vcx.ps1`, fara commit). Sursa: cache
|
||||
text `.vc2`/`.prg` din `COMUN\clase\ofacturare.vc2`, `COMUN\programe\ofacturare.prg`,
|
||||
`COMUN\programe\ofacturare_comun.prg`, `COMUN\programe\ofacturare_stoc.prg`,
|
||||
`COMUN\programe\oproceduri_curs.prg`, plus pachetul Oracle
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\03\ff_2026_03_23_04_COMUN_PACK_FACTURARE.sql` (copie pe disc,
|
||||
alta numerotare decat baza). Reutilizeaza si confirma cercetari anterioare din
|
||||
`docs\cercetare\rec_cale_vanzari_detalii.md` si `docs\cercetare\rec_consumatori_vanzari.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. `poDate.in_valuta` — unde se seteaza si din ce
|
||||
|
||||
**Concluzie**: `in_valuta` e determinat **o singura data**, la `Init`, exclusiv din **tipul
|
||||
documentului** (`tnTip`) plus o lista fixa de `id_set` — niciodata din alegerea manuala a unei
|
||||
valute in antet si niciodata resetat ulterior. E o proprietate a *tipului de factura* (Invoice /
|
||||
credit note / retur valuta / factura fiscala valuta pe contract), nu a faptului ca articolele au
|
||||
preturi in valuta.
|
||||
|
||||
**Dovezi**:
|
||||
- Valoare implicita `0`: `COMUN\programe\ofacturare_comun.prg:165` (`in_valuta = 0`, in blocul de
|
||||
proprietati al obiectului `poDate`).
|
||||
- Singurul loc care il seteaza pe `1`, in `Procedure Init`:
|
||||
```
|
||||
ofacturare_comun.prg:248-250
|
||||
If Inlist(tnIdSet,223,225,226,227,271) OR INLIST(m.tnTip, 5,6,7,9,10,52)
|
||||
.in_valuta = 1
|
||||
Endif
|
||||
```
|
||||
- Legenda tipurilor (comentariu din `frm_date_factura.Init`), `ofacturare.vc2:9571-9582`:
|
||||
`1`=lista preturi, `2`=contract, `3`=comanda, `4`=aviz, `5`=Invoice lista preturi, `6`=Invoice
|
||||
contract, `7`=credit note, `8`=retur lei, `9`=retur valuta, `48`=avize valoric, `52`=Factura
|
||||
fiscala valuta contract. Tipul `10` nu are comentariu explicit in acest bloc (adaugat separat,
|
||||
v2.0.56, ca variatie de tip 1/5).
|
||||
- Nicio alta cale de scriere pe `in_valuta` in `.vc2`/`.prg` din COMUN — verificat cu grep
|
||||
(`\.in_valuta\s*=\s*[01]`) pe intreg `ofacturare.vc2` si `ofacturare.prg`: restul potrivirilor
|
||||
sunt toate **citiri** (`If poDate.in_valuta = 1 ...`), nu atribuiri. `ofacturare_stoc.prg:549`
|
||||
(`poDate.in_valuta = in_valuta`) e o cale alternativa (facturare "din stoc") care primeste
|
||||
parametrul `in_valuta` deja calculat in amonte, cu aceeasi semantica.
|
||||
- Consecinta directa, confirmata de cod: alegerea manuala a unei valute pentru document (control
|
||||
`ct_clb_valuta`) nu poate schimba `in_valuta` — controlul insusi e eliminat din formular cand
|
||||
`in_valuta = 0` (`ofacturare.vc2:9725-9728`), deci userul nu are cum sa-l "aleaga" pe o factura
|
||||
care nu e deja de tip valuta.
|
||||
|
||||
---
|
||||
|
||||
## 2. Campul „Data curs valutar" (`Clb_zi_curs`) — unde e definit si cand e eliminat azi
|
||||
|
||||
**Concluzie**: campul e eliminat **doar** pentru facturi de retur (`tip` 8 sau 9), niciodata pe
|
||||
baza de `in_valuta`. **Da, azi campul apare si pe facturile in lei** (`in_valuta=0`) de orice alt
|
||||
tip — comportament confirmat explicit prin simetrie de cod: imediat dupa blocul de retur, exista un
|
||||
bloc separat care elimina `ct_clb_valuta` cand `in_valuta=0`, dar echivalentul lipseste pentru
|
||||
`clb_zi_curs`.
|
||||
|
||||
**Dovezi** (identificarea claselor facuta cu `vfp_symbols.ps1 -Where`):
|
||||
|
||||
| Clasa | Interval | `Clb_zi_curs` definit | Eliminat azi? |
|
||||
|---|---|---|---|
|
||||
| `frm_date_aviz` | `ofacturare.vc2:6566-7618` | `:6727-6740` (caption "Data cursului valutar") | Niciodata — zero `RemoveObject`/conditionare pe `in_valuta` in toata clasa (verificat exhaustiv) |
|
||||
| `frm_date_aviz_lucrare` | `:7620-8201` | `:7787-7801` | Niciodata; in plus, validare **necondiționata**: `:8076` `Case Empty(Nvl(poDate.zi_curs,{}))` fara nicio garda pe `in_valuta` (spre deosebire de `frm_date_factura`, vezi mai jos) |
|
||||
| `frm_date_factura` | `:8482-9869` | `:8701-8714` (caption "Data curs valutar") | **Doar** pentru `tip` 8/9, in `Init`: |
|
||||
|
||||
```
|
||||
ofacturare.vc2:9717-9722 (frm_date_factura.Init)
|
||||
*!* modificare v 2.0.56
|
||||
If Inlist(poDate.tip, 8, 9)
|
||||
lnHeight = lnHeight - .clb_zi_curs.Height
|
||||
laPozitii(.clb_zi_curs.TabIndex, 2) = 1
|
||||
.RemoveObject('clb_zi_curs')
|
||||
Endif
|
||||
*!* modificare v 2.0.56 ^
|
||||
|
||||
ofacturare.vc2:9725-9728 (imediat dupa, in ACEEASI metoda)
|
||||
If poDate.in_valuta = 0
|
||||
lnHeight = lnHeight - .ct_clb_valuta.Height
|
||||
laPozitii(.ct_clb_valuta.TabIndex, 2) = 1
|
||||
.RemoveObject('ct_clb_valuta')
|
||||
```
|
||||
|
||||
Cele doua blocuri sunt adiacente si scrise dupa acelasi tipar (inaltime, `laPozitii`,
|
||||
`RemoveObject`) — dovada ca autorul original a tratat `ct_clb_valuta` (selectorul de valuta) ca
|
||||
dependent de `in_valuta`, dar **nu** a facut acelasi lucru pentru `clb_zi_curs`. Validarea de
|
||||
completare e de asemenea asimetrica: `ofacturare.vc2:9484`
|
||||
(`Case poDate.in_valuta = 1 And Empty(Nvl(poDate.zi_curs,{})) And ...`) cere data curs **doar** cand
|
||||
`in_valuta=1`, in timp ce `frm_date_aviz_lucrare` (`:8076`) o cere mereu — inconsistenta intre cele
|
||||
doua forme, de retinut daca regula noua trebuie aplicata uniform.
|
||||
|
||||
Nota: `frm_facturare_articole2` (clasa separata, `:15741-19355`) are propriul label "Curs valutar"
|
||||
(control diferit, `:16285-16299`), tratat la punctul 3/5 — nu e acelasi camp cu `Clb_zi_curs` din
|
||||
antet, dar citeste aceeasi `poDate.zi_curs`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Cele doua concepte, in cod — confirmate distinct
|
||||
|
||||
**Concluzie**: da, distinctia exista clar in cod, pe doua axe independente:
|
||||
- **(a) valuta de document**: `poDate.in_valuta` / `poDate.Curs` / `poDate.multiplicator` /
|
||||
`poDate.id_valuta` — un singur curs, al documentului intreg, folosit cand tot documentul e emis
|
||||
in valuta.
|
||||
- **(b) articol cu pret in valuta pe document in lei**: `poArticol.tip_valuta = 1` (proprietate a
|
||||
politicii de pret a articolului, independenta de `poDate.in_valuta`), cu preturile brute in
|
||||
valuta pastrate in `poArticol.pretftva_val`/`pretctva_val`/`pretd` + `id_valuta_d`, convertite in
|
||||
lei **client-side, in VFP**, folosind cursul zilei `poDate.zi_curs`.
|
||||
|
||||
**Dovezi — conversia in lei pentru cazul (b)**:
|
||||
```
|
||||
ofacturare.vc2:1989 poArticol.pretftva = Round(poArticol.pretftva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
ofacturare.vc2:2953 poArticol.pretftva = Round(poArticol.pretftva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
ofacturare.vc2:2017 poArticol.pretctva = Round(poArticol.pretctva_val * poArticol.Curs / poArticol.multiplicator, gnPPretV)
|
||||
```
|
||||
`poArticol.Curs`/`multiplicator` (nu e alt curs decat cel al zilei documentului) provin din cursorul
|
||||
`crscursuri`, incarcat explicit **cand documentul e in lei** — exact pentru articolele cu preturi in
|
||||
valuta:
|
||||
```
|
||||
ofacturare.prg:407-418 (identic si la :941-947)
|
||||
If poDate.in_valuta = 1
|
||||
Select Distinct Curs, nume_val, id_valuta, multiplicator From (lcCursor) ... Where tip_valuta = 1 ... Into Cursor crscursuri
|
||||
Select crscursuri
|
||||
poDate.Curs = Curs
|
||||
poDate.multiplicator = multiplicator
|
||||
Else
|
||||
citeste_cursuri_zi(poDate.zi_curs)
|
||||
If Reccount('crscursuri') = 0
|
||||
Use In crscursuri
|
||||
Endif
|
||||
Endif
|
||||
```
|
||||
`citeste_cursuri_zi` (`COMUN\programe\oproceduri_curs.prg:113-124`) construieste `crscursuri` cu
|
||||
**toate** cursurile valabile la `tdDataCurs` (`= poDate.zi_curs`):
|
||||
```
|
||||
oproceduri_curs.prg:117-118
|
||||
lcSql = [select nume_val,curs,id_valuta,multiplicator from ] + gcS + [.vcurs where data <= ... and data2 >= ...]
|
||||
```
|
||||
Cursorul e apoi afisat direct pe grila de selectie a articolelor, cu eticheta construita din
|
||||
`poDate.zi_curs`, **indiferent de `in_valuta`**:
|
||||
```
|
||||
ofacturare.vc2:15097-15098 si 19004-19005 (frm_facturare_articole2)
|
||||
If !Empty(Nvl(poDate.zi_curs, {}))
|
||||
Thisform.lb_cursuri.Caption = "Curs valutar " + Iif(!Inlist(poDate.tip, 8, 9), "(" + Dtoc(poDate.zi_curs) + ")", "")
|
||||
```
|
||||
Grila/eticheta apar doar daca `crscursuri` are randuri (`ofacturare.vc2:15092`/`19000`), ceea ce se
|
||||
intampla si pe un document in lei, daca exista macar un articol cu politica in valuta.
|
||||
|
||||
**`VANZARI` vs `VANZARI_DETALII` — ce se stocheaza**:
|
||||
- `VANZARI` (document): coloane proprii `CURS`/`ID_VALUTA`/`MULTIPLICATOR` — cursul/valuta **doar
|
||||
ale documentului**, populate din `poDate.Curs`/`id_valuta`/`multiplicator` (relevante cand
|
||||
`in_valuta=1`).
|
||||
- `VANZARI_DETALII` (linie): **nu are coloana `CURS`** — confirmat din `all_tab_columns`
|
||||
(`docs\cercetare\rec_cale_vanzari_detalii.md:171-175`) si din SQL-ul live al pachetului, care
|
||||
reface cursul liniei prin JOIN, nu dintr-o coloana proprie:
|
||||
```
|
||||
PACK_FACTURARE.sql:3773-3778 (identic la :4034-4036, :6393-6396, :6571-6573)
|
||||
LEFT JOIN VANZARI_CURSURI B1 ON A1.ID_VANZARE = B1.ID_VANZARE AND A1.ID_VALUTA = B1.ID_VALUTA
|
||||
```
|
||||
Linia stocheaza insa `PRET` (pretul efectiv, in lei, folosit pe factura) **si** `PRETD` +
|
||||
`ID_VALUTAD` (pretul brut in valuta si valuta originii, pastrate ca referinta/audit) — vezi
|
||||
INSERT-ul din `adauga_articol_factura`
|
||||
(`docs\cercetare\rec_cale_vanzari_detalii.md:59-65`, coloanele `PRET`, `PRETD`, `ID_VALUTAD`,
|
||||
`ID_VALUTA` alaturi). Deci **da**, se pastreaza si urma valutei originale pe linie, dar valoarea
|
||||
de facturare efectiva e mereu in lei pe `VANZARI_DETALII.PRET`.
|
||||
|
||||
**La ce se foloseste `VANZARI_CURSURI`**: e un instantaneu al cursurilor pentru **orice valuta
|
||||
straina aparuta printre liniile documentului** (nu doar valuta proprie a documentului), scris o
|
||||
singura data la emitere, indiferent de `in_valuta`:
|
||||
```
|
||||
PACK_FACTURARE.sql:14491-14501
|
||||
PROCEDURE scrie_cursuri(V_ID_VANZARE IN NUMBER) IS
|
||||
BEGIN
|
||||
INSERT INTO VANZARI_CURSURI (ID_VANZARE, ID_VALUTA, CURS, MULTIPLICATOR)
|
||||
SELECT DISTINCT V_ID_VANZARE, ID_VALUTA, CURS, MULTIPLICATOR
|
||||
FROM VANZARI_DETALII_TEMP
|
||||
WHERE ID_VALUTA <> pack_facturare.nid_moneda_nationala;
|
||||
END scrie_cursuri;
|
||||
```
|
||||
Rulat necondiționat la fiecare emitere (apelat din `scrie_in_vanzari`, vezi
|
||||
`docs\cercetare\rec_cale_vanzari_detalii.md:98-102`) — deci **si pe o factura in lei** cu articole
|
||||
in valuta se scrie cate un rand `VANZARI_CURSURI` pentru fiecare valuta straina aparuta pe linii,
|
||||
cu cursul citit la `poDate.zi_curs`. Tabela e folosita ulterior la reafisare/reprint/retur, ca sursa
|
||||
a cursului per-linie (JOIN-urile de mai sus).
|
||||
|
||||
---
|
||||
|
||||
## 4. Ce se strica daca ascundem campul cand "nu are sens"
|
||||
|
||||
**Concluzie**: nu exista risc de "factura fara curs deloc" — `poDate.zi_curs` primeste mereu o
|
||||
valoare implicita la `Init` (data documentului) si nu poate ramane `NULL`. Riscul real e altul:
|
||||
**userul pierde controlul asupra datei de curs pentru cazul (b)** — o factura in lei cu articole in
|
||||
valuta ar folosi mereu cursul zilei curente/implicite, fara sa poata fi corectat manual, exact in
|
||||
situatia in care lipseste cursul pentru acea data (eroarea Oracle 20005, punctul 5) sau cand userul
|
||||
vrea sa aliniaze cursul cu data unui document sursa (aviz, contract).
|
||||
|
||||
**Consumatori confirmati ai `poDate.zi_curs`** (grep exhaustiv `poDate\.zi_curs`, fisiere
|
||||
`ofacturare.vc2`, `ofacturare.prg`, `ofacturare_stoc.prg` — singurele 3 din COMUN):
|
||||
|
||||
| Loc | Ce primeste | Conditionat de `in_valuta`? |
|
||||
|---|---|---|
|
||||
| `ofacturare.vc2:6105-6107`, `:13994-13996`, `:18030-18032` | parametru `to_date(...)` catre `pack_facturare.initializeaza_date_factura(...)` la fiecare finalizare de antet | **Nu** — trimis pentru orice tip |
|
||||
| `ofacturare.prg:272,276,281,297,303` | primul parametru al `pack_facturare.cursor_articole_k` / `cursor_preturi` / `cursor_gestiune` / `cursor_lucrare` — SQL-ul care aduce lista de articole/preturi afisata userului | **Nu** — inclusiv pentru `tip=1` (lista de preturi, lei) |
|
||||
| `ofacturare_stoc.prg:79,335` | acelasi rol, pe calea alternativa "facturare din stoc" | Nu |
|
||||
| `ofacturare.vc2:15097-15098`, `:19004-19005` | eticheta grilei "Curs valutar (data)" din `frm_facturare_articole2` | Nu — apare oricand `crscursuri` are randuri |
|
||||
| `ofacturare.vc2:9484` | validare "Nu ati completat ziua cursului valutar" | **Da**, doar `in_valuta=1` (`frm_date_factura`) |
|
||||
| `ofacturare.vc2:8076` | aceeasi validare | **Nu**, necondiționata (`frm_date_aviz_lucrare`) |
|
||||
|
||||
**Riscul concret**: daca regula noua ascunde/dezactiveaza campul strict cand `poDate.in_valuta=0`,
|
||||
pe `frm_date_factura` (tip 1, lista de preturi) userul nu va mai putea edita `zi_curs` inainte de a
|
||||
deschide grila de articole — dar `ofacturare.prg:279-282` tot va trimite acel `poDate.zi_curs`
|
||||
(neschimbat, ramas pe data initializata la `Init`) catre `cursor_preturi`, iar daca acolo Oracle
|
||||
ridica eroarea 20005 (curs lipsa pentru acea data/valuta), fluxul de recuperare
|
||||
(`vizualizeaza_curs`, punctul 5) va porni oricum, dar userul nu va (mai) avea camp pe antet ca sa
|
||||
retina/corecteze data dupa ce inchide formularul de curs. Pe `frm_date_aviz_lucrare`, ascunderea ar
|
||||
intra chiar in conflict cu validarea necondiționata de la `:8076`, care ar bloca finalizarea
|
||||
antetului cerand un camp care nu mai exista pe ecran — de reparat impreuna, nu doar ascuns.
|
||||
|
||||
---
|
||||
|
||||
## 5. Formularul de curs valutar din antet — localizare si traseu
|
||||
|
||||
**Concluzie**: nu exista niciun buton/dblclick pe `Clb_zi_curs` care sa deschida formularul de curs
|
||||
(verificat exhaustiv — zero hit pentru `Clb_zi_curs.DblClick/RightClick/Click` sau `but_curs` in
|
||||
`ofacturare.vc2`). Formularul se deschide **automat**, ca recuperare de eroare, dupa ce antetul
|
||||
(`frm_date_factura`/`frm_date_aviz`) s-a inchis deja si codul incearca sa incarce lista de articole.
|
||||
|
||||
**Traseu**:
|
||||
1. `ofacturare.prg:228-235` — `ofrmceredate = Createobject(lcObiect, toFactura)` (`lcObiect` =
|
||||
`frm_date_factura` sau `frm_date_aviz`), `.Show()` modal; la inchidere, `Release ofrmceredate`
|
||||
(`:248`).
|
||||
2. `ofacturare.prg:266-308` — pe baza tipului, se construieste apelul catre
|
||||
`pack_facturare.cursor_preturi(?poDate.zi_curs, ...)` (sau `cursor_articole_k`/`cursor_gestiune`/
|
||||
`cursor_lucrare`) si se executa (`:311` `goExecutor.oExecute(lcSqlCursor, lcCursor)`).
|
||||
3. Daca esueaza cu eroarea Oracle **20005** (curs lipsa pentru data/valuta ceruta):
|
||||
```
|
||||
ofacturare.prg:313-317 (identic la :828-832)
|
||||
If lnSucces < 0
|
||||
AMESSAGEBOX(goExecutor.oPrelucrareEroare(), 16, "Eroare")
|
||||
If goExecutor.nEroare = 20005
|
||||
vizualizeaza_curs(poDate.zi_curs)
|
||||
ENDIF
|
||||
```
|
||||
4. `vizualizeaza_curs(tdDataCurs)` — `COMUN\programe\oproceduri_curs.prg:8-42` — construieste
|
||||
cursorul `crscurs` si deschide `loFrmCurs = Createobject("frm_curs", tdDataCurs)` /
|
||||
`.Show(1)` (modal).
|
||||
5. Clasa `frm_curs` e definita in **`COMUN\clase\onom_curs.vc2:537`** (`DEFINE CLASS frm_curs AS
|
||||
_frmbase ...`), cu formulare-satelit pentru adaugare curs: `frm_curs_nou`
|
||||
(`onom_curs.vc2:1066`) si `frm_curs_nou_multiplu` (`onom_curs.vc2:1330`, apelat de la
|
||||
`onom_curs.vc2:941`).
|
||||
6. A doua cale catre acelasi formular: `citeste_cursuri_stoc` (`oproceduri_curs.prg:45-110`, folosit
|
||||
pe fluxul de facturare din stoc) cheama `vizualizeaza_curs()` **fara parametru de data**
|
||||
(`oproceduri_curs.prg:94`) cand gaseste valute fara curs pentru ziua ceruta, in bucla `Do While
|
||||
llVerificare` (retry pana userul completeaza sau renunta).
|
||||
|
||||
Aceasta e exact situatia din `COMUN\docs\todos.txt:45` (punctul 16): "la finalizare se verifica
|
||||
cursul valutar necesar pentru politicile de preturi care se factureaza [...] la revenire din
|
||||
formularul de curs valutar, focusul revine [...] pe TIP DOCUMENT, si la iesire din serie se
|
||||
regenereaza numar act" — confirmat ca fenomenul are loc **dupa** ce antetul (`frm_date_factura`) e
|
||||
deja inchis si eliberat (`Release ofrmceredate`, pasul 1), deci orice regenerare de numar/focus
|
||||
vizibila dupa inchiderea `frm_curs` tine de ecranul/starea care ramane activa in spate (nu s-a
|
||||
localizat mai departe — cere depanare separata, in afara scopului "doar localizare" cerut aici).
|
||||
|
||||
---
|
||||
|
||||
## Cand are sens campul „Data curs valutar" — propunere de regula
|
||||
|
||||
Campul are sens de aratat/editabil pe antet exact cand exista **vreo** sansa ca cursul zilei sa fie
|
||||
folosit la facturare — nu doar cand documentul insusi e in valuta:
|
||||
|
||||
> Arata (si activeaza) `Clb_zi_curs` cand `poDate.tip` NU e retur (`!Inlist(poDate.tip,8,9)`) **SI**
|
||||
> (`poDate.in_valuta = 1` **SAU** exista macar o politica de pret in valuta accesibila tipului
|
||||
> curent de document — adica exact conditia care astazi populeaza `crscursuri` cu randuri, verificata
|
||||
> deja empiric la `ofacturare.vc2:15092`/`:19000`: `Used('crscursuri') And Reccount('crscursuri') > 0`
|
||||
> dupa incarcarea listei de articole). Pe retur (8/9) ramane ascuns ca azi.
|
||||
|
||||
Pe `frm_date_aviz`/`frm_date_aviz_lucrare`, unde `crscursuri` nu e inca disponibil la momentul
|
||||
antetului (se incarca dupa, la fel ca la factura), regula echivalenta practicabila **pe antet** (nu
|
||||
dupa) ar fi: arata campul daca tipul documentului admite politici de pret in valuta pentru
|
||||
sucursala/gestiunea curenta (verificare care azi nu exista pe antet, doar mai tarziu pe grila de
|
||||
articole) — necesita fie mutarea verificarii mai devreme, fie acceptarea ca antetul nu poate sti cu
|
||||
certitudine inainte de a incarca articolele, caz in care campul ramane vizibil implicit si doar
|
||||
eticheta/relevanta lui se clarifica ulterior (ca azi, in `frm_facturare_articole2`).
|
||||
|
||||
---
|
||||
|
||||
## Necunoscute ramase
|
||||
|
||||
- Nu s-a confirmat daca exista si alte politici (`CRM_POLITICI_PRET*`) sau reguli de sucursala care
|
||||
determina *inainte* de deschiderea grilei de articole daca vor exista linii `tip_valuta=1` — utile
|
||||
pentru a decide vizibilitatea campului chiar pe antet, nu doar reactiv dupa incarcarea articolelor.
|
||||
- Nu s-a urmarit complet "focusul sare pe tip document / regenerare numar act" (punctul 5/todos #16)
|
||||
dupa inchiderea `frm_curs` — s-a localizat doar traseul de deschidere, nu si ecranul/handler-ul
|
||||
care ramane activ in spate si cauzeaza simptomul; cere sesiune separata de depanare (posibil in
|
||||
`poGeneratorNumere`/`clb_serie_act`, cf. `ofacturare.vc2:9735-9737`, needatate aici).
|
||||
- Layout-urile `.frx` (neconvertite) care afiseaza `poDate.Curs`/`cValuta` pe hartie nu au fost
|
||||
verificate — gap deja semnalat in `rec_consumatori_vanzari.md` (risc posibil #3), ramane valabil.
|
||||
- Nu s-a confirmat empiric (interogare Oracle) daca exista azi in productie facturi `tip=1` (lei) cu
|
||||
linii `ID_VALUTA <> moneda_nationala` in `VANZARI_DETALII` — dovada ar intari direct concluzia
|
||||
punctului 3, dar cercetarea a fost strict pe cod (fara conexiuni DB, conform mandatului).
|
||||
@@ -3,7 +3,7 @@
|
||||
Bloc #6 / S5, parte din "editare factura emisa". Stare la 10.08.2026. Scop: Marius decide
|
||||
commit / push / SVN pe baza acestui fisier, fara sa recititeasca cele zece rapoarte de mai jos.
|
||||
|
||||
Surse: `docs\progres.md` (sectiunea #6/S5), `docs\handoff_s5.md` (deciziile 38-41),
|
||||
Surse: `docs\progres.md` (sectiunea #6/S5), handoff intermediar (sters) (deciziile 38-41),
|
||||
`docs\cercetare\rec_s5_scriere_reala.md`, `docs\cercetare\rec_s5_discount_valuta.md`,
|
||||
`docs\cercetare\rec_s5_teste.md`, `docs\cercetare\rec_s5_grid_articole.md`.
|
||||
|
||||
@@ -32,17 +32,17 @@ reeditare.
|
||||
|
||||
| Fisier | Repo | Ce s-a schimbat | Patch |
|
||||
|---|---|---|---|
|
||||
| `clase\omodificari.vc2` | COMUN | Coloana `pret_achizitie` in grid, editabilitate per rand (linii de set needitabile, marcaj albastru), 5 validari noi in `inainte_de_do_termin` | `docs\diff_s5_grid_articole.patch` |
|
||||
| `clase\ofacturare_comun.vc2` | COMUN | Agatarea apelului `ScrieArticoleFacturaEditate` dupa `finalizeaza_modificare_nota` (primul punct de intrare, `do_editare_factura`) | `docs\diff_s5_agatare.patch` |
|
||||
| `clase\comun.vc2` | COMUN | Aceeasi agatare, al doilea punct de intrare (`:2491`) | `docs\diff_s5_agatare.patch` |
|
||||
| `programe\ofacturare_editare.prg` | COMUN | Helper nou `ScrieArticoleFacturaEditate` (marcheaza tot sters / invie ce ramane / insereaza linii noi / apeleaza recalculul Oracle) | `docs\diff_s5_helper_scriere.patch` |
|
||||
| `utile\Teste\editare_factura\test_page3_articole.prg` | COMUN | Asteptari actualizate: `ColumnCount=15`, tip si editabilitate pe coloanele noi | `docs\diff_s5_teste.patch` |
|
||||
| `utile\Teste\editare_factura\test_s5_validari_articole.prg` (nou) | COMUN | Suita headless: validari + SQL generat de helper, cu mock pe `goExecutor` | `docs\diff_s5_teste.patch` |
|
||||
| `utile\Teste\editare_factura\test_ui_s5_grid_pret_achizitie.prg` (nou) | COMUN | Suita UI vizibila: coloana noua, needitabilitate pe linii de set, focus pe linie noua | `docs\diff_s5_teste.patch` |
|
||||
| `utile\Teste\editare_factura\test_s5_scriere_reala.prg` (nou) | COMUN | Test cu scriere reala in Oracle, doua treceri, COMMIT real | `docs\diff_s5_test_scriere_reala.patch` |
|
||||
| `utile\Teste\editare_factura\test_s5_discount_valuta.prg` (nou) | COMUN | Test parametru discount (NULL vs 0 vs valoare) + documente reale in valuta | `docs\diff_s5_discount_valuta.patch` |
|
||||
| `utile\Teste\editare_factura\test_s5_rollback_real.prg` (nou) | COMUN | Calea de ROLLBACK la esec partial, cu eroare Oracle provocata deliberat | `docs\diff_s5_goluri_test.patch` |
|
||||
| `utile\Teste\editare_factura\test_s5_al_doilea_intrare.prg` (nou) | COMUN | Al doilea punct de intrare (`comun.vc2:2491`) parcurs real | `docs\diff_s5_goluri_test.patch` |
|
||||
| `clase\omodificari.vc2` | COMUN | Coloana `pret_achizitie` in grid, editabilitate per rand (linii de set needitabile, marcaj albastru), 5 validari noi in `inainte_de_do_termin` | diff aplicat (sters) |
|
||||
| `clase\ofacturare_comun.vc2` | COMUN | Agatarea apelului `ScrieArticoleFacturaEditate` dupa `finalizeaza_modificare_nota` (primul punct de intrare, `do_editare_factura`) | diff aplicat (sters) |
|
||||
| `clase\comun.vc2` | COMUN | Aceeasi agatare, al doilea punct de intrare (`:2491`) | diff aplicat (sters) |
|
||||
| `programe\ofacturare_editare.prg` | COMUN | Helper nou `ScrieArticoleFacturaEditate` (marcheaza tot sters / invie ce ramane / insereaza linii noi / apeleaza recalculul Oracle) | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_page3_articole.prg` | COMUN | Asteptari actualizate: `ColumnCount=15`, tip si editabilitate pe coloanele noi | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_s5_validari_articole.prg` (nou) | COMUN | Suita headless: validari + SQL generat de helper, cu mock pe `goExecutor` | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_ui_s5_grid_pret_achizitie.prg` (nou) | COMUN | Suita UI vizibila: coloana noua, needitabilitate pe linii de set, focus pe linie noua | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_s5_scriere_reala.prg` (nou) | COMUN | Test cu scriere reala in Oracle, doua treceri, COMMIT real | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_s5_discount_valuta.prg` (nou) | COMUN | Test parametru discount (NULL vs 0 vs valoare) + documente reale in valuta | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_s5_rollback_real.prg` (nou) | COMUN | Calea de ROLLBACK la esec partial, cu eroare Oracle provocata deliberat | diff aplicat (sters) |
|
||||
| `utile\Teste\editare_factura\test_s5_al_doilea_intrare.prg` (nou) | COMUN | Al doilea punct de intrare (`comun.vc2:2491`) parcurs real | diff aplicat (sters) |
|
||||
| `docs\oracle_export.md` | COMUN | Corectie documentatie: `linesize 32767` in loc de 400 (cauza incidentului de export, vezi sectiunea 3) | fara patch dedicat |
|
||||
| `docs\scripturi-migrare-db.md` | COMUN | Corectie documentatie: `UpdateVersiune` nu primeste extensia `.sql` in argument | fara patch dedicat |
|
||||
| `versiune_db.txt` | ROAFACTURARE | `2026_08_08_01` -> `2026_08_09_02` | fara patch (fisier text, un rand) |
|
||||
|
||||
@@ -3517,6 +3517,34 @@ luna inchisa, referentiate, sau care au urmasi (retur, factura din aviz, factura
|
||||
> il inchide** — cele doua se unifica, nu se aleg. Din intrebarea 7 ramane deschisa **numai** partea de
|
||||
> tipuri 48/49.
|
||||
|
||||
> **CERINTA DE EXECUTIE ADAUGATA IN RUNDA 17 — `IN_STOC` se incarca din document, nu din nomenclator.**
|
||||
> Vine din consecinta 1 a deciziei 54 (vezi S10, „Trei consecinte"), si se prinde **aici**, nu la S12.
|
||||
> Cu flag-ul de regenerare pornit, `IN_STOC` nu mai e re-derivat de `adauga_articol_factura`, ci **vine
|
||||
> din formular** — deci valoarea pe care o incarca S8 devine valoarea care decide **descarcarea de
|
||||
> gestiune la reemitere**. Azi loader-ul lui #6 o citeste din nomenclatorul curent
|
||||
> (`ofacturare_editare.prg:302-303`), deci un articol devenit intre timp gestionabil (sau invers) ar
|
||||
> face reemiterea sa atinga **alt stoc decat documentul initial**, tacut.
|
||||
>
|
||||
> Trei consecinte concrete pentru canalul de citire (intrebarea 1 din §8.2, *recomandat* (B),
|
||||
> `cursor_editare_document`):
|
||||
> - canalul trebuie sa intoarca `IN_STOC` **asa cum a fost la emitere**, nu `GESTIONABIL = B.IN_STOC`
|
||||
> din nomenclatorul de azi, cum face `cursor_retur_document` (`PACK:3993-4000`). E un **al treilea
|
||||
> argument** pentru procedura noua, langa `ID_VANZARE_DET` / `TAXCODE` si langa `ID_POL` / `ID_CTR`
|
||||
> lipsa din `VVANZARI_ARTICOLE`;
|
||||
> - **valoarea istorica nu e stocata nicaieri**: `IN_STOC` nu e coloana pe `VANZARI_DETALII` (verificat
|
||||
> pe DB, vezi S10), traieste doar in temp. Deci primul pas al lui S8 pe aceasta cerinta e sa
|
||||
> stabileasca **de unde se reconstituie** — fie din urma lasata in rulaje / gestiune pentru documentul
|
||||
> respectiv, fie se accepta nomenclatorul curent ca aproximatie **declarata explicit**, fie se adauga
|
||||
> coloana (migrare DB, deci **DB inainte de EXE**, ca la S10). **Nu se presupune niciuna dintre
|
||||
> variante**; e o **preconditie de proiectare a lui S8**, nu un detaliu de implementare;
|
||||
> - pe tipurile **48/49** cerinta se intalneste cu decizia 60: acolo invariantul e `IN_STOC = 0` prin
|
||||
> constructie, deci valoarea incarcata trebuie sa fie `0` indiferent ce zice nomenclatorul azi.
|
||||
>
|
||||
> *Criteriu de test (intra in „gata cand" al lui S8):* un document emis cu un articol caruia i s-a
|
||||
> schimbat intre timp `IN_STOC` in nomenclator, deschis in formular, poarta **valoarea de la emitere**;
|
||||
> iar reemiterea lui lasa **stocul agregat neschimbat** (masurat inainte / dupa, nu prin inspectia
|
||||
> codului).
|
||||
|
||||
> **Cerinta noua din S8b e mai blanda decat se credea:** lookup-ul „ultimul delegat / ultima masina"
|
||||
> **are deja o garda** — `Empty(id_delegat) And Empty(id_masina)` (`ferestre_cere_date.vc2:3111`).
|
||||
> Riscul ramane real, dar **numai** pe documentele fara delegat si fara masina. Raportul da inventarul
|
||||
@@ -3537,7 +3565,8 @@ Formularul arata **identic** cu cel de introducere: fara banda de avertizare, fa
|
||||
valorile initiale, fara panou de diferente (decizia 5). Se schimba titlul ferestrei si **butonul
|
||||
principal** (decizia 9, vezi S8c).
|
||||
*Gata cand:* formularul deschis pe un document existent arata exact documentul, pe fiecare tip de
|
||||
sursa, si nu se distinge vizual de formularul de introducere.
|
||||
sursa, si nu se distinge vizual de formularul de introducere; **si** liniile incarcate poarta `IN_STOC`
|
||||
de la emitere, nu din nomenclatorul de azi (cerinta rundei 17, mai sus).
|
||||
*Depinde de:* S7.
|
||||
|
||||
#### S8b — Rutarea scrierii dupa ce s-a schimbat
|
||||
@@ -3878,6 +3907,9 @@ comportament nou:
|
||||
**comportamentul de stoc** al reemiterii. Ca reemiterea sa fie identica, **S8 trebuie sa incarce
|
||||
valoarea cu care s-a scris documentul initial** — si **azi nu o incarca**: loader-ul lui #6 o citeste
|
||||
din nomenclatorul curent (`ofacturare_editare.prg:302-303`). **Flag-ul singur nu rezolva asta.**
|
||||
**PRELUAT (runda 17) ca cerinta de executie in S8**, cu cele trei consecinte pentru canalul de citire
|
||||
si criteriul de test — vezi caseta „CERINTA DE EXECUTIE ADAUGATA IN RUNDA 17" din S8. Aici nu mai e
|
||||
nimic de decis.
|
||||
2. **Se pierde o validare pe ramura comenzi.** Azi, `A.PRET = V_PRET_TEMP` + lipsa lui `EXCEPTION` fac
|
||||
ca o linie care nu se mai potriveste cu comanda sa **opreasca** scrierea. Cu flag-ul pornit,
|
||||
reemiterea unei facturi din comanda nu mai verifica linia fata de comanda. Decizia 54 pare sa vrea
|
||||
|
||||
@@ -9,7 +9,7 @@ si verificari proprii, ca sa nu se amestece.
|
||||
| — | #8 — denormalizare VANZARI | **mediu** (scop extins 06.08) | `PACK_FACTURARE` + ambele view-uri (COMUN) + reparare date | **TERMINAT si COMIS** 07.08.2026 (r17990-r17993). Planul a fost sters la curatenie; istoricul e in `progres.md` |
|
||||
| — | [#7 — pret cu TVA pe linie](plan_07_pret_cu_tva_pe_linie.md) | mic-mediu | doar VFP, gridul de articole din `frm_facturare_articole` | **TERMINAT** 08.08.2026 (changelog 2.11.14). Editarea flagului pe o factura **deja salvata** a fost mutata explicit in #6 |
|
||||
| 1 | [#6 — editare factura emisa](plan_06_editare_factura.md) | mediu | `omodificari.vc2` (COMUN) + `PACK_FACTURARE` | **IN LUCRU, aproape gata** — S1-S7 si S9 comise (S4b incheiat 11.08.2026). Ramane **S8**: 2 esecuri reale pe „factura din aviz" (rulajele nu se refac pe nota noua) + 3 tipuri de sursa neacoperite. Stare: antetul planului |
|
||||
| 2 | [#13 — formular unificat + editare prin regenerare](plan_13_unificare_formular_facturare.md) | **mare** | `ofacturare.vc2` + `ofacturare.prg` + `PACK_FACTURARE` (COMUN) | propunere, 09.08.2026. Mockup: [`mockup_13_formular_unificat.html`](mockup_13_formular_unificat.html). **Perimetru comun cu #6** — de transat inainte de start |
|
||||
| 2 | [#13 — formular unificat + editare prin regenerare](plan_13_unificare_formular_facturare.md) | **mare** | `ofacturare.vc2` + `ofacturare.prg` + `PACK_FACTURARE` (COMUN) | **PROIECTAT INTEGRAL, cod neatins** (17 runde de proiectare, 11.08.2026). Etapele I si II sunt proiectate story cu story (S1-S14); raman testele (S6, S12) si inchiderea (S13). **65 de decizii luate**, niciuna deschisa. Perimetrul cu #6 e transat: **#13 incepe dupa terminarea lui #6** (decizia 30). Mockup: [`mockup_13_formular_unificat.html`](mockup_13_formular_unificat.html). Stare curenta: `handoff_13_formular_unificat.md` |
|
||||
| — | [#12 — nomenclator ca sursa de pret](plan_12_nomenclator_ca_lista_preturi.md) | mediu | depinde de varianta | valabil, **amanat** |
|
||||
| — | [#11 — integrare politici de preturi](plan_11_integrare_politici_preturi.md) | mare | COMUN + ROAPRETURI | valabil, **amanat** |
|
||||
| — | [#10 — integrare contracte](plan_10_integrare_contracte.md) | mare | COMUN + ROACONTRACTE | valabil, **amanat** |
|
||||
|
||||
180
docs/progres.md
180
docs/progres.md
@@ -4,33 +4,63 @@
|
||||
incheie. Planurile (`plan_0*.md`) spun *ce* e de facut; acesta spune *unde s-a ajuns*. Istoricul
|
||||
sesiunilor nu se pastreaza aici — doar starea la zi, deciziile, faptele stabilite si datoriile.
|
||||
|
||||
Ultima actualizare: **10.08.2026, dupa-amiaza**. **S5 e TERMINAT, LIVRAT SI COMIS in git.**
|
||||
**Decizia 42 (inclusiv discountul de antet) e IMPLEMENTATA si VERIFICATA, necomisa.** **S8 are acum
|
||||
toate cele patru tipuri de sursa** — mai ramane matricea de editare.
|
||||
Ultima actualizare: **11.08.2026, seara**. **Punctul #6 e practic terminat: S1-S7 si S9 sunt gata si
|
||||
comise.** Ramane **S8** — si nu ca lipsa de acoperire, ci cu doua esecuri reale.
|
||||
|
||||
**PREDAREA CURENTA, pentru sesiunea noua: `docs\handoff_punct6_10082026_pm.md`** — se citeste
|
||||
**prima**. Primul lucru de facut de acolo: **stergerea celor sase documente parazite** (`1051`, `1056`,
|
||||
`1057`, `1058`, `1059`, `1060`) prin aplicatie.
|
||||
**PREDAREA CURENTA e chiar acest fisier.** Handoff-urile intermediare intre sesiuni au fost
|
||||
desfiintate (11.08.2026, decizia lui Marius) impreuna cu diff-urile deja aplicate; ce era durabil in
|
||||
ele a intrat in antetele fisierelor de test sau in mesajele de commit. Nu mai cauta `handoff_*.md`.
|
||||
|
||||
Predarea anterioara, tot valabila pe reguli si comenzi: `docs\handoff_punct6_dupa_s5.md`. Dosarul de
|
||||
livrare al lui S5: `docs\livrare_s5.md`. Jurnalul blocului (decizii 38-41, incidente):
|
||||
`docs\handoff_s5.md`.
|
||||
**De facut, in ordine:**
|
||||
|
||||
**Comis in git, pe ramura `punct6-s4-runda3`**: `COMUN` `1c42ae0` (13 fisiere), `ROAFACTURARE`
|
||||
`316b6f7` (changelog **2.11.15** + `versiune_db.txt` pe `2026_08_09_02`). **Nefacute deliberat**:
|
||||
`git push` si `svn commit` — publicare pe server, decizia lui Marius. Cele doua scripturi Oracle sunt
|
||||
mutate in `D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08` cu `svn add` (status `A`, necomis).
|
||||
1. **Stergerea celor sase documente parazite** (`1051`, `1056`, `1057`, `1058`, `1059`, `1060`) prin
|
||||
aplicatie — ramasa din blocul de creare documente pentru S8.
|
||||
2. **S8 — doua esecuri reale.** Pe „factura din aviz" (tip 4), din **ambele** puncte de intrare,
|
||||
rulajele nu se refac pe nota noua (`Reccount(trul)=0`): `test_s8_matrice_surse.prg` da
|
||||
**42 PASS / 2 FAIL**. Tot acolo, trei tipuri de sursa au fost sarite la ultima rulare (lista de
|
||||
preturi `1048`, aviz `1052`, factura din contract `1055`), iar harnessul
|
||||
`COMUN\utile\Teste\editare_factura\creeaza_documente_s8.prg` **nu a scris inca niciun document** —
|
||||
capcanele de mediu (plaja de serii care chiar prinde, ordinea lui `mock_amessagebox`) sunt scrise
|
||||
in antetul lui.
|
||||
3. **Rebuild `roafacturare.exe`** din IDE si verificarea pe ecran, pe `1140895` / `1140921` — ambele
|
||||
contin `IV93900901` (`id_articol = 3598545102`), adica exact cazul corectat pe 11.08.
|
||||
4. **Punctele A si B** din `docs\rec_s4b_etapa2.md` — **deja implementate**, asteapta doar
|
||||
confirmarea lui Marius. Nu sunt lucru ramas.
|
||||
5. **`git push` nefacut** in ambele repo-uri (remote `romfast`) — decizia lui Marius.
|
||||
|
||||
**Starea la incheierea sesiunii — nimic periculos, verificat nu presupus**: zero procese `vfp9.exe`,
|
||||
zero tranzactii Oracle deschise, write-back dovedit prin **reconversie si diff** pe toate cele trei
|
||||
`.vc2` (nu pe mtime — `txt2vcx.ps1:300` il rescrie), `docs\verificare_s5_writeback.md`. Toti agentii
|
||||
inchisi.
|
||||
**Comis pe ramura `punct6-s4-runda3`, 11.08.2026**: `COMUN` `40a112a` (S4b etapa 2 — butonul,
|
||||
dialogul `frm_sincronizare_articole`, `id_articol` de la `I` la `N(20)` in toate cele 6 locuri, si
|
||||
doua `This.` -> `Thisform.` care faceau butonul „Adauga articol" sa dea eroare la orice click real) si
|
||||
`93a2718` (harnessul S8 intra in versionare); `ROAFACTURARE` `40933df` (changelog 2.11.15) si
|
||||
`d9f5ca4` (`docs\` intra in git). In SVN: **r18011** si **r18012**.
|
||||
|
||||
**Ce ramane din planul #6**: **S8** (matricea pe tipuri de sursa — se creeaza in dev documentele
|
||||
lipsa) si **implementarea deciziei 42** (articolele raman vizibile, dar needitabile, cand documentul e
|
||||
in eFactura). **S4b, S7 si S9 sunt GATA** (10.08.2026 — S4b inchis prin decizia 43, fara enumerarea
|
||||
vechi -> nou). Plus verificarea pe ecran de Marius.
|
||||
Detaliu si ordinea recomandata: `docs\handoff_punct6_dupa_s5.md`.
|
||||
**Cifre de test, citite din log, nu din rapoarte**: `test_s4b_sincronizare` **42/0** (include cazul de
|
||||
regresie `id_articol = 3598545102`, dovedit cu control negativ — cu campul `I` iese perechea
|
||||
`Adaugare`+`Semnalare` in loc de `Modificare`), `test_s4b_dialog` **35/0**, `test_s7_rotunjire` **6/0**,
|
||||
`test_s8_matrice_surse` **42 PASS / 2 FAIL**.
|
||||
|
||||
**Doua capcane de mediu platite pe 11.08, valabile pentru orice sesiune viitoare:**
|
||||
|
||||
- **`.FXP` vechi.** `vfp9.exe -A -T test.prg` poate executa **bytecode vechi** si „reusi" degeaba — o
|
||||
rulare a reprodus identic logul dinainte de o editare deja scrisa pe disc. **Sterge `.FXP`-ul suitei
|
||||
ca parte din comanda de rulare.** `SET PROCEDURE TO ...prg ADDITIVE` recompileaza corect, deci
|
||||
suspiciunea priveste `.FXP`-ul suitei, nu al modulelor.
|
||||
- **`GETFONT()`.** Un formular instantiat headless fara `goApp` ajunge in `_frmbase.Init` la
|
||||
`goApp.ReadIni`; eroarea e doar logata, parametrul cade pe `.F.` si `accessibility` deschide un
|
||||
dialog modal care atarna procesul si apare pe ecranul lui Marius. Fixul e **in harness**
|
||||
(`PUBLIC goApp, gcAcces` + `Createobject("wzApplication")`), **nu** in `_frm_base.vc2` — clasa e
|
||||
partajata de toata suita, iar in productie `goApp` exista mereu. Ruleaza mereu cu garda de timp.
|
||||
|
||||
**Documentatia, dupa curatenia din 11.08.2026**: `docs\` e acum versionat in **git si SVN** — era in
|
||||
afara oricarui control de versiuni. In `docs\cercetare\` au ramas **91** de rapoarte: sunt baza de
|
||||
dovezi a planului #13 (85 de trimiteri din `plan_13`), **nu le sterge**. Alte **14** cercetari
|
||||
trans-proiect au trecut in `COMUN\docs\cercetare\` (valuta si curs, TVA/VANZARI, consumatorii
|
||||
`VANZARI` in suita, integrarile #10/#11/#12, watchdog VFP, proiectarea Oracle a lui S5, view-ul
|
||||
`VVANZARI_ARTICOLE`), iar 20 de rapoarte de executie ale lui #6 au fost sterse.
|
||||
|
||||
**Starea la incheierea sesiunii — verificat, nu presupus**: zero procese `vfp9.exe`, zero tranzactii
|
||||
Oracle deschise (in acest bloc nu s-a atins Oracle), niciun fisier binar editat fara write-back,
|
||||
ambii arbori git curati fata de commituri.
|
||||
|
||||
## S8 — VERIFICAT PE VENDING PRODUCTIE, 10.08.2026: nu deblocheaza avizul
|
||||
|
||||
@@ -173,7 +203,7 @@ Mecanismul de editabilitate per rand exista deja din S5 in `omodificari.vc2` —
|
||||
conditie la nivel de formular.
|
||||
|
||||
**IMPLEMENTATA SI VERIFICATA, 10.08.2026** (agent `d42-efactura`, din alta sesiune; verificata pe disc de
|
||||
orchestratorul acestei sesiuni). **Necomisa.** Diff: `docs\diff_d42_efactura_readonly.patch`. Raport:
|
||||
orchestratorul acestei sesiuni). **Necomisa.** Diff: diff aplicat (sters). Raport:
|
||||
`docs\cercetare\rec_d42_efactura.md`. Forma implementata: flag `lArticoleReadOnly` pus in
|
||||
`frm_modific2024.Show` (`:14789-14813`), impins peste `.When`-urile existente din S5
|
||||
(`:16550`, `:16557`, `:16571`, `:16588`), `cmdAdaugaArticol`/`cmdStergeArticol.Enabled` plus garda
|
||||
@@ -329,7 +359,7 @@ editare factura de vanzare" + 2 puncte in „Implicatii practice". Acopera condi
|
||||
puncte de intrare cu garzile lor, secventa de scriere in tranzactia manuala unica, cei 4 pasi din
|
||||
`ScrieArticoleFacturaEditate`, `recalculeaza_totaluri_vanzari`, view-ul `VVANZARI_ARTICOLE` si
|
||||
comportamentul gridului. Regula deciziei 38 e scrisa **ca regula**, fara numarul deciziei, conform
|
||||
conventiei de comentarii. Diff: `docs\diff_s9_flux_nota_jurnal.patch`. Raport:
|
||||
conventiei de comentarii. Diff: diff aplicat (sters). Raport:
|
||||
`docs\cercetare\rec_s9_documentatie.md`.
|
||||
|
||||
**Verificat de orchestrator pe disc**, nu din raport: modificat **doar** fisierul de documentatie
|
||||
@@ -347,7 +377,7 @@ documentatie e corect. **Tipar de retinut**: constatarea „nu exista X in metod
|
||||
|
||||
## #6 / S5 — scrierea sumelor editate in Oracle, TERMINAT SI COMIS 10.08.2026
|
||||
|
||||
**Starea completa a blocului e in `docs\handoff_s5.md`** — se citeste inaintea acestei sectiuni.
|
||||
**Starea completa a blocului e in handoff intermediar (sters)** — se citeste inaintea acestei sectiuni.
|
||||
Aici doar ce trebuie sa stie o sesiune noua din prima:
|
||||
|
||||
- **Codul e scris integral si write-back-ul e facut** pe toate cele patru fisiere atinse:
|
||||
@@ -359,19 +389,19 @@ Aici doar ce trebuie sa stie o sesiune noua din prima:
|
||||
(view-ul, cu `ID_VANZARE_SET` si `PRET_ACHIZITIE`). Pachetul e `VALID`, zero erori.
|
||||
`versiune_db.txt` = **`2026_08_09_02`**. Scripturile sunt in `docs\`, **nu** in `SCRIPTURI_CLAR`.
|
||||
- **Deciziile 38-41** (ordonarea scrierii, liniile de set, `PRET_ACHIZITIE`, discountul ca parametru)
|
||||
sunt in `handoff_s5.md`. **Decizia 38 corecteaza planul S5**: recalculul se apeleaza din VFP, nu
|
||||
sunt in handoff intermediar (sters). **Decizia 38 corecteaza planul S5**: recalculul se apeleaza din VFP, nu
|
||||
din `finalizeaza_modificare_nota`, altfel ar calcula totalurile pe liniile dinainte de editare.
|
||||
- **Runda 2 pe grid, INCHISA** (`s5-grid`, 09.08.2026 tarziu): cele trei corectii de code-review sunt
|
||||
in binar. **Write-back verificat prin reconversie si diff, nu pe mtime** — textul regenerat din
|
||||
binar e identic octet cu octet cu `.vc2` (`txt2vcx.ps1:300` rescrie mtime-ul textului, deci mtime
|
||||
nu dovedeste nimic). O a patra constatare s-a dovedit **nerealizabila** pe codul de acum si nu se
|
||||
repara — detalii si conditia care ar activa-o, in `handoff_s5.md`.
|
||||
repara — detalii si conditia care ar activa-o, in handoff intermediar (sters).
|
||||
- **Regresia e la baseline pe toate cele sase suite**, cifre numarate din loguri de orchestrator,
|
||||
toate rulate **dupa** write-back (binar 23:15:50): `test_page3_articole` **14/2** (23:19:52),
|
||||
`test_adauga_linie_articol` **20/0**, `test_adauga_linie_valuta` **16/0**, `test_ui_sterge_linie`
|
||||
**8/0**, `test_verdict_act_rul` **26/0**, `test_incarca_vanzare_din_nota` **5/0** (23:27:52).
|
||||
- **Acoperirea cu teste, LIVRATA** (`s5-teste`, `docs\cercetare\rec_s5_teste.md`,
|
||||
`docs\diff_s5_teste.patch`): suita noua headless `test_s5_validari_articole.prg` **35 PASS / 0 FAIL**
|
||||
diff aplicat (sters)): suita noua headless `test_s5_validari_articole.prg` **35 PASS / 0 FAIL**
|
||||
(validarile din `inainte_de_do_termin`, garda de no-op, SQL-ul din `ScrieArticoleFacturaEditate` cu
|
||||
mock pe `goExecutor`, fara Oracle) si suita noua pe formular vizibil
|
||||
`test_ui_s5_grid_pret_achizitie.prg` **14 PASS / 0 FAIL** (15 coloane, linie de set needitabila cu
|
||||
@@ -427,7 +457,7 @@ Aici doar ce trebuie sa stie o sesiune noua din prima:
|
||||
- **Capcana platita, sa nu se repete**: exportul `all_source` cu `linesize` prea mic **rupe linii
|
||||
lungi prin mijlocul identificatorilor** si corupe tacut orice script construit din el. Un script
|
||||
de pachet se face de la **ultimul script aplicat din `SCRIPTURI_CLAR`**, nu de la un export.
|
||||
Detalii in `handoff_s5.md`; `COMUN\docs\oracle_export.md` a fost corectat.
|
||||
Detalii in handoff intermediar (sters); `COMUN\docs\oracle_export.md` a fost corectat.
|
||||
|
||||
## COMIS PE BRANCH `punct6-s4-runda3` — 09.08.2026, NEIMPINS, NEINTRAT IN SVN
|
||||
|
||||
@@ -458,7 +488,7 @@ Cand documentul e in valuta (`tvanz.in_valuta = 1`), dialogul `frm_articol_factu
|
||||
`frm_facturare_articole2` folosesc **activ, in productie**, aceeasi ramura `tip_valuta = 1`, deci
|
||||
orice atingere a codului dialogului ar fi fost o regresie potentiala pe formularul de compunere.
|
||||
Premisa initiala a deciziei 35 (ca ar fi nevoie de `poDate.in_valuta`/`zi_curs`/`id_valuta`) era
|
||||
gresita — vezi corectia de la decizia 35 si `docs\handoff_decizia35_valuta_dialog.md`.
|
||||
gresita — vezi corectia de la decizia 35 si handoff intermediar (sters).
|
||||
|
||||
**Verificat de orchestrator pe disc** (cifre numarate din loguri): `test_adauga_linie_valuta.prg`
|
||||
extins la **16 PASS / 0 FAIL** — acopera **ambele** ramuri, scenariul A (intrare in RON, conversie la
|
||||
@@ -470,8 +500,8 @@ headless de la datoria 7), `test_incarca_vanzare_din_nota` **5/0**, `test_adauga
|
||||
**20/0**, `test_ui_sterge_linie` **8/0**, `test_verdict_act_rul` **26/0**. Rulari 18:57-18:59, toate
|
||||
**dupa** ultima editare de cod (`omodificari.vc2` 18:53:21, `ofacturare_editare.prg` 18:52:59).
|
||||
Cens de octeti `2 aa / 2 e3 / 2 fe`, zero `EF BF BD`. Text si binar sincrone, **necomis**.
|
||||
Diff: `docs\diff_s4_valuta_dialog.patch` + `docs\diff_s4_valuta_dialog_prg.patch` +
|
||||
`docs\diff_s4_valuta_dialog_test.patch`. Raport: `docs\cercetare\rec_s4_valuta_dialog.md`.
|
||||
Diff: diff aplicat (sters) + diff aplicat (sters) +
|
||||
diff aplicat (sters). Raport: `docs\cercetare\rec_s4_valuta_dialog.md`.
|
||||
|
||||
**Ramas de verificat pe ecran de Marius** (netestabil headless, dialogul e modal `Show(1)`): tastarea
|
||||
reala in caseta de pret pe un document in valuta, eticheta de valuta afisata, si interactiunea cu
|
||||
@@ -508,7 +538,7 @@ aplica", ascundere pe transfer/custodie, alegere cont pe grupa de tip, corectie
|
||||
nestocata). Cens de octeti: stricat si reparat (acelasi tipar cunoscut), identic cu baseline la
|
||||
final. **Scris in binar** (write-back OK dupa un fidelity-check picat pe formatarea liniilor goale,
|
||||
rezolvat prin adoptarea textului regenerat), **necomis**. Diff:
|
||||
`docs\diff_s4_runda3c2_verdict.patch` + `docs\diff_s4_runda3c2_ofacturare_editare.patch`.
|
||||
diff aplicat (sters) + diff aplicat (sters).
|
||||
|
||||
**Reverificat de orchestrator pe starea de pe disc** (nu din raportul agentului): cifrele numarate
|
||||
din loguri, nu citite din raport — toate se confirma, inclusiv cele 18/0 ale suitei noi. Rularile
|
||||
@@ -535,7 +565,7 @@ valoare. Pe `cod=1140895`: `Total ACT` = `Total RUL` = **1924.59**, verdict **si
|
||||
(asertia veche care astepta "divergent" a fost inversata, cu verificare explicita a cifrei).
|
||||
Regresie neschimbata + suita dedicata **26 PASS / 0 FAIL** (18 vechi + 8 noi: excludere
|
||||
`id_tip_rulaj=3`, includere `id_tip_rulaj=0`, cele trei conturi rate/contract). Scris in binar,
|
||||
necomis. Diff: `docs\diff_s4_runda3c3_decizii_36_37.patch` + `docs\diff_s4_runda3c3_test.patch`.
|
||||
necomis. Diff: diff aplicat (sters) + diff aplicat (sters).
|
||||
**Reverificat de orchestrator pe disc**: cifre numarate din loguri (26/0 pe suita dedicata, regresie
|
||||
`14/2 · 5/0 · 20/0 · 6/0 · 8/0`), rulari 18:40-18:42 **dupa** ultima editare (18:34:03); filtrul din
|
||||
cod e `SUM (Nvl(cant,0)+Nvl(cante,0))*Nvl(pretvtva,0) FOR Nvl(sters,0)=0 AND Nvl(id_tip_rulaj,0)=0`
|
||||
@@ -549,7 +579,7 @@ inchide capcana prefixului `411`/`4111` mai bine decat un `==` repetat; (3) exis
|
||||
|
||||
**Ce urmeaza** (stabilit de Marius, 09.08.2026): **intrarea directa in valuta in
|
||||
`frm_articol_factura`** — decizia 35. **Premisa deciziei a fost corectata** intre timp: nu cere
|
||||
atins `ofacturare.vc2` (vezi decizia 35 mai jos si `docs\handoff_decizia35_valuta_dialog.md`).
|
||||
atins `ofacturare.vc2` (vezi decizia 35 mai jos si handoff intermediar (sters)).
|
||||
|
||||
Ultima actualizare anterioara: **09.08.2026**, dupa **cele doua defecte de pe pagina de articole
|
||||
(culoare + valuta), REZOLVATE**.
|
||||
@@ -585,8 +615,8 @@ din log, nu din raport**, si dovada ca rularea a ajuns la capat e linia de `REZU
|
||||
Raportate dupa livrarea sub-blocului B partea 2 (mai jos). Ambele in `COMUN\clase\omodificari.vc2`
|
||||
(+ `ofacturare_editare.prg` pentru al doilea). Write-back facut (fidelity check OK), text si binar
|
||||
sincrone, **necomise**. Backup dinaintea fixului: `omodificari.vc2.pre_fix_culoare.bak`,
|
||||
`ofacturare_editare.prg.pre_fix_culoare.bak`. Diff: `docs\diff_s4_fix_culoare_valuta.patch` +
|
||||
`docs\diff_s4_fix_culoare_valuta_ofacturare_editare.patch`.
|
||||
`ofacturare_editare.prg.pre_fix_culoare.bak`. Diff: diff aplicat (sters) +
|
||||
diff aplicat (sters).
|
||||
**Reverificat de orchestrator pe starea finala de pe disc**: `ofacturare_editare.prg` fusese modificat
|
||||
la 17:08:48, adica **la 40 de secunde dupa ultima rulare de test** (17:08:08), deci starea livrata nu
|
||||
era acoperita de nicio suita. Rerulat `test_page3_articole.prg` pe starea de pe disc: **14 PASS /
|
||||
@@ -675,7 +705,7 @@ anterioare** (stergerea logica, sub-blocul B partea 1) — nereparat, predat mai
|
||||
octeti stricat si reparat de 2 ori in sesiune (acelasi tipar cunoscut), identic cu baseline la
|
||||
final: `2 aa/2 e3/2 fe`, zero `EF BF BD`. **Scris in binar (write-back OK dupa 2 fidelity-check-uri
|
||||
picate pe ordine, rezolvate prin adoptarea textului regenerat), necomis.** Diff:
|
||||
`docs\diff_s4_runda3b2_adaugare.patch` (+ `docs\diff_s4_runda3b2_ofacturare_editare.patch`).
|
||||
diff aplicat (sters) (+ diff aplicat (sters)).
|
||||
Raport: `docs\cercetare\rec_s4_runda3b2.md`.
|
||||
|
||||
Inaintea acesteia, in aceeasi zi: **sub-blocul C, PARTIAL — bara de totaluri + discount de
|
||||
@@ -702,7 +732,7 @@ acelasi tipar de infrastructura documentat mai jos, nu problema de cod). Cens de
|
||||
2 fe`, zero `EF BF BD`, identic inainte/dupa (stricat si reparat de mai multe ori in timpul editarii,
|
||||
capcana deja cunoscuta). **Scris in binar (write-back OK dupa 3 rulari, fidelity-check picat pe
|
||||
ordine de fiecare data, rezolvat prin adoptarea textului regenerat), necomis.** Diff:
|
||||
`docs\diff_s4_runda3c_totaluri.patch` (+ `docs\diff_s4_runda3c_ofacturare_editare.patch`, izolat).
|
||||
diff aplicat (sters) (+ diff aplicat (sters), izolat).
|
||||
Raport: `docs\cercetare\rec_s4_runda3c.md`. **Verdictul de corelatie cu `ACT`/`RUL` NU e facut** —
|
||||
formulele sunt deja stabilite si verificate pe date in `rec_suma_act.md`, predat ca partea 2 a
|
||||
sub-blocului C (contul pe tip, filtrul `cod+an+luna`, indicatorul cu 3 stari, threading `an`/`luna`
|
||||
@@ -714,7 +744,7 @@ Inaintea acesteia, in aceeasi zi: **sub-blocul B, PARTIAL — doar stergerea de
|
||||
e facuta** — sub-blocul s-a dovedit prea mare pentru un context si a fost impartit, cu aprobarea
|
||||
briefingului. Cercetarea de contract pentru adaugare (proprietati `poArticol`/`poDate` citite de
|
||||
dialog, cum se ocoleste `gnScadereStoc`, ce lipseste inca — picker de articol) e completa si
|
||||
predata in `docs\handoff_s4_runda3b_adaugare.md`. Testat: regresie neschimbata (`14/2`, `5/5`),
|
||||
predata in handoff intermediar (sters). Testat: regresie neschimbata (`14/2`, `5/5`),
|
||||
plus test UI nou dedicat (`test_ui_sterge_linie.prg`). **Atentie la cifra**: logul are **6 PASS /
|
||||
0 FAIL**, nu 7/7 cum s-a raportat initial — rularea s-a **taiat la `READY`**, adica exact la
|
||||
handshake-ul de captura, si n-a ajuns la linia de `REZULTAT`. Dovedit: butonul exista si e vizibil,
|
||||
@@ -724,13 +754,13 @@ dupa handshake si n-a mai rulat. **Captura de ecran n-a putut fi obtinuta** (`vf
|
||||
desi procesul chiar a rulat testul complet pana la capat de fiecare data — problema de
|
||||
infrastructura/masina ocupata, nu de cod; detalii in raport). **Scris in binar (write-back
|
||||
FACUT dupa un fidelity-check picat pe ordine, rezolvat prin adoptarea textului regenerat),
|
||||
necomis.** Diff: `docs\diff_s4_runda3b_linii.patch`. Raport: `docs\cercetare\rec_s4_runda3b.md`.
|
||||
necomis.** Diff: diff aplicat (sters). Raport: `docs\cercetare\rec_s4_runda3b.md`.
|
||||
Inaintea acesteia, in aceeasi zi: **extinderea la cei 5 apelanti `frm_modific2024` + linia din
|
||||
`roagest.prg`** — helper nou `PregatesteArticoleFacturaEditare` in `ofacturare_editare.prg`, apelat
|
||||
gardat inainte de `Createobject` la `afisjurcom.do_modifica` (registrul jurnal, viu in ROACONT),
|
||||
`anaf_efactura.importmodifica` si cele doua `.sc2` de import; linia `SET PROCEDURE TO
|
||||
ofacturare_editare.prg` adaugata in `roagest.prg`. Detalii: `docs\cercetare\rec_s4_apelanti.md`,
|
||||
diff `docs\diff_s4_apelanti_frm_modific2024.patch`. Mai devreme: **rezolvarea datoriei 6** — baza
|
||||
diff diff aplicat (sters). Mai devreme: **rezolvarea datoriei 6** — baza
|
||||
de regresie #6/S4 e din nou solida, iar suitele nu mai hardcodeaza documente: si-l descopera
|
||||
singure, deci nu mai mor la urmatoarea realocare de `cod`. Mai devreme inca: doua defecte de
|
||||
editare pe pagina de articole (coloanele cantitate/pret needitabile, valoare defazata la bifa
|
||||
@@ -774,7 +804,7 @@ nevoie de alta sursa pentru plafon.
|
||||
|
||||
## #6, runda 1 (S1-S3) — implementat 08.08.2026, corectii 08.08.2026
|
||||
|
||||
Diff: `docs\diff_consolidat_runda1_3.patch` + `docs\diff_runda4_scoate_garda.patch` (netrimise inca
|
||||
Diff: diff aplicat (sters) + diff aplicat (sters) (netrimise inca
|
||||
la commit, asteapta review). Patch-urile per runda raman pe disc pentru istoric.
|
||||
|
||||
- **`COMUN\clase\ofacturare_comun.vc2`**, clasa `frm_facturi`: metoda `do_editare_factura`
|
||||
@@ -792,7 +822,7 @@ la commit, asteapta review). Patch-urile per runda raman pe disc pentru istoric.
|
||||
`Createobject('frm_modific2024')` pica cu "Class definition not found" chiar si in productie):
|
||||
`SET CLASSLIB TO omodificari.vcx additive`. ROAFACTURARE nu incarcase niciodata aceasta clasa —
|
||||
se foloseste azi doar din ROACONT/ROAGEST (registrul jurnal).
|
||||
- **Corectii de review aplicate 08.08.2026** (`docs\diff_runda2_corectii.patch`):
|
||||
- **Corectii de review aplicate 08.08.2026** (diff aplicat (sters)):
|
||||
- `IncarcaCursoareModificareNota` propaga acum esecul: pe eroare Oracle la interogarea `vrul_tot` sau
|
||||
`vrul_obinv_tot` face `RETURN .F.` (curatand cursoarele deschise pana atunci), nu mai continua pana la
|
||||
`RETURN .T.` final ca si cum ar fi reusit. **Corectie de premisa fata de constatarea initiala**:
|
||||
@@ -805,7 +835,7 @@ la commit, asteapta review). Patch-urile per runda raman pe disc pentru istoric.
|
||||
in `afisjurcom.do_modifica` la `buton=1`) — corect prin constructie, pentru ca acum ajunge acolo doar
|
||||
daca incarcarea a reusit integral.
|
||||
- **Garda pe `id_set`: adaugata in runda 2, rafinata in runda 3, SCOASA DE TOT in runda 4**
|
||||
(`docs\diff_runda4_scoate_garda.patch`, decizia 24). Istoric, ca sa nu se reia: premisa ei era ca
|
||||
(diff aplicat (sters), decizia 24). Istoric, ca sa nu se reia: premisa ei era ca
|
||||
`PACK_FACTURARE.scrie_discount` scrie randurile `DISCOUNT`/`TVA DISCOUNT` cu `id_set + 5`, deci o
|
||||
nota poate avea 2 `id_set`. **Fals la destinatie**: `cumuleaza_note_act_temp` normalizeaza inainte
|
||||
de `ACT`, offsetul e tranzitoriu. Pe date: 558 de note legate de `VANZARI` cu un singur `id_set`,
|
||||
@@ -895,7 +925,7 @@ sincronizate**, dar **fara diff livrat si fara raport** — runda nu e inchisa.
|
||||
inofensiv; zero `CREATE SQL VIEW` / `USE ... VIA` in toata ierarhia de clase.
|
||||
- **B.2 (marcaje stare linii) nu e in scope runda 1** — grid-ul e strict readonly; marcajele sunt runda 2.
|
||||
- **Runda 1 e INCHISA pe cod si testata**, asteapta doar review-ul lui Marius. Diff:
|
||||
`docs\diff_s4_runda1_page3.patch` (2 fisiere, fata de backup-urile de dinainte de S4). Raport:
|
||||
diff aplicat (sters) (2 fisiere, fata de backup-urile de dinainte de S4). Raport:
|
||||
`docs\cercetare\rec_s4_runda1.md`. Instrumentarea de depanare a fost scoasa din suita si suita
|
||||
rerulata dupa curatare — 7 PASS, zero erori. `test_baseline_isolation.prg` sters (temporar prin
|
||||
design, si cu concluzie nula: testa copia ROACONT). **Fara commit — se asteapta aprobarea.**
|
||||
@@ -935,14 +965,14 @@ sincronizate**, dar **fara diff livrat si fara raport** — runda nu e inchisa.
|
||||
`cod=1139934`->`id_vanzare=882` si un test de garda care scoate `ofacturare_editare.prg` din
|
||||
`SET PROCEDURE` si verifica `PageCount=2`). Verificat separat (test dedicat) ca `SCAN...ENDSCAN` din
|
||||
`IncarcaVanzareDinNota` continua corect chiar daca IncarcaVanzareNota schimba workarea in interiorul
|
||||
buclei. Write-back `.vc2`->binar OK (fidelity check trecut). Diff: `docs\diff_s4_runda2_view_pozitionare.patch`.
|
||||
buclei. Write-back `.vc2`->binar OK (fidelity check trecut). Diff: diff aplicat (sters).
|
||||
Raport: `docs\cercetare\rec_s4_runda2.md`. **Fara commit — asteapta review.**
|
||||
- **ANCORAREA COLOANELOR — REZOLVATA prin view Oracle dedicat** (decizia 26, 08.08.2026).
|
||||
`VVANZARI_ARTICOLE` e **creat si validat** pe `MARIUSM_AUTO` (`VALID`, 21 de coloane, verificat independent prin
|
||||
`sqlplus` dupa aplicare): `id_vanzare` + cele 20 consumate azi, valori **RAW**, fara conversie
|
||||
valutara, fara filtru `sters` (apelantul filtreaza, ca la `vact_tot`/`vrul_tot`). Script:
|
||||
`D:\ROA\DATABASE\SCRIPTURI_CLAR\2026\08\ff_2026_08_08_01_COMUN_VVANZARI_ARTICOLE.sql` (CRLF pur, idempotent,
|
||||
**necomis in SVN**). Proiectarea: `docs\cercetare\rec_view_articole_vanzare.md`.
|
||||
**necomis in SVN**). Proiectarea: `COMUN\docs\cercetare\rec_view_articole_vanzare.md`.
|
||||
- **`id_vanzare` era omis** din `SELECT`-ul vechi desi e cheia de filtrare — omisiune reala, corectata.
|
||||
- **`FACT_VFACTURI_DETALII` exista si a fost respins motivat**: recalculeaza `pret`/`discount_unitar`
|
||||
la cursul curent, pentru tiparire. Editarea are nevoie de valorile stocate, ca S5 sa scrie inapoi
|
||||
@@ -994,7 +1024,7 @@ sub-blocuri mici, cu cate un agent proaspat, ca review-ul sa ramana mic.
|
||||
|
||||
**Sub-blocul A e SCRIS IN BINAR** (08.08.2026). Contrar a ce scria aici, write-back-ul s-a facut:
|
||||
`omodificari.vct` contine `cSubtotalArt`, `lmodificat`, `cPretCuTvaArt`, iar textul are
|
||||
`ColumnCount = 14`. Fidelity-check-ul picat descris in `docs\handoff_s4_runda3a.md` a fost depasit
|
||||
`ColumnCount = 14`. Fidelity-check-ul picat descris in handoff intermediar (sters) a fost depasit
|
||||
(remediul era ordinea `Header1` dupa `_checkbox1` la `cPretCuTvaArt`). Ramane necomis, ca tot restul.
|
||||
|
||||
Doua rezultate stabilite in runda 3A, de nu mai reluat:
|
||||
@@ -1019,7 +1049,7 @@ Ultimul camp se numeste **`valoare`** (fost `subtotal`), vezi sectiunea de defec
|
||||
## #6, doua defecte de AFISARE pe pagina de articole — REZOLVATE 08.08.2026, dovedite pe ecran
|
||||
|
||||
Raportate de Marius dupa testarea pe ecran. Ambele in `frm_modific2024`. Write-back facut, text si
|
||||
binar sincrone, **necomise**. Diff: `docs\diff_fix_grid_tvd_blank.patch`. Raport:
|
||||
binar sincrone, **necomise**. Diff: diff aplicat (sters). Raport:
|
||||
`docs\cercetare\rec_fix_grid_tvd_blank.md`.
|
||||
|
||||
- **Grid-ul de articole aparea COMPLET GOL** (nici macar coloane), desi `tvd` avea randuri. Cauza:
|
||||
@@ -1078,7 +1108,7 @@ totaluri (deciziile 20 si 25).
|
||||
|
||||
Raportate de Marius dupa testarea pe ecran a rundei 3A, in `COMUN\clase\omodificari.vc2`
|
||||
(`frm_modific2024`) si `COMUN\programe\ofacturare_editare.prg`. Write-back facut (fidelity check
|
||||
trecut), text si binar sincrone, **necomise**. Diff: `docs\diff_fix_grid_editabil_subtotal.patch`.
|
||||
trecut), text si binar sincrone, **necomise**. Diff: diff aplicat (sters).
|
||||
Backup-uri dinaintea fixului: `COMUN\clase\omodificari.vc2.pre_fix3a.bak`,
|
||||
`COMUN\programe\ofacturare_editare.prg.pre_valoare.bak`.
|
||||
|
||||
@@ -1128,7 +1158,7 @@ recreeaza cursorul.
|
||||
## #6, S4 runda 3 sub-blocul B — stergerea de linii GATA, adaugarea predata mai departe, 09.08.2026
|
||||
|
||||
Detalii complete: `docs\cercetare\rec_s4_runda3b.md` (implementare + testare) si
|
||||
`docs\handoff_s4_runda3b_adaugare.md` (cercetarea de contract pentru partea neinceputa).
|
||||
handoff intermediar (sters) (cercetarea de contract pentru partea neinceputa).
|
||||
|
||||
- **Stergere logica** — buton nou `cmdStergeArticol` pe `pgfArticole.PAGE3`
|
||||
(`omodificari.vc2:12260-12274`), `Click` comuta `tvd.sters` intre 0/1 si seteaza
|
||||
@@ -1171,7 +1201,7 @@ Detalii complete: `docs\cercetare\rec_s4_runda3b.md` (implementare + testare) si
|
||||
activ al lui Marius: RustDesk, VS Code, PL/SQL Developer, Explorer), nu de cod. Recomandare:
|
||||
o trecere de confirmare vizuala cand masina e libera, inainte de commit — nu blocheaza
|
||||
livrarea.
|
||||
- Diff: `docs\diff_s4_runda3b_linii.patch` (162 linii, scopat strict pe aceasta lucrare —
|
||||
- Diff: diff aplicat (sters) (162 linii, scopat strict pe aceasta lucrare —
|
||||
reconstruit dintr-un backup `.pre_runda3b.bak` obtinut prin reversul exact al editarilor,
|
||||
pentru ca nu s-a luat backup INAINTE de prima editare).
|
||||
|
||||
@@ -1273,9 +1303,9 @@ s-a facut cu `COMUN\utile\curatenie.ps1` (47 de intrari: patch-uri, handoff-uri,
|
||||
`utile/Teste/editare_factura/test_page3_articole.prg`, plus cele 3 fisiere `.md` din `docs\`
|
||||
(encoding). `svn status` arata in plus binarele `clase\ofacturare_comun.vcx`/`.vct` si
|
||||
`clase\omodificari.vcx`/`.VCT` ca `M`. Arborele ROAFACTURARE principal e curat. Diff-urile de review:
|
||||
`docs\diff_s4_fix_butoane_crsjtva.patch`, `docs\diff_reguli_encoding.patch`,
|
||||
`docs\raport_sweep_encoding.md`, `docs\diff_fix_grid_tvd_blank.patch`,
|
||||
`docs\diff_fix_grid_editabil_subtotal.patch`.
|
||||
diff aplicat (sters), diff aplicat (sters),
|
||||
`docs\raport_sweep_encoding.md`, diff aplicat (sters),
|
||||
diff aplicat (sters).
|
||||
|
||||
### Copiile de `COMUN` din ROACONT si ROAGEST: aduse la r18010 (08.08.2026)
|
||||
|
||||
@@ -1290,12 +1320,12 @@ pierdut; cer `svn resolve`, decizia e a lui Marius. Au ramas modificate local do
|
||||
|
||||
## #6, S4 runda 2 — ce contine, pe scurt
|
||||
|
||||
Starea completa, inventarul si ce ramane: **`docs\handoff_sesiune_08082026_e.md`**. Pe scurt: view-ul
|
||||
Starea completa, inventarul si ce ramane: **handoff intermediar (sters)**. Pe scurt: view-ul
|
||||
`VVANZARI_ARTICOLE` consumat cu `select *`, pozitionarea pe triplete (decizia 27), garda pentru ROACONT/ROAGEST,
|
||||
`AMESSAGEBOX` pe erorile Oracle, structura unica pentru cursorul `tvd`. Validata pe starea curenta,
|
||||
dupa redenumirea view-ului si taierea comentariilor: fidelity check trecut, suita **10/10** si
|
||||
**5/5** la data validarii (cifrele nu mai sunt valabile azi — vezi datoria 6), exit 0, zero
|
||||
dialoguri. Diff: `docs\diff_s4_runda2_view_pozitionare.patch`.
|
||||
dialoguri. Diff: diff aplicat (sters).
|
||||
|
||||
`vvanzari_detalii` / `vvanzari_detalii_tot` **nu se extind** — motivele pe date, in handoff: 11 coloane
|
||||
lipsa, cost de 3.7x fata de `VVANZARI_ARTICOLE`, si `select * from vvanzari_detalii_tot` in `oproceduri_listari.prg`
|
||||
@@ -1313,10 +1343,10 @@ din ~10 produse.
|
||||
2. **Build ROAAUTO, la Marius**: rebuild din IDE + test UI pe un deviz real — fara el corectia S7 din
|
||||
#8 n-are efect. Partea ROAFACTURARE e inchisa (build + deploy 2.11.14, 08.08.2026).
|
||||
**Agentul nu atinge `.PJX`/`.PJT`/`.exe`.**
|
||||
3. **Changelog ROAAUTO** — textul propus e in `docs\cercetare\rec_s10_s12.md`, neaplicat in
|
||||
3. **Changelog ROAAUTO** — textul propus e in `COMUN\docs\cercetare\rec_s10_s12.md`, neaplicat in
|
||||
`changelog_roaauto.txt`.
|
||||
4. **Curatarea tabelei `VERSIUNE`** de numele vechi de scripturi (`_02`..`_06`), cu inregistrari
|
||||
multiple din aplicarile succesive. `docs\cercetare\s10_curata_versiune.sql`, de extins cu numele
|
||||
multiple din aplicarile succesive. `COMUN\docs\cercetare\s10_curata_versiune.sql`, de extins cu numele
|
||||
vechi. Fara impact functional, doar istoric zgomotos.
|
||||
5. **Puncte nedecise de la #8, niciunul blocant**:
|
||||
- `tip=1` cu `id_comanda` — 16 facturi pe productie care n-ar trebui sa aiba;
|
||||
@@ -1324,7 +1354,7 @@ din ~10 produse.
|
||||
afisa un `/` singur. Zero documente azi in ambele scheme;
|
||||
- cele 620 de randuri cu `ID_VALUTA` NULL — normalizarea la `0`/`1`;
|
||||
- **propagarea corectiei `xmlefactura.prg`** in cele ~16 cai ramase din alte produse ROA.
|
||||
Inventarul: `docs\cercetare\rec_consumatori_vanzari.md`. Grup A (byte-identice, acelasi patch):
|
||||
Inventarul: `COMUN\docs\cercetare\rec_consumatori_vanzari.md`. Grup A (byte-identice, acelasi patch):
|
||||
ROAACNPRO, ROAAUTO, ROACONT, ROACONTRACTE, ROADEF, ROAGEST, ROAIMOB, ROAREGISTRATURA, ROARES,
|
||||
ROASTART. Grup B (fisier divergent, acelasi tipar la alta linie): OUTPUT/ROACONT `:350`,
|
||||
ROACONIMPORT / ROAEFACTURA / ROAPRINT / ROASITFIN `:356`, ROAPRODUCTIE `:326`. Grup C (fara
|
||||
@@ -1346,7 +1376,7 @@ din ~10 produse.
|
||||
acoperite pe ecran de `test_ui_fix_editabil_subtotal.prg` (11/11). O asertie s-a **intarit**
|
||||
(cazul B verifica acum numarul real de linii, nu `-1`), niciuna nu s-a slabit. Cifra veche
|
||||
`7 PASS / 3 FAIL` din acest fisier era stale — numara doar cele 10 asertii de la runda 2.
|
||||
Raport: `docs\cercetare\rec_datoria6_baza_regresie.md`. Diff: `docs\diff_datoria6_suite_regresie.patch`.
|
||||
Raport: `docs\cercetare\rec_datoria6_baza_regresie.md`. Diff: diff aplicat (sters).
|
||||
**Necomis.** Neprobat pe alta schema decat `MARIUSM_AUTO`.
|
||||
7. **REZOLVATA 08.08.2026 — se verifica pe ecran, cu formular vizibil.** Harness nou:
|
||||
`COMUN\utile\Teste\editare_factura\vfp_ui_harness.ps1` (formular vizibil off-screen, `PrintWindow`,
|
||||
@@ -1507,7 +1537,7 @@ din ~10 produse.
|
||||
`poDate.in_valuta = 1` cere in plus `zi_curs` si `id_valuta`, validate intern de dialog, iar calea
|
||||
**nu e testabila headless** (dialogul e modal, `Show(1)`) — verificarea trece prin
|
||||
`vfp_ui_harness.ps1`, cu `-SyncDir` explicit.
|
||||
**CORECTIE DE PREMISA, 09.08.2026** (`docs\handoff_decizia35_valuta_dialog.md`, verificat si de
|
||||
**CORECTIE DE PREMISA, 09.08.2026** (handoff intermediar (sters), verificat si de
|
||||
orchestrator pe cod): **`frm_articol_factura` nu citeste deloc `poDate.in_valuta` / `zi_curs` /
|
||||
`id_valuta`** — singurele aparitii din intervalul clasei sunt **comentate** (`ofacturare.vc2:2088`,
|
||||
`:2136`, ramura scoasa la v2.0.56). Ramura de valuta a dialogului e condusa integral de
|
||||
@@ -1801,29 +1831,29 @@ Sursa `PACK_FACTURARE` se exporta din `MARIUSM_AUTO` (`all_source`), conform
|
||||
| `plan_10` / `plan_11` / `plan_12` | amanate |
|
||||
| `verificare_vfacturi.sql` | harnessul de regresie pentru cele doua view-uri |
|
||||
| `plan_06_s4_proiectare.md` | proiectarea S4/S4b; C.1 rescrisa 08.08.2026, A.3 aliniata la decizia 19 |
|
||||
| `diff_s4_runda1_page3.patch` | **diff-ul S4 runda 1, de revizuit** (`omodificari.vc2` + `ofacturare_editare.prg`) |
|
||||
| diff aplicat (sters) | **diff-ul S4 runda 1, de revizuit** (`omodificari.vc2` + `ofacturare_editare.prg`) |
|
||||
| `cercetare\rec_s4_runda1.md` | raportul rundei 1: ce s-a implementat, ce s-a testat, ce NU e acoperit |
|
||||
| `cercetare\rec_review_ancorare_s4.md` | review-ul de ancorare a coloanelor (sursa deciziei 26) |
|
||||
| `cercetare\rec_gotop_tact_s4.md` | blocantul `Go Top In tact`, confirmat pe date (sursa deciziei 27) |
|
||||
| `cercetare\rec_view_articole_vanzare.md` | proiectarea `VVANZARI_ARTICOLE` + ce s-a respins |
|
||||
| `cercetare\ff_view_articole_vanzare.sql` | copia de lucru a scriptului (originalul e in `SCRIPTURI_CLAR`) |
|
||||
| `COMUN\docs\cercetare\rec_view_articole_vanzare.md` | proiectarea `VVANZARI_ARTICOLE` + ce s-a respins |
|
||||
| `COMUN\docs\cercetare\ff_view_articole_vanzare.sql` | copia de lucru a scriptului (originalul e in `SCRIPTURI_CLAR`) |
|
||||
| `cercetare\handoff_s4_runda1.md` | predarea agentului `s4-runda1`; detaliile blocajului „View Parameter" |
|
||||
| `cercetare\rec_watchdog_vfp.md`, `handoff_propr_custom.md` | watchdog-ul VFP si regula `*p:` pentru proprietati noi |
|
||||
| `COMUN\docs\cercetare\rec_watchdog_vfp.md`, handoff intermediar (sters) | watchdog-ul VFP si regula `*p:` pentru proprietati noi |
|
||||
| `cercetare\rec_editare_factura.md`, `rec_modific2024.md` | #6 |
|
||||
| `cercetare\rec_suma_act.md` | regula sumei din `ACT` pe tip de document (sursa lui C.1) |
|
||||
| `cercetare\rec_pozitionare_actactan.md` | de unde se citesc `id_set`/`id_fact`/`id_factd` (runda 4) |
|
||||
| `cercetare\rec_datoria6_baza_regresie.md` | realocarea de `cod` 1140888->1140895 si re-ancorarea suitelor pe descoperire |
|
||||
| `diff_datoria6_suite_regresie.patch` | diff-ul celor doua suite + `descopera_caz_test.prg` |
|
||||
| diff aplicat (sters) | diff-ul celor doua suite + `descopera_caz_test.prg` |
|
||||
| `cercetare\rec_cele_41_facturi.md` | cine sunt cele 41 de la decizia 9; `cod=1138989` = nota dublata |
|
||||
| `cercetare\rec_tva_vanzari.md`, `rec_pret_lazy.md` | #7 (fond) si #12 |
|
||||
| `cercetare\rec_integrari.md` | #10, #11, #12 |
|
||||
| `cercetare\rec_consumatori_vanzari.md` | inventarul celor ~16 cai `xmlefactura` (datoria 5) |
|
||||
| `cercetare\rec_s10_s12.md` | textul propus pentru `changelog_roaauto.txt` (datoria 3) |
|
||||
| `COMUN\docs\cercetare\rec_tva_vanzari.md`, `rec_pret_lazy.md` | #7 (fond) si #12 |
|
||||
| `COMUN\docs\cercetare\rec_integrari.md` | #10, #11, #12 |
|
||||
| `COMUN\docs\cercetare\rec_consumatori_vanzari.md` | inventarul celor ~16 cai `xmlefactura` (datoria 5) |
|
||||
| `COMUN\docs\cercetare\rec_s10_s12.md` | textul propus pentru `changelog_roaauto.txt` (datoria 3) |
|
||||
| `cercetare\rec_todos_done.md` | starea punctelor din `todos.txt` |
|
||||
| `cercetare\rec_s4_runda3b.md` | sub-blocul B: stergerea de linii (implementare + testare) |
|
||||
| `handoff_s4_runda3b_adaugare.md` | contractul `frm_articol_factura`/`poArticol`/`poDate`/`gnScadereStoc` pentru adaugarea de linii (neinceputa) |
|
||||
| `diff_s4_runda3b_linii.patch` | diff-ul stergerii de linii |
|
||||
| `cercetare\s10_curata_versiune.sql` | curatarea tabelei `VERSIUNE` (datoria 4) |
|
||||
| handoff intermediar (sters) | contractul `frm_articol_factura`/`poArticol`/`poDate`/`gnScadereStoc` pentru adaugarea de linii (neinceputa) |
|
||||
| diff aplicat (sters) | diff-ul stergerii de linii |
|
||||
| `COMUN\docs\cercetare\s10_curata_versiune.sql` | curatarea tabelei `VERSIUNE` (datoria 4) |
|
||||
|
||||
`docs\` **nu e urmarit nici de git, nici de SVN**, si `COMUN\utile\curatenie.ps1` l-ar sterge la
|
||||
curatenia dinainte de commit. Ce trebuie pastrat, se muta sau se comite.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Propunere S4b — actiunea explicita de sincronizare RUL <-> articole factura
|
||||
|
||||
Document de **proiectare**, nu implementare. Niciun `.vc2`/`.prg` nu a fost modificat. Cerinta
|
||||
sursa: `docs\plan_06_editare_factura.md:208-231`. Context: `docs\handoff_punct6_dupa_s5.md`
|
||||
(sectiunea „S4b — ce e facut si ce lipseste"), `docs\handoff_punct6_10082026_seara.md`.
|
||||
sursa: `docs\plan_06_editare_factura.md:208-231`. Context: handoff intermediar (sters)
|
||||
(sectiunea „S4b — ce e facut si ce lipseste"), handoff intermediar (sters).
|
||||
|
||||
## Corectie fata de predarea anterioara — nu e nevoie de cursor de instantaneu
|
||||
|
||||
@@ -200,7 +200,7 @@ actionat manual dupa ce utilizatorul a vazut divergenta.
|
||||
| **Total** | **~5-6.5 zile** |
|
||||
|
||||
Confirma caracterizarea din plan: „cea mai mare ramasa, nu blocheaza pe nimeni"
|
||||
(`docs\handoff_punct6_10082026_seara.md:120`).
|
||||
(handoff intermediar (sters)).
|
||||
|
||||
## Ce ramane deschis, de decis cu Marius inainte de implementare
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# S4b etapa 2 — butonul, dialogul si verificarea la salvare
|
||||
|
||||
Continuarea lui `docs\handoff_punct6_10082026_seara.md`, sectiunea „S4b etapa 2". Diff-ul complet:
|
||||
**`docs\diff_s4b_etapa2.patch`** (342 randuri adaugate, 0 sterse, un singur fisier atins:
|
||||
Continuarea lui handoff intermediar (sters), sectiunea „S4b etapa 2". Diff-ul complet:
|
||||
**diff aplicat (sters)** (342 randuri adaugate, 0 sterse, un singur fisier atins:
|
||||
`COMUN\clase\omodificari.vc2`).
|
||||
|
||||
**STARE: WRITE-BACK FACUT, NECOMIS.** `omodificari.vcx`/`.vct` sunt regenerate (11.08.2026 09:34),
|
||||
@@ -37,7 +37,7 @@ TabIndex 6 e liber in PAGE3 (folosite: 3, 4, 5, 20 — verificat).
|
||||
|
||||
## Ce am schimbat fata de patch-ul partial al agentului mort
|
||||
|
||||
Patch-ul din `diff_s4b_etapa2_partial.patch` era mai complet decat il descria predarea (avea si
|
||||
Patch-ul din diff aplicat (sters) era mai complet decat il descria predarea (avea si
|
||||
verificarea la salvare, in metoda corecta). Cinci corectii:
|
||||
|
||||
**1. Lipsea `cmdSincronizeazaArticole.Click`** — butonul exista, dar nu facea nimic. Adaugat, cu
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Review: diff_s5_grid_articole.patch (omodificari.vc2, frm_modific2024)
|
||||
# Review: diff aplicat (sters) (omodificari.vc2, frm_modific2024)
|
||||
|
||||
Status: GATA. Review read-only, fara editari de cod. Nicio tranzactie/proces deschis.
|
||||
|
||||
## Scop verificat
|
||||
|
||||
`docs/diff_s5_grid_articole.patch` pe `COMUN/clase/omodificari.vc2`:
|
||||
diff aplicat (sters) pe `COMUN/clase/omodificari.vc2`:
|
||||
- insereaza coloana de grid `cPretAchizitieArt` (legata de `tvd.pret_achizitie`) intre
|
||||
`cPretArt` (Column6) si fostul `cPretCuTvaArt` (Column7), renumeroteaza Column7..14 -> 8..15;
|
||||
- adauga campul `id_vanzare_set` in cursorul `tvd`;
|
||||
|
||||
Reference in New Issue
Block a user