#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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
This commit is contained in:
2026-08-11 20:05:14 +03:00
parent d3268a69bc
commit 40a112a42d
4 changed files with 901 additions and 8 deletions

View File

@@ -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.grdArticoleFactura.cValoareArt.Text1" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdStergeArticol" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdStergeArticol" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.cmdAdaugaArticol" 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.lblTotalLiniiArt" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.txtTotalLiniiArt" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.txtTotalLiniiArt" UniqueID="" Timestamp="" />
*< OBJECTDATA: ObjPath="pgfArticole.PAGE3.lblDiscountArt" UniqueID="" Timestamp="" /> *< OBJECTDATA: ObjPath="pgfArticole.PAGE3.lblDiscountArt" UniqueID="" Timestamp="" />
@@ -6797,6 +6798,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
*<DefinedPropArrayMethod> *<DefinedPropArrayMethod>
*m: actualizeazabaratotaluri *m: actualizeazabaratotaluri
*m: actualizeazaverdictactrul *m: actualizeazaverdictactrul
*m: afiseazadialogsincronizarearticole
*m: afiseaza_rulaje *m: afiseaza_rulaje
*m: alege_partener *m: alege_partener
*m: aleg_document_pereche *m: aleg_document_pereche
@@ -12304,6 +12306,22 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
ZOrderSet = 0 ZOrderSet = 0
*< END OBJECT: BaseClass="commandbutton" /> *< 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 ; ADD OBJECT 'pgfArticole.PAGE3.cmdStergeArticol' AS commandbutton WITH ;
Anchor = 8, ; Anchor = 8, ;
AutoSize = .F., ; AutoSize = .F., ;
@@ -13170,6 +13188,20 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Thisform.calculeaza_valori_articol() Thisform.calculeaza_valori_articol()
ENDPROC 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 PROCEDURE afiseaza_rulaje
* COLAPSEAZA SAU MARESTE PAGEFRAME-UL RULAJE * COLAPSEAZA SAU MARESTE PAGEFRAME-UL RULAJE
* Daca butonul are imaginea sus, inseamna ca pageframe-ul cu rulaje este ascuns * 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 ENDIF
SELECT (m.lnAreaTvd) SELECT (m.lnAreaTvd)
ENDIF 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 RETURN m.llRet
@@ -14676,7 +14726,7 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
IF Used('tvd') IF Used('tvd')
Use In tvd Use In tvd
ENDIF 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 ENDIF
*!* cursorul tvanz - placeholder gol, ca bara de totaluri (ControlSource pe tvanz.discount) sa se lege la construire *!* 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.cmdStergeArticol.Enabled = !This.lArticoleReadOnly
This.pgfArticole.PAGE3.txtDiscountArt.ReadOnly = This.lArticoleReadOnly This.pgfArticole.PAGE3.txtDiscountArt.ReadOnly = This.lArticoleReadOnly
This.pgfArticole.PAGE3.lblArticoleReadOnly.Visible = This.lArticoleReadOnly This.pgfArticole.PAGE3.lblArticoleReadOnly.Visible = This.lArticoleReadOnly
This.pgfArticole.PAGE3.cmdSincronizeazaArticole.Enabled = !This.lArticoleReadOnly
This.ActualizeazaBaraTotaluri() This.ActualizeazaBaraTotaluri()
ELSE ELSE
This.pgfArticole.PageCount = 2 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/ *!* 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 *!* nume_val/id_valuta se populeaza cu valorile documentului, ca dialogul sa lucreze in valuta
LOCAL loArticolAles, lnIdArticol, llInValutaDoc, lnCursDoc, lnMultDoc, lcNumeValDoc, lnIdValutaDoc 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 RETURN
ENDIF ENDIF
loArticolAles = caut_articol() 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, ; poArticol = CreeazaPoArticolNouTvd(m.lnIdArticol, loArticolAles.codmat, loArticolAles.denumire, loArticolAles.um, loArticolAles.cont, ;
m.llInValutaDoc, m.lnCursDoc, m.lnMultDoc, m.lcNumeValDoc, m.lnIdValutaDoc) m.llInValutaDoc, m.lnCursDoc, m.lnMultDoc, m.lcNumeValDoc, m.lnIdValutaDoc)
poDate = Createobject('Empty') poDate = Createobject('Empty')
AddProperty(poDate, 'tip', This.nTipVanzare) AddProperty(poDate, 'tip', Thisform.nTipVanzare)
AddProperty(poDate, 'in_valuta', 0) AddProperty(poDate, 'in_valuta', 0)
AddProperty(poDate, 'dataact', Iif(Used('tact') And Reccount('tact') > 0, Nvl(tact.dataact, Date()), Date())) AddProperty(poDate, 'dataact', Iif(Used('tact') And Reccount('tact') > 0, Nvl(tact.dataact, Date()), Date()))
gnScadereStoc = 0 gnScadereStoc = 0
@@ -16529,6 +16580,14 @@ DEFINE CLASS frm_modific2024 AS _frmbase OF "_frm_base.vcx"
Release loDlg Release loDlg
ENDPROC 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 PROCEDURE pgfArticole.PAGE3.cmdStergeArticol.Click
*!* comuta flagul sters pe linia curenta din tvd - stergerea e logica, ramane vizibila (grizata) pana la salvare *!* 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 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 ENDPROC
ENDDEFINE 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="" />
*<DefinedPropArrayMethod>
*m: construiesteenumerare
*p: cdirectie
*p: oformarticole
*</DefinedPropArrayMethod>
*<PropValue>
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
*</PropValue>
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

