Compare commits

...

3 Commits

Author SHA1 Message Date
13b4f65723 sync SVN r18004/r18007: #6 editare factura emisa - pagina de articole
ofacturare_editare.prg (nou): helpere comune - garda eFactura, cursoarele
notei si ale rulajelor, randul de vanzare corespunzator notei si liniile de
articole citite din view-ul VVANZARI_ARTICOLE.

omodificari.vc2 (frm_modific2024): pagina noua de articole ale facturii,
deocamdata doar afisare. Apare numai cand ofacturare_editare.prg e
inregistrat si documentul are rand in VANZARI; in ROACONT si ROAGEST, unde
fisierul nu e incarcat, pagina lipseste si registrul jurnal ramane neatins.
Randul de vanzare al notei se cauta pe toate tripletele distincte (nract,
serie_act, dataact) din nota, pentru ca primul rand poate fi o incasare.

ofacturare_comun.vc2 (frm_facturi): do_editare_factura si butonul aferent,
dupa modelul lui do_sterge, cu garzile de luna inchisa, luna curenta,
document sters, referinte si eFactura.

docs: comentariile se scriu strict necesar, si in cod si in scripturile de
migrare - fara referinte la planuri, stories, decizii sau erori, istoricul
doar in antetul fisierului. Plus regula zero (predarea contextului),
capcanele de la testarea headless si completari pe fluxul text -> binar.

utile/Teste: suita de regresie pentru editarea facturii si harness-ul
watchdog (nu sunt in SVN, unde utile/Teste e ignorat). .gitignore ignora si
capturile PNG si watchdog_out/, ramase din rulari.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-08 16:47:24 +03:00
c5b0ce3a25 teste: suita headless pentru pretul cu TVA pe linie (ROAFACTURARE 2.11.14)
Patru niveluri, 38 de asertii, toate PASS pe binarul din SVN r17998:

- test_pret_cu_tva_dialog        - dialogul frm_articol_factura izolat (14)
- test_pret_cu_tva_nivel2        - factura in curs de compunere, adaugare si ambele cai de
                                   modificare (buton si dublu-clic), Renunta bit-identic (7)
- test_pret_cu_tva_nivel2_retur  - plafonul de cantitate recalculat, pe ramura de retur (4)
- test_pret_cu_tva_nivel3_gestiuni - ramura gestionabila, cu Oracle mockuit la granita prin
                                   dummyexecutor: preselectia gestiunii, excluderea liniei din
                                   propriul stoc, plafonul pe lot, multi-selectia (13)

Nivelurile 2 si 3 conduc dialoguri modale deschise din codul aplicatiei (Show(1) hardcodat),
prin Timer pe _SCREEN si detectie in _SCREEN.Forms - mecanismul e descris in
docs/testare-ui-vfp.md.

Suita nu e in SVN (utile/Teste e ignorat acolo), deci traieste doar in git.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-08 00:23:15 +03:00
f88b2b9a5b sync SVN r18000: todos - puncte marcate DONE si doua puncte noi
Marcate DONE: 2, 3, 4, 5, 8, 9. Punctul 13 precizeaza formularul unificat
frm_facturare_articole2. Noi: 16 (focus si renumerotare act la revenirea din formularul
de curs valutar) si 17 (eroare ORA neprietenoasa cand id_venchelt e null la finalizarea
facturii).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-08 00:23:01 +03:00
28 changed files with 5546 additions and 28 deletions

2
.gitignore vendored
View File

@@ -133,3 +133,5 @@ bash.exe.stackdump
utile/Teste/**/screenshots*/ utile/Teste/**/screenshots*/
utile/Teste/**/uisync*/ utile/Teste/**/uisync*/
utile/Teste/**/*_log.txt utile/Teste/**/*_log.txt
utile/Teste/**/watchdog_out/
utile/Teste/**/*_dialog*.png

View File

@@ -150,7 +150,7 @@ DEFINE CLASS frm_borderou_facturi AS _frmbase OF "_frm_base.vcx"
ADD OBJECT 'Cmd_executa1' AS cmd_executa WITH ; ADD OBJECT 'Cmd_executa1' AS cmd_executa WITH ;
Anchor = 6, ; Anchor = 6, ;
Caption = "Marcheaz<61> \<trimis", ; Caption = "Marcheaz<61> \<trimis", ;
ForeColor = 0,128,0, ; ForeColor = 0,128,0, ;
Height = 27, ; Height = 27, ;
Left = 140, ; Left = 140, ;
@@ -1334,8 +1334,10 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
*< OBJECTDATA: ObjPath="But_attach1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="But_attach1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="But_listare1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="But_listare1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="But_editare1" UniqueID="" Timestamp="" />
*<DefinedPropArrayMethod> *<DefinedPropArrayMethod>
*m: do_editare_factura
*m: do_listare_cc *m: do_listare_cc
*m: do_listare_centr *m: do_listare_centr
*m: do_listare_document *m: do_listare_document
@@ -1350,7 +1352,7 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
*<PropValue> *<PropValue>
BorderStyle = 1 BorderStyle = 1
cbuton2 = but_listare1;but_listare2;But_listare3 cbuton2 = but_listare1;but_listare2;But_listare3
cbuton3 = but_modifica1;but_modifica2 cbuton3 = but_modifica1;but_modifica2;But_editare1
cfiltru_initial = cfiltru_initial =
cgridsortlist = grid_facturi,grid_detalii cgridsortlist = grid_facturi,grid_detalii
DoCreate = .T. DoCreate = .T.
@@ -1410,6 +1412,17 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
Visible = .F. Visible = .F.
*< END OBJECT: ClassLib="cmd_butoane.vcx" BaseClass="commandbutton" /> *< END OBJECT: ClassLib="cmd_butoane.vcx" BaseClass="commandbutton" />
ADD OBJECT 'But_editare1' AS but_modifica WITH ;
Anchor = 12, ;
caction = do_editare_factura, ;
Caption = "", ;
Left = 650, ;
Name = "But_editare1", ;
TabIndex = 29, ;
ToolTipText = "Editare factura (articole, cantitati, preturi)", ;
Top = 341
*< END OBJECT: ClassLib="cmd_butoane.vcx" BaseClass="commandbutton" />
ADD OBJECT 'But_listare1' AS but_listare WITH ; ADD OBJECT 'But_listare1' AS but_listare WITH ;
Anchor = 8, ; Anchor = 8, ;
Left = 698, ; Left = 698, ;
@@ -3471,7 +3484,7 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
Anchor = 12, ; Anchor = 12, ;
AutoSize = .T., ; AutoSize = .T., ;
BackStyle = 0, ; BackStyle = 0, ;
Caption = "Total <20>n valuta", ; Caption = "Total <20>n valuta", ;
FontSize = 10, ; FontSize = 10, ;
Height = 18, ; Height = 18, ;
Left = 311, ; Left = 311, ;
@@ -3711,6 +3724,150 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx"
This.do_cauta() This.do_cauta()
ENDPROC ENDPROC
PROCEDURE do_editare_factura
If !This.lactiv3
Return
Endif
If Reccount('crsfacturi') = 0
amessagebox("Nu exista inregistrari pentru editare!",0+48,"Atentie")
Return
Endif
If glLunaInchisa
Return
Endif
Local lnSters, llEProforma, lnIdSet, lnIdFactD, lnSucces, Omodif, llGasitRand
Private pnAn, pnLuna, lnCod, lnIdFact, lnIdVanzare
Store 0 To pnAn, pnLuna, lnCod, lnIdFact, lnIdSet, lnIdFactD, lnIdVanzare
Select crsfacturi
lnIdVanzare = id_vanzare
lnCod = cod
pnAn = Year(data_act)
pnLuna = Month(data_act)
lnSters = sters
lnIdFact = id_fact
llEProforma = (eproforma = 1)
If lnSters = 1
amessagebox("Acest document este deja sters!",0+48,"Atentie")
Return
Endif
If llEProforma
amessagebox("Proformele nu pot fi editate pe aceasta cale!",0+48,"Atentie")
Return
Endif
If (pnAn * 12) + pnLuna <> (gnAn * 12) + gnLuna
amessagebox('Nu puteti edita decat inregistrari din luna curenta!',0,'Atentie!')
Return
Endif
*** verificare restrictie editare documente cu referinte (incasari/plati)
If ReferinteDocumenteNota(pnAn, pnLuna, lnCod) && odocumente.prg
amessagebox("Documentul are referinte (incasari/plati). Nu poate fi editat.", 0+48,"Editare")
Return
Endif
*** verificare restrictie editare facturi trimise in eFactura
If EsteInEFactura(lnIdFact) && ofacturare_editare.prg
amessagebox("Documentul a fost trimis in eFactura. Nu poate fi editat.", 0+48,"Editare")
Return
Endif
If IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.) && ofacturare_editare.prg
If Reccount('actactan') = 0
amessagebox("Nu exista nota contabila pentru aceasta factura.",0+48,"Atentie")
Else
Select actactan
llGasitRand = .F.
If lnIdFact > 0
Locate For Nvl(id_fact, 0) = lnIdFact
llGasitRand = Found()
Endif
If !llGasitRand
*** rezerva: nota nu contine id_fact-ul din vanzari (avize, transferuri, documente vechi)
Go Top
lnIdFact = id_fact
Endif
lnIdSet = id_set
lnIdFactD = id_factd
Select a.*, Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
Select tact
Omodif = Createobject([frm_modific2024], lnIdSet)
Omodif.Show()
If buton = 1
If Thisform.do_deschide_tranzactie()
Select actactan
lnSucces = OSCRIE_IN_FISIERE(2,.T.,.T.)
If lnSucces > 0
If Used('actactan')
Use In actactan
Endif
Select tact
Replace id_jtva_coloana With Null, proc_tva With 0 For cu_Tva = 0
Select * From tact Into Cursor actactan Readwrite
Replace All id_util With gnIdUtil, sters With 0
If Used('rul_temp')
Use In rul_temp
Endif
Select * From trul Into Cursor RUL_TEMP Readwrite
Replace All id_util With gnIdUtil, sters With 0
If Used('rul_temp_obinv')
Use In rul_temp_obinv
Endif
Select * From trul_obinv Into Cursor RUL_TEMP_OBINV Readwrite
Replace All id_util With gnIdUtil, sters With 0
lnSucces = OSCRIE_IN_FISIERE(0,.T.,.T.)
Endif
If lnSucces > 0
lcSql = [begin pack_contafin.finalizeaza_modificare_nota(?pnLuna,?pnAn,Null,] + Alltrim(Str(lnIdSet)) + [,] + ;
Alltrim(Str(lnCod)) + [,] + Alltrim(Str(lnIdFact)) + [,] + Alltrim(Str(lnIdFactD)) + [,?gnIdUtil); end;]
lnSucces = Iif(goExecutor.oExecuta(lcSql),1,-1)
Endif
If Thisform.do_inchide_tranzactie(Iif(lnSucces<0,2,1))
If lnSucces > 0
Thisform.do_cauta()
Endif
Endif
Endif
Endif
Endif
If Used('actactan')
Use In actactan
Endif
If Used('tact')
Use In tact
Endif
If Used('rul_temp')
Use In rul_temp
Endif
If Used('trul')
Use In trul
Endif
If Used('rul_temp_obinv')
Use In rul_temp_obinv
Endif
If Used('trul_obinv')
Use In trul_obinv
Endif
Endif
Select crsfacturi
Locate For id_vanzare = lnIdVanzare
If !Found()
Go Top
Endif
ENDPROC
PROCEDURE do_listare PROCEDURE do_listare
*!* 26.11.2019 *!* 26.11.2019
*!* marius.mutu *!* marius.mutu
@@ -4988,7 +5145,7 @@ DEFINE CLASS frm_modifica_articol_factura AS frm_termin_renunt OF "_frm_child.vc
_shape2.Top = 0 _shape2.Top = 0
_shape2.Width = 64 _shape2.Width = 64
_shape2.ZOrderSet = 2 _shape2.ZOrderSet = 2
Lb_titlu_alb_b121.Caption = "Modific<69> explica<63>ie articol" Lb_titlu_alb_b121.Caption = "Modific<69> explica<63>ie articol"
Lb_titlu_alb_b121.Name = "Lb_titlu_alb_b121" Lb_titlu_alb_b121.Name = "Lb_titlu_alb_b121"
Lb_titlu_alb_b121.TabIndex = 5 Lb_titlu_alb_b121.TabIndex = 5
Lb_titlu_alb_b121.ZOrderSet = 3 Lb_titlu_alb_b121.ZOrderSet = 3
@@ -5046,7 +5203,7 @@ DEFINE CLASS frm_modifica_articol_factura AS frm_termin_renunt OF "_frm_child.vc
_edbase1.Name = "_edbase1", ; _edbase1.Name = "_edbase1", ;
_edbase1.Top = 23, ; _edbase1.Top = 23, ;
_edbase1.Width = 325, ; _edbase1.Width = 325, ;
_lbbase1.Caption = "Explica<63>ie", ; _lbbase1.Caption = "Explica<63>ie", ;
_lbbase1.Name = "_lbbase1" _lbbase1.Name = "_lbbase1"
*< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" /> *< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" />
@@ -5280,7 +5437,7 @@ DEFINE CLASS frm_modifica_factura AS frm_termin_renunt OF "_frm_child.vcx"
Text_simplu1.Name = "Text_simplu1", ; Text_simplu1.Name = "Text_simplu1", ;
Text_simplu1.Top = 3, ; Text_simplu1.Top = 3, ;
Text_simplu1.Width = 177, ; Text_simplu1.Width = 177, ;
Lb_simplu1.Caption = "Data <20>i ora expedierii", ; Lb_simplu1.Caption = "Data <20>i ora expedierii", ;
Lb_simplu1.Name = "Lb_simplu1" Lb_simplu1.Name = "Lb_simplu1"
*< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" /> *< END OBJECT: ClassLib="lb_tx.vcx" BaseClass="container" />
@@ -5330,7 +5487,7 @@ DEFINE CLASS frm_modifica_factura AS frm_termin_renunt OF "_frm_child.vcx"
Top = 128, ; Top = 128, ;
ZOrderSet = 9, ; ZOrderSet = 9, ;
img_cautare.Name = "img_cautare", ; img_cautare.Name = "img_cautare", ;
clb_tx_cautare.Lb_simplu1.Caption = "Ma<4D>ina", ; clb_tx_cautare.Lb_simplu1.Caption = "Ma<4D>ina", ;
clb_tx_cautare.Lb_simplu1.Name = "Lb_simplu1", ; clb_tx_cautare.Lb_simplu1.Name = "Lb_simplu1", ;
clb_tx_cautare.Name = "clb_tx_cautare", ; clb_tx_cautare.Name = "clb_tx_cautare", ;
clb_tx_cautare.Text_simplu1.Left = 133, ; clb_tx_cautare.Text_simplu1.Left = 133, ;
@@ -6820,7 +6977,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx"
Anchor = 12, ; Anchor = 12, ;
AutoSize = .T., ; AutoSize = .T., ;
BackStyle = 0, ; BackStyle = 0, ;
Caption = "Total <20>n valuta", ; Caption = "Total <20>n valuta", ;
FontSize = 10, ; FontSize = 10, ;
Height = 18, ; Height = 18, ;
Left = 311, ; Left = 311, ;
@@ -6852,7 +7009,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx"
OPTION1.Top = 5, ; OPTION1.Top = 5, ;
OPTION1.Value = 1, ; OPTION1.Value = 1, ;
OPTION2.AutoSize = .T., ; OPTION2.AutoSize = .T., ;
OPTION2.Caption = "<22>n valuta", ; OPTION2.Caption = "<22>n valuta", ;
OPTION2.FontCharSet = 238, ; OPTION2.FontCharSet = 238, ;
OPTION2.FontSize = 10, ; OPTION2.FontSize = 10, ;
OPTION2.Left = 55, ; OPTION2.Left = 55, ;
@@ -6860,7 +7017,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx"
OPTION2.Top = 5, ; OPTION2.Top = 5, ;
Option3.AutoSize = .T., ; Option3.AutoSize = .T., ;
Option3.BackStyle = 0, ; Option3.BackStyle = 0, ;
Option3.Caption = "<22>n RON", ; Option3.Caption = "<22>n RON", ;
Option3.FontCharSet = 238, ; Option3.FontCharSet = 238, ;
Option3.FontSize = 10, ; Option3.FontSize = 10, ;
Option3.Height = 18, ; Option3.Height = 18, ;
@@ -6891,7 +7048,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx"
OPTION1.Top = 5, ; OPTION1.Top = 5, ;
OPTION1.Value = 0, ; OPTION1.Value = 0, ;
OPTION2.AutoSize = .T., ; OPTION2.AutoSize = .T., ;
OPTION2.Caption = "<22>terse", ; OPTION2.Caption = "<22>terse", ;
OPTION2.FontCharSet = 238, ; OPTION2.FontCharSet = 238, ;
OPTION2.FontSize = 10, ; OPTION2.FontSize = 10, ;
OPTION2.ForeColor = 255,0,0, ; OPTION2.ForeColor = 255,0,0, ;
@@ -6900,7 +7057,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx"
OPTION2.Top = 5, ; OPTION2.Top = 5, ;
Option3.AutoSize = .T., ; Option3.AutoSize = .T., ;
Option3.BackStyle = 0, ; Option3.BackStyle = 0, ;
Option3.Caption = "Ne<4E>terse", ; Option3.Caption = "Ne<4E>terse", ;
Option3.FontCharSet = 238, ; Option3.FontCharSet = 238, ;
Option3.FontSize = 10, ; Option3.FontSize = 10, ;
Option3.Height = 18, ; Option3.Height = 18, ;

View File

@@ -6628,6 +6628,33 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarecTVA.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarecTVA.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevTVA.Header1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevTVA.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevTVA.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevTVA.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cDenumireArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cDenumireArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cCodmatArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cCodmatArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cLotArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cLotArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cCantitateArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cCantitateArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cPretArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cPretArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cPretCuTvaArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cPretCuTvaArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cDiscountUnitarArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cDiscountUnitarArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cGestiuneArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cGestiuneArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cValutaArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cValutaArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cExplicatieArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cExplicatieArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Header1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevcTVA.cvaloarevcTVA" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevcTVA.cvaloarevcTVA" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevcTVA.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE2.grdRulajeObinv.cvaloarevcTVA.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="Grid1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Grid1" UniqueID="" Timestamp="" />
@@ -6774,18 +6801,21 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*p: ccontrol *p: ccontrol
*p: cpaymentcode *p: cpaymentcode
*p: fel_compensare *p: fel_compensare
*p: larearticolevanzari
*p: lavertizatexigibilizare *p: lavertizatexigibilizare
*p: leditare *p: leditare
*p: lmodificare *p: lmodificare
*p: lnotanoua *p: lnotanoua
*p: lverificare *p: lverificare
*p: lvizualizare *p: lvizualizare
*p: nidvanzare
*p: nid_set *p: nid_set
*p: nnnirvechi *p: nnnirvechi
*p: noldsuma && Valoarea la intrarea in campul "Suma" *p: noldsuma && Valoarea la intrarea in campul "Suma"
*p: nprimadata *p: nprimadata
*p: nsuma && Total suma inregistrari *p: nsuma && Total suma inregistrari
*p: ntaxcode *p: ntaxcode
*p: ntipvanzare
*p: obackupxml *p: obackupxml
*p: oldvalue *p: oldvalue
*p: oset *p: oset
@@ -6805,6 +6835,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
DoCreate = .T. DoCreate = .T.
FontCharSet = 238 FontCharSet = 238
Height = 508 Height = 508
larearticolevanzari = .F.
lavertizatexigibilizare = .F. lavertizatexigibilizare = .F.
leditare = .F. leditare = .F.
lmodificare = .F. lmodificare = .F.
@@ -6812,12 +6843,14 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
lverificare = .F. lverificare = .F.
lvizualizare = .F. lvizualizare = .F.
Name = "frm_modific2024" Name = "frm_modific2024"
nidvanzare = 0
nid_set = 0 nid_set = 0
nnnirvechi = 0 nnnirvechi = 0
noldsuma = 0 noldsuma = 0
nprimadata = 0 nprimadata = 0
nsuma = 0 nsuma = 0
ntaxcode = 0 ntaxcode = 0
ntipvanzare = 0
obackupxml = NULL obackupxml = NULL
oldvalue = oldvalue =
oset = NULL oset = NULL
@@ -8630,6 +8663,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Height = 142, ; Height = 142, ;
Left = 5, ; Left = 5, ;
Name = "pgfArticole", ; Name = "pgfArticole", ;
PageCount = 3, ;
Top = 361, ; Top = 361, ;
Width = 764, ; Width = 764, ;
ZOrderSet = 0, ; ZOrderSet = 0, ;
@@ -8638,7 +8672,10 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
PAGE1.Name = "PAGE1", ; PAGE1.Name = "PAGE1", ;
PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)", ; PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)", ;
PAGE2.ForeColor = 0,128,64, ; PAGE2.ForeColor = 0,128,64, ;
PAGE2.Name = "PAGE2" PAGE2.Name = "PAGE2", ;
PAGE3.Caption = "Articole factura", ;
PAGE3.ForeColor = 128,0,128, ;
PAGE3.Name = "PAGE3"
*< END OBJECT: ClassLib="_baza.vcx" BaseClass="pageframe" /> *< END OBJECT: ClassLib="_baza.vcx" BaseClass="pageframe" />
ADD OBJECT 'pgfArticole.PAGE1._grdfooter1' AS _grdfooter WITH ; ADD OBJECT 'pgfArticole.PAGE1._grdfooter1' AS _grdfooter WITH ;
@@ -12217,6 +12254,374 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
SelectedBackColor = 100,185,255 SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" /> *< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura' AS _grdrow WITH ;
Anchor = 15, ;
ColumnCount = 13, ;
DeleteMark = .F., ;
FontSize = 10, ;
GridLineColor = 128,128,128, ;
HeaderHeight = 35, ;
Height = 107, ;
Left = 0, ;
Name = "grdArticoleFactura", ;
ReadOnly = .T., ;
RecordSource = "tvd", ;
RowHeight = 19, ;
TabIndex = 4, ;
Tag = "RESIZABLE", ;
Top = 0, ;
Width = 759, ;
ZOrderSet = 1, ;
Column1.ControlSource = "tvd.denumire", ;
Column1.FontName = "Arial", ;
Column1.FontSize = 10, ;
Column1.Name = "cDenumireArt", ;
Column1.Width = 170, ;
Column2.ControlSource = "tvd.codmat", ;
Column2.FontName = "Arial", ;
Column2.FontSize = 10, ;
Column2.Name = "cCodmatArt", ;
Column2.Width = 90, ;
Column3.ControlSource = "tvd.serie", ;
Column3.FontName = "Arial", ;
Column3.FontSize = 10, ;
Column3.Name = "cSerieArt", ;
Column3.Width = 70, ;
Column4.ControlSource = "tvd.lot", ;
Column4.FontName = "Arial", ;
Column4.FontSize = 10, ;
Column4.Name = "cLotArt", ;
Column4.Width = 60, ;
Column5.ControlSource = "tvd.cantitate", ;
Column5.FontName = "Arial", ;
Column5.FontSize = 10, ;
Column5.Format = "R", ;
Column5.InputMask = (get_mask(12,gnPCANT)), ;
Column5.Name = "cCantitateArt", ;
Column5.Width = 70, ;
Column6.ControlSource = "tvd.pret", ;
Column6.FontName = "Arial", ;
Column6.FontSize = 10, ;
Column6.Format = "R", ;
Column6.InputMask = (get_mask(12,gnPPRET)), ;
Column6.Name = "cPretArt", ;
Column6.Width = 70, ;
Column7.ControlSource = "tvd.pret_cu_tva", ;
Column7.FontName = "Arial", ;
Column7.FontSize = 10, ;
Column7.Format = "R", ;
Column7.InputMask = (get_mask(12,gnPPRET)), ;
Column7.Name = "cPretCuTvaArt", ;
Column7.Width = 80, ;
Column8.ControlSource = "tvd.proc_tvav", ;
Column8.FontName = "Arial", ;
Column8.FontSize = 10, ;
Column8.Format = "R", ;
Column8.InputMask = "9.99", ;
Column8.Name = "cProcTvavArt", ;
Column8.Width = 55, ;
Column9.ControlSource = "tvd.discount_unitar", ;
Column9.FontName = "Arial", ;
Column9.FontSize = 10, ;
Column9.Format = "R", ;
Column9.InputMask = (get_mask(12,gnPPRET)), ;
Column9.Name = "cDiscountUnitarArt", ;
Column9.Width = 90, ;
Column10.ControlSource = "tvd.nume_gestiune", ;
Column10.FontName = "Arial", ;
Column10.FontSize = 10, ;
Column10.Name = "cGestiuneArt", ;
Column10.Width = 90, ;
Column11.ControlSource = "tvd.nume_val", ;
Column11.FontName = "Arial", ;
Column11.FontSize = 10, ;
Column11.Name = "cValutaArt", ;
Column11.Width = 60, ;
Column12.ControlSource = "tvd.explicatie", ;
Column12.FontName = "Arial", ;
Column12.FontSize = 10, ;
Column12.Name = "cExplicatieArt", ;
Column12.Width = 150, ;
Column13.ControlSource = "tvd.taxcode", ;
Column13.FontName = "Arial", ;
Column13.FontSize = 10, ;
Column13.Name = "cTaxcodeArt", ;
Column13.Width = 60
*< END OBJECT: ClassLib="_grd_base.vcx" BaseClass="grid" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cCantitateArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Cantitate", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cCantitateArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cCodmatArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Cod material", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cCodmatArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cDenumireArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Articol", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cDenumireArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cDiscountUnitarArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Discount unitar", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cDiscountUnitarArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cExplicatieArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Explicatie", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cExplicatieArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cGestiuneArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Gestiune", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cGestiuneArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cLotArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Lot", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cLotArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cPretArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Pret", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cPretArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cPretCuTvaArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Pret cu TVA", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cPretCuTvaArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "TVA %", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cProcTvavArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Serie", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cSerieArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Taxcode", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cTaxcodeArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cValutaArt.Header1' AS header WITH ;
Alignment = 2, ;
Caption = "Valuta", ;
FontName = "Arial", ;
FontSize = 10, ;
Name = "Header1", ;
WordWrap = .T.
*< END OBJECT: BaseClass="header" />
ADD OBJECT 'pgfArticole.PAGE3.grdArticoleFactura.cValutaArt.Text1' AS textbox WITH ;
BackColor = 225,225,225, ;
BorderStyle = 0, ;
FontName = "Arial", ;
FontSize = 10, ;
ForeColor = 0,0,0, ;
Margin = 0, ;
Name = "Text1", ;
ReadOnly = .T., ;
SelectedBackColor = 100,185,255
*< END OBJECT: BaseClass="textbox" />
ADD OBJECT 'txtSuma' AS _textbox WITH ; ADD OBJECT 'txtSuma' AS _textbox WITH ;
Alignment = 3, ; Alignment = 3, ;
Anchor = 8, ; Anchor = 8, ;
@@ -13667,6 +14072,16 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
If !Used('saft_mecanisme_plati') If !Used('saft_mecanisme_plati')
update_saft_mecanisme_plati() update_saft_mecanisme_plati()
ENDIF ENDIF
*!* cursorul tvd, gol - din functia comuna daca ofacturare_editare.prg e incarcat
If !Used('tvd')
IF "OFACTURARE_EDITARE" $ Upper(Set("Procedure"))
CreeazaCursorTvdGol()
ELSE
*!* structura se repeta: in ROACONT/ROAGEST functia comuna nu e incarcata
CREATE CURSOR tvd (id_vanzare I, id_vanzare_det I, id_articol I, cantitate N(12,3), pret N(14,4), pret_cu_tva N(14,4), proc_tvav N(6,4), discount_unitar N(14,4), id_gestiune I, cont C(20), id_valuta I, id_jtva_coloana I, serie C(20), explicatie C(60), taxcode I, lot C(20), sters I, denumire C(100), codmat C(30), nume_gestiune C(60), nume_val C(20))
ENDIF
ENDIF
ENDPROC ENDPROC
PROCEDURE Resize PROCEDURE Resize
@@ -13754,6 +14169,27 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
This.Grid1.HeaderHeight = 37 This.Grid1.HeaderHeight = 37
this.pgfArticole.page1.grdRulaje.HeaderHeight = 37 this.pgfArticole.page1.grdRulaje.HeaderHeight = 37
this.pgfArticole.page2.grdRulajeObinv.HeaderHeight = 37 this.pgfArticole.page2.grdRulajeObinv.HeaderHeight = 37
* pagina de articole factura (VANZARI/VANZARI_DETALII) - apare doar cand ofacturare_editare.prg
* e incarcat (doar ROAFACTURARE - ROACONT/ROAGEST nu-l inregistreaza) si documentul are rand in vanzari
This.lAreArticoleVanzari = .F.
This.nIdVanzare = 0
This.nTipVanzare = 0
IF "OFACTURARE_EDITARE" $ Upper(Set("Procedure")) AND Reccount('tact') > 0
IncarcaVanzareDinNota('tact')
IF Reccount('tvanz') = 1
This.lAreArticoleVanzari = .T.
This.nIdVanzare = tvanz.id_vanzare
This.nTipVanzare = tvanz.tip
ENDIF
ENDIF
IF This.lAreArticoleVanzari
IncarcaArticoleFactura(This.nIdVanzare)
This.pgfArticole.PageCount = 3
ELSE
This.pgfArticole.PageCount = 2
ENDIF
This.grid1.column42.visible = m.gl406 && saft taxa This.grid1.column42.visible = m.gl406 && saft taxa
This.grid1.column43.visible = m.gl406 && saft plata This.grid1.column43.visible = m.gl406 && saft plata

View File

