Cercetarile si propunerile rundelor 4-6 pe editarea facturii emise. Starea rundei 6 si ce s-a stabilit intra in progres.md. Nou: docs/conventii_mediu_oracle.md - pe dev/test se lucreaza numai cu ROA_CENTRAL si schemele CONTAFIN_ORACLE si MARIUSM_AUTO; schema ACN nu se foloseste. Scripturile de pachet sunt necalificate, deci schema tinta o decide sirul de conectare, nu fisierul. roafacturare.pj2 regenerat de git_sync. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013gYCNE26G1G7UoGu2ju7aS
15 KiB
R6 - butonul "Modificare articol" din frm_facturi + explicatie TVA - diagnostic
Raspuns la cerinta: pe formularul de facturare frm_facturi (lista facturi/avize/proforme, NU
frm_modific2024), butonul care edita azi explicatie+taxcode sa expuna si "explicatie TVA",
cu sincronizare automata explicatie TVA -> taxcode. Fiecare afirmatie e VERIFICAT (citit din
sursa, fisier:linie) - nu apare nimic marcat NESTABILIT, tot ce s-a cerut s-a putut confirma din
cod.
A. Localizarea frm_facturi
Clasa frm_facturi (nu form .scx separat) - definita in
COMUN\clase\ofacturare_comun.vc2:1168:
DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
Lant de mostenire: frm_facturi -> _frmbase (_frm_base.vc2:7) -> _form (_baza.vc2:157) -> form.
Instantiat din roafacturare.prg (meniul principal), nu are .scx propriu - toata definitia e in
binarul ofacturare_comun.vcx.
B. Butonul "Modificare articol"
Obiect But_modifica2, definit in frm_facturi la ofacturare_comun.vc2:1436-1444:
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
*< END OBJECT: ClassLib="cmd_butoane.vcx" BaseClass="commandbutton" />
Caption e gol (e un buton cu picture, nu text); ToolTipText = "Modificare explicatie
articol". Clasa but_modifica (cmd_butoane.vc2:184-197) nu are Click propriu - mosteneste
buton.Click din _cmd_base.vc2:41-71, care e un dispatcher generic:
PROCEDURE Click
Local lcAction, lcCommand, lcListaParametri
lcAction = This.cAction
...
If Type('this.parent') = 'O' And Pemstatus(This.Parent,lcAction,5)
lcCommand = [this.Parent.] + lcAction + lcListaParametri
&lcCommand
Else
If Type('this.parent.PARENT') = 'O' And Pemstatus(This.Parent.Parent,lcAction,5)
lcCommand = [this.Parent.Parent.] + lcAction + lcListaParametri
&lcCommand
Else
If Pemstatus(Thisform,lcAction,5)
lcCommand = [thisform.] + lcAction + lcListaParametri
&lcCommand
Endif
Endif
Endif
ENDPROC
Cu caction = do_modifica_explicatie si parintele But_modifica2 fiind direct frm_facturi
(fara container intermediar cu aceeasi metoda), rezultatul e efectiv thisform.do_modifica_explicatie().
Corpul integral al metodei (ofacturare_comun.vc2:4642-4659):
PROCEDURE do_modifica_explicatie
If Reccount('crsDetalii') > 0
update_saft_taxtable()
Select crsDetalii
Scatter Name poRec Memo
poRec.explicatie = NVL(poRec.explicatie, ' ')
If poRec.sters = 0
ofrmmodificare = Createobject("frm_modifica_articol_factura")
ofrmmodificare.Show()
If gnButon = 1
Thisform.actualizeaza_grid2()
Endif
Endif
Endif
ENDPROC
C. Ce deschide butonul
Un formular modal separat: frm_modifica_articol_factura
(ofacturare_comun.vc2:5129-5253), clasa AS frm_termin_renunt OF "_frm_child.vcx" (dialog
copil standard, cu But_termin1/But_renunt1). Titlu: Lb_titlu_alb_b121.Caption = "Modifică explicație articol" (:5163).
Campuri editabile azi, cu ControlSource si linii:
| control | tip | ControlSource | label | linie |
|---|---|---|---|---|
Ed_tx_simplu1._edbase1 |
editbox | porec.explicatie |
"Explicație" (+ "( maxim N caractere )" adaugat in Init) |
:5213-5223 |
cbo_saft |
combobox | poRec.taxcode |
"Cod taxa" (lbSaft) |
:5185-5199 |
cbo_saft e legat direct pe poRec.taxcode (BoundColumn=4), cu:
RowSource = "Select taxname, tip, procent_taxa, taxcode From saft_taxtable where tva = 1 order by taxcode Into Cursor crsTaxTableX"
adica lista tuturor codurilor SAF-T (cursor local saft_taxtable, populat de
update_saft_taxtable() apelat inainte de deschidere) - nu exista azi nicio legatura cu
explicatia TVA; userul alege direct un taxcode dintr-o lista plata de coduri fiscale.
Niciun alt camp (cantitate, pret, articol, id_jtva_coloana) nu e pe acest dialog.
D. Cum se scrie inapoi - si confirmarea premisei "nu modifica valorile"
Salvare in inainte_de_do_termin (ofacturare_comun.vc2:5225-5233):
PROCEDURE inainte_de_do_termin
Local llReturn
If amessagebox("Doriti sa salvati modificarile?",4+32,"Confirmare salvare explicatie") = 6
lcSql = [begin pack_facturare.modifica_explicatie_articol(] + Alltrim(Str(poRec.id_vanzare_det)) + [,] + ;
['] + Nvl(Alltrim(OracleSpecialCharacters(poRec.explicatie)),'') + [',?gnIdUtil,?poRec.taxcode); end;]
llReturn = goExecutor.oExecuta(lcSql)
Else
llReturn = .F.
Endif
Return llReturn
ENDPROC
Scrierea e direct in Oracle, prin pack_facturare.modifica_explicatie_articol(id_vanzare_det, explicatie, id_util, taxcode). Cercetare anterioara deja confirmase corpul acestei proceduri
(docs\cercetare\rec_cale_vanzari_detalii.md:195-199, citat identic aici pentru trasabilitate):
UPDATE VANZARI_DETALII SET EXPLICATIE = V_EXPLICATIE, TAXCODE = V_TAXCODE
WHERE ID_VANZARE_DET = V_ID_VANZARE_DET
Confirmat: doar 2 coloane se scriu (explicatie, taxcode). Nu se ating cantitate, pret,
pret_cu_tva, proc_tvav, id_jtva_coloana si nu exista niciun apel de recalcul de totaluri
(gcs.vact_tot/vrul_tot, note contabile, rulaje) in acest flux - premisa utilizatorului
("campuri care nu modifica valorile") e corecta pentru starea de azi a acestor doua campuri.
E. "Explicatie TVA" ca data + sincronizarea cu taxcode - sablonul deja aplicat in frm_modific2024
Campul din baza este id_jtva_coloana (nu taxcode) - nomenclator vjtva_coloane
(id_jtva_coloana, denumire, cota_tva). taxcode e un cod SAF-T/e-Factura separat, derivat din
id_jtva_coloana + context (partener, data, tip TVA), nu ales direct de nomenclatorul de
explicatii.
Sablonul de sincronizare cerut de utilizator exista deja, aplicat in runda 5 pe
frm_modific2024 / pgfArticole.PAGE3.grdArticoleFactura (cursor tvd), documentat in
docs\raport_runda5_omodificari.md si docs\propunere_runda4_note_sincronizare_tva.md (sectiunea
5, "varianta B"). Cod citit direct din sursa curenta (COMUN\programe\ofacturare_editare.prg,
ArticoleNotaEditor.ModificaNomenclator, :1100-1108):
CASE m.lcCamp == 'id_jtva_coloana'
*!* cota vine din explicatia aleasa, ca la randul de nota; taxcode-ul SAF-T se recoreleaza dupa ea
REPLACE id_jtva_coloana WITH loCauta.id_jtva_coloana, ;
proc_tvav WITH (Nvl(loCauta.cota_tva, 0) + 100) / 100
This.oForm.UpdateExplicatieSAFTArt()
This.oForm.calculeaza_valori_articol()
UpdateExplicatieSAFTArt (omodificari.vc2:15049-15074) e "jumatatea taxcode" a sincronizarii -
deriva taxcode din id_jtva_coloana prin functia comuna GetTaxCodeIdPart:
PROCEDURE updateexplicatiesaftart
IF !m.gl406
RETURN
ENDIF
...
lnIdJtva = tvd.id_jtva_coloana
lnIdPart = Nvl(tAct.id_partc, tAct.id_partd)
...
lnTaxCode = GetTaxCodeIdPart(m.gnAn, m.gnLuna, m.ldDataAct, m.lnIdJtva, m.lnIdPart, m.llN50, m.llN100, m.llNeexigibil)
Replace taxcode With m.lnTaxCode In tvd
This.pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Refresh()
ENDPROC
Relatia exacta explicatie TVA -> taxcode: id_jtva_coloana (+ an/luna/data act/partener/steaguri
N50-N100/neexigibil) -> GetTaxCodeIdPart() -> taxcode. Nu e un Do Case simplu pe
id_jtva_coloana; GetTaxCodeIdPart (functie globala, COMUN\programe\oproceduri_comune.prg:6059-6125,
NEschimbata pentru aceasta cerere) incapsuleaza toata logica SAF-T 406.
Garda gl406: UpdateExplicatieSAFTArt (si perechile ei Rul/simplu) nu fac nimic daca
gl406 = .F. (COMUN\programe\oinit_optiuni.prg:524, flag global de optiuni). Adica sincronizarea
taxcode <- explicatie TVA e activa doar cand raportarea SAF-T 406 e activata pentru firma curenta -
de verificat la implementare daca frm_facturi are acces la acelasi gl406.
F. Cum se deschide azi nomenclatorul de explicatie TVA
Doua rutine globale, refolosibile din orice formular (nu legate de contextul lui
frm_modific2024):
caut_explicatie_tva(tnIdJtva, tnPornire, tlDesktop, tlTipEx, tnCotaTva)(COMUN\programe\ocautare.prg:3174-3238) - deschide dialogul de cautare peselect id_jtva_coloana, denumire, cota_tva from vjtva_coloane, filtrat implicit peid_jtva_coloana > 0(candtlTipExe gol) si, dacatnCotaTva > 0, suplimentar pecota_tva = tnCotaTva(:3218-3220, filtru adaugat tot in runda asta). Returneaza obiectulloCautadincauta_alfa(are.id_jtva_coloana,.denumire,.cota_tva).GetTaxCodeIdPart(an, luna, data_act, id_jtva, id_part, n50, n100, neexigibil)(COMUN\programe\oproceduri_comune.prg:6059-6125) - returneazataxcode-ul SAF-T.
Apelul concret cu filtrul de cota (ArticoleNotaEditor.CautaExplicatieTva,
ofacturare_editare.prg:1142-1147):
PROCEDURE CautaExplicatieTva
LOCAL lnCotaFiltru
lnCotaFiltru = Round((Nvl(tvd.proc_tvav, 0) - 1) * 100, 2)
RETURN caut_explicatie_tva(Nvl(tvd.id_jtva_coloana, -1), , , , m.lnCotaFiltru)
ENDPROC
Ambele functii sunt .prg-uri globale incarcate ADDITIVE la pornirea aplicatiei (deci apelabile
si din frm_facturi) - nu cer nicio extragere de cod, doar apel direct.
G. frm_facturi deja afiseaza explicatia TVA - doar needitabil
Grila grid_detalii din frm_facturi are deja doua coloane needitabile pentru asta
(ofacturare_comun.vc2:1679-1687):
Column24.ControlSource = "jtva_coloana", ;
Column24.Name = "cExplicatieTVA", ;
Column24.ReadOnly = .T., ;
...
Column25.ControlSource = "jtva_coloana_ex", ;
Column25.Name = "cExplicatieTVAEx", ;
Column25.ReadOnly = .T., ;
cu header-ele "Explicatie TVA" / "Explicatie TVA 2" (:1920-1946). jtva_coloana/jtva_coloana_ex
sunt (dupa tiparul din restul fisierului, ex. :2107-2109) denumirile derivate din
jtva_coloane/jtva_coloane_explicatii, nu ID-uri brute - afisare, nu editare. Nu exista alt
traseu in frm_facturi unde utilizatorul alege interactiv o explicatie TVA (nu la adaugare de
linie - acest formular nu are adaugare de linii, e formular de listare/editare metadate, nu de
compunere a facturii).
Concluzie G: campul exista deja ca read-only in grid; nu trebuie adaugata coloana in grid, doar expunerea editabila in dialogul de modificare (punctul C).
H. Riscul - taxcode NU e neutru daca se copiaza tot sablonul
Rezultat cheie, marcat apasat: sablonul din E (runda 5, frm_modific2024) nu e neutru
valoric. La alegerea unei explicatii TVA, pe langa taxcode, se rescrie explicit proc_tvav
(cota TVA a liniei) si se cheama calculeaza_valori_articol(), care recalculeaza valoarea
liniei si bara de totaluri (docs\raport_runda5_omodificari.md, linia 41 din tabelul de apeluri
ActualizeazaBaraTotaluri, si citatul de la punctul E de mai sus). Adica in acel context,
"explicatie TVA" schimba valorile documentului daca explicatia aleasa are alta cota decat cea
curenta - filtrul de cota din caut_explicatie_tva (punctul F) doar restrange lista, nu blocheaza
o alegere cu cota diferita daca userul o cauta explicit sau daca linia are proc_tvav gol/0
(caz in care filtrul nu se aplica deloc, ocautare.prg:3218: If ... tnCotaTva > 0).
Pentru taxcode insusi, in fluxul actual: taxcode nu e citit nicaieri in calculul
totalurilor VFP - cautare in COMUN\programe\ofacturare_comun.prg si in schema campurilor din
ofacturare_comun.vc2 (punctul D) nu arata taxcode folosit in nicio expresie de valctva,
valtva, total_cu_tva sau similar; acelea se calculeaza din proc_tvav/pret/cantitate,
coloane distincte. taxcode e strict o eticheta de raportare SAF-T/e-Factura, stocata pe linie.
Deci verdictul depinde strict de ce se implementeaza:
- Daca se reface
pack_facturare.modifica_explicatie_articolsa scrie DOARid_jtva_coloana(nou parametru) +taxcodederivat, FARA sa atingaproc_tvav- si daca dialogul defrm_facturifolosestecaut_explicatie_tvacu filtrul de cota calculat dinpoRec.proc_tvavcurent (ca sa nu se poata alege o explicatie de alta cota) - atunci operatia ramane neutra valoric, exact ce cere utilizatorul. Aceasta e o varianta redusa a sablonului din E, nu o copiere 1:1. - Daca se copiaza sablonul din E exact cum e (inclusiv rescrierea
proc_tvav+ recalcul) - operatia NU mai e neutra: ar schimba cota TVA si valorile unei facturi deja emise, fara mecanismul de recalcul de totaluri/note/rulaje care exista infrm_modific2024(acolo editarea e pe cursoare locale, salvata printr-un flux dedicat de recalcul;frm_facturinu are asa ceva - e un UPDATE punctual pe o singura linie, deja emisa). Risc fiscal si de coerenta (SAF-T/e-Factura ar raporta untaxcodecare nu mai corespunde cuproc_tvav/totalurile deja emise, sau invers, daca doar taxcode se sincronizeaza fara proc_tvav).
Recomandare de proiectare (schita, fara cod aplicat): varianta redusa de mai sus -
dialog frm_modifica_articol_factura capata un al treilea camp (combo pe explicatie TVA,
caut_explicatie_tva filtrat pe cota curenta a liniei, ca in CautaExplicatieTva), la alegere
se recalculeaza doar taxcode local (GetTaxCodeIdPart, acelasi apel ca UpdateExplicatieSAFTArt
dar fara REPLACE proc_tvav), iar la salvare pack_facturare.modifica_explicatie_articol capata
un parametru nou id_jtva_coloana (schimbare PL/SQL, in afara acestui repo VFP - de coordonat
separat) pe langa explicatie/taxcode existente. Cod nou estimat: mic pe partea VFP (~30-40
linii: un combo nou + un handler de alegere + un parametru in apelul SQL), dar cere schimbare de
pachet Oracle (pack_facturare.modifica_explicatie_articol) care nu exista in acest working
copy si trebuie facuta/aprobata separat in DATABASE.
Rezumat surse
| ce | fisier:linie |
|---|---|
clasa frm_facturi |
COMUN\clase\ofacturare_comun.vc2:1168 |
butonul But_modifica2 |
COMUN\clase\ofacturare_comun.vc2:1436-1444 |
dispatcher buton.Click |
COMUN\clase\_cmd_base.vc2:41-71 |
do_modifica_explicatie |
COMUN\clase\ofacturare_comun.vc2:4642-4659 |
dialog frm_modifica_articol_factura |
COMUN\clase\ofacturare_comun.vc2:5129-5253 |
salvare (inainte_de_do_termin) |
COMUN\clase\ofacturare_comun.vc2:5225-5233 |
grid cExplicatieTVA/cExplicatieTVAEx (read-only) |
COMUN\clase\ofacturare_comun.vc2:1679-1687, :1920-1946 |
| sablon sincronizare (runda 5) | COMUN\programe\ofacturare_editare.prg:1100-1147, COMUN\clase\omodificari.vc2:15049-15074 |
caut_explicatie_tva |
COMUN\programe\ocautare.prg:3174-3238 |
GetTaxCodeIdPart |
COMUN\programe\oproceduri_comune.prg:6059-6125 |
gl406 |
COMUN\programe\oinit_optiuni.prg:524 |
| procedura Oracle (citata din cercetare anterioara) | docs\cercetare\rec_cale_vanzari_detalii.md:195-199 |