View File

@@ -273,7 +273,7 @@ FUNCTION CreeazaCursorArticoleGol
IF Used(m.lcAlias) IF Used(m.lcAlias)
Use In (m.lcAlias) Use In (m.lcAlias)
ENDIF 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, ; 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, ; 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) lmodificat L, valoare N(14,2), in_stoc I NULL)
@@ -584,7 +584,7 @@ FUNCTION ConstruiestePropunereSincronizare
IF Used('propunere_sincronizare') IF Used('propunere_sincronizare')
Use In propunere_sincronizare Use In propunere_sincronizare
ENDIF 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), ; 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)) actiune C(12), motiv C(80))
@@ -601,7 +601,7 @@ FUNCTION ConstruiestePropunereSincronizare
IF Used('agg_rul') IF Used('agg_rul')
Use In agg_rul Use In agg_rul
ENDIF 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 SELECT trul
SCAN FOR Nvl(sters,0) <> 1 SCAN FOR Nvl(sters,0) <> 1
@@ -624,7 +624,7 @@ FUNCTION ConstruiestePropunereSincronizare
IF Used('agg_tvd') IF Used('agg_tvd')
Use In agg_tvd Use In agg_tvd
ENDIF 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 SELECT tvd
SCAN FOR Nvl(sters,0) <> 1 SCAN FOR Nvl(sters,0) <> 1

View File

@@ -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

View File

@@ -195,6 +195,29 @@ IF Used('tvanz')
Use In tvanz Use In tvanz
ENDIF 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 --- *!* --- A9: retur .F. cand tvd/trul nu sunt deschise, cursorul iese oricum creat ---
IF Used('tvd') IF Used('tvd')
Use In 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) 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) * SECTIUNEA C - AplicaSincronizareArticole, directia ARTICOLE_SURSA (scrie in trul)
*============================================================================================ *============================================================================================
@@ -347,7 +394,7 @@ PROCEDURE CreeazaTrulTest
IF Used('trul') IF Used('trul')
Use In trul Use In trul
ENDIF 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)) pretvtva N(14,4), id_tip_rulaj I, sters I, id_gestiune I, cont C(20), proc_tvav N(6,4))
ENDPROC ENDPROC