@@ -76,6 +76,17 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata:
- Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare - Metoda noua de clasa cere `*m: nume` in `*<DefinedPropArrayMethod>`; fara ea, prima salvare
din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri). din IDE o arunca tacut, iar refresh-ul urmator absoarbe pierderea in cache (si in .bak-uri).
Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`. Override-urile de metode de baza (Init, Show, hook-uri) nu au nevoie de `*m:`.
- **Proprietate noua de clasa cere identic `*p: nume` in `*<DefinedPropArrayMethod>`** — nu doar
valoarea in `*<PropValue>`. Fara `*p:`, valoarea se scrie in text, **trece fidelity-check-ul**
(fidelity compara doar text-sursa cu text-regenerat) si ajunge in binar ca text, dar VFP nu o
materializeaza pe obiect: `PEMSTATUS(o,'nume',5)` da `.F.` si orice acces cade cu eroarea 1734
"Property ... is not found". Dovedit in ambele sensuri pe o clasa de proba izolata (cu `*p:` ->
`.T.`, fara -> `.F.`).
- **FoxBin2Prg sorteaza alfabetic cu `_` DUPA literele obisnuite**, nu in ordine ASCII brut (unde
`'_' (0x5F) < 'v' (0x76)` pe litere mici). O intrare `*p:`/`*m:` scrisa de mana in ordine "ASCII
corecta" pica fidelity-check-ul; ordinea canonica se citeste din textul regenerat in
`<staging>\verify\*.vc2` (vezi punctul de mai jos despre pozitia metodelor noi — se aplica identic
proprietatilor).
- FoxBin2Prg NU pastreaza pozitia in text a unei metode noi: o regenereaza la pozitia - FoxBin2Prg NU pastreaza pozitia in text a unei metode noi: o regenereaza la pozitia
alfabetica din `*<DefinedPropArrayMethod>`. O metoda scrisa in alta parte a fisierului alfabetica din `*<DefinedPropArrayMethod>`. O metoda scrisa in alta parte a fisierului
face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din

View File

@@ -4,6 +4,45 @@ Regula (valabila in toate proiectele ROA/VFP): un singur subagent care duce o mi
(iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias — (iteratii de teste, investigatii, mai multe sarcini inlantuite) acumuleaza context urias —
calitate degradata, cost mare. Nu se lucreaza asa. calitate degradata, cost mare. Nu se lucreaza asa.
## REGULA ZERO: predarea contextului e OBLIGATORIE, nu optionala
Se aplica **identic sesiunii principale si oricarui subagent**. Nu e o recomandare de eficienta,
e o conditie de corectitudine: un context supraincarcat pierde tacut decizii deja luate si reia
investigatii deja platite.
**Declansatoare — la oricare dintre ele, predarea porneste imediat:**
1. contextul propriu a trecut de **~50% din fereastra** (orchestrator) sau de **~200-250k tokens**
(subagent);
2. harness-ul anunta compactare automata (`PreCompact`) — **prea tarziu ca sa mai amani, dar nu
prea tarziu ca sa scrii fisierul**; scrie handoff-ul inainte sa raspunzi orice altceva;
3. utilizatorul semnaleaza ca s-a atins limita;
4. s-a terminat un bloc de lucru — indiferent cat context a mai ramas.
**Procedura, in ordine, fara exceptii:**
1. **Opreste lucrul.** Nu incepe o sarcina noua, nu porni o rulare noua. Daca esti in mijlocul unei
editari, du-o pana la o stare **consistenta pe disc** (text si binare sincronizate) si atat.
2. **Scrie handoff-ul pe disc** (`docs\handoff_<subiect>.md`). Nu in mesaj, nu in raport — **pe
disc**. Un mesaj catre orchestrator se pierde; fisierul nu.
3. **Confirma in doua randuri** ce ai lasat in urma si daca ceva e intr-o stare periculoasa
(fisier editat fara write-back, tranzactie deschisa, proces ramas viu, date de test consumate).
4. **Opreste-te.** Blocul urmator il ia un agent proaspat. "Mai am putin" nu e motiv de amanare —
exact acolo se pierd lucrurile.
**Obligatia e a fiecaruia, nu doar a orchestratorului.** Un subagent care simte ca se apropie de
prag **anunta singur** si cere predarea; nu asteapta sa fie oprit. Un orchestrator care se apropie
de prag isi scrie propriul handoff si preda orchestrarea unei sesiuni noi — regula nu are portita
pentru "eu doar coordonez".
**Ce intra obligatoriu in handoff**: inventarul livrabilelor cu `fisier:linie`; ce e terminat si ce
nu; **daca write-back-ul e facut** pentru fiecare fisier atins; comanda exacta de rulare a testelor
si unde scriu logurile; ce s-a stabilit deja (ca sa nu se reia); ce e interzis; starea datelor de
test consumate; capcanele de mediu platite. Fara analize noi — doar stare.
Doua lectii platite scump, amandoua din aceeasi cauza — un agent tinut peste prag (`s5-nivel2`
533k, `s2d-modifica-gestiuni` 434k). Predarea e aproape gratuita: raportul e oricum deja scris.
## Cum se lucreaza ## Cum se lucreaza
- Sesiunea principala (sau un agent primar) e ORCHESTRATOR: imparte planul pe sarcini - Sesiunea principala (sau un agent primar) e ORCHESTRATOR: imparte planul pe sarcini
@@ -58,7 +97,9 @@ diagnostic, fixuri aplicate direct in loc de delegate.
care intoarce da/nu, nu continutul din care ai deduce singur. care intoarce da/nu, nu continutul din care ai deduce singur.
- **Nu aplica fixuri direct** decat sub ~5 linii si doar daca ai deja contextul in sesiune. - **Nu aplica fixuri direct** decat sub ~5 linii si doar daca ai deja contextul in sesiune.
- **Prag si pe orchestrator**: la ~50% din fereastra, scrie handoff-ul si reia orchestrarea - **Prag si pe orchestrator**: la ~50% din fereastra, scrie handoff-ul si reia orchestrarea
dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. dintr-o sesiune noua. Handoff-ul e deja pe disc - exact pentru asta exista. Vezi **Regula zero**
de la inceputul fisierului: obligatia e aceeasi ca pentru subagenti, fara portita pentru
"eu doar coordonez".
## Model de lucru: backlog de story-uri mici, context mic per story ## Model de lucru: backlog de story-uri mici, context mic per story

View File

@@ -12,13 +12,20 @@
handoff-uri/planuri de runda, `*.pre_runda*.bak`, `.bak`-urile din cache-ul text si artefactele handoff-uri/planuri de runda, `*.pre_runda*.bak`, `.bak`-urile din cache-ul text si artefactele
de test (`screenshots*`, `uisync*`, `.fxp`, `.err`, loguri). Sterge doar fisiere neurmarite de de test (`screenshots*`, `uisync*`, `.fxp`, `.err`, loguri). Sterge doar fisiere neurmarite de
git — cele tracked sunt sarite. git — cele tracked sunt sarite.
2. Comentarii in cod: minime, strict functionale, descriu comportamentul CURENT (ca si cum ar fi 2. Comentarii in cod SI in scripturile de migrare `.sql`: minime, strict functionale, descriu
scris asa de la inceput) — o linie de regula, 2-3 doar pentru metode cu contract nebanal comportamentul CURENT (ca si cum ar fi scris asa de la inceput). **Doar daca e cazul** — un
(parametri, cursor asteptat/lasat deschis, pozitionare la iesire). Istoricul modificarilor comentariu se scrie acolo unde explica o **ramura** sau un **filtru** care nu se citeste singur,
sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg` si in PL/SQL Oracle. ca sa se inteleaga codul; unde codul e limpede, nu se comenteaza. O linie de regula, 2-3 doar
INTERZIS in comentariu: nume de agent ("claude"), referinte la propuneri/decizii/etape pentru metode cu contract nebanal (parametri, cursor asteptat/lasat deschis, pozitionare la
(`docs/propuneri_*.md`, "M2", "T3", "dec.6", "runda27", "E7", "D-H2"), istoricul modificarii iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are). Istoricul
("inlocuieste...", "nu mai depinde de...", "mutat din..."), date si autori pe cod nou. modificarilor sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg`, in `.sql`
si in PL/SQL Oracle.
INTERZIS in comentariu: nume de agent ("claude"), referinte la planuri, stories, propuneri,
decizii, etape sau erori (`docs/plan_*.md`, `docs/propuneri_*.md`, "#6", "S4", "M2", "T3",
"dec.6", "runda27", "E7", "D-H2"), trimiteri la rapoartele din `docs/` ("vezi raportul,
sectiunea ..."), justificarea alegerii facute (de ce numele acesta, de ce s-a respins varianta
cealalta), istoricul modificarii ("inlocuieste...", "nu mai depinde de...", "mutat din..."),
date si autori pe cod nou.
Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins Comentarii vechi in stil jurnal nu se rescriu din oficiu — doar cand blocul e oricum atins
sau la cerere explicita. sau la cerere explicita.
Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` / Antet: o singura intrare CUMULATIVA per functionalitate (`*!* DD.MM.YYYY` / `*!* autor` /
@@ -46,6 +53,20 @@
se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k se umple contextul. Misiuni lungi: subagenti proaspeti per sarcina (max ~200-250k
tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc: tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc:
`orchestrare-subagenti.md`. `orchestrare-subagenti.md`.
**Verificarea a ce se intoarce** — pentru executie delegarea merge, pentru concluzii nu:
- **citeste contractul functiei apelate, nu-l presupune.** Un raport care descrie corect
structura codului poate gresi sensul: ex. `goExecutor.oExecute` intoarce succes/insucces
(`CT_SUCCES`/`CT_INSUCCES`), NU numarul de randuri — o garda `If lnSucces > 0` citita ca
"are randuri" a produs un bug inexistent, raportat ca blocant. Deschide functia.
- **fix ingust, nu supra-constructie.** Cand premisa se corecteaza, corectia se restrange:
mecanismele noi introduse "ca sa fie sigur" diverg de la codul-sablon si blocheaza
refolosirea lui in alta parte.
- **"zero cazuri in date" nu dovedeste nimic** pe scheme cu date de test; raspunsul vine din
cod. Si invers: o potrivire de cifre pe 1-2 documente nu e o regula.
- **cere raportul sa separe "testat" de "analizat static"**, si ce n-a putut fi acoperit. Un
agent care nu e intrebat explicit va prezenta amandoua la fel.
- **spune-i ca poate infirma briefingul.** Altfel implementeaza corectia ceruta chiar cand a
descoperit ca nu e nevoie de ea.
7. Conventii obligatorii, de citit cand atingi zona respectiva: 7. Conventii obligatorii, de citit cand atingi zona respectiva:
- editezi fisiere cu octeti cp1252 - `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`, - editezi fisiere cu octeti cp1252 - `.vc2`/`.sc2`, dar si `.prg` (ex. `programe\ocautare.prg`,
unde `s`-urile cu virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) -> unde `s`-urile cu virgula din `masina`/`si contul`/`transa` sunt octetul `0xBA`) ->

View File

@@ -70,6 +70,10 @@ Marius ce nu e aplicat. Exportul sursei de referinta: `oracle_export.md`.
- **Idempotent**: rulat de doua ori nu mai schimba nimic (`merge`, `where <coloana> is null`). - **Idempotent**: rulat de doua ori nu mai schimba nimic (`merge`, `where <coloana> is null`).
- **Un pachet sta singur in scriptul lui**, fara alt DDL sau DML alaturi: modificarile de tabele si - **Un pachet sta singur in scriptul lui**, fara alt DDL sau DML alaturi: modificarile de tabele si
curateniile de date merg in scripturi separate, cu numar propriu. curateniile de date merg in scripturi separate, cu numar propriu.
- **Comentarii strict necesare**, ca in cod: antet de 4-5 randuri (data + autor, ce e obiectul, ce
contract are), fara referinte la planuri, stories, propuneri, decizii sau erori, fara trimiteri la
rapoartele din `docs/`, fara justificarea alegerilor si fara istoricul modificarii. Regula completa
si lista de interdictii: `reguli_lucru.md`, punctul 2.
## Compatibilitate cu serverele clientilor ## Compatibilitate cu serverele clientilor

View File

@@ -175,3 +175,40 @@ p. **Nu numi variabilele ca functii built-in VFP.** VFP e insensibil la litere m
**tacut false** si par sa spuna ca obiectul nu a fost gasit — masuratoarea e stricata, nu **tacut false** si par sa spuna ca obiectul nu a fost gasit — masuratoarea e stricata, nu
rezultatul. Simptom de recunoscut: mesajul de eroare contine numele **cu majuscule** al unei rezultatul. Simptom de recunoscut: mesajul de eroare contine numele **cu majuscule** al unei
functii VFP, nu numele variabilei asa cum ai scris-o. Prefixeaza distinctiv (`loBifa`, `loCtrl`). functii VFP, nu numele variabilei asa cum ai scris-o. Prefixeaza distinctiv (`loBifa`, `loCtrl`).
q. **`DO ... WITH` paseaza PRIN REFERINTA, iar variabila devine invizibila sub numele ei propriu in
procedura apelata.** Consecinta urata: orice `?variabila` din SQL passthrough de pe lantul
apelurilor respective nu se mai poate lega, si VFP deschide dialogul nativ **"View Parameter —
Enter the value for `<var>`"**, care blocheaza testul headless la infinit (fara log, fara
eroare). Dovedit pe date: o variabila globala era valida in programul principal la fiecare
checkpoint, dar `TYPE()` intorcea `'U'` (nedefinita) exact la intrarea in procedurile apelate cu
`DO proc WITH gnAn, gnLuna` — si valida in cele apelate fara `DO ... WITH` — corelatie exacta cu
**sintaxa apelului**, nu cu ce face procedura. Remediu: paranteze pe fiecare argument forteaza
pasarea prin valoare — `DO proc WITH (gnAn), (gnLuna)`.
r. **O suita care testeaza o clasa din `COMUN` poate incarca implicit copia ALTUI PRODUS**, daca
harnessul de mediu comun (ex. `test_init_env_auto.prg`) face `SET DEFAULT TO`/`SET PATH` pe
working copy-ul altui produs (ex. `D:\ROA\ROACONT\...`) inainte de `SET CLASSLIB TO <clasa>
ADDITIVE`: `Createobject` gaseste prima clasa cu acel nume pe `PATH`, care poate fi
`D:\ROA\ROACONT\COMUN\clase\<clasa>.vcx` in loc de fisierul editat sub test — silentios, fara
eroare. Simptom: testul trece curat, dar valideaza cod vechi/alt working copy; orice concluzie
trasa asa e nula. Remediu, dupa initializarea mediului comun: `RELEASE CLASSLIB <nume>` +
`SET CLASSLIB TO <cale completa a fisierului sub test> ADDITIVE` (`SET CLASSLIB ... ADDITIVE`
**singur**, fara `RELEASE` intai, da eroarea 24 "Alias name is already in use" si pastreaza
tacut copia veche). Verificare obligatorie dupa instantiere: `loForm.ClassLibrary` trebuie sa
arate calea completa asteptata.
s. **Dialoguri native care nu apar in log si nu sunt prinse de `ON ERROR`/mock-uri** (ex. "View
Parameter", "Open" pe fisier lipsa): nu se depaneaza orbeste, se ruleaza sub
`COMUN\utile\Teste\watchdog_vfp.ps1 -Script <test.prg> -AutoDismiss`. Lanseaza `vfp9.exe -A -T`,
polleaza ferestrele top-level ale procesului (identificate prin `Process.MainWindowHandle`, nu
dupa numele clasei — VFP foloseste clase `vfp9...` si pentru shell-ul principal si pentru
dialogurile proprii), captureaza PNG + textul fiecarui control copil (`WM_GETTEXT`) la orice
fereastra noua, si omoara procesul la iesire (`finally`, niciodata ramas viu). **Interzis strict:
input real** (`keybd_event`/`SetForegroundWindow`/`SendInput`/`mouse_event`) — masina e
partajata, un input injectat la nivel de sistem ajunge in orice fereastra are focus in acel
moment, nu neaparat in dialogul tintit (patit: un ESCAPE injectat a intrerupt sesiunea IDE a
utilizatorului, aflat in lucru in paralel). `-AutoDismiss` foloseste STRICT mesaje Windows
tintite pe handle (`BM_CLICK` pe buton Cancel/Anulare, altfel `WM_COMMAND IDCANCEL` ->
ESCAPE ca mesaj `WM_KEYDOWN`/`WM_KEYUP` -> `WM_CLOSE`); pe dialogurile proprii VFP owner-drawn
(butoane desenate, nu HWND-uri reale) dismiss-ul poate esua cinstit — captura PNG + dump text
raman oricum de incredere, indiferent de rezultatul dismiss-ului. Sterge intotdeauna `.fxp`-ul
vechi inainte de FIECARE rulare (watchdog-ul o face singur la lansare) — altfel VFP ruleaza
tacut codul compilat vechi si rulari "identice" dau rezultate diferite, fara nicio urma in log.

View File

@@ -5,22 +5,22 @@ Poate folosesti exact datele de la anaf descarcate pentru verificarea codurilor
Vreau ca verificarile de coduri fiscale din D406, D394, Registrele de TVA sa foloseasca direct ANAF, si sa actualizeze cache-ul istoricul din baza de date (ISTORIC_CODURI_FISCALE) Vreau ca verificarile de coduri fiscale din D406, D394, Registrele de TVA sa foloseasca direct ANAF, si sa actualizeze cache-ul istoricul din baza de date (ISTORIC_CODURI_FISCALE)
2. ROACONT - Borderou eFactura, checkbox-urile diferente fata de Registrele de TVA sa aiba in caption si numarul de inregistrari cu diferente, astfel incat utilizatorul sa stie daca este cazul sa filtreze pentru afisarea facturilor cu diferente DONE 2. ROACONT - Borderou eFactura, checkbox-urile diferente fata de Registrele de TVA sa aiba in caption si numarul de inregistrari cu diferente, astfel incat utilizatorul sa stie daca este cazul sa filtreze pentru afisarea facturilor cu diferente
3. ROACONT - modificare nota, explicatia tva sa filtreze dupa procent tva din tabel, ca sa arate o selectie mai mica de explicatii tva. vezi cum ai facut la explicatia tva din ointroduceri.vcx > import_nota. DONE 3. ROACONT - modificare nota, explicatia tva sa filtreze dupa procent tva din tabel, ca sa arate o selectie mai mica de explicatii tva. vezi cum ai facut la explicatia tva din ointroduceri.vcx > import_nota.
4. ROACONT - overificari.vcx > formularul istoric coduri fiscale are coloane care nu mai au relavanta sau nu mai sunt completate din tabel. in tabelul contafin_oracle.istoric_coduri_fiscale, campul regcom are spatii si nu se afiseaza in formularul istoric. verifica DONE 4. ROACONT - overificari.vcx > formularul istoric coduri fiscale are coloane care nu mai au relavanta sau nu mai sunt completate din tabel. in tabelul contafin_oracle.istoric_coduri_fiscale, campul regcom are spatii si nu se afiseaza in formularul istoric. verifica
5. ROACONT - VERIFICARE cod fiscal, label-ul de sub grid-ul cu rezultate si detalii F4 sa contina si status "TVA Incasare" DONE 5. ROACONT - VERIFICARE cod fiscal, label-ul de sub grid-ul cu rezultate si detalii F4 sa contina si status "TVA Incasare"
6. ROAFACTURARE - EDITARE FACTURA EMISA ANTERIOR, CARE NU A FOST TRIMISA INCA IN EFACTURA (anaf_efactura.id_fact). punctul critic este ca notele contabile si eventual rulajele generate se genereaza complicat la emiterea facturii prin pack_facturare, iar editarea este o simpla editare, si nu sincronizeaza si notele contabile si rulajele. si sunt diverse tipuri de facturi sau de avize (pe baza de lista de preturi, pe baza de comanda, pe baza de contract, pe baza de aviz) si fiecare genereaza note contabile sau rulaje si articole de vanzare (vanzari si vanzari_detalii) 6. ROAFACTURARE - EDITARE FACTURA EMISA ANTERIOR, CARE NU A FOST TRIMISA INCA IN EFACTURA (anaf_efactura.id_fact). punctul critic este ca notele contabile si eventual rulajele generate se genereaza complicat la emiterea facturii prin pack_facturare, iar editarea este o simpla editare, si nu sincronizeaza si notele contabile si rulajele. si sunt diverse tipuri de facturi sau de avize (pe baza de lista de preturi, pe baza de comanda, pe baza de contract, pe baza de aviz) si fiecare genereaza note contabile sau rulaje si articole de vanzare (vanzari si vanzari_detalii)
7. ROAFACTURARE - TVA unitar si valoarea TVA pe o linie de articol este calculata si nu salvata in vanzari si vanzari_detalii. din aceasta cauza, daca o factura are valoare totala 99.99 lei, dar utilizatorul doreste 100.00 lei total cu tva (pentru ca politica de preturi are bifat preturi fara TVA si se porneste calculul incepand de la pretul fara TVA al articolului) tva-ul se calculeaza rotunjit si nu se poate edita, ca sa dea factura fix 100.00 lei. implicatiile calculului TVA in loc de salvare sunt foarte mari si adanci in program, la introducerea facturii, listarea facturii initiale, relistarea facturii 7. ROAFACTURARE - TVA unitar si valoarea TVA pe o linie de articol este calculata si nu salvata in vanzari si vanzari_detalii. din aceasta cauza, daca o factura are valoare totala 99.99 lei, dar utilizatorul doreste 100.00 lei total cu tva (pentru ca politica de preturi are bifat preturi fara TVA si se porneste calculul incepand de la pretul fara TVA al articolului) tva-ul se calculeaza rotunjit si nu se poate edita, ca sa dea factura fix 100.00 lei. implicatiile calculului TVA in loc de salvare sunt foarte mari si adanci in program, la introducerea facturii, listarea facturii initiale, relistarea facturii
Sau de fapt este posibil sa poata utilizatorul sa modifice "preturi_cu_tva" la nivel de fiecare articol, la introducerea facturii si ulterior la editare factura, tocmai pentru ca utilizatorul doreste sa ajusteze tva-ul total pentru ca are restrictie sa dea facturii o valoare totala rotunjita, si se poate ajusta exact din pretul cu tva individual. pret_cu_tva se salveaza in vanzari_detalii pe fiecare articol. Sau de fapt este posibil sa poata utilizatorul sa modifice "preturi_cu_tva" la nivel de fiecare articol, la introducerea facturii si ulterior la editare factura, tocmai pentru ca utilizatorul doreste sa ajusteze tva-ul total pentru ca are restrictie sa dea facturii o valoare totala rotunjita, si se poate ajusta exact din pretul cu tva individual. pret_cu_tva se salveaza in vanzari_detalii pe fiecare articol.
8. ROAFACTURARE - in pack_facturare am salvat in vanzari valori totale denormalizat (fara tva, tva, cu tva, numarul avizului/comanda/contract etc.) ca sa nu le calculez in view din vanzari_detalii pentru ca view-ul de facturi este foarte complex, cu functii si expresii si nu era optimizabil si acceseaza total tabelele vanzari si vanzari_detalii. folosesc un view pe modelul original, si un view cu valorile totale din vanzari. doar ca am observat un bug, la facturile din avize, nu se salveaza corect in vanzari avizul sau numarul/data/suma chitantei daca factura este achitata numerar. trebuie depanat. schema de verificare productie este VENDING@ROA_VENDING DONE 8. ROAFACTURARE - in pack_facturare am salvat in vanzari valori totale denormalizat (fara tva, tva, cu tva, numarul avizului/comanda/contract etc.) ca sa nu le calculez in view din vanzari_detalii pentru ca view-ul de facturi este foarte complex, cu functii si expresii si nu era optimizabil si acceseaza total tabelele vanzari si vanzari_detalii. folosesc un view pe modelul original, si un view cu valorile totale din vanzari. doar ca am observat un bug, la facturile din avize, nu se salveaza corect in vanzari avizul sau numarul/data/suma chitantei daca factura este achitata numerar. trebuie depanat. schema de verificare productie este VENDING@ROA_VENDING
9. ROAGEST - MODIFICARE REGISTRU JURNAL - SA SE POATA MODIFICA SI "NNIR" in notele contabile si sincronizat in rulajele asociate. nu exista coloana NNIR in formularul de editare. DONE 9. ROAGEST - MODIFICARE REGISTRU JURNAL - SA SE POATA MODIFICA SI "NNIR" in notele contabile si sincronizat in rulajele asociate. nu exista coloana NNIR in formularul de editare.
10. ROAFACTURARE - Integrare pagina contracte si rapoarte contracte in ROAFACTURARE, similar COMENZI in ROAFACTURARE - facturare pe baza de comenzi/contracte. trebuie comasate si drepturile pe obiectele din roacontracte cu obiectele noi din ROAFACTURARE. 10. ROAFACTURARE - Integrare pagina contracte si rapoarte contracte in ROAFACTURARE, similar COMENZI in ROAFACTURARE - facturare pe baza de comenzi/contracte. trebuie comasate si drepturile pe obiectele din roacontracte cu obiectele noi din ROAFACTURARE.
@@ -34,7 +34,7 @@ Am vazut la SAGA (alt ERP popular) ca in nomenclatorul de articole au cateva col
Ideea este sa se poata face configurarea mult mai repede, eficient, dintr-un singur loc, ca sa se poata face factura mai rapid. Acum este nevoie de mult suport tehnic/instructaj si configurari pana se ajunge la facturare, si daca apare un articol diferit (ex: vanzare auto, in loc de marfa in mod normal), trebuie creata o politica noua de preturi, ca sa ii spun ce nota contabila de vanzare (4111 = 7xx) sa aiba aiba articolul respectiv. Ideea este sa se poata face configurarea mult mai repede, eficient, dintr-un singur loc, ca sa se poata face factura mai rapid. Acum este nevoie de mult suport tehnic/instructaj si configurari pana se ajunge la facturare, si daca apare un articol diferit (ex: vanzare auto, in loc de marfa in mod normal), trebuie creata o politica noua de preturi, ca sa ii spun ce nota contabila de vanzare (4111 = 7xx) sa aiba aiba articolul respectiv.
13. ROAFACTURARE - FORMULARUL DE FACTURARE SA INCLUDA SI FORMULARUL DATE_FACTURA/DATE_AVIZ ETC. SI SA NU MAI INCARCE DE PE SERVER TOATE ARTICOLELE DIN TOATE POLITICELE DE PRETURI - INTRUCAT ESTE POSIBIL SA FIE SI MII DE ARTICOLE SI DUREAZA MULT SA LE ADUCA DE PE SERVER. AM INCEPUT DEJA MAI DEMULT UN FORMULAR UNIFICAT, DAR ERA MULT DE INTEGRAT DIN FORMULARUL VECHI. 13. ROAFACTURARE - FORMULARUL DE FACTURARE SA INCLUDA SI FORMULARUL DATE_FACTURA/DATE_AVIZ ETC. SI SA NU MAI INCARCE DE PE SERVER TOATE ARTICOLELE DIN TOATE POLITICELE DE PRETURI - INTRUCAT ESTE POSIBIL SA FIE SI MII DE ARTICOLE SI DUREAZA MULT SA LE ADUCA DE PE SERVER. AM INCEPUT DEJA MAI DEMULT UN FORMULAR UNIFICAT frm_facturare_articole2, DAR ERA MULT DE INTEGRAT DIN FORMULARUL VECHI.
FRONTEND SIMILAR PE CARE IL DORESC ESTE IN ROAACPRO > FACTURA, SAU IN IMPORTUL DE EFACTURA, IN CARE AM INTEGRAT DATELE FACTURI, DOAR CA FACTURAREA DIN ROAFACTURARE ESTE MAI COMPLEXA - ESTE FOLOSITA SI PENTRU POLITICI DE PRETURI SI PENTRU CONTRACT/COMANDA/AVIZ/RETUR ETC. FRONTEND SIMILAR PE CARE IL DORESC ESTE IN ROAACPRO > FACTURA, SAU IN IMPORTUL DE EFACTURA, IN CARE AM INTEGRAT DATELE FACTURI, DOAR CA FACTURAREA DIN ROAFACTURARE ESTE MAI COMPLEXA - ESTE FOLOSITA SI PENTRU POLITICI DE PRETURI SI PENTRU CONTRACT/COMANDA/AVIZ/RETUR ETC.
INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FORMULARE PENTRU FACTURA, SA FAC MAI RAPID. INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FORMULARE PENTRU FACTURA, SA FAC MAI RAPID.
@@ -42,3 +42,10 @@ INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FOR
15. ROACONT - ce locuri din program mai folosesc frm_modific2007 in loc de frm_modific2024. trebuie migrat la formularul mai nou. 15. ROACONT - ce locuri din program mai folosesc frm_modific2007 in loc de frm_modific2024. trebuie migrat la formularul mai nou.
16. ROAFACTURARE - in date_factura/date_aviz etc, la finalizare se verifica cursul valutar necesar pentru politicile de preturi care se factureaza. la revenire din formularul de curs valutar, focusul revine inainte de numar document, cred ca pe TIP DOCUMENT, si la iesire din serie se regenereaza numar act, ceea ce este periculos daca utilizatorul l-a schimbat si se modifica automat.
17. ROAFACTURARE - daca o nota contabile de vanzare nu are configurat tip de venit/cheltuiala, si nici articolele din lista de preturi, si nici nu se completeaza tip venit/cheltuiala la facturare, la finalizarea facturii apare o eroare oracle ORA ca id_venchelt nu are voie sa fie null. eroarea nu este user friendly si nu se poate recupera usor, pentru ca trebuie sa se dea renunt la toata factura si sa se reia tot porcesul, cu completarea tip venit cheltuiala. si nici nu stiu de ce este obligatoriu tip venit/cheltuiala.
18. ROAFACTURARE - EMITERE FACTURA DIN PROFORMA
19. ROAFACTURARE - EDITARE PROFORMA

View File

@@ -0,0 +1,296 @@
*** ofacturare_editare
*!* 08.08.2026
*!* marius.mutu
*!* helpere comune pentru editarea unei facturi emise: garda eFactura, cursoarele notei si ale rulajelor,
*!* randul de vanzare corespunzator notei si liniile de articole pentru pagina de articole factura
*!* parametru: id_fact
*!* verifica daca factura cu id_fact dat a fost deja trimisa in eFactura (anaf_efactura)
FUNCTION EsteInEFactura
LPARAMETERS tnIdFact
LOCAL lcSql, lnEFactura, llSucces
lnEFactura = 0
lcSql = [select count(*) as lneFactura from anaf_efactura where id_fact = ] + Alltrim(Str(Nvl(m.tnIdFact,0)))
llSucces = goExecutor.oSelecteaza2Value(m.lcSql, @lnEFactura)
RETURN (Nvl(m.lnEFactura,0) > 0)
ENDFUNC && EsteInEFactura
*!* parametri: cod, an, luna, arata si randurile sterse (implicit .F.)
*!* incarca cursoarele notei (tact) si ale rulajelor (trul, trul_obinv), cu recalculul de
*!* valoare/valtva/valoarev/valtvav pe randurile goale; raman deschise READWRITE pe seama apelantului
*!* pe eroare Oracle intoarce .F. si inchide ce a deschis pana atunci
FUNCTION IncarcaCursoareModificareNota
LPARAMETERS tnCod, tnAn, tnLuna, tlAratasterse
LOCAL lcConditieSters, lcSql, lcCursor, lnSucces
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
lcConditieSters = IIF(m.tlAratasterse, [ ], [ STERS = 0 AND ])
lcSql = [select * from vact_tot where ] + lcConditieSters + [ an = ] + Transform(m.tnAn) + [ and luna = ] + Transform(m.tnLuna) + [ and cod = ] + Alltrim(Str(m.tnCod)) + [ order by id_act]
lcCursor = [v_act]
lnSucces = goExecutor.oExecute(lcSql,lcCursor)
goExecutor.oReset()
IF lnSucces < 0
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
RETURN .F.
ENDIF
SELECT * FROM v_act INTO CURSOR actactan
SELECT .F. AS ales, T.*, CAST(0 AS N(2)) AS tipnota FROM actactan T INTO CURSOR tact READWRITE
USE IN v_act
IF lnSucces > 0
lcSql = [select * from vrul_tot where ] + lcConditieSters + [ an = ] + Transform(m.tnAn) + [ and luna = ] + Transform(m.tnLuna) + [ and cod = ] + Alltrim(Str(m.tnCod)) + [ order by id_rul]
lcCursor = [v_rul]
lnSucces = goExecutor.oExecute(lcSql,lcCursor)
goExecutor.oReset()
IF lnSucces < 0
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
RETURN .F.
ENDIF
IF lnSucces > 0
UPDATE v_rul SET valoare = ROUND(IIF(cant<>0, cant, cante)*pret,m.gnPC) WHERE EMPTY(NVL(valoare,0))
UPDATE v_rul SET valtva = ROUND(IIF(cant<>0, cant, cante)*pret * (IIF(!EMPTY(NVL(proc_tva,0)), proc_tva, 1)-1), m.gnPC) WHERE EMPTY(NVL(valtva,0))
UPDATE v_rul SET valoarev = ROUND(IIF(cant<>0, cant, cante)*pretv,m.gnPC) WHERE EMPTY(NVL(valoarev,0))
UPDATE v_rul SET valtvav = ROUND(IIF(cant<>0, cant, cante)*pretv * (IIF(!EMPTY(NVL(proc_tvav,0)), proc_tvav, 1)-1), m.gnPC) WHERE EMPTY(NVL(valtvav,0))
SELECT *, ;
valoare + valtva AS valoarectva, ;
valoarev + valtvav AS valoarevctva ;
FROM v_rul ;
INTO CURSOR RUL_TEMP READWRITE
SELECT * FROM RUL_TEMP INTO CURSOR trul READWRITE
USE IN v_rul
lcSql = [select * from vrul_obinv_tot where ] + lcConditieSters + [ an = ] + Transform(m.tnAn) + [ and luna = ] + Transform(m.tnLuna) + [ and cod = ] + Alltrim(Str(m.tnCod)) + [ order by id_rul_obinv]
lcCursor = [v_rul_obinv]
lnSucces = goExecutor.oExecute(lcSql,lcCursor)
goExecutor.oReset()
IF lnSucces < 0
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
RETURN .F.
ENDIF
ENDIF
IF lnSucces > 0
UPDATE v_rul_obinv SET valoare = ROUND(IIF(cant<>0, cant, cante)*pret,m.gnPC) WHERE EMPTY(NVL(valoare,0))
UPDATE v_rul_obinv SET valtva = ROUND(IIF(cant<>0, cant, cante)*pret * (IIF(!EMPTY(NVL(proc_tva,0)), proc_tva, 1)-1), m.gnPC) WHERE EMPTY(NVL(valtva,0))
UPDATE v_rul_obinv SET valoarev = ROUND(IIF(cant<>0, cant, cante)*pretv,m.gnPC) WHERE EMPTY(NVL(valoarev,0))
UPDATE v_rul_obinv SET valtvav = ROUND(IIF(cant<>0, cant, cante)*pretv * (IIF(!EMPTY(NVL(proc_tvav,0)), proc_tvav, 1)-1), m.gnPC) WHERE EMPTY(NVL(valtvav,0))
SELECT *, ;
valoare + valtva AS valoarectva, ;
valoarev + valtvav AS valoarevctva ;
FROM v_rul_obinv ;
INTO CURSOR RUL_TEMP_OBINV READWRITE
SELECT * FROM RUL_TEMP_OBINV INTO CURSOR trul_obinv READWRITE
USE IN v_rul_obinv
ENDIF
ENDIF
RETURN .T.
ENDFUNC && IncarcaCursoareModificareNota
*!* creeaza cursorul tvanz gol (structura VANZARI redusa) - fallback la eroare Oracle sau cod/data lipsa
FUNCTION CreeazaCursorTvanzGol
IF Used('tvanz')
Use In tvanz
ENDIF
CREATE CURSOR tvanz (id_vanzare I, tip I, discount N(12,2), total_fara_tva N(14,2), total_tva N(14,2), total_cu_tva N(14,2))
ENDFUNC && CreeazaCursorTvanzGol
*!* parametri: cod, nract, serie_act, dataact (din cursorul notei, ex. tact)
*!* incarca in tvanz randul din VANZARI al notei; cod singur nu e unic, de aceea filtrul cere tot setul
*!* tvanz ramane deschis READWRITE, cu 0 randuri daca nu s-a gasit sau la eroare Oracle
FUNCTION IncarcaVanzareNota
LPARAMETERS tnCod, tnNract, tcSerieAct, tdDataAct
LOCAL lcSql, lnSucces, lcSerieAct
IF Used('v_vanz')
Use In v_vanz
ENDIF
IF Empty(m.tnCod) OR Empty(m.tdDataAct)
CreeazaCursorTvanzGol()
RETURN .T.
ENDIF
lcSerieAct = Alltrim(Nvl(m.tcSerieAct,""))
lcSql = [select id_vanzare, tip, discount, total_fara_tva, total_tva, total_cu_tva from vanzari where cod = ] + Transform(m.tnCod) + ;
[ and Nvl(numar_act,-1) = ] + Transform(Nvl(m.tnNract,-1)) + ;
[ and Nvl(serie_act,'') = '] + m.lcSerieAct + [' and trunc(data_act) = to_date('] + Dtoc(m.tdDataAct,1) + [','YYYYMMDD') and sters = 0]
lnSucces = goExecutor.oExecute(lcSql,[v_vanz])
goExecutor.oReset()
IF lnSucces < 0
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
CreeazaCursorTvanzGol()
RETURN .T.
ENDIF
IF Used('tvanz')
Use In tvanz
ENDIF
SELECT * FROM v_vanz INTO CURSOR tvanz READWRITE
USE IN v_vanz
RETURN .T.
ENDFUNC && IncarcaVanzareNota
*!* parametru: alias cu randurile notei (tact), cu campurile cod/nract/serie_act/dataact/sters
*!* incearca toate combinatiile distincte (cod, nract, serie_act, dataact) din alias (sters=0) pana
*!* gaseste un rand in VANZARI; lasa workarea si pozitia curenta neschimbate, .F. cu tvanz gol daca nu gaseste
FUNCTION IncarcaVanzareDinNota
LPARAMETERS tcAliasAct
LOCAL lnAreaOrigine, lnRecnoOrigine, llGasit
lnAreaOrigine = Select()
llGasit = .F.
IF Empty(m.tcAliasAct) OR !Used(m.tcAliasAct) OR Reccount(m.tcAliasAct) = 0
CreeazaCursorTvanzGol()
IF m.lnAreaOrigine > 0
SELECT (m.lnAreaOrigine)
ENDIF
RETURN .F.
ENDIF
lnRecnoOrigine = Recno(m.tcAliasAct)
IF Used('tmp_triplete_pozvanz')
Use In tmp_triplete_pozvanz
ENDIF
*!* cod se ia tot din cursor, nu de pe randul curent - acesta poate fi la EOF dupa CalculeazaTotal
SELECT DISTINCT cod, nract, serie_act, dataact FROM (m.tcAliasAct) WHERE sters = 0 INTO CURSOR tmp_triplete_pozvanz READWRITE
SELECT tmp_triplete_pozvanz
SCAN
IncarcaVanzareNota(cod, nract, serie_act, dataact)
IF Reccount('tvanz') = 1
llGasit = .T.
EXIT
ENDIF
ENDSCAN
IF Used('tmp_triplete_pozvanz')
Use In tmp_triplete_pozvanz
ENDIF
IF !m.llGasit
CreeazaCursorTvanzGol()
ENDIF
IF Used(m.tcAliasAct)
IF m.lnRecnoOrigine > 0 AND m.lnRecnoOrigine <= Reccount(m.tcAliasAct)
Go (m.lnRecnoOrigine) In (m.tcAliasAct)
ELSE
*!* pozitia initiala era EOF (Recno() peste Reccount()) - se restaureaza tot la EOF
Go Bottom In (m.tcAliasAct)
Skip In (m.tcAliasAct)
ENDIF
ENDIF
IF m.lnAreaOrigine > 0
SELECT (m.lnAreaOrigine)
ENDIF
RETURN m.llGasit
ENDFUNC && IncarcaVanzareDinNota
*!* creeaza cursorul tvd gol, cu structura view-ului VVANZARI_ARTICOLE
FUNCTION CreeazaCursorTvdGol
IF Used('tvd')
Use In tvd
ENDIF
CREATE CURSOR tvd (id_vanzare I, id_vanzare_det I, id_articol I, cantitate N(12,3), pret N(14,4), pret_cu_tva N(14,4), proc_tvav N(6,4), ;
discount_unitar N(14,4), id_gestiune I, cont C(20), id_valuta I, id_jtva_coloana I, serie C(20), explicatie C(60), ;
taxcode I, lot C(20), sters I, denumire C(100), codmat C(30), nume_gestiune C(60), nume_val C(20))
ENDFUNC && CreeazaCursorTvdGol
*!* parametru: id_vanzare
*!* incarca in tvd liniile active (sters=0) ale vanzarii, din VVANZARI_ARTICOLE
*!* tvd ramane deschis READWRITE, cu 0 randuri la eroare Oracle
FUNCTION IncarcaArticoleFactura
LPARAMETERS tnIdVanzare
LOCAL lcSql, lnSucces
IF Used('v_vd')
Use In v_vd
ENDIF
lcSql = [select * from vvanzari_articole where id_vanzare = ] + Transform(Nvl(m.tnIdVanzare,0)) + [ and sters = 0 order by id_vanzare_det]
lnSucces = goExecutor.oExecute(lcSql,[v_vd])
goExecutor.oReset()
IF lnSucces < 0
AMESSAGEBOX(goExecutor.cEroare,0+16,"Eroare")
CreeazaCursorTvdGol()
RETURN .T.
ENDIF
IF Used('tvd')
Use In tvd
ENDIF
SELECT * FROM v_vd INTO CURSOR tvd READWRITE
USE IN v_vd
RETURN .T.
ENDFUNC && IncarcaArticoleFactura

View File

@@ -0,0 +1,72 @@
* test_incarca_articole_view.prg
* Smoke test izolat pentru IncarcaArticoleFactura pe vvanzari_articole (runda 2), inainte de a atinge omodificari.vc2.
* Regresie: id_vanzare=1050 (cod=1140888) -> 4 randuri, id_vanzare=1047 (cod=1140885) -> 2 randuri,
* coincide cu baza din rec_view_articole_vanzare.md. Verifica si coloana noua tvd.id_vanzare.
* Nu atinge Oracle in scriere. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_incarca_articole_view_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
DO verifica WITH 1050, 'cod=1140888', lcLog, 4
DO verifica WITH 1047, 'cod=1140885', lcLog, 2
*!* cursorul gol - structura cu 21 de campuri, inclusiv id_vanzare (nou)
CreeazaCursorTvdGol()
STRTOFILE('--- CreeazaCursorTvdGol ---' + CHR(13) + CHR(10) + ;
' Fcount(tvd) = ' + TRANSFORM(FCOUNT('tvd')) + ' (asteptat 21)' + CHR(13) + CHR(10) + ;
' are id_vanzare: ' + TRANSFORM(TYPE('tvd.id_vanzare') <> 'U') + CHR(13) + CHR(10) + ;
' ' + IIF(FCOUNT('tvd') == 21, 'PASS', 'FAIL') + CHR(13) + CHR(10), lcLog, 1)
IF Used('tvd')
Use In tvd
ENDIF
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
PROCEDURE verifica
LPARAMETERS tnIdVanzare, tcEticheta, tcLog, tnLiniiAsteptate
LOCAL lnLinii, lnIdVanzareCol
IncarcaArticoleFactura(tnIdVanzare)
lnLinii = Reccount('tvd')
lnIdVanzareCol = -1
IF lnLinii > 0
SELECT tvd
GO TOP
lnIdVanzareCol = tvd.id_vanzare
ENDIF
STRTOFILE('--- id_vanzare=' + TRANSFORM(tnIdVanzare) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' Reccount(tvd) = ' + TRANSFORM(lnLinii) + ' (asteptat ' + TRANSFORM(tnLiniiAsteptate) + ')' + CHR(13) + CHR(10) + ;
' tvd.id_vanzare pe primul rand = ' + TRANSFORM(lnIdVanzareCol) + ' (asteptat ' + TRANSFORM(tnIdVanzare) + ')' + CHR(13) + CHR(10) + ;
' ' + IIF(lnLinii == tnLiniiAsteptate AND (lnLinii == 0 OR lnIdVanzareCol == tnIdVanzare), 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
IF Used('tvd')
Use In tvd
ENDIF
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,141 @@
* test_incarca_cursoare.prg
* Verifica IncarcaCursoareModificareNota (COMUN\programe\ofacturare_editare.prg) pe date reale:
* cod=1140888 - nota cu rulaje (non-regresie)
* cod=1140885 - nota FARA randuri in rul (productie/manopera, fara miscare de stoc)
* si pozitionarea in actactan din do_editare_factura (ofacturare_comun.vc2), pe cursoare sintetice.
* Nu atinge Oracle in scriere - doar SELECT-uri prin goExecutor. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_incarca_cursoare_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
STRTOFILE('gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) + CHR(13) + CHR(10), lcLog, 1)
DO verifica_cod WITH 1140888, 'A (regresie, cu rulaje)', lcLog
DO verifica_cod WITH 1140885, 'B (fara randuri in rul)', lcLog
DO verifica_pozitionare_actactan WITH 9999995, 'a) nota normala, un singur id_fact pe toate randurile', lcLog, 5000, 5000, 25010, 100, .T.
DO verifica_pozitionare_actactan WITH 9999996, 'b) prim rand INCASARE cu id_fact-1, Locate il sare', lcLog, 5000, 5000, 25010, 200, .T.
DO verifica_pozitionare_actactan WITH 9999997, 'c) nota fara randul cu id_fact cerut, cade pe Go Top', lcLog, 9999, 7000, 25011, 50, .F.
DO verifica_pozitionare_actactan WITH 9999998, 'd) lnIdFact=0 (aviz/transfer), direct Go Top', lcLog, 0, 8000, 25012, 10, .F.
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
* reproduce mecanica pozitionarii din do_editare_factura (ofacturare_comun.vc2): cauta in actactan
* randul cu id_fact = lnIdFact (cel citit din crsfacturi/VANZARI.ID_FACT); daca nu-l gaseste (sau
* lnIdFact e 0 - avize, transferuri), cade pe Go Top si preia id_fact de acolo. lnIdSet si
* lnIdFactD se citesc mereu de pe randul gasit (Locate sau Go Top).
PROCEDURE verifica_pozitionare_actactan
LPARAMETERS tnCod, tcEticheta, tcLog, tnIdFactIntrare, tnIdFactAsteptat, tnIdSetAsteptat, tnIdFactDAsteptat, tlGasitAsteptat
LOCAL lnIdFact, lnIdSet, lnIdFactD, llGasitRand, llOk
CREATE CURSOR actactan (id_fact N(9), id_factd N(9), id_set N(9))
DO CASE
CASE tnCod = 9999995
&& a) nota normala: toate randurile cu acelasi id_fact
INSERT INTO actactan VALUES (5000, 100, 25010)
INSERT INTO actactan VALUES (5000, 101, 25010)
CASE tnCod = 9999996
&& b) prim rand INCASARE, id_fact = id_fact-ul facturii - 1
INSERT INTO actactan VALUES (4999, 0, 25010)
INSERT INTO actactan VALUES (5000, 200, 25010)
CASE tnCod = 9999997
&& c) nota nu contine id_fact-ul cerut (document vechi)
INSERT INTO actactan VALUES (7000, 50, 25011)
CASE tnCod = 9999998
&& d) aviz/transfer, fara id_fact la intrare
INSERT INTO actactan VALUES (8000, 10, 25012)
ENDCASE
lnIdFact = tnIdFactIntrare
SELECT actactan
llGasitRand = .F.
IF lnIdFact > 0
LOCATE FOR NVL(id_fact, 0) = lnIdFact
llGasitRand = FOUND()
ENDIF
IF !llGasitRand
GO TOP
lnIdFact = id_fact
ENDIF
lnIdSet = id_set
lnIdFactD = id_factd
USE IN actactan
llOk = (lnIdFact == tnIdFactAsteptat AND lnIdSet == tnIdSetAsteptat AND ;
lnIdFactD == tnIdFactDAsteptat AND llGasitRand == tlGasitAsteptat)
STRTOFILE('--- pozitionare actactan, cod=' + TRANSFORM(tnCod) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' gasit rand = ' + TRANSFORM(llGasitRand) + ' (asteptat ' + TRANSFORM(tlGasitAsteptat) + ')' + CHR(13) + CHR(10) + ;
' id_fact = ' + TRANSFORM(lnIdFact) + ' (asteptat ' + TRANSFORM(tnIdFactAsteptat) + ')' + CHR(13) + CHR(10) + ;
' id_set = ' + TRANSFORM(lnIdSet) + ' (asteptat ' + TRANSFORM(tnIdSetAsteptat) + ')' + CHR(13) + CHR(10) + ;
' id_factd = ' + TRANSFORM(lnIdFactD) + ' (asteptat ' + TRANSFORM(tnIdFactDAsteptat) + ')' + CHR(13) + CHR(10) + ;
' ' + IIF(llOk, 'OK', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
ENDPROC
PROCEDURE verifica_cod
LPARAMETERS tnCod, tcEticheta, tcLog
LOCAL llOk, lcMsg, lnIdSetDistinct
llOk = IncarcaCursoareModificareNota(tnCod, gnAn, gnLuna, .F.)
lnIdSetDistinct = -1
IF Used('actactan') AND Reccount('actactan') > 0
SELECT Distinct id_set FROM actactan INTO CURSOR csr_idset_verif_test
lnIdSetDistinct = Reccount('csr_idset_verif_test')
USE IN csr_idset_verif_test
ENDIF
lcMsg = '--- cod=' + TRANSFORM(tnCod) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' IncarcaCursoareModificareNota => ' + TRANSFORM(llOk) + CHR(13) + CHR(10) + ;
' Reccount(actactan) = ' + TRANSFORM(IIF(Used('actactan'), Reccount('actactan'), -1)) + CHR(13) + CHR(10) + ;
' Reccount(tact) = ' + TRANSFORM(IIF(Used('tact'), Reccount('tact'), -1)) + CHR(13) + CHR(10) + ;
' id_set distincte in actactan = ' + TRANSFORM(lnIdSetDistinct) + CHR(13) + CHR(10) + ;
' Used(trul) = ' + TRANSFORM(Used('trul')) + ' Reccount(trul) = ' + TRANSFORM(IIF(Used('trul'), Reccount('trul'), -1)) + CHR(13) + CHR(10) + ;
' Used(trul_obinv) = ' + TRANSFORM(Used('trul_obinv')) + ' Reccount(trul_obinv) = ' + TRANSFORM(IIF(Used('trul_obinv'), Reccount('trul_obinv'), -1)) + CHR(13) + CHR(10)
STRTOFILE(lcMsg, tcLog, 1)
IF Used('actactan')
USE IN actactan
ENDIF
IF Used('tact')
USE IN tact
ENDIF
IF Used('rul_temp')
USE IN rul_temp
ENDIF
IF Used('trul')
USE IN trul
ENDIF
IF Used('rul_temp_obinv')
USE IN rul_temp_obinv
ENDIF
IF Used('trul_obinv')
USE IN trul_obinv
ENDIF
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,154 @@
* test_incarca_vanzare_din_nota.prg
* Smoke test izolat pentru IncarcaVanzareDinNota (ofacturare_editare.prg), inainte de a atinge
* omodificari.vc2 runda 2. Verifica pe cazurile de regresie ale bugului "Go Top orb pe tact":
* cod=1137874/an=2009/luna=8 -> trebuie sa gaseasca id_vanzare=506 (azi, cu Go Top orb, da 0 randuri)
* cod=1139934/an=2021/luna=12 -> id_vanzare=882 (coliziune VANZARI.COD deja cunoscuta)
* plus regresie pe cazurile vechi: cod=1140888 -> id_vanzare=1050; cod=1125486 -> nu gaseste (tact fara VANZARI)
* plus cazul EOF: tact pozitionat deliberat la EOF (ca dupa CalculeazaTotal() din Show()) inainte de
* apel - dovedeste ca "cod" se ia din cursorul de triplete (SELECT DISTINCT), nu de pe randul curent
* Nu atinge Oracle in scriere - doar SELECT-uri prin goExecutor. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_incarca_vanzare_din_nota_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
DO verifica WITH 1137874, 2009, 8, 'blocant Go Top - prim rand INCASARE', lcLog, .T., 506
DO verifica WITH 1139934, 2021, 12, 'coliziune VANZARI.COD', lcLog, .T., 882
DO verifica WITH 1140888, (gnAn), (gnLuna), 'regresie runda 1 - factura normala', lcLog, .T., 1050
DO verifica WITH 1125486, 2008, 2, 'regresie runda 1 - fara VANZARI', lcLog, .F., 0
DO verifica_eof WITH 1137874, 2009, 8, lcLog, 506
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
* pozitioneaza tact deliberat la EOF (Go Bottom + Skip) inainte de IncarcaVanzareDinNota - dovedeste
* ca "cod" nu se mai citeste de pe randul curent al aliasului (corectia care a inlocuit Evaluate(alias.cod))
PROCEDURE verifica_eof
LPARAMETERS tnCod, tnAn, tnLuna, tcLog, tnIdVanzareAsteptat
LOCAL llOk, llGasit, lnIdVanzare, llEofInainte, llEofDupa
llOk = IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, .F.)
llGasit = .F.
lnIdVanzare = 0
llEofInainte = .F.
llEofDupa = .F.
IF llOk AND Used('tact')
SELECT tact
Go Bottom In tact
Skip In tact
llEofInainte = Eof('tact')
llGasit = IncarcaVanzareDinNota('tact')
llEofDupa = Eof('tact')
IF llGasit
lnIdVanzare = tvanz.id_vanzare
ENDIF
ENDIF
STRTOFILE('--- EOF pe tact, cod=' + TRANSFORM(tnCod) + ' [pozitionare la EOF inainte de apel] ---' + CHR(13) + CHR(10) + ;
' Eof(tact) inainte de apel = ' + TRANSFORM(llEofInainte) + ' (asteptat .T.)' + CHR(13) + CHR(10) + ;
' gasit = ' + TRANSFORM(llGasit) + ' (asteptat .T.)' + CHR(13) + CHR(10) + ;
' id_vanzare = ' + TRANSFORM(lnIdVanzare) + ' (asteptat ' + TRANSFORM(tnIdVanzareAsteptat) + ')' + CHR(13) + CHR(10) + ;
' Eof(tact) dupa apel (pozitia restaurata) = ' + TRANSFORM(llEofDupa) + ' (asteptat .T.)' + CHR(13) + CHR(10) + ;
' ' + IIF(llEofInainte AND llGasit AND lnIdVanzare == tnIdVanzareAsteptat AND llEofDupa, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
IF Used('tvanz')
Use In tvanz
ENDIF
ENDPROC
PROCEDURE verifica
LPARAMETERS tnCod, tnAn, tnLuna, tcEticheta, tcLog, tlAsteptatGasit, tnIdVanzareAsteptat
LOCAL llOk, llGasit, lnIdVanzare, lcMsg, lnAreaOrigineTest, lcAliasOrigineTest
llOk = IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, .F.)
llGasit = .F.
lnIdVanzare = 0
lnAreaOrigineTest = 0
lcAliasOrigineTest = ''
IF llOk AND Used('tact')
SELECT tact
lnAreaOrigineTest = Select()
lcAliasOrigineTest = Alias()
llGasit = IncarcaVanzareDinNota('tact')
IF llGasit
lnIdVanzare = tvanz.id_vanzare
ENDIF
ENDIF
lcMsg = '--- cod=' + TRANSFORM(tnCod) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' IncarcaCursoareModificareNota => ' + TRANSFORM(llOk) + CHR(13) + CHR(10) + ;
' gasit = ' + TRANSFORM(llGasit) + ' (asteptat ' + TRANSFORM(tlAsteptatGasit) + ')' + CHR(13) + CHR(10) + ;
' id_vanzare = ' + TRANSFORM(lnIdVanzare) + ' (asteptat ' + TRANSFORM(tnIdVanzareAsteptat) + ')' + CHR(13) + CHR(10) + ;
' workarea restaurata la ' + TRANSFORM(lnAreaOrigineTest) + ': ' + TRANSFORM(Select() == lnAreaOrigineTest) + CHR(13) + CHR(10) + ;
' ' + IIF(llGasit == tlAsteptatGasit AND lnIdVanzare == tnIdVanzareAsteptat AND Select() == lnAreaOrigineTest, 'PASS', 'FAIL') + CHR(13) + CHR(10)
STRTOFILE(lcMsg, tcLog, 1)
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
IF Used('tvanz')
Use In tvanz
ENDIF
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,305 @@
* test_page3_articole.prg
* Verifica S4 runda 1+2 (PAGE3, view VVANZARI_ARTICOLE, pozitionare in tact, garda ROACONT/ROAGEST) pe date reale:
* - IncarcaVanzareNota/IncarcaArticoleFactura (ofacturare_editare.prg) direct, pe cod=1140888,
* cod=1140885 (au rand in VANZARI) si cod=1125486 (nota fara rand in VANZARI)
* - cazul de coliziune pe cod: cod=1139934 are 4 randuri VANZARI cu acelasi cod - verifica ca
* filtrul compus (cod+nract+serie_act+data_act) gaseste exact randul corect si NU gaseste
* nimic pentru un nract fara corespondent (evitarea unei potriviri gresite)
* - frm_modific2024 instantiat ca in do_editare_factura (Createobject+Show): PageCount ajunge 3
* pe documente cu rand in VANZARI, ramane 2 pe o nota fara VANZARI
* - regresie runda 2: cod=1137874/an=2009/luna=8 si cod=1139934/an=2021/luna=12, unde primul
* rand din tact e o INCASARE - Go Top orb (runda 1) rata id_vanzare, IncarcaVanzareDinNota il
* gaseste prin toate tripletele distincte (nract,serie_act,dataact) din tact
* - garda ROACONT/ROAGEST: cu ofacturare_editare.prg eliberat din SET PROCEDURE, Show() degradeaza
* curat la PageCount=2, fara eroare
* Nu atinge Oracle in scriere - doar SELECT-uri prin goExecutor. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_page3_articole_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
*!* OBLIGATORIU: test_init_env_auto:139 face "Set Classlib To omodificari Additive", iar SET PATH
*!* e pe D:\ROA\ROACONT\..., deci se incarca copia ROACONT a clasei (alt working copy, fara
*!* modificarile noastre). O eliberam si o reincarcam pe cea DE SUB TEST, cu cale completa -
*!* altfel Createobject valideaza cu totul alt fisier decat cel editat.
RELEASE CLASSLIB omodificari
SET CLASSLIB TO D:\ROA\ROAFACTURARE\COMUN\clase\omodificari.vcx ADDITIVE
*!* 1) IncarcaVanzareNota / IncarcaArticoleFactura direct, pe documente reale
*!* (gnAn)/(gnLuna) in paranteze = pasare PRIN VALOARE: DO ... WITH paseaza prin REFERINTA, iar o
*!* variabila pasata prin referinta devine invizibila sub numele ei propriu in procedura apelata -
*!* de acolo venea dialogul nativ "View Parameter: Enter the value for gnAn" (?gnAn din SQL passthrough)
DO verifica_vanzare_nota WITH 1140888, (gnAn), (gnLuna), 'A (factura, cu articole)', lcLog, .T., 1050, 1, 4
DO verifica_vanzare_nota WITH 1140885, (gnAn), (gnLuna), 'B (aviz/tip -12, cu rand in VANZARI)', lcLog, .T., 1047, -12, -1
DO verifica_vanzare_nota WITH 1125486, 2008, 2, 'C (nota fara rand in VANZARI)', lcLog, .F., 0, 0, -1
*!* 2) cazul de coliziune pe cod=1139934 (4 randuri VANZARI cu acelasi cod) - filtrul compus
DO verifica_coliziune_cod WITH lcLog
*!* 3) frm_modific2024 - PageCount pe factura reala (cod=1140888) si pe nota fara VANZARI (cod=1125486)
DO verifica_pagecount_form WITH 1140888, (gnAn), (gnLuna), 'A (factura reala)', lcLog, 3, .T., 1050
DO verifica_pagecount_form WITH 1125486, 2008, 2, 'C (nota fara VANZARI)', lcLog, 2, .F., 0
*!* 4) regresie runda 2 - blocantul "Go Top orb pe tact": prim rand din tact e o INCASARE, cu
*!* nract/serie_act/dataact diferite de randul facturii - Go Top orb (runda 1) rata id_vanzare
DO verifica_pagecount_form WITH 1137874, 2009, 8, 'D (Go Top orb - blocant runda 2)', lcLog, 3, .T., 506
DO verifica_pagecount_form WITH 1139934, 2021, 12, 'E (coliziune cod + Go Top orb)', lcLog, 3, .T., 882
*!* 5) garda ROACONT/ROAGEST: cu ofacturare_editare.prg eliberat, Show() nu mai gaseste garda si
*!* degradeaza curat la PageCount=2 - ultimul test, elibereaza procedura definitiv pentru restul rularii
DO verifica_garda_procedura_lipsa WITH 1140888, (gnAn), (gnLuna), lcLog
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
PROCEDURE verifica_vanzare_nota
LPARAMETERS tnCod, tnAn, tnLuna, tcEticheta, tcLog, tlAsteptatGasit, tnIdVanzareAsteptat, tnTipAsteptat, tnLiniiAsteptate
LOCAL llOk, lcMsg, llGasit, lnIdVanzare, lnTip, lnLinii, llIdOk, llTipOk, llLiniiOk
llOk = IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, .F.)
llGasit = .F.
lnIdVanzare = 0
lnTip = 0
lnLinii = -1
IF llOk AND Used('tact') AND Reccount('tact') > 0
Go Top In tact
IncarcaVanzareNota(tact.cod, tact.nract, tact.serie_act, tact.dataact)
IF Reccount('tvanz') = 1
llGasit = .T.
lnIdVanzare = tvanz.id_vanzare
lnTip = tvanz.tip
IncarcaArticoleFactura(lnIdVanzare)
lnLinii = Reccount('tvd')
ENDIF
ENDIF
llIdOk = IIF(tlAsteptatGasit, lnIdVanzare == tnIdVanzareAsteptat, .T.)
llTipOk = IIF(tlAsteptatGasit, lnTip == tnTipAsteptat, .T.)
llLiniiOk = IIF(tlAsteptatGasit AND tnLiniiAsteptate >= 0, lnLinii == tnLiniiAsteptate, .T.)
lcMsg = '--- cod=' + TRANSFORM(tnCod) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' IncarcaCursoareModificareNota => ' + TRANSFORM(llOk) + CHR(13) + CHR(10) + ;
' gasit in vanzari = ' + TRANSFORM(llGasit) + ' (asteptat ' + TRANSFORM(tlAsteptatGasit) + ')' + CHR(13) + CHR(10) + ;
' id_vanzare = ' + TRANSFORM(lnIdVanzare) + ' (asteptat ' + TRANSFORM(tnIdVanzareAsteptat) + ')' + CHR(13) + CHR(10) + ;
' tip = ' + TRANSFORM(lnTip) + ' (asteptat ' + TRANSFORM(tnTipAsteptat) + ')' + CHR(13) + CHR(10) + ;
' Reccount(tvd) = ' + TRANSFORM(lnLinii) + ' (asteptat ' + TRANSFORM(tnLiniiAsteptate) + ')' + CHR(13) + CHR(10) + ;
' ' + IIF(llGasit == tlAsteptatGasit AND llIdOk AND llTipOk AND llLiniiOk, 'PASS', 'FAIL') + CHR(13) + CHR(10)
STRTOFILE(lcMsg, tcLog, 1)
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
IF Used('tvanz')
Use In tvanz
ENDIF
IF Used('tvd')
Use In tvd
ENDIF
ENDPROC
* cod=1139934 are 4 randuri active in VANZARI cu acelasi cod (verificat pe MARIUSM_AUTO):
* id_vanzare=882 numar_act=375/SSS, 883=24/PF, 884=25/PF, 885=26/PF - filtrul pe cod singur
* ar fi ambiguu; filtrul compus (cod+nract+serie_act+data_act) trebuie sa gaseasca exact
* randul cerut si sa NU gaseasca nimic pentru un nract fara corespondent in VANZARI (ACT are
* randuri cu nract=13 pe acelasi cod, fara VANZARI corespunzator)
PROCEDURE verifica_coliziune_cod
LPARAMETERS tcLog
LOCAL ldDataAct, llOk1, llOk2
ldDataAct = DATE(2021,12,31)
IncarcaVanzareNota(1139934, 375, 'SSS', ldDataAct)
llOk1 = (Reccount('tvanz') = 1 AND tvanz.id_vanzare == 882)
IF Used('tvanz')
Use In tvanz
ENDIF
IncarcaVanzareNota(1139934, 13, '', ldDataAct)
llOk2 = (Reccount('tvanz') = 0)
IF Used('tvanz')
Use In tvanz
ENDIF
STRTOFILE('--- coliziune cod=1139934 (4 randuri VANZARI cu acelasi cod) ---' + CHR(13) + CHR(10) + ;
' nract=375/SSS => gaseste id_vanzare=882: ' + IIF(llOk1, 'PASS', 'FAIL') + CHR(13) + CHR(10) + ;
' nract=13 (fara corespondent) => 0 randuri: ' + IIF(llOk2, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
ENDPROC
* instantiaza frm_modific2024 exact ca in do_editare_factura (ofacturare_comun.vc2:3781-3803):
* IncarcaCursoareModificareNota, rebuild tact cu coloana cu_Tva, Createobject+Show; verifica
* pgfArticole.PageCount si proprietatile de detectie dupa Show()
PROCEDURE verifica_pagecount_form
LPARAMETERS tnCod, tnAn, tnLuna, tcEticheta, tcLog, tnPageCountAsteptat, tlAreArticoleAsteptat, tnIdVanzareAsteptat
LOCAL llOk, lnIdSet, lnPageCount, llAreArticole, lnIdVanzare, loForm, llIdVanzareOk
llOk = IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, .F.)
lnPageCount = -1
llAreArticole = .F.
lnIdVanzare = 0
IF llOk AND Used('tact') AND Reccount('tact') > 0
Select a.*, Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
Go Top In tact
lnIdSet = tact.id_set
IF !Used('crsJtvaTemp')
update_jtva_coloane("", "crsJtvaTemp", 6)
ENDIF
Select tact
loForm = Createobject([frm_modific2024], lnIdSet)
loForm.WindowType = 0
loForm.Show()
lnPageCount = loForm.pgfArticole.PageCount
llAreArticole = loForm.lAreArticoleVanzari
lnIdVanzare = loForm.nIdVanzare
loForm.Release()
ENDIF
llIdVanzareOk = IIF(PCOUNT() >= 9, lnIdVanzare == tnIdVanzareAsteptat, .T.)
STRTOFILE('--- frm_modific2024, cod=' + TRANSFORM(tnCod) + ' [' + tcEticheta + '] ---' + CHR(13) + CHR(10) + ;
' PageCount = ' + TRANSFORM(lnPageCount) + ' (asteptat ' + TRANSFORM(tnPageCountAsteptat) + ')' + CHR(13) + CHR(10) + ;
' lAreArticoleVanzari = ' + TRANSFORM(llAreArticole) + ' (asteptat ' + TRANSFORM(tlAreArticoleAsteptat) + ')' + CHR(13) + CHR(10) + ;
' nIdVanzare = ' + TRANSFORM(lnIdVanzare) + IIF(PCOUNT() >= 9, ' (asteptat ' + TRANSFORM(tnIdVanzareAsteptat) + ')', '') + CHR(13) + CHR(10) + ;
' ' + IIF(lnPageCount == tnPageCountAsteptat AND llAreArticole == tlAreArticoleAsteptat AND llIdVanzareOk, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
IF Used('tvanz')
Use In tvanz
ENDIF
IF Used('tvd')
Use In tvd
ENDIF
ENDPROC
* verifica garda ROACONT/ROAGEST: cu ofacturare_editare.prg eliberat din SET PROCEDURE, Show()
* trebuie sa degradeze curat la PageCount=2, fara eroare - ultimul test din suita, procedura
* ramane eliberata pentru restul rularii (QUIT urmeaza imediat)
PROCEDURE verifica_garda_procedura_lipsa
LPARAMETERS tnCod, tnAn, tnLuna, tcLog
LOCAL llOk, lnIdSet, lnPageCount, loForm, lcProcList, lnI, lcFile
llOk = IncarcaCursoareModificareNota(tnCod, tnAn, tnLuna, .F.)
lnPageCount = -1
IF llOk AND Used('tact') AND Reccount('tact') > 0
Select a.*, Iif(Nvl(id_jtva_coloana,0)=0,0,1) As cu_Tva From tact a Into Cursor tact Readwrite
Go Top In tact
lnIdSet = tact.id_set
IF !Used('crsJtvaTemp')
update_jtva_coloane("", "crsJtvaTemp", 6)
ENDIF
*!* simuleaza ROACONT/ROAGEST: reconstruieste lista de proceduri incarcate, fara ofacturare_editare.prg
*!* (VFP nu are un "release" pe un singur fisier din SET PROCEDURE - se inchid toate si se redeschid restul)
lcProcList = Set('Procedure')
SET PROCEDURE TO
FOR lnI = 1 TO GETWORDCOUNT(lcProcList, ',')
lcFile = ALLTRIM(GETWORDNUM(lcProcList, lnI, ','))
IF !EMPTY(lcFile) AND !("OFACTURARE_EDITARE" $ UPPER(lcFile))
SET PROCEDURE TO (lcFile) ADDITIVE
ENDIF
ENDFOR
Select tact
loForm = Createobject([frm_modific2024], lnIdSet)
loForm.WindowType = 0
loForm.Show()
lnPageCount = loForm.pgfArticole.PageCount
loForm.Release()
ENDIF
STRTOFILE('--- garda ofacturare_editare.prg lipsa, cod=' + TRANSFORM(tnCod) + ' ---' + CHR(13) + CHR(10) + ;
' PageCount = ' + TRANSFORM(lnPageCount) + ' (asteptat 2, ca pe ROACONT/ROAGEST)' + CHR(13) + CHR(10) + ;
' ' + IIF(lnPageCount == 2, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
IF Used('actactan')
Use In actactan
ENDIF
IF Used('tact')
Use In tact
ENDIF
IF Used('rul_temp')
Use In rul_temp
ENDIF
IF Used('trul')
Use In trul
ENDIF
IF Used('rul_temp_obinv')
Use In rul_temp_obinv
ENDIF
IF Used('trul_obinv')
Use In trul_obinv
ENDIF
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,40 @@
* test_repro_izolat_gnan.prg
* Experimentul B (cerut de team-lead): reproduce izolat, FARA nimic din S4 - fara
* IncarcaCursoareModificareNota, fara frm_modific2024, fara PAGE3. Doar init mediu +
* update_jtva_coloane singura. Daca dialogul "View Parameter" apare si aici, blocajul nu are
* nicio legatura cu modificarea S4 - e o capcana preexistenta a harness-ului/mediului.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_repro_izolat_gnan_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_repro_izolat_gnan_errhandler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
STRTOFILE(' TYPE(gnAn)=' + TYPE('gnAn') + ' TRANSFORM(gnAn)=' + TRANSFORM(gnAn) + ;
' TYPE(gnLuna)=' + TYPE('gnLuna') + ' TRANSFORM(gnLuna)=' + TRANSFORM(gnLuna) + CHR(13) + CHR(10), lcLog, 1)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\updateserver.prg ADDITIVE
update_jtva_coloane("", "crsJtvaTemp", 6)
STRTOFILE(' dupa update_jtva_coloane: Used(crsJtvaTemp)=' + TRANSFORM(Used('crsJtvaTemp')) + ;
' Reccount=' + IIF(Used('crsJtvaTemp'), TRANSFORM(Reccount('crsJtvaTemp')), '(n/a)') + CHR(13) + CHR(10), lcLog, 1)
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
PROCEDURE test_repro_izolat_gnan_errhandler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,55 @@
* test_scan_workarea.prg
* Verificare punctuala: IncarcaVanzareDinNota foloseste SCAN...ENDSCAN pe tmp_triplete_pozvanz, iar
* corpul buclei (IncarcaVanzareNota) schimba workarea curenta (creeaza/selecteaza tvanz). SCAN in VFP
* poate sa nu tolereze schimbarea workareai curente in interiorul buclei (SKIP/EOF() implicit la
* ENDSCAN se aplica pe workarea CURENTA, nu neaparat pe cea de la inceputul SCAN). Testul forteaza
* explicit cazul cu 2+ triplete unde primul NU se potriveste, ca sa verifice daca a doua iteratie
* chiar se executa (nu doar "a mers din intamplare" pe cod=1137874 unde ordinea DISTINCT ar fi putut
* pune din start tripletul corect primul).
* Nu atinge Oracle in scriere. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_scan_workarea_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
*!* construieste un cursor "tact" sintetic cu 2 triplete, ordonate explicit ca primul (INCASARE,
*!* nract=99999 fara corespondent in VANZARI) sa iasa PRIMUL din SELECT DISTINCT (fara ORDER BY,
*!* dar inserat primul si numeric mai mic), iar al doilea sa fie tripletul real (cod=1137874,
*!* nract=5, serie=FFFFF, data=27.08.2009) care CHIAR exista in VANZARI (id_vanzare=506)
CREATE CURSOR tact (cod I, nract I, serie_act C(20), dataact D, sters I)
INSERT INTO tact (cod, nract, serie_act, dataact, sters) VALUES (1137874, 1, '', {}, 0)
INSERT INTO tact (cod, nract, serie_act, dataact, sters) VALUES (1137874, 5, 'FFFFF', DATE(2009,8,27), 0)
LOCAL llGasit, lnIdVanzare
llGasit = IncarcaVanzareDinNota('tact')
lnIdVanzare = IIF(llGasit, tvanz.id_vanzare, -1)
STRTOFILE('--- SCAN cu workarea schimbata in corp: 2 triplete, primul fara corespondent ---' + CHR(13) + CHR(10) + ;
' gasit = ' + TRANSFORM(llGasit) + ' (asteptat .T.)' + CHR(13) + CHR(10) + ;
' id_vanzare = ' + TRANSFORM(lnIdVanzare) + ' (asteptat 506)' + CHR(13) + CHR(10) + ;
' ' + IIF(llGasit AND lnIdVanzare == 506, 'PASS', 'FAIL') + CHR(13) + CHR(10), lcLog, 1)
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,27 @@
* test_set_procedure.prg
* Verifica strict formatul intors de SET("PROCEDURE") in VFP9, dupa mai multe
* SET PROCEDURE TO ... ADDITIVE succesive, ca sa se stabileasca garda din omodificari.vc2 Show().
* Nu atinge Oracle, nu deschide formulare. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_set_procedure_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
STRTOFILE('dupa 1 SET PROCEDURE: [' + SET('PROCEDURE') + ']' + CHR(13) + CHR(10), lcLog, 1)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\oproceduri_facturare.prg ADDITIVE
STRTOFILE('dupa 2 SET PROCEDURE (alt fisier ADDITIVE): [' + SET('PROCEDURE') + ']' + CHR(13) + CHR(10), lcLog, 1)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_stoc.prg ADDITIVE
STRTOFILE('dupa 3 SET PROCEDURE (al treilea fisier ADDITIVE): [' + SET('PROCEDURE') + ']' + CHR(13) + CHR(10), lcLog, 1)
LOCAL llGasit
llGasit = "OFACTURARE_EDITARE" $ UPPER(SET('PROCEDURE'))
STRTOFILE('contine OFACTURARE_EDITARE dupa 3 seturi: ' + TRANSFORM(llGasit) + CHR(13) + CHR(10), lcLog, 1)
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT

View File

@@ -0,0 +1,523 @@
* test_writeback_buton1.prg
* Test REAL de write-back pentru ramura buton=1 a lui frm_facturi.do_editare_factura
* (COMUN\clase\ofacturare_comun.vc2:3805-3840) - APROBAT explicit de Marius pe 08.08.2026 sa
* scrie in schema de dev MARIUSM_AUTO@ROA_CENTRAL (nu doar sa citeasca).
*
* Document consumat: cod=1140886, id_vanzare=1048 (factura tip 1, 07-AUG-26, total_cu_tva=302.51,
* 1 linie in VANZARI_DETALII, 5 randuri in ACT, id_set=25010, id_fact=8009658, 1 rand in RUL).
* NU foloseste cod=1140888/1140885 (baze de regresie ale test_incarca_cursoare.prg).
*
* Harness, nu apel direct al metodei: nu instantiaza frm_facturi si NU mai instantiaza
* frm_modific2024 deloc (incercarea initiala s-a blocat la Createobject/Show pe un dialog nativ
* Windows "Open" - cursor/tabela lipsa in acest mediu minimal, capcana j din testare-ui-vfp.md -
* fara legatura cu calea de scriere care se testeaza aici). In loc, harnessul:
* 1) reproduce exact starea de cursoare pe care do_editare_factura o lasa inainte de
* Createobject('frm_modific2024',...) (IncarcaCursoareModificareNota, functia reala din
* ofacturare_editare.prg);
* 2) seteaza buton=1 direct (SARE peste inainte_de_do_termin - vezi ATENTIE mai jos);
* 3) ruleaza LITERAL codul ramurii buton=1 (copiat din ofacturare_comun.vc2:3805-3840).
* Thisform.do_deschide_tranzactie/do_inchide_tranzactie (mostenite nemodificate din _frm_base,
* fara dependinta de vreo clasa de formular anume) sunt reproduse local, INLINE, dupa codul din
* _frm_base.vc2:252-302 - ocolesc si instantierea unui _frmbase generic, ca sa nu riste acelasi
* fel de blocaj vazut la frm_modific2024.
*
* ATENTIE - ce NU acopera acest test: validarea din inainte_de_do_termin
* (omodificari.vc2:13357-13549 - verificare_note_contabile, echilibru 4426-4428,
* VerificaAvertizareExigibilizareTVA) si comportamentul real al formularului la butonul
* "Terminat". Testul demonstreaza ca LANTUL DE SCRIERE merge, nu ca utilizatorul ajunge la el
* prin UI - cele doua nu trebuie confundate la interpretarea rezultatului.
*
* Mediu: test_init_env_auto.prg (bootstrap ROACONT, conexiune reala MARIUSM_AUTO) - acelasi mediu
* folosit deja cu succes de test_incarca_cursoare.prg si test_page3_articole.prg. oscrie_in_fisiere.prg
* e incarcat explicit din COMUN-ul ROAFACTURARE (nu cel auto-rezolvat din calea ROACONT) ca sa
* ruleze exact fisierul pe care il ruleaza aplicatia.
*
* Ruleaza 2 treceri pe acelasi document (cod-ul se schimba dupa fiecare salvare, se recitesc din
* VANZARI la fiecare trecere):
* TEST 1 - salvare "goala" (fara nicio modificare in tact) - proba ca lantul chiar scrie.
* TEST 2 - modifica explicatia unui rand ACT inainte de salvare - proba ca modificarea ajunge.
*
* Nu atinge .PJX/.PJT/.exe, nu modifica cod aplicatie. QUIT la final.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_writeback_buton1_log.txt'
STRTOFILE('start ' + TTOC(DATETIME()) + CHR(13) + CHR(10), lcLog)
PUBLIC gcErrLog
gcErrLog = lcLog
ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
*-- mock amessagebox INCARCAT PRIMUL (inaintea lantului din test_init_env_auto, care incarca
*-- amessagebox real) - la nume duplicat de procedura, castiga fisierul cautat PRIMUL (testare-ui-vfp.md, capcana g)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg ADDITIVE
DO ('D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_init_env_auto.prg') WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
IF gnHandle <= 0
STRTOFILE('EROARE: conectare esuata' + CHR(13) + CHR(10), lcLog, 1)
QUIT
ENDIF
*-- verificare ca mock-ul chiar umbreste amessebox real (altfel un dialog real ar bloca headless)
LOCAL lnVerifMock
lnVerifMock = amessagebox('verificare mock', 4+32, 'test')
STRTOFILE('verificare mock amessagebox = ' + TRANSFORM(lnVerifMock) + ;
IIF(lnVerifMock = 6, ' (OK, mock activ)', ' (ATENTIE: real amessagebox activ, risc de blocaj)') + CHR(13) + CHR(10), lcLog, 1)
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE
SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\oscrie_in_fisiere.prg ADDITIVE
IF TYPE('gnPC') <> 'N'
PUBLIC gnPC
gnPC = 2
ENDIF
*-- capteaza textul ultimului amessagebox mocked (mock_amessagebox.prg, liniile 13-14/23-26) -
*-- necesar ca sa vedem CE mesaj de eroare arunca oscrie_in_fisiere.prg pe caile de esec
PUBLIC gcMockUltimMesaj, gnMockUltimTip
gcMockUltimMesaj = ''
gnMockUltimTip = 0
STRTOFILE('gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) + ' gcS=' + gcS + CHR(13) + CHR(10), lcLog, 1)
DO test_editare_writeback WITH 1048, .F., 'TEST 1: salvare fara nicio modificare', lcLog
DO test_editare_writeback WITH 1048, .T., 'TEST 2: modificare explicatie pe un rand ACT', lcLog
STRTOFILE('done ' + TTOC(DATETIME()) + CHR(13) + CHR(10), lcLog, 1)
QUIT
*-- executa SELECT-ul agregat prin goExecutor si intoarce lnSucces; NU citi campurile cursorului
*-- decat dupa ce ai verificat lnSucces > 0 (IIF() evalueaza ambele ramuri, ar da eroare pe alias lipsa)
PROCEDURE ExecAgg
LPARAMETERS tcSql, tcCursor
LOCAL lnQ
IF USED(tcCursor)
USE IN (tcCursor)
ENDIF
lnQ = goExecutor.oExecute(tcSql, tcCursor)
RETURN lnQ
ENDPROC
*-- logheaza si RESETEAZA gcMockUltimMesaj/goExecutor.cEroare - reseteaza ca sa nu se confunde
*-- mesajul de la un pas cu mesajul (sau lipsa lui) de la pasul urmator
PROCEDURE LogMockSiEroare
LPARAMETERS tcEticheta, tcLog
STRTOFILE(' [' + tcEticheta + '] gcMockUltimMesaj=[' + ALLTRIM(gcMockUltimMesaj) + '] ' + ;
'goExecutor.cEroare=[' + ALLTRIM(TRANSFORM(NVL(goExecutor.cEroare, ''))) + ']' + CHR(13) + CHR(10), tcLog, 1)
gcMockUltimMesaj = ''
ENDPROC
*-- reproduce _frm_base.vc2:252-265 (do_deschide_tranzactie) fara sa instantieze niciun formular
PROCEDURE MyDeschideTranzactie
LOCAL llReturn, lnSuccesLocal
IF TYPE('goExecutor') = 'O'
goExecutor.oExecuta([select * from dual])
ENDIF
lnSuccesLocal = SQLSetprop(gnHandle, "Transactions", 2)
llReturn = IIF(lnSuccesLocal < 0, .F., .T.)
RETURN llReturn
ENDPROC
*-- reproduce _frm_base.vc2:279-302 (do_inchide_tranzactie) fara sa instantieze niciun formular
PROCEDURE MyInchideTranzactie
LPARAMETERS tnTip
LOCAL llReturn, lnSuccesLocal
IF tnTip = 1
lnSuccesLocal = SQLCOMMIT(gnHandle)
ELSE
lnSuccesLocal = SQLROLLBACK(gnHandle)
ENDIF
IF lnSuccesLocal < 0
llReturn = .F.
ELSE
lnSuccesLocal = SQLSetprop(gnHandle, "Transactions", 1)
llReturn = IIF(lnSuccesLocal < 0, .F., .T.)
ENDIF
RETURN llReturn
ENDPROC
PROCEDURE test_editare_writeback
LPARAMETERS tnIdVanzare, tlModificaLinie, tcEticheta, tcLog
*-- pnAn/pnLuna/lnCod/lnIdFact PRIVATE (nu LOCAL), identic cu declararea reala
*-- (ofacturare_comun.vc2:3742) - finalizeaza_modificare_nota le foloseste ca bind-variabile
*-- ?pnLuna/?pnAn in interiorul lui goExecutor.oExecuta, care le cere vizibile PRIVATE pe stiva
PRIVATE pnAn, pnLuna, lnCod, lnIdFact
LOCAL lnSters, llEProforma
LOCAL lnIdSet, lnIdFactD, lnSucces, llGasitRand
LOCAL lcSql, lnQ
LOCAL lnActBeforeCnt, lnActBeforeSuma, lnRulBeforeCnt, lnRulObinvBeforeCnt
LOCAL lnVdCnt, lnVdSumaPret, lnVdSumaPretCuTva
LOCAL lcExplicatieVeche, lcExplicatieNoua
LOCAL lnVzCodBefore, lnVzStersBefore, lnVzTotalFaraTvaBefore, lnVzTotalTvaBefore, lnVzTotalCuTvaBefore, lnVzDiscountBefore
STRTOFILE(CHR(13) + CHR(10) + '========== ' + tcEticheta + ' (id_vanzare=' + TRANSFORM(tnIdVanzare) + ') ==========' + CHR(13) + CHR(10), tcLog, 1)
*-- 1) starea curenta din VANZARI (cod-ul se poate schimba fata de trecerea anterioara)
lcSql = [select cod, sters, id_fact, eproforma, total_fara_tva, total_tva, total_cu_tva, discount, ] + ;
[extract(year from data_act) as anact, extract(month from data_act) as lunaact from vanzari where id_vanzare = ] + TRANSFORM(tnIdVanzare)
lnQ = ExecAgg(lcSql, 'v_vanzare_curenta')
IF lnQ <= 0 OR RECCOUNT('v_vanzare_curenta') <> 1
STRTOFILE('FAIL: VANZARI id_vanzare=' + TRANSFORM(tnIdVanzare) + ' - lnQ=' + TRANSFORM(lnQ) + ;
' reccount=' + IIF(lnQ > 0, TRANSFORM(RECCOUNT('v_vanzare_curenta')), '?') + ;
' cEroare=[' + ALLTRIM(TRANSFORM(NVL(goExecutor.cEroare, ''))) + ']' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
SELECT v_vanzare_curenta
lnCod = cod
lnSters = sters
lnIdFact = id_fact
llEProforma = (eproforma = 1)
pnAn = anact
pnLuna = lunaact
lnVzCodBefore = cod
lnVzStersBefore = sters
lnVzTotalFaraTvaBefore = total_fara_tva
lnVzTotalTvaBefore = total_tva
lnVzTotalCuTvaBefore = total_cu_tva
lnVzDiscountBefore = discount
USE IN v_vanzare_curenta
STRTOFILE(' VANZARI inainte: cod=' + TRANSFORM(lnCod) + ' sters=' + TRANSFORM(lnSters) + ' id_fact=' + TRANSFORM(lnIdFact) + ;
' an/luna=' + TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna) + ' total_cu_tva=' + TRANSFORM(lnVzTotalCuTvaBefore) + CHR(13) + CHR(10), tcLog, 1)
*-- 2) garzi (replica do_editare_factura, fara UI)
IF lnSters = 1
STRTOFILE(' SKIP: document deja sters' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
IF llEProforma
STRTOFILE(' SKIP: proforma' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
IF (pnAn*12) + pnLuna <> (gnAn*12) + gnLuna
STRTOFILE(' SKIP: nu e luna curenta (document ' + TRANSFORM(pnAn) + '/' + TRANSFORM(pnLuna) + ', curenta ' + TRANSFORM(gnAn) + '/' + TRANSFORM(gnLuna) + ')' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
IF EsteInEFactura(lnIdFact)
STRTOFILE(' SKIP: trimis in eFactura' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
*-- 3) instantaneu INAINTE: ACT / RUL / RUL_OBINV (pe cod-ul curent) + VANZARI_DETALII
lcSql = [select count(*) as cnt, sum(suma) as totsuma from vact_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCod)
lnQ = ExecAgg(lcSql, 'v_act_before')
IF lnQ > 0
lnActBeforeCnt = v_act_before.cnt
lnActBeforeSuma = NVL(v_act_before.totsuma, 0)
USE IN v_act_before
ELSE
lnActBeforeCnt = -1
lnActBeforeSuma = -1
ENDIF
lcSql = [select count(*) as cnt from vrul_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCod)
lnQ = ExecAgg(lcSql, 'v_rul_before')
IF lnQ > 0
lnRulBeforeCnt = v_rul_before.cnt
USE IN v_rul_before
ELSE
lnRulBeforeCnt = -1
ENDIF
lcSql = [select count(*) as cnt from vrul_obinv_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCod)
lnQ = ExecAgg(lcSql, 'v_rulobinv_before')
IF lnQ > 0
lnRulObinvBeforeCnt = v_rulobinv_before.cnt
USE IN v_rulobinv_before
ELSE
lnRulObinvBeforeCnt = -1
ENDIF
lcSql = [select count(*) as cnt, sum(cantitate) as sumcant, sum(pret) as sumpret, sum(pret_cu_tva) as sumpretcutva ] + ;
[from vanzari_detalii where sters = 0 and id_vanzare = ] + TRANSFORM(tnIdVanzare)
lnQ = ExecAgg(lcSql, 'v_vd_before')
IF lnQ > 0
lnVdCnt = v_vd_before.cnt
lnVdSumaPret = NVL(v_vd_before.sumpret, 0)
lnVdSumaPretCuTva = NVL(v_vd_before.sumpretcutva, 0)
USE IN v_vd_before
ELSE
lnVdCnt = -1
lnVdSumaPret = -1
lnVdSumaPretCuTva = -1
ENDIF
STRTOFILE(' INAINTE: ACT cnt=' + TRANSFORM(lnActBeforeCnt) + ' suma=' + TRANSFORM(lnActBeforeSuma) + ;
' RUL cnt=' + TRANSFORM(lnRulBeforeCnt) + ' RUL_OBINV cnt=' + TRANSFORM(lnRulObinvBeforeCnt) + ;
' VANZARI_DETALII cnt=' + TRANSFORM(lnVdCnt) + ' sum(pret)=' + TRANSFORM(lnVdSumaPret) + ' sum(pret_cu_tva)=' + TRANSFORM(lnVdSumaPretCuTva) + CHR(13) + CHR(10), tcLog, 1)
*-- 4) IncarcaCursoareModificareNota (functia reala, ofacturare_editare.prg)
IF !IncarcaCursoareModificareNota(lnCod, pnAn, pnLuna, .F.)
STRTOFILE(' FAIL: IncarcaCursoareModificareNota a esuat (eroare Oracle)' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
IF RECCOUNT('actactan') = 0
STRTOFILE(' FAIL: nu exista nota contabila (Reccount(actactan)=0)' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
*-- 5) pozitionare id_fact/id_set/id_factd - copiat identic din do_editare_factura
*-- (ofacturare_comun.vc2:3785-3797; garda id_set scoasa - decizia 24, cod curent nu o mai are)
SELECT actactan
llGasitRand = .F.
IF lnIdFact > 0
LOCATE FOR NVL(id_fact, 0) = lnIdFact
llGasitRand = FOUND()
ENDIF
IF !llGasitRand
GO TOP
lnIdFact = id_fact
ENDIF
lnIdSet = id_set
lnIdFactD = NVL(id_factd, 0)
STRTOFILE(' pozitionare actactan: gasit=' + TRANSFORM(llGasitRand) + ' id_fact=' + TRANSFORM(lnIdFact) + ;
' id_set=' + TRANSFORM(lnIdSet) + ' id_factd=' + TRANSFORM(lnIdFactD) + CHR(13) + CHR(10), tcLog, 1)
SELECT a.*, IIF(NVL(id_jtva_coloana, 0) = 0, 0, 1) AS cu_Tva FROM tact a INTO CURSOR tact READWRITE
*-- 6) TEST 2: modifica un camp simplu si verificabil (explicatia) INAINTE de salvare
lcExplicatieVeche = ''
lcExplicatieNoua = ''
IF tlModificaLinie
SELECT tact
LOCATE FOR !EMPTY(ALLTRIM(NVL(explicatia, '')))
IF FOUND()
lcExplicatieVeche = ALLTRIM(explicatia)
lcExplicatieNoua = lcExplicatieVeche + ' (test writeback)'
REPLACE explicatia WITH lcExplicatieNoua
STRTOFILE(' modific tact.explicatia: [' + lcExplicatieVeche + '] -> [' + lcExplicatieNoua + ']' + CHR(13) + CHR(10), tcLog, 1)
ELSE
STRTOFILE(' ATENTIE: nu am gasit niciun rand cu explicatia completata, testul nu modifica nimic real' + CHR(13) + CHR(10), tcLog, 1)
ENDIF
ENDIF
*-- 7) frm_modific2024 OCOLIT COMPLET (a blocat Createobject/Show pe dialog nativ "Open" -
*-- vezi antetul fisierului). buton=1 fortat direct - inainte_de_do_termin NU se executa.
buton = 1
STRTOFILE(' frm_modific2024 ocolit: buton=1 fortat direct, inainte_de_do_termin SARIT' + CHR(13) + CHR(10), tcLog, 1)
*-- 8) ramura buton=1 din do_editare_factura (ofacturare_comun.vc2:3805-3840), copiata identic;
*-- Thisform.do_deschide_tranzactie/do_inchide_tranzactie sunt reproduse INLINE mai jos
*-- (MyDeschideTranzactie/MyInchideTranzactie, dupa _frm_base.vc2:252-302) - fara sa instantieze
*-- niciun formular, ca sa nu riste acelasi blocaj vazut la frm_modific2024
lnSucces = 0
TRY
STRTOFILE(' [chk] inainte de MyDeschideTranzactie()' + CHR(13) + CHR(10), tcLog, 1)
IF MyDeschideTranzactie()
STRTOFILE(' [chk] MyDeschideTranzactie() => .T., inainte de OSCRIE_IN_FISIERE(2,...)' + CHR(13) + CHR(10), tcLog, 1)
SELECT actactan
lnSucces = OSCRIE_IN_FISIERE(2, .T., .T.)
STRTOFILE(' [chk] OSCRIE_IN_FISIERE(2,...) => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1)
LogMockSiEroare('dupa OSCRIE_IN_FISIERE(2,...)', tcLog)
IF lnSucces > 0
IF USED('actactan')
USE IN actactan
ENDIF
SELECT tact
REPLACE id_jtva_coloana WITH NULL, proc_tva WITH 0 FOR cu_Tva = 0
SELECT * FROM tact INTO CURSOR actactan READWRITE
REPLACE ALL id_util WITH gnIdUtil, sters WITH 0
IF USED('rul_temp')
USE IN rul_temp
ENDIF
SELECT * FROM trul INTO CURSOR RUL_TEMP READWRITE
REPLACE ALL id_util WITH gnIdUtil, sters WITH 0
IF USED('rul_temp_obinv')
USE IN rul_temp_obinv
ENDIF
SELECT * FROM trul_obinv INTO CURSOR RUL_TEMP_OBINV READWRITE
REPLACE ALL id_util WITH gnIdUtil, sters WITH 0
STRTOFILE(' [chk] cursoare rebuild OK, inainte de OSCRIE_IN_FISIERE(0,...)' + CHR(13) + CHR(10), tcLog, 1)
lnSucces = OSCRIE_IN_FISIERE(0, .T., .T.)
STRTOFILE(' [chk] OSCRIE_IN_FISIERE(0,...) => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1)
LogMockSiEroare('dupa OSCRIE_IN_FISIERE(0,...)', tcLog)
ENDIF
IF lnSucces > 0
STRTOFILE(' [chk] inainte de pack_contafin.finalizeaza_modificare_nota' + CHR(13) + CHR(10), tcLog, 1)
lcSql = [begin pack_contafin.finalizeaza_modificare_nota(?pnLuna,?pnAn,Null,] + ALLTRIM(STR(lnIdSet)) + [,] + ;
ALLTRIM(STR(lnCod)) + [,] + ALLTRIM(STR(lnIdFact)) + [,] + ALLTRIM(STR(lnIdFactD)) + [,?gnIdUtil); end;]
STRTOFILE(' [chk] SQL finalizeaza_modificare_nota = [' + lcSql + ']' + CHR(13) + CHR(10), tcLog, 1)
lnSucces = IIF(goExecutor.oExecuta(lcSql), 1, -1)
STRTOFILE(' [chk] finalizeaza_modificare_nota => ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1)
LogMockSiEroare('dupa finalizeaza_modificare_nota', tcLog)
ENDIF
STRTOFILE(' lnSucces dupa lant scriere = ' + TRANSFORM(lnSucces) + CHR(13) + CHR(10), tcLog, 1)
STRTOFILE(' [chk] inainte de MyInchideTranzactie' + CHR(13) + CHR(10), tcLog, 1)
IF MyInchideTranzactie(IIF(lnSucces < 0, 2, 1))
STRTOFILE(' tranzactie inchisa cu ' + IIF(lnSucces < 0, 'ROLLBACK', 'COMMIT') + CHR(13) + CHR(10), tcLog, 1)
ELSE
STRTOFILE(' FAIL la do_inchide_tranzactie' + CHR(13) + CHR(10), tcLog, 1)
ENDIF
ELSE
STRTOFILE(' FAIL: do_deschide_tranzactie a esuat' + CHR(13) + CHR(10), tcLog, 1)
ENDIF
CATCH TO loExc
STRTOFILE(' EXCEPTIE in lantul de scriere: ' + TRANSFORM(loExc.ErrorNo) + ' [' + loExc.Message + '] ' + ;
loExc.Procedure + ':' + TRANSFORM(loExc.LineNo) + ' -> ROLLBACK' + CHR(13) + CHR(10), tcLog, 1)
lnSucces = -99
MyInchideTranzactie(2)
ENDTRY
IF USED('actactan')
USE IN actactan
ENDIF
IF USED('tact')
USE IN tact
ENDIF
IF USED('rul_temp')
USE IN rul_temp
ENDIF
IF USED('trul')
USE IN trul
ENDIF
IF USED('rul_temp_obinv')
USE IN rul_temp_obinv
ENDIF
IF USED('trul_obinv')
USE IN trul_obinv
ENDIF
IF lnSucces <= 0
STRTOFILE(' TEST FAIL - scrierea nu s-a produs (lnSucces=' + TRANSFORM(lnSucces) + '), fara verificari after' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
*-- 9) instantaneu DUPA + verificarile 1-5 cerute
LOCAL lnCodNou, lnVzStersAfter, llV3ok
lcSql = [select cod, sters, id_fact, total_fara_tva, total_tva, total_cu_tva, discount from vanzari where id_vanzare = ] + TRANSFORM(tnIdVanzare)
lnQ = ExecAgg(lcSql, 'v_vanzare_dupa')
IF lnQ <= 0 OR RECCOUNT('v_vanzare_dupa') <> 1
STRTOFILE(' FAIL: VANZARI dupa - nu am gasit exact 1 rand' + CHR(13) + CHR(10), tcLog, 1)
RETURN
ENDIF
SELECT v_vanzare_dupa
lnCodNou = cod
lnVzStersAfter = sters
llV3ok = (lnCodNou <> lnVzCodBefore) AND (lnVzStersAfter = 0) AND (id_fact == lnIdFact) AND ;
(ABS(total_fara_tva - lnVzTotalFaraTvaBefore) < 0.01) AND (ABS(total_tva - lnVzTotalTvaBefore) < 0.01) AND ;
(ABS(total_cu_tva - lnVzTotalCuTvaBefore) < 0.01) AND (ABS(discount - lnVzDiscountBefore) < 0.01)
STRTOFILE(' [3] VANZARI dupa: cod=' + TRANSFORM(lnCodNou) + ' (era ' + TRANSFORM(lnVzCodBefore) + ') sters=' + TRANSFORM(lnVzStersAfter) + ;
' id_fact=' + TRANSFORM(id_fact) + ' total_cu_tva=' + TRANSFORM(total_cu_tva) + ' -> ' + IIF(llV3ok, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
USE IN v_vanzare_dupa
*-- [1] ACT: randurile vechi STERS=1 pe cod vechi; randuri noi pe cod nou, acelasi id_fact, aceeasi suma (daca nemodificat)
LOCAL lnActVechiCnt, lnActVechiSumSters, lnActNouCnt, lnActNouSuma, llV1ok
lcSql = [select count(*) as cnt, sum(sters) as sumsters from vact_tot where an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnVzCodBefore)
lnQ = ExecAgg(lcSql, 'v_act_vechi_dupa')
IF lnQ > 0
lnActVechiCnt = v_act_vechi_dupa.cnt
lnActVechiSumSters = NVL(v_act_vechi_dupa.sumsters, 0)
USE IN v_act_vechi_dupa
ELSE
lnActVechiCnt = -1
lnActVechiSumSters = -1
ENDIF
lcSql = [select count(*) as cnt, sum(suma) as totsuma from vact_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCodNou)
lnQ = ExecAgg(lcSql, 'v_act_nou_dupa')
IF lnQ > 0
lnActNouCnt = v_act_nou_dupa.cnt
lnActNouSuma = NVL(v_act_nou_dupa.totsuma, 0)
USE IN v_act_nou_dupa
ELSE
lnActNouCnt = -1
lnActNouSuma = -1
ENDIF
llV1ok = (lnActVechiCnt = lnActBeforeCnt) AND (lnActVechiSumSters = lnActVechiCnt) AND (lnActNouCnt = lnActBeforeCnt) AND ;
(IIF(tlModificaLinie, .T., ABS(lnActNouSuma - lnActBeforeSuma) < 0.01))
STRTOFILE(' [1] ACT: vechi(cod=' + TRANSFORM(lnVzCodBefore) + ') cnt=' + TRANSFORM(lnActVechiCnt) + ' toate sters=' + TRANSFORM(lnActVechiSumSters = lnActVechiCnt) + ;
'; nou(cod=' + TRANSFORM(lnCodNou) + ') cnt=' + TRANSFORM(lnActNouCnt) + ' suma=' + TRANSFORM(lnActNouSuma) + ;
' (era ' + TRANSFORM(lnActBeforeSuma) + ') -> ' + IIF(llV1ok, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
*-- [2] RUL: acelasi tipar (daca documentul are randuri RUL)
LOCAL lnRulVechiCnt, lnRulVechiSumSters, lnRulNouCnt, llV2ok
lcSql = [select count(*) as cnt, sum(sters) as sumsters from vrul_tot where an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnVzCodBefore)
lnQ = ExecAgg(lcSql, 'v_rul_vechi_dupa')
IF lnQ > 0
lnRulVechiCnt = v_rul_vechi_dupa.cnt
lnRulVechiSumSters = NVL(v_rul_vechi_dupa.sumsters, 0)
USE IN v_rul_vechi_dupa
ELSE
lnRulVechiCnt = -1
lnRulVechiSumSters = -1
ENDIF
lcSql = [select count(*) as cnt from vrul_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCodNou)
lnQ = ExecAgg(lcSql, 'v_rul_nou_dupa')
IF lnQ > 0
lnRulNouCnt = v_rul_nou_dupa.cnt
USE IN v_rul_nou_dupa
ELSE
lnRulNouCnt = -1
ENDIF
llV2ok = (lnRulVechiCnt = lnRulBeforeCnt) AND (lnRulVechiSumSters = lnRulVechiCnt) AND (lnRulNouCnt = lnRulBeforeCnt)
STRTOFILE(' [2] RUL: vechi cnt=' + TRANSFORM(lnRulVechiCnt) + ' toate sters=' + TRANSFORM(lnRulVechiSumSters = lnRulVechiCnt) + ;
'; nou cnt=' + TRANSFORM(lnRulNouCnt) + ' (era ' + TRANSFORM(lnRulBeforeCnt) + ') -> ' + IIF(llV2ok, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
*-- [4] VANZARI_DETALII: neatins de aceasta cale
LOCAL lnVdCntDupa, lnVdSumaPretDupa, lnVdSumaPretCuTvaDupa, llV4ok
lcSql = [select count(*) as cnt, sum(cantitate) as sumcant, sum(pret) as sumpret, sum(pret_cu_tva) as sumpretcutva ] + ;
[from vanzari_detalii where sters = 0 and id_vanzare = ] + TRANSFORM(tnIdVanzare)
lnQ = ExecAgg(lcSql, 'v_vd_dupa')
IF lnQ > 0
lnVdCntDupa = v_vd_dupa.cnt
lnVdSumaPretDupa = NVL(v_vd_dupa.sumpret, 0)
lnVdSumaPretCuTvaDupa = NVL(v_vd_dupa.sumpretcutva, 0)
USE IN v_vd_dupa
ELSE
lnVdCntDupa = -1
lnVdSumaPretDupa = -1
lnVdSumaPretCuTvaDupa = -1
ENDIF
llV4ok = (lnVdCntDupa = lnVdCnt) AND (ABS(lnVdSumaPretDupa - lnVdSumaPret) < 0.01) AND (ABS(lnVdSumaPretCuTvaDupa - lnVdSumaPretCuTva) < 0.01)
STRTOFILE(' [4] VANZARI_DETALII: cnt=' + TRANSFORM(lnVdCntDupa) + ' (era ' + TRANSFORM(lnVdCnt) + ') sum(pret)=' + TRANSFORM(lnVdSumaPretDupa) + ;
' (era ' + TRANSFORM(lnVdSumaPret) + ') -> ' + IIF(llV4ok, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
*-- [5] lnSucces>0 pe tot lantul + tranzactia inchisa cu commit (deja logat mai sus, sintetizat aici)
STRTOFILE(' [5] lnSucces final = ' + TRANSFORM(lnSucces) + ' -> ' + IIF(lnSucces > 0, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
*-- verificare suplimentara TEST 2: explicatia modificata ajunge efectiv in ACT pe randul nou
IF tlModificaLinie AND !EMPTY(lcExplicatieNoua)
LOCAL lnExplicatieCnt
lcSql = [select count(*) as cnt from vact_tot where sters = 0 and an = ] + TRANSFORM(pnAn) + ;
[ and luna = ] + TRANSFORM(pnLuna) + [ and cod = ] + TRANSFORM(lnCodNou) + ;
[ and explicatia = '] + STRTRAN(lcExplicatieNoua, "'", "''") + [']
lnQ = ExecAgg(lcSql, 'v_act_explicatie')
IF lnQ > 0
lnExplicatieCnt = v_act_explicatie.cnt
USE IN v_act_explicatie
ELSE
lnExplicatieCnt = -1
ENDIF
STRTOFILE(' [2b] explicatia modificata ajunge in ACT: cnt=' + TRANSFORM(lnExplicatieCnt) + ' -> ' + IIF(lnExplicatieCnt = 1, 'PASS', 'FAIL') + CHR(13) + CHR(10), tcLog, 1)
ENDIF
STRTOFILE(' REZUMAT ' + tcEticheta + ': cod ' + TRANSFORM(lnVzCodBefore) + ' -> ' + TRANSFORM(lnCodNou) + CHR(13) + CHR(10), tcLog, 1)
ENDPROC
PROCEDURE test_error_handler
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
STRTOFILE('EROARE ' + TRANSFORM(tnError) + ' [' + tcProgram + ':' + TRANSFORM(tnLineNo) + '] ' + tcMessage + CHR(13) + CHR(10), gcErrLog, 1)
ENDPROC

View File

@@ -0,0 +1,663 @@
* test_pret_cu_tva_dialog.prg
* Test UI Nivel 1 (S5, plan #7) pentru dialogul PER-ARTICOL real, clasa frm_articol_factura din
* COMUN\clase\ofacturare.vc2. Instantiaza clasa exact cum o instantiaza aplicatia in
* frm_facturare_articole.do_adauga_articol (ofacturare.vc2:12869):
* Createobject("frm_articol_factura", lnCantitate, tlImplicit)
* apoi exerseaza handlerele REALE (ck_pret_cu_tva.InteractiveChange, Clb_pretctva.tx_suma_nat.
* InteractiveChange, Clb_discountctva.tx_suma_nat.Valid) - nu populeaza direct poArticol cu
* rezultate calculate manual, doar cu DATELE DE INTRARE (pretul tastat, bifa), exact ce ar
* introduce utilizatorul. poArticol se construieste ca obiect liber (CREATEOBJECT+ADDPROPERTY),
* echivalent cu Scatter Name poArticol MEMO din crsarticole (acelasi shape de date), pentru ca
* testul sa ramana independent de Oracle si de celelalte doua griduri ale formularului parinte.
*
* Nivel 2 (flux complet prin frm_facturare_articole, propagare in crsfactura, buton
* but_modificare din S2b) NU e acoperit aici - vezi docs\cercetare\rec_s5_teste.md pentru motiv.
*
* Pasi (vezi vfp_ui_harness.ps1 -Steps):
* 0 mediu pregatit
* 1 cazul tinta: bifa=1, pret tastat 100.00 cu TVA, cantitate 1 -> total exact 100.00
* 2 comutare bifa OFF->ON: pretul fara TVA tastat nu se pierde
* 3 comutare bifa ON->OFF: pretul cu TVA tastat nu se pierde
* 4 cota standard 21%
* 5 cota redusa 11%
* 6 discount unitar cu TVA (ramura discountctva)
* 7 bifa activa pe tip de document din lista (Inlist 1,5,10,22,23,25,29,41)
* 8 bifa dezactivata pe tip din afara listei, cu pret nenul
* 9 final
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog, gcSyncDir
gcUILog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\test_pret_cu_tva_dialog_log.txt"
gcSyncDir = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\uisync\"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAFACTURARE\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + ;
gcAppPath + 'COMUN\UTILE\CALENDAR;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EMAIL;' + ;
gcAppPath + 'COMUN\UTILE\NFJSON;' + gcAppPath + 'COMUN\UTILE\NFXML;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO AfLog WITH 'SET PATH OK'
*----- CLASE (lista din Programe\roafacturare.prg, scopul minim pentru ofacturare.vcx) -----
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms ADDITIVE
SET CLASSLIB TO ofacturare.vcx ADDITIVE
SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO ofacturare_rapoarte ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO onom_curs ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO ferestre_cere_date ADDITIVE
SET CLASSLIB TO baza ADDITIVE
SET CLASSLIB TO caut ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO serii_numere ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO _calendar.vcx ADDITIVE
SET CLASSLIB TO locale ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ocomenzi ADDITIVE
DO AfLog WITH 'SET CLASSLIB OK'
*----- PROCEDURI (mock amessagebox PRIMUL, ui_harness la final) -----
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg"
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO onomenclatoare.prg ADDITIVE
SET PROCEDURE TO onomenclatoare2.prg ADDITIVE
SET PROCEDURE TO oproceduri_rapoarte_fact.prg ADDITIVE
SET PROCEDURE TO email.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO odocumente ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO cauta_alfa.prg ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO oproceduri_curs.prg ADDITIVE
SET PROCEDURE TO proceduri.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO ofacturare.prg ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO wwApi.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO ofacturare_comun.prg ADDITIVE
SET PROCEDURE TO ofacturare_stoc.prg ADDITIVE
SET PROCEDURE TO pmenu.prg ADDITIVE
SET PROCEDURE TO ointroduceri.prg ADDITIVE
SET PROCEDURE TO ovariabile_globale.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO filebringer.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO oupdate.prg ADDITIVE
SET PROCEDURE TO procese.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO wwhttp.prg ADDITIVE
SET PROCEDURE TO xmlaccess.prg ADDITIVE
SET PROCEDURE TO xmlparser.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO suma_in_vorbe.prg ADDITIVE
SET PROCEDURE TO controllerecr ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
DO AfLog WITH 'SET PROCEDURE OK'
*----- Globale aplicatie cerute de frm_articol_factura / calculeaza_totaluri -----
PUBLIC gnPc, gnPVal, gnPcant, gnPPretV, gnScadereStoc, gnMemProcDisc, gl406, gcAcces
gnPc = 2 && precizie sume lei
gnPVal = 2 && precizie sume valuta
gnPcant = 3 && precizie cantitate (doar pt. InputMask)
gnPPretV = 4 && precizie unitara pret/tva/discount
gnScadereStoc = 0 && ocoleste ramura serie/lot needitabila si clb_procent_adaos
gnMemProcDisc = 0 && ocoleste memorarea procentului de discount intre articole
gl406 = .F. && SAFT dezactivat - flagul pret_cu_tva nu are legatura cu taxcode
gcAcces = "1;2;3;4;5;6;7;8;"
PUBLIC nror(65000)
PUBLIC goApp
goApp = CREATEOBJECT('dummyapp')
*----- jtva_coloane: cotele curente (regim post 01.08.2025) - 21% standard, 11% redusa -----
IF USED('jtva_coloane')
USE IN ('jtva_coloane')
ENDIF
CREATE CURSOR jtva_coloane (id_jtva_coloana N(14), denumire C(50), cota_tva N(6,2))
INSERT INTO jtva_coloane VALUES (1, 'TVA 21%', 21)
INSERT INTO jtva_coloane VALUES (2, 'TVA 11%', 11)
GO TOP IN jtva_coloane
*----- saft_taxtable: desi gl406=.F. (codul aplicatiei nu-l cere explicit), cb_explicatie_saft
* din frm_articol_factura are RowSource="select ... from saft_taxtable ..." legat direct
* pe control (RowSourceType=3) - fara cursorul cu acest alias, SELECT-ul cauta un fisier
* saft_taxtable.dbf inexistent si scoate dialogul nativ Windows "Open" care blocheaza
* headless la nesfarsit, fara nicio linie noua in log (capcana j, testare-ui-vfp.md). -----
IF USED('saft_taxtable')
USE IN ('saft_taxtable')
ENDIF
CREATE CURSOR saft_taxtable (taxname C(250), procent_taxa N(7,2), taxcode N(6), tva_livrari N(1))
INSERT INTO saft_taxtable VALUES ('301104-Achizitii de bunuri si servicii taxabile cu cota de 21%', 21, 301104, 1)
INSERT INTO saft_taxtable VALUES ('3011XX-Achizitii de bunuri si servicii taxabile cu cota de 11%', 11, 301108, 1)
*----- tablourile cu campurile poArticol: constructie poArticol INLINE in main la fiecare
* scenariu (nu intr-o PROCEDURA - vezi capcana ADDPROPERTY apelat dintr-o procedura,
* testare-ui-vfp.md litera l), dar bucla de ADDPROPERTY ramane in corpul principal, deci
* e sigura; reduce field-urile "neutre" (0 / '') la doua tablouri reutilizate. -----
LOCAL lnI
LOCAL ARRAY laPropN(49)
laPropN( 1)='id_articol' && identificatori si asociatii
laPropN( 2)='Id_Pol'
laPropN( 3)='id_gestiune'
laPropN( 4)='id_c'
laPropN( 5)='id_ctr'
laPropN( 6)='id_valuta'
laPropN( 7)='id_valuta_d'
laPropN( 8)='id_lucrare_rez'
laPropN( 9)='id_part_rez'
laPropN(10)='id_jtva_coloana'
laPropN(11)='taxcode'
laPropN(12)='opt_facturare'
laPropN(13)='gestionabil' && cantitate / pret / valuta
laPropN(14)='tip_valuta'
laPropN(15)='cantitate'
laPropN(16)='Curs'
laPropN(17)='multiplicator'
laPropN(18)='pret_achizitie'
laPropN(19)='pretv_orig'
laPropN(20)='pretd'
laPropN(21)='proc_tvav'
laPropN(22)='preturi_cu_tva' && preturi
laPropN(23)='pretftva'
laPropN(24)='pretftva_val'
laPropN(25)='pretctva'
laPropN(26)='pretctva_val'
laPropN(27)='tva'
laPropN(28)='tva_val'
laPropN(29)='discount_unitar' && discount unitar
laPropN(30)='discount_unitar_val'
laPropN(31)='discount_unitar_ctva'
laPropN(32)='discount_unitar_ctva_val'
laPropN(33)='valftva' && totaluri lei (calculate de calculeaza_totaluri)
laPropN(34)='valtva'
laPropN(35)='valctva'
laPropN(36)='valdiscountftva'
laPropN(37)='valdiscounttva'
laPropN(38)='valdiscountctva'
laPropN(39)='valdiminuatftva'
laPropN(40)='valdiminuattva'
laPropN(41)='valdiminuatctva'
laPropN(42)='vvalftva' && totaluri valuta (calculate de calculeaza_totaluri)
laPropN(43)='vvaltva'
laPropN(44)='vvalctva'
laPropN(45)='vvaldiscountftva'
laPropN(46)='vvaldiscounttva'
laPropN(47)='vvaldiscountctva'
laPropN(48)='vvaldiminuatftva'
laPropN(49)='vvaldiminuattva'
*-- (vvaldiminuatctva se adauga separat mai jos, ALEN a ramas 49 din motive de numarare initiala)
LOCAL ARRAY laPropC(11)
laPropC( 1)='codmat'
laPropC( 2)='codmatf'
laPropC( 3)='denumire'
laPropC( 4)='um'
laPropC( 5)='serie'
laPropC( 6)='lot'
laPropC( 7)='explicatie'
laPropC( 8)='numar_contract'
laPropC( 9)='codbare'
laPropC(10)='nume_val'
laPropC(11)='Cont'
PRIVATE poArticol, poDate
DO AfLog WITH 'mediu pregatit, incep scenariile'
*========================= PAS 0: mediu pregatit =========================
DO HarnessStep WITH 0, 'mediu pregatit, jtva_coloane cu ' + TRANSFORM(RECCOUNT('jtva_coloane')) + ' cote'
*========================= SCENARIU 1 (cazul tinta): bifa=1, 100.00 cu TVA, cant 1 =========
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1001
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART001'
poArticol.denumire = 'ARTICOL TEST 100 CU TVA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21 && cota standard 21%
poArticol.preturi_cu_tva = 1 && bifa PORNITA - politica implicita cu TVA inclus
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1) && 1 = lista de preturi, in Inlist activator bifa
=ADDPROPERTY(poDate, 'in_valuta', 0)
PUBLIC goDlg
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
IF VARTYPE(goDlg) <> 'O'
DO AfLog WITH 'FAIL: instantiere frm_articol_factura (scenariul 1)'
DO HarnessDone WITH 'done-error'
QUIT
ENDIF
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
DO AfLog WITH 'S1 dupa Init: preturi_cu_tva=' + TRANSFORM(poArticol.preturi_cu_tva) + ;
' ck_pret_cu_tva.Value=' + TRANSFORM(goDlg.ck_pret_cu_tva.Value) + ;
' Enabled=' + TRANSFORM(goDlg.ck_pret_cu_tva.Enabled)
*-- utilizatorul tasteaza 100.00 in campul "Pret cu TVA" (bifa deja pornita)
goDlg.Clb_pretctva.tx_suma_nat.Value = 100
goDlg.Clb_pretctva.tx_suma_nat.InteractiveChange()
DOEVENTS FORCE
DO HarnessStep WITH 1, 'cazul tinta: pretctva tastat 100.00, cantitate 1'
DO VerificaNumeric WITH 'S1 pretctva pastrat', poArticol.pretctva, 100, 0.005
DO VerificaNumeric WITH 'S1 CAZUL TINTA totalul facturii (valctva)', poArticol.valctva, 100, 0.005
*-- cifrele complete ale cazului tinta, indiferent de PASS/FAIL - de citat in raport ca atare
DO AfLog WITH 'S1 CIFRE CAZ TINTA: pretftva=' + TRANSFORM(poArticol.pretftva) + ;
' pretctva=' + TRANSFORM(poArticol.pretctva) + ' tva=' + TRANSFORM(poArticol.tva) + ;
' valftva=' + TRANSFORM(poArticol.valftva) + ' valtva=' + TRANSFORM(poArticol.valtva) + ;
' valctva=' + TRANSFORM(poArticol.valctva)
*-- butonul OK (inainte_de_do_termin): parte din fluxul real, dar poate cere ActiveControl
*-- (focus real de fereastra), nesigur headless. Daca arunca eroare, pasul e NEACOPERIT -
*-- nu se raporteaza PASS/FAIL pe o executie care nu s-a confirmat.
LOCAL llOkS1
TRY
llOkS1 = goDlg.inainte_de_do_termin()
DO VerificaLogic WITH 'S1 buton OK (inainte_de_do_termin)', llOkS1, .T.
CATCH TO loExcOk
DO AfLog WITH 'NEACOPERIT S1 buton OK (inainte_de_do_termin): eroare ' + ;
TRANSFORM(loExcOk.ErrorNo) + ' [' + loExcOk.Message + '] in ' + loExcOk.Procedure + ;
':' + TRANSFORM(loExcOk.LineNo) + ' - pasul nu s-a putut executa headless, nu e nici PASS nici FAIL'
ENDTRY
goDlg.Hide()
DOEVENTS FORCE
*========================= SCENARIU 2: comutare bifa, valoarea tastata nu se pierde =========
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1002
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 2
poArticol.codmat = 'ART002'
poArticol.denumire = 'ARTICOL TEST COMUTARE BIFA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21
poArticol.preturi_cu_tva = 0 && bifa OPRITA - pretul fara TVA e cel editabil
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 2, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
*-- utilizatorul tasteaza 50.00 fara TVA (bifa oprita)
goDlg.Clb_pretftva.tx_suma_nat.Value = 50
goDlg.Clb_pretftva.tx_suma_nat.InteractiveChange()
DOEVENTS FORCE
DO AfLog WITH 'S2 dupa tastare pretftva=50: pretftva=' + TRANSFORM(poArticol.pretftva) + ;
' pretctva=' + TRANSFORM(poArticol.pretctva)
*-- bifeaza (OFF -> ON): pretul fara TVA tastat (50) nu trebuie sa se piarda
goDlg.ck_pret_cu_tva.Value = 1
goDlg.ck_pret_cu_tva.InteractiveChange()
DOEVENTS FORCE
DO HarnessStep WITH 2, 'bifa OFF->ON: pretftva tastat=50 trebuie pastrat'
DO VerificaNumeric WITH 'S2 comutare OFF->ON: pretftva NEPIERDUT', poArticol.pretftva, 50, 0.005
DO VerificaNumeric WITH 'S2 comutare OFF->ON: pretctva derivat', poArticol.pretctva, 60.5, 0.005
*-- debifeaza (ON -> OFF): pretul (acum cu TVA, derivat) trebuie sa duca inapoi la acelasi pretftva=50
goDlg.ck_pret_cu_tva.Value = 0
goDlg.ck_pret_cu_tva.InteractiveChange()
DOEVENTS FORCE
DO HarnessStep WITH 3, 'bifa ON->OFF: pretftva trebuie sa ramana 50 (roundtrip)'
DO VerificaNumeric WITH 'S2 comutare ON->OFF: pretftva NEPIERDUT (roundtrip)', poArticol.pretftva, 50, 0.005
goDlg.Hide()
DOEVENTS FORCE
*========================= SCENARIU 3: cota standard 21% vs cota redusa 11% =========
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1003
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART003A'
poArticol.denumire = 'ARTICOL TEST COTA STANDARD'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21 && cota standard 21%
poArticol.preturi_cu_tva = 0
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
goDlg.Clb_pretftva.tx_suma_nat.Value = 100
goDlg.Clb_pretftva.tx_suma_nat.InteractiveChange()
DOEVENTS FORCE
DO HarnessStep WITH 4, 'cota standard 21%: pretftva=100 -> tva/pretctva'
DO VerificaNumeric WITH 'S3a cota 21%: tva', poArticol.tva, 21, 0.005
DO VerificaNumeric WITH 'S3a cota 21%: pretctva', poArticol.pretctva, 121, 0.005
goDlg.Hide()
DOEVENTS FORCE
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1004
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART003B'
poArticol.denumire = 'ARTICOL TEST COTA REDUSA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.11 && cota redusa 11%
poArticol.preturi_cu_tva = 0
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
goDlg.Clb_pretftva.tx_suma_nat.Value = 100
goDlg.Clb_pretftva.tx_suma_nat.InteractiveChange()
DOEVENTS FORCE
DO HarnessStep WITH 5, 'cota redusa 11%: pretftva=100 -> tva/pretctva'
DO VerificaNumeric WITH 'S3b cota 11%: tva', poArticol.tva, 11, 0.005
DO VerificaNumeric WITH 'S3b cota 11%: pretctva', poArticol.pretctva, 111, 0.005
goDlg.Hide()
DOEVENTS FORCE
*========================= SCENARIU 4: discount unitar cu TVA (ramura discountctva) =========
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1005
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART004'
poArticol.denumire = 'ARTICOL TEST DISCOUNT CU TVA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21
poArticol.preturi_cu_tva = 1 && bifa pornita - ramura discountctva e cea activa
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
goDlg.Clb_pretctva.tx_suma_nat.Value = 100
goDlg.Clb_pretctva.tx_suma_nat.InteractiveChange()
DOEVENTS FORCE
*-- utilizatorul tasteaza 10.00 discount unitar cu TVA (Valid, cu When intai - ca la focus real)
goDlg.Clb_discountctva.tx_suma_nat.When()
goDlg.Clb_discountctva.tx_suma_nat.Value = 10
goDlg.Clb_discountctva.tx_suma_nat.Valid()
DOEVENTS FORCE
DO HarnessStep WITH 6, 'discount unitar cu TVA = 10, pret 100, cant 1'
DO VerificaNumeric WITH 'S4 discount_unitar_ctva pastrat', poArticol.discount_unitar_ctva, 10, 0.005
DO VerificaNumeric WITH 'S4 total diminuat cu TVA (valdiminuatctva)', poArticol.valdiminuatctva, 90, 0.005
DO AfLog WITH 'S4 comparatie: fara discount (scenariul 1) valctva=100.00, cu discount 10 -> valdiminuatctva=' + TRANSFORM(poArticol.valdiminuatctva)
goDlg.Hide()
DOEVENTS FORCE
*========================= SCENARIU 5: bifa ACTIVA pe tip din Inlist =========================
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1006
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART005'
poArticol.denumire = 'ARTICOL TEST BIFA ACTIVA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21
poArticol.preturi_cu_tva = 0
poArticol.pretftva = 0 && pret zero - irelevant, tip 1 activeaza bifa oricum
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 1) && 1 = lista de preturi, IN Inlist(1,5,10,22,23,25,29,41)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
DO HarnessStep WITH 7, 'tip=1 (Inlist) -> bifa trebuie activa (Enabled=.T.)'
DO VerificaLogic WITH 'S5 bifa ACTIVA pe tip din Inlist', goDlg.ck_pret_cu_tva.Enabled, .T.
goDlg.Hide()
DOEVENTS FORCE
*========================= SCENARIU 6: bifa DEZACTIVATA pe tip din afara listei =========
poArticol = CREATEOBJECT('Empty')
FOR lnI = 1 TO ALEN(laPropN)
=ADDPROPERTY(poArticol, laPropN(lnI), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnI = 1 TO ALEN(laPropC)
=ADDPROPERTY(poArticol, laPropC(lnI), '')
ENDFOR
poArticol.id_articol = 1007
poArticol.Id_Pol = 1
poArticol.Cont = '707'
poArticol.id_gestiune = 1
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 1
poArticol.codmat = 'ART006'
poArticol.denumire = 'ARTICOL TEST BIFA DEZACTIVATA'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21
poArticol.preturi_cu_tva = 0
poArticol.pretftva = 50 && pret NENUL - conditie ceruta ca bifa sa ramana dezactivata
poDate = CREATEOBJECT('Empty')
=ADDPROPERTY(poDate, 'tip', 3) && 3 = comanda, NU e in Inlist(1,5,10,22,23,25,29,41)
=ADDPROPERTY(poDate, 'in_valuta', 0)
goDlg = CREATEOBJECT('frm_articol_factura', 1, .F.)
goDlg.WindowType = 0
goDlg.Visible = .T.
goDlg.Show()
DOEVENTS FORCE
DO HarnessStep WITH 8, 'tip=3 (afara Inlist), pret nenul -> bifa trebuie dezactivata'
DO VerificaLogic WITH 'S6 bifa DEZACTIVATA pe tip din afara listei, pret nenul', goDlg.ck_pret_cu_tva.Enabled, .F.
goDlg.Hide()
DOEVENTS FORCE
DO AfLog WITH 'GATA - toate scenariile Nivel 1 executate'
DO HarnessStep WITH 9, 'final'
DO HarnessDone WITH 'done'
CATCH TO loExc
DO AfLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
DO HarnessDone WITH 'done-error'
ENDTRY
QUIT
*==================================================================================
PROCEDURE VerificaNumeric
LPARAMETERS tcEticheta, tnObtinut, tnAsteptat, tnToleranta
LOCAL lcMsg
IF ABS(NVL(tnObtinut,-999999) - tnAsteptat) < tnToleranta
lcMsg = 'PASS ' + tcEticheta + ': ' + TRANSFORM(tnObtinut) + ' (asteptat ' + TRANSFORM(tnAsteptat) + ')'
ELSE
lcMsg = 'FAIL ' + tcEticheta + ': obtinut=' + TRANSFORM(tnObtinut) + ' asteptat=' + TRANSFORM(tnAsteptat)
ENDIF
DO AfLog WITH lcMsg
ENDPROC
PROCEDURE VerificaLogic
LPARAMETERS tcEticheta, tlObtinut, tlAsteptat
LOCAL lcMsg
IF tlObtinut = tlAsteptat
lcMsg = 'PASS ' + tcEticheta + ': ' + TRANSFORM(tlObtinut) + ' (asteptat ' + TRANSFORM(tlAsteptat) + ')'
ELSE
lcMsg = 'FAIL ' + tcEticheta + ': obtinut=' + TRANSFORM(tlObtinut) + ' asteptat=' + TRANSFORM(tlAsteptat)
ENDIF
DO AfLog WITH lcMsg
ENDPROC
PROCEDURE AfErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO AfLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE AfLog
LPARAMETERS tcMsg
SET SAFETY OFF
LOCAL lcL
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
ENDPROC
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,10 @@
# test_pret_cu_tva_dialog.ps1 - wrapper peste harness-ul generic pentru testul frm_articol_factura
# (S5, plan #7 - pret_cu_tva). Rulare: powershell -ExecutionPolicy Bypass -File test_pret_cu_tva_dialog.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
-TestPrg (Join-Path $Teste 'test_pret_cu_tva_dialog.prg') `
-Steps @('mediu','tinta_100', 'comutare_on', 'comutare_off', 'cota_21', 'cota_11', 'discount', 'bifa_activa', 'bifa_dezactivata', 'final') `
-ShotsDir (Join-Path $Teste 'screenshots') `
-SyncDir (Join-Path $Teste 'uisync') `
-StepTimeoutSec 60

View File

@@ -0,0 +1,630 @@
* test_pret_cu_tva_nivel2.prg
* Test UI Nivel 2 (S5, plan #7) pentru fluxul COMPLET prin frm_facturare_articole - cazurile 6 si 8
* din task. Foloseste mecanismul validat in test_modal_unlock_smoketest2.prg (Timer pe _SCREEN +
* _SCREEN.Forms + Controls(i)) ca sa conduca dialogul frm_articol_factura, deschis cu Show(1)
* hardcodat in do_adauga_articol/do_modifica (frm_facturare_articole, ofacturare.vc2).
*
* Flux REAL, nu populare directa: articolul intra in crsfactura prin But_urmator1.Click() ->
* do_urmator() -> do_adauga_articol() (cazul 6); modificarea trece prin But_modifica1.Click() /
* grd_factura.DblClick() -> do_modifica() (cazul 8). crsarticole si crsfactura au structura REALA
* (creeaza_facturacrs, aceleasi campuri ca in productie), fara Oracle.
*
* Cazuri:
* PAS 0: grid gol - But_modifica1.Click() si grd_factura.DblClick() nu fac nimic, fara eroare.
* PAS 1 (caz 6): adaugare cu bifa schimbata fata de politica (policy=0, user seteaza 1, pret cu
* TVA=100) -> crsfactura.cu_tva=1, valctva=100.00 exact.
* PAS 2 (caz 8a): modificare - But_modifica1 redeschide dialogul pe randul adaugat, comuta bifa
* OFF, tasteaza pret fara TVA=60 -> acelasi rand actualizat (cu_tva=0, valctva=72.60).
* PAS 3 (caz 8b): modificare prin grd_factura.DblClick() (al doilea canal, acelasi rezultat) -
* schimba pretul cu TVA la 200, bifa ramane ON dupa pasul anterior... de fapt pasul 2 a
* lasat bifa OFF, deci verifica ramura fara TVA din nou, cu alta valoare.
* PAS 4 (caz 8c): Renunta - deschide dialogul, schimba o valoare, apasa Renunta -> randul ramane
* BIT-IDENTIC (comparat camp cu camp fata de starea dinainte).
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog, gcSyncDir
gcUILog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\test_pret_cu_tva_nivel2_log.txt"
gcSyncDir = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\uisync_nivel2\"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAFACTURARE\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + ;
gcAppPath + 'COMUN\UTILE\CALENDAR;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EMAIL;' + ;
gcAppPath + 'COMUN\UTILE\NFJSON;' + gcAppPath + 'COMUN\UTILE\NFXML;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO AfLog WITH 'SET PATH OK'
*----- CLASE (lista dovedita de suita Nivel 1 - mediul unei suite noi se mosteneste din suita
* care TRECE, nu dintr-un smoke-test) -----
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms ADDITIVE
SET CLASSLIB TO ofacturare.vcx ADDITIVE
SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO ofacturare_rapoarte ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO onom_curs ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO ferestre_cere_date ADDITIVE
SET CLASSLIB TO baza ADDITIVE
SET CLASSLIB TO caut ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO serii_numere ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO _calendar.vcx ADDITIVE
SET CLASSLIB TO locale ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ocomenzi ADDITIVE
DO AfLog WITH 'SET CLASSLIB OK'
*----- PROCEDURI (mock amessagebox PRIMUL, ui_harness la final) -----
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg"
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO onomenclatoare.prg ADDITIVE
SET PROCEDURE TO onomenclatoare2.prg ADDITIVE
SET PROCEDURE TO oproceduri_rapoarte_fact.prg ADDITIVE
SET PROCEDURE TO email.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO odocumente ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO cauta_alfa.prg ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO oproceduri_curs.prg ADDITIVE
SET PROCEDURE TO proceduri.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO ofacturare.prg ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO wwApi.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO ofacturare_comun.prg ADDITIVE
SET PROCEDURE TO ofacturare_stoc.prg ADDITIVE
SET PROCEDURE TO pmenu.prg ADDITIVE
SET PROCEDURE TO ointroduceri.prg ADDITIVE
SET PROCEDURE TO ovariabile_globale.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO filebringer.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO oupdate.prg ADDITIVE
SET PROCEDURE TO procese.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO wwhttp.prg ADDITIVE
SET PROCEDURE TO xmlaccess.prg ADDITIVE
SET PROCEDURE TO xmlparser.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO suma_in_vorbe.prg ADDITIVE
SET PROCEDURE TO controllerecr ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
DO AfLog WITH 'SET PROCEDURE OK'
*----- Globale aplicatie -----
PUBLIC gnPc, gnPVal, gnPcant, gnPPretV, gnScadereStoc, gnMemProcDisc, gl406, gcAcces
PUBLIC gnModTotFact, gnRF_FACTURARE_FARA_STOC
*-- gnModTotFact/gnRF_FACTURARE_FARA_STOC: lista completa a globalelor de aplicatie cerute de
*-- Init/do_adauga_articol/do_modifica/do_verifica_articol/do_initializeaza_articol (extrasa cu
*-- vfp_symbols.ps1 -Class frm_facturare_articole, identificatori g[nlc]\w+), restul deja
*-- prezente in mediu. Puse pe 0 (implicit prudent) ca sa NU activeze ramuri neintentionate -
*-- gnModTotFact=1 ar intra pe modificarea totalului facturii, gnRF_FACTURARE_FARA_STOC=1 pe
*-- facturare fara stoc; niciuna nu e ce se testeaza aici. NVL() nu apara de variabila
*-- nedeclarata, doar de valoare NULL - trebuie sa existe.
gnModTotFact = 0
gnRF_FACTURARE_FARA_STOC = 0
*-- gnPPret/gnPPretVal: presupuse (nu exista in cod - vin din configuratia Oracle citita la
*-- pornirea reala; ceruta de creeaza_facturacrs, ofacturare_comun.prg:1770, neintalnita la
*-- Nivel 1 care nu atinge acel cursor). Ating DOAR pret_achizitie/pretd (max(...,4)) - niciun
*-- camp verificat de testele de mai jos (pretftva/pretctva/valftva/valtva/valctva folosesc
*-- gnPPretV+gnPc, deja corecte). precizie_max_pret_vz e #define=6 in acelasi fisier, nu
*-- variabila - nu se declara aici.
PUBLIC gnPPret, gnPPretVal
gnPc = 2
gnPVal = 2
gnPcant = 3
gnPPretV = 4
gnPPret = 4
gnPPretVal = 4
gnScadereStoc = 0 && bypass complet logica de stoc (do_alege_stoc nu se apeleaza)
gnMemProcDisc = 0
gl406 = .F.
gcAcces = "1;2;3;4;5;6;7;8;"
PUBLIC nror(65000)
PUBLIC goApp, goExport, goExecutor
goApp = CREATEOBJECT('dummyapp')
goExport = CREATEOBJECT('dummyexport')
goExecutor = CREATEOBJECT('dummyexecutor')
IF USED('jtva_coloane')
USE IN ('jtva_coloane')
ENDIF
CREATE CURSOR jtva_coloane (id_jtva_coloana N(14), denumire C(50), cota_tva N(6,2))
INSERT INTO jtva_coloane VALUES (1, 'TVA 21%', 21)
INSERT INTO jtva_coloane VALUES (2, 'TVA 11%', 11)
GO TOP IN jtva_coloane
IF USED('saft_taxtable')
USE IN ('saft_taxtable')
ENDIF
CREATE CURSOR saft_taxtable (taxname C(250), procent_taxa N(7,2), taxcode N(6), tva_livrari N(1))
INSERT INTO saft_taxtable VALUES ('301104-Achizitii de bunuri si servicii taxabile cu cota de 21%', 21, 301104, 1)
INSERT INTO saft_taxtable VALUES ('3011XX-Achizitii de bunuri si servicii taxabile cu cota de 11%', 11, 301108, 1)
*----- crsfactura: structura REALA, fara Oracle (creeaza_facturacrs, ofacturare_comun.prg:1770) -----
DO creeaza_facturacrs WITH 'crsfactura'
DO AfLog WITH 'crsfactura creat, Reccount=' + TRANSFORM(RECCOUNT('crsfactura'))
*----- crsarticole: sursa (stoc/lista de preturi) - RecordSource al grd_articole. Campuri
* alese ca sa acopere atat coloanele gridului (denumire, gestionabil, codmat, pret,
* cantitate, preturi_cu_tva, pret_val, nume_val, nume_lista_preturi, serie, codbare) cat
* si tot ce Scatter+do_initializeaza_articol au nevoie (restul, verificat din cod). -----
IF USED('crsarticole')
USE IN ('crsarticole')
ENDIF
CREATE CURSOR crsarticole (id_articol N(10), Id_Pol N(10), id_gestiune N(10), denumire C(100), ;
codmat C(50), codbare C(50), gestionabil N(1), cantitate N(18,4), pret N(18,4), ;
pret_val N(18,4), preturi_cu_tva N(1), proc_tvav N(18,4), discount_unitar N(18,4), ;
discount_unitar_val N(18,4), pret_achizitie N(18,4), tip_valuta N(1), Curs N(18,4), ;
multiplicator N(10,4), Cont C(10), um C(10), serie C(30), lot C(30), explicatie C(200), ;
opt_facturare N(3), id_ctr N(10), numar_contract C(50), pretd N(18,4), id_valuta N(10), ;
nume_val C(20), nume_lista_preturi C(100), id_jtva_coloana N(10), taxcode N(6), id_c N(10))
INSERT INTO crsarticole (id_articol, Id_Pol, id_gestiune, denumire, codmat, codbare, ;
gestionabil, cantitate, pret, pret_val, preturi_cu_tva, proc_tvav, discount_unitar, ;
discount_unitar_val, pret_achizitie, tip_valuta, Curs, multiplicator, Cont, um, serie, ;
lot, explicatie, opt_facturare, id_ctr, numar_contract, pretd, id_valuta, nume_val, ;
nume_lista_preturi, id_jtva_coloana, taxcode, id_c) ;
VALUES (2001, 1, 1, 'ARTICOL NIVEL2', 'ART2001', '', ;
0, 100, 50, 0, 0, 1.21, 0, ;
0, 0, 0, 1, 1, '707', 'BUC', '', ;
'', '', 0, 0, '', 0, 0, '', ;
'LISTA TEST', 1, 0, 1)
GO TOP IN crsarticole
DO AfLog WITH 'crsarticole creat, Reccount=' + TRANSFORM(RECCOUNT('crsarticole'))
*----- poDate: clasa REALA oDateFactura (ofacturare_comun.prg:99, deja incarcata prin SET
* PROCEDURE), nu obiect Empty umplut manual - are toate proprietatile cu valorile
* implicite de productie (inclusiv discount_evidentiat=0). PRIVATE la nivel de PROGRAM
* PRINCIPAL, vizibil (scoping VFP) in tot lantul apelat mai jos (frm_facturare_articole,
* do_adauga_articol, do_modifica, frm_articol_factura) - la fel ca in productie
* (Procedure factureaza, ofacturare.prg:95). Constructia ramane INLINE in main (capcana l). -----
PRIVATE poDate
poDate = CREATEOBJECT('oDateFactura')
poDate.tip = 1 && 1 = facturare pe baza de lista de preturi
poDate.serie_act = 'TST'
poDate.nract = 1
DO AfLog WITH 'poDate pregatit (oDateFactura), tip=' + TRANSFORM(poDate.tip)
*----- driverul de deblocare Show(1): Timer la nivel _SCREEN + _SCREEN.Forms + Controls(i),
* mecanism validat in test_modal_unlock_smoketest2.prg (PASS). gcCazAct selecteaza
* interactiunea de aplicat la fiecare dialog nou detectat. -----
PUBLIC goDriver, gnDriverTick, glDlgTratat, gcCazAct
gnDriverTick = 0
glDlgTratat = .F.
gcCazAct = ''
goDriver = CREATEOBJECT('driverdeblocare3')
_SCREEN.AddObject('tmrDrvN2', 'Timer')
_SCREEN.tmrDrvN2.Interval = 200
BINDEVENT(_SCREEN.tmrDrvN2, 'Timer', goDriver, 'Executa')
_SCREEN.tmrDrvN2.Enabled = .T.
DO AfLog WITH 'driver+timer pregatiti'
*----- Desktop VFP vizibil, ca la celelalte suite UI -----
_SCREEN.Visible = .T.
_SCREEN.WindowState = 2
_SCREEN.Caption = 'TEST UI Nivel 2 (cazurile 6 si 8)'
PUBLIC goFrm
goFrm = CREATEOBJECT('frm_facturare_articole')
goFrm.WindowType = 0 && testul instantiaza direct - modeless, Show() revine imediat
goFrm.Show()
goFrm.WindowState = 2
DOEVENTS FORCE
DO AfLog WITH 'frm_facturare_articole afisat modeless, Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
DO HarnessStep WITH 0, 'formular afisat, grid gol'
*========================= PAS 0: grid gol - But_modifica1/DblClick nu fac nimic =========
LOCAL lnRecFataDe0
lnRecFataDe0 = RECCOUNT('crsfactura')
goFrm.But_modifica1.Click()
DOEVENTS FORCE
IF RECCOUNT('crsfactura') = lnRecFataDe0
DO UILog WITH 'PASS P0a But_modifica1 pe grid gol: nu a modificat Reccount (' + TRANSFORM(RECCOUNT('crsfactura')) + ')'
ELSE
DO UILog WITH 'FAIL P0a But_modifica1 pe grid gol: Reccount a devenit ' + TRANSFORM(RECCOUNT('crsfactura'))
ENDIF
goFrm.grd_factura.DblClick()
DOEVENTS FORCE
IF RECCOUNT('crsfactura') = lnRecFataDe0
DO UILog WITH 'PASS P0b grd_factura.DblClick pe grid gol: nu a modificat Reccount'
ELSE
DO UILog WITH 'FAIL P0b grd_factura.DblClick pe grid gol: Reccount a devenit ' + TRANSFORM(RECCOUNT('crsfactura'))
ENDIF
DO HarnessStep WITH 1, 'P0 grid gol verificat'
*========================= PAS 1 (CAZUL 6): adaugare cu bifa schimbata =========================
*-- politica implicita (crsarticole.preturi_cu_tva=0, fara TVA) - userul o schimba in dialog la
*-- 1 (cu TVA), tasteaza pret cu TVA=100, cantitate=1 (zerorizata de do_initializeaza_articol
*-- pt. tip=1, se completeaza in dialog, ca la fluxul real).
SELECT crsarticole
GO TOP
gcCazAct = 'CASE6'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_urmator1.Click()
DOEVENTS FORCE
LOCAL lnWait
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_urmator1: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
IF RECCOUNT('crsfactura') = 1
SELECT crsfactura
GO TOP
IF cu_tva = 1 AND ABS(valctva - 100) < 0.01
DO UILog WITH 'PASS P1 CAZUL 6: cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=1 valctva=100)'
ELSE
DO UILog WITH 'FAIL P1 CAZUL 6: cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=1 valctva=100)'
ENDIF
DO UILog WITH 'P1 cifre complete: pretftva=' + TRANSFORM(pretftva) + ' pretctva=' + TRANSFORM(pretctva) + ' valftva=' + TRANSFORM(valftva) + ' valtva=' + TRANSFORM(valtva)
ELSE
DO UILog WITH 'FAIL P1 CAZUL 6: Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura')) + ' (asteptat 1) - articolul nu a fost adaugat'
ENDIF
DO HarnessStep WITH 2, 'P1 caz 6 propagare: Reccount=' + TRANSFORM(RECCOUNT('crsfactura'))
*========================= PAS 2 (CAZUL 8a): modificare prin But_modifica1 =========================
*-- comuta bifa OFF (fara TVA), tasteaza pret fara TVA=60 -> valctva asteptat 60*1.21=72.60
IF RECCOUNT('crsfactura') = 1
gcCazAct = 'CASE8_MOD_OFF'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P2): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF cu_tva = 0 AND ABS(valctva - 72.6) < 0.01
DO UILog WITH 'PASS P2 CAZUL 8a (But_modifica1): cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=0 valctva=72.60)'
ELSE
DO UILog WITH 'FAIL P2 CAZUL 8a (But_modifica1): cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=0 valctva=72.60)'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P2: nu exista randul din P1 (Reccount=' + TRANSFORM(RECCOUNT('crsfactura')) + ')'
ENDIF
DO HarnessStep WITH 3, 'P2 caz 8a modificare But_modifica1'
*========================= PAS 3 (CAZUL 8b): modificare prin grd_factura.DblClick() =========
*-- al doilea canal cerut de task - schimba pretul cu TVA la 200, bifa ON
IF RECCOUNT('crsfactura') = 1
gcCazAct = 'CASE8_MOD_ON'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.grd_factura.DblClick()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa grd_factura.DblClick (P3): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF cu_tva = 1 AND ABS(valctva - 200) < 0.01
DO UILog WITH 'PASS P3 CAZUL 8b (DblClick): cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=1 valctva=200)'
ELSE
DO UILog WITH 'FAIL P3 CAZUL 8b (DblClick): cu_tva=' + TRANSFORM(cu_tva) + ' valctva=' + TRANSFORM(valctva) + ' (asteptat cu_tva=1 valctva=200)'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P3: nu exista randul (Reccount=' + TRANSFORM(RECCOUNT('crsfactura')) + ')'
ENDIF
DO HarnessStep WITH 4, 'P3 caz 8b modificare DblClick'
*========================= PAS 4 (CAZUL 8c): Renunta - randul ramane BIT-IDENTIC =========
*-- SCATTER TO array (nu AFIELDS - AFIELDS umple un tablou de METADATE si intoarce un numar,
*-- nu e o colectie FOR EACH) captureaza VALORILE campurilor din randul curent, memo inclusiv.
IF RECCOUNT('crsfactura') = 1
LOCAL ARRAY laSnapDinainte[1]
LOCAL lnF, lnCampuri
SELECT crsfactura
GO TOP
SCATTER TO laSnapDinainte
gcCazAct = 'CASE8_RENUNTA'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P4, Renunta): glDlgTratat=' + TRANSFORM(glDlgTratat)
LOCAL ARRAY laSnapDupa[1]
SELECT crsfactura
GO TOP
SCATTER TO laSnapDupa
LOCAL llIdentic
llIdentic = (ALEN(laSnapDinainte,1) == ALEN(laSnapDupa,1))
lnCampuri = 0
IF llIdentic
FOR lnF = 1 TO ALEN(laSnapDinainte,1)
lnCampuri = lnCampuri + 1
IF !(TRANSFORM(laSnapDinainte(lnF)) == TRANSFORM(laSnapDupa(lnF)))
llIdentic = .F.
DO AfLog WITH 'P4 diagnostic - campul ' + TRANSFORM(lnF) + ' difera: [' + ;
TRANSFORM(laSnapDinainte(lnF)) + '] -> [' + TRANSFORM(laSnapDupa(lnF)) + ']'
ENDIF
ENDFOR
ENDIF
IF llIdentic
DO UILog WITH 'PASS P4 CAZUL 8c Renunta: randul ramane BIT-IDENTIC (' + TRANSFORM(lnCampuri) + ' campuri comparate)'
ELSE
DO UILog WITH 'FAIL P4 CAZUL 8c Renunta: randul S-A MODIFICAT desi s-a apasat Renunta (vezi diag pe campuri mai sus)'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P4: nu exista randul (Reccount=' + TRANSFORM(RECCOUNT('crsfactura')) + ')'
ENDIF
DO HarnessStep WITH 5, 'P4 caz 8c Renunta'
*========================= PAS 5 (CAZUL 11, rec_s2c): crestere cantitate pe tip FARA verificare
*========================= de stoc -> acceptata neconditionat (plafonul exista dar nu se verifica)
*-- tip=1 nu e in Inlist(poDate.tip,4,21,23,28,42,47) din inainte_de_do_termin, deci cresterea
*-- cantitatii nu are plafon real - verifica ca S2c (recalcularea plafonului pt. tipurile CU
*-- stoc) nu a introdus vreo restrictie neintentionata pe tipurile FARA verificare.
IF RECCOUNT('crsfactura') = 1
gcCazAct = 'CASE11_CANTITATE'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P5, caz 11): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF ABS(cantitate - 50) < 0.001
DO UILog WITH 'PASS P5 CAZUL 11 (rec_s2c): crestere cantitate pe tip fara verificare de stoc acceptata: cantitate=' + TRANSFORM(cantitate) + ' (asteptat 50)'
ELSE
DO UILog WITH 'FAIL P5 CAZUL 11 (rec_s2c): cantitate=' + TRANSFORM(cantitate) + ' (asteptat 50) - crestere respinsa sau neaplicata'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P5: nu exista randul (Reccount=' + TRANSFORM(RECCOUNT('crsfactura')) + ')'
ENDIF
DO HarnessStep WITH 6, 'P5 caz 11 plafon - final'
DO HarnessDone WITH 'done'
CATCH TO loExc
DO AfLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
DO HarnessDone WITH 'done-error'
ENDTRY
QUIT
*==================================================================================
PROCEDURE AfErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO AfLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE AfLog
LPARAMETERS tcMsg
SET SAFETY OFF
LOCAL lcL
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
ENDPROC
PROCEDURE UILog
LPARAMETERS tcMsg
DO AfLog WITH tcMsg
ENDPROC
*-- FindCtl: referinta directa la un control prin Controls(i), potrivit dupa .Name - tehnica
*-- validata in test_modal_unlock_smoketest2.prg (accesul cu prefix direct pe o referinta obtinuta
*-- din _SCREEN.Forms a dat eroare 1925 in acel diagnostic; Controls(i) e calea sigura, folosita
*-- consecvent, inclusiv pentru nivelurile imbricate).
PROCEDURE FindCtl
LPARAMETERS toParent, tcName
LOCAL lnI, loGasit
loGasit = .NULL.
FOR lnI = 1 TO toParent.ControlCount
IF UPPER(toParent.Controls(lnI).Name) == UPPER(tcName)
loGasit = toParent.Controls(lnI)
ENDIF
ENDFOR
RETURN loGasit
ENDPROC
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexport AS Custom
PROCEDURE citesteSetareRegistru
LPARAMETERS tcCheie
RETURN ''
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexecutor AS Custom
cEroare = ''
PROCEDURE oExecute
LPARAMETERS tcSql, tcCursor
IF USED(tcCursor)
USE IN (tcCursor)
ENDIF
CREATE CURSOR (tcCursor) (codmatf C(50))
RETURN 1
ENDPROC
PROCEDURE oReset
ENDPROC
ENDDEFINE
DEFINE CLASS driverdeblocare3 AS Custom
PROCEDURE Executa
*-- rulat la fiecare tick al _SCREEN.tmrDrvN2. Cauta FRM_ARTICOL_FACTURA prin _SCREEN.Forms,
*-- aplica interactiunea selectata de gcCazAct (setata de test INAINTE de fiecare click),
*-- si inchide dialogul (do_termin sau do_renunt, dupa caz).
LOCAL lnI, loForm, llGasit
gnDriverTick = gnDriverTick + 1
llGasit = .F.
FOR lnI = 1 TO _SCREEN.FormCount
IF UPPER(_SCREEN.Forms(lnI).Class) == 'FRM_ARTICOL_FACTURA'
loForm = _SCREEN.Forms(lnI)
llGasit = .T.
ENDIF
ENDFOR
IF glDlgTratat OR !llGasit
RETURN
ENDIF
DO AfLog WITH 'driver3 tick ' + TRANSFORM(gnDriverTick) + ' POTRIVIT (caz=' + gcCazAct + '), intru in interactiune'
LOCAL loBifa, loCantitateCtn, loCantitate, loPretCtvaCtn, loPretCtvaNat, loPretFtvaCtn, loPretFtvaNat, loRenunt
TRY
DO CASE
CASE gcCazAct == 'CASE6'
loBifa = FindCtl(loForm, 'ck_pret_cu_tva')
loBifa.Value = 1
loBifa.InteractiveChange()
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 1
loCantitate.InteractiveChange()
loPretCtvaCtn = FindCtl(loForm, 'Clb_pretctva')
loPretCtvaNat = FindCtl(loPretCtvaCtn, 'tx_suma_nat')
loPretCtvaNat.Value = 100
loPretCtvaNat.InteractiveChange()
DO AfLog WITH 'driver3 CASE6: bifa=1 cantitate=1 pretctva=100, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'CASE8_MOD_OFF'
loBifa = FindCtl(loForm, 'ck_pret_cu_tva')
loBifa.Value = 0
loBifa.InteractiveChange()
loPretFtvaCtn = FindCtl(loForm, 'Clb_pretftva')
loPretFtvaNat = FindCtl(loPretFtvaCtn, 'tx_suma_nat')
loPretFtvaNat.Value = 60
loPretFtvaNat.InteractiveChange()
DO AfLog WITH 'driver3 CASE8_MOD_OFF: bifa=0 pretftva=60, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'CASE8_MOD_ON'
loBifa = FindCtl(loForm, 'ck_pret_cu_tva')
loBifa.Value = 1
loBifa.InteractiveChange()
loPretCtvaCtn = FindCtl(loForm, 'Clb_pretctva')
loPretCtvaNat = FindCtl(loPretCtvaCtn, 'tx_suma_nat')
loPretCtvaNat.Value = 200
loPretCtvaNat.InteractiveChange()
DO AfLog WITH 'driver3 CASE8_MOD_ON: bifa=1 pretctva=200, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'CASE8_RENUNTA'
loPretCtvaCtn = FindCtl(loForm, 'Clb_pretctva')
loPretCtvaNat = FindCtl(loPretCtvaCtn, 'tx_suma_nat')
loPretCtvaNat.Value = 9999
loPretCtvaNat.InteractiveChange()
loRenunt = FindCtl(loForm, 'But_renunt1')
DO AfLog WITH 'driver3 CASE8_RENUNTA: pretctva tastat 9999, apas But_renunt1 (Renunta)'
loRenunt.Click()
CASE gcCazAct == 'CASE11_CANTITATE'
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 50
loCantitate.InteractiveChange()
DO AfLog WITH 'driver3 CASE11_CANTITATE: cantitate=50 (tip fara verificare de stoc), apas do_termin()'
loForm.do_termin()
OTHERWISE
DO AfLog WITH 'driver3: gcCazAct necunoscut [' + gcCazAct + ']'
ENDCASE
glDlgTratat = .T.
DO AfLog WITH 'driver3: interactiune REUSITA pentru caz=' + gcCazAct
CATCH TO loExcDrv
DO AfLog WITH 'driver3: CATCH caz=' + gcCazAct + ' ErrorNo=' + TRANSFORM(loExcDrv.ErrorNo) + ;
' Message=' + loExcDrv.Message + ' Procedure=' + loExcDrv.Procedure + ;
' LineNo=' + TRANSFORM(loExcDrv.LineNo) + ' LineContents=[' + loExcDrv.LineContents + ']'
ENDTRY
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,11 @@
# test_pret_cu_tva_nivel2.ps1 - wrapper peste harness-ul generic pentru testele Nivel 2
# (cazurile 6 si 8, S5, plan #7). Rulare: powershell -ExecutionPolicy Bypass -File test_pret_cu_tva_nivel2.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
-TestPrg (Join-Path $Teste 'test_pret_cu_tva_nivel2.prg') `
-Steps @('grid_gol_afisat', 'p0_grid_gol', 'p1_caz6', 'p2_caz8a', 'p3_caz8b', 'p4_caz8c', 'p5_caz11_plafon') `
-ShotsDir (Join-Path $Teste 'screenshots_nivel2') `
-SyncDir (Join-Path $Teste 'uisync_nivel2') `
-StepTimeoutSec 60 `
-ReadyTimeoutSec 90

View File

@@ -0,0 +1,506 @@
* test_pret_cu_tva_nivel2_retur.prg
* Test UI Nivel 2 (S5, plan #7) pentru RAMURA DE RETUR (tip 8/9) a plafonului recalculat de S2c
* (rec_s2c_ncantitatemax.md). Verificarea de plafon pentru retur (frm_articol_factura.
* inainte_de_do_termin, ofacturare.vc2:2265, "Nu se poate returna mai mult decat a fost facturat!")
* NU are garda de gestionabil/llStoculConteaza - se verifica NECONDITIONAT - deci articolul poate
* fi gestionabil=0, ceea ce pastreaza fluxul de adaugare pe calea SIMPLA (frm_articol_factura
* direct, fara do_alege_stoc), aceeasi infrastructura dovedita la cazurile 6/8.
*
* Cazuri (din rec_s2c_ncantitatemax.md, ramura retur - tip 8/9):
* PAS 0: adaugare linie retur (crsarticole.cantitate=10 "cat s-a facturat", id_c=3001) prin
* But_urmator1.Click() real -> crsfactura.cantitate=-10 (negat de do_initializeaza_articol
* pt. tip 8/9), crsarticole.cantitate scade la 0 (decrementata de do_adauga_articol).
* PAS 1: modificare DOAR de pret (cantitate neschimbata) -> trebuie ACCEPTATA (plafonul recalculat
* egaleaza cantitatea curenta a liniei: 0 - (-10) = 10 = Abs(-10), nu strict mai mare).
* PAS 2: se simuleaza o schimbare externa a stocului sursa (alt utilizator/proces a modificat
* cat mai e disponibil de returnat) - crsarticole.cantitate setat manual la 5 (NU e
* populare de crsfactura, e o schimbare pe cursorul SURSA, plauzibila in productie).
* PAS 3: crestere cantitate returnata la -12 (magnitudine 12) -> plafonul RECALCULAT e
* 5 - (-10) = 15, deci 12 <= 15 -> ACCEPTATA. Sub formula VECHE (ncantitatemax fixat la
* cantitatea curenta a liniei, magnitudine 10, nerecalculat), 12 > 10 ar fi fost RESPINSA -
* acesta e cazul care distinge formula veche de cea noua (S2c).
* PAS 4: crestere cantitate returnata la -20 (magnitudine 20) -> peste plafonul recalculat (15) ->
* RESPINSA cu mesajul "Nu se poate returna mai mult decat a fost facturat!"; iesire din
* dialog prin do_renunt() (nu do_termin(), care nu elibereaza formularul la respingere).
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog, gcSyncDir
gcUILog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\test_pret_cu_tva_nivel2_retur_log.txt"
gcSyncDir = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\uisync_nivel2_retur\"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAFACTURARE\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + ;
gcAppPath + 'COMUN\UTILE\CALENDAR;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EMAIL;' + ;
gcAppPath + 'COMUN\UTILE\NFJSON;' + gcAppPath + 'COMUN\UTILE\NFXML;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO AfLog WITH 'SET PATH OK'
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms ADDITIVE
SET CLASSLIB TO ofacturare.vcx ADDITIVE
SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO ofacturare_rapoarte ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO onom_curs ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO ferestre_cere_date ADDITIVE
SET CLASSLIB TO baza ADDITIVE
SET CLASSLIB TO caut ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO serii_numere ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO _calendar.vcx ADDITIVE
SET CLASSLIB TO locale ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ocomenzi ADDITIVE
DO AfLog WITH 'SET CLASSLIB OK'
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg"
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO onomenclatoare.prg ADDITIVE
SET PROCEDURE TO onomenclatoare2.prg ADDITIVE
SET PROCEDURE TO oproceduri_rapoarte_fact.prg ADDITIVE
SET PROCEDURE TO email.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO odocumente ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO cauta_alfa.prg ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO oproceduri_curs.prg ADDITIVE
SET PROCEDURE TO proceduri.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO ofacturare.prg ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO wwApi.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO ofacturare_comun.prg ADDITIVE
SET PROCEDURE TO ofacturare_stoc.prg ADDITIVE
SET PROCEDURE TO pmenu.prg ADDITIVE
SET PROCEDURE TO ointroduceri.prg ADDITIVE
SET PROCEDURE TO ovariabile_globale.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO filebringer.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO oupdate.prg ADDITIVE
SET PROCEDURE TO procese.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO wwhttp.prg ADDITIVE
SET PROCEDURE TO xmlaccess.prg ADDITIVE
SET PROCEDURE TO xmlparser.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO suma_in_vorbe.prg ADDITIVE
SET PROCEDURE TO controllerecr ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
DO AfLog WITH 'SET PROCEDURE OK'
PUBLIC gnPc, gnPVal, gnPcant, gnPPretV, gnScadereStoc, gnMemProcDisc, gl406, gcAcces
PUBLIC gnModTotFact, gnRF_FACTURARE_FARA_STOC, gnPPret, gnPPretVal
gnPc = 2
gnPVal = 2
gnPcant = 3
gnPPretV = 4
gnPPret = 4
gnPPretVal = 4
gnScadereStoc = 0
gnMemProcDisc = 0
gl406 = .F.
gcAcces = "1;2;3;4;5;6;7;8;"
gnModTotFact = 0
gnRF_FACTURARE_FARA_STOC = 0
PUBLIC nror(65000)
PUBLIC goApp, goExport, goExecutor
goApp = CREATEOBJECT('dummyapp')
goExport = CREATEOBJECT('dummyexport')
goExecutor = CREATEOBJECT('dummyexecutor')
IF USED('jtva_coloane')
USE IN ('jtva_coloane')
ENDIF
CREATE CURSOR jtva_coloane (id_jtva_coloana N(14), denumire C(50), cota_tva N(6,2))
INSERT INTO jtva_coloane VALUES (1, 'TVA 21%', 21)
GO TOP IN jtva_coloane
IF USED('saft_taxtable')
USE IN ('saft_taxtable')
ENDIF
CREATE CURSOR saft_taxtable (taxname C(250), procent_taxa N(7,2), taxcode N(6), tva_livrari N(1))
INSERT INTO saft_taxtable VALUES ('301104-Achizitii de bunuri si servicii taxabile cu cota de 21%', 21, 301104, 1)
DO creeaza_facturacrs WITH 'crsfactura'
DO AfLog WITH 'crsfactura creat, Reccount=' + TRANSFORM(RECCOUNT('crsfactura'))
*-- crsarticole: cantitate=10 reprezinta "cat s-a facturat / e disponibil de returnat".
*-- gestionabil=0: verificarea de retur (:2265) nu are garda de gestionabil, deci ramane pe
*-- calea simpla (frm_articol_factura direct), dar plafonul tot se verifica.
IF USED('crsarticole')
USE IN ('crsarticole')
ENDIF
CREATE CURSOR crsarticole (id_articol N(10), Id_Pol N(10), id_gestiune N(10), denumire C(100), ;
codmat C(50), codbare C(50), gestionabil N(1), cantitate N(18,4), pret N(18,4), ;
pret_val N(18,4), preturi_cu_tva N(1), proc_tvav N(18,4), discount_unitar N(18,4), ;
discount_unitar_val N(18,4), pret_achizitie N(18,4), tip_valuta N(1), Curs N(18,4), ;
multiplicator N(10,4), Cont C(10), um C(10), serie C(30), lot C(30), explicatie C(200), ;
opt_facturare N(3), id_ctr N(10), numar_contract C(50), pretd N(18,4), id_valuta N(10), ;
nume_val C(20), nume_lista_preturi C(100), id_jtva_coloana N(10), taxcode N(6), id_c N(10))
INSERT INTO crsarticole (id_articol, Id_Pol, id_gestiune, denumire, codmat, codbare, ;
gestionabil, cantitate, pret, pret_val, preturi_cu_tva, proc_tvav, discount_unitar, ;
discount_unitar_val, pret_achizitie, tip_valuta, Curs, multiplicator, Cont, um, serie, ;
lot, explicatie, opt_facturare, id_ctr, numar_contract, pretd, id_valuta, nume_val, ;
nume_lista_preturi, id_jtva_coloana, taxcode, id_c) ;
VALUES (3001, 1, 1, 'ARTICOL RETUR NIVEL2', 'ART3001', '', ;
0, 10, 50, 0, 1, 1.21, 0, ;
0, 0, 0, 1, 1, '707', 'BUC', '', ;
'', '', 0, 0, '', 0, 0, '', ;
'LISTA TEST', 1, 0, 3001)
GO TOP IN crsarticole
DO AfLog WITH 'crsarticole (retur) creat, Reccount=' + TRANSFORM(RECCOUNT('crsarticole'))
PRIVATE poDate
poDate = CREATEOBJECT('oDateFactura')
poDate.tip = 8 && 8 = factura retur lei
poDate.serie_act = 'TST'
poDate.nract = 1
DO AfLog WITH 'poDate pregatit (oDateFactura), tip=' + TRANSFORM(poDate.tip)
PUBLIC goDriver, gnDriverTick, glDlgTratat, gcCazAct
gnDriverTick = 0
glDlgTratat = .F.
gcCazAct = ''
goDriver = CREATEOBJECT('driverdeblocare4')
_SCREEN.AddObject('tmrDrvN2R', 'Timer')
_SCREEN.tmrDrvN2R.Interval = 200
BINDEVENT(_SCREEN.tmrDrvN2R, 'Timer', goDriver, 'Executa')
_SCREEN.tmrDrvN2R.Enabled = .T.
DO AfLog WITH 'driver+timer pregatiti'
_SCREEN.Visible = .T.
_SCREEN.WindowState = 2
_SCREEN.Caption = 'TEST UI Nivel 2 - ramura retur (S2c)'
PUBLIC goFrm
goFrm = CREATEOBJECT('frm_facturare_articole')
goFrm.WindowType = 0
goFrm.Show()
goFrm.WindowState = 2
DOEVENTS FORCE
DO AfLog WITH 'frm_facturare_articole afisat modeless, Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
DO HarnessStep WITH 0, 'formular afisat, grid gol'
*========================= PAS 0: adaugare linie retur (cantitate default, neschimbata) =========
SELECT crsarticole
GO TOP
gcCazAct = 'ADD_DEFAULT'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_urmator1.Click()
DOEVENTS FORCE
LOCAL lnWait
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_urmator1: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
IF RECCOUNT('crsfactura') = 1
SELECT crsfactura
GO TOP
SELECT crsarticole
LOCATE FOR id_c = 3001
IF ABS(crsfactura.cantitate - (-10)) < 0.001 AND ABS(crsarticole.cantitate - 0) < 0.001
DO UILog WITH 'PASS P0 adaugare retur: crsfactura.cantitate=' + TRANSFORM(crsfactura.cantitate) + ' crsarticole.cantitate=' + TRANSFORM(crsarticole.cantitate) + ' (asteptat -10 / 0)'
ELSE
DO UILog WITH 'FAIL P0 adaugare retur: crsfactura.cantitate=' + TRANSFORM(crsfactura.cantitate) + ' crsarticole.cantitate=' + TRANSFORM(crsarticole.cantitate) + ' (asteptat -10 / 0)'
ENDIF
ELSE
DO UILog WITH 'FAIL P0: Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura')) + ' (asteptat 1) - articolul retur nu a fost adaugat'
ENDIF
DO HarnessStep WITH 1, 'P0 adaugare retur: Reccount=' + TRANSFORM(RECCOUNT('crsfactura'))
*========================= PAS 1: modificare DOAR de pret, cantitate neschimbata -> ACCEPTATA ===
IF RECCOUNT('crsfactura') = 1
gcCazAct = 'RETUR_DOAR_PRET'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P1): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF ABS(cantitate - (-10)) < 0.001 AND ABS(pretftva - 77) < 0.01
DO UILog WITH 'PASS P1 retur - doar pret modificat, ACCEPTAT: cantitate=' + TRANSFORM(cantitate) + ' pretftva=' + TRANSFORM(pretftva) + ' (asteptat -10 / 77)'
ELSE
DO UILog WITH 'FAIL P1 retur - doar pret: cantitate=' + TRANSFORM(cantitate) + ' pretftva=' + TRANSFORM(pretftva) + ' (asteptat -10 / 77 - verifica daca a fost respins pe nedrept)'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P1: nu exista randul'
ENDIF
DO HarnessStep WITH 2, 'P1 retur doar pret'
*========================= PAS 2: simulare schimbare externa a stocului sursa =========
SELECT crsarticole
LOCATE FOR id_c = 3001
IF FOUND()
REPLACE cantitate WITH 5
DO AfLog WITH 'P2: crsarticole.cantitate setat manual la 5 (simuleaza schimbare externa a stocului sursa, NU populare de crsfactura)'
ENDIF
DO HarnessStep WITH 3, 'P2 stoc extern schimbat'
*========================= PAS 3: crestere la -12 (in limita plafonului RECALCULAT=15, dar peste
*========================= plafonul VECHI fixat la 10) -> trebuie ACCEPTATA =========
IF RECCOUNT('crsfactura') = 1
gcCazAct = 'RETUR_CRESTERE_IN_PLAFON_NOU'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P3): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF ABS(cantitate - (-12)) < 0.001
DO UILog WITH 'PASS P3 retur - crestere la magnitudine 12 (peste plafonul VECHI=10, in plafonul NOU recalculat=15), ACCEPTATA: cantitate=' + TRANSFORM(cantitate) + ' - confirma ca S2c chiar RECALCULEAZA plafonul, nu il fixeaza la cantitatea initiala a liniei'
ELSE
DO UILog WITH 'FAIL P3 retur - crestere in plafonul nou: cantitate=' + TRANSFORM(cantitate) + ' (asteptat -12) - fie a fost respinsa (plafon nerecalculat), fie alta problema'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P3: nu exista randul'
ENDIF
DO HarnessStep WITH 4, 'P3 retur crestere in plafon nou'
*========================= PAS 4: crestere la -20 (peste plafonul NOU=15) -> RESPINSA =========
IF RECCOUNT('crsfactura') = 1
LOCAL lnCantitateInainte
SELECT crsfactura
GO TOP
lnCantitateInainte = cantitate
gcCazAct = 'RETUR_CRESTERE_PESTE_PLAFON'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa But_modifica1 (P4): glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
GO TOP
IF ABS(cantitate - lnCantitateInainte) < 0.001
DO UILog WITH 'PASS P4 retur - crestere la magnitudine 20 (peste plafonul nou=15) RESPINSA: randul a ramas neschimbat, cantitate=' + TRANSFORM(cantitate)
ELSE
DO UILog WITH 'FAIL P4 retur - crestere peste plafon: cantitate=' + TRANSFORM(cantitate) + ' (asteptat neschimbat, ' + TRANSFORM(lnCantitateInainte) + ') - a fost acceptata desi trebuia respinsa'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P4: nu exista randul'
ENDIF
DO HarnessStep WITH 5, 'P4 retur peste plafon - final'
DO HarnessDone WITH 'done'
CATCH TO loExc
DO AfLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
DO HarnessDone WITH 'done-error'
ENDTRY
QUIT
*==================================================================================
PROCEDURE AfErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO AfLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE AfLog
LPARAMETERS tcMsg
SET SAFETY OFF
LOCAL lcL
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
ENDPROC
PROCEDURE UILog
LPARAMETERS tcMsg
DO AfLog WITH tcMsg
ENDPROC
PROCEDURE FindCtl
LPARAMETERS toParent, tcName
LOCAL lnI, loGasit
loGasit = .NULL.
FOR lnI = 1 TO toParent.ControlCount
IF UPPER(toParent.Controls(lnI).Name) == UPPER(tcName)
loGasit = toParent.Controls(lnI)
ENDIF
ENDFOR
RETURN loGasit
ENDPROC
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexport AS Custom
PROCEDURE citesteSetareRegistru
LPARAMETERS tcCheie
RETURN ''
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexecutor AS Custom
cEroare = ''
PROCEDURE oExecute
LPARAMETERS tcSql, tcCursor
IF USED(tcCursor)
USE IN (tcCursor)
ENDIF
CREATE CURSOR (tcCursor) (codmatf C(50))
RETURN 1
ENDPROC
PROCEDURE oReset
ENDPROC
ENDDEFINE
DEFINE CLASS driverdeblocare4 AS Custom
PROCEDURE Executa
LOCAL lnI, loForm, llGasit
gnDriverTick = gnDriverTick + 1
llGasit = .F.
FOR lnI = 1 TO _SCREEN.FormCount
IF UPPER(_SCREEN.Forms(lnI).Class) == 'FRM_ARTICOL_FACTURA'
loForm = _SCREEN.Forms(lnI)
llGasit = .T.
ENDIF
ENDFOR
IF glDlgTratat OR !llGasit
RETURN
ENDIF
DO AfLog WITH 'driver4 tick ' + TRANSFORM(gnDriverTick) + ' POTRIVIT (caz=' + gcCazAct + '), intru in interactiune'
LOCAL loCantitateCtn, loCantitate, loPretFtvaCtn, loPretFtvaNat, loRenunt
TRY
DO CASE
CASE gcCazAct == 'ADD_DEFAULT'
DO AfLog WITH 'driver4 ADD_DEFAULT: nu ating nimic, apas do_termin() (accepta valorile implicite)'
loForm.do_termin()
CASE gcCazAct == 'RETUR_DOAR_PRET'
loPretFtvaCtn = FindCtl(loForm, 'Clb_pretftva')
loPretFtvaNat = FindCtl(loPretFtvaCtn, 'tx_suma_nat')
loPretFtvaNat.Value = 77
loPretFtvaNat.InteractiveChange()
DO AfLog WITH 'driver4 RETUR_DOAR_PRET: pretftva=77, cantitate neatinsa, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'RETUR_CRESTERE_IN_PLAFON_NOU'
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = -12
loCantitate.InteractiveChange()
DO AfLog WITH 'driver4 RETUR_CRESTERE_IN_PLAFON_NOU: cantitate=-12, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'RETUR_CRESTERE_PESTE_PLAFON'
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = -20
loCantitate.InteractiveChange()
DO AfLog WITH 'driver4 RETUR_CRESTERE_PESTE_PLAFON: cantitate=-20, apas do_termin() (asteptat: respins, ramane deschis)'
loForm.do_termin()
DO AfLog WITH 'driver4: dupa do_termin() pe cazul de respingere - inchid explicit prin do_renunt() ca sa nu ramana Show(1) blocat'
loForm.do_renunt()
OTHERWISE
DO AfLog WITH 'driver4: gcCazAct necunoscut [' + gcCazAct + ']'
ENDCASE
glDlgTratat = .T.
DO AfLog WITH 'driver4: interactiune REUSITA pentru caz=' + gcCazAct
CATCH TO loExcDrv
DO AfLog WITH 'driver4: CATCH caz=' + gcCazAct + ' ErrorNo=' + TRANSFORM(loExcDrv.ErrorNo) + ;
' Message=' + loExcDrv.Message + ' Procedure=' + loExcDrv.Procedure + ;
' LineNo=' + TRANSFORM(loExcDrv.LineNo) + ' LineContents=[' + loExcDrv.LineContents + ']'
ENDTRY
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,12 @@
# test_pret_cu_tva_nivel2_retur.ps1 - wrapper peste harness-ul generic pentru ramura de retur
# a plafonului recalculat (S2c, rec_s2c_ncantitatemax.md). Rulare:
# powershell -ExecutionPolicy Bypass -File test_pret_cu_tva_nivel2_retur.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
-TestPrg (Join-Path $Teste 'test_pret_cu_tva_nivel2_retur.prg') `
-Steps @('formular_afisat', 'p0_adaugare', 'p1_doar_pret', 'p2_stoc_extern', 'p3_in_plafon_nou', 'p4_peste_plafon') `
-ShotsDir (Join-Path $Teste 'screenshots_nivel2_retur') `
-SyncDir (Join-Path $Teste 'uisync_nivel2_retur') `
-StepTimeoutSec 60 `
-ReadyTimeoutSec 90

View File

@@ -0,0 +1,940 @@
* test_pret_cu_tva_nivel3_gestiuni.prg
* Test UI Nivel 3 (S2d, plan #7) pentru ramura GESTIONABILA a lui do_modifica/do_adauga_articol -
* dialogul frm_articol_gest_factura, deschis prin do_alege_stoc (frm_facturare_articole,
* ofacturare.vc2). Decizia coordonatorului: se mockuieste Oracle la GRANITA (goExecutor.oExecute,
* singurul punct de contact al lui do_alege_stoc cu Oracle), NU se populeaza direct crsgestarticol/
* crsfactura - fluxul real (butoane, taste, SPACE) ramane intact, doar sursa de date se inlocuieste.
*
* Articol 3001, gestionabil=1, gnScadereStoc=1, poDate.tip=4 (aviz - in Inlist-ul validat de
* inainte_de_do_termin SI de plafonul S2c/S2d). 4 gestiuni mock, stoc constant (10/15/8/6) - Oracle
* nu stie de cosul in lucru, exact ca in productie; scaderea celor deja pe factura o face codul
* real (sub-selectul cu excluderea id_temp, S2d pct. 1).
*
* Cazuri (litere din review-ul S2d):
* PAS 1 (caz a): adaugare linie1 din gestiunea G1 -> dialogul cu gestiuni arata mai multe
* gestiuni (nu auto-select), ck_pret_cu_tva exista si e la Top=510 pe forma Height=546.
* PAS 2: adaugare linie2 (acelasi articol) din gestiunea G2 - pregateste discriminantul de la c.
* PAS 3 (cazuri b+c): redeschide linia1 -> crsgestarticol pozitionat pe gestiunea G1 a liniei;
* randul G1 arata stocul disponibil PLUS cantitatea proprie (10, nu 7); randul G2 (linia2,
* neexclusa) arata stocul scazut normal (11, nu 15). Inchis cu Renunta, nimic comis.
* PAS 4 (caz d, respins): redeschide linia1, cere cantitate 11 (peste stocul gestiunii G1=10) ->
* respins cu mesajul real "Cantitatea nu poate fi mai mare decat stocul gestiunii ...".
* PAS 5 (caz d, acceptat): redeschide linia1, cere cantitate 10 (exact stocul gestiunii) ->
* acceptat.
* PAS 6 (caz e): redeschide linia1, navigheaza (fara SPACE) pe gestiunea G3, cantitate 5 ->
* acceptat, linia1 trece pe G3. Verifica si g) crsarticole ajustat cu diferenta (-5).
* PAS 7 (caz f+g): redeschide linia1, SPACE pe G1 si G4 (multi-selectie) -> linia1 devine G1/10,
* apare O SINGURA linie noua G4/6 (exact regresia Scan/Skip, deja corectata) - Reccount
* creste cu 1, nu cu 2. Verifica si crsarticole ajustat cu diferenta (delta 16-5=11).
* PAS 8 (caz h): redeschide linia1, schimba pretul, apasa Renunta -> randul ramane BIT-IDENTIC.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcUILog, gcSyncDir
gcUILog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\test_pret_cu_tva_nivel3_gestiuni_log.txt"
gcSyncDir = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\facturare_pret_cu_tva\uisync_nivel3\"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcUILog)
ON ERROR DO AfErr WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAFACTURARE\"
SET DEFAULT TO (gcAppPath)
lcPath = gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + ;
gcAppPath + 'COMUN\UTILE\CALENDAR;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EMAIL;' + ;
gcAppPath + 'COMUN\UTILE\NFJSON;' + gcAppPath + 'COMUN\UTILE\NFXML;' + ;
gcAppPath + 'COMUN\UTILE\GridExtras;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO AfLog WITH 'SET PATH OK'
*----- CLASE (lista dovedita de Nivel 1/2 - mediul unei suite noi se mosteneste din suita
* care TRECE, nu dintr-un smoke-test) -----
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms ADDITIVE
SET CLASSLIB TO ofacturare.vcx ADDITIVE
SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO ofacturare_rapoarte ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO onom_curs ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO ferestre_cere_date ADDITIVE
SET CLASSLIB TO baza ADDITIVE
SET CLASSLIB TO caut ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO serii_numere ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO _calendar.vcx ADDITIVE
SET CLASSLIB TO locale ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ocomenzi ADDITIVE
DO AfLog WITH 'SET CLASSLIB OK'
*----- PROCEDURI (mock amessagebox PRIMUL, ui_harness la final) -----
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg"
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO onomenclatoare.prg ADDITIVE
SET PROCEDURE TO onomenclatoare2.prg ADDITIVE
SET PROCEDURE TO oproceduri_rapoarte_fact.prg ADDITIVE
SET PROCEDURE TO email.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO odocumente ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO cauta_alfa.prg ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO oproceduri_curs.prg ADDITIVE
SET PROCEDURE TO proceduri.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO ofacturare.prg ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO wwApi.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO ofacturare_comun.prg ADDITIVE
SET PROCEDURE TO ofacturare_stoc.prg ADDITIVE
SET PROCEDURE TO pmenu.prg ADDITIVE
SET PROCEDURE TO ointroduceri.prg ADDITIVE
SET PROCEDURE TO ovariabile_globale.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO filebringer.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO oupdate.prg ADDITIVE
SET PROCEDURE TO procese.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO wwhttp.prg ADDITIVE
SET PROCEDURE TO xmlaccess.prg ADDITIVE
SET PROCEDURE TO xmlparser.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO suma_in_vorbe.prg ADDITIVE
SET PROCEDURE TO controllerecr ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\ui_harness.prg" ADDITIVE
DO AfLog WITH 'SET PROCEDURE OK'
*----- Globale aplicatie -----
PUBLIC gnPc, gnPVal, gnPcant, gnPPretV, gnScadereStoc, gnMemProcDisc, gl406, gcAcces
PUBLIC gnModTotFact, gnRF_FACTURARE_FARA_STOC
gnModTotFact = 0
gnRF_FACTURARE_FARA_STOC = 0
PUBLIC gnPPret, gnPPretVal
gnPc = 2
gnPVal = 2
gnPcant = 3
gnPPretV = 4
gnPPret = 4
gnPPretVal = 4
gnScadereStoc = 1 && activeaza ramura de stoc - do_alege_stoc SE apeleaza (opusul Nivel 2)
gnMemProcDisc = 0
gl406 = .F.
gcAcces = "1;2;3;4;5;6;7;8;"
*-- do_alege_stoc citeste si aceste globale (parametri SQL cursor_gestiuni_articol) - lipsa lor
*-- da ON ERROR 12 "Variable not found" la primul apel
PUBLIC gnAn, gnLuna, gnIdUtil, gnIdSucursala
gnAn = YEAR(DATE())
gnLuna = MONTH(DATE())
gnIdUtil = 1
gnIdSucursala = 0
PUBLIC nror(65000)
*-- gcMockUltimMesaj: mock_amessagebox.prg memoreaza aici ultimul mesaj afisat - folosit pt.
*-- asertia pe TEXTUL respingerii de plafon (caz d).
PUBLIC gcMockUltimMesaj, gnMockUltimTip
gcMockUltimMesaj = ''
gnMockUltimTip = 0
PUBLIC goApp, goExport, goExecutor
goApp = CREATEOBJECT('dummyapp')
goExport = CREATEOBJECT('dummyexport')
goExecutor = CREATEOBJECT('dummyexecutor')
IF USED('jtva_coloane')
USE IN ('jtva_coloane')
ENDIF
CREATE CURSOR jtva_coloane (id_jtva_coloana N(14), denumire C(50), cota_tva N(6,2))
INSERT INTO jtva_coloane VALUES (1, 'TVA 21%', 21)
INSERT INTO jtva_coloane VALUES (2, 'TVA 11%', 11)
GO TOP IN jtva_coloane
IF USED('saft_taxtable')
USE IN ('saft_taxtable')
ENDIF
CREATE CURSOR saft_taxtable (taxname C(250), procent_taxa N(7,2), taxcode N(6), tva_livrari N(1))
INSERT INTO saft_taxtable VALUES ('301104-Achizitii de bunuri si servicii taxabile cu cota de 21%', 21, 301104, 1)
INSERT INTO saft_taxtable VALUES ('3011XX-Achizitii de bunuri si servicii taxabile cu cota de 11%', 11, 301108, 1)
*----- crsfactura: structura REALA, fara Oracle -----
DO creeaza_facturacrs WITH 'crsfactura'
DO AfLog WITH 'crsfactura creat, Reccount=' + TRANSFORM(RECCOUNT('crsfactura'))
*----- crsarticole: sursa (stoc/lista de preturi). Articolul 3001, gestionabil=1, cantitate mare
* (plafonul S2c/S2d ramane generos - testele de mai jos verifica plafonul PE LOT din
* dialogul de gestiuni, nu plafonul pe articol din crsarticole). -----
IF USED('crsarticole')
USE IN ('crsarticole')
ENDIF
CREATE CURSOR crsarticole (id_articol N(10), Id_Pol N(10), id_gestiune N(10), denumire C(100), ;
codmat C(50), codbare C(50), gestionabil N(1), cantitate N(18,4), pret N(18,4), ;
pret_val N(18,4), preturi_cu_tva N(1), proc_tvav N(18,4), discount_unitar N(18,4), ;
discount_unitar_val N(18,4), pret_achizitie N(18,4), tip_valuta N(1), Curs N(18,4), ;
multiplicator N(10,4), Cont C(10), um C(10), serie C(30), lot C(30), explicatie C(200), ;
opt_facturare N(3), id_ctr N(10), numar_contract C(50), pretd N(18,4), id_valuta N(10), ;
nume_val C(20), nume_lista_preturi C(100), id_jtva_coloana N(10), taxcode N(6), id_c N(10))
INSERT INTO crsarticole (id_articol, Id_Pol, id_gestiune, denumire, codmat, codbare, ;
gestionabil, cantitate, pret, pret_val, preturi_cu_tva, proc_tvav, discount_unitar, ;
discount_unitar_val, pret_achizitie, tip_valuta, Curs, multiplicator, Cont, um, serie, ;
lot, explicatie, opt_facturare, id_ctr, numar_contract, pretd, id_valuta, nume_val, ;
nume_lista_preturi, id_jtva_coloana, taxcode, id_c) ;
VALUES (3001, 1, 0, 'ARTICOL GESTIUNI NIVEL3', 'ART3001', '', ;
1, 1000, 50, 0, 0, 1.21, 0, ;
0, 0, 0, 1, 1, '701', 'BUC', '', ;
'', '', 0, 0, '', 0, 0, '', ;
'LISTA TEST', 1, 0, 3001)
GO TOP IN crsarticole
DO AfLog WITH 'crsarticole creat, Reccount=' + TRANSFORM(RECCOUNT('crsarticole'))
*----- crsMockStoc: gestiunile "Oracle" pentru articolul 3001, stoc FIX pe tot testul - Oracle
* nu stie de cosul in lucru; scaderea celor deja pe factura o face codul real (LEFT JOIN +
* excluderea id_temp, S2d pct. 1), nu mock-ul. dummyexecutor.oExecute o serveste la fiecare
* apel cu 'cursor_gestiuni_articol' in SQL. Coloanele sunt exact cele citite de do_alege_stoc
* (Insert Into (lcCursor) (...), ofacturare.vc2:13299, si copiaza_structura_cursor). -----
IF USED('crsMockStoc')
USE IN ('crsMockStoc')
ENDIF
*-- Cont/serie/lot cu ACEEASI latime ca in crsfactura (creeaza_facturacrs: Cont c(4), serie c(100),
*-- lot C(20)) - LEFT JOIN-ul din do_alege_stoc compara aceste campuri intre cele doua cursoare
*-- (:13304-13306); latimi diferite ar produce padding diferit si ar rupe egalitatea sub SET EXACT ON.
*-- datain e DateTime (T), nu Date: coloana cDataIn a gridului are ControlSource "TTOD(datain)"
*-- (ofacturare.vc2:3519), iar TTOD pe un camp D da eroarea 11 la constructia formularului.
CREATE CURSOR crsMockStoc (ales N(1), id_gestiune N(10), cantitate N(18,4), Cont C(4), ;
serie C(100), lot C(20), Pret N(18,4), nume_gestiune C(50), datain T, pretv N(18,4), ;
pretvctva N(18,4), part_rez C(30), id_part_rez N(10), nrord_rez N(10), id_lucrare_rez N(10), ;
pretd N(18,4), id_valuta N(10), nume_val C(20))
INSERT INTO crsMockStoc VALUES (0, 101, 10, '701', 'SG1', 'LOT1', 50, 'GESTIUNE 1', {^2020-01-01 08:00:00}, 50, 60.50, '', 0, 0, 0, 0, 0, '')
INSERT INTO crsMockStoc VALUES (0, 102, 15, '701', 'SG2', 'LOT2', 55, 'GESTIUNE 2', {^2020-01-02 08:00:00}, 55, 66.55, '', 0, 0, 0, 0, 0, '')
INSERT INTO crsMockStoc VALUES (0, 103, 8, '701', 'SG3', 'LOT3', 52, 'GESTIUNE 3', {^2020-01-03 08:00:00}, 52, 62.92, '', 0, 0, 0, 0, 0, '')
INSERT INTO crsMockStoc VALUES (0, 104, 6, '701', 'SG4', 'LOT4', 48, 'GESTIUNE 4', {^2020-01-04 08:00:00}, 48, 58.08, '', 0, 0, 0, 0, 0, '')
GO TOP IN crsMockStoc
DO AfLog WITH 'crsMockStoc creat (4 gestiuni, stoc 10/15/8/6), Reccount=' + TRANSFORM(RECCOUNT('crsMockStoc'))
*----- poDate: clasa REALA oDateFactura -----
PRIVATE poDate
poDate = CREATEOBJECT('oDateFactura')
poDate.tip = 4 && 4 = aviz - in Inlist-ul validat de inainte_de_do_termin SI de plafonul S2c/S2d
poDate.serie_act = 'TST'
poDate.nract = 1
DO AfLog WITH 'poDate pregatit (oDateFactura), tip=' + TRANSFORM(poDate.tip) + ' gnScadereStoc=' + TRANSFORM(gnScadereStoc)
*----- driverul de deblocare Show(1): Timer la nivel _SCREEN + _SCREEN.Forms + Controls(i),
* mecanism validat (test_modal_unlock_smoketest2.prg / Nivel 2). De data asta cauta
* FRM_ARTICOL_GEST_FACTURA, nu FRM_ARTICOL_FACTURA. -----
PUBLIC goDriver, gnDriverTick, glDlgTratat, gcCazAct
gnDriverTick = 0
glDlgTratat = .F.
gcCazAct = ''
goDriver = CREATEOBJECT('driverdeblocaregest')
_SCREEN.AddObject('tmrDrvN3', 'Timer')
_SCREEN.tmrDrvN3.Interval = 200
BINDEVENT(_SCREEN.tmrDrvN3, 'Timer', goDriver, 'Executa')
_SCREEN.tmrDrvN3.Enabled = .T.
DO AfLog WITH 'driver+timer pregatiti (cauta FRM_ARTICOL_GEST_FACTURA)'
*----- Desktop VFP vizibil, ca la celelalte suite UI -----
_SCREEN.Visible = .T.
_SCREEN.WindowState = 2
_SCREEN.Caption = 'TEST UI Nivel 3 (S2d - ramura gestiuni)'
PUBLIC goFrm
goFrm = CREATEOBJECT('frm_facturare_articole')
goFrm.WindowType = 0 && testul instantiaza direct - modeless, Show() revine imediat
goFrm.Show()
goFrm.WindowState = 2
DOEVENTS FORCE
DO AfLog WITH 'frm_facturare_articole afisat modeless, Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
DO HarnessStep WITH 0, 'formular afisat, mediu pregatit'
*-- Local-e folosite pe tot parcursul --
LOCAL lnWait, lnIdTempLinie1, lnIdTempLinie2, lnArtStocInainte, lnArtStocDupa
*========================= PAS 1 (caz a): adaugare linie1 din G1 =========================
SELECT crsarticole
GO TOP
gcCazAct = 'ADD_G1_Q3'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_urmator1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa ADD_G1_Q3: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
IF RECCOUNT('crsfactura') = 1
SELECT crsfactura
GO TOP
lnIdTempLinie1 = id_temp
IF id_gestiune = 101 AND ABS(cantitate - 3) < 0.001
DO UILog WITH 'PASS P1 (caz a) linia1 adaugata din G1: id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' pret_achizitie=' + TRANSFORM(pret_achizitie)
ELSE
DO UILog WITH 'FAIL P1 (caz a) linia1: id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' (asteptat id_gestiune=101 cantitate=3)'
ENDIF
ELSE
DO UILog WITH 'FAIL P1 (caz a): Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura')) + ' (asteptat 1) - linia1 nu a fost adaugata'
ENDIF
DO HarnessStep WITH 1, 'P1 linia1 adaugata din G1'
*========================= PAS 2: adaugare linie2 (acelasi articol) din G2 =========================
SELECT crsarticole
GO TOP
gcCazAct = 'ADD_G2_Q4'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_urmator1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa ADD_G2_Q4: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
IF RECCOUNT('crsfactura') = 2
SELECT crsfactura
LOCATE FOR id_gestiune = 102
IF FOUND()
lnIdTempLinie2 = id_temp
IF ABS(cantitate - 4) < 0.001
DO UILog WITH 'PASS P2 linia2 adaugata din G2: cantitate=' + TRANSFORM(cantitate)
ELSE
DO UILog WITH 'FAIL P2 linia2: cantitate=' + TRANSFORM(cantitate) + ' (asteptat 4)'
ENDIF
ELSE
DO UILog WITH 'FAIL P2: nu exista rand cu id_gestiune=102'
ENDIF
ELSE
DO UILog WITH 'FAIL P2: Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura')) + ' (asteptat 2)'
ENDIF
DO HarnessStep WITH 2, 'P2 linia2 adaugata din G2'
*========================= PAS 3 (cazuri b+c): redeschide linia1, verifica preselectia si
*========================= excluderea id_temp, apoi Renunta (nimic comis) =========================
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
gcCazAct = 'MOD_L1_PRESELECT_CHECK'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_PRESELECT_CHECK: glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
IF RECCOUNT('crsfactura') = 2 AND FOUND() AND id_gestiune = 101 AND ABS(cantitate - 3) < 0.001
DO UILog WITH 'PASS P3 (caz b+c, Renunta) nimic comis: Reccount=2, linia1 neschimbata (G1/3)'
ELSE
DO UILog WITH 'FAIL P3 (caz b+c, Renunta): Reccount=' + TRANSFORM(RECCOUNT('crsfactura')) + ' found=' + TRANSFORM(FOUND()) + ' id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' (asteptat 2 / 101 / 3)'
ENDIF
DO HarnessStep WITH 3, 'P3 cazuri b+c - preselectie si excludere id_temp'
*========================= PAS 4 (caz d, respins): redeschide linia1, cere 11 (peste stocul G1=10) =========================
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
gcCazAct = 'MOD_L1_REJECT_OVER_LOT'
glDlgTratat = .F.
gnDriverTick = 0
gcMockUltimMesaj = ''
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_REJECT_OVER_LOT: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' mesaj=[' + gcMockUltimMesaj + ']'
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
IF ABS(cantitate - 3) < 0.001 AND 'stocul gestiunii' $ gcMockUltimMesaj
DO UILog WITH 'PASS P4 (caz d, respins) cantitate 11 peste stocul G1(10) respinsa, linia neschimbata (cantitate=' + TRANSFORM(cantitate) + '), mesaj=[' + gcMockUltimMesaj + ']'
ELSE
DO UILog WITH 'FAIL P4 (caz d, respins): cantitate=' + TRANSFORM(cantitate) + ' (asteptat 3, neschimbata) mesaj=[' + gcMockUltimMesaj + ']'
ENDIF
DO HarnessStep WITH 4, 'P4 caz d - respins peste plafonul lotului'
*========================= PAS 5 (caz d, acceptat): redeschide linia1, cere exact 10 =========================
SELECT crsarticole
lnArtStocInainte = cantitate
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
gcCazAct = 'MOD_L1_ACCEPT_AT_LOT'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_ACCEPT_AT_LOT: glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
IF ABS(cantitate - 10) < 0.001 AND id_gestiune = 101
DO UILog WITH 'PASS P5 (caz d, acceptat) cantitate 10 (exact stocul G1) acceptata: cantitate=' + TRANSFORM(cantitate)
ELSE
DO UILog WITH 'FAIL P5 (caz d, acceptat): cantitate=' + TRANSFORM(cantitate) + ' id_gestiune=' + TRANSFORM(id_gestiune) + ' (asteptat 10 / 101)'
ENDIF
*-- caz g: cantitatea liniei a crescut de la 3 la 10 (delta +7) -> crsarticole trebuie sa scada cu 7
SELECT crsarticole
lnArtStocDupa = cantitate
IF ABS((lnArtStocInainte - lnArtStocDupa) - 7) < 0.001
DO UILog WITH 'PASS P5 (caz g) crsarticole ajustat cu diferenta: ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (-7, cantitatea liniei a crescut 3->10)'
ELSE
DO UILog WITH 'FAIL P5 (caz g): crsarticole ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (asteptat -7)'
ENDIF
DO HarnessStep WITH 5, 'P5 caz d - acceptat la exact plafonul lotului'
*========================= PAS 6 (caz e + g): navigheaza (fara SPACE) pe G3, cantitate 5 =========================
*-- martorul se ia AICI: cel din PAS 5 masoara efectul lui PAS 5, nu al lui PAS 6
SELECT crsarticole
lnArtStocInainte = cantitate
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
gcCazAct = 'MOD_L1_CHANGE_GESTIUNE_NAV'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_CHANGE_GESTIUNE_NAV: glDlgTratat=' + TRANSFORM(glDlgTratat)
SELECT crsarticole
lnArtStocDupa = cantitate
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
IF id_gestiune = 103 AND ABS(cantitate - 5) < 0.001 AND ABS(pret_achizitie - 52) < 0.001
DO UILog WITH 'PASS P6 (caz e) schimbare gestiune prin navigare (fara SPACE): id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' pret_achizitie=' + TRANSFORM(pret_achizitie)
ELSE
DO UILog WITH 'FAIL P6 (caz e): id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' pret_achizitie=' + TRANSFORM(pret_achizitie) + ' (asteptat 103 / 5 / 52)'
ENDIF
*-- caz g: cantitatea liniei a scazut de la 10 la 5 (delta -5) -> crsarticole trebuie sa creasca cu 5
IF ABS((lnArtStocDupa - lnArtStocInainte) - 5) < 0.001
DO UILog WITH 'PASS P6 (caz g) crsarticole ajustat cu diferenta: ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (+5, cantitatea liniei a scazut 10->5)'
ELSE
DO UILog WITH 'FAIL P6 (caz g): crsarticole ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (asteptat +5)'
ENDIF
DO HarnessStep WITH 6, 'P6 caz e+g - schimbare gestiune prin navigare + sincronizare crsarticole'
*========================= PAS 7 (caz f + g): multi-selectie SPACE pe G1 si G4 =========================
SELECT crsarticole
lnArtStocInainte = cantitate
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
gcCazAct = 'MOD_L1_MULTISELECT'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_MULTISELECT: glDlgTratat=' + TRANSFORM(glDlgTratat) + ' Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
SELECT crsarticole
lnArtStocDupa = cantitate
IF RECCOUNT('crsfactura') = 3
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
LOCAL llL1ok, llL2ok, llNouaOk
llL1ok = (id_gestiune = 101 AND ABS(cantitate - 10) < 0.001)
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie2
llL2ok = FOUND() AND id_gestiune = 102 AND ABS(cantitate - 4) < 0.001
SELECT crsfactura
LOCATE FOR id_gestiune = 104
llNouaOk = FOUND() AND ABS(cantitate - 6) < 0.001 AND id_temp <> lnIdTempLinie1 AND id_temp <> lnIdTempLinie2
IF llL1ok AND llL2ok AND llNouaOk
DO UILog WITH 'PASS P7 (caz f) multi-selectie: Reccount=3 (linia1 actualizata G1/10, linia2 neschimbata G2/4, O SINGURA linie noua G4/6 - fara duplicat)'
ELSE
DO UILog WITH 'FAIL P7 (caz f): llL1ok=' + TRANSFORM(llL1ok) + ' llL2ok=' + TRANSFORM(llL2ok) + ' llNouaOk=' + TRANSFORM(llNouaOk)
ENDIF
ELSE
DO UILog WITH 'FAIL P7 (caz f): Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura')) + ' (asteptat 3 - daca e 4, a reaparut regresia Scan/Skip cu linie duplicat)'
ENDIF
*-- caz g: cantitatea totala a articolului pe factura a crescut de la 5+4=9 la 10+6+4=20, delta +11 -> crsarticole trebuie sa scada cu 11
IF ABS((lnArtStocInainte - lnArtStocDupa) - 11) < 0.001
DO UILog WITH 'PASS P7 (caz g) crsarticole ajustat cu diferenta: ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (-11, cantitatea totala a crescut de la 5 la 16 pe aceasta redeschidere)'
ELSE
DO UILog WITH 'FAIL P7 (caz g): crsarticole ' + TRANSFORM(lnArtStocInainte) + ' -> ' + TRANSFORM(lnArtStocDupa) + ' (asteptat -11)'
ENDIF
DO HarnessStep WITH 7, 'P7 caz f+g - multi-selectie si sincronizare crsarticole'
*========================= PAS 8 (caz h): Renunta pe dialogul cu gestiuni - rand bit-identic =========================
IF RECCOUNT('crsfactura') >= 1
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
IF FOUND()
LOCAL ARRAY laSnapDinainte[1]
LOCAL lnF, lnCampuri
SCATTER TO laSnapDinainte
gcCazAct = 'MOD_L1_RENUNTA'
glDlgTratat = .F.
gnDriverTick = 0
goFrm.But_modifica1.Click()
DOEVENTS FORCE
lnWait = 0
DO WHILE !glDlgTratat AND lnWait < 150
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO AfLog WITH 'dupa MOD_L1_RENUNTA: glDlgTratat=' + TRANSFORM(glDlgTratat)
LOCAL ARRAY laSnapDupa[1]
SELECT crsfactura
LOCATE FOR id_temp = lnIdTempLinie1
SCATTER TO laSnapDupa
LOCAL llIdentic
llIdentic = (ALEN(laSnapDinainte,1) == ALEN(laSnapDupa,1))
lnCampuri = 0
IF llIdentic
FOR lnF = 1 TO ALEN(laSnapDinainte,1)
lnCampuri = lnCampuri + 1
IF !(TRANSFORM(laSnapDinainte(lnF)) == TRANSFORM(laSnapDupa(lnF)))
llIdentic = .F.
DO AfLog WITH 'P8 diagnostic - campul ' + TRANSFORM(lnF) + ' difera: [' + ;
TRANSFORM(laSnapDinainte(lnF)) + '] -> [' + TRANSFORM(laSnapDupa(lnF)) + ']'
ENDIF
ENDFOR
ENDIF
IF llIdentic
DO UILog WITH 'PASS P8 (caz h) Renunta pe dialogul cu gestiuni: randul ramane BIT-IDENTIC (' + TRANSFORM(lnCampuri) + ' campuri comparate)'
ELSE
DO UILog WITH 'FAIL P8 (caz h): randul S-A MODIFICAT desi s-a apasat Renunta (vezi diag pe campuri mai sus)'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P8: linia1 (id_temp=' + TRANSFORM(lnIdTempLinie1) + ') nu mai exista'
ENDIF
ELSE
DO UILog WITH 'NEACOPERIT P8: crsfactura gol'
ENDIF
DO HarnessStep WITH 8, 'P8 caz h - Renunta bit-identic'
DO HarnessDone WITH 'done'
CATCH TO loExc
DO AfLog WITH 'CATCH ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
*-- DIAGNOSTIC temporar: AERROR() suplimentar, stare crsgestarticol, si o proba izolata de
*-- CREATEOBJECT("frm_articol_gest_factura",...) cu poArticol construit liber (ca Nivel 1) -
*-- separa o cauza de MEDIU (clase/globale) de una legata de FORMA lui poArticol produs de
*-- fluxul real (do_initializeaza_articol).
LOCAL ARRAY laErrDiag(1)
LOCAL lnEd
=AERROR(laErrDiag)
FOR lnEd = 1 TO ALEN(laErrDiag,1)
DO AfLog WITH 'AERROR[' + TRANSFORM(lnEd) + ']=' + TRANSFORM(NVL(laErrDiag(lnEd),'.NULL.'))
ENDFOR
DO AfLog WITH 'DIAG: USED(crsgestarticol)=' + TRANSFORM(USED('crsgestarticol')) + IIF(USED('crsgestarticol'), ' Reccount=' + TRANSFORM(RECCOUNT('crsgestarticol')), '')
LOCAL lnPi, loProba
LOCAL ARRAY laPPropN(49), laPPropC(11)
laPPropN( 1)='id_articol'
laPPropN( 2)='Id_Pol'
laPPropN( 3)='id_gestiune'
laPPropN( 4)='id_c'
laPPropN( 5)='id_ctr'
laPPropN( 6)='id_valuta'
laPPropN( 7)='id_valuta_d'
laPPropN( 8)='id_lucrare_rez'
laPPropN( 9)='id_part_rez'
laPPropN(10)='id_jtva_coloana'
laPPropN(11)='taxcode'
laPPropN(12)='opt_facturare'
laPPropN(13)='gestionabil'
laPPropN(14)='tip_valuta'
laPPropN(15)='cantitate'
laPPropN(16)='Curs'
laPPropN(17)='multiplicator'
laPPropN(18)='pret_achizitie'
laPPropN(19)='pretv_orig'
laPPropN(20)='pretd'
laPPropN(21)='proc_tvav'
laPPropN(22)='preturi_cu_tva'
laPPropN(23)='pretftva'
laPPropN(24)='pretftva_val'
laPPropN(25)='pretctva'
laPPropN(26)='pretctva_val'
laPPropN(27)='tva'
laPPropN(28)='tva_val'
laPPropN(29)='discount_unitar'
laPPropN(30)='discount_unitar_val'
laPPropN(31)='discount_unitar_ctva'
laPPropN(32)='discount_unitar_ctva_val'
laPPropN(33)='valftva'
laPPropN(34)='valtva'
laPPropN(35)='valctva'
laPPropN(36)='valdiscountftva'
laPPropN(37)='valdiscounttva'
laPPropN(38)='valdiscountctva'
laPPropN(39)='valdiminuatftva'
laPPropN(40)='valdiminuattva'
laPPropN(41)='valdiminuatctva'
laPPropN(42)='vvalftva'
laPPropN(43)='vvaltva'
laPPropN(44)='vvalctva'
laPPropN(45)='vvaldiscountftva'
laPPropN(46)='vvaldiscounttva'
laPPropN(47)='vvaldiscountctva'
laPPropN(48)='vvaldiminuatftva'
laPPropN(49)='vvaldiminuattva'
laPPropC( 1)='codmat'
laPPropC( 2)='codmatf'
laPPropC( 3)='denumire'
laPPropC( 4)='um'
laPPropC( 5)='serie'
laPPropC( 6)='lot'
laPPropC( 7)='explicatie'
laPPropC( 8)='numar_contract'
laPPropC( 9)='codbare'
laPPropC(10)='nume_val'
laPPropC(11)='Cont'
PRIVATE poArticol
poArticol = CREATEOBJECT('Empty')
FOR lnPi = 1 TO 49
=ADDPROPERTY(poArticol, laPPropN(lnPi), 0)
ENDFOR
=ADDPROPERTY(poArticol, 'vvaldiminuatctva', 0)
FOR lnPi = 1 TO 11
=ADDPROPERTY(poArticol, laPPropC(lnPi), '')
ENDFOR
poArticol.id_articol = 3001
poArticol.Id_Pol = 1
poArticol.Cont = '701'
poArticol.id_gestiune = 101
poArticol.gestionabil = 1
poArticol.tip_valuta = 0
poArticol.Curs = 1
poArticol.multiplicator = 1
poArticol.cantitate = 3
poArticol.codmat = 'ART3001'
poArticol.denumire = 'ARTICOL GESTIUNI NIVEL3'
poArticol.um = 'BUC'
poArticol.proc_tvav = 1.21
poArticol.preturi_cu_tva = 0
poArticol.pretftva = 50
poArticol.pretctva = 60.5
TRY
loProba = CREATEOBJECT('frm_articol_gest_factura', 3, .F., .F.)
DO AfLog WITH 'DIAG PROBA: CREATEOBJECT reusit izolat, Class=' + loProba.Class
loProba.Release()
CATCH TO loExcProba
DO AfLog WITH 'DIAG PROBA: CATCH ErrorNo=' + TRANSFORM(loExcProba.ErrorNo) + ' Message=' + loExcProba.Message + ' Proc=' + loExcProba.Procedure + ' Line=' + TRANSFORM(loExcProba.LineNo) + ' [' + loExcProba.LineContents + ']'
ENDTRY
DO HarnessDone WITH 'done-error'
ENDTRY
QUIT
*==================================================================================
PROCEDURE AfErr
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO AfLog WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
PROCEDURE AfLog
LPARAMETERS tcMsg
SET SAFETY OFF
LOCAL lcL
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcUILog)
ENDPROC
PROCEDURE UILog
LPARAMETERS tcMsg
DO AfLog WITH tcMsg
ENDPROC
*-- FindCtl: referinta directa la un control prin Controls(i), potrivit dupa .Name - tehnica
*-- validata in test_modal_unlock_smoketest2.prg / Nivel 2 (accesul cu prefix direct pe o referinta
*-- obtinuta din _SCREEN.Forms da eroare 1925; Controls(i) e calea sigura).
PROCEDURE FindCtl
LPARAMETERS toParent, tcName
LOCAL lnI, loGasit
loGasit = .NULL.
FOR lnI = 1 TO toParent.ControlCount
IF UPPER(toParent.Controls(lnI).Name) == UPPER(tcName)
loGasit = toParent.Controls(lnI)
ENDIF
ENDFOR
RETURN loGasit
ENDPROC
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexport AS Custom
PROCEDURE citesteSetareRegistru
LPARAMETERS tcCheie
RETURN ''
ENDPROC
ENDDEFINE
*-- dummyexecutor: mock la GRANITA (goExecutor.oExecute e singurul punct de contact al lui
*-- do_alege_stoc cu Oracle, ofacturare.vc2:13254). Ramifica pe continutul SQL-ului: cererile
*-- 'cursor_gestiuni_articol*' (normal/_retur/_stoc0 - toate three trec prin acelasi mock, textul
*-- nu se distinge in teste, doar sursa comuna crsMockStoc) primesc structura+datele din
*-- crsMockStoc; orice alta interogare (ex. select codmatf ... from nom_articole, apelata dupa
*-- gnButon=1) primeste comportamentul implicit de dinainte (cursor gol cu un singur camp).
DEFINE CLASS dummyexecutor AS Custom
cEroare = ''
PROCEDURE oExecute
LPARAMETERS tcSql, tcCursor
IF USED(tcCursor)
USE IN (tcCursor)
ENDIF
IF 'CURSOR_GESTIUNI_ARTICOL' $ UPPER(tcSql)
SELECT * FROM crsMockStoc INTO CURSOR (tcCursor) READWRITE
ELSE
CREATE CURSOR (tcCursor) (codmatf C(50))
ENDIF
RETURN 1
ENDPROC
PROCEDURE oPrelucrareEroare
RETURN cEroare
ENDPROC
PROCEDURE oReset
ENDPROC
ENDDEFINE
DEFINE CLASS driverdeblocaregest AS Custom
PROCEDURE Executa
*-- rulat la fiecare tick al _SCREEN.tmrDrvN3. Cauta FRM_ARTICOL_GEST_FACTURA (nu
*-- FRM_ARTICOL_FACTURA - dialogul cu gridul de gestiuni, deschis de do_alege_stoc),
*-- aplica interactiunea selectata de gcCazAct, inchide dialogul (do_termin sau
*-- But_renunt1.Click(), dupa caz).
LOCAL lnI, loForm, llGasit
gnDriverTick = gnDriverTick + 1
llGasit = .F.
FOR lnI = 1 TO _SCREEN.FormCount
IF UPPER(_SCREEN.Forms(lnI).Class) == 'FRM_ARTICOL_GEST_FACTURA'
loForm = _SCREEN.Forms(lnI)
llGasit = .T.
ENDIF
ENDFOR
IF glDlgTratat OR !llGasit
RETURN
ENDIF
DO AfLog WITH 'driverGest tick ' + TRANSFORM(gnDriverTick) + ' POTRIVIT (caz=' + gcCazAct + '), intru in interactiune'
LOCAL loCantitateCtn, loCantitate, loBifa, loRenunt, loGrid
TRY
DO CASE
CASE gcCazAct == 'ADD_G1_Q3'
*-- caz a: dialogul cu gestiuni s-a deschis pe mai multe gestiuni (nu auto-select);
*-- verific ck_pret_cu_tva (mostenit din frm_articol_factura, S2a) - existenta si layout.
loBifa = FindCtl(loForm, 'ck_pret_cu_tva')
IF VARTYPE(loBifa) = 'O'
IF loForm.Height = 546 AND loBifa.Top = 510
DO AfLog WITH 'driverGest ADD_G1_Q3: ck_pret_cu_tva EXISTA, Top=' + TRANSFORM(loBifa.Top) + ' pe forma Height=' + TRANSFORM(loForm.Height) + ' -> PASS layout'
ELSE
DO AfLog WITH 'driverGest ADD_G1_Q3: ck_pret_cu_tva EXISTA dar layout neasteptat: Top=' + TRANSFORM(loBifa.Top) + ' Height forma=' + TRANSFORM(loForm.Height)
ENDIF
ELSE
DO AfLog WITH 'driverGest ADD_G1_Q3: ck_pret_cu_tva LIPSESTE din instanta'
ENDIF
DO AfLog WITH 'driverGest ADD_G1_Q3: Reccount(crsgestarticol)=' + TRANSFORM(RECCOUNT('crsgestarticol'))
*-- pozitia implicita (Go Top, tnIdTempExclus=0 la adaugare) e deja pe G1 (datain cel mai vechi)
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 3
loCantitate.InteractiveChange()
DO AfLog WITH 'driverGest ADD_G1_Q3: cantitate=3 pe G1 (pozitia implicita), apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'ADD_G2_Q4'
SELECT crsgestarticol
LOCATE FOR id_gestiune = 102
loGrid = FindCtl(loForm, 'grd_gestiuni')
loGrid.AfterRowColChange(1)
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 4
loCantitate.InteractiveChange()
DO AfLog WITH 'driverGest ADD_G2_Q4: navigheaza pe G2, cantitate=4, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'MOD_L1_PRESELECT_CHECK'
*-- cazuri b+c: verifica preselectia pe randul liniei si excluderea id_temp, fara sa comita nimic
SELECT crsgestarticol
IF id_gestiune = 101 AND ABS(cantitate - 10) < 0.001
DO UILog WITH 'PASS P3 (caz b) preselectie pe randul liniei modificate, cu propria cantitate reintoarsa in stoc: id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate)
ELSE
DO UILog WITH 'FAIL P3 (caz b): id_gestiune=' + TRANSFORM(id_gestiune) + ' cantitate=' + TRANSFORM(cantitate) + ' (asteptat 101 / 10)'
ENDIF
LOCATE FOR id_gestiune = 102
IF FOUND() AND ABS(cantitate - 11) < 0.001
DO UILog WITH 'PASS P3 (caz c) randul G2 (linia2, neexclusa) scade normal cu cantitatea ei: cantitate=' + TRANSFORM(cantitate) + ' (15-4)'
ELSE
DO UILog WITH 'FAIL P3 (caz c): randul G2 found=' + TRANSFORM(FOUND()) + IIF(FOUND(), ' cantitate=' + TRANSFORM(cantitate), '') + ' (asteptat 11 = 15-4)'
ENDIF
loRenunt = FindCtl(loForm, 'But_renunt1')
DO AfLog WITH 'driverGest MOD_L1_PRESELECT_CHECK: apas Renunta (nimic de comis)'
loRenunt.Click()
CASE gcCazAct == 'MOD_L1_REJECT_OVER_LOT'
SELECT crsgestarticol
LOCATE FOR id_gestiune = 101
loGrid = FindCtl(loForm, 'grd_gestiuni')
loGrid.AfterRowColChange(1)
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 11
loCantitate.InteractiveChange()
DO AfLog WITH 'driverGest MOD_L1_REJECT_OVER_LOT: cantitate=11 pe G1 (stoc 10), apas do_termin() - astept respingere'
loForm.do_termin()
*-- daca a respins, formularul ramane deschis (testare-ui-vfp.md, "Dialoguri modale") - inchid prin Renunta
loRenunt = FindCtl(loForm, 'But_renunt1')
IF VARTYPE(loRenunt) = 'O'
DO AfLog WITH 'driverGest MOD_L1_REJECT_OVER_LOT: dialogul a ramas deschis (validare respinsa, cum era asteptat), inchid cu Renunta'
loRenunt.Click()
ENDIF
CASE gcCazAct == 'MOD_L1_ACCEPT_AT_LOT'
SELECT crsgestarticol
LOCATE FOR id_gestiune = 101
loGrid = FindCtl(loForm, 'grd_gestiuni')
loGrid.AfterRowColChange(1)
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 10
loCantitate.InteractiveChange()
DO AfLog WITH 'driverGest MOD_L1_ACCEPT_AT_LOT: cantitate=10 pe G1 (exact stocul), apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'MOD_L1_CHANGE_GESTIUNE_NAV'
SELECT crsgestarticol
LOCATE FOR id_gestiune = 103
loGrid = FindCtl(loForm, 'grd_gestiuni')
loGrid.AfterRowColChange(1)
loCantitateCtn = FindCtl(loForm, 'clb_cantitate')
loCantitate = FindCtl(loCantitateCtn, 'Text_simplu1')
loCantitate.Value = 5
loCantitate.InteractiveChange()
DO AfLog WITH 'driverGest MOD_L1_CHANGE_GESTIUNE_NAV: navigheaza (fara SPACE) pe G3, cantitate=5, apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'MOD_L1_MULTISELECT'
SELECT crsgestarticol
LOCATE FOR id_gestiune = 101
DO AfLog WITH 'driverGest MOD_L1_MULTISELECT: SPACE (do_executa) pe G1'
loForm.do_executa()
SELECT crsgestarticol
LOCATE FOR id_gestiune = 104
DO AfLog WITH 'driverGest MOD_L1_MULTISELECT: SPACE (do_executa) pe G4'
loForm.do_executa()
DO AfLog WITH 'driverGest MOD_L1_MULTISELECT: nselectate=' + TRANSFORM(loForm.nselectate) + IIF(TYPE('poArticol.cantitate') = 'N', ' poArticol.cantitate acumulata=' + TRANSFORM(poArticol.cantitate), '') + ', apas do_termin()'
loForm.do_termin()
CASE gcCazAct == 'MOD_L1_RENUNTA'
loCantitateCtn = FindCtl(loForm, 'Clb_pretftva')
IF VARTYPE(loCantitateCtn) = 'O'
loCantitate = FindCtl(loCantitateCtn, 'tx_suma_nat')
IF VARTYPE(loCantitate) = 'O'
loCantitate.Value = 9999
loCantitate.InteractiveChange()
ENDIF
ENDIF
loRenunt = FindCtl(loForm, 'But_renunt1')
DO AfLog WITH 'driverGest MOD_L1_RENUNTA: pret tastat 9999, apas But_renunt1 (Renunta)'
loRenunt.Click()
OTHERWISE
DO AfLog WITH 'driverGest: gcCazAct necunoscut [' + gcCazAct + ']'
ENDCASE
glDlgTratat = .T.
DO AfLog WITH 'driverGest: interactiune REUSITA pentru caz=' + gcCazAct
CATCH TO loExcDrv
DO AfLog WITH 'driverGest: CATCH caz=' + gcCazAct + ' ErrorNo=' + TRANSFORM(loExcDrv.ErrorNo) + ;
' Message=' + loExcDrv.Message + ' Procedure=' + loExcDrv.Procedure + ;
' LineNo=' + TRANSFORM(loExcDrv.LineNo) + ' LineContents=[' + loExcDrv.LineContents + ']'
ENDTRY
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,13 @@
# test_pret_cu_tva_nivel3_gestiuni.ps1 - wrapper peste harness-ul generic pentru ramura GESTIONABILA
# a lui do_modifica/do_adauga_articol (S2d, review). Oracle mockuit la granita (goExecutor), fluxul
# real (butoane, taste, SPACE) ramane intact. Rulare:
# powershell -ExecutionPolicy Bypass -File test_pret_cu_tva_nivel3_gestiuni.ps1
$ErrorActionPreference = 'Stop'
$Teste = $PSScriptRoot
& (Join-Path (Split-Path $Teste -Parent) 'vfp_ui_harness.ps1') `
-TestPrg (Join-Path $Teste 'test_pret_cu_tva_nivel3_gestiuni.prg') `
-Steps @('mediu', 'p1_add_g1', 'p2_add_g2', 'p3_preselectie_excludere', 'p4_respins_peste_lot', 'p5_acceptat_la_lot', 'p6_schimbare_gestiune_nav', 'p7_multiselectie', 'p8_renunta') `
-ShotsDir (Join-Path $Teste 'screenshots_nivel3') `
-SyncDir (Join-Path $Teste 'uisync_nivel3') `
-StepTimeoutSec 60 `
-ReadyTimeoutSec 90

View File

@@ -0,0 +1,14 @@
* watchdog_selftest.prg - caz banal pentru validarea watchdog_vfp.ps1: afiseaza un MESSAGEBOX
* nativ (OK/Cancel) si asteapta. Foloseste doar pentru testarea utilitarului, nu face parte
* din nicio suita de regresie.
SET SAFETY OFF
SET TALK OFF
LOCAL lcLog
lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\watchdog_selftest_log.txt'
STRTOFILE('start' + CHR(13) + CHR(10), lcLog)
= MESSAGEBOX('Mesaj de test watchdog_vfp.ps1', 1, 'Watchdog selftest')
STRTOFILE('done' + CHR(13) + CHR(10), lcLog, 1)
QUIT

View File

@@ -0,0 +1,390 @@
# watchdog_vfp.ps1 - lanseaza un test VFP headless si detecteaza dialoguri native blocante
# (mesaje Windows, "View Parameter", erori modale) care nu apar in logul scris de script si
# nu sunt prinse de ON ERROR / mock-uri - cazul clasic de proces "agatat" cu CPU~0.
#
# Ce face: sterge .fxp-ul vechi, lanseaza `vfp9.exe -A -T "<script>"`, apoi polleaza la interval
# scurt ferestrele TOP-LEVEL ale procesului (EnumWindows + GetWindowThreadProcessId). Fereastra
# principala VFP se identifica prin Process.MainWindowHandle (.NET) - NU dupa numele clasei:
# VFP inregistreaza clase diferite prefixate "vfp9..." atat pentru shell-ul principal cat si
# pentru dialogurile proprii (ex. "View Parameter"), deci clasificarea pe clasa e nesigura.
# Orice fereastra NOUA, diferita de MainWindowHandle, e tratata ca dialog blocant.
#
# Pentru fiecare dialog detectat: captura PNG (PrintWindow, fallback CopyFromScreen daca iese
# neagra) + dump text (titlu, clasa, si textul/clasa fiecarui control copil via WM_GETTEXT - se
# citesc controale native Windows chiar daca apartin unui proces strain pe alta arhitectura).
#
# INTERZIS: watchdog-ul NU are voie sa foloseasca input real de tastatura/mouse (keybd_event,
# SetForegroundWindow, SendInput, mouse_event) - masina e PARTAJATA cu utilizatorul, iar un
# ESCAPE/click injectat la nivel de sistem ajunge in orice fereastra are focus in acel moment,
# nu neaparat in dialogul tintit (verificat: a ajuns in IDE-ul VFP al utilizatorului aflat in
# lucru in paralel, intrerupandu-l). -AutoDismiss foloseste STRICT mesaje Windows tintite pe
# handle-ul dialogului: buton copil cu text Cancel/Anulare/Renunta -> BM_CLICK; altfel
# WM_COMMAND IDCANCEL -> ESCAPE ca mesaj (WM_KEYDOWN/WM_KEYUP, nu input real) -> WM_CLOSE, in
# ordine, primul care inchide fereastra castiga. Dialogurile proprii VFP owner-drawn (ex.
# "View Parameter" - butoanele sunt desenate, nu HWND-uri reale) pot sa NU raspunda la niciunul -
# atunci dismiss-ul ESUEAZA CINSTIT (ramane deschis pana la timeout), nu se cade pe input real.
# Captura (PNG+dump text) e intotdeauna de incredere, indiferent de rezultatul dismiss-ului.
# Continua polling-ul dupa fiecare dismiss reusit, ca sa prinda si eventuale dialoguri urmatoare
# (pana la -MaxDialogs). Fara -AutoDismiss: captureaza primul dialog gasit, apoi opreste
# polling-ul (nu-l atinge).
#
# Procesul e omorat mereu la iesire (finally) - nu ramane niciodata viu.
#
# Utilizare:
# powershell -ExecutionPolicy Bypass -File watchdog_vfp.ps1 -Script "D:\...\test_x.prg" -AutoDismiss
# powershell -ExecutionPolicy Bypass -File watchdog_vfp.ps1 -Script "D:\...\test_x.prg" -TimeoutSec 60 -OutDir "D:\...\out"
#
# Parametri:
# -Script cale completa la .prg de rulat (obligatoriu)
# -Vfp cale la vfp9.exe (implicit instalarea standard x86)
# -TimeoutSec timeout total de polling (implicit 90)
# -OutDir folder pentru PNG-uri + log text (implicit "<folderul scriptului>\watchdog_out")
# -AutoDismiss inchide automat dialogurile gasite (Cancel/WM_CLOSE) si continua polling-ul
# -MaxDialogs cate dialoguri succesive sa trateze cu -AutoDismiss (implicit 10)
#
# Iesire: rezumat pe stdout (numar dialoguri, textul fiecaruia, caile PNG, exit code-ul
# procesului) + acelasi continut scris in "<Script>_watchdog.log" din -OutDir.
param(
[Parameter(Mandatory=$true)][string]$Script,
[string]$Vfp = 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe',
[int]$TimeoutSec = 90,
[string]$OutDir,
[switch]$AutoDismiss,
[int]$MaxDialogs = 10
)
$ErrorActionPreference = 'Stop'
if (-not (Test-Path $Script)) { throw "Nu gasesc scriptul: $Script" }
$Script = (Resolve-Path $Script).Path
$ScriptDir = [System.IO.Path]::GetDirectoryName($Script)
$ScriptBase = [System.IO.Path]::GetFileNameWithoutExtension($Script)
if (-not $OutDir) { $OutDir = Join-Path $ScriptDir 'watchdog_out' }
if (-not (Test-Path $OutDir)) { New-Item -ItemType Directory -Path $OutDir | Out-Null }
$LogPath = Join-Path $OutDir ($ScriptBase + '_watchdog.log')
Add-Type -AssemblyName System.Drawing
Add-Type @"
using System;
using System.Text;
using System.Runtime.InteropServices;
public class WdWin32 {
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
public static extern IntPtr SendMessageText(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
[StructLayout(LayoutKind.Sequential)]
public struct RECT { public int Left, Top, Right, Bottom; }
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, uint nFlags);
}
"@
$WM_GETTEXT = 0x000D
$WM_CLOSE = 0x0010
$BM_CLICK = 0x00F5
function Get-TopWindowsForPid([int]$ProcId) {
$result = New-Object System.Collections.Generic.List[IntPtr]
$cb = {
param($hWnd, $lParam)
$owner = 0
[void][WdWin32]::GetWindowThreadProcessId($hWnd, [ref]$owner)
if ($owner -eq $ProcId -and [WdWin32]::IsWindowVisible($hWnd)) { $result.Add($hWnd) }
return $true
}
[WdWin32]::EnumWindows($cb, [IntPtr]::Zero) | Out-Null
return $result
}
function Get-ChildWindowsOf([IntPtr]$hWndParent) {
$result = New-Object System.Collections.Generic.List[IntPtr]
$cb = {
param($hWnd, $lParam)
$result.Add($hWnd)
return $true
}
[WdWin32]::EnumChildWindows($hWndParent, $cb, [IntPtr]::Zero) | Out-Null
return $result
}
# WM_GETTEXT (nu GetWindowText) - citeste text de la controale ale unui proces strain, indiferent
# de arhitectura (32/64 bit); GetWindowText poate esua tacut pe controale custom VFP.
function Get-WmText([IntPtr]$hWnd, [int]$MaxLen = 1024) {
$sb = New-Object System.Text.StringBuilder $MaxLen
[WdWin32]::SendMessageText($hWnd, $WM_GETTEXT, $MaxLen, $sb) | Out-Null
return $sb.ToString()
}
function Get-WinClassName([IntPtr]$hWnd) {
$sb = New-Object System.Text.StringBuilder 256
[WdWin32]::GetClassName($hWnd, $sb, $sb.Capacity) | Out-Null
return $sb.ToString()
}
function Test-BitmapAllBlack([System.Drawing.Bitmap]$bmp) {
$w = $bmp.Width; $h = $bmp.Height
if ($w -le 0 -or $h -le 0) { return $true }
for ($i = 0; $i -lt 9; $i++) {
$x = [Math]::Min($w - 1, [int]($w * (($i % 3) + 0.5) / 3))
$y = [Math]::Min($h - 1, [int]($h * ([Math]::Floor($i / 3) + 0.5) / 3))
$px = $bmp.GetPixel($x, $y)
if ($px.R -ne 0 -or $px.G -ne 0 -or $px.B -ne 0) { return $false }
}
return $true
}
# PrintWindow direct pe handle; fallback CopyFromScreen daca iese neagra (fereastra themed/GDI+
# care nu se randeaza corect prin PrintWindow). Foloseste doar pentru dialoguri surprinse
# on-screen - nu se muta off-screen aici (spre deosebire de vfp_ui_harness.ps1), fiindca scopul
# e sa surprindem exact dialogul care blocheaza, o singura data.
function Save-DialogScreenshot([IntPtr]$hWnd, [string]$Path) {
$rect = New-Object WdWin32+RECT
[WdWin32]::GetWindowRect($hWnd, [ref]$rect) | Out-Null
$w = $rect.Right - $rect.Left
$h = $rect.Bottom - $rect.Top
if ($w -le 0 -or $h -le 0) { return $false }
$bmp = New-Object System.Drawing.Bitmap $w, $h
$g = [System.Drawing.Graphics]::FromImage($bmp)
$hdc = $g.GetHdc()
$ok = [WdWin32]::PrintWindow($hWnd, $hdc, 2)
$g.ReleaseHdc($hdc)
$g.Dispose()
if ((-not $ok) -or (Test-BitmapAllBlack $bmp)) {
$bmp.Dispose()
$bmp = New-Object System.Drawing.Bitmap $w, $h
$g2 = [System.Drawing.Graphics]::FromImage($bmp)
try { $g2.CopyFromScreen($rect.Left, $rect.Top, 0, 0, (New-Object System.Drawing.Size $w, $h)) } catch {}
$g2.Dispose()
}
$bmp.Save($Path, [System.Drawing.Imaging.ImageFormat]::Png)
$bmp.Dispose()
return $true
}
function Get-DialogDump([IntPtr]$hWnd, [System.Collections.Generic.List[IntPtr]]$children) {
$title = Get-WmText $hWnd
$class = Get-WinClassName $hWnd
$lines = New-Object System.Collections.Generic.List[string]
$lines.Add("dialog hwnd=$hWnd class='$class' title='$title'")
foreach ($c in $children) {
$ct = (Get-WmText $c 512).Trim()
$cc = Get-WinClassName $c
if ($ct -or $cc) { $lines.Add(" child hwnd=$c class='$cc' text='$ct'") }
}
# unary comma obligatoriu: fara ea, un List[string] cu UN SINGUR element (dialog fara copii,
# ex. "View Parameter") e "descompus" de PowerShell la scalar string simplu la return, iar
# indexarea ulterioara $dumpLines[0] citeste primul CARACTER, nu primul rand - prins la testul
# pe test_page3_articole.prg (rezumatul arata titlul "d" in loc de linia intreaga)
return , $lines.ToArray()
}
function Find-DismissButton([System.Collections.Generic.List[IntPtr]]$children) {
foreach ($c in $children) {
if ((Get-WinClassName $c) -ne 'Button') { continue }
$txt = ((Get-WmText $c 256) -replace '&', '').Trim()
if ($txt -ieq 'Cancel' -or $txt -ieq 'Anulare' -or $txt -ieq 'Renunta' -or $txt -ieq 'Renunță') { return $c }
}
return [IntPtr]::Zero
}
$WM_COMMAND = 0x0111
$WM_KEYDOWN = 0x0100
$WM_KEYUP = 0x0101
$VK_ESCAPE = 0x1B
$IDCANCEL = 2
# INTERZIS: input real de tastatura/mouse (keybd_event, SetForegroundWindow, SendInput,
# mouse_event). Masina e PARTAJATA cu utilizatorul - un ESCAPE injectat la nivel de sistem
# ajunge in orice fereastra are focus in acel moment, INDIFERENT carui proces ii apartine
# (verificat: a ajuns in IDE-ul VFP al utilizatorului, aflat in lucru in paralel, intrerupandu-l
# cu o eroare + "Execution was canceled by the user"). Foloseste STRICT mesaje Windows tintite pe
# HANDLE-ul dialogului (PostMessage/SendMessage: WM_COMMAND IDCANCEL, WM_KEYDOWN/WM_KEYUP
# VK_ESCAPE, WM_CLOSE, BM_CLICK) - astea nu ating focusul/inputul global, raman izolate la
# fereastra tintita. Dialogurile native VFP proprii (ex. "View Parameter") NU au controale copil
# reale (owner-drawn) si pot sa NU raspunda la niciunul dintre mesajele de mai jos - in acel caz
# dismiss-ul ESUEAZA CINSTIT (dialogul ramane deschis, procesul e omorat la timeout de finally),
# nu se cade pe input real. Captura (PNG+dump text) ramane oricum de incredere, indiferent de
# rezultatul dismiss-ului.
function Dismiss-Dialog([IntPtr]$hWnd, [System.Collections.Generic.List[IntPtr]]$children) {
$btn = Find-DismissButton $children
if ($btn -ne [IntPtr]::Zero) {
[WdWin32]::SendMessage($btn, $BM_CLICK, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null
Start-Sleep -Milliseconds 300
if (-not [WdWin32]::IsWindow($hWnd)) { return 'click Cancel/Anulare' }
return 'NEREUSIT: BM_CLICK pe Cancel/Anulare nu a inchis dialogul'
}
[WdWin32]::SendMessage($hWnd, $WM_COMMAND, [IntPtr]$IDCANCEL, [IntPtr]::Zero) | Out-Null
Start-Sleep -Milliseconds 300
if (-not [WdWin32]::IsWindow($hWnd)) { return 'WM_COMMAND IDCANCEL' }
[WdWin32]::SendMessage($hWnd, $WM_KEYDOWN, [IntPtr]$VK_ESCAPE, [IntPtr]::Zero) | Out-Null
[WdWin32]::SendMessage($hWnd, $WM_KEYUP, [IntPtr]$VK_ESCAPE, [IntPtr]::Zero) | Out-Null
Start-Sleep -Milliseconds 300
if (-not [WdWin32]::IsWindow($hWnd)) { return 'tasta ESCAPE trimisa cu SendMessage (mesaj, nu input real)' }
[WdWin32]::SendMessage($hWnd, $WM_CLOSE, [IntPtr]::Zero, [IntPtr]::Zero) | Out-Null
Start-Sleep -Milliseconds 300
if (-not [WdWin32]::IsWindow($hWnd)) { return 'WM_CLOSE' }
$motiv = if ($children.Count -eq 0) { 'fara controale copil (owner-drawn) si niciun mesaj tintit nu a functionat' } else { 'niciun mesaj tintit (WM_COMMAND/ESCAPE mesaj/WM_CLOSE) nu a functionat' }
return "NEREUSIT: dialogul a ramas deschis ($motiv) - fara input real, per regula masinii partajate"
}
# omoara doar vfp9 lansate pe ACEST script (linia de comanda contine calea lui), nu instante straine
function Stop-VfpForScript([string]$ScriptPath) {
Get-CimInstance Win32_Process -Filter "Name='vfp9.exe'" -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.CommandLine -and $_.CommandLine.ToLower().Contains($ScriptPath.ToLower())) {
Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue
}
}
}
# --- pregatire ---
$Fxp = [System.IO.Path]::ChangeExtension($Script, 'fxp')
if (Test-Path $Fxp) { Remove-Item $Fxp -Force }
Stop-VfpForScript $Script
Start-Sleep -Milliseconds 300
$log = New-Object System.Collections.Generic.List[string]
function Log([string]$s) { Write-Host $s; $log.Add($s) }
Log "watchdog_vfp: lansez $Vfp -A -T `"$Script`""
$proc = Start-Process -FilePath $Vfp -ArgumentList @('-A', '-T', "`"$Script`"") -PassThru
$dialogs = New-Object System.Collections.Generic.List[object]
$exitCode = $null
try {
# Fereastra principala = Process.MainWindowHandle (.NET), latch-uita o singura data. NU se
# poate distinge dupa numele clasei: VFP inregistreaza clase diferite prefixate "vfp9..." atat
# pentru shell-ul principal ("vfp99400000") CAT SI pentru dialoguri native proprii precum
# "View Parameter" ("vfp994000002") - verificat empiric, clasificarea pe clasa a lasat
# "View Parameter" nedetectat. MainWindowHandle e acelasi mecanism folosit deja cu succes in
# vfp_ui_harness.ps1 (Wait-MainWindowHandle) pentru shell-ul VFP.
$mainHwnd = [IntPtr]::Zero
$mwDeadline = (Get-Date).AddSeconds(20)
while ($mainHwnd -eq [IntPtr]::Zero -and (Get-Date) -lt $mwDeadline) {
$proc.Refresh()
if ($proc.HasExited) { break }
if ($proc.MainWindowHandle -ne [IntPtr]::Zero) { $mainHwnd = $proc.MainWindowHandle }
else { Start-Sleep -Milliseconds 200 }
}
if ($mainHwnd -ne [IntPtr]::Zero) {
Log ("fereastra principala VFP: hwnd={0} class='{1}' title='{2}'" -f $mainHwnd, (Get-WinClassName $mainHwnd), (Get-WmText $mainHwnd))
} else {
Log "ATENTIE: MainWindowHandle nu a aparut in 20s - orice fereastra gasita va fi tratata ca dialog."
}
$knownWindows = New-Object System.Collections.Generic.HashSet[IntPtr]
if ($mainHwnd -ne [IntPtr]::Zero) { [void]$knownWindows.Add($mainHwnd) }
$deadline = (Get-Date).AddSeconds($TimeoutSec)
$stop = $false
while (-not $stop -and (Get-Date) -lt $deadline) {
$proc.Refresh()
if ($proc.HasExited) { Log "proces terminat singur (exit code $($proc.ExitCode))"; break }
# daca MainWindowHandle inca nu era prins, incearca din nou (fereastra principala poate
# aparea mai tarziu decat asteptarea initiala de 20s in cazuri lente)
if ($mainHwnd -eq [IntPtr]::Zero -and $proc.MainWindowHandle -ne [IntPtr]::Zero) {
$mainHwnd = $proc.MainWindowHandle
[void]$knownWindows.Add($mainHwnd)
Log ("fereastra principala VFP (intarziata): hwnd={0} class='{1}' title='{2}'" -f $mainHwnd, (Get-WinClassName $mainHwnd), (Get-WmText $mainHwnd))
}
$windows = Get-TopWindowsForPid $proc.Id
foreach ($w in $windows) {
if ($knownWindows.Contains($w)) { continue }
[void]$knownWindows.Add($w)
if ($w -eq $mainHwnd) { continue }
$children = Get-ChildWindowsOf $w
$dumpLines = Get-DialogDump $w $children
$idx = $dialogs.Count
$png = Join-Path $OutDir ("{0}_dialog{1}.png" -f $ScriptBase, $idx)
Save-DialogScreenshot $w $png | Out-Null
Log "=== DIALOG $idx detectat ==="
foreach ($l in $dumpLines) { Log $l }
Log " screenshot: $png"
$dismissMethod = $null
if ($AutoDismiss) {
$dismissMethod = Dismiss-Dialog $w $children
Log " dismiss: $dismissMethod"
}
$dialogs.Add([pscustomobject]@{
Index = $idx
Title = ($dumpLines[0])
Png = $png
Dismiss = $dismissMethod
DumpText = ($dumpLines -join "`r`n")
})
if ($dialogs.Count -ge $MaxDialogs) { Log "MaxDialogs ($MaxDialogs) atins."; $stop = $true; break }
if (-not $AutoDismiss) { Log "AutoDismiss oprit - opresc polling-ul dupa primul dialog."; $stop = $true; break }
}
if (-not $stop) { Start-Sleep -Milliseconds 700 }
}
if (-not $proc.HasExited -and (Get-Date) -ge $deadline) {
Log "TIMEOUT (${TimeoutSec}s) - procesul e inca viu, il opresc."
}
$proc.Refresh()
if ($proc.HasExited) { $exitCode = $proc.ExitCode }
}
finally {
if ($proc -and -not $proc.HasExited) {
try { $proc.Kill() } catch {}
}
Stop-VfpForScript $Script
}
# --- rezumat ---
Log ""
Log "=== REZUMAT ==="
Log ("dialoguri detectate: {0}" -f $dialogs.Count)
foreach ($d in $dialogs) {
Log (" [{0}] {1}" -f $d.Index, $d.Title)
Log (" png: {0}" -f $d.Png)
if ($d.Dismiss) { Log (" dismiss: {0}" -f $d.Dismiss) }
}
Log ("exit code proces: {0}" -f ($(if ($null -ne $exitCode) { $exitCode } else { '(omorat de watchdog, nu s-a terminat singur)' })))
Log ("log complet: {0}" -f $LogPath)
[System.IO.File]::WriteAllLines($LogPath, $log)