From 40a112a42d5b63dead25f1e27f39bef1b93aad8d Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Tue, 11 Aug 2026 20:05:14 +0300 Subject: [PATCH] #6 editare factura emisa: S4b etapa 2 - butonul, dialogul si tipul lui id_articol Enumerarea diferentelor dintre rulaje si articole capata interfata: buton pe pagina de articole, dialog cu grid si comutator de directie, plus verificarea la salvare. Dialogul propune, nu decide - aplicarea ramane o apasare explicita. - omodificari.vc2: cmdSincronizeazaArticole pe PAGE3, dezactivat odata cu restul paginii cand documentul e blocat in eFactura; frm_sincronizare_articole, derivata din frm_termin_renunt. Gridul e legat de propunere_afisata, cursor stabil creat in Load si doar golit si reumplut - propunere_sincronizare se recreeaza la fiecare apel, deci o legare directa s-ar rupe la prima comutare de directie. - id_articol trece de la I la N(20), in toate cele 6 locuri scrise pentru acest punct. Restul codebase-ului foloseste dintotdeauna N(20): valorile reale trec de 2^31 pe 89.8% din NOM_ARTICOLE, iar un camp I le trunchia tacit, asa incat potrivirea pe id_articol cadea si iesea perechea Adaugare+Semnalare in locul unei Modificari. Nu e o schimbare de design, e revenire la conventia casei. - doua accesari This. in loc de Thisform. in Click-ul butonului de adaugare articol: proprietatile sunt ale formularului, iar scurtcircuitul OR le evalua exact cand documentul avea articole - orice click real dadea eroare. - teste: test_s4b_dialog (35/0) acopera instantierea, comutarea directiei si aplicarea la salvare; test_s4b_sincronizare (42/0) capata cazul id_articol 3598545102, care ar fi picat inainte de schimbarea de tip. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3 --- clase/omodificari.vc2 | 348 +++++++++++- programe/ofacturare_editare.prg | 8 +- .../Teste/editare_factura/test_s4b_dialog.prg | 504 ++++++++++++++++++ .../editare_factura/test_s4b_sincronizare.prg | 49 +- 4 files changed, 901 insertions(+), 8 deletions(-) create mode 100644 utile/Teste/editare_factura/test_s4b_dialog.prg diff --git a/clase/omodificari.vc2 b/clase/omodificari.vc2 index 6a2b128..456bc09 100644 --- a/clase/omodificari.vc2 +++ b/clase/omodificari.vc2 @@ -6661,6 +6661,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.grdArticoleFactura.cValoareArt.Text1" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdStergeArticol" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdAdaugaArticol" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdSincronizeazaArticole" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.lblTotalLiniiArt" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.txtTotalLiniiArt" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.lblDiscountArt" UniqueID="" Timestamp="" /> @@ -6797,6 +6798,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" * *m: actualizeazabaratotaluri *m: actualizeazaverdictactrul + *m: afiseazadialogsincronizarearticole *m: afiseaza_rulaje *m: alege_partener *m: aleg_document_pereche @@ -12304,6 +12306,22 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" ZOrderSet = 0 *< END OBJECT: BaseClass="commandbutton" /> + ADD OBJECT 'pgfArticole.PAGE3.cmdSincronizeazaArticole' AS commandbutton WITH ; + Anchor = 8, ; + AutoSize = .F., ; + Caption = "Sincronizeaza cu rulaje...", ; + FontCharSet = 238, ; + FontSize = 9, ; + ForeColor = 0,0,64, ; + Height = 22, ; + Left = 350, ; + Name = "cmdSincronizeazaArticole", ; + TabIndex = 6, ; + Top = 0, ; + Width = 250, ; + ZOrderSet = 0 + *< END OBJECT: BaseClass="commandbutton" /> + ADD OBJECT 'pgfArticole.PAGE3.cmdStergeArticol' AS commandbutton WITH ; Anchor = 8, ; AutoSize = .F., ; @@ -13170,6 +13188,20 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" Thisform.calculeaza_valori_articol() ENDPROC + PROCEDURE AfiseazaDialogSincronizareArticole + *!* dialogul compara rulajele cu articolele si aplica diferentele doar in cursoare, la Aplica + LOCAL loDlg + IF !Used('tvd') OR !Used('trul') + RETURN + ENDIF + PUBLIC gnButon + gnButon = 2 + loDlg = Createobject('frm_sincronizare_articole') + loDlg.oFormArticole = This + loDlg.Show(1) + Release loDlg + ENDPROC + PROCEDURE afiseaza_rulaje * COLAPSEAZA SAU MARESTE PAGEFRAME-UL RULAJE * Daca butonul are imaginea sus, inseamna ca pageframe-ul cu rulaje este ascuns @@ -14401,6 +14433,24 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" ENDIF SELECT (m.lnAreaTvd) ENDIF + *!* al doilea punct de declansare al sincronizarii: enumerarea diferentelor la salvare, cu + *!* continuarea salvarii daca utilizatorul renunta - de aceea llRet nu se schimba aici + IF m.llRet AND This.lAreArticoleVanzari AND !This.lArticoleReadOnly + LOCAL lnAreaInainte, lnDivergente + lnAreaInainte = Select() + lnDivergente = 0 + IF ConstruiestePropunereSincronizare('RUL_SURSA') + SELECT propunere_sincronizare + COUNT FOR Inlist(Alltrim(actiune),'Modificare','Adaugare','Semnalare') TO lnDivergente + ENDIF + IF m.lnAreaInainte > 0 + SELECT (m.lnAreaInainte) + ENDIF + *!* liniile N-A singure nu opresc salvarea: sunt "nu se poate compara", nu divergente + IF m.lnDivergente > 0 + This.AfiseazaDialogSincronizareArticole() + ENDIF + ENDIF RETURN m.llRet @@ -14676,7 +14726,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" IF Used('tvd') Use In tvd ENDIF - CREATE CURSOR tvd (id_vanzare I NULL, id_vanzare_det I NULL, id_articol I NULL, cantitate N(12,3) NULL, pret N(14,4) NULL, pret_cu_tva N(14,4) NULL, proc_tvav N(6,4) NULL, discount_unitar N(14,4) NULL, id_gestiune I NULL, cont C(20) NULL, id_valuta I NULL, id_jtva_coloana I NULL, serie C(20) NULL, explicatie C(60) NULL, taxcode I NULL, lot C(20) NULL, sters I NULL, id_vanzare_set I NULL, pret_achizitie N(14,4) NULL, denumire C(100) NULL, codmat C(30) NULL, nume_gestiune C(60) NULL, nume_val C(20) NULL, lmodificat L, valoare N(14,2), in_stoc I NULL) + CREATE CURSOR tvd (id_vanzare I NULL, id_vanzare_det I NULL, id_articol N(20) NULL, cantitate N(12,3) NULL, pret N(14,4) NULL, pret_cu_tva N(14,4) NULL, proc_tvav N(6,4) NULL, discount_unitar N(14,4) NULL, id_gestiune I NULL, cont C(20) NULL, id_valuta I NULL, id_jtva_coloana I NULL, serie C(20) NULL, explicatie C(60) NULL, taxcode I NULL, lot C(20) NULL, sters I NULL, id_vanzare_set I NULL, pret_achizitie N(14,4) NULL, denumire C(100) NULL, codmat C(30) NULL, nume_gestiune C(60) NULL, nume_val C(20) NULL, lmodificat L, valoare N(14,2), in_stoc I NULL) ENDIF *!* cursorul tvanz - placeholder gol, ca bara de totaluri (ControlSource pe tvanz.discount) sa se lege la construire @@ -14812,6 +14862,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" This.pgfArticole.PAGE3.cmdStergeArticol.Enabled = !This.lArticoleReadOnly This.pgfArticole.PAGE3.txtDiscountArt.ReadOnly = This.lArticoleReadOnly This.pgfArticole.PAGE3.lblArticoleReadOnly.Visible = This.lArticoleReadOnly + This.pgfArticole.PAGE3.cmdSincronizeazaArticole.Enabled = !This.lArticoleReadOnly This.ActualizeazaBaraTotaluri() ELSE This.pgfArticole.PageCount = 2 @@ -16492,7 +16543,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" *!* daca documentul e in valuta (tvanz.in_valuta=1), poArticol.tip_valuta/Curs/multiplicator/ *!* nume_val/id_valuta se populeaza cu valorile documentului, ca dialogul sa lucreze in valuta LOCAL loArticolAles, lnIdArticol, llInValutaDoc, lnCursDoc, lnMultDoc, lcNumeValDoc, lnIdValutaDoc - IF !Used('tvd') OR !This.lAreArticoleVanzari OR Thisform.lArticoleReadOnly + IF !Used('tvd') OR !Thisform.lAreArticoleVanzari OR Thisform.lArticoleReadOnly RETURN ENDIF loArticolAles = caut_articol() @@ -16511,7 +16562,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" poArticol = CreeazaPoArticolNouTvd(m.lnIdArticol, loArticolAles.codmat, loArticolAles.denumire, loArticolAles.um, loArticolAles.cont, ; m.llInValutaDoc, m.lnCursDoc, m.lnMultDoc, m.lcNumeValDoc, m.lnIdValutaDoc) poDate = Createobject('Empty') - AddProperty(poDate, 'tip', This.nTipVanzare) + AddProperty(poDate, 'tip', Thisform.nTipVanzare) AddProperty(poDate, 'in_valuta', 0) AddProperty(poDate, 'dataact', Iif(Used('tact') And Reccount('tact') > 0, Nvl(tact.dataact, Date()), Date())) gnScadereStoc = 0 @@ -16529,6 +16580,14 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" Release loDlg ENDPROC + PROCEDURE pgfArticole.PAGE3.cmdSincronizeazaArticole.Click + *!* primul punct de declansare: comparatia ceruta explicit de utilizator, de pe pagina de articole + IF !Used('tvd') OR !Thisform.lAreArticoleVanzari OR Thisform.lArticoleReadOnly + RETURN + ENDIF + Thisform.AfiseazaDialogSincronizareArticole() + ENDPROC + PROCEDURE pgfArticole.PAGE3.cmdStergeArticol.Click *!* comuta flagul sters pe linia curenta din tvd - stergerea e logica, ramane vizibila (grizata) pana la salvare IF !Used('tvd') OR Reccount('tvd') = 0 OR Thisform.lArticoleReadOnly @@ -16594,3 +16653,286 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx" ENDPROC ENDDEFINE + +DEFINE CLASS frm_sincronizare_articole AS frm_termin_renunt OF "_frm_child.vcx" + *< CLASSDATA: Baseclass="form" Timestamp="" Scale="Pixels" Uniqueid="" /> + + *-- OBJECTDATA items order determines ZOrder / El orden de los items OBJECTDATA determina el ZOrder + *< OBJECTDATA: ObjPath="lblDirectie" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="optDirectie" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="lblAvertisment" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cArticolProp.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cCantVecheProp.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cCantNouaProp.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cPretVechiProp.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cPretNouProp.Header1" UniqueID="" Timestamp="" /> + *< OBJECTDATA: ObjPath="grdPropunere.cActiuneProp.Header1" UniqueID="" Timestamp="" /> + + * + *m: construiesteenumerare + *p: cdirectie + *p: oformarticole + * + + * + BorderStyle = 1 + cDirectie = "RUL_SURSA" + DoCreate = .T. + Height = 480 + Name = "frm_sincronizare_articole" + oFormArticole = .F. + Width = 700 + _shape1.Name = "_shape1" + _shape1.ZOrderSet = 1 + _shape2.Height = 29 + _shape2.Left = 636 + _shape2.Name = "_shape2" + _shape2.Top = 0 + _shape2.Width = 64 + _shape2.ZOrderSet = 2 + Lb_titlu_alb_b121.Caption = "Sincronizare articole factura - rulaje" + Lb_titlu_alb_b121.Name = "Lb_titlu_alb_b121" + Lb_titlu_alb_b121.TabIndex = 5 + Lb_titlu_alb_b121.ZOrderSet = 3 + BUT_TERMIN1.Left = 668 + BUT_TERMIN1.Name = "BUT_TERMIN1" + BUT_TERMIN1.TabIndex = 3 + BUT_TERMIN1.ToolTipText = "Aplica sincronizarea propusa" + BUT_TERMIN1.Top = 1 + BUT_TERMIN1.ZOrderSet = 4 + Gridsort1.Name = "Gridsort1" + But_renunt1.Left = 639 + But_renunt1.Name = "But_renunt1" + But_renunt1.TabIndex = 4 + But_renunt1.Top = 1 + But_renunt1.ZOrderSet = 6 + * + + ADD OBJECT 'grdPropunere' AS _grdrow WITH ; + ColumnCount = 6, ; + DeleteMark = .F., ; + FontSize = 9, ; + GridLineColor = 128,128,128, ; + HeaderHeight = 22, ; + Height = 300, ; + Left = 16, ; + Name = "grdPropunere", ; + ReadOnly = .T., ; + RecordSource = "propunere_afisata", ; + RowHeight = 18, ; + Top = 108, ; + Width = 668, ; + ZOrderSet = 2, ; + Column1.ControlSource = "ALLTRIM(propunere_afisata.denumire) + ' (' + ALLTRIM(propunere_afisata.codmat) + ')'", ; + Column1.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column1.Name = "cArticolProp", ; + Column1.ReadOnly = .T., ; + Column1.Width = 220, ; + Column2.ControlSource = "propunere_afisata.cantitate_veche", ; + Column2.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column2.Format = "R", ; + Column2.InputMask = (get_mask(12,gnPCANT)), ; + Column2.Name = "cCantVecheProp", ; + Column2.ReadOnly = .T., ; + Column2.Width = 88, ; + Column3.ControlSource = "propunere_afisata.cantitate_noua", ; + Column3.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column3.Format = "R", ; + Column3.InputMask = (get_mask(12,gnPCANT)), ; + Column3.Name = "cCantNouaProp", ; + Column3.ReadOnly = .T., ; + Column3.Width = 88, ; + Column4.ControlSource = "propunere_afisata.pret_vechi", ; + Column4.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column4.Format = "R", ; + Column4.InputMask = (get_mask(12,gnPPRET)), ; + Column4.Name = "cPretVechiProp", ; + Column4.ReadOnly = .T., ; + Column4.Width = 88, ; + Column5.ControlSource = "propunere_afisata.pret_nou", ; + Column5.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column5.Format = "R", ; + Column5.InputMask = (get_mask(12,gnPPRET)), ; + Column5.Name = "cPretNouProp", ; + Column5.ReadOnly = .T., ; + Column5.Width = 88, ; + Column6.ControlSource = "propunere_afisata.actiune", ; + Column6.DynamicForeColor = "IIF(ALLTRIM(propunere_afisata.actiune)='N-A',RGB(150,150,150),RGB(0,0,0))", ; + Column6.Name = "cActiuneProp", ; + Column6.ReadOnly = .T., ; + Column6.Width = 96 + *< END OBJECT: ClassLib="_grd_base.vcx" BaseClass="grid" /> + + ADD OBJECT 'grdPropunere.cActiuneProp.Header1' AS header WITH ; + Caption = "Actiune", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdPropunere.cArticolProp.Header1' AS header WITH ; + Caption = "Articol", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdPropunere.cCantNouaProp.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Cantitate noua", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdPropunere.cCantVecheProp.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Cantitate veche", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdPropunere.cPretNouProp.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Pret nou", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'grdPropunere.cPretVechiProp.Header1' AS header WITH ; + Alignment = 2, ; + Caption = "Pret vechi", ; + FontName = "Arial", ; + FontSize = 9, ; + Name = "Header1", ; + WordWrap = .T. + *< END OBJECT: BaseClass="header" /> + + ADD OBJECT 'lblAvertisment' AS _label WITH ; + AutoSize = .T., ; + Caption = "Propunere calculata automat - verificati valorile inainte de aplicare.", ; + ForeColor = 153,0,0, ; + Left = 16, ; + Name = "lblAvertisment", ; + Top = 420, ; + ZOrderSet = 3 + *< END OBJECT: ClassLib="_baza.vcx" BaseClass="label" /> + + ADD OBJECT 'lblDirectie' AS _label WITH ; + AutoSize = .T., ; + Caption = "Directie sincronizare:", ; + Left = 16, ; + Name = "lblDirectie", ; + Top = 38, ; + ZOrderSet = 0 + *< END OBJECT: ClassLib="_baza.vcx" BaseClass="label" /> + + ADD OBJECT 'optDirectie' AS _optiongrup WITH ; + AutoSize = .F., ; + ButtonCount = 2, ; + Height = 46, ; + Left = 16, ; + Name = "optDirectie", ; + Top = 56, ; + Value = 1, ; + Width = 660, ; + ZOrderSet = 1, ; + OPTION1.AutoSize = .T., ; + OPTION1.Caption = "Rulajul e sursa (actualizeaza articolele facturii)", ; + OPTION1.FontSize = 10, ; + OPTION1.Left = 5, ; + OPTION1.Name = "OPTION1", ; + OPTION1.Top = 4, ; + OPTION1.Value = 1, ; + OPTION2.AutoSize = .T., ; + OPTION2.Caption = "Articolele sunt sursa (actualizeaza rulajul)", ; + OPTION2.FontSize = 10, ; + OPTION2.Left = 5, ; + OPTION2.Name = "OPTION2", ; + OPTION2.Top = 24 + *< END OBJECT: ClassLib="_baza.vcx" BaseClass="optiongroup" /> + + PROCEDURE ConstruiesteEnumerare + *!* propunere_sincronizare se recreeaza la fiecare apel, deci gridul nu poate sta legat de el; + *!* continutul se copiaza in propunere_afisata, cursorul stabil creat in Load + LOCAL lnAreaOrigine, lnAplicabile + lnAreaOrigine = Select() + lnAplicabile = 0 + ConstruiestePropunereSincronizare(This.cDirectie) + SELECT propunere_afisata + ZAP + IF Used('propunere_sincronizare') + SELECT propunere_sincronizare + SCAN + SCATTER MEMVAR + INSERT INTO propunere_afisata FROM MEMVAR + SELECT propunere_sincronizare + ENDSCAN + ENDIF + SELECT propunere_afisata + COUNT FOR Inlist(Alltrim(actiune),'Modificare','Adaugare') TO lnAplicabile + GO TOP + IF m.lnAreaOrigine > 0 + SELECT (m.lnAreaOrigine) + ENDIF + This.grdPropunere.Refresh() + This.But_termin1.Enabled = (m.lnAplicabile > 0) + ENDPROC + + PROCEDURE inainte_de_do_termin + *!* "Aplica" muta valorile doar in cursoarele tvd/trul - scrierea in Oracle ramane la salvare + LOCAL lnAplicate + lnAplicate = AplicaSincronizareArticole(This.cDirectie, This.oFormArticole) + IF Vartype(This.oFormArticole) == 'O' + IF m.lnAplicate > 0 AND Pemstatus(This.oFormArticole,'ActualizeazaBaraTotaluri',5) + This.oFormArticole.ActualizeazaBaraTotaluri() + ENDIF + IF Pemstatus(This.oFormArticole,'pgfArticole',5) + This.oFormArticole.pgfArticole.PAGE3.grdArticoleFactura.Refresh() + ENDIF + ENDIF + RETURN .T. + ENDPROC + + PROCEDURE Init + DoDefault() + This.ConstruiesteEnumerare() + ENDPROC + + PROCEDURE Load + *!* Load ruleaza inaintea controalelor: cursorul trebuie sa existe cand gridul se leaga de el + LOCAL lnAreaOrigine + DoDefault() + lnAreaOrigine = Select() + IF Used('propunere_afisata') + Use In propunere_afisata + ENDIF + CREATE CURSOR propunere_afisata (id_articol N(20), denumire C(100), codmat C(30), ; + cantitate_veche N(12,3), cantitate_noua N(12,3), pret_vechi N(14,4), pret_nou N(14,4), ; + actiune C(12), motiv C(80)) + IF m.lnAreaOrigine > 0 + SELECT (m.lnAreaOrigine) + ENDIF + ENDPROC + + PROCEDURE Unload + IF Used('propunere_afisata') + Use In propunere_afisata + ENDIF + DoDefault() + ENDPROC + + PROCEDURE optDirectie.Click + Thisform.cDirectie = Iif(This.Value = 2, 'ARTICOLE_SURSA', 'RUL_SURSA') + Thisform.ConstruiesteEnumerare() + ENDPROC + +ENDDEFINE diff --git a/programe/ofacturare_editare.prg b/programe/ofacturare_editare.prg index b05b62c..1f88da7 100644 --- a/programe/ofacturare_editare.prg +++ b/programe/ofacturare_editare.prg @@ -273,7 +273,7 @@ FUNCTION CreeazaCursorArticoleGol IF Used(m.lcAlias) Use In (m.lcAlias) ENDIF - CREATE CURSOR (m.lcAlias) (id_vanzare I NULL, id_vanzare_det I NULL, id_articol I NULL, cantitate N(12,3) NULL, pret N(14,4) NULL, pret_cu_tva N(14,4) NULL, proc_tvav N(6,4) NULL, ; + CREATE CURSOR (m.lcAlias) (id_vanzare I NULL, id_vanzare_det I NULL, id_articol N(20) NULL, cantitate N(12,3) NULL, pret N(14,4) NULL, pret_cu_tva N(14,4) NULL, proc_tvav N(6,4) NULL, ; discount_unitar N(14,4) NULL, id_gestiune I NULL, cont C(20) NULL, id_valuta I NULL, id_jtva_coloana I NULL, serie C(20) NULL, explicatie C(60) NULL, ; taxcode I NULL, lot C(20) NULL, sters I NULL, id_vanzare_set I NULL, pret_achizitie N(14,4) NULL, denumire C(100) NULL, codmat C(30) NULL, nume_gestiune C(60) NULL, nume_val C(20) NULL, ; lmodificat L, valoare N(14,2), in_stoc I NULL) @@ -584,7 +584,7 @@ FUNCTION ConstruiestePropunereSincronizare IF Used('propunere_sincronizare') Use In propunere_sincronizare ENDIF - CREATE CURSOR propunere_sincronizare (id_articol I, denumire C(100), codmat C(30), ; + CREATE CURSOR propunere_sincronizare (id_articol N(20), denumire C(100), codmat C(30), ; cantitate_veche N(12,3), cantitate_noua N(12,3), pret_vechi N(14,4), pret_nou N(14,4), ; actiune C(12), motiv C(80)) @@ -601,7 +601,7 @@ FUNCTION ConstruiestePropunereSincronizare IF Used('agg_rul') Use In agg_rul ENDIF - CREATE CURSOR agg_rul (id_articol I, denumire C(100), codmat C(30), cant N(12,3), val N(16,4), nrand I) + CREATE CURSOR agg_rul (id_articol N(20), denumire C(100), codmat C(30), cant N(12,3), val N(16,4), nrand I) SELECT trul SCAN FOR Nvl(sters,0) <> 1 @@ -624,7 +624,7 @@ FUNCTION ConstruiestePropunereSincronizare IF Used('agg_tvd') Use In agg_tvd ENDIF - CREATE CURSOR agg_tvd (id_articol I, denumire C(100), codmat C(30), cant N(12,3), val N(16,4), nrand I, in_stoc I) + CREATE CURSOR agg_tvd (id_articol N(20), denumire C(100), codmat C(30), cant N(12,3), val N(16,4), nrand I, in_stoc I) SELECT tvd SCAN FOR Nvl(sters,0) <> 1 diff --git a/utile/Teste/editare_factura/test_s4b_dialog.prg b/utile/Teste/editare_factura/test_s4b_dialog.prg new file mode 100644 index 0000000..0ac8e1c --- /dev/null +++ b/utile/Teste/editare_factura/test_s4b_dialog.prg @@ -0,0 +1,504 @@ +* test_s4b_dialog.prg +* Smoke test pentru clasa noua frm_sincronizare_articole (COMUN\clase\omodificari.vc2, la finalul +* fisierului) - dialogul S4b etapa 2 (buton cmdSincronizeazaArticole + AfiseazaDialogSincronizareArticole +* in frm_modific2024). Complet headless, FARA Oracle: tvd/trul se construiesc in test (helperele +* AdaugaTvd/AdaugaTrul, copiate din test_s4b_sincronizare.prg, acelasi folder), dummyform (copiat din +* acelasi fisier) se refoloseste ca oFormArticole. Logica pura din spatele dialogului +* (ConstruiestePropunereSincronizare/AplicaSincronizareArticole, ofacturare_editare.prg) e deja +* acoperita de test_s4b_sincronizare.prg (35/0) - aici se verifica DOAR ca dialogul (Load/Init/ +* ConstruiesteEnumerare/inainte_de_do_termin/Unload) leaga corect gridul de propunere_afisata, +* comuta directia fara sa dubleze/ramana cu randuri vechi, si activeaza/dezactiveaza But_termin1. +* +* Clasa e OF "_frm_child.vcx" (WindowType=1, modala), dar modalitatea se declanseaza la .Show(), nu +* la Createobject() - niciun test de aici cheama .Show(), deci nimic nu ramane blocat headless. +* Mediul de clase/proceduri e cel din Programe\roafacturare.prg (SET PATH + SET CLASSLIB, replicat +* aici ca sa rezolve lantul de mostenire _frm_child.vcx -> _frm_base.vcx -> _baza.vcx si controalele +* _grdrow/_optiongrup/_label), FARA test_init_env_auto (acela deschide o conexiune Oracle reala, +* nefolositoare aici si interzisa de scopul sarcinii). +* +* Nu scrie in Oracle. Nu da COMMIT. QUIT la final. + +SET SAFETY OFF +SET TALK OFF + +LOCAL lcLog +lcLog = 'D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\test_s4b_dialog_log.txt' +STRTOFILE('start ' + TTOC(DATETIME()) + CHR(13) + CHR(10), lcLog) + +PUBLIC gcErrLog, gnPass, gnFail +gcErrLog = lcLog +gnPass = 0 +gnFail = 0 +ON ERROR DO test_error_handler WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() + +IF Type('gnPC') <> 'N' + PUBLIC gnPC + gnPC = 2 +ENDIF +*!* defensiv - Column.InputMask din grdPropunere foloseste get_mask(12,gnPCANT)/get_mask(12,gnPPRET); +*!* sub -A -T coloanele de grid nu se materializeaza (nu se evalueaza InputMask), dar le definim oricum +IF Type('gnPCANT') <> 'N' + PUBLIC gnPCANT + gnPCANT = 3 +ENDIF +IF Type('gnPPRET') <> 'N' + PUBLIC gnPPRET + gnPPRET = 4 +ENDIF + +CLOSE DATABASES +Set Century On +Set Deleted On +Set Date To Dmy +Set Exact On +Set NullDisplay To '' +Set Decimals To 6 + +LOCAL gcAppPath, lcPath +gcAppPath = 'D:\ROA\ROAFACTURARE\' +SET DEFAULT TO (gcAppPath) + +lcPath = gcAppPath + 'Date;' + ; + gcAppPath + 'Include;' + ; + gcAppPath + 'FERESTRE;' + ; + gcAppPath + 'GRAFICE;' + ; + gcAppPath + 'CLASE;' + ; + gcAppPath + 'MENIURI;' + ; + gcAppPath + 'PROGRAME;' + ; + gcAppPath + 'RAPOARTE;' + ; + gcAppPath + 'COMUN\CLASE;' + ; + gcAppPath + 'COMUN\FERESTRE;' + ; + gcAppPath + 'COMUN\PROGRAME;' + ; + gcAppPath + 'COMUN\GRAFICE;' + ; + gcAppPath + 'COMUN\RAPOARTE;' + ; + gcAppPath + 'COMUN\UTILE\CALENDAR;' + ; + gcAppPath + 'COMUN\UTILE\CTL32;' + ; + gcAppPath + 'COMUN\UTILE\HPDF;' + ; + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ; + gcAppPath + 'COMUN\UTILE\WEB;' + ; + gcAppPath + 'COMUN\UTILE\EMAIL;' + ; + gcAppPath + 'COMUN\UTILE\NFJSON;' + ; + gcAppPath + 'COMUN\UTILE\NFXML;' + ; + 'D:\ROA\COMUNROA\' +SET PATH TO &lcPath ADDITIVE + +*!* CLASE - lantul replicat din Programe\roafacturare.prg, fara init_program/Oracle +SET CLASSLIB TO (gcAppPath + 'comun\clase\appwiz.vcx') ADDITIVE +SET CLASSLIB TO registry ADDITIVE +SET CLASSLIB TO cauta_alfa_forms ADDITIVE +SET CLASSLIB TO ofacturare.vcx ADDITIVE +SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE +SET CLASSLIB TO omodificari.vcx ADDITIVE +SET CLASSLIB TO accessibility.vcx ADDITIVE +SET CLASSLIB TO ocriterii.vcx ADDITIVE +SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE +SET CLASSLIB TO ctl32_common.vcx ADDITIVE +SET CLASSLIB TO ctl32_structs.vcx ADDITIVE +SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE +SET CLASSLIB TO DECABAZA ADDITIVE +SET CLASSLIB TO onomenclatoare ADDITIVE +SET CLASSLIB TO onomenclatoare2 ADDITIVE +SET CLASSLIB TO ofacturare ADDITIVE +SET CLASSLIB TO ofacturare_rapoarte ADDITIVE +SET CLASSLIB TO orapoarte ADDITIVE +SET CLASSLIB TO ferestre_oracle ADDITIVE +SET CLASSLIB TO Messagebox ADDITIVE +SET CLASSLIB TO otoolbar ADDITIVE +SET CLASSLIB TO onom_curs ADDITIVE +SET CLASSLIB TO comun ADDITIVE +SET CLASSLIB TO ferestre_cere_date ADDITIVE +SET CLASSLIB TO baza ADDITIVE +SET CLASSLIB TO caut ADDITIVE +SET CLASSLIB TO ointroduceri ADDITIVE +SET CLASSLIB TO serii_numere ADDITIVE +SET CLASSLIB TO caut_ora ADDITIVE +SET CLASSLIB TO wwdialogs.vcx ADDITIVE +SET CLASSLIB TO _calendar.vcx ADDITIVE +SET CLASSLIB TO locale ADDITIVE +SET CLASSLIB TO overificari ADDITIVE +SET CLASSLIB TO ocomenzi ADDITIVE + +*!* PROCEDURI - doar cele chiar necesare logicii testate (fara Oracle) +SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\proceduri_comune.prg ADDITIVE +SET PROCEDURE TO D:\ROA\ROAFACTURARE\COMUN\programe\ofacturare_editare.prg ADDITIVE + +*!* MEDIU - fara goApp, _frmbase.Init trimite .F. in SetFont si accessibility deschide GETFONT(), +*!* dialog modal care atarna rularea headless; gcAcces e cerut de actualizeaza_drepturi +PUBLIC goApp, gcAcces +gcAcces = [1;2;3;4;5;6;7;8;] +goApp = Createobject("wzApplication") + + +*============================================================================================ +* T1 - instantiere pe dataset cu Modificare+Adaugare+Semnalare+N-A: fara eroare, propunere_afisata +* identica (camp cu camp) cu propunere_sincronizare, But_termin1.Enabled = .T. +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(800, 2, 10, 1, 1, 'ARTICOL 800', 'COD800', 20) +AdaugaTrul(800, 4, 0, 16, 0, 1, '371', 1.19) +AdaugaTrul(900, 1, 0, 50, 0, 2, '371', 1.19) +AdaugaTvd(1000, 1, 1, 1, 1, 'ARTICOL 1000', 'COD1000', 1) +AdaugaTvd(1100, 1, 1, 1, 0, 'ARTICOL 1100', 'COD1100', 1) + +LOCAL loForm1 +loForm1 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T1 instantiere fara eroare (Modificare+Adaugare+Semnalare+N-A)', ; + Vartype(loForm1) == 'O' AND Upper(loForm1.Class) == 'FRM_SINCRONIZARE_ARTICOLE', TRANSFORM(Vartype(loForm1)) + +IF Vartype(loForm1) == 'O' + DO asserteaza WITH 'T1 propunere_afisata exista si e deschisa', Used('propunere_afisata'), '' + DO asserteaza WITH 'T1 propunere_sincronizare exista (sursa copiata de ConstruiesteEnumerare)', Used('propunere_sincronizare'), '' + + IF Used('propunere_afisata') AND Used('propunere_sincronizare') + DO asserteaza WITH 'T1 propunere_afisata are 4 randuri (800 Modificare, 900 Adaugare, 1000 Semnalare, 1100 N-A)', ; + Reccount('propunere_afisata') == 4, TRANSFORM(Reccount('propunere_afisata')) + DO asserteaza WITH 'T1 acelasi numar de randuri in propunere_sincronizare si propunere_afisata', ; + Reccount('propunere_sincronizare') == Reccount('propunere_afisata'), ; + TRANSFORM(Reccount('propunere_sincronizare')) + '/' + TRANSFORM(Reccount('propunere_afisata')) + + LOCAL lnMismatch1 + lnMismatch1 = VerificaCursoareIdentice('propunere_sincronizare', 'propunere_afisata') + DO asserteaza WITH 'T1 propunere_afisata identica camp-cu-camp cu propunere_sincronizare', lnMismatch1 == 0, TRANSFORM(lnMismatch1) + ENDIF + + DO asserteaza WITH 'T1 But_termin1.Enabled = .T. (exista Modificare 800 si Adaugare 900)', loForm1.But_termin1.Enabled, TRANSFORM(loForm1.But_termin1.Enabled) + + loForm1.Release() +ENDIF + + +*============================================================================================ +* T2 - But_termin1.Enabled = .F. cand propunerea e goala (document identic) +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(100, 5, 10, 1, 1, 'ARTICOL 100', 'COD100', 50) +AdaugaTrul(100, 5, 0, 10, 0, 1, '371', 1) + +LOCAL loForm2 +loForm2 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T2 instantiere pe document identic: fara eroare', Vartype(loForm2) == 'O', TRANSFORM(Vartype(loForm2)) +IF Vartype(loForm2) == 'O' + DO asserteaza WITH 'T2 propunere_afisata goala (nimic de sincronizat)', Reccount('propunere_afisata') == 0, TRANSFORM(Reccount('propunere_afisata')) + DO asserteaza WITH 'T2 But_termin1.Enabled = .F. (propunere goala)', !loForm2.But_termin1.Enabled, TRANSFORM(loForm2.But_termin1.Enabled) + loForm2.Release() +ENDIF + + +*============================================================================================ +* T2b - But_termin1.Enabled = .F. cand propunerea contine DOAR N-A/Semnalare (niciun aplicabil) +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(500, 1, 99, 1, 0, 'ARTICOL 500 SERVICIU', 'COD500', 99) +AdaugaTvd(1000, 1, 1, 1, 1, 'ARTICOL 1000', 'COD1000', 1) + +LOCAL loForm2b +loForm2b = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T2b instantiere pe document doar N-A/Semnalare: fara eroare', Vartype(loForm2b) == 'O', TRANSFORM(Vartype(loForm2b)) +IF Vartype(loForm2b) == 'O' + DO asserteaza WITH 'T2b propunere_afisata are 2 randuri (500 N-A, 1000 Semnalare), niciunul aplicabil', ; + Reccount('propunere_afisata') == 2, TRANSFORM(Reccount('propunere_afisata')) + DO asserteaza WITH 'T2b But_termin1.Enabled = .F. (doar N-A/Semnalare)', !loForm2b.But_termin1.Enabled, TRANSFORM(loForm2b.But_termin1.Enabled) + loForm2b.Release() +ENDIF + + +*============================================================================================ +* T3 - comutarea directiei: optDirectie.Click() reumple propunere_afisata (nu dubleaza, nu ramane veche) +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(800, 2, 10, 1, 1, 'ARTICOL 800', 'COD800', 20) +AdaugaTrul(800, 4, 0, 16, 0, 1, '371', 1.19) +AdaugaTrul(900, 1, 0, 50, 0, 2, '371', 1.19) +AdaugaTvd(1000, 1, 1, 1, 1, 'ARTICOL 1000', 'COD1000', 1) + +LOCAL loForm3 +loForm3 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T3 instantiere: fara eroare', Vartype(loForm3) == 'O', TRANSFORM(Vartype(loForm3)) + +IF Vartype(loForm3) == 'O' + DO asserteaza WITH 'T3 initial (RUL_SURSA implicit): 3 randuri (800 Modificare, 900 Adaugare, 1000 Semnalare)', ; + Reccount('propunere_afisata') == 3, TRANSFORM(Reccount('propunere_afisata')) + + SELECT propunere_afisata + LOCATE FOR id_articol == 900 + DO asserteaza WITH 'T3 initial: 900 e Adaugare (doar in trul)', Found() AND Alltrim(actiune) == 'Adaugare', Iif(Found(), Alltrim(actiune), 'lipsa') + LOCATE FOR id_articol == 1000 + DO asserteaza WITH 'T3 initial: 1000 e Semnalare (doar in tvd, stocat)', Found() AND Alltrim(actiune) == 'Semnalare', Iif(Found(), Alltrim(actiune), 'lipsa') + + loForm3.optDirectie.Value = 2 + loForm3.optDirectie.Click() + + DO asserteaza WITH 'T3 dupa comutare: cDirectie == ARTICOLE_SURSA', Alltrim(loForm3.cDirectie) == 'ARTICOLE_SURSA', loForm3.cDirectie + DO asserteaza WITH 'T3 dupa comutare: propunere_afisata tot 3 randuri (reumpluta, nu dublata)', ; + Reccount('propunere_afisata') == 3, TRANSFORM(Reccount('propunere_afisata')) + + SELECT propunere_afisata + LOCATE FOR id_articol == 900 + DO asserteaza WITH 'T3 dupa comutare: 900 e acum Semnalare (rolul s-a inversat, nu a ramas Adaugare)', ; + Found() AND Alltrim(actiune) == 'Semnalare', Iif(Found(), Alltrim(actiune), 'lipsa') + LOCATE FOR id_articol == 1000 + DO asserteaza WITH 'T3 dupa comutare: 1000 e acum Adaugare (rolul s-a inversat)', ; + Found() AND Alltrim(actiune) == 'Adaugare', Iif(Found(), Alltrim(actiune), 'lipsa') + LOCATE FOR id_articol == 800 + DO asserteaza WITH 'T3 dupa comutare: 800 tot Modificare (in ambele directii)', ; + Found() AND Alltrim(actiune) == 'Modificare', Iif(Found(), Alltrim(actiune), 'lipsa') + + loForm3.Release() +ENDIF + + +*============================================================================================ +* T4 - inainte_de_do_termin() aplica efectiv in tvd (RUL_SURSA), cu oFormArticole = dummyform +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(800, 2, 10, 1, 1, 'ARTICOL 800', 'COD800', 20) +AdaugaTrul(800, 4, 0, 16, 0, 1, '371', 1.19) +AdaugaTrul(900, 1, 0, 50, 0, 2, '371', 1.19) + +LOCAL loDummy4, loForm4, llRet4 +loDummy4 = Createobject('dummyform') +loForm4 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T4 instantiere: fara eroare', Vartype(loForm4) == 'O', TRANSFORM(Vartype(loForm4)) + +IF Vartype(loForm4) == 'O' + loForm4.oFormArticole = loDummy4 + + llRet4 = loForm4.inainte_de_do_termin() + DO asserteaza WITH 'T4 inainte_de_do_termin() intoarce .T.', llRet4 == .T., TRANSFORM(llRet4) + + SELECT tvd + LOCATE FOR id_articol == 800 + DO asserteaza WITH 'T4 aplicat in tvd: 800 modificat (cantitate=4, pret=16)', Found() AND cantitate == 4 AND pret == 16, ; + TRANSFORM(cantitate) + '/' + TRANSFORM(pret) + LOCATE FOR id_articol == 900 + DO asserteaza WITH 'T4 aplicat in tvd: 900 adaugat (linie noua, cantitate=1, pret=50)', Found() AND cantitate == 1 AND pret == 50, ; + TRANSFORM(cantitate) + '/' + TRANSFORM(pret) + + DO asserteaza WITH 'T4 dummyform.AdaugaLinieTvdDinArticol apelat o singura data (Adaugarea 900)', loDummy4.nAdaugaCalls == 1, TRANSFORM(loDummy4.nAdaugaCalls) + DO asserteaza WITH 'T4 dummyform.ActualizeazaBaraTotaluri apelat (Pemstatus + lnAplicate>0)', loDummy4.nBaraCalls >= 1, TRANSFORM(loDummy4.nBaraCalls) + + loForm4.Release() +ENDIF + + +*============================================================================================ +* T5 - oFormArticole ramas .F. (implicit): nicio eroare, se aplica tot REPLACE-ul de baza pe tvd +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(800, 2, 10, 1, 1, 'ARTICOL 800', 'COD800', 20) +AdaugaTrul(800, 4, 0, 16, 0, 1, '371', 1.19) + +LOCAL loForm5, llRet5 +loForm5 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T5 instantiere: fara eroare', Vartype(loForm5) == 'O', TRANSFORM(Vartype(loForm5)) + +IF Vartype(loForm5) == 'O' + DO asserteaza WITH 'T5 oFormArticole implicit e .F. (nesetat)', Vartype(loForm5.oFormArticole) == 'L' AND !loForm5.oFormArticole, TRANSFORM(Vartype(loForm5.oFormArticole)) + + llRet5 = loForm5.inainte_de_do_termin() + DO asserteaza WITH 'T5 inainte_de_do_termin() cu oFormArticole=.F.: fara eroare, intoarce .T.', llRet5 == .T., TRANSFORM(llRet5) + + SELECT tvd + LOCATE FOR id_articol == 800 + DO asserteaza WITH 'T5 REPLACE de baza tot s-a aplicat pe 800 (cantitate=4, pret=16), fara toForm', Found() AND cantitate == 4 AND pret == 16, ; + TRANSFORM(cantitate) + '/' + TRANSFORM(pret) + + loForm5.Release() +ENDIF + + +*============================================================================================ +* T6 - Unload/Release inchide propunere_afisata +*============================================================================================ + +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(100, 5, 10, 1, 1, 'ARTICOL 100', 'COD100', 50) +AdaugaTrul(100, 5, 0, 10, 0, 1, '371', 1) + +LOCAL loForm6 +loForm6 = Createobject('frm_sincronizare_articole') +DO asserteaza WITH 'T6 instantiere: fara eroare', Vartype(loForm6) == 'O', TRANSFORM(Vartype(loForm6)) +IF Vartype(loForm6) == 'O' + DO asserteaza WITH 'T6 inainte de Release: propunere_afisata deschisa', Used('propunere_afisata'), '' + loForm6.Release() + DO asserteaza WITH 'T6 dupa Release: propunere_afisata inchisa (Unload a facut Use In)', !Used('propunere_afisata'), TRANSFORM(Used('propunere_afisata')) +ENDIF + + +STRTOFILE('REZULTAT: ' + TRANSFORM(gnPass) + ' PASS / ' + TRANSFORM(gnFail) + ' FAIL' + CHR(13) + CHR(10), lcLog, 1) + +IF Used('tvd') + Use In tvd +ENDIF +IF Used('trul') + Use In trul +ENDIF +IF Used('propunere_sincronizare') + Use In propunere_sincronizare +ENDIF +IF Used('propunere_afisata') + Use In propunere_afisata +ENDIF + +QUIT + + +*!* --- helpere de constructie a cursoarelor de test (copiate din test_s4b_sincronizare.prg) --- + +PROCEDURE CreeazaTvdTest + CreeazaCursorArticoleGol('tvd') +ENDPROC + + +PROCEDURE CreeazaTrulTest + IF Used('trul') + Use In trul + ENDIF + CREATE CURSOR trul (id_articol I, denumire C(100), codmat C(30), um C(10), cant N(12,3), cante N(12,3), ; + pretvtva N(14,4), id_tip_rulaj I, sters I, id_gestiune I, cont C(20), proc_tvav N(6,4)) +ENDPROC + + +*!* adauga o linie in tvd, cu valoarea data explicit (nu recalculata aici - fixture, nu logica de productie) +PROCEDURE AdaugaTvd + LPARAMETERS tnIdArticol, tnCantitate, tnPret, tnPretCuTva, tnInStoc, tcDenumire, tcCodmat, tnValoare + + SELECT tvd + APPEND BLANK + REPLACE id_vanzare WITH 1, id_vanzare_det WITH Recno('tvd'), id_articol WITH m.tnIdArticol, ; + cantitate WITH m.tnCantitate, pret WITH m.tnPret, pret_cu_tva WITH m.tnPretCuTva, proc_tvav WITH 1, ; + discount_unitar WITH 0, sters WITH 0, denumire WITH m.tcDenumire, codmat WITH m.tcCodmat, ; + in_stoc WITH m.tnInStoc, valoare WITH m.tnValoare, lmodificat WITH .F. IN tvd +ENDPROC + + +*!* adauga o linie in trul: id_articol, cant, cante, pretvtva, id_tip_rulaj, id_gestiune, cont, proc_tvav +PROCEDURE AdaugaTrul + LPARAMETERS tnIdArticol, tnCant, tnCante, tnPretvtva, tnIdTipRulaj, tnIdGestiune, tcCont, tnProcTvav + + SELECT trul + APPEND BLANK + REPLACE id_articol WITH m.tnIdArticol, cant WITH m.tnCant, cante WITH m.tnCante, pretvtva WITH m.tnPretvtva, ; + id_tip_rulaj WITH m.tnIdTipRulaj, sters WITH 0, um WITH 'BUC', id_gestiune WITH m.tnIdGestiune, ; + cont WITH m.tcCont, proc_tvav WITH m.tnProcTvav, denumire WITH 'ARTICOL ' + Transform(m.tnIdArticol), ; + codmat WITH 'COD' + Transform(m.tnIdArticol) IN trul +ENDPROC + + +*!* compara doua cursoare cu structura identica (id_articol/denumire/codmat/cantitate_veche/cantitate_noua/ +*!* pret_vechi/pret_nou/actiune/motiv), matching pe id_articol; intoarce numarul de randuri nepotrivite +*!* (lipsa in tinta sau cu vreun camp diferit) +PROCEDURE VerificaCursoareIdentice + LPARAMETERS tcSursa, tcTinta + LOCAL lnMismatch, lnIdArt, lcDenSursa, lcCodSursa, lnCvSursa, lnCnSursa, lnPvSursa, lnPnSursa, lcActSursa, lcMotSursa + + lnMismatch = 0 + SELECT (tcSursa) + SCAN + lnIdArt = id_articol + lcDenSursa = Alltrim(denumire) + lcCodSursa = Alltrim(codmat) + lnCvSursa = cantitate_veche + lnCnSursa = cantitate_noua + lnPvSursa = pret_vechi + lnPnSursa = pret_nou + lcActSursa = Alltrim(actiune) + lcMotSursa = Alltrim(motiv) + + SELECT (tcTinta) + LOCATE FOR id_articol == m.lnIdArt + IF !Found() + lnMismatch = lnMismatch + 1 + ELSE + IF !(Alltrim(denumire) == m.lcDenSursa AND Alltrim(codmat) == m.lcCodSursa AND ; + cantitate_veche == m.lnCvSursa AND cantitate_noua == m.lnCnSursa AND ; + pret_vechi == m.lnPvSursa AND pret_nou == m.lnPnSursa AND ; + Alltrim(actiune) == m.lcActSursa AND Alltrim(motiv) == m.lcMotSursa) + lnMismatch = lnMismatch + 1 + ENDIF + ENDIF + SELECT (tcSursa) + ENDSCAN + + RETURN m.lnMismatch +ENDPROC + + +PROCEDURE asserteaza + LPARAMETERS tcNume, tlConditie, tcValoare + + IF m.tlConditie + gnPass = gnPass + 1 + STRTOFILE('PASS ' + m.tcNume + CHR(13) + CHR(10), gcErrLog, 1) + ELSE + gnFail = gnFail + 1 + STRTOFILE('FAIL ' + m.tcNume + ' (valoare: ' + m.tcValoare + ')' + CHR(13) + CHR(10), gcErrLog, 1) + 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 + + +*!* test-double pentru frm_modific2024 - oglindeste EXACT calculeaza_valori_articol/AdaugaLinieTvdDinArticol/ +*!* ActualizeazaBaraTotaluri din omodificari.vc2, copiat din test_s4b_sincronizare.prg (acelasi folder) +DEFINE CLASS dummyform AS Custom + nCalcCalls = 0 + nAdaugaCalls = 0 + nBaraCalls = 0 + + PROCEDURE calculeaza_valori_articol + LOCAL lnCantitate, lnPretNet, lnProcTvav, lnValoare + This.nCalcCalls = This.nCalcCalls + 1 + + SELECT tvd + lnCantitate = Nvl(cantitate,0) + lnPretNet = Nvl(pret,0) - Nvl(discount_unitar,0) + lnProcTvav = Nvl(proc_tvav,1) + lnValoare = Round(m.lnCantitate * Iif(Nvl(pret_cu_tva,0) = 0, m.lnPretNet * m.lnProcTvav, m.lnPretNet), gnPC) + REPLACE lmodificat WITH .T., valoare WITH m.lnValoare IN tvd + This.ActualizeazaBaraTotaluri() + ENDPROC + + PROCEDURE AdaugaLinieTvdDinArticol + LPARAMETERS toArticol + LOCAL lnPretRon, lnDiscountRon, lnPret, lnDiscount + This.nAdaugaCalls = This.nAdaugaCalls + 1 + + lnPretRon = Iif(toArticol.preturi_cu_tva = 0, toArticol.pretftva, toArticol.pretctva) + lnDiscountRon = Iif(toArticol.preturi_cu_tva = 0, toArticol.discount_unitar, toArticol.discount_unitar_ctva) + lnPret = m.lnPretRon * 1 / 1 + lnDiscount = m.lnDiscountRon * 1 / 1 + + SELECT tvd + APPEND BLANK + REPLACE id_vanzare WITH 1, id_vanzare_det WITH 0, id_articol WITH toArticol.id_articol, ; + cantitate WITH toArticol.cantitate, pret WITH m.lnPret, pret_cu_tva WITH toArticol.preturi_cu_tva, ; + proc_tvav WITH toArticol.proc_tvav, discount_unitar WITH m.lnDiscount, ; + id_gestiune WITH toArticol.id_gestiune, cont WITH toArticol.Cont, sters WITH 0, ; + denumire WITH toArticol.denumire, codmat WITH toArticol.codmat, ; + pret_achizitie WITH Nvl(toArticol.pret_achizitie,0), lmodificat WITH .T. IN tvd + This.calculeaza_valori_articol() + ENDPROC + + PROCEDURE ActualizeazaBaraTotaluri + This.nBaraCalls = This.nBaraCalls + 1 + ENDPROC +ENDDEFINE diff --git a/utile/Teste/editare_factura/test_s4b_sincronizare.prg b/utile/Teste/editare_factura/test_s4b_sincronizare.prg index 822bd56..8d5a119 100644 --- a/utile/Teste/editare_factura/test_s4b_sincronizare.prg +++ b/utile/Teste/editare_factura/test_s4b_sincronizare.prg @@ -195,6 +195,29 @@ IF Used('tvanz') Use In tvanz ENDIF +*!* --- A10: id_articol peste 2^31 (3598545102 = IV93900901, din documentele 1140895/1140921) --- +*!* cu id_articol I in tvd valoarea se trunchia tacit si potrivirea cadea: iesea Adaugare+Semnalare +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(3598545102, 3, 10, 1, 1, 'IV93900901', 'IV93900901', 30) +AdaugaTrul(3598545102, 5, 0, 12, 0, 1, '371', 1) + +SELECT tvd +LOCATE FOR id_articol = 3598545102 +DO asserteaza WITH 'A10 tvd pastreaza id_articol 3598545102 nealterat (campul nu mai e I)', ; + Found() AND id_articol == 3598545102, 'citit=' + TRANSFORM(id_articol) + +ConstruiestePropunereSincronizare('RUL_SURSA') +DO asserteaza WITH 'A10 o singura linie in propunere, nu perechea Adaugare+Semnalare', ; + Reccount('propunere_sincronizare') == 1, 'randuri=' + TRANSFORM(Reccount('propunere_sincronizare')) + +SELECT propunere_sincronizare +LOCATE FOR id_articol = 3598545102 +DO asserteaza WITH 'A10 potrivire reusita: Modificare, cant 3->5, pret 10->12', ; + Found() AND Alltrim(actiune) == 'Modificare' AND cantitate_veche == 3 AND cantitate_noua == 5 ; + AND pret_vechi == 10 AND pret_nou == 12, 'gasit=' + TRANSFORM(Found()) + + *!* --- A9: retur .F. cand tvd/trul nu sunt deschise, cursorul iese oricum creat --- IF Used('tvd') Use In tvd @@ -287,6 +310,30 @@ DO asserteaza WITH 'B3 pret_cu_tva=0 pastrat: pret scris = pret_nou_cu_tva / pro Found() AND pret_cu_tva == 0 AND Round(pret,4) == 20.0000, TRANSFORM(pret) +*!* --- B4: aplicarea pe id_articol peste 2^31 nimereste randul corect, nu creeaza linie noua --- +CreeazaTvdTest() +CreeazaTrulTest() +AdaugaTvd(3598545102, 3, 10, 1, 1, 'IV93900901', 'IV93900901', 30) +AdaugaTvd(700, 1, 5, 1, 1, 'ARTICOL 700', 'COD700', 5) +AdaugaTrul(3598545102, 5, 0, 12, 0, 1, '371', 1) + +LOCAL lnTvdInainteB4, lnAplicateB4 +lnTvdInainteB4 = Reccount('tvd') +lnAplicateB4 = AplicaSincronizareArticole('RUL_SURSA', loForm) +DO asserteaza WITH 'B4 id mare: o singura linie aplicata', lnAplicateB4 == 1, TRANSFORM(lnAplicateB4) +DO asserteaza WITH 'B4 id mare: tvd nu a crescut (modificare, nu adaugare)', ; + Reccount('tvd') == m.lnTvdInainteB4, TRANSFORM(Reccount('tvd')) + +SELECT tvd +LOCATE FOR id_articol = 3598545102 +DO asserteaza WITH 'B4 id mare: randul corect actualizat (cantitate=5, pret=12)', ; + Found() AND cantitate == 5 AND pret == 12, TRANSFORM(cantitate) + '/' + TRANSFORM(pret) + +LOCATE FOR id_articol = 700 +DO asserteaza WITH 'B4 id mare: articolul vecin 700 neatins', ; + Found() AND cantitate == 1 AND pret == 5, '' + + *============================================================================================ * SECTIUNEA C - AplicaSincronizareArticole, directia ARTICOLE_SURSA (scrie in trul) *============================================================================================ @@ -347,7 +394,7 @@ PROCEDURE CreeazaTrulTest IF Used('trul') Use In trul ENDIF - CREATE CURSOR trul (id_articol I, denumire C(100), codmat C(30), um C(10), cant N(12,3), cante N(12,3), ; + CREATE CURSOR trul (id_articol N(20), denumire C(100), codmat C(30), um C(10), cant N(12,3), cante N(12,3), ; pretvtva N(14,4), id_tip_rulaj I, sters I, id_gestiune I, cont C(20), proc_tvav N(6,4)) ENDPROC