From 13b4f6572348dcc82cb1571064bd4242df2903af Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Sat, 8 Aug 2026 16:47:24 +0300 Subject: [PATCH] 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) Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3 --- .gitignore | 2 + clase/ofacturare_comun.vc2 | 181 +++++- clase/omodificari.vc2 | 438 ++++++++++++++- docs/flux-editare-vfp-text.md | 11 + docs/orchestrare-subagenti.md | 43 +- docs/reguli_lucru.md | 35 +- docs/scripturi-migrare-db.md | 4 + docs/testare-ui-vfp.md | 37 ++ docs/todos.txt | 3 + programe/ofacturare_editare.prg | 296 ++++++++++ .../test_incarca_articole_view.prg | 72 +++ .../editare_factura/test_incarca_cursoare.prg | 141 +++++ .../test_incarca_vanzare_din_nota.prg | 154 ++++++ .../editare_factura/test_page3_articole.prg | 305 ++++++++++ .../test_repro_izolat_gnan.prg | 40 ++ .../editare_factura/test_scan_workarea.prg | 55 ++ .../editare_factura/test_set_procedure.prg | 27 + .../editare_factura/test_writeback_buton1.prg | 523 ++++++++++++++++++ utile/Teste/watchdog_selftest.prg | 14 + utile/Teste/watchdog_vfp.ps1 | 390 +++++++++++++ 20 files changed, 2750 insertions(+), 21 deletions(-) create mode 100644 programe/ofacturare_editare.prg create mode 100644 utile/Teste/editare_factura/test_incarca_articole_view.prg create mode 100644 utile/Teste/editare_factura/test_incarca_cursoare.prg create mode 100644 utile/Teste/editare_factura/test_incarca_vanzare_din_nota.prg create mode 100644 utile/Teste/editare_factura/test_page3_articole.prg create mode 100644 utile/Teste/editare_factura/test_repro_izolat_gnan.prg create mode 100644 utile/Teste/editare_factura/test_scan_workarea.prg create mode 100644 utile/Teste/editare_factura/test_set_procedure.prg create mode 100644 utile/Teste/editare_factura/test_writeback_buton1.prg create mode 100644 utile/Teste/watchdog_selftest.prg create mode 100644 utile/Teste/watchdog_vfp.ps1 diff --git a/.gitignore b/.gitignore index 5c3545e..222de41 100644 --- a/.gitignore +++ b/.gitignore @@ -133,3 +133,5 @@ bash.exe.stackdump utile/Teste/**/screenshots*/ utile/Teste/**/uisync*/ utile/Teste/**/*_log.txt +utile/Teste/**/watchdog_out/ +utile/Teste/**/*_dialog*.png diff --git a/clase/ofacturare_comun.vc2 b/clase/ofacturare_comun.vc2 index 7f7e394..7525b80 100644 --- a/clase/ofacturare_comun.vc2 +++ b/clase/ofacturare_comun.vc2 @@ -150,7 +150,7 @@ DEFINE CLASS frm_borderou_facturi AS _frmbase OF "_frm_base.vcx" ADD OBJECT 'Cmd_executa1' AS cmd_executa WITH ; Anchor = 6, ; - Caption = "Marcheazã \ *< OBJECTDATA: ObjPath="But_listare1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="But_verifica1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="But_editare1" UniqueID="" Timestamp="" /> * + *m: do_editare_factura *m: do_listare_cc *m: do_listare_centr *m: do_listare_document @@ -1350,7 +1352,7 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx" * BorderStyle = 1 cbuton2 = but_listare1;but_listare2;But_listare3 - cbuton3 = but_modifica1;but_modifica2 + cbuton3 = but_modifica1;but_modifica2;But_editare1 cfiltru_initial = cgridsortlist = grid_facturi,grid_detalii DoCreate = .T. @@ -1410,6 +1412,17 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx" Visible = .F. *< 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 ; Anchor = 8, ; Left = 698, ; @@ -3471,7 +3484,7 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx" Anchor = 12, ; AutoSize = .T., ; BackStyle = 0, ; - Caption = "Total în valuta", ; + Caption = "Total �n valuta", ; FontSize = 10, ; Height = 18, ; Left = 311, ; @@ -3711,6 +3724,150 @@ DEFINE CLASS frm_facturi AS _frmbase OF "_frm_base.vcx" This.do_cauta() 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 *!* 26.11.2019 *!* marius.mutu @@ -4988,7 +5145,7 @@ DEFINE CLASS frm_modifica_articol_factura AS frm_termin_renunt OF "_frm_child.vc _shape2.Top = 0 _shape2.Width = 64 _shape2.ZOrderSet = 2 - Lb_titlu_alb_b121.Caption = "Modificã explicaþie articol" + Lb_titlu_alb_b121.Caption = "Modific� explica�ie articol" Lb_titlu_alb_b121.Name = "Lb_titlu_alb_b121" Lb_titlu_alb_b121.TabIndex = 5 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.Top = 23, ; _edbase1.Width = 325, ; - _lbbase1.Caption = "Explicaþie", ; + _lbbase1.Caption = "Explica�ie", ; _lbbase1.Name = "_lbbase1" *< 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.Top = 3, ; Text_simplu1.Width = 177, ; - Lb_simplu1.Caption = "Data ºi ora expedierii", ; + Lb_simplu1.Caption = "Data �i ora expedierii", ; Lb_simplu1.Name = "Lb_simplu1" *< 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, ; ZOrderSet = 9, ; img_cautare.Name = "img_cautare", ; - clb_tx_cautare.Lb_simplu1.Caption = "Maºina", ; + clb_tx_cautare.Lb_simplu1.Caption = "Ma�ina", ; clb_tx_cautare.Lb_simplu1.Name = "Lb_simplu1", ; clb_tx_cautare.Name = "clb_tx_cautare", ; clb_tx_cautare.Text_simplu1.Left = 133, ; @@ -6820,7 +6977,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx" Anchor = 12, ; AutoSize = .T., ; BackStyle = 0, ; - Caption = "Total în valuta", ; + Caption = "Total �n valuta", ; FontSize = 10, ; Height = 18, ; Left = 311, ; @@ -6852,7 +7009,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx" OPTION1.Top = 5, ; OPTION1.Value = 1, ; OPTION2.AutoSize = .T., ; - OPTION2.Caption = "În valuta", ; + OPTION2.Caption = "�n valuta", ; OPTION2.FontCharSet = 238, ; OPTION2.FontSize = 10, ; OPTION2.Left = 55, ; @@ -6860,7 +7017,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx" OPTION2.Top = 5, ; Option3.AutoSize = .T., ; Option3.BackStyle = 0, ; - Option3.Caption = "În RON", ; + Option3.Caption = "�n RON", ; Option3.FontCharSet = 238, ; Option3.FontSize = 10, ; Option3.Height = 18, ; @@ -6891,7 +7048,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx" OPTION1.Top = 5, ; OPTION1.Value = 0, ; OPTION2.AutoSize = .T., ; - OPTION2.Caption = "ªterse", ; + OPTION2.Caption = "�terse", ; OPTION2.FontCharSet = 238, ; OPTION2.FontSize = 10, ; OPTION2.ForeColor = 255,0,0, ; @@ -6900,7 +7057,7 @@ DEFINE CLASS frm_proforme AS _frmbase OF "_frm_base.vcx" OPTION2.Top = 5, ; Option3.AutoSize = .T., ; Option3.BackStyle = 0, ; - Option3.Caption = "Neºterse", ; + Option3.Caption = "Ne�terse", ; Option3.FontCharSet = 238, ; Option3.FontSize = 10, ; Option3.Height = 18, ; diff --git a/clase/omodificari.vc2 b/clase/omodificari.vc2 index a6efe21..71edc03 100644 --- a/clase/omodificari.vc2 +++ b/clase/omodificari.vc2 @@ -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.cvaloarevTVA.Header1" 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.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="Grid1" UniqueID="" Timestamp="" /> @@ -6774,18 +6801,21 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" *p: ccontrol *p: cpaymentcode *p: fel_compensare + *p: larearticolevanzari *p: lavertizatexigibilizare *p: leditare *p: lmodificare *p: lnotanoua *p: lverificare *p: lvizualizare + *p: nidvanzare *p: nid_set *p: nnnirvechi *p: noldsuma && Valoarea la intrarea in campul "Suma" *p: nprimadata *p: nsuma && Total suma inregistrari *p: ntaxcode + *p: ntipvanzare *p: obackupxml *p: oldvalue *p: oset @@ -6805,6 +6835,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" DoCreate = .T. FontCharSet = 238 Height = 508 + larearticolevanzari = .F. lavertizatexigibilizare = .F. leditare = .F. lmodificare = .F. @@ -6812,12 +6843,14 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" lverificare = .F. lvizualizare = .F. Name = "frm_modific2024" + nidvanzare = 0 nid_set = 0 nnnirvechi = 0 noldsuma = 0 nprimadata = 0 nsuma = 0 ntaxcode = 0 + ntipvanzare = 0 obackupxml = NULL oldvalue = oset = NULL @@ -8630,6 +8663,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" Height = 142, ; Left = 5, ; Name = "pgfArticole", ; + PageCount = 3, ; Top = 361, ; Width = 764, ; ZOrderSet = 0, ; @@ -8638,7 +8672,10 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" PAGE1.Name = "PAGE1", ; PAGE2.Caption = "Rulaje obiecte inventar in folosinta (8039)", ; 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" /> 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 *< 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 ; Alignment = 3, ; Anchor = 8, ; @@ -13667,6 +14072,16 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" If !Used('saft_mecanisme_plati') update_saft_mecanisme_plati() 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 PROCEDURE Resize @@ -13754,6 +14169,27 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" This.Grid1.HeaderHeight = 37 this.pgfArticole.page1.grdRulaje.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.column43.visible = m.gl406 && saft plata diff --git a/docs/flux-editare-vfp-text.md b/docs/flux-editare-vfp-text.md index bb4ce27..be20aa4 100644 --- a/docs/flux-editare-vfp-text.md +++ b/docs/flux-editare-vfp-text.md @@ -76,6 +76,17 @@ fals `roundtrip text1 != text2`. Ruleaza atunci cu lista rebazata: - Metoda noua de clasa cere `*m: nume` in `*`; fara ea, prima salvare 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:`. +- **Proprietate noua de clasa cere identic `*p: nume` in `*`** — nu doar + valoarea in `*`. 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 + `\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 alfabetica din `*`. O metoda scrisa in alta parte a fisierului face fidelity-check-ul sa pice. Sursa de adevar pentru relocare e textul regenerat din diff --git a/docs/orchestrare-subagenti.md b/docs/orchestrare-subagenti.md index 75d58fa..7d581af 100644 --- a/docs/orchestrare-subagenti.md +++ b/docs/orchestrare-subagenti.md @@ -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 — 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_.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 - 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. - **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 - 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 diff --git a/docs/reguli_lucru.md b/docs/reguli_lucru.md index 317c148..cf19541 100644 --- a/docs/reguli_lucru.md +++ b/docs/reguli_lucru.md @@ -12,13 +12,20 @@ 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 git — cele tracked sunt sarite. -2. Comentarii in cod: minime, strict functionale, descriu comportamentul CURENT (ca si cum ar fi - scris asa de la inceput) — o linie de regula, 2-3 doar pentru metode cu contract nebanal - (parametri, cursor asteptat/lasat deschis, pozitionare la iesire). Istoricul modificarilor - sta DOAR in ANTETUL fisierului (niciodata inline) — la fel in `.prg` si in PL/SQL Oracle. - INTERZIS in comentariu: nume de agent ("claude"), referinte la propuneri/decizii/etape - (`docs/propuneri_*.md`, "M2", "T3", "dec.6", "runda27", "E7", "D-H2"), istoricul modificarii - ("inlocuieste...", "nu mai depinde de...", "mutat din..."), date si autori pe cod nou. +2. Comentarii in cod SI in scripturile de migrare `.sql`: minime, strict functionale, descriu + comportamentul CURENT (ca si cum ar fi scris asa de la inceput). **Doar daca e cazul** — un + comentariu se scrie acolo unde explica o **ramura** sau un **filtru** care nu se citeste singur, + ca sa se inteleaga codul; unde codul e limpede, nu se comenteaza. O linie de regula, 2-3 doar + pentru metode cu contract nebanal (parametri, cursor asteptat/lasat deschis, pozitionare la + iesire), 4-5 in antetul unui script de migrare (ce e obiectul si ce contract are). Istoricul + 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 sau la cerere explicita. 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 tokens/subagent), nu unul singur cu context acumulat; handoff compact pe disc: `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: - 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`) -> diff --git a/docs/scripturi-migrare-db.md b/docs/scripturi-migrare-db.md index ce06133..c7ee029 100644 --- a/docs/scripturi-migrare-db.md +++ b/docs/scripturi-migrare-db.md @@ -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 is null`). - **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. +- **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 diff --git a/docs/testare-ui-vfp.md b/docs/testare-ui-vfp.md index 69e2309..fc8b1c2 100644 --- a/docs/testare-ui-vfp.md +++ b/docs/testare-ui-vfp.md @@ -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 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`). +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 ``"**, 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 + ADDITIVE`: `Createobject` gaseste prima clasa cu acel nume pe `PATH`, care poate fi + `D:\ROA\ROACONT\COMUN\clase\.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 ` + + `SET CLASSLIB TO 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 -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. diff --git a/docs/todos.txt b/docs/todos.txt index ca69b69..8e4d300 100644 --- a/docs/todos.txt +++ b/docs/todos.txt @@ -46,3 +46,6 @@ INTERESUL MEU ESTE SA SIMPLIFIC INTERFATA, SA FIE MAI EFICIENTA, SA NU FIE 2 FOR 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 \ No newline at end of file diff --git a/programe/ofacturare_editare.prg b/programe/ofacturare_editare.prg new file mode 100644 index 0000000..eb891b7 --- /dev/null +++ b/programe/ofacturare_editare.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_incarca_articole_view.prg b/utile/Teste/editare_factura/test_incarca_articole_view.prg new file mode 100644 index 0000000..2ddf09b --- /dev/null +++ b/utile/Teste/editare_factura/test_incarca_articole_view.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_incarca_cursoare.prg b/utile/Teste/editare_factura/test_incarca_cursoare.prg new file mode 100644 index 0000000..0b702ea --- /dev/null +++ b/utile/Teste/editare_factura/test_incarca_cursoare.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_incarca_vanzare_din_nota.prg b/utile/Teste/editare_factura/test_incarca_vanzare_din_nota.prg new file mode 100644 index 0000000..9b6ce2b --- /dev/null +++ b/utile/Teste/editare_factura/test_incarca_vanzare_din_nota.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_page3_articole.prg b/utile/Teste/editare_factura/test_page3_articole.prg new file mode 100644 index 0000000..2768e06 --- /dev/null +++ b/utile/Teste/editare_factura/test_page3_articole.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_repro_izolat_gnan.prg b/utile/Teste/editare_factura/test_repro_izolat_gnan.prg new file mode 100644 index 0000000..06ce872 --- /dev/null +++ b/utile/Teste/editare_factura/test_repro_izolat_gnan.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_scan_workarea.prg b/utile/Teste/editare_factura/test_scan_workarea.prg new file mode 100644 index 0000000..9f33ba3 --- /dev/null +++ b/utile/Teste/editare_factura/test_scan_workarea.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_set_procedure.prg b/utile/Teste/editare_factura/test_set_procedure.prg new file mode 100644 index 0000000..744e049 --- /dev/null +++ b/utile/Teste/editare_factura/test_set_procedure.prg @@ -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 diff --git a/utile/Teste/editare_factura/test_writeback_buton1.prg b/utile/Teste/editare_factura/test_writeback_buton1.prg new file mode 100644 index 0000000..b4dc2f1 --- /dev/null +++ b/utile/Teste/editare_factura/test_writeback_buton1.prg @@ -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 diff --git a/utile/Teste/watchdog_selftest.prg b/utile/Teste/watchdog_selftest.prg new file mode 100644 index 0000000..e984e91 --- /dev/null +++ b/utile/Teste/watchdog_selftest.prg @@ -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 diff --git a/utile/Teste/watchdog_vfp.ps1 b/utile/Teste/watchdog_vfp.ps1 new file mode 100644 index 0000000..3558fb1 --- /dev/null +++ b/utile/Teste/watchdog_vfp.ps1 @@ -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